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);
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
169{
170}
171
173{
174}
175
176#endif
177
vrpn_float64 channel[vrpn_CHANNEL_MAX]
Definition vrpn_Analog.h:38
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_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.
virtual int send_pending_reports(void)=0
send pending report, clear the buffer. This function was protected, now is public,...
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