Serial modem is not returning '>' - c

I'm communicating GSM modem through Serial Port. And send AT commands to control GSM modem. Using below code. Working fine except when sending SMS.
To Send SMS:
AT+CMGS="+31628870634"
> This is the text message.→
+CMGS: 198
OK
When u send AT+CMGS="+31628870634" it must immediately return >. But my code doesn't return > and returning > with ERROR. Where am i making mistake ?
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#define BAUDRATE B38400
#define dev "/dev/ttyUSB0"
#define _POSIX_SOURCE 1
#define FALSE 0
#define TRUE 1
volatile int STOP=FALSE;
main()
{
char pinn[20];
char buf[255];
int fd,res=0;
printf("%s\n", dev);
struct termios oldtio,newtio;
fd = open(dev, O_RDWR | O_NOCTTY );
if (fd <0) {perror(dev); exit(-1); }
tcgetattr(fd,&oldtio); /* save current serial port settings */
bzero(&newtio, sizeof(newtio));
newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
newtio.c_iflag = IGNPAR | ICRNL;
newtio.c_oflag = 0;
newtio.c_lflag = ICANON;
newtio.c_cc[VMIN] = 1;
tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&newtio);
if (fd < 0)
{
printf("Error opening serial port\n");
exit(1);
}
// while(1){
scanf("%s",pinn);
strcat(pinn,"\r");
if (write(fd, pinn, strlen(pinn)) < strlen(pinn)) printf("Write error - %s \n", strerror(errno));
pinn[strlen(pinn)-1]=0;
while(1){
res = read(fd,buf,255);
buf[res]=0;
buf[res-1]=0;
if (res>1&&NULL==strstr(buf,pinn)) break;
}
printf("\"%s\"\n", buf);
tcsetattr(fd,TCSANOW,&oldtio);
close(fd);
}
Here's Output of my code:
./serial_test
AT+CMGS="99928626"
After a while returns:
"> "
"ERROR"

Related

C - Weird termios behaviour when calling read() function Linux

I encountered problem when reading ELM327 chip over serial port.
This is my code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <string.h
#include <sys/ioctl.h>
#define DEVICE "/dev/ttyUSB0"
#define SPEED B38400
int main()
{
struct termios old_stdio; //save the current port settings
int tty_fd; //file descriptor for serial port
int retval, res, n, res2, read1, wri;
char buf[255];
char buf2[255];
tty_fd = open(DEVICE, O_RDWR | O_NOCTTY | O_NDELAY );
if(tty_fd < 0)
{
perror(DEVICE);
exit(-1);
}
printf("Init 1 complete.\n");
tcflush(tty_fd, TCIOFLUSH);
fcntl(tty_fd, F_SETFL, 0);
if(tcgetattr(tty_fd, &old_stdio) != 0)
{
perror(DEVICE);
exit(-1);
}
printf("Init 2 complete.\n");
struct termios newtio;
if(tcgetattr(tty_fd, &newtio) != 0)
{
perror(DEVICE);
exit(-1);
}
cfsetospeed(&newtio, B38400);
cfsetispeed(&newtio, B38400);
printf("Init 3 complete.\n");
newtio.c_cflag |= CLOCAL | CREAD | HUPCL;
newtio.c_iflag |= ICRNL | IGNPAR;
newtio.c_lflag &= !(ICANON | ISIG);
newtio.c_lflag |= ECHOK | ECHOE | ECHOKE;
newtio.c_oflag |= ONLCR;
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 0;
if(tcsetattr(tty_fd, TCSANOW, &newtio) != 0)
{
perror(DEVICE);
exit(-1);
}
printf("Init 4 complete.\n");
for(n = 55; n > 0; n--)
{
printf("Please enter a command: ");
(void)fgets(buf2, 255, stdin);
printf("Ok.input was %s ",&buf2);
(void)write(tty_fd, buf2, strlen(buf2));
(void)write(tty_fd, "\r", 1);
printf("Ok. Waiting for reply\n");
res = read(tty_fd, &buf, 255);
printf("Read:%d %s \n",res, &buf);
}
//restore the original port settings
tcsetattr(tty_fd, TCSANOW, &old_stdio);
close(tty_fd);
return EXIT_SUCCESS; //return all good
}
I can write to device but after writing atz read function isn't reading anything. But after hitting enter \n one more time it prints output in terminal.
Init 1 complete.
Init 2 complete.
Init 3 complete.
Init 4 complete.
Please enter a command: atz
Ok.input was atz
Ok. Waiting for reply
Read:0
Please enter a command:
Ok.input was
Ok. Waiting for reply
Read:20 atz
ELM327 v1.5
>�
Please enter a command:
Dose anyone have idea why is this happening??

# of Bytes at Serial Port Input Buffer

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.)

sending AT command to teltonika GSM modem using C in ubuntu 12.04

