Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

899 lines (764 sloc) 26.748 kb
#ifndef _WIN32_WCE
#include <time.h>
#endif
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#ifndef _WIN32_WCE
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#endif
#include <string.h> // for memcpy
#ifdef linux
#include <linux/lp.h>
#include <sys/ioctl.h>
#endif
// Include vrpn_Shared.h _first_ to avoid conflicts with sys/time.h
// and unistd.h
#include "vrpn_Shared.h"
#ifdef _WIN32
#ifndef __CYGWIN__
#ifndef _WIN32_WCE
#include <conio.h> // for _inp()
#endif
#endif
#ifndef VRPN_USE_WINSOCK_SOCKETS
#include <netinet/in.h>
#endif
#else
#include <netinet/in.h>
#endif // _WIN32
#if (defined(sgi)&&(!defined(VRPN_CLIENT_ONLY)))
//need these for the gl based setdblight calls
#include <gl/gl.h>
#include <gl/device.h>
#endif
#include "vrpn_Button.h"
#define BUTTON_READY (1)
#define BUTTON_FAIL (-1)
// Bits in the status register
#ifndef VRPN_CLIENT_ONLY
static const unsigned char PORT_ERROR = (1 << 3);
static const unsigned char PORT_SLCT = (1 << 4);
static const unsigned char PORT_PE = (1 << 5);
static const unsigned char PORT_ACK = (1 << 6);
static const unsigned char PORT_BUSY = (1 << 7);
static const unsigned char
BIT_MASK = PORT_ERROR | PORT_SLCT | PORT_PE | PORT_ACK | PORT_BUSY;
#endif
// message constants for the PinchGolve code.
const unsigned char PG_START_BYTE_DATA(0x80);
const unsigned char PG_START_BYTE_DATA_TIME(0x81);
const unsigned char PG_START_BYTE_TEXT(0x82);
const unsigned char PG_END_BYTE(0x8F);
static int VRPN_CALLBACK client_msg_handler(void *userdata, vrpn_HANDLERPARAM p);
#define PACK_ADMIN_MESSAGE(i,event) { \
char msgbuf[1000]; \
vrpn_int32 len = encode_to(msgbuf,i, event); \
if (d_connection->pack_message(len, timestamp, \
admin_message_id, d_sender_id, msgbuf, vrpn_CONNECTION_RELIABLE)) {\
fprintf(stderr,"vrpn_Button: can't write message: tossing\n");\
}\
}
#define PACK_ALERT_MESSAGE(i,event) { \
char msgbuf[1000]; \
vrpn_int32 len = encode_to(msgbuf,i, event); \
if (d_connection->pack_message(len, timestamp, \
alert_message_id, d_sender_id, msgbuf, vrpn_CONNECTION_RELIABLE)) {\
fprintf(stderr,"vrpn_Button: can't write message: tossing\n");\
}\
}
#define PACK_MESSAGE(i,event) { \
char msgbuf[1000]; \
vrpn_int32 len = encode_to(msgbuf,i, event); \
if (d_connection->pack_message(len, timestamp, \
change_message_id, d_sender_id, msgbuf, vrpn_CONNECTION_RELIABLE)) {\
fprintf(stderr,"vrpn_Button: can't write message: tossing\n");\
}\
}
vrpn_Button::vrpn_Button(const char *name, vrpn_Connection *c)
: vrpn_BaseClass(name, c),
num_buttons(0)
{
vrpn_BaseClass::init();
// Set the time to 0 just to have something there.
timestamp.tv_usec = timestamp.tv_sec = 0;
for (vrpn_int32 i=0; i< vrpn_BUTTON_MAX_BUTTONS; i++) {
buttons[i] = lastbuttons[i]=0;
}
}
int vrpn_Button::register_types(void)
{
//used to handle button strikes
change_message_id = d_connection->register_message_type("vrpn_Button Change");
//to handle button state changes -- see Buton_Filter should register a handler
//for this ID -- ideally the message will be ignored otherwise
admin_message_id = d_connection->register_message_type("vrpn_Button Admin");
return 0;
}
// virtual
vrpn_Button::~vrpn_Button (void) {
// do nothing
}
vrpn_Button_Filter::vrpn_Button_Filter(const char *name, vrpn_Connection *c)
:vrpn_Button(name, c)
{
if ( (d_sender_id == -1) || (admin_message_id == -1) ) {
fprintf(stderr,"vrpn_Button: Can't register IDs\n");
d_connection = NULL;
}
register_autodeleted_handler(admin_message_id, client_msg_handler, this);
//setup message id type for alert messages to alert a device about changes
alert_message_id = d_connection->register_message_type("vrpn_Button Alert");
send_alerts=0; //used to turn on/off alerts -- send and admin message from
//remote to turn it on -- or server side call set_alerts();
//set button default buttonstates
for (vrpn_int32 i=0; i< vrpn_BUTTON_MAX_BUTTONS; i++) {
buttonstate[i] = vrpn_BUTTON_MOMENTARY;
}
return;
}
void vrpn_Button_Filter::set_alerts(vrpn_int32 i){
if(i==0 || i==1) send_alerts=i;
else fprintf(stderr,"Invalid send_alert state\n");
return;
}
void vrpn_Button_Filter::set_momentary(vrpn_int32 which_button) {
if (which_button >= num_buttons) {
char msg[200];
sprintf(msg, "vrpn_Button::set_momentary() buttons id %d is greater than the number of buttons(%d)\n", which_button, num_buttons);
send_text_message(msg, timestamp, vrpn_TEXT_ERROR);
return;
}
buttonstate[which_button] = vrpn_BUTTON_MOMENTARY;
if(send_alerts)PACK_ALERT_MESSAGE(which_button,vrpn_BUTTON_TOGGLE_OFF);
}
void vrpn_Button::set_momentary(vrpn_int32 which_button) {
if (which_button >= num_buttons) {
char msg[200];
sprintf(msg, "vrpn_Button::set_momentary() buttons id %d is greater than the number of buttons(%d)\n", which_button, num_buttons);
send_text_message(msg, timestamp, vrpn_TEXT_ERROR);
return;
}
PACK_ADMIN_MESSAGE(which_button,vrpn_BUTTON_MOMENTARY);
}
void vrpn_Button_Filter::set_toggle(vrpn_int32 which_button, vrpn_int32 current_state) {
if (which_button >= num_buttons) {
char msg[200];
sprintf(msg, "vrpn_Button::set_toggle() buttons id %d is greater then the number of buttons(%d)\n", which_button, num_buttons);
send_text_message(msg, timestamp, vrpn_TEXT_ERROR);
return;
}
if (current_state==vrpn_BUTTON_TOGGLE_ON){
buttonstate[which_button] = vrpn_BUTTON_TOGGLE_ON;
if(send_alerts)PACK_ALERT_MESSAGE(which_button,vrpn_BUTTON_TOGGLE_ON);
}
else{
buttonstate[which_button] = vrpn_BUTTON_TOGGLE_OFF;
if(send_alerts)PACK_ALERT_MESSAGE(which_button,vrpn_BUTTON_TOGGLE_OFF);
}
}
void vrpn_Button::set_toggle(vrpn_int32 which_button, vrpn_int32 current_state) {
if (which_button >= num_buttons) {
char msg[200];
sprintf(msg, "vrpn_Button::set_toggle() buttons id %d is greater then the number of buttons(%d)\n", which_button, num_buttons);
send_text_message(msg, timestamp, vrpn_TEXT_ERROR);
return;
}
if (current_state==vrpn_BUTTON_TOGGLE_ON) {
PACK_ADMIN_MESSAGE(which_button,vrpn_BUTTON_TOGGLE_ON);
}
else{
PACK_ADMIN_MESSAGE(which_button,vrpn_BUTTON_TOGGLE_OFF);
}
}
void vrpn_Button_Filter::set_all_momentary(void) {
for (vrpn_int32 i=0; i< num_buttons; i++){
if (buttonstate[i] != vrpn_BUTTON_MOMENTARY) {
buttonstate[i] = vrpn_BUTTON_MOMENTARY;
if(send_alerts) PACK_ALERT_MESSAGE(i,vrpn_BUTTON_TOGGLE_OFF);
}
}
}
void vrpn_Button::set_all_momentary(void) {
PACK_ADMIN_MESSAGE(vrpn_ALL_ID,vrpn_BUTTON_MOMENTARY);
}
void vrpn_Button::set_all_toggle(vrpn_int32 default_state) {
PACK_ADMIN_MESSAGE(vrpn_ALL_ID,default_state);
}
void vrpn_Button_Filter::set_all_toggle(vrpn_int32 default_state) {
for (vrpn_int32 i=0; i< num_buttons; i++){
if (buttonstate[i] == vrpn_BUTTON_MOMENTARY){
buttonstate[i] = default_state;
if(send_alerts){PACK_ALERT_MESSAGE(i,default_state); }
}
}
}
void vrpn_Button::print(void)
{
vrpn_int32 i;
printf("CurrButtons: ");
for (i = num_buttons-1; i >= 0; i--) {
printf("%c",buttons[i]?'1':'0');
}
printf("\n");
printf("LastButtons: ");
for (i = num_buttons-1; i >= 0; i--) {
printf("%c",lastbuttons[i]?'1':'0');
}
printf("\n");
}
/** Encode a message describing the new state of a button.
Assumes that there is enough room in the buffer to hold
the bytes from the message. Returns the number of bytes
sent.
*/
vrpn_int32 vrpn_Button::encode_to(char *buf,
vrpn_int32 button, vrpn_int32 state)
{
char *bufptr = buf;
int buflen = 1000;
// Message includes: vrpn_int32 buttonNum, vrpn_int32 state
vrpn_buffer( &bufptr, &buflen, button );
vrpn_buffer( &bufptr, &buflen, state );
return 1000 - buflen;
}
static int VRPN_CALLBACK client_msg_handler(void *userdata, vrpn_HANDLERPARAM p) {
vrpn_Button_Filter * instance = (vrpn_Button_Filter *) userdata;
const char *bufptr = p.buffer;
vrpn_int32 event;
vrpn_int32 buttonid;
vrpn_unbuffer(&bufptr, &buttonid);
vrpn_unbuffer(&bufptr, &event);
if (event== vrpn_BUTTON_MOMENTARY) {
if (buttonid == vrpn_ALL_ID)
instance->set_all_momentary();
else instance->set_momentary(buttonid);
}else if (event== vrpn_BUTTON_TOGGLE_OFF || event==vrpn_BUTTON_TOGGLE_ON ){
if (buttonid == vrpn_ALL_ID)
instance->set_all_toggle(event);
else instance->set_toggle(buttonid,event);
}
return 0;
}
void vrpn_Button_Filter::report_changes (void){
vrpn_int32 i;
// vrpn_Button::report_changes();
if (d_connection) {
for (i = 0; i < num_buttons; i++) {
switch (buttonstate[i]) {
case vrpn_BUTTON_MOMENTARY:
if (buttons[i] != lastbuttons[i])
PACK_MESSAGE(i, buttons[i]);
break;
case vrpn_BUTTON_TOGGLE_ON:
if (buttons[i] && !lastbuttons[i]) {
buttonstate[i] = vrpn_BUTTON_TOGGLE_OFF;
if(send_alerts) PACK_ALERT_MESSAGE(i,vrpn_BUTTON_TOGGLE_OFF);
PACK_MESSAGE(i, 0);
}
break;
case vrpn_BUTTON_TOGGLE_OFF:
if (buttons[i] && !lastbuttons[i]) {
buttonstate[i] = vrpn_BUTTON_TOGGLE_ON;
if(send_alerts)PACK_ALERT_MESSAGE(i,vrpn_BUTTON_TOGGLE_ON);
PACK_MESSAGE(i, 1);
}
break;
default:
fprintf(stderr,"vrpn_Button::report_changes(): Button %d in \
invalid state (%d)\n",i,buttonstate[i]);
}
lastbuttons[i] = buttons[i];
}
} else {
fprintf(stderr,"vrpn_Button: No valid connection\n");
}
}
void vrpn_Button::report_changes(void)
{
vrpn_int32 i;
if (d_connection) {
for (i = 0; i < num_buttons; i++) {
if (buttons[i] != lastbuttons[i])
PACK_MESSAGE(i, buttons[i]);
lastbuttons[i] = buttons[i];
}
} else {
fprintf(stderr,"vrpn_Button: No valid connection\n");
}
}
#ifndef VRPN_CLIENT_ONLY
vrpn_Button_Server::vrpn_Button_Server(const char *name, vrpn_Connection *c,
int numbuttons) : vrpn_Button_Filter(name, c)
{
if (numbuttons > vrpn_BUTTON_MAX_BUTTONS) {
num_buttons = vrpn_BUTTON_MAX_BUTTONS;
} else {
num_buttons = numbuttons;
}
}
int vrpn_Button_Server::number_of_buttons(void)
{
return num_buttons;
}
void vrpn_Button_Server::mainloop(void)
{
server_mainloop();
report_changes();
}
int vrpn_Button_Server::set_button(int button, int new_value)
{
if ( (button < 0) || (button >= num_buttons) ) {
return -1;
}
buttons[button] = (unsigned char)(new_value != 0);
return 0;
}
static unsigned long duration(struct timeval t1, struct timeval t2)
{
return (t1.tv_usec - t2.tv_usec) +
1000000L * (t1.tv_sec - t2.tv_sec);
}
vrpn_Button_Example_Server::vrpn_Button_Example_Server(const char *name,
vrpn_Connection *c,
int numbuttons,
vrpn_float64 rate)
: vrpn_Button_Filter(name, c)
{
if (numbuttons > vrpn_BUTTON_MAX_BUTTONS) {
num_buttons = vrpn_BUTTON_MAX_BUTTONS;
} else {
num_buttons = numbuttons;
}
_update_rate = rate;
// IN A REAL SERVER, open the device that will service the buttons here
}
void vrpn_Button_Example_Server::mainloop()
{
struct timeval current_time;
int i;
// Call the generic server mainloop, since we are a server
server_mainloop();
// See if its time to generate a new report (every 1 second).
// IN A REAL SERVER, this check would not be done; although the
// time of the report would be updated to the current time so
// that the correct timestamp would be issued on the report.
vrpn_gettimeofday(&current_time, NULL);
if ( duration(current_time,timestamp) >= 1000000.0/_update_rate) {
// Update the time
timestamp.tv_sec = current_time.tv_sec;
timestamp.tv_usec = current_time.tv_usec;
// Update the values for the buttons, to say that each one has
// switched its state.
// THIS CODE WILL BE REPLACED by the user code that
// actually reads from the button devices and fills in buttons[]
// appropriately.
for (i = 0; i < num_buttons; i++) {
buttons[i] = !lastbuttons[i];
}
// Send reports. Stays the same in a real server.
report_changes();
}
}
// changed to take raw port hex address
vrpn_Button_Parallel::vrpn_Button_Parallel(const char *name,
vrpn_Connection *c,
int portno, unsigned porthex)
: vrpn_Button_Filter(name, c)
{
#ifdef linux
const char *portname;
switch (portno) {
case 1: portname = "/dev/lp0";
break;
case 2: portname = "/dev/lp1";
break;
case 3: portname = "/dev/lp2";
break;
default:
fprintf(stderr, "vrpn_Button_Parallel: "
"Bad port number (%x) for Linux lp#\n",portno);
status = BUTTON_FAIL;
portname = "UNKNOWN";
break;
}
// Open the port
if ( (port = open(portname, O_RDWR)) < 0) {
perror("vrpn_Button_Parallel::vrpn_Button_Parallel(): "
"Can't open port");
fprintf(stderr, "vrpn_Button_Parallel::vrpn_Button_Parallel(): "
"Can't open port %s\n",portname);
status = BUTTON_FAIL;
return;
}
#elif _WIN32
// if on NT we need a device driver to do direct reads
// from the parallel port
if (!openGiveIO()) {
fprintf(stderr, "vrpn_Button: need giveio driver for port access!\n");
fprintf(stderr, "vrpn_Button: can't use vrpn_Button()\n");
status = BUTTON_FAIL;
return;
}
if (porthex != 0) // using direct hex port address
port = porthex;
else { // using old style port 1, 2, or 3
switch (portno) {
// we use this mapping, although LPT? can actually
// have different addresses.
case 1: port = 0x378; break; // usually LPT1
case 2: port = 0x3bc; break; // usually LPT2
case 3: port = 0x278; break; // usually LPT3
default:
fprintf(stderr,"vrpn_Button_Parallel: Bad port number (%d)\n",portno);
status = BUTTON_FAIL;
break;
}
}
fprintf(stderr,"vrpn_Button_Parallel: Using port %x\n",port);
#else // _WIN32
fprintf(stderr, "vrpn_Button_Parallel: not supported on this platform\n?");
status = BUTTON_FAIL;
portno = portno; // unused argument
return;
#endif
#if defined(linux) || defined(_WIN32)
// Set the INIT line on the device to provide power to the python
// update: don't need this for builtin LPT1 on DELLs, but do need it
// for warp9 PCI parallel port. Added next lines. BCE Nov07.00
// Setting Bit 1 high also for a specific HiBall system
// requirement (IR blocking device on same port)
// - BCE 08 July 03
#ifdef _outp
static const unsigned short DATA_REGISTER_OFFSET = 0;
_outp((unsigned short)(port + DATA_REGISTER_OFFSET), 3);
#else
fprintf(stderr,"vrpn_Button_Parallel: Not setting bit 0 on Linux, may not work with all ports\n");
#endif
// Zero the button states
num_buttons = 5; //XXX This is specific to the python
for (vrpn_int32 i = 0; i < num_buttons; i++) {
buttons[i] = lastbuttons[i] = 0;
}
status = BUTTON_READY;
vrpn_gettimeofday(&timestamp, NULL);
#endif
}
vrpn_Button_Python::vrpn_Button_Python (const char * name, vrpn_Connection * c, int p) :
vrpn_Button_Parallel (name, c, p) {
}
vrpn_Button_Python::vrpn_Button_Python (const char * name, vrpn_Connection * c, int p, unsigned ph) :
vrpn_Button_Parallel (name, c, p, ph) {
}
void vrpn_Button_Python::mainloop()
{
// Call the generic server mainloop, since we are a server
server_mainloop();
switch (status) {
case BUTTON_READY:
read();
report_changes();
break;
case BUTTON_FAIL:
{ static int first = 1;
if (first) {
first = 0;
fprintf(stderr, "vrpn_Button_Python failure!\n");
send_text_message("Failure", timestamp, vrpn_TEXT_ERROR);
}
}
break;
}
}
// Fill in the buttons[] array with the current value of each of the
// buttons. Debounce the buttons (make sure that they have had the
// same value for the past several times to debounce noise).
void vrpn_Button_Python::read(void)
{
int i;
const int debounce_count = 30;
int status_register[debounce_count];
// Make sure we're ready to read
if (status != BUTTON_READY) {
return;
}
// Read from the status register, read 3 times to debounce noise.
#ifdef linux
for (i = 0; i < debounce_count; i++)
if (ioctl(port, LPGETSTATUS, &status_register[i]) == -1) {
perror("vrpn_Button_Python::read(): ioctl() failed");
return;
}
#elif _WIN32
#ifndef __CYGWIN__
static const unsigned short STATUS_REGISTER_OFFSET = 1;
for (i = 0; i < debounce_count; i++) {
#ifdef _inp
status_register[i] = _inp((unsigned short)(port + STATUS_REGISTER_OFFSET));
#else
status_register[i] = 0;
#endif
}
#else
for (i = 0; i < debounce_count; i++) {
status_register[i] = 0;
}
#endif
#else
for (i = 0; i < debounce_count; i++) {
status_register[i] = 0;
}
#endif
for (i = 0; i < debounce_count; i++) {
status_register[i] = status_register[i] & BIT_MASK;
}
// Make sure they are all the same; if not, return and assume that
// we are still debouncing.
for (i = 1; i < debounce_count; i++) {
if (status_register[0] != status_register[i]) {
return;
}
}
// Assign values to the bits based on the control signals
buttons[0] = ((status_register[0] & PORT_SLCT) == 0);
buttons[1] = ((status_register[0] & PORT_BUSY) != 0);
buttons[2] = ((status_register[0] & PORT_PE) == 0);
buttons[3] = ((status_register[0] & PORT_ERROR) == 0);
buttons[4] = ((status_register[0] & PORT_ACK) == 0);
vrpn_gettimeofday(&timestamp, NULL);
}
vrpn_Button_Serial::vrpn_Button_Serial(const char* name, vrpn_Connection *c,
const char *port, long baud) :
vrpn_Button_Filter(name, c)
{
// port name and baud rate
if (port == NULL) {
fprintf(stderr,"vrpn_Button_Serial: NULL port name\n");
status = BUTTON_FAIL;
return;
} else {
strncpy(portname, port, sizeof(portname));
portname[sizeof(portname)-1] = '\0';
}
baudrate = baud;
// Open the serial port
if ( (serial_fd=vrpn_open_commport(portname, baudrate)) == -1) {
fprintf(stderr,"vrpn_Button_Serial: Cannot Open serial port\n");
status = BUTTON_FAIL;
}
// Reset the tracker and find out what time it is
status = BUTTON_READY;
vrpn_gettimeofday(&timestamp, NULL);
}
vrpn_Button_Serial::~vrpn_Button_Serial() {
vrpn_close_commport(serial_fd);
}
// init pinch glove to send hand data only
vrpn_Button_PinchGlove::vrpn_Button_PinchGlove(const char* name, vrpn_Connection *c,
const char *port, long baud) : vrpn_Button_Serial(name, c, port, baud)
{
num_buttons = 10; // 0-4: right, 5-9: left starting from thumb
status = BUTTON_READY;
// check if the number of buttons is not more than max allowed.
if (num_buttons > vrpn_BUTTON_MAX_BUTTONS) {
fprintf(stderr,"vrpn_Button_PinchGlove: Too many buttons. The limit is ");
fprintf(stderr,"%i but this device has %i.\n",vrpn_BUTTON_MAX_BUTTONS,num_buttons);
status = BUTTON_FAIL;
}
// set glove to report with no timestamp
report_no_timestamp();
// initialize the buttons
for (vrpn_int32 i=0; i<num_buttons; i++)
buttons[i] = lastbuttons[i] = VRPN_BUTTON_OFF;
// Reset the tracker and find out what time it is
vrpn_gettimeofday(&timestamp, NULL);
}
void vrpn_Button_PinchGlove::mainloop()
{
// Call the generic server mainloop, since we are a server
server_mainloop();
switch (status) {
case BUTTON_READY:
read();
report_changes();
break;
case BUTTON_FAIL:
{ static int first = 1;
if (first) {
first = 0;
fprintf(stderr, "vrpn_Button_PinchGlove failure!\n");
}
}
break;
}
return;
}
// Pinch glove should only report hand data(see contructor). If the message has
// time stamp data change the the message type by sending command to just send
// hand data. Any other kind of message is ignored and the buffer is read until
// end of message byte(PG_END_BYTE) is reached.
void vrpn_Button_PinchGlove::read()
{
// check if button is ready
if (status != BUTTON_READY) return;
// check if there is something to read
if (vrpn_read_available_characters(serial_fd,buffer,1) != 1) return;
// This while loop is to keep reading messages until its empty.
while (buffer[0] != PG_END_BYTE ) {
// switch according to its message start byte
if (buffer[0] == PG_START_BYTE_DATA) {
// reset button state
for (vrpn_int32 i=0; i<num_buttons; i++) buttons[i] = VRPN_BUTTON_OFF;
// read next message
bufcount = vrpn_read_available_characters(serial_fd,buffer,2);
// read until end of message
while (buffer[0] != PG_END_BYTE) {
// if only one byte read, read the left hand byte
while (bufcount != 2)
bufcount += vrpn_read_available_characters(serial_fd,buffer+1,1);
unsigned char mask = 0x10;
// set button states
for (int j=0; j<5; j++, mask=(unsigned char)(mask>>1)) {
if (mask & buffer[1]) { // right hand
buttons[j] = VRPN_BUTTON_ON;
}
if (mask & buffer[0]) { // left hand
buttons[j+5] = VRPN_BUTTON_ON;
}
}
// read next bytes
bufcount = vrpn_read_available_characters(serial_fd,buffer,2);
} // while (buffer[0] != PG_END_BYTE)
// if there is another message read it
if (bufcount != 1) buffer[0] = buffer[1];
} // if (buffer[0] == PG_START_BYTE_DATA) {
else if (buffer[0] == PG_START_BYTE_DATA_TIME) {
send_text_message("vrpn_Button_PinchGlove message start byte: time stamped byte!", timestamp, vrpn_TEXT_ERROR);
report_no_timestamp();
}
else { // ignore any other type of messages: empty butter till PG_END_BYTE
// clear messages
while(buffer[0] != PG_END_BYTE)
vrpn_read_available_characters(serial_fd,buffer,1);
send_text_message("vrpn_Button_PinchGlove wrong message start byte", timestamp, vrpn_TEXT_ERROR);
} // else
} // while (buffer[0] != PG_END_BYTE )
vrpn_gettimeofday(&timestamp, NULL);
return;
}
// set the glove to report data without timestamp
void vrpn_Button_PinchGlove::report_no_timestamp()
{
struct timeval timeout = {0, 30000}; // time_out for response from glove: 30 msec
struct timeval timeout_to_pass;
// read until correct reply is recieved
do {
vrpn_flush_input_buffer(serial_fd);
vrpn_write_characters(serial_fd, (unsigned char *)"T0", 2);
vrpn_drain_output_buffer(serial_fd);
timeout_to_pass.tv_sec = timeout.tv_sec;
timeout_to_pass.tv_usec = timeout.tv_usec;
bufcount = vrpn_read_available_characters(serial_fd,buffer,3,&timeout_to_pass) ;
} while ( (bufcount!=3) || (buffer[1]!='0') || (buffer[2]!=PG_END_BYTE) );
return;
}
#endif // VRPN_CLIENT_ONLY
vrpn_Button_Remote::vrpn_Button_Remote(const char *name, vrpn_Connection *cn):
vrpn_Button(name, cn)
{
vrpn_int32 i;
// Register a handler for the change callback from this device,
// if we got a connection.
if (d_connection != NULL) {
if (register_autodeleted_handler(change_message_id, handle_change_message,
this, d_sender_id)) {
fprintf(stderr,"vrpn_Button_Remote: can't register handler\n");
d_connection = NULL;
}
} else {
fprintf(stderr,"vrpn_Button_Remote: Can't get connection!\n");
}
// XXX These should be read from a description message that comes
// from the button device (as a response to a query?). For now,
// we assume an SGI button box.
num_buttons = 32;
for (i = 0; i < num_buttons; i++) {
buttons[i] = lastbuttons[i] = 0;
}
vrpn_gettimeofday(&timestamp, NULL);
}
// virtual
vrpn_Button_Remote::~vrpn_Button_Remote (void)
{
}
void vrpn_Button_Remote::mainloop()
{
if (d_connection) {
d_connection->mainloop();
}
client_mainloop();
}
int vrpn_Button_Remote::handle_change_message(void *userdata,
vrpn_HANDLERPARAM p)
{
vrpn_Button_Remote *me = (vrpn_Button_Remote *)userdata;
const char *bufptr = p.buffer;
vrpn_BUTTONCB bp;
// Fill in the parameters to the button from the message
if (p.payload_len != 2*sizeof(vrpn_int32)) {
fprintf(stderr,"vrpn_Button: change message payload error\n");
fprintf(stderr," (got %d, expected %lud)\n",
p.payload_len, static_cast<unsigned long>(2*sizeof(vrpn_int32)));
return -1;
}
bp.msg_time = p.msg_time;
vrpn_unbuffer(&bufptr, &bp.button);
vrpn_unbuffer(&bufptr, &bp.state);
// Go down the list of callbacks that have been registered.
// Fill in the parameter and call each.
me->d_callback_list.call_handlers(bp);
return 0;
}
// We use _inp (inport) to read the parallel port status register
// since we haven't found a way to do it through the Win32 API.
// On NT we need a special device driver (giveio) to be installed
// so that we can get permission to execute _inp. On Win95 we
// don't need to do anything.
//
// The giveio driver is from the May 1996 issue of Dr. Dobb's,
// an article by Dale Roberts called "Direct Port I/O and Windows NT"
//
// This function returns 1 if either running Win95 or running NT and
// the giveio device was opened. 0 if device not opened.
#ifndef VRPN_CLIENT_ONLY
#ifdef _WIN32
int vrpn_Button_Parallel::openGiveIO(void)
{
OSVERSIONINFO osvi;
memset(&osvi, 0, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
// if Win95: no initialization required
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
return 1;
}
// else if NT: use giveio driver
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
HANDLE h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE) {
// maybe driver not installed?
return 0;
}
CloseHandle(h);
// giveio opened successfully
return 1;
}
// else GetVersionEx gave unexpected result
fprintf(stderr, "vrpn_Button_Parallel::openGiveIO: unknown windows version\n");
return 0;
}
#endif // _WIN32
#endif // VRPN_CLIENT_ONLY
Jump to Line
Something went wrong with that request. Please try again.