xref: /haiku/src/kits/device/Joystick.cpp (revision 1ac8a0b5cb9f49c223290607d42bb6cc59f74de6)
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 <Joystick.h>
8 #include <List.h>
9 #include <Entry.h>
10 #include <Path.h>
11 #include <Directory.h>
12 
13 #include <String.h>
14 #include <Debug.h>
15 
16 #include <errno.h>
17 #include <fcntl.h>
18 #include <stdio.h>
19 
20 #define DEVICEPATH "/dev/joystick/"
21 
22 typedef struct _joystick_info {
23 	char			module_name[64];
24 	char			device_name[64];
25 	int16			num_axes;
26 	int16			num_buttons;
27 	int16			num_hats;
28 	uint16			num_sticks;
29 } joystick_info;
30 
31 //Scans a directory and adds the entries it founds as strings to the given list
32 static status_t
33 scan_directory(const char* rootPath, BList *list, BEntry *rootEntry = NULL)
34 {
35 	BDirectory root;
36 
37 	if (rootEntry != NULL)
38 		root.SetTo( rootEntry);
39 	else if (rootPath != NULL)
40 		root.SetTo(rootPath);
41 	else
42 		return B_ERROR;
43 
44 	BEntry entry;
45 
46 	ASSERT(list != NULL);
47 	while ((root.GetNextEntry(&entry)) > B_ERROR ) {
48 		if (entry.IsDirectory()) {
49 			scan_directory(rootPath, list, &entry);
50 		} else {
51 			BPath path;
52 			entry.GetPath(&path);
53 			BString str(path.Path());
54 			str.RemoveFirst(rootPath);
55 			list->AddItem(strdup(str.String()));
56 		}
57 	}
58 	return B_OK;
59 }
60 
61 class _BJoystickTweaker {
62 
63 public:
64 					_BJoystickTweaker();
65 					_BJoystickTweaker(BJoystick &stick);
66 virtual				~_BJoystickTweaker();
67 
68 protected:
69 private:
70 		status_t	scan_including_disabled();
71 		status_t	save_config(const entry_ref * ref = NULL);
72 		status_t	get_info();
73 		BJoystick* fJoystick;
74 };
75 //-------------------------------------------------------------------//
76 
77 
78 BJoystick::BJoystick()
79 	: _mBeBoxMode(false)
80 	, _fDevices(new BList)
81 {
82 	ScanDevices();
83 }
84 
85 
86 BJoystick::~BJoystick()
87 {
88 	if (ffd >= 0)
89 		close(ffd);
90 
91 	for (int32 count = _fDevices->CountItems() - 1; count >= 0; count--)
92 		free(_fDevices->RemoveItem(count));
93 
94 	delete _fDevices;
95 }
96 
97 
98 status_t
99 BJoystick::Open(const char *portName)
100 {
101 	return Open(portName, true);
102 }
103 
104 
105 status_t
106 BJoystick::Open(const char *portName,
107 				bool enter_enhanced)
108 {
109 	char buf[64];
110 
111 	//We don't want to use enhanced mode but _mBeBoxMode sugest if we use
112 	//BeBoxMode
113 	if(!enter_enhanced)
114 		_mBeBoxMode = !enter_enhanced;
115 
116 	if (portName == NULL)
117 		return B_BAD_VALUE; // Heheee, we won't crash
118 
119 	if (portName[0] != '/')
120 		snprintf(buf, 64, DEVICEPATH"/%s", portName);
121 	else
122 		// A name like "/dev/joystick/usb/0" was passed
123 		snprintf(buf, 64, "%s", portName);
124 
125 	if (ffd >= 0) //If this port is already open, close it
126 		close(ffd);
127 
128 	// TODO: BeOS don't use O_EXCL, and this seems to lead to some issues. I
129 	// added this flag having read some comments by Marco Nelissen on the
130 	// annotated BeBook. I think BeOS uses O_RDWR|O_NONBLOCK here.
131 	ffd = open(buf, O_RDWR | O_NONBLOCK | O_EXCL);
132 
133 	if (ffd >= 0) {
134 		// we used open() with O_NONBLOCK flag to let it return immediately,
135 		// but we want read/write operations to block if needed, so we clear
136 		// that bit here.
137 		int flags = fcntl(ffd, F_GETFL);
138 		fcntl(ffd, F_SETFL, flags & ~O_NONBLOCK);
139 
140 		//DriverControl();
141 	}
142 	// TODO: I wonder why the return type is a status_t,
143 	// since we (as BeOS does) return the descriptor number for the device...
144 	return (ffd >= 0) ? ffd : errno;
145 }
146 
147 
148 void
149 BJoystick::Close(void)
150 {
151 	if (ffd >= 0)
152 		close(ffd);
153 	ffd = -1;
154 }
155 
156 
157 void
158 BJoystick::ScanDevices(bool use_disabled = false)
159 {
160 	// First, we empty the list
161 	for (int32 count = _fDevices->CountItems() - 1; count >= 0; count--)
162 		free(_fDevices->RemoveItem(count));
163 
164 	// Add devices to the list
165 	scan_directory(DEVICEPATH, _fDevices);
166 }
167 
168 
169 int32
170 BJoystick::CountDevices()
171 {
172 	int32 count = 0;
173 
174 	// Refresh devices list
175 	ScanDevices();
176 
177 	if (_fDevices != NULL)
178 		count = _fDevices->CountItems();
179 
180 	return count;
181 }
182 
183 
184 status_t
185 BJoystick::GetDeviceName(int32 n, char *name, size_t bufSize)
186 {
187 	status_t result = B_ERROR;
188 	const char *dev = NULL;
189 	if (_fDevices != NULL)
190 		dev = static_cast<char*>(_fDevices->ItemAt(n));
191 
192 	if (dev != NULL && name != NULL) {
193 		strncpy(name, dev, bufSize);
194 		name[bufSize - 1] = '\0';
195 		result = B_OK;
196 	}
197 	return result;
198 }
199 
200 
201 status_t
202 BJoystick::Update(void)
203 {
204 	return B_ERROR;
205 }
206 
207 
208 status_t
209 BJoystick::SetMaxLatency(bigtime_t max_latency)
210 {
211 	return B_ERROR;
212 }
213 
214 
215 bool
216 BJoystick::EnterEnhancedMode(const entry_ref *ref)
217 {
218 	_mBeBoxMode = false;
219 	return !_mBeBoxMode;
220 }
221 
222 
223 int32
224 BJoystick::CountSticks()
225 {
226 	return 0;
227 }
228 
229 
230 int32
231 BJoystick::CountAxes()
232 {
233 	return 0;
234 }
235 
236 
237 int32
238 BJoystick::CountHats()
239 {
240 	return 0;
241 }
242 
243 
244 int32
245 BJoystick::CountButtons()
246 {
247 	return 0;
248 }
249 
250 
251 status_t
252 BJoystick::GetAxisValues(int16 *out_values,
253 						 int32 for_stick)
254 {
255 	return B_ERROR;
256 }
257 
258 
259 status_t
260 BJoystick::GetHatValues(uint8 *out_hats,
261 						int32 for_stick)
262 {
263 	return B_ERROR;
264 }
265 
266 
267 uint32
268 BJoystick::ButtonValues(int32 for_stick)
269 {
270 	return 0;
271 }
272 
273 
274 status_t
275 BJoystick::GetAxisNameAt(int32 index,
276 						 BString *out_name)
277 {
278 	return B_ERROR;
279 }
280 
281 
282 status_t
283 BJoystick::GetHatNameAt(int32 index,
284 						BString *out_name)
285 {
286 	return B_ERROR;
287 }
288 
289 
290 status_t
291 BJoystick::GetButtonNameAt(int32 index,
292 						   BString *out_name)
293 {
294 	return B_ERROR;
295 }
296 
297 
298 status_t
299 BJoystick::GetControllerModule(BString *out_name)
300 {
301 	return B_ERROR;
302 }
303 
304 
305 status_t
306 BJoystick::GetControllerName(BString *out_name)
307 {
308 	return B_ERROR;
309 }
310 
311 
312 bool
313 BJoystick::IsCalibrationEnabled()
314 {
315 	return false;
316 }
317 
318 
319 status_t
320 BJoystick::EnableCalibration(bool calibrates)
321 {
322 	return false;
323 }
324 
325 
326 void
327 BJoystick::Calibrate(struct _extended_joystick *reading)
328 {
329 }
330 
331 
332 status_t
333 BJoystick::gather_enhanced_info(const entry_ref *ref)
334 {
335 	return B_ERROR;
336 }
337 
338 
339 status_t
340 BJoystick::save_config(const entry_ref *ref)
341 {
342 	return B_ERROR;
343 }
344 
345 
346 /* These functions are here to maintain Binary Compatibility */
347 void BJoystick::_ReservedJoystick1() {}
348 void BJoystick::_ReservedJoystick2() {}
349 void BJoystick::_ReservedJoystick3() {}
350 status_t BJoystick::_Reserved_Joystick_4(void *, ...) {return B_ERROR;}
351 status_t BJoystick::_Reserved_Joystick_5(void *, ...) {return B_ERROR;}
352 status_t BJoystick::_Reserved_Joystick_6(void *, ...) {return B_ERROR;}
353 
354 
355 //-------------------------------------------------------------------//
356 
357 
358 _BJoystickTweaker::_BJoystickTweaker()
359 {
360 }
361 
362 
363 _BJoystickTweaker::_BJoystickTweaker(BJoystick &stick)
364 {
365 	fJoystick = &stick;
366 }
367 
368 
369 _BJoystickTweaker::~_BJoystickTweaker()
370 {
371 }
372 
373 
374 status_t
375 _BJoystickTweaker::save_config(const entry_ref *ref)
376 {
377 	return B_ERROR;
378 }
379 
380 
381 status_t
382 _BJoystickTweaker::scan_including_disabled()
383 {
384 	return B_ERROR;
385 }
386 
387 
388 status_t
389 _BJoystickTweaker::get_info()
390 {
391 	return B_ERROR;
392 }
393