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