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
23 #include "wine/port.h"
26 #ifdef HAVE_SYS_ERRNO_H
27 # include <sys/errno.h>
35 #include "dinput_private.h"
36 #include "device_private.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
41 static ICOM_VTABLE(IDirectInputDevice8A) SysKeyboardAvt;
43 typedef struct SysKeyboardAImpl SysKeyboardAImpl;
44 struct SysKeyboardAImpl
50 IDirectInputAImpl *dinput;
53 /* SysKeyboardAImpl */
55 int buffersize; /* set in 'SetProperty' */
56 LPDIDEVICEOBJECTDATA buffer; /* buffer for 'GetDeviceData'.
57 Alloc at 'Acquire', Free at
59 int count; /* number of objects in use in
61 int start; /* 'buffer' rotates. This is the
62 first in use (if count > 0) */
63 BOOL overflow; /* return DI_BUFFEROVERFLOW in
65 CRITICAL_SECTION crit;
68 SysKeyboardAImpl *current; /* Today's acquired device
69 FIXME: currently this can be only one.
70 Maybe this should be a linked list or st.
71 I don't know what the rules are for multiple acquired keyboards,
72 but 'DI_LOSTFOCUS' and 'DI_UNACQUIRED' exist for a reason.
75 static BYTE DInputKeyState[256]; /* array for 'GetDeviceState' */
79 LRESULT CALLBACK KeyboardCallback( int code, WPARAM wparam, LPARAM lparam )
81 TRACE("(%d,%d,%ld)\n", code, wparam, lparam);
83 if (code == HC_ACTION)
90 KBDLLHOOKSTRUCT *hook = (KBDLLHOOKSTRUCT *)lparam;
91 dik_code = hook->scanCode;
92 if (hook->flags & LLKHF_EXTENDED) dik_code |= 0x80;
93 down = !(hook->flags & LLKHF_UP);
94 timestamp = hook->time;
97 DInputKeyState[dik_code] = (down ? 0x80 : 0);
102 SetEvent(current->hEvent);
104 if (current->buffer != NULL)
108 EnterCriticalSection(&(current->crit));
110 n = (current->start + current->count) % current->buffersize;
112 current->buffer[n].dwOfs = dik_code;
113 current->buffer[n].dwData = down ? 0x80 : 0;
114 current->buffer[n].dwTimeStamp = timestamp;
115 current->buffer[n].dwSequence = current->dinput->evsequence++;
117 TRACE("Adding event at offset %d : %ld - %ld - %ld - %ld\n", n,
118 current->buffer[n].dwOfs, current->buffer[n].dwData, current->buffer[n].dwTimeStamp, current->buffer[n].dwSequence);
120 if (current->count == current->buffersize)
123 current->overflow = TRUE;
128 LeaveCriticalSection(&(current->crit));
133 return CallNextHookEx(keyboard_hook, code, wparam, lparam);
136 static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
140 {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41}
143 static BOOL keyboarddev_enum_device(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi)
145 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
146 TRACE("Enumerating the Keyboard device\n");
148 lpddi->guidInstance = GUID_SysKeyboard;/* DInput's GUID */
149 lpddi->guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
150 lpddi->dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
151 strcpy(lpddi->tszInstanceName, "Keyboard");
152 strcpy(lpddi->tszProductName, "Wine Keyboard");
160 static SysKeyboardAImpl *alloc_device(REFGUID rguid, LPVOID kvt, IDirectInputAImpl *dinput)
162 SysKeyboardAImpl* newDevice;
163 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardAImpl));
164 newDevice->lpVtbl = kvt;
166 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
167 newDevice->dinput = dinput;
173 static HRESULT keyboarddev_create_device(IDirectInputAImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEA* pdev)
175 if ((IsEqualGUID(&GUID_SysKeyboard,rguid)) || /* Generic Keyboard */
176 (IsEqualGUID(&DInput_Wine_Keyboard_GUID,rguid))) { /* Wine Keyboard */
177 if ((riid == NULL) ||
178 IsEqualGUID(&IID_IDirectInputDeviceA,riid) ||
179 IsEqualGUID(&IID_IDirectInputDevice2A,riid) ||
180 IsEqualGUID(&IID_IDirectInputDevice7A,riid) ||
181 IsEqualGUID(&IID_IDirectInputDevice8A,riid)) {
182 *pdev=(IDirectInputDeviceA*) alloc_device(rguid, &SysKeyboardAvt, dinput);
183 TRACE("Creating a Keyboard device (%p)\n", *pdev);
186 return DIERR_NOINTERFACE;
189 return DIERR_DEVICENOTREG;
192 static dinput_device keyboarddev = {
194 keyboarddev_enum_device,
195 keyboarddev_create_device
198 DECL_GLOBAL_CONSTRUCTOR(keyboarddev_register) { dinput_register_device(&keyboarddev); }
200 static HRESULT WINAPI SysKeyboardAImpl_SetProperty(
201 LPDIRECTINPUTDEVICE8A iface,REFGUID rguid,LPCDIPROPHEADER ph
204 ICOM_THIS(SysKeyboardAImpl,iface);
206 TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
207 TRACE("(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
208 ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
209 if (!HIWORD(rguid)) {
210 switch ((DWORD)rguid) {
211 case (DWORD) DIPROP_BUFFERSIZE: {
212 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
214 TRACE("(buffersize=%ld)\n",pd->dwData);
217 return DIERR_INVALIDPARAM;
219 This->buffersize = pd->dwData;
224 WARN("Unknown type %ld\n",(DWORD)rguid);
231 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(
232 LPDIRECTINPUTDEVICE8A iface,DWORD len,LPVOID ptr
235 /* Note: device does not need to be acquired */
237 return DIERR_INVALIDPARAM;
239 memcpy(ptr, DInputKeyState, 256);
243 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData(
244 LPDIRECTINPUTDEVICE8A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
245 LPDWORD entries,DWORD flags
248 ICOM_THIS(SysKeyboardAImpl,iface);
249 int ret = DI_OK, i = 0;
251 TRACE("(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
252 This,dodsize,dod,entries,entries?*entries:0,flags);
254 if (This->acquired == 0)
255 return DIERR_NOTACQUIRED;
257 if (This->buffer == NULL)
258 return DIERR_NOTBUFFERED;
260 if (dodsize < sizeof(*dod))
261 return DIERR_INVALIDPARAM;
263 EnterCriticalSection(&(This->crit));
265 /* Copy item at a time for the case dodsize > sizeof(buffer[n]) */
266 while ((i < *entries || *entries == INFINITE) && i < This->count)
270 int n = (This->start + i) % This->buffersize;
271 LPDIDEVICEOBJECTDATA pd
272 = (LPDIDEVICEOBJECTDATA)((BYTE *)dod + dodsize * i);
273 pd->dwOfs = This->buffer[n].dwOfs;
274 pd->dwData = This->buffer[n].dwData;
275 pd->dwTimeStamp = This->buffer[n].dwTimeStamp;
276 pd->dwSequence = This->buffer[n].dwSequence;
284 ret = DI_BUFFEROVERFLOW;
286 if (!(flags & DIGDD_PEEK))
290 This->start = (This->start + i) % This->buffersize;
291 This->overflow = FALSE;
294 LeaveCriticalSection(&(This->crit));
296 TRACE("Returning %ld events queued\n", *entries);
301 static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface);
303 static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
305 ICOM_THIS(SysKeyboardAImpl,iface);
307 TRACE("(this=%p)\n",This);
316 FIXME("Not more than one keyboard can be acquired at the same time.\n");
317 SysKeyboardAImpl_Unacquire(iface);
322 if (This->buffersize > 0)
324 This->buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
325 This->buffersize * sizeof(*(This->buffer)));
328 This->overflow = FALSE;
329 InitializeCriticalSection(&(This->crit));
337 static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
339 ICOM_THIS(SysKeyboardAImpl,iface);
340 TRACE("(this=%p)\n",This);
342 if (This->acquired == 0)
348 ERR("this != current\n");
352 if (This->buffersize >= 0)
354 HeapFree(GetProcessHeap(), 0, This->buffer);
356 DeleteCriticalSection(&(This->crit));
362 static HRESULT WINAPI SysKeyboardAImpl_SetEventNotification(LPDIRECTINPUTDEVICE8A iface,
364 ICOM_THIS(SysKeyboardAImpl,iface);
366 TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
372 /******************************************************************************
373 * GetCapabilities : get the device capablitites
375 static HRESULT WINAPI SysKeyboardAImpl_GetCapabilities(
376 LPDIRECTINPUTDEVICE8A iface,
377 LPDIDEVCAPS lpDIDevCaps)
379 ICOM_THIS(SysKeyboardAImpl,iface);
381 TRACE("(this=%p,%p)\n",This,lpDIDevCaps);
383 if (lpDIDevCaps->dwSize == sizeof(DIDEVCAPS)) {
384 lpDIDevCaps->dwFlags = DIDC_ATTACHED;
385 lpDIDevCaps->dwDevType = DIDEVTYPE_KEYBOARD;
386 lpDIDevCaps->dwAxes = 0;
387 lpDIDevCaps->dwButtons = 0;
388 lpDIDevCaps->dwPOVs = 0;
389 lpDIDevCaps->dwFFSamplePeriod = 0;
390 lpDIDevCaps->dwFFMinTimeResolution = 0;
391 lpDIDevCaps->dwFirmwareRevision = 100;
392 lpDIDevCaps->dwHardwareRevision = 100;
393 lpDIDevCaps->dwFFDriverVersion = 0;
396 FIXME("DirectX 3.0 not supported....\n");
402 static ICOM_VTABLE(IDirectInputDevice8A) SysKeyboardAvt =
404 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
405 IDirectInputDevice2AImpl_QueryInterface,
406 IDirectInputDevice2AImpl_AddRef,
407 IDirectInputDevice2AImpl_Release,
408 SysKeyboardAImpl_GetCapabilities,
409 IDirectInputDevice2AImpl_EnumObjects,
410 IDirectInputDevice2AImpl_GetProperty,
411 SysKeyboardAImpl_SetProperty,
412 SysKeyboardAImpl_Acquire,
413 SysKeyboardAImpl_Unacquire,
414 SysKeyboardAImpl_GetDeviceState,
415 SysKeyboardAImpl_GetDeviceData,
416 IDirectInputDevice2AImpl_SetDataFormat,
417 SysKeyboardAImpl_SetEventNotification,
418 IDirectInputDevice2AImpl_SetCooperativeLevel,
419 IDirectInputDevice2AImpl_GetObjectInfo,
420 IDirectInputDevice2AImpl_GetDeviceInfo,
421 IDirectInputDevice2AImpl_RunControlPanel,
422 IDirectInputDevice2AImpl_Initialize,
423 IDirectInputDevice2AImpl_CreateEffect,
424 IDirectInputDevice2AImpl_EnumEffects,
425 IDirectInputDevice2AImpl_GetEffectInfo,
426 IDirectInputDevice2AImpl_GetForceFeedbackState,
427 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
428 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
429 IDirectInputDevice2AImpl_Escape,
430 IDirectInputDevice2AImpl_Poll,
431 IDirectInputDevice2AImpl_SendDeviceData,
432 IDirectInputDevice7AImpl_EnumEffectsInFile,
433 IDirectInputDevice7AImpl_WriteEffectToFile,
434 IDirectInputDevice8AImpl_BuildActionMap,
435 IDirectInputDevice8AImpl_SetActionMap,
436 IDirectInputDevice8AImpl_GetImageInfo