Hi I am trying to send AT commands to teltonika gsm modem using com port(ttyS0) of my ubuntu desktop. The problem is instead of getting "OK" reply to the AT command ( or any other command or string), the same AT command is getting echo'ed back. Any help in this regard will be appreciated. Here's the C code m working on:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>
#define BAUDRATE B115200
#define COM1 "/dev/ttyS0"
static int fd;
static struct termios oldtio,newtio;
//==============================================================
int tty_read(char *buf1,int nbytes)
{
int temp;
temp = read(fd,buf1,nbytes);
printf("Read string: %s\n", buf1);
return temp;
}
//==============================================================
int tty_end()
{
tcsetattr(fd,TCSANOW,&oldtio);
close(fd);
}
//==============================================================
int tty_writecmd(char *buf,int nbytes)
{
write(fd,buf,nbytes);
usleep(1000);
return tcdrain(fd);
}
//==============================================================
int baud = B115200;
int tty_init()
{
fd = open(COM1, O_RDWR );
if (fd <0) {
perror(COM1);
exit(1);
}
tcgetattr(fd,&oldtio);
bzero(&newtio, sizeof(newtio));
newtio.c_cflag = baud | CRTSCTS | CS8 | CLOCAL | CREAD ;
newtio.c_iflag = IGNPAR | ICRNL;
newtio.c_oflag = 0;
newtio.c_lflag = ICANON;
newtio.c_cc[VINTR] = 0;
newtio.c_cc[VQUIT] = 0;
newtio.c_cc[VERASE] = 0;
newtio.c_cc[VKILL] = 0;
newtio.c_cc[VEOF] = 4;
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 1;
newtio.c_cc[VSWTC] = 0;
newtio.c_cc[VSTART] = 0;
newtio.c_cc[VSTOP] = 0;
newtio.c_cc[VSUSP] = 0;
newtio.c_cc[VEOL] = 0;
newtio.c_cc[VREPRINT] = 0;
newtio.c_cc[VDISCARD] = 0;
newtio.c_cc[VWERASE] = 0;
newtio.c_cc[VLNEXT] = 0;
newtio.c_cc[VEOL2] = 0;
tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&newtio);
return 0;
}
int main(int argc, char *argv[])
{ int wr,rd;
char *buff;
char recv[15];
char command[] = "AT\r\n";
tty_init();
printf("Write: %d\n", tty_writecmd(command, sizeof(command)));
usleep(10000);
printf("Read: %d\n", tty_read(recv ,sizeof(recv)));
tty_end();
}
and the output is like
write:0
Read string: AT
Read:3
Thanks
P.S : This behaviour occurs in Ubuntu desktop, the program reads nothing from serial port in VMware station.
instead of usleep(10000);
use
usleep(1000);

C program to read data from USB device connected to the system

I am trying to fetch data from the USB device (say pendrive) connected to the USB port of a system. Here, I am able to open the device file and read some random raw data. But I want to fetch data like minicom/teraterm.
Please let me know what methods and libraries I can use to do it successfully and how can it be done.
#include <stdio.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <signal.h>
#include <sys/time.h>
int main()
{
short portfd=-1;
int n,f,len;
char buf[256],*s;
alarm(2);
#if defined(O_NDELAY) && defined(F_SETFL)
portfd = open("/dev/ttyUSB0", O_RDWR|O_NDELAY);
if (portfd >= 0){
/* Cancel the O_NDELAY flag. */
printf("port openend\n");
n = fcntl(portfd, F_GETFL, 0);
(void) fcntl(portfd, F_SETFL, n & ~O_NDELAY);
}
#else
portfd = open("/dev/ttyUSB0", O_RDWR);
#endif
if (portfd >= 0)
{
if (len == 0) len = strlen(s);
for(f = 0; f < len && f <100; f++)
buf[f] = *s++ | 0x80;
write(portfd, buf, f);
printf("Do write\n");
while(portfd>=0){
printf("%s\n",buf);
}
}
alarm(0);
signal(SIGALRM, SIG_IGN);
if (portfd < 0) {
printf("cannot open %s. Sorry.\n", "/dev/ttyUSB0");
}
}
Log of the output:
���������鉀�������������������鍀���������������������������������������������������������������2
����������鉀�������������������鍀���������������������������������������������������������������2
you will need to set the correct port configuration...
struct termios oldtio,newtio;
// open port...
// save existing attributes
tcgetattr(fd,&oldtio);
// set attributes - these flags may change for your device
#define BAUDRATE B9600
memset(&newtio, 0x00, sizeof(newtio));
newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
newtio.c_iflag = IGNPAR | ICRNL;
newtio.c_oflag = 0;
tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&newtio);
//reset attributes
tcsetattr(fd,TCSANOW,&oldtio);
I have a rough working example here... http://file-hub.com/cmd:thread/142300

Linux receive signal break for ttycontrol program

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.

Resources