alphascrooge
Posts: 8
Joined: Thu May 17, 2018 8:00 pm

How to record mouse data and remove cursor/button functionality

Thu May 17, 2018 8:07 pm

Hi,

I'm pretty new to RPi and slightly less new to C. I am hoping to find a solution to a problem I've been running into.
I am trying to use two mice with my Pi, one which I'm hoping to use as a regular mouse, and the other which I am trying to record data from and then do something with that data, without using it as a mouse. I don't want the second mouse to interact with the OS at all: ideally, I can simply print the data to the screen without having the movement or clicks actually do anything.

Is this possible? I have figured out how to record movement data and clicks by looking at /dev/input/mouse0 and mouse1, but am not sure where to go from there.

Thank you for any help

ghans
Posts: 7654
Joined: Mon Dec 12, 2011 8:30 pm
Location: Germany

Re: How to record mouse data and remove cursor/button functionality

Fri May 18, 2018 5:18 am

• Don't like the board ? Missing features ? Change to the prosilver theme ! You can find it in your settings.
• Don't like to search the forum BEFORE posting 'cos it's useless ? Try googling : yoursearchtermshere site:raspberrypi.org

alphascrooge
Posts: 8
Joined: Thu May 17, 2018 8:00 pm

Re: How to record mouse data and remove cursor/button functionality

Fri May 18, 2018 4:06 pm

Thank you for the reply!

I was poking around earlier and found a similar thread suggesting I edit xorg.conf. I can't seem to find that file though, and online resources are telling me that it has since been deprecated, and that these .conf files are now held in xorg.conf.d. I was able to locate this on my RPi in /usr/share/X11 but am not sure which .conf file to alter with the new lines- none of them hold similar syntax to what is shown in the stackexchange link you posted.

10-evdev.conf seems to have catchalls for pointers, keyboards, touchpads, etc.... but no individual mice files that I should alter per the suggestion of the stackexchange post. Can I write an individual Section "InputClass" for my mouse? Should I alter the catchall for pointers in some way? I'm worried that changing the catchall will mess with my first mouse, and I really would like to handle the mice individually. I can't seem to find much online regarding this, but I'll try to keep poking around. Maybe I'm just not looking in the right places.

Thanks again for your help, I'm a newbie in this area so it's really appreciated.

EDIT: I also can't use xinput for some reason. Not sure why this is?

n67
Posts: 621
Joined: Mon Oct 30, 2017 4:55 pm

Re: How to record mouse data and remove cursor/button functionality

Fri May 18, 2018 4:16 pm

A couple of "basic Unix" notes - that, admittedly, have little to do with your actual issue:

1) Install the "locate" command. It is very useful, for finding files. apt-get install locate should do it.

Note: After installing locate, either wait a day (i.e., until tomorrow) or run "updatedb" (as root).

On my system, "locate xorg.conf" get me:

Code: Select all

$ locate xorg.conf
/usr/share/man/man5/xorg.conf.5.gz
/usr/share/man/man5/xorg.conf.d.5.gz
/usr/share/X11/xorg.conf.d
/usr/share/X11/xorg.conf.d/10-evdev.conf
/usr/share/X11/xorg.conf.d/10-quirks.conf
/usr/share/X11/xorg.conf.d/40-libinput.conf
/usr/share/X11/xorg.conf.d/70-synaptics.conf
/usr/share/X11/xorg.conf.d/99-fbturbo.conf
$
Note that there isn't any xorg.conf file, per se. Only files in xorg.conf.d

2) You should create a new file in xorg.conf.d, not edit an existing one.
(Not sure what number to use, though - that gets beyond my pay grade).

alphascrooge
Posts: 8
Joined: Thu May 17, 2018 8:00 pm

Re: How to record mouse data and remove cursor/button functionality

Fri May 18, 2018 4:20 pm

Thanks for the quick reply!

I'll install locate right now, seems like a useful tool.

Creating a new file in xorg.conf.d seems promising, just not sure what to name it and how to format it. I'm assuming something like this:

Code: Select all

Section "InputClass"
	Identifier "Mouse4"
	MatchIsPointer "on"
	MatchDevicePath "/dev/input/event4"
	Driver "evdev"
EndSection
Would be good to include (I know event4 is the event associated with the mouse I am trying to mute). This is essentially copy pasted from 10-evdev.conf with Identifier and MatchDevicePath updated to point to my new mouse.
Still not sure what to name it though... I'll try to see if there is anything online that would be helpful.
Last edited by alphascrooge on Fri May 18, 2018 4:22 pm, edited 1 time in total.

User avatar
PeterO
Posts: 4100
Joined: Sun Jul 22, 2012 4:14 pm

Re: How to record mouse data and remove cursor/button functionality

Fri May 18, 2018 4:21 pm

If you open the "non-X-mouse" file in /dev/input and set it for "exclusive access" in your program the events will not be passed on to X while your program has it open....

Code: Select all

result = ioctl(mouseFd, EVIOCGRAB, 1);
Also "evtest" is a useful tool to use when trying to learn about the events that come from a particular device.

PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),Aeromodelling,1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

alphascrooge
Posts: 8
Joined: Thu May 17, 2018 8:00 pm

Re: How to record mouse data and remove cursor/button functionality

Fri May 18, 2018 4:31 pm

Thank you for the reply, that was very helpful!

Just to be clear, ioctl with the EVIOCGRAB tag will not pass the events to X? I'm having a hard time finding documentation for EVIOCGRAB, the man page for ioctl and ioctl_list doesn't seem to describe it, so I don't really know what that tag does.

I'll check out evtest per your suggestion

Thanks again :)

User avatar
PeterO
Posts: 4100
Joined: Sun Jul 22, 2012 4:14 pm

Re: How to record mouse data and remove cursor/button functionality

Fri May 18, 2018 4:47 pm

alphascrooge wrote:
Fri May 18, 2018 4:31 pm
Thank you for the reply, that was very helpful!

Just to be clear, ioctl with the EVIOCGRAB tag will not pass the events to X? I'm having a hard time finding documentation for EVIOCGRAB, the man page for ioctl and ioctl_list doesn't seem to describe it, so I don't really know what that tag does.

I'll check out evtest per your suggestion

Thanks again :)
Indeed I'm not sure where I found out about it, probably someone on a forum told me about it (and so the myth is passed on to the next generation :-) ). But it does work !
PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),Aeromodelling,1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

alphascrooge
Posts: 8
Joined: Thu May 17, 2018 8:00 pm

Re: How to record mouse data and remove cursor/button functionality

Fri May 18, 2018 4:54 pm

Hi Peter,

Thanks for you quick replies, its super helpful. Its odd that there's no clear documentation on this....

I'm running into an issue where EVIOCGRAB isn't declared, so I'm getting a compilation error. Should I be including a file where it is defined?

I have been googling around and https://unix.stackexchange.com/question ... documented seems to say that EVIOCGRAB would be located in drivers/input/evdev.c, but I can't seem to find this directory. Does this not exist on RPi or is it named something else?

Thanks very much for your help!

User avatar
PeterO
Posts: 4100
Joined: Sun Jul 22, 2012 4:14 pm

Re: How to record mouse data and remove cursor/button functionality

Fri May 18, 2018 5:02 pm

It's in /usr/include/linux/input.h so you'll need to "#include linux/input.h".

PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),Aeromodelling,1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

alphascrooge
Posts: 8
Joined: Thu May 17, 2018 8:00 pm

Re: How to record mouse data and remove cursor/button functionality

Fri May 18, 2018 5:53 pm

Thanks for all your help so far, maybe I could bother you just a little more?

So I'm now using ioctl on the mousefd. Looks something like this:

Code: Select all

fd1 = open(mouse1, O_RDWR);
if(fd1 == -1) {return -1}

//mute mouse1
result = ioctl(fd1, EVIOCGRAB, 1);
if(result == -1) 
{
	printf("Muting broke. %s\n", strerror(errno));
}
The issue is that ioctl is returning with an error, specifically "Inappropriate ioctl for device".
Is there anything immediately apparent that I'm doing wrong here? I'm not sure why ioctl isn't working, it's throwing the error and isn't blocking mouse input. I've checked around online, and it seems that this error is a result of something to do with tty, but I don't really understand it.

User avatar
PeterO
Posts: 4100
Joined: Sun Jul 22, 2012 4:14 pm

Re: How to record mouse data and remove cursor/button functionality

Fri May 18, 2018 9:32 pm

alphascrooge wrote:
Fri May 18, 2018 5:53 pm
Thanks for all your help so far, maybe I could bother you just a little more?

So I'm now using ioctl on the mousefd. Looks something like this:

Code: Select all

fd1 = open(mouse1, O_RDWR);
if(fd1 == -1) {return -1}

//mute mouse1
result = ioctl(fd1, EVIOCGRAB, 1);
if(result == -1) 
{
	printf("Muting broke. %s\n", strerror(errno));
}
The issue is that ioctl is returning with an error, specifically "Inappropriate ioctl for device".
Is there anything immediately apparent that I'm doing wrong here? I'm not sure why ioctl isn't working, it's throwing the error and isn't blocking mouse input. I've checked around online, and it seems that this error is a result of something to do with tty, but I don't really understand it.
Without knowing what "mouse1" is I can't say much....

In my openGLES code I look for a file that ends with "event-mouse" in "/dev/input/by-id", so it normally finds the file for my tracker ball which is :
/dev/input/by-id/usb-Logitech_USB_Trackball-event-mouse which is in turn a link to /dev/input/mouse0

In your case I expect it will be /dev/input/mouse1 that you will need to open, though there may be no gaurantee mouse0 and mouse1 will always be the same way round.

My code opens the file with " mouseFd = open(fullPath,O_RDONLY | O_NONBLOCK);" You can't write to is so it should not be opened with O_RDWR. I use O_NONBLOCK so my code can just try to read events and not block if there aren't any to read.


PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),Aeromodelling,1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

alphascrooge
Posts: 8
Joined: Thu May 17, 2018 8:00 pm

