From 8172e4dce76de057df2a5d14e53b0b5d0f76f334 Mon Sep 17 00:00:00 2001 From: Jan Krupa Date: Sat, 3 Feb 2024 02:53:13 +0100 Subject: [PATCH] [atari][pclink] merge FN-PC and FN-ESP PCLink code --- data/webui/config/fujiapple-iec.yaml | 1 + data/webui/config/fujiapple-rev0.yaml | 1 + data/webui/config/fujiloaf-rev0.yaml | 1 + data/webui/config/fujinet-adam-v1.yaml | 1 + data/webui/config/fujinet-atari-v1.yaml | 1 + data/webui/config/fujinet-cx16.yaml | 1 + data/webui/config/fujinet-heathkit-h89.yaml | 1 + data/webui/config/fujinet-iec.yaml | 1 + data/webui/config/fujinet-lynx-devkitc.yaml | 1 + data/webui/config/fujinet-lynx-prototype.yaml | 1 + data/webui/config/fujinet-pc-atari.yaml | 1 + data/webui/config/fujinet-rc2014spi-rev0.yaml | 1 + data/webui/config/fujinet-rs232-rev0.yaml | 1 + data/webui/config/fujinet-v1-4mb.yaml | 1 + data/webui/config/fujinet-v1-8mb.yaml | 1 + data/webui/config/fujinet-v1.yaml | 1 + data/webui/config/lolin-d32-iec.yaml | 1 + data/webui/template/www/index.tmpl.html | 188 +++++++----- data/webui/template/www/js/settings.tmpl.js | 4 + lib/bus/sio/siocom/netsio.cpp | 4 +- lib/config/fnConfig.h | 3 + lib/config/fnc_enable.cpp | 16 + lib/config/fnc_save.cpp | 1 + lib/device/device.h | 6 +- lib/device/sio/pclink.cpp | 279 +++++++++++------- lib/device/sio/pclink.h | 5 +- lib/http/httpServiceConfigurator.cpp | 11 + lib/http/httpServiceConfigurator.h | 1 + lib/http/httpServiceParser.cpp | 7 +- src/main.cpp | 13 +- 30 files changed, 370 insertions(+), 185 deletions(-) diff --git a/data/webui/config/fujiapple-iec.yaml b/data/webui/config/fujiapple-iec.yaml index ece2c5c11..23416e289 100644 --- a/data/webui/config/fujiapple-iec.yaml +++ b/data/webui/config/fujiapple-iec.yaml @@ -16,5 +16,6 @@ components: disk_swap: true boot_settings: true apetime: false + pclink: false tweaks: # webui tweaks, if any diff --git a/data/webui/config/fujiapple-rev0.yaml b/data/webui/config/fujiapple-rev0.yaml index 777b30d9e..e16783027 100644 --- a/data/webui/config/fujiapple-rev0.yaml +++ b/data/webui/config/fujiapple-rev0.yaml @@ -17,5 +17,6 @@ components: boot_settings: true apetime: false cpm_settings: true + pclink: false tweaks: # webui tweaks, if any diff --git a/data/webui/config/fujiloaf-rev0.yaml b/data/webui/config/fujiloaf-rev0.yaml index ece2c5c11..23416e289 100644 --- a/data/webui/config/fujiloaf-rev0.yaml +++ b/data/webui/config/fujiloaf-rev0.yaml @@ -16,5 +16,6 @@ components: disk_swap: true boot_settings: true apetime: false + pclink: false tweaks: # webui tweaks, if any diff --git a/data/webui/config/fujinet-adam-v1.yaml b/data/webui/config/fujinet-adam-v1.yaml index 0d325f37e..caf4581a7 100644 --- a/data/webui/config/fujinet-adam-v1.yaml +++ b/data/webui/config/fujinet-adam-v1.yaml @@ -16,5 +16,6 @@ components: disk_swap: true boot_settings: true apetime: false + pclink: false tweaks: # webui tweaks, if any diff --git a/data/webui/config/fujinet-atari-v1.yaml b/data/webui/config/fujinet-atari-v1.yaml index 413202a2b..db84a5366 100644 --- a/data/webui/config/fujinet-atari-v1.yaml +++ b/data/webui/config/fujinet-atari-v1.yaml @@ -18,5 +18,6 @@ components: boot_settings: true apetime: true cpm_settings: true + pclink: true tweaks: # webui tweaks, if any diff --git a/data/webui/config/fujinet-cx16.yaml b/data/webui/config/fujinet-cx16.yaml index d899bfe5e..6103b49b5 100644 --- a/data/webui/config/fujinet-cx16.yaml +++ b/data/webui/config/fujinet-cx16.yaml @@ -16,5 +16,6 @@ components: disk_swap: true boot_settings: true apetime: false + pclink: false tweaks: # webui tweaks, if any diff --git a/data/webui/config/fujinet-heathkit-h89.yaml b/data/webui/config/fujinet-heathkit-h89.yaml index 0d325f37e..caf4581a7 100644 --- a/data/webui/config/fujinet-heathkit-h89.yaml +++ b/data/webui/config/fujinet-heathkit-h89.yaml @@ -16,5 +16,6 @@ components: disk_swap: true boot_settings: true apetime: false + pclink: false tweaks: # webui tweaks, if any diff --git a/data/webui/config/fujinet-iec.yaml b/data/webui/config/fujinet-iec.yaml index ece2c5c11..23416e289 100644 --- a/data/webui/config/fujinet-iec.yaml +++ b/data/webui/config/fujinet-iec.yaml @@ -16,5 +16,6 @@ components: disk_swap: true boot_settings: true apetime: false + pclink: false tweaks: # webui tweaks, if any diff --git a/data/webui/config/fujinet-lynx-devkitc.yaml b/data/webui/config/fujinet-lynx-devkitc.yaml index d899bfe5e..6103b49b5 100644 --- a/data/webui/config/fujinet-lynx-devkitc.yaml +++ b/data/webui/config/fujinet-lynx-devkitc.yaml @@ -16,5 +16,6 @@ components: disk_swap: true boot_settings: true apetime: false + pclink: false tweaks: # webui tweaks, if any diff --git a/data/webui/config/fujinet-lynx-prototype.yaml b/data/webui/config/fujinet-lynx-prototype.yaml index d899bfe5e..6103b49b5 100644 --- a/data/webui/config/fujinet-lynx-prototype.yaml +++ b/data/webui/config/fujinet-lynx-prototype.yaml @@ -16,5 +16,6 @@ components: disk_swap: true boot_settings: true apetime: false + pclink: false tweaks: # webui tweaks, if any diff --git a/data/webui/config/fujinet-pc-atari.yaml b/data/webui/config/fujinet-pc-atari.yaml index 2dcadc28a..bcb4801ff 100644 --- a/data/webui/config/fujinet-pc-atari.yaml +++ b/data/webui/config/fujinet-pc-atari.yaml @@ -20,6 +20,7 @@ components: serial_port: true emulator_settings: true cpm_settings: true + pclink: true tweaks: # webui tweaks, if any fujinet_pc: true diff --git a/data/webui/config/fujinet-rc2014spi-rev0.yaml b/data/webui/config/fujinet-rc2014spi-rev0.yaml index 0d325f37e..caf4581a7 100644 --- a/data/webui/config/fujinet-rc2014spi-rev0.yaml +++ b/data/webui/config/fujinet-rc2014spi-rev0.yaml @@ -16,5 +16,6 @@ components: disk_swap: true boot_settings: true apetime: false + pclink: false tweaks: # webui tweaks, if any diff --git a/data/webui/config/fujinet-rs232-rev0.yaml b/data/webui/config/fujinet-rs232-rev0.yaml index d899bfe5e..6103b49b5 100644 --- a/data/webui/config/fujinet-rs232-rev0.yaml +++ b/data/webui/config/fujinet-rs232-rev0.yaml @@ -16,5 +16,6 @@ components: disk_swap: true boot_settings: true apetime: false + pclink: false tweaks: # webui tweaks, if any diff --git a/data/webui/config/fujinet-v1-4mb.yaml b/data/webui/config/fujinet-v1-4mb.yaml index 19dd30e98..e2dfd9773 100644 --- a/data/webui/config/fujinet-v1-4mb.yaml +++ b/data/webui/config/fujinet-v1-4mb.yaml @@ -16,5 +16,6 @@ components: disk_swap: true boot_settings: true apetime: true + pclink: true tweaks: # webui tweaks, if any diff --git a/data/webui/config/fujinet-v1-8mb.yaml b/data/webui/config/fujinet-v1-8mb.yaml index 19dd30e98..e2dfd9773 100644 --- a/data/webui/config/fujinet-v1-8mb.yaml +++ b/data/webui/config/fujinet-v1-8mb.yaml @@ -16,5 +16,6 @@ components: disk_swap: true boot_settings: true apetime: true + pclink: true tweaks: # webui tweaks, if any diff --git a/data/webui/config/fujinet-v1.yaml b/data/webui/config/fujinet-v1.yaml index 19dd30e98..e2dfd9773 100644 --- a/data/webui/config/fujinet-v1.yaml +++ b/data/webui/config/fujinet-v1.yaml @@ -16,5 +16,6 @@ components: disk_swap: true boot_settings: true apetime: true + pclink: true tweaks: # webui tweaks, if any diff --git a/data/webui/config/lolin-d32-iec.yaml b/data/webui/config/lolin-d32-iec.yaml index ece2c5c11..23416e289 100644 --- a/data/webui/config/lolin-d32-iec.yaml +++ b/data/webui/config/lolin-d32-iec.yaml @@ -16,5 +16,6 @@ components: disk_swap: true boot_settings: true apetime: false + pclink: false tweaks: # webui tweaks, if any diff --git a/data/webui/template/www/index.tmpl.html b/data/webui/template/www/index.tmpl.html index 7c0c3cb90..3c26bcf84 100644 --- a/data/webui/template/www/index.tmpl.html +++ b/data/webui/template/www/index.tmpl.html @@ -878,6 +878,121 @@

