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