C++ KeyboardEmulator - c++

I'm trying to code a KeyBoard Emulator for Linux, first I thought to use python to achieve it, but all the libraries were using X (and I don't want to use it). I decided to code in C++ to write in the keyboard buffer. After a few days of learning C++ and doing some research on Linux and how the input system works, I came up with this:
#include <stdio.h>
#include <fcntl.h>
#include <linux/input.h>
#include <sstream>
#include <unistd.h>
#define EV_PRESSED 1
#define EV_RELEASED 0
int Emulate(char character)
{
printf("Starting the keyboard buffer writer\n");
int fd = 0;
char *device = "/dev/input/event1";
//write to buffer
if( (fd = open(device, O_RDWR)) > 0 )
{
struct input_event event;
printf("The keyboard code is: %d \n", KEY_A);
event.type = EV_KEY;
event.value = EV_PRESSED;
event.code = KEY_A;
write(fd, &event, sizeof(struct input_event));
event.value = EV_RELEASED;
event.code = KEY_A;
write(fd, &event, sizeof(struct input_event));
close(fd);
}
return 0;
}
int main(int argc, char *argv[]){
for(int i=0; i < sizeof(argv[1])/sizeof(int); i++){
Emulate(argv[1][i]);//for each car in the argv 1 call Emulate
}
}
As you can see I'm writing manually KEY_A to press the a key. And I was wondering if there is a function or a way to change a char to the keycodes definded in the file /usr/include/linux/input-event-codes.h.
Thank you for your help !

Related

read and write doesn't work in named pipes c++

Please excuse my English, its not the best. Thank you.
I am suppose to write 2 simple programs, which are suppose to enable two communication between processes in/with named pipes(C++).
Each code search through the directory and (name of the directory is suppose to be inputed by a user) search for FIFO file type. After finding a file, first code opens to read, second code opens to write. If process can't find a file, then it will ask user to input a new path.
First code write the message in the terminal(stdin) and send it through the pipe to second process. Second process read the message from the pipe and shows it in terminal(stdout). Both processes are suppose to end after reading message from stdin and sending a statement 'END';
I am still learning and trying to find more about named pipes so for now I could only write some basics programs(just to read and write) but still I don't understand why both of them doesn't work.
Can You tell me what is wrong with my codes? Thank You.
here is my code for read
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
char sentence [256];
int fp, numr ,numop;
umask(0);
fp = mkfifo("myfifo", S_IFIFO|0666);
if(fp < 0)
{
printf("Cant make a file\n");
return 1;
}
numop = open("myfifo",O_RDONLY);
if(numop < 0)
{
printf("Cant open the file\n");
return 1;
}
numr = read(fp,&sentence,sizeof(sentence));
if( numr < 0)
{
printf("Cant read the message\n");
return 1;
}
fgets(sentence,256,stdin);
printf("Message: %s\n",sentence);
close(fp);
return 0;
}
here is for write
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int fd , numw;
char sentence [256];
fd = open("myfifo", O_WRONLY);
if(fd < 0)
{
printf("Can't open a file\n");
return 1;
}
printf ("Enter the message : ");
fgets(sentence,250,stdin);
numw = write(fd,sentence,strlen(sentence)+1);
if(numw < 0)
{
printf("Can write the message");
return 1;
}
close(fd);
return 0;
}
can you tell me what am I doing wrong?

QSerialPort cannot open with error code 11

