1 /* DirectInput Keyboard device
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998,1999 Lionel Ulmer
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.
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.
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
23 #ifdef HAVE_SYS_ERRNO_H
24 # include <sys/errno.h>
32 #include "dinput_private.h"
33 #include "device_private.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(dinput
);
38 static ICOM_VTABLE(IDirectInputDevice2A
) SysKeyboardAvt
;
39 static ICOM_VTABLE(IDirectInputDevice7A
) SysKeyboard7Avt
;
41 typedef struct SysKeyboardAImpl SysKeyboardAImpl
;
42 struct SysKeyboardAImpl
44 /* IDirectInputDevice2AImpl */
45 ICOM_VFIELD(IDirectInputDevice2A
);
49 IDirectInputAImpl
*dinput
;
52 /* SysKeyboardAImpl */
54 int buffersize
; /* set in 'SetProperty' */
55 LPDIDEVICEOBJECTDATA buffer
; /* buffer for 'GetDeviceData'.
56 Alloc at 'Acquire', Free at
58 int count
; /* number of objects in use in
60 int start
; /* 'buffer' rotates. This is the
61 first in use (if count > 0) */
62 BOOL overflow
; /* return DI_BUFFEROVERFLOW in
64 CRITICAL_SECTION crit
;
67 SysKeyboardAImpl
*current
; /* Today's acquired device
68 FIXME: currently this can be only one.
69 Maybe this should be a linked list or st.
70 I don't know what the rules are for multiple acquired keyboards,
71 but 'DI_LOSTFOCUS' and 'DI_UNACQUIRED' exist for a reason.
74 static BYTE DInputKeyState
[256]; /* array for 'GetDeviceState' */
78 LRESULT CALLBACK
KeyboardCallback( int code
, WPARAM wparam
, LPARAM lparam
)
80 if (code
== HC_ACTION
)
87 KBDLLHOOKSTRUCT
*hook
= (KBDLLHOOKSTRUCT
*)lparam
;
88 dik_code
= hook
->scanCode
;
89 if (hook
->flags
& LLKHF_EXTENDED
) dik_code
|= 0x80;
90 down
= !(hook
->flags
& LLKHF_UP
);
91 timestamp
= hook
->time
;
94 DInputKeyState
[dik_code
] = (down
? 0x80 : 0);
99 SetEvent(current
->hEvent
);
101 if (current
->buffer
!= NULL
)
105 EnterCriticalSection(&(current
->crit
));
107 n
= (current
->start
+ current
->count
) % current
->buffersize
;
109 current
->buffer
[n
].dwOfs
= dik_code
;
110 current
->buffer
[n
].dwData
= down
? 0x80 : 0;
111 current
->buffer
[n
].dwTimeStamp
= timestamp
;
112 current
->buffer
[n
].dwSequence
= current
->dinput
->evsequence
++;
114 if (current
->count
== current
->buffersize
)
117 current
->overflow
= TRUE
;
122 LeaveCriticalSection(&(current
->crit
));
127 return CallNextHookEx(keyboard_hook
, code
, wparam
, lparam
);
130 static GUID DInput_Wine_Keyboard_GUID
= { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
134 {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41}
137 static BOOL
keyboarddev_enum_device(DWORD dwDevType
, DWORD dwFlags
, LPDIDEVICEINSTANCEA lpddi
)
139 if ((dwDevType
== 0) || (dwDevType
== DIDEVTYPE_KEYBOARD
)) {
140 TRACE("Enumerating the Keyboard device\n");
142 lpddi
->guidInstance
= GUID_SysKeyboard
;/* DInput's GUID */
143 lpddi
->guidProduct
= DInput_Wine_Keyboard_GUID
; /* Vendor's GUID */
144 lpddi
->dwDevType
= DIDEVTYPE_KEYBOARD
| (DIDEVTYPEKEYBOARD_UNKNOWN
<< 8);
145 strcpy(lpddi
->tszInstanceName
, "Keyboard");
146 strcpy(lpddi
->tszProductName
, "Wine Keyboard");
154 static SysKeyboardAImpl
*alloc_device(REFGUID rguid
, ICOM_VTABLE(IDirectInputDevice2A
) *kvt
, IDirectInputAImpl
*dinput
)
156 SysKeyboardAImpl
* newDevice
;
157 newDevice
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(SysKeyboardAImpl
));
159 ICOM_VTBL(newDevice
) = kvt
;
160 memcpy(&(newDevice
->guid
),rguid
,sizeof(*rguid
));
161 newDevice
->dinput
= dinput
;
167 static HRESULT
keyboarddev_create_device(IDirectInputAImpl
*dinput
, REFGUID rguid
, REFIID riid
, LPDIRECTINPUTDEVICEA
* pdev
)
169 if ((IsEqualGUID(&GUID_SysKeyboard
,rguid
)) || /* Generic Keyboard */
170 (IsEqualGUID(&DInput_Wine_Keyboard_GUID
,rguid
))) { /* Wine Keyboard */
171 if ((riid
== NULL
) || (IsEqualGUID(&IID_IDirectInputDevice2A
,riid
)) || (IsEqualGUID(&IID_IDirectInputDevice2A
,riid
))) {
172 *pdev
=(IDirectInputDeviceA
*) alloc_device(rguid
, &SysKeyboardAvt
, dinput
);
174 TRACE("Creating a Keyboard device (%p)\n", *pdev
);
176 } else if (IsEqualGUID(&IID_IDirectInputDevice7A
,riid
)) {
177 *pdev
=(IDirectInputDeviceA
*) alloc_device(rguid
, (ICOM_VTABLE(IDirectInputDevice2A
) *) &SysKeyboard7Avt
, dinput
);
179 TRACE("Creating a Keyboard DInput7A device (%p)\n", *pdev
);
182 return DIERR_NOINTERFACE
;
185 return DIERR_DEVICENOTREG
;
188 static dinput_device keyboarddev
= {
190 keyboarddev_enum_device
,
191 keyboarddev_create_device
194 DECL_GLOBAL_CONSTRUCTOR(keyboarddev_register
) { dinput_register_device(&keyboarddev
); }
196 static HRESULT WINAPI
SysKeyboardAImpl_SetProperty(
197 LPDIRECTINPUTDEVICE2A iface
,REFGUID rguid
,LPCDIPROPHEADER ph
200 ICOM_THIS(SysKeyboardAImpl
,iface
);
202 TRACE("(this=%p,%s,%p)\n",This
,debugstr_guid(rguid
),ph
);
203 TRACE("(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
204 ph
->dwSize
,ph
->dwHeaderSize
,ph
->dwObj
,ph
->dwHow
);
205 if (!HIWORD(rguid
)) {
206 switch ((DWORD
)rguid
) {
207 case (DWORD
) DIPROP_BUFFERSIZE
: {
208 LPCDIPROPDWORD pd
= (LPCDIPROPDWORD
)ph
;
210 TRACE("(buffersize=%ld)\n",pd
->dwData
);
213 return DIERR_INVALIDPARAM
;
215 This
->buffersize
= pd
->dwData
;
220 WARN("Unknown type %ld\n",(DWORD
)rguid
);
227 static HRESULT WINAPI
SysKeyboardAImpl_GetDeviceState(
228 LPDIRECTINPUTDEVICE2A iface
,DWORD len
,LPVOID ptr
231 /* Note: device does not need to be acquired */
233 return DIERR_INVALIDPARAM
;
235 memcpy(ptr
, DInputKeyState
, 256);
239 static HRESULT WINAPI
SysKeyboardAImpl_GetDeviceData(
240 LPDIRECTINPUTDEVICE2A iface
,DWORD dodsize
,LPDIDEVICEOBJECTDATA dod
,
241 LPDWORD entries
,DWORD flags
244 ICOM_THIS(SysKeyboardAImpl
,iface
);
245 int ret
= DI_OK
, i
= 0;
247 TRACE("(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
248 This
,dodsize
,dod
,entries
,entries
?*entries
:0,flags
);
250 if (This
->buffer
== NULL
)
251 return DIERR_NOTBUFFERED
;
253 if (dodsize
< sizeof(*dod
))
254 return DIERR_INVALIDPARAM
;
256 EnterCriticalSection(&(This
->crit
));
258 /* Copy item at a time for the case dodsize > sizeof(buffer[n]) */
259 while ((i
< *entries
|| *entries
== INFINITE
) && i
< This
->count
)
263 int n
= (This
->start
+ i
) % This
->buffersize
;
264 LPDIDEVICEOBJECTDATA pd
265 = (LPDIDEVICEOBJECTDATA
)((BYTE
*)dod
+ dodsize
* i
);
266 pd
->dwOfs
= This
->buffer
[n
].dwOfs
;
267 pd
->dwData
= This
->buffer
[n
].dwData
;
268 pd
->dwTimeStamp
= This
->buffer
[n
].dwTimeStamp
;
269 pd
->dwSequence
= This
->buffer
[n
].dwSequence
;
277 ret
= DI_BUFFEROVERFLOW
;
279 if (!(flags
& DIGDD_PEEK
))
283 This
->start
= (This
->start
+ i
) % This
->buffersize
;
284 This
->overflow
= FALSE
;
287 LeaveCriticalSection(&(This
->crit
));
292 static HRESULT WINAPI
SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface
);
294 static HRESULT WINAPI
SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface
)
296 ICOM_THIS(SysKeyboardAImpl
,iface
);
298 TRACE("(this=%p)\n",This
);
307 FIXME("Not more than one keyboard can be acquired at the same time.\n");
308 SysKeyboardAImpl_Unacquire(iface
);
313 if (This
->buffersize
> 0)
315 This
->buffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
316 This
->buffersize
* sizeof(*(This
->buffer
)));
319 This
->overflow
= FALSE
;
320 InitializeCriticalSection(&(This
->crit
));
328 static HRESULT WINAPI
SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface
)
330 ICOM_THIS(SysKeyboardAImpl
,iface
);
331 TRACE("(this=%p)\n",This
);
333 if (This
->acquired
== 0)
339 ERR("this != current\n");
343 if (This
->buffersize
>= 0)
345 HeapFree(GetProcessHeap(), 0, This
->buffer
);
347 DeleteCriticalSection(&(This
->crit
));
353 static HRESULT WINAPI
SysKeyboardAImpl_SetEventNotification(LPDIRECTINPUTDEVICE2A iface
,
355 ICOM_THIS(SysKeyboardAImpl
,iface
);
357 TRACE("(this=%p,0x%08lx)\n",This
,(DWORD
)hnd
);
363 /******************************************************************************
364 * GetCapabilities : get the device capablitites
366 static HRESULT WINAPI
SysKeyboardAImpl_GetCapabilities(
367 LPDIRECTINPUTDEVICE2A iface
,
368 LPDIDEVCAPS lpDIDevCaps
)
370 ICOM_THIS(SysKeyboardAImpl
,iface
);
372 TRACE("(this=%p,%p)\n",This
,lpDIDevCaps
);
374 if (lpDIDevCaps
->dwSize
== sizeof(DIDEVCAPS
)) {
375 lpDIDevCaps
->dwFlags
= DIDC_ATTACHED
;
376 lpDIDevCaps
->dwDevType
= DIDEVTYPE_KEYBOARD
;
377 lpDIDevCaps
->dwAxes
= 0;
378 lpDIDevCaps
->dwButtons
= 0;
379 lpDIDevCaps
->dwPOVs
= 0;
380 lpDIDevCaps
->dwFFSamplePeriod
= 0;
381 lpDIDevCaps
->dwFFMinTimeResolution
= 0;
382 lpDIDevCaps
->dwFirmwareRevision
= 100;
383 lpDIDevCaps
->dwHardwareRevision
= 100;
384 lpDIDevCaps
->dwFFDriverVersion
= 0;
387 FIXME("DirectX 3.0 not supported....\n");
393 static ICOM_VTABLE(IDirectInputDevice2A
) SysKeyboardAvt
=
395 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
396 IDirectInputDevice2AImpl_QueryInterface
,
397 IDirectInputDevice2AImpl_AddRef
,
398 IDirectInputDevice2AImpl_Release
,
399 SysKeyboardAImpl_GetCapabilities
,
400 IDirectInputDevice2AImpl_EnumObjects
,
401 IDirectInputDevice2AImpl_GetProperty
,
402 SysKeyboardAImpl_SetProperty
,
403 SysKeyboardAImpl_Acquire
,
404 SysKeyboardAImpl_Unacquire
,
405 SysKeyboardAImpl_GetDeviceState
,
406 SysKeyboardAImpl_GetDeviceData
,
407 IDirectInputDevice2AImpl_SetDataFormat
,
408 SysKeyboardAImpl_SetEventNotification
,
409 IDirectInputDevice2AImpl_SetCooperativeLevel
,
410 IDirectInputDevice2AImpl_GetObjectInfo
,
411 IDirectInputDevice2AImpl_GetDeviceInfo
,
412 IDirectInputDevice2AImpl_RunControlPanel
,
413 IDirectInputDevice2AImpl_Initialize
,
414 IDirectInputDevice2AImpl_CreateEffect
,
415 IDirectInputDevice2AImpl_EnumEffects
,
416 IDirectInputDevice2AImpl_GetEffectInfo
,
417 IDirectInputDevice2AImpl_GetForceFeedbackState
,
418 IDirectInputDevice2AImpl_SendForceFeedbackCommand
,
419 IDirectInputDevice2AImpl_EnumCreatedEffectObjects
,
420 IDirectInputDevice2AImpl_Escape
,
421 IDirectInputDevice2AImpl_Poll
,
422 IDirectInputDevice2AImpl_SendDeviceData
425 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
426 # define XCAST(fun) (typeof(SysKeyboard7Avt.fun))
428 # define XCAST(fun) (void*)
431 static ICOM_VTABLE(IDirectInputDevice7A
) SysKeyboard7Avt
=
433 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
434 XCAST(QueryInterface
)IDirectInputDevice2AImpl_QueryInterface
,
435 XCAST(AddRef
)IDirectInputDevice2AImpl_AddRef
,
436 XCAST(Release
)IDirectInputDevice2AImpl_Release
,
437 XCAST(GetCapabilities
)SysKeyboardAImpl_GetCapabilities
,
438 XCAST(EnumObjects
)IDirectInputDevice2AImpl_EnumObjects
,
439 XCAST(GetProperty
)IDirectInputDevice2AImpl_GetProperty
,
440 XCAST(SetProperty
)SysKeyboardAImpl_SetProperty
,
441 XCAST(Acquire
)SysKeyboardAImpl_Acquire
,
442 XCAST(Unacquire
)SysKeyboardAImpl_Unacquire
,
443 XCAST(GetDeviceState
)SysKeyboardAImpl_GetDeviceState
,
444 XCAST(GetDeviceData
)SysKeyboardAImpl_GetDeviceData
,
445 XCAST(SetDataFormat
)IDirectInputDevice2AImpl_SetDataFormat
,
446 XCAST(SetEventNotification
)SysKeyboardAImpl_SetEventNotification
,
447 XCAST(SetCooperativeLevel
)IDirectInputDevice2AImpl_SetCooperativeLevel
,
448 XCAST(GetObjectInfo
)IDirectInputDevice2AImpl_GetObjectInfo
,
449 XCAST(GetDeviceInfo
)IDirectInputDevice2AImpl_GetDeviceInfo
,
450 XCAST(RunControlPanel
)IDirectInputDevice2AImpl_RunControlPanel
,
451 XCAST(Initialize
)IDirectInputDevice2AImpl_Initialize
,
452 XCAST(CreateEffect
)IDirectInputDevice2AImpl_CreateEffect
,
453 XCAST(EnumEffects
)IDirectInputDevice2AImpl_EnumEffects
,
454 XCAST(GetEffectInfo
)IDirectInputDevice2AImpl_GetEffectInfo
,
455 XCAST(GetForceFeedbackState
)IDirectInputDevice2AImpl_GetForceFeedbackState
,
456 XCAST(SendForceFeedbackCommand
)IDirectInputDevice2AImpl_SendForceFeedbackCommand
,
457 XCAST(EnumCreatedEffectObjects
)IDirectInputDevice2AImpl_EnumCreatedEffectObjects
,
458 XCAST(Escape
)IDirectInputDevice2AImpl_Escape
,
459 XCAST(Poll
)IDirectInputDevice2AImpl_Poll
,
460 XCAST(SendDeviceData
)IDirectInputDevice2AImpl_SendDeviceData
,
461 IDirectInputDevice7AImpl_EnumEffectsInFile
,
462 IDirectInputDevice7AImpl_WriteEffectToFile