1 /* DirectInput Keyboard device
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998,1999 Lionel Ulmer
5 * Copyright 2000-2001 TransGaming Technologies Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #ifdef HAVE_SYS_ERRNO_H
25 # include <sys/errno.h>
33 #include "dinput_private.h"
34 #include "device_private.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
39 static ICOM_VTABLE(IDirectInputDevice8A) SysKeyboardAvt;
41 typedef struct SysKeyboardAImpl SysKeyboardAImpl;
42 struct SysKeyboardAImpl
48 IDirectInputAImpl *dinput;
51 /* SysKeyboardAImpl */
53 int buffersize; /* set in 'SetProperty' */
54 LPDIDEVICEOBJECTDATA buffer; /* buffer for 'GetDeviceData'.
55 Alloc at 'Acquire', Free at
57 int count; /* number of objects in use in
59 int start; /* 'buffer' rotates. This is the
60 first in use (if count > 0) */
61 BOOL overflow; /* return DI_BUFFEROVERFLOW in
63 CRITICAL_SECTION crit;
66 SysKeyboardAImpl *current; /* Today's acquired device
67 FIXME: currently this can be only one.
68 Maybe this should be a linked list or st.
69 I don't know what the rules are for multiple acquired keyboards,
70 but 'DI_LOSTFOCUS' and 'DI_UNACQUIRED' exist for a reason.
73 static BYTE DInputKeyState[256]; /* array for 'GetDeviceState' */
77 LRESULT CALLBACK KeyboardCallback( int code, WPARAM wparam, LPARAM lparam )
79 if (code == HC_ACTION)
86 KBDLLHOOKSTRUCT *hook = (KBDLLHOOKSTRUCT *)lparam;
87 dik_code = hook->scanCode;
88 if (hook->flags & LLKHF_EXTENDED) dik_code |= 0x80;
89 down = !(hook->flags & LLKHF_UP);
90 timestamp = hook->time;
93 DInputKeyState[dik_code] = (down ? 0x80 : 0);
98 SetEvent(current->hEvent);
100 if (current->buffer != NULL)
104 EnterCriticalSection(&(current->crit));
106 n = (current->start + current->count) % current->buffersize;
108 current->buffer[n].dwOfs = dik_code;
109 current->buffer[n].dwData = down ? 0x80 : 0;
110 current->buffer[n].dwTimeStamp = timestamp;
111 current->buffer[n].dwSequence = current->dinput->evsequence++;
113 if (current->count == current->buffersize)
116 current->overflow = TRUE;
121 LeaveCriticalSection(&(current->crit));
126 return CallNextHookEx(keyboard_hook, code, wparam, lparam);
129 static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
133 {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41}
136 static BOOL keyboarddev_enum_device(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi)
138 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
139 TRACE("Enumerating the Keyboard device\n");
141 lpddi->guidInstance = GUID_SysKeyboard;/* DInput's GUID */
142 lpddi->guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
143 lpddi->dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
144 strcpy(lpddi->tszInstanceName, "Keyboard");
145 strcpy(lpddi->tszProductName, "Wine Keyboard");
153 static SysKeyboardAImpl *alloc_device(REFGUID rguid, LPVOID kvt, IDirectInputAImpl *dinput)
155 SysKeyboardAImpl* newDevice;
156 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardAImpl));
157 newDevice->lpVtbl = kvt;
159 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
160 newDevice->dinput = dinput;
166 static HRESULT keyboarddev_create_device(IDirectInputAImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEA* pdev)
168 if ((IsEqualGUID(&GUID_SysKeyboard,rguid)) || /* Generic Keyboard */
169 (IsEqualGUID(&DInput_Wine_Keyboard_GUID,rguid))) { /* Wine Keyboard */
170 if ((riid == NULL) ||
171 IsEqualGUID(&IID_IDirectInputDeviceA,riid) ||
172 IsEqualGUID(&IID_IDirectInputDevice2A,riid) ||
173 IsEqualGUID(&IID_IDirectInputDevice7A,riid) ||
174 IsEqualGUID(&IID_IDirectInputDevice8A,riid)) {
175 *pdev=(IDirectInputDeviceA*) alloc_device(rguid, &SysKeyboardAvt, dinput);
176 TRACE("Creating a Keyboard device (%p)\n", *pdev);
179 return DIERR_NOINTERFACE;
182 return DIERR_DEVICENOTREG;
185 static dinput_device keyboarddev = {
187 keyboarddev_enum_device,
188 keyboarddev_create_device
191 DECL_GLOBAL_CONSTRUCTOR(keyboarddev_register) { dinput_register_device(&keyboarddev); }
193 static HRESULT WINAPI SysKeyboardAImpl_SetProperty(
194 LPDIRECTINPUTDEVICE8A iface,REFGUID rguid,LPCDIPROPHEADER ph
197 ICOM_THIS(SysKeyboardAImpl,iface);
199 TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
200 TRACE("(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
201 ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
202 if (!HIWORD(rguid)) {
203 switch ((DWORD)rguid) {
204 case (DWORD) DIPROP_BUFFERSIZE: {
205 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
207 TRACE("(buffersize=%ld)\n",pd->dwData);
210 return DIERR_INVALIDPARAM;
212 This->buffersize = pd->dwData;
217 WARN("Unknown type %ld\n",(DWORD)rguid);
224 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(
225 LPDIRECTINPUTDEVICE8A iface,DWORD len,LPVOID ptr
228 /* Note: device does not need to be acquired */
230 return DIERR_INVALIDPARAM;
232 memcpy(ptr, DInputKeyState, 256);
236 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData(
237 LPDIRECTINPUTDEVICE8A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
238 LPDWORD entries,DWORD flags
241 ICOM_THIS(SysKeyboardAImpl,iface);
242 int ret = DI_OK, i = 0;
244 TRACE("(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
245 This,dodsize,dod,entries,entries?*entries:0,flags);
247 if (This->buffer == NULL)
248 return DIERR_NOTBUFFERED;
250 if (dodsize < sizeof(*dod))
251 return DIERR_INVALIDPARAM;
253 EnterCriticalSection(&(This->crit));
255 /* Copy item at a time for the case dodsize > sizeof(buffer[n]) */
256 while ((i < *entries || *entries == INFINITE) && i < This->count)
260 int n = (This->start + i) % This->buffersize;
261 LPDIDEVICEOBJECTDATA pd
262 = (LPDIDEVICEOBJECTDATA)((BYTE *)dod + dodsize * i);
263 pd->dwOfs = This->buffer[n].dwOfs;
264 pd->dwData = This->buffer[n].dwData;
265 pd->dwTimeStamp = This->buffer[n].dwTimeStamp;
266 pd->dwSequence = This->buffer[n].dwSequence;
274 ret = DI_BUFFEROVERFLOW;
276 if (!(flags & DIGDD_PEEK))
280 This->start = (This->start + i) % This->buffersize;
281 This->overflow = FALSE;
284 LeaveCriticalSection(&(This->crit));
289 static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface);
291 static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
293 ICOM_THIS(SysKeyboardAImpl,iface);
295 TRACE("(this=%p)\n",This);
304 FIXME("Not more than one keyboard can be acquired at the same time.\n");
305 SysKeyboardAImpl_Unacquire(iface);
310 if (This->buffersize > 0)
312 This->buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
313 This->buffersize * sizeof(*(This->buffer)));
316 This->overflow = FALSE;
317 InitializeCriticalSection(&(This->crit));
325 static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
327 ICOM_THIS(SysKeyboardAImpl,iface);
328 TRACE("(this=%p)\n",This);
330 if (This->acquired == 0)
336 ERR("this != current\n");
340 if (This->buffersize >= 0)
342 HeapFree(GetProcessHeap(), 0, This->buffer);
344 DeleteCriticalSection(&(This->crit));
350 static HRESULT WINAPI SysKeyboardAImpl_SetEventNotification(LPDIRECTINPUTDEVICE8A iface,
352 ICOM_THIS(SysKeyboardAImpl,iface);
354 TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
360 /******************************************************************************
361 * GetCapabilities : get the device capablitites
363 static HRESULT WINAPI SysKeyboardAImpl_GetCapabilities(
364 LPDIRECTINPUTDEVICE8A iface,
365 LPDIDEVCAPS lpDIDevCaps)
367 ICOM_THIS(SysKeyboardAImpl,iface);
369 TRACE("(this=%p,%p)\n",This,lpDIDevCaps);
371 if (lpDIDevCaps->dwSize == sizeof(DIDEVCAPS)) {
372 lpDIDevCaps->dwFlags = DIDC_ATTACHED;
373 lpDIDevCaps->dwDevType = DIDEVTYPE_KEYBOARD;
374 lpDIDevCaps->dwAxes = 0;
375 lpDIDevCaps->dwButtons = 0;
376 lpDIDevCaps->dwPOVs = 0;
377 lpDIDevCaps->dwFFSamplePeriod = 0;
378 lpDIDevCaps->dwFFMinTimeResolution = 0;
379 lpDIDevCaps->dwFirmwareRevision = 100;
380 lpDIDevCaps->dwHardwareRevision = 100;
381 lpDIDevCaps->dwFFDriverVersion = 0;
384 FIXME("DirectX 3.0 not supported....\n");
390 static ICOM_VTABLE(IDirectInputDevice8A) SysKeyboardAvt =
392 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
393 IDirectInputDevice2AImpl_QueryInterface,
394 IDirectInputDevice2AImpl_AddRef,
395 IDirectInputDevice2AImpl_Release,
396 SysKeyboardAImpl_GetCapabilities,
397 IDirectInputDevice2AImpl_EnumObjects,
398 IDirectInputDevice2AImpl_GetProperty,
399 SysKeyboardAImpl_SetProperty,
400 SysKeyboardAImpl_Acquire,
401 SysKeyboardAImpl_Unacquire,
402 SysKeyboardAImpl_GetDeviceState,
403 SysKeyboardAImpl_GetDeviceData,
404 IDirectInputDevice2AImpl_SetDataFormat,
405 SysKeyboardAImpl_SetEventNotification,
406 IDirectInputDevice2AImpl_SetCooperativeLevel,
407 IDirectInputDevice2AImpl_GetObjectInfo,
408 IDirectInputDevice2AImpl_GetDeviceInfo,
409 IDirectInputDevice2AImpl_RunControlPanel,
410 IDirectInputDevice2AImpl_Initialize,
411 IDirectInputDevice2AImpl_CreateEffect,
412 IDirectInputDevice2AImpl_EnumEffects,
413 IDirectInputDevice2AImpl_GetEffectInfo,
414 IDirectInputDevice2AImpl_GetForceFeedbackState,
415 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
416 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
417 IDirectInputDevice2AImpl_Escape,
418 IDirectInputDevice2AImpl_Poll,
419 IDirectInputDevice2AImpl_SendDeviceData,
420 IDirectInputDevice7AImpl_EnumEffectsInFile,
421 IDirectInputDevice7AImpl_WriteEffectToFile,
422 IDirectInputDevice8AImpl_BuildActionMap,
423 IDirectInputDevice8AImpl_SetActionMap,
424 IDirectInputDevice8AImpl_GetImageInfo