summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--taptoser.c207
1 files changed, 201 insertions, 6 deletions
diff --git a/taptoser.c b/taptoser.c
index dd53d19..87c9f15 100644
--- a/taptoser.c
+++ b/taptoser.c
@@ -3,6 +3,7 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
+#include <stdint.h>
#include <getopt.h>
#include <termios.h>
#include <error.h>
@@ -40,6 +41,27 @@ struct sigaction saterm; /* definition of signal action */
float width; // width of terminal
long pos = 0;
+int scp = 0;
+int is_scp_read = 0;
+
+typedef struct {
+ uint16_t block_len;
+ uint8_t block_xor;
+ uint8_t block_sum;
+} __attribute__((packed)) fi_sum;
+
+typedef struct {
+ uint16_t length; // delka dat ve fileinfo
+ uint8_t h_xor; // xor bajtu fileinfa od fi_numblocks
+ uint8_t h_sum; // sum bajtu fileinfa od fi_numblocks
+ uint8_t fi_numblocks; // pocet bloku
+ uint8_t fi_name[64]; // jmeno souboru - prozatim musi byt ve fromatu 8.3 - kvuli esxdosu
+ uint8_t fi_date[8]; // nepouzito
+ uint8_t fi_time[8]; // nepouzito
+ fi_sum fi_blocks[256]; // delky a soucty bloku
+} __attribute__((packed)) FILEINFO;
+
+FILEINFO fileinfo;
void usage(void) {
@@ -88,12 +110,14 @@ void TestArgs (int argc, char *argv[])
{"device", required_argument, NULL, 'd'},
{"baud", required_argument, NULL, 'b'},
{"wait", required_argument, NULL, 'w'},
+ {"scp", no_argument, NULL, 's'},
+ {"read", no_argument, NULL, 'r'},
{"binary", no_argument, NULL, 'B'},
{"version", no_argument, NULL, 'v'},
{"help", no_argument, NULL, 'h'},
{0, 0, 0, 0}
};
- c = getopt_long (argc, argv, "o:d:b:w:Bvh", long_options, &option_index);
+ c = getopt_long (argc, argv, "o:d:b:w:srBvh", long_options, &option_index);
if (c == -1) {
// konec parametru
break;
@@ -109,6 +133,14 @@ void TestArgs (int argc, char *argv[])
case 'w':
wait_us = atoi(optarg);
break;
+ case 's':
+ printf ("Serial CP mode is activated\n");
+ scp = 1;
+ break;
+ case 'r':
+ printf ("scp read...\n");
+ is_scp_read = 1;
+ break;
case 'd':
strncpy(MODEMDEVICE, optarg, strlen(optarg));
// printf ("Serial port: %s\n", MODEMDEVICE);
@@ -408,6 +440,160 @@ void SendTap() {
}
+int CheckFileInfo(FILEINFO* p_fi) {
+ unsigned char *p_fiinfo = (unsigned char*)p_fi;
+ uint16_t fi_len;
+ uint8_t fi_xor = 0;
+ uint8_t fi_sum = 0;
+ fi_len = p_fi->length;
+ p_fiinfo += 4; // suma se bude pocitat od offsetu 4
+ for (uint16_t indx = 0; indx < (fi_len-4); indx++) {
+ fi_xor ^= *p_fiinfo;
+ fi_sum += *p_fiinfo;
+ p_fiinfo++;
+ }
+ if (fi_xor == p_fi->h_xor && fi_sum == p_fi->h_sum) {
+ return 0;
+ }
+ return -1;
+}
+
+int CheckSumBlock(FILEINFO* p_fi, uint8_t block_indx, uint8_t *p_buffer) {
+ uint16_t block_len;
+ uint8_t b_xor = 0;
+ uint8_t b_sum = 0;
+ uint8_t block_xor;
+ uint8_t block_sum;
+ block_len = p_fi->fi_blocks[block_indx].block_len;
+ block_sum = p_fi->fi_blocks[block_indx].block_sum;
+ block_xor = p_fi->fi_blocks[block_indx].block_xor;
+ for (uint16_t indx = 0; indx < block_len; indx++) {
+ b_xor ^= *p_buffer;
+ b_sum += *p_buffer;
+ p_buffer++;
+ }
+ if (b_xor == block_xor && b_sum == block_sum) {
+ return 0; // vrat se, je to v poradku
+ }
+ return -1; // vrat se s chybou bloku
+}
+
+unsigned char buff[32768];
+
+uint32_t GetOverallLen(FILEINFO *p_fi) {
+ uint32_t overall_len = 0;
+ uint8_t block_num = p_fi->fi_numblocks;
+ for (uint8_t indx = 0; indx < block_num; indx++) {
+ overall_len += p_fi->fi_blocks[indx].block_len;
+ }
+ return overall_len;
+}
+
+void RecvSCP(void) {
+ int recv_phase = 0; // 0 - fileinfo, 1 - blok 16kiB, 2 - posledni blok
+ uint8_t block_index = 0;
+ int result;
+ uint16_t len;
+ uint16_t length = 0;
+ uint16_t expected_len = 0;
+// uint8_t expected_xor;
+// uint8_t expected_sum;
+ uint32_t overall_length = 0; // celkova delka souboru
+ uint32_t recv_length = 0; // zatim prijatych dat ze souboru
+ int err;
+
+ FILEINFO *p_fileinfo = &fileinfo;
+ unsigned char *p_buff = buff;
+ tapout_fd = NULL;
+
+ memset (p_fileinfo, 0, sizeof(fileinfo));
+ while (is_continue) {
+ result = poll (spolfd_serial, 1, 200); // 200ms timeout
+ if (result == 0) {
+ // nic neprislo
+ continue;
+ }
+ switch (recv_phase) {
+ case 0:
+ // prijem fileinfo
+ if (spolfd_serial[0].revents & POLLIN) {
+ len = read (serial_fd, p_buff, sizeof(fileinfo));
+ p_buff += len;
+ length += len;
+ if (length == sizeof(fileinfo)) {
+ memcpy((unsigned char*) p_fileinfo, buff, sizeof(fileinfo));
+ if (CheckFileInfo(p_fileinfo) == 0) {
+ printf("Prijato fileinfo\n");
+ overall_length = GetOverallLen(p_fileinfo);
+ printf("Nazev souboru: \"%s\" pocet bloku:%d, delka souboru: %u\n", p_fileinfo->fi_name, p_fileinfo->fi_numblocks, overall_length);
+ recv_phase++; // priste se uz prijimaji bloky
+ block_index = 0; // zacina se prvnim blokem
+ p_buff = buff; // buffer na zacatek
+ length = 0;
+ expected_len = p_fileinfo->fi_blocks[block_index].block_len;
+
+
+ tapout_fd = fopen ((char*)p_fileinfo->fi_name, "w");
+ if (tapout_fd == NULL) {
+ err = errno;
+ error (1, err, "can't open output file");
+ }
+// expected_xor = p_fileinfo->fi_blocks[block_index].block_xor;
+// expected_sum = p_fileinfo->fi_blocks[block_index].block_sum;
+ } else {
+ printf("Fileinfo neni v cajku. Koncim...\n");
+ break;
+ }
+ break;
+ } else if (length > sizeof(fileinfo)){
+ len = read (serial_fd, p_buff, sizeof(fileinfo));
+ printf("Nejaky bordel. Koncim...\n");
+ break;
+ }
+ }
+ break;
+ case 1:
+ // prijem datoveho bloku - max. delka 16kiB
+ if (spolfd_serial[0].revents & POLLIN) {
+ len = read (serial_fd, p_buff, expected_len);
+ p_buff += len;
+ expected_len -= len;
+ length += len;
+ recv_length += len;
+ DoProgress(recv_length, overall_length, PROGRESS_PERCENT);
+ if (length == p_fileinfo->fi_blocks[block_index].block_len) {
+ // prijaty prvni block
+// printf("Prijaty blok c.%d delky: %d\n", block_index, length);
+ if (CheckSumBlock(p_fileinfo, block_index, buff) == 0) {
+ // blok je v cajku - zapsat do souboru
+ if (tapout_fd) fwrite(buff, length, 1, tapout_fd);
+ }
+ length = 0;
+ p_buff = buff;
+ block_index++;
+ expected_len = p_fileinfo->fi_blocks[block_index].block_len;
+ }
+ if (expected_len == 0 || block_index == 255) {
+ printf ("\nKonec prenosu\n");
+ recv_phase++;
+ is_continue = 0;
+ break;
+ }
+ } else if (length > 16384) {
+ len = read (serial_fd, p_buff, 16384);
+ printf("Nejaky bordel. Koncim...\n");
+ break;
+ }
+ }
+ }
+ if (tapout_fd) fclose (tapout_fd);
+ printf ("\n\nulozeno...\n");
+}
+
+void SendSCP(void) {
+
+}
+
int main(int argc, char** argv, char** env)
{
// osetreni breaku ^C
@@ -444,7 +630,7 @@ int main(int argc, char** argv, char** env)
newtio.c_cflag = B57600 | CS8 | CLOCAL | CREAD | CSTOPB | CRTSCTS;
break;
case 38400:
- newtio.c_cflag = B38400 | CS8 | CLOCAL | CREAD | CSTOPB | CRTSCTS; // dva stopbity jsou nastaveny vsude
+ newtio.c_cflag = B38400 | CS8 | CLOCAL | CREAD | CRTSCTS; // dva stopbity jsou nastaveny vsude
break;
case 19200:
newtio.c_cflag = B19200 | CS8 | CLOCAL | CREAD | CSTOPB | CRTSCTS;
@@ -475,11 +661,20 @@ int main(int argc, char** argv, char** env)
spolfd_serial[0].fd = serial_fd; // nastaveni hlidaneho descriptoru
spolfd_serial[0].events = POLLIN; // hlidaji se data na vstupu
- Set_DTR(true); // PC can read data from speccy everytime
- if (is_outfile) {
- RecvTap(); // cteni tap souboru ze seriaku a zapis na disk pocitace
+ if (scp) {
+ // serial copy activated
+ if (is_scp_read) {
+ RecvSCP();
+ } else {
+ SendSCP();
+ }
} else {
- SendTap(); // poslat na seriak tap soubor do spectra
+ Set_DTR(true); // PC can read data from speccy everytime
+ if (is_outfile) {
+ RecvTap(); // cteni tap souboru ze seriaku a zapis na disk pocitace
+ } else {
+ SendTap(); // poslat na seriak tap soubor do spectra
+ }
}
close (serial_fd);
return 0;