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