I am doing a program to open, write and read the port ttyUSB0, I have the next program and I don´t write anything. Can anyone help me please????
My question is that I have a problem with the write or read function, because I can´t read and write in the ttyUSB0 port, and I search a solution to write and read ttyUSB0 port.
#include <sys/time.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <termios.h>
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
using namespace std;
int serial_open(char *serial_name, speed_t baud)
{
struct termios newtermios;
int fd;
fd = open(serial_name,O_RDWR | O_NOCTTY);
newtermios.c_cflag= CBAUD | CS8 | CLOCAL | CREAD;
newtermios.c_iflag=IGNPAR;
newtermios.c_oflag=0;
newtermios.c_lflag=0;
newtermios.c_cc[VMIN]=1;
newtermios.c_cc[VTIME]=0;
cfsetospeed(&newtermios,baud);
cfsetispeed(&newtermios,baud);
if (tcflush(fd,TCIFLUSH)==-1) return -1;
if (tcflush(fd,TCOFLUSH)==-1) return -1;
if (tcsetattr(fd,TCSANOW,&newtermios)==-1) return -1;
return fd;
}
void serial_send(int serial_fd, char *data, int size)
{
write(serial_fd, data, size);
}
int serial_read(int serial_fd, char *data, int size, int timeout_usec)
{
fd_set fds;
struct timeval timeout;
int count=0;
int ret;
int n;
do {
FD_ZERO(&fds);
FD_SET (serial_fd, &fds);
timeout.tv_sec = 0;
timeout.tv_usec = timeout_usec;
ret=select (FD_SETSIZE,&fds, NULL, NULL,&timeout);
if (ret==1) {
n=read (serial_fd, &data[count], size-count);
count+=n;
data[count]=0;
}
} while (count<size && ret==1);
return count;
}
void serial_close(int fd)
{
close(fd);
}
int main(int argc, char *argv[])
{
int serial_fd, n, longitud,;
char *device=”at”;
char *data;
longitud=strlen(device);
serial_fd = serial_open("/dev/ttyUSB0",B38400);
if (serial_fd == -1) {
printf ("Error opening the serial device: %s\n",argv[1]);
perror("OPEN");
exit(0);
}
printf("SERIAL OPEN:%s\n", device);
serial_send(serial_fd, device, longitud);
printf ("String sent------> %s\n",device);
n=serial_read(serial_fd,data,longitud,10000);
printf("Se ha recibido %s \n Tamaño: %d\n n:%d \n serial_fd:%d\n",data, longitud,n,serial_fd);
puts(data);
serial_close(serial_fd);
// cout << "Hello world!" << endl;
return 0;
}
Your program works just fine with the writing and reading, but you have another problem: Undefined behavior.
You have a pointer variable in your main function named data, and you pass this to your serial_read function. But nowhere do you make this pointer actually point anywhere, so when that pointer is dereferenced you have the undefined behavior.
Local (non-static) variables are not initialized, their value is indeterminate. You need to initialize the variable, to make it actually point somewhere. I recommend you make it into an array instead.
And then when you call serial_read you only ask to read two bytes (the length of the string "at"), instead of the actual size of the data (which currently is none), you need to pass the actual size of the buffer instead.
So to sum it up:
int main(void)
{
...
char data[256];
...
n = serial_read(serial_fd, data, sizeof(data), 10000);
...
}
Related
I've never worked with file descriptors and I'm a bit confused about some of this behavior. I'm also fairly new to concurrency and the documentation for these functions is fairly lacking.
My MessageReciever constructor opens a pty. Upon calling the Receive message, as I understand it, the code forks. The master should hit the next conditional and return from the function. I know this is happening because the code in main doesn't block. The child reads in the file descriptor, converts it to a string and saves it in a vector. Currently I'm printing the buffer directly but I also can print the last element in the vector and it acts basically the same. However, when I attempt to access this outside the class, in main, I get nothing. I thought this might be some type of concurrency problem, but I'm not really sure how to address.
CODE
#include <sys/time.h>
#include <sys/types.h>
#include <sys/select.h>
#include <stdio.h>
#include <util.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string>
#include <vector>
class MessageReceiver
{
public:
MessageReceiver()
{
openpty(&master, &slave, NULL, NULL, NULL);
}
~MessageReceiver()
{
close(master);
close(slave);
}
void receiveMessage()
{
pid_t pid = fork();
printf("PID = %d\n",pid);
if(pid > 0)
{
fd_set rfds;
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
char buf[4097];
ssize_t size;
size_t count = 0;
while (1)
{
if (waitpid(pid, NULL, WNOHANG) == pid)
{
break;
}
FD_ZERO(&rfds);
FD_SET(master, &rfds);
if (select(master + 1, &rfds, NULL, NULL, &tv))
{
size = read(master, buf, 4096);
printf("Buffer = %s", buf);
messageBuffer.push_back(std::string(buf));
buf[size] = '\0';
count += size;
}
}
}
}
std::string getLastMessage()
{
std::string s;
if(messageBuffer.size() > 0)
{
s = messageBuffer.back();
}
else
{
s = "NULL";
}
return s;
}
private:
int master, slave;
std::vector<std::string> messageBuffer;
};
int main()
{
MessageReceiver m;
m.receiveMessage();
std::string lastMessage = m.getLastMessage();
printf("Printing message buffer:\n");
for(;;)
{
if(m.getLastMessage() != lastMessage)
{
printf("Message: %s\n", m.getLastMessage().c_str());
}
}
return 0;
}
Initial output
PID = 8170
PID = 0
Printing message buffer:
Additional output when hello is echoed to the pty
Buffer = hello
So I have this code that I have to edit a bit but the code itself doesn't compile when I try in mobaxterm and since I don't really have much experience with C++ I hope u guys can help. This is the code:
//critical_example2.c
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "se207_sems.h"
int main(int argc, char argv[]){
//Use our source file as the "key"
int id=se207_semget("critical_example2.c",1);
int pid=fork();
if(pid){
//P1
while(1){
se207_wait(id);
printf("In critical section P1 ... \n");
rsleep();
printf("Ending critical section P1 ... \n");
se207_signal(id);
}
}else{
//P2
while(1){
se207_wait(id);
printf("In critical section P2 ... \n");
rsleep();
printf("Ending critical section P2 ... \n");
se207_signal(id);
}
}
}
This are the errors i get:
toneve#hvs-its-lnx01:~$ gcc critical_example2.c
In file included from critical_example2.c:9:0:
se207_sems.h: In function ‘se207_wait’:
se207_sems.h:91:6: warning: type of ‘id’ defaults to ‘int’ [-Wimplicit-int]
void se207_wait(id){
^
se207_sems.h: In function ‘se207_signal’:
se207_sems.h:95:6: warning: type of ‘id’ defaults to ‘int’ [-Wimplicit-int]
void se207_signal(id){
This might be the problematic code:
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <stdlib.h>
void rsleep(){
//Random sleep function. Comes in handy demoing stuff.
int stime=2+(rand()/(float)(RAND_MAX))*4;
printf("Sleeping for %d secs\n",stime);
sleep(stime);
}
int se207_semget(char* path, int val){
//Very simple semaphore "getting",
//always uses 1 as the project ID
//takes path to file and initial value of semaphore
int id; /* Number by which the semaphore
is known within a program */
union semun {
int val;
struct semid_ds *buf;
ushort * array;
} argument;
argument.val = val;
/* Create the semaphore with external key from
ftok if it doesn't already
exist. Give permissions to the world. */
id = semget(ftok(path,1), 1, 0666 | IPC_CREAT);
/* Always check system returns. */
if(id < 0)
{
fprintf(stderr, "Unable to obtain semaphore.\n");
exit(0);
}
/* Set the value of the number 0 semaphore in semaphore array # id
to the value "val". */
if( semctl(id, 0, SETVAL, argument) < 0)
fprintf( stderr, "Cannot set semaphore value.\n");
else
fprintf(stderr, "Semaphore %d initialized with path '%s'.\n",
ftok(path,1),path);
return id;
}
void se207_semop(int id,int val){
struct sembuf operations[1];
int retval; /* Return value from semop() */
//simple wait on semaphore
operations[0].sem_num = 0;
/* Which operation? Subtract 1 from semaphore value to wait, add to
signal */
operations[0].sem_op = val;
operations[0].sem_flg = 0;
retval = semop(id, operations, 1);
}
int void se207_wait(id){
se207_semop(id,-1);
}
int void se207_signal(id){
se207_semop(id,1);
}
Remove the int from your se207_wait and se207_signal functions, and declare id as an int in the parameter list.
void se207_wait(int id){
se207_semop(id,-1);
}
void se207_signal(int id){
se207_semop(id,1);
}
I am trying to create a minimal code to use pipe/fork/execlp.
So far so good, I am using execlp with bash -c, so if I do.
echo asd |./a.out cat
> asd
So it is working as expected.
But if I try to use anything that needs a TTY, it does not work.
Like ./a.out vim, I get "Vim: Warning: Input is not from a terminal"
And the vim that was open does not works as expected.
I tried to find on the internet an example on how to open a TTY, the only one that I found was:
http://www.danlj.org/lad/src/minopen.c
My Code, so far is:
#include <iostream>
#include <cstdio>
#include <string.h>
#include <cstdlib>
#include <unistd.h>
#include <sys/wait.h>
typedef struct pCon{
int fout[2];
int fin[2];
int fd[2];
int pid1, pid2;
} connectionManager;
std::string command = "";
/*
* Implementation
*/
void childFork(connectionManager *cm);
int main(int argc, char *argv[]) {
int size;
if(argc < 2) exit(1);
else command = argv[1];
connectionManager *cm = new connectionManager;
pipe(cm->fd);
if((cm->pid1 = fork()) == -1)exit(1);
if (cm->pid1 == 0)
{
const unsigned int RCVBUFSIZE = 2000;
char echoString[RCVBUFSIZE];
while((size = read(fileno(stdin),echoString,RCVBUFSIZE)) > 0)
write(cm->fd[1], echoString, size);
close(cm->fd[1]);
}
else
childFork(cm);
return 0;
}
void childFork(connectionManager *cm){
char *buffer = new char[2000];
int size;
close(cm->fd[1]);
dup2(cm->fd[0], 0);
close(cm->fd[0]);
pipe(cm->fout);
if((cm->pid2 = fork()) == -1)exit(1);
if (cm->pid2 == 0)
{
close(cm->fout[0]);
int returnCode = execlp("bash", "bash", "-c", command.c_str(), NULL);
if(returnCode!=0)
std::cerr << "Error starting the bash program" << std::endl;
}
else
{
close(cm->fout[1]);
while((size = read(cm->fout[0], buffer, 2000 )) > 0 )
write(fileno(stdout), buffer, size);
}
}
I tried to keep the minimal necessary code to make it work.
Is there any way to implement TTY on this code, I know that does not seems to be such trivial task.
Can someone help me with that?
I also tried to open the tty and dup it, but no luck so far.
Try to use pseudo terminal. You can use opentty. For your purpose you can use forkpty which combines pty with fork. I've created a small example for you. About the same as your program, just it works. I've kept it simple, so I don't handle the terminal control characters.
#include <pty.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/select.h>
int main(int argc, char *argv[])
{
if (argc<1) return 1;
int master;
pid_t pid = forkpty(&master, NULL, NULL, NULL); // opentty + login_tty + fork
if (pid < 0) {
return 1; // fork with pseudo terminal failed
}
else if (pid == 0) { // child
char *args[] = { argv[1], argv[2], NULL }; // prg + 1 argument
execvp(argv[1], args); // run the program given in first param
}
else { // parent
struct termios tios;
tcgetattr(master, &tios);
tios.c_lflag &= ~(ECHO | ECHONL);
tcsetattr(master, TCSAFLUSH, &tios);
while(1) {
fd_set read_fd, write_fd, err_fd;
FD_ZERO(&read_fd);
FD_ZERO(&write_fd);
FD_ZERO(&err_fd);
FD_SET(master, &read_fd);
FD_SET(STDIN_FILENO, &read_fd);
select(master+1, &read_fd, &write_fd, &err_fd, NULL);
if (FD_ISSET(master, &read_fd))
{
char ch;
int c;
if (c=read(master, &ch, 1) != -1) // read from program
write(STDOUT_FILENO, &ch, c); // write to tty
else
break; // exit when end of communication channel with program
}
if (FD_ISSET(STDIN_FILENO, &read_fd))
{
char ch;
int c=read(STDIN_FILENO, &ch, 1); // read from tty
write(master, &ch, c); // write to program
}
}
}
return 0;
}
For compiling use -lutil .
While running a new tty device appears in /dev/pts .
vim accepts it as a terminal.
Is it possible to use getline(cin,buffer); at the top of my program, then have a "animated menu" still running below it?
For example (very basic):
#include <iostream>
#include <string>
using namespace std;
int stringLen=0;
string buffer;
getline(cin, buffer);
for (int i = 0; i < kMaxWait;i++)
{
printf("counter waiting for user input %d",i);
if (1 >= buffer.length())
break;
}
Would I have to fork that loop somehow so it would keep counting and display the counter until the user enters something??
One possible answer, given in the comments, is to use threads. But it's not necessary, there's a way to do this without threads.
Make stdin a non-blocking file descriptor.
Wait for stdin to become readable, via poll()/select(), in the meantime do your animation, etc...
Make stdin a blocking file descriptor, again.
Use std::getline().
There are also some ancillary issues to consider, such as the buffering that comes from std::streambuf, so before doing all that, check if there's already something to read from std::cin, first.
This is something I used sometime ago. It's quite rudimentary, but you can get the gist of the process - using poll. It returns true if there is input, and puts it in str, false otherwise. So, you can put this in your loop somewhere, and take action when there is input.
bool polled_input(std::string& str)
{
struct pollfd fd_user_in;
fd_user_in.fd = STDIN_FILENO;
fd_user_in.events = POLLIN;
fd_user_in.revents = 0;
int rv = poll(&fd_user_in, 1, 0);
if (rv == -1) {/* error */}
else if (rv == 0) return false;
else if (fd_user_in.revents & POLLIN)
{
char buffer[MAX_BUFF_SIZE];
int rc = read(STDIN_FILENO, buffer, MAX_BUFF_SIZE-1);
if (rc >= 0)
{
buffer[rc]='\0';
str = std::string(buffer);
return true;
}
else {/* error */}
}
else {/* error */}
}
select is meant for this, multiplexed, blocking I/O. It can be done without a poll I think:
#include <iostream>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char **arg)
{
const int time_in_secs = 10;
const int buffer_size = 1024;
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(STDIN_FILENO, &readfds);
struct timeval tv;
tv.tv_sec = time_in_secs;
tv.tv_usec = 0;
int ret = select(STDIN_FILENO + 1, &readfds, NULL, NULL, &tv);
if (!ret)
{
std::cout << "Timeout\n";
exit(1);
}
char buf[buffer_size];
if (FD_ISSET(STDIN_FILENO, &readfds))
{
int len = read(STDIN_FILENO, buf, buffer_size);
buf[len] = '\0';
}
std::cout << "You typed: " << buf << "\n";
return 0;
}
This program runs on PC and I want him wait until there are data available on serial connection from Arduino, and display them. If Arduino don't send anything, I want the program to wait indefinitely.
What happens, is that I've got only Resource temporarily unavailable messages.
After kind help from Kurt Stutsman here is a working program that waits for binary input from serial connection, (from the Arduino in this case).
#include <string.h>
#include <iostream>
#include <stdint.h>
#include <errno.h>
#include <fcntl.h> // File control definitions
#include <termios.h> // POSIX terminal control definitions
#include <unistd.h> // UNIX standard function definitions
using namespace std;
int connect(const char* serialport)
{
struct termios toptions;
int fd;
fd = open(serialport, O_RDWR );
if (fd == -1) {
return -1;
}
if (tcgetattr(fd, &toptions) < 0)
return -1;
speed_t brate = B9600; //9600 bauds
cfsetospeed(&toptions, brate);
cfmakeraw(&toptions);
toptions.c_cc[VMIN] = 1; //I want read to wait for the input
toptions.c_cc[VTIME] = 0; //indefinitely, until it arrives. Byte after byte.
tcsetattr(fd, TCSANOW, &toptions);
if( tcsetattr(fd, TCSAFLUSH, &toptions) < 0) {
return -1;
}
return fd;
}
int main() {
int fd = connect("/dev/ttyACM0");
if (fd==-1)
{
cout<<"Error in opening serial port\n";
cout<<strerror(errno)<<'\n';
return -1;
}
while(true)
{
uint8_t b=0;
int ret=read(fd, &b, 1);
if (ret == 1)
{
cout<<"received byte "<<int(b)<<'\n';
} else if (ret == 0)
{
cout<<"EOF\n";
} else
{
cout<<strerror(errno)<<'\n';
}
}
return 0;
}
You can test it with this simple Arduino C++ code:
void setup() {
Serial.begin(9600); // connect to the serial port
}
void loop()
{
Serial.write(uint8_t(42));
delay(1000);
}