LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 10-31-2006, 10:57 AM   #1
alexandre_fs
LQ Newbie
 
Registered: Oct 2006
Distribution: kubuntu 6.06
Posts: 18

Rep: Reputation: 0
optical mouse as a motion sensor - writting an aplication in C++ using Linux


Hello.

I am new to the Linux OS, and I am having some difficulties in creating an application (in c++) for reading the data transmitted by the computer mouse to the OS. ( I'm using linux because i think it's easier to access this type of information than in windows...)

The objective of the application is to use an optical mouse as a motion capture sensor (replacing the need to buy industrial encoders that are too expensive...)


Using the 'xxd' in the terminal, i can now understand the imps/2 protocol, and how to interpret each bit transmitted.


The command I use is: xxd -b -c 3 /dev/input/mice


Now, my problem

I want to create a C++ application for interpreting in real-time the data transmitted by the mouse. Until now I have thought about 3 processes, and none of them is working...

process #1: opening a pipe with the terminal, using the xxd command i previously explained:

void readSensor2()
{
FILE *fp;
char line[BUFSIZ];
if ((fp = popen("sudo xxd -ps -c 3 /dev/input/mice", "r")) != NULL)
{
while (fgets( line, BUFSIZ, fp) != NULL)
{
/*
if (strcmp(line, "080001")==0 )
printf("forward \n");
else if (strcmp(line, "2800ff")==0)
printf("backward \n");
else if (strcmp(line, "080100")==0)
printf("right \n");
else if (strcmp(line, "18ff00")==0)
printf("left \n");
*/
printf("%s", line);
}
pclose(fp);
}
}

