diff --git a/debian/changelog b/debian/changelog index 6074cd0..c729b53 100755 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -a2pi (0.1.8-1) unstable; urgency=low +a2pi (0.1.8-2) unstable; urgency=low * Fix FUSE create file function * Add VSDRIVE functionality diff --git a/debian/postinst b/debian/postinst index 887e791..90ea15e 100755 --- a/debian/postinst +++ b/debian/postinst @@ -60,12 +60,12 @@ case "$1" in # # Set up VSDRIVEs # - if [ ! -f /usr/share/a2pid/A2VD1.PO ] ; then - ln -s /usr/share/a2pid/A2PI-1.4.PO A2VD1.PO - fin - if [ ! -f /usr/share/a2pid/A2VD2.PO ] ; then - ln -s /usr/share/a2pid/BLANKDISK.PO A2VD2.PO - fin + if [ ! -e /usr/share/a2pi/A2VD1.PO ] ; then + ln -s /usr/share/a2pi/A2PI-1.4.PO /usr/share/a2pi/A2VD1.PO + fi + if [ ! -e /usr/share/a2pi/A2VD2.PO ] ; then + ln -s /usr/share/a2pi/BLANK.PO /usr/share/a2pi/A2VD2.PO + fi # # Add schmenk.is-a-geek.com to apt sources # diff --git a/src/Makefile b/src/Makefile index 09e0bd7..c12f69a 100755 --- a/src/Makefile +++ b/src/Makefile @@ -7,7 +7,7 @@ else BINDIR=$(DESTDIR)/usr/bin SHAREDIR=$(DESTDIR)/usr/share/a2pi endif -BIN=a2joy a2joymou a2joypad a2mon a2term fusea2pi dskread dskwrite bload brun +BIN=a2joy a2joymou a2joypad a2mon a2term fusea2pi a2pidcmd dskread dskwrite bload brun SBIN=a2pid A2PIDEFS=-DSETSERCLK @@ -25,6 +25,7 @@ clean: install: -mkdir -p $(BINDIR) cp $(BIN) a2mount $(BINDIR) + cp $(BIN) a2setvd $(BINDIR) -mkdir -p $(SBINDIR) cp $(SBIN) $(SBINDIR) -mkdir -p $(SHAREDIR) diff --git a/src/a2lib.c b/src/a2lib.c index cbf62bc..9adae82 100755 --- a/src/a2lib.c +++ b/src/a2lib.c @@ -14,8 +14,8 @@ int a2open(char *ipaddr) int fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (fd < 0) { - perror("Cannot create socket"); - return -1; + perror("Cannot create socket"); + return -1; } memset(&piaddr, 0, sizeof(piaddr)); piaddr.sin_family = AF_INET; @@ -23,21 +23,21 @@ int a2open(char *ipaddr) res = inet_pton(AF_INET, ipaddr, &piaddr.sin_addr); if (res < 0) { - perror("First parameter is not a valid address family"); - close(fd); - return -1; + perror("First parameter is not a valid address family"); + close(fd); + return -1; } else if (res == 0) { - perror("Char string (second parameter does not contain valid ipaddress)"); - close(fd); - return -1; + perror("Char string (second parameter does not contain valid ipaddress)"); + close(fd); + return -1; } if (connect(fd, (struct sockaddr *)&piaddr, sizeof(piaddr)) < 0) { - perror("Connect failed"); - close(fd); - return -1; + perror("Connect failed"); + close(fd); + return -1; } return fd; } @@ -84,7 +84,7 @@ int a2call(int fd, int address, int *result) write(fd, callpkt, 3); read(fd, callpkt, 2); if (result) - *result = (unsigned char)callpkt[1]; + *result = (unsigned char)callpkt[1]; return ((unsigned char)callpkt[0] == 0x9E); } int a2quickcall(int fd, int address, int *result) @@ -96,6 +96,6 @@ int a2quickcall(int fd, int address, int *result) write(fd, callpkt, 3); read(fd, callpkt, 2); if (result) - *result = (unsigned char)callpkt[1]; + *result = (unsigned char)callpkt[1]; return ((unsigned char)callpkt[0] == 0x9E); } diff --git a/src/a2pid.c b/src/a2pid.c index 3d3b118..cd438fa 100755 --- a/src/a2pid.c +++ b/src/a2pid.c @@ -363,38 +363,27 @@ int vdriveopen(char *path) strcat(filename, "A2VD1.PO"); //printf("vdrive: open %s\n", filename); if ((vdrivefd[0] = open(filename, O_RDWR, 0)) < 0) - return 0; + vdrivefd[0] = 0; strcpy(filename, path); strcat(filename, "A2VD2.PO"); //printf("vdrive: open %s\n", filename); if ((vdrivefd[1] = open(filename, O_RDWR, 0)) < 0) - { - close(vdrivefd[0]); - return 0; - } - prlog("vdrive: opened successfully\n"); - return 1; + vdrivefd[1] = 0; + return vdrivefd[0] + vdrivefd[1]; } -int vdriveclose(void) +void vdriveclose(void) { - return close(vdrivefd[0]) | close(vdrivefd[1]); + if (vdrivefd[0]) close(vdrivefd[0]); + if (vdrivefd[1]) close(vdrivefd[1]); + vdrivefd[0] = vdrivefd[1] = 0; } -unsigned int prodos_time(int year, int month, int day, int hour, int minute) +void vdrivecmd(int afd, int command, int block, unsigned char crc_in) { - if (year > 99) - year -= 100; - month += 1; - return (day & 0x1F) - | ((month & 0x0F) << 5) - | ((year & 0x7F) << 9) - | ((minute & 0x3F) << 16) - | ((hour & 0x1F) << 24); -} -void vdrivecmd(int fd, int command, int block, unsigned char crc_in) -{ - int i; - unsigned char crc_out = crc_in, block_buff[512]; - + int i, vfd = vdrivefd[command >> 2]; + unsigned char block_buff[512], crc_out = 0xC5 ^ command ^ block ^ (block >> 8); + + if (crc_in != crc_out) + prlog("vdrive: CRC mismatch!\n"); if (command == 0x01 || command == 0x03 || command == 0x05) { //printf("vdrive: read block=%d from unit:%d\n", block, command >> 2); @@ -402,7 +391,7 @@ void vdrivecmd(int fd, int command, int block, unsigned char crc_in) block_buff[1] = command; block_buff[2] = block; block_buff[3] = block >> 8; - write(fd, block_buff, 4); + write(afd, block_buff, 4); if (command > 0x01) { unsigned char time_buff[4]; @@ -411,40 +400,50 @@ void vdrivecmd(int fd, int command, int block, unsigned char crc_in) */ time_t now = time(NULL); struct tm *tm = localtime(&now); - int ptime = prodos_time(tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min); + int ptime = (tm->tm_mday & 0x1F) + | (((tm->tm_mon + 1) & 0x0F) << 5) + | (((tm->tm_year - 100) & 0x7F) << 9) + | ((tm->tm_min & 0x3F) << 16) + | ((tm->tm_hour & 0x1F) << 24); time_buff[0] = (unsigned char) ptime; time_buff[1] = (unsigned char) (ptime >> 8); time_buff[2] = (unsigned char) (ptime >> 16); time_buff[3] = (unsigned char) (ptime >> 24); - write(fd, time_buff, 4); + write(afd, time_buff, 4); crc_out ^= time_buff[0] ^ time_buff[1] ^ time_buff[2] ^ time_buff[3]; } - lseek(vdrivefd[command >> 2], block * 512, 0); - write(fd, &crc_out, 1); - read(vdrivefd[command >> 2], block_buff, 512); - write(fd, block_buff, 512); + write(afd, &crc_out, 1); + if (vfd) + { + lseek(vfd, block * 512, 0); + read(vfd, block_buff, 512); + } + write(afd, block_buff, 512); for (crc_out = i = 0; i < 512; i++) crc_out ^= block_buff[i]; - write(fd, &crc_out, 1); + write(afd, &crc_out, 1); } else if (command == 0x02 || command == 0x04) { //printf("vdrive: write block=%d to unit:%d\n", block, command >> 2); for (crc_out = i = 0; i < 512; i++) { - read(fd, &block_buff[i], 1); + read(afd, &block_buff[i], 1); crc_out ^= block_buff[i]; } - lseek(vdrivefd[command >> 2], block * 512, 0); - read(fd, &crc_in, 1); + if (vfd) + { + lseek(vfd, block * 512, 0); + read(afd, &crc_in, 1); + } if (crc_in == crc_out) - write(vdrivefd[command >> 2], block_buff, 512); + write(vfd, block_buff, 512); block_buff[0] = 0xC5; block_buff[1] = command; block_buff[2] = block; block_buff[3] = block >> 8; block_buff[4] = crc_out; - write(fd, block_buff, 5); + write(afd, block_buff, 5); } else state = RESET; // ??? What else to do ??? @@ -464,18 +463,18 @@ void sendkeycodedown(int fd, int code) evkey.value = 1; if (code & MOD_ALT) { - evkey.code = KEY_LEFTALT; - write(fd, &evkey, sizeof(evkey)); + evkey.code = KEY_LEFTALT; + write(fd, &evkey, sizeof(evkey)); } if (code & MOD_CTRL) { - evkey.code = KEY_LEFTCTRL; - write(fd, &evkey, sizeof(evkey)); + evkey.code = KEY_LEFTCTRL; + write(fd, &evkey, sizeof(evkey)); } if (code & MOD_SHIFT) { - evkey.code = KEY_LEFTSHIFT; - write(fd, &evkey, sizeof(evkey)); + evkey.code = KEY_LEFTSHIFT; + write(fd, &evkey, sizeof(evkey)); } evkey.code = code & KEY_CODE; write(fd, &evkey, sizeof(evkey)); @@ -491,50 +490,49 @@ void sendkeycodeup(int fd, int code) write(fd, &evkey, sizeof(evkey)); if (code & MOD_SHIFT) { - evkey.code = KEY_LEFTSHIFT; - write(fd, &evkey, sizeof(evkey)); + evkey.code = KEY_LEFTSHIFT; + write(fd, &evkey, sizeof(evkey)); } if (code & MOD_CTRL) { - evkey.code = KEY_LEFTCTRL; - write(fd, &evkey, sizeof(evkey)); + evkey.code = KEY_LEFTCTRL; + write(fd, &evkey, sizeof(evkey)); } if (code & MOD_ALT) { - evkey.code = KEY_LEFTALT; - write(fd, &evkey, sizeof(evkey)); + evkey.code = KEY_LEFTALT; + write(fd, &evkey, sizeof(evkey)); } write(fd, &evsync, sizeof(evsync)); } static int prevkeycode = -1; void sendkey(int fd, int mod, int key) { - int code = keycode[(mod & MOD_FN) | (key & KEY_ASCII)] - | ((mod << 8) & MOD_ALT); + int code = keycode[(mod & MOD_FN) | (key & KEY_ASCII)] | ((mod << 8) & MOD_ALT); if (prevkeycode >= 0) { - sendkeycodeup(fd, prevkeycode); - if (!(key & KEY_PRESS) && ((code & KEY_CODE) != (prevkeycode & KEY_CODE))) - /* - * missed a key down event - * synthesize one - */ - sendkeycodedown(fd, code); - (key & KEY_PRESS) ? sendkeycodedown(fd, code) : sendkeycodeup(fd, code); + sendkeycodeup(fd, prevkeycode); + if (!(key & KEY_PRESS) && ((code & KEY_CODE) != (prevkeycode & KEY_CODE))) + /* + * missed a key down event + * synthesize one + */ + sendkeycodedown(fd, code); + (key & KEY_PRESS) ? sendkeycodedown(fd, code) : sendkeycodeup(fd, code); } else { - if (code != -prevkeycode) /* key may have been released before client call */ - { - sendkeycodedown(fd, code); - if (!(key & KEY_PRESS)) - /* - * missed a key down event - * already synthesized one - */ - sendkeycodeup(fd, code); - } + if (code != -prevkeycode) /* key may have been released before client call */ + { + sendkeycodedown(fd, code); + if (!(key & KEY_PRESS)) + /* + * missed a key down event + * already synthesized one + */ + sendkeycodeup(fd, code); + } } prevkeycode = (key & KEY_PRESS) ? code : -KEYCODE_MAX; } @@ -544,16 +542,15 @@ void sendbttn(int fd, int mod, int bttn) if (bttn) { - lastbtn = - evkey.code = (mod == 0) ? BTN_LEFT - : (mod & 0x40) ? BTN_RIGHT - : BTN_MIDDLE; - evkey.value = 1; + lastbtn = evkey.code = (mod == 0) ? BTN_LEFT + : (mod & 0x40) ? BTN_RIGHT + : BTN_MIDDLE; + evkey.value = 1; } else { - evkey.code = lastbtn; - evkey.value = 0; + evkey.code = lastbtn; + evkey.value = 0; } write(fd, &evkey, sizeof(evkey)); write(fd, &evsync, sizeof(evsync)); @@ -562,7 +559,7 @@ void sendrelxy(int fd, int x, int y) { #if 0 static int accel[32] = { 0, 1, 4, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, -8, -4, -1}; + -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, -8, -4, -1}; x = ((x > 4) || (x < -4)) ? x * 2 : accel[x & 0x1F]; y = ((y > 4) || (y < -4)) ? y * 2 : accel[y & 0x1F]; #else @@ -576,7 +573,7 @@ void sendrelxy(int fd, int x, int y) write(fd, &evsync, sizeof(evsync)); } /*****************************************************************\ -* * + * * * Request queue management * * * \*****************************************************************/ @@ -588,10 +585,10 @@ int writeword(int fd, int word, char ack) write(fd, &rwchar, 1); if ((read(fd, &rwchar, 1) == 1) && (rwchar == ack)) /* receive ack */ { - rwchar = word >> 8; /* send high byte of word */ - write(fd, &rwchar, 1); - if ((read(fd, &rwchar, 1) == 1) && (rwchar == ack)) /* receive ack */ - return TRUE; + rwchar = word >> 8; /* send high byte of word */ + write(fd, &rwchar, 1); + if ((read(fd, &rwchar, 1) == 1) && (rwchar == ack)) /* receive ack */ + return TRUE; } return FALSE; } @@ -600,34 +597,34 @@ struct a2request *addreq(int a2fd, int clidx, int type, int addr, int count, cha char rwchar; struct a2request *a2req = a2reqfree; if (a2req == NULL) - a2req = malloc(sizeof(struct a2request)); + a2req = malloc(sizeof(struct a2request)); else - a2reqfree = a2reqfree->next; + a2reqfree = a2reqfree->next; a2req->idx = clidx; a2req->type = type; a2req->addr = addr; a2req->count = count; a2req->xfer = 0; - a2req->buffer = buffer; + a2req->buffer = buffer; a2req->next = NULL; if (a2reqlist == NULL) { - /* - * Initiate request. - */ - a2reqlist = a2req; - rwchar = a2req->type; - write(a2fd, &rwchar, 1); + /* + * Initiate request. + */ + a2reqlist = a2req; + rwchar = a2req->type; + write(a2fd, &rwchar, 1); } else { - /* - * Add to end of request list. - */ - struct a2request *a2reqnext = a2reqlist; - while (a2reqnext->next != NULL) - a2reqnext = a2reqnext->next; - a2reqnext->next = a2req; + /* + * Add to end of request list. + */ + struct a2request *a2reqnext = a2reqlist; + while (a2reqnext->next != NULL) + a2reqnext = a2reqnext->next; + a2reqnext->next = a2req; } return a2req; } @@ -637,27 +634,27 @@ void finreq(int a2fd, int status, int result) struct a2request *a2req = a2reqlist; if (a2req->next) { - /* - * Initiate next request. - */ - finbuf[0] = a2req->next->type; - write(a2fd, finbuf, 1); + /* + * Initiate next request. + */ + finbuf[0] = a2req->next->type; + write(a2fd, finbuf, 1); } /* * Send result to socket. */ if (a2client[a2req->idx].flags & CLIENT_OPEN) { - if (a2req->type == 0x90) /* read bytes */ - write(a2client[a2req->idx].fd, a2req->buffer, a2req->count); - finbuf[0] = status; - finbuf[1] = result; - write(a2client[a2req->idx].fd, finbuf, 2); + if (a2req->type == 0x90) /* read bytes */ + write(a2client[a2req->idx].fd, a2req->buffer, a2req->count); + finbuf[0] = status; + finbuf[1] = result; + write(a2client[a2req->idx].fd, finbuf, 2); } if (a2req->buffer) { - free(a2req->buffer); - a2req->buffer = NULL; + free(a2req->buffer); + a2req->buffer = NULL; } /* * Update lists. @@ -672,47 +669,47 @@ void flushreqs(int a2fd, int clidx, int status, int result) struct a2request *a2req = a2reqlist, *a2reqprev = NULL; while (a2req) { - if (clidx < 0 || clidx == a2req->idx) - { - /* - * Send result to socket. - */ - if (a2client[a2req->idx].flags & CLIENT_OPEN) - { - if (a2req->type == 0x90) /* read bytes */ - write(a2client[a2req->idx].fd, a2req->buffer, a2req->count); - finbuf[0] = status; - finbuf[1] = result; - write(a2client[a2req->idx].fd, finbuf, 2); - } - if (a2req->buffer) - { - free(a2req->buffer); - a2req->buffer = NULL; - } - /* - * Update lists. - */ - 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; - } + if (clidx < 0 || clidx == a2req->idx) + { + /* + * Send result to socket. + */ + if (a2client[a2req->idx].flags & CLIENT_OPEN) + { + if (a2req->type == 0x90) /* read bytes */ + write(a2client[a2req->idx].fd, a2req->buffer, a2req->count); + finbuf[0] = status; + finbuf[1] = result; + write(a2client[a2req->idx].fd, finbuf, 2); + } + if (a2req->buffer) + { + free(a2req->buffer); + a2req->buffer = NULL; + } + /* + * Update lists. + */ + 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; + } } } /*****************************************************************\ @@ -737,54 +734,54 @@ void main(int argc, char **argv) */ if (argc > 1) { - /* - * Are we running as a daemon? - */ - if (strcmp(argv[1], "--daemon") == 0) - { - if (daemon(0, 0) != 0) - die("a2pid: daemon() failure"); - isdaemon = TRUE; - /* - * Another argument must be tty device - */ - if (argc > 2) - devtty = argv[2]; - } - else - /* - * Must be tty device - */ - devtty = argv[1]; + /* + * Are we running as a daemon? + */ + if (strcmp(argv[1], "--daemon") == 0) + { + if (daemon(0, 0) != 0) + die("a2pid: daemon() failure"); + isdaemon = TRUE; + /* + * Another argument must be tty device + */ + if (argc > 2) + devtty = argv[2]; + } + else + /* + * Must be tty device + */ + devtty = argv[1]; } /* * Add signal handlers. */ if (signal(SIGTERM, sig_bye) == SIG_ERR) - die("signal"); + die("signal"); if (signal(SIGINT, sig_bye) == SIG_ERR) - die("signal"); + die("signal"); if (signal(SIGHUP, sig_bye) == SIG_ERR) - die("signal"); + die("signal"); /* * Create keyboard input device */ prlog("a2pid: Create keyboard input device\n"); kbdfd = open("/dev/uinput", O_WRONLY | O_NONBLOCK); if (kbdfd < 0) - die("error: uinput open"); + die("error: uinput open"); if (ioctl(kbdfd, UI_SET_EVBIT, EV_KEY) < 0) - die("error: uinput ioctl EV_KEY"); + die("error: uinput ioctl EV_KEY"); if (ioctl(kbdfd, UI_SET_EVBIT, EV_REP) < 0) - die("error: uinput ioctl EV_REP"); + die("error: uinput ioctl EV_REP"); for (i = KEY_ESC; i <= KEY_F10; i++) - if (ioctl(kbdfd, UI_SET_KEYBIT, i) < 0) - die("error: uinput ioctl SET_KEYBITs"); + if (ioctl(kbdfd, UI_SET_KEYBIT, i) < 0) + die("error: uinput ioctl SET_KEYBITs"); for (i = KEY_HOME; i <= KEY_DELETE; i++) - if (ioctl(kbdfd, UI_SET_KEYBIT, i) < 0) - die("error: uinput ioctl SET_KEYBITs"); + if (ioctl(kbdfd, UI_SET_KEYBIT, i) < 0) + die("error: uinput ioctl SET_KEYBITs"); if (ioctl(kbdfd, UI_SET_EVBIT, EV_SYN) < 0) - die("error: ioctl EV_SYN"); + die("error: ioctl EV_SYN"); bzero(&uidev, sizeof(uidev)); snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "Apple2 Pi Keyboard"); uidev.id.bustype = BUS_RS232; @@ -793,7 +790,7 @@ void main(int argc, char **argv) uidev.id.version = 1; write(kbdfd, &uidev, sizeof(uidev)); if (ioctl(kbdfd, UI_DEV_CREATE) < 0) - die("error: ioctl DEV_CREATE"); + die("error: ioctl DEV_CREATE"); /* * Set repeat delay values that make sense. */ @@ -802,35 +799,35 @@ void main(int argc, char **argv) evkey.code = REP_DELAY; evkey.value = 500; /* 0.5 sec delay */ if (write(kbdfd, &evkey, sizeof(evkey)) < 0) - die("error: REP_DELAY"); + die("error: REP_DELAY"); evkey.type = EV_REP; evkey.code = REP_PERIOD; evkey.value = 67; /* 15 reps/sec */ if (write(kbdfd, &evkey, sizeof(evkey)) < 0) - die("error: REP_PERIOD"); + die("error: REP_PERIOD"); /* * Create mouse input device */ prlog("a2pid: Create mouse input device\n"); moufd = open("/dev/uinput", O_WRONLY | O_NONBLOCK); if (moufd < 0) - die("error: uinput open"); + die("error: uinput open"); if (ioctl(moufd, UI_SET_EVBIT, EV_KEY) < 0) - die("error: uinput ioctl EV_KEY"); + die("error: uinput ioctl EV_KEY"); if (ioctl(moufd, UI_SET_KEYBIT, BTN_LEFT) < 0) - die("error: uinput ioctl BTN_LEFT"); + die("error: uinput ioctl BTN_LEFT"); if (ioctl(moufd, UI_SET_KEYBIT, BTN_RIGHT) < 0) - die("error: uinput ioctl BTN_RIGHT"); + die("error: uinput ioctl BTN_RIGHT"); if (ioctl(moufd, UI_SET_KEYBIT, BTN_MIDDLE) < 0) - die("error: uinput ioctl BTN_MIDDLE"); + die("error: uinput ioctl BTN_MIDDLE"); if (ioctl(moufd, UI_SET_EVBIT, EV_REL) < 0) - die("error: ioctl EV_REL"); + die("error: ioctl EV_REL"); if (ioctl(moufd, UI_SET_RELBIT, REL_X) < 0) - die("error: ioctl REL_X"); + die("error: ioctl REL_X"); if (ioctl(moufd, UI_SET_RELBIT, REL_Y) < 0) - die("error: ioctl REL_Y"); + die("error: ioctl REL_Y"); if (ioctl(moufd, UI_SET_EVBIT, EV_SYN) < 0) - die("error: ioctl EV_SYN"); + die("error: ioctl EV_SYN"); bzero(&uidev, sizeof(uidev)); snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "Apple2 Pi Mouse"); uidev.id.bustype = BUS_RS232; @@ -839,7 +836,7 @@ void main(int argc, char **argv) uidev.id.version = 1; write(moufd, &uidev, sizeof(uidev)); if (ioctl(moufd, UI_DEV_CREATE) < 0) - die("error: ioctl DEV_CREATE"); + die("error: ioctl DEV_CREATE"); /* * Initialize event structures. */ @@ -857,13 +854,35 @@ void main(int argc, char **argv) * Get VDRIVE images. */ vdriveactive = vdriveopen(vdrivedir); + /* + * Open socket. + */ + prlog("a2pid: Open server socket\n"); + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(6551); + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + srvfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (srvfd < 0) + die("error: socket create"); + if (bind(srvfd,(struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) + die("error: bind socket"); + if (listen(srvfd, MAX_CLIENT - 1) < 0) + die("error: listen socket"); +#if defined(SETSERCLK) && defined(__ARMEL__) + /* + * Initialize ACIA clock for Apple II Pi card + */ + gpclk(271); /* divisor for ~1.8 MHz => (500/271) MHz */ + sleep(1); /* give clock chance to settle down */ +#endif /* * Open serial port. */ prlog("a2pid: Open serial port\n"); a2fd = open(devtty, O_RDWR | O_NOCTTY); if (a2fd < 0) - die("error: serial port open"); + die("error: serial port open"); tcflush(a2fd, TCIFLUSH); tcgetattr(a2fd, &oldtio); /* save current port settings */ bzero(&newtio, sizeof(newtio)); @@ -875,51 +894,29 @@ void main(int argc, char **argv) newtio.c_cc[VMIN] = 1; /* blocking read until 1 char received */ tcsetattr(a2fd, TCSANOW, &newtio); prlog("a2pid: Waiting to connect to Apple II...\n"); -#if defined(SETSERCLK) && defined(__ARMEL__) - /* - * Initialize ACIA clock for Apple II Pi card - */ - gpclk(271); /* divisor for ~1.8 MHz => (500/271) MHz */ - sleep(1); /* give clock chance to settle down */ -#endif iopkt[0] = 0x80; /* request re-sync if Apple II already running */ write(a2fd, iopkt, 1); if (read(a2fd, iopkt, 1) == 1) { - if (iopkt[0] == 0x80) /* receive sync */ - { - prlog("a2pid: Connected.\n"); - iopkt[0] = 0x81; /* acknowledge */ - write(a2fd, iopkt, 1); - } - else if (iopkt[0] == 0x9F) /* bad request from Apple II */ - { - prlog("a2pi: Bad Connect Request.\n"); - tcflush(a2fd, TCIFLUSH); - } - else - { - prlog("a2pi: Bad Sync ACK\n"); - state = RESET; - } + if (iopkt[0] == 0x80) /* receive sync */ + { + prlog("a2pid: Connected.\n"); + iopkt[0] = 0x81; /* acknowledge */ + write(a2fd, iopkt, 1); + } + else if (iopkt[0] == 0x9F) /* bad request from Apple II */ + { + prlog("a2pi: Bad Connect Request.\n"); + tcflush(a2fd, TCIFLUSH); + } + else + { + prlog("a2pi: Bad Sync ACK\n"); + state = RESET; + } } newtio.c_cc[VMIN] = 3; /* blocking read until 3 chars received */ tcsetattr(a2fd, TCSANOW, &newtio); - /* - * Open socket. - */ - prlog("a2pid: Open server socket\n"); - bzero(&servaddr, sizeof(servaddr)); - servaddr.sin_family = AF_INET; - servaddr.sin_port = htons(6551); - servaddr.sin_addr.s_addr = htonl(INADDR_ANY); - srvfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (srvfd < 0) - die("error: socket create"); - if (bind(srvfd,(struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) - die("error: bind socket"); - if (listen(srvfd, MAX_CLIENT - 1) < 0) - die("error: listen socket"); /* * Come basck here on RESET. */ @@ -927,8 +924,8 @@ reset: state = RUN; for (i = 0; i < MAX_CLIENT; i++) { - a2client[i].fd = 0; - a2client[i].flags = 0; + a2client[i].fd = 0; + a2client[i].flags = 0; } maxfd = 0; FD_ZERO(&openset); @@ -940,174 +937,68 @@ reset: prlog("a2pid: Enter event loop\n"); 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)); - if ((rdycnt = select(maxfd + 1, &readset, NULL, NULL, NULL)) > 0) - { - /* - * Serial port to Apple II transaction. - */ - if (FD_ISSET(a2fd, &readset)) - { - rdycnt--; - if (read(a2fd, iopkt, 3) == 3) - { - // printf("a2pi: A2 Event [0x%02X] [0x%02X] [0x%02X]\n", iopkt[0], iopkt[1], iopkt[2]); - switch (iopkt[0]) - { - case 0x80: /* sync */ - prlog("a2pid: Re-Connected.\n"); - iopkt[0] = 0x81; /* acknowledge */ - write(a2fd, iopkt, 1); - tcflush(a2fd, TCIFLUSH); - flushreqs(a2fd, 0, -1, -1); - break; - case 0x82: /* keyboard event */ - // printf("Keyboard Event: 0x%02X:%c\n", iopkt[1], iopkt[2] & 0x7F); - sendkey(kbdfd, iopkt[1], iopkt[2]); - //if (iopkt[2] == 0x9B && iopkt[1] == 0xC0) - //state = STOP; - break; - case 0x84: /* mouse move event */ - //printf("Mouse XY Event: %d,%d\n", (signed char)iopkt[1], (signed char)iopkt[2]); - sendrelxy(moufd, (signed char)iopkt[1], (signed char)iopkt[2]); - break; - case 0x86: /* mouse button event */ - // printf("Mouse Button %s Event 0x%02X\n", iopkt[2] ? "[PRESS]" : "[RELEASE]", iopkt[1]); - sendbttn(moufd, iopkt[1], iopkt[2]); - break; - case 0x90: /* acknowledge read bytes request*/ - if (a2reqlist) /* better have an outstanding request */ - { - //printf("a2pid: read %d of %d bytes from 0x%04X\n", a2reqlist->xfer, a2reqlist->count, a2reqlist->addr); - newtio.c_cc[VMIN] = 1; /* blocking read until 1 char received */ - tcsetattr(a2fd, TCSANOW, &newtio); - c = a2reqlist->count - a2reqlist->xfer > MAX_XFER - ? MAX_XFER - : a2reqlist->count - a2reqlist->xfer; - if (writeword(a2fd, a2reqlist->addr + a2reqlist->xfer, 0x91) && writeword(a2fd, c, 0x91)) - { - for (i = 0; i < c; i++) - { - if (read(a2fd, iopkt, 1) == 1) - a2reqlist->buffer[a2reqlist->xfer++] = iopkt[0]; - else - { - state = RESET; - break; - } - } - } - else - state = RESET; - newtio.c_cc[VMIN] = 3; /* blocking read until 3 chars received */ - tcsetattr(a2fd, TCSANOW, &newtio); - } - else - state = RESET; - break; - case 0x92: /* acknowledge write bytes */ - if (a2reqlist) /* better have an outstanding request */ - { - //printf("a2pid: wrote %d of %d bytes to 0x%04X\n", a2reqlist->xfer, a2reqlist->count, a2reqlist->addr); - newtio.c_cc[VMIN] = 1; /* blocking read until 1 char received */ - tcsetattr(a2fd, TCSANOW, &newtio); - c = a2reqlist->count - a2reqlist->xfer > MAX_XFER - ? MAX_XFER - : a2reqlist->count - a2reqlist->xfer; - if (writeword(a2fd, a2reqlist->addr + a2reqlist->xfer, 0x93) && writeword(a2fd, c, 0x93)) - { - if (write(a2fd, a2reqlist->buffer + a2reqlist->xfer, c) == c) - a2reqlist->xfer += c; - else - state = RESET; - } - else - state = RESET; - newtio.c_cc[VMIN] = 3; /* blocking read until 3 chars received */ - tcsetattr(a2fd, TCSANOW, &newtio); - } - else - state = RESET; - break; - case 0x9A: /* acknowledge call with keyboard flush*/ - if (prevkeycode >= 0) /* flush keyboard if going away for awhile */ - { - sendkeycodeup(kbdfd, prevkeycode); - prevkeycode = -prevkeycode; - } - case 0x94: /* acknowledge call */ - if (a2reqlist) /* better have an outstanding request */ - { - //printf("a2pid: call address 0x%04X\n", a2reqlist->addr); - newtio.c_cc[VMIN] = 1; /* blocking read until 1 char received */ - tcsetattr(a2fd, TCSANOW, &newtio); - if (!writeword(a2fd, a2reqlist->addr, iopkt[0] + 1)) - state = RESET; - newtio.c_cc[VMIN] = 3; /* blocking read until 3 chars received */ - tcsetattr(a2fd, TCSANOW, &newtio); - } - else - state = RESET; - break; - case 0x96: /* send input char to Apple II */ - if (a2reqlist) /* better have an outstanding request */ - { - //printf("a2pid: call address 0x%04X\n", a2reqlist->addr); - newtio.c_cc[VMIN] = 1; /* blocking read until 1 char received */ - tcsetattr(a2fd, TCSANOW, &newtio); - if (!writeword(a2fd, a2reqlist->addr, 0x97)) - state = RESET; - newtio.c_cc[VMIN] = 3; /* blocking read until 3 chars received */ - tcsetattr(a2fd, TCSANOW, &newtio); - } - else - state = RESET; - break; - case 0x98: /* get output char from Apple II */ - for (i = 0; i < MAX_CLIENT; i++) - if (a2client[i].flags & CLIENT_COUT) - write(a2client[i].fd, iopkt, 2); - - break; - case 0x9E: /* request complete ok */ - case 0x9F: /* request complete error */ - if (a2reqlist) /* better have an outstanding request */ - { - //printf("a2pid: complete request 0x%02X:0x%02X\n", (unsigned char)iopkt[0], (unsigned char)iopkt[1]); - if ((a2reqlist->type == 0x90 || a2reqlist->type == 0x92) - && (a2reqlist->count > a2reqlist->xfer)) - { - iopkt[0] = a2reqlist->type; - write(a2fd, iopkt, 1); - } - else - { - //printf("a2pid: finish request 0x%02X:0x%02X\n", (unsigned char)iopkt[0], (unsigned char)iopkt[1]); - finreq(a2fd, (unsigned char)iopkt[0], (unsigned char)iopkt[1]); - } - } - else - state = RESET; - break; - case 0xC5: /* virtual drive request */ - //printf("a2pid: vdrive request\n"); - if (vdriveactive) + 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)); + if ((rdycnt = select(maxfd + 1, &readset, NULL, NULL, NULL)) > 0) + { + /* + * Serial port to Apple II transaction. + */ + if (FD_ISSET(a2fd, &readset)) + { + rdycnt--; + if (read(a2fd, iopkt, 3) == 3) + { + // printf("a2pi: A2 Event [0x%02X] [0x%02X] [0x%02X]\n", iopkt[0], iopkt[1], iopkt[2]); + switch (iopkt[0]) + { + case 0x80: /* sync */ + prlog("a2pid: Re-Connected.\n"); + iopkt[0] = 0x81; /* acknowledge */ + write(a2fd, iopkt, 1); + tcflush(a2fd, TCIFLUSH); + flushreqs(a2fd, 0, -1, -1); + break; + case 0x82: /* keyboard event */ + // printf("Keyboard Event: 0x%02X:%c\n", iopkt[1], iopkt[2] & 0x7F); + sendkey(kbdfd, iopkt[1], iopkt[2]); + //if (iopkt[2] == 0x9B && iopkt[1] == 0xC0) + //state = STOP; + break; + case 0x84: /* mouse move event */ + //printf("Mouse XY Event: %d,%d\n", (signed char)iopkt[1], (signed char)iopkt[2]); + sendrelxy(moufd, (signed char)iopkt[1], (signed char)iopkt[2]); + break; + case 0x86: /* mouse button event */ + // printf("Mouse Button %s Event 0x%02X\n", iopkt[2] ? "[PRESS]" : "[RELEASE]", iopkt[1]); + sendbttn(moufd, iopkt[1], iopkt[2]); + break; + case 0x90: /* acknowledge read bytes request*/ + if (a2reqlist) /* better have an outstanding request */ { - newtio.c_cc[VMIN] = 1; /* blocking read until command packet received */ + //printf("a2pid: read %d of %d bytes from 0x%04X\n", a2reqlist->xfer, a2reqlist->count, a2reqlist->addr); + newtio.c_cc[VMIN] = 1; /* blocking read until 1 char received */ tcsetattr(a2fd, TCSANOW, &newtio); - if (read(a2fd, &iopkt[3], 1) + read(a2fd, &iopkt[4], 1) == 2) + c = a2reqlist->count - a2reqlist->xfer > MAX_XFER + ? MAX_XFER + : a2reqlist->count - a2reqlist->xfer; + if (writeword(a2fd, a2reqlist->addr + a2reqlist->xfer, 0x91) && writeword(a2fd, c, 0x91)) { - //printf("vdrive cmd:%02X blk:%d crc:%02X\n", iopkt[1], iopkt[2] | (iopkt[3] << 8), iopkt[4]); - if ((iopkt[0] ^ iopkt[1] ^ iopkt[2] ^ iopkt[3]) == iopkt[4]) - vdrivecmd(a2fd, iopkt[1], iopkt[2] | (iopkt[3] << 8), iopkt[4]); - else - prlog("vdrive: bad CRC\n"); + for (i = 0; i < c; i++) + { + if (read(a2fd, iopkt, 1) == 1) + a2reqlist->buffer[a2reqlist->xfer++] = iopkt[0]; + else + { + state = RESET; + break; + } + } } else state = RESET; @@ -1117,147 +1008,258 @@ reset: else state = RESET; break; - default: - prlog("a2pid: Unknown Event\n"); - tcflush(a2fd, TCIFLUSH); - //stop = TRUE; - } - } - else - { - prlog("a2pid: error read serial port ????\n"); - state = STOP; - } - } - /* - * Open client connection. - */ - if (FD_ISSET(srvfd, &readset)) - { - rdycnt--; - int clientfd = accept(srvfd, NULL, NULL); - 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 - prlog("a2pid: error accept"); - } - /* - * Socket client request. - */ - for (i = 0; rdycnt > 0 && i < MAX_CLIENT; i++) - { - if (a2client[i].flags && FD_ISSET(a2client[i].fd, &readset)) - { - int addr, count; - char *databuf; - rdycnt--; - if (read(a2client[i].fd, iopkt, 1) == 1) - { - // printf("a2pi: Client Request [0x%02X]\n", iopkt[0]); - switch (iopkt[0]) - { - case 0x90: /* read bytes */ - if (read(a2client[i].fd, 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); - addreq(a2fd, i, 0x90, addr, count, databuf); - } - else - { - iopkt[0] = 0x9E; - iopkt[1] = 0x00; - write(a2client[i].fd, iopkt, 2); - } - } - break; - case 0x92: /* write bytes */ - if (read(a2client[i].fd, 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); - 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; - case 0x94: /* call */ - case 0x9A: /* call with keyboard flush */ - if (read(a2client[i].fd, iopkt + 1, 2) == 2) - { - addr = (unsigned char)iopkt[1] | ((unsigned char)iopkt[2] << 8); - addreq(a2fd, i, iopkt[0], addr, 0, NULL); - } - break; - case 0x96: /* send input char to Apple II */ - if (read(a2client[i].fd, iopkt, 1) == 1) - addreq(a2fd, i, 0x96, iopkt[0], 0, NULL); - break; - case 0x98: /* get output chars from Apple II */ - a2client[i].flags |= CLIENT_COUT; - break; - case 0xFF: /* close */ - a2client[i].flags = CLIENT_CLOSING; - break; - default: - prlog("a2pid: Unknown Request\n"); - } - } - else - { - /* - * Close client socket connection. - */ - FD_CLR(a2client[i].fd, &openset); - close(a2client[i].fd); - if (a2client[i].fd >= maxfd) - maxfd = 0; - a2client[i].fd = 0; - a2client[i].flags = 0; - flushreqs(a2fd, i, -1, -1); - } - } - } - } + case 0x92: /* acknowledge write bytes */ + if (a2reqlist) /* better have an outstanding request */ + { + //printf("a2pid: wrote %d of %d bytes to 0x%04X\n", a2reqlist->xfer, a2reqlist->count, a2reqlist->addr); + newtio.c_cc[VMIN] = 1; /* blocking read until 1 char received */ + tcsetattr(a2fd, TCSANOW, &newtio); + c = a2reqlist->count - a2reqlist->xfer > MAX_XFER + ? MAX_XFER + : a2reqlist->count - a2reqlist->xfer; + if (writeword(a2fd, a2reqlist->addr + a2reqlist->xfer, 0x93) && writeword(a2fd, c, 0x93)) + { + if (write(a2fd, a2reqlist->buffer + a2reqlist->xfer, c) == c) + a2reqlist->xfer += c; + else + state = RESET; + } + else + state = RESET; + newtio.c_cc[VMIN] = 3; /* blocking read until 3 chars received */ + tcsetattr(a2fd, TCSANOW, &newtio); + } + else + state = RESET; + break; + case 0x9A: /* acknowledge call with keyboard flush*/ + if (prevkeycode >= 0) /* flush keyboard if going away for awhile */ + { + sendkeycodeup(kbdfd, prevkeycode); + prevkeycode = -prevkeycode; + } + case 0x94: /* acknowledge call */ + if (a2reqlist) /* better have an outstanding request */ + { + //printf("a2pid: call address 0x%04X\n", a2reqlist->addr); + newtio.c_cc[VMIN] = 1; /* blocking read until 1 char received */ + tcsetattr(a2fd, TCSANOW, &newtio); + if (!writeword(a2fd, a2reqlist->addr, iopkt[0] + 1)) + state = RESET; + newtio.c_cc[VMIN] = 3; /* blocking read until 3 chars received */ + tcsetattr(a2fd, TCSANOW, &newtio); + } + else + state = RESET; + break; + case 0x96: /* send input char to Apple II */ + if (a2reqlist) /* better have an outstanding request */ + { + //printf("a2pid: call address 0x%04X\n", a2reqlist->addr); + newtio.c_cc[VMIN] = 1; /* blocking read until 1 char received */ + tcsetattr(a2fd, TCSANOW, &newtio); + if (!writeword(a2fd, a2reqlist->addr, 0x97)) + state = RESET; + newtio.c_cc[VMIN] = 3; /* blocking read until 3 chars received */ + tcsetattr(a2fd, TCSANOW, &newtio); + } + else + state = RESET; + break; + case 0x98: /* get output char from Apple II */ + for (i = 0; i < MAX_CLIENT; i++) + if (a2client[i].flags & CLIENT_COUT) + write(a2client[i].fd, iopkt, 2); + + break; + case 0x9E: /* request complete ok */ + case 0x9F: /* request complete error */ + if (a2reqlist) /* better have an outstanding request */ + { + //printf("a2pid: complete request 0x%02X:0x%02X\n", (unsigned char)iopkt[0], (unsigned char)iopkt[1]); + if ((a2reqlist->type == 0x90 || a2reqlist->type == 0x92) + && (a2reqlist->count > a2reqlist->xfer)) + { + iopkt[0] = a2reqlist->type; + write(a2fd, iopkt, 1); + } + else + { + //printf("a2pid: finish request 0x%02X:0x%02X\n", (unsigned char)iopkt[0], (unsigned char)iopkt[1]); + finreq(a2fd, (unsigned char)iopkt[0], (unsigned char)iopkt[1]); + } + } + else + state = RESET; + break; + case 0xC5: /* virtual drive request */ + //printf("a2pid: vdrive request\n"); + newtio.c_cc[VMIN] = 1; /* blocking read until command packet received */ + tcsetattr(a2fd, TCSANOW, &newtio); + if (read(a2fd, &iopkt[3], 1) + read(a2fd, &iopkt[4], 1) == 2) + { + //printf("vdrive cmd:%02X blk:%d crc:%02X\n", iopkt[1], iopkt[2] | (iopkt[3] << 8), iopkt[4]); + vdrivecmd(a2fd, iopkt[1], iopkt[2] | (iopkt[3] << 8), iopkt[4]); + } + else + state = RESET; + newtio.c_cc[VMIN] = 3; /* blocking read until 3 chars received */ + tcsetattr(a2fd, TCSANOW, &newtio); + if (a2reqlist) /* resend last request */ + write(a2fd, &a2reqlist->type, 1); + break; + default: + prlog("a2pid: Unknown Event\n"); + tcflush(a2fd, TCIFLUSH); + //stop = TRUE; + } + } + else + { + prlog("a2pid: error read serial port ????\n"); + state = STOP; + } + } + /* + * Open client connection. + */ + if (FD_ISSET(srvfd, &readset)) + { + rdycnt--; + int clientfd = accept(srvfd, NULL, NULL); + 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 + prlog("a2pid: error accept"); + } + /* + * Socket client request. + */ + for (i = 0; rdycnt > 0 && i < MAX_CLIENT; i++) + { + if (a2client[i].flags && FD_ISSET(a2client[i].fd, &readset)) + { + int addr, count; + char *databuf; + rdycnt--; + if (read(a2client[i].fd, iopkt, 1) == 1) + { + // printf("a2pi: Client Request [0x%02X]\n", iopkt[0]); + switch (iopkt[0]) + { + case 0x90: /* read bytes */ + if (read(a2client[i].fd, 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); + addreq(a2fd, i, 0x90, addr, count, databuf); + } + else + { + iopkt[0] = 0x9E; + iopkt[1] = 0x00; + write(a2client[i].fd, iopkt, 2); + } + } + break; + case 0x92: /* write bytes */ + if (read(a2client[i].fd, 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); + 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; + case 0x94: /* call */ + case 0x9A: /* call with keyboard flush */ + if (read(a2client[i].fd, iopkt + 1, 2) == 2) + { + addr = (unsigned char)iopkt[1] | ((unsigned char)iopkt[2] << 8); + addreq(a2fd, i, iopkt[0], addr, 0, NULL); + } + break; + case 0x96: /* send input char to Apple II */ + if (read(a2client[i].fd, iopkt, 1) == 1) + addreq(a2fd, i, 0x96, iopkt[0], 0, NULL); + break; + case 0x98: /* get output chars from Apple II */ + a2client[i].flags |= CLIENT_COUT; + break; + case 0xC0: /* reconnect VDRIVEs */ + vdriveclose(); + vdriveactive = vdriveopen(vdrivedir); + iopkt[0]++; /* ack */ + write(a2client[i].fd, iopkt, 1); + break; + case 0xC2: /* disconnect VDRIVEs */ + vdriveclose(); + vdriveactive = 0; + iopkt[0]++; /* ack */ + write(a2client[i].fd, iopkt, 1); + break; + case 0xFF: /* close */ + a2client[i].flags = CLIENT_CLOSING; + break; + default: + prlog("a2pid: Unknown Request\n"); + } + } + else + { + /* + * Close client socket connection. + */ + FD_CLR(a2client[i].fd, &openset); + close(a2client[i].fd); + if (a2client[i].fd >= maxfd) + maxfd = 0; + a2client[i].fd = 0; + a2client[i].flags = 0; + flushreqs(a2fd, i, -1, -1); + } + } + } + } } flushreqs(a2fd, -1, -1, -1); for (i = 0; i < MAX_CLIENT; i++) - if (a2client[i].flags) - close(a2client[i].fd); + if (a2client[i].flags) + close(a2client[i].fd); if (state == RESET) - goto reset; - if (vdriveactive) - vdriveclose(); + goto reset; + vdriveclose(); shutdown(srvfd, SHUT_RDWR); close(srvfd); tcsetattr(a2fd, TCSANOW, &oldtio); diff --git a/src/a2pidcmd.c b/src/a2pidcmd.c new file mode 100755 index 0000000..6bb9d6e --- /dev/null +++ b/src/a2pidcmd.c @@ -0,0 +1,22 @@ +#include "a2lib.c" + +int main(int argc, char **argv) +{ + unsigned char cmd, ack; + int pifd = a2open(argc > 3 ? argv[3] : "127.0.0.1"); + if (pifd < 0) + { + perror("Unable to connect to Apple II Pi"); + exit(EXIT_FAILURE); + } + if (argc < 2) + { + perror("Usage: a2picmd \n"); + exit(EXIT_FAILURE); + } + cmd = (int)strtol(argv[1], NULL, 0); /* treat command as value */ + write(pifd, &cmd, 1); + read(pifd, &ack, 1); + a2close(pifd); + return ack == (cmd + 1); +} diff --git a/src/a2setvd b/src/a2setvd new file mode 100755 index 0000000..f2e41cc --- /dev/null +++ b/src/a2setvd @@ -0,0 +1,6 @@ +#!/bin/bash +a2pidcmd 0xC2 +rm /usr/share/a2pi/A2VD$1.PO +ln -s $2 /usr/share/a2pi/A2VD$1.PO +a2pidcmd 0xC0 + diff --git a/src/fusea2pi.c b/src/fusea2pi.c index a790fa2..7df5126 100755 --- a/src/fusea2pi.c +++ b/src/fusea2pi.c @@ -1036,7 +1036,7 @@ static int a2pi_mkdir(const char *path, mode_t mode) return -EACCES; A2PI_WAIT; cachepath[0] = '\0'; - err = prodos_map_errno(prodos_create(prodos_path(path, NULL, NULL, NULL), 0xE3, 0x0F, 0, 0)); + err = prodos_map_errno(prodos_create(prodos_path(path, NULL, NULL, NULL), 0xC3, 0x0F, 0, 0)); A2PI_RELEASE; return err; }