Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Parity and Blocking Read support #3

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
4 changes: 2 additions & 2 deletions README
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
Cross-platform serial / RS232 library
Version 0.21, 11/10/2015
Version 0.22, 21/01/2019
The MIT License (MIT)

Supported platforms:
- Windows (XP / Win7, possibly 8 and 10)
- Linux
- MacOS X

Copyright (c) 2007 - 2015 Fr�d�ric Meslin
Copyright (c) 2007 - 2015 Fr�d�ric Meslin
Contact: [email protected], @marzacdev

Permission is hereby granted, free of charge, to any person obtaining a copy
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# rs232
C / C++ RS232 cross-platform serial library
Version 0.21, 11/10/2015
Version 0.22, 19/01/2019

Supported platforms:
- Windows (XP / Win7, possibly 8 and 10)
- Linux
- MacOS X

Copyright (c) 2013-2015 Fr�d�ric Meslin
Copyright (c) 2013-2015 Fr�d�ric Meslin
Email: [email protected]
Website: www.fredslab.net
Twitter: @marzacdev
95 changes: 88 additions & 7 deletions rs232-linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,20 @@
#include "rs232.h"

#include <unistd.h>
#define __USE_MISC // For CRTSCTS
#if !defined(__USE_MISC)
#define __USE_MISC // For CRTSCTS
#endif
#include <termios.h>
#include <fcntl.h>
#include <dirent.h>

#define __USE_SVID // For strdup
#if !defined(__USE_SVID)
#define __USE_SVID // For strdup
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>

/*****************************************************************************/
/** Base name for COM devices */
Expand All @@ -69,7 +74,9 @@ typedef struct {
int handle;
} COMDevice;

#define COM_MAXDEVICES 64
#if !defined(COM_MAXDEVICES)
#define COM_MAXDEVICES 64
#endif
static COMDevice comDevices[COM_MAXDEVICES];
static int noDevices = 0;

Expand Down Expand Up @@ -132,7 +139,7 @@ const char * comGetPortName(int index) {
}

/*****************************************************************************/
int comOpen(int index, int baudrate)
int comOpen(int index, int baudrate_and_parity)
{
if (index >= noDevices || index < 0)
return 0;
Expand All @@ -149,13 +156,23 @@ int comOpen(int index, int baudrate)
struct termios config;
memset(&config, 0, sizeof(config));
tcgetattr(handle, &config);
config.c_iflag &= ~(INLCR | ICRNL);
config.c_iflag &= ~(INLCR | ICRNL | IXON | IXOFF);
config.c_iflag |= IGNPAR | IGNBRK;
config.c_oflag &= ~(OPOST | ONLCR | OCRNL);
config.c_cflag &= ~(PARENB | PARODD | CSTOPB | CSIZE | CRTSCTS);
config.c_cflag |= CLOCAL | CREAD | CS8;
config.c_lflag &= ~(ICANON | ISIG | ECHO);
int flag = _BaudFlag(baudrate);
switch (baudrate_and_parity & PARITY_BITMASK)
{
case PARITY_NONE: break;
case PARITY_ODD: config.c_cflag |= PARENB|PARODD; break;
case PARITY_EVEN: config.c_cflag |= PARENB; break;
#if !defined(_DARWIN_C_SOURCE)
case PARITY_SPACE: config.c_cflag |= PARENB|CMSPAR; break;
case PARITY_MARK: config.c_cflag |= PARENB|CMSPAR|PARODD; break;
#endif
}
int flag = _BaudFlag(baudrate_and_parity & BAUDRATE_BITMASK);
cfsetospeed(&config, flag);
cfsetispeed(&config, flag);
// Timeouts configuration
Expand All @@ -176,7 +193,7 @@ void comClose(int index)
if (index >= noDevices || index < 0)
return;
COMDevice * com = &comDevices[index];
if (com->handle < 0)
if (com->handle < 0)
return;
tcdrain(com->handle);
close(com->handle);
Expand Down Expand Up @@ -214,6 +231,32 @@ int comRead(int index, char * buffer, size_t len)
return res;
}

