xref: /haiku/src/kits/device/Joystick.cpp (revision 959ff00ddee8411dabb09211f3bfbd52d87229da)
1 /*
2  * Copyright 2002-2008, Marcus Overhagen, Stefano Ceccherini, Fredrik Modéen.
3  * All rights reserved.
4  * Distributed under the terms of the MIT License.
5  */
6 
7 #include <List.h>
8 #include "Joystick.h"
9 
10 #include <errno.h>
11 #include <fcntl.h>
12 #include <stdio.h>
13 
14 #include <sys/ioctl.h>
15 
16 #include <Path.h>
17 #include <Directory.h>
18 #include <String.h>
19 #include <Debug.h>
20 
21 
22 #if DEBUG
23 inline void
24 LOG(const char *fmt, ...)
25 {
26 	char buf[1024];
27 	va_list ap;
28 	va_start(ap, fmt);
29 	vsprintf(buf, fmt, ap);
30 	va_end(ap);
31 	fputs(buf, BJoystick::sLogFile); fflush(BJoystick::sLogFile);
32 }
33 #	define LOG_ERR(text...) LOG(text)
34 FILE *BJoystick::sLogFile = NULL;
35 #else
36 #	define LOG(text...)
37 #	define LOG_ERR(text...) fprintf(stderr, text)
38 #endif
39 
40 #define CALLED() LOG("%s\n", __PRETTY_FUNCTION__)
41 
42 #include "JoystickTweaker.h"
43 
44 BJoystick::BJoystick()
45 	:
46 	fBeBoxMode(false),
47 	fDevices(new BList),
48 	fJoystickInfo(new _joystick_info())
49 {
50 #if DEBUG
51 	sLogFile = fopen("/var/log/libdevice.log", "a");
52 #endif
53 	//ScanDevices();
54 }
55 
56 
57 BJoystick::~BJoystick()
58 {
59 	if (ffd >= 0)
60 		close(ffd);
61 
62 	for (int32 count = fDevices->CountItems() - 1; count >= 0; count--) {
63 		free(fDevices->RemoveItem(count));
64 	}
65 
66 	delete fDevices;
67 	delete fJoystickInfo;
68 }
69 
70 
71 status_t
72 BJoystick::Open(const char *portName)
73 {
74 	CALLED();
75 	return Open(portName, true);
76 }
77 
78 
79 status_t
80 BJoystick::Open(const char *portName, bool enter_enhanced)
81 {
82 	CALLED();
83 	char buf[64];
84 
85 	if(!enter_enhanced)
86 		fBeBoxMode = !enter_enhanced;
87 
88 	if (portName == NULL)
89 		return B_BAD_VALUE;
90 
91 	if (portName[0] != '/')
92 		snprintf(buf, 64, DEVICEPATH"/%s", portName);
93 	else
94 		snprintf(buf, 64, "%s", portName);
95 
96 	if (ffd >= 0)
97 		close(ffd);
98 
99 	// TODO: BeOS don't use O_EXCL, and this seems to lead to some issues. I
100 	// added this flag having read some comments by Marco Nelissen on the
101 	// annotated BeBook. I think BeOS uses O_RDWR|O_NONBLOCK here.
102 	ffd = open(buf, O_RDWR | O_NONBLOCK | O_EXCL);
103 
104 	if (ffd >= 0) {
105 		// we used open() with O_NONBLOCK flag to let it return immediately,
106 		// but we want read/write operations to block if needed, so we clear
107 		// that bit here.
108 		int flags = fcntl(ffd, F_GETFL);
109 		fcntl(ffd, F_SETFL, flags & ~O_NONBLOCK);
110 
111 		//Read the Joystick Description file for this port/joystick
112 		_BJoystickTweaker jt(*this);
113 		jt.GetInfo(fJoystickInfo, portName);
114 
115 		LOG("ioctl - %d\n", fJoystickInfo->num_buttons);
116 		ioctl(ffd, B_JOYSTICK_SET_DEVICE_MODULE, fJoystickInfo);
117 		ioctl(ffd, B_JOYSTICK_GET_DEVICE_MODULE, fJoystickInfo);
118 		LOG("ioctl - %d\n", fJoystickInfo->num_buttons);
119 
120 		return ffd;
121 	} else
122 		return errno;
123 }
124 
125 
126 void
127 BJoystick::Close(void)
128 {
129 	CALLED();
130 	if (ffd >= 0)
131 		close(ffd);
132 	ffd = -1;
133 }
134 
135 
136 void
137 BJoystick::ScanDevices(bool use_disabled)
138 {
139 	CALLED();
140 	if (use_disabled) {
141 		_BJoystickTweaker temp(*this);
142 		temp.scan_including_disabled();
143 	}
144 }
145 
146 
147 int32
148 BJoystick::CountDevices()
149 {
150 	CALLED();
151 
152 	// Refresh devices list
153 	ScanDevices(true);
154 
155 	int32 count = 0;
156 	if (fDevices != NULL)
157 		count = fDevices->CountItems();
158 
159 	LOG("Count = %d\n", count);
160 	return count;
161 }
162 
163 
164 status_t
165 BJoystick::GetDeviceName(int32 n, char *name, size_t bufSize)
166 {
167 	CALLED();
168 	BString *temp = NULL;
169 	if (fDevices != NULL && fDevices->CountItems() > n)
170 		temp = static_cast<BString*>(fDevices->ItemAt(n));
171 	else
172 		return B_BAD_INDEX;
173 
174 	if (temp != NULL && name != NULL) {
175 		if(temp->Length() > (int32)bufSize)
176 			return B_NAME_TOO_LONG;
177 		strncpy(name, temp->String(), bufSize);
178 		name[bufSize - 1] = '\0';
179 		LOG("Device Name = %s\n", name);
180 		return B_OK;
181 	}
182 	return B_ERROR;
183 }
184 
185 
186 bool
187 BJoystick::EnterEnhancedMode(const entry_ref *ref)
188 {
189 	CALLED();
190 	fBeBoxMode = false;
191 	return !fBeBoxMode;
192 }
193 
194 
195 int32
196 BJoystick::CountSticks()
197 {
198 	CALLED();
199 	return fJoystickInfo->num_sticks;
200 }
201 
202 
203 int32
204 BJoystick::CountAxes()
205 {
206 	CALLED();
207 	return fJoystickInfo->num_axes;
208 }
209 
210 
211 int32
212 BJoystick::CountHats()
213 {
214 	CALLED();
215 	return fJoystickInfo->num_hats;
216 }
217 
218 
219 int32
220 BJoystick::CountButtons()
221 {
222 	CALLED();
223 	return fJoystickInfo->num_buttons;
224 }
225 
226 status_t
227 BJoystick::GetControllerModule(BString *out_name)
228 {
229 	CALLED();
230 	if (fJoystickInfo != NULL && ffd >= 0) {
231 		out_name->SetTo(fJoystickInfo->module_name);
232 		return B_OK;
233 	} else
234 		return B_ERROR;
235 
236 }
237 
238 
239 status_t
240 BJoystick::GetControllerName(BString *out_name)
241 {
242 	CALLED();
243 	if (fJoystickInfo != NULL && ffd >= 0) {
244 		out_name->SetTo(fJoystickInfo->controller_name);
245 		return B_OK;
246 	} else
247 		return B_ERROR;
248 }
249 
250 
251 bool
252 BJoystick::IsCalibrationEnabled()
253 {
254 	CALLED();
255 	return fJoystickInfo->calibration_enable;
256 }
257 
258 
259 status_t
260 BJoystick::EnableCalibration(bool calibrates)
261 {
262 	CALLED();
263 	if (ffd >= 0) {
264 		fJoystickInfo->calibration_enable = calibrates;
265 		return B_OK;
266 	} else
267 		return B_NO_INIT;
268 }
269 
270 
271 status_t
272 BJoystick::SetMaxLatency(bigtime_t max_latency)
273 {
274 	CALLED();
275 	fJoystickInfo->max_latency = max_latency;
276 	 //else B_ERROR (when?)
277 	return B_OK;
278 }
279 
280 //--------- not done -------------------
281 
282 status_t
283 BJoystick::GetAxisNameAt(int32 index, BString *out_name)
284 {
285 	CALLED();
286 	return B_BAD_INDEX;
287 }
288 
289 
290 status_t
291 BJoystick::GetHatNameAt(int32 index, BString *out_name)
292 {
293 	CALLED();
294 	return B_BAD_INDEX;
295 }
296 
297 
298 status_t
299 BJoystick::GetButtonNameAt(int32 index, BString *out_name)
300 {
301 	CALLED();
302 	return B_BAD_INDEX;
303 }
304 
305 
306 status_t
307 BJoystick::GetAxisValues(int16 *out_values, int32 for_stick)
308 {
309 	CALLED();
310 	return B_BAD_VALUE;
311 }
312 
313 
314 status_t
315 BJoystick::GetHatValues(uint8 *out_hats, int32 for_stick)
316 {
317 	CALLED();
318 	return B_BAD_VALUE;
319 }
320 
321 
322 uint32
323 BJoystick::ButtonValues(int32 for_stick)
324 {
325 	CALLED();
326 	return 0;
327 }
328 
329 
330 status_t
331 BJoystick::Update(void)
332 {
333 	CALLED();
334 	if (ffd >= 0) {
335 		return B_OK;
336 	} else
337 		return B_ERROR;
338 }
339 
340 
341 void
342 BJoystick::Calibrate(struct _extended_joystick *reading)
343 {
344 	CALLED();
345 }
346 
347 
348 status_t
349 BJoystick::GatherEnhanced_info(const entry_ref *ref)
350 {
351 	CALLED();
352 	return B_ERROR;
353 }
354 
355 
356 status_t
357 BJoystick::SaveConfig(const entry_ref *ref)
358 {
359 	CALLED();
360 	return B_ERROR;
361 }
362 
363