vrpn  07.33
Virtual Reality Peripheral Network
vrpn_Button.C
Go to the documentation of this file.
1 #include <stdio.h> // for fprintf, stderr, NULL, etc
2 #ifndef _WIN32_WCE
3 #include <fcntl.h> // for open, O_RDWR
4 #endif
5 #include <string.h> // for strncpy
6 
7 #if defined(linux) && !defined(VRPN_CLIENT_ONLY)
8 #include <linux/lp.h> // for LPGETSTATUS
9 #include <sys/ioctl.h> // for ioctl
10 #endif
11 
12 #include "vrpn_Connection.h" // for vrpn_Connection, etc
13 #ifndef VRPN_CLIENT_ONLY
14 #include "vrpn_Serial.h"
15 #endif
16 // Include vrpn_Shared.h _first_ to avoid conflicts with sys/time.h
17 // and unistd.h
18 #include "vrpn_Shared.h" // for timeval, vrpn_buffer, etc
19 
20 #ifdef linux
21 #include <unistd.h>
22 #endif
23 #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(_WIN32_WCE)
24 #include <conio.h> // for _inp()
25 #endif
26 
27 #if (defined(sgi) && (!defined(VRPN_CLIENT_ONLY)))
28 #include <gl/device.h>
29 // need these for the gl based setdblight calls
30 #include <gl/gl.h>
31 #endif
32 
33 #include "vrpn_Button.h"
34 
35 #define BUTTON_READY (1)
36 #define BUTTON_FAIL (-1)
37 
38 // Bits in the status register
39 #ifndef VRPN_CLIENT_ONLY
40 static const unsigned char PORT_ERROR = (1 << 3);
41 static const unsigned char PORT_SLCT = (1 << 4);
42 static const unsigned char PORT_PE = (1 << 5);
43 static const unsigned char PORT_ACK = (1 << 6);
44 static const unsigned char PORT_BUSY = (1 << 7);
45 static const unsigned char BIT_MASK =
46  PORT_ERROR | PORT_SLCT | PORT_PE | PORT_ACK | PORT_BUSY;
47 
48 // message constants for the PinchGlove code.
49 const unsigned char PG_START_BYTE_DATA(0x80);
50 const unsigned char PG_START_BYTE_DATA_TIME(0x81);
51 //const unsigned char PG_START_BYTE_TEXT(0x82);
52 const unsigned char PG_END_BYTE(0x8F);
53 #endif
54 
55 static int VRPN_CALLBACK
56 client_msg_handler(void *userdata, vrpn_HANDLERPARAM p);
57 
58 #define PACK_ADMIN_MESSAGE(i, event) \
59  { \
60  char msgbuf[1000]; \
61  vrpn_int32 len = encode_to(msgbuf, i, event); \
62  if (d_connection->pack_message(len, timestamp, admin_message_id, \
63  d_sender_id, msgbuf, \
64  vrpn_CONNECTION_RELIABLE)) { \
65  fprintf(stderr, "vrpn_Button: can't write message: tossing\n"); \
66  } \
67  }
68 #define PACK_ALERT_MESSAGE(i, event) \
69  { \
70  char msgbuf[1000]; \
71  vrpn_int32 len = encode_to(msgbuf, i, event); \
72  if (d_connection->pack_message(len, timestamp, alert_message_id, \
73  d_sender_id, msgbuf, \
74  vrpn_CONNECTION_RELIABLE)) { \
75  fprintf(stderr, "vrpn_Button: can't write message: tossing\n"); \
76  } \
77  }
78 
79 #define PACK_MESSAGE(i, event) \
80  { \
81  char msgbuf[1000]; \
82  vrpn_int32 len = encode_to(msgbuf, i, event); \
83  if (d_connection->pack_message(len, timestamp, change_message_id, \
84  d_sender_id, msgbuf, \
85  vrpn_CONNECTION_RELIABLE)) { \
86  fprintf(stderr, "vrpn_Button: can't write message: tossing\n"); \
87  } \
88  }
89 
91  : vrpn_BaseClass(name, c)
92  , num_buttons(0)
93 {
95 
96  // Set the time to 0 just to have something there.
97  timestamp.tv_usec = timestamp.tv_sec = 0;
98  for (vrpn_int32 i = 0; i < vrpn_BUTTON_MAX_BUTTONS; i++) {
99  buttons[i] = lastbuttons[i] = 0;
100  }
101 }
102 
104 {
105  // used to handle button strikes
107  d_connection->register_message_type("vrpn_Button Change");
108 
109  // used to handle button states reports
111  d_connection->register_message_type("vrpn_Button States");
112 
113  // to handle button state changes -- see Buton_Filter should register a
114  // handler
115  // for this ID -- ideally the message will be ignored otherwise
116  admin_message_id = d_connection->register_message_type("vrpn_Button Admin");
117 
118  return 0;
119 }
120 
121 // virtual
123 {
124 
125  // do nothing
126 }
127 
129  : vrpn_Button(name, c)
130 {
131  if ((d_sender_id == -1) || (admin_message_id == -1)) {
132  fprintf(stderr, "vrpn_Button: Can't register IDs\n");
133  d_connection = NULL;
134  }
135  register_autodeleted_handler(admin_message_id, client_msg_handler, this);
136 
137  // setup message id type for alert messages to alert a device about changes
138  alert_message_id = d_connection->register_message_type("vrpn_Button Alert");
139  send_alerts = 0; // used to turn on/off alerts -- send and admin message
140  // from
141  // remote to turn it on -- or server side call set_alerts();
142 
143  // Set up callback handler for ping message from client so that it
144  // sends the button states. This will make sure that the other side hears
145  // the initial button states. Also set this up
146  // to fire on the "new connection" system message.
147 
149  d_sender_id);
153 
154  // set button default buttonstates
155  for (vrpn_int32 i = 0; i < vrpn_BUTTON_MAX_BUTTONS; i++) {
157  }
158  return;
159 }
160 
162 {
164  me->report_states();
165  return 0;
166 }
167 
169 {
170  if (i == 0 || i == 1)
171  send_alerts = i;
172  else
173  fprintf(stderr, "Invalid send_alert state\n");
174  return;
175 }
176 
177 void vrpn_Button_Filter::set_momentary(vrpn_int32 which_button)
178 {
179  if (which_button >= num_buttons) {
180  char msg[200];
181  sprintf(msg, "vrpn_Button::set_momentary() buttons id %d is greater "
182  "than the number of buttons(%d)\n",
183  which_button, num_buttons);
185  return;
186  }
187  buttonstate[which_button] = vrpn_BUTTON_MOMENTARY;
189 }
190 
191 void vrpn_Button::set_momentary(vrpn_int32 which_button)
192 {
193  if (which_button >= num_buttons) {
194  char msg[200];
195  sprintf(msg, "vrpn_Button::set_momentary() buttons id %d is greater "
196  "than the number of buttons(%d)\n",
197  which_button, num_buttons);
199  return;
200  }
202 }
203 
204 void vrpn_Button_Filter::set_toggle(vrpn_int32 which_button,
205  vrpn_int32 current_state)
206 {
207  if (which_button >= num_buttons) {
208  char msg[200];
209  sprintf(msg, "vrpn_Button::set_toggle() buttons id %d is greater then "
210  "the number of buttons(%d)\n",
211  which_button, num_buttons);
213  return;
214  }
215  if (current_state == vrpn_BUTTON_TOGGLE_ON) {
216  buttonstate[which_button] = vrpn_BUTTON_TOGGLE_ON;
217  if (send_alerts)
219  }
220  else {
221  buttonstate[which_button] = vrpn_BUTTON_TOGGLE_OFF;
222  if (send_alerts)
224  }
225 }
226 void vrpn_Button::set_toggle(vrpn_int32 which_button, vrpn_int32 current_state)
227 {
228  if (which_button >= num_buttons) {
229  char msg[200];
230  sprintf(msg, "vrpn_Button::set_toggle() buttons id %d is greater then "
231  "the number of buttons(%d)\n",
232  which_button, num_buttons);
234  return;
235  }
236  if (current_state == vrpn_BUTTON_TOGGLE_ON) {
238  }
239  else {
241  }
242 }
243 
245 {
246  for (vrpn_int32 i = 0; i < num_buttons; i++) {
250  }
251  }
252 }
253 
255 {
257 }
258 
259 void vrpn_Button::set_all_toggle(vrpn_int32 default_state)
260 {
261  PACK_ADMIN_MESSAGE(vrpn_ALL_ID, default_state);
262 }
263 
264 void vrpn_Button_Filter::set_all_toggle(vrpn_int32 default_state)
265 {
266  for (vrpn_int32 i = 0; i < num_buttons; i++) {
268  buttonstate[i] = default_state;
269  if (send_alerts) {
270  PACK_ALERT_MESSAGE(i, default_state);
271  }
272  }
273  }
274 }
275 
277 {
278  vrpn_int32 i;
279  printf("CurrButtons: ");
280  for (i = num_buttons - 1; i >= 0; i--) {
281  printf("%c", buttons[i] ? '1' : '0');
282  }
283  printf("\n");
284 
285  printf("LastButtons: ");
286  for (i = num_buttons - 1; i >= 0; i--) {
287  printf("%c", lastbuttons[i] ? '1' : '0');
288  }
289  printf("\n");
290 }
291 
298 vrpn_int32 vrpn_Button::encode_to(char *buf, vrpn_int32 button,
299  vrpn_int32 state)
300 {
301  char *bufptr = buf;
302  int buflen = 1000;
303 
304  // Message includes: vrpn_int32 buttonNum, vrpn_int32 state
305  vrpn_buffer(&bufptr, &buflen, button);
306  vrpn_buffer(&bufptr, &buflen, state);
307 
308  return 1000 - buflen;
309 }
310 
317 vrpn_int32 vrpn_Button::encode_states_to(char *buf)
318 {
319  // Message includes: vrpn_int32 number_of_buttons, vrpn_int32 states
320  // Byte order of each needs to be reversed to match network standard
321 
322  vrpn_int32 int_btn = num_buttons;
323  int buflen = (vrpn_BUTTON_MAX_BUTTONS + 1) * sizeof(vrpn_int32);
324 
325  vrpn_buffer(&buf, &buflen, int_btn);
326  for (int i = 0; i < num_buttons; i++) {
327  vrpn_int32 state = buttons[i];
328  vrpn_buffer(&buf, &buflen, state);
329  }
330 
331  return (num_buttons + 1) * sizeof(vrpn_int32);
332 }
333 
341 {
342  // Message includes: vrpn_int32 number_of_buttons, vrpn_int32 state
343  // Byte order of each needs to be reversed to match network standard
344 
345  vrpn_int32 int_btn = num_buttons;
346  int buflen = (vrpn_BUTTON_MAX_BUTTONS + 1) * sizeof(vrpn_int32);
347 
348  vrpn_buffer(&buf, &buflen, int_btn);
349  for (int i = 0; i < num_buttons; i++) {
350  vrpn_buffer(&buf, &buflen, buttonstate[i]);
351  }
352 
353  return (num_buttons + 1) * sizeof(vrpn_int32);
354 }
355 
356 static int VRPN_CALLBACK client_msg_handler(void *userdata, vrpn_HANDLERPARAM p)
357 {
358  vrpn_Button_Filter *instance = (vrpn_Button_Filter *)userdata;
359  const char *bufptr = p.buffer;
360  vrpn_int32 event;
361  vrpn_int32 buttonid;
362 
363  vrpn_unbuffer(&bufptr, &buttonid);
364  vrpn_unbuffer(&bufptr, &event);
365 
366  if (event == vrpn_BUTTON_MOMENTARY) {
367  if (buttonid == vrpn_ALL_ID)
368  instance->set_all_momentary();
369  else
370  instance->set_momentary(buttonid);
371  }
372  else if (event == vrpn_BUTTON_TOGGLE_OFF ||
373  event == vrpn_BUTTON_TOGGLE_ON) {
374  if (buttonid == vrpn_ALL_ID)
375  instance->set_all_toggle(event);
376  else
377  instance->set_toggle(buttonid, event);
378  }
379  return 0;
380 }
381 
383 {
384  vrpn_int32 i;
385 
386  // vrpn_Button::report_changes();
387  if (d_connection) {
388  for (i = 0; i < num_buttons; i++) {
389  switch (buttonstate[i]) {
391  if (buttons[i] != lastbuttons[i]) PACK_MESSAGE(i, buttons[i]);
392  break;
394  if (buttons[i] && !lastbuttons[i]) {
396  if (send_alerts)
398  PACK_MESSAGE(i, 0);
399  }
400  break;
402  if (buttons[i] && !lastbuttons[i]) {
404  if (send_alerts)
406  PACK_MESSAGE(i, 1);
407  }
408  break;
409  default:
410  fprintf(stderr, "vrpn_Button::report_changes(): Button %d in \
411  invalid state (%d)\n",
412  i, buttonstate[i]);
413  }
414  lastbuttons[i] = buttons[i];
415  }
416  }
417  else {
418  fprintf(stderr, "vrpn_Button: No valid connection\n");
419  }
420 }
421 
423 {
424  vrpn_int32 i;
425 
426  if (d_connection) {
427  for (i = 0; i < num_buttons; i++) {
428  if (buttons[i] != lastbuttons[i]) PACK_MESSAGE(i, buttons[i]);
429  lastbuttons[i] = buttons[i];
430  }
431  }
432  else {
433  fprintf(stderr, "vrpn_Button: No valid connection\n");
434  }
435 }
436 
438 {
439  // msgbuf must be int32-aligned!
440  vrpn_int32 ibuf[vrpn_BUTTON_MAX_BUTTONS + 1];
441  char *msgbuf = (char *)ibuf;
442 
443  vrpn_int32 len;
444 
445  len = vrpn_Button::encode_states_to(msgbuf);
446  if (d_connection &&
448  d_sender_id, msgbuf,
450  fprintf(stderr, "vrpn_Button: cannot write states message: tossing\n");
451  }
452 }
453 
454 #ifndef VRPN_CLIENT_ONLY
455 
457  int numbuttons)
458  : vrpn_Button_Filter(name, c)
459 {
460  if (numbuttons > vrpn_BUTTON_MAX_BUTTONS) {
462  }
463  else {
464  num_buttons = numbuttons;
465  }
466 }
467 
469 
471 {
472  server_mainloop();
473  report_changes();
474 }
475 
476 int vrpn_Button_Server::set_button(int button, int new_value)
477 {
478  if ((button < 0) || (button >= num_buttons)) {
479  return -1;
480  }
481 
482  buttons[button] = (unsigned char)(new_value != 0);
483 
484  return 0;
485 }
486 
488  vrpn_Connection *c,
489  int numbuttons,
490  vrpn_float64 rate)
491  : vrpn_Button_Filter(name, c)
492 {
493  if (numbuttons > vrpn_BUTTON_MAX_BUTTONS) {
495  }
496  else {
497  num_buttons = numbuttons;
498  }
499 
500  _update_rate = rate;
501 
502  // IN A REAL SERVER, open the device that will service the buttons here
503 }
504 
506 {
507  struct timeval current_time;
508  int i;
509 
510  // Call the generic server mainloop, since we are a server
511  server_mainloop();
512 
513  // See if its time to generate a new report (every 1 second).
514  // IN A REAL SERVER, this check would not be done; although the
515  // time of the report would be updated to the current time so
516  // that the correct timestamp would be issued on the report.
517  vrpn_gettimeofday(&current_time, NULL);
518  if (vrpn_TimevalDuration(current_time, timestamp) >=
519  1000000.0 / _update_rate) {
520 
521  // Update the time
522  timestamp.tv_sec = current_time.tv_sec;
523  timestamp.tv_usec = current_time.tv_usec;
524 
525  // Update the values for the buttons, to say that each one has
526  // switched its state.
527  // THIS CODE WILL BE REPLACED by the user code that
528  // actually reads from the button devices and fills in buttons[]
529  // appropriately.
530  for (i = 0; i < num_buttons; i++) {
531  buttons[i] = !lastbuttons[i];
532  }
533 
534  // Send reports. Stays the same in a real server.
535  report_changes();
536  }
537 }
538 
539 // changed to take raw port hex address
541  int portno, unsigned porthex)
542  : vrpn_Button_Filter(name, c)
543 {
544 #ifdef linux
545  const char *portname;
546  switch (portno) {
547  case 1:
548  portname = "/dev/lp0";
549  break;
550  case 2:
551  portname = "/dev/lp1";
552  break;
553  case 3:
554  portname = "/dev/lp2";
555  break;
556  default:
557  fprintf(stderr, "vrpn_Button_Parallel: "
558  "Bad port number (%x) for Linux lp#\n",
559  portno);
561  portname = "UNKNOWN";
562  break;
563  }
564 
565  // Open the port
566  if ((port = open(portname, O_RDWR)) < 0) {
567  perror("vrpn_Button_Parallel::vrpn_Button_Parallel(): "
568  "Can't open port");
569  fprintf(stderr, "vrpn_Button_Parallel::vrpn_Button_Parallel(): "
570  "Can't open port %s\n",
571  portname);
573  return;
574  }
575 #elif _WIN32
576  // if on NT we need a device driver to do direct reads
577  // from the parallel port
578  if (!openGiveIO()) {
579  fprintf(stderr, "vrpn_Button: need giveio driver for port access!\n");
580  fprintf(stderr, "vrpn_Button: can't use vrpn_Button()\n");
582  return;
583  }
584  if (porthex != 0) // using direct hex port address
585  port = porthex;
586  else { // using old style port 1, 2, or 3
587  switch (portno) {
588  // we use this mapping, although LPT? can actually
589  // have different addresses.
590  case 1:
591  port = 0x378;
592  break; // usually LPT1
593  case 2:
594  port = 0x3bc;
595  break; // usually LPT2
596  case 3:
597  port = 0x278;
598  break; // usually LPT3
599  default:
600  fprintf(stderr, "vrpn_Button_Parallel: Bad port number (%d)\n",
601  portno);
603  break;
604  }
605  }
606  fprintf(stderr, "vrpn_Button_Parallel: Using port %x\n", port);
607 #else // _WIN32
608  fprintf(stderr, "vrpn_Button_Parallel: not supported on this platform\n?");
610  portno = portno; // unused argument
611  return;
612 #endif
613 
614 #if defined(linux) || defined(_WIN32)
615 // Set the INIT line on the device to provide power to the python
616 // update: don't need this for builtin LPT1 on DELLs, but do need it
617 // for warp9 PCI parallel port. Added next lines. BCE Nov07.00
618 // Setting Bit 1 high also for a specific HiBall system
619 // requirement (IR blocking device on same port)
620 // - BCE 08 July 03
621 
622 #ifdef _outp
623  const unsigned short DATA_REGISTER_OFFSET = 0;
624  _outp((unsigned short)(port + DATA_REGISTER_OFFSET), 3);
625 #else
626  fprintf(stderr, "vrpn_Button_Parallel: Not setting bit 0 on Linux, may not "
627  "work with all ports\n");
628 #endif
629 
630  // Zero the button states
631  num_buttons = 5; // XXX This is specific to the python
632  for (vrpn_int32 i = 0; i < num_buttons; i++) {
633  buttons[i] = lastbuttons[i] = 0;
634  }
635 
638 #endif
639 }
640 
642 {
643 #ifdef linux
644  if (port >= 0) {
645  close(port);
646  }
647 #endif
648 }
649 
651  int p)
652  : vrpn_Button_Parallel(name, c, p)
653  , d_first_fail(true)
654 {
655 }
656 
658  int p, unsigned ph)
659  : vrpn_Button_Parallel(name, c, p, ph)
660  , d_first_fail(true)
661 {
662 }
663 
665 {
666  // Call the generic server mainloop, since we are a server
667  server_mainloop();
668 
669  switch (status) {
670  case BUTTON_READY:
671  read();
672  report_changes();
673  break;
674  case BUTTON_FAIL:
675  if (d_first_fail) {
676  d_first_fail = false;
677  fprintf(stderr, "vrpn_Button_Python failure!\n");
679  }
680  break;
681  }
682 }
683 
684 // Fill in the buttons[] array with the current value of each of the
685 // buttons. Debounce the buttons (make sure that they have had the
686 // same value for the past several times to debounce noise).
688 {
689  int i;
690  const int debounce_count = 30;
691  int status_register[debounce_count];
692 
693  // Make sure we're ready to read
694  if (status != BUTTON_READY) {
695  return;
696  }
697 
698 // Read from the status register, read 3 times to debounce noise.
699 #ifdef linux
700  for (i = 0; i < debounce_count; i++)
701  if (ioctl(port, LPGETSTATUS, &status_register[i]) == -1) {
702  perror("vrpn_Button_Python::read(): ioctl() failed");
703  return;
704  }
705 
706 #elif _WIN32
707 #ifndef __CYGWIN__
708  const unsigned short STATUS_REGISTER_OFFSET = 1;
709  for (i = 0; i < debounce_count; i++) {
710 #ifdef _inp
711  status_register[i] =
712  _inp((unsigned short)(port + STATUS_REGISTER_OFFSET));
713 #else
714  status_register[i] = 0;
715 #endif
716  }
717 #else
718  for (i = 0; i < debounce_count; i++) {
719  status_register[i] = 0;
720  }
721 #endif
722 #else
723  for (i = 0; i < debounce_count; i++) {
724  status_register[i] = 0;
725  }
726 #endif
727  for (i = 0; i < debounce_count; i++) {
728  status_register[i] = status_register[i] & BIT_MASK;
729  }
730 
731  // Make sure they are all the same; if not, return and assume that
732  // we are still debouncing.
733  for (i = 1; i < debounce_count; i++) {
734  if (status_register[0] != status_register[i]) {
735  return;
736  }
737  }
738 
739  // Assign values to the bits based on the control signals
740  buttons[0] = ((status_register[0] & PORT_SLCT) == 0);
741  buttons[1] = ((status_register[0] & PORT_BUSY) != 0);
742  buttons[2] = ((status_register[0] & PORT_PE) == 0);
743  buttons[3] = ((status_register[0] & PORT_ERROR) == 0);
744  buttons[4] = ((status_register[0] & PORT_ACK) == 0);
745 
747 }
748 
750  const char *port, long baud)
751  : vrpn_Button_Filter(name, c)
752 {
753  // port name and baud rate
754  if (port == NULL) {
755  fprintf(stderr, "vrpn_Button_Serial: NULL port name\n");
757  return;
758  }
759  else {
760  strncpy(portname, port, sizeof(portname));
761  portname[sizeof(portname) - 1] = '\0';
762  }
763  baudrate = baud;
764 
765  // Open the serial port
766  if ((serial_fd = vrpn_open_commport(portname, baudrate)) == -1) {
767  fprintf(stderr, "vrpn_Button_Serial: Cannot Open serial port\n");
769  }
770 
771  // Reset the tracker and find out what time it is
774 }
775 
777 
778 // init pinch glove to send hand data only
780  vrpn_Connection *c,
781  const char *port, long baud)
782  : vrpn_Button_Serial(name, c, port, baud)
783  , reported_failure(false)
784 {
785  num_buttons = 10; // 0-4: right, 5-9: left starting from thumb
787 
788  // check if the number of buttons is not more than max allowed.
790  fprintf(stderr,
791  "vrpn_Button_PinchGlove: Too many buttons. The limit is ");
792  fprintf(stderr, "%i but this device has %i.\n", vrpn_BUTTON_MAX_BUTTONS,
793  num_buttons);
795  }
796 
797  // set glove to report with no timestamp
799 
800  // initialize the buttons
801  for (vrpn_int32 i = 0; i < num_buttons; i++)
803 
804  // Reset the tracker and find out what time it is
806 }
807 
809 {
810  // Call the generic server mainloop, since we are a server
811  server_mainloop();
812 
813  switch (status) {
814  case BUTTON_READY:
815  read();
816  report_changes();
817  break;
818  case BUTTON_FAIL: {
819  if (!reported_failure) {
820  reported_failure = true;
821  fprintf(stderr, "vrpn_Button_PinchGlove failure!\n");
822  }
823  } break;
824  }
825  return;
826 }
827 
828 // Pinch glove should only report hand data(see contructor). If the message has
829 // time stamp data change the the message type by sending command to just send
830 // hand data. Any other kind of message is ignored and the buffer is read until
831 // end of message byte(PG_END_BYTE) is reached.
833 {
834  // check if button is ready
835  if (status != BUTTON_READY) return;
836 
837  // check if there is something to read
838  if (vrpn_read_available_characters(serial_fd, buffer, 1) != 1) return;
839 
840  // This while loop is to keep reading messages until its empty.
841  while (buffer[0] != PG_END_BYTE) {
842  // switch according to its message start byte
843  if (buffer[0] == PG_START_BYTE_DATA) {
844  // reset button state
845  for (vrpn_int32 i = 0; i < num_buttons; i++)
847 
848  // read next message
850 
851  // read until end of message
852  while (buffer[0] != PG_END_BYTE) {
853 
854  // if only one byte read, read the left hand byte
855  while (bufcount != 2)
857  buffer + 1, 1);
858 
859  unsigned char mask = 0x10;
860  // set button states
861  for (int j = 0; j < 5; j++, mask = (unsigned char)(mask >> 1)) {
862  if (mask & buffer[1]) { // right hand
863  buttons[j] = VRPN_BUTTON_ON;
864  }
865  if (mask & buffer[0]) { // left hand
866  buttons[j + 5] = VRPN_BUTTON_ON;
867  }
868  }
869 
870  // read next bytes
872  } // while (buffer[0] != PG_END_BYTE)
873  // if there is another message read it
874  if (bufcount != 1) buffer[0] = buffer[1];
875  } // if (buffer[0] == PG_START_BYTE_DATA) {
876  else if (buffer[0] == PG_START_BYTE_DATA_TIME) {
878  "vrpn_Button_PinchGlove message start byte: time stamped byte!",
881  }
882  else { // ignore any other type of messages: empty butter till
883  // PG_END_BYTE
884  // clear messages
885  while (buffer[0] != PG_END_BYTE)
887  send_text_message("vrpn_Button_PinchGlove wrong message start byte",
889  } // else
890  } // while (buffer[0] != PG_END_BYTE )
891 
893  return;
894 }
895 
896 // set the glove to report data without timestamp
898 {
899  struct timeval timeout = {
900  0, 30000}; // time_out for response from glove: 30 msec
901  struct timeval timeout_to_pass;
902 
903  // read until correct reply is received
904  do {
906  vrpn_write_characters(serial_fd, (unsigned char *)"T0", 2);
908  timeout_to_pass.tv_sec = timeout.tv_sec;
909  timeout_to_pass.tv_usec = timeout.tv_usec;
911  &timeout_to_pass);
912  } while ((bufcount != 3) || (buffer[1] != '0') ||
913  (buffer[2] != PG_END_BYTE));
914 
915  return;
916 }
917 
918 #endif // VRPN_CLIENT_ONLY
919 
921  : vrpn_Button(name, cn)
922 {
923  vrpn_int32 i;
924 
925  // Register a handler for the change callback from this device,
926  // if we got a connection.
927  if (d_connection != NULL) {
930  fprintf(stderr,
931  "vrpn_Button_Remote: can't register change handler\n");
932  d_connection = NULL;
933  }
936  fprintf(stderr,
937  "vrpn_Button_Remote: can't register states handler\n");
938  d_connection = NULL;
939  }
940  }
941  else {
942  fprintf(stderr, "vrpn_Button_Remote: Can't get connection!\n");
943  }
944 
945  // Fill in all possible buttons with off. The number of buttons
946  // will be overwritten when the states message comes in from the
947  // server.
949  for (i = 0; i < num_buttons; i++) {
950  buttons[i] = lastbuttons[i] = 0;
951  }
953 }
954 
955 // virtual
957 
959 {
960  if (d_connection) {
962  }
963  client_mainloop();
964 }
965 
968 {
970  const char *bufptr = p.buffer;
971  vrpn_BUTTONCB bp;
972 
973  // Fill in the parameters to the button from the message
974  if (p.payload_len != 2 * sizeof(vrpn_int32)) {
975  fprintf(stderr, "vrpn_Button: change message payload error\n");
976  fprintf(stderr, " (got %d, expected %lud)\n", p.payload_len,
977  static_cast<unsigned long>(2 * sizeof(vrpn_int32)));
978  return -1;
979  }
980  bp.msg_time = p.msg_time;
981  vrpn_unbuffer(&bufptr, &bp.button);
982  vrpn_unbuffer(&bufptr, &bp.state);
983 
984  // Go down the list of callbacks that have been registered.
985  // Fill in the parameter and call each.
987 
988  return 0;
989 }
990 
993 {
994  const char *bufptr = p.buffer;
995  vrpn_int32 numbuttons; //< Number of buttons
997  vrpn_BUTTONSTATESCB cp;
998 
999  cp.msg_time = p.msg_time;
1000  vrpn_unbuffer(&bufptr, &numbuttons);
1001  cp.num_buttons = numbuttons;
1002  me->num_buttons = cp.num_buttons;
1003  for (vrpn_int32 i = 0; i < cp.num_buttons; i++) {
1004  vrpn_unbuffer(&bufptr, &cp.states[i]);
1005  }
1006 
1007  // Go down the list of callbacks that have been registered.
1008  // Fill in the parameter and call each.
1010 
1011  return 0;
1012 }
1013 
1014 // We use _inp (inport) to read the parallel port status register
1015 // since we haven't found a way to do it through the Win32 API.
1016 // On NT we need a special device driver (giveio) to be installed
1017 // so that we can get permission to execute _inp. On Win95 we
1018 // don't need to do anything.
1019 //
1020 // The giveio driver is from the May 1996 issue of Dr. Dobb's,
1021 // an article by Dale Roberts called "Direct Port I/O and Windows NT"
1022 //
1023 // This function returns 1 if either running Win95 or running NT and
1024 // the giveio device was opened. 0 if device not opened.
1025 #ifndef VRPN_CLIENT_ONLY
1026 #ifdef _WIN32
1027 int vrpn_Button_Parallel::openGiveIO(void)
1028 {
1029  OSVERSIONINFO osvi;
1030 
1031  memset(&osvi, 0, sizeof(OSVERSIONINFO));
1032  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
1033  GetVersionEx(&osvi);
1034 
1035  // if Win95: no initialization required
1036  if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
1037  return 1;
1038  }
1039 
1040  // else if NT: use giveio driver
1041  if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
1042  HANDLE h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL,
1043  OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1044  if (h == INVALID_HANDLE_VALUE) {
1045  // maybe driver not installed?
1046  return 0;
1047  }
1048  CloseHandle(h);
1049  // giveio opened successfully
1050  return 1;
1051  }
1052 
1053  // else GetVersionEx gave unexpected result
1054  fprintf(stderr,
1055  "vrpn_Button_Parallel::openGiveIO: unknown windows version\n");
1056  return 0;
1057 }
1058 #endif // _WIN32
1059 #endif // VRPN_CLIENT_ONLY
vrpn_Button_Remote::~vrpn_Button_Remote
virtual ~vrpn_Button_Remote(void)
Definition: vrpn_Button.C:956
vrpn_Button_Filter::handle_ping_message
static int VRPN_CALLBACK handle_ping_message(void *userdata, vrpn_HANDLERPARAM p)
Definition: vrpn_Button.C:161
vrpn_BaseClassUnique::register_autodeleted_handler
int register_autodeleted_handler(vrpn_int32 type, vrpn_MESSAGEHANDLER handler, void *userdata, vrpn_int32 sender=vrpn_ANY_SENDER)
Registers a handler with the connection, and remembers to delete at destruction.
Definition: vrpn_BaseClass.C:503
vrpn_Connection::pack_message
virtual int pack_message(vrpn_uint32 len, struct timeval time, vrpn_int32 type, vrpn_int32 sender, const char *buffer, vrpn_uint32 class_of_service)
Pack a message that will be sent the next time mainloop() is called. Turn off the RELIABLE flag if yo...
Definition: vrpn_Connection.C:4632
vrpn_Button_Filter::set_all_toggle
virtual void set_all_toggle(vrpn_int32 default_state)
Definition: vrpn_Button.C:264
vrpn_Button_Filter::encode_states_to
virtual vrpn_int32 encode_states_to(char *buf)
Encode a message describing the state of all buttons.
Definition: vrpn_Button.C:340
vrpn_BaseClassUnique::client_mainloop
void client_mainloop(void)
Handles functions that all clients should provide in their mainloop() (warning of no server,...
Definition: vrpn_BaseClass.C:637
vrpn_Button::report_changes
virtual void report_changes(void)
Definition: vrpn_Button.C:422
vrpn_got_connection
const char * vrpn_got_connection
Definition: vrpn_Connection.C:185
vrpn_Button::admin_message_id
vrpn_int32 admin_message_id
Definition: vrpn_Button.h:51
vrpn_TimevalDuration
unsigned long vrpn_TimevalDuration(struct timeval endT, struct timeval startT)
Return number of microseconds between startT and endT.
Definition: vrpn_Shared.C:129
vrpn_Button_Filter::report_changes
virtual void report_changes(void)
Definition: vrpn_Button.C:382
vrpn_BaseClassUnique::d_ping_message_id
vrpn_int32 d_ping_message_id
Ask the server if they are there.
Definition: vrpn_BaseClass.h:230
vrpn_BUTTON_MAX_BUTTONS
const int vrpn_BUTTON_MAX_BUTTONS
Definition: vrpn_Button.h:12
vrpn_Button_Python::vrpn_Button_Python
vrpn_Button_Python(const char *name, vrpn_Connection *c, int p)
Definition: vrpn_Button.C:650
PACK_MESSAGE
#define PACK_MESSAGE(i, event)
Definition: vrpn_Button.C:79
vrpn_Button::change_message_id
vrpn_int32 change_message_id
Definition: vrpn_Button.h:49
BUTTON_READY
#define BUTTON_READY
Definition: vrpn_Button.C:35
vrpn_Button_Remote::d_callback_list
vrpn_Callback_List< vrpn_BUTTONCB > d_callback_list
Definition: vrpn_Button.h:286
vrpn_Button::states_message_id
vrpn_int32 states_message_id
Definition: vrpn_Button.h:50
PACK_ADMIN_MESSAGE
#define PACK_ADMIN_MESSAGE(i, event)
Definition: vrpn_Button.C:58
vrpn_Button_Example_Server::vrpn_Button_Example_Server
vrpn_Button_Example_Server(const char *name, vrpn_Connection *c, int numbuttons=1, vrpn_float64 rate=1.0)
Definition: vrpn_Button.C:487
vrpn_Button_Serial::serial_fd
int serial_fd
Definition: vrpn_Button.h:182
vrpn_drain_output_buffer
int vrpn_drain_output_buffer(int comm)
Wait until all of the characters in the output buffer are sent, then return.
Definition: vrpn_Serial.C:485
vrpn_BUTTON_TOGGLE_ON
const int vrpn_BUTTON_TOGGLE_ON
Definition: vrpn_Button.h:20
vrpn_Button_Serial::status
int status
Definition: vrpn_Button.h:183
vrpn_Button::set_toggle
virtual void set_toggle(vrpn_int32 which_button, vrpn_int32 current_state)
Definition: vrpn_Button.C:226
vrpn_BaseClassUnique::userdata
void * userdata
Definition: vrpn_BaseClass.h:287
vrpn_Button_Python::d_first_fail
bool d_first_fail
Definition: vrpn_Button.h:169
PG_END_BYTE
const unsigned char PG_END_BYTE(0x8F)
vrpn_Button_Remote
Definition: vrpn_Button.h:250
vrpn_Button_Remote::mainloop
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
Definition: vrpn_Button.C:958
vrpn_ALL_ID
const int vrpn_ALL_ID
Definition: vrpn_Button.h:23
vrpn_Button_Parallel::port
int port
Definition: vrpn_Button.h:143
vrpn_Button_Parallel::~vrpn_Button_Parallel
~vrpn_Button_Parallel()
Definition: vrpn_Button.C:641
vrpn_HANDLERPARAM::payload_len
vrpn_int32 payload_len
Definition: vrpn_Connection.h:48
vrpn_Button::print
void print(void)
Definition: vrpn_Button.C:276
vrpn_Button_Remote::handle_states_message
static int VRPN_CALLBACK handle_states_message(void *userdata, vrpn_HANDLERPARAM p)
Definition: vrpn_Button.C:991
vrpn_Serial.h
vrpn_Serial: Pulls all the serial port routines into one file to make porting to new operating system...
vrpn_Button::num_buttons
vrpn_int32 num_buttons
Definition: vrpn_Button.h:47
vrpn_Button_Server::vrpn_Button_Server
vrpn_Button_Server(const char *name, vrpn_Connection *c, int numbuttons=1)
Definition: vrpn_Button.C:456
vrpn_Button::set_all_momentary
virtual void set_all_momentary(void)
Definition: vrpn_Button.C:254
vrpn_Button::buttons
unsigned char buttons[vrpn_BUTTON_MAX_BUTTONS]
Definition: vrpn_Button.h:44
vrpn_unbuffer
VRPN_API int vrpn_unbuffer(const char **buffer, timeval *t)
Utility routine for taking a struct timeval from a buffer that was sent as a message.
Definition: vrpn_Shared.C:312
vrpn_Button_PinchGlove::report_no_timestamp
void report_no_timestamp()
Definition: vrpn_Button.C:897
vrpn_Button::set_all_toggle
virtual void set_all_toggle(vrpn_int32 default_state)
Definition: vrpn_Button.C:259
vrpn_Button_Remote::handle_change_message
static int VRPN_CALLBACK handle_change_message(void *userdata, vrpn_HANDLERPARAM p)
Definition: vrpn_Button.C:966
vrpn_Button_Serial::bufcount
vrpn_uint32 bufcount
Definition: vrpn_Button.h:187
vrpn_BaseClassUnique::d_connection
vrpn_Connection * d_connection
Connection that this object talks to.
Definition: vrpn_BaseClass.h:224
vrpn_Button_Filter::set_toggle
virtual void set_toggle(vrpn_int32 which_button, vrpn_int32 current_state)
Definition: vrpn_Button.C:204
vrpn_HANDLERPARAM::buffer
const char * buffer
Definition: vrpn_Connection.h:49
vrpn_Button::~vrpn_Button
virtual ~vrpn_Button(void)
Definition: vrpn_Button.C:122
vrpn_Connection::register_message_type
virtual vrpn_int32 register_message_type(const char *name)
Definition: vrpn_Connection.C:5074
vrpn_Button_Python::mainloop
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
Definition: vrpn_Button.C:664
vrpn_TEXT_ERROR
@ vrpn_TEXT_ERROR
Definition: vrpn_BaseClass.h:103
vrpn_flush_input_buffer
int vrpn_flush_input_buffer(int comm)
Throw out any characters within the input buffer.
Definition: vrpn_Serial.C:435
vrpn_CONNECTION_RELIABLE
const vrpn_uint32 vrpn_CONNECTION_RELIABLE
Classes of service for messages, specify multiple by ORing them together Priority of satisfying these...
Definition: vrpn_Connection.h:120
vrpn_HANDLERPARAM
This structure is what is passed to a vrpn_Connection message callback.
Definition: vrpn_Connection.h:44
vrpn_Shared.h
vrpn_Button_Server::mainloop
virtual void mainloop()
Called once each time through the server program's mainloop to handle various functions (like setting...
Definition: vrpn_Button.C:470
vrpn_Button.h
vrpn_BaseClassUnique::d_sender_id
vrpn_int32 d_sender_id
Sender ID registered with the connection.
Definition: vrpn_BaseClass.h:228
vrpn_Button_PinchGlove::mainloop
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
Definition: vrpn_Button.C:808
vrpn_Button::timestamp
struct timeval timestamp
Definition: vrpn_Button.h:48
vrpn_Button::set_momentary
virtual void set_momentary(vrpn_int32 which_button)
Definition: vrpn_Button.C:191
vrpn_Button_Filter::buttonstate
vrpn_int32 buttonstate[vrpn_BUTTON_MAX_BUTTONS]
Definition: vrpn_Button.h:67
vrpn_Button_Filter::alert_message_id
vrpn_int32 alert_message_id
Definition: vrpn_Button.h:78
vrpn_Connection::mainloop
virtual int mainloop(const struct timeval *timeout=NULL)=0
Call each time through program main loop to handle receiving any incoming messages and sending any pa...
vrpn_Button_Server::number_of_buttons
int number_of_buttons(void)
Tells how many buttons there are (may be clipped to MAX_BUTTONS)
Definition: vrpn_Button.C:468
vrpn_HANDLERPARAM::msg_time
struct timeval msg_time
Definition: vrpn_Connection.h:47
vrpn_Connection
Generic connection class not specific to the transport mechanism.
Definition: vrpn_Connection.h:510
vrpn_Connection.h
vrpn_Button::register_types
virtual int register_types(void)
Register the types of messages this device sends/receives. Return 0 on success, -1 on fail.
Definition: vrpn_Button.C:103
vrpn_Button_PinchGlove::vrpn_Button_PinchGlove
vrpn_Button_PinchGlove(const char *name, vrpn_Connection *c, const char *port="/dev/ttyS1/", long baud=38400)
Definition: vrpn_Button.C:779
vrpn_Button_PinchGlove::reported_failure
bool reported_failure
Definition: vrpn_Button.h:205
vrpn_Button_Serial
Definition: vrpn_Button.h:173
vrpn_Button_Remote::d_states_callback_list
vrpn_Callback_List< vrpn_BUTTONSTATESCB > d_states_callback_list
Definition: vrpn_Button.h:290
vrpn_gettimeofday
#define vrpn_gettimeofday
Definition: vrpn_Shared.h:89
BUTTON_FAIL
#define BUTTON_FAIL
Definition: vrpn_Button.C:36
vrpn_Button_PinchGlove::read
virtual void read()
Definition: vrpn_Button.C:832
vrpn_Button_Filter::set_alerts
void set_alerts(vrpn_int32)
Definition: vrpn_Button.C:168
vrpn_Button::lastbuttons
unsigned char lastbuttons[vrpn_BUTTON_MAX_BUTTONS]
Definition: vrpn_Button.h:45
vrpn_Button
This is the base class for both the client and server for a button device (a device with one or more ...
Definition: vrpn_Button.h:30
vrpn_Button_Parallel::vrpn_Button_Parallel
vrpn_Button_Parallel(const char *name, vrpn_Connection *connection, int portno, unsigned porthex=0)
Definition: vrpn_Button.C:540
vrpn_Button_Example_Server::_update_rate
vrpn_float64 _update_rate
Definition: vrpn_Button.h:128
vrpn_Button::encode_states_to
virtual vrpn_int32 encode_states_to(char *buf)
Encode a message describing the state of all buttons.
Definition: vrpn_Button.C:317
vrpn_read_available_characters
int vrpn_read_available_characters(int comm, unsigned char *buffer, size_t bytes)
Definition: vrpn_Serial.C:512
vrpn_ANY_SENDER
const int vrpn_ANY_SENDER
vrpn_ANY_SENDER can be used to register callbacks on a given message type from any sender.
Definition: vrpn_Connection.h:77
vrpn_close_commport
int vrpn_close_commport(int comm)
Definition: vrpn_Serial.C:345
VRPN_BUTTON_OFF
#define VRPN_BUTTON_OFF
Definition: vrpn_Button.h:222
vrpn_Button_Python::read
virtual void read(void)
Definition: vrpn_Button.C:687
vrpn_Button_Serial::portname
char portname[VRPN_BUTTON_BUF_SIZE]
Definition: vrpn_Button.h:180
vrpn_Button_Serial::baudrate
long baudrate
Definition: vrpn_Button.h:181
vrpn_Button::vrpn_Button
vrpn_Button(const char *name, vrpn_Connection *c=NULL)
Definition: vrpn_Button.C:90
VRPN_CALLBACK
#define VRPN_CALLBACK
Definition: vrpn_Configure.h:647
vrpn_Button_Filter::vrpn_Button_Filter
vrpn_Button_Filter(const char *, vrpn_Connection *c=NULL)
Definition: vrpn_Button.C:128
vrpn_Button_Filter::set_all_momentary
virtual void set_all_momentary(void)
Definition: vrpn_Button.C:244
vrpn_Button_Example_Server::mainloop
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
Definition: vrpn_Button.C:505
vrpn_Button_Serial::buffer
unsigned char buffer[VRPN_BUTTON_BUF_SIZE]
Definition: vrpn_Button.h:186
PG_START_BYTE_DATA_TIME
const unsigned char PG_START_BYTE_DATA_TIME(0x81)
vrpn_BaseClass::init
virtual int init(void)
Initialize things that the constructor can't. Returns 0 on success, -1 on failure.
Definition: vrpn_BaseClass.C:363
vrpn_Button_Serial::vrpn_Button_Serial
vrpn_Button_Serial(const char *name, vrpn_Connection *c, const char *port="/dev/ttyS1/", long baud=38400)
Definition: vrpn_Button.C:749
vrpn_buffer
VRPN_API int vrpn_buffer(char **insertPt, vrpn_int32 *buflen, const timeval t)
Utility routine for placing a timeval struct into a buffer that is to be sent as a message.
Definition: vrpn_Shared.C:241
vrpn_BUTTON_TOGGLE_OFF
const int vrpn_BUTTON_TOGGLE_OFF
Definition: vrpn_Button.h:19
vrpn_write_characters
int vrpn_write_characters(int comm, const unsigned char *buffer, size_t bytes)
Write the buffer to the serial port.
Definition: vrpn_Serial.C:643
vrpn_open_commport
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
vrpn_BaseClassUnique::send_text_message
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.
Definition: vrpn_BaseClass.C:568
vrpn_BUTTON_MOMENTARY
const int vrpn_BUTTON_MOMENTARY
Definition: vrpn_Button.h:18
vrpn_Button::encode_to
virtual vrpn_int32 encode_to(char *buf, vrpn_int32 button, vrpn_int32 state)
Encode a message describing the new state of a button.
Definition: vrpn_Button.C:298
PACK_ALERT_MESSAGE
#define PACK_ALERT_MESSAGE(i, event)
Definition: vrpn_Button.C:68
vrpn_Button_Server::set_button
int set_button(int button, int new_value)
Allows the server program to set current button states (to 0 or 1)
Definition: vrpn_Button.C:476
vrpn_Button_Filter::set_momentary
virtual void set_momentary(vrpn_int32 which_button)
Definition: vrpn_Button.C:177
vrpn_Button_Filter::send_alerts
int send_alerts
Definition: vrpn_Button.h:75
vrpn_Callback_List::call_handlers
void call_handlers(const CALLBACK_STRUCT &info)
This will pass the referenced parameter as a const to all the callbacks.
Definition: vrpn_BaseClass.h:451
vrpn_Button::report_states
virtual void report_states(void)
Definition: vrpn_Button.C:437
PG_START_BYTE_DATA
const unsigned char PG_START_BYTE_DATA(0x80)
vrpn_Button_Remote::vrpn_Button_Remote
vrpn_Button_Remote(const char *name, vrpn_Connection *cn=NULL)
Definition: vrpn_Button.C:920
vrpn_Button_Parallel::status
int status
Definition: vrpn_Button.h:144
vrpn_Button_Serial::~vrpn_Button_Serial
virtual ~vrpn_Button_Serial()
Definition: vrpn_Button.C:776
vrpn_Button_Parallel
Definition: vrpn_Button.h:134
vrpn_BaseClassUnique::server_mainloop
void server_mainloop(void)
Handles functions that all servers should provide in their mainloop() (ping/pong, for example) Should...
Definition: vrpn_BaseClass.C:603
vrpn_BaseClass
Class from which all user-level (and other) classes that communicate with vrpn_Connections should der...
Definition: vrpn_BaseClass.h:313
vrpn_Button_Filter
All button servers should derive from this class, which provides the ability to turn any of the butto...
Definition: vrpn_Button.h:65
VRPN_BUTTON_ON
#define VRPN_BUTTON_ON
Definition: vrpn_Button.h:223