Use DllOverrides from wine.ini as defaults also in
[wine] / multimedia / joystick.c
1 /*
2  * joystick functions
3  *
4  * Copyright 1997 Andreas Mohr
5  *
6  * nearly all joystick functions can be regarded as obsolete,
7  * as Linux (2.1.x) now supports extended joysticks
8  * with a completely new joystick driver interface
9  * new driver's docu says:
10  * "For backward compatibility the old interface is still included,
11  * but will be dropped in the future."
12  * Thus we should implement the new interface and at most keep the old
13  * routines for backward compatibility.
14  */
15
16 #include <unistd.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <fcntl.h>
20 #include <sys/ioctl.h>
21 #include <sys/errno.h>
22 #include "winuser.h"
23 #include "mmsystem.h"
24 #include "debug.h"
25
26 DEFAULT_DEBUG_CHANNEL(mmsys)
27
28 #define MAXJOYDRIVERS   4
29
30 static int count_use[MAXJOYDRIVERS] = {0, 0, 0, 0};
31 static int dev_stat;
32 static int joy_nr_open = 0;
33 static BOOL16 joyCaptured = FALSE;
34 static HWND16 CaptureWnd[MAXJOYDRIVERS] = {0, 0};
35 static int joy_dev[MAXJOYDRIVERS] = {-1, -1,-1,-1};
36 static JOYINFO16 joyCapData[MAXJOYDRIVERS];
37 static unsigned int joy_threshold[MAXJOYDRIVERS] = {0, 0, 0, 0};
38
39 struct js_status
40 {
41     int buttons;
42     int x;
43     int y;
44 };
45
46
47 /**************************************************************************
48  *                              joyOpenDriver           [internal]
49  */
50 BOOL16 joyOpenDriver(WORD wID)
51 {
52         char dev_name[] = "/dev/js%d";
53         char    buf[20];
54
55         if (wID>3) return FALSE;
56         if (joy_dev[wID] >= 0) return TRUE;
57         sprintf(buf,dev_name,wID);
58         if ((joy_dev[wID] = open(buf, O_RDONLY)) >= 0) {
59                 joy_nr_open++;
60                 return TRUE;
61         } else
62                 return FALSE;
63 }
64
65 /**************************************************************************
66  *                              joyCloseDriver           [internal]
67  */
68 void joyCloseDriver(WORD wID)
69 {
70         if (joy_dev[wID] >= 0) {
71                 close(joy_dev[wID]);
72                 joy_dev[wID] = -1;
73                 joy_nr_open--;
74         }
75 }
76
77 /**************************************************************************
78  *                              joySendMessages           [internal]
79  */
80 void joySendMessages(void)
81 {
82         int joy;
83         struct js_status js;
84
85         if (joy_nr_open)
86         {
87             for (joy=0; joy < MAXJOYDRIVERS; joy++) 
88                 if (joy_dev[joy] >= 0) {
89                         if (count_use[joy] > 250) {
90                                 joyCloseDriver(joy);
91                                 count_use[joy] = 0;
92                         }
93                         count_use[joy]++;
94                 } else
95                         return;
96         }
97         if (joyCaptured == FALSE) return;
98
99         TRACE(mmsys, " --\n");
100
101         for (joy=0; joy < MAXJOYDRIVERS; joy++) {
102                 if (joyOpenDriver(joy) == FALSE) continue;
103                 dev_stat = read(joy_dev[joy], &js, sizeof(js));
104                 if (dev_stat == sizeof(js)) {
105                         js.x = js.x*37;
106                         js.y = js.y*37;
107                         if ((joyCapData[joy].wXpos != js.x) || (joyCapData[joy].wYpos != js.y)) {
108                                 SendMessageA(CaptureWnd[joy], MM_JOY1MOVE + joy, js.buttons, MAKELONG(js.x, js.y));
109                                 joyCapData[joy].wXpos = js.x;
110                                 joyCapData[joy].wYpos = js.y;
111                         }
112                         if (joyCapData[joy].wButtons != js.buttons) {
113                                 unsigned int ButtonChanged = (WORD)(joyCapData[joy].wButtons ^ js.buttons)<<8;
114                                 if (joyCapData[joy].wButtons < js.buttons)
115                                 SendMessageA(CaptureWnd[joy], MM_JOY1BUTTONDOWN + joy, ButtonChanged, MAKELONG(js.x, js.y));
116                                 else
117                                 if (joyCapData[joy].wButtons > js.buttons)
118                                 SendMessageA(CaptureWnd[joy], MM_JOY1BUTTONUP
119 + joy, ButtonChanged, MAKELONG(js.x, js.y));
120                                 joyCapData[joy].wButtons = js.buttons;
121                         }
122                 }
123         }
124 }
125
126
127 /**************************************************************************
128  *                              JoyGetNumDevs           [MMSYSTEM.101]
129  */
130 UINT WINAPI joyGetNumDevs(void)
131 {
132         return joyGetNumDevs16();
133 }
134
135 /**************************************************************************
136  *                              JoyGetNumDevs           [MMSYSTEM.101]
137  */
138 UINT16 WINAPI joyGetNumDevs16(void)
139 {
140     int joy;
141     UINT16 joy_cnt = 0;
142
143     for (joy=0; joy<MAXJOYDRIVERS; joy++)
144         if (joyOpenDriver(joy) == TRUE) {               
145                 joyCloseDriver(joy);
146                 joy_cnt++;
147     }
148     TRACE(mmsys, "returning %d\n", joy_cnt);
149     if (!joy_cnt) ERR(mmsys, "No joystick found - "
150                           "perhaps get joystick-0.8.0.tar.gz and load"
151                           "it as module or use Linux >= 2.1.45 to be "
152                           "able to use joysticks.\n");
153     return joy_cnt;
154 }
155
156 /**************************************************************************
157  *                              JoyGetDevCaps           [WINMM.27]
158  */
159 MMRESULT WINAPI joyGetDevCapsA(UINT wID, LPJOYCAPSA lpCaps,UINT wSize)
160 {
161         JOYCAPS16       jc16;
162         MMRESULT16      ret = joyGetDevCaps16(wID,&jc16,sizeof(jc16));
163
164         lpCaps->wMid = jc16.wMid;
165         lpCaps->wPid = jc16.wPid;
166         strcpy(lpCaps->szPname,jc16.szPname);
167         lpCaps->wXmin = jc16.wXmin;
168         lpCaps->wXmax = jc16.wXmax;
169         lpCaps->wYmin = jc16.wYmin;
170         lpCaps->wYmax = jc16.wYmax;
171         lpCaps->wZmin = jc16.wZmin;
172         lpCaps->wZmax = jc16.wZmax;
173         lpCaps->wNumButtons = jc16.wNumButtons;
174         lpCaps->wPeriodMin = jc16.wPeriodMin;
175         lpCaps->wPeriodMax = jc16.wPeriodMax;
176
177         lpCaps->wRmin = jc16.wRmin;
178         lpCaps->wRmax = jc16.wRmax;
179         lpCaps->wUmin = jc16.wUmin;
180         lpCaps->wUmax = jc16.wUmax;
181         lpCaps->wVmin = jc16.wVmin;
182         lpCaps->wVmax = jc16.wVmax;
183         lpCaps->wCaps = jc16.wCaps;
184         lpCaps->wMaxAxes = jc16.wMaxAxes;
185         lpCaps->wNumAxes = jc16.wNumAxes;
186         lpCaps->wMaxButtons = jc16.wMaxButtons;
187         strcpy(lpCaps->szRegKey,jc16.szRegKey);
188         strcpy(lpCaps->szOEMVxD,jc16.szOEMVxD);
189         return ret;
190 }
191
192 /**************************************************************************
193  *                              JoyGetDevCaps           [WINMM.28]
194  */
195 MMRESULT WINAPI joyGetDevCapsW(UINT wID, LPJOYCAPSW lpCaps,UINT wSize)
196 {
197         JOYCAPS16       jc16;
198         MMRESULT16      ret = joyGetDevCaps16(wID,&jc16,sizeof(jc16));
199
200         lpCaps->wMid = jc16.wMid;
201         lpCaps->wPid = jc16.wPid;
202         lstrcpyAtoW(lpCaps->szPname,jc16.szPname);
203         lpCaps->wXmin = jc16.wXmin;
204         lpCaps->wXmax = jc16.wXmax;
205         lpCaps->wYmin = jc16.wYmin;
206         lpCaps->wYmax = jc16.wYmax;
207         lpCaps->wZmin = jc16.wZmin;
208         lpCaps->wZmax = jc16.wZmax;
209         lpCaps->wNumButtons = jc16.wNumButtons;
210         lpCaps->wPeriodMin = jc16.wPeriodMin;
211         lpCaps->wPeriodMax = jc16.wPeriodMax;
212
213         lpCaps->wRmin = jc16.wRmin;
214         lpCaps->wRmax = jc16.wRmax;
215         lpCaps->wUmin = jc16.wUmin;
216         lpCaps->wUmax = jc16.wUmax;
217         lpCaps->wVmin = jc16.wVmin;
218         lpCaps->wVmax = jc16.wVmax;
219         lpCaps->wCaps = jc16.wCaps;
220         lpCaps->wMaxAxes = jc16.wMaxAxes;
221         lpCaps->wNumAxes = jc16.wNumAxes;
222         lpCaps->wMaxButtons = jc16.wMaxButtons;
223         lstrcpyAtoW(lpCaps->szRegKey,jc16.szRegKey);
224         lstrcpyAtoW(lpCaps->szOEMVxD,jc16.szOEMVxD);
225         return ret;
226 }
227 /**************************************************************************
228  *                              JoyGetDevCaps           [MMSYSTEM.102]
229  */
230 MMRESULT16 WINAPI joyGetDevCaps16(UINT16 wID, LPJOYCAPS16 lpCaps, UINT16 wSize)
231 {
232     TRACE(mmsys, "(%04X, %p, %d);\n",
233             wID, lpCaps, wSize);
234     if (joyOpenDriver(wID) == TRUE) {
235         lpCaps->wMid = MM_MICROSOFT;
236         lpCaps->wPid = MM_PC_JOYSTICK;
237         strcpy(lpCaps->szPname, "WineJoy"); /* joystick product name */
238         lpCaps->wXmin = 0; /* FIXME */
239         lpCaps->wXmax = 0xffff;
240         lpCaps->wYmin = 0;
241         lpCaps->wYmax = 0xffff;
242         lpCaps->wZmin = 0;
243         lpCaps->wZmax = 0xffff;
244         lpCaps->wNumButtons = 2;
245         lpCaps->wPeriodMin = 0;
246         lpCaps->wPeriodMax = 50; /* FIXME end */
247         if (wSize == sizeof(JOYCAPS16)) {
248                 /* complete 95 structure */
249                 lpCaps->wRmin = 0;
250                 lpCaps->wRmax = 0xffff;
251                 lpCaps->wUmin = 0;
252                 lpCaps->wUmax = 0xffff;
253                 lpCaps->wVmin = 0;
254                 lpCaps->wVmax = 0xffff;
255                 lpCaps->wCaps = 0;
256                 lpCaps->wMaxAxes = 6;
257                 lpCaps->wNumAxes = 2;
258                 lpCaps->wMaxButtons = 3;
259                 strcpy(lpCaps->szRegKey,"");
260                 strcpy(lpCaps->szOEMVxD,"");
261         }
262         joyCloseDriver(wID);
263         return JOYERR_NOERROR;
264     }
265     else
266     return MMSYSERR_NODRIVER;
267 }
268
269 /**************************************************************************
270  *                              JoyGetPosEx             [WINMM.31]
271  */
272 MMRESULT WINAPI joyGetPosEx(UINT wID, LPJOYINFOEX lpInfo)
273 {
274         /* FIXME: implement it */
275         return MMSYSERR_NODRIVER;
276 }
277
278 /**************************************************************************
279  *                              JoyGetPos               [WINMM.30]
280  */
281 MMRESULT WINAPI joyGetPos(UINT wID, LPJOYINFO lpInfo)
282 {
283         JOYINFO16       ji;
284         MMRESULT16      ret = joyGetPos16(wID,&ji);
285
286         lpInfo->wXpos = ji.wXpos;
287         lpInfo->wYpos = ji.wYpos;
288         lpInfo->wZpos = ji.wZpos;
289         lpInfo->wButtons = ji.wButtons;
290         return ret;
291 }
292
293 /**************************************************************************
294  *                              JoyGetPos               [MMSYSTEM.103]
295  */
296 MMRESULT16 WINAPI joyGetPos16(UINT16 wID, LPJOYINFO16 lpInfo)
297 {
298         struct js_status js;
299
300         TRACE(mmsys, "(%04X, %p)\n", wID, lpInfo);
301         if (joyOpenDriver(wID) == FALSE) return MMSYSERR_NODRIVER;
302         dev_stat = read(joy_dev[wID], &js, sizeof(js));
303         if (dev_stat != sizeof(js)) {
304                 joyCloseDriver(wID);
305                 return JOYERR_UNPLUGGED; /* FIXME: perhaps wrong, but what should I return else ? */
306         }
307         count_use[wID] = 0;
308         js.x = js.x*37;
309         js.y = js.y*37;
310         lpInfo->wXpos = js.x;   /* FIXME: perhaps multiply it somehow ? */
311         lpInfo->wYpos = js.y;
312         lpInfo->wZpos = 0; /* FIXME: Don't know what to do with this value as joystick driver doesn't provide a Z value */
313         lpInfo->wButtons = js.buttons;
314         TRACE(mmsys, "x: %d, y: %d, buttons: %d\n", js.x, js.y, js.buttons);
315         return JOYERR_NOERROR;
316 }
317
318 /**************************************************************************
319  *                              JoyGetThreshold         [WINMM.32]
320  */
321 MMRESULT WINAPI joyGetThreshold(UINT wID, LPUINT lpThreshold)
322 {
323         UINT16          thresh;
324         MMRESULT16      ret = joyGetThreshold16(wID,&thresh);
325
326         *lpThreshold = thresh;
327         return ret;
328 }
329
330 /**************************************************************************
331  *                              JoyGetThreshold         [MMSYSTEM.104]
332  */
333 MMRESULT16 WINAPI joyGetThreshold16(UINT16 wID, LPUINT16 lpThreshold)
334 {
335     TRACE(mmsys, "(%04X, %p);\n", wID, lpThreshold);
336     if (wID >= MAXJOYDRIVERS) return JOYERR_PARMS;
337     *lpThreshold = joy_threshold[wID];
338     return JOYERR_NOERROR;
339 }
340
341 /**************************************************************************
342  *                              JoyReleaseCapture       [WINMM.33]
343  */
344 MMRESULT WINAPI joyReleaseCapture(UINT wID)
345 {
346         return joyReleaseCapture16(wID);
347 }
348
349 /**************************************************************************
350  *                              JoyReleaseCapture       [MMSYSTEM.105]
351  */
352 MMRESULT16 WINAPI joyReleaseCapture16(UINT16 wID)
353 {
354     TRACE(mmsys, "(%04X);\n", wID);
355     joyCaptured = FALSE;
356     joyCloseDriver(wID);
357     joy_dev[wID] = -1;
358     CaptureWnd[wID] = 0;
359     return JOYERR_NOERROR;
360 }
361
362 /**************************************************************************
363  *                              JoySetCapture           [MMSYSTEM.106]
364  */
365 MMRESULT WINAPI joySetCapture(HWND hWnd,UINT wID,UINT wPeriod,BOOL bChanged)
366 {
367         return joySetCapture16(hWnd,wID,wPeriod,bChanged);
368 }
369
370 /**************************************************************************
371  *                              JoySetCapture           [MMSYSTEM.106]
372  */
373 MMRESULT16 WINAPI joySetCapture16(HWND16 hWnd,UINT16 wID,UINT16 wPeriod,BOOL16 bChanged)
374 {
375
376     TRACE(mmsys, "(%04X, %04X, %d, %d);\n",
377             hWnd, wID, wPeriod, bChanged);
378
379     if (!CaptureWnd[wID]) {
380         if (joyOpenDriver(wID) == FALSE) return MMSYSERR_NODRIVER;
381         joyCaptured = TRUE;
382         CaptureWnd[wID] = hWnd;
383         return JOYERR_NOERROR;
384     }
385     else
386     return JOYERR_NOCANDO; /* FIXME: what should be returned ? */
387 }
388
389 /**************************************************************************
390  *                              JoySetThreshold         [WINMM.35]
391  */
392 MMRESULT WINAPI joySetThreshold(UINT wID, UINT wThreshold)
393 {
394         return joySetThreshold16(wID,wThreshold);
395 }
396 /**************************************************************************
397  *                              JoySetThreshold         [MMSYSTEM.107]
398  */
399 MMRESULT16 WINAPI joySetThreshold16(UINT16 wID, UINT16 wThreshold)
400 {
401     TRACE(mmsys, "(%04X, %d);\n", wID, wThreshold);
402
403     if (wID > 3) return JOYERR_PARMS;
404     joy_threshold[wID] = wThreshold;
405     return JOYERR_NOERROR;
406 }
407
408 /**************************************************************************
409  *                              JoySetCalibration       [MMSYSTEM.109]
410  */
411 MMRESULT16 WINAPI joySetCalibration16(UINT16 wID)
412 {
413     FIXME(mmsys, "(%04X): stub.\n", wID);
414     return JOYERR_NOCANDO;
415 }