1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
5 * Copyright 1997 Andreas Mohr
6 * 2000 Wolfgang Schwotzer
17 #include <sys/ioctl.h>
25 #include "wine/mmsystem16.h"
28 #include "debugtools.h"
30 DEFAULT_DEBUG_CHANNEL(mmsys);
32 #define MAXJOYSTICK (JOYSTICKID2 + 1)
33 #define JOY_PERIOD_MIN (10) /* min Capture time period */
34 #define JOY_PERIOD_MAX (1000) /* max Capture time period */
36 typedef struct tagWINE_JOYSTICK {
45 static WINE_JOYSTICK JOY_Sticks[MAXJOYSTICK];
47 /**************************************************************************
48 * JOY_LoadDriver [internal]
50 static BOOL JOY_LoadDriver(DWORD dwJoyID)
52 if (dwJoyID >= MAXJOYSTICK)
54 if (JOY_Sticks[dwJoyID].hDriver)
57 return JOY_Sticks[dwJoyID].hDriver = OpenDriverA("joystick.drv", 0, dwJoyID);
60 /**************************************************************************
61 * JOY_Timer [internal]
63 static void CALLBACK JOY_Timer(HWND hWnd, UINT wMsg, UINT wTimer, DWORD dwTime)
69 unsigned buttonChange;
71 for (i = 0; i < MAXJOYSTICK; i++) {
74 if (joy->hCapture != hWnd) continue;
77 pos = MAKELONG(ji.wXpos, ji.wYpos);
80 abs(joy->ji.wXpos - ji.wXpos) > joy->threshold ||
81 abs(joy->ji.wYpos - ji.wYpos) > joy->threshold) {
82 SendMessageA(joy->hCapture, MM_JOY1MOVE + i, ji.wButtons, pos);
83 joy->ji.wXpos = ji.wXpos;
84 joy->ji.wYpos = ji.wYpos;
87 abs(joy->ji.wZpos - ji.wZpos) > joy->threshold) {
88 SendMessageA(joy->hCapture, MM_JOY1ZMOVE + i, ji.wButtons, pos);
89 joy->ji.wZpos = ji.wZpos;
91 if ((buttonChange = joy->ji.wButtons ^ ji.wButtons) != 0) {
92 if (ji.wButtons & buttonChange)
93 SendMessageA(joy->hCapture, MM_JOY1BUTTONDOWN + i,
94 (buttonChange << 8) | (ji.wButtons & buttonChange), pos);
95 if (joy->ji.wButtons & buttonChange)
96 SendMessageA(joy->hCapture, MM_JOY1BUTTONUP + i,
97 (buttonChange << 8) | (joy->ji.wButtons & buttonChange), pos);
98 joy->ji.wButtons = ji.wButtons;
103 /**************************************************************************
104 * joyGetNumDevs [WINMM.@]
106 UINT WINAPI joyGetNumDevs(void)
111 for (i = 0; i < MAXJOYSTICK; i++) {
112 if (JOY_LoadDriver(i)) {
113 ret += SendDriverMessage(JOY_Sticks[i].hDriver, JDD_GETNUMDEVS, 0L, 0L);
119 /**************************************************************************
120 * joyGetNumDevs [MMSYSTEM.101]
122 UINT16 WINAPI joyGetNumDevs16(void)
124 return joyGetNumDevs();
127 /**************************************************************************
128 * joyGetDevCapsA [WINMM.@]
130 MMRESULT WINAPI joyGetDevCapsA(UINT wID, LPJOYCAPSA lpCaps, UINT wSize)
132 if (wID >= MAXJOYSTICK) return JOYERR_PARMS;
133 if (!JOY_LoadDriver(wID)) return MMSYSERR_NODRIVER;
135 lpCaps->wPeriodMin = JOY_PERIOD_MIN; /* FIXME */
136 lpCaps->wPeriodMax = JOY_PERIOD_MAX; /* FIXME (same as MS Joystick Driver) */
138 return SendDriverMessage(JOY_Sticks[wID].hDriver, JDD_GETDEVCAPS, (DWORD)lpCaps, wSize);
141 /**************************************************************************
142 * joyGetDevCapsW [WINMM.@]
144 MMRESULT WINAPI joyGetDevCapsW(UINT wID, LPJOYCAPSW lpCaps, UINT wSize)
147 MMRESULT ret = joyGetDevCapsA(wID, &jca, sizeof(jca));
149 if (ret != JOYERR_NOERROR) return ret;
150 lpCaps->wMid = jca.wMid;
151 lpCaps->wPid = jca.wPid;
152 MultiByteToWideChar( CP_ACP, 0, jca.szPname, -1, lpCaps->szPname,
153 sizeof(lpCaps->szPname)/sizeof(WCHAR) );
154 lpCaps->wXmin = jca.wXmin;
155 lpCaps->wXmax = jca.wXmax;
156 lpCaps->wYmin = jca.wYmin;
157 lpCaps->wYmax = jca.wYmax;
158 lpCaps->wZmin = jca.wZmin;
159 lpCaps->wZmax = jca.wZmax;
160 lpCaps->wNumButtons = jca.wNumButtons;
161 lpCaps->wPeriodMin = jca.wPeriodMin;
162 lpCaps->wPeriodMax = jca.wPeriodMax;
164 if (wSize >= sizeof(JOYCAPSW)) { /* Win95 extensions ? */
165 lpCaps->wRmin = jca.wRmin;
166 lpCaps->wRmax = jca.wRmax;
167 lpCaps->wUmin = jca.wUmin;
168 lpCaps->wUmax = jca.wUmax;
169 lpCaps->wVmin = jca.wVmin;
170 lpCaps->wVmax = jca.wVmax;
171 lpCaps->wCaps = jca.wCaps;
172 lpCaps->wMaxAxes = jca.wMaxAxes;
173 lpCaps->wNumAxes = jca.wNumAxes;
174 lpCaps->wMaxButtons = jca.wMaxButtons;
175 MultiByteToWideChar( CP_ACP, 0, jca.szRegKey, -1, lpCaps->szRegKey,
176 sizeof(lpCaps->szRegKey)/sizeof(WCHAR) );
177 MultiByteToWideChar( CP_ACP, 0, jca.szOEMVxD, -1, lpCaps->szOEMVxD,
178 sizeof(lpCaps->szOEMVxD)/sizeof(WCHAR) );
184 /**************************************************************************
185 * joyGetDevCaps [MMSYSTEM.102]
187 MMRESULT16 WINAPI joyGetDevCaps16(UINT16 wID, LPJOYCAPS16 lpCaps, UINT16 wSize)
190 MMRESULT ret = joyGetDevCapsA(wID, &jca, sizeof(jca));
192 if (ret != JOYERR_NOERROR) return ret;
193 lpCaps->wMid = jca.wMid;
194 lpCaps->wPid = jca.wPid;
195 strcpy(lpCaps->szPname, jca.szPname);
196 lpCaps->wXmin = jca.wXmin;
197 lpCaps->wXmax = jca.wXmax;
198 lpCaps->wYmin = jca.wYmin;
199 lpCaps->wYmax = jca.wYmax;
200 lpCaps->wZmin = jca.wZmin;
201 lpCaps->wZmax = jca.wZmax;
202 lpCaps->wNumButtons = jca.wNumButtons;
203 lpCaps->wPeriodMin = jca.wPeriodMin;
204 lpCaps->wPeriodMax = jca.wPeriodMax;
206 if (wSize >= sizeof(JOYCAPS16)) { /* Win95 extensions ? */
207 lpCaps->wRmin = jca.wRmin;
208 lpCaps->wRmax = jca.wRmax;
209 lpCaps->wUmin = jca.wUmin;
210 lpCaps->wUmax = jca.wUmax;
211 lpCaps->wVmin = jca.wVmin;
212 lpCaps->wVmax = jca.wVmax;
213 lpCaps->wCaps = jca.wCaps;
214 lpCaps->wMaxAxes = jca.wMaxAxes;
215 lpCaps->wNumAxes = jca.wNumAxes;
216 lpCaps->wMaxButtons = jca.wMaxButtons;
217 strcpy(lpCaps->szRegKey, jca.szRegKey);
218 strcpy(lpCaps->szOEMVxD, jca.szOEMVxD);
224 /**************************************************************************
225 * joyGetPosEx [WINMM.@]
227 MMRESULT WINAPI joyGetPosEx(UINT wID, LPJOYINFOEX lpInfo)
229 TRACE("(%d, %p);\n", wID, lpInfo);
231 if (wID >= MAXJOYSTICK) return JOYERR_PARMS;
232 if (!JOY_LoadDriver(wID)) return MMSYSERR_NODRIVER;
240 lpInfo->dwButtons = 0;
241 lpInfo->dwButtonNumber = 0;
243 lpInfo->dwReserved1 = 0;
244 lpInfo->dwReserved2 = 0;
246 return SendDriverMessage(JOY_Sticks[wID].hDriver, JDD_GETPOSEX, (DWORD)lpInfo, 0L);
249 /**************************************************************************
250 * joyGetPosEx [MMSYSTEM.110]
252 MMRESULT16 WINAPI joyGetPosEx16(UINT16 wID, LPJOYINFOEX lpInfo)
254 return joyGetPosEx(wID, lpInfo);
257 /**************************************************************************
258 * joyGetPos [WINMM.@]
260 MMRESULT WINAPI joyGetPos(UINT wID, LPJOYINFO lpInfo)
262 TRACE("(%d, %p);\n", wID, lpInfo);
264 if (wID >= MAXJOYSTICK) return JOYERR_PARMS;
265 if (!JOY_LoadDriver(wID)) return MMSYSERR_NODRIVER;
270 lpInfo->wButtons = 0;
272 return SendDriverMessage(JOY_Sticks[wID].hDriver, JDD_GETPOS, (DWORD)lpInfo, 0L);
275 /**************************************************************************
276 * joyGetPos [MMSYSTEM.103]
278 MMRESULT16 WINAPI joyGetPos16(UINT16 wID, LPJOYINFO16 lpInfo)
283 TRACE("(%d, %p);\n", wID, lpInfo);
285 if ((ret = joyGetPos(wID, &ji)) == JOYERR_NOERROR) {
286 lpInfo->wXpos = ji.wXpos;
287 lpInfo->wYpos = ji.wYpos;
288 lpInfo->wZpos = ji.wZpos;
289 lpInfo->wButtons = ji.wButtons;
294 /**************************************************************************
295 * joyGetThreshold [WINMM.@]
297 MMRESULT WINAPI joyGetThreshold(UINT wID, LPUINT lpThreshold)
299 TRACE("(%04X, %p);\n", wID, lpThreshold);
301 if (wID >= MAXJOYSTICK) return JOYERR_PARMS;
303 *lpThreshold = JOY_Sticks[wID].threshold;
304 return JOYERR_NOERROR;
307 /**************************************************************************
308 * joyGetThreshold [MMSYSTEM.104]
310 MMRESULT16 WINAPI joyGetThreshold16(UINT16 wID, LPUINT16 lpThreshold)
312 TRACE("(%04X, %p);\n", wID, lpThreshold);
314 if (wID >= MAXJOYSTICK) return JOYERR_PARMS;
316 *lpThreshold = JOY_Sticks[wID].threshold;
317 return JOYERR_NOERROR;
320 /**************************************************************************
321 * joyReleaseCapture [WINMM.@]
323 MMRESULT WINAPI joyReleaseCapture(UINT wID)
325 TRACE("(%04X);\n", wID);
327 if (wID >= MAXJOYSTICK) return JOYERR_PARMS;
328 if (!JOY_LoadDriver(wID)) return MMSYSERR_NODRIVER;
329 if (!JOY_Sticks[wID].hCapture) return JOYERR_NOCANDO;
331 KillTimer(JOY_Sticks[wID].hCapture, JOY_Sticks[wID].wTimer);
332 JOY_Sticks[wID].hCapture = 0;
333 JOY_Sticks[wID].wTimer = 0;
335 return JOYERR_NOERROR;
338 /**************************************************************************
339 * joyReleaseCapture [MMSYSTEM.105]
341 MMRESULT16 WINAPI joyReleaseCapture16(UINT16 wID)
343 return joyReleaseCapture(wID);
346 /**************************************************************************
347 * joySetCapture [WINMM.@]
349 MMRESULT WINAPI joySetCapture(HWND hWnd, UINT wID, UINT wPeriod, BOOL bChanged)
351 TRACE("(%04X, %04X, %d, %d);\n", hWnd, wID, wPeriod, bChanged);
353 if (wID >= MAXJOYSTICK || hWnd == 0) return JOYERR_PARMS;
354 if (wPeriod<JOY_PERIOD_MIN || wPeriod>JOY_PERIOD_MAX) return JOYERR_PARMS;
355 if (!JOY_LoadDriver(wID)) return MMSYSERR_NODRIVER;
357 if (JOY_Sticks[wID].hCapture || !IsWindow(hWnd))
358 return JOYERR_NOCANDO; /* FIXME: what should be returned ? */
360 if (joyGetPos(wID, &JOY_Sticks[wID].ji) != JOYERR_NOERROR)
361 return JOYERR_UNPLUGGED;
363 if ((JOY_Sticks[wID].wTimer = SetTimer(hWnd, 0, wPeriod, JOY_Timer)) == 0)
364 return JOYERR_NOCANDO;
366 JOY_Sticks[wID].hCapture = hWnd;
367 JOY_Sticks[wID].bChanged = bChanged;
369 return JOYERR_NOERROR;
372 /**************************************************************************
373 * joySetCapture [MMSYSTEM.106]
375 MMRESULT16 WINAPI joySetCapture16(HWND16 hWnd, UINT16 wID, UINT16 wPeriod, BOOL16 bChanged)
377 return joySetCapture16(hWnd, wID, wPeriod, bChanged);
380 /**************************************************************************
381 * joySetThreshold [WINMM.@]
383 MMRESULT WINAPI joySetThreshold(UINT wID, UINT wThreshold)
385 TRACE("(%04X, %d);\n", wID, wThreshold);
387 if (wID >= MAXJOYSTICK) return MMSYSERR_INVALPARAM;
389 JOY_Sticks[wID].threshold = wThreshold;
391 return JOYERR_NOERROR;
394 /**************************************************************************
395 * joySetThreshold [MMSYSTEM.107]
397 MMRESULT16 WINAPI joySetThreshold16(UINT16 wID, UINT16 wThreshold)
399 return joySetThreshold16(wID,wThreshold);
402 /**************************************************************************
403 * joySetCalibration [MMSYSTEM.109]
405 MMRESULT16 WINAPI joySetCalibration16(UINT16 wID)
407 FIXME("(%04X): stub.\n", wID);
408 return JOYERR_NOCANDO;