1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
5 * Copyright 1997 Andreas Mohr
7 * nearly all joystick functions can be regarded as obsolete,
8 * as Linux (2.1.x) now supports extended joysticks
9 * with a completely new joystick driver interface
10 * new driver's docu says:
11 * "For backward compatibility the old interface is still included,
12 * but will be dropped in the future."
13 * Thus we should implement the new interface and at most keep the old
14 * routines for backward compatibility.
20 * 01/2000 added support for new joystick driver
31 #include <sys/ioctl.h>
32 #ifdef HAVE_LINUX_JOYSTICK_H
33 #include <linux/joystick.h>
34 #define JOYDEV "/dev/js%d"
36 #ifdef HAVE_SYS_ERRNO_H
37 #include <sys/errno.h>
44 #include "debugtools.h"
46 DEFAULT_DEBUG_CHANNEL(joystick);
48 #ifdef HAVE_LINUX_JOYSTICK_H
50 #define MAXJOYSTICK (JOYSTICKID2 + 1)
52 static struct dummy_struct* JSTCK_Dummy = NULL;
54 /**************************************************************************
55 * JSTCK_drvOpen [internal]
57 static DWORD JSTCK_drvOpen(LPSTR str)
62 /* I know, this is ugly, but who cares... */
63 JSTCK_Dummy = (struct dummy_struct*)1;
67 /**************************************************************************
68 * JSTCK_drvClose [internal]
70 static DWORD JSTCK_drvClose(DWORD dwDevID)
86 /**************************************************************************
87 * JSTCK_OpenDevice [internal]
89 static int JSTCK_OpenDevice(WORD wID)
94 if (wID >= MAXJOYSTICK) return -1;
96 sprintf(buf, JOYDEV, wID);
97 #ifdef HAVE_LINUX_22_JOYSTICK_API
98 flags = O_RDONLY | O_NONBLOCK;
102 return open(buf, flags);
105 /**************************************************************************
106 * JoyGetDevCaps [MMSYSTEM.102]
108 static LONG JSTCK_GetDevCaps(DWORD dwDevID, LPJOYCAPSA lpCaps, DWORD dwSize)
110 #ifdef HAVE_LINUX_22_JOYSTICK_API
114 char identString[MAXPNAMELEN];
118 if (dwDevID >= MAXJOYSTICK) return MMSYSERR_NODRIVER;
120 #ifdef HAVE_LINUX_22_JOYSTICK_API
122 if ((dev = JSTCK_OpenDevice(dwDevID)) < 0) return JOYERR_PARMS;
123 ioctl(dev, JSIOCGAXES, &nrOfAxes);
124 ioctl(dev, JSIOCGBUTTONS, &nrOfButtons);
125 ioctl(dev, JSIOCGVERSION, &driverVersion);
126 ioctl(dev, JSIOCGNAME(sizeof(identString)), &identString);
127 TRACE("Driver: 0x%06x, Name: %s, #Axes: %d, #Buttons: %d\n",
128 driverVersion, identString, nrOfAxes, nrOfButtons);
129 lpCaps->wMid = MM_MICROSOFT;
130 lpCaps->wPid = MM_PC_JOYSTICK;
131 strncpy(lpCaps->szPname, identString, MAXPNAMELEN);
132 lpCaps->szPname[MAXPNAMELEN-1] = '\0';
134 lpCaps->wXmax = 0xFFFF;
136 lpCaps->wYmax = 0xFFFF;
138 lpCaps->wZmax = (nrOfAxes >= 3) ? 0xFFFF : 0;
139 lpCaps->wNumButtons = nrOfButtons;
140 if (dwSize == sizeof(JOYCAPSA)) {
141 /* since we supose ntOfAxes <= 6 in the following code, do it explicitely */
142 if (nrOfAxes > 6) nrOfAxes = 6;
143 /* complete 95 structure */
145 lpCaps->wRmax = nrOfAxes >= 4 ? 0xFFFF : 0;
147 lpCaps->wUmax = nrOfAxes >= 5 ? 0xFFFF : 0;
149 lpCaps->wVmax = nrOfAxes >= 6 ? 0xFFFF : 0;
150 lpCaps->wMaxAxes = 6; /* same as MS Joystick Driver */
151 lpCaps->wNumAxes = nrOfAxes; /* nr of axes in use */
152 lpCaps->wMaxButtons = 32; /* same as MS Joystick Driver */
153 strcpy(lpCaps->szRegKey, "");
154 strcpy(lpCaps->szOEMVxD, "");
157 case 6: lpCaps->wCaps |= JOYCAPS_HASV;
158 case 5: lpCaps->wCaps |= JOYCAPS_HASU;
159 case 4: lpCaps->wCaps |= JOYCAPS_HASR;
160 case 3: lpCaps->wCaps |= JOYCAPS_HASZ;
161 /* FIXME: don't know how to detect for
162 JOYCAPS_HASPOV, JOYCAPS_POV4DIR, JOYCAPS_POVCTS */
168 lpCaps->wMid = MM_MICROSOFT;
169 lpCaps->wPid = MM_PC_JOYSTICK;
170 strcpy(lpCaps->szPname, "WineJoy"); /* joystick product name */
172 lpCaps->wXmax = 0xFFFF;
174 lpCaps->wYmax = 0xFFFF;
177 lpCaps->wNumButtons = 2;
178 if (dwSize == sizeof(JOYCAPSA)) {
179 /* complete 95 structure */
187 lpCaps->wMaxAxes = 2;
188 lpCaps->wNumAxes = 2;
189 lpCaps->wMaxButtons = 4;
190 strcpy(lpCaps->szRegKey,"");
191 strcpy(lpCaps->szOEMVxD,"");
195 return JOYERR_NOERROR;
198 /**************************************************************************
199 * JSTCK_GetPos [internal]
201 static LONG JSTCK_GetPosEx(DWORD dwDevID, LPJOYINFOEX lpInfo)
204 #ifdef HAVE_LINUX_22_JOYSTICK_API
211 if ((dev = JSTCK_OpenDevice(dwDevID)) < 0) return JOYERR_PARMS;
213 #ifdef HAVE_LINUX_22_JOYSTICK_API
214 /* After opening the device it's state can be
215 read with JS_EVENT_INIT flag */
216 while ((read(dev, &ev, sizeof(struct js_event))) > 0) {
217 if (ev.type == (JS_EVENT_AXIS | JS_EVENT_INIT)) {
220 if (lpInfo->dwFlags & JOY_RETURNX)
221 lpInfo->dwXpos = ev.value + 32767;
224 if (lpInfo->dwFlags & JOY_RETURNY)
225 lpInfo->dwYpos = ev.value + 32767;
228 if (lpInfo->dwFlags & JOY_RETURNZ)
229 lpInfo->dwZpos = ev.value + 32767;
232 if (lpInfo->dwFlags & JOY_RETURNR)
233 lpInfo->dwRpos = ev.value + 32767;
235 if (lpInfo->dwFlags & JOY_RETURNU)
236 lpInfo->dwUpos = ev.value + 32767;
238 if (lpInfo->dwFlags & JOY_RETURNV)
239 lpInfo->dwVpos = ev.value + 32767;
242 FIXME("Unknown joystick event '%d'\n", ev.number);
244 } else if (ev.type == (JS_EVENT_BUTTON | JS_EVENT_INIT)) {
245 if (lpInfo->dwFlags & JOY_RETURNBUTTONS) {
247 lpInfo->dwButtons |= (1 << ev.number);
248 /* FIXME: what to do for this field when
249 * multiple buttons are depressed ?
251 lpInfo->dwButtonNumber = ev.number + 1;
256 /* EAGAIN is returned when the queue is empty */
257 if (errno != EAGAIN) {
258 /* FIXME: error should not be ignored */
259 ERR("Error while reading joystick state (%d)\n", errno);
262 dev_stat = read(dev, &js, sizeof(js));
263 if (dev_stat != sizeof(js)) {
265 return JOYERR_UNPLUGGED; /* FIXME: perhaps wrong, but what should I return else ? */
269 if (lpInfo->dwFlags & JOY_RETURNX)
270 lpInfo->dwXpos = js.x; /* FIXME: perhaps multiply it somehow ? */
271 if (lpInfo->dwFlags & JOY_RETURNY)
272 lpInfo->dwYpos = js.y;
273 if (lpInfo->dwFlags & JOY_RETURNBUTTONS)
274 lpInfo->dwButtons = js.buttons;
279 TRACE("x: %ld, y: %ld, z: %ld, r: %ld, u: %ld, v: %ld, buttons: 0x%04x, flags: 0x%04x\n",
280 lpInfo->dwXpos, lpInfo->dwYpos, lpInfo->dwZpos,
281 lpInfo->dwRpos, lpInfo->dwUpos, lpInfo->dwVpos,
282 (unsigned int)lpInfo->dwButtons,
283 (unsigned int)lpInfo->dwFlags);
285 return JOYERR_NOERROR;
288 /**************************************************************************
289 * JSTCK_GetPos [internal]
291 static LONG JSTCK_GetPos(DWORD dwDevID, LPJOYINFO lpInfo)
296 memset(&ji, 0, sizeof(ji));
298 ji.dwSize = sizeof(ji);
299 ji.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ | JOY_RETURNBUTTONS;
300 ret = JSTCK_GetPosEx(dwDevID, &ji);
301 if (ret == JOYERR_NOERROR) {
302 lpInfo->wXpos = ji.dwXpos;
303 lpInfo->wYpos = ji.dwYpos;
304 lpInfo->wZpos = ji.dwZpos;
305 lpInfo->wButtons = ji.dwButtons;
311 /**************************************************************************
312 * JSTCK_DriverProc [internal]
314 LONG CALLBACK JSTCK_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg,
315 DWORD dwParam1, DWORD dwParam2)
317 /* EPP TRACE("(%08lX, %04X, %08lX, %08lX, %08lX)\n", */
318 /* EPP dwDevID, hDriv, wMsg, dwParam1, dwParam2); */
321 case DRV_LOAD: return 1;
322 case DRV_FREE: return 1;
323 case DRV_OPEN: return JSTCK_drvOpen((LPSTR)dwParam1);
324 case DRV_CLOSE: return JSTCK_drvClose(dwDevID);
325 case DRV_ENABLE: return 1;
326 case DRV_DISABLE: return 1;
327 case DRV_QUERYCONFIGURE: return 1;
328 case DRV_CONFIGURE: MessageBoxA(0, "JoyStick MultiMedia Driver !", "JoyStick Driver", MB_OK); return 1;
329 case DRV_INSTALL: return DRVCNF_RESTART;
330 case DRV_REMOVE: return DRVCNF_RESTART;
332 case JDD_GETNUMDEVS: return MAXJOYSTICK;
333 case JDD_GETDEVCAPS: return JSTCK_GetDevCaps(dwDevID, (LPJOYCAPSA)dwParam1, dwParam2);
334 case JDD_GETPOS: return JSTCK_GetPos(dwDevID, (LPJOYINFO)dwParam1);
335 case JDD_SETCALIBRATION:
336 case JDD_CONFIGCHANGED: return JOYERR_NOCANDO;
337 case JDD_GETPOSEX: return JSTCK_GetPosEx(dwDevID, (LPJOYINFOEX)dwParam1);
339 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
345 /**************************************************************************
346 * JSTCK_DriverProc [internal]
348 LONG CALLBACK JSTCK_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg,
349 DWORD dwParam1, DWORD dwParam2)
351 /* EPP TRACE("(%08lX, %04X, %08lX, %08lX, %08lX)\n", */
352 /* EPP dwDevID, hDriv, wMsg, dwParam1, dwParam2); */
361 case DRV_QUERYCONFIGURE: return 0;
362 case DRV_CONFIGURE: MessageBoxA(0, "JoyStick MultiMedia Driver !", "JoyStick Driver", MB_OK); return 1;
363 case DRV_INSTALL: return DRVCNF_RESTART;
364 case DRV_REMOVE: return DRVCNF_RESTART;
366 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);