From 926e7d66e62b14e66a558b1bfec6dc43f16d39f8 Mon Sep 17 00:00:00 2001 From: Boisy Pitre Date: Wed, 11 Sep 2024 04:29:14 -0500 Subject: [PATCH 1/2] Added support for missing DriveWire commands Moved to a state machine for processing DriveWire commands Moved to a state machine for processing FujiNet commands --- lib/bus/drivewire/drivewire.cpp | 979 +++++++++++++---- lib/bus/drivewire/drivewire.h | 95 +- lib/bus/drivewire/dwcom/fnDwCom.h | 70 ++ lib/device/drivewire/fuji.cpp | 1683 +++++++++++++++++++---------- lib/device/drivewire/fuji.h | 129 ++- 5 files changed, 2083 insertions(+), 873 deletions(-) diff --git a/lib/bus/drivewire/drivewire.cpp b/lib/bus/drivewire/drivewire.cpp index 21136ee87..ec97ec324 100755 --- a/lib/bus/drivewire/drivewire.cpp +++ b/lib/bus/drivewire/drivewire.cpp @@ -43,6 +43,55 @@ static void IRAM_ATTR drivewire_isr_handler(void *arg) } #endif +/** + * Static callback function for the DriveWire state machine. + */ +#ifdef ESP_PLATFORM +void onTimer(void *info) +{ + systemBus *parent = (systemBus *)info; + parent->resetState(); +} +#endif + +/** + * Start the DriveWire state machine recovery timer. + */ +void systemBus::timer_start() +{ +#ifdef ESP_PLATFORM + esp_timer_create_args_t tcfg; + tcfg.arg = this; + tcfg.callback = onTimer; + tcfg.dispatch_method = esp_timer_dispatch_t::ESP_TIMER_TASK; + tcfg.name = nullptr; + esp_timer_create(&tcfg, &stateMachineRecoveryTimerHandle); + esp_timer_start_periodic(stateMachineRecoveryTimerHandle, timerRate * 1000); +#else + timerActive = true; + lastInterruptMs = fnSystem.millis(); +#endif +} + +/** + * Stop the DriveWire state machine recovery timer + */ +void systemBus::timer_stop() +{ +#ifdef ESP_PLATFORM + // Delete existing timer + if (stateMachineRecoveryTimerHandle != nullptr) + { + Debug_println("Deleting existing DriveWire state machine timer\n"); + esp_timer_stop(stateMachineRecoveryTimerHandle); + esp_timer_delete(stateMachineRecoveryTimerHandle); + stateMachineRecoveryTimerHandle = nullptr; + } +#else + timerActive = false; +#endif +} + // Calculate 8-bit checksum inline uint16_t drivewire_checksum(uint8_t *buf, unsigned short len) { @@ -54,11 +103,10 @@ inline uint16_t drivewire_checksum(uint8_t *buf, unsigned short len) return chk; } -#ifdef ESP_PLATFORM +#if defined(ESP_PLATFORM) && 1 == 0 static void drivewire_intr_task(void *arg) { uint32_t gpio_num; - int64_t d; systemBus *bus = (systemBus *)arg; @@ -83,194 +131,249 @@ static void drivewire_intr_task(void *arg) } #endif -// Helper functions outside the class defintions +// Helper functions outside the class definintions systemBus virtualDevice::get_bus() { return DRIVEWIRE; } -void systemBus::op_jeff() + + +void systemBus::resetState(void) { - fnDwCom.print("FUJINET"); - Debug_println("Jeff's op"); + dwStateMethod = &systemBus::_drivewire_process_cmd; + timer_stop(); } -void systemBus::op_nop() +int systemBus::op_jeff(std::vector *q) { + int result = 1; + + resetState(); + Debug_println("OP_JEFF\n"); + + return result; } -void systemBus::op_reset() +int systemBus::op_nop(std::vector *q) { - Debug_printv("op_reset()"); + int result = 1; + + resetState(); - // When a reset transaction occurs, set the mounted disk image to the CONFIG disk image. - theFuji.boot_config = true; - theFuji.insert_boot_device(Config.get_general_boot_mode()); + return result; } -void systemBus::op_readex() +int systemBus::op_reset(std::vector *q) { - drivewireDisk *d = nullptr; - uint16_t c1 = 0, c2 = 0; - - uint8_t *blk_buffer = sector_data; - uint16_t blk_size = MEDIA_BLOCK_SIZE; - - uint8_t rc = DISK_CTRL_STATUS_CLEAR; - - drive_num = fnDwCom.read(); - - lsn = fnDwCom.read() << 16; - lsn |= fnDwCom.read() << 8; - lsn |= fnDwCom.read(); - - Debug_printf("OP_READ: DRIVE %3u - SECTOR %8lu\n", drive_num, lsn); + int result = 1; + + Debug_printv("op_reset()"); - if (theFuji.boot_config && drive_num == 0) - d = theFuji.bootdisk(); - else - d = &theFuji.get_disks(drive_num)->disk_dev; + // When a reset transaction occurs, set the mounted disk image to the CONFIG disk image. + theFuji.boot_config = true; + theFuji.insert_boot_device(Config.get_general_boot_mode()); - if (!d) + for (int i = 0; i < 16; i++) { - Debug_printv("Invalid drive #%3u", drive_num); - rc = 0xF6; + // clear all channel queues + fnDwCom.outgoingChannel[i].clear(); + fnDwCom.incomingChannel[i].clear(); + fnDwCom.incomingScreen[i].clear(); } + + resetState(); + + return result; +} - if (rc == DISK_CTRL_STATUS_CLEAR && !d->device_active) - { - Debug_printv("Device not active."); - rc = 0xF6; - } +int readexChecksum = 0; +int readexError = 0; - if (rc == DISK_CTRL_STATUS_CLEAR) - { - bool use_media_buffer = true; - d->get_media_buffer(&blk_buffer, &blk_size); - if (blk_buffer == nullptr || blk_size == 0) +int systemBus::op_readex(std::vector *q) +{ + int result = 0; + readexChecksum = 0; + + if (q->size() >= 5) { + uint8_t drive_num = q->at(1); + int lsn = q->at(2) << 16 | q->at(3) << 8 | q->at(4); + drivewireDisk *d = nullptr; + uint8_t sector_data[MEDIA_BLOCK_SIZE]; + uint8_t *blk_buffer = sector_data; + uint16_t blk_size = MEDIA_BLOCK_SIZE; + + result = 5; + + Debug_printf("OP_READEX: DRIVE %3u - SECTOR %8lu\n", drive_num, lsn); + + if (theFuji.boot_config && drive_num == 0) + d = theFuji.bootdisk(); + else + d = &theFuji.get_disks(drive_num)->disk_dev; + + if (!d) { - // no media buffer, use "bus buffer" with default block size - blk_buffer = sector_data; - blk_size = MEDIA_BLOCK_SIZE; - use_media_buffer = false; + Debug_printv("Invalid drive #%3u", drive_num); + readexError = 0xF6; } - - if (d->read(lsn, use_media_buffer ? nullptr : sector_data)) + + if (readexError == DISK_CTRL_STATUS_CLEAR && !d->device_active) + { + Debug_printv("Device not active."); + readexError = 0xF6; + } + + if (readexError == DISK_CTRL_STATUS_CLEAR) { - if (d->get_media_status() == 2) + bool use_media_buffer = true; + d->get_media_buffer(&blk_buffer, &blk_size); + if (blk_buffer == nullptr || blk_size == 0) { - Debug_printf("EOF\n"); - rc = 211; + // no media buffer, use "bus buffer" with default block size + blk_buffer = sector_data; + blk_size = MEDIA_BLOCK_SIZE; + use_media_buffer = false; } - else + + if (d->read(lsn, use_media_buffer ? nullptr : sector_data)) { - Debug_printf("Read error\n"); - rc = 0xF4; + if (d->get_media_status() == 2) + { + Debug_printf("EOF\n"); + readexError = 211; + } + else + { + Debug_printf("Read error\n"); + readexError = 0xF4; + } } } - } - - // send zeros on error - if (rc != DISK_CTRL_STATUS_CLEAR) - memset(blk_buffer, 0x00, blk_size); + + // send zeros on error + if (readexError != DISK_CTRL_STATUS_CLEAR) + { + memset(blk_buffer, 0x00, blk_size); + } + + readexChecksum = drivewire_checksum(blk_buffer, blk_size); - // send sector data - fnDwCom.write(blk_buffer, blk_size); + // send sector data + fnDwCom.write(blk_buffer, blk_size); + + fnDwCom.flush(); - // receive checksum - c1 = (fnDwCom.read()) << 8; - c1 |= fnDwCom.read(); + dwStateMethod = &systemBus::op_readex_p2; + } + + return result; +} + +int systemBus::op_readex_p2(std::vector *q) +{ + int result = 0; + + if (q->size() >= 2) { + // We read 2 bytes into this buffer (guest's checksum). + // Here we're expecting the checksum from the guest. + result = 2; + + int guestChecksum = q->at(0) * 256 + q->at(1); + if (readexChecksum != guestChecksum) { + Debug_printf("Checksum error: expected %d, got %d\n", readexChecksum, guestChecksum); + readexError = 243; + } + + // send status + fnDwCom.write(readexError); - // test checksum - if (rc == DISK_CTRL_STATUS_CLEAR) - { - c2 = drivewire_checksum(blk_buffer, blk_size); + resetState(); + } + + return result; +} - if (c1 != c2) +int systemBus::op_write(std::vector *q) +{ + int result = 0; + int rc = 0; + int expectedResult = 263; + + if (q->size() >= expectedResult) { + resetState(); + result = expectedResult; + + int drive_num = q->at(1); + int lsn = q->at(2) << 16 | q->at(3) << 8 | q->at(4); + std::vector sector_data(256); + std::copy(q->begin() + 5, q->begin() + 260, sector_data.begin()); + int checksum = q->at(261)*256 + q->at(262); + + int computedChecksum = drivewire_checksum(sector_data.data(), MEDIA_BLOCK_SIZE); + + if (computedChecksum == checksum) { + Debug_printf("OP_WRITE DRIVE %3u - SECTOR %8lu\n", drive_num, lsn); + drivewireDisk *d = &theFuji.get_disks(drive_num)->disk_dev; + + if (!d) + { + Debug_printv("Invalid drive #%3u", drive_num); + rc = 0xF6; + } + else if (!d->device_active) + { + Debug_printv("Device not active."); + rc = 0xF6; + } + else if (d->write(lsn, sector_data.data())) + { + Debug_print("Write error\n"); + rc = 0xF5; + } + } + else { - Debug_printf("Checksum error: expected %d, got %d\n", c2, c1); rc = 243; } - } - // finally, send the transaction status - fnDwCom.write(rc); - fnDwCom.flush(); + resetState(); + } + + return result; } -void systemBus::op_write() +int systemBus::op_fuji(std::vector *q) { - drivewireDisk *d = nullptr; - uint16_t c1 = 0, c2 = 0; - - drive_num = fnDwCom.read(); - - lsn = fnDwCom.read() << 16; - lsn |= fnDwCom.read() << 8; - lsn |= fnDwCom.read(); - - size_t s = fnDwCom.readBytes(sector_data, MEDIA_BLOCK_SIZE); - - if (s != MEDIA_BLOCK_SIZE) + int result = 0; + + result = theFuji.process(q); + + if (result > 0) { - Debug_printv("Insufficient # of bytes for write, total recvd: %u", s); - fnDwCom.flush_input(); - return; + Debug_printv("OP_FUJI"); + Debug_printf("result = %d\n", result); } - - // Todo handle checksum. - c1 = fnDwCom.read(); - c1 |= fnDwCom.read() << 8; - - c2 = drivewire_checksum(sector_data, MEDIA_BLOCK_SIZE); - - // if (c1 != c2) - // { - // Debug_printf("Checksum error\n"); - // fnDwCom.write(243); - // return; - // } - - Debug_printf("OP_WRITE DRIVE %3u - SECTOR %8lu\n", drive_num, lsn); - - d = &theFuji.get_disks(drive_num)->disk_dev; - - if (!d) - { - Debug_printv("Invalid drive #%3u", drive_num); - fnDwCom.write(0xF6); - return; - } - - if (!d->device_active) - { - Debug_printv("Device not active."); - fnDwCom.write(0xF6); - return; - } - - if (d->write(lsn, sector_data)) - { - Debug_print("Write error\n"); - fnDwCom.write(0xF5); - return; - } - - fnDwCom.write(0x00); // success -} - -void systemBus::op_fuji() -{ - theFuji.process(); + + return result; } -void systemBus::op_cpm() +int systemBus::op_cpm(std::vector *q) { + int result = 1; + #ifdef ESP_PLATFORM theCPM.process(); #endif /* ESP_PLATFORM */ + + resetState(); + Debug_printv("OP_CPM"); + + return result; } -void systemBus::op_net() +int systemBus::op_net(std::vector *q) { + int result = 1; + // Get device ID uint8_t device_id = (uint8_t)fnDwCom.read(); @@ -282,22 +385,27 @@ void systemBus::op_net() } // And pass control to it - Debug_printf("OP_NET: %u\n",device_id); _netDev[device_id]->process(); + resetState(); + Debug_printf("OP_NET: %u\n", device_id); + + return result; } -void systemBus::op_unhandled(uint8_t c) +int systemBus::op_unhandled(std::vector *q) { - Debug_printv("Unhandled opcode: %02x", c); - - while (fnDwCom.available()) - Debug_printf("%02x ", fnDwCom.read()); - - fnDwCom.flush_input(); + int result = 1; + + resetState(); + Debug_printv("Unhandled opcode: %02x", q->at(0)); + + return result; } -void systemBus::op_time() +int systemBus::op_time(std::vector *q) { + int result = 1; + time_t tt = time(nullptr); struct tm *now = localtime(&tt); @@ -305,120 +413,478 @@ void systemBus::op_time() Debug_printf("Returning %02d/%02d/%02d %02d:%02d:%02d\n", now->tm_year, now->tm_mon, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec); - fnDwCom.write(now->tm_year - 1900); + fnDwCom.write(now->tm_year); fnDwCom.write(now->tm_mon); fnDwCom.write(now->tm_mday); fnDwCom.write(now->tm_hour); fnDwCom.write(now->tm_min); fnDwCom.write(now->tm_sec); + + resetState(); + Debug_printv("OP_TIME"); + + return result; } -void systemBus::op_init() +int systemBus::op_init(std::vector *q) { + int result = 1; + + resetState(); Debug_printv("OP_INIT"); + + return result; } -void systemBus::op_dwinit() +int systemBus::op_term(std::vector *q) { - Debug_printv("OP_DWINIT - Sending feature byte 0x%02x", DWINIT_FEATURES); - fnDwCom.write(DWINIT_FEATURES); + int result = 1; + + resetState(); + Debug_printv("OP_TERM"); + + return result; } -void systemBus::op_getstat() +int systemBus::op_serinit(std::vector *q) { - Debug_printv("OP_GETSTAT: 0x%02x 0x%02x", fnDwCom.read(),fnDwCom.read()); + int result = 0; + int expectedResult = 2; + + if (q->size() >= expectedResult) + { + // Clear the outgoing channel. + result = expectedResult; + int vchan = q->at(1); + fnDwCom.outgoingChannel[vchan].clear(); + resetState(); + Debug_printv("OP_SERINIT"); + } + + return result; } -void systemBus::op_setstat() +int systemBus::op_serterm(std::vector *q) { - Debug_printv("OP_SETSTAT: 0x%02x 0x%02x", fnDwCom.read(),fnDwCom.read()); + int result = 0; + int expectedResult = 2; + + if (q->size() >= expectedResult) + { + // Clear the outgoing channel. + result = expectedResult; + int vchan = q->at(1); + fnDwCom.outgoingChannel[vchan].clear(); + resetState(); + Debug_printv("OP_SERTERM"); + } + + return result; } -void systemBus::op_serread() +int systemBus::op_dwinit(std::vector *q) { - // TODO: Temporary until modem and network are working - fnDwCom.write(0x00); - fnDwCom.write(0x00); + int result = 0; + int expectedResult = 2; + + if (q->size() >= expectedResult) + { + result = expectedResult; + + // save capabilities byte + guestCapabilityByte = q->at(1); + uint8_t hostResponse = 0x00; + + if (guestCapabilityByte == 1) + { + // OS-9 is the only environment that uses OP_DWINIT. + // dwio sends OP_DWINIT followed by $01. + // If the host responds with $04, dwio starts the + // virtual interrupt service routine to poll for input, + // so we'll respond with that value here. + hostResponse = 0x04; + fnDwCom.pollingMode = true; + } + fnDwCom.write(hostResponse); + + resetState(); + Debug_printv("OP_DWINIT: %02x", guestCapabilityByte); + } + + return result; } -void systemBus::op_print() +int systemBus::op_getstat(std::vector *q) { - _printerdev->write(fnDwCom.read()); + int result = 0; + int expectedResult = 3; + + if (q->size() >= expectedResult) { + result = expectedResult; + int lastDriveNumber = q->at(1); + int lastGetStat = q->at(2); + resetState(); + Debug_printv("OP_GETSTAT: 0x%02x 0x%02x", lastDriveNumber, lastGetStat); + } + + return result; } -// Read and process a command frame from DRIVEWIRE -void systemBus::_drivewire_process_cmd() +int systemBus::op_setstat(std::vector *q) { - int c = fnDwCom.read(); - if (c < 0) + int result = 0; + int expectedResult = 3; + + if (q->size() >= expectedResult) { + result = expectedResult; + int lastDriveNumber = q->at(1); + int lastSetStat = q->at(2); + resetState(); + Debug_printv("OP_SETSTAT: 0x%02x 0x%02x", lastDriveNumber, lastSetStat); + } + + return result; +} + +int systemBus::op_sergetstat(std::vector *q) +{ + int result = 0; + int expectedResult = 3; + + if (q->size() >= expectedResult) { + result = expectedResult; + int lastChannelNumber = q->at(1); + int lastGetStat = q->at(2); + resetState(); + Debug_printv("OP_SERGETSTAT: 0x%02x 0x%02x", lastChannelNumber, lastGetStat); + } + + return result; +} + +int systemBus::op_sersetstat(std::vector *q) +{ + int result = 0; + int expectedResult = 3; + + if (q->size() >= expectedResult) { + result = expectedResult; + int lastChannelNumber = q->at(1); + int lastSetStat = q->at(2); + + if (lastSetStat == 0x28) + { + dwStateMethod = &systemBus::op_sersetstat_comstat; + } + else + { + resetState(); + } + Debug_printv("OP_SERSETSTAT: 0x%02x 0x%02x", lastChannelNumber, lastSetStat); + } + + return result; +} + +int systemBus::op_sersetstat_comstat(std::vector *q) +{ + int result = 0; + int expectedResult = 26; + + if (q->size() >= expectedResult) { + result = expectedResult; + resetState(); + } + + return result; +} + +int systemBus::op_serread(std::vector *q) +{ + int result = 1; + uint8_t responseByte1 = 0x00; + uint8_t responseByte2 = 0x00; + bool hasData = false; + + // scan client channels for first that has available data + for (int i = 0; i < 16; i++) { + if (fnDwCom.outgoingChannel[i].empty() == false) { + responseByte1 = (i + 1); // virtual channel indicator + int sizeInChannel = fnDwCom.outgoingChannel[i].size(); + if (sizeInChannel > 1) + { + responseByte1 |= 0x10; // multibyte response + responseByte2 = (sizeInChannel > 16) ? 16 : sizeInChannel; + } + else + { + responseByte2 = fnDwCom.outgoingChannel[i].front(); + fnDwCom.outgoingChannel[i].erase(fnDwCom.outgoingChannel[i].begin()); + } + fnDwCom.write(responseByte1); + fnDwCom.write(responseByte2); + Debug_printv("OP_SERREAD: response1 $%02x - response2 $%02x\n", responseByte1, responseByte2); + hasData = true; + break; + } + } + + if (hasData == false) { - Debug_println("Failed to read cmd!"); - return; + responseByte1 = 0x00; + responseByte2 = 0x00; + fnDwCom.write(responseByte1); + fnDwCom.write(responseByte2); + Debug_printv("OP_SERREAD: response1 $%02x - response2 $%02x\n", responseByte1, responseByte2); + } + + resetState(); + + return result; +} + +int systemBus::op_serreadm(std::vector *q) +{ + int result = 0; + int expectedResult = 3; + + if (q->size() >= expectedResult) { + result = expectedResult; + uint8_t vchan = q->at(1); + uint8_t count = q->at(2); + + Debug_printv("OP_SERREADM: vchan $%02x - count $%02x\n", vchan, count); + + // scan client channels for first that has available data + if (fnDwCom.outgoingChannel[vchan].empty() == false) { + if (fnDwCom.outgoingChannel[vchan].size() < count) count = fnDwCom.outgoingChannel[vchan].size(); + for (int i = 0; i < count; i++) { + int response = fnDwCom.outgoingChannel[vchan].front(); + fnDwCom.outgoingChannel[vchan].erase(fnDwCom.outgoingChannel[vchan].begin()); + fnDwCom.write(response); + Debug_printv("Data to client -> $%02x", response); + } + } + + resetState(); + } + + return result; +} + +int systemBus::op_serwrite(std::vector *q) +{ + int result = 0; + int expectedResult = 3; + + if (q->size() >= expectedResult) { + result = expectedResult; + uint8_t vchan = q->at(1); + uint8_t byte = q->at(2); + + fnDwCom.incomingChannel[vchan].push_back(byte); + resetState(); + Debug_printv("OP_SERWRITE: vchan $%02x - byte $%02x\n", vchan, byte); } + + return result; +} +int systemBus::op_serwritem(std::vector *q) +{ + int result = 0; + int expectedResult = 3; + + if (q->size() >= expectedResult) { + result = expectedResult; + uint8_t vchan = q->at(1); + uint8_t count = q->at(2); + + for (int i = 0; i < count; i++) { + int byte = q->at(i+3); + fnDwCom.incomingChannel[vchan].push_back(byte); + } + + resetState(); + Debug_printv("OP_SERWRITEM: vchan $%02x\n", vchan); + } + + return result; +} + +int systemBus::op_print(std::vector *q) +{ + int result = 0; + int expectedResult = 2; + + if (q->size() >= expectedResult) { + uint8_t byte = q->at(1); + _printerdev->write(byte); + + resetState(); + Debug_printv("OP_PRINT: byte $%02x\n", byte); + } + + return result; +} + +int systemBus::op_printflush(std::vector *q) +{ + int result = 1; + + resetState(); + Debug_printv("OP_PRINTFLUSH\n"); + + return result; +} + +int systemBus::op_fastwrite_serial(std::vector *q) +{ + int result = 0; + int expectedResult = 2; + + if (q->size() >= expectedResult) { + result = expectedResult; + int vchan = q->at(0) & 0x7F; + uint8_t c = q->at(1); + fnDwCom.incomingChannel[vchan].push_back(c); + + resetState(); + Debug_printv("OP_FASTWRITE (serial): vchan = $%02x, byte $%02x\n", vchan, c); + } + + return result; +} + +int systemBus::op_fastwrite_screen(std::vector *q) +{ + int result = 0; + int expectedResult = 2; + + if (q->size() >= expectedResult) { + result = expectedResult; + int vchan = q->at(0) & 0x7F; + uint8_t c = q->at(1); + fnDwCom.incomingChannel[vchan].push_back(c); + + resetState(); + Debug_printv("OP_FASTWRITE (serial): vchan = $%02x, byte $%02x\n", vchan, c); + } + + return result; +} + +// Read and process a command frame from DRIVEWIRE +int systemBus::_drivewire_process_cmd(std::vector *q) +{ + int result = 0; + + timer_start(); + + uint8_t c = q->at(0); + fnLedManager.set(eLed::LED_BUS, true); - switch (c) + if (c >= 0x80 && c <= 0x8E) + { + // handle FASTWRITE serial + dwStateMethod = &systemBus::op_fastwrite_serial; + } + else if (c >= 0x91 && c <= 0x9E) + { + // handle FASTWRITE virtual screen + dwStateMethod = &systemBus::op_fastwrite_screen; + } + else { - case OP_JEFF: - op_jeff(); - break; - case OP_NOP: - op_nop(); - break; - case OP_RESET1: - case OP_RESET2: - case OP_RESET3: - op_reset(); - break; - case OP_READEX: - op_readex(); - break; - case OP_WRITE: - op_write(); - break; - case OP_TIME: - op_time(); - break; - case OP_INIT: - op_init(); - break; - case OP_DWINIT: - op_dwinit(); - break; - case OP_SERREAD: - op_serread(); - break; - case OP_PRINT: - op_print(); - break; - case OP_PRINTFLUSH: - // Not needed. - break; - case OP_GETSTAT: - op_getstat(); - break; - case OP_SETSTAT: - op_setstat(); - break; - case OP_TERM: - Debug_printf("OP_TERM!\n"); - break; - case OP_FUJI: - op_fuji(); - break; - case OP_NET: - op_net(); - break; - case OP_CPM: - op_cpm(); - break; - default: - op_unhandled(c); - break; + switch (c) + { + case OP_JEFF: + dwStateMethod = &systemBus::op_jeff; + break; + case OP_NOP: + dwStateMethod = &systemBus::op_nop; + break; + case OP_RESET1: + case OP_RESET2: + case OP_RESET3: + dwStateMethod = &systemBus::op_reset; + break; + case OP_READEX: + dwStateMethod = &systemBus::op_readex; + break; + case OP_WRITE: + dwStateMethod = &systemBus::op_write; + break; + case OP_TIME: + dwStateMethod = &systemBus::op_time; + break; + case OP_INIT: + dwStateMethod = &systemBus::op_init; + break; + case OP_SERINIT: + dwStateMethod = &systemBus::op_serinit; + break; + case OP_DWINIT: + dwStateMethod = &systemBus::op_dwinit; + break; + case OP_SERREAD: + dwStateMethod = &systemBus::op_serread; + break; + case OP_SERREADM: + dwStateMethod = &systemBus::op_serreadm; + break; + case OP_SERWRITE: + dwStateMethod = &systemBus::op_serwrite; + break; + case OP_SERWRITEM: + dwStateMethod = &systemBus::op_serwritem; + break; + case OP_PRINT: + dwStateMethod = &systemBus::op_print; + break; + case OP_PRINTFLUSH: + dwStateMethod = &systemBus::op_printflush; + break; + case OP_GETSTAT: + dwStateMethod = &systemBus::op_getstat; + break; + case OP_SETSTAT: + dwStateMethod = &systemBus::op_setstat; + break; + case OP_SERGETSTAT: + dwStateMethod = &systemBus::op_sergetstat; + break; + case OP_SERSETSTAT: + dwStateMethod = &systemBus::op_sersetstat; + break; + case OP_TERM: + dwStateMethod = &systemBus::op_term; + break; + case OP_SERTERM: + dwStateMethod = &systemBus::op_serterm; + break; + case OP_FUJI: + q->erase(q->begin()); // lob off OP_FUJI so parsing in fuji.cpp can go smoothly + dwStateMethod = &systemBus::op_fuji; + break; + case OP_NET: + dwStateMethod = &systemBus::op_net; + break; + case OP_CPM: + dwStateMethod = &systemBus::op_cpm; + break; + default: + dwStateMethod = &systemBus::op_unhandled; + break; + } } + + result = (this->*dwStateMethod)(q); fnLedManager.set(eLed::LED_BUS, false); + + return result; } // Look to see if we have any waiting messages and process them accordingly @@ -458,11 +924,60 @@ void systemBus::service() } } - if (fnDwCom.available()) - _drivewire_process_cmd(); - - fnDwCom.poll(1); + // TODO: read from serial port... +// if (fnDwCom.available()) +// _drivewire_process_cmd(); +// fnDwCom.poll(1); + + int gotNewData = 0; + + while (fnDwCom.available()) { + int byte = fnDwCom.read(); + serialBuffer.push_back(byte); + gotNewData = 1; + } + + int showDump = 1; + +#ifdef ESP_PLATFORM +#else + uint64_t ms = fnSystem.millis(); +#if 0 + if (ms % 100 == 0) { + Debug_printv("MS = %ld, lastInterruptMs = %ld, TIMER = %ld\n", ms, lastInterruptMs, (timerActive == true && ms - lastInterruptMs >= timerRate)); + } +#endif + if (timerActive == true && ms - lastInterruptMs >= timerRate) + { + Debug_printv("State Reset Timer INVOKED!\n"); + resetState(); + } +#endif + if (gotNewData == 1 && showDump == 1 && serialBuffer.size() > 0) + { + for (int i = 0; i < serialBuffer.size(); i++) + { + Debug_printf("$%02x ", serialBuffer.at(i)); + } + + Debug_printf("=====================================\n"); + } + + if (gotNewData == 1) + { + int bytesConsumed = 0; + + do { + bytesConsumed = (this->*dwStateMethod)(&serialBuffer); + + if (bytesConsumed > 0 && serialBuffer.size() >= bytesConsumed) { + // chop off consumed bytes + serialBuffer.erase(serialBuffer.begin(), serialBuffer.begin() + bytesConsumed); + } + } while (bytesConsumed > 0 && serialBuffer.size() > 0); + } + // dload.dload_process(); } @@ -539,6 +1054,8 @@ void systemBus::setup() fnDwCom.set_becker_host(Config.get_boip_host().c_str(), Config.get_boip_port()); // Becker fnDwCom.set_drivewire_mode(Config.get_boip_enabled() ? DwCom::dw_mode::BECKER : DwCom::dw_mode::SERIAL); + resetState(); + fnDwCom.begin(_drivewireBaud); fnDwCom.flush_input(); Debug_printv("DRIVEWIRE MODE"); diff --git a/lib/bus/drivewire/drivewire.h b/lib/bus/drivewire/drivewire.h index 95a1ad952..e933573e2 100644 --- a/lib/bus/drivewire/drivewire.h +++ b/lib/bus/drivewire/drivewire.h @@ -24,6 +24,10 @@ #include #endif +#include +#include + +#include #include #include // fnUartBUS (Serial only) was replaced with fnDwCom (Serial|TCP/Becker) @@ -37,8 +41,13 @@ #define OP_NOP 0 #define OP_JEFF 0xA5 #define OP_SERREAD 'C' +#define OP_SERREADM 'c' +#define OP_SERWRITE 0xC3 +#define OP_SERWRITEM 0x64 #define OP_GETSTAT 'G' #define OP_SETSTAT 'S' +#define OP_SERGETSTAT 'D' +#define OP_SERSETSTAT 'D'+128 #define OP_READ 'R' #define OP_READEX 'R'+128 #define OP_WRITE 'W' @@ -46,6 +55,8 @@ #define OP_REREADEX 'r'+128 #define OP_REWRITE 'w' #define OP_INIT 'I' +#define OP_SERINIT 'E' +#define OP_SERTERM 'E'+128 #define OP_DWINIT 'Z' #define OP_TERM 'T' #define OP_TIME '#' @@ -181,6 +192,10 @@ struct drivewire_message_t class systemBus { +public: + int (drivewireFuji::*fnStateMethod)(std::vector *); + void resetState(void); + private: virtualDevice *_activeDev = nullptr; drivewireModem *_modemDev = nullptr; @@ -191,9 +206,11 @@ class systemBus drivewireCPM *_cpmDev = nullptr; drivewirePrinter *_printerdev = nullptr; - void _drivewire_process_cmd(); + int _drivewire_process_cmd(std::vector *q); void _drivewire_process_queue(); + int guestCapabilityByte; + /** * @brief Current Baud Rate */ @@ -214,25 +231,69 @@ class systemBus */ uint8_t sector_data[MEDIA_BLOCK_SIZE]; + int (systemBus::*dwStateMethod)(std::vector *); + std::vector serialBuffer; + + /** + * Timer Rate for interrupt timer (ms) + */ +#ifdef ESP_PLATFORM + int timerRate = 2000; +#else + int timerRate = 2000; + bool timerActive = false; +#endif + + /** + * Timer handle for the DriveWire state machine recovery timer + */ +#ifdef ESP_PLATFORM + esp_timer_handle_t stateMachineRecoveryTimerHandle = nullptr; +#else + uint64_t lastInterruptMs; +#endif + /** + * Start the Interrupt rate limiting timer + */ + void timer_start(); + + /** + * Stop the Interrupt rate limiting timer + */ + void timer_stop(); + /** * @brief NOP command (do nothing) */ - void op_jeff(); - void op_nop(); - void op_reset(); - void op_readex(); - void op_fuji(); - void op_net(); - void op_cpm(); - void op_write(); - void op_time(); - void op_init(); - void op_dwinit(); - void op_unhandled(uint8_t c); - void op_getstat(); - void op_setstat(); - void op_serread(); - void op_print(); + int op_jeff(std::vector *q); + int op_nop(std::vector *q); + int op_reset(std::vector *q); + int op_readex(std::vector *q); + int op_readex_p2(std::vector *q); + int op_fuji(std::vector *q); + int op_net(std::vector *q); + int op_cpm(std::vector *q); + int op_write(std::vector *q); + int op_time(std::vector *q); + int op_init(std::vector *q); + int op_term(std::vector *q); + int op_fastwrite_serial(std::vector *q); + int op_fastwrite_screen(std::vector *q); + int op_serinit(std::vector *q); + int op_serterm(std::vector *q); + int op_dwinit(std::vector *q); + int op_unhandled(std::vector *q); + int op_getstat(std::vector *q); + int op_setstat(std::vector *q); + int op_sergetstat(std::vector *q); + int op_sersetstat(std::vector *q); + int op_sersetstat_comstat(std::vector *q); + int op_serread(std::vector *q); + int op_serreadm(std::vector *q); + int op_serwrite(std::vector *q); + int op_serwritem(std::vector *q); + int op_print(std::vector *q); + int op_printflush(std::vector *q); // int readSector(struct dwTransferData *dp); // int writeSector(struct dwTransferData *dp); diff --git a/lib/bus/drivewire/dwcom/fnDwCom.h b/lib/bus/drivewire/dwcom/fnDwCom.h index 556a0458c..2cceddafc 100644 --- a/lib/bus/drivewire/dwcom/fnDwCom.h +++ b/lib/bus/drivewire/dwcom/fnDwCom.h @@ -25,6 +25,14 @@ class DwCom BECKER }; + bool pollingMode; + + // Host & client channel queues + std::vector outgoingChannel[16]; + std::vector incomingChannel[16]; + std::vector incomingScreen[16]; + + private: dw_mode _dw_mode; DwPort *_dwPort; @@ -68,14 +76,76 @@ class DwCom // write buffer ssize_t write(const uint8_t *buffer, size_t size) { return _dwPort->write(buffer, size); } + + // write buffer to FN channel + ssize_t writeToFNChannel(int channel, const uint8_t *buffer, size_t size) + { + int result = 0; + + if (pollingMode == true) + { + for (int i = 0; i < size; i++) + { + outgoingChannel[channel].push_back(buffer[i]); + } + result = size; + } + else + { + result = write(buffer, size); + } + + return result; + } + // write C-string ssize_t write(const char *str) { return _dwPort->write((const uint8_t *)str, strlen(str)); } + // write C-string to FN channel + ssize_t writeToFNChannel(int channel, const char *str) + { + int result = 0; + + if (pollingMode == true) + { + result = strlen(str); + for (int i = 0; i < result; i++) + { + outgoingChannel[channel].push_back(str[i]); + } + } + else + { + result = write(str); + } + + return result; + } + // read single byte, mimic UARTManager int read(); + // write single byte, mimic UARTManager ssize_t write(uint8_t b) { return _dwPort->write(&b, 1); } + // write C-string to FN channel + ssize_t writeToFNChannel(int channel, uint8_t b) + { + int result = 0; + + if (pollingMode == true) + { + result = 1; + outgoingChannel[channel].push_back(b); + } + else + { + result = write(b); + } + + return result; + } + // mimic UARTManager overloaded write functions size_t write(unsigned long n) { return write((uint8_t)n); } size_t write(long n) { return write((uint8_t)n); } diff --git a/lib/device/drivewire/fuji.cpp b/lib/device/drivewire/fuji.cpp index 658039fd1..11268ab3c 100755 --- a/lib/device/drivewire/fuji.cpp +++ b/lib/device/drivewire/fuji.cpp @@ -35,6 +35,12 @@ drivewireNetwork drivewireNetDevs[MAX_NETWORK_DEVICES]; bool _validate_host_slot(uint8_t slot, const char *dmsg = nullptr); bool _validate_device_slot(uint8_t slot, const char *dmsg = nullptr); +void drivewireFuji::resetState(void) +{ + _drivewire_bus->fnStateMethod = &drivewireFuji::process; + _drivewire_bus->resetState(); +} + bool _validate_host_slot(uint8_t slot, const char *dmsg) { if (slot < MAX_HOSTS) @@ -128,16 +134,24 @@ drivewireFuji::drivewireFuji() } // Reset FujiNet -void drivewireFuji::reset_fujinet() +int drivewireFuji::reset_fujinet(std::vector *q) { + int result = 1; + Debug_println("Fuji cmd: REBOOT"); // drivewire_complete(); fnSystem.reboot(); + + resetState(); + + return result; } // Scan for networks -void drivewireFuji::net_scan_networks() +int drivewireFuji::net_scan_networks(std::vector *q) { + int result = 1; + Debug_println("Fuji cmd: SCAN NETWORKS"); if (!wifiScanStarted) @@ -150,43 +164,61 @@ void drivewireFuji::net_scan_networks() response.shrink_to_fit(); response += _countScannedSSIDs; + + resetState(); + + return result; } // Return scanned network entry -void drivewireFuji::net_scan_result() +int drivewireFuji::net_scan_result(std::vector *q) { - Debug_println("Fuji cmd: GET SCAN RESULT"); - - uint8_t n = fnDwCom.read(); - - wifiScanStarted = false; - - // Response to FUJICMD_GET_SCAN_RESULT - struct - { - char ssid[MAX_SSID_LEN + 1]; - uint8_t rssi; - } detail; - - if (n < _countScannedSSIDs) - fnWiFi.get_scan_result(n, detail.ssid, &detail.rssi); - else + int result = 0; + int expectedResult = 2; + + if (q->size() >= expectedResult) { - memset(&detail, 0, sizeof(detail)); - errorCode = 144; + result = expectedResult; + + Debug_println("Fuji cmd: GET SCAN RESULT"); + + uint8_t n = q->at(1); + + wifiScanStarted = false; + + // Response to FUJICMD_GET_SCAN_RESULT + struct + { + char ssid[MAX_SSID_LEN + 1]; + uint8_t rssi; + } detail; + + if (n < _countScannedSSIDs) + fnWiFi.get_scan_result(n, detail.ssid, &detail.rssi); + else + { + memset(&detail, 0, sizeof(detail)); + errorCode = 144; + } + + response.clear(); + response.shrink_to_fit(); + + response = std::string((const char *)&detail, sizeof(detail)); + + errorCode = 1; + + resetState(); } - - response.clear(); - response.shrink_to_fit(); - - response = std::string((const char *)&detail, sizeof(detail)); - - errorCode = 1; + + return result; } // Get SSID -void drivewireFuji::net_get_ssid() +int drivewireFuji::net_get_ssid(std::vector *q) { + int result = 1; + Debug_println("Fuji cmd: GET SSID"); // Response to FUJICMD_GET_SSID @@ -217,45 +249,66 @@ void drivewireFuji::net_get_ssid() response = std::string((const char *)&cfg, sizeof(cfg)); errorCode = 1; + + resetState(); + + return result; } // Set SSID -void drivewireFuji::net_set_ssid() +int drivewireFuji::net_set_ssid(std::vector *q) { - Debug_printf("\r\nFuji cmd: SET SSID"); struct { char ssid[MAX_SSID_LEN + 1]; char password[MAX_WIFI_PASS_LEN]; } cfg; - fnDwCom.readBytes((uint8_t *)&cfg, sizeof(cfg)); - - bool save = false; // for now don't save - to do save if connection was succesful - - // URL Decode SSID/PASSWORD to handle special chars (FIXME) - //mstr::urlDecode(cfg.ssid, sizeof(cfg.ssid)); - //mstr::urlDecode(cfg.password, sizeof(cfg.password)); - - Debug_printf("\r\nConnecting to net: %s password: %s\n", cfg.ssid, cfg.password); - - if (fnWiFi.connect(cfg.ssid, cfg.password) == ESP_OK) - { - Config.store_wifi_ssid(cfg.ssid, sizeof(cfg.ssid)); - Config.store_wifi_passphrase(cfg.password, sizeof(cfg.password)); - } - - // Only save these if we're asked to, otherwise assume it was a test for connectivity - // should only save if connection was successful - i think - if (save) + int result = 0; + int expectedResult = 1 + sizeof(cfg); + + if (q->size() >= expectedResult) { - Config.save(); + result = expectedResult; + + Debug_printf("\r\nFuji cmd: SET SSID"); + + std::vector buff(sizeof(cfg)); + std::copy(q->begin() + 1, q->begin() + expectedResult, buff.begin()); + memcpy((uint8_t *)&cfg, buff.data(), sizeof(cfg)); + + bool save = false; // for now don't save - to do save if connection was succesful + + // URL Decode SSID/PASSWORD to handle special chars (FIXME) + //mstr::urlDecode(cfg.ssid, sizeof(cfg.ssid)); + //mstr::urlDecode(cfg.password, sizeof(cfg.password)); + + Debug_printf("\r\nConnecting to net: %s password: %s\n", cfg.ssid, cfg.password); + + if (fnWiFi.connect(cfg.ssid, cfg.password) == ESP_OK) + { + Config.store_wifi_ssid(cfg.ssid, sizeof(cfg.ssid)); + Config.store_wifi_passphrase(cfg.password, sizeof(cfg.password)); + } + + // Only save these if we're asked to, otherwise assume it was a test for connectivity + // should only save if connection was successful - i think + if (save) + { + Config.save(); + } + + resetState(); } + + return result; } // Get WiFi Status -void drivewireFuji::net_get_wifi_status() +int drivewireFuji::net_get_wifi_status(std::vector *q) { + int result = 1; + uint8_t wifiStatus = fnWiFi.connected() ? 3 : 6; Debug_printv("Fuji cmd: GET WIFI STATUS: %u", wifiStatus); @@ -265,11 +318,17 @@ void drivewireFuji::net_get_wifi_status() response += wifiStatus; errorCode = 1; + + resetState(); + + return result; } // Check if Wifi is enabled -void drivewireFuji::net_get_wifi_enabled() +int drivewireFuji::net_get_wifi_enabled(std::vector *q) { + int result = 1; + uint8_t e = Config.get_wifi_enabled() ? 1 : 0; Debug_printv("Fuji cmd: GET WIFI ENABLED: %u", e); @@ -280,69 +339,103 @@ void drivewireFuji::net_get_wifi_enabled() response += e; errorCode = 1; // Set it anyway. + + resetState(); + + return result; } // Mount Server -void drivewireFuji::mount_host() +int drivewireFuji::mount_host(std::vector *q) { - Debug_println("Fuji cmd: MOUNT HOST"); + int result = 0; + int expectedResult = 2; + + if (q->size() >= expectedResult) + { + result = expectedResult; + Debug_println("Fuji cmd: MOUNT HOST"); - unsigned char hostSlot = fnDwCom.read(); + unsigned char hostSlot = q->at(1); - _fnHosts[hostSlot].mount(); + _fnHosts[hostSlot].mount(); + + resetState(); + } + + return result; } // Disk Image Mount -void drivewireFuji::disk_image_mount() +int drivewireFuji::disk_image_mount(std::vector *q) { - // TAPE or CASSETTE handling: this function can also mount CAS and WAV files - // to the C: device. Everything stays the same here and the mounting - // where all the magic happens is done in the drivewireDisk::mount() function. - // This function opens the file, so cassette does not need to open the file. - // Cassette needs the file pointer and file size. - - Debug_println("Fuji cmd: MOUNT IMAGE"); - - uint8_t deviceSlot = fnDwCom.read(); - uint8_t options = fnDwCom.read(); // DISK_ACCESS_MODE - - // TODO: Implement FETCH? - char flag[3] = {'r', 0, 0}; - if (options == DISK_ACCESS_MODE_WRITE) - flag[1] = '+'; - - // A couple of reference variables to make things much easier to read... - fujiDisk &disk = _fnDisks[deviceSlot]; - fujiHost &host = _fnHosts[disk.host_slot]; - - Debug_printf("Selecting '%s' from host #%u as %s on D%u:\n", - disk.filename, disk.host_slot, flag, deviceSlot + 1); - - // TODO: Refactor along with mount disk image. - disk.disk_dev.host = &host; - - disk.fileh = host.fnfile_open(disk.filename, disk.filename, sizeof(disk.filename), flag); - - // We've gotten this far, so make sure our bootable CONFIG disk is disabled - boot_config = false; - - // We need the file size for loading XEX files and for CASSETTE, so get that too - disk.disk_size = host.file_size(disk.fileh); - - // And now mount it - disk.disk_type = disk.disk_dev.mount(disk.fileh, disk.filename, disk.disk_size); + int result = 0; + int expectedResult = 3; + + if (q->size() >= expectedResult) + { + // TAPE or CASSETTE handling: this function can also mount CAS and WAV files + // to the C: device. Everything stays the same here and the mounting + // where all the magic happens is done in the drivewireDisk::mount() function. + // This function opens the file, so cassette does not need to open the file. + // Cassette needs the file pointer and file size. + result = expectedResult; + + Debug_println("Fuji cmd: MOUNT IMAGE"); + + uint8_t deviceSlot = q->at(1); + uint8_t options = q->at(2); // DISK_ACCESS_MODE + + // TODO: Implement FETCH? + char flag[3] = {'r', 0, 0}; + if (options == DISK_ACCESS_MODE_WRITE) + flag[1] = '+'; + + // A couple of reference variables to make things much easier to read... + fujiDisk &disk = _fnDisks[deviceSlot]; + fujiHost &host = _fnHosts[disk.host_slot]; + + Debug_printf("Selecting '%s' from host #%u as %s on D%u:\n", + disk.filename, disk.host_slot, flag, deviceSlot + 1); + + // TODO: Refactor along with mount disk image. + disk.disk_dev.host = &host; + + disk.fileh = host.fnfile_open(disk.filename, disk.filename, sizeof(disk.filename), flag); + + // We've gotten this far, so make sure our bootable CONFIG disk is disabled + boot_config = false; + + // We need the file size for loading XEX files and for CASSETTE, so get that too + disk.disk_size = host.file_size(disk.fileh); + + // And now mount it + disk.disk_type = disk.disk_dev.mount(disk.fileh, disk.filename, disk.disk_size); + + resetState(); + } + + return result; } // Toggle boot config on/off, aux1=0 is disabled, aux1=1 is enabled -void drivewireFuji::set_boot_config() +int drivewireFuji::set_boot_config(std::vector *q) { + int result = 1; + // boot_config = cmdFrame.aux1; // drivewire_complete(); + + resetState(); + + return result; } // Do DRIVEWIRE copy -void drivewireFuji::copy_file() +int drivewireFuji::copy_file(std::vector *q) { + int result = 1; + // uint8_t csBuf[256]; // string copySpec; // string sourcePath; @@ -474,11 +567,26 @@ void drivewireFuji::copy_file() // fclose(sourceFile); // fclose(destFile); // free(dataBuf); + + resetState(); + + return result; } // Mount all -void drivewireFuji::mount_all() +int drivewireFuji::local_mount_all(std::vector *q) { + int result = 1; + + mount_all(); + + resetState(); + + return result; +} + +void drivewireFuji::mount_all() +{ bool nodisks = true; // Check at the end if no disks are in a slot and disable config Debug_printf("drivewireFuji::mount_all()\n"); @@ -534,14 +642,24 @@ void drivewireFuji::mount_all() } Debug_printf("drivewireFuji::mount_all() done.\n"); - } // Set boot mode -void drivewireFuji::set_boot_mode() +int drivewireFuji::set_boot_mode(std::vector *q) { - insert_boot_device(fnDwCom.read()); - boot_config = true; + int result = 0; + int expectedResult = 2; + + if (q->size() >= expectedResult) + { + result = expectedResult; + insert_boot_device(q->at(1)); + boot_config = true; + + resetState(); + } + + return result; } char *_generate_appkey_filename(appkey *info) @@ -559,116 +677,148 @@ char *_generate_appkey_filename(appkey *info) Requiring a separate OPEN command makes both the read and write commands behave similarly and leaves the possibity for a more robust/general file read/write function later. */ -void drivewireFuji::open_app_key() -{ - Debug_print("Fuji cmd: OPEN APPKEY\n"); - - fnDwCom.readBytes((uint8_t *)&_current_appkey, sizeof(_current_appkey)); - - // Endian swap - uint16_t tmp = _current_appkey.creator; - _current_appkey.creator = tmp >> 8 | tmp << 8; - - // Basic check for valid data - if (_current_appkey.creator == 0 || _current_appkey.mode == APPKEYMODE_INVALID) - { - Debug_println("Invalid app key data"); - errorCode = 144; - return; +int drivewireFuji::open_app_key(std::vector *q) +{ + int result = 0; + int expectedResult = sizeof(_current_appkey) + 1; + + if (q->size() >= expectedResult) { + result = expectedResult; + Debug_print("Fuji cmd: OPEN APPKEY\n"); + + std::vector app_key(256); + std::copy(q->begin() + 1, q->begin() + expectedResult, app_key.begin()); + memcpy((uint8_t *)&_current_appkey, app_key.data(), sizeof(_current_appkey)); + + // Endian swap + uint16_t tmp = _current_appkey.creator; + _current_appkey.creator = tmp >> 8 | tmp << 8; + + // Basic check for valid data + if (_current_appkey.creator == 0 || _current_appkey.mode == APPKEYMODE_INVALID) + { + Debug_println("Invalid app key data"); + errorCode = 144; + } + else if (fnSDFAT.running() == false) + { + Debug_println("No SD mounted - returning error"); + errorCode = 144; + } + else + { + errorCode = 1; + + Debug_printf("App key creator = 0x%04hx, app = 0x%02hhx, key = 0x%02hhx, mode = %hhu, filename = \"%s\"\n", + _current_appkey.creator, _current_appkey.app, _current_appkey.key, _current_appkey.mode, + _generate_appkey_filename(&_current_appkey)); + } + + resetState(); } - - if (fnSDFAT.running() == false) - { - Debug_println("No SD mounted - returning error"); - errorCode = 144; - return; - } - - errorCode = 1; - - Debug_printf("App key creator = 0x%04hx, app = 0x%02hhx, key = 0x%02hhx, mode = %hhu, filename = \"%s\"\n", - _current_appkey.creator, _current_appkey.app, _current_appkey.key, _current_appkey.mode, - _generate_appkey_filename(&_current_appkey)); + + return result; } /* The app key close operation is a placeholder in case we want to provide more robust file read/write operations. Currently, the file is closed immediately after the read or write operation. */ -void drivewireFuji::close_app_key() +int drivewireFuji::close_app_key(std::vector *q) { + int result = 1; + Debug_print("Fuji cmd: CLOSE APPKEY\n"); _current_appkey.creator = 0; _current_appkey.mode = APPKEYMODE_INVALID; errorCode = 1; + + resetState(); + + return result; } /* Write an "app key" to SD (ONLY!) storage. */ -void drivewireFuji::write_app_key() +int drivewireFuji::write_app_key(std::vector *q) { - uint8_t lenh = fnDwCom.read(); - uint8_t lenl = fnDwCom.read(); - uint16_t len = lenh << 8 | lenl; - uint8_t value[MAX_APPKEY_LEN]; - - memset(value,0,sizeof(value)); - - fnDwCom.readBytes(value, len); - - // Make sure we have valid app key information - if (_current_appkey.creator == 0 || _current_appkey.mode != APPKEYMODE_WRITE) - { - Debug_println("Invalid app key metadata - aborting"); - errorCode = 144; - return; - } - - // Make sure we have an SD card mounted - if (fnSDFAT.running() == false) - { - Debug_println("No SD mounted - can't write app key"); - errorCode = 144; - return; - } - - char *filename = _generate_appkey_filename(&_current_appkey); - - // Reset the app key data so we require calling APPKEY OPEN before another attempt - _current_appkey.creator = 0; - _current_appkey.mode = APPKEYMODE_INVALID; - - Debug_printf("Writing appkey to \"%s\"\n", filename); - - // Make sure we have a "/FujiNet" directory, since that's where we're putting these files - fnSDFAT.create_path("/FujiNet"); - - FILE *fOut = fnSDFAT.file_open(filename, "w"); - if (fOut == nullptr) - { - Debug_printf("Failed to open/create output file: errno=%d\n", errno); - errorCode = 144; - return; - } - size_t count = fwrite(value, 1, len, fOut); - int e = errno; - - fclose(fOut); - - if (count != len) + int result = 0; + int expectedResult = 3 + MAX_APPKEY_LEN; + + if (q->size() >= expectedResult) { - Debug_printf("Only wrote %u bytes of expected %hu, errno=%d\n", count, len, e); - errorCode = 144; + result = expectedResult; + uint8_t lenh = q->at(1); + uint8_t lenl = q->at(2); + uint16_t len = lenh << 8 | lenl; + uint8_t value[MAX_APPKEY_LEN]; + + memset(value,0,sizeof(value)); + + std::vector buff(256); + std::copy(q->begin() + 3, q->begin() + 3 + MAX_APPKEY_LEN, buff.begin()); + memcpy((uint8_t *)value, buff.data(), MAX_APPKEY_LEN); + + // Make sure we have valid app key information + if (_current_appkey.creator == 0 || _current_appkey.mode != APPKEYMODE_WRITE) + { + Debug_println("Invalid app key metadata - aborting"); + errorCode = 144; + return result; + } + + // Make sure we have an SD card mounted + if (fnSDFAT.running() == false) + { + Debug_println("No SD mounted - can't write app key"); + errorCode = 144; + return result; + } + + char *filename = _generate_appkey_filename(&_current_appkey); + + // Reset the app key data so we require calling APPKEY OPEN before another attempt + _current_appkey.creator = 0; + _current_appkey.mode = APPKEYMODE_INVALID; + + Debug_printf("Writing appkey to \"%s\"\n", filename); + + // Make sure we have a "/FujiNet" directory, since that's where we're putting these files + fnSDFAT.create_path("/FujiNet"); + + FILE *fOut = fnSDFAT.file_open(filename, "w"); + if (fOut == nullptr) + { + Debug_printf("Failed to open/create output file: errno=%d\n", errno); + errorCode = 144; + return result; + } + size_t count = fwrite(value, 1, len, fOut); + int e = errno; + + fclose(fOut); + + if (count != len) + { + Debug_printf("Only wrote %u bytes of expected %hu, errno=%d\n", count, len, e); + errorCode = 144; + } + errorCode = 1; + + resetState(); } - errorCode = 1; + + return result; } /* Read an "app key" from SD (ONLY!) storage */ -void drivewireFuji::read_app_key() +int drivewireFuji::read_app_key(std::vector *q) { + int result = 1; + Debug_println("Fuji cmd: READ APPKEY"); // Make sure we have an SD card mounted @@ -676,7 +826,7 @@ void drivewireFuji::read_app_key() { Debug_println("No SD mounted - can't read app key"); errorCode = 144; - return; + return result; } // Make sure we have valid app key information @@ -684,7 +834,7 @@ void drivewireFuji::read_app_key() { Debug_println("Invalid app key metadata - aborting"); errorCode = 144; - return; + return result; } char *filename = _generate_appkey_filename(&_current_appkey); @@ -696,7 +846,7 @@ void drivewireFuji::read_app_key() { Debug_printf("Failed to open input file: errno=%d\n", errno); errorCode = 144; - return; + return result; } std::vector buffer(MAX_APPKEY_LEN); @@ -711,22 +861,36 @@ void drivewireFuji::read_app_key() response.append(reinterpret_cast(buffer.data()), count); errorCode = 1; + + resetState(); + + return result; } // Disk Image Unmount -void drivewireFuji::disk_image_umount() +int drivewireFuji::disk_image_umount(std::vector *q) { - uint8_t deviceSlot = fnDwCom.read(); - - Debug_printf("Fuji cmd: UNMOUNT IMAGE 0x%02X\n", deviceSlot); - - // Handle disk slots - if (deviceSlot < MAX_DISK_DEVICES) + int result = 0; + int expectedResult = 2; + + if (q->size() >= expectedResult) { - _fnDisks[deviceSlot].disk_dev.unmount(); - _fnDisks[deviceSlot].disk_dev.device_active = false; - _fnDisks[deviceSlot].reset(); - } + result = expectedResult; + uint8_t deviceSlot = q->at(1); + + Debug_printf("Fuji cmd: UNMOUNT IMAGE 0x%02X\n", deviceSlot); + + // Handle disk slots + if (deviceSlot < MAX_DISK_DEVICES) + { + _fnDisks[deviceSlot].disk_dev.unmount(); + _fnDisks[deviceSlot].disk_dev.device_active = false; + _fnDisks[deviceSlot].reset(); + } + + resetState(); + } + return result; } // Disk Image Rotate @@ -777,22 +941,30 @@ void drivewireFuji::image_rotate() } // This gets called when we're about to shutdown/reboot -void drivewireFuji::shutdown() +void drivewireFuji::shutdown(void) { for (int i = 0; i < MAX_DISK_DEVICES; i++) _fnDisks[i].disk_dev.unmount(); -} + } -void drivewireFuji::open_directory() +int drivewireFuji::open_directory(std::vector *q) { - Debug_println("Fuji cmd: OPEN DIRECTORY"); - - uint8_t hostSlot = fnDwCom.read(); + int result = 0; + int expectedResult = 2 + 256; + + if (q->size() >= expectedResult) + { + result = expectedResult; + Debug_println("Fuji cmd: OPEN DIRECTORY"); - fnDwCom.readBytes((uint8_t *)&dirpath, 256); + uint8_t hostSlot = q->at(1); - if (_current_open_directory_slot == -1) - { + std::vector buff(256); + std::copy(q->begin() + 2, q->begin() + 2 + 256, buff.begin()); + memcpy((uint8_t *)dirpath, buff.data(), 256); + + if (_current_open_directory_slot == -1) + { // See if there's a search pattern after the directory path const char *pattern = nullptr; int pathlen = strnlen(dirpath, sizeof(dirpath)); @@ -803,18 +975,23 @@ void drivewireFuji::open_directory() if (patternlen < 1) pattern = nullptr; } - + // Remove trailing slash if (pathlen > 1 && dirpath[pathlen - 1] == '/') dirpath[pathlen - 1] = '\0'; - + Debug_printf("Opening directory: \"%s\", pattern: \"%s\"\n", dirpath, pattern ? pattern : ""); - + if (_fnHosts[hostSlot].dir_open(dirpath, pattern, 0)) { _current_open_directory_slot = hostSlot; } + } + + resetState(); } + + return result; } void _set_additional_direntry_details(fsdir_entry_t *f, uint8_t *dest, uint8_t maxlen) @@ -861,95 +1038,127 @@ void _set_additional_direntry_details(fsdir_entry_t *f, uint8_t *dest, uint8_t m char current_entry[256]; -void drivewireFuji::read_directory_entry() +int drivewireFuji::read_directory_entry(std::vector *q) { - uint8_t maxlen = fnDwCom.read(); - uint8_t addtl = fnDwCom.read(); - - Debug_printf("Fuji cmd: READ DIRECTORY ENTRY (max=%hu) (addtl=%02x)\n", maxlen, addtl); - - memset(current_entry, 0, sizeof(current_entry)); - - fsdir_entry_t *f = _fnHosts[_current_open_directory_slot].dir_nextfile(); - - if (f == nullptr) - { - Debug_println("Reached end of of directory"); - current_entry[0] = 0x7F; - current_entry[1] = 0x7F; - } - else + int result = 0; + int expectedResult = 3; + + if (q->size() >= expectedResult) { - Debug_printf("::read_direntry \"%s\"\n", f->filename); - - int bufsize = sizeof(current_entry); - int fno=0; - - // If 0x80 is set on AUX2, send back additional information - if (addtl & 0x80) - { - Debug_printf("Add additional info.\n"); - _set_additional_direntry_details(f, (uint8_t *)current_entry, maxlen); - // Adjust remaining size of buffer and file path destination - bufsize = sizeof(dirpath) - ADDITIONAL_DETAILS_BYTES; - fno += ADDITIONAL_DETAILS_BYTES; - } - else - { - bufsize = maxlen; - } - - // int filelen = strlcpy(filenamedest, f->filename, bufsize); - int filelen = util_ellipsize(f->filename, ¤t_entry[fno], bufsize); - - // Add a slash at the end of directory entries - if (f->isDir && filelen < (bufsize - 2)) - { - current_entry[filelen] = '/'; - current_entry[filelen + 1] = '\0'; - } + result = expectedResult; + + uint8_t maxlen = q->at(1); + uint8_t addtl = q->at(2); + + Debug_printf("Fuji cmd: READ DIRECTORY ENTRY (max=%hu) (addtl=%02x)\n", maxlen, addtl); + + memset(current_entry, 0, sizeof(current_entry)); + + fsdir_entry_t *f = _fnHosts[_current_open_directory_slot].dir_nextfile(); + + if (f == nullptr) + { + Debug_println("Reached end of of directory"); + current_entry[0] = 0x7F; + current_entry[1] = 0x7F; + } + else + { + Debug_printf("::read_direntry \"%s\"\n", f->filename); + + int bufsize = sizeof(current_entry); + int fno=0; + + // If 0x80 is set on AUX2, send back additional information + if (addtl & 0x80) + { + Debug_printf("Add additional info.\n"); + _set_additional_direntry_details(f, (uint8_t *)current_entry, maxlen); + // Adjust remaining size of buffer and file path destination + bufsize = sizeof(dirpath) - ADDITIONAL_DETAILS_BYTES; + fno += ADDITIONAL_DETAILS_BYTES; + } + else + { + bufsize = maxlen; + } + + // int filelen = strlcpy(filenamedest, f->filename, bufsize); + int filelen = util_ellipsize(f->filename, ¤t_entry[fno], bufsize); + + // Add a slash at the end of directory entries + if (f->isDir && filelen < (bufsize - 2)) + { + current_entry[filelen] = '/'; + current_entry[filelen + 1] = '\0'; + } + } + + response.clear(); + response.shrink_to_fit(); + + response = std::string((const char *)current_entry, maxlen); + + resetState(); } - response.clear(); - response.shrink_to_fit(); - - response = std::string((const char *)current_entry, maxlen); + return result; } -void drivewireFuji::get_directory_position() +int drivewireFuji::get_directory_position(std::vector *q) { + int result = 1; + Debug_println("Fuji cmd: GET DIRECTORY POSITION"); uint16_t pos = _fnHosts[_current_open_directory_slot].dir_tell(); // Return the value we read - fnDwCom.write(pos << 8); - fnDwCom.write(pos & 0xFF); + fnDwCom.writeToFNChannel(0, pos << 8); + fnDwCom.writeToFNChannel(0, pos & 0xFF); errorCode = 1; + + resetState(); + + return result; } -void drivewireFuji::set_directory_position() +int drivewireFuji::set_directory_position(std::vector *q) { - uint8_t h, l; - - Debug_println("Fuji cmd: SET DIRECTORY POSITION"); - - // DAUX1 and DAUX2 hold the position to seek to in low/high order - h = fnDwCom.read(); - l = fnDwCom.read(); - - Debug_printf("H: %02x L: %02x", h, l); - - uint16_t pos = UINT16_FROM_HILOBYTES(h, l); - - bool result = _fnHosts[_current_open_directory_slot].dir_seek(pos); - - errorCode = (result == true); + int result = 0; + int expectedResult = 3; + + if (q->size() >= expectedResult) + { + result = expectedResult; + + uint8_t h, l; + + Debug_println("Fuji cmd: SET DIRECTORY POSITION"); + + // DAUX1 and DAUX2 hold the position to seek to in low/high order + h = q->at(1); + l = q->at(2); + + Debug_printf("H: %02x L: %02x", h, l); + + uint16_t pos = UINT16_FROM_HILOBYTES(h, l); + + bool seekResult = _fnHosts[_current_open_directory_slot].dir_seek(pos); + + errorCode = (seekResult == true); + + resetState(); + } + + return result; } -void drivewireFuji::close_directory() +int drivewireFuji::close_directory(std::vector *q) { + int result = 1; + Debug_println("Fuji cmd: CLOSE DIRECTORY"); if (_current_open_directory_slot != -1) @@ -957,11 +1166,17 @@ void drivewireFuji::close_directory() _current_open_directory_slot = -1; errorCode = 1; + + resetState(); + + return result; } // Get network adapter configuration -void drivewireFuji::get_adapter_config() +int drivewireFuji::get_adapter_config(std::vector *q) { + int result = 1; + Debug_println("Fuji cmd: GET ADAPTER CONFIG"); // Response to FUJICMD_GET_ADAPTERCONFIG @@ -991,11 +1206,17 @@ void drivewireFuji::get_adapter_config() errorCode = 1; response = std::string((const char *)&cfg, sizeof(cfg)); + + resetState(); + + return result; } // Get network adapter configuration - extended -void drivewireFuji::get_adapter_config_extended() +int drivewireFuji::get_adapter_config_extended(std::vector *q) { + int result = 1; + // also return string versions of the data to save the host some computing Debug_printf("Fuji cmd: GET ADAPTER CONFIG EXTENDED\r\n"); AdapterConfigExtended cfg; @@ -1032,13 +1253,15 @@ void drivewireFuji::get_adapter_config_extended() errorCode = 1; response = std::string((const char *)&cfg, sizeof(cfg)); + + resetState(); + + return result; } // Make new disk and shove into device slot -void drivewireFuji::new_disk() +int drivewireFuji::new_disk(std::vector *q) { - Debug_println("Fuji cmd: NEW DISK"); - struct { unsigned char numDisks; @@ -1047,67 +1270,95 @@ void drivewireFuji::new_disk() char filename[MAX_FILENAME_LEN]; // WIll set this to MAX_FILENAME_LEN, later. } newDisk; - fnDwCom.readBytes((uint8_t *)&newDisk, sizeof(newDisk)); - - Debug_printf("numDisks: %u\n",newDisk.numDisks); - Debug_printf("hostSlot: %u\n",newDisk.hostSlot); - Debug_printf("deviceSl: %u\n",newDisk.deviceSlot); - Debug_printf("filename: %s\n",newDisk.filename); - - // A couple of reference variables to make things much easier to read... - fujiDisk &disk = _fnDisks[newDisk.deviceSlot]; - fujiHost &host = _fnHosts[newDisk.hostSlot]; - - disk.host_slot = newDisk.hostSlot; - disk.access_mode = DISK_ACCESS_MODE_WRITE; - strlcpy(disk.filename, newDisk.filename, sizeof(disk.filename)); - - if (host.file_exists(disk.filename)) - { - Debug_printf("drivewire_new_disk File exists: \"%s\"\n", disk.filename); - errorCode = 144; - return; - } - - disk.fileh = host.fnfile_open(disk.filename, disk.filename, sizeof(disk.filename), "w"); - if (disk.fileh == nullptr) + int result = 0; + int expectedResult = 1 + sizeof(newDisk); + + if (q->size() >= expectedResult) { - Debug_printf("drivewire_new_disk Couldn't open file for writing: \"%s\"\n", disk.filename); - return; + result = expectedResult; + Debug_println("Fuji cmd: NEW DISK"); + + std::vector buff(256); + std::copy(q->begin() + 1, q->begin() + 1 + sizeof(newDisk), buff.begin()); + memcpy((uint8_t *)&newDisk, buff.data(), sizeof(newDisk)); + + Debug_printf("numDisks: %u\n",newDisk.numDisks); + Debug_printf("hostSlot: %u\n",newDisk.hostSlot); + Debug_printf("deviceSl: %u\n",newDisk.deviceSlot); + Debug_printf("filename: %s\n",newDisk.filename); + + // A couple of reference variables to make things much easier to read... + fujiDisk &disk = _fnDisks[newDisk.deviceSlot]; + fujiHost &host = _fnHosts[newDisk.hostSlot]; + + disk.host_slot = newDisk.hostSlot; + disk.access_mode = DISK_ACCESS_MODE_WRITE; + strlcpy(disk.filename, newDisk.filename, sizeof(disk.filename)); + + if (host.file_exists(disk.filename)) + { + Debug_printf("drivewire_new_disk File exists: \"%s\"\n", disk.filename); + errorCode = 144; + return result; + } + + disk.fileh = host.fnfile_open(disk.filename, disk.filename, sizeof(disk.filename), "w"); + if (disk.fileh == nullptr) + { + Debug_printf("drivewire_new_disk Couldn't open file for writing: \"%s\"\n", disk.filename); + return result; + } + + bool ok = disk.disk_dev.write_blank(disk.fileh, newDisk.numDisks); + + errorCode = (ok == NETWORK_ERROR_SUCCESS); + + fnio::fclose(disk.fileh); + + resetState(); } - - bool ok = disk.disk_dev.write_blank(disk.fileh, newDisk.numDisks); - - errorCode = (ok == NETWORK_ERROR_SUCCESS); - - fnio::fclose(disk.fileh); + + return result; } // Unmount specified host -void drivewireFuji::unmount_host() +int drivewireFuji::unmount_host(std::vector *q) { - Debug_println("Fuji cmd: UNMOUNT HOST"); - - unsigned char hostSlot = fnDwCom.read(); - - // Unmount any disks associated with host slot - for (int i = 0; i < MAX_DISK_DEVICES; i++) + int result = 0; + int expectedResult = 2; + + if (q->size() >= expectedResult) { - if (_fnDisks[i].host_slot == hostSlot) - { - _fnDisks[i].disk_dev.unmount(); - _fnDisks[i].disk_dev.device_active = false; - _fnDisks[i].reset(); - } + result = expectedResult; + Debug_println("Fuji cmd: UNMOUNT HOST"); + + unsigned char hostSlot = q->at(1); + + // Unmount any disks associated with host slot + for (int i = 0; i < MAX_DISK_DEVICES; i++) + { + if (_fnDisks[i].host_slot == hostSlot) + { + _fnDisks[i].disk_dev.unmount(); + _fnDisks[i].disk_dev.device_active = false; + _fnDisks[i].reset(); + } + } + + // Unmount the host + _fnHosts[hostSlot].umount(); + + resetState(); } - - // Unmount the host - _fnHosts[hostSlot].umount(); + + return result; } // Send host slot data to computer -void drivewireFuji::read_host_slots() +int drivewireFuji::read_host_slots(std::vector *q) { + int result = 1; + Debug_println("Fuji cmd: READ HOST SLOTS"); char hostSlots[MAX_HOSTS][MAX_HOSTNAME_LEN]; @@ -1121,26 +1372,46 @@ void drivewireFuji::read_host_slots() response = std::string((const char *)hostSlots,256); errorCode = 1; + + resetState(); + + return result; } // Read and save host slot data from computer -void drivewireFuji::write_host_slots() +int drivewireFuji::write_host_slots(std::vector *q) { - Debug_println("Fuji cmd: WRITE HOST SLOTS"); - char hostSlots[MAX_HOSTS][MAX_HOSTNAME_LEN]; - fnDwCom.readBytes((uint8_t *)&hostSlots, sizeof(hostSlots)); - for (int i = 0; i < MAX_HOSTS; i++) - _fnHosts[i].set_hostname(hostSlots[i]); - - _populate_config_from_slots(); - Config.save(); + int result = 0; + int expectedResult = 1 + sizeof(hostSlots); + + if (q->size() >= expectedResult) + { + result = expectedResult; + Debug_println("Fuji cmd: WRITE HOST SLOTS"); + + std::vector buff(256); + std::copy(q->begin() + 1, q->begin() + 1 + sizeof(hostSlots), buff.begin()); + memcpy((uint8_t *)&hostSlots, buff.data(), sizeof(hostSlots)); + + for (int i = 0; i < MAX_HOSTS; i++) + _fnHosts[i].set_hostname(hostSlots[i]); + + _populate_config_from_slots(); + Config.save(); + + resetState(); + } + + return result; } // Send device slot data to computer -void drivewireFuji::read_device_slots() +int drivewireFuji::read_device_slots(std::vector *q) { + int result = 1; + Debug_println("Fuji cmd: READ DEVICE SLOTS"); struct disk_slot @@ -1186,13 +1457,15 @@ void drivewireFuji::read_device_slots() errorCode = 1; response = std::string((const char *)&diskSlots, returnsize); + + resetState(); + + return result; } // Read and save disk slot data from computer -void drivewireFuji::write_device_slots() +int drivewireFuji::write_device_slots(std::vector *q) { - Debug_println("Fuji cmd: WRITE DEVICE SLOTS"); - struct { uint8_t hostSlot; @@ -1200,15 +1473,30 @@ void drivewireFuji::write_device_slots() char filename[MAX_DISPLAY_FILENAME_LEN]; } diskSlots[MAX_DISK_DEVICES]; - fnDwCom.readBytes((uint8_t *)&diskSlots, sizeof(diskSlots)); - - // Load the data into our current device array - for (int i = 0; i < MAX_DISK_DEVICES; i++) - _fnDisks[i].reset(diskSlots[i].filename, diskSlots[i].hostSlot, diskSlots[i].mode); - - // Save the data to disk - _populate_config_from_slots(); - Config.save(); + int result = 0; + int expectedResult = 1 + sizeof(diskSlots); + + if (q->size() >= expectedResult) + { + result = expectedResult; + Debug_println("Fuji cmd: WRITE DEVICE SLOTS"); + + std::vector buff(256); + std::copy(q->begin() + 1, q->begin() + 1 + sizeof(diskSlots), buff.begin()); + memcpy((uint8_t *)&diskSlots, buff.data(), sizeof(diskSlots)); + + // Load the data into our current device array + for (int i = 0; i < MAX_DISK_DEVICES; i++) + _fnDisks[i].reset(diskSlots[i].filename, diskSlots[i].hostSlot, diskSlots[i].mode); + + // Save the data to disk + _populate_config_from_slots(); + Config.save(); + + resetState(); + } + + return result; } // Temporary(?) function while we move from old config storage to new @@ -1272,57 +1560,86 @@ void drivewireFuji::_populate_config_from_slots() } // Write a 256 byte filename to the device slot -void drivewireFuji::set_device_filename() +int drivewireFuji::set_device_filename(std::vector *q) { - char tmp[MAX_FILENAME_LEN]; - - // AUX1 is the desired device slot - uint8_t slot = fnDwCom.read(); - // AUX2 contains the host slot and the mount mode (READ/WRITE) - uint8_t host = fnDwCom.read(); - uint8_t mode = fnDwCom.read(); - - fnDwCom.readBytes((uint8_t *)tmp, MAX_FILENAME_LEN); - - Debug_printf("Fuji cmd: SET DEVICE SLOT 0x%02X/%02X/%02X FILENAME: %s\n", slot, host, mode, tmp); - - // Handle DISK slots - if (slot < MAX_DISK_DEVICES) + int result = 0; + int expectedResult = 4 + MAX_FILENAME_LEN; + + if (q->size() >= expectedResult) { - memcpy(_fnDisks[slot].filename, tmp, MAX_FILENAME_LEN); - // If the filename is empty, mark this as an invalid host, so that mounting will ignore it too - if (strlen(_fnDisks[slot].filename) == 0) { - _fnDisks[slot].host_slot = INVALID_HOST_SLOT; - } else { - _fnDisks[slot].host_slot = host; - } - _fnDisks[slot].access_mode = mode; - _populate_config_from_slots(); + result = expectedResult; + + char tmp[MAX_FILENAME_LEN]; + + // AUX1 is the desired device slot + uint8_t slot = q->at(1); + // AUX2 contains the host slot and the mount mode (READ/WRITE) + uint8_t host = q->at(2); + uint8_t mode = q->at(3); + + std::vector buff(256); + std::copy(q->begin() + 4, q->begin() + 4 + MAX_FILENAME_LEN, buff.begin()); + memcpy((uint8_t *)&tmp, buff.data(), MAX_FILENAME_LEN); + + Debug_printf("Fuji cmd: SET DEVICE SLOT 0x%02X/%02X/%02X FILENAME: %s\n", slot, host, mode, tmp); + + // Handle DISK slots + if (slot < MAX_DISK_DEVICES) + { + memcpy(_fnDisks[slot].filename, tmp, MAX_FILENAME_LEN); + // If the filename is empty, mark this as an invalid host, so that mounting will ignore it too + if (strlen(_fnDisks[slot].filename) == 0) { + _fnDisks[slot].host_slot = INVALID_HOST_SLOT; + } else { + _fnDisks[slot].host_slot = host; + } + _fnDisks[slot].access_mode = mode; + _populate_config_from_slots(); + } + + Config.save(); + + resetState(); } - - Config.save(); + + return result; } // Get a 256 byte filename from device slot -void drivewireFuji::get_device_filename() +int drivewireFuji::get_device_filename(std::vector *q) { - char tmp[MAX_FILENAME_LEN]; - - // AUX1 is the desired device slot - uint8_t slot = fnDwCom.read(); - - if (slot > 7) + int result = 0; + int expectedResult = 2; + + if (q->size() >= expectedResult) { - errorCode = 144; - } - - memcpy(tmp, _fnDisks[slot].filename, MAX_FILENAME_LEN); - response.clear(); - response.shrink_to_fit(); - - errorCode = 1; - - response = std::string(tmp, MAX_FILENAME_LEN); + result = expectedResult; + char tmp[MAX_FILENAME_LEN] = {0}; + + // AUX1 is the desired device slot + uint8_t slot = q->at(1); + + if (slot > 7) + { + errorCode = 144; + } + else + { + memcpy(tmp, _fnDisks[slot].filename, MAX_FILENAME_LEN); + } + response.clear(); + response.shrink_to_fit(); + + Debug_printf("Fuji cmd: GET DEVICE SLOT 0x%02X FILENAME: %s\n", slot, tmp); + + errorCode = 1; + + response = std::string(tmp, MAX_FILENAME_LEN); + + resetState(); + } + + return result; } // Mounts the desired boot disk number @@ -1360,27 +1677,56 @@ void drivewireFuji::insert_boot_device(uint8_t d) } } -void drivewireFuji::base64_encode_input() +int drivewireFuji::base64_encode_input(std::vector *q) { - uint8_t lenh = fnDwCom.read(); - uint8_t lenl = fnDwCom.read(); - uint16_t len = lenh << 8 | lenl; - - if (!len) + int result = 0; + int expectedResult = 3; + + if (q->size() >= expectedResult) { - Debug_printf("Zero length. Aborting.\n"); - errorCode = 144; - return; + result = expectedResult; + uint8_t lenh = q->at(1); + uint8_t lenl = q->at(2); + base64_encode_length_var = lenh << 8 | lenl; + + if (!base64_encode_length_var) + { + Debug_printf("Zero length. Aborting.\n"); + errorCode = 144; + resetState(); + return result; + } + + _drivewire_bus->fnStateMethod = &drivewireFuji::base64_encode_input_p2; } + + return result; +} - std::vector p(len); - fnDwCom.readBytes(p.data(), len); - base64.base64_buffer += std::string((const char *)p.data(), len); - errorCode = 1; +int drivewireFuji::base64_encode_input_p2(std::vector *q) +{ + int result = 0; + int expectedResult = base64_encode_length_var; + + if (q->size() >= expectedResult) + { + result = expectedResult; + + std::vector p(base64_encode_length_var); + std::copy(q->begin(), q->begin() + base64_encode_length_var - 1, p.begin()); + base64.base64_buffer += std::string((const char *)p.data(), base64_encode_length_var); + errorCode = 1; + + resetState(); + } + + return result; } -void drivewireFuji::base64_encode_compute() +int drivewireFuji::base64_encode_compute(std::vector *q) { + int result = 1; + size_t out_len; std::unique_ptr p = Base64::encode(base64.base64_buffer.c_str(), base64.base64_buffer.size(), &out_len); @@ -1389,17 +1735,23 @@ void drivewireFuji::base64_encode_compute() { Debug_printf("base64_encode_compute() failed.\n"); errorCode = 144; - return; + return result; } base64.base64_buffer.clear(); base64.base64_buffer = std::string(p.get(), out_len); errorCode = 1; + + resetState(); + + return result; } -void drivewireFuji::base64_encode_length() +int drivewireFuji::base64_encode_length(std::vector *q) { + int result = 1; + size_t l = base64.base64_buffer.length(); uint8_t o[4] = { @@ -1415,52 +1767,95 @@ void drivewireFuji::base64_encode_length() response = std::string((const char *)&o, 4); errorCode = 1; + + resetState(); + + return result; } -void drivewireFuji::base64_encode_output() +int drivewireFuji::base64_encode_output(std::vector *q) { - uint8_t lenl = fnDwCom.read(); - uint8_t lenh = fnDwCom.read(); - uint16_t len = lenh << 8 | lenl; - - if (!len) + int result = 0; + int expectedResult = 3; + + if (q->size() >= expectedResult) { - Debug_printf("Refusing to send zero byte buffer. Exiting."); - errorCode = 144; - return; + result = expectedResult; + uint8_t lenl = q->at(1); + uint8_t lenh = q->at(2); + uint16_t len = lenh << 8 | lenl; + + if (!len) + { + Debug_printf("Refusing to send zero byte buffer. Exiting."); + errorCode = 144; + return result; + } + + std::vector p(len); + std::memcpy(p.data(), base64.base64_buffer.data(), len); + base64.base64_buffer.erase(0, len); + base64.base64_buffer.shrink_to_fit(); + + response = std::string((const char *)p.data(), len); + errorCode = 1; + + resetState(); } - - std::vector p(len); - std::memcpy(p.data(), base64.base64_buffer.data(), len); - base64.base64_buffer.erase(0, len); - base64.base64_buffer.shrink_to_fit(); - - response = std::string((const char *)p.data(), len); - errorCode = 1; + + return result; } -void drivewireFuji::base64_decode_input() +int drivewireFuji::base64_decode_input(std::vector *q) { - uint8_t lenl = fnDwCom.read(); - uint8_t lenh = fnDwCom.read(); - uint16_t len = lenh << 8 | lenl; - - if (!len) + int result = 0; + int expectedResult = 3; + + if (q->size() >= expectedResult) { - Debug_printf("Refusing to input zero length. Exiting.\n"); - errorCode = 144; - return; + result = expectedResult; + uint8_t lenh = q->at(1); + uint8_t lenl = q->at(2); + base64_decode_length_var = lenh << 8 | lenl; + + if (!base64_decode_length_var) + { + Debug_printf("Refusing to input zero length. Exiting.\n"); + errorCode = 144; + resetState(); + return result; + } + + _drivewire_bus->fnStateMethod = &drivewireFuji::base64_decode_input_p2; } + + return result; +} - std::vector p(len); - fnDwCom.readBytes(p.data(), len); - base64.base64_buffer += std::string((const char *)p.data(), len); - - errorCode = 1; +int drivewireFuji::base64_decode_input_p2(std::vector *q) +{ + int result = 0; + int expectedResult = base64_decode_length_var; + + if (q->size() >= expectedResult) + { + result = expectedResult; + + std::vector p(base64_decode_length_var); + std::copy(q->begin(), q->begin() + base64_decode_length_var - 1, p.begin()); + base64.base64_buffer += std::string((const char *)p.data(), base64_decode_length_var); + errorCode = 1; + + resetState(); + } + + return result; } -void drivewireFuji::base64_decode_compute() +int drivewireFuji::base64_decode_compute(std::vector *q) { + int result = 1; + size_t out_len; Debug_printf("FUJI: BASE64 DECODE COMPUTE\n"); @@ -1470,7 +1865,7 @@ void drivewireFuji::base64_decode_compute() { Debug_printf("base64_encode compute failed\n"); errorCode = 144; - return; + return result; } base64.base64_buffer.clear(); @@ -1478,10 +1873,16 @@ void drivewireFuji::base64_decode_compute() Debug_printf("Resulting BASE64 encoded data is: %u bytes\n", out_len); errorCode = 1; + + resetState(); + + return result; } -void drivewireFuji::base64_decode_length() +int drivewireFuji::base64_decode_length(std::vector *q) { + int result = 1; + Debug_printf("FUJI: BASE64 DECODE LENGTH\n"); size_t len = base64.base64_buffer.length(); @@ -1496,7 +1897,7 @@ void drivewireFuji::base64_decode_length() { Debug_printf("BASE64 buffer is 0 bytes, sending error.\n"); errorCode = 144; - return; + return result; } Debug_printf("base64 buffer length: %u bytes\n", len); @@ -1506,101 +1907,202 @@ void drivewireFuji::base64_decode_length() response = std::string((const char *)_response, 4); errorCode = 1; + + resetState(); + + return result; } -void drivewireFuji::base64_decode_output() +int drivewireFuji::base64_decode_output(std::vector *q) { - Debug_printf("FUJI: BASE64 DECODE OUTPUT\n"); - - uint8_t lenl = fnDwCom.read(); - uint8_t lenh = fnDwCom.read(); - uint16_t len = lenh << 8 | lenl; - - if (!len) + int result = 0; + int expectedResult = 3; + + if (q->size() >= expectedResult) { - Debug_printf("Refusing to send a zero byte buffer. Aborting\n"); - errorCode = 144; - return; + result = expectedResult; + Debug_printf("FUJI: BASE64 DECODE OUTPUT\n"); + + uint8_t lenl = q->at(1); + uint8_t lenh = q->at(2); + uint16_t len = lenh << 8 | lenl; + + if (!len) + { + Debug_printf("Refusing to send a zero byte buffer. Aborting\n"); + errorCode = 144; + return result; + } + else if (len > base64.base64_buffer.length()) + { + Debug_printf("Requested %u bytes, but buffer is only %u bytes, aborting.\n", len, base64.base64_buffer.length()); + errorCode = 144; + return result; + } + else + { + Debug_printf("Requested %u bytes\n", len); + } + + std::vector p(len); + memcpy(p.data(), base64.base64_buffer.data(), len); + base64.base64_buffer.erase(0, len); + base64.base64_buffer.shrink_to_fit(); + response.clear(); + response.shrink_to_fit(); + response = std::string((const char *)p.data(), len); + + errorCode = 1; + + resetState(); } - else if (len > base64.base64_buffer.length()) + + return result; +} + +int drivewireFuji::hash_input(std::vector *q) +{ + int result = 0; + int expectedResult = 3; + + if (q->size() >= expectedResult) { - Debug_printf("Requested %u bytes, but buffer is only %u bytes, aborting.\n", len, base64.base64_buffer.length()); - errorCode = 144; - return; + Debug_printf("FUJI: HASH INPUT\n"); + result = expectedResult; + uint8_t lenh = q->at(1); + uint8_t lenl = q->at(2); + hash_length_var = lenh << 8 | lenl; + + if (!hash_length_var) + { + Debug_printf("Invalid length. Aborting"); + errorCode = 144; + resetState(); + return result; + } + + _drivewire_bus->fnStateMethod = &drivewireFuji::hash_input_p2; } - else + + return result; +} + +int drivewireFuji::hash_input_p2(std::vector *q) +{ + int result = 0; + int expectedResult = hash_length_var; + + if (q->size() >= expectedResult) { - Debug_printf("Requested %u bytes\n", len); + result = expectedResult; + + std::vector p(hash_length_var); + std::copy(q->begin(), q->begin() + hash_length_var - 1, p.begin()); + hasher.add_data(p); + errorCode = 1; + + resetState(); } - - std::vector p(len); - memcpy(p.data(), base64.base64_buffer.data(), len); - base64.base64_buffer.erase(0, len); - base64.base64_buffer.shrink_to_fit(); - response.clear(); - response.shrink_to_fit(); - response = std::string((const char *)p.data(), len); - - errorCode = 1; + + return result; } -void drivewireFuji::hash_input() +int drivewireFuji::state_hash_compute_true(std::vector *q) { - Debug_printf("FUJI: HASH INPUT\n"); - uint8_t lenl = fnDwCom.read(); - uint8_t lenh = fnDwCom.read(); - uint16_t len = lenh << 8 | lenl; + int result = 0; + int expectedResult = 2; + + if (q->size() >= expectedResult) + { + result = expectedResult; + hash_compute(q->at(1), true); + resetState(); + } + + return result; +} - if (!len) +int drivewireFuji::state_hash_compute_false(std::vector *q) +{ + int result = 0; + int expectedResult = 2; + + if (q->size() >= expectedResult) { - Debug_printf("Invalid length. Aborting"); - errorCode = 144; - return; - } + result = expectedResult; + hash_compute(q->at(1), false); - std::vector p(len); - fnDwCom.readBytes(p.data(), len); - hasher.add_data(p); - errorCode = 1; + resetState(); + } + + return result; } -void drivewireFuji::hash_compute(bool clear_data) +void drivewireFuji::hash_compute(uint8_t value, bool clear_data) { Debug_printf("FUJI: HASH COMPUTE\n"); - algorithm = Hash::to_algorithm(fnDwCom.read()); + algorithm = Hash::to_algorithm(value); hasher.compute(algorithm, clear_data); errorCode = 1; } -void drivewireFuji::hash_length() +int drivewireFuji::hash_length(std::vector *q) { - Debug_printf("FUJI: HASH LENGTH\n"); - uint8_t is_hex = fnDwCom.read() == 1; - uint8_t r = hasher.hash_length(algorithm, is_hex); - response = std::string((const char *)&r, 1); - errorCode = 1; + int result = 0; + int expectedResult = 2; + + if (q->size() >= expectedResult) + { + result = expectedResult; + Debug_printf("FUJI: HASH LENGTH\n"); + uint8_t is_hex = q->at(1) == 1; + uint8_t r = hasher.hash_length(algorithm, is_hex); + response = std::string((const char *)&r, 1); + errorCode = 1; + + resetState(); + } + + return result; } -void drivewireFuji::hash_output() +int drivewireFuji::hash_output(std::vector *q) { - Debug_printf("FUJI: HASH OUTPUT\n"); - - uint8_t is_hex = fnDwCom.read() == 1; - if (is_hex) { - response = hasher.output_hex(); - } else { - std::vector hashed_data = hasher.output_binary(); - response = std::string(hashed_data.begin(), hashed_data.end()); - } - errorCode = 1; + int result = 0; + int expectedResult = 2; + + if (q->size() >= expectedResult) + { + result = expectedResult; + Debug_printf("FUJI: HASH OUTPUT\n"); + + uint8_t is_hex = q->at(1) == 1; + if (is_hex) { + response = hasher.output_hex(); + } else { + std::vector hashed_data = hasher.output_binary(); + response = std::string(hashed_data.begin(), hashed_data.end()); + } + errorCode = 1; + + resetState(); + } + + return result; } -void drivewireFuji::hash_clear() +int drivewireFuji::hash_clear(std::vector *q) { + int result = 1; + Debug_printf("FUJI: HASH INIT\n"); hasher.clear(); errorCode = 1; + + resetState(); + + return result; } // Initializes base settings and adds our devices to the DRIVEWIRE bus @@ -1637,14 +2139,22 @@ std::string drivewireFuji::get_host_prefix(int host_slot) return _fnHosts[host_slot].get_prefix(); } -void drivewireFuji::send_error() +int drivewireFuji::send_error(std::vector *q) { + int result = 1; + Debug_printf("drivewireFuji::send_error(%u)\n",errorCode); - fnDwCom.write(errorCode); + fnDwCom.writeToFNChannel(0, errorCode); + + resetState(); + + return result; } -void drivewireFuji::random() +int drivewireFuji::random(std::vector *q) { + int result = 1; + int r = rand(); Debug_printf("drivewireFuji::random(%u)\n",r); @@ -1653,173 +2163,210 @@ void drivewireFuji::random() // Endianness does not matter, so long as it is random. response = std::string((const char *)&r,sizeof(r)); + + resetState(); + + return result; } -void drivewireFuji::send_response() +int drivewireFuji::send_response(std::vector *q) { + int result = 1; + // Send body - fnDwCom.write((uint8_t *)response.c_str(),response.length()); + fnDwCom.writeToFNChannel(0, (uint8_t *)response.c_str(),response.length()); // Clear the response response.clear(); - response.shrink_to_fit(); + response.shrink_to_fit(); + + Debug_println("Fuji cmd: SEND_RESPONSE"); + + resetState(); + + return result; } -void drivewireFuji::ready() +int drivewireFuji::ready(std::vector *q) { - fnDwCom.write(0x01); // Yes, ready. + int result = 1; + + fnDwCom.writeToFNChannel(0, 0x01); // Yes, ready. + + resetState(); + + return result; } -void drivewireFuji::process() +int drivewireFuji::process(std::vector *q) { - uint8_t c = fnDwCom.read(); + int result = 0; + + uint8_t c = q->at(0); switch (c) { case FUJICMD_SEND_ERROR: - send_error(); + _drivewire_bus->fnStateMethod = &drivewireFuji::send_error; break; case FUJICMD_GET_ADAPTERCONFIG: - get_adapter_config(); + _drivewire_bus->fnStateMethod = &drivewireFuji::get_adapter_config; break; case FUJICMD_GET_ADAPTERCONFIG_EXTENDED: - get_adapter_config_extended(); + _drivewire_bus->fnStateMethod = &drivewireFuji::get_adapter_config_extended; break; case FUJICMD_GET_SCAN_RESULT: - net_scan_result(); + _drivewire_bus->fnStateMethod = &drivewireFuji::net_scan_result; break; case FUJICMD_SCAN_NETWORKS: - net_scan_networks(); + _drivewire_bus->fnStateMethod = &drivewireFuji::net_scan_networks; break; case FUJICMD_SET_SSID: - net_set_ssid(); + _drivewire_bus->fnStateMethod = &drivewireFuji::net_set_ssid; break; case FUJICMD_GET_SSID: - net_get_ssid(); + _drivewire_bus->fnStateMethod = &drivewireFuji::net_get_ssid; break; case FUJICMD_READ_HOST_SLOTS: - read_host_slots(); + _drivewire_bus->fnStateMethod = &drivewireFuji::read_host_slots; break; case FUJICMD_READ_DEVICE_SLOTS: - read_device_slots(); + _drivewire_bus->fnStateMethod = &drivewireFuji::read_device_slots; break; case FUJICMD_WRITE_DEVICE_SLOTS: - write_device_slots(); + _drivewire_bus->fnStateMethod = &drivewireFuji::write_device_slots; break; case FUJICMD_WRITE_HOST_SLOTS: - write_host_slots(); + _drivewire_bus->fnStateMethod = &drivewireFuji::write_host_slots; break; case FUJICMD_GET_WIFI_ENABLED: - net_get_wifi_enabled(); + _drivewire_bus->fnStateMethod = &drivewireFuji::net_get_wifi_enabled; break; case FUJICMD_GET_WIFISTATUS: - net_get_wifi_status(); + _drivewire_bus->fnStateMethod = &drivewireFuji::net_get_wifi_status; break; case FUJICMD_MOUNT_HOST: - mount_host(); + _drivewire_bus->fnStateMethod = &drivewireFuji::mount_host; break; case FUJICMD_OPEN_DIRECTORY: - open_directory(); + _drivewire_bus->fnStateMethod = &drivewireFuji::open_directory; break; case FUJICMD_CLOSE_DIRECTORY: - close_directory(); + _drivewire_bus->fnStateMethod = &drivewireFuji::close_directory; break; case FUJICMD_READ_DIR_ENTRY: - read_directory_entry(); + _drivewire_bus->fnStateMethod = &drivewireFuji::read_directory_entry; break; case FUJICMD_SET_DIRECTORY_POSITION: - set_directory_position(); + _drivewire_bus->fnStateMethod = &drivewireFuji::set_directory_position; break; case FUJICMD_SET_DEVICE_FULLPATH: - set_device_filename(); + _drivewire_bus->fnStateMethod = &drivewireFuji::set_device_filename; break; case FUJICMD_GET_DEVICE_FULLPATH: - get_device_filename(); + _drivewire_bus->fnStateMethod = &drivewireFuji::get_device_filename; break; case FUJICMD_MOUNT_IMAGE: - disk_image_mount(); + _drivewire_bus->fnStateMethod = &drivewireFuji::disk_image_mount; break; case FUJICMD_UNMOUNT_HOST: - unmount_host(); + _drivewire_bus->fnStateMethod = &drivewireFuji::unmount_host; break; case FUJICMD_UNMOUNT_IMAGE: - disk_image_umount(); + _drivewire_bus->fnStateMethod = &drivewireFuji::disk_image_umount; break; case FUJICMD_NEW_DISK: - new_disk(); + _drivewire_bus->fnStateMethod = &drivewireFuji::new_disk; break; case FUJICMD_SEND_RESPONSE: - send_response(); + _drivewire_bus->fnStateMethod = &drivewireFuji::send_response; break; case FUJICMD_DEVICE_READY: - ready(); + _drivewire_bus->fnStateMethod = &drivewireFuji::ready; break; case FUJICMD_OPEN_APPKEY: - open_app_key(); + _drivewire_bus->fnStateMethod = &drivewireFuji::open_app_key; break; case FUJICMD_CLOSE_APPKEY: - close_app_key(); + _drivewire_bus->fnStateMethod = &drivewireFuji::close_app_key; break; case FUJICMD_READ_APPKEY: - read_app_key(); + _drivewire_bus->fnStateMethod = &drivewireFuji::read_app_key; break; case FUJICMD_WRITE_APPKEY: - write_app_key(); + _drivewire_bus->fnStateMethod = &drivewireFuji::write_app_key; break; case FUJICMD_RANDOM_NUMBER: - random(); + _drivewire_bus->fnStateMethod = &drivewireFuji::random; break; case FUJICMD_BASE64_ENCODE_INPUT: - base64_encode_input(); + _drivewire_bus->fnStateMethod = &drivewireFuji::base64_encode_input; break; case FUJICMD_BASE64_ENCODE_COMPUTE: - base64_encode_compute(); + _drivewire_bus->fnStateMethod = &drivewireFuji::base64_encode_compute; break; case FUJICMD_BASE64_ENCODE_LENGTH: - base64_encode_length(); + _drivewire_bus->fnStateMethod = &drivewireFuji::base64_encode_length; break; case FUJICMD_BASE64_ENCODE_OUTPUT: - base64_encode_output(); + _drivewire_bus->fnStateMethod = &drivewireFuji::base64_encode_output; break; case FUJICMD_BASE64_DECODE_INPUT: - base64_decode_input(); + _drivewire_bus->fnStateMethod = &drivewireFuji::base64_decode_input; break; case FUJICMD_BASE64_DECODE_COMPUTE: - base64_decode_compute(); + _drivewire_bus->fnStateMethod = &drivewireFuji::base64_decode_compute; break; case FUJICMD_BASE64_DECODE_LENGTH: - base64_decode_length(); + _drivewire_bus->fnStateMethod = &drivewireFuji::base64_decode_length; break; case FUJICMD_BASE64_DECODE_OUTPUT: - base64_decode_output(); + _drivewire_bus->fnStateMethod = &drivewireFuji::base64_decode_output; break; case FUJICMD_HASH_INPUT: - hash_input(); + _drivewire_bus->fnStateMethod = &drivewireFuji::hash_input; break; case FUJICMD_HASH_COMPUTE: - hash_compute(true); + _drivewire_bus->fnStateMethod = &drivewireFuji::state_hash_compute_true; break; case FUJICMD_HASH_COMPUTE_NO_CLEAR: - hash_compute(false); + _drivewire_bus->fnStateMethod = &drivewireFuji::state_hash_compute_false; break; case FUJICMD_HASH_LENGTH: - hash_length(); + _drivewire_bus->fnStateMethod = &drivewireFuji::hash_length; break; case FUJICMD_HASH_OUTPUT: - hash_output(); + _drivewire_bus->fnStateMethod = &drivewireFuji::hash_output; break; case FUJICMD_HASH_CLEAR: - hash_clear(); + _drivewire_bus->fnStateMethod = &drivewireFuji::hash_clear; break; case FUJICMD_SET_BOOT_MODE: - set_boot_mode(); + _drivewire_bus->fnStateMethod = &drivewireFuji::set_boot_mode; break; case FUJICMD_MOUNT_ALL: - mount_all(); + _drivewire_bus->fnStateMethod = &drivewireFuji::local_mount_all; break; default: + _drivewire_bus->fnStateMethod = &drivewireFuji::op_unhandled; + _drivewire_bus->resetState(); break; } + + result = (this->*_drivewire_bus->fnStateMethod)(q); + + return result; } +int drivewireFuji::op_unhandled(std::vector *q) +{ + int result = 1; + + resetState(); + Debug_printv("Unhandled opcode: %02x", q->at(0)); + + return result; +} + + #endif /* BUILD_COCO */ \ No newline at end of file diff --git a/lib/device/drivewire/fuji.h b/lib/device/drivewire/fuji.h index 12345cfec..7f21b79c3 100755 --- a/lib/device/drivewire/fuji.h +++ b/lib/device/drivewire/fuji.h @@ -114,63 +114,76 @@ class drivewireFuji : public virtualDevice appkey _current_appkey; + void resetState(); + uint16_t base64_encode_length_var; + uint16_t base64_decode_length_var; + uint16_t hash_length_var; + + protected: - void reset_fujinet(); // 0xFF - void net_get_ssid(); // 0xFE - void net_scan_networks(); // 0xFD - void net_scan_result(); // 0xFC - void net_set_ssid(); // 0xFB - void net_get_wifi_status(); // 0xFA - void mount_host(); // 0xF9 - void disk_image_mount(); // 0xF8 - void open_directory(); // 0xF7 - void read_directory_entry(); // 0xF6 - void close_directory(); // 0xF5 - void read_host_slots(); // 0xF4 - void write_host_slots(); // 0xF3 - void read_device_slots(); // 0xF2 - void write_device_slots(); // 0xF1 - void enable_udpstream(); // 0xF0 - void net_get_wifi_enabled(); // 0xEA - void disk_image_umount(); // 0xE9 - void get_adapter_config(); // 0xE8 - void new_disk(); // 0xE7 - void unmount_host(); // 0xE6 - void get_directory_position(); // 0xE5 - void set_directory_position(); // 0xE4 - void set_hdrivewire_index(); // 0xE3 - void set_device_filename(); // 0xE2 - void set_host_prefix(); // 0xE1 - void get_host_prefix(); // 0xE0 - void set_drivewire_external_clock(); // 0xDF - void write_app_key(); // 0xDE - void read_app_key(); // 0xDD - void open_app_key(); // 0xDC - void close_app_key(); // 0xDB - void get_device_filename(); // 0xDA - void set_boot_config(); // 0xD9 - void copy_file(); // 0xD8 - void set_boot_mode(); // 0xD6 - void random(); // 0xD3 - void base64_encode_input(); // 0xD0 - void base64_encode_compute(); // 0xCF - void base64_encode_length(); // 0xCE - void base64_encode_output(); // 0xCD - void base64_decode_input(); // 0xCC - void base64_decode_compute(); // 0xCB - void base64_decode_length(); // 0xCA - void base64_decode_output(); // 0xC9 - void hash_input(); // 0xC8 - void hash_compute(bool clear_data); // 0xC7, 0xC3 - void hash_length(); // 0xC6 - void hash_output(); // 0xC5 - void get_adapter_config_extended(); // 0xC4 - void hash_clear(); // 0xC2 - - void send_error(); // 0x02 - void send_response(); // 0x01 - void ready(); // 0x00 - void shutdown() override; + int reset_fujinet(std::vector *); // 0xFF + int net_get_ssid(std::vector *); // 0xFE + int net_scan_networks(std::vector *); // 0xFD + int net_scan_result(std::vector *); // 0xFC + int net_set_ssid(std::vector *); // 0xFB + int net_get_wifi_status(std::vector *); // 0xFA + int mount_host(std::vector *); // 0xF9 + int disk_image_mount(std::vector *); // 0xF8 + int open_directory(std::vector *); // 0xF7 + int read_directory_entry(std::vector *); // 0xF6 + int close_directory(std::vector *); // 0xF5 + int read_host_slots(std::vector *); // 0xF4 + int write_host_slots(std::vector *); // 0xF3 + int read_device_slots(std::vector *); // 0xF2 + int write_device_slots(std::vector *); // 0xF1 + int enable_udpstream(std::vector *); // 0xF0 + int net_get_wifi_enabled(std::vector *); // 0xEA + int disk_image_umount(std::vector *); // 0xE9 + int get_adapter_config(std::vector *); // 0xE8 + int new_disk(std::vector *); // 0xE7 + int unmount_host(std::vector *); // 0xE6 + int get_directory_position(std::vector *); // 0xE5 + int set_directory_position(std::vector *); // 0xE4 + int set_hdrivewire_index(std::vector *); // 0xE3 + int set_device_filename(std::vector *); // 0xE2 + int set_host_prefix(std::vector *); // 0xE1 + int get_host_prefix(std::vector *); // 0xE0 + int set_drivewire_external_clock(std::vector *); // 0xDF + int write_app_key(std::vector *); // 0xDE + int read_app_key(std::vector *); // 0xDD + int open_app_key(std::vector *); // 0xDC + int close_app_key(std::vector *); // 0xDB + int get_device_filename(std::vector *); // 0xDA + int set_boot_config(std::vector *); // 0xD9 + int copy_file(std::vector *); // 0xD8 + int set_boot_mode(std::vector *); // 0xD6 + int random(std::vector *); // 0xD3 + int base64_encode_input(std::vector *); // 0xD0 + int base64_encode_input_p2(std::vector *q); + int base64_encode_compute(std::vector *); // 0xCF + int base64_encode_length(std::vector *); // 0xCE + int base64_encode_output(std::vector *); // 0xCD + int base64_decode_input(std::vector *); // 0xCC + int base64_decode_input_p2(std::vector *); // 0xCC + int base64_decode_compute(std::vector *); // 0xCB + int base64_decode_length(std::vector *); // 0xCA + int base64_decode_output(std::vector *); // 0xC9 + int hash_input(std::vector *); // 0xC8 + int hash_input_p2(std::vector *); // 0xC8 + int state_hash_compute_true(std::vector *); // 0xC7, 0xC3 + int state_hash_compute_false(std::vector *); // 0xC7, 0xC3 + int hash_length(std::vector *); // 0xC6 + int hash_output(std::vector *); // 0xC5 + int get_adapter_config_extended(std::vector *); // 0xC4 + int hash_clear(std::vector *); // 0xC2 + int op_unhandled(std::vector *q); + + int send_error(std::vector *q); // 0x02 + int send_response(std::vector *); // 0x01 + int ready(std::vector *); // 0x00 + void shutdown(void) override; + + void hash_compute(uint8_t value, bool clear_data); // 0xC7, 0xC3 public: bool boot_config = true; @@ -200,7 +213,9 @@ class drivewireFuji : public virtualDevice void _populate_slots_from_config(); void _populate_config_from_slots(); - void process(); + int process(std::vector *q); + + int local_mount_all(std::vector *q); // 0xD7 void mount_all(); // 0xD7 From 4d4ce9f21ed9b717e7e89dcc00caf324ddacba9a Mon Sep 17 00:00:00 2001 From: Boisy Pitre Date: Sun, 15 Sep 2024 10:40:24 -0500 Subject: [PATCH 2/2] Renamed onTimer because it's a global and conflicts. --- lib/bus/drivewire/drivewire.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/bus/drivewire/drivewire.cpp b/lib/bus/drivewire/drivewire.cpp index ec97ec324..46a5806b7 100755 --- a/lib/bus/drivewire/drivewire.cpp +++ b/lib/bus/drivewire/drivewire.cpp @@ -47,7 +47,7 @@ static void IRAM_ATTR drivewire_isr_handler(void *arg) * Static callback function for the DriveWire state machine. */ #ifdef ESP_PLATFORM -void onTimer(void *info) +void onDriveWireStateMachineTimer(void *info) { systemBus *parent = (systemBus *)info; parent->resetState(); @@ -62,7 +62,7 @@ void systemBus::timer_start() #ifdef ESP_PLATFORM esp_timer_create_args_t tcfg; tcfg.arg = this; - tcfg.callback = onTimer; + tcfg.callback = onDriveWireStateMachineTimer; tcfg.dispatch_method = esp_timer_dispatch_t::ESP_TIMER_TASK; tcfg.name = nullptr; esp_timer_create(&tcfg, &stateMachineRecoveryTimerHandle); @@ -942,7 +942,7 @@ void systemBus::service() #ifdef ESP_PLATFORM #else uint64_t ms = fnSystem.millis(); -#if 0 +#ifdef SUPER_DEBUGGING if (ms % 100 == 0) { Debug_printv("MS = %ld, lastInterruptMs = %ld, TIMER = %ld\n", ms, lastInterruptMs, (timerActive == true && ms - lastInterruptMs >= timerRate)); } @@ -954,6 +954,7 @@ void systemBus::service() } #endif +#ifdef SUPER_DEBUGING if (gotNewData == 1 && showDump == 1 && serialBuffer.size() > 0) { for (int i = 0; i < serialBuffer.size(); i++) @@ -963,7 +964,8 @@ void systemBus::service() Debug_printf("=====================================\n"); } - +#endif + if (gotNewData == 1) { int bytesConsumed = 0;