int comReadBlocking(int index, char * buffer, size_t len, unsigned timeout)
{
fd_set set;
struct timeval to;
int rv, res;

if (index >= noDevices || index < 0)
return 0;
if (comDevices[index].handle <= 0)
return 0;

FD_ZERO(&set); /* clear the set */
FD_SET(comDevices[index].handle, &set);

to.tv_sec = timeout / 1000;
to.tv_usec = (timeout % 1000) * 1000;

rv = select(comDevices[index].handle + 1, &set, NULL, NULL, &to);
if(rv <= 0)
return 0;
res = (int) read(comDevices[index].handle, buffer, len);
if (res < 0)
res = 0;
return res;
}

/*****************************************************************************/
int _BaudFlag(int BaudRate)
{
Expand All @@ -236,6 +279,19 @@ int _BaudFlag(int BaudRate)
case 57600: return B57600; break;
case 115200: return B115200; break;
case 230400: return B230400; break;
#if defined(B500000)
case 500000: return B500000; break;
case 576000: return B576000; break;
case 921600: return B921600; break;
case 1000000: return B1000000; break;
case 1152000: return B1152000; break;
case 1500000: return B1500000; break;
case 2000000: return B2000000; break;
case 2500000: return B2500000; break;
case 3000000: return B3000000; break;
case 3500000: return B3500000; break;
case 4000000: return B4000000; break;
#endif
default : return B0; break;
}
}
Expand All @@ -258,4 +314,29 @@ void _AppendDevices(const char * base)
closedir(dirp);
}


int comSetDtr(int index, int state)
{
int cmd = state ? TIOCMBIS : TIOCMBIC;
int flag = TIOCM_DTR;
if (index >= noDevices || index < 0)
return 0;
if (comDevices[index].handle <= 0)
return 0;
return ioctl(comDevices[index].handle, cmd, &flag) != -1;
}


int comSetRts(int index, int state)
{
int cmd = state ? TIOCMBIS : TIOCMBIC;
int flag = TIOCM_RTS;
if (index >= noDevices || index < 0)
return 0;
if (comDevices[index].handle <= 0)
return 0;
return ioctl(comDevices[index].handle, cmd, &flag) != -1;
}


#endif // unix
89 changes: 75 additions & 14 deletions rs232-win.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

The MIT License (MIT)

Copyright (c) 2013-2015 Fr�d�ric Meslin, Florent Touchard
Copyright (c) 2013-2015 Fr�d�ric Meslin, Florent Touchard
Email: [email protected]
Website: www.fredslab.net
Twitter: @marzacdev
Expand Down Expand Up @@ -48,11 +48,15 @@ typedef struct {
} COMDevice;

/*****************************************************************************/
#define COM_MAXDEVICES 64
#if !defined(COM_MAXDEVICES)
#define COM_MAXDEVICES 64
#endif
static COMDevice comDevices[COM_MAXDEVICES];
static int noDevices = 0;

#define COM_MINDEVNAME 16384
#if !defined(COM_MINDEVNAME)
#define COM_MINDEVNAME 16384
#endif
const char * comPtn = "COM???";

/*****************************************************************************/
Expand Down Expand Up @@ -108,6 +112,11 @@ typedef struct _DCB {
#define OPEN_EXISTING 3
#define MAX_DWORD 0xFFFFFFFF

#define SETRTS 3
#define CLRRTS 4
#define SETDTR 5
#define CLRDTR 6

/*****************************************************************************/
/** Windows system functions */
void * __stdcall CreateFileA(const char * lpFileName, uint32_t dwDesiredAccess, uint32_t dwShareMode, void * lpSecurityAttributes, uint32_t dwCreationDisposition, uint32_t dwFlagsAndAttributes, void * hTemplateFile);
Expand All @@ -125,6 +134,7 @@ bool __stdcall GetCommTimeouts(void * hFile, COMMTIMEOUTS * lpCommTimeouts);
bool __stdcall SetCommState(void * hFile, DCB * lpDCB);
bool __stdcall SetCommTimeouts(void * hFile, COMMTIMEOUTS * lpCommTimeouts);
bool __stdcall SetupComm(void * hFile, uint32_t dwInQueue, uint32_t dwOutQueue);
bool __stdcall EscapeCommFunction(void * hFile, uint32_t dwFunc);

/*****************************************************************************/
int comEnumerate()
Expand All @@ -133,7 +143,7 @@ int comEnumerate()
size_t size = COM_MINDEVNAME;
char * list = (char *) malloc(size);
SetLastError(0);
QueryDosDeviceA(NULL, list, size);
QueryDosDeviceA(NULL, list, (uint32_t) size);
while (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
size *= 2;
char * nlist = realloc(list, size);
Expand All @@ -143,7 +153,7 @@ int comEnumerate()
}
list = nlist;
SetLastError(0);
QueryDosDeviceA(NULL, list, size);
QueryDosDeviceA(NULL, list, (uint32_t) size);
}
// Gather all COM ports
int port;
Expand Down Expand Up @@ -199,18 +209,18 @@ const char * comGetInternalName(int index)
}

