1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
5 * Copyright 1997 Andreas Mohr
6 * 2000 Wolfgang Schwotzer
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 #ifdef HAVE_SYS_IOCTL_H
34 #include <sys/ioctl.h>
45 #include "wine/debug.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(mmsys);
49 #define MAXJOYSTICK (JOYSTICKID2 + 1)
50 #define JOY_PERIOD_MIN (10) /* min Capture time period */
51 #define JOY_PERIOD_MAX (1000) /* max Capture time period */
53 typedef struct tagWINE_JOYSTICK {
62 static WINE_JOYSTICK JOY_Sticks[MAXJOYSTICK];
64 /**************************************************************************
65 * JOY_LoadDriver [internal]
67 static BOOL JOY_LoadDriver(DWORD dwJoyID)
69 if (dwJoyID >= MAXJOYSTICK)
71 if (JOY_Sticks[dwJoyID].hDriver)
74 JOY_Sticks[dwJoyID].hDriver = OpenDriverA("joystick.drv", 0, dwJoyID);
75 return (JOY_Sticks[dwJoyID].hDriver != 0);
78 /**************************************************************************
79 * JOY_Timer [internal]
81 static void CALLBACK JOY_Timer(HWND hWnd, UINT wMsg, UINT wTimer, DWORD dwTime)
87 unsigned buttonChange;
89 for (i = 0; i < MAXJOYSTICK; i++) {
92 if (joy->hCapture != hWnd) continue;
95 pos = MAKELONG(ji.wXpos, ji.wYpos);
98 abs(joy->ji.wXpos - ji.wXpos) > joy->threshold ||
99 abs(joy->ji.wYpos - ji.wYpos) > joy->threshold) {
100 SendMessageA(joy->hCapture, MM_JOY1MOVE + i, ji.wButtons, pos);
101 joy->ji.wXpos = ji.wXpos;
102 joy->ji.wYpos = ji.wYpos;
104 if (!joy->bChanged ||
105 abs(joy->ji.wZpos - ji.wZpos) > joy->threshold) {
106 SendMessageA(joy->hCapture, MM_JOY1ZMOVE + i, ji.wButtons, pos);
107 joy->ji.wZpos = ji.wZpos;
109 if ((buttonChange = joy->ji.wButtons ^ ji.wButtons) != 0) {
110 if (ji.wButtons & buttonChange)
111 SendMessageA(joy->hCapture, MM_JOY1BUTTONDOWN + i,
112 (buttonChange << 8) | (ji.wButtons & buttonChange), pos);
113 if (joy->ji.wButtons & buttonChange)
114 SendMessageA(joy->hCapture, MM_JOY1BUTTONUP + i,
115 (buttonChange << 8) | (joy->ji.wButtons & buttonChange), pos);
116 joy->ji.wButtons = ji.wButtons;
121 /**************************************************************************
122 * joyGetNumDevs [WINMM.@]
124 UINT WINAPI joyGetNumDevs(void)
129 for (i = 0; i < MAXJOYSTICK; i++) {
130 if (JOY_LoadDriver(i)) {
131 ret += SendDriverMessage(JOY_Sticks[i].hDriver, JDD_GETNUMDEVS, 0L, 0L);
137 /**************************************************************************
138 * joyGetNumDevs [MMSYSTEM.101]
140 UINT16 WINAPI joyGetNumDevs16(void)
142 return joyGetNumDevs();
145 /**************************************************************************
146 * joyGetDevCapsA [WINMM.@]
148 MMRESULT WINAPI joyGetDevCapsA(UINT wID, LPJOYCAPSA lpCaps, UINT wSize)
150 if (wID >= MAXJOYSTICK) return JOYERR_PARMS;
151 if (!JOY_LoadDriver(wID)) return MMSYSERR_NODRIVER;
153 lpCaps->wPeriodMin = JOY_PERIOD_MIN; /* FIXME */
154 lpCaps->wPeriodMax = JOY_PERIOD_MAX; /* FIXME (same as MS Joystick Driver) */
156 return SendDriverMessage(JOY_Sticks[wID].hDriver, JDD_GETDEVCAPS, (DWORD)lpCaps, wSize);
159 /**************************************************************************
160 * joyGetDevCapsW [WINMM.@]
162 MMRESULT WINAPI joyGetDevCapsW(UINT wID, LPJOYCAPSW lpCaps, UINT wSize)
165 MMRESULT ret = joyGetDevCapsA(wID, &jca, sizeof(jca));
167 if (ret != JOYERR_NOERROR) return ret;
168 lpCaps->wMid = jca.wMid;
169 lpCaps->wPid = jca.wPid;
170 MultiByteToWideChar( CP_ACP, 0, jca.szPname, -1, lpCaps->szPname,
171 sizeof(lpCaps->szPname)/sizeof(WCHAR) );
172 lpCaps->wXmin = jca.wXmin;
173 lpCaps->wXmax = jca.wXmax;
174 lpCaps->wYmin = jca.wYmin;
175 lpCaps->wYmax = jca.wYmax;
176 lpCaps->wZmin = jca.wZmin;
177 lpCaps->wZmax = jca.wZmax;
178 lpCaps->wNumButtons = jca.wNumButtons;
179 lpCaps->wPeriodMin = jca.wPeriodMin;
180 lpCaps->wPeriodMax = jca.wPeriodMax;
182 if (wSize >= sizeof(JOYCAPSW)) { /* Win95 extensions ? */
183 lpCaps->wRmin = jca.wRmin;
184 lpCaps->wRmax = jca.wRmax;
185 lpCaps->wUmin = jca.wUmin;
186 lpCaps->wUmax = jca.wUmax;
187 lpCaps->wVmin = jca.wVmin;
188 lpCaps->wVmax = jca.wVmax;
189 lpCaps->wCaps = jca.wCaps;
190 lpCaps->wMaxAxes = jca.wMaxAxes;
191 lpCaps->wNumAxes = jca.wNumAxes;
192 lpCaps->wMaxButtons = jca.wMaxButtons;
193 MultiByteToWideChar( CP_ACP, 0, jca.szRegKey, -1, lpCaps->szRegKey,
194 sizeof(lpCaps->szRegKey)/sizeof(WCHAR) );
195 MultiByteToWideChar( CP_ACP, 0, jca.szOEMVxD, -1, lpCaps->szOEMVxD,
196 sizeof(lpCaps->szOEMVxD)/sizeof(WCHAR) );
202 /**************************************************************************
203 * joyGetDevCaps [MMSYSTEM.102]
205 MMRESULT16 WINAPI joyGetDevCaps16(UINT16 wID, LPJOYCAPS16 lpCaps, UINT16 wSize)
208 MMRESULT ret = joyGetDevCapsA(wID, &jca, sizeof(jca));
210 if (ret != JOYERR_NOERROR) return ret;
211 lpCaps->wMid = jca.wMid;
212 lpCaps->wPid = jca.wPid;
213 strcpy(lpCaps->szPname, jca.szPname);
214 lpCaps->wXmin = jca.wXmin;
215 lpCaps->wXmax = jca.wXmax;
216 lpCaps->wYmin = jca.wYmin;
217 lpCaps->wYmax = jca.wYmax;
218 lpCaps->wZmin = jca.wZmin;
219 lpCaps->wZmax = jca.wZmax;
220 lpCaps->wNumButtons = jca.wNumButtons;
221 lpCaps->wPeriodMin = jca.wPeriodMin;
222 lpCaps->wPeriodMax = jca.wPeriodMax;
224 if (wSize >= sizeof(JOYCAPS16)) { /* Win95 extensions ? */
225 lpCaps->wRmin = jca.wRmin;
226 lpCaps->wRmax = jca.wRmax;
227 lpCaps->wUmin = jca.wUmin;
228 lpCaps->wUmax = jca.wUmax;
229 lpCaps->wVmin = jca.wVmin;
230 lpCaps->wVmax = jca.wVmax;
231 lpCaps->wCaps = jca.wCaps;
232 lpCaps->wMaxAxes = jca.wMaxAxes;
233 lpCaps->wNumAxes = jca.wNumAxes;
234 lpCaps->wMaxButtons = jca.wMaxButtons;
235 strcpy(lpCaps->szRegKey, jca.szRegKey);
236 strcpy(lpCaps->szOEMVxD, jca.szOEMVxD);
242 /**************************************************************************
243 * joyGetPosEx [WINMM.@]
245 MMRESULT WINAPI joyGetPosEx(UINT wID, LPJOYINFOEX lpInfo)
247 TRACE("(%d, %p);\n", wID, lpInfo);
249 if (wID >= MAXJOYSTICK) return JOYERR_PARMS;
250 if (!JOY_LoadDriver(wID)) return MMSYSERR_NODRIVER;
258 lpInfo->dwButtons = 0;
259 lpInfo->dwButtonNumber = 0;
261 lpInfo->dwReserved1 = 0;
262 lpInfo->dwReserved2 = 0;
264 return SendDriverMessage(JOY_Sticks[wID].hDriver, JDD_GETPOSEX, (DWORD)lpInfo, 0L);
267 /**************************************************************************
268 * joyGetPosEx [MMSYSTEM.110]
270 MMRESULT16 WINAPI joyGetPosEx16(UINT16 wID, LPJOYINFOEX lpInfo)
272 return joyGetPosEx(wID, lpInfo);
275 /**************************************************************************
276 * joyGetPos [WINMM.@]
278 MMRESULT WINAPI joyGetPos(UINT wID, LPJOYINFO lpInfo)
280 TRACE("(%d, %p);\n", wID, lpInfo);
282 if (wID >= MAXJOYSTICK) return JOYERR_PARMS;
283 if (!JOY_LoadDriver(wID)) return MMSYSERR_NODRIVER;
288 lpInfo->wButtons = 0;
290 return SendDriverMessage(JOY_Sticks[wID].hDriver, JDD_GETPOS, (DWORD)lpInfo, 0L);
293 /**************************************************************************
294 * joyGetPos [MMSYSTEM.103]
296 MMRESULT16 WINAPI joyGetPos16(UINT16 wID, LPJOYINFO16 lpInfo)
301 TRACE("(%d, %p);\n", wID, lpInfo);
303 if ((ret = joyGetPos(wID, &ji)) == JOYERR_NOERROR) {
304 lpInfo->wXpos = ji.wXpos;
305 lpInfo->wYpos = ji.wYpos;
306 lpInfo->wZpos = ji.wZpos;
307 lpInfo->wButtons = ji.wButtons;
312 /**************************************************************************
313 * joyGetThreshold [WINMM.@]
315 MMRESULT WINAPI joyGetThreshold(UINT wID, LPUINT lpThreshold)
317 TRACE("(%04X, %p);\n", wID, lpThreshold);
319 if (wID >= MAXJOYSTICK) return JOYERR_PARMS;
321 *lpThreshold = JOY_Sticks[wID].threshold;
322 return JOYERR_NOERROR;
325 /**************************************************************************
326 * joyGetThreshold [MMSYSTEM.104]
328 MMRESULT16 WINAPI joyGetThreshold16(UINT16 wID, LPUINT16 lpThreshold)
330 TRACE("(%04X, %p);\n", wID, lpThreshold);
332 if (wID >= MAXJOYSTICK) return JOYERR_PARMS;
334 *lpThreshold = JOY_Sticks[wID].threshold;
335 return JOYERR_NOERROR;
338 /**************************************************************************
339 * joyReleaseCapture [WINMM.@]
341 MMRESULT WINAPI joyReleaseCapture(UINT wID)
343 TRACE("(%04X);\n", wID);
345 if (wID >= MAXJOYSTICK) return JOYERR_PARMS;
346 if (!JOY_LoadDriver(wID)) return MMSYSERR_NODRIVER;
347 if (!JOY_Sticks[wID].hCapture) return JOYERR_NOCANDO;
349 KillTimer(JOY_Sticks[wID].hCapture, JOY_Sticks[wID].wTimer);
350 JOY_Sticks[wID].hCapture = 0;
351 JOY_Sticks[wID].wTimer = 0;
353 return JOYERR_NOERROR;
356 /**************************************************************************
357 * joyReleaseCapture [MMSYSTEM.105]
359 MMRESULT16 WINAPI joyReleaseCapture16(UINT16 wID)
361 return joyReleaseCapture(wID);
364 /**************************************************************************
365 * joySetCapture [WINMM.@]
367 MMRESULT WINAPI joySetCapture(HWND hWnd, UINT wID, UINT wPeriod, BOOL bChanged)
369 TRACE("(%04X, %04X, %d, %d);\n", hWnd, wID, wPeriod, bChanged);
371 if (wID >= MAXJOYSTICK || hWnd == 0) return JOYERR_PARMS;
372 if (wPeriod<JOY_PERIOD_MIN || wPeriod>JOY_PERIOD_MAX) return JOYERR_PARMS;
373 if (!JOY_LoadDriver(wID)) return MMSYSERR_NODRIVER;
375 if (JOY_Sticks[wID].hCapture || !IsWindow(hWnd))
376 return JOYERR_NOCANDO; /* FIXME: what should be returned ? */
378 if (joyGetPos(wID, &JOY_Sticks[wID].ji) != JOYERR_NOERROR)
379 return JOYERR_UNPLUGGED;
381 if ((JOY_Sticks[wID].wTimer = SetTimer(hWnd, 0, wPeriod, JOY_Timer)) == 0)
382 return JOYERR_NOCANDO;
384 JOY_Sticks[wID].hCapture = hWnd;
385 JOY_Sticks[wID].bChanged = bChanged;
387 return JOYERR_NOERROR;
390 /**************************************************************************
391 * joySetCapture [MMSYSTEM.106]
393 MMRESULT16 WINAPI joySetCapture16(HWND16 hWnd, UINT16 wID, UINT16 wPeriod, BOOL16 bChanged)
395 return joySetCapture16(hWnd, wID, wPeriod, bChanged);
398 /**************************************************************************
399 * joySetThreshold [WINMM.@]
401 MMRESULT WINAPI joySetThreshold(UINT wID, UINT wThreshold)
403 TRACE("(%04X, %d);\n", wID, wThreshold);
405 if (wID >= MAXJOYSTICK) return MMSYSERR_INVALPARAM;
407 JOY_Sticks[wID].threshold = wThreshold;
409 return JOYERR_NOERROR;
412 /**************************************************************************
413 * joySetThreshold [MMSYSTEM.107]
415 MMRESULT16 WINAPI joySetThreshold16(UINT16 wID, UINT16 wThreshold)
417 return joySetThreshold16(wID,wThreshold);
420 /**************************************************************************
421 * joySetCalibration [MMSYSTEM.109]
423 MMRESULT16 WINAPI joySetCalibration16(UINT16 wID)
425 FIXME("(%04X): stub.\n", wID);
426 return JOYERR_NOCANDO;