vrpn 07.35
Virtual Reality Peripheral Network
 
Loading...
Searching...
No Matches
vrpn_Joylin.C
Go to the documentation of this file.
1/*
2# Linux Joystick. Interface to the Linux Joystick driver by Vojtech Pavlik
3# included in several Linux distributions. The server code has been tested
4# with Linux Joystick driver version 1.2.14. Yet, there is no way how to
5# map a typical joystick's zillion buttons and axes on few buttons and axes
6# really used. Unfortunately, even joysticks of the same kind can have
7# different button mappings from one to another. Driver written by Harald
8# Barth (haba@pdc.kth.se).
9*/
10
11#include "vrpn_Joylin.h"
12
13#ifdef VRPN_USE_JOYLIN
14
15#define NAME_LENGTH 128
16
17#include <fcntl.h> // for open, O_RDONLY
18#include <stdio.h> // for NULL, fprintf, perror, etc
19#include <stdlib.h> // for exit
20#include <sys/select.h> // for select, FD_ISSET, FD_SET, etc
21#include "vrpn_Shared.h" // for timeval, vrpn_gettimeofday
22#include "vrpn_Types.h" // for vrpn_float64
23
24#include <sys/ioctl.h> // for ioctl
25#include <unistd.h> // for read
26#include <string.h>
27
28#include "vrpn_BaseClass.h" // for ::vrpn_TEXT_ERROR
29#include "vrpn_Connection.h" // for vrpn_Connection
30#include <linux/joystick.h> // for js_event, JSIOCGAXES, etc
31
32vrpn_Joylin::vrpn_Joylin(const char * name,
34 const char *portname):
35 vrpn_Analog(name, c), vrpn_Button_Filter(name, c)
36{
37 namelen = 128;
38 num_channel = 2; // inherited : default for generic me-know-nothing PC joystick
39 num_buttons = 2; // inherited : this value is corrected by the ioctl call below.
40 fd = -1;
41 version = 0x000800;
42 devname = (char *) calloc(namelen, sizeof(char));
43 if (devname == NULL) {
44 fprintf(stderr,"vrpn_Joylin::vrpn_Joylin(): Out of memory\n");
45 return;
46 }
47
48 device = strdup(portname);
49 init();
50}
51
53{
54 if (fd >= 0) {
55 close(fd);
56 fd = -1;
57 }
58 free(device);
59 device = NULL;
60
61 free(devname);
62 devname = NULL;
63}
64
65/****************************************************************************/
66/* Initialize the device
67*/
69{
70 if ((fd = open(device, O_RDONLY)) < 0) { /* FIX LATER */
71 fprintf(stderr, "vrpn_Joylin constructor could not open %s", device);
72 perror(" joystick device");
73 return -1;
74 }
75
76 ioctl(fd, JSIOCGVERSION, &version);
77 ioctl(fd, JSIOCGAXES, &num_channel);
78 ioctl(fd, JSIOCGBUTTONS, &num_buttons);
79 ioctl(fd, JSIOCGNAME(namelen), devname);
80
81#ifdef DEBUG
82 printf("Joystick (%s) has %d axes and %d buttons. Driver version is %d.%d.%d.\n",
83 devname, num_channel, num_buttons, version >> 16, (version >> 8) & 0xff, version & 0xff);
84#endif
85
86 return 0;
87}
88
89void vrpn_Joylin::mainloop(void)
90{
91 struct timeval zerotime;
92 fd_set fdset;
93 struct js_event js;
94
95 zerotime.tv_sec = 0;
96 zerotime.tv_usec = 0;
97
98 // Since we are a server, call the generic server mainloop()
100
101 if (fd < 0) { return; }
102
103 bool got_response;
104 do {
105 got_response = false;
106 FD_ZERO(&fdset); /* clear fdset */
107 FD_SET(fd, &fdset); /* include fd in fdset */
108 select(fd+1, &fdset, NULL, NULL, &zerotime);
109
110 if (FD_ISSET(fd, &fdset)){
111 if (read(fd, &js, sizeof(struct js_event)) != sizeof(struct js_event)) {
112 send_text_message("Error reading from joystick", vrpn_Analog::timestamp, vrpn_TEXT_ERROR);
113 if (d_connection) { d_connection->send_pending_reports(); }
114
115 /* try to reopen the device, e.g. wireless joysticks
116 * like to disconnect when not in use to save battery */
117 close(fd);
118 vrpn_SleepMsecs(5000);
119 init();
120 return;
121 }
122 got_response = true;
123
124 switch(js.type & ~JS_EVENT_INIT) {
125 case JS_EVENT_BUTTON:
126 vrpn_gettimeofday((timeval *)&this->vrpn_Button::timestamp, NULL);
127 buttons[js.number] = js.value;
128 break;
129 case JS_EVENT_AXIS:
130 vrpn_gettimeofday((timeval *)&this->vrpn_Analog::timestamp, NULL);
131 channel[js.number] = js.value / 32767.0; /* FIX LATER */
132 break;
133 }
134
135#ifdef DEBUG
136 if (num_channel) {
137 printf("Axes: ");
138 for (i = 0; i < num_channel; i++) {
139 printf("%2d:%.3f ", i, channel[i]);
140 }
141 }
142 if (num_buttons) {
143 printf("Buttons: ");
144 for (i = 0; i < num_buttons; i++) {
145 printf("%2d:%s ", i, buttons[i] ? "on " : "off");
146 }
147 }
148 printf("\n");
149 fflush(stdout);
150#endif
151
152 vrpn_Analog::report_changes(); // report any analog event;
153 vrpn_Button::report_changes(); // report any button event;
154 }
155 } while (got_response);
156}
157
158#else
159
160vrpn_Joylin::vrpn_Joylin(const char * name,
161 vrpn_Connection * c,
162 const char *):
163 vrpn_Analog(name, c), vrpn_Button_Filter(name, c)
164{
165 fprintf(stderr,"vrpn_Joylin::vrpn_Joylin: Can't open Linux joystick on non-Linux machine\n");
166}
167
171
173{
174}
175
176#endif
177
vrpn_float64 channel[vrpn_CHANNEL_MAX]
Definition vrpn_Analog.h:38
vrpn_Analog(const char *name, vrpn_Connection *c=NULL)
Definition vrpn_Analog.C:14
struct timeval timestamp
Definition vrpn_Analog.h:41
vrpn_int32 num_channel
Definition vrpn_Analog.h:40
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
vrpn_Connection * d_connection
Connection that this object talks to.
void server_mainloop(void)
Handles functions that all servers should provide in their mainloop() (ping/pong, for example) Should...
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.
virtual int init(void)
Initialize things that the constructor can't. Returns 0 on success, -1 on failure.
All button servers should derive from this class, which provides the ability to turn any of the butto...
Definition vrpn_Button.h:66
vrpn_Button_Filter(const char *, vrpn_Connection *c=NULL)
vrpn_int32 num_buttons
Definition vrpn_Button.h:48
struct timeval timestamp
Definition vrpn_Button.h:49
virtual void report_changes(void)
unsigned char buttons[vrpn_BUTTON_MAX_BUTTONS]
Definition vrpn_Button.h:45
Generic connection class not specific to the transport mechanism.
void mainloop(void)
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
vrpn_Joylin(const char *name, vrpn_Connection *c, const char *portname)
All types of client/server/peer objects in VRPN should be derived from the vrpn_BaseClass type descri...
@ vrpn_TEXT_ERROR
void vrpn_SleepMsecs(double dMilliSecs)
#define vrpn_gettimeofday
Definition vrpn_Shared.h:99