Renamed some 16-bit spec files to match the dll name.
[wine] / dlls / dinput / keyboard / main.c
1 /*              DirectInput Keyboard device
2  *
3  * Copyright 1998 Marcus Meissner
4  * Copyright 1998,1999 Lionel Ulmer
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22 #include <string.h>
23 #ifdef HAVE_SYS_ERRNO_H
24 # include <sys/errno.h>
25 #endif
26
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "winerror.h"
30 #include "dinput.h"
31
32 #include "dinput_private.h"
33 #include "device_private.h"
34 #include "wine/debug.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
37
38 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt;
39 static ICOM_VTABLE(IDirectInputDevice7A) SysKeyboard7Avt;
40      
41 typedef struct SysKeyboardAImpl SysKeyboardAImpl;
42 struct SysKeyboardAImpl
43 {
44         /* IDirectInputDevice2AImpl */
45         ICOM_VFIELD(IDirectInputDevice2A);
46         DWORD                           ref;
47         GUID                            guid;
48
49         IDirectInputAImpl *dinput;
50         
51         /* SysKeyboardAImpl */
52         BYTE                            keystate[256];
53         int                             acquired;
54 };
55
56 static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
57   0x0ab8648a,
58   0x7735,
59   0x11d2,
60   {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41}
61 };
62
63 static BOOL keyboarddev_enum_device(DWORD dwDevType, DWORD dwFlags, LPCDIDEVICEINSTANCEA lpddi)
64 {
65   if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
66     TRACE("Enumerating the Keyboard device\n");
67     
68     lpddi->guidInstance = GUID_SysKeyboard;/* DInput's GUID */
69     lpddi->guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
70     lpddi->dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
71     strcpy(lpddi->tszInstanceName, "Keyboard");
72     strcpy(lpddi->tszProductName, "Wine Keyboard");
73     
74     return TRUE;
75   }
76
77   return FALSE;
78 }
79
80 static SysKeyboardAImpl *alloc_device(REFGUID rguid, ICOM_VTABLE(IDirectInputDevice2A) *kvt, IDirectInputAImpl *dinput)
81 {
82     SysKeyboardAImpl* newDevice;
83     newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardAImpl));
84     newDevice->ref = 1;
85     ICOM_VTBL(newDevice) = kvt;
86     memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
87     memset(newDevice->keystate,0,256);
88     newDevice->dinput = dinput;
89
90     return newDevice;
91 }
92
93
94 static HRESULT keyboarddev_create_device(IDirectInputAImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEA* pdev)
95 {
96   if ((IsEqualGUID(&GUID_SysKeyboard,rguid)) ||          /* Generic Keyboard */
97       (IsEqualGUID(&DInput_Wine_Keyboard_GUID,rguid))) { /* Wine Keyboard */
98     if ((riid == NULL) || (IsEqualGUID(&IID_IDirectInputDevice2A,riid)) || (IsEqualGUID(&IID_IDirectInputDevice2A,riid))) {
99       *pdev=(IDirectInputDeviceA*) alloc_device(rguid, &SysKeyboardAvt, dinput);
100     
101       TRACE("Creating a Keyboard device (%p)\n", *pdev);
102       return DI_OK;
103     } else if (IsEqualGUID(&IID_IDirectInputDevice7A,riid)) {
104       *pdev=(IDirectInputDeviceA*) alloc_device(rguid, (ICOM_VTABLE(IDirectInputDevice2A) *) &SysKeyboard7Avt, dinput);
105     
106       TRACE("Creating a Keyboard DInput7A device (%p)\n", *pdev);
107       return DI_OK;
108     } else
109       return DIERR_NOINTERFACE;
110   }
111
112   return DIERR_DEVICENOTREG;
113 }
114
115 static dinput_device keyboarddev = {
116   100,
117   keyboarddev_enum_device,
118   keyboarddev_create_device
119 };
120
121 DECL_GLOBAL_CONSTRUCTOR(keyboarddev_register) { dinput_register_device(&keyboarddev); }
122
123 static HRESULT WINAPI SysKeyboardAImpl_SetProperty(
124         LPDIRECTINPUTDEVICE2A iface,REFGUID rguid,LPCDIPROPHEADER ph
125 )
126 {
127         ICOM_THIS(SysKeyboardAImpl,iface);
128
129         TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
130         TRACE("(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
131             ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
132         if (!HIWORD(rguid)) {
133                 switch ((DWORD)rguid) {
134                 case (DWORD) DIPROP_BUFFERSIZE: {
135                         LPCDIPROPDWORD  pd = (LPCDIPROPDWORD)ph;
136
137                         TRACE("(buffersize=%ld)\n",pd->dwData);
138                         break;
139                 }
140                 default:
141                         WARN("Unknown type %ld\n",(DWORD)rguid);
142                         break;
143                 }
144         }
145         return 0;
146 }
147
148 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(
149         LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
150 )
151 {
152     DWORD i;
153
154     memset( ptr, 0, len );
155     if (len != 256)
156     {
157         WARN("whoops, got len %ld?\n", len);
158         return DI_OK;
159     }
160     for (i = 0; i < 0x80; i++)
161     {
162         WORD vkey = MapVirtualKeyA( i, 1 );
163         if (vkey && (GetAsyncKeyState( vkey ) & 0x8000))
164         {
165             ((LPBYTE)ptr)[i] = 0x80;
166             ((LPBYTE)ptr)[i | 0x80] = 0x80;
167         }
168     }
169     return DI_OK;
170 }
171
172 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData(
173         LPDIRECTINPUTDEVICE2A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
174         LPDWORD entries,DWORD flags
175 )
176 {
177         ICOM_THIS(SysKeyboardAImpl,iface);
178         int i, n;
179
180         TRACE("(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
181               This,dodsize,dod,entries,entries?*entries:0,flags);
182
183
184         for (i = n = 0; (i < 0x80) && (n < *entries); i++)
185         {
186             WORD state, vkey = MapVirtualKeyA( i, 1 );
187             if (!vkey) continue;
188             state = (GetAsyncKeyState( vkey ) >> 8) & 0x80;
189             if (state != This->keystate[vkey])
190             {
191                 if (dod)
192                 {
193                     /* add an entry */
194                     dod[n].dwOfs       = i; /* scancode */
195                     dod[n].dwData      = state;
196                     dod[n].dwTimeStamp = GetCurrentTime(); /* umm */
197                     dod[n].dwSequence  = This->dinput->evsequence++;
198                     n++;
199                 }
200                 if (!(flags & DIGDD_PEEK)) This->keystate[vkey] = state;
201             }
202         }
203         if (n) TRACE_(dinput)("%d entries\n",n);
204         *entries = n;
205         return DI_OK;
206 }
207
208 static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
209 {
210         ICOM_THIS(SysKeyboardAImpl,iface);
211         
212         TRACE("(this=%p)\n",This);
213         
214         if (This->acquired == 0) {
215           This->acquired = 1;
216         }
217         
218         return DI_OK;
219 }
220
221 static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
222 {
223         ICOM_THIS(SysKeyboardAImpl,iface);
224         TRACE("(this=%p)\n",This);
225
226         if (This->acquired == 1) {
227           This->acquired = 0;
228         } else {
229           ERR("Unacquiring a not-acquired device !!!\n");
230         }
231
232         return DI_OK;
233 }
234
235 /******************************************************************************
236   *     GetCapabilities : get the device capablitites
237   */
238 static HRESULT WINAPI SysKeyboardAImpl_GetCapabilities(
239         LPDIRECTINPUTDEVICE2A iface,
240         LPDIDEVCAPS lpDIDevCaps)
241 {
242   ICOM_THIS(SysKeyboardAImpl,iface);
243
244   TRACE("(this=%p,%p)\n",This,lpDIDevCaps);
245
246   if (lpDIDevCaps->dwSize == sizeof(DIDEVCAPS)) {
247     lpDIDevCaps->dwFlags = DIDC_ATTACHED;
248     lpDIDevCaps->dwDevType = DIDEVTYPE_KEYBOARD;
249     lpDIDevCaps->dwAxes = 0;
250     lpDIDevCaps->dwButtons = 0;
251     lpDIDevCaps->dwPOVs = 0;
252     lpDIDevCaps->dwFFSamplePeriod = 0;
253     lpDIDevCaps->dwFFMinTimeResolution = 0;
254     lpDIDevCaps->dwFirmwareRevision = 100;
255     lpDIDevCaps->dwHardwareRevision = 100;
256     lpDIDevCaps->dwFFDriverVersion = 0;
257   } else {
258     /* DirectX 3.0 */
259     FIXME("DirectX 3.0 not supported....\n");
260   }
261   
262   return DI_OK;
263 }
264
265 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt = 
266 {
267         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
268         IDirectInputDevice2AImpl_QueryInterface,
269         IDirectInputDevice2AImpl_AddRef,
270         IDirectInputDevice2AImpl_Release,
271         SysKeyboardAImpl_GetCapabilities,
272         IDirectInputDevice2AImpl_EnumObjects,
273         IDirectInputDevice2AImpl_GetProperty,
274         SysKeyboardAImpl_SetProperty,
275         SysKeyboardAImpl_Acquire,
276         SysKeyboardAImpl_Unacquire,
277         SysKeyboardAImpl_GetDeviceState,
278         SysKeyboardAImpl_GetDeviceData,
279         IDirectInputDevice2AImpl_SetDataFormat,
280         IDirectInputDevice2AImpl_SetEventNotification,
281         IDirectInputDevice2AImpl_SetCooperativeLevel,
282         IDirectInputDevice2AImpl_GetObjectInfo,
283         IDirectInputDevice2AImpl_GetDeviceInfo,
284         IDirectInputDevice2AImpl_RunControlPanel,
285         IDirectInputDevice2AImpl_Initialize,
286         IDirectInputDevice2AImpl_CreateEffect,
287         IDirectInputDevice2AImpl_EnumEffects,
288         IDirectInputDevice2AImpl_GetEffectInfo,
289         IDirectInputDevice2AImpl_GetForceFeedbackState,
290         IDirectInputDevice2AImpl_SendForceFeedbackCommand,
291         IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
292         IDirectInputDevice2AImpl_Escape,
293         IDirectInputDevice2AImpl_Poll,
294         IDirectInputDevice2AImpl_SendDeviceData
295 };
296
297 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
298 # define XCAST(fun)     (typeof(SysKeyboard7Avt.fun))
299 #else
300 # define XCAST(fun)     (void*)
301 #endif
302
303 static ICOM_VTABLE(IDirectInputDevice7A) SysKeyboard7Avt = 
304 {
305         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
306         XCAST(QueryInterface)IDirectInputDevice2AImpl_QueryInterface,
307         XCAST(AddRef)IDirectInputDevice2AImpl_AddRef,
308         XCAST(Release)IDirectInputDevice2AImpl_Release,
309         XCAST(GetCapabilities)SysKeyboardAImpl_GetCapabilities,
310         XCAST(EnumObjects)IDirectInputDevice2AImpl_EnumObjects,
311         XCAST(GetProperty)IDirectInputDevice2AImpl_GetProperty,
312         XCAST(SetProperty)SysKeyboardAImpl_SetProperty,
313         XCAST(Acquire)SysKeyboardAImpl_Acquire,
314         XCAST(Unacquire)SysKeyboardAImpl_Unacquire,
315         XCAST(GetDeviceState)SysKeyboardAImpl_GetDeviceState,
316         XCAST(GetDeviceData)SysKeyboardAImpl_GetDeviceData,
317         XCAST(SetDataFormat)IDirectInputDevice2AImpl_SetDataFormat,
318         XCAST(SetEventNotification)IDirectInputDevice2AImpl_SetEventNotification,
319         XCAST(SetCooperativeLevel)IDirectInputDevice2AImpl_SetCooperativeLevel,
320         XCAST(GetObjectInfo)IDirectInputDevice2AImpl_GetObjectInfo,
321         XCAST(GetDeviceInfo)IDirectInputDevice2AImpl_GetDeviceInfo,
322         XCAST(RunControlPanel)IDirectInputDevice2AImpl_RunControlPanel,
323         XCAST(Initialize)IDirectInputDevice2AImpl_Initialize,
324         XCAST(CreateEffect)IDirectInputDevice2AImpl_CreateEffect,
325         XCAST(EnumEffects)IDirectInputDevice2AImpl_EnumEffects,
326         XCAST(GetEffectInfo)IDirectInputDevice2AImpl_GetEffectInfo,
327         XCAST(GetForceFeedbackState)IDirectInputDevice2AImpl_GetForceFeedbackState,
328         XCAST(SendForceFeedbackCommand)IDirectInputDevice2AImpl_SendForceFeedbackCommand,
329         XCAST(EnumCreatedEffectObjects)IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
330         XCAST(Escape)IDirectInputDevice2AImpl_Escape,
331         XCAST(Poll)IDirectInputDevice2AImpl_Poll,
332         XCAST(SendDeviceData)IDirectInputDevice2AImpl_SendDeviceData,
333         IDirectInputDevice7AImpl_EnumEffectsInFile,
334         IDirectInputDevice7AImpl_WriteEffectToFile
335 };
336
337 #undef XCAST