I'm trying to communicate with a device which provided a serial port. When I use the example C program provided by the device producer, it was successfully connected and I can send/receive data. But when I use my C++ program with QSerialPort, the open() method returned false and the error() returned 11 (An unidentified error occurred, as described by Qt documentation). Could anyone please help me?
OS: Cent OS 6.9
gcc/g++: 4.8
Qt: 5.6.0
An example of connecting with QSerialPort:
#include <qserialport.h>
#include <qstring.h>
int main(int argc, const char *argv[])
{
QString portName = "/dev/corser/x64ExpCL4x1_s0";
QSerialPort *pSerial = new QSerialPort();
pSerial->setPortName(portName);
pSerial->setBaudRate(QSerialPort::Baud9600);
pSerial->setParity(QSerialPort::NoParity);
pSerial->setDataBits(QSerialPort::Data8);
pSerial->setStopBits(QSerialPort::OneStop);
pSerial->setFlowControl(QSerialPort::NoFlowControl);
bool success = pSerial->open(QIODevice::ReadWrite);
if (!success) {
printf("Error: %d\n", pSerial->error());
} else {
printf("Success.\n");
pSerial->close();
}
delete pSerial;
return 0;
}
This program prints out Error: 11.
Here is a C program which is excerpted from the device's example program. This program just try to connect the serial port and then close the connection. While the original example program is complicated. It is actually kind of a "Terminal" program which sends user-input commands to the device and prints out the responses from the device.
#include <unistd.h>
#include <termios.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <ctype.h> /* Character types */
#define TRUE 1
#define FALSE 0
typedef struct
{
int open; // Flag for current open status of port
int update; // Flag indicating parameter changes
char *port; // Current port to be opened
int iod; // I/O index for open device port
struct termios stty; // Terminal port control structure
} SCOM_CTL;
struct termios ttctl = {0};
struct termios ttsav = {0};
struct termios coctl = {0};
struct termios cnctl = {0};
#define OPEN 1
#define CLOSE 2
#define UPDATE 3
#define NO_UPDATE 4
SCOM_CTL scom;
int main( int argc, char **argv )
{
scom.port = "/dev/corser/x64ExpCL4x1_s0";
scom_init();
scom_open_port();
if (scom.open == OPEN)
{
fputs("\rSuccess.\r\n", stdout);
scom_close_port(scom.iod);
}
else
{
fputs("\rError.\r\n", stdout);
}
}
// Initialize the console (stdin) for raw access.
int scom_init()
{
int i;
scom.open = CLOSE;
scom.update = NO_UPDATE;
scom.iod = -1;
tcgetattr(0, &coctl); // Save a copy to restore stdin.
tcgetattr(0, &cnctl);
cfmakeraw( &cnctl); // Set stdin to raw !
tcsetattr(0, 0, &cnctl);
}
int scom_open_port()
{
int i, iod;
if (scom.open == OPEN)
{
close(scom.iod);
scom.open = CLOSE;
}
if ( (iod = open( scom.port, (O_RDWR | O_NOCTTY))) == -1)
{
conres(); /* Reset the console. */
fputs("term : Open Failure on device\n", stdout);
return -1;
}
scom.iod = iod;
scom.open = OPEN;
scom.update = NO_UPDATE;
}
int scom_close_port()
{
scom.open = CLOSE;
close(scom.iod);
}
int conres()
{
return(tcsetattr(0, 0, &coctl));
}
This program prints out Success.

Write/Read a stream of data (double) using named pipes in C++

