FUSE fixes and updates for virtual drives

This commit is contained in:
dschmenk 2014-02-08 10:50:56 -08:00
parent 2aec13ef83
commit d8bf70b34d
8 changed files with 590 additions and 559 deletions

2
debian/changelog vendored
View File

@ -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

12
debian/postinst vendored
View File

@ -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
#

View File

@ -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)

View File

@ -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;
vdrivefd[1] = 0;
return vdrivefd[0] + vdrivefd[1];
}
prlog("vdrive: opened successfully\n");
return 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 ???
@ -509,8 +508,7 @@ void sendkeycodeup(int fd, int code)
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)
{
@ -544,8 +542,7 @@ void sendbttn(int fd, int mod, int bttn)
if (bttn)
{
lastbtn =
evkey.code = (mod == 0) ? BTN_LEFT
lastbtn = evkey.code = (mod == 0) ? BTN_LEFT
: (mod & 0x40) ? BTN_RIGHT
: BTN_MIDDLE;
evkey.value = 1;
@ -857,6 +854,28 @@ 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.
*/
@ -875,13 +894,6 @@ 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)
@ -905,21 +917,6 @@ void main(int argc, char **argv)
}
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.
*/
@ -1097,25 +1094,19 @@ reset:
break;
case 0xC5: /* virtual drive request */
//printf("a2pid: vdrive request\n");
if (vdriveactive)
{
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]);
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");
}
else
state = RESET;
newtio.c_cc[VMIN] = 3; /* blocking read until 3 chars received */
tcsetattr(a2fd, TCSANOW, &newtio);
}
else
state = RESET;
if (a2reqlist) /* resend last request */
write(a2fd, &a2reqlist->type, 1);
break;
default:
prlog("a2pid: Unknown Event\n");
@ -1226,6 +1217,18 @@ reset:
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;
@ -1256,7 +1259,6 @@ reset:
close(a2client[i].fd);
if (state == RESET)
goto reset;
if (vdriveactive)
vdriveclose();
shutdown(srvfd, SHUT_RDWR);
close(srvfd);

22
src/a2pidcmd.c Executable file
View File

@ -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 <cmd>\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);
}

6
src/a2setvd Executable file
View File

@ -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

View File

@ -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;
}