/*
(c) 2005-2017 Teunis van Beelen <teuniz@gmail.com>
*/
#include "rs232.h"
#include <stdio.h>
#ifdef _WIN32
RS232::RS232(const char*name):hCom(0) {
char n[16];
_snprintf(n,sizeof n,"\\\\.\\%s",name);
HANDLE h = CreateFileA(n, // name is ASCII only
GENERIC_READ|GENERIC_WRITE,
0,0, // no share, no security
OPEN_EXISTING, // required for devices
0,0); // not asynchronous, no template
if (h==INVALID_HANDLE_VALUE) return;
DCB dcb;
memset(&dcb, 0, sizeof dcb);
dcb.DCBlength = sizeof dcb;
COMMTIMEOUTS to = {MAXDWORD};
static const char mode_str[] = "baud=9600 data=8 parity=n stop=1 dtr=off rts=off";
if(!BuildCommDCBAndTimeoutsA(mode_str, &dcb, &to)) {
#ifdef _DEBUG
fprintf(stderr,"> unable to apply comport settings\n");
#endif
CloseHandle(h);
return;
}
if(!SetCommState(h, &dcb)) {
#ifdef _DEBUG
fprintf(stderr,"> unable to apply comport settings\n");
#endif
CloseHandle(h);
return;
}
if(!SetCommTimeouts(h, &to)) {
#ifdef _DEBUG
fprintf(stderr,"> unable to apply comport settings\n");
#endif
CloseHandle(h);
return;
}
hCom=h; // keep handle
}
int RS232::SendByte(unsigned char byte) {
DWORD n;
if (!WriteFile(hCom, &byte, 1, &n, NULL)) return -1;
return n;
}
RS232::~RS232() {if (hCom) CloseHandle(hCom);}
void RS232::enableDTR() {EscapeCommFunction(hCom, SETDTR);}
void RS232::disableDTR() {EscapeCommFunction(hCom, CLRDTR);}
void RS232::enableRTS() {EscapeCommFunction(hCom, SETRTS);}
void RS232::disableRTS() {EscapeCommFunction(hCom, CLRRTS);}
void RS232::send_magic() {
DWORD n;
WriteFile(hCom, "1EAF", 4, &n, NULL);
}
#else // Linux & FreeBSD
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <sys/file.h>
#include <errno.h>
#include <string.h> // strerror
RS232::RS232(const char*name):hCom(0) {
char str[64];
snprintf(str,sizeof str,"/dev/%s",name);
int fd = open(str, O_RDWR|O_NOCTTY);
if (fd < 0) {
fprintf(stderr, "error, counldn't open [%s]\n", str);
return;
}
if (tcgetattr(fd, &old_termios) != 0) {
fprintf(stderr, "tcgetattr(fd, &old_termios) failed: %s\n", strerror(errno));
return;
}
termios tio;
memset(&tio, 0, sizeof tio);
tio.c_iflag = IGNPAR;
tio.c_cflag = CS8|CREAD|CLOCAL|HUPCL;
tio.c_cc[VEOF] = 4;
tio.c_cc[VMIN] = 1;
if (cfsetispeed(&tio, B9600) != 0) {
fprintf(stderr, "cfsetispeed(&new_termios, B9600) failed: %s\n", strerror(errno));
close(fd);
return;
}
if (cfsetospeed(&tio, B9600) != 0) {
fprintf(stderr, "cfsetospeed(&new_termios, B9600) failed: %s\n", strerror(errno));
close(fd);
return;
}
if (tcsetattr(fd, TCSANOW, &tio) != 0) {
fprintf(stderr, "tcsetattr(fd, TCSANOW, &new_termios) failed: %s\n", strerror(errno));
close(fd);
return;
}
hCom = fd;
}
int RS232::SendByte(unsigned char byte) {
int n = write(hCom, &byte, 1);
if (n < 0) return errno==EAGAIN ? 0 : n;
return n;
}
RS232::~RS232() {
if (!hCom) return;
tcsetattr(hCom, TCSANOW, &old_termios);
close(hCom);
}
void RS232::change_status(int a, int x) {
int status;
if(ioctl(hCom, TIOCMGET, &status) == -1) {
perror("unable to get portstatus");
}
status &= a;
status ^= x;
if(ioctl(hCom, TIOCMSET, &status) == -1) {
perror("unable to set portstatus");
}
}
void RS232::enableDTR() {
change_status(~TIOCM_DTR,TIOCM_DTR); // turn on DTR
}
void RS232::disableDTR() {
change_status(~TIOCM_DTR); // turn off DTR
}
void RS232::enableRTS() {
change_status(~TIOCM_RTS,TIOCM_RTS); // turn on RTS
}
void RS232::disableRTS() {
change_status(~TIOCM_RTS); // turn off RTS
}
void RS232::send_magic() {
write(hCom,"1EAF",4);
}
#endif
Vorgefundene Kodierung: ASCII (7 bit) | 2
|