vrpn  07.33
Virtual Reality Peripheral Network
vrpn_Mouse.C
Go to the documentation of this file.
1 /* file: vrpn_Mouse.cpp
2  * author: Mike Weiblen mew@mew.cx 2004-01-14
3  * copyright: (C) 2003,2004 Michael Weiblen
4  * license: Released to the Public Domain.
5  * depends: gpm 1.19.6, VRPN 06_04
6  * tested on: Linux w/ gcc 2.95.4
7  * references: http://mew.cx/ http://vrpn.org/
8  * http://linux.schottelius.org/gpm/
9 */
10 
11 #include <stdio.h> // for NULL, fprintf, printf, etc
12 #include <string.h> // for strncpy
13 
14 #include "vrpn_BaseClass.h" // for ::vrpn_TEXT_ERROR
15 #include "vrpn_Mouse.h"
16 #include "vrpn_Serial.h" // for vrpn_open_commport, etc
17 
18 #if defined(linux) && defined(VRPN_USE_GPM_MOUSE)
19 #include <gpm.h> // for Gpm_Event, Gpm_Connect, etc
20 #endif
21 
22 
23 #if !( defined(_WIN32) && defined(VRPN_USE_WINSOCK_SOCKETS) )
24 # include <sys/select.h> // for select, FD_ISSET, FD_SET, etc
25 #endif
26 
27 #ifdef _WIN32
28 #include <windows.h>
29 
30 #pragma comment (lib, "user32.lib")
31 
32 // Fix sent in by Andrei State to make this compile under Visual Studio 6.0.
33 // If you need this, you also have to copy multimon.h from the DirectX or
34 // another Windows SDK into a place where the compiler can find it.
35 #ifndef SM_XVIRTUALSCREEN
36 #define COMPILE_MULTIMON_STUBS
37 #include "multimon.h"
38 #endif
39 
40 #endif
41 
43 
44 vrpn_Mouse::vrpn_Mouse( const char* name, vrpn_Connection * cxn ) :
45  vrpn_Analog( name, cxn ),
46  vrpn_Button_Filter( name, cxn )
47 {
48  int i;
49 
50  // initialize the vrpn_Analog
52  for( i = 0; i < vrpn_Analog::num_channel; i++) {
54  }
55 
56  // initialize the vrpn_Button_Filter
58  for( i = 0; i < vrpn_Button_Filter::num_buttons; i++) {
60  }
61 
62 #if defined(linux) && defined(VRPN_USE_GPM_MOUSE)
63  // attempt to connect to the GPM server
64  gpm_zerobased = 1;
65  gpm_visiblepointer = 1;
66 
67  Gpm_Connect gc;
68  gc.eventMask = ~0;
69  gc.defaultMask = GPM_MOVE | GPM_HARD;
70  gc.maxMod = 0;
71  gc.minMod = 0;
72 
73  if( Gpm_Open( &gc, 0 ) < 0 )
74  {
75  // either GPM server is not running, or we're trying to run
76  // on an xterm.
77  throw GpmOpenFailure();
78  }
79 
80  set_alerts( 1 );
81 #elif defined(_WIN32)
82  // Nothing needs to be opened under Windows; we just make direct
83  // calls below to find the values.
84 #else
85  fprintf(stderr,"vrpn_Mouse::vrpn_Mouse() Not implement on this architecture\n");
86 #endif
87 }
88 
90 
92 {
93 #if defined(linux) && defined(VRPN_USE_GPM_MOUSE)
94  Gpm_Close();
95 #endif
96 }
97 
99 
101 {
102  get_report();
103  server_mainloop();
104 }
105 
107 
109 {
110 #if defined(linux) && defined(VRPN_USE_GPM_MOUSE)
111  fd_set readset;
112 
113  FD_ZERO( &readset );
114  FD_SET( gpm_fd, &readset );
115  struct timeval timeout = { 0, 0 };
116  select( gpm_fd+1, &readset, NULL, NULL, &timeout );
117  if( ! FD_ISSET( gpm_fd, &readset ) )
118  return 0;
119 
120  Gpm_Event evt;
121  if( Gpm_GetEvent( &evt ) <= 0 )
122  return 0;
123 
124  if( evt.type & GPM_UP )
125  {
126  if( evt.buttons & GPM_B_LEFT ) buttons[0] = 0;
127  if( evt.buttons & GPM_B_MIDDLE ) buttons[1] = 0;
128  if( evt.buttons & GPM_B_RIGHT ) buttons[2] = 0;
129  }
130  else
131  {
132  buttons[0] = (evt.buttons & GPM_B_LEFT) ? 1 : 0;
133  buttons[1] = (evt.buttons & GPM_B_MIDDLE) ? 1 : 0;
134  buttons[2] = (evt.buttons & GPM_B_RIGHT) ? 1 : 0;
135  }
136 
137  channel[0] = (vrpn_float64) evt.dx / gpm_mx;
138  channel[1] = (vrpn_float64) evt.dy / gpm_my;
139  return 1;
140 #elif defined(_WIN32)
141  const unsigned LEFT_MOUSE_BUTTON = 0x01;
142  const unsigned RIGHT_MOUSE_BUTTON = 0x02;
143  const unsigned MIDDLE_MOUSE_BUTTON = 0x04;
144 
145  // Find out if the mouse buttons are pressed.
146  if (0x80000 & GetKeyState(LEFT_MOUSE_BUTTON)) {
147  vrpn_Button::buttons[0] = 1;
148  } else {
149  vrpn_Button::buttons[0] = 0;
150  }
151  if (0x80000 & GetKeyState(MIDDLE_MOUSE_BUTTON)) {
152  vrpn_Button::buttons[1] = 1;
153  } else {
154  vrpn_Button::buttons[1] = 0;
155  }
156  if (0x80000 & GetKeyState(RIGHT_MOUSE_BUTTON)) {
157  vrpn_Button::buttons[2] = 1;
158  } else {
159  vrpn_Button::buttons[2] = 0;
160  }
161 
162  // Find the position of the cursor in X,Y with range 0..1 across the screen
163  POINT curPos;
164  GetCursorPos(&curPos);
165  vrpn_Analog::channel[0] = (vrpn_float64)(curPos.x - GetSystemMetrics(SM_XVIRTUALSCREEN)) / GetSystemMetrics(SM_CXVIRTUALSCREEN);
166  vrpn_Analog::channel[1] = (vrpn_float64)(curPos.y - GetSystemMetrics(SM_YVIRTUALSCREEN)) / GetSystemMetrics(SM_CYVIRTUALSCREEN);
167 
168  vrpn_gettimeofday( &timestamp, NULL );
169  report_changes();
170  return 1;
171 #else
172  return 0;
173 #endif
174 }
175 
177 
178 void vrpn_Mouse::report_changes( vrpn_uint32 class_of_service )
179 {
182 
183  vrpn_Analog::report_changes( class_of_service );
185 }
186 
188 
189 void vrpn_Mouse::report( vrpn_uint32 class_of_service )
190 {
193 
194  vrpn_Analog::report( class_of_service );
196 }
197 
199 #define BUTTON_READY (1)
200 #define BUTTON_FAIL (-1)
201 
202 // (RDK) serial mouse wired up as button device
204  const char *port, int baud, vrpn_MOUSETYPE type)
205  : vrpn_Button_Filter(name, c)
206 {
208  bool printed_error = false;
209  // Find out the port name and baud rate;
210  if (port == NULL) {
211  fprintf(stderr,"vrpn_Button_SerialMouse: NULL port name\n");
212  return;
213  } else {
214  strncpy(portname, port, sizeof(portname));
215  portname[sizeof(portname)-1] = '\0';
216  }
217  num_buttons = 3;
218  baudrate = baud;
219 
220  // Open the serial port we are going to use
222  fprintf(stderr,"vrpn_Button_SerialMouse: Cannot open serial port\n");
223  return;
224  }
225 
226  for (vrpn_int32 i = 0; i < num_buttons; i++) {
227  buttons[i] = lastbuttons[i] = 0;
229  }
230 
231  mousetype = type;
232  lastL = lastR = 0;
233  // first time in read(), this will get set to 0
235 
236  // Say we are ready and find out what time it is
238  vrpn_gettimeofday(&timestamp, NULL);
239 }
240 
242 {
243  // Call the generic server mainloop, since we are a server
244  server_mainloop();
245 
246  switch (status) {
247  case BUTTON_READY:
248  read();
249  report_changes();
250  break;
251  case BUTTON_FAIL:
252  {
253  if (!printed_error) break;
254  printed_error = 0;
255  send_text_message("vrpn_Button_SerialMouse failure!", timestamp, vrpn_TEXT_ERROR);
256  }
257  break;
258  }
259 }
260 
261 // Fill in the buttons[] array with the current value of each of the
262 // buttons For a description of the protocols for a Microsoft 3button
263 // mouse and a MouseSystems mouse, see http://www.hut.fi/~then/mytexts/mouse.html
265 {
266  // Make sure we're ready to read
267  if (status != BUTTON_READY) {
268  return;
269  }
270 
271  unsigned char buffer;
272 
273  // process as long as we can get characters
274  int num = 1;
275  int debounce = 0;
276  while (num)
277  {
278  num = vrpn_read_available_characters(serial_fd, &buffer, 1);
279 
280  if (num <= 0) {
281  if (debounce) {
282 #ifdef VERBOSE
283  fprintf (stderr,"state: %d %d %d last: %d %d %d\n",
284  buttons[0],buttons[1],buttons[2],
285  lastL, lastM, lastR);
286 #endif
287  lastL = buttons[0];
288  lastM = buttons[1];
289  lastR = buttons[2];
290  }
291  return; // nothing there or error, so return
292  }
293 
294  switch (mousetype) {
296  // a mouse capable of 3 button emulation
297  // this mouse encodes its buttons in a byte that is one of
298  // 0xc0 0xd0 0xe0 0xf0.
299 
300  // Throw away all bytes that are not one of C0, D0, E0 or F0.
301  if ( (buffer != 0xc0) && (buffer != 0xd0) &&
302  (buffer != 0xe0) && (buffer != 0xf0) ) {
303  continue;
304  }
305 
306  buttons[0] = (unsigned char)( (buffer & 0x20)?1:0 );
307  buttons[2] = (unsigned char)( (buffer & 0x10)?1:0 );
308  // middle button check:: we get here without a change in left or right
309  // This means that we toggle the middle button by moving the mouse
310  // around while not pressing or releasing the other buttons!
311  if ((buttons[0] == lastL) && (buttons[2] == lastR) && !debounce) {
312  buttons[1] = (unsigned char)( lastM?0:1 );
313  }
314  debounce = 1;
315  break;
316 
317  case MOUSESYSTEMS:
318 
319  // mousesystems (real PC 3 button mouse) protocol
320  // The pc three button mouse encodes its buttons in a byte
321  // that looks like 1 0 0 0 0 lb mb rb
322 
323  if ((buffer & 0xf8) != 0x80) { // Ignore all bytes but first in record
324  continue;
325  }
326  debounce = 1;
327  buttons[0] = (unsigned char)( (buffer & 4)?0:1 );
328  buttons[1] = (unsigned char)( (buffer & 2)?0:1 );
329  buttons[2] = (unsigned char)( (buffer & 1)?0:1 );
330  break;
331 
332  default:
333  printf("vrpn_Button_SerialMouse::read(): Unknown mouse type\n");
334  break;
335  } // switch
336  } // while (num)
337 }
338 
339 
340 /*EOF*/
void server_mainloop(void)
Handles functions that all servers should provide in their mainloop() (ping/pong, for example) Should...
virtual void report_changes(vrpn_uint32 class_of_service=vrpn_CONNECTION_LOW_LATENCY, const struct timeval time=vrpn_ANALOG_NOW)
Send a report only if something has changed (for servers) Optionally, tell what time to stamp the val...
Definition: vrpn_Analog.C:71
int vrpn_open_commport(const char *portname, long baud, int charsize, vrpn_SER_PARITY parity, bool rts_flow)
Open a serial port, given its name and baud rate.
Definition: vrpn_Serial.C:54
virtual void mainloop(void)
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
Definition: vrpn_Mouse.C:241
vrpn_int32 num_buttons
Definition: vrpn_Button.h:47
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
Definition: vrpn_Mouse.C:100
vrpn_Serial: Pulls all the serial port routines into one file to make porting to new operating system...
#define BUTTON_FAIL
Definition: vrpn_Mouse.C:200
vrpn_float64 channel[vrpn_CHANNEL_MAX]
Definition: vrpn_Analog.h:38
vrpn_MOUSETYPE mousetype
Definition: vrpn_Mouse.h:114
Generic connection class not specific to the transport mechanism.
virtual void report(vrpn_uint32 class_of_service=vrpn_CONNECTION_LOW_LATENCY, const struct timeval time=vrpn_ANALOG_NOW)
Send a report whether something has changed or not (for servers) Optionally, tell what time to stamp ...
Definition: vrpn_Analog.C:94
#define BUTTON_READY
Definition: vrpn_Mouse.C:199
struct timeval timestamp
time of last report from device
Definition: vrpn_Mouse.h:82
All types of client/server/peer objects in VRPN should be derived from the vrpn_BaseClass type descri...
virtual void report_changes(void)
Definition: vrpn_Button.C:382
virtual void report(vrpn_uint32 class_of_service=vrpn_CONNECTION_LOW_LATENCY)
send report whether or not changed
Definition: vrpn_Mouse.C:189
const int vrpn_BUTTON_MOMENTARY
Definition: vrpn_Button.h:18
vrpn_int32 num_channel
Definition: vrpn_Analog.h:40
int vrpn_read_available_characters(int comm, unsigned char *buffer, size_t bytes)
Definition: vrpn_Serial.C:512
virtual ~vrpn_Mouse()
Definition: vrpn_Mouse.C:91
int send_text_message(const char *msg, struct timeval timestamp, vrpn_TEXT_SEVERITY type=vrpn_TEXT_NORMAL, vrpn_uint32 level=0)
Sends a NULL-terminated text message from the device d_sender_id.
struct timeval timestamp
Definition: vrpn_Button.h:48
virtual int get_report()
Try to read reports from the device. Returns 1 if msg received, or 0 if none received.
Definition: vrpn_Mouse.C:108
#define vrpn_gettimeofday
Definition: vrpn_Shared.h:89
All button servers should derive from this class, which provides the ability to turn any of the butto...
Definition: vrpn_Button.h:65
vrpn_int32 buttonstate[vrpn_BUTTON_MAX_BUTTONS]
Definition: vrpn_Button.h:67
unsigned char lastbuttons[vrpn_BUTTON_MAX_BUTTONS]
Definition: vrpn_Button.h:45
vrpn_MOUSETYPE
Definition: vrpn_Mouse.h:97
vrpn_Mouse(const char *name, vrpn_Connection *cxn)
Definition: vrpn_Mouse.C:44
unsigned char buttons[vrpn_BUTTON_MAX_BUTTONS]
Definition: vrpn_Button.h:44
struct timeval timestamp
Definition: vrpn_Analog.h:41
vrpn_float64 last[vrpn_CHANNEL_MAX]
Definition: vrpn_Analog.h:39
void set_alerts(vrpn_int32)
Definition: vrpn_Button.C:168
vrpn_Button_SerialMouse(const char *name, vrpn_Connection *connection, const char *port, int baud, vrpn_MOUSETYPE type)
Definition: vrpn_Mouse.C:203