I am trying to develop a little application in C++, within a Linux environment, which does the following:
1) gets a data stream (a series of arrays of doubles) from the output of a 'black-box' and writes it to a pipe. The black-box can be thought as an ADC;
2) reads the data stream from the pipe and feeds it to another application which requires these data as stdin;
Unfortunately, I was not able to find tutorials or examples. The best way I found to realize this is summarized in the following test-bench example:
#include <iostream>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdio.h>
#define FIFO "/tmp/data"
using namespace std;
int main() {
int fd;
int res = mkfifo(FIFO,0777);
float *writer = new float[10];
float *buffer = new float[10];
if( res == 0 ) {
cout<<"FIFO created"<<endl;
int fres = fork();
if( fres == -1 ) {
// throw an error
}
if( fres == 0 )
{
fd = open(FIFO, O_WRONLY);
int idx = 1;
while( idx <= 10) {
for(int i=0; i<10; i++) writer[i]=1*idx;
write(fd, writer, sizeof(writer)*10);
}
close(fd);
}
else
{
fd = open(FIFO, O_RDONLY);
while(1) {
read(fd, buffer, sizeof(buffer)*10);
for(int i=0; i<10; i++) printf("buf: %f",buffer[i]);
cout<<"\n"<<endl;
}
close(fd);
}
}
delete[] writer;
delete[] buffer;
}
The problem is that, by running this example, I do not get a printout of all the 10 arrays I am feeding to the pipe, whereas I keep getting always the first array (filled by 1).
Any suggestion/correction/reference is very welcome to make it work and learn more about the behavior of pipes.
EDIT:
Sorry guys! I found a very trivial error in my code: in the while loop within the writer part, I am not incrementing the index idx......once I correct it, I get the printout of all the arrays.
But now I am facing another problem: when using a lot of large arrays, these are randomly printed out (the whole sequence is not printed); as if the reader part is not able to cope with the speed of the writer. Here is the new sample code:
#include <iostream>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdio.h>
#define FIFO "/tmp/data"
using namespace std;
int main(int argc, char** argv) {
int fd;
int res = mkfifo(FIFO,0777);
int N(1000);
float writer[N];
float buffer[N];
if( res == 0 ) {
cout<<"FIFO created"<<endl;
int fres = fork();
if( fres == -1 ) {
// throw an error
}
if( fres == 0 )
{
fd = open(FIFO, O_WRONLY | O_NONBLOCK);
int idx = 1;
while( idx <= 1000 ) {
for(int i=0; i<N; i++) writer[i]=1*idx;
write(fd, &writer, sizeof(float)*N);
idx++;
}
close(fd);
unlink(FIFO);
}
else
{
fd = open(FIFO, O_RDONLY);
while(1) {
int res = read(fd, &buffer, sizeof(float)*N);
if( res == 0 ) break;
for(int i=0; i<N; i++) printf(" buf: %f",buffer[i]);
cout<<"\n"<<endl;
}
close(fd);
}
}
}
Is there some mechanism to implement in order to make the write() wait until read() is still reading data from the fifo, or am I missing something trivial also in this case?
Thank you for those who have already given answers to the previous version of my question, I have implemented the suggestions.
The arguments to read and write are incorrect. Correct ones:
write(fd, writer, 10 * sizeof *writer);
read(fd, buffer, 10 * sizeof *buffer);
Also, these functions may do partial reads/writes, so that the code needs to check the return values to determine whether the operation must be continued.
Not sure why while( idx <= 10) loop in the writer, this loop never ends. Even on a 5GHz CPU. Same comment for the reader.

Open TTY to use with execlp and dup

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.

How to create pty that is connectable by Screen app in Linux

I wanted to create C/C++ application, that creates new (virtual) device in /dev/xxx and will be able to connect with 'screen' application.
For example program running in loop, that creates new /dev/ttyABC. Then I'll use 'screen /dev/ttyABC', and when I send there some chars, then app send it back to the 'screen'.
I really don't know where start. I found some referencies on pty library but I don't even know, if I have right direction.
Could you help me? Where to look? Post example?
Thanks
You could use a Pseudoterminal via openpty to achieve this. openpty returns a pair of file descriptors (master and slave pty devices) that are connected to each other via their stdout / stdin. The output of one will appear at the input of another and vice-versa.
Using this (rough!) example...
#include <fcntl.h>
#include <cstdio>
#include <errno.h>
#include <pty.h>
#include <string.h>
#include <unistd.h>
int main(int, char const *[])
{
int master, slave;
char name[256];
auto e = openpty(&master, &slave, &name[0], nullptr, nullptr);
if(0 > e) {
std::printf("Error: %s\n", strerror(errno));
return -1;
}
std::printf("Slave PTY: %s\n", name);
int r;
while((r = read(master, &name[0], sizeof(name)-1)) > 0) {
name[r] = '\0';
std::printf("%s", &name[0]);
}
close(slave);
close(master);
return 0;
}
... Echoing some text (in another terminal session) to the slave pty sends it to master's input. E.g. echo "Hello" > /dev/pts/2
Based on the answer provided by #gmbeard , I was able to create an echo PTY device and connect to it with screen and minicom. What made the difference was using a raw PTY device by initializing a termios struct.
Here is the code
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <cstdio>
#include <pty.h>
#include <termios.h>
#define BUF_SIZE (256)
int main(int, char const *[])
{
int master, slave;
char buf[BUF_SIZE];
struct termios tty;
tty.c_iflag = (tcflag_t) 0;
tty.c_lflag = (tcflag_t) 0;
tty.c_cflag = CS8;
tty.c_oflag = (tcflag_t) 0;
auto e = openpty(&master, &slave, buf, &tty, nullptr);
if(0 > e) {
std::printf("Error: %s\n", strerror(errno));
return -1;
}
std::printf("Slave PTY: %s\n", buf);
int r;
while ( (r = read(master, buf, BUF_SIZE)) > 0 )
{
write(master, buf, r);
}
close(slave);
close(master);
return 0;
}