Skip to content

Commit d86a171

Browse files
authored
Add firmware update and file copy commands to iecFuji (#1200)
* Add firmware update and file copy commands to iecFuji * Refactor enable and disable device functions to accept device IDs as parameters * Add DIR_OPTION_UNSORTED to support unsorted directory entries (#1201) * Enhance device slot enable/disable functionality in fnConfig (#1203) * Refactor QR code version handling and update output mode enumeration (#1202)
1 parent b005b5d commit d86a171

File tree

3 files changed

+171
-14
lines changed

3 files changed

+171
-14
lines changed

include/fujiCommandID.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ enum fujiCommandID_t : uint8_t {
8080
FUJICMD_GET_DEVICE3_FULLPATH = 0xA2,
8181
FUJICMD_GET_DEVICE2_FULLPATH = 0xA1,
8282
FUJICMD_GET_DEVICE1_FULLPATH = 0xA0,
83+
FUJICMD_UPDATE_FIRMWARE = 0x90,
8384
FUJICMD_STATUS = 0x53, // S
8485
FUJICMD_HSIO_INDEX = 0x3F, // ?
8586
FUJICMD_NAK = 0x15, // ASCII NAK

lib/device/iec/iecFuji.cpp

Lines changed: 160 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,10 @@ void iecFuji::process_basic_commands()
480480
fujicmd_generate_guid();
481481
response = mstr::toPETSCII2(response);
482482
}
483+
else if (payload.find("copy") != std::string::npos)
484+
copy_file_basic();
485+
else if (payload.find("update") != std::string::npos)
486+
update_firmware();
483487
else if (payload.find("bptiming") != std::string::npos)
484488
{
485489
if ( pt.size() < 3 )
@@ -535,6 +539,8 @@ bool iecFuji::is_supported(uint8_t cmd)
535539
case FUJICMD_WRITE_APPKEY:
536540
case FUJICMD_WRITE_DEVICE_SLOTS:
537541
case FUJICMD_WRITE_HOST_SLOTS:
542+
case FUJICMD_COPY_FILE:
543+
case FUJICMD_UPDATE_FIRMWARE:
538544
result = true;
539545
break;
540546
}
@@ -694,6 +700,9 @@ void iecFuji::process_immediate_raw_cmds()
694700
fujicmd_generate_guid();
695701
response = mstr::toPETSCII2(response);
696702
break;
703+
case FUJICMD_UPDATE_FIRMWARE:
704+
update_firmware();
705+
break;
697706
default:
698707
// not an immediate command, so exit without changing current_fuji_cmd, as we need to be sent data
699708
was_immediate_cmd = false;
@@ -817,36 +826,78 @@ void iecFuji::net_set_ssid_basic(bool store)
817826
fujicmd_net_set_ssid_success(net_config.ssid, net_config.password, store);
818827
}
819828

820-
void iecFuji::enable_device_basic()
829+
void iecFuji::enable_device_basic(std::string ids)
821830
{
831+
if(ids.empty()) {
822832
// Strip off the ENABLE: part of the command
823-
pt[0] = pt[0].substr(7, std::string::npos);
833+
pt[0] = pt[0].substr(7, std::string::npos);
834+
} else {
835+
pt = util_tokenize(ids, ',');
836+
}
824837

825838
// Enable devices
826839
for (int i = 0; i < pt.size(); i++) {
827840
uint8_t device = atoi(pt[i].c_str());
828-
auto d = SYSTEM_BUS.findDevice(device, true);
829-
if (d) {
830-
d->setActive(true);
831-
Debug_printv("Enable Device #%d [%d]", device, d->isActive());
841+
if (device == 0) {
842+
// special case for device 0, we want to enable all drives if that is the case
843+
for (int dnum = 1; dnum <= MAX_DISK_DEVICES; dnum++) {
844+
auto d = SYSTEM_BUS.m_devices[dnum];
845+
if (d) {
846+
d->setActive(true);
847+
Config.store_device_slot_enable(dnum, true);
848+
Debug_printv("Enable Device #%d [%d]", (dnum + 7), d->isActive());
849+
}
850+
}
851+
break;
852+
}
853+
else
854+
{
855+
auto d = SYSTEM_BUS.findDevice(device, true);
856+
if (d) {
857+
d->setActive(true);
858+
Config.store_device_slot_enable((device - 7), true);
859+
Debug_printv("Enable Device #%d [%d]", device, d->isActive());
860+
}
832861
}
833862
}
863+
Config.save();
834864
}
835865

836-
void iecFuji::disable_device_basic()
866+
void iecFuji::disable_device_basic(std::string ids)
837867
{
868+
if(ids.empty()) {
838869
// Strip off the DISABLE: part of the command
839-
pt[0] = pt[0].substr(8, std::string::npos);
870+
pt[0] = pt[0].substr(8, std::string::npos);
871+
} else {
872+
pt = util_tokenize(ids, ',');
873+
}
840874

841875
// Disable devices
842876
for (int i = 0; i < pt.size(); i++) {
843877
uint8_t device = atoi(pt[i].c_str());
844-
auto d = SYSTEM_BUS.findDevice(device, true);
845-
if (d) {
846-
d->setActive(false);
847-
Debug_printv("Disable Device #%d [%d]", device, d->isActive());
878+
if (device == 0) {
879+
// special case for device 0, we want to disable all drives if that is the case
880+
for (int dnum = 1; dnum <= MAX_DISK_DEVICES; dnum++) {
881+
auto d = SYSTEM_BUS.m_devices[dnum];
882+
if (d) {
883+
d->setActive(false);
884+
Config.store_device_slot_enable(dnum, false);
885+
Debug_printv("Disable Device #%d [%d]", (dnum + 7), d->isActive());
886+
}
887+
}
888+
break;
889+
}
890+
else
891+
{
892+
auto d = SYSTEM_BUS.findDevice(device, true);
893+
if (d) {
894+
d->setActive(false);
895+
Config.store_device_slot_enable((device - 7), false);
896+
Debug_printv("Disable Device #%d [%d]", device, d->isActive());
897+
}
848898
}
849899
}
900+
Config.save();
850901
}
851902

852903
void iecFuji::net_set_ssid_raw(bool store)
@@ -1971,4 +2022,101 @@ void iecFuji::hash_clear()
19712022
hasher.clear();
19722023
}
19732024

2025+
void iecFuji::copy_file_basic()
2026+
{
2027+
if (pt.size() != 2)
2028+
{
2029+
Debug_printv("error: bad args");
2030+
response = "BAD COPY ARGS";
2031+
return;
2032+
}
2033+
2034+
// Strip off the COPY: part of the command
2035+
pt[0] = pt[0].substr(5, std::string::npos);
2036+
if (mstr::isNumeric(pt[0])) {
2037+
// Find SSID by CRC8 Number
2038+
pt[0] = fnWiFi.get_network_name_by_crc8(std::stoi(pt[0]));
2039+
}
2040+
2041+
copy_file(pt[0], pt[1]);
2042+
}
2043+
2044+
void iecFuji::copy_file_raw()
2045+
{
2046+
copy_file(pt[0], pt[1]);
2047+
}
2048+
2049+
void iecFuji::copy_file(std::string source, std::string destination)
2050+
{
2051+
std::unique_ptr<MFile> in_file(MFSOwner::File(source));
2052+
std::unique_ptr<MFile> out_file(MFSOwner::File(destination));
2053+
2054+
// If destination is a directory then save with source filename
2055+
if ( out_file->isDirectory() )
2056+
{
2057+
destination += "/" + in_file->name;
2058+
out_file.reset(MFSOwner::File(destination));
2059+
}
2060+
2061+
// Create streams and copy file
2062+
{
2063+
auto in_stream = in_file->getSourceStream(std::ios_base::in);
2064+
if (in_stream == nullptr)
2065+
{
2066+
Serial.printf("2 Error: Can't open source!\r\n");
2067+
set_fuji_iec_status(62, "can't open source stream");
2068+
return;
2069+
}
2070+
2071+
auto out_stream = out_file->getSourceStream(std::ios_base::out);
2072+
if (out_stream == nullptr)
2073+
{
2074+
Serial.printf("2 Error: Can't open destination!\r\n");
2075+
set_fuji_iec_status(62, "can't open destination stream");
2076+
return;
2077+
}
2078+
2079+
Debug_printv("size[%lu] name[%s] url[%s] destination[%s]", in_file->size, in_file->name.c_str(), in_stream->url.c_str(), destination.c_str());
2080+
2081+
// Receive File
2082+
int count = 0;
2083+
uint8_t bytes[255];
2084+
while (true)
2085+
{
2086+
int bytes_read = in_stream->read(bytes, 255);
2087+
if (bytes_read < 1)
2088+
{
2089+
if (in_stream->available())
2090+
Serial.printf("\nError reading '%s'\r", in_file->name.c_str());
2091+
break;
2092+
}
2093+
2094+
int bytes_written = out_stream->write(bytes, bytes_read);
2095+
if (bytes_written != bytes_read)
2096+
{
2097+
Serial.printf("\nError writing '%s'\r", out_file->name.c_str());
2098+
break;
2099+
}
2100+
2101+
// Show percentage complete in stdout
2102+
uint8_t percent = (in_stream->position() * 100) / in_stream->size();
2103+
#ifdef ENABLE_DISPLAY
2104+
LEDS.progress = percent;
2105+
#endif
2106+
Serial.printf("Downloading '%s' %d%% [%lu]\r", in_file->name.c_str(), percent, in_stream->position());
2107+
count++;
2108+
}
2109+
Serial.printf("\n");
2110+
}
2111+
2112+
set_fuji_iec_status(0, "");
2113+
}
2114+
2115+
void iecFuji::update_firmware()
2116+
{
2117+
fnSystem.update_firmware();
2118+
set_fuji_iec_status(0, "");
2119+
}
2120+
2121+
19742122
#endif /* BUILD_IEC */

lib/device/iec/iecFuji.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,11 @@ class iecFuji : public fujiDevice
185185
void set_boot_config_basic();
186186
void set_boot_config_raw();
187187

188+
// 0xD8
189+
void copy_file(std::string source, std::string destination);
190+
void copy_file_basic();
191+
void copy_file_raw();
192+
188193
// 0xD6
189194
void set_boot_mode_basic();
190195
void set_boot_mode_raw();
@@ -213,6 +218,9 @@ class iecFuji : public fujiDevice
213218
void hash_clear();
214219
void hash_clear_raw();
215220

221+
// Commodore specific
222+
void update_firmware();
223+
216224
// Commodore specific
217225
void local_ip();
218226
void netmask();
@@ -222,8 +230,8 @@ class iecFuji : public fujiDevice
222230
void bssid();
223231
void fn_version();
224232

225-
void enable_device_basic();
226-
void disable_device_basic();
233+
void enable_device_basic(std::string ids = "");
234+
void disable_device_basic(std::string ids = "");
227235

228236
bool check_appkey_creator(bool check_is_write);
229237

0 commit comments

Comments
 (0)