i'm trying to make an app for the remote control of mouse on linux server by android application. As a beginner, i've got lot of probs..before writing the linux Server with C, I tried to check if i can control and move the mouse on Linux according to the code :
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <linux/input.h>
int main(){
struct input_event event, event_end;
int i=0;
int fd = -1;
fd = open("/dev/input/event4", O_RDWR | O_NONBLOCK);
if(fd<0){
perror("error");
}
memset(&event, 0, sizeof(event));
memset(&event, 0, sizeof(event_end));
gettimeofday(&event.time, NULL);
event.type = EV_REL;
event.code = REL_X;
event.value = 100;
gettimeofday(&event_end.time, NULL);
event_end.type = EV_SYN;
event_end.code = SYN_REPORT;
event_end.value = 0;
for( i=0; i<5; i++){
write(fd, &event, sizeof(event));// Move the mouse
write(fd, &event_end, sizeof(event_end));// Show move
sleep(1);
}
close(fd);
return 0;
}
after build compile execute.. nothing happens
cursor never moves..will it be somekind of VirtualBox setting issue?
sudo cat /dev/input/event4 shows weird string of symbols when i physically move the mouse.
That means to be able to get contol of mouse cursor movement by event4 isn't it?
i wonder why the cursor won't move... anyone can help?
And further, I would be glad if anyone suggests Library and Functions to control mouse
thx a lot
You can't just write to the device file and expect the drivers to behave as if actual hardware was sending these events. Things are way more complicated than that.
If you are only concerned with X Windows environment you are in luck. You can use this function to send events to the window:
http://tronche.com/gui/x/xlib/event-handling/XSendEvent.html
If you don't know which window should be receiving your events just send them to the root window, they will be routed appropriately.
Also there is a library for that.
http://www.x.org/releases/X11R7.6/doc/libXtst/recordlib.html
Just keep in mind that in X windows events have a flag that indicates whether the event came from the actual hardware or was synthesized by one of the above methods. In most cases programs just ignore this flag and behave the same regardless. But sometimes you can have weird surprises.
Related
I am currently attempting to retrieve device information for a built in web-cam using the following code:
#include <fcntl.h>
#include <unistd.h>
#include <linux/media.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main(int argc, char **argv) {
int fd = open("/dev/video0", O_RDONLY, 0);
if (fd > 0) {
struct media_device_info *device_data = (struct media_device_info *) malloc (sizeof(struct media_device_info) * 1);
if (ioctl(fd, MEDIA_IOC_DEVICE_INFO, device_data) == 0)
printf("Media Version: %u\nDriver: %s\nVersion: %d\nSerial: %s\n", (unsigned int) device_data->media_version, device_data->driver, (int) device_data->driver_version, device_data->serial);
else {
fprintf(stderr, "Couldn't get device info: %d: %s\n", errno, strerror(errno));
}
close(fd);
free(device_data);
}
return 0;
}
When the code executes the else block is entered thus giving the following:
Couldn't get device info: 25: Inappropriate ioctl for device
From this it would seem that the device is being opened in the wrong manner such that ioctl cannot use the file descriptor. I must be missing something; could anyone here help me with regards to opening the /dev/video0 device?
Thanks!
p.s. If this has been answered before elsewhere please let me know. If this question is invalid in anyway then please accept my apologies.
It seems that the /dev/video* devices may be bound to separate /dev/media* devices, and you need to issue your MEDIA_IOC_DEVICE_INFO ioctl against the corresponding /dev/media* device for your /dev/video* device.
As to how to locate that corresponding device id, the best I have come up with is to search for media* files within the /sys/class/video4linux/video{N}/device directory.
For example, for a given device /dev/video0 on my system (kernel 4.15.0-34-generic), searching for media* files under /sys/class/video4linux/video0/device turned up media10, which I was then able to use to recover the serial number (open /dev/media10, issue the ioctl command).
I don't know whether this method of finding the corresponding media devices is consistent across distros/versions/kernels/etc.
I've been using the following C code to try to simulate keystrokes on a CentOS 6.0 machine:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#inlcude <linux/input.h>
#include <linux/uinput.h>
#include <sys/time.h>
static int fd = -1;
struct uinput_user_dev uidev;
struct input_event event;
int main()
{
int i;
fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
memset(&uidev, 0, sizeof(uidev));
snrpintf(uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-kbd");
uidev.id.version = 1;
uidev.id.vendor = 0x1;
uidev.id.product = 0x1;
uidev.id.bustype = BUS_USB;
ioctl(fd, UI_SET_EVBIT, EV_KEY);
for(i = 0; i < 256; i++)
{
ioctl(fd, UI_SET_KEYBIT, i);
}
ioctl(fd, UI_SET_EVBIT, EV_SYN);
write(fd, &uidev, sizeof(uidev));
ioctl(fd, UI_DEV_CREATE));
memset(&event, 0, sizeof(event));
gettimeofday(&event.time, NULL);
event.type = EV_KEY;
event.code = KEY_1;
event.value = 1;
write(fd, &event, sizeof(event));
event.type = EV_SYN;
event.code = SYN_REPORT;
event.value = 0;
write(fd, &event, sizeof(event));
memset(&event, 0, sizeof(event));
gettimeofday(&event.time, NULL);
event.type = EV_KEY;
event.code = KEY_1;
event.value = 0;
write(fd, &event, sizeof(event));
event.type = EV_SYN;
event.code = SYN_REPORT;
event.value = 0;
write(fd, &event, sizeof(event));
ioctl(fd, UI_DEV_DESTROY);
close(fd);
return 0;
}
If I'm correct, this code should create a virtual input device on the machine and then press the "1" key on that device. And when I execute the code, it seems to run without any issues (I haven't include the code that checks to make sure the device is being created and the keystrokes are being written, etc, in my example code, because it would have gotten way too long), but I can't see any sign of the actual keystroke.
My impression was that if I run this from a terminal window while logged directly into the machine, I should see a "1" character appear on the terminal window that I'm running it from. And if I log into the machine via ssh and run it that way, the keystroke should register on the machine rather than the ssh session. But I'm not getting anything in either situation.
Am I misunderstanding the purpose of this code? Have I done it wrong? Or is the more that I need to add to properly simulate a keystroke?
Wow, I was having the same issue as you just a few minutes ago, but now I don't have the issue anymore, and according to evtest it seems to work. I don't know what I did that resolved the problem unfortunately.
Here's the steps I used to troubleshoot, hopefully that at least gets you somewhere:
Verify that dmesg reports input device when connected.
Example:
[Fri Jul 22 22:38:55 2022] input: Custom Tourbox TBG_H Driver as /devices/virtual/input/input25
Verify that program can write to /dev/uinput file. Can be done via checking return value of write() call (the example code you listed doesn't).
If you have any issues with the above, double-check permissions. ( I did the hack of running my program as root and then changing the permission on the /dev/uinput file to be world-writable, via:
$ chmod +0666 /dev/uinput
This probably isn't recommended though, it would probably be better to create a group and then add your user to that group )
Verify that evtest recognizes your new driver.
Run:
$ sudo evtest
And you should see your device (probably at the bottom):
/dev/input/event24: Custom Tourbox TBG_H Driver
Verify that evtest recognizes that your device has registered an event handler for the keys you wish to use. In my case, I need to simulate key presses for 'a', so I made sure to verify that key was listed as one of the possible event types:
This is what the example output looked like:
Input driver version is 1.0.1
Input device ID: bus 0x3 vendor 0x483 product 0xbeef version 0x0
Input device name: "Custom Tourbox TBG_H Driver"
Supported events:
Event type 0 (EV_SYN)
Event type 1 (EV_KEY)
Event code 30 (KEY_A)
From there, all I did was press the key and it worked.
Here now I found why this can't work, I spend two days finding the problem. Luckily and finally, I found it in linux kernel 5.60 source example which is in chapter 7.4. Here is the picture .Solution
the document said that we'd better wait for some time so that there is a space for userspace to detect event, because creating a device node in kernel state will spend lots of time compared to sending a event to fd, hopes that the answer is not too late.
Here is the link 7.Uinput-module
I was playing around with the Pulseaudio API and due to my little knowledge on how the sound system works, I'm not really understanding why it's possible having multiple applications using the mic at the same time.
Or to better phrase it: why the fprintf is not called I have 2 applications that are actively recording stuffs and I start the following program?
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <pulse/simple.h>
#include <pulse/error.h>
#define BUFSIZE 1024
int main(int argc, char*argv[]) {
/* The sample type to use */
static const pa_sample_spec ss = {
.format = PA_SAMPLE_S16LE,
.rate = 44100,
.channels = 2
};
pa_simple *s = NULL;
int ret = 1;
int error;
/* Create the recording stream */
if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_RECORD, NULL, "record", &ss, NULL, NULL, &error)))
fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
return 0;
}
I'd guess you're not getting an error message because the program is successfully creating a pa_simple connection to the pulse audio server.
You may wish to add pa_simple_free(s); to the end of your main() before you return.
Also, here is a link to an example pa_simple record program:parec-simple_8c-example
See Pulse Audio API at freedesktop.org
EDIT: Your question "why the fprintf is not called" is because the Pulse Audio Simple API doesn't guarantee exclusive access to the Microphone. Therefor, when two other applications are already "using" the microphone, and you create a simple stream connection to the server, there is no error generated. Is your question really "How to determine if the microphone is being used by any program - and which one"?
I am using BAFO bf-810 USB to Serial adapter with pl2303 drivers on Mac OS X. I am a beginner in the field and so have got the high level APIs from here which is a cross-platform API.
I have two programs, one to write and one to read. This API does not have a inbuilt samples in the code. So I had to look at other's APIs to get a picture of what had to be done (like, comOpen, comWrite etc.). With the limited knowledge, I wrote the following little programs using the linked APIs.
sendSerial.c
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include "rs232.h"
extern int errno;
int main(){
comEnumerate();
if(!comOpen(1, 9600)) printf("Cannot open the port\n");
while (1){
char data[1024] = "Hello World";
int ret = comWrite(1, data, 512);
printf("%d\n", ret);
if(ret>0){
printf("Bytes transferred!\n");
} else{
printf("%s\n", strerror(errno));
}
sleep(1);
}
return 0;
}
.
recSerial.c
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include "rs232.h"
extern int errno;
int main(){
comEnumerate();
if(!comOpen(1, 9600)) printf("Cannot open the port\n");
char read[1024] = "EMPTY";
printf("\nNow reading data at %s...\n",comGetPortName(1));
while (1){
printf(".\n");
if(comRead(1, read, 4)){
printf("Data: %s\n**\n", read);
}
sleep(1);
}
return 0;
}
The source has a single C program and might help on what I might be missing.
Question
When sending data, the write returns the Resource temporarily unavailable error after the third iteration. Why is this happening consistently? When I restart the sender program when the receiver is running, the error starts off with the first iteration itself.
In any case, I am not able to read any data on the read side of the program. I understand that the RS232 is an async protocol, but I've read somewhere that the system has a buffer of around 4 Mb before the data gets overwritten. So the second question is, do I have to manually handle the clock synchronisation?
P.S.: For the loopback test, I have connected, Send-Recieve, RTS-CTS and DTR-DSR on the DB9 connector.
I'm working on a new project where I want to make a connection with an FTDI which is connected to my debian machine. I am intending to write the code with C, not C++. Here lies my problem. All the examples I find are incomplete or are made for a c++ compiler in stead of the GCC compiler.
The goal is to talk to my microcontroller which is connected to the FTDI. For debugging i want to start building a linux application which is able to:
initialize a serial connection on startup with ttyUSB1
send a character string
display character strings when they are received by the pc
save the communication to a .txt file
Is there any example code or tutorial to make this?
If I succeed I will defenetly place the code here so that new viewers can use it to!
Edit:
Like I said I would post the code if I had it, and this is what worked for me:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#define MODEM "/dev/ttyUSB0"
#define BAUDRATE B115200
int main(int argc,char** argv)
{
struct termios tio;
struct termios stdio;
struct termios old_stdio;
int tty_fd, flags;
unsigned char c='D';
tcgetattr(STDOUT_FILENO,&old_stdio);
printf("Please start with %s /dev/ttyS1 (for example)\n",argv[0]);
memset(&stdio,0,sizeof(stdio));
stdio.c_iflag=0;
stdio.c_oflag=0;
stdio.c_cflag=0;
stdio.c_lflag=0;
stdio.c_cc[VMIN]=1;
stdio.c_cc[VTIME]=0;
tcsetattr(STDOUT_FILENO,TCSANOW,&stdio);
tcsetattr(STDOUT_FILENO,TCSAFLUSH,&stdio);
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); // make the reads non-blocking
memset(&tio,0,sizeof(tio));
tio.c_iflag=0;
tio.c_oflag=0;
tio.c_cflag=CS8|CREAD|CLOCAL; // 8n1, see termios.h for more information
tio.c_lflag=0;
tio.c_cc[VMIN]=1;
tio.c_cc[VTIME]=5;
if((tty_fd = open(MODEM , O_RDWR | O_NONBLOCK)) == -1){
printf("Error while opening\n"); // Just if you want user interface error control
return -1;
}
cfsetospeed(&tio,BAUDRATE);
cfsetispeed(&tio,BAUDRATE); // baudrate is declarated above
tcsetattr(tty_fd,TCSANOW,&tio);
while (c!='q'){
if (read(tty_fd,&c,1)>0){
write(STDOUT_FILENO,&c,1); // if new data is available on the serial port, print it out
printf("\n");
}
if (read(STDIN_FILENO,&c,1)>0){
write(tty_fd,&c,1);//if new data is available on the console, send it to serial port
printf("\n");
}
}
close(tty_fd);
tcsetattr(STDOUT_FILENO,TCSANOW,&old_stdio);
return EXIT_SUCCESS;
}
Most of the code came from http://en.wikibooks.org/wiki/Serial_Programming/Serial_Linux but i also used a bit from the code posted below.
Handling with serial ports ( for linux OS ) :
- To open communication, you will need a descriptor which will be the handle for your serial port.
- Set the flags to control how the comunication will be.
- Write the command to this Handle ( make sure you're formatting the input correctly ).
- Get the answer. (make sure you're to read the amount of information you want )
- Close the handle.
It will seem like this:
int fd; // file descriptor
int flags; // communication flags
int rsl_len; // result size
char message[128]; // message to send, you can even dinamically alocate.
char result[128]; // result to read, same from above, thanks to #Lu
flags = O_RDWR | O_NOCTTY; // Read and write, and make the job control for portability
if ((fd = open("/dev/ttyUSB1", flags)) == -1 ) {
printf("Error while opening\n"); // Just if you want user interface error control
return -1;
}
// In this point your communication is already estabilished, lets send out something
strcpy(message, "Hello");
if (rsl_len = write(fd, message, strlen(message)) < 0 ) {
printf("Error while sending message\n"); // Again just in case
return -2;
}
if (rsl_len = read(fd, &result, sizeof(result)) < 0 ) {
printf("Error while reading return\n");
return -3;
}
close(fd);
Note that you have to care about what to write and what to read.
Some more flags can be used in case of parity control, stop bits, baud rate and more.
Since gcc is a C/C++ compiler, you don't need to limit yourself to pure C.
Sticking to pure C is OK if you enjoy writing lots of boilerplate code, and if you really know what you're doing. Many people use Unix APIs incorrectly, and a lot of example code out there is much too simplistic. Writing correct Unix C code is somewhat annoying, to say the least.
Personally, I'd suggest using not only C++, but also a higher-level application development framework like Qt. Qt 5 comes bundled with a QtSerialPort module that makes it easy to enumerate the serial ports, configure them, and get data into and out of them. Qt does not force you to use the gui modules, it can be a command line application, or a non-interactive server/daemon.
QtSerialPort is also usable from Qt 4, but it doesn't come bundled with Qt 4, you have to add it to your project. I suggest starting out with Qt 5, it's nicer to use with its C++11 support.
The code using Qt can be pretty simple, not much longer than your plain-English description. The below is a Qt console application using Qt 5 and C++11. It uses the core and serialport modules. It also handles the SIGINT signal so that the output file gets flushed before the process would terminate due to a ^C. I'm using QLocalSocket in place of raw Unix API to communicate from the Unix signal handler, the functionality is the same.
Only the code within main is strictly required, the rest is just to make it properly wrap things up when you hit ^C.
#include <QCoreApplication>
#include <QSerialPort>
#include <QFile>
#include <QTextStream>
#include <QLocalServer>
#include <QLocalSocket>
#include <cstdio>
#include <csignal>
QLocalSocket * xmit;
static void signalHandler(int)
{
xmit->write(" ");
xmit->flush();
}
static bool setupSignalHandler()
{
QLocalServer srv;
srv.listen("foobarbaz");
xmit = new QLocalSocket(qApp);
xmit->connectToServer(srv.serverName(), QIODevice::WriteOnly);
srv.waitForNewConnection();
QLocalSocket * receive = srv.nextPendingConnection();
receive->setParent(qApp);
qApp->connect(receive, &QLocalSocket::readyRead, &QCoreApplication::quit);
struct sigaction sig;
sig.sa_handler = signalHandler;
sigemptyset(&sig.sa_mask);
sig.sa_flags = SA_RESTART;
return ! sigaction(SIGINT, &sig, NULL);
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
setupSignalHandler();
QSerialPort port("ttyUSB1");
QFile file("file.txt");
QTextStream err(stderr, QIODevice::WriteOnly);
QTextStream out(stdout, QIODevice::WriteOnly);
if (!file.open(QIODevice::WriteOnly)) {
err << "Couldn't open the output file" << endl;
return 1;
}
if (!port.open(QIODevice::ReadWrite)) {
err << "Couldn't open the port" << endl;
return 2;
}
port.setBaudRate(9600);
QObject::connect(&port, &QSerialPort::readyRead, [&](){
QByteArray data = port.readAll();
out << data;
file.write(data);
});
out << "Use ^C to quit" << endl;
return a.exec();
}