mirror of
				https://github.com/Telecominfraproject/wlan-ap.git
				synced 2025-10-30 01:52:51 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			880 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			880 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /*
 | |
| ***************************************************************************
 | |
| *
 | |
| * Author: Teunis van Beelen
 | |
| *
 | |
| * Copyright (C) 2005 - 2021 Teunis van Beelen
 | |
| *
 | |
| * Email: teuniz@protonmail.com
 | |
| *
 | |
| ***************************************************************************
 | |
| *
 | |
| * This program 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.
 | |
| *
 | |
| * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 | |
| *
 | |
| ***************************************************************************
 | |
| */
 | |
| 
 | |
| 
 | |
| /* Last revision: February 9, 2021 */
 | |
| /* For more info and how to use this library, visit: http://www.teuniz.net/RS-232/ */
 | |
| 
 | |
| 
 | |
| #include "rs232.h"
 | |
| 
 | |
| 
 | |
| #if defined(__linux__) || defined(__FreeBSD__)   /* Linux & FreeBSD */
 | |
| 
 | |
| #define RS232_PORTNR  40
 | |
| 
 | |
| 
 | |
| int Cport[RS232_PORTNR],
 | |
|     error;
 | |
| 
 | |
| struct termios new_port_settings,
 | |
|        old_port_settings[RS232_PORTNR];
 | |
| 
 | |
| const char *comports[RS232_PORTNR]={"/dev/ttyS0","/dev/ttyS1","/dev/ttyS2","/dev/ttyS3","/dev/ttyS4","/dev/ttyS5",
 | |
|                                     "/dev/ttyS6","/dev/ttyS7","/dev/ttyS8","/dev/ttyS9","/dev/ttyS10","/dev/ttyS11",
 | |
|                                     "/dev/ttyS12","/dev/ttyS13","/dev/ttyS14","/dev/ttyS15","/dev/ttyUSB0",
 | |
|                                     "/dev/ttyUSB1","/dev/ttyUSB2","/dev/ttyUSB3","/dev/ttyUSB4","/dev/ttyUSB5",
 | |
|                                     "/dev/ttyAMA0","/dev/ttyAMA1","/dev/ttyACM0","/dev/ttyACM1",
 | |
|                                     "/dev/rfcomm0","/dev/rfcomm1","/dev/ircomm0","/dev/ircomm1",
 | |
|                                     "/dev/cuau0","/dev/cuau1","/dev/cuau2","/dev/cuau3",
 | |
|                                     "/dev/cuaU0","/dev/cuaU1","/dev/cuaU2","/dev/cuaU3",
 | |
|                                     "/dev/ttyMSM0","/dev/ttyMSM1"};
 | |
| int RS232_OpenComport(int comport_number, int baudrate, const char *mode, int flowctrl)
 | |
