Add roel's JVS pass through code
This commit is contained in:
parent
031044c5bd
commit
f494984cdc
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -7,6 +7,7 @@
|
||||
"time.h": "c",
|
||||
"stdarg.h": "c",
|
||||
"ioctl.h": "c",
|
||||
"segaeax.h": "c"
|
||||
"segaeax.h": "c",
|
||||
"passthrough.h": "c"
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +1,16 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <linux/serial.h>
|
||||
#include <termios.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/serial.h>
|
||||
#include <stdio.h> /* Standard input/output definitions */
|
||||
#include <string.h> /* String function definitions */
|
||||
#include <unistd.h> /* UNIX standard function definitions */
|
||||
#include <fcntl.h> /* File control definitions */
|
||||
#include <errno.h> /* Error number definitions */
|
||||
#include <stdlib.h> /* Standard library functions like malloc, free, exit, and atoi */
|
||||
|
||||
#include "baseboard.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "jvs.h"
|
||||
#include "serial.h"
|
||||
#include "passthrough.h"
|
||||
|
||||
#define SERIAL_STRING "FE11-X018012022X"
|
||||
|
||||
@ -83,21 +72,21 @@ int initBaseboard()
|
||||
printf("Error: Cannot open %s\n", sramPath);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fclose(sram);
|
||||
|
||||
sram = fopen(sramPath, "rb+");
|
||||
|
||||
fseek(sram, 0, SEEK_SET);
|
||||
|
||||
if (getConfig()->emulateJVS == 0 && strcmp(getConfig()->jvsPath, "none") != 0)
|
||||
{
|
||||
jvsFileDescriptor = open(getConfig()->jvsPath, O_RDWR | O_NOCTTY | O_SYNC | O_NDELAY);
|
||||
jvsFileDescriptor = openJVSSerial(getConfig()->jvsPath);
|
||||
if (jvsFileDescriptor < 0)
|
||||
{
|
||||
printf("Error: Failed to open %s for JVS\n", getConfig()->jvsPath);
|
||||
return -1;
|
||||
}
|
||||
setSerialAttributes(jvsFileDescriptor, B115200);
|
||||
|
||||
initJVSSerial(jvsFileDescriptor);
|
||||
startJVSFrameThread(&jvsFileDescriptor);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -206,11 +195,9 @@ int baseboardIoctl(int fd, unsigned int request, void *data)
|
||||
}
|
||||
else if (jvsFileDescriptor >= 0)
|
||||
{
|
||||
|
||||
write(jvsFileDescriptor, inputBuffer, jvsCommand.srcSize);
|
||||
|
||||
for (int i = 0; i < jvsCommand.srcSize; i++)
|
||||
{
|
||||
write(jvsFileDescriptor, &inputBuffer[i], 1);
|
||||
if (inputBuffer[i] == 0xF0)
|
||||
{
|
||||
setSenseLine(3);
|
||||
@ -270,14 +257,11 @@ int baseboardIoctl(int fd, unsigned int request, void *data)
|
||||
}
|
||||
else if (jvsFileDescriptor >= 0)
|
||||
{
|
||||
int count = readBytes(jvsFileDescriptor, &sharedMemory[jvsCommand.destAddress], 255);
|
||||
|
||||
if (count == -1)
|
||||
count = 0;
|
||||
|
||||
JVSFrame frame = readJVSFrameFromThread();
|
||||
memcpy(&sharedMemory[jvsCommand.destAddress], frame.buffer, frame.size);
|
||||
_data[2] = jvsCommand.destAddress;
|
||||
_data[3] = count;
|
||||
_data[1] = (count > 0); // Success if we receive any sort of data back
|
||||
_data[3] = frame.size;
|
||||
_data[1] = frame.ready;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -88,7 +88,7 @@ FGAPI void FGAPIENTRY glutGameModeString(const char *string)
|
||||
Window XCreateWindow(Display *display, Window parent, int x, int y, unsigned int width, unsigned int height, unsigned int border_width, int depth, unsigned int class, Visual *visual, unsigned long valueMask, XSetWindowAttributes *attributes)
|
||||
{
|
||||
|
||||
Window (*_XCreateWindow)(Display * display, Window parent, int x, int y, unsigned int width, unsigned int height, unsigned int border_width, int depth, unsigned int class, Visual *visual, unsigned long valueMask, XSetWindowAttributes *attributes) = dlsym(RTLD_NEXT, "XCreateWindow");
|
||||
Window (*_XCreateWindow)(Display *display, Window parent, int x, int y, unsigned int width, unsigned int height, unsigned int border_width, int depth, unsigned int class, Visual *visual, unsigned long valueMask, XSetWindowAttributes *attributes) = dlsym(RTLD_NEXT, "XCreateWindow");
|
||||
|
||||
width = getConfig()->width;
|
||||
height = getConfig()->height;
|
||||
@ -112,7 +112,7 @@ Window XCreateWindow(Display *display, Window parent, int x, int y, unsigned int
|
||||
|
||||
int XGrabPointer(Display *display, Window grab_window, Bool owner_events, unsigned int event_mask, int pointer_mode, int keyboard_mode, Window confine_to, Cursor cursor, Time time)
|
||||
{
|
||||
int (*_XGrabPointer)(Display * display, Window grab_window, Bool owner_events, unsigned int event_mask, int pointer_mode, int keyboard_mode, Window confine_to, Cursor cursor, Time time) = dlsym(RTLD_NEXT, "XGrabPointer");
|
||||
int (*_XGrabPointer)(Display *display, Window grab_window, Bool owner_events, unsigned int event_mask, int pointer_mode, int keyboard_mode, Window confine_to, Cursor cursor, Time time) = dlsym(RTLD_NEXT, "XGrabPointer");
|
||||
int returnValue = _XGrabPointer(display, grab_window, owner_events, event_mask, pointer_mode, keyboard_mode, confine_to, cursor, time);
|
||||
XUngrabPointer(display, time);
|
||||
return returnValue;
|
||||
@ -120,7 +120,7 @@ int XGrabPointer(Display *display, Window grab_window, Bool owner_events, unsign
|
||||
|
||||
int XGrabKeyboard(Display *display, Window grab_window, Bool owner_events, int pointer_mode, int keyboard_mode, Time time)
|
||||
{
|
||||
int (*_XGrabKeyboard)(Display * display, Window grab_window, Bool owner_events, int pointer_mode, int keyboard_mode, Time time) = dlsym(RTLD_NEXT, "XGrabKeyboard");
|
||||
int (*_XGrabKeyboard)(Display *display, Window grab_window, Bool owner_events, int pointer_mode, int keyboard_mode, Time time) = dlsym(RTLD_NEXT, "XGrabKeyboard");
|
||||
int returnValue = _XGrabKeyboard(display, grab_window, owner_events, pointer_mode, keyboard_mode, time);
|
||||
XUngrabKeyboard(display, time);
|
||||
return returnValue;
|
||||
@ -133,7 +133,7 @@ int XDefineCursor(Display *display, Window w, Cursor cursor)
|
||||
|
||||
int XStoreName(Display *display, Window w, const char *window_name)
|
||||
{
|
||||
int (*_XStoreName)(Display * display, Window w, const char *window_name) = dlsym(RTLD_NEXT, "XStoreName");
|
||||
int (*_XStoreName)(Display *display, Window w, const char *window_name) = dlsym(RTLD_NEXT, "XStoreName");
|
||||
char gameTitle[256] = {0};
|
||||
strcat(gameTitle, getGameName());
|
||||
strcat(gameTitle, " (X11)");
|
||||
@ -143,8 +143,15 @@ int XStoreName(Display *display, Window w, const char *window_name)
|
||||
int XNextEvent(Display *display, XEvent *event_return)
|
||||
{
|
||||
|
||||
int (*_XNextEvent)(Display * display, XEvent * event_return) = dlsym(RTLD_NEXT, "XNextEvent");
|
||||
int (*_XNextEvent)(Display *display, XEvent *event_return) = dlsym(RTLD_NEXT, "XNextEvent");
|
||||
int returnValue = _XNextEvent(display, event_return);
|
||||
|
||||
// Return now if we're not emulating JVS
|
||||
if (!getConfig()->emulateJVS)
|
||||
{
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
switch (event_return->type)
|
||||
{
|
||||
|
||||
@ -231,7 +238,7 @@ int XNextEvent(Display *display, XEvent *event_return)
|
||||
|
||||
int XSetStandardProperties(Display *display, Window window, const char *window_name, const char *icon_name, Pixmap icon_pixmap, char **argv, int argc, XSizeHints *hints)
|
||||
{
|
||||
int (*_XSetStandardProperties)(Display * display, Window window, const char *window_name, const char *icon_name, Pixmap icon_pixmap, char **argv, int argc, XSizeHints *hints) = dlsym(RTLD_NEXT, "XSetStandardProperties");
|
||||
int (*_XSetStandardProperties)(Display *display, Window window, const char *window_name, const char *icon_name, Pixmap icon_pixmap, char **argv, int argc, XSizeHints *hints) = dlsym(RTLD_NEXT, "XSetStandardProperties");
|
||||
char gameTitle[256] = {0};
|
||||
strcat(gameTitle, getGameName());
|
||||
strcat(gameTitle, " (X11)");
|
||||
@ -245,30 +252,36 @@ Bool XF86VidModeSwitchToMode(Display *display, int screen, XF86VidModeModeInfo *
|
||||
|
||||
typedef unsigned int uint;
|
||||
|
||||
int glXSwapIntervalSGI(int interval) {
|
||||
int glXSwapIntervalSGI(int interval)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int glXGetVideoSyncSGI(uint *count) {
|
||||
int glXGetVideoSyncSGI(uint *count)
|
||||
{
|
||||
static unsigned int frameCount = 0;
|
||||
//TODO: Framecount should depend on current system time
|
||||
*count = (frameCount++)/2; // NOTE: Keeps the same frame for 2 calls
|
||||
// TODO: Framecount should depend on current system time
|
||||
*count = (frameCount++) / 2; // NOTE: Keeps the same frame for 2 calls
|
||||
return 0;
|
||||
}
|
||||
|
||||
int glXGetRefreshRateSGI(unsigned int * rate) { //TODO: need an actual prototype
|
||||
*rate = 60; //TODO: what does this function return?
|
||||
int glXGetRefreshRateSGI(unsigned int *rate)
|
||||
{ // TODO: need an actual prototype
|
||||
*rate = 60; // TODO: what does this function return?
|
||||
return 0;
|
||||
}
|
||||
|
||||
void glGenFencesNV(int n, uint *fences) {
|
||||
void glGenFencesNV(int n, uint *fences)
|
||||
{
|
||||
static unsigned int curf = 1;
|
||||
while(n--) {
|
||||
while (n--)
|
||||
{
|
||||
*fences++ = curf++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void glDeleteFencesNV(int a, const uint *b) {
|
||||
void glDeleteFencesNV(int a, const uint *b)
|
||||
{
|
||||
return;
|
||||
}
|
@ -598,6 +598,13 @@ JVSStatus writePacket(JVSPacket *packet)
|
||||
return JVS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the sense line value
|
||||
*
|
||||
* Values are:
|
||||
* 3 = no device, after a RESET
|
||||
* 1 = address assigned
|
||||
*/
|
||||
int getSenseLine()
|
||||
{
|
||||
return senseLine;
|
||||
@ -635,6 +642,7 @@ int setAnalogue(JVSInput channel, int value)
|
||||
return 1;
|
||||
}
|
||||
|
||||
void setSenseLine(int _senseLine) {
|
||||
void setSenseLine(int _senseLine)
|
||||
{
|
||||
senseLine = _senseLine;
|
||||
}
|
||||
|
258
src/lindbergh/passthrough.c
Normal file
258
src/lindbergh/passthrough.c
Normal file
@ -0,0 +1,258 @@
|
||||
#include <stdio.h> /* Standard input/output definitions */
|
||||
#include <string.h> /* String function definitions */
|
||||
#include <unistd.h> /* UNIX standard function definitions */
|
||||
#include <fcntl.h> /* File control definitions */
|
||||
#include <errno.h> /* Error number definitions */
|
||||
#include <termios.h> /* POSIX terminal control definitions */
|
||||
#include <sys/ioctl.h> /* Ioctl function to control device drivers in the kernel */
|
||||
#include <stdlib.h> /* Standard library functions like malloc, free, exit, and atoi */
|
||||
#include <pthread.h> /* POSIX threads API to create and manage threads in the program */
|
||||
|
||||
#include "passthrough.h"
|
||||
|
||||
#define TIMEOUT_SELECT 200
|
||||
#define CTS_ON_RETRY 20
|
||||
|
||||
// Used to read JVS frame in a non-blocking way
|
||||
JVSFrame jvsFrameBuffer;
|
||||
pthread_mutex_t jvsBuffer_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
|
||||
/**
|
||||
* Open the serial interface and return a file descriptor
|
||||
* @param jvsPath The serial port path. Ex: "/dev/ttyS3"
|
||||
* @return A file descriptor
|
||||
*/
|
||||
int openJVSSerial(char *jvsPath) {
|
||||
int jvsFileDescriptor = -1;
|
||||
|
||||
// TODO: check O_NOCTTY declaration
|
||||
jvsFileDescriptor = open(jvsPath, O_RDWR | O_NOCTTY);
|
||||
if (jvsFileDescriptor < 0) {
|
||||
printf("Failed to open '%s' for JVS.\n", jvsPath);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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 &= ~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_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
|
||||
|
||||
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;
|
||||
|
||||
|
||||
tcsetattr(fd, TCSANOW, &options);
|
||||
|
||||
/* 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);
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
int getDCD(int fd) {
|
||||
int status;
|
||||
ioctl(fd, TIOCMGET, &status);
|
||||
return (status & TIOCM_CAR) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
int getDSR(int fd) {
|
||||
int status;
|
||||
ioctl(fd, TIOCMGET, &status);
|
||||
return (status & TIOCM_DSR) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
int getCTS(int fd) {
|
||||
int status;
|
||||
ioctl(fd, TIOCMGET, &status);
|
||||
return (status & TIOCM_CTS) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* In charge of reading serial port and bufferize JVS frame
|
||||
* @param arg
|
||||
* @return
|
||||
*/
|
||||
void *readJVSFrameThread(void * arg)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Init the thread in charge of reading serial port
|
||||
* @param fd
|
||||
* @return 0|1
|
||||
*/
|
||||
int startJVSFrameThread(int * fd) {
|
||||
int fdlocal = *((int *) fd);
|
||||
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)
|
||||
{
|
||||
printf("SERIAL: Failed to create reader thread\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a JVSFrame structure with empty or full data, no in between
|
||||
* @return
|
||||
*/
|
||||
JVSFrame readJVSFrameFromThread() {
|
||||
|
||||
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 red, 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;
|
||||
}
|
20
src/lindbergh/passthrough.h
Normal file
20
src/lindbergh/passthrough.h
Normal file
@ -0,0 +1,20 @@
|
||||
#define JVSBUFFER_SIZE 1024
|
||||
|
||||
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);
|
||||
|
||||
int openJVSSerial(char *jvsPath);
|
||||
int initJVSSerial(int fd);
|
||||
int readJVSFrame(int fd, unsigned char *buffer);
|
Loading…
x
Reference in New Issue
Block a user