diff options
| -rw-r--r-- | SimpleMotionV2.pri | 4 | ||||
| -rw-r--r-- | busdevice.c | 168 | ||||
| -rw-r--r-- | pcserialport.c | 102 | ||||
| -rw-r--r-- | simplemotion_defs.h | 8 | ||||
| -rw-r--r-- | tcpclient.c | 189 | ||||
| -rw-r--r-- | tcpclient.h | 22 |
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 + + |
