From 1ee08ef388621b88e92336f7c19a27fe378a813f Mon Sep 17 00:00:00 2001 From: Bobby Dilley Date: Sat, 27 Jun 2026 22:02:57 +0100 Subject: [PATCH 1/2] Add JVS passthrough rewrite for linux and windows --- src/loader/hardware/lindbergh/baseBoard.c | 56 ++- src/loader/hardware/lindbergh/passthrough.c | 479 ++++++++++++-------- src/loader/hardware/lindbergh/passthrough.h | 27 +- 3 files changed, 330 insertions(+), 232 deletions(-) diff --git a/src/loader/hardware/lindbergh/baseBoard.c b/src/loader/hardware/lindbergh/baseBoard.c index a379cbd..49447d9 100644 --- a/src/loader/hardware/lindbergh/baseBoard.c +++ b/src/loader/hardware/lindbergh/baseBoard.c @@ -57,11 +57,12 @@ unsigned int sharedMemoryIndex = 0; uint8_t sharedMemory[1024 * 32] = {0}; int selectReply = -1; -int jvsFileDescriptor = -1; int jvsPacketSize = -1; char serialString[1024] = {0}; +unsigned char passthroughOutputBuffer[JVS_MAX_PACKET_SIZE], passthroughInputBuffer[JVS_MAX_PACKET_SIZE]; + int initBaseboard() { char *sramPath = getConfig()->sramPath; @@ -81,15 +82,11 @@ int initBaseboard() #ifdef __linux__ if (getConfig()->emulateJVS == 0 && strcmp(getConfig()->jvsPath, "none") != 0) { - jvsFileDescriptor = openJVSSerial(getConfig()->jvsPath); - if (jvsFileDescriptor < 0) + JVSPassthroughStatus status = initJVSPassthrough(getConfig()->jvsPath); + if (status != JVS_PASSTHROUGH_STATUS_OK) { - printf("Error: Failed to open %s for JVS\n", getConfig()->jvsPath); - return -1; + printf("Warning: Failed to initialize JVS passthrough at %s\n", getConfig()->jvsPath); } - - initJVSSerial(jvsFileDescriptor); - startJVSFrameThread(&jvsFileDescriptor); } #endif @@ -221,11 +218,12 @@ int baseboardIoctl(int fd, unsigned long request, void *data) { processPacket(&jvsPacketSize); } - else if (jvsFileDescriptor >= 0) + else { + writeJVSFrame(inputBuffer, jvsCommand.srcSize); + for (uint32_t i = 0; i < jvsCommand.srcSize; i++) { - write(jvsFileDescriptor, &inputBuffer[i], 1); if (inputBuffer[i] == 0xF0) { setSenseLine(3); @@ -276,25 +274,43 @@ int baseboardIoctl(int fd, unsigned long request, void *data) case BASEBOARD_PROCESS_JVS: { -#ifdef __linux__ if (getConfig()->emulateJVS) { -#endif memcpy(&sharedMemory[jvsCommand.destAddress], outputBuffer, jvsPacketSize); _data[2] = jvsCommand.destAddress; _data[3] = jvsPacketSize; _data[1] = 1; // Set the status to success -#ifdef __linux__ } - else if (jvsFileDescriptor >= 0) + else { - JVSFrame frame = readJVSFrameFromThread(); - memcpy(&sharedMemory[jvsCommand.destAddress], frame.buffer, frame.size); - _data[2] = jvsCommand.destAddress; - _data[3] = frame.size; - _data[1] = frame.ready; + if (getSenseLine() == 3) + { + char errorMessage[5] = {0xE0, 0x00, 0x02, 0x01, 0x03}; + memcpy(&sharedMemory[jvsCommand.destAddress], errorMessage, 5); + _data[2] = jvsCommand.destAddress; + _data[3] = 5; + _data[1] = 1; + } + else + { + JVSPassthroughStatus status = readJVSFrame(passthroughInputBuffer, &jvsPacketSize); + if (status == JVS_PASSTHROUGH_STATUS_OK) + { + memcpy(&sharedMemory[jvsCommand.destAddress], passthroughInputBuffer, jvsPacketSize); + _data[2] = jvsCommand.destAddress; + _data[3] = jvsPacketSize; + _data[1] = 1; // Set the status to success + } + else + { + // If it times out then we can just set the system to error out + memcpy(&sharedMemory[jvsCommand.destAddress], "/x00", 1); + _data[2] = jvsCommand.destAddress; + _data[3] = 1; + _data[1] = 1; // Set the status to failure + } + } } -#endif } break; diff --git a/src/loader/hardware/lindbergh/passthrough.c b/src/loader/hardware/lindbergh/passthrough.c index f82f2fb..1b6ef33 100644 --- a/src/loader/hardware/lindbergh/passthrough.c +++ b/src/loader/hardware/lindbergh/passthrough.c @@ -1,83 +1,69 @@ -#ifdef __linux__ -#include /* Standard input/output definitions */ -#include /* String function definitions */ -#include /* UNIX standard function definitions */ -#include /* File control definitions */ -#include /* Error number definitions */ -#include /* POSIX terminal control definitions */ +#include +#include + +#if defined(__linux__) || defined(__APPLE__) +#include /* String function definitions */ +#include /* UNIX standard function definitions */ +#include /* File control definitions */ +#include /* Error number definitions */ +#include /* POSIX terminal control definitions */ #include /* Ioctl function to control device drivers in the kernel */ -#include /* POSIX threads API to create and manage threads in the program */ +#endif -#include "passthrough.h" +#ifdef _WIN32 +#include /* Windows API functions and types */ +#endif -#define TIMEOUT_SELECT 200 -#define CTS_ON_RETRY 20 +#include "passthrough.h" -// Used to read JVS frame in a non-blocking way -JVSFrame jvsFrameBuffer; -pthread_mutex_t jvsBuffer_lock = PTHREAD_MUTEX_INITIALIZER; +#if defined(__linux__) || defined(__APPLE__) + int jvsHandle = -1; +#elif defined(_WIN32) + HANDLE jvsHandle = INVALID_HANDLE_VALUE; +#endif +#define SYNC 0xE0 +#define ESCAPE 0xD0 /** - * Open the serial interface and return a file descriptor - * @param jvsPath The serial port path. Ex: "/dev/ttyS3" - * @return A file descriptor + * Setups the JVS passthrough by opening the specified serial port and configuring its settings. + * @param jvsPath The path to the serial port device (e.g., "/dev/ttyUSB0"). + * @return JVS_PASSTHROUGH_STATUS_OK on success, JVS_PASSTHROUGH_STATUS_ERROR on failure. */ -int openJVSSerial(char *jvsPath) +JVSPassthroughStatus initJVSPassthroughLinux(char *jvsPath) { - int jvsFileDescriptor = -1; - - // TODO: check O_NOCTTY declaration - jvsFileDescriptor = open(jvsPath, O_RDWR | O_NOCTTY); - if (jvsFileDescriptor < 0) +#if defined(__linux__) || defined(__APPLE__) + jvsHandle = open(jvsPath, O_RDWR | O_NOCTTY); + if (jvsHandle < 0) { - printf("Failed to open '%s' for JVS.\n", jvsPath); + printf("Error: Failed to open '%s' for JVS passthrough\n", jvsPath); + return JVS_PASSTHROUGH_STATUS_ERROR; } - return jvsFileDescriptor; -} - - -/** - * Init a serial port (using file descriptor) so it behaves correctly for JVS usage - * @param fd - * @return 0|1 - */ -int initJVSSerial(int fd) -{ struct termios options; - int status; - // Get the current options - if (tcgetattr(fd, &options) != 0) { - printf("Error %i from tcgetattr: %s\n", errno, strerror(errno)); - return 1; + if (tcgetattr(jvsHandle, &options) != 0) + { + printf("Error: Failed to get terminal attributes for JVS passthrough\n"); + return JVS_PASSTHROUGH_STATUS_ERROR; } - // Set rates cfsetispeed(&options, B115200); cfsetospeed(&options, B115200); - /* From doc: - * If the CLOCAL flag for a line is off, the hardware carrier detect (DCD) signal is significant, - * an open(2) of the corresponding terminal will block until DCD is asserted, unless the O_NONBLOCK - * flag is given. If CLOCAL is set, the line behaves as if DCD is always asserted. The software - * carrier flag is usually turned on for local devices, and is off for lines with modems. - */ - // options.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines options.c_cflag |= CREAD; // Turn on READ, let ctrl lines work - options.c_cflag &= ~PARENB; // Clear parity bit & disable parity - options.c_cflag &= ~CSTOPB; // Clear stop field, 1 stop bit - options.c_cflag &= ~CSIZE; // Clear all bits that set the data size - options.c_cflag |= CS8; // 8 bits + options.c_cflag &= ~PARENB; // Clear parity bit & disable parity + options.c_cflag &= ~CSTOPB; // Clear stop field, 1 stop bit + options.c_cflag &= ~CSIZE; // Clear all bits that set the data size + options.c_cflag |= CS8; // 8 bits options.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control - options.c_lflag &= ~ICANON; // Disable canonical mode, so no input processing is performed - options.c_lflag &= ~ECHO; // Disable echo - options.c_lflag &= ~ECHOE; // Disable erasure - options.c_lflag &= ~ECHONL; // Disable new-line echo - options.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP + options.c_lflag &= ~ICANON; // Disable canonical mode, so no input processing is performed + options.c_lflag &= ~ECHO; // Disable echo + options.c_lflag &= ~ECHOE; // Disable erasure + options.c_lflag &= ~ECHONL; // Disable new-line echo + options.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP options.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl options.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL); // Disable any special handling of received bytes @@ -85,184 +71,281 @@ int initJVSSerial(int fd) options.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars) options.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed - // Set VMIN and VTIME to 0, so it returns immediately when no data are present - // options.c_cc[VMIN] = 0; - // options.c_cc[VTIME] = 0; - - // With threaded serial read we should rely on a blocking read() function so the loop doesn't run crazy => read() could block indefinitely. - // options.c_cc[VMIN] = 1; - // options.c_cc[VTIME] = 0; - - // Block until either VMIN characters have been received or VTIME **after first character** has been received options.c_cc[VMIN] = 0; - options.c_cc[VTIME] = 1; - + options.c_cc[VTIME] = 2; // 200ms - tcsetattr(fd, TCSANOW, &options); + if (tcsetattr(jvsHandle, TCSANOW, &options) != 0) + { + printf("Error: Failed to set terminal attributes for JVS passthrough\n"); + return JVS_PASSTHROUGH_STATUS_ERROR; + } - /* No use ? Save it for later - // Set the serial port to non-blocking mode - int flags = fcntl(fd, F_GETFL, 0); - fcntl(fd, F_SETFL, flags | O_NONBLOCK); - */ +#endif - return 0; + return JVS_PASSTHROUGH_STATUS_OK; } - /** - * The DCD (Data Carrier Detect) status of a serial port indicates whether a carrier is present on the line, meaning that a connection has been established with another device. - * @param fd File descriptor of JVS (serial) port - * @return 0|1 According to control line status + * Setups the JVS passthrough by opening the specified serial port and configuring its settings. + * @param jvsPath The path to the serial port device (e.g., "/dev/ttyUSB0"). + * @return JVS_PASSTHROUGH_STATUS_OK on success, JVS_PASSTHROUGH_STATUS_ERROR on failure. */ -int getDCD(int fd) +JVSPassthroughStatus initJVSPassthroughWindows(char *jvsPath) { - int status; - ioctl(fd, TIOCMGET, &status); - return (status & TIOCM_CAR) != 0; +#if defined(_WIN32) + jvsHandle = CreateFileA(jvsPath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); + if (jvsHandle == INVALID_HANDLE_VALUE) + { + printf("Error: Failed to open '%s' for JVS passthrough\n", jvsPath); + return JVS_PASSTHROUGH_STATUS_ERROR; + } + + DCB dcb; + COMMTIMEOUTS timeouts; + + SecureZeroMemory(&dcb, sizeof(dcb)); + dcb.DCBlength = sizeof(dcb); + + if (!GetCommState(jvsHandle, &dcb)) + { + printf("Error: Failed to get comm state for JVS passthrough\n"); + return JVS_PASSTHROUGH_STATUS_ERROR; + } + + dcb.BaudRate = baud; + dcb.ByteSize = 8; + dcb.Parity = NOPARITY; + dcb.StopBits = ONESTOPBIT; + + dcb.fBinary = TRUE; + dcb.fParity = FALSE; + + dcb.fOutxCtsFlow = FALSE; + dcb.fOutxDsrFlow = FALSE; + dcb.fDtrControl = DTR_CONTROL_DISABLE; + dcb.fDsrSensitivity = FALSE; + + dcb.fTXContinueOnXoff = TRUE; + dcb.fOutX = FALSE; + dcb.fInX = FALSE; + + dcb.fErrorChar = FALSE; + dcb.fNull = FALSE; + dcb.fRtsControl = RTS_CONTROL_DISABLE; + dcb.fAbortOnError = FALSE; + + if (!SetCommState(jvsHandle, &dcb)) + { + printf("Error: Failed to set comm state for JVS passthrough\n"); + return JVS_PASSTHROUGH_STATUS_ERROR; + } + + SecureZeroMemory(&timeouts, sizeof(timeouts)); + + timeouts.ReadIntervalTimeout = 50; + timeouts.ReadTotalTimeoutMultiplier = 0; + timeouts.ReadTotalTimeoutConstant = 50; + + timeouts.WriteTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 100; + + if (!SetCommTimeouts(jvsHandle, &timeouts)) + { + printf("Error: Failed to set comm timeouts for JVS passthrough\n"); + return JVS_PASSTHROUGH_STATUS_ERROR; + } +#endif + return JVS_PASSTHROUGH_STATUS_OK; } /** - * The DSR (Data Set Ready) status of a serial port indicates whether the device at the other end of the connection is ready to receive data. - * @param fd File descriptor of JVS (serial) port - * @return 0|1 According to control line status + * Setups the JVS passthrough by opening the specified serial port and configuring its settings. + * @param jvsPath The path to the serial port device (e.g., "/dev/ttyUSB0"). + * @return JVS_PASSTHROUGH_STATUS_OK on success, JVS_PASSTHROUGH_STATUS_ERROR on failure. */ -int getDSR(int fd) +JVSPassthroughStatus initJVSPassthrough(char *jvsPath) { - int status; - ioctl(fd, TIOCMGET, &status); - return (status & TIOCM_DSR) != 0; +#if defined(__linux__) || defined(__APPLE__) + return initJVSPassthroughLinux(jvsPath); +#elif defined(_WIN32) + return initJVSPassthroughWindows(jvsPath); +#else + printf("Error: Unsupported platform for JVS passthrough\n"); + return JVS_PASSTHROUGH_STATUS_ERROR; +#endif } /** - * The CTS (Clear To Send) status of a serial port indicates whether the device at the other end of the connection is ready to accept data. - * @param fd File descriptor of JVS (serial) port - * @return 0|1 According to control line status + * Writes bytes to the serial port. + * @param buffer The buffer containing the data to write. + * @param size The size of the data to write. + * @return The number of bytes written, or 0 on failure. */ -int getCTS(int fd) +int writeBytes(const unsigned char *buffer, int size) { - int status; - ioctl(fd, TIOCMGET, &status); - return (status & TIOCM_CTS) != 0; +#if defined(__linux__) || defined(__APPLE__) + return write(jvsHandle, buffer, size); +#elif defined(_WIN32) + DWORD written = 0; + + if (!WriteFile(jvsHandle, buffer, size, &written, NULL)) { + printf("Error: Failed to write to JVS passthrough\n"); + return 0; + } + + return (int) written; +#else + printf("Error: Cannot write, unsupported platform for JVS passthrough\n"); + return JVS_PASSTHROUGH_STATUS_ERROR; +#endif } /** - * In charge of reading serial port and bufferize JVS frame - * @param arg - * @return + * Reads bytes from the serial port. + * @param buffer The buffer to store the received data. + * @param size The size of the buffer. + * @return The number of bytes read, or 0 on failure. */ -void *readJVSFrameThread(void * arg) +int readBytes(unsigned char *buffer, int size) { - int fd = *((int *) arg); - int byteCount, bytesRead, ackSize, waitForEnd; - int ctsRetry = CTS_ON_RETRY; - char localBuffer[JVSBUFFER_SIZE]; - - while (1) - { - // Reset local variable - byteCount = 0; - ackSize = 0; - waitForEnd = 0; - - do - { - // printf("SERIAL thread debug: trying to read byte.\n"); - // Try to read a byte from serial, this call will be blocking if VMIN > 0 and VTIME = 0 - bytesRead = read(fd, &localBuffer[byteCount], 1); - - // If nothing on serial and CTS is ON, we try to read "CTS_ON_RETRY" times - ctsRetry = CTS_ON_RETRY; - while (bytesRead < 1 && --ctsRetry > 0 && jvsFrameBuffer.ready == 0) { - bytesRead = read(fd, &localBuffer[byteCount], 1); - // printf("SERIAL: Retry number %d.\n", ctsRetry); - } - - if (bytesRead > 0) { - // Sync byte, we will stick in the loop - if (byteCount == 0 && localBuffer[byteCount] == (char) 0xE0) { - waitForEnd = 1; - } - - // Size byte - if (byteCount == 2) { - ackSize = localBuffer[byteCount] + 3; - } - - // Start counting bytes only if SYNC has been found - if (waitForEnd) { - byteCount++; - } - - // Reached the end of the message - if (byteCount == ackSize) { - waitForEnd = 0; - } - } - } while (waitForEnd); - - // Lock the buffer while we write to it - pthread_mutex_lock(&jvsBuffer_lock); - memcpy(jvsFrameBuffer.buffer, localBuffer, byteCount); - jvsFrameBuffer.size = byteCount; - jvsFrameBuffer.ready = 1; - ctsRetry = CTS_ON_RETRY; - pthread_mutex_unlock(&jvsBuffer_lock); +#if defined(__linux__) || defined(__APPLE__) + return read(jvsHandle, buffer, size); +#elif defined(_WIN32) + DWORD read = 0; + + if (!ReadFile(jvsHandle, buffer, size, &read, NULL)) { + printf("Error: Failed to read from JVS passthrough\n"); + return 0; } - return NULL; + return (int) read; +#else + printf("Error: Cannot read, unsupported platform for JVS passthrough\n"); + return JVS_PASSTHROUGH_STATUS_ERROR; +#endif } /** - * Init the thread in charge of reading serial port - * @param fd - * @return 0|1 + * Writes a JVS frame to the serial port. + * @param buffer The buffer containing the JVS frame data to write. + * @param size The size of the data to write. + * @return JVS_PASSTHROUGH_STATUS_OK on success, JVS_PASSTHROUGH_STATUS_ERROR on failure. */ -int startJVSFrameThread(int *fd) +JVSPassthroughStatus writeJVSFrame(unsigned char *buffer, int size) { - printf("SERIAL: starting thread.\n"); - - // Clean shared JVS frame buffer - jvsFrameBuffer.ready = 0; - jvsFrameBuffer.size = 0; - memset(jvsFrameBuffer.buffer, 0, JVSBUFFER_SIZE); - pthread_t jvsFrameThread; - int ret = pthread_create(&jvsFrameThread, NULL, readJVSFrameThread, fd); - if (ret != 0) + int written = writeBytes(buffer, size); + if (written < 0) { - printf("SERIAL: Failed to create reader thread\n"); - return 1; + printf("Error: Failed to write to JVS passthrough\n"); + return JVS_PASSTHROUGH_STATUS_ERROR; } - return 0; + return JVS_PASSTHROUGH_STATUS_OK; } /** - * Return a JVSFrame structure with empty or full data, no in between - * @return + * Reads a JVS frame from the serial port. + * @param buffer The buffer to store the received JVS frame data. + * @param size A pointer to an integer containing the size of the buffer. On return, this will be updated with the number of bytes read. + * @return JVS_PASSTHROUGH_STATUS_OK on success, JVS_PASSTHROUGH_STATUS_ERROR on failure. */ -JVSFrame readJVSFrameFromThread() +JVSPassthroughStatus readJVSFrame(unsigned char *buffer, int *size) { - JVSFrame frame; - // Lock while reading/writing to shared frame - pthread_mutex_lock(&jvsBuffer_lock); - - // Check if we have a valid frame - if (jvsFrameBuffer.ready == 1) - { - frame = jvsFrameBuffer; - // It has been read, we disable this frame - jvsFrameBuffer.ready = 0; - } - else - { - frame.ready = 0; - frame.size = 0; - memset(frame.buffer, 0, JVSBUFFER_SIZE); - } - pthread_mutex_unlock(&jvsBuffer_lock); - - return frame; -} -#endif \ No newline at end of file + int bytesAvailable = 0, escape = 0, phase = 0, index = 0, finished = 0; + unsigned char checksum = 0x00; + int timeout = 3; + + unsigned char destination, length; + unsigned char inputBuffer[JVSBUFFER_SIZE]; + + *size = 0; + + while (!finished) + { + int bytesRead = read(jvsHandle, inputBuffer + bytesAvailable, JVSBUFFER_SIZE - bytesAvailable); + + if(bytesRead > 0) { + timeout = 3; + } else { + timeout = timeout - 1; + } + + if(timeout == 0) { + return JVS_PASSTHROUGH_STATUS_TIMEOUT; + } + + + if (bytesRead < 0) + return JVS_PASSTHROUGH_STATUS_ERROR; + + bytesAvailable += bytesRead; + + while ((index < bytesAvailable) && !finished) + { + /* If we encounter a SYNC start again */ + if (!escape && (inputBuffer[index] == SYNC)) + { + phase = 0; + *size = 0; + buffer[*size++] = inputBuffer[index]; + index++; + continue; + } + + /* If we encounter an ESCAPE byte escape the next byte */ + if (!escape && inputBuffer[index] == ESCAPE) + { + escape = 1; + index++; + continue; + } + + /* Escape next byte by adding 1 to it */ + if (escape) + { + inputBuffer[index]++; + escape = 0; + } + + /* Deal with the main bulk of the data */ + switch (phase) + { + case 0: // If we have not yet got the address + buffer[*size++] = inputBuffer[index]; + destination = inputBuffer[index]; + checksum = destination & 0xFF; + phase++; + break; + case 1: // If we have not yet got the length + length = inputBuffer[index]; + buffer[*size++] = inputBuffer[index]; + checksum = (checksum + length) & 0xFF; + phase++; + break; + case 2: // If there is still data to read + if (*size == (length + 2)) + { + if (checksum != inputBuffer[index]) { + printf("CHEKCSUM ERROR\n"); + return JVS_PASSTHROUGH_STATUS_ERROR; // Checksum error, return empty frame + } + + buffer[*size++] = checksum; + + + finished = 1; + break; + } + buffer[*size++] = inputBuffer[index]; + checksum = (checksum + inputBuffer[index]) & 0xFF; + break; + default: + return JVS_PASSTHROUGH_STATUS_ERROR; + } + index++; + } + } + + return JVS_PASSTHROUGH_STATUS_OK; +} \ No newline at end of file diff --git a/src/loader/hardware/lindbergh/passthrough.h b/src/loader/hardware/lindbergh/passthrough.h index 4d55ea2..1ae327c 100644 --- a/src/loader/hardware/lindbergh/passthrough.h +++ b/src/loader/hardware/lindbergh/passthrough.h @@ -1,22 +1,21 @@ -#ifdef __linux__ -#define JVSBUFFER_SIZE 1024 -typedef struct { +#define JVSBUFFER_SIZE 256 + +typedef struct +{ int ctsCounter; int ready; int size; char buffer[JVSBUFFER_SIZE]; } JVSFrame; -int getDCD(int fd); -int getDSR(int fd); -int getCTS(int fd); - -JVSFrame readJVSFrameFromThread(); -int startJVSFrameThread(int * fd); -void * readJVSFrameThread(void * arg); +typedef enum +{ + JVS_PASSTHROUGH_STATUS_OK = 0, + JVS_PASSTHROUGH_STATUS_ERROR = 1, + JVS_PASSTHROUGH_STATUS_TIMEOUT = 2 +} JVSPassthroughStatus; -int openJVSSerial(char *jvsPath); -int initJVSSerial(int fd); -int readJVSFrame(int fd, unsigned char *buffer); -#endif \ No newline at end of file +JVSPassthroughStatus initJVSPassthrough(char *jvsPath); +JVSPassthroughStatus writeJVSFrame(unsigned char *buffer, int size); +JVSPassthroughStatus readJVSFrame(unsigned char *buffer, int *size); \ No newline at end of file From 29c6307b4a485ec61447b13b3b08fb264400f8e9 Mon Sep 17 00:00:00 2001 From: Bobby Dilley Date: Sat, 27 Jun 2026 22:53:42 +0100 Subject: [PATCH 2/2] Fix the linux issues --- src/loader/hardware/lindbergh/baseBoard.c | 24 +++++++++++-------- src/loader/hardware/lindbergh/passthrough.c | 26 +++++++-------------- 2 files changed, 22 insertions(+), 28 deletions(-) diff --git a/src/loader/hardware/lindbergh/baseBoard.c b/src/loader/hardware/lindbergh/baseBoard.c index 49447d9..4ef76f6 100644 --- a/src/loader/hardware/lindbergh/baseBoard.c +++ b/src/loader/hardware/lindbergh/baseBoard.c @@ -220,7 +220,10 @@ int baseboardIoctl(int fd, unsigned long request, void *data) } else { - writeJVSFrame(inputBuffer, jvsCommand.srcSize); + JVSPassthroughStatus status = writeJVSFrame(inputBuffer, jvsCommand.srcSize); + if(status != JVS_PASSTHROUGH_STATUS_OK) { + printf("Error: Failed to write JVS frame, status: %d\n", status); + } for (uint32_t i = 0; i < jvsCommand.srcSize; i++) { @@ -294,21 +297,22 @@ int baseboardIoctl(int fd, unsigned long request, void *data) else { JVSPassthroughStatus status = readJVSFrame(passthroughInputBuffer, &jvsPacketSize); - if (status == JVS_PASSTHROUGH_STATUS_OK) - { - memcpy(&sharedMemory[jvsCommand.destAddress], passthroughInputBuffer, jvsPacketSize); + if(status != JVS_PASSTHROUGH_STATUS_OK) { + printf("Error: Failed to read JVS frame, status: %d\n", status); + // If it times out then we can just set the system to error out + memcpy(&sharedMemory[jvsCommand.destAddress], "\x00", 1); _data[2] = jvsCommand.destAddress; - _data[3] = jvsPacketSize; - _data[1] = 1; // Set the status to success + _data[3] = 1; + _data[1] = 1; // Set the status to failure } else { - // If it times out then we can just set the system to error out - memcpy(&sharedMemory[jvsCommand.destAddress], "/x00", 1); + memcpy(&sharedMemory[jvsCommand.destAddress], passthroughInputBuffer, jvsPacketSize); _data[2] = jvsCommand.destAddress; - _data[3] = 1; - _data[1] = 1; // Set the status to failure + _data[3] = jvsPacketSize; + _data[1] = 1; // Set the status to success } + } } } diff --git a/src/loader/hardware/lindbergh/passthrough.c b/src/loader/hardware/lindbergh/passthrough.c index 1b6ef33..2a78404 100644 --- a/src/loader/hardware/lindbergh/passthrough.c +++ b/src/loader/hardware/lindbergh/passthrough.c @@ -72,7 +72,7 @@ JVSPassthroughStatus initJVSPassthroughLinux(char *jvsPath) options.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed options.c_cc[VMIN] = 0; - options.c_cc[VTIME] = 2; // 200ms + options.c_cc[VTIME] = 1; // 200ms if (tcsetattr(jvsHandle, TCSANOW, &options) != 0) { @@ -254,7 +254,7 @@ JVSPassthroughStatus readJVSFrame(unsigned char *buffer, int *size) { int bytesAvailable = 0, escape = 0, phase = 0, index = 0, finished = 0; unsigned char checksum = 0x00; - int timeout = 3; + int timeout = 1; unsigned char destination, length; unsigned char inputBuffer[JVSBUFFER_SIZE]; @@ -265,20 +265,10 @@ JVSPassthroughStatus readJVSFrame(unsigned char *buffer, int *size) { int bytesRead = read(jvsHandle, inputBuffer + bytesAvailable, JVSBUFFER_SIZE - bytesAvailable); - if(bytesRead > 0) { - timeout = 3; - } else { - timeout = timeout - 1; - } - - if(timeout == 0) { + if(bytesRead < 1) { return JVS_PASSTHROUGH_STATUS_TIMEOUT; } - - if (bytesRead < 0) - return JVS_PASSTHROUGH_STATUS_ERROR; - bytesAvailable += bytesRead; while ((index < bytesAvailable) && !finished) @@ -288,7 +278,7 @@ JVSPassthroughStatus readJVSFrame(unsigned char *buffer, int *size) { phase = 0; *size = 0; - buffer[*size++] = inputBuffer[index]; + buffer[(*size)++] = inputBuffer[index]; index++; continue; } @@ -312,14 +302,14 @@ JVSPassthroughStatus readJVSFrame(unsigned char *buffer, int *size) switch (phase) { case 0: // If we have not yet got the address - buffer[*size++] = inputBuffer[index]; + buffer[(*size)++] = inputBuffer[index]; destination = inputBuffer[index]; checksum = destination & 0xFF; phase++; break; case 1: // If we have not yet got the length length = inputBuffer[index]; - buffer[*size++] = inputBuffer[index]; + buffer[(*size)++] = inputBuffer[index]; checksum = (checksum + length) & 0xFF; phase++; break; @@ -331,13 +321,13 @@ JVSPassthroughStatus readJVSFrame(unsigned char *buffer, int *size) return JVS_PASSTHROUGH_STATUS_ERROR; // Checksum error, return empty frame } - buffer[*size++] = checksum; + buffer[(*size)++] = checksum; finished = 1; break; } - buffer[*size++] = inputBuffer[index]; + buffer[(*size)++] = inputBuffer[index]; checksum = (checksum + inputBuffer[index]) & 0xFF; break; default: