I have two C Programs 1. To Write Data to Serial Port and 2. To Read Data from Serial Port. I have connected a USB-Serial converter to my laptop and shorted Tx & Rx to test the program.
Program 1 is getting executed successfully.
Program 2 blocks at read.
Can anyone please suggest a solution for this.
Thanks in advance.
Program to Write to Serial Port:
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
/*
* 'open_port()' - Open serial port 1.
*
* Returns the file descriptor on success or -1 on error.
*/
int write_port(void)
{
int fd; /* File descriptor for the port */
fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1)
{
/* Could not open the port. */
perror("open_port: Unable to open /dev/ttyUSB0 - ");
}
else
fcntl(fd, F_SETFL, 0);
int n = write(fd, "ATZ\r", 4);
if (n < 0)
fputs("write() of 4 bytes failed!\n", stderr);
return (fd);
}
void main(){
printf("\nAccessing Serial Port to Write\n");
int fd=write_port();
if(fd<0){
printf("\nSerial Port Access Failed\n");
return;
}
printf("\n%d\tSuccess\n",fd);
}
Program to Read from Serial Port:
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
/*
* 'read_port()' - Reads serial port 1.
*
* Returns the file descriptor on success or -1 on error.
*/
int read_port(void)
{
int fd = open("/dev/ttyUSB0", O_RDONLY | O_NOCTTY);
if (fd == -1)
{
/* Could not open the port. */
perror("open_port: Unable to open /dev/ttyUSB0 - ");
}
char buffer[32];
int n = read(fd, buffer, sizeof(buffer));
if (n < 0)
fputs("read failed!\n", stderr);
return (fd);
}
void main(){
printf("\nAccessing Serial Port to Read\n");
int fd=read_port();
if(fd<0){
printf("\nSerial Port Access Failed\n");
return;
}
printf("\n%d\tSuccess\n",fd);
}
Related
I have a RPI Zero W connected to my virtual machine through USB, which can be found under /dev/ttyS0 on both PC and the RPI. Currently I am trying to send something from the RPI through the USB cable to the virtual machine (PC).
I am trying to read on the port with the following code:
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
/* * 'open_port()' − Open serial port 1. *
* Returns the file descriptor on success or −1 on error. */
int fd; /* File descriptor for the port */
int open_port(void)
{
fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
if(fd == -1)
{
/* * Could not open the port. */
perror("open_port: Unable to open /dev/ttyS0 − ");
}
else
fcntl(fd, F_SETFL, FNDELAY);
return (fd);
}
int close_port(void)
{
close(fd);
return (fd);
}
int main()
{
printf("Serial reader has started...\n\n");
while(1)
{
open_port();
close_port();
}
return 0;
}
and on the RPI side, I have made a little bash script, which sends the character 1:
while :
do
echo "sending character 1 to /dev/ttyS0"
echo "1" > /dev/ttyS0
done
However, even though the bash script and the c program are both running in continuous loops, I am not receiving anything on the PC side.
What could be the reason?
I am trying to get familiar with tuntap devices. I have read the following article:
https://backreference.org/2010/03/26/tuntap-interface-tutorial/
but somehow the code from the article doesn't work.
I have this code:
#include <sys/socket.h> //well get our socket
#include <sys/ioctl.h> //thats our input output control
#include <sys/time.h>
#include <fcntl.h>
#include <asm/types.h> //these are data types liked signed unsingend
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> //read write close and stuff
#include <signal.h> //different signals
#include <linux/if_packet.h> //interface for packets
#include <linux/if_ether.h> //interface or ethernet frames
#include <linux/if_arp.h> //interface for arp
#include <linux/if.h>
#include <linux/if_tun.h>
#include <arpa/inet.h>
int tun_alloc(char *dev, int flags) {
struct ifreq ifr;
int fd, err;
char *clonedev = "/dev/net/tun";
/* Arguments taken by the function:
*
* char *dev: the name of an interface (or '\0'). MUST have enough
* space to hold the interface name if '\0' is passed
* int flags: interface flags (eg, IFF_TUN etc.)
*/
/* open the clone device */
if( (fd = open(clonedev, O_RDWR)) < 0 ) {
return fd;
}
/* preparation of the struct ifr, of type "struct ifreq" */
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = flags; /* IFF_TUN or IFF_TAP, plus maybe IFF_NO_PI */
if (*dev) {
/* if a device name was specified, put it in the structure; otherwise,
* the kernel will try to allocate the "next" device of the
* specified type */
strncpy(ifr.ifr_name, dev, IFNAMSIZ);
}
/* try to create the device */
if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) {
close(fd);
return err;
}
/* if the operation was successful, write back the name of the
* interface to the variable "dev", so the caller can know
* it. Note that the caller MUST reserve space in *dev (see calling
* code below) */
strcpy(dev, ifr.ifr_name);
/* this is the special file descriptor that the caller will use to talk
* with the virtual interface */
return fd;
}
int main(void){
unsigned int seconds = 1;
char tap_name[IFNAMSIZ];
strcpy(tap_name, "tun0");
printf("%s\n", tap_name);
int tap_fd = tun_alloc(tap_name, IFF_TUN);
void *buffer = (void *)(malloc(3000));
printf("%s\n", tap_name);
if(tap_fd < 0){
perror("Allocating interface");
exit(1);
}
int nread;
while(1){
nread = read(tap_fd, buffer, sizeof(buffer));
if (nread < 0){
perror("Nread: ");
close(tap_fd);
free(buffer);
exit(1);
}
printf("Read %d Bytes from devies %s \n", nread, tap_name);
sleep(seconds);
}
}
I executed this program on one terminal and pinged the interface from another terminal.
But when I ping the interface from the command line (ping 192.168.0.24, I have assigned that IP to the interface), on the terminal of the program there's always written "read 8 Bytes from interface", although the number of bytes should vary when I ping the interface. Does anyone see the mistake?
New to C programming here so bear with me.. I wrote a program to write/read data to and from the serial port. Everything appears to be working except when I try to read the number of bytes available at the port that have been received. Here's my code (see the read_port function):
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
#include <sys/ioctl.h> /* Serial Port IO Controls */
int fd; /* File descriptor for the port */
struct termios options_original; /* Original Serial Port Options */
int main()
{
fd = open_port();
flush_port();
write_port();
printf("FIONBIO value %d\n", FIONBIO);
usleep(2);
printf("FIONREAD value %d\n", FIONREAD);
read_port();
close_port();
}
/*
* open_port() - Open serial port 1.
*
* Returns the file descriptor on success or -1 on error
*/
int open_port(void)
{
struct termios options;
fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
if (fd != -1)
{
printf("Serial Port Open\n");
fcntl(fd, F_SETFL, 0);
tcgetattr(fd, &options_original);
tcgetattr(fd, &options);
cfsetispeed(&options, B115200);
cfsetospeed(&options, B115200);
options.c_cflag |= (CLOCAL | CREAD); /* Enable the receiver and set local mode */
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* Raw Input Mode */
tcsetattr(fd, TCSANOW, &options); /* Set the new options for the port */
}
else
{
/* Could not open the port */
perror("open_port: Unable to open /dev/ttyUSB0 - ");
}
return (fd);
}
int close_port(void)
{
tcsetattr(fd, TCSANOW, &options_original);
printf("Serial Port Closed\n");
close(fd);
}
int flush_port(void)
{
usleep(2); // required to make flush work, for some reason
printf("Flushing IO Buffers\n");
tcflush(fd, TCIOFLUSH);
}
int write_port(void)
{
int n = write(fd, "DSC", 3);
if (n < 0)
fputs("write() of 1 byte failed!\n", stderr);
else
printf("Wrote %0d bytes to serial port\n", n);
}
int read_port(void)
{
int chars_read = 3;
int bytes;
char read_buffer[3] = {0};
int i;
fcntl(fd, F_SETFL, 0);
ioctl(fd, FIONBIO, &bytes);
printf("Number of bytes = %d\n", bytes);
int n = read(fd, read_buffer, chars_read);
printf("Character at Port: %s\n", read_buffer);
printf("Number of chars read = %0d\n", n);
}
Here's the output:
Serial Port Open
Flushing IO Buffers
Wrote 3 bytes to serial port
FIONBIO value 21537
FIONREAD value 21531
Number of bytes = 0
Character at Port: DSC
Number of chars read = 3
Serial Port Closed
For some reason 'Number of bytes' always equals 0. I have no idea why. Is there something wrong with doing this?
int bytes;
ioctl(fd, FIONBIO, &bytes);
printf("Number of bytes = %d\n", bytes);
It's pretty much verbatim from this site:
http://www.cmrr.umn.edu/~strupp/serial.html#config
Am I missing or not understanding something?
BTW I'm just doing a simple loopback test here.
ioctl(fd, FIONBIO, ...) sets a file descriptor (e.g. a socket) into blocking or
non-blocking mode. What you probably meant is
ioctl(fd, FIONREAD, &bytes);
to get the number of bytes available in the input buffer (i.e. the number of bytes
that can be read without blocking.)
I would like to check a network devices status e.g. promiscous mode. Basically like shown with ip a command.
Maybe someone could push me in the right direction?
I want to do this in C for linux so linux specific headers are available.
You need to use the SIOCGIFFLAGS ioctl to retrieve the flags associated with an interface. You can then check if the IFF_PROMISC flag is set:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h> /* ioctl() */
#include <sys/socket.h> /* socket() */
#include <arpa/inet.h>
#include <unistd.h> /* close() */
#include <linux/if.h> /* struct ifreq */
int main(int argc, char* argv[])
{
/* this socket doesn't really matter, we just need a descriptor
* to perform the ioctl on */
int fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
struct ifreq ethreq;
memset(ðreq, 0, sizeof(ethreq));
/* set the name of the interface we wish to check */
strncpy(ethreq.ifr_name, "eth0", IFNAMSIZ);
/* grab flags associated with this interface */
ioctl(fd, SIOCGIFFLAGS, ðreq);
if (ethreq.ifr_flags & IFF_PROMISC) {
printf("%s is in promiscuous mode\n",
ethreq.ifr_name);
} else {
printf("%s is NOT in promiscuous mode\n",
ethreq.ifr_name);
}
close(fd);
return 0;
}
If you want to set the interface to promiscuous mode, you will need root privileges, but you can simply set the field in ifr_flags and use the SIOCSIFFLAGS ioctl:
/* ... */
ethreq.ifr_flags |= IFF_PROMISC;
ioctl(fd, SIOCSIFFLAGS, ðreq);
I would like to receive SIGINT if my process controlling /dev/ttyS2 receives BREAK on a serial port. I run this program from a shell. From what I discovered only "the terminal is the controlling terminal of a foreground process group, it will cause a SIGINT to be sent to this foreground process group" I tried make process making controller of terminal but it fails.
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#define BAUDRATE B115200
#define MODEMDEVICE "/dev/ttyS2"
#define _POSIX_SOURCE 1 /* POSIX compliant source */
#define FALSE 0
#define TRUE 1
__sighandler_t sighandle(int signum, __sighandler_t h) {
fprintf(stderr, "BREAK DETECTED\n");
signal(SIGINT, (__sighandler_t) sighandle);
return SIG_IGN;
}
volatile int STOP=FALSE;
int main()
{
int fd,c, res;
struct termios oldtio,newtio;
char buf[255];
pid_t pid;
signal(SIGINT, (__sighandler_t) sighandle);
fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
if (fd <0) {perror(MODEMDEVICE); return (-1); }
tcgetattr(fd,&oldtio); /* save current port settings */
memset(&newtio, 0,sizeof(newtio));
newtio.c_cflag |= BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD | BRKINT;
newtio.c_iflag &= ~IGNBRK ;
newtio.c_oflag = 0;
/* set input mode (non-canonical, no echo,...) */
newtio.c_lflag = 0;
newtio.c_cc[VTIME] = 0; /* inter-character timer unused */
newtio.c_cc[VMIN] = 1; /* blocking read until 5 chars received */
tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&newtio);
if( ioctl(fd, TIOCSCTTY, 1) <0 )
{
printf("Error number: %d\n", errno);
}
if ( tcsetpgrp(fd, tcgetpgrp(0) ) < 0 )
{
syslog(LOG_PERROR,"tcsetpgrp failed: %d " ,errno);
syslog(LOG_PERROR,"EBADF is %d " ,EBADF);
syslog(LOG_PERROR,"EINVAL is %d " ,EINVAL);
syslog(LOG_PERROR,"ENOTTY is %d " ,ENOTTY);
syslog(LOG_PERROR,"EPERM is %d " ,EPERM);
}
while (STOP==FALSE) { /* loop for input */
res = read(fd,buf,255); /* returns after 5 chars have been input */
buf[res]=0; /* so we can printf... */
printf(":%s:%d\n", buf, res);
if (buf[0]=='z') {STOP=TRUE;}
}
tcsetattr(fd,TCSANOW,&oldtio);
return 0;
}
I finally found answer to my problem. I am using custom board so it don't have to work always but when serial port is configured correctly user can get number of breaks by serial port by cat /proc/tty/device/serial, that kind of functionality I was hoping to get
#define _POSIX_SOURCE 1 has no effect unless it precedes the #includes.
With a C99 compiler, you may #include <stdbool.h> instead of #define your own TRUE and FALSE.
/* from signal.h, */
typedef void(*sighandler_t)(int);
/* which means the handler must be declared thusly */
void sighandle(int);
/* as a result, no casting is necessary */
sighandler_t p_sighandle = &sighandle;
The foreground process group is set by tcsetpgrp, which you appear to be missing.