Need help? Go to the +
+
+
+ CP/MSettings +
+
+
+ + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+ +
+
+ +
+
+
+
+
+ Custom CCP must be a valid path on the SD Card
+ Example: /some/directory/custom.ccp
+ Set CCP to $ for default built-in CCP
+
+
+ +
+ +
+
+ + {% endif %} + {% if components.pclink %} +
+
+
+
+ PCLink +
+ +
+
+ +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+ +
+
+
+ {% endif %} {% if components.disk_swap %}
- {% endif %} diff --git a/data/webui/template/www/js/settings.tmpl.js b/data/webui/template/www/js/settings.tmpl.js index 5dea91c11..81711e3cc 100644 --- a/data/webui/template/www/js/settings.tmpl.js +++ b/data/webui/template/www/js/settings.tmpl.js @@ -144,3 +144,7 @@ setSerialProceed(current_serial_proceed); {% if components.emulator_settings %} setInputValue(current_netsio_enabled == 1, "netsio-yes", "netsio-no"); {% endif %} + +{% if components.pclink %} +setInputValue(current_pclink == 1, "pclink-yes", "pclink-no"); +{% endif %} diff --git a/lib/bus/sio/siocom/netsio.cpp b/lib/bus/sio/siocom/netsio.cpp index be7e6ae28..60c874621 100644 --- a/lib/bus/sio/siocom/netsio.cpp +++ b/lib/bus/sio/siocom/netsio.cpp @@ -354,7 +354,7 @@ int NetSioPort::handle_netsio() case NETSIO_DATA_BYTE: b = rxbuf[1]; - if (_baud_peer < _baud * 95 / 100 || _baud_peer > _baud * 105 / 100) + if (_baud_peer < _baud * 90 / 100 || _baud_peer > _baud * 110 / 100) b ^= (uint8_t)_baud_peer ^ (uint8_t)_baud; // corrupt byte if (rxbuffer_put(b)) Debug_println("NetSIO rxbuffer overrun"); @@ -367,7 +367,7 @@ int NetSioPort::handle_netsio() // for (int i = 1; i < received; i++) { b = rxbuf[i]; - if (_baud_peer < _baud * 95 / 100 || _baud_peer > _baud * 105 / 100) + if (_baud_peer < _baud * 90 / 100 || _baud_peer > _baud * 110 / 100) b ^= (uint8_t)_baud_peer ^ (uint8_t)_baud; // corrupt byte if (rxbuffer_put(b)) Debug_println("NetSIO rxbuffer overrun"); diff --git a/lib/config/fnConfig.h b/lib/config/fnConfig.h index 5d5f97f67..d73eb8004 100755 --- a/lib/config/fnConfig.h +++ b/lib/config/fnConfig.h @@ -250,6 +250,8 @@ class fnConfig bool get_apetime_enabled(); void store_apetime_enabled(bool enabled); + bool get_pclink_enabled(); + void store_pclink_enabled(bool enabled); #ifndef ESP_PLATFORM // NETSIO (Connection to Atari emulator) @@ -488,6 +490,7 @@ class fnConfig bool device_7_enabled = true; bool device_8_enabled = true; bool apetime = true; + bool pclink = true; }; struct phbook_info diff --git a/lib/config/fnc_enable.cpp b/lib/config/fnc_enable.cpp index 5b1d52b87..d55d90ece 100644 --- a/lib/config/fnc_enable.cpp +++ b/lib/config/fnc_enable.cpp @@ -127,6 +127,20 @@ void fnConfig::store_apetime_enabled(bool enabled) } } +bool fnConfig::get_pclink_enabled() +{ + return _denable.pclink; +} + +void fnConfig::store_pclink_enabled(bool enabled) +{ + if (_denable.pclink != enabled) + { + _denable.pclink = enabled; + _dirty = true; + } +} + void fnConfig::_read_section_device_enable(std::stringstream &ss) { std::string line; @@ -156,6 +170,8 @@ void fnConfig::_read_section_device_enable(std::stringstream &ss) _denable.device_8_enabled = atoi(value.c_str()); else if (strcasecmp(name.c_str(), "enable_apetime") == 0) _denable.apetime = atoi(value.c_str()); + else if (strcasecmp(name.c_str(), "enable_pclink") == 0) + _denable.pclink = atoi(value.c_str()); } } } diff --git a/lib/config/fnc_save.cpp b/lib/config/fnc_save.cpp index 15186e9f9..a953999e8 100644 --- a/lib/config/fnc_save.cpp +++ b/lib/config/fnc_save.cpp @@ -162,6 +162,7 @@ void fnConfig::save() ss << "enable_device_slot_7=" << _denable.device_7_enabled << LINETERM; ss << "enable_device_slot_8=" << _denable.device_8_enabled << LINETERM; ss << "enable_apetime=" << _denable.apetime << LINETERM; + ss << "enable_pclink=" << _denable.pclink << LINETERM; #ifndef ESP_PLATFORM // SERIAL diff --git a/lib/device/device.h b/lib/device/device.h index aae3b19ed..ad6e1258a 100644 --- a/lib/device/device.h +++ b/lib/device/device.h @@ -5,9 +5,7 @@ # include "sio/apetime.h" # include "sio/cassette.h" # include "sio/disk.h" -# ifndef ESP_PLATFORM -# include "sio/pclink.h" -# endif +# include "sio/pclink.h" # include "sio/udpstream.h" # include "../lib/modem/modem.h" # include "sio/network.h" @@ -27,9 +25,7 @@ // sioCassette sioC; // now part of sioFuji theFuji object modem *sioR; sioCPM sioZ; -# ifndef ESP_PLATFORM sioPCLink pcLink; -# endif #endif // BUILD_ATARI #ifdef BUILD_COCO diff --git a/lib/device/sio/pclink.cpp b/lib/device/sio/pclink.cpp index 4215ee58c..9180a03be 100644 --- a/lib/device/sio/pclink.cpp +++ b/lib/device/sio/pclink.cpp @@ -1,5 +1,3 @@ -#ifndef ESP_PLATFORM - #ifdef BUILD_ATARI /* @@ -23,6 +21,11 @@ #include "compat_dirent.h" +#include "modem.h" +#include "utils.h" +#include "fnConfig.h" +#include "fnSystem.h" + #include "pclink.h" #include "../../include/debug.h" @@ -164,8 +167,8 @@ static DEVICE device[16]; /* one PCLINK device with 16 units */ # define COM_DATA 1 static void pclink_ack(ushort devno, ushort d, uchar what); -static void com_read(uchar *buf, int size, const ushort type); -static void com_write(uchar *buf, int size); +static uint8_t pclink_read(uint8_t *buf, int len); +static void pclink_write(uint8_t *buf, int len); /* Calculate Atari-style CRC for the given buffer */ @@ -719,6 +722,28 @@ set_status_size(uchar devno, uchar cunit, ushort size) device[cunit].status.none = (size & 0xff00) >> 8; } +#ifdef ESP_PLATFORM +static int +validate_user_path(char *defwd, char *newpath) +{ + char *d; + struct stat st; + + d = strstr(newpath, defwd); + if (d == NULL || d != newpath) + return 0; + d = newpath + strlen(defwd); + if (*d != '\0' && *d != '/') + return 0; + + if (stat(newpath, &st) < 0) + return 0; + if (!S_ISDIR(st.st_mode)) + return 0; + + return 1; +} +#else static int validate_user_path(char *defwd, char *newpath) { @@ -755,6 +780,7 @@ abs_path(const char *path, char *abspath, int size) return 0; return 1; } +#endif static int ispathsep(uchar c) @@ -837,6 +863,9 @@ create_user_path(uchar devno, uchar cunit, char *newpath) } strcat(newpath, (char *)upath); sl = strlen(newpath); + // resolve ".." and "." + strcpy(newpath, util_get_canonical_path(std::string(newpath)).c_str()); + sl = strlen(newpath); if (sl && (newpath[sl-1] == '/')) newpath[sl-1] = 0; } @@ -906,11 +935,8 @@ do_pclink(uchar devno, uchar ccom, uchar caux1, uchar caux2) pclink_ack(devno, cunit, 'a'); /* ack the command (late_ack) */ memset(&pbuf, 0, sizeof(PARBUF)); - - com_read((uchar *)&pbuf, (int)parsize, COM_DATA); - com_read(&sck, 1, COM_DATA); - - ck = calc_checksum((uchar *)&pbuf, (int)parsize); + sck = pclink_read((uchar *)&pbuf, (int)parsize); // read data + checksum byte + ck = calc_checksum((uchar *)&pbuf, (int)parsize); // calculate checksum from data device[cunit].status.stat &= ~0x02; @@ -920,24 +946,8 @@ do_pclink(uchar devno, uchar ccom, uchar caux1, uchar caux2) { device[cunit].status.stat |= 0x02; Debug_printf("PARBLK CRC error, Atari: $%02x, PC: $%02x\n", sck, ck); - -# if 0 - Debug_printf("PARBLK size %d, dump:\n", (int)parsize); - { - int dumpi; - uchar *dumpp = (uchar *)&pbuf; - - for (dumpi = 0; dumpi < parsize; dumpi++) - { - Debug_printf("%02x ", dumpp[dumpi]); - } - Debug_printf("\n"); - } -# endif - device[cunit].status.err = 143; goto complete; -// goto exit; } Debug_printf("PARBLK size %d, dump: ", (int)parsize); @@ -949,12 +959,14 @@ do_pclink(uchar devno, uchar ccom, uchar caux1, uchar caux2) { Debug_printf("%02x ", dumpp[dumpi]); } - //Debug_printf("\n"); +#ifdef ESP_PLATFORM + Debug_printf("\n"); +#endif } device[cunit].status.stat &= ~0x04; -# if 1 +# if 0 /* True if Atari didn't catch the ACK above and retried the command */ if (pbuf.fno > PCL_MAX_FNO) { @@ -1047,7 +1059,8 @@ do_pclink(uchar devno, uchar ccom, uchar caux1, uchar caux2) Debug_printf("handle %d\n", handle); - mem = (uchar*)malloc(blk_size + 1); + //mem = (uchar*)malloc(blk_size + 1); + mem = (uchar*)malloc(blk_size); if (device[cunit].status.err == 1) { @@ -1118,10 +1131,11 @@ do_pclink(uchar devno, uchar ccom, uchar caux1, uchar caux2) Debug_printf("FREAD: send $%04lx (%ld), status $%02x\n", blk_size, blk_size, device[cunit].status.err); - sck = calc_checksum(mem, blk_size); - mem[blk_size] = sck; + //sck = calc_checksum(mem, blk_size); + //mem[blk_size] = sck; pclink_ack(devno, cunit, 'C'); - com_write(mem, blk_size + 1); + //com_write(mem, blk_size + 1); + pclink_write(mem, blk_size); // write data + checksum byte free(mem); @@ -1177,15 +1191,14 @@ do_pclink(uchar devno, uchar ccom, uchar caux1, uchar caux2) } } - mem = (uchar*)malloc(blk_size + 1); + //mem = (uchar*)malloc(blk_size + 1); + mem = (uchar*)malloc(blk_size); - com_read(mem, blk_size, COM_DATA); - com_read(&sck, sizeof(uchar), COM_DATA); + sck = pclink_read(mem, blk_size); // read data + checksum byte + ck = calc_checksum(mem, blk_size); // calculate checksum from data pclink_ack(devno, cunit, 'A'); /* ack the block of data */ - ck = calc_checksum(mem, blk_size); - if (ck != sck) { Debug_printf("FWRITE: block CRC mismatch (sent $%02x, calculated $%02x)\n", sck, ck); @@ -1266,7 +1279,8 @@ do_pclink(uchar devno, uchar ccom, uchar caux1, uchar caux2) if ((fno == 0x03) || (fno == 0x04)) /* FTELL/FLEN */ { ulong outval = 0; - uchar out[4]; + //uchar out[4]; + uchar out[3]; if (ccom == 'P') { @@ -1296,9 +1310,10 @@ do_pclink(uchar devno, uchar ccom, uchar caux1, uchar caux2) out[1] = (uchar)((outval & 0x0000ff00L) >> 8); out[2] = (uchar)((outval & 0x00ff0000L) >> 16); - out[3] = calc_checksum(out, sizeof(out)-1); + //out[3] = calc_checksum(out, sizeof(out)-1); pclink_ack(devno, cunit, 'C'); - com_write(out, sizeof(out)); + //com_write(out, sizeof(out)); + pclink_write(out, sizeof(out)); // write data + checksum byte goto exit; } @@ -1381,10 +1396,11 @@ do_pclink(uchar devno, uchar ccom, uchar caux1, uchar caux2) pcl_dbf.dirbuf[17], pcl_dbf.dirbuf[18], pcl_dbf.dirbuf[19], pcl_dbf.dirbuf[20], pcl_dbf.dirbuf[21], pcl_dbf.dirbuf[22]); - sck = calc_checksum((uchar *)&pcl_dbf, sizeof(pcl_dbf)); + //sck = calc_checksum((uchar *)&pcl_dbf, sizeof(pcl_dbf)); pclink_ack(devno, cunit, 'C'); - com_write((uchar *)&pcl_dbf, sizeof(pcl_dbf)); - com_write(&sck, 1); + //com_write((uchar *)&pcl_dbf, sizeof(pcl_dbf)); + //com_write(&sck, 1); + pclink_write((uchar *)&pcl_dbf, sizeof(pcl_dbf)); // write data + checksum byte goto exit; } @@ -1789,10 +1805,11 @@ do_pclink(uchar devno, uchar ccom, uchar caux1, uchar caux2) } complete_fopen: - sck = calc_checksum((uchar *)&pcl_dbf, sizeof(pcl_dbf)); + //sck = calc_checksum((uchar *)&pcl_dbf, sizeof(pcl_dbf)); pclink_ack(devno, cunit, 'C'); - com_write((uchar *)&pcl_dbf, sizeof(pcl_dbf)); - com_write(&sck, 1); + //com_write((uchar *)&pcl_dbf, sizeof(pcl_dbf)); + //com_write(&sck, 1); + pclink_write((uchar *)&pcl_dbf, sizeof(pcl_dbf)); // write data + checksum byte goto exit; } @@ -2045,11 +2062,14 @@ do_pclink(uchar devno, uchar ccom, uchar caux1, uchar caux2) newmode |= S_IWUSR; if (fatr2 & SA_PROTECT) newmode &= ~S_IWUSR; + // TODO - chmod is not available on platformio +#ifndef ESP_PLATFORM if (chmod(xpath, newmode)) { Debug_printf("CHMOD: failed on '%s'\n", xpath); device[cunit].status.err |= 255; } +#endif fcnt++; } } @@ -2127,6 +2147,7 @@ do_pclink(uchar devno, uchar ccom, uchar caux1, uchar caux2) Debug_printf("MKDIR: setting timestamp in '%s'\n", newpath); # endif + utime(newpath, &ub); } } goto complete; @@ -2211,7 +2232,7 @@ do_pclink(uchar devno, uchar ccom, uchar caux1, uchar caux2) if (fno == 0x10) /* CHDIR */ { ulong i; - char newpath[1024], newwd[1024], oldwd[1024]; + char newpath[1024]; if (ccom == 'R') { @@ -2221,9 +2242,10 @@ do_pclink(uchar devno, uchar ccom, uchar caux1, uchar caux2) goto complete; } -// Debug_printf("req. path '%s'\n", device[cunit].parbuf.path); + Debug_printf("req. path '%s'\n", device[cunit].parbuf.path); create_user_path(devno, cunit, newpath); + Debug_printf("newpath '%s'\n", newpath); if (!validate_user_path(device[cunit].dirname, newpath)) { @@ -2232,29 +2254,16 @@ do_pclink(uchar devno, uchar ccom, uchar caux1, uchar caux2) goto complete; } - (void)getcwd(oldwd, sizeof(oldwd)); + // chdir and getcwd not implemented on platformio (as of July 2023) + // https://github.com/espressif/esp-idf/issues/8540 - if (chdir(newpath)) - { - Debug_printf("cannot access '%s', %s\n", newpath, strerror(errno)); - device[cunit].status.err = 150; - goto complete; - } - - (void)getcwd(newwd, sizeof(newwd)); - -# if 0 - Debug_printf("newwd %s\n", newwd); -# endif /* validate_user_path() guarantees that .dirname is part of newwd */ i = strlen(device[cunit].dirname); - strcpy((char *)device[cunit].cwd, newwd + i); + strcpy((char *)device[cunit].cwd, newpath + i); Debug_printf("new current dir '%s'\n", (char *)device[cunit].cwd); device[cunit].status.err = 1; - (void)chdir(oldwd); - goto complete; } @@ -2289,10 +2298,11 @@ do_pclink(uchar devno, uchar ccom, uchar caux1, uchar caux2) Debug_printf("send '%s'\n", tempcwd); - sck = calc_checksum(tempcwd, sizeof(tempcwd)-1); + //sck = calc_checksum(tempcwd, sizeof(tempcwd)-1); pclink_ack(devno, cunit, 'C'); - com_write(tempcwd, sizeof(tempcwd)-1); - com_write(&sck, sizeof(sck)); + //com_write(tempcwd, sizeof(tempcwd)-1); + //com_write(&sck, sizeof(sck)); + pclink_write(tempcwd, sizeof(tempcwd)-1); // write data + checksum byte goto exit; } @@ -2303,7 +2313,7 @@ do_pclink(uchar devno, uchar ccom, uchar caux1, uchar caux2) int x; uchar c = 0, volname[8]; char lpath[1024]; - static uchar dfree[65] = + static uchar dfree[64] = { 0x21, /* data format version */ 0x00, 0x00, /* main directory ptr */ @@ -2328,7 +2338,7 @@ do_pclink(uchar devno, uchar ccom, uchar caux1, uchar caux2) 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0, - 0 /* CRC */ + //0 /* CRC */ }; device[cunit].status.err = 1; @@ -2402,9 +2412,10 @@ do_pclink(uchar devno, uchar ccom, uchar caux1, uchar caux2) Debug_printf("DFREE: send info (%d bytes)\n", (int)sizeof(dfree)-1); - dfree[64] = calc_checksum(dfree, sizeof(dfree)-1); + //dfree[64] = calc_checksum(dfree, sizeof(dfree)-1); pclink_ack(devno, cunit, 'C'); - com_write(dfree, sizeof(dfree)); + //com_write(dfree, sizeof(dfree)); + pclink_write(dfree, sizeof(dfree)); // write data + checksum byte goto exit; } @@ -2476,31 +2487,83 @@ do_pclink(uchar devno, uchar ccom, uchar caux1, uchar caux2) return; } -static void -com_read(uchar *buf, int size, const ushort type) +/* + * PCLink specific version of bus_to_peripheral(), no ACK/NAK is send here + */ +static uint8_t +pclink_read(uint8_t *buf, int len) { - fnSioCom.read(buf, size, type == COM_COMD); + // Retrieve data frame from computer + Debug_printf("<-SIO read (PCLINK) %hu bytes\n", len); + +#ifdef ESP_PLATFORM + UARTManager *uart = pcLink.sio_get_bus().get_modem()->get_uart(); + + __BEGIN_IGNORE_UNUSEDVARS + size_t l = uart->readBytes(buf, len); + __END_IGNORE_UNUSEDVARS + + // Wait for checksum + while (uart->available() <= 0) + fnSystem.yield(); + uint8_t ck_rcv = uart->read(); +#else + if (fnSioCom.get_sio_mode() == SioCom::sio_mode::NETSIO) + { + fnSioCom.netsio_write_size(len); // set hint for NetSIO + } + + size_t l = fnSioCom.readBytes(buf, len); + + // Wait for checksum + while (0 == fnSioCom.available()) + fnSystem.yield(); + uint8_t ck_rcv = fnSioCom.read(); +#endif + +#ifdef VERBOSE_SIO + Debug_printf("RECV <%u> BYTES, checksum: %hu\n\t", (unsigned int)l, ck_rcv); + for (int i = 0; i < len; i++) + Debug_printf("%02x ", buf[i]); + Debug_print("\n"); +#endif + + return ck_rcv; } +/* + * PCLink specific version of bus_to_computer(), no C/E is send here + */ static void -com_write(uchar *buf, int size) +pclink_write(uint8_t *buf, int len) { -# ifdef SIOTRACE - if (log_flag) - { - Debug_printf("<- send %d bytes ... ", size); - } -# endif + // Write data frame to computer + Debug_printf("->SIO write (PCLINK) %hu bytes\n", len); +#ifdef VERBOSE_SIO + Debug_printf("SEND <%u> BYTES\n\t", len); + for (int i = 0; i < len; i++) + Debug_printf("%02x ", buf[i]); + Debug_print("\n"); +#endif - fnSioCom.write(buf, size); - fnSioCom.flush(); + // Write data frame +#ifdef ESP_PLATFORM + UARTManager *uart = pcLink.sio_get_bus().get_modem()->get_uart(); + uart->write(buf, len); + // Write checksum + uart->write(sio_checksum(buf, len)); -# ifdef SIOTRACE - if (log_flag) - Debug_printf("OK\n"); -# endif + uart->flush(); +#else + fnSioCom.write(buf, len); + // Write checksum + fnSioCom.write(sio_checksum(buf, len)); + + fnSioCom.flush(); +#endif } + static void get_device_status(ushort devno, ushort d, uchar *st) { @@ -2514,7 +2577,13 @@ get_device_status(ushort devno, ushort d, uchar *st) static void pclink_ack(ushort devno, ushort d, uchar what) { + fnSystem.delay_microseconds(DELAY_T4); + + // call one of sio_ack/sio_nak/sio_complete/sio_error + pcLink.send_ack_byte(what); + device[d].status.stat &= ~(0x01|0x04); + switch (what) { case 'E': @@ -2525,8 +2594,7 @@ pclink_ack(ushort devno, ushort d, uchar what) break; } - // call one of sio_ack/sio_nak/sio_complete/sio_error - pcLink.send_ack_byte(what); + fnSystem.delay_microseconds(DELAY_T4); # ifdef SIOTRACE if (log_flag) @@ -2544,12 +2612,14 @@ void sioPCLink::send_ack_byte(uint8_t what) { switch (what) { + case 'a': +#ifndef ESP_PLATFORM + sio_late_ack(); + break; +#endif case 'A': sio_ack(); break; - case 'a': - sio_late_ack(); - break; case 'N': sio_nak(); break; @@ -2569,12 +2639,15 @@ void sioPCLink::mount(int no, const char* path) fps_close(no); memset(&device[no].parbuf, 0, sizeof(PARBUF)); +#ifdef ESP_PLATFORM + strncpy(device[no].dirname,path,1023); +#else if (!abs_path(path, device[no].dirname, 1024)) { Debug_printf("PCLINK failed to get absolute path for \"%s\"\n", path); return; } - //strncpy(device[no].dirname,path,1023); +#endif device[no].dirname[1023]=0; device[no].cwd[0]=0; device[no].on = 1; @@ -2599,11 +2672,11 @@ void sioPCLink::unmount(int no) // Status void sioPCLink::sio_status() { +// # ifdef SIOTRACE +// if (log_flag) + Debug_printf("STATUS: %02x %02x %02x %02x\n", status[0], status[1], status[2], status[3]); +// # endif bus_to_computer(status, sizeof(status), false); -# ifdef SIOTRACE - if (log_flag) - Debug_printf("<- STATUS $%02x $%02x $%02x $%02x\n", status[0], status[1], status[2], status[3]); -# endif } // Process SIO command @@ -2616,7 +2689,13 @@ void sioPCLink::sio_process(uint32_t commanddata, uint8_t checksum) uchar cdev = SIO_DEVICEID_PCLINK; uchar devno = cdev >> 4; // ??? magical 6 - Debug_print("PCLink sio_process()\n"); + if (!Config.get_pclink_enabled()) + { + Debug_println("PCLink disabled, ignoring"); + return; + } + + Debug_println("PCLink sio_process()"); /* cunit == 0 is init during warm reset */ if ((cunit == 0) || device[cunit].on) @@ -2624,11 +2703,11 @@ void sioPCLink::sio_process(uint32_t commanddata, uint8_t checksum) switch (cmdFrame.comnd) { case 'P': - Debug_println("PARAMETERS"); + Debug_println("PARBLK"); do_pclink(devno, cmdFrame.comnd, cmdFrame.aux1, cmdFrame.aux2); break; case 'R': - Debug_println("RESULT"); + Debug_println("EXEC"); do_pclink(devno, cmdFrame.comnd, cmdFrame.aux1, cmdFrame.aux2); break; case 'S': /* status */ @@ -2650,5 +2729,3 @@ void sioPCLink::sio_process(uint32_t commanddata, uint8_t checksum) } #endif /* BUILD_ATARI */ - -#endif // !ESP_PLATFORM \ No newline at end of file diff --git a/lib/device/sio/pclink.h b/lib/device/sio/pclink.h index 92a791adc..6a6f8f4a1 100644 --- a/lib/device/sio/pclink.h +++ b/lib/device/sio/pclink.h @@ -10,10 +10,13 @@ class sioPCLink : public virtualDevice public: sioPCLink(); + + // these methods must be implemented void sio_process(uint32_t commanddata, uint8_t checksum) override; virtual void sio_status() override; - // public wrapper around sio_ack(), sio_nak(), etc... + // public wrapper around protected virtualDevice::sio_ack(), virtualDevice::sio_nak() + // to make these protected methotds reachable from sio2bsd/pclink code void send_ack_byte(uint8_t what); void mount(int no, const char* fileName); diff --git a/lib/http/httpServiceConfigurator.cpp b/lib/http/httpServiceConfigurator.cpp index 6f7dbe6ec..38874e0ad 100644 --- a/lib/http/httpServiceConfigurator.cpp +++ b/lib/http/httpServiceConfigurator.cpp @@ -580,6 +580,13 @@ void fnHttpServiceConfigurator::config_netsio(std::string enable_netsio, std::st } #endif // !ESP_PLATFORM +void fnHttpServiceConfigurator::config_pclink_enabled(std::string enabled) +{ + Debug_printf("New PCLink Enable Value: %s\n", enabled.c_str()); + Config.store_pclink_enabled(atoi(enabled.c_str())); + Config.save(); +} + int fnHttpServiceConfigurator::process_config_post(const char *postdata, size_t postlen) { #ifdef DEBUG @@ -713,6 +720,10 @@ int fnHttpServiceConfigurator::process_config_post(const char *postdata, size_t update_netsio = true; } #endif + else if (i->first.compare("pclink_enabled") == 0) + { + config_pclink_enabled(i->second); + } } // end for loop #ifndef ESP_PLATFORM diff --git a/lib/http/httpServiceConfigurator.h b/lib/http/httpServiceConfigurator.h index e8765c310..30a20c681 100755 --- a/lib/http/httpServiceConfigurator.h +++ b/lib/http/httpServiceConfigurator.h @@ -32,6 +32,7 @@ class fnHttpServiceConfigurator static void config_cpm_enabled(std::string cpm_enabled); static void config_cpm_ccp(std::string cpm_ccp); static void config_alt_filename(std::string alt_cfg); + static void config_pclink_enabled(std::string pclink_enabled); #ifndef ESP_PLATFORM static void config_serial(std::string port, std::string command, std::string proceed); diff --git a/lib/http/httpServiceParser.cpp b/lib/http/httpServiceParser.cpp index 4a2031525..0d6ce9491 100644 --- a/lib/http/httpServiceParser.cpp +++ b/lib/http/httpServiceParser.cpp @@ -130,6 +130,7 @@ const string fnHttpServiceParser::substitute_tag(const string &tag) FN_CPM_ENABLED, FN_CPM_CCP, FN_ALT_CFG, + FN_PCLINK_ENABLED, FN_LASTTAG }; @@ -244,7 +245,8 @@ const string fnHttpServiceParser::substitute_tag(const string &tag) "FN_APETIME_ENABLED", "FN_CPM_ENABLED", "FN_CPM_CCP", - "FN_ALT_CFG" + "FN_ALT_CFG", + "FN_PCLINK_ENABLED", }; stringstream resultstream; @@ -343,6 +345,9 @@ const string fnHttpServiceParser::substitute_tag(const string &tag) case FN_APETIME_ENABLED: resultstream << Config.get_apetime_enabled(); break; + case FN_PCLINK_ENABLED: + resultstream << Config.get_pclink_enabled(); + break; #endif /* BUILD_ATARI */ case FN_ROTATION_SOUNDS: diff --git a/src/main.cpp b/src/main.cpp index c625f83e8..edb26fa6f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -239,10 +239,19 @@ void main_setup(int argc, char *argv[]) #ifdef ESP_PLATFORM SIO.addDevice(&udpDev, SIO_DEVICEID_MIDI); // UDP/MIDI device +#endif + + // add PCLink device only if we have SD card + if (fnSDFAT.running()) + { +#ifdef ESP_PLATFORM + // TODO how to get the folder SD is mounted on? + pcLink.mount(1, "/sd"); // mount SD card as PCL1: #else - pcLink.mount(1, Config.get_general_SD_path().c_str()); // mount SD as PCL1: - SIO.addDevice(&pcLink, SIO_DEVICEID_PCLINK); // PCLink + pcLink.mount(1, Config.get_general_SD_path().c_str()); // mount SD as PCL1: #endif + SIO.addDevice(&pcLink, SIO_DEVICEID_PCLINK); // PCLink + } // Create a new printer object, setting its output depending on whether we have SD or not FileSystem *ptrfs = fnSDFAT.running() ? (FileSystem *)&fnSDFAT : (FileSystem *)&fsFlash;