/*****************************************************************************/
int comOpen(int index, int baudrate)
int comOpen(int index, int baudrate_and_parity)
{
DCB config;
COMMTIMEOUTS timeouts;
if (index < 0 || index >= noDevices)
if (index < 0 || index >= noDevices)
return 0;
// Close if already open
COMDevice * com = &comDevices[index];
if (com->handle) comClose(index);
// Open COM port
void * handle = CreateFileA(comGetInternalName(index), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (handle == INVALID_HANDLE_VALUE)
if (handle == INVALID_HANDLE_VALUE)
return 0;
com->handle = handle;
// Prepare read / write timeouts
Expand All @@ -223,14 +233,21 @@ int comOpen(int index, int baudrate)
SetCommTimeouts(handle, &timeouts);
// Prepare serial communication format
GetCommState(handle, &config);
config.BaudRate = baudrate;
config.fBinary = true;
config.fParity = 0;
config.BaudRate = baudrate_and_parity & BAUDRATE_BITMASK;
config.fBinary = 1;
config.fParity = 1;
config.fErrorChar = 0;
config.fNull = 0;
config.fAbortOnError = 0;
config.ByteSize = 8;
config.Parity = 0;
switch (baudrate_and_parity & PARITY_BITMASK)
{
case PARITY_NONE: config.Parity = 0; break;
case PARITY_ODD: config.Parity = 1; break;
case PARITY_EVEN: config.Parity = 2; break;
case PARITY_SPACE: config.Parity = 3; break;
case PARITY_MARK: config.Parity = 4; break;
}
config.StopBits = 0;
config.EvtChar = '\n';
// Set the port state
Expand Down Expand Up @@ -265,7 +282,7 @@ int comWrite(int index, const char * buffer, size_t len)
return 0;
COMDevice * com = &comDevices[index];
uint32_t bytes = 0;
WriteFile(com->handle, buffer, len, &bytes, NULL);
WriteFile(com->handle, buffer, (uint32_t) len, &bytes, NULL);
return bytes;
}

Expand All @@ -275,7 +292,34 @@ int comRead(int index, char * buffer, size_t len)
return 0;
COMDevice * com = &comDevices[index];
uint32_t bytes = 0;
ReadFile(com->handle, buffer, len, &bytes, NULL);
ReadFile(com->handle, buffer, (uint32_t) len, &bytes, NULL);
return bytes;
}

int comReadBlocking(int index, char * buffer, size_t len, unsigned timeout)
{
if (index < 0 || index >= noDevices)
return 0;
COMDevice * com = &comDevices[index];
COMMTIMEOUTS timeouts;

timeouts.ReadIntervalTimeout = MAX_DWORD;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.ReadTotalTimeoutConstant = (uint32_t) timeout;
timeouts.WriteTotalTimeoutConstant = 0;
timeouts.WriteTotalTimeoutMultiplier = 0;
SetCommTimeouts(com->handle, &timeouts);

uint32_t bytes = 0;
ReadFile(com->handle, buffer, (uint32_t) len, &bytes, NULL);

timeouts.ReadIntervalTimeout = MAX_DWORD;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.WriteTotalTimeoutConstant = 0;
timeouts.WriteTotalTimeoutMultiplier = 0;
SetCommTimeouts(com->handle, &timeouts);

return bytes;
}

Expand Down Expand Up @@ -319,4 +363,21 @@ const char * findPattern(const char * string, const char * pattern, int * value)
return sp;
}


int comSetDtr(int index, int state)
{
if (index < 0 || index >= noDevices)
return 0;
return EscapeCommFunction(comDevices[index].handle, state ? SETDTR :CLRDTR);
}


int comSetRts(int index, int state)
{
if (index < 0 || index >= noDevices)
return 0;
return EscapeCommFunction(comDevices[index].handle, state ? SETRTS :CLRRTS);
}


#endif // _WIN32
Loading