source: trunk/src/dinput/keyboard.c@ 10010

Last change on this file since 10010 was 9016, checked in by sandervl, 23 years ago

Wine resync; added missing bugfix

File size: 13.0 KB
Line 
1/* DirectInput Keyboard device
2 *
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998,1999 Lionel Ulmer
5 * Copyright 2000-2001 TransGaming Technologies Inc.
6 *
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.
11 *
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.
16 *
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
20 */
21
22#include "config.h"
23#include "wine/port.h"
24
25#include <string.h>
26#ifdef HAVE_SYS_ERRNO_H
27# include <sys/errno.h>
28#endif
29
30#include "winbase.h"
31#include "winuser.h"
32#include "winerror.h"
33#include "dinput.h"
34
35#include "dinput_private.h"
36#include "device_private.h"
37#include "wine/debug.h"
38
39WINE_DEFAULT_DEBUG_CHANNEL(dinput);
40
41static ICOM_VTABLE(IDirectInputDevice8A) SysKeyboardAvt;
42
43typedef struct SysKeyboardAImpl SysKeyboardAImpl;
44struct SysKeyboardAImpl
45{
46 LPVOID lpVtbl;
47 DWORD ref;
48 GUID guid;
49
50 IDirectInputAImpl *dinput;
51
52 HANDLE hEvent;
53 /* SysKeyboardAImpl */
54 int acquired;
55 int buffersize; /* set in 'SetProperty' */
56 LPDIDEVICEOBJECTDATA buffer; /* buffer for 'GetDeviceData'.
57 Alloc at 'Acquire', Free at
58 'Unacquire' */
59 int count; /* number of objects in use in
60 'buffer' */
61 int start; /* 'buffer' rotates. This is the
62 first in use (if count > 0) */
63 BOOL overflow; /* return DI_BUFFEROVERFLOW in
64 'GetDeviceData' */
65 CRITICAL_SECTION crit;
66};
67
68SysKeyboardAImpl *current; /* Today's acquired device
69FIXME: currently this can be only one.
70Maybe this should be a linked list or st.
71I don't know what the rules are for multiple acquired keyboards,
72but 'DI_LOSTFOCUS' and 'DI_UNACQUIRED' exist for a reason.
73*/
74
75static BYTE DInputKeyState[256]; /* array for 'GetDeviceState' */
76
77HHOOK keyboard_hook;
78
79LRESULT CALLBACK KeyboardCallback( int code, WPARAM wparam, LPARAM lparam )
80{
81 TRACE("(%d,%d,%ld)\n", code, wparam, lparam);
82
83 if (code == HC_ACTION)
84 {
85 BYTE dik_code;
86 BOOL down;
87 DWORD timestamp;
88
89 {
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;
95 }
96
97 DInputKeyState[dik_code] = (down ? 0x80 : 0);
98
99 if (current != NULL)
100 {
101 if (current->hEvent)
102 SetEvent(current->hEvent);
103
104 if (current->buffer != NULL)
105 {
106 int n;
107
108 EnterCriticalSection(&(current->crit));
109
110 n = (current->start + current->count) % current->buffersize;
111
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++;
116
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);
119
120 if (current->count == current->buffersize)
121 {
122 current->start++;
123 current->overflow = TRUE;
124 }
125 else
126 current->count++;
127
128 LeaveCriticalSection(&(current->crit));
129 }
130 }
131 }
132
133 return CallNextHookEx(keyboard_hook, code, wparam, lparam);
134}
135
136static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
137 0x0ab8648a,
138 0x7735,
139 0x11d2,
140 {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41}
141};
142
143static BOOL keyboarddev_enum_device(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi)
144{
145 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
146 TRACE("Enumerating the Keyboard device\n");
147
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");
153
154 return TRUE;
155 }
156
157 return FALSE;
158}
159
160static SysKeyboardAImpl *alloc_device(REFGUID rguid, LPVOID kvt, IDirectInputAImpl *dinput)
161{
162 SysKeyboardAImpl* newDevice;
163 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardAImpl));
164 newDevice->lpVtbl = kvt;
165 newDevice->ref = 1;
166 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
167 newDevice->dinput = dinput;
168
169 return newDevice;
170}
171
172
173static HRESULT keyboarddev_create_device(IDirectInputAImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEA* pdev)
174{
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);
184 return DI_OK;
185 } else
186 return DIERR_NOINTERFACE;
187 }
188
189 return DIERR_DEVICENOTREG;
190}
191
192static dinput_device keyboarddev = {
193 100,
194 keyboarddev_enum_device,
195 keyboarddev_create_device
196};
197
198DECL_GLOBAL_CONSTRUCTOR(keyboarddev_register) { dinput_register_device(&keyboarddev); }
199
200static HRESULT WINAPI SysKeyboardAImpl_SetProperty(
201 LPDIRECTINPUTDEVICE8A iface,REFGUID rguid,LPCDIPROPHEADER ph
202)
203{
204 ICOM_THIS(SysKeyboardAImpl,iface);
205
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;
213
214 TRACE("(buffersize=%ld)\n",pd->dwData);
215
216 if (This->acquired)
217 return DIERR_INVALIDPARAM;
218
219 This->buffersize = pd->dwData;
220
221 break;
222 }
223 default:
224 WARN("Unknown type %ld\n",(DWORD)rguid);
225 break;
226 }
227 }
228 return 0;
229}
230
231static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(
232 LPDIRECTINPUTDEVICE8A iface,DWORD len,LPVOID ptr
233)
234{
235 /* Note: device does not need to be acquired */
236 if (len != 256)
237 return DIERR_INVALIDPARAM;
238
239 memcpy(ptr, DInputKeyState, 256);
240 return DI_OK;
241}
242
243static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData(
244 LPDIRECTINPUTDEVICE8A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
245 LPDWORD entries,DWORD flags
246)
247{
248 ICOM_THIS(SysKeyboardAImpl,iface);
249 int ret = DI_OK, i = 0;
250
251 TRACE("(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
252 This,dodsize,dod,entries,entries?*entries:0,flags);
253
254 if (This->acquired == 0)
255 return DIERR_NOTACQUIRED;
256
257 if (This->buffer == NULL)
258 return DIERR_NOTBUFFERED;
259
260 if (dodsize < sizeof(*dod))
261 return DIERR_INVALIDPARAM;
262
263 EnterCriticalSection(&(This->crit));
264
265 /* Copy item at a time for the case dodsize > sizeof(buffer[n]) */
266 while ((i < *entries || *entries == INFINITE) && i < This->count)
267 {
268 if (dod != NULL)
269 {
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;
277 }
278 i++;
279 }
280
281 *entries = i;
282
283 if (This->overflow)
284 ret = DI_BUFFEROVERFLOW;
285
286 if (!(flags & DIGDD_PEEK))
287 {
288 /* Empty buffer */
289 This->count -= i;
290 This->start = (This->start + i) % This->buffersize;
291 This->overflow = FALSE;
292 }
293
294 LeaveCriticalSection(&(This->crit));
295
296 TRACE("Returning %ld events queued\n", *entries);
297
298 return ret;
299}
300
301static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface);
302
303static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
304{
305 ICOM_THIS(SysKeyboardAImpl,iface);
306
307 TRACE("(this=%p)\n",This);
308
309 if (This->acquired)
310 return S_FALSE;
311
312 This->acquired = 1;
313
314 if (current != NULL)
315 {
316 FIXME("Not more than one keyboard can be acquired at the same time.\n");
317 SysKeyboardAImpl_Unacquire(iface);
318 }
319
320 current = This;
321
322 if (This->buffersize > 0)
323 {
324 This->buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
325 This->buffersize * sizeof(*(This->buffer)));
326 This->start = 0;
327 This->count = 0;
328 This->overflow = FALSE;
329 InitializeCriticalSection(&(This->crit));
330 }
331 else
332 This->buffer = NULL;
333
334 return DI_OK;
335}
336
337static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
338{
339 ICOM_THIS(SysKeyboardAImpl,iface);
340 TRACE("(this=%p)\n",This);
341
342 if (This->acquired == 0)
343 return DI_NOEFFECT;
344
345 if (current == This)
346 current = NULL;
347 else
348 ERR("this != current\n");
349
350 This->acquired = 0;
351
352 if (This->buffersize >= 0)
353 {
354 HeapFree(GetProcessHeap(), 0, This->buffer);
355 This->buffer = NULL;
356 DeleteCriticalSection(&(This->crit));
357 }
358
359 return DI_OK;
360}
361
362static HRESULT WINAPI SysKeyboardAImpl_SetEventNotification(LPDIRECTINPUTDEVICE8A iface,
363 HANDLE hnd) {
364 ICOM_THIS(SysKeyboardAImpl,iface);
365
366 TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
367
368 This->hEvent = hnd;
369 return DI_OK;
370}
371
372/******************************************************************************
373 * GetCapabilities : get the device capablitites
374 */
375static HRESULT WINAPI SysKeyboardAImpl_GetCapabilities(
376 LPDIRECTINPUTDEVICE8A iface,
377 LPDIDEVCAPS lpDIDevCaps)
378{
379 ICOM_THIS(SysKeyboardAImpl,iface);
380
381 TRACE("(this=%p,%p)\n",This,lpDIDevCaps);
382
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;
394 } else {
395 /* DirectX 3.0 */
396 FIXME("DirectX 3.0 not supported....\n");
397 }
398
399 return DI_OK;
400}
401
402static ICOM_VTABLE(IDirectInputDevice8A) SysKeyboardAvt =
403{
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
437};
Note: See TracBrowser for help on using the repository browser.