aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SimpleMotionV2.pri4
-rw-r--r--busdevice.c168
-rw-r--r--pcserialport.c102
-rw-r--r--simplemotion_defs.h8
-rw-r--r--tcpclient.c189
-rw-r--r--tcpclient.h22
6 files changed, 469 insertions, 24 deletions
diff --git a/SimpleMotionV2.pri b/SimpleMotionV2.pri
index b5619bc..79bfc56 100644
--- a/SimpleMotionV2.pri
+++ b/SimpleMotionV2.pri
@@ -6,9 +6,9 @@ DEPENDPATH += $$PWD
DEFINES += SIMPLEMOTIONV2_LIBRARY
SOURCES += $$PWD/sm_consts.c $$PWD/simplemotion.c $$PWD/busdevice.c $$PWD/pcserialport.c \
- $$PWD/bufferedmotion.c
+ $$PWD/bufferedmotion.c $$PWD/tcpclient.c
HEADERS += $$PWD/simplemotion_private.h\
$$PWD/pcserialport.h $$PWD/busdevice.h $$PWD/simplemotion.h $$PWD/sm485.h $$PWD/simplemotion_defs.h \
- $$PWD/bufferedmotion.h
+ $$PWD/bufferedmotion.h $$PWD/tcpclient.h
diff --git a/busdevice.c b/busdevice.c
index c4f89a1..6a89396 100644
--- a/busdevice.c
+++ b/busdevice.c
@@ -1,11 +1,17 @@
#include "busdevice.h"
#include "pcserialport.h"
+#include "tcpclient.h"
+
#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <ctype.h>
#define BD_NONE 0
#define BD_RS 1
#define BD_FTDI 2
+#define BD_TCP 3
//how much bytes available in transmit buffer
#define TANSMIT_BUFFER_LENGTH 128
@@ -46,6 +52,116 @@ void smBDinit()
bdInitialized=smtrue;
}
+static int validateIpAddress(const char *s, const char **pip_end,
+ const char **pport_start)
+{
+ int octets = 0;
+ int ch = 0, prev = 0;
+ int len = 0;
+ const char *ip_end = NULL;
+ const char *port_start = NULL;
+
+ while (*s)
+ {
+ ch = *s;
+
+ if (isdigit(ch))
+ {
+ ++len;
+ // Octet len must be 1-3 digits
+ if (len > 3)
+ {
+ return -1;
+ }
+ }
+ else if (ch == '.' && isdigit(prev))
+ {
+ ++octets;
+ len = 0;
+ // No more than 4 octets please
+ if (octets > 4)
+ {
+ return -1;
+ }
+ }
+ else if (ch == ':' && isdigit(prev))
+ {
+ ++octets;
+ // We want exactly 4 octets at this point
+ if (octets != 4)
+ {
+ return -1;
+ }
+ ip_end = s;
+ ++s;
+ port_start = s;
+ while (isdigit((ch = *s)))
+ ++s;
+ // After port we want the end of the string
+ if (ch != '\0')
+ return -1;
+ // This will skip over the ++s below
+ continue;
+ }
+ else
+ {
+ return -1;
+ }
+
+ prev = ch;
+ ++s;
+ }
+
+ // We reached the end of the string and did not encounter the port
+ if (*s == '\0' && ip_end == NULL)
+ {
+ ++octets;
+ ip_end = s;
+ }
+
+ // Check that there are exactly 4 octets
+ if (octets != 4)
+ return -1;
+
+ if (pip_end)
+ *pip_end = ip_end;
+
+ if (pport_start)
+ *pport_start = port_start;
+
+ return 0;
+}
+
+static int parseIpAddress(const char *s, char *ip, size_t ipsize, short *port)
+{
+ const char *ip_end, *port_start;
+
+ if (validateIpAddress(s, &ip_end, &port_start) == -1)
+ return -1;
+
+ // If ip=NULL, we just report that the parsing was ok
+ if (!ip)
+ return 0;
+
+ if (ipsize < ip_end - s + 1)
+ return -1;
+
+ memcpy(ip, s, ip_end - s);
+ ip[ip_end - s] = '\0';
+
+ if (port_start)
+ {
+ *port = 0;
+ while (*port_start)
+ {
+ *port = *port * 10 + (*port_start - '0');
+ ++port_start;
+ }
+ }
+
+ return 0;
+}
+
//ie "COM1" "VSD2USB"
//return -1 if fails, otherwise handle number
smbusdevicehandle smBDOpen( const char *devicename )
@@ -75,10 +191,24 @@ smbusdevicehandle smBDOpen( const char *devicename )
BusDevice[handle].bdType=BD_RS;
BusDevice[handle].txBufferUsed=0;
}
- else//no other bus types supproted yet
- {
- return -1;
- }
+ else if (validateIpAddress(devicename, NULL, NULL) == 0)
+ {
+ char ip[128];
+ short port = 4001;
+ if (parseIpAddress(devicename, ip, sizeof(ip), &port) < 0)
+ return -1;
+ BusDevice[handle].comPort=OpenTCPPort( ip, port );
+ if( BusDevice[handle].comPort == -1 )
+ {
+ return -1; //failed to open
+ }
+ BusDevice[handle].bdType=BD_TCP;
+ BusDevice[handle].txBufferUsed=0;
+ }
+ else//no other bus types supproted yet
+ {
+ return -1;
+ }
//success
BusDevice[handle].cumulativeSmStatus=0;
@@ -105,6 +235,12 @@ smbool smBDClose( const smbusdevicehandle handle )
BusDevice[handle].opened=smfalse;
return smtrue;
}
+ else if( BusDevice[handle].bdType==BD_TCP )
+ {
+ CloseTCPport( BusDevice[handle].comPort );
+ BusDevice[handle].opened=smfalse;
+ return smtrue;
+ }
return smfalse;
}
@@ -119,7 +255,7 @@ smbool smBDWrite(const smbusdevicehandle handle, const smuint8 byte )
//check if handle valid & open
if( smIsBDHandleOpen(handle)==smfalse ) return smfalse;
- if( BusDevice[handle].bdType==BD_RS )
+ if( BusDevice[handle].bdType==BD_RS || BusDevice[handle].bdType==BD_TCP )
{
if(BusDevice[handle].txBufferUsed<TANSMIT_BUFFER_LENGTH)
{
@@ -153,6 +289,20 @@ smbool smBDTransmit(const smbusdevicehandle handle)
return smfalse;
}
}
+ else if( BusDevice[handle].bdType==BD_TCP )
+ {
+ if(SendTCPBuf(BusDevice[handle].comPort,BusDevice[handle].txBuffer, BusDevice[handle].txBufferUsed)==BusDevice[handle].txBufferUsed)
+ {
+ BusDevice[handle].txBufferUsed=0;
+ return smtrue;
+ }
+ else
+ {
+ BusDevice[handle].txBufferUsed=0;
+ return smfalse;
+ }
+ }
+
return smfalse;
}
@@ -170,6 +320,14 @@ smbool smBDRead( const smbusdevicehandle handle, smuint8 *byte )
if( n!=1 ) return smfalse;
else return smtrue;
}
+ else if( BusDevice[handle].bdType==BD_TCP )
+ {
+ int n;
+ n=PollTCPPort(BusDevice[handle].comPort, byte, 1);
+ if( n!=1 ) return smfalse;
+ else return smtrue;
+ }
+
return smfalse;
}
diff --git a/pcserialport.c b/pcserialport.c
index 2b44add..35a7668 100644
--- a/pcserialport.c
+++ b/pcserialport.c
@@ -14,7 +14,7 @@
#include "pcserialport.h"
#include "simplemotion_private.h" //needed for timeout variable
-#ifdef __unix__
+#if defined(__unix__) || defined(__APPLE__)
#include <termios.h>
#include <limits.h>
@@ -25,59 +25,129 @@
#include <sys/types.h>
#include <string.h>
+#if defined(__APPLE__)
+#include <CoreFoundation/CoreFoundation.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/serial/IOSerialKeys.h>
+#include <IOKit/serial/ioss.h>
+#include <IOKit/IOBSD.h>
+#endif
+
smint32 serialPortOpen(const char * port_device_name, smint32 baudrate_bps)
{
int port_handle;
int err;
int baudrateEnumValue;
struct termios new_port_settings;
+ int customBaudRate = 0;
+
+ port_handle = open(port_device_name, O_RDWR | O_NOCTTY);
+
+ if(port_handle==-1)
+ {
+ smDebug(-1, Low, "Serial port error: port open failed");
+ return(port_handle);
+ }
switch(baudrate_bps)
{
+#if defined(B9600)
case 9600 : baudrateEnumValue = B9600; break;
+#endif
+#if defined(B19200)
case 19200 : baudrateEnumValue = B19200; break;
+#endif
+#if defined(B38400)
case 38400 : baudrateEnumValue = B38400; break;
+#endif
+#if defined(B57600)
case 57600 : baudrateEnumValue = B57600; break;
+#endif
+#if defined(B115200)
case 115200 : baudrateEnumValue = B115200; break;
+#endif
+#if defined(B230400)
case 230400 : baudrateEnumValue = B230400; break;
+#endif
+#if defined(B460800)
case 460800 : baudrateEnumValue = B460800; break;
+#endif
+#if defined(B500000)
case 500000 : baudrateEnumValue = B500000; break;
+#endif
+#if defined(B576000)
case 576000 : baudrateEnumValue = B576000; break;
+#endif
+#if defined(B921600)
case 921600 : baudrateEnumValue = B921600; break;
+#endif
+#if defined(B1000000)
case 1000000 : baudrateEnumValue = B1000000; break;
+#endif
+#if defined(B1152000)
case 1115200 : baudrateEnumValue = B1152000; break;
+#endif
+#if defined(B1500000)
case 1500000 : baudrateEnumValue = B1500000; break;
+#endif
+#if defined(B2000000)
case 2000000 : baudrateEnumValue = B2000000; break;
+#endif
+#if defined(B2500000)
case 2500000 : baudrateEnumValue = B2500000; break;
+#endif
+#if defined(B3000000)
case 3000000 : baudrateEnumValue = B3000000; break;
+#endif
+#if defined(B3500000)
case 3500000 : baudrateEnumValue = B3500000; break;
+#endif
+#if defined(B4000000)
case 4000000 : baudrateEnumValue = B4000000; break;
- default : smDebug(-1,Low,"Serial port error: unsupported baudrate\n");
- return(1);
- break;
- }
-
- port_handle = open(port_device_name, O_RDWR | O_NOCTTY );
- if(port_handle==-1)
- {
- smDebug(-1, Low, "Serial port error: port open failed");
- return(port_handle);
+#endif
+ default:
+ customBaudRate = 1;
+#if defined(__APPLE__)
+ if (ioctl(port_handle, IOSSIOSPEED, &baudrate_bps) == -1)
+ {
+ smDebug(-1, Low, "Serial port error: unsupported baudrate\n");
+ close(port_handle);
+ return -1;
+ }
+#else
+ smDebug(-1,Low,"Serial port error: unsupported baudrate\n");
+ close(port_handle);
+ return(-1);
+ break;
+#endif
}
memset(&new_port_settings, 0, sizeof(new_port_settings)); //reset struct
- new_port_settings.c_cflag = baudrateEnumValue | CS8 | CLOCAL | CREAD;
+ new_port_settings.c_cflag = CS8 | CLOCAL | CREAD;
new_port_settings.c_iflag = IGNPAR;
new_port_settings.c_oflag = 0;
new_port_settings.c_lflag = 0;
new_port_settings.c_cc[VMIN] = 0; /* non blocking mode */
new_port_settings.c_cc[VTIME] = readTimeoutMs/100; /* timeout 100 ms steps */
- err = tcsetattr(port_handle, TCSANOW, &new_port_settings);
+
+ if (!customBaudRate)
+ {
+#if defined(_BSD_SOURCE)
+ cfsetspeed(&new_port_settings, baudrateEnumValue);
+#else
+ cfsetispeed(&new_port_settings, baudrateEnumValue);
+ cfsetospeed(&new_port_settings, baudrateEnumValue);
+#endif
+ }
+
+ // Activate settings
+ err = tcsetattr(port_handle, TCSANOW, &new_port_settings);
if(err==-1)
{
- close(port_handle);
- smDebug(-1, Low, "Serial port error: failed to set port parameters");
- return -1;
+ close(port_handle);
+ smDebug(-1, Low, "Serial port error: failed to set port parameters");
+ return -1;
}
//flush any stray bytes from device receive buffer that may reside in it
diff --git a/simplemotion_defs.h b/simplemotion_defs.h
index 138c42b..fc8d8c0 100644
--- a/simplemotion_defs.h
+++ b/simplemotion_defs.h
@@ -709,11 +709,15 @@
#define TRIG_FAULT 2
#define TRIG_TARGETCHANGE 3
#define TRIG_TARGETCHANGE_POS 4
- #define TRIG_SERIALCMD 5
+ #define TRIG_EXTERNAL_INPUT 5
#define SMP_CAPTURE_SAMPLERATE 5012
//rdonly
#define SMP_CAPTURE_BUF_LENGHT 5013
+//SMP_CAPTURE_BEFORE_TRIGGER_PERCENTS sets how much samples will be preserved before trigger event. Value 0 is traditional, +n starts capture n percents before trigger (relative to whole capture length), -n after trigger. Value range -1000000%..+100%.
+#define SMP_CAPTURE_BEFORE_TRIGGER_PERCENTS 5014
+//SMP_CAPTURE_STATE, states: 0=idle (capture complete or not started), 1=waiting for trigger, 2=capturing. to start capture, write value 1 here starting from IONI FW V1110
+#define SMP_CAPTURE_STATE 5015
//this is looped 0-n to make samples 0-n readable from SMP_CAPTURE_BUFFER_GET_VALUE
#define SMP_CAPTURE_BUFFER_GET_ADDR 5333
#define SMP_CAPTURE_BUFFER_GET_VALUE 5334
@@ -735,6 +739,8 @@
#define DEVICE_CAPABILITY_AUTOSETUP_COMMUTATION_SENSOR BV(7)
#define DEVICE_CAPABILITY_SENSORLESS_COMMUTATION BV(8)
#define DEVICE_CAPABILITY_ANALOG_OUTPUT BV(9)
+ #define DEVICE_CAPABILITY_SCOPE_TRIGGER_DELAY BV(10) /*also means that params SMP_CAPTURE_BEFORE_TRIGGER_PERCENTS and SMP_CAPTURE_STATE exist */
+ #define DEVICE_CAPABILITY_SCOPE_EXTERNAL_TRIGGER BV(11)
#define SMP_FIRMWARE_VERSION 6010
#define SMP_FIRMWARE_BACKWARDS_COMP_VERSION 6011
diff --git a/tcpclient.c b/tcpclient.c
new file mode 100644
index 0000000..31fb2f2
--- /dev/null
+++ b/tcpclient.c
@@ -0,0 +1,189 @@
+#include "simplemotion_private.h"
+#include "tcpclient.h"
+#include <stdio.h>
+
+#if defined(_WIN32)
+#if defined(CM_NONE)
+#undef CM_NONE
+#endif
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#define close closesocket
+#define read(SOCKET, BUF, LEN) recv((SOCKET), (BUF), (LEN), 0)
+#define write(SOCKET, BUF, LEN) send((SOCKET), (BUF), (LEN), 0)
+#ifdef errno
+#undef errno
+#endif
+#define errno (WSAGetLastError())
+#ifdef EINPROGRESS
+#undef EINPROGRESS
+#endif
+#define EINPROGRESS WSAEWOULDBLOCK
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+#include <netdb.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#endif
+
+#if defined(_WIN32)
+static int initwsa()
+{
+ WORD req;
+ WSADATA data;
+ req = MAKEWORD(2, 2);
+ int err = WSAStartup(req, &data);
+ if (err != 0)
+ {
+ printf("WSAStartup failed\n");
+ return 0;
+ }
+ return 1;
+}
+#endif
+
+int OpenTCPPort(const char * ip_addr, int port)
+{
+ int sockfd;
+ struct sockaddr_in server;
+ struct timeval tv;
+ fd_set myset;
+ int res, valopt;
+ socklen_t lon;
+ long arg;
+
+#if defined(_WIN32)
+ initwsa();
+#endif
+
+ //Create socket
+ sockfd = socket(AF_INET , SOCK_STREAM , IPPROTO_TCP);
+ if (sockfd == -1)
+ {
+ return -1;
+ }
+
+ // Set OFF NAGLE algorithm to reduce latency with small packets
+ /*
+ int one = 1;
+ setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (void *)&one, sizeof(one));
+ */
+
+ server.sin_addr.s_addr = inet_addr(ip_addr);
+ server.sin_family = AF_INET;
+ server.sin_port = htons(port);
+
+ // Set non-blocking when trying to establish the connection
+#if !defined(_WIN32)
+ arg = fcntl(sockfd, F_GETFL, NULL);
+ arg |= O_NONBLOCK;
+ fcntl(sockfd, F_SETFL, arg);
+#else
+ arg = 1;
+ ioctlsocket(sockfd, FIONBIO, &arg);
+#endif
+
+ res = connect(sockfd, (struct sockaddr *)&server, sizeof(server));
+
+ if (res < 0)
+ {
+ if (errno == EINPROGRESS)
+ {
+ tv.tv_sec = 5;
+ tv.tv_usec = 0;
+ FD_ZERO(&myset);
+ FD_SET(sockfd, &myset);
+ if (select(sockfd+1, NULL, &myset, NULL, &tv) > 0)
+ {
+ lon = sizeof(int);
+ getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon);
+ if (valopt)
+ {
+ return -1;
+ }
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ else
+ {
+ return -1;
+ }
+ }
+
+ // Set to blocking mode again
+#if !defined(_WIN32)
+ arg = fcntl(sockfd, F_GETFL, NULL);
+ arg &= (~O_NONBLOCK);
+ fcntl(sockfd, F_SETFL, arg);
+#else
+ arg = 0;
+ ioctlsocket(sockfd, FIONBIO, &arg);
+#endif
+
+ return sockfd;
+}
+
+// Read bytes from socket
+int PollTCPPort(int sockfd, unsigned char *buf, int size)
+{
+ int n;
+ fd_set input;
+ FD_ZERO(&input);
+ FD_SET(sockfd, &input);
+ struct timeval timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = readTimeoutMs * 1000;
+
+ n = select(sockfd + 1, &input, NULL, NULL, &timeout);
+
+ // Error or timeout
+ if (n < 1)
+ {
+ return(-1);
+ }
+ if(!FD_ISSET(sockfd, &input))
+ {
+ return(-1);
+ }
+
+ n = read(sockfd, buf, size);
+ return(n);
+}
+
+int SendTCPByte(int sockfd, unsigned char byte)
+{
+ int n;
+ n = write(sockfd, &byte, 1);
+ if(n<0)
+ return(1);
+ return(0);
+}
+
+
+int SendTCPBuf(int sockfd, unsigned char *buf, int size)
+{
+ int sent = write(sockfd, buf, size);
+ if (sent != size)
+ {
+ return sent;
+ }
+ return sent;
+}
+
+
+void CloseTCPport(int sockfd)
+{
+ close(sockfd);
+#if defined(_WIN32)
+ WSACleanup();
+#endif
+}
diff --git a/tcpclient.h b/tcpclient.h
new file mode 100644
index 0000000..ea02e42
--- /dev/null
+++ b/tcpclient.h
@@ -0,0 +1,22 @@
+#ifndef tcpclient_INCLUDED
+#define tcpclient_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//return port handle or -1 if fails
+int OpenTCPPort(const char * ip_addr, int port);
+int PollTCPPort(int, unsigned char *, int);
+int SendTCPByte(int, unsigned char);
+int SendTCPBuf(int, unsigned char *, int);
+void CloseTCPport(int);
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif
+
+