Source file: /~heha/hsn/bl/hid-flash.zip/src/rs232.cpp

/*
 (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
Detected encoding: ASCII (7 bit)2