Skip to content

Instantly share code, notes, and snippets.

@varlen
Last active February 10, 2022 15:22
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save varlen/c47e807e647cc56a6faf9d548d2c00f3 to your computer and use it in GitHub Desktop.
Save varlen/c47e807e647cc56a6faf9d548d2c00f3 to your computer and use it in GitHub Desktop.
Sample of direct communication with virtual game controller using Python. The first file uses PyWin32 and works directly with the Windows API, for older versions of vJoy. The second file uses the DLL of vJoy SDK to command the device.
from win32file import *
import struct, time
CONST_PPJOY_DEVICE = "\\\\.\\PPJoyIOCTL1"
CONST_LOAD_POSITIONS = 0x910
class vJoy(object):
def __init__(self):
self.handle = None
def open(self):
self.handle = CreateFile( CONST_PPJOY_DEVICE, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, None, OPEN_EXISTING, 0, None )
if self.handle.__class__.__name__ == "PyHANDLE":
return True
return False
def close(self):
if self.handle.__class__.__name__ == "PyHANDLE":
self.handle.close()
return True
return False
def generateJoystickPosition(self,
wThrottle = 0, wRudder = 0, wAileron = 0,
wAxisX = 0, wAxisY = 0, wAxisZ = 0,
wAxisXRot = 0, wAxisYRot = 0, wAxisZRot = 0,
wSlider = 0, wDial = 0, wWheel = 0,
wAxisVX = 0, wAxisVY = 0, wAxisVZ = 0,
wAxisVBRX = 0, wAxisVBRY = 0, wAxisVBRZ = 0,
lButtons = 0, bHats = 0):
"""
typedef struct _JOYSTICK_POSITION
{
LONG wThrottle;
LONG wRudder;
LONG wAileron;
LONG wAxisX;
LONG wAxisY;
LONG wAxisZ;
LONG wAxisXRot;
LONG wAxisYRot;
LONG wAxisZRot;
LONG wSlider;
LONG wDial;
LONG wWheel;
LONG wAxisVX;
LONG wAxisVY;
LONG wAxisVZ;
LONG wAxisVBRX;
LONG wAxisVBRY;
LONG wAxisVBRZ;
LONG lButtons; // 32 buttons: 0x00000001 means button1 is pressed, 0x80000000 -> button32 is pressed
UCHAR bHats; // Lower 4 bits: HAT switch
} JOYSTICK_POSITION, *PJOYSTICK_POSITION;
"""
joyPosFormat = "lllllllllllllllllllB"
pos = struct.pack( joyPosFormat, wThrottle, wRudder, wAileron, wAxisX, wAxisY, wAxisZ, wAxisXRot, wAxisYRot, wAxisZRot, wSlider, wDial, wWheel, wAxisVX, wAxisVY, wAxisVZ, wAxisVBRX, wAxisVBRY, wAxisVBRZ, lButtons, bHats )
return pos
def update(self, joystickPosition):
if self.handle.__class__.__name__ == "PyHANDLE":
DeviceIoControl(self.handle, CONST_LOAD_POSITIONS, joystickPosition, 0 )
return True
return False
def sendButtons( self, bState ):
joyPosition = self.generateJoystickPosition( lButtons = bState )
return self.update( joyPosition )
vj = vJoy()
def test():
vj.open()
btn = 1
time.sleep(2)
for i in range(0,10,1):
vj.sendButtons( btn << i )
time.sleep( 1 )
vj.sendButtons(0)
vj.close()
import ctypes
import struct, time
CONST_DLL_VJOY = "C:\\Program Files\\vJoy\\x64\\vJoyInterface.dll"
class vJoy(object):
def __init__(self, reference = 1):
self.handle = None
self.dll = ctypes.CDLL( CONST_DLL_VJOY )
self.reference = reference
self.acquired = False
def open(self):
if self.dll.AcquireVJD( self.reference ):
self.acquired = True
return True
return False
def close(self):
if self.dll.RelinquishVJD( self.reference ):
self.acquired = False
return True
return False
def generateJoystickPosition(self,
wThrottle = 0, wRudder = 0, wAileron = 0,
wAxisX = 0, wAxisY = 0, wAxisZ = 0,
wAxisXRot = 0, wAxisYRot = 0, wAxisZRot = 0,
wSlider = 0, wDial = 0, wWheel = 0,
wAxisVX = 0, wAxisVY = 0, wAxisVZ = 0,
wAxisVBRX = 0, wAxisVBRY = 0, wAxisVBRZ = 0,
lButtons = 0, bHats = 0, bHatsEx1 = 0, bHatsEx2 = 0, bHatsEx3 = 0):
"""
typedef struct _JOYSTICK_POSITION
{
BYTE bDevice; // Index of device. 1-based
LONG wThrottle;
LONG wRudder;
LONG wAileron;
LONG wAxisX;
LONG wAxisY;
LONG wAxisZ;
LONG wAxisXRot;
LONG wAxisYRot;
LONG wAxisZRot;
LONG wSlider;
LONG wDial;
LONG wWheel;
LONG wAxisVX;
LONG wAxisVY;
LONG wAxisVZ;
LONG wAxisVBRX;
LONG wAxisVBRY;
LONG wAxisVBRZ;
LONG lButtons; // 32 buttons: 0x00000001 means button1 is pressed, 0x80000000 -> button32 is pressed
DWORD bHats; // Lower 4 bits: HAT switch or 16-bit of continuous HAT switch
DWORD bHatsEx1; // 16-bit of continuous HAT switch
DWORD bHatsEx2; // 16-bit of continuous HAT switch
DWORD bHatsEx3; // 16-bit of continuous HAT switch
} JOYSTICK_POSITION, *PJOYSTICK_POSITION;
"""
joyPosFormat = "BlllllllllllllllllllIIII"
pos = struct.pack( joyPosFormat, self.reference, wThrottle, wRudder,
wAileron, wAxisX, wAxisY, wAxisZ, wAxisXRot, wAxisYRot,
wAxisZRot, wSlider, wDial, wWheel, wAxisVX, wAxisVY, wAxisVZ,
wAxisVBRX, wAxisVBRY, wAxisVBRZ, lButtons, bHats, bHatsEx1, bHatsEx2, bHatsEx3 )
return pos
def update(self, joystickPosition):
if self.dll.UpdateVJD( self.reference, joystickPosition ):
return True
return False
#Not working, send buttons one by one
def sendButtons( self, bState ):
joyPosition = self.generateJoystickPosition( lButtons = bState )
return self.update( joyPosition )
def setButton( self, index, state ):
if self.dll.SetBtn( state, self.reference, index ):
return True
return False
vj = vJoy()
def test():
vj.open()
btn = 1
time.sleep(2)
for i in range(0,10,1):
vj.sendButtons( btn << i )
time.sleep( 1 )
vj.sendButtons(0)
vj.close()
@varlen
Copy link
Author

varlen commented May 10, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment