vrpn 07.35
Virtual Reality Peripheral Network
Loading...
Searching...
No Matches
vrpn_DevInput.C
Go to the documentation of this file.
1/* file: vrpn_DevInput.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 "vrpn_DevInput.h"
12
14
15#ifdef VRPN_USE_DEV_INPUT
16#include <sys/select.h> // for select, FD_ISSET, FD_SET, etc
17#include <vrpn_Shared.h> // for vrpn_gettimeofday
18#include <unistd.h> // for close, read
19#include <utility> // for pair
20#include <fcntl.h> // for open, O_RDONLY
21#include <linux/input.h> // for input_event, ABS_MAX, etc
22#include <errno.h> // for errno, EACCES, ENOENT
23#include <string.h> // for strcmp, NULL, strerror
24#include <sys/ioctl.h> // for ioctl
25#include <iostream> // for operator<<, ostringstream, etc
26#include <map> // for map, _Rb_tree_iterator, etc
27#include <string> // for string, operator+, etc
28#include <sstream>
29
30#define REPORT_ERROR(msg) { send_text_message(msg, timestamp, vrpn_TEXT_ERROR); }
31
32static const std::string EMPTY_STRING("");
33
34static std::string getDeviceNodes(const std::string &device_name)
35{
36 std::map<std::string, std::string> s_devicesNodes;
37
38 bool permission_missing = false;
39 unsigned int id = 0;
40 while (1) {
41 std::ostringstream oss;
42 oss << "/dev/input/event" << id;
43
44 int fd = open(oss.str().c_str(), O_RDONLY);
45 if(fd >= 0){
46 char name[512];
47 if((ioctl(fd, EVIOCGNAME(sizeof(name)), name) >= 0)
48 && (s_devicesNodes.find(name) == s_devicesNodes.end())) {
49 s_devicesNodes[name] = oss.str();
50 }
51
52 close(fd);
53 } else {
54 if (errno == ENOENT) break;
55 if (errno == EACCES) permission_missing = true;
56 }
57 errno = 0;
58 id++;
59 }
60 if (permission_missing) {
61 std::cout << "vrpn_DevInput device scan warning : permission denied for some nodes !" << std::endl;
62 }
63
64 std::map<std::string, std::string>::iterator node_name = s_devicesNodes.find(device_name);
65 if (node_name != s_devicesNodes.end()) {
66 return node_name->second;
67 }
68
69 return EMPTY_STRING;
70}
71
73
74vrpn_DevInput::vrpn_DevInput( const char* name, vrpn_Connection * cxn, const char *device_name, const char * type, int int_param )
75 : vrpn_Analog( name, cxn )
76 , vrpn_Button_Filter( name, cxn )
77 , d_fileDescriptor(-1) // None found yet, device broken.
78{
79 int i;
80
81 if (strcmp(type, "keyboard") == 0) {
82 d_type = DEVICE_KEYBOARD;
83 } else if (strcmp(type, "absolute") == 0) {
84 d_type = DEVICE_MOUSE_ABSOLUTE;
85 } else if (strcmp(type, "relative") == 0) {
86 d_type = DEVICE_MOUSE_RELATIVE;
87 } else {
88 REPORT_ERROR("Third parameter must be keyboard, absolute or relative");
89 return;
90 }
91
94
95 switch (d_type) {
96 case DEVICE_KEYBOARD:
97 if ((int_param < 1) || (int_param >= vrpn_BUTTON_MAX_BUTTONS)) {
98 REPORT_ERROR("In case of keyboard, the value must be between 1 and 256");
99 return;
100 }
102 break;
103 case DEVICE_MOUSE_ABSOLUTE:
104 vrpn_Analog::num_channel = REL_MAX;
106 d_absolute_min = 0;
107 d_absolute_range = int_param;
108 break;
109 case DEVICE_MOUSE_RELATIVE:
110 vrpn_Analog::num_channel = ABS_MAX;
112 break;
113 };
114
115 // initialize the vrpn_Analog
116 for( i = 0; i < vrpn_Analog::num_channel; i++) {
118 }
119
120 // initialize the vrpn_Button_Filter
121 for( i = 0; i < vrpn_Button_Filter::num_buttons; i++) {
123 }
124
125 std::string node = getDeviceNodes(device_name);
126 if (node.length() == 0) {
127 char msg[4096];
128 sprintf(msg, "vrpn_DevInput::vrpn_DevInput(): Could not get device %s",
129 device_name);
130 REPORT_ERROR(msg);
131 return;
132 }
133
134 d_fileDescriptor = open(node.c_str(), O_RDONLY);
135 if(d_fileDescriptor < 0){
136 char msg[4096];
137 sprintf(msg, "vrpn_DevInput::vrpn_DevInput(): Could not open device %s (%s)",
138 device_name, strerror(errno));
139 REPORT_ERROR(msg);
140 return;
141 }
142}
143
145
146vrpn_DevInput::~vrpn_DevInput()
147{
148 if (d_fileDescriptor >= 0) {
149 close(d_fileDescriptor);
150 }
151 d_fileDescriptor = -1;
152}
153
155
156void vrpn_DevInput::mainloop()
157{
158 get_report();
159
160 server_mainloop();
161
162 report_changes();
163}
164
166
167int vrpn_DevInput::get_report()
168{
169 fd_set readset;
170
171 if (d_fileDescriptor < 0) {
172 return 0;
173 }
174
175 FD_ZERO( &readset );
176 FD_SET( d_fileDescriptor, &readset );
177 struct timeval timeout = { 0, 0 };
178 select( d_fileDescriptor+1, &readset, NULL, NULL, &timeout );
179
180 vrpn_gettimeofday( &timestamp, NULL );
181
182 if( ! FD_ISSET( d_fileDescriptor, &readset ) )
183 return 0;
184
185 struct input_event event;
186 if (read(d_fileDescriptor, &event, sizeof(event)) < sizeof(event)) {
187 return 0;
188 }
189
190 switch (event.type) {
191 case EV_KEY: {
192 int button_number = event.code;
193 if ((d_type == DEVICE_MOUSE_RELATIVE) || (d_type == DEVICE_MOUSE_ABSOLUTE)) {
194 button_number -= BTN_MOUSE;
195 }
196 if ((button_number >= 0) && (button_number < vrpn_Button_Filter::num_buttons)) {
197 buttons[button_number] = event.value;
198 }
199 } break;
200 case EV_REL: {
201 int channel_number = event.code;
202 if ((channel_number >= 0) && (channel_number < vrpn_Analog::num_channel)) {
203 for (unsigned int i = 0 ; i < vrpn_Analog::num_channel ; i++) {
204 vrpn_Analog::last[i] = 0;
205 }
206 vrpn_Analog::channel[channel_number] = (vrpn_float64)event.value;
207 }
208 } break;
209 case EV_ABS:
210 int channel_number = event.code;
211 if ((channel_number >= 0) && (channel_number < vrpn_Analog::num_channel)) {
212 vrpn_float64 value = ((vrpn_float64)event.value - d_absolute_min) / d_absolute_range;
213 vrpn_Analog::channel[channel_number] = value;
214 }
215 break;
216 };
217
218 return 1;
219}
220
222
223void vrpn_DevInput::report_changes( vrpn_uint32 class_of_service )
224{
225 vrpn_Analog::timestamp = timestamp;
227
228 vrpn_Analog::report_changes( class_of_service );
230}
231
233
234void vrpn_DevInput::report( vrpn_uint32 class_of_service )
235{
236 vrpn_Analog::timestamp = timestamp;
238
239 vrpn_Analog::report( class_of_service );
241}
242
243#endif
244
245/*EOF*/
vrpn_float64 last[vrpn_CHANNEL_MAX]
Definition: vrpn_Analog.h:39
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(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
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
All button servers should derive from this class, which provides the ability to turn any of the butto...
Definition: vrpn_Button.h:66
virtual void report_changes(void)
Definition: vrpn_Button.C:383
vrpn_int32 num_buttons
Definition: vrpn_Button.h:48
struct timeval timestamp
Definition: vrpn_Button.h:49
unsigned char lastbuttons[vrpn_BUTTON_MAX_BUTTONS]
Definition: vrpn_Button.h:46
unsigned char buttons[vrpn_BUTTON_MAX_BUTTONS]
Definition: vrpn_Button.h:45
Generic connection class not specific to the transport mechanism.
const int vrpn_BUTTON_MAX_BUTTONS
Definition: vrpn_Button.h:13
#define VRPN_SUPPRESS_EMPTY_OBJECT_WARNING()
#define EV_REL
#define EV_KEY
#define REPORT_ERROR(msg)
Definition: vrpn_LUDL.C:27
#define vrpn_gettimeofday
Definition: vrpn_Shared.h:99