| {
 | |
|   int baudr,
 | |
|       status;
 | |
| 
 | |
|   if((comport_number>=RS232_PORTNR)||(comport_number<0))
 | |
|   {
 | |
|     printf("illegal comport number\n");
 | |
|     return(1);
 | |
|   }
 | |
| 
 | |
|   switch(baudrate)
 | |
|   {
 | |
|     case      50 : baudr = B50;
 | |
|                    break;
 | |
|     case      75 : baudr = B75;
 | |
|                    break;
 | |
|     case     110 : baudr = B110;
 | |
|                    break;
 | |
|     case     134 : baudr = B134;
 | |
|                    break;
 | |
|     case     150 : baudr = B150;
 | |
|                    break;
 | |
|     case     200 : baudr = B200;
 | |
|                    break;
 | |
|     case     300 : baudr = B300;
 | |
|                    break;
 | |
|     case     600 : baudr = B600;
 | |
|                    break;
 | |
|     case    1200 : baudr = B1200;
 | |
|                    break;
 | |
|     case    1800 : baudr = B1800;
 | |
|                    break;
 | |
|     case    2400 : baudr = B2400;
 | |
|                    break;
 | |
|     case    4800 : baudr = B4800;
 | |
|                    break;
 | |
|     case    9600 : baudr = B9600;
 | |
|                    break;
 | |
|     case   19200 : baudr = B19200;
 | |
|                    break;
 | |
|     case   38400 : baudr = B38400;
 | |
|                    break;
 | |
|     case   57600 : baudr = B57600;
 | |
|                    break;
 | |
|     case  115200 : baudr = B115200;
 | |
|                    break;
 | |
|     case  230400 : baudr = B230400;
 | |
|                    break;
 | |
|     case  460800 : baudr = B460800;
 | |
|                    break;
 | |
| #if defined(__linux__)
 | |
|     case  500000 : baudr = B500000;
 | |
|                    break;
 | |
|     case  576000 : baudr = B576000;
 | |
|                    break;
 | |
|     case  921600 : baudr = B921600;
 | |
|                    break;
 | |
|     case 1000000 : baudr = B1000000;
 | |
|                    break;
 | |
|     case 1152000 : baudr = B1152000;
 | |
|                    break;
 | |
|     case 1500000 : baudr = B1500000;
 | |
|                    break;
 | |
|     case 2000000 : baudr = B2000000;
 | |
|                    break;
 | |
|     case 2500000 : baudr = B2500000;
 | |
|                    break;
 | |
|     case 3000000 : baudr = B3000000;
 | |
|                    break;
 | |
|     case 3500000 : baudr = B3500000;
 | |
|                    break;
 | |
|     case 4000000 : baudr = B4000000;
 | |
|                    break;
 | |
| #endif
 | |
|     default      : printf("invalid baudrate\n");
 | |
|                    return(1);
 | |
|                    break;
 | |
|   }
 | |
| 
 | |
|   int cbits=CS8,
 | |
|       cpar=0,
 | |
|       ipar=IGNPAR,
 | |
|       bstop=0;
 | |
| 
 | |
|   if(strlen(mode) != 3)
 | |
|   {
 | |
|     printf("invalid mode \"%s\"\n", mode);
 | |
|     return(1);
 | |
|   }
 | |
| 
 | |
|   switch(mode[0])
 | |
|   {
 | |
|     case '8': cbits = CS8;
 | |
|               break;
 | |
|     case '7': cbits = CS7;
 | |
|               break;
 | |
|     case '6': cbits = CS6;
 | |
|               break;
 | |
|     case '5': cbits = CS5;
 | |
|               break;
 | |
|     default : printf("invalid number of data-bits '%c'\n", mode[0]);
 | |
|               return(1);
 | |
|               break;
 | |
|   }
 | |
| 
 | |
|   switch(mode[1])
 | |
|   {
 | |
|     case 'N':
 | |
|     case 'n': cpar = 0;
 | |
|               ipar = IGNPAR;
 | |
|               break;
 | |
|     case 'E':
 | |
|     case 'e': cpar = PARENB;
 | |
|               ipar = INPCK;
 | |
|               break;
 | |
|     case 'O':
 | |
|     case 'o': cpar = (PARENB | PARODD);
 | |
|               ipar = INPCK;
 | |
|               break;
 | |
|     default : printf("invalid parity '%c'\n", mode[1]);
 | |
|               return(1);
 | |
|               break;
 | |
|   }
 | |
| 
 | |
|   switch(mode[2])
 | |
|   {
 | |
|     case '1': bstop = 0;
 | |
|               break;
 | |
|     case '2': bstop = CSTOPB;
 | |
|               break;
 | |
|     default : printf("invalid number of stop bits '%c'\n", mode[2]);
 | |
|               return(1);
 | |
|               break;
 | |
|   }
 | |
| 
 | |
| /*
 | |
| http://pubs.opengroup.org/onlinepubs/7908799/xsh/termios.h.html
 | |
| 
 | |
| http://man7.org/linux/man-pages/man3/termios.3.html
 | |
| */
 | |
| 
 | |
|   Cport[comport_number] = open(comports[comport_number], O_RDWR | O_NOCTTY | O_NDELAY);
 | |
|   if(Cport[comport_number]==-1)
 | |
|   {
 | |
|     perror("unable to open comport ");
 | |
|     return(1);
 | |
|   }
 | |
| 
 | |
|   /* lock access so that another process can't also use the port */
 | |
|   if(flock(Cport[comport_number], LOCK_EX | LOCK_NB) != 0)
 | |
|   {
 | |
|     close(Cport[comport_number]);
 | |
|     perror("Another process has locked the comport.");
 | |
|     return(1);
 | |
|   }
 | |
| 
 | |
|   error = tcgetattr(Cport[comport_number], old_port_settings + comport_number);
 | |
|   if(error==-1)
 | |
|   {
 | |
|     close(Cport[comport_number]);
 | |
|     flock(Cport[comport_number], LOCK_UN);  /* free the port so that others can use it. */
 | |
|     perror("unable to read portsettings ");
 | |
|     return(1);
 | |
|   }
 | |
|   memset(&new_port_settings, 0, sizeof(new_port_settings));  /* clear the new struct */
 | |
| 
 | |
|   new_port_settings.c_cflag = cbits | cpar | bstop | CLOCAL | CREAD;
 | |
|   if(flowctrl)
 | |
|   {
 | |
|     new_port_settings.c_cflag |= CRTSCTS;
 | |
|   }
 | |
|   new_port_settings.c_iflag = ipar;
 | |
|   new_port_settings.c_oflag = 0;
 | |
|   new_port_settings.c_lflag = 0;
 | |
|   new_port_settings.c_cc[VMIN] = 0;      /* block untill n bytes are received */
 | |
|   new_port_settings.c_cc[VTIME] = 0;     /* block untill a timer expires (n * 100 mSec.) */
 | |
| 
 | |
|   cfsetispeed(&new_port_settings, baudr);
 | |
|   cfsetospeed(&new_port_settings, baudr);
 | |
| 
 | |
|   error = tcsetattr(Cport[comport_number], TCSANOW, &new_port_settings);
 | |
|   if(error==-1)
 | |
|   {
 | |
|     tcsetattr(Cport[comport_number], TCSANOW, old_port_settings + comport_number);
 | |
|     close(Cport[comport_number]);
 | |
|     flock(Cport[comport_number], LOCK_UN);  /* free the port so that others can use it. */
 | |
|     perror("unable to adjust portsettings ");
 | |
|     return(1);
 | |
|   }
 | |
| 
 | |
| /* http://man7.org/linux/man-pages/man4/tty_ioctl.4.html */
 | |
| 
 | |
|   if(ioctl(Cport[comport_number], TIOCMGET, &status) == -1)
 | |
|   {
 | |
|     tcsetattr(Cport[comport_number], TCSANOW, old_port_settings + comport_number);
 | |
|     flock(Cport[comport_number], LOCK_UN);  /* free the port so that others can use it. */
 | |
|     perror("unable to get portstatus");
 | |
|     return(1);
 | |
|   }
 | |
| 
 | |
|   status |= TIOCM_DTR;    /* turn on DTR */
 | |
|   status |= TIOCM_RTS;    /* turn on RTS */
 | |
| 
 | |
|   if(ioctl(Cport[comport_number], TIOCMSET, &status) == -1)
 | |
|   {
 | |
|     tcsetattr(Cport[comport_number], TCSANOW, old_port_settings + comport_number);
 | |
|     flock(Cport[comport_number], LOCK_UN);  /* free the port so that others can use it. */
 | |
|     perror("unable to set portstatus");
 | |
|     return(1);
 | |
|   }
 | |
| 
 | |
|   return(0);
 | |
| }
 | |
