using LFS_Connection = System.Collections.Generic.List<byte>;
class LFS_Player {
byte PLID;
byte UCID;
bool inPits;
class GameData; // Something specific to your game
LFS_Player(byte PLID, byte UCID) {
this.PLID = PLID;
this.UCID = UCID;
}
void takenOver(const byte UCID) {
this.UCID = UCID;
}
void enteredPits() {
inPits = true;
}
void leftPits() {
inPits = false;
}
...
}
Dictionary<byte, LFS_Player> activePlayers;
Dictionary<byte, LFS_Connection> activeConnections;
void on_IS_NCN(ncn) {
if (activeConnections.ContainsKey(ncn.UCID)) {
// This connection is already registered, this should not happen. Throw an error
}
activeConnections[ncn.UCID] = new LFS_Connection();
}
void on_IS_NPL(npl) {
// If the PLID is already registered, player left pits
if (activePlayers.ContainsKey(npl.PLID)) {
activePlayers[npl.PLID].leftPits();
return;
}
// Register new player within the players' list
AddNewPlayer(npl.PLID, npl.UCID);
// Add PLID of the new player to the list of PLIDs belonging to the respective UCID
if (!activeConnections.ContainsKey(npl.UCID)) {
// UCID of this player is not registered. Throw an error as this cannot happen
}
activeConnections[npl.UCID].Add(npl.PLID);
}
void on_IS_PLL(pll) {
if (!activePlayers.ContainsKey(pll.PLID)) {
// Throw an error, this cannot happed
}
const byte UCID = activePlayers[pll.PLID].UCID;
RemovePlayer(pll.PLID);
RemovePLIDfromConnection(pll.PLID, UCID);
}
void on_IS_TOC(toc) {
RemovePLIDfromConnection(toc.PLID, toc.OldUCID);
if (!activePlayers.ContainsKey(toc.PLID)) {
// This should never happen, throw an error
}
activePlayers[toc.PLID].TakenOver(toc.NewUCID);
if (!activeConnections.ContainsKey(toc.NewUCID)) {
// This should never happen, throw an error
}
activeConnections[toc.NewUCID].Add(toc.PLID);
}
void on_IS_CNL(cnl) {
if (!activeConnections.ContainsKey(cnl.UCID)) {
// This should never happen, throw an error
}
const LFS_Connection c = activeConnections[cnl.UCID];
// Make sure that we do not have any players stored for this connections
foreach (byte PLID in c) {
if (activePlayers.ContainsKey(PLID)) {
// Throw a warning, all players for this connection should have been removed already
RemovePlayer(PLID);
}
}
activeConnections.Remove(cnl.UCID);
}
void AddNewPlayer(const byte PLID, const byte UCID) {
if (activePlayers.ContainsKey(PLID)) {
// Throw an error, this cannot happen
}
activePlayers[PLID] = new LFS_Player(PLID, UCID);
...
}
void RemovePlayer(byte PLID) {
if (!activePlayers.ContainsKey(PLID)) {
// Throw an error, this cannot happen
}
...
activePlayers.Remove(PLID);
}
void RemovePLIDfromConnection(byte PLID, byte UCID) {
if (!activeConnections.ContainsKey(UCID)) {
// This UCID should be registered, throw an error
}
activeConnections[UCID].Remove(PLID);
}
List<byte> GetPLIDsByUCID(const byte UCID) {
List<byte> PLIDs = new List<byte>();
foreach (KeyValuePair<byte, byte> e in Connections) {
if (e.Value == UCID) {
PLIDs.Add(e.Key);
}
}
return PLIDs;
}
Dictionary<byte, List<byte>> UCID_to_PLIDs_List;
Dictionary<byte, byte> PLID_to_UCID_List;
byte GetUCIDforPLID(const byte PLID) {
if (!PLID_to_UCID_List.ContainsKey(PLID)) /
// Throw an exception because this PLID is not known
}
return PLID_to_UCID_List[PLID];
}
List<byte> GetPLIDsOfUCID(const byte UCID) {
if (!UCID_to_PLIDs_List.ContainsKey(UCID)) {
// Throw an exception because this UCID is not known
}
return new List<byte>(UCID_to_PLIDs_List[UCID]);
}
HRESULT myIDirectInput8::CreateDevice(REFGUID a, LPDIRECTINPUTDEVICE8W *b, LPUNKNOWN c)
{
if (WantToIntercept(a)) {
LPDIRECTINPUTDEVICE8W fake;
HRESULT res = CreateFakeDIObject(&fake); // my own function
gl_myFakeObjectsStorage[FreeSlot] = fake;
*b = fake;
return hres;
}
return CreateDevice(a, b, c); // DirectInput internal function
}
HRESULT myIDirectInput8::EnumDevices(DWORD a, LPDIENUMDEVICESCALLBACKW b, LPVOID c, DWORD d)
{
m_pIDirectInput8->EnumDevices(a, MyDevEnumCallBack, c, d);
return m_pIDirectInput8->EnumDevices(a, b, c, d);
}
BOOL CALLBACK myIDirectInput8::MyDevEnumCallBack(const DIDEVICEINSTANCE* inst, VOID* context)
{
UNREFERENCED_PARAMETER(context);
/* Here is where we store the GUIDs of devices that we want to manipulate with later */
extern std::vector<GUID> gl_myG27Instance;
/* Check the device's identity */
if ((inst->guidProduct.Data1 == G27ID) /* || (inst->guidProduct.Data1 == DFPID) */) {
/* Check if we already have this device added */
if (gl_myG27Instance.size() > 20)
return DIENUM_CONTINUE;
for (std::vector<GUID>::const_iterator cit = gl_myG27Instance.begin(); cit != gl_myG27Instance.end(); cit++) {
if (IsEqualCLSID(inst->guidProduct, *cit))
return DIENUM_CONTINUE;
}
gl_myG27Instance.push_back(inst->guidInstance);
}
return DIENUM_CONTINUE;
}
HRESULT myIDirectInput8::CreateDevice(REFGUID a, LPDIRECTINPUTDEVICE8W *b, LPUNKNOWN c)
{
extern std::vector<GUID> gl_myG27Instance;
std::vector<GUID>::const_iterator cit;
for (cit = gl_myG27Instance.begin(); cit < gl_myG27Instance.end(); cit++) {
if (IsEqualCLSID(a, *cit)) {
/* A G27 (or DFP) found, take control over this device */
// global var
extern myIDirectInputDevice8* gl_pmyIDirectInputDevice8Array[];
LogMessage(L"DI::CreateDevice> Creating DIDevice");
// we intercept this call and provide our own "fake" Device Object
HRESULT hres = m_pIDirectInput8->CreateDevice(a,b,c);
/*
* Check for error
*/
// find free Device slot
int i;
for (i=0; i<MAXNUMBER_DEVICES; i++)
if (gl_pmyIDirectInputDevice8Array[i] == NULL) break;
/*
* Should return an error if i == MAXNUMBER_DEVICES
*/
// Create our own Device object and store it in global pointer
// note: the object will delete itself once Ref count is zero (similar to COM objects)
gl_pmyIDirectInputDevice8Array[i] = new myIDirectInputDevice8(*b, i, *cit);
// store our pointer (the fake one) for returning it to the calling progam
*b = gl_pmyIDirectInputDevice8Array[i];
LPOLESTR guidHash;
HRESULT guidHRes = StringFromCLSID(a, &guidHash);
if (guidHRes == S_OK) {
std::wostringstream oss;
oss << L"DI::CreateDevice> Creating DIDevice, GUID " << guidHash;
LogMessage(oss.str().c_str());
CoTaskMemFree(guidHash);
} else
LogMessage(L"(WARN)DI::CreateDevice> Unable to convert GUID to string.");
if (hres == S_OK)
LogMessage(L"DI::CreateDevice> Device sucessfully created.");
else
LogMessage(L"(WARN)DI::CreateDevice> Unable to create device.");
return(hres);
}
}
/* Not a G27 (or DFP), don't touch this device */
LogMessage(L"DI::CreateDevice> Not a G27, ignoring.");
return m_pIDirectInput8->CreateDevice(a, b, c);
}
lsusb -sX:Y -vvv | grep bcdDevice
echo xxx > /sys/module/hid_logitech/drivers/hid:logitech/*:*/range