Re: How to record mouse data and remove cursor/button functionality

Fri May 18, 2018 9:47 pm

Awesome! That solved the issue! Now X isn't seeing mouse1, once I changed the path to the by-id directory and added O_RDONLY.
There's only 1 problem: I used to have the coordinates and buttons status printed to screen when a mouse event was detected. Upon moving either mouse it would print something like:

Mouse0: x=1, y=0, left=0, right=0, middle=0 (When I move mouse 0).
or
Mouse1: x=0, y=0, left=1, right=0, middle=0 (When I left click mouse 1).

Now, it isn't printing anything for mouse1. As far as I can tell, I've effectively disconnected mouse1 and can't read any of the data it's outputting. I'm hoping to be able to still access that data but not have it do anything on screen. Is this possible?

Thank you so much for all your help, you're a true hero :)

alphascrooge
Posts: 8
Joined: Thu May 17, 2018 8:00 pm

Re: How to record mouse data and remove cursor/button functionality

Fri May 18, 2018 9:53 pm

In case it's helpful, here's my (relevant) code:
fd0 is the file descriptor for mouse0: open(fullpath, O_RDWR);
fd1 is the file descriptor for mouse1: open(fullpath, O_RDONLY|O_NONBLOCK);

Code: Select all

	result = ioctl(fd1, EVIOCGRAB, 1);
	if(result == -1){
		fprintf(stderr, "?\n");
		printf("muting broke. %s\n", strerror(errno));
	
	}
	printf("result: %d\n", result);
	
	//more initialization
	int left0, left1, middle0, middle1, right0, right1;
	signed char x0, x1, y0, y1;
	
	//-----------------------------------------------------------//
	//I track the data from the mice in 2 different processes.   //
	//Tracking the data on the same process led to weird errors  //
	//where it would only read data from one mouse at a time, but//
	//would alternate which mouse it read from based on the mouse//
	//it read from last, every 5 seconds or so.                  //
	//Therefore, using different processes for each mouse.       //
	//-----------------------------------------------------------//
	
	
	if(fork() == 0) 	//child process
	{
		while(1){
			bytes0 = read(fd0, data0, sizeof(data0));//Read data from mouse
			
			if(bytes0 > 0){
				left0 = data0[0] & 0x1;				//mask to find data on the left mouse button (first bit)
				right0 = data0[0] & 0x2;			//mask to find data on the right mouse button (2nd bit)
				middle0 = data0[0] & 0x4;			//(3rd bit)
		
				x0 = data0[1];						//get position data
				y0 = data0[2];
				
				//Now we can use the data. In this case, print.
				printf("Mouse0:  x=%d, y=%d, left=%d, middle=%d, right=%d\n", x0,y0,left0,middle0,right0);
			}
		}
	}
	else{				//parent process
		while(1){
			bytes1 = read(fd1, data1, sizeof(data1));
		
			if(bytes1 > 0){
				left1 = data1[0] & 0x1;
				right1 = data1[0] & 0x2;
				middle1 = data1[0] & 0x4;
				x1 = data1[1];
				y1 = data1[2];
			
				printf("Mouse1:  x=%d, y=%d, left=%d, middle=%d, right=%d\n", x1,y1,left1,middle1,right1);
			}
		}
	}

User avatar
PeterO
Posts: 4100
Joined: Sun Jul 22, 2012 4:14 pm

Re: How to record mouse data and remove cursor/button functionality

Fri May 18, 2018 10:00 pm

Yes you will have to read events from the file you opened...

Here is the code I use... My main program loop calls "mouseMotion" which reads the evens and set the appropriate global variables (mouseMoveLR and mouseMoveUD) to reflect the mouse movements since the function was last called. It will try to read upto 64 events at a time.

Code: Select all

void mouseMotion(void)
{
    struct input_event ev[64];
    int rd;

    mouseMoveLR = mouseMoveUD = 0;
    if(mouseFd != -1)
    {
	rd = read(mouseFd,ev,sizeof(ev));
	if(rd > 0)
	{
	    int count,n;
	    struct input_event *evp;

	    count = rd / sizeof(struct input_event);
	    n = 0;
	    while(count--)
	    {
		evp = &ev[n++];

		if(evp->type == 1)
		{
		    if(evp->value == 1)
		    {
			if(evp->code == BTN_LEFT)  
			{
			    mousePressLeft = true;
			}
			if(evp->code == BTN_RIGHT)  
			{
			    mousePressRight = true;
			}
		    }

		}
		if(evp->type == 2)
		{
		    if(evp->code == 0)
		    {   // Mouse Left/Right
			//printf("Mouse moved %d left/right\n",evp->value);
			mouseMoveLR += evp->value;
		    }
		    if(evp->code == 1)
		    {   // Mouse Up/Down
			//printf("Mouse moved %d up/down\n",evp->value);
			mouseMoveUD += evp->value;
		    }
		}

	    }
	}
    }
}

struct input_event is defined in /usr/include/linux/input.h


HTH

PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),Aeromodelling,1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

Return to “C/C++”

Who is online

Users browsing this forum: No registered users and 4 guests