| 
 | |
| 
 | |
| int RS232_PollComport(int comport_number, unsigned char *buf, int size)
 | |
| {
 | |
|   int n;
 | |
| 
 | |
|   n = read(Cport[comport_number], buf, size);
 | |
| 
 | |
|   if(n < 0)
 | |
|   {
 | |
|     if(errno == EAGAIN)  return 0;
 | |
|   }
 | |
| 
 | |
|   return(n);
 | |
| }
 | |
| 
 | |
| 
 | |
| int RS232_SendByte(int comport_number, unsigned char byte)
 | |
| {
 | |
|   int n = write(Cport[comport_number], &byte, 1);
 | |
|   if(n < 0)
 | |
|   {
 | |
|     if(errno == EAGAIN)
 | |
|     {
 | |
|       return 0;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       return 1;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return(0);
 | |
| }
 | |
| 
 | |
| 
 | |
| int RS232_SendBuf(int comport_number, unsigned char *buf, int size)
 | |
| {
 | |
|   int n = write(Cport[comport_number], buf, size);
 | |
|   if(n < 0)
 | |
|   {
 | |
|     if(errno == EAGAIN)
 | |
|     {
 | |
|       return 0;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       return -1;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return(n);
 | |
| }
 | |
| 
 | |
| 
 | |
| void RS232_CloseComport(int comport_number)
 | |
| {
 | |
|   int status;
 | |
| 
 | |
|   if(ioctl(Cport[comport_number], TIOCMGET, &status) == -1)
 | |
|   {
 | |
|     perror("unable to get portstatus");
 | |
|   }
 | |
| 
 | |
|   status &= ~TIOCM_DTR;    /* turn off DTR */
 | |
|   status &= ~TIOCM_RTS;    /* turn off RTS */
 | |
| 
 | |
|   if(ioctl(Cport[comport_number], TIOCMSET, &status) == -1)
 | |
|   {
 | |
|     perror("unable to set portstatus");
 | |
|   }
 | |
| 
 | |
|   tcsetattr(Cport[comport_number], TCSANOW, old_port_settings + comport_number);
 | |
|   close(Cport[comport_number]);
 | |
| 
 | |
|   flock(Cport[comport_number], LOCK_UN);  /* free the port so that others can use it. */
 | |
| }
 | |
| 
 | |
| /*
 | |
| Constant  Description
 | |
| TIOCM_LE        DSR (data set ready/line enable)
 | |
| TIOCM_DTR       DTR (data terminal ready)
 | |
| TIOCM_RTS       RTS (request to send)
 | |
| TIOCM_ST        Secondary TXD (transmit)
 | |
| TIOCM_SR        Secondary RXD (receive)
 | |
| TIOCM_CTS       CTS (clear to send)
 | |
| TIOCM_CAR       DCD (data carrier detect)
 | |
| TIOCM_CD        see TIOCM_CAR
 | |
| TIOCM_RNG       RNG (ring)
 | |
| TIOCM_RI        see TIOCM_RNG
 | |
| TIOCM_DSR       DSR (data set ready)
 | |
| 
 | |
| http://man7.org/linux/man-pages/man4/tty_ioctl.4.html
 | |
| */
 | |
| 
 | |
| int RS232_IsDCDEnabled(int comport_number)
 | |
| {
 | |
|   int status;
 | |
| 
 | |
|   ioctl(Cport[comport_number], TIOCMGET, &status);
 | |
| 
 | |
|   if(status&TIOCM_CAR) return(1);
 | |
|   else return(0);
 | |
| }
 | |
| 
 | |
| 
 | |
| int RS232_IsRINGEnabled(int comport_number)
 | |
| {
 | |
|   int status;
 | |
| 
 | |
|   ioctl(Cport[comport_number], TIOCMGET, &status);
 | |
| 
 | |
|   if(status&TIOCM_RNG) return(1);
 | |
|   else return(0);
 | |
| }
 | |
| 
 | |
| 
 | |
| int RS232_IsCTSEnabled(int comport_number)
 | |
| {
 | |
|   int status;
 | |
| 
 | |
|   ioctl(Cport[comport_number], TIOCMGET, &status);
 | |
| 
 | |
|   if(status&TIOCM_CTS) return(1);
 | |
|   else return(0);
 | |
| }
 | |
| 
 | |
| 
 | |
| int RS232_IsDSREnabled(int comport_number)
 | |
| {
 | |
|   int status;
 | |
| 
 | |
|   ioctl(Cport[comport_number], TIOCMGET, &status);
 | |
| 
 | |
|   if(status&TIOCM_DSR) return(1);
 | |
|   else return(0);
 | |
| }
 | |
| 
 | |
| 
 | |
| void RS232_enableDTR(int comport_number)
 | |
| {
 | |
|   int status;
 | |
| 
 | |
|   if(ioctl(Cport[comport_number], TIOCMGET, &status) == -1)
 | |
|   {
 | |
|     perror("unable to get portstatus");
 | |
|   }
 | |
| 
 | |
|   status |= TIOCM_DTR;    /* turn on DTR */
 | |
| 
 | |
|   if(ioctl(Cport[comport_number], TIOCMSET, &status) == -1)
 | |
|   {
 | |
|     perror("unable to set portstatus");
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| void RS232_disableDTR(int comport_number)
 | |
| {
 | |
|   int status;
 | |
| 
 | |
|   if(ioctl(Cport[comport_number], TIOCMGET, &status) == -1)
 | |
|   {
 | |
|     perror("unable to get portstatus");
 | |
|   }
 | |
| 
 | |
|   status &= ~TIOCM_DTR;    /* turn off DTR */
 | |
| 
 | |
|   if(ioctl(Cport[comport_number], TIOCMSET, &status) == -1)
 | |
|   {
 | |
|     perror("unable to set portstatus");
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| void RS232_enableRTS(int comport_number)
 | |
| {
 | |
|   int status;
 | |
| 
 | |
|   if(ioctl(Cport[comport_number], TIOCMGET, &status) == -1)
 | |
|   {
 | |
|     perror("unable to get portstatus");
 | |
|   }
 | |
| 
 | |
|   status |= TIOCM_RTS;    /* turn on RTS */
 | |
| 
 | |
|   if(ioctl(Cport[comport_number], TIOCMSET, &status) == -1)
 | |
|   {
 | |
|     perror("unable to set portstatus");
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| void RS232_disableRTS(int comport_number)
 | |
| {
 | |
|   int status;
 | |
| 
 | |
|   if(ioctl(Cport[comport_number], TIOCMGET, &status) == -1)
 | |
|   {
 | |
|     perror("unable to get portstatus");
 | |
|   }
 | |
| 
 | |
|   status &= ~TIOCM_RTS;    /* turn off RTS */
 | |
| 
 | |
|   if(ioctl(Cport[comport_number], TIOCMSET, &status) == -1)
 | |
|   {
 | |
|     perror("unable to set portstatus");
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| void RS232_flushRX(int comport_number)
 | |
| {
 | |
|   tcflush(Cport[comport_number], TCIFLUSH);
 | |
| }
 | |
| 
 | |
| 
 | |
| void RS232_flushTX(int comport_number)
 | |
| {
 | |
|   tcflush(Cport[comport_number], TCOFLUSH);
 | |
| }
 | |
| 
 | |
| 
 | |
| void RS232_flushRXTX(int comport_number)
 | |
| {
 | |
|   tcflush(Cport[comport_number], TCIOFLUSH);
 | |
| }
 | |
| 
 | |
| 
 | |
| #else  /* windows */
 | |
| 
 | |
| #define RS232_PORTNR  32
 | |
| 
 | |
| HANDLE Cport[RS232_PORTNR];
 | |
| 
 | |
| 
 | |
| const char *comports[RS232_PORTNR]={"\\\\.\\COM1",  "\\\\.\\COM2",  "\\\\.\\COM3",  "\\\\.\\COM4",
 | |
|                                     "\\\\.\\COM5",  "\\\\.\\COM6",  "\\\\.\\COM7",  "\\\\.\\COM8",
 | |
|                                     "\\\\.\\COM9",  "\\\\.\\COM10", "\\\\.\\COM11", "\\\\.\\COM12",
 | |
|                                     "\\\\.\\COM13", "\\\\.\\COM14", "\\\\.\\COM15", "\\\\.\\COM16",
 | |
|                                     "\\\\.\\COM17", "\\\\.\\COM18", "\\\\.\\COM19", "\\\\.\\COM20",
 | |
|                                     "\\\\.\\COM21", "\\\\.\\COM22", "\\\\.\\COM23", "\\\\.\\COM24",
 | |
|                                     "\\\\.\\COM25", "\\\\.\\COM26", "\\\\.\\COM27", "\\\\.\\COM28",
 | |
|                                     "\\\\.\\COM29", "\\\\.\\COM30", "\\\\.\\COM31", "\\\\.\\COM32"};
 | |
| 
 | |
| char mode_str[128];
 | |
| 
 | |
| 
 | |
| int RS232_OpenComport(int comport_number, int baudrate, const char *mode, int flowctrl)
 | |
| {
 | |
|   if((comport_number>=RS232_PORTNR)||(comport_number<0))
 | |
|   {
 | |
|     printf("illegal comport number\n");
 | |
|     return(1);
 | |
|   }
 | |
| 
 | |
|   switch(baudrate)
 | |
|   {
 | |
|     case     110 : strcpy(mode_str, "baud=110");
 | |
|                    break;
 | |
|     case     300 : strcpy(mode_str, "baud=300");
 | |
|                    break;
 | |
|     case     600 : strcpy(mode_str, "baud=600");
 | |
|                    break;
 | |
|     case    1200 : strcpy(mode_str, "baud=1200");
 | |
|                    break;
 | |
|     case    2400 : strcpy(mode_str, "baud=2400");
 | |
|                    break;
 | |
|     case    4800 : strcpy(mode_str, "baud=4800");
 | |
|                    break;
 | |
|     case    9600 : strcpy(mode_str, "baud=9600");
 | |
|                    break;
 | |
|     case   19200 : strcpy(mode_str, "baud=19200");
 | |
|                    break;
 | |
|     case   38400 : strcpy(mode_str, "baud=38400");
 | |
|                    break;
 | |
|     case   57600 : strcpy(mode_str, "baud=57600");
 | |
|                    break;
 | |
|     case  115200 : strcpy(mode_str, "baud=115200");
 | |
|                    break;
 | |
|     case  128000 : strcpy(mode_str, "baud=128000");
 | |
|                    break;
 | |
|     case  256000 : strcpy(mode_str, "baud=256000");
 | |
|                    break;
 | |
|     case  500000 : strcpy(mode_str, "baud=500000");
 | |
|                    break;
 | |
|     case  921600 : strcpy(mode_str, "baud=921600");
 | |
|                    break;
 | |
|     case 1000000 : strcpy(mode_str, "baud=1000000");
 | |
|                    break;
 | |
|     case 1500000 : strcpy(mode_str, "baud=1500000");
 | |
|                    break;
 | |
|     case 2000000 : strcpy(mode_str, "baud=2000000");
 | |
|                    break;
 | |
|     case 3000000 : strcpy(mode_str, "baud=3000000");
 | |
|                    break;
 | |
|     default      : printf("invalid baudrate\n");
 | |
|                    return(1);
 | |
|                    break;
 | |
|   }
 | |
| 
 | |
|   if(strlen(mode) != 3)
 | |
|   {
 | |
|     printf("invalid mode \"%s\"\n", mode);
 | |
|     return(1);
 | |
|   }
 | |
| 
 | |
|   switch(mode[0])
 | |
|   {
 | |
|     case '8': strcat(mode_str, " data=8");
 | |
|               break;
 | |
|     case '7': strcat(mode_str, " data=7");
 | |
|               break;
 | |
|     case '6': strcat(mode_str, " data=6");
 | |
|               break;
 | |
|     case '5': strcat(mode_str, " data=5");
 | |
|               break;
 | |
|     default : printf("invalid number of data-bits '%c'\n", mode[0]);
 | |
|               return(1);
 | |
|               break;
 | |
|   }
 | |
| 
 | |
|   switch(mode[1])
 | |
|   {
 | |
|     case 'N':
 | |
|     case 'n': strcat(mode_str, " parity=n");
 | |
|               break;
 | |
|     case 'E':
 | |
|     case 'e': strcat(mode_str, " parity=e");
 | |
|               break;
 | |
|     case 'O':
 | |
|     case 'o': strcat(mode_str, " parity=o");
 | |
|               break;
 | |
|     default : printf("invalid parity '%c'\n", mode[1]);
 | |
|               return(1);
 | |
|               break;
 | |
|   }
 | |
| 
 | |
|   switch(mode[2])
 | |
|   {
 | |
|     case '1': strcat(mode_str, " stop=1");
 | |
|               break;
 | |
|     case '2': strcat(mode_str, " stop=2");
 | |
|               break;
 | |
|     default : printf("invalid number of stop bits '%c'\n", mode[2]);
 | |
|               return(1);
 | |
|               break;
 | |
|   }
 | |
| 
 | |
|   if(flowctrl)
 | |
|   {
 | |
|     strcat(mode_str, " xon=off to=off odsr=off dtr=on rts=off");
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     strcat(mode_str, " xon=off to=off odsr=off dtr=on rts=on");
 | |
|   }
 | |
| 
 | |
| /*
 | |
| http://msdn.microsoft.com/en-us/library/windows/desktop/aa363145%28v=vs.85%29.aspx
 | |
| 
 | |
| http://technet.microsoft.com/en-us/library/cc732236.aspx
 | |
| 
 | |
| https://docs.microsoft.com/en-us/windows/desktop/api/winbase/ns-winbase-_dcb
 | |
| */
 | |
| 
 | |
|   Cport[comport_number] = CreateFileA(comports[comport_number],
 | |
|                       GENERIC_READ|GENERIC_WRITE,
 | |
|                       0,                          /* no share  */
 | |
|                       NULL,                       /* no security */
 | |
|                       OPEN_EXISTING,
 | |
|                       0,                          /* no threads */
 | |
|                       NULL);                      /* no templates */
 | |
| 
 | |
|   if(Cport[comport_number]==INVALID_HANDLE_VALUE)
 | |
|   {
 | |
|     printf("unable to open comport\n");
 | |
|     return(1);
 | |
|   }
 | |
| 
 | |
|   DCB port_settings;
 | |
|   memset(&port_settings, 0, sizeof(port_settings));  /* clear the new struct  */
 | |
|   port_settings.DCBlength = sizeof(port_settings);
 | |
| 
 | |
|   if(!BuildCommDCBA(mode_str, &port_settings))
 | |
|   {
 | |
|     printf("unable to set comport dcb settings\n");
 | |
|     CloseHandle(Cport[comport_number]);
 | |
|     return(1);
 | |
|   }
 | |
| 
 | |
|   if(flowctrl)
 | |
|   {
 | |
|     port_settings.fOutxCtsFlow = TRUE;
 | |
|     port_settings.fRtsControl = RTS_CONTROL_HANDSHAKE;
 | |
|   }
 | |
| 
 | |
|   if(!SetCommState(Cport[comport_number], &port_settings))
 | |
|   {
 | |
|     printf("unable to set comport cfg settings\n");
 | |
|     CloseHandle(Cport[comport_number]);
 | |
|     return(1);
 | |
|   }
 | |
| 
 | |
|   COMMTIMEOUTS Cptimeouts;
 | |
| 
 | |
|   Cptimeouts.ReadIntervalTimeout         = MAXDWORD;
 | |
|   Cptimeouts.ReadTotalTimeoutMultiplier  = 0;
 | |
|   Cptimeouts.ReadTotalTimeoutConstant    = 0;
 | |
|   Cptimeouts.WriteTotalTimeoutMultiplier = 0;
 | |
|   Cptimeouts.WriteTotalTimeoutConstant   = 0;
 | |
| 
 | |
|   if(!SetCommTimeouts(Cport[comport_number], &Cptimeouts))
 | |
|   {
 | |
|     printf("unable to set comport time-out settings\n");
 | |
|     CloseHandle(Cport[comport_number]);
 | |
|     return(1);
 | |
|   }
 | |
| 
 | |
|   return(0);
 | |
| }
 | |
| 
 | |
| 
 | |
| int RS232_PollComport(int comport_number, unsigned char *buf, int size)
 | |
| {
 | |
|   int n;
 | |
| 
 | |
| /* added the void pointer cast, otherwise gcc will complain about */
 | |
| /* "warning: dereferencing type-punned pointer will break strict aliasing rules" */
 | |
| 
 | |
|   if(!ReadFile(Cport[comport_number], buf, size, (LPDWORD)((void *)&n), NULL))
 | |
|   {
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   return(n);
 | |
| }
 | |
| 
 | |
| 
 | |
| int RS232_SendByte(int comport_number, unsigned char byte)
 | |
| {
 | |
|   int n;
 | |
| 
 | |
|   if(!WriteFile(Cport[comport_number], &byte, 1, (LPDWORD)((void *)&n), NULL))
 | |
|   {
 | |
|     return(1);
 | |
|   }
 | |
| 
 | |
|   if(n<0)  return(1);
 | |
| 
 | |
|   return(0);
 | |
| }
 | |
| 
 | |
| 
 | |
| int RS232_SendBuf(int comport_number, unsigned char *buf, int size)
 | |
| {
 | |
|   int n;
 | |
| 
 | |
|   if(WriteFile(Cport[comport_number], buf, size, (LPDWORD)((void *)&n), NULL))
 | |
|   {
 | |
|     return(n);
 | |
|   }
 | |
| 
 | |
|   return(-1);
 | |
| }
 | |
| 
 | |
| 
 | |
| void RS232_CloseComport(int comport_number)
 | |
| {
 | |
|   CloseHandle(Cport[comport_number]);
 | |
| }
 | |
| 
 | |
| /*
 | |
| http://msdn.microsoft.com/en-us/library/windows/desktop/aa363258%28v=vs.85%29.aspx
 | |
| */
 | |
| 
 | |
| int RS232_IsDCDEnabled(int comport_number)
 | |
| {
 | |
|   int status;
 | |
| 
 | |
|   GetCommModemStatus(Cport[comport_number], (LPDWORD)((void *)&status));
 | |
| 
 | |
|   if(status&MS_RLSD_ON) return(1);
 | |
|   else return(0);
 | |
| }
 | |
| 
 | |
| 
 | |
| int RS232_IsRINGEnabled(int comport_number)
 | |
| {
 | |
|   int status;
 | |
| 
 | |
|   GetCommModemStatus(Cport[comport_number], (LPDWORD)((void *)&status));
 | |
| 
 | |
|   if(status&MS_RING_ON) return(1);
 | |
|   else return(0);
 | |
| }
 | |
| 
 | |
| 
 | |
| int RS232_IsCTSEnabled(int comport_number)
 | |
| {
 | |
|   int status;
 | |
| 
 | |
|   GetCommModemStatus(Cport[comport_number], (LPDWORD)((void *)&status));
 | |
| 
 | |
|   if(status&MS_CTS_ON) return(1);
 | |
|   else return(0);
 | |
| }
 | |
| 
 | |
| 
 | |
| int RS232_IsDSREnabled(int comport_number)
 | |
| {
 | |
|   int status;
 | |
| 
 | |
|   GetCommModemStatus(Cport[comport_number], (LPDWORD)((void *)&status));
 | |
| 
 | |
|   if(status&MS_DSR_ON) return(1);
 | |
|   else return(0);
 | |
| }
 | |
| 
 | |
| 
 | |
| void RS232_enableDTR(int comport_number)
 | |
| {
 | |
|   EscapeCommFunction(Cport[comport_number], SETDTR);
 | |
| }
 | |
| 
 | |
| 
 | |
| void RS232_disableDTR(int comport_number)
 | |
| {
 | |
|   EscapeCommFunction(Cport[comport_number], CLRDTR);
 | |
| }
 | |
| 
 | |
| 
 | |
| void RS232_enableRTS(int comport_number)
 | |
| {
 | |
|   EscapeCommFunction(Cport[comport_number], SETRTS);
 | |
| }
 | |
| 
 | |
| 
 | |
| void RS232_disableRTS(int comport_number)
 | |
| {
 | |
|   EscapeCommFunction(Cport[comport_number], CLRRTS);
 | |
| }
 | |
| 
 | |
| /*
 | |
| https://msdn.microsoft.com/en-us/library/windows/desktop/aa363428%28v=vs.85%29.aspx
 | |
| */
 | |
| 
 | |
| void RS232_flushRX(int comport_number)
 | |
| {
 | |
|   PurgeComm(Cport[comport_number], PURGE_RXCLEAR | PURGE_RXABORT);
 | |
| }
 | |
| 
 | |
| 
 | |
| void RS232_flushTX(int comport_number)
 | |
| {
 | |
|   PurgeComm(Cport[comport_number], PURGE_TXCLEAR | PURGE_TXABORT);
 | |
| }
 | |
| 
 | |
| 
 | |
| void RS232_flushRXTX(int comport_number)
 | |
| {
 | |
|   PurgeComm(Cport[comport_number], PURGE_RXCLEAR | PURGE_RXABORT);
 | |
|   PurgeComm(Cport[comport_number], PURGE_TXCLEAR | PURGE_TXABORT);
 | |
| }
 | |
| 
 | |
| 
 | |
| #endif
 | |
| 
 | |
| 
 | |
| void RS232_cputs(int comport_number, const char *text)  /* sends a string to serial port */
 | |
| {
 | |
|   while(*text != 0)   RS232_SendByte(comport_number, *(text++));
 | |
| }
 | |
| 
 | |
| 
 | |
| /* return index in comports matching to device name or -1 if not found */
 | |
| int RS232_GetPortnr(const char *devname)
 | |
| {
 | |
|   int i;
 | |
| 
 | |
|   char str[32];
 | |
| 
 | |
| #if defined(__linux__) || defined(__FreeBSD__)   /* Linux & FreeBSD */
 | |
|   strcpy(str, "/dev/");
 | |
| #else  /* windows */
 | |
|   strcpy(str, "\\\\.\\");
 | |
| #endif
 | |
|   strncat(str, devname, 16);
 | |
|   str[31] = 0;
 | |
| 
 | |
|   for(i=0; i<RS232_PORTNR; i++)
 | |
|   {
 | |
|     if(!strcmp(comports[i], str))
 | |
|     {
 | |
|       return i;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return -1;  /* device not found */
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | 
