/* DirectInput Keyboard device * * Copyright 1998 Marcus Meissner * Copyright 1998,1999 Lionel Ulmer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include #ifdef HAVE_SYS_ERRNO_H # include #endif #include "winbase.h" #include "winuser.h" #include "winerror.h" #include "dinput.h" #include "dinput_private.h" #include "device_private.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(dinput); static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt; static ICOM_VTABLE(IDirectInputDevice7A) SysKeyboard7Avt; typedef struct SysKeyboardAImpl SysKeyboardAImpl; struct SysKeyboardAImpl { /* IDirectInputDevice2AImpl */ ICOM_VFIELD(IDirectInputDevice2A); DWORD ref; GUID guid; IDirectInputAImpl *dinput; /* SysKeyboardAImpl */ BYTE keystate[256]; int acquired; }; static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */ 0x0ab8648a, 0x7735, 0x11d2, {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41} }; static BOOL keyboarddev_enum_device(DWORD dwDevType, DWORD dwFlags, LPCDIDEVICEINSTANCEA lpddi) { if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) { TRACE("Enumerating the Keyboard device\n"); lpddi->guidInstance = GUID_SysKeyboard;/* DInput's GUID */ lpddi->guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */ lpddi->dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8); strcpy(lpddi->tszInstanceName, "Keyboard"); strcpy(lpddi->tszProductName, "Wine Keyboard"); return TRUE; } return FALSE; } static SysKeyboardAImpl *alloc_device(REFGUID rguid, ICOM_VTABLE(IDirectInputDevice2A) *kvt, IDirectInputAImpl *dinput) { SysKeyboardAImpl* newDevice; newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardAImpl)); newDevice->ref = 1; ICOM_VTBL(newDevice) = kvt; memcpy(&(newDevice->guid),rguid,sizeof(*rguid)); memset(newDevice->keystate,0,256); newDevice->dinput = dinput; return newDevice; } static HRESULT keyboarddev_create_device(IDirectInputAImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEA* pdev) { if ((IsEqualGUID(&GUID_SysKeyboard,rguid)) || /* Generic Keyboard */ (IsEqualGUID(&DInput_Wine_Keyboard_GUID,rguid))) { /* Wine Keyboard */ if ((riid == NULL) || (IsEqualGUID(&IID_IDirectInputDevice2A,riid)) || (IsEqualGUID(&IID_IDirectInputDevice2A,riid))) { *pdev=(IDirectInputDeviceA*) alloc_device(rguid, &SysKeyboardAvt, dinput); TRACE("Creating a Keyboard device (%p)\n", *pdev); return DI_OK; } else if (IsEqualGUID(&IID_IDirectInputDevice7A,riid)) { *pdev=(IDirectInputDeviceA*) alloc_device(rguid, (ICOM_VTABLE(IDirectInputDevice2A) *) &SysKeyboard7Avt, dinput); TRACE("Creating a Keyboard DInput7A device (%p)\n", *pdev); return DI_OK; } else return DIERR_NOINTERFACE; } return DIERR_DEVICENOTREG; } static dinput_device keyboarddev = { 100, keyboarddev_enum_device, keyboarddev_create_device }; DECL_GLOBAL_CONSTRUCTOR(keyboarddev_register) { dinput_register_device(&keyboarddev); } static HRESULT WINAPI SysKeyboardAImpl_SetProperty( LPDIRECTINPUTDEVICE2A iface,REFGUID rguid,LPCDIPROPHEADER ph ) { ICOM_THIS(SysKeyboardAImpl,iface); TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph); TRACE("(size=%ld,headersize=%ld,obj=%ld,how=%ld\n", ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow); if (!HIWORD(rguid)) { switch ((DWORD)rguid) { case (DWORD) DIPROP_BUFFERSIZE: { LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph; TRACE("(buffersize=%ld)\n",pd->dwData); break; } default: WARN("Unknown type %ld\n",(DWORD)rguid); break; } } return 0; } static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState( LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr ) { DWORD i; memset( ptr, 0, len ); if (len != 256) { WARN("whoops, got len %ld?\n", len); return DI_OK; } for (i = 0; i < 0x80; i++) { WORD vkey = MapVirtualKeyA( i, 1 ); if (vkey && (GetAsyncKeyState( vkey ) & 0x8000)) { ((LPBYTE)ptr)[i] = 0x80; ((LPBYTE)ptr)[i | 0x80] = 0x80; } } return DI_OK; } static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData( LPDIRECTINPUTDEVICE2A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod, LPDWORD entries,DWORD flags ) { ICOM_THIS(SysKeyboardAImpl,iface); int i, n; TRACE("(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n", This,dodsize,dod,entries,entries?*entries:0,flags); for (i = n = 0; (i < 0x80) && (n < *entries); i++) { WORD state, vkey = MapVirtualKeyA( i, 1 ); if (!vkey) continue; state = (GetAsyncKeyState( vkey ) >> 8) & 0x80; if (state != This->keystate[vkey]) { if (dod) { /* add an entry */ dod[n].dwOfs = i; /* scancode */ dod[n].dwData = state; dod[n].dwTimeStamp = GetCurrentTime(); /* umm */ dod[n].dwSequence = This->dinput->evsequence++; n++; } if (!(flags & DIGDD_PEEK)) This->keystate[vkey] = state; } } if (n) TRACE_(dinput)("%d entries\n",n); *entries = n; return DI_OK; } static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface) { ICOM_THIS(SysKeyboardAImpl,iface); TRACE("(this=%p)\n",This); if (This->acquired == 0) { This->acquired = 1; } return DI_OK; } static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface) { ICOM_THIS(SysKeyboardAImpl,iface); TRACE("(this=%p)\n",This); if (This->acquired == 1) { This->acquired = 0; } else { ERR("Unacquiring a not-acquired device !!!\n"); } return DI_OK; } /****************************************************************************** * GetCapabilities : get the device capablitites */ static HRESULT WINAPI SysKeyboardAImpl_GetCapabilities( LPDIRECTINPUTDEVICE2A iface, LPDIDEVCAPS lpDIDevCaps) { ICOM_THIS(SysKeyboardAImpl,iface); TRACE("(this=%p,%p)\n",This,lpDIDevCaps); if (lpDIDevCaps->dwSize == sizeof(DIDEVCAPS)) { lpDIDevCaps->dwFlags = DIDC_ATTACHED; lpDIDevCaps->dwDevType = DIDEVTYPE_KEYBOARD; lpDIDevCaps->dwAxes = 0; lpDIDevCaps->dwButtons = 0; lpDIDevCaps->dwPOVs = 0; lpDIDevCaps->dwFFSamplePeriod = 0; lpDIDevCaps->dwFFMinTimeResolution = 0; lpDIDevCaps->dwFirmwareRevision = 100; lpDIDevCaps->dwHardwareRevision = 100; lpDIDevCaps->dwFFDriverVersion = 0; } else { /* DirectX 3.0 */ FIXME("DirectX 3.0 not supported....\n"); } return DI_OK; } static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt = { ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE IDirectInputDevice2AImpl_QueryInterface, IDirectInputDevice2AImpl_AddRef, IDirectInputDevice2AImpl_Release, SysKeyboardAImpl_GetCapabilities, IDirectInputDevice2AImpl_EnumObjects, IDirectInputDevice2AImpl_GetProperty, SysKeyboardAImpl_SetProperty, SysKeyboardAImpl_Acquire, SysKeyboardAImpl_Unacquire, SysKeyboardAImpl_GetDeviceState, SysKeyboardAImpl_GetDeviceData, IDirectInputDevice2AImpl_SetDataFormat, IDirectInputDevice2AImpl_SetEventNotification, IDirectInputDevice2AImpl_SetCooperativeLevel, IDirectInputDevice2AImpl_GetObjectInfo, IDirectInputDevice2AImpl_GetDeviceInfo, IDirectInputDevice2AImpl_RunControlPanel, IDirectInputDevice2AImpl_Initialize, IDirectInputDevice2AImpl_CreateEffect, IDirectInputDevice2AImpl_EnumEffects, IDirectInputDevice2AImpl_GetEffectInfo, IDirectInputDevice2AImpl_GetForceFeedbackState, IDirectInputDevice2AImpl_SendForceFeedbackCommand, IDirectInputDevice2AImpl_EnumCreatedEffectObjects, IDirectInputDevice2AImpl_Escape, IDirectInputDevice2AImpl_Poll, IDirectInputDevice2AImpl_SendDeviceData }; #if !defined(__STRICT_ANSI__) && defined(__GNUC__) # define XCAST(fun) (typeof(SysKeyboard7Avt.fun)) #else # define XCAST(fun) (void*) #endif static ICOM_VTABLE(IDirectInputDevice7A) SysKeyboard7Avt = { ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE XCAST(QueryInterface)IDirectInputDevice2AImpl_QueryInterface, XCAST(AddRef)IDirectInputDevice2AImpl_AddRef, XCAST(Release)IDirectInputDevice2AImpl_Release, XCAST(GetCapabilities)SysKeyboardAImpl_GetCapabilities, XCAST(EnumObjects)IDirectInputDevice2AImpl_EnumObjects, XCAST(GetProperty)IDirectInputDevice2AImpl_GetProperty, XCAST(SetProperty)SysKeyboardAImpl_SetProperty, XCAST(Acquire)SysKeyboardAImpl_Acquire, XCAST(Unacquire)SysKeyboardAImpl_Unacquire, XCAST(GetDeviceState)SysKeyboardAImpl_GetDeviceState, XCAST(GetDeviceData)SysKeyboardAImpl_GetDeviceData, XCAST(SetDataFormat)IDirectInputDevice2AImpl_SetDataFormat, XCAST(SetEventNotification)IDirectInputDevice2AImpl_SetEventNotification, XCAST(SetCooperativeLevel)IDirectInputDevice2AImpl_SetCooperativeLevel, XCAST(GetObjectInfo)IDirectInputDevice2AImpl_GetObjectInfo, XCAST(GetDeviceInfo)IDirectInputDevice2AImpl_GetDeviceInfo, XCAST(RunControlPanel)IDirectInputDevice2AImpl_RunControlPanel, XCAST(Initialize)IDirectInputDevice2AImpl_Initialize, XCAST(CreateEffect)IDirectInputDevice2AImpl_CreateEffect, XCAST(EnumEffects)IDirectInputDevice2AImpl_EnumEffects, XCAST(GetEffectInfo)IDirectInputDevice2AImpl_GetEffectInfo, XCAST(GetForceFeedbackState)IDirectInputDevice2AImpl_GetForceFeedbackState, XCAST(SendForceFeedbackCommand)IDirectInputDevice2AImpl_SendForceFeedbackCommand, XCAST(EnumCreatedEffectObjects)IDirectInputDevice2AImpl_EnumCreatedEffectObjects, XCAST(Escape)IDirectInputDevice2AImpl_Escape, XCAST(Poll)IDirectInputDevice2AImpl_Poll, XCAST(SendDeviceData)IDirectInputDevice2AImpl_SendDeviceData, IDirectInputDevice7AImpl_EnumEffectsInFile, IDirectInputDevice7AImpl_WriteEffectToFile }; #undef XCAST