- added serial port hal
- moved hal to separate directory - added new hal cmake projectpull/72/head
parent
dc4fbd76ad
commit
2f71744079
@ -0,0 +1,107 @@
|
|||||||
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
|
||||||
|
# automagically detect if we should cross-compile
|
||||||
|
if(DEFINED ENV{TOOLCHAIN})
|
||||||
|
set(CMAKE_C_COMPILER $ENV{TOOLCHAIN}gcc)
|
||||||
|
set(CMAKE_CXX_COMPILER $ENV{TOOLCHAIN}g++)
|
||||||
|
set(CMAKE_AR "$ENV{TOOLCHAIN}ar" CACHE FILEPATH "CW archiver" FORCE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
project(hal)
|
||||||
|
|
||||||
|
set(LIBHAL_VERSION_MAJOR "2")
|
||||||
|
set(LIBHAL_VERSION_MINOR "0")
|
||||||
|
set(LIBHAL_VERSION_PATCH "0")
|
||||||
|
|
||||||
|
include_directories(
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/inc
|
||||||
|
)
|
||||||
|
|
||||||
|
set (libhal_linux_SRCS
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/socket/linux/socket_linux.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/ethernet/linux/ethernet_linux.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/thread/linux/thread_linux.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/filesystem/linux/file_provider_linux.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/time/unix/time.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/serial/linux/serial_port_linux.c
|
||||||
|
)
|
||||||
|
|
||||||
|
set (libhal_windows_SRCS
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/socket/win32/socket_win32.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/ethernet/win32/ethernet_win32.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/thread/win32/thread_win32.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/filesystem/win32/file_provider_win32.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/time/win32/time.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/serial/win32/serial_port_win32.c
|
||||||
|
)
|
||||||
|
|
||||||
|
set (libhal_bsd_SRCS
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/socket/bsd/socket_bsd.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/ethernet/bsd/ethernet_bsd.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/thread/bsd/thread_bsd.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/filesystem/linux/file_provider_linux.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/time/unix/time.c
|
||||||
|
)
|
||||||
|
|
||||||
|
IF(WIN32)
|
||||||
|
|
||||||
|
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/Lib/wpcap.lib")
|
||||||
|
message("Found winpcap -> can compile with GOOSE support")
|
||||||
|
set(WITH_WPCAP 1)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
set (libhal_SRCS
|
||||||
|
${libhal_windows_SRCS}
|
||||||
|
)
|
||||||
|
|
||||||
|
ELSEIF(UNIX)
|
||||||
|
IF(APPLE)
|
||||||
|
set (libhal_SRCS
|
||||||
|
${libhal_bsd_SRCS}
|
||||||
|
)
|
||||||
|
ELSEIF(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
||||||
|
set (libhal_SRCS
|
||||||
|
${libhal_bsd_SRCS}}
|
||||||
|
)
|
||||||
|
ELSE()
|
||||||
|
set (libhal_SRCS
|
||||||
|
${libhal_linux_SRCS}
|
||||||
|
)
|
||||||
|
ENDIF(APPLE)
|
||||||
|
ENDIF(WIN32)
|
||||||
|
|
||||||
|
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC" )
|
||||||
|
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC" )
|
||||||
|
|
||||||
|
add_library (hal STATIC ${libhal_SRCS})
|
||||||
|
|
||||||
|
add_library (hal-shared STATIC ${libhal_SRCS})
|
||||||
|
|
||||||
|
SET_TARGET_PROPERTIES(hal-shared PROPERTIES
|
||||||
|
COMPILE_FLAGS "-fPIC"
|
||||||
|
)
|
||||||
|
|
||||||
|
IF(UNIX)
|
||||||
|
IF (CONFIG_SYSTEM_HAS_CLOCK_GETTIME)
|
||||||
|
target_link_libraries (hal
|
||||||
|
-lpthread
|
||||||
|
-lrt
|
||||||
|
)
|
||||||
|
ELSE ()
|
||||||
|
target_link_libraries (hal
|
||||||
|
-lpthread
|
||||||
|
)
|
||||||
|
ENDIF (CONFIG_SYSTEM_HAS_CLOCK_GETTIME)
|
||||||
|
ENDIF(UNIX)
|
||||||
|
IF(MINGW)
|
||||||
|
target_link_libraries(hal ws2_32 iphlpapi)
|
||||||
|
ENDIF(MINGW)
|
||||||
|
|
||||||
|
iF(WITH_WPCAP)
|
||||||
|
target_link_libraries(hal
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/lib/wpcap.lib
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/lib/packet.lib
|
||||||
|
)
|
||||||
|
ENDIF(WITH_WPCAP)
|
@ -0,0 +1,277 @@
|
|||||||
|
/*
|
||||||
|
* serial_port_linux.c
|
||||||
|
*
|
||||||
|
* Copyright 2017 MZ Automation GmbH
|
||||||
|
*
|
||||||
|
* This file is part of lib60870-C
|
||||||
|
*
|
||||||
|
* lib60870-C is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* lib60870-C is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with lib60870-C. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* See COPYING file for the complete license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lib_memory.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "hal_serial.h"
|
||||||
|
#include "hal_time.h"
|
||||||
|
|
||||||
|
struct sSerialPort {
|
||||||
|
char interfaceName[100];
|
||||||
|
int fd;
|
||||||
|
int baudRate;
|
||||||
|
uint8_t dataBits;
|
||||||
|
char parity;
|
||||||
|
uint8_t stopBits;
|
||||||
|
uint64_t lastSentTime;
|
||||||
|
struct timeval timeout;
|
||||||
|
SerialPortError lastError;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
SerialPort
|
||||||
|
SerialPort_create(const char* interfaceName, int baudRate, uint8_t dataBits, char parity, uint8_t stopBits)
|
||||||
|
{
|
||||||
|
SerialPort self = (SerialPort) GLOBAL_MALLOC(sizeof(struct sSerialPort));
|
||||||
|
|
||||||
|
if (self != NULL) {
|
||||||
|
self->fd = -1;
|
||||||
|
self->baudRate = baudRate;
|
||||||
|
self->dataBits = dataBits;
|
||||||
|
self->stopBits = stopBits;
|
||||||
|
self->parity = parity;
|
||||||
|
self->lastSentTime = 0;
|
||||||
|
self->timeout.tv_sec = 0;
|
||||||
|
self->timeout.tv_usec = 100000; /* 100 ms */
|
||||||
|
strncpy(self->interfaceName, interfaceName, 100);
|
||||||
|
self->lastError = SERIAL_PORT_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SerialPort_destroy(SerialPort self)
|
||||||
|
{
|
||||||
|
if (self != NULL) {
|
||||||
|
GLOBAL_FREEMEM(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
SerialPort_open(SerialPort self)
|
||||||
|
{
|
||||||
|
self->fd = open(self->interfaceName, O_RDWR | O_NOCTTY | O_NDELAY | O_EXCL);
|
||||||
|
|
||||||
|
if (self->fd == -1) {
|
||||||
|
self->lastError = SERIAL_PORT_ERROR_OPEN_FAILED;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct termios tios;
|
||||||
|
speed_t baudrate;
|
||||||
|
|
||||||
|
tcgetattr(self->fd, &tios);
|
||||||
|
|
||||||
|
switch (self->baudRate) {
|
||||||
|
case 110:
|
||||||
|
baudrate = B110;
|
||||||
|
break;
|
||||||
|
case 300:
|
||||||
|
baudrate = B300;
|
||||||
|
break;
|
||||||
|
case 600:
|
||||||
|
baudrate = B600;
|
||||||
|
break;
|
||||||
|
case 1200:
|
||||||
|
baudrate = B1200;
|
||||||
|
break;
|
||||||
|
case 2400:
|
||||||
|
baudrate = B2400;
|
||||||
|
break;
|
||||||
|
case 4800:
|
||||||
|
baudrate = B4800;
|
||||||
|
break;
|
||||||
|
case 9600:
|
||||||
|
baudrate = B9600;
|
||||||
|
break;
|
||||||
|
case 19200:
|
||||||
|
baudrate = B19200;
|
||||||
|
break;
|
||||||
|
case 38400:
|
||||||
|
baudrate = B38400;
|
||||||
|
break;
|
||||||
|
case 57600:
|
||||||
|
baudrate = B57600;
|
||||||
|
break;
|
||||||
|
case 115200:
|
||||||
|
baudrate = B115200;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
baudrate = B9600;
|
||||||
|
self->lastError = SERIAL_PORT_ERROR_INVALID_BAUDRATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set baud rate */
|
||||||
|
if ((cfsetispeed(&tios, baudrate) < 0) || (cfsetospeed(&tios, baudrate) < 0)) {
|
||||||
|
close(self->fd);
|
||||||
|
self->fd = -1;
|
||||||
|
self->lastError = SERIAL_PORT_ERROR_INVALID_BAUDRATE;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tios.c_cflag |= (CREAD | CLOCAL);
|
||||||
|
|
||||||
|
/* Set data bits (5/6/7/8) */
|
||||||
|
tios.c_cflag &= ~CSIZE;
|
||||||
|
switch (self->dataBits) {
|
||||||
|
case 5:
|
||||||
|
tios.c_cflag |= CS5;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
tios.c_cflag |= CS6;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
tios.c_cflag |= CS7;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
default:
|
||||||
|
tios.c_cflag |= CS8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set stop bits (1/2) */
|
||||||
|
if (self->stopBits == 1)
|
||||||
|
tios.c_cflag &=~ CSTOPB;
|
||||||
|
else /* 2 */
|
||||||
|
tios.c_cflag |= CSTOPB;
|
||||||
|
|
||||||
|
if (self->parity == 'N') {
|
||||||
|
tios.c_cflag &=~ PARENB;
|
||||||
|
} else if (self->parity == 'E') {
|
||||||
|
tios.c_cflag |= PARENB;
|
||||||
|
tios.c_cflag &=~ PARODD;
|
||||||
|
} else { /* 'O' */
|
||||||
|
tios.c_cflag |= PARENB;
|
||||||
|
tios.c_cflag |= PARODD;
|
||||||
|
}
|
||||||
|
|
||||||
|
tios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
|
||||||
|
|
||||||
|
if (self->parity == 'N') {
|
||||||
|
tios.c_iflag &= ~INPCK;
|
||||||
|
} else {
|
||||||
|
tios.c_iflag |= INPCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
tios.c_iflag &= ~(IXON | IXOFF | IXANY);
|
||||||
|
tios.c_iflag |= IGNBRK; /* Set ignore break to allow 0xff characters */
|
||||||
|
tios.c_iflag |= IGNPAR;
|
||||||
|
tios.c_oflag &=~ OPOST;
|
||||||
|
|
||||||
|
tios.c_cc[VMIN] = 0;
|
||||||
|
tios.c_cc[VTIME] = 0;
|
||||||
|
|
||||||
|
if (tcsetattr(self->fd, TCSANOW, &tios) < 0) {
|
||||||
|
close(self->fd);
|
||||||
|
self->fd = -1;
|
||||||
|
self->lastError = SERIAL_PORT_ERROR_INVALID_ARGUMENT;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SerialPort_close(SerialPort self)
|
||||||
|
{
|
||||||
|
if (self->fd != -1) {
|
||||||
|
close(self->fd);
|
||||||
|
self->fd = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SerialPort_getBaudRate(SerialPort self)
|
||||||
|
{
|
||||||
|
return self->baudRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SerialPort_discardInBuffer(SerialPort self)
|
||||||
|
{
|
||||||
|
tcflush(self->fd, TCIOFLUSH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SerialPort_setTimeout(SerialPort self, int timeout)
|
||||||
|
{
|
||||||
|
self->timeout.tv_sec = timeout / 1000;
|
||||||
|
self->timeout.tv_usec = (timeout % 1000) * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
SerialPortError
|
||||||
|
SerialPort_getLastError(SerialPort self)
|
||||||
|
{
|
||||||
|
return self->lastError;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SerialPort_readByte(SerialPort self)
|
||||||
|
{
|
||||||
|
uint8_t buf[1];
|
||||||
|
fd_set set;
|
||||||
|
|
||||||
|
self->lastError = SERIAL_PORT_ERROR_NONE;
|
||||||
|
|
||||||
|
FD_ZERO(&set);
|
||||||
|
FD_SET(self->fd, &set);
|
||||||
|
|
||||||
|
int ret = select(self->fd + 1, &set, NULL, NULL, &(self->timeout));
|
||||||
|
|
||||||
|
if (ret == -1) {
|
||||||
|
self->lastError = SERIAL_PORT_ERROR_UNKNOWN;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (ret == 0)
|
||||||
|
return -1;
|
||||||
|
else {
|
||||||
|
read(self->fd, (char*) buf, 1);
|
||||||
|
|
||||||
|
return (int) buf[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SerialPort_write(SerialPort self, uint8_t* buffer, int startPos, int bufSize)
|
||||||
|
{
|
||||||
|
//TODO assure minimum line idle time
|
||||||
|
|
||||||
|
self->lastError = SERIAL_PORT_ERROR_NONE;
|
||||||
|
|
||||||
|
ssize_t result = write(self->fd, buffer + startPos, bufSize);
|
||||||
|
|
||||||
|
tcdrain(self->fd);
|
||||||
|
|
||||||
|
self->lastSentTime = Hal_getTimeInMs();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
@ -0,0 +1,283 @@
|
|||||||
|
/*
|
||||||
|
* serial_port_win32.c
|
||||||
|
*
|
||||||
|
* Copyright 2017 MZ Automation GmbH
|
||||||
|
*
|
||||||
|
* This file is part of lib60870-C
|
||||||
|
*
|
||||||
|
* lib60870-C is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* lib60870-C is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with lib60870-C. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* See COPYING file for the complete license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include "lib_memory.h"
|
||||||
|
|
||||||
|
#include "hal_serial.h"
|
||||||
|
#include "hal_time.h"
|
||||||
|
|
||||||
|
struct sSerialPort {
|
||||||
|
char interfaceName[100];
|
||||||
|
HANDLE comPort;
|
||||||
|
int baudRate;
|
||||||
|
uint8_t dataBits;
|
||||||
|
char parity;
|
||||||
|
uint8_t stopBits;
|
||||||
|
uint64_t lastSentTime;
|
||||||
|
int timeout;
|
||||||
|
SerialPortError lastError;
|
||||||
|
};
|
||||||
|
|
||||||
|
SerialPort
|
||||||
|
SerialPort_create(const char* interfaceName, int baudRate, uint8_t dataBits, char parity, uint8_t stopBits)
|
||||||
|
{
|
||||||
|
SerialPort self = (SerialPort)GLOBAL_MALLOC(sizeof(struct sSerialPort));
|
||||||
|
|
||||||
|
if (self != NULL) {
|
||||||
|
self->comPort = NULL;
|
||||||
|
self->baudRate = baudRate;
|
||||||
|
self->dataBits = dataBits;
|
||||||
|
self->stopBits = stopBits;
|
||||||
|
self->parity = parity;
|
||||||
|
self->lastSentTime = 0;
|
||||||
|
self->timeout = 100; /* 100 ms */
|
||||||
|
strncpy(self->interfaceName, interfaceName, 100);
|
||||||
|
self->lastError = SERIAL_PORT_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SerialPort_destroy(SerialPort self)
|
||||||
|
{
|
||||||
|
if (self != NULL) {
|
||||||
|
|
||||||
|
if (self->comPort != INVALID_HANDLE_VALUE)
|
||||||
|
SerialPort_close(self);
|
||||||
|
|
||||||
|
GLOBAL_FREEMEM(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
SerialPort_open(SerialPort self)
|
||||||
|
{
|
||||||
|
self->comPort = CreateFile(self->interfaceName, GENERIC_READ | GENERIC_WRITE,
|
||||||
|
0, NULL, OPEN_EXISTING, 0, NULL);
|
||||||
|
|
||||||
|
|
||||||
|
if (self->comPort == INVALID_HANDLE_VALUE) {
|
||||||
|
self->lastError = SERIAL_PORT_ERROR_OPEN_FAILED;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DCB _serialParams = { 0 };
|
||||||
|
_serialParams.DCBlength = sizeof(DCB);
|
||||||
|
|
||||||
|
LPDCB serialParams = &_serialParams;
|
||||||
|
|
||||||
|
BOOL status = GetCommState(self->comPort, serialParams);
|
||||||
|
|
||||||
|
if (status == false) {
|
||||||
|
self->lastError = SERIAL_PORT_ERROR_UNKNOWN;
|
||||||
|
goto exit_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set baud rate */
|
||||||
|
switch (self->baudRate) {
|
||||||
|
case 110:
|
||||||
|
serialParams->BaudRate = CBR_110;
|
||||||
|
break;
|
||||||
|
case 300:
|
||||||
|
serialParams->BaudRate = CBR_300;
|
||||||
|
break;
|
||||||
|
case 600:
|
||||||
|
serialParams->BaudRate = CBR_600;
|
||||||
|
break;
|
||||||
|
case 1200:
|
||||||
|
serialParams->BaudRate = CBR_1200;
|
||||||
|
break;
|
||||||
|
case 2400:
|
||||||
|
serialParams->BaudRate = CBR_2400;
|
||||||
|
break;
|
||||||
|
case 4800:
|
||||||
|
serialParams->BaudRate = CBR_4800;
|
||||||
|
break;
|
||||||
|
case 9600:
|
||||||
|
serialParams->BaudRate = CBR_9600;
|
||||||
|
break;
|
||||||
|
case 19200:
|
||||||
|
serialParams->BaudRate = CBR_19200;
|
||||||
|
break;
|
||||||
|
case 38400:
|
||||||
|
serialParams->BaudRate = CBR_38400;
|
||||||
|
break;
|
||||||
|
case 57600:
|
||||||
|
serialParams->BaudRate = CBR_57600;
|
||||||
|
break;
|
||||||
|
case 115200:
|
||||||
|
serialParams->BaudRate = CBR_115200;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
serialParams->BaudRate = CBR_9600;
|
||||||
|
self->lastError = SERIAL_PORT_ERROR_INVALID_BAUDRATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set data bits (5/6/7/8) */
|
||||||
|
serialParams->ByteSize = self->dataBits;
|
||||||
|
|
||||||
|
/* Set stop bits (1/2) */
|
||||||
|
if (self->stopBits == 1)
|
||||||
|
serialParams->StopBits = ONESTOPBIT;
|
||||||
|
else /* 2 */
|
||||||
|
serialParams->StopBits = TWOSTOPBITS;
|
||||||
|
|
||||||
|
if (self->parity == 'N')
|
||||||
|
serialParams->Parity = NOPARITY;
|
||||||
|
else if (self->parity == 'E')
|
||||||
|
serialParams->Parity = EVENPARITY;
|
||||||
|
else /* 'O' */
|
||||||
|
serialParams->Parity = ODDPARITY;
|
||||||
|
|
||||||
|
status = SetCommState(self->comPort, serialParams);
|
||||||
|
|
||||||
|
if (status == false) {
|
||||||
|
self->lastError = SERIAL_PORT_ERROR_INVALID_ARGUMENT;
|
||||||
|
goto exit_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
COMMTIMEOUTS timeouts = { 0 };
|
||||||
|
|
||||||
|
timeouts.ReadIntervalTimeout = 100;
|
||||||
|
timeouts.ReadTotalTimeoutConstant = 50;
|
||||||
|
timeouts.ReadTotalTimeoutMultiplier = 10;
|
||||||
|
timeouts.WriteTotalTimeoutConstant = 100;
|
||||||
|
timeouts.WriteTotalTimeoutMultiplier = 10;
|
||||||
|
|
||||||
|
status = SetCommTimeouts(self->comPort, &timeouts);
|
||||||
|
|
||||||
|
if (status == false) {
|
||||||
|
self->lastError = SERIAL_PORT_ERROR_UNKNOWN;
|
||||||
|
goto exit_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = SetCommMask(self->comPort, EV_RXCHAR);
|
||||||
|
|
||||||
|
if (status == false) {
|
||||||
|
printf("SetCommMask failed!\n");
|
||||||
|
self->lastError = SERIAL_PORT_ERROR_UNKNOWN;
|
||||||
|
goto exit_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->lastError = SERIAL_PORT_ERROR_NONE;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
exit_error:
|
||||||
|
|
||||||
|
if (self->comPort != INVALID_HANDLE_VALUE) {
|
||||||
|
CloseHandle(self->comPort);
|
||||||
|
self->comPort = INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SerialPort_close(SerialPort self)
|
||||||
|
{
|
||||||
|
if (self->comPort != INVALID_HANDLE_VALUE) {
|
||||||
|
CloseHandle(self->comPort);
|
||||||
|
self->comPort = INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SerialPort_getBaudRate(SerialPort self)
|
||||||
|
{
|
||||||
|
return self->baudRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SerialPort_discardInBuffer(SerialPort self)
|
||||||
|
{
|
||||||
|
PurgeComm(self->comPort, PURGE_RXCLEAR | PURGE_TXCLEAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SerialPort_setTimeout(SerialPort self, int timeout)
|
||||||
|
{
|
||||||
|
self->timeout = timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
SerialPortError
|
||||||
|
SerialPort_getLastError(SerialPort self)
|
||||||
|
{
|
||||||
|
return self->lastError;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SerialPort_readByte(SerialPort self)
|
||||||
|
{
|
||||||
|
uint8_t buf[1];
|
||||||
|
|
||||||
|
DWORD bytesRead = 0;
|
||||||
|
|
||||||
|
BOOL status = ReadFile(self->comPort, buf, 1, &bytesRead, NULL);
|
||||||
|
|
||||||
|
if (status == false) {
|
||||||
|
self->lastError = SERIAL_PORT_ERROR_UNKNOWN;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->lastError = SERIAL_PORT_ERROR_NONE;
|
||||||
|
|
||||||
|
if (bytesRead == 0)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return (int) buf[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SerialPort_write(SerialPort self, uint8_t* buffer, int startPos, int bufSize)
|
||||||
|
{
|
||||||
|
//TODO assure minimum line idle time
|
||||||
|
|
||||||
|
self->lastError = SERIAL_PORT_ERROR_NONE;
|
||||||
|
|
||||||
|
DWORD numberOfBytesWritten;
|
||||||
|
|
||||||
|
BOOL status = WriteFile(self->comPort, buffer + startPos, bufSize, &numberOfBytesWritten, NULL);
|
||||||
|
|
||||||
|
if (status == false) {
|
||||||
|
self->lastError = SERIAL_PORT_ERROR_UNKNOWN;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = FlushFileBuffers(self->comPort);
|
||||||
|
|
||||||
|
if (status == false) {
|
||||||
|
printf("FlushFileBuffers failed!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
self->lastSentTime = Hal_getTimeInMs();
|
||||||
|
|
||||||
|
return (int) numberOfBytesWritten;
|
||||||
|
}
|
Loading…
Reference in New Issue