really simple example, just to test the idea... the problem here, is that (i don't know why...) i can't have a real-time analysis... the data only appears each 2-3 seconds...

and if i do this:

void readSensor()
{
FILE *fp;
char line[BUFSIZ];
fp = popen("sudo xxd -l 3 -ps /dev/input/mice", "r");
fgets( line, BUFSIZ, fp);
if (strcmp(line, "080001")==0)
printf("forward \n");
else if (strcmp(line, "2800ff")==0)
printf("backward \n");
else if (strcmp(line, "080100")==0)
printf("right \n");
else if (strcmp(line, "18ff00")==0)
printf("left \n");

//printf("%s", line);
pclose(fp);
}

be constantly calling the readSensor() function, too much data is lost.


process #2: using 'ncurses'

The problem is that ncurses as far as I know, only captures the mouse movement in the screen. I mean, if the pointer is in the right upper corner, and you are still moving it further, no movement will be detected.


process #3: using GPM

here, i think relies my solution
but i can't find any good documentation for programming using gpm..
...and i can't compile the code... it says that

undefined reference to `Gpm_Open'
(...)

code:

#include <stdio.h>
#include <gpm.h>
#include <ncurses.h>

int my_handler(Gpm_Event *event, void *data)
{ printf("Event Type : %d at x=%d y=%d\n", event->type, event->x, event->y);
return 0;
}
int main()
{ Gpm_Connect conn;
int c;
conn.eventMask = ~0; /* Want to know about all the events */
conn.defaultMask = 0; /* don't handle anything by default */
conn.minMod = 0; /* want everything */
conn.maxMod = ~0; /* all modifiers included */

if(Gpm_Open(&conn, 0) == -1)
printf("Cannot connect to mouse server\n");

gpm_handler = my_handler;
while((c = Gpm_Getc(stdin)) != EOF)
printf("%c", c);
Gpm_Close();
return 0;
}


the best solution would definitly be without using gpm too...


any ideas??

thanks for reading this!!
 
Old 10-31-2006, 11:31 AM   #2
tuxdev
Senior Member
 
Registered: Jul 2005
Distribution: Slackware
Posts: 2,014

Rep: Reputation: 115Reputation: 115
Just open the device directly instead of using xxd. Or, ask the X-Server if you have that option. The X-Server might not give you movement data outside the window, though.

Also, please use [code] tags to preserve indentation and improve readability
 
Old 01-23-2008, 11:09 AM   #3
divot_powell
LQ Newbie
 
Registered: Nov 2007
Posts: 8

Rep: Reputation: 0
Just pick apart the xxd source....

I'm sure this doesn't matter anymore given the time of posting, however I'm working on a wee project very similar to this. And to work out how to do it real time, all I've done is picked apart the source to the xxd program and strip it down for what you need. I've done just that and ended up with:

Code:
#include <stdio.h>

char hexxa[] = "0123456789abcdef0123456789ABCDEF", *hexx = hexxa;

int main() {
  FILE *fp;
  signed short e, p = 3;

  if ((fp = fopen("/dev/input/mice", "r")) == NULL) {
    printf ("ERROR!! No such file\n");
    return 2;
  }

  while ((e = getc(fp)) != EOF) {
    if (e > 128) e = e - 256;
    printf("%d", e);
//    putchar(hexx[(e >> 4) & 0xf]);
//    putchar(hexx[(e     ) & 0xf]);
    if (!--p) {
      putchar('\n');
      p = 3;
    } else {
      putchar(' ');
    }
  }

  if (p < 3)
    putchar('\n');

  fclose(fp);

  return 0;
}

/* Modified from xxd source code originally provided and copyrighted by Juergen Weigert:
 * * "(c) 1990-1998 by Juergen Weigert (jnweiger@informatik.uni-erlangen.de)
 * * 
 * * Distribute freely and credit me,
 * * make money and share with me,
 * * lose money and don't ask me."
 */
If you want the hex output then comment out the printf statement, and uncomment the two putchar lines, however I found it more useful to have a decimal output:

40 12 -6

First number is direction and button presses, you'll have to work the exacts yourself. Negative second number for left, with the value as the speed, and positive for right. And finally the last number is negative for backwards, positive for forwards, and the value as speed.
 
Old 01-25-2008, 03:50 PM   #4
alexandre_fs
LQ Newbie
 
Registered: Oct 2006
Distribution: kubuntu 6.06
Posts: 18

Original Poster
Rep: Reputation: 0
hello. thank you for your post anyway. that project is terminated, but it still might be useful to someone else.

i ended up by listening the device files port directly and processing its information in real-time. it worked great!

if you need some info, just let me know.

bye
 
Old 01-26-2008, 11:57 AM   #5
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 70
@divot If you want to be as efficient as possible, you might want to use the evdev interface rather than mousedev. The reason is twofold:
  1. For evdev you are guaranteed to read 32 bytes at a time (and read() will block until data becomes available), so you don’t have to do character-by-character reading.
  2. The mousedev driver (as it is today) is a wrapper for the evdev driver. So by using evdev directly, you eliminate one layer of unnecessary wrapping.
Here is a thread about using evdev. Of course if all you want is a motion sensor, you can ignore any information about button presses, etc.
 
Old 01-27-2008, 05:12 PM   #6
divot_powell
LQ Newbie
 
Registered: Nov 2007
Posts: 8

Rep: Reputation: 0
Hiya, thanks for your help. I've noticed in testing that the evdev method creates alot more information and I've found that the first method provides all the information at a quick enough speed for my purposes. The box I'm using is also not quick enough to allow me to process all of that information..

I have a follow up question though. Firstly I'd like to point out this is a peculiar linux version for an arm architecture I'm using here so not everything works, for instance /dev/input/ does not exist and I'm using /dev/usbmouse for my purposes. I have (finally) managed to find a method for distinguishing between two mouses that are plugged into my device by creating two separate usbmouse files using mknod. Now I'm trying to find a way to have linux make a file, or a c program to combine those two seperate outputs so that they can be read at the same time. Such that it displays similar to x1 y1 x2 y2, where x1 and y1 are from mouse 1 and x2 and y2 are from mouse two. If one mouse moves but not the other, the relevant mouse just displays zeroes, whilst if they both move it displays the correct values. Do you know of any way to do this?

I have noticed that it is possible to have one file be updated by two seperate devices, the situation I was in at first, however there was no way of distinguishing which device it was that had updated the file.. If there is a method that easily distinguishes this I can decode the information contained within it easily enough myself, however I cannot find a way of distinguishing the information without using two separate files, which provides a noodlescratcher of a problem with blocked reads of two files...

Any help on this issue would be very much appreciated.

The fact that it's a peculiar version of linux might cause issues so here's my /proc/version:
Linux version 2.6.12.2-cm-x255 (nils@abode) (gcc version 4.0.3) #2 Fri Dec 15 15:47:24 GMT 2006
 
Old 01-27-2008, 10:25 PM   #7
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 70
Quote:
Originally Posted by divot_powell View Post
The box I'm using is also not quick enough to allow me to process all of that information..
You donít need to process all of it if you donít want to. I.e., ignore any events which are not of type EV_REL.
Quote:
Originally Posted by divot_powell View Post
I have a follow up question though. Firstly I'd like to point out this is a peculiar linux version for an arm architecture I'm using here so not everything works, for instance /dev/input/ does not exist and I'm using /dev/usbmouse for my purposes. I have (finally) managed to find a method for distinguishing between two mouses that are plugged into my device by creating two separate usbmouse files using mknod. Now I'm trying to find a way to have linux make a file, or a c program to combine those two seperate outputs so that they can be read at the same time. Such that it displays similar to x1 y1 x2 y2, where x1 and y1 are from mouse 1 and x2 and y2 are from mouse two. If one mouse moves but not the other, the relevant mouse just displays zeroes, whilst if they both move it displays the correct values. Do you know of any way to do this?
You can create the equivalent of /dev/mice, by making a node whose major number is 13 and whose minor number is 31. This device is exactly like /dev/mouse0 except that events from both mice are sent (asynchronously, except whole packets of 3 bytes or so donít overlap). But it seems like this is what your situation was before (i.e., it doesnít distinguish the events).

There is no kernel-provided interface for a single file that distinguishes the devices (AFAIK), but you can accomplish the same by either having two forked processes with some sort of IPC, or by using non-blocking file descriptors with select(). In fact, this is just the kind of thing youíre supposed to do with select().

Also note that it is most reliable to read all three (or four) bytes at once in a single call to read() and process them in a separate function. The reason I say four is that if your mouse is configured specially, it might sent four bytes instead of three (this is why the evdev interface is more reliable).
 
  


Reply

Tags
mouse, programming


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
microsoft comfort optical mouse 3000 linux linuxmandrake Linux - Hardware 1 02-09-2006 04:23 PM
Optical Mouse Won't Powerup in Linux carl0ski Linux - Hardware 3 11-11-2005 07:38 PM
how to install an optical mouse in Linux? xiaochao Linux - Hardware 2 08-04-2004 11:25 PM
mouse motion xlord Linux - Newbie 1 06-14-2004 02:38 PM
Logitech Mouseman Optical Duel Sensor does not work limdeswein Linux - Hardware 8 02-13-2004 07:42 PM


All times are GMT -5. The time now is 05:52 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration