reformat lilypad

Note: I'm worried on the EXPORT/CALLBACK behavior on multiple OS
This commit is contained in:
Clang Format 2016-09-04 14:16:34 +02:00 committed by Gregory Hainaut
parent f06f44c30a
commit d6ae5bfafa
35 changed files with 7158 additions and 6772 deletions

File diff suppressed because it is too large Load Diff

View File

@ -21,60 +21,65 @@
extern u8 ps2e; extern u8 ps2e;
enum PadType { enum PadType {
DisabledPad, DisabledPad,
Dualshock2Pad, Dualshock2Pad,
GuitarPad, GuitarPad,
PopnPad PopnPad
}; };
const int numPadTypes= 4; const int numPadTypes = 4;
extern const wchar_t *padTypes[numPadTypes]; extern const wchar_t *padTypes[numPadTypes];
struct PadConfig { struct PadConfig
PadType type; {
u8 autoAnalog; PadType type;
u8 autoAnalog;
}; };
struct GeneralConfig { struct GeneralConfig
{
public: public:
PadConfig padConfigs[2][4]; PadConfig padConfigs[2][4];
u8 closeHacks; u8 closeHacks;
DeviceAPI keyboardApi; DeviceAPI keyboardApi;
DeviceAPI mouseApi; DeviceAPI mouseApi;
// Derived value, calculated by GetInput(). // Derived value, calculated by GetInput().
u8 ignoreKeys; u8 ignoreKeys;
union { union
struct { {
u8 forceHide; struct
u8 mouseUnfocus; {
u8 background; u8 forceHide;
u8 multipleBinding; u8 mouseUnfocus;
u8 background;
u8 multipleBinding;
struct { struct
u8 directInput; {
u8 xInput; u8 directInput;
u8 dualShock3; u8 xInput;
} gameApis; u8 dualShock3;
} gameApis;
u8 multitap[2]; u8 multitap[2];
u8 escapeFullscreenHack; u8 escapeFullscreenHack;
u8 disableScreenSaver; u8 disableScreenSaver;
u8 debug; u8 debug;
u8 saveStateTitle; u8 saveStateTitle;
u8 GH2; u8 GH2;
u8 turboKeyHack; u8 turboKeyHack;
}; };
u8 bools[15]; u8 bools[15];
}; };
wchar_t lastSaveConfigPath[MAX_PATH+1]; wchar_t lastSaveConfigPath[MAX_PATH + 1];
wchar_t lastSaveConfigFileName[MAX_PATH+1]; wchar_t lastSaveConfigFileName[MAX_PATH + 1];
}; };
extern GeneralConfig config; extern GeneralConfig config;

View File

@ -33,24 +33,25 @@
#include "Linux/JoyEvdev.h" #include "Linux/JoyEvdev.h"
#endif #endif
void EnumDevices(int hideDXXinput) { void EnumDevices(int hideDXXinput)
// Needed for enumeration of some device types. {
dm->ReleaseInput(); // Needed for enumeration of some device types.
InputDeviceManager *oldDm = dm; dm->ReleaseInput();
dm = new InputDeviceManager(); InputDeviceManager *oldDm = dm;
dm = new InputDeviceManager();
#ifdef _MSC_VER #ifdef _MSC_VER
EnumWindowsMessagingDevices(); EnumWindowsMessagingDevices();
EnumRawInputDevices(); EnumRawInputDevices();
EnumDualShock3s(); EnumDualShock3s();
EnumXInputDevices(); EnumXInputDevices();
EnumDirectInputDevices(hideDXXinput); EnumDirectInputDevices(hideDXXinput);
#else #else
EnumLnx(); EnumLnx();
EnumJoystickEvdev(); EnumJoystickEvdev();
#endif #endif
dm->CopyBindings(oldDm->numDevices, oldDm->devices); dm->CopyBindings(oldDm->numDevices, oldDm->devices);
delete oldDm; delete oldDm;
} }

View File

@ -16,4 +16,3 @@
*/ */
void EnumDevices(int hideDXXinput); void EnumDevices(int hideDXXinput);

View File

@ -25,121 +25,121 @@
Device *dev; Device *dev;
INT_PTR CALLBACK DiagDialog(HWND hWnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam) { INT_PTR CALLBACK DiagDialog(HWND hWnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam)
int i; {
HWND hWndList = GetDlgItem(hWnd, IDC_LIST); int i;
static int fullRefresh; HWND hWndList = GetDlgItem(hWnd, IDC_LIST);
if (dev) { static int fullRefresh;
switch (uMsg) { if (dev) {
case WM_INITDIALOG: switch (uMsg) {
{ case WM_INITDIALOG: {
fullRefresh = 1; fullRefresh = 1;
SetWindowText(hWnd, dev->displayName); SetWindowText(hWnd, dev->displayName);
LVCOLUMNW c; LVCOLUMNW c;
c.mask = LVCF_TEXT | LVCF_WIDTH; c.mask = LVCF_TEXT | LVCF_WIDTH;
c.cx = 151; c.cx = 151;
c.pszText = L"Control"; c.pszText = L"Control";
ListView_InsertColumn(hWndList, 0, &c); ListView_InsertColumn(hWndList, 0, &c);
c.cx = 90; c.cx = 90;
c.pszText = L"Value"; c.pszText = L"Value";
ListView_InsertColumn(hWndList, 1, &c); ListView_InsertColumn(hWndList, 1, &c);
ListView_DeleteAllItems(hWndList); ListView_DeleteAllItems(hWndList);
LVITEM item; LVITEM item;
item.mask = LVIF_TEXT; item.mask = LVIF_TEXT;
item.iSubItem = 0; item.iSubItem = 0;
for (i=0; i<dev->numVirtualControls; i++) { for (i = 0; i < dev->numVirtualControls; i++) {
item.pszText = dev->GetVirtualControlName(dev->virtualControls+i); item.pszText = dev->GetVirtualControlName(dev->virtualControls + i);
item.iItem = i; item.iItem = i;
ListView_InsertItem(hWndList, &item); ListView_InsertItem(hWndList, &item);
} }
SetTimer(hWnd, 1, 200, 0); SetTimer(hWnd, 1, 200, 0);
} }
//break; //break;
case WM_TIMER: case WM_TIMER: {
{ hWndButtonProc.SetWndHandle(hWndList);
hWndButtonProc.SetWndHandle(hWndList); InitInfo info = {0, 1, hWnd, &hWndButtonProc};
InitInfo info = {0, 1, hWnd, &hWndButtonProc}; dm->Update(&info);
dm->Update(&info); LVITEMW item;
LVITEMW item; item.mask = LVIF_TEXT;
item.mask = LVIF_TEXT; item.iSubItem = 1;
item.iSubItem = 1; //ShowWindow(hWndList, 0);
//ShowWindow(hWndList, 0); //LockWindowUpdate(hWndList);
//LockWindowUpdate(hWndList); if (!dev->active) {
if (!dev->active) { item.pszText = L"?";
item.pszText = L"?"; for (i = 0; i < dev->numVirtualControls; i++) {
for (i=0; i<dev->numVirtualControls; i++) { item.iItem = i;
item.iItem = i; ListView_SetItem(hWndList, &item);
ListView_SetItem(hWndList, &item); }
} fullRefresh = 1;
fullRefresh = 1; } else {
} for (i = 0; i < dev->numVirtualControls; i++) {
else { if (fullRefresh || dev->virtualControlState[i] != dev->oldVirtualControlState[i]) {
for (i=0; i<dev->numVirtualControls; i++) {
if (fullRefresh || dev->virtualControlState[i] != dev->oldVirtualControlState[i]) {
VirtualControl *c = dev->virtualControls + i; VirtualControl *c = dev->virtualControls + i;
wchar_t temp[50]; wchar_t temp[50];
int val = dev->virtualControlState[i]; int val = dev->virtualControlState[i];
if (c->uid & (UID_POV)) { if (c->uid & (UID_POV)) {
wsprintfW(temp, L"%i", val); wsprintfW(temp, L"%i", val);
} } else {
else { wchar_t *sign = L"";
wchar_t *sign = L""; if (val < 0) {
if (val < 0) { sign = L"-";
sign = L"-"; val = -val;
val = -val; }
} if ((c->uid & UID_AXIS) && val) {
if ((c->uid& UID_AXIS) && val) { val = val;
val = val; }
} val = (int)floor(0.5 + val * 1000.0 / (double)FULLY_DOWN);
val = (int)floor(0.5 + val * 1000.0 / (double)FULLY_DOWN); wsprintfW(temp, L"%s%i.%03i", sign, val / 1000, val % 1000);
wsprintfW(temp, L"%s%i.%03i", sign, val/1000, val%1000); }
} item.pszText = temp;
item.pszText = temp; item.iItem = i;
item.iItem = i; ListView_SetItem(hWndList, &item);
ListView_SetItem(hWndList, &item); }
} }
} dm->PostRead();
dm->PostRead(); fullRefresh = 0;
fullRefresh = 0; }
} //LockWindowUpdate(0);
//LockWindowUpdate(0); //ShowWindow(hWndList, 1);
//ShowWindow(hWndList, 1); //UpdateWindow(hWnd);
//UpdateWindow(hWnd); } break;
} case WM_NOTIFY: {
break; NMLVKEYDOWN *n = (NMLVKEYDOWN *)lParam;
case WM_NOTIFY: // Don't always get the notification when testing DirectInput non-keyboard devices.
{ // Don't get it (Or want it) when testing keyboards.
NMLVKEYDOWN *n = (NMLVKEYDOWN *) lParam; if (n->hdr.idFrom != IDC_LIST || n->hdr.code != LVN_KEYDOWN || n->wVKey != VK_ESCAPE)
// Don't always get the notification when testing DirectInput non-keyboard devices. break;
// Don't get it (Or want it) when testing keyboards. }
if (n->hdr.idFrom != IDC_LIST || n->hdr.code != LVN_KEYDOWN || n->wVKey != VK_ESCAPE) break; case WM_ACTIVATE:
} if (uMsg == WM_ACTIVATE && wParam != WA_INACTIVE)
case WM_ACTIVATE: break;
if (uMsg == WM_ACTIVATE && wParam != WA_INACTIVE) break; break;
break; case WM_CLOSE:
case WM_CLOSE: KillTimer(hWnd, 1);
KillTimer(hWnd, 1); dm->ReleaseInput();
dm->ReleaseInput(); // Prevents reaching this branch again.
// Prevents reaching this branch again. dev = 0;
dev = 0; EndDialog(hWnd, 1);
EndDialog(hWnd, 1); break;
break; default:
default: break;
break; }
} }
} return 0;
return 0;
} }
void Diagnose(int id, HWND hWnd) { void Diagnose(int id, HWND hWnd)
// init = 0; {
dev = dm->devices[id]; // init = 0;
for (int i=0; i<dm->numDevices; i++) { dev = dm->devices[id];
if (i != id) dm->DisableDevice(i); for (int i = 0; i < dm->numDevices; i++) {
// Shouldn't be needed. if (i != id)
else dm->EnableDevice(i); dm->DisableDevice(i);
} // Shouldn't be needed.
DialogBox(hInst, MAKEINTRESOURCE(IDD_DIAG), hWnd, DiagDialog); else
ClearKeyQueue(); dm->EnableDevice(i);
}
DialogBox(hInst, MAKEINTRESOURCE(IDD_DIAG), hWnd, DiagDialog);
ClearKeyQueue();
} }

File diff suppressed because it is too large Load Diff

View File

@ -41,15 +41,15 @@
unsigned int lastDS3Check = 0; unsigned int lastDS3Check = 0;
unsigned int lastDS3Enum = 0; unsigned int lastDS3Enum = 0;
typedef void (__cdecl *_usb_init)(void); typedef void(__cdecl *_usb_init)(void);
typedef int (__cdecl *_usb_close)(usb_dev_handle *dev); typedef int(__cdecl *_usb_close)(usb_dev_handle *dev);
typedef int (__cdecl *_usb_get_string_simple)(usb_dev_handle *dev, int index, char *buf, size_t buflen); typedef int(__cdecl *_usb_get_string_simple)(usb_dev_handle *dev, int index, char *buf, size_t buflen);
typedef usb_dev_handle *(__cdecl *_usb_open)(struct usb_device *dev); typedef usb_dev_handle *(__cdecl *_usb_open)(struct usb_device *dev);
typedef int (__cdecl *_usb_find_busses)(void); typedef int(__cdecl *_usb_find_busses)(void);
typedef int (__cdecl *_usb_find_devices)(void); typedef int(__cdecl *_usb_find_devices)(void);
typedef struct usb_bus *(__cdecl *_usb_get_busses)(void); typedef struct usb_bus *(__cdecl *_usb_get_busses)(void);
typedef usb_dev_handle *(__cdecl *_usb_open)(struct usb_device *dev); typedef usb_dev_handle *(__cdecl *_usb_open)(struct usb_device *dev);
typedef int (__cdecl *_usb_control_msg)(usb_dev_handle *dev, int requesttype, int request, int value, int index, char *bytes, int size, int timeout); typedef int(__cdecl *_usb_control_msg)(usb_dev_handle *dev, int requesttype, int request, int value, int index, char *bytes, int size, int timeout);
_usb_init pusb_init; _usb_init pusb_init;
_usb_close pusb_close; _usb_close pusb_close;
@ -62,408 +62,435 @@ _usb_control_msg pusb_control_msg;
HMODULE hModLibusb = 0; HMODULE hModLibusb = 0;
void UninitLibUsb() { void UninitLibUsb()
if (hModLibusb) { {
FreeLibrary(hModLibusb); if (hModLibusb) {
hModLibusb = 0; FreeLibrary(hModLibusb);
} hModLibusb = 0;
}
} }
void TryInitDS3(usb_device *dev) { void TryInitDS3(usb_device *dev)
while (dev) { {
if (dev->descriptor.idVendor == VID && dev->descriptor.idProduct == PID) { while (dev) {
usb_dev_handle *handle = pusb_open(dev); if (dev->descriptor.idVendor == VID && dev->descriptor.idProduct == PID) {
if (handle) { usb_dev_handle *handle = pusb_open(dev);
char junk[20]; if (handle) {
// This looks like HidD_GetFeature with a feature report id of 0xF2 to me and a length of 17. char junk[20];
// That doesn't work, however, and 17 is shorter than the report length. // This looks like HidD_GetFeature with a feature report id of 0xF2 to me and a length of 17.
pusb_control_msg(handle, 0xa1, 1, 0x03f2, dev->config->interface->altsetting->bInterfaceNumber, junk, 17, 1000); // That doesn't work, however, and 17 is shorter than the report length.
pusb_close(handle); pusb_control_msg(handle, 0xa1, 1, 0x03f2, dev->config->interface->altsetting->bInterfaceNumber, junk, 17, 1000);
} pusb_close(handle);
} }
if (dev->num_children) { }
for (int i=0; i<dev->num_children; i++) { if (dev->num_children) {
TryInitDS3(dev->children[i]); for (int i = 0; i < dev->num_children; i++) {
} TryInitDS3(dev->children[i]);
} }
dev = dev->next; }
} dev = dev->next;
}
} }
void DS3Enum(unsigned int time) { void DS3Enum(unsigned int time)
if (time - lastDS3Enum < DOUBLE_ENUM_DELAY) { {
return; if (time - lastDS3Enum < DOUBLE_ENUM_DELAY) {
} return;
lastDS3Enum = time; }
pusb_find_busses(); lastDS3Enum = time;
pusb_find_devices(); pusb_find_busses();
pusb_find_devices();
} }
void DS3Check(unsigned int time) { void DS3Check(unsigned int time)
if (time - lastDS3Check < DOUBLE_CHECK_DELAY) { {
return; if (time - lastDS3Check < DOUBLE_CHECK_DELAY) {
} return;
if (!lastDS3Check) { }
DS3Enum(time); if (!lastDS3Check) {
} DS3Enum(time);
lastDS3Check = time; }
lastDS3Check = time;
usb_bus *bus = pusb_get_busses(); usb_bus *bus = pusb_get_busses();
while (bus) { while (bus) {
TryInitDS3(bus->devices); TryInitDS3(bus->devices);
bus = bus->next; bus = bus->next;
} }
} }
int InitLibUsb() { int InitLibUsb()
if (hModLibusb) { {
return 1; if (hModLibusb) {
} return 1;
hModLibusb = LoadLibraryA("C:\\windows\\system32\\libusb0.dll"); }
if (hModLibusb) { hModLibusb = LoadLibraryA("C:\\windows\\system32\\libusb0.dll");
if ((pusb_init = (_usb_init) GetProcAddress(hModLibusb, "usb_init")) && if (hModLibusb) {
(pusb_close = (_usb_close) GetProcAddress(hModLibusb, "usb_close")) && if ((pusb_init = (_usb_init)GetProcAddress(hModLibusb, "usb_init")) &&
(pusb_get_string_simple = (_usb_get_string_simple) GetProcAddress(hModLibusb, "usb_get_string_simple")) && (pusb_close = (_usb_close)GetProcAddress(hModLibusb, "usb_close")) &&
(pusb_open = (_usb_open) GetProcAddress(hModLibusb, "usb_open")) && (pusb_get_string_simple = (_usb_get_string_simple)GetProcAddress(hModLibusb, "usb_get_string_simple")) &&
(pusb_find_busses = (_usb_find_busses) GetProcAddress(hModLibusb, "usb_find_busses")) && (pusb_open = (_usb_open)GetProcAddress(hModLibusb, "usb_open")) &&
(pusb_find_devices = (_usb_find_devices) GetProcAddress(hModLibusb, "usb_find_devices")) && (pusb_find_busses = (_usb_find_busses)GetProcAddress(hModLibusb, "usb_find_busses")) &&
(pusb_get_busses = (_usb_get_busses) GetProcAddress(hModLibusb, "usb_get_busses")) && (pusb_find_devices = (_usb_find_devices)GetProcAddress(hModLibusb, "usb_find_devices")) &&
(pusb_control_msg = (_usb_control_msg) GetProcAddress(hModLibusb, "usb_control_msg"))) { (pusb_get_busses = (_usb_get_busses)GetProcAddress(hModLibusb, "usb_get_busses")) &&
pusb_init(); (pusb_control_msg = (_usb_control_msg)GetProcAddress(hModLibusb, "usb_control_msg"))) {
return 1; pusb_init();
} return 1;
UninitLibUsb(); }
} UninitLibUsb();
return 0; }
return 0;
} }
int DualShock3Possible() { int DualShock3Possible()
return InitLibUsb(); {
return InitLibUsb();
} }
#include <pshpack1.h> #include <pshpack1.h>
struct MotorState { struct MotorState
unsigned char duration; {
unsigned char force; unsigned char duration;
unsigned char force;
}; };
struct LightState { struct LightState
// 0xFF makes it stay on. {
unsigned char duration; // 0xFF makes it stay on.
// Have to make one or the other non-zero to turn on light. unsigned char duration;
unsigned char dunno[2]; // Have to make one or the other non-zero to turn on light.
// 0 is fully lit. unsigned char dunno[2];
unsigned char dimness; // 0 is fully lit.
// Have to make non-zero to turn on light. unsigned char dimness;
unsigned char on; // Have to make non-zero to turn on light.
unsigned char on;
}; };
// Data sent to DS3 to set state. // Data sent to DS3 to set state.
struct DS3Command { struct DS3Command
unsigned char id; {
unsigned char unsure; unsigned char id;
// Small is first, then big. unsigned char unsure;
MotorState motors[2]; // Small is first, then big.
unsigned char noClue[4]; MotorState motors[2];
// 2 is pad 1 light, 4 is pad 2, 8 is pad 3, 16 is pad 4. No clue about the others. unsigned char noClue[4];
unsigned char lightFlags; // 2 is pad 1 light, 4 is pad 2, 8 is pad 3, 16 is pad 4. No clue about the others.
// Lights are in reverse order. pad 1 is last. unsigned char lightFlags;
LightState lights[4]; // Lights are in reverse order. pad 1 is last.
unsigned char dunno[18]; LightState lights[4];
unsigned char dunno[18];
}; };
#include <poppack.h> #include <poppack.h>
int CharToAxis(unsigned char c) { int CharToAxis(unsigned char c)
int v = (int)c + ((unsigned int)c >> 7); {
return ((c-128) * FULLY_DOWN)>>7; int v = (int)c + ((unsigned int)c >> 7);
return ((c - 128) * FULLY_DOWN) >> 7;
} }
int CharToButton(unsigned char c) { int CharToButton(unsigned char c)
int v = (int)c + ((unsigned int)c >> 7); {
return (v * FULLY_DOWN)>>8; int v = (int)c + ((unsigned int)c >> 7);
return (v * FULLY_DOWN) >> 8;
} }
class DualShock3Device : public Device { class DualShock3Device : public Device
// Cached last vibration values by pad and motor. {
// Need this, as only one value is changed at a time. // Cached last vibration values by pad and motor.
int ps2Vibration[2][4][2]; // Need this, as only one value is changed at a time.
int vibration[2]; int ps2Vibration[2][4][2];
int vibration[2];
public: public:
int index; int index;
HANDLE hFile; HANDLE hFile;
DS3Command sendState; DS3Command sendState;
unsigned char getState[49]; unsigned char getState[49];
OVERLAPPED readop; OVERLAPPED readop;
OVERLAPPED writeop; OVERLAPPED writeop;
int writeCount; int writeCount;
int lastWrite; int lastWrite;
unsigned int dataLastReceived; unsigned int dataLastReceived;
int writeQueued; int writeQueued;
int writing; int writing;
int StartRead() { int StartRead()
int res = ReadFile(hFile, &getState, sizeof(getState), 0, &readop); {
return (res || GetLastError() == ERROR_IO_PENDING); int res = ReadFile(hFile, &getState, sizeof(getState), 0, &readop);
} return (res || GetLastError() == ERROR_IO_PENDING);
}
void QueueWrite() { void QueueWrite()
// max of 2 queued writes allowed, one for either motor. {
if (writeQueued < 2) { // max of 2 queued writes allowed, one for either motor.
writeQueued++; if (writeQueued < 2) {
StartWrite(); writeQueued++;
} StartWrite();
} }
}
int StartWrite() { int StartWrite()
if (!writing && writeQueued) { {
lastWrite = GetTickCount(); if (!writing && writeQueued) {
writing++; lastWrite = GetTickCount();
writeQueued--; writing++;
sendState.motors[0].duration = 0x50; writeQueued--;
sendState.motors[1].duration = 0x50; sendState.motors[0].duration = 0x50;
sendState.motors[1].duration = 0x50;
int bigForce = vibration[0] * 256/FULLY_DOWN; int bigForce = vibration[0] * 256 / FULLY_DOWN;
if (bigForce > 255) bigForce = 255; if (bigForce > 255)
sendState.motors[1].force = (unsigned char) bigForce; bigForce = 255;
sendState.motors[0].force = (unsigned char) (vibration[1] >= FULLY_DOWN/2); sendState.motors[1].force = (unsigned char)bigForce;
// Can't seem to have them both non-zero at once. sendState.motors[0].force = (unsigned char)(vibration[1] >= FULLY_DOWN / 2);
if (sendState.motors[writeCount&1].force) { // Can't seem to have them both non-zero at once.
sendState.motors[(writeCount&1)^1].force = 0; if (sendState.motors[writeCount & 1].force) {
sendState.motors[(writeCount&1)^1].duration = 0; sendState.motors[(writeCount & 1) ^ 1].force = 0;
} sendState.motors[(writeCount & 1) ^ 1].duration = 0;
}
writeCount++; writeCount++;
int res = WriteFile(hFile, &sendState, sizeof(sendState), 0, &writeop); int res = WriteFile(hFile, &sendState, sizeof(sendState), 0, &writeop);
return (res || GetLastError() == ERROR_IO_PENDING); return (res || GetLastError() == ERROR_IO_PENDING);
} }
return 1; return 1;
} }
DualShock3Device(int index, wchar_t *name, wchar_t *path) : Device(DS3, OTHER, name, path, L"DualShock 3") { DualShock3Device(int index, wchar_t *name, wchar_t *path)
writeCount = 0; : Device(DS3, OTHER, name, path, L"DualShock 3")
writing = 0; {
writeQueued = 0; writeCount = 0;
memset(&readop, 0, sizeof(readop)); writing = 0;
memset(&writeop, 0, sizeof(writeop)); writeQueued = 0;
memset(&sendState, 0, sizeof(sendState)); memset(&readop, 0, sizeof(readop));
sendState.id = 1; memset(&writeop, 0, sizeof(writeop));
int temp = (index&4); memset(&sendState, 0, sizeof(sendState));
sendState.lightFlags = (1 << (temp+1)); sendState.id = 1;
sendState.lights[3-temp].duration = 0xFF; int temp = (index & 4);
sendState.lights[3-temp].dunno[0] = 1; sendState.lightFlags = (1 << (temp + 1));
sendState.lights[3-temp].on = 1; sendState.lights[3 - temp].duration = 0xFF;
memset(ps2Vibration, 0, sizeof(ps2Vibration)); sendState.lights[3 - temp].dunno[0] = 1;
vibration[0] = vibration[1] = 0; sendState.lights[3 - temp].on = 1;
this->index = index; memset(ps2Vibration, 0, sizeof(ps2Vibration));
int i; vibration[0] = vibration[1] = 0;
for (i=0; i<16; i++) { this->index = index;
if (i != 14 && i != 15 && i != 8 && i != 9) { int i;
AddPhysicalControl(PRESSURE_BTN, i, 0); for (i = 0; i < 16; i++) {
} if (i != 14 && i != 15 && i != 8 && i != 9) {
else { AddPhysicalControl(PRESSURE_BTN, i, 0);
AddPhysicalControl(PSHBTN, i, 0); } else {
} AddPhysicalControl(PSHBTN, i, 0);
} }
for (; i<23; i++) { }
AddPhysicalControl(ABSAXIS, i, 0); for (; i < 23; i++) {
} AddPhysicalControl(ABSAXIS, i, 0);
AddFFAxis(L"Big Motor", 0); }
AddFFAxis(L"Small Motor", 1); AddFFAxis(L"Big Motor", 0);
AddFFEffectType(L"Constant Effect", L"Constant", EFFECT_CONSTANT); AddFFAxis(L"Small Motor", 1);
hFile = INVALID_HANDLE_VALUE; AddFFEffectType(L"Constant Effect", L"Constant", EFFECT_CONSTANT);
} hFile = INVALID_HANDLE_VALUE;
}
wchar_t *GetPhysicalControlName(PhysicalControl *c) { wchar_t *GetPhysicalControlName(PhysicalControl *c)
const static wchar_t *names[] = { {
L"Square", const static wchar_t *names[] = {
L"Cross", L"Square",
L"Circle", L"Cross",
L"Triangle", L"Circle",
L"R1", L"Triangle",
L"L1", L"R1",
L"R2", L"L1",
L"L2", L"R2",
L"R3", L"L2",
L"L3", L"R3",
L"Left", L"L3",
L"Down", L"Left",
L"Right", L"Down",
L"Up", L"Right",
L"Start", L"Up",
L"Select", L"Start",
L"L-Stick X", L"Select",
L"L-Stick Y", L"L-Stick X",
L"R-Stick X", L"L-Stick Y",
L"R-Stick Y", L"R-Stick X",
L"Left/Right Tilt", L"R-Stick Y",
L"Forward/Back Tilt", L"Left/Right Tilt",
L"???", L"Forward/Back Tilt",
}; L"???",
unsigned int i = (unsigned int) (c - physicalControls); };
if (i < sizeof(names)/sizeof(names[0])) { unsigned int i = (unsigned int)(c - physicalControls);
return (wchar_t*)names[i]; if (i < sizeof(names) / sizeof(names[0])) {
} return (wchar_t *)names[i];
return Device::GetPhysicalControlName(c); }
} return Device::GetPhysicalControlName(c);
}
int Activate(InitInfo *initInfo) { int Activate(InitInfo *initInfo)
if (active) Deactivate(); {
// Give grace period before get mad. if (active)
lastWrite = dataLastReceived = GetTickCount(); Deactivate();
readop.hEvent = CreateEvent(0, 0, 0, 0); // Give grace period before get mad.
writeop.hEvent = CreateEvent(0, 0, 0, 0); lastWrite = dataLastReceived = GetTickCount();
hFile = CreateFileW(instanceID, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); readop.hEvent = CreateEvent(0, 0, 0, 0);
if (!readop.hEvent || !writeop.hEvent || hFile == INVALID_HANDLE_VALUE || writeop.hEvent = CreateEvent(0, 0, 0, 0);
!StartRead()) { hFile = CreateFileW(instanceID, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
Deactivate(); if (!readop.hEvent || !writeop.hEvent || hFile == INVALID_HANDLE_VALUE ||
return 0; !StartRead()) {
} Deactivate();
active = 1; return 0;
AllocState(); }
return 1; active = 1;
} AllocState();
return 1;
}
int Update() { int Update()
if (!active) return 0; {
HANDLE h[2] = { if (!active)
readop.hEvent, return 0;
writeop.hEvent HANDLE h[2] = {
}; readop.hEvent,
unsigned int time = GetTickCount(); writeop.hEvent};
if (time - lastWrite > UPDATE_INTERVAL) { unsigned int time = GetTickCount();
QueueWrite(); if (time - lastWrite > UPDATE_INTERVAL) {
} QueueWrite();
while (1) { }
DWORD res = WaitForMultipleObjects(2, h, 0, 0); while (1) {
if (res == WAIT_OBJECT_0) { DWORD res = WaitForMultipleObjects(2, h, 0, 0);
dataLastReceived = time; if (res == WAIT_OBJECT_0) {
if (!StartRead()) { dataLastReceived = time;
Deactivate(); if (!StartRead()) {
return 0; Deactivate();
} return 0;
}
physicalControlState[0] = CharToButton(getState[25]); physicalControlState[0] = CharToButton(getState[25]);
physicalControlState[1] = CharToButton(getState[24]); physicalControlState[1] = CharToButton(getState[24]);
physicalControlState[2] = CharToButton(getState[23]); physicalControlState[2] = CharToButton(getState[23]);
physicalControlState[3] = CharToButton(getState[22]); physicalControlState[3] = CharToButton(getState[22]);
physicalControlState[4] = CharToButton(getState[21]); physicalControlState[4] = CharToButton(getState[21]);
physicalControlState[5] = CharToButton(getState[20]); physicalControlState[5] = CharToButton(getState[20]);
physicalControlState[6] = CharToButton(getState[19]); physicalControlState[6] = CharToButton(getState[19]);
physicalControlState[7] = CharToButton(getState[18]); physicalControlState[7] = CharToButton(getState[18]);
physicalControlState[10] = CharToButton(getState[17]); physicalControlState[10] = CharToButton(getState[17]);
physicalControlState[11] = CharToButton(getState[16]); physicalControlState[11] = CharToButton(getState[16]);
physicalControlState[12] = CharToButton(getState[15]); physicalControlState[12] = CharToButton(getState[15]);
physicalControlState[13] = CharToButton(getState[14]); physicalControlState[13] = CharToButton(getState[14]);
physicalControlState[8] = ((getState[2]&4)/4) * FULLY_DOWN; physicalControlState[8] = ((getState[2] & 4) / 4) * FULLY_DOWN;
physicalControlState[9] = ((getState[2]&2)/2) * FULLY_DOWN; physicalControlState[9] = ((getState[2] & 2) / 2) * FULLY_DOWN;
physicalControlState[15] = ((getState[2]&1)/1) * FULLY_DOWN; physicalControlState[15] = ((getState[2] & 1) / 1) * FULLY_DOWN;
physicalControlState[14] = ((getState[2]&8)/8) * FULLY_DOWN; physicalControlState[14] = ((getState[2] & 8) / 8) * FULLY_DOWN;
physicalControlState[16] = CharToAxis(getState[6]); physicalControlState[16] = CharToAxis(getState[6]);
physicalControlState[17] = CharToAxis(getState[7]); physicalControlState[17] = CharToAxis(getState[7]);
physicalControlState[18] = CharToAxis(getState[8]); physicalControlState[18] = CharToAxis(getState[8]);
physicalControlState[19] = CharToAxis(getState[9]); physicalControlState[19] = CharToAxis(getState[9]);
physicalControlState[20] = CharToAxis(getState[42]+128); physicalControlState[20] = CharToAxis(getState[42] + 128);
physicalControlState[21] = CharToAxis(getState[44]+128); physicalControlState[21] = CharToAxis(getState[44] + 128);
physicalControlState[22] = CharToAxis(getState[46]+128); physicalControlState[22] = CharToAxis(getState[46] + 128);
continue; continue;
} } else if (res == WAIT_OBJECT_0 + 1) {
else if (res == WAIT_OBJECT_0+1) { writing = 0;
writing = 0; if (!writeQueued && (vibration[0] | vibration[1])) {
if (!writeQueued && (vibration[0] | vibration[1])) { QueueWrite();
QueueWrite(); }
} if (!StartWrite()) {
if (!StartWrite()) { Deactivate();
Deactivate(); return 0;
return 0; }
} } else {
} if (time - dataLastReceived >= DEVICE_CHECK_DELAY) {
else { if (time - dataLastReceived >= DEVICE_ENUM_DELAY) {
if (time-dataLastReceived >= DEVICE_CHECK_DELAY) { DS3Enum(time);
if (time-dataLastReceived >= DEVICE_ENUM_DELAY) { }
DS3Enum(time); DS3Check(time);
} QueueWrite();
DS3Check(time); }
QueueWrite(); }
} break;
} }
break; return 1;
} }
return 1;
}
void SetEffects(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force) { void SetEffects(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force)
ps2Vibration[port][slot][motor] = force; {
vibration[0] = vibration[1] = 0; ps2Vibration[port][slot][motor] = force;
for (int p=0; p<2; p++) { vibration[0] = vibration[1] = 0;
for (int s=0; s<4; s++) { for (int p = 0; p < 2; p++) {
for (int i=0; i<pads[p][s].numFFBindings; i++) { for (int s = 0; s < 4; s++) {
// Technically should also be a *65535/BASE_SENSITIVITY, but that's close enough to 1 for me. for (int i = 0; i < pads[p][s].numFFBindings; i++) {
ForceFeedbackBinding *ffb = &pads[p][s].ffBindings[i]; // Technically should also be a *65535/BASE_SENSITIVITY, but that's close enough to 1 for me.
vibration[0] += (int)((ffb->axes[0].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255); ForceFeedbackBinding *ffb = &pads[p][s].ffBindings[i];
vibration[1] += (int)((ffb->axes[1].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255); vibration[0] += (int)((ffb->axes[0].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255);
} vibration[1] += (int)((ffb->axes[1].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255);
} }
} }
// Make sure at least 2 writes are queued, to update both motors. }
QueueWrite(); // Make sure at least 2 writes are queued, to update both motors.
QueueWrite(); QueueWrite();
} QueueWrite();
}
void SetEffect(ForceFeedbackBinding *binding, unsigned char force) { void SetEffect(ForceFeedbackBinding *binding, unsigned char force)
PadBindings pBackup = pads[0][0]; {
pads[0][0].ffBindings = binding; PadBindings pBackup = pads[0][0];
pads[0][0].numFFBindings = 1; pads[0][0].ffBindings = binding;
SetEffects(0, 0, binding->motor, 255); pads[0][0].numFFBindings = 1;
pads[0][0] = pBackup; SetEffects(0, 0, binding->motor, 255);
} pads[0][0] = pBackup;
}
void Deactivate() { void Deactivate()
if (hFile != INVALID_HANDLE_VALUE) { {
CancelIo(hFile); if (hFile != INVALID_HANDLE_VALUE) {
CloseHandle(hFile); CancelIo(hFile);
hFile = INVALID_HANDLE_VALUE; CloseHandle(hFile);
} hFile = INVALID_HANDLE_VALUE;
if (readop.hEvent) { }
CloseHandle(readop.hEvent); if (readop.hEvent) {
} CloseHandle(readop.hEvent);
if (writeop.hEvent) { }
CloseHandle(writeop.hEvent); if (writeop.hEvent) {
} CloseHandle(writeop.hEvent);
writing = 0; }
writeQueued = 0; writing = 0;
memset(ps2Vibration, 0, sizeof(ps2Vibration)); writeQueued = 0;
vibration[0] = vibration[1] = 0; memset(ps2Vibration, 0, sizeof(ps2Vibration));
vibration[0] = vibration[1] = 0;
FreeState(); FreeState();
active = 0; active = 0;
} }
~DualShock3Device() { ~DualShock3Device()
} {
}
}; };
void EnumDualShock3s() { void EnumDualShock3s()
if (!InitLibUsb()) return; {
if (!InitLibUsb())
return;
HidDeviceInfo *foundDevs = 0; HidDeviceInfo *foundDevs = 0;
int numDevs = FindHids(&foundDevs, VID, PID); int numDevs = FindHids(&foundDevs, VID, PID);
if (!numDevs) return; if (!numDevs)
int index = 0; return;
for (int i=0; i<numDevs; i++) { int index = 0;
if (foundDevs[i].caps.FeatureReportByteLength == 49 && for (int i = 0; i < numDevs; i++) {
foundDevs[i].caps.InputReportByteLength == 49 && if (foundDevs[i].caps.FeatureReportByteLength == 49 &&
foundDevs[i].caps.OutputReportByteLength == 49) { foundDevs[i].caps.InputReportByteLength == 49 &&
wchar_t temp[100]; foundDevs[i].caps.OutputReportByteLength == 49) {
wsprintfW(temp, L"DualShock 3 #%i", index+1); wchar_t temp[100];
dm->AddDevice(new DualShock3Device(index, temp, foundDevs[i].path)); wsprintfW(temp, L"DualShock 3 #%i", index + 1);
index++; dm->AddDevice(new DualShock3Device(index, temp, foundDevs[i].path));
} index++;
free(foundDevs[i].path); }
} free(foundDevs[i].path);
free(foundDevs); }
free(foundDevs);
} }

View File

@ -23,58 +23,62 @@
typedef uint32_t DWORD; typedef uint32_t DWORD;
typedef uint16_t USHORT; typedef uint16_t USHORT;
#ifndef __INTEL_COMPILER #ifndef __INTEL_COMPILER
typedef int64_t __int64; typedef int64_t __int64;
#endif #endif
#define MAX_PATH (256) // random value #define MAX_PATH (256) // random value
#include <X11/keysym.h> #include <X11/keysym.h>
#define VK_SHIFT XK_Shift_L #define VK_SHIFT XK_Shift_L
#define VK_LSHIFT XK_Shift_L #define VK_LSHIFT XK_Shift_L
#define VK_RSHIFT XK_Shift_R #define VK_RSHIFT XK_Shift_R
#define VK_LMENU XK_Menu #define VK_LMENU XK_Menu
#define VK_RMENU XK_Menu #define VK_RMENU XK_Menu
#define VK_MENU XK_Menu #define VK_MENU XK_Menu
#define VK_CONTROL XK_Control_L #define VK_CONTROL XK_Control_L
#define VK_TAB XK_Tab #define VK_TAB XK_Tab
#define VK_ESCAPE XK_Escape #define VK_ESCAPE XK_Escape
#define VK_F4 XK_F4 #define VK_F4 XK_F4
#include <cwchar> #include <cwchar>
#include <cstdarg> #include <cstdarg>
template <typename Array> template <typename Array>
void wsprintfW(Array& buf, const wchar_t *format, ...) { void wsprintfW(Array &buf, const wchar_t *format, ...)
va_list a; {
va_start(a, format); va_list a;
va_start(a, format);
vswprintf(buf, sizeof(buf)/sizeof(buf[0]), format, a); vswprintf(buf, sizeof(buf) / sizeof(buf[0]), format, a);
va_end(a); va_end(a);
} }
template <typename Array> template <typename Array>
void wsprintf(Array& buf, const wchar_t *format, ...) { void wsprintf(Array &buf, const wchar_t *format, ...)
va_list a; {
va_start(a, format); va_list a;
va_start(a, format);
vswprintf(buf, sizeof(buf)/sizeof(buf[0]), format, a); vswprintf(buf, sizeof(buf) / sizeof(buf[0]), format, a);
va_end(a); va_end(a);
} }
static inline int wcsicmp(const wchar_t* w1, const wchar_t* w2) { static inline int wcsicmp(const wchar_t *w1, const wchar_t *w2)
// I didn't find a way to put ignore case ... {
return wcscmp(w1, w2); // I didn't find a way to put ignore case ...
return wcscmp(w1, w2);
} }
#include <sys/time.h> #include <sys/time.h>
static inline unsigned int timeGetTime() { static inline unsigned int timeGetTime()
struct timeval now; {
gettimeofday(&now, NULL); struct timeval now;
uint64_t ms = (now.tv_usec/1000) + ((uint64_t)now.tv_sec * 1000); gettimeofday(&now, NULL);
return (ms & 0xFFFFFFFF); // MS code is u32 ... uint64_t ms = (now.tv_usec / 1000) + ((uint64_t)now.tv_sec * 1000);
return (ms & 0xFFFFFFFF); // MS code is u32 ...
} }
#include "Utilities/Dependencies.h" #include "Utilities/Dependencies.h"
@ -84,7 +88,7 @@ static inline unsigned int timeGetTime() {
#include <X11/Xutil.h> #include <X11/Xutil.h>
extern Display *GSdsp; extern Display *GSdsp;
extern Window GSwin; extern Window GSwin;
#endif #endif
@ -95,7 +99,7 @@ extern Window GSwin;
#ifdef _MSC_VER #ifdef _MSC_VER
#define EXPORT_C_(type) extern "C" type CALLBACK #define EXPORT_C_(type) extern "C" type CALLBACK
#else #else
#define EXPORT_C_(type) extern "C" __attribute__((stdcall,externally_visible,visibility("default"))) type CALLBACK #define EXPORT_C_(type) extern "C" __attribute__((stdcall, externally_visible, visibility("default"))) type CALLBACK
#endif #endif
#ifdef _MSC_VER #ifdef _MSC_VER
@ -136,35 +140,60 @@ extern HINSTANCE hInst;
// Needed for config screen // Needed for config screen
void GetNameAndVersionString(wchar_t *out); void GetNameAndVersionString(wchar_t *out);
typedef struct { typedef struct
unsigned char controllerType; {
unsigned short buttonStatus; unsigned char controllerType;
unsigned char rightJoyX, rightJoyY, leftJoyX, leftJoyY; unsigned short buttonStatus;
unsigned char moveX, moveY; unsigned char rightJoyX, rightJoyY, leftJoyX, leftJoyY;
unsigned char reserved[91]; unsigned char moveX, moveY;
unsigned char reserved[91];
} PadDataS; } PadDataS;
EXPORT_C_(void) PADupdate(int pad); EXPORT_C_(void)
EXPORT_C_(u32) PS2EgetLibType(void); PADupdate(int pad);
EXPORT_C_(u32) PS2EgetLibVersion2(u32 type); EXPORT_C_(u32)
EXPORT_C_(char*) PSEgetLibName(); PS2EgetLibType(void);
EXPORT_C_(char*) PS2EgetLibName(void); EXPORT_C_(u32)
EXPORT_C_(void) PADshutdown(); PS2EgetLibVersion2(u32 type);
EXPORT_C_(s32) PADinit(u32 flags); EXPORT_C_(char *)
EXPORT_C_(s32) PADopen(void *pDsp); PSEgetLibName();
EXPORT_C_(void) PADclose(); EXPORT_C_(char *)
EXPORT_C_(u8) PADstartPoll(int pad); PS2EgetLibName(void);
EXPORT_C_(u8) PADpoll(u8 value); EXPORT_C_(void)
EXPORT_C_(u32) PADquery(); PADshutdown();
EXPORT_C_(void) PADabout(); EXPORT_C_(s32)
EXPORT_C_(s32) PADtest(); PADinit(u32 flags);
EXPORT_C_(keyEvent*) PADkeyEvent(); EXPORT_C_(s32)
EXPORT_C_(u32) PADreadPort1 (PadDataS* pads); PADopen(void *pDsp);
EXPORT_C_(u32) PADreadPort2 (PadDataS* pads); EXPORT_C_(void)
EXPORT_C_(u32) PSEgetLibType(); PADclose();
EXPORT_C_(u32) PSEgetLibVersion(); EXPORT_C_(u8)
EXPORT_C_(void) PADconfigure(); PADstartPoll(int pad);
EXPORT_C_(s32) PADfreeze(int mode, freezeData *data); EXPORT_C_(u8)
EXPORT_C_(s32) PADsetSlot(u8 port, u8 slot); PADpoll(u8 value);
EXPORT_C_(s32) PADqueryMtap(u8 port); EXPORT_C_(u32)
EXPORT_C_(void) PADsetSettingsDir(const char *dir); PADquery();
EXPORT_C_(void)
PADabout();
EXPORT_C_(s32)
PADtest();
EXPORT_C_(keyEvent *)
PADkeyEvent();
EXPORT_C_(u32)
PADreadPort1(PadDataS *pads);
EXPORT_C_(u32)
PADreadPort2(PadDataS *pads);
EXPORT_C_(u32)
PSEgetLibType();
EXPORT_C_(u32)
PSEgetLibVersion();
EXPORT_C_(void)
PADconfigure();
EXPORT_C_(s32)
PADfreeze(int mode, freezeData *data);
EXPORT_C_(s32)
PADsetSlot(u8 port, u8 slot);
EXPORT_C_(s32)
PADqueryMtap(u8 port);
EXPORT_C_(void)
PADsetSettingsDir(const char *dir);

View File

@ -20,57 +20,61 @@
#include <setupapi.h> #include <setupapi.h>
#include <hidsdi.h> #include <hidsdi.h>
int FindHids(HidDeviceInfo **foundDevs, int vid, int pid) { int FindHids(HidDeviceInfo **foundDevs, int vid, int pid)
GUID GUID_DEVINTERFACE_HID; {
int numFoundDevs = 0; GUID GUID_DEVINTERFACE_HID;
*foundDevs = 0; int numFoundDevs = 0;
HidD_GetHidGuid(&GUID_DEVINTERFACE_HID); *foundDevs = 0;
HDEVINFO hdev = SetupDiGetClassDevs(&GUID_DEVINTERFACE_HID, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); HidD_GetHidGuid(&GUID_DEVINTERFACE_HID);
if (hdev != INVALID_HANDLE_VALUE) { HDEVINFO hdev = SetupDiGetClassDevs(&GUID_DEVINTERFACE_HID, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
SP_DEVICE_INTERFACE_DATA devInterfaceData; if (hdev != INVALID_HANDLE_VALUE) {
devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); SP_DEVICE_INTERFACE_DATA devInterfaceData;
for (int i=0; SetupDiEnumDeviceInterfaces(hdev, 0, &GUID_DEVINTERFACE_HID, i, &devInterfaceData); i++) { devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
for (int i = 0; SetupDiEnumDeviceInterfaces(hdev, 0, &GUID_DEVINTERFACE_HID, i, &devInterfaceData); i++) {
DWORD size = 0; DWORD size = 0;
SetupDiGetDeviceInterfaceDetail(hdev, &devInterfaceData, 0, 0, &size, 0); SetupDiGetDeviceInterfaceDetail(hdev, &devInterfaceData, 0, 0, &size, 0);
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER || !size) continue; if (GetLastError() != ERROR_INSUFFICIENT_BUFFER || !size)
SP_DEVICE_INTERFACE_DETAIL_DATA *devInterfaceDetails = (SP_DEVICE_INTERFACE_DETAIL_DATA *) malloc(size); continue;
if (!devInterfaceDetails) continue; SP_DEVICE_INTERFACE_DETAIL_DATA *devInterfaceDetails = (SP_DEVICE_INTERFACE_DETAIL_DATA *)malloc(size);
if (!devInterfaceDetails)
continue;
devInterfaceDetails->cbSize = sizeof(*devInterfaceDetails); devInterfaceDetails->cbSize = sizeof(*devInterfaceDetails);
SP_DEVINFO_DATA devInfoData; SP_DEVINFO_DATA devInfoData;
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
if (!SetupDiGetDeviceInterfaceDetail(hdev, &devInterfaceData, devInterfaceDetails, size, &size, &devInfoData)) continue; if (!SetupDiGetDeviceInterfaceDetail(hdev, &devInterfaceData, devInterfaceDetails, size, &size, &devInfoData))
continue;
HANDLE hfile = CreateFile(devInterfaceDetails->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); HANDLE hfile = CreateFile(devInterfaceDetails->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
if (hfile != INVALID_HANDLE_VALUE) { if (hfile != INVALID_HANDLE_VALUE) {
HIDD_ATTRIBUTES attributes; HIDD_ATTRIBUTES attributes;
attributes.Size = sizeof(attributes); attributes.Size = sizeof(attributes);
if (HidD_GetAttributes(hfile, &attributes)) { if (HidD_GetAttributes(hfile, &attributes)) {
if (attributes.VendorID == vid && attributes.ProductID == pid) { if (attributes.VendorID == vid && attributes.ProductID == pid) {
PHIDP_PREPARSED_DATA pData; PHIDP_PREPARSED_DATA pData;
HIDP_CAPS caps; HIDP_CAPS caps;
if (HidD_GetPreparsedData(hfile, &pData)) { if (HidD_GetPreparsedData(hfile, &pData)) {
if (HidP_GetCaps(pData, &caps) == HIDP_STATUS_SUCCESS) { if (HidP_GetCaps(pData, &caps) == HIDP_STATUS_SUCCESS) {
if (numFoundDevs % 32 == 0) { if (numFoundDevs % 32 == 0) {
*foundDevs = (HidDeviceInfo*) realloc(*foundDevs, sizeof(HidDeviceInfo) * (32 + numFoundDevs)); *foundDevs = (HidDeviceInfo *)realloc(*foundDevs, sizeof(HidDeviceInfo) * (32 + numFoundDevs));
} }
HidDeviceInfo *dev = &foundDevs[0][numFoundDevs++]; HidDeviceInfo *dev = &foundDevs[0][numFoundDevs++];
dev->caps = caps; dev->caps = caps;
dev->vid = attributes.VendorID; dev->vid = attributes.VendorID;
dev->pid = attributes.ProductID; dev->pid = attributes.ProductID;
dev->path = wcsdup(devInterfaceDetails->DevicePath); dev->path = wcsdup(devInterfaceDetails->DevicePath);
} }
HidD_FreePreparsedData(pData); HidD_FreePreparsedData(pData);
} }
} }
} }
CloseHandle(hfile); CloseHandle(hfile);
} }
free(devInterfaceDetails); free(devInterfaceDetails);
} }
SetupDiDestroyDeviceInfoList(hdev); SetupDiDestroyDeviceInfoList(hdev);
} }
return numFoundDevs; return numFoundDevs;
} }

View File

@ -20,11 +20,12 @@
#include <hidsdi.h> #include <hidsdi.h>
struct HidDeviceInfo { struct HidDeviceInfo
HIDP_CAPS caps; {
wchar_t *path; HIDP_CAPS caps;
unsigned short vid; wchar_t *path;
unsigned short pid; unsigned short vid;
unsigned short pid;
}; };
int FindHids(HidDeviceInfo **foundDevs, int vid, int pid); int FindHids(HidDeviceInfo **foundDevs, int vid, int pid);

File diff suppressed because it is too large Load Diff

View File

@ -23,10 +23,10 @@
// Fully down means that value corresponds to a button being fully down (255). // Fully down means that value corresponds to a button being fully down (255).
// a value of 128 or more corresponds to that button being pressed, for binary // a value of 128 or more corresponds to that button being pressed, for binary
// values. // values.
#define BASE_SENSITIVITY (1<<16) #define BASE_SENSITIVITY (1 << 16)
#define FULLY_DOWN (1<<16) #define FULLY_DOWN (1 << 16)
#define DEFAULT_DEADZONE (BASE_SENSITIVITY * 201/1000) #define DEFAULT_DEADZONE (BASE_SENSITIVITY * 201 / 1000)
/* Idea is for this file and the associated cpp file to be Windows independent. /* Idea is for this file and the associated cpp file to be Windows independent.
* Still more effort than it's worth to port to Linux, however. * Still more effort than it's worth to port to Linux, however.
@ -36,28 +36,28 @@
// One physical axis maps to 3 virtual ones, and one physical POV control maps to // One physical axis maps to 3 virtual ones, and one physical POV control maps to
// 4 virtual ones. // 4 virtual ones.
enum ControlType { enum ControlType {
NO_CONTROL = 0, NO_CONTROL = 0,
// Axes are ints. Relative axes are for mice, mice wheels, etc, // Axes are ints. Relative axes are for mice, mice wheels, etc,
// and are always reported relative to their last value. // and are always reported relative to their last value.
// Absolute axes range from -65536 to 65536 and are absolute positions, // Absolute axes range from -65536 to 65536 and are absolute positions,
// like for joysticks and pressure sensitive buttons. // like for joysticks and pressure sensitive buttons.
RELAXIS = 1, RELAXIS = 1,
ABSAXIS = 2, ABSAXIS = 2,
// Buttons range from 0 to 65536. // Buttons range from 0 to 65536.
PSHBTN = 4, PSHBTN = 4,
TGLBTN = 8, TGLBTN = 8,
// POV controls are ints, values range from -1 to 36000. // POV controls are ints, values range from -1 to 36000.
// -1 means not pressed, otherwise it's an angle. // -1 means not pressed, otherwise it's an angle.
// For easy DirectInput compatibility, anything outside. // For easy DirectInput compatibility, anything outside.
// that range is treated as -1 (Though 36000-37000 is treated // that range is treated as -1 (Though 36000-37000 is treated
// like 0 to 1000, just in case). // like 0 to 1000, just in case).
POV = 16, POV = 16,
// Pressure sensitive buttons. Only a different type because // Pressure sensitive buttons. Only a different type because
// they have configurable dead zones, unlike push or toggle buttons. // they have configurable dead zones, unlike push or toggle buttons.
PRESSURE_BTN = 32, PRESSURE_BTN = 32,
}; };
// Masks to determine button type. Don't need one for POV. // Masks to determine button type. Don't need one for POV.
@ -65,37 +65,39 @@ enum ControlType {
#define BINARY_BUTTON (PSHBTN | TGLBTN) #define BINARY_BUTTON (PSHBTN | TGLBTN)
#define AXIS 3 #define AXIS 3
struct Binding { struct Binding
int controlIndex; {
int command; int controlIndex;
int sensitivity; int command;
int deadZone; int sensitivity;
unsigned char turbo; int deadZone;
unsigned char turbo;
}; };
#define UID_AXIS (1U<<31) #define UID_AXIS (1U << 31)
#define UID_POV (1<<30) #define UID_POV (1 << 30)
#define UID_AXIS_POS (1U<<24) #define UID_AXIS_POS (1U << 24)
#define UID_AXIS_NEG (2U<<24) #define UID_AXIS_NEG (2U << 24)
#define UID_POV_N (3<<24) #define UID_POV_N (3 << 24)
#define UID_POV_E (4<<24) #define UID_POV_E (4 << 24)
#define UID_POV_S (5<<24) #define UID_POV_S (5 << 24)
#define UID_POV_W (6<<24) #define UID_POV_W (6 << 24)
// One of these exists for each bindable object. // One of these exists for each bindable object.
// Bindable objects consist of buttons, axis, pov controls, // Bindable objects consist of buttons, axis, pov controls,
// and individual axis/pov directions. Not that pov controls // and individual axis/pov directions. Not that pov controls
// cannot actually be bound, but when trying to bind as an axis, // cannot actually be bound, but when trying to bind as an axis,
// all directions are assigned individually. // all directions are assigned individually.
struct VirtualControl { struct VirtualControl
// Unique id for control, given device. Based on source control's id, {
// source control type, axis/pov flags if it's a pov/axis (Rather than // Unique id for control, given device. Based on source control's id,
// a button or a pov/axis control's individual button), and an index, // source control type, axis/pov flags if it's a pov/axis (Rather than
// if the control is split. // a button or a pov/axis control's individual button), and an index,
unsigned int uid; // if the control is split.
// virtual key code. 0 if none. unsigned int uid;
int physicalControlIndex; // virtual key code. 0 if none.
int physicalControlIndex;
}; };
// Need one for each button, axis, and pov control. // Need one for each button, axis, and pov control.
@ -103,79 +105,84 @@ struct VirtualControl {
// updates their state, standard function then populates // updates their state, standard function then populates
// the VirtualControls and queues the keyboard messages, if // the VirtualControls and queues the keyboard messages, if
// needed. // needed.
struct PhysicalControl { struct PhysicalControl
// index of the first virtual control corresponding to this. {
// Buttons have 1 virtual control, axes 3, and povs 5, all // index of the first virtual control corresponding to this.
// in a row. // Buttons have 1 virtual control, axes 3, and povs 5, all
int baseVirtualControlIndex; // in a row.
ControlType type; int baseVirtualControlIndex;
// id. Must be unique for control type. ControlType type;
// short so can be combined with other values to get // id. Must be unique for control type.
// uid for virtual controls. // short so can be combined with other values to get
unsigned short id; // uid for virtual controls.
unsigned short vkey; unsigned short id;
wchar_t *name; unsigned short vkey;
wchar_t *name;
}; };
enum DeviceAPI { enum DeviceAPI {
NO_API = 0, NO_API = 0,
DI = 1, DI = 1,
WM = 2, WM = 2,
RAW = 3, RAW = 3,
XINPUT = 4, XINPUT = 4,
DS3 = 5, DS3 = 5,
// Not currently used. // Not currently used.
LLHOOK = 6, LLHOOK = 6,
// Not a real API, obviously. Only used with keyboards, // Not a real API, obviously. Only used with keyboards,
// to ignore individual buttons. Wrapper itself takes care // to ignore individual buttons. Wrapper itself takes care
// of ignoring bound keys. Otherwise, works normally. // of ignoring bound keys. Otherwise, works normally.
IGNORE_KEYBOARD = 7, IGNORE_KEYBOARD = 7,
// XXX // XXX
LNX_KEYBOARD = 16, LNX_KEYBOARD = 16,
LNX_JOY = 17, LNX_JOY = 17,
}; };
enum DeviceType { enum DeviceType {
NO_DEVICE = 0, NO_DEVICE = 0,
KEYBOARD = 1, KEYBOARD = 1,
MOUSE = 2, MOUSE = 2,
OTHER = 3 OTHER = 3
}; };
enum EffectType { enum EffectType {
EFFECT_CONSTANT, EFFECT_CONSTANT,
EFFECT_PERIODIC, EFFECT_PERIODIC,
EFFECT_RAMP EFFECT_RAMP
}; };
// force range sfrom -BASE_SENSITIVITY to BASE_SENSITIVITY. // force range sfrom -BASE_SENSITIVITY to BASE_SENSITIVITY.
// Order matches ForceFeedbackAxis order. force of 0 means to // Order matches ForceFeedbackAxis order. force of 0 means to
// ignore that axis completely. Force of 1 or -1 means to initialize // ignore that axis completely. Force of 1 or -1 means to initialize
// the axis with minimum force (Possibly 0 force), if applicable. // the axis with minimum force (Possibly 0 force), if applicable.
struct AxisEffectInfo { struct AxisEffectInfo
int force; {
int force;
}; };
struct ForceFeedbackBinding { struct ForceFeedbackBinding
AxisEffectInfo *axes; {
int effectIndex; AxisEffectInfo *axes;
unsigned char motor; int effectIndex;
unsigned char motor;
}; };
// Bindings listed by effect, so I don't have to bother with // Bindings listed by effect, so I don't have to bother with
// indexing effects. // indexing effects.
struct ForceFeedbackEffectType { struct ForceFeedbackEffectType
wchar_t *displayName; {
// Because I'm lazy, can only have ASCII characters and no spaces. wchar_t *displayName;
wchar_t *effectID; // Because I'm lazy, can only have ASCII characters and no spaces.
// constant, ramp, or periodic wchar_t *effectID;
EffectType type; // constant, ramp, or periodic
EffectType type;
}; };
struct ForceFeedbackAxis { struct ForceFeedbackAxis
wchar_t *displayName; {
int id; wchar_t *displayName;
int id;
}; };
// Used both for active devices and for sets of settings for devices. // Used both for active devices and for sets of settings for devices.
@ -184,190 +191,200 @@ struct ForceFeedbackAxis {
// one set of generic devices. Then I enumerate all devices. Then I merge // one set of generic devices. Then I enumerate all devices. Then I merge
// them, moving settings from the generic devices to the enumerated ones. // them, moving settings from the generic devices to the enumerated ones.
struct PadBindings { struct PadBindings
Binding *bindings; {
int numBindings; Binding *bindings;
ForceFeedbackBinding *ffBindings; int numBindings;
int numFFBindings; ForceFeedbackBinding *ffBindings;
int numFFBindings;
}; };
class WndProcEater; class WndProcEater;
struct InitInfo { struct InitInfo
// 1 when binding key to ignore. {
int bindingIgnore; // 1 when binding key to ignore.
// 1 when binding. int bindingIgnore;
int binding; // 1 when binding.
int binding;
#ifdef _MSC_VER #ifdef _MSC_VER
HWND hWndTop; HWND hWndTop;
// For config screen, need to eat button's message handling. // For config screen, need to eat button's message handling.
//HWND hWndButton; //HWND hWndButton;
WndProcEater* hWndProc; WndProcEater *hWndProc;
#else #else
// Linux equivalent to HWND // Linux equivalent to HWND
Display *GSdsp; Display *GSdsp;
Window GSwin; Window GSwin;
#endif #endif
}; };
// Mostly self-contained, but bindings are modified by config.cpp, to make // Mostly self-contained, but bindings are modified by config.cpp, to make
// updating the ListView simpler. // updating the ListView simpler.
class Device { class Device
{
public: public:
DeviceAPI api; DeviceAPI api;
DeviceType type; DeviceType type;
char active; char active;
char attached; char attached;
// Based on input modes. // Based on input modes.
char enabled; char enabled;
#ifdef _MSC_VER #ifdef _MSC_VER
// Not all devices need to subclass the windproc, but most do so might as well // Not all devices need to subclass the windproc, but most do so might as well
// put it here... --air // put it here... --air
WndProcEater* hWndProc; WndProcEater *hWndProc;
#endif #endif
union { union
// Allows for one loop to compare all 3 in order. {
wchar_t *IDs[3]; // Allows for one loop to compare all 3 in order.
struct { wchar_t *IDs[3];
// Same as DisplayName, when not given. Absolutely must be unique. struct
// Used for loading/saving controls. If matches, all other strings {
// are ignored, so must be unique. // Same as DisplayName, when not given. Absolutely must be unique.
wchar_t *instanceID; // Used for loading/saving controls. If matches, all other strings
// Not required. Used when a device's instance id changes, doesn't have to // are ignored, so must be unique.
// be unique. For devices that can only have one instance, not needed. wchar_t *instanceID;
wchar_t *productID; // Not required. Used when a device's instance id changes, doesn't have to
// be unique. For devices that can only have one instance, not needed.
wchar_t *productID;
wchar_t *displayName; wchar_t *displayName;
}; };
}; };
PadBindings pads[2][4]; PadBindings pads[2][4];
// Virtual controls. All basically act like pressure sensitivity buttons, with // Virtual controls. All basically act like pressure sensitivity buttons, with
// values between 0 and 2^16. 2^16 is fully down, 0 is up. Larger values // values between 0 and 2^16. 2^16 is fully down, 0 is up. Larger values
// are allowed, but *only* for absolute axes (Which don't support the flip checkbox). // are allowed, but *only* for absolute axes (Which don't support the flip checkbox).
// Each control on a device must have a unique id, used for binding. // Each control on a device must have a unique id, used for binding.
VirtualControl *virtualControls; VirtualControl *virtualControls;
int numVirtualControls; int numVirtualControls;
int *virtualControlState; int *virtualControlState;
int *oldVirtualControlState; int *oldVirtualControlState;
PhysicalControl *physicalControls; PhysicalControl *physicalControls;
int numPhysicalControls; int numPhysicalControls;
int *physicalControlState; int *physicalControlState;
ForceFeedbackEffectType *ffEffectTypes; ForceFeedbackEffectType *ffEffectTypes;
int numFFEffectTypes; int numFFEffectTypes;
ForceFeedbackAxis *ffAxes; ForceFeedbackAxis *ffAxes;
int numFFAxes; int numFFAxes;
void AddFFAxis(const wchar_t *displayName, int id); void AddFFAxis(const wchar_t *displayName, int id);
void AddFFEffectType(const wchar_t *displayName, const wchar_t *effectID, EffectType type); void AddFFEffectType(const wchar_t *displayName, const wchar_t *effectID, EffectType type);
Device(DeviceAPI, DeviceType, const wchar_t *displayName, const wchar_t *instanceID = 0, const wchar_t *deviceID = 0); Device(DeviceAPI, DeviceType, const wchar_t *displayName, const wchar_t *instanceID = 0, const wchar_t *deviceID = 0);
virtual ~Device(); virtual ~Device();
// Allocates memory for old and new state, sets everything to 0. // Allocates memory for old and new state, sets everything to 0.
// all old states are in one array, buttons, axes, and then POVs. // all old states are in one array, buttons, axes, and then POVs.
// start of each section is int aligned. This makes it DirectInput // start of each section is int aligned. This makes it DirectInput
// compatible. // compatible.
void AllocState(); void AllocState();
// Doesn't actually flip. Copies current state to old state. // Doesn't actually flip. Copies current state to old state.
void FlipState(); void FlipState();
// Frees state variables. // Frees state variables.
void FreeState(); void FreeState();
ForceFeedbackEffectType *GetForcefeedbackEffect(wchar_t *id); ForceFeedbackEffectType *GetForcefeedbackEffect(wchar_t *id);
ForceFeedbackAxis *GetForceFeedbackAxis(int id); ForceFeedbackAxis *GetForceFeedbackAxis(int id);
VirtualControl *GetVirtualControl(unsigned int uid); VirtualControl *GetVirtualControl(unsigned int uid);
PhysicalControl *AddPhysicalControl(ControlType type, unsigned short id, unsigned short vkey, const wchar_t *name = 0); PhysicalControl *AddPhysicalControl(ControlType type, unsigned short id, unsigned short vkey, const wchar_t *name = 0);
VirtualControl *AddVirtualControl(unsigned int uid, int physicalControlIndex); VirtualControl *AddVirtualControl(unsigned int uid, int physicalControlIndex);
virtual wchar_t *GetVirtualControlName(VirtualControl *c); virtual wchar_t *GetVirtualControlName(VirtualControl *c);
virtual wchar_t *GetPhysicalControlName(PhysicalControl *c); virtual wchar_t *GetPhysicalControlName(PhysicalControl *c);
void CalcVirtualState(); void CalcVirtualState();
virtual int Activate(InitInfo *args) { virtual int Activate(InitInfo *args)
return 0; {
} return 0;
}
inline virtual void Deactivate() { inline virtual void Deactivate()
FreeState(); {
active = 0; FreeState();
} active = 0;
}
// Default update proc. All that's needed for post-based APIs. // Default update proc. All that's needed for post-based APIs.
inline virtual int Update() { inline virtual int Update()
return active; {
} return active;
}
// force is from -FULLY_DOWN to FULLY_DOWN. // force is from -FULLY_DOWN to FULLY_DOWN.
// Either function can be overridden. Second one by default calls the first // Either function can be overridden. Second one by default calls the first
// for every bound effect that's affected. // for every bound effect that's affected.
// Note: Only used externally for binding, so if override the other one, can assume // Note: Only used externally for binding, so if override the other one, can assume
// all other forces are currently 0. // all other forces are currently 0.
inline virtual void SetEffect(ForceFeedbackBinding *binding, unsigned char force) {} inline virtual void SetEffect(ForceFeedbackBinding *binding, unsigned char force) {}
virtual void SetEffects(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force); virtual void SetEffects(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force);
// Called after reading. Basically calls FlipState(). // Called after reading. Basically calls FlipState().
// Some device types (Those that don't incrementally update) // Some device types (Those that don't incrementally update)
// could call FlipState elsewhere, but this makes it simpler to ignore // could call FlipState elsewhere, but this makes it simpler to ignore
// while binding. // while binding.
virtual void PostRead(); virtual void PostRead();
}; };
class InputDeviceManager { class InputDeviceManager
{
public: public:
Device **devices; Device **devices;
int numDevices; int numDevices;
void ClearDevices(); void ClearDevices();
// When refreshing devices, back up old devices, then // When refreshing devices, back up old devices, then
// populate this with new devices, then call copy bindings. // populate this with new devices, then call copy bindings.
// All old bindings are copied to matching devices. // All old bindings are copied to matching devices.
// When old devices are missing, I do a slightly more careful search // When old devices are missing, I do a slightly more careful search
// using productIDs and then (in desperation) displayName. // using productIDs and then (in desperation) displayName.
// Finally create new dummy devices if no matches found. // Finally create new dummy devices if no matches found.
void CopyBindings(int numDevices, Device **devices); void CopyBindings(int numDevices, Device **devices);
InputDeviceManager(); InputDeviceManager();
~InputDeviceManager(); ~InputDeviceManager();
void AddDevice(Device *d); void AddDevice(Device *d);
Device *GetActiveDevice(InitInfo *info, unsigned int *uid, int *index, int *value); Device *GetActiveDevice(InitInfo *info, unsigned int *uid, int *index, int *value);
void Update(InitInfo *initInfo); void Update(InitInfo *initInfo);
// Called after reading state, after Update(). // Called after reading state, after Update().
void PostRead(); void PostRead();
void SetEffect(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force); void SetEffect(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force);
// Update does this as needed. // Update does this as needed.
// void GetInput(void *v); // void GetInput(void *v);
void ReleaseInput(); void ReleaseInput();
void DisableDevice(int index); void DisableDevice(int index);
inline void EnableDevice(int i) { inline void EnableDevice(int i)
devices[i]->enabled = 1; {
} devices[i]->enabled = 1;
}
void EnableDevices(DeviceType type, DeviceAPI api); void EnableDevices(DeviceType type, DeviceAPI api);
void DisableAllDevices(); void DisableAllDevices();
}; };
extern InputDeviceManager *dm; extern InputDeviceManager *dm;

View File

@ -34,64 +34,68 @@ static u8 lastQueuedEvent = 0;
static u8 nextQueuedEvent = 0; static u8 nextQueuedEvent = 0;
static keyEvent queuedEvents[EVENT_QUEUE_LEN]; static keyEvent queuedEvents[EVENT_QUEUE_LEN];
void QueueKeyEvent(int key, int event) { void QueueKeyEvent(int key, int event)
{
#ifdef _MSC_VER #ifdef _MSC_VER
if (!csInitialized) { if (!csInitialized) {
csInitialized = 1; csInitialized = 1;
InitializeCriticalSection(&cSection); InitializeCriticalSection(&cSection);
} }
EnterCriticalSection(&cSection); EnterCriticalSection(&cSection);
#else #else
std::lock_guard<std::mutex> lock(cSection); std::lock_guard<std::mutex> lock(cSection);
#endif #endif
// Don't queue events if escape is on top of queue. This is just for safety // Don't queue events if escape is on top of queue. This is just for safety
// purposes when a game is killing the emulator for whatever reason. // purposes when a game is killing the emulator for whatever reason.
if (nextQueuedEvent == lastQueuedEvent || if (nextQueuedEvent == lastQueuedEvent ||
queuedEvents[nextQueuedEvent].key != VK_ESCAPE || queuedEvents[nextQueuedEvent].key != VK_ESCAPE ||
queuedEvents[nextQueuedEvent].evt != KEYPRESS) { queuedEvents[nextQueuedEvent].evt != KEYPRESS) {
// Clear queue on escape down, bringing escape to front. May do something // Clear queue on escape down, bringing escape to front. May do something
// with shift/ctrl/alt and F-keys, later. // with shift/ctrl/alt and F-keys, later.
if (event == KEYPRESS && key == VK_ESCAPE) { if (event == KEYPRESS && key == VK_ESCAPE) {
nextQueuedEvent = lastQueuedEvent; nextQueuedEvent = lastQueuedEvent;
} }
queuedEvents[lastQueuedEvent].key = key; queuedEvents[lastQueuedEvent].key = key;
queuedEvents[lastQueuedEvent].evt = event; queuedEvents[lastQueuedEvent].evt = event;
lastQueuedEvent = (lastQueuedEvent + 1) % EVENT_QUEUE_LEN; lastQueuedEvent = (lastQueuedEvent + 1) % EVENT_QUEUE_LEN;
// If queue wrapped around, remove last element. // If queue wrapped around, remove last element.
if (nextQueuedEvent == lastQueuedEvent) { if (nextQueuedEvent == lastQueuedEvent) {
nextQueuedEvent = (nextQueuedEvent + 1) % EVENT_QUEUE_LEN; nextQueuedEvent = (nextQueuedEvent + 1) % EVENT_QUEUE_LEN;
} }
} }
#ifdef _MSC_VER #ifdef _MSC_VER
LeaveCriticalSection(&cSection); LeaveCriticalSection(&cSection);
#endif #endif
} }
int GetQueuedKeyEvent(keyEvent *event) { int GetQueuedKeyEvent(keyEvent *event)
if (lastQueuedEvent == nextQueuedEvent) return 0; {
if (lastQueuedEvent == nextQueuedEvent)
return 0;
#ifdef _MSC_VER #ifdef _MSC_VER
EnterCriticalSection(&cSection); EnterCriticalSection(&cSection);
#else #else
std::lock_guard<std::mutex> lock(cSection); std::lock_guard<std::mutex> lock(cSection);
#endif #endif
*event = queuedEvents[nextQueuedEvent]; *event = queuedEvents[nextQueuedEvent];
nextQueuedEvent = (nextQueuedEvent + 1) % EVENT_QUEUE_LEN; nextQueuedEvent = (nextQueuedEvent + 1) % EVENT_QUEUE_LEN;
#ifdef _MSC_VER #ifdef _MSC_VER
LeaveCriticalSection(&cSection); LeaveCriticalSection(&cSection);
#endif #endif
return 1; return 1;
} }
void ClearKeyQueue() { void ClearKeyQueue()
lastQueuedEvent = nextQueuedEvent; {
lastQueuedEvent = nextQueuedEvent;
#ifdef _MSC_VER #ifdef _MSC_VER
if (csInitialized) { if (csInitialized) {
DeleteCriticalSection(&cSection); DeleteCriticalSection(&cSection);
csInitialized = 0; csInitialized = 0;
} }
#endif #endif
} }

View File

@ -26,7 +26,7 @@ int GetQueuedKeyEvent(keyEvent *event);
void ClearKeyQueue(); void ClearKeyQueue();
#ifdef __linux__ #ifdef __linux__
void R_QueueKeyEvent(const keyEvent& event); void R_QueueKeyEvent(const keyEvent &event);
int R_GetQueuedKeyEvent(keyEvent *event); int R_GetQueuedKeyEvent(keyEvent *event);
void R_ClearKeyQueue(); void R_ClearKeyQueue();
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -28,393 +28,411 @@ u8 ps2e = 0;
#if 0 #if 0
remove 0x10F0 to compute the cmd value remove 0x10F0 to compute the cmd value
#define ID_SENSITIVITY 0x1007 #define ID_SENSITIVITY 0x1007
#define ID_LOCK_BUTTONS 0x10FC #define ID_LOCK_BUTTONS 0x10FC
#define ID_LOCK 0x10FD #define ID_LOCK 0x10FD
#define ID_LOCK_DIRECTION 0x10FE #define ID_LOCK_DIRECTION 0x10FE
#define ID_MOUSE 0x10FF #define ID_MOUSE 0x10FF
#define ID_SELECT 0x1100 #define ID_SELECT 0x1100
#define ID_L3 0x1101 #define ID_L3 0x1101
#define ID_R3 0x1102 #define ID_R3 0x1102
#define ID_START 0x1103 #define ID_START 0x1103
#define ID_DPAD_UP 0x1104 #define ID_DPAD_UP 0x1104
#define ID_DPAD_RIGHT 0x1105 #define ID_DPAD_RIGHT 0x1105
#define ID_DPAD_DOWN 0x1106 #define ID_DPAD_DOWN 0x1106
#define ID_DPAD_LEFT 0x1107 #define ID_DPAD_LEFT 0x1107
#define ID_L2 0x1108 #define ID_L2 0x1108
#define ID_R2 0x1109 #define ID_R2 0x1109
#define ID_L1 0x110A #define ID_L1 0x110A
#define ID_R1 0x110B #define ID_R1 0x110B
#define ID_TRIANGLE 0x110C #define ID_TRIANGLE 0x110C
#define ID_CIRCLE 0x110D #define ID_CIRCLE 0x110D
#define ID_CROSS 0x110E #define ID_CROSS 0x110E
#define ID_SQUARE 0x110F #define ID_SQUARE 0x110F
#define ID_LSTICK_UP 0x1110 #define ID_LSTICK_UP 0x1110
#define ID_LSTICK_RIGHT 0x1111 #define ID_LSTICK_RIGHT 0x1111
#define ID_LSTICK_DOWN 0x1112 #define ID_LSTICK_DOWN 0x1112
#define ID_LSTICK_LEFT 0x1113 #define ID_LSTICK_LEFT 0x1113
#define ID_RSTICK_UP 0x1114 #define ID_RSTICK_UP 0x1114
#define ID_RSTICK_RIGHT 0x1115 #define ID_RSTICK_RIGHT 0x1115
#define ID_RSTICK_DOWN 0x1116 #define ID_RSTICK_DOWN 0x1116
#define ID_RSTICK_LEFT 0x1117 #define ID_RSTICK_LEFT 0x1117
#define ID_ANALOG 0x1118 #define ID_ANALOG 0x1118
#define ID_DELETE 0x11FF #define ID_DELETE 0x11FF
#define ID_DEBUG 0x1200 #define ID_DEBUG 0x1200
#define ID_IGNORE 0x1201 #define ID_IGNORE 0x1201
#define ID_CLEAR 0x1202 #define ID_CLEAR 0x1202
#define ID_REFRESH 0x1202 #define ID_REFRESH 0x1202
#define ID_SAVE 0x1204 #define ID_SAVE 0x1204
#define ID_LOAD 0x1205 #define ID_LOAD 0x1205
#define ID_BIG_MOTOR 0x120A #define ID_BIG_MOTOR 0x120A
#define ID_SMALL_MOTOR 0x120B #define ID_SMALL_MOTOR 0x120B
#define ID_TEST 0x1300 #define ID_TEST 0x1300
#define ID_CONTROLS 0x1301 #define ID_CONTROLS 0x1301
#define ID_FF 0x1304 #define ID_FF 0x1304
#endif #endif
struct GeneralSettingsBool { struct GeneralSettingsBool
const wchar_t *name; {
unsigned int ControlId; const wchar_t *name;
u8 defaultValue; unsigned int ControlId;
u8 defaultValue;
}; };
// XXX: I try to remove only gui stuff // XXX: I try to remove only gui stuff
void DeleteBinding(int port, int slot, Device *dev, Binding *b) { void DeleteBinding(int port, int slot, Device *dev, Binding *b)
fprintf(stderr, "delete binding %d:%d\n", port, slot); {
Binding *bindings = dev->pads[port][slot].bindings; fprintf(stderr, "delete binding %d:%d\n", port, slot);
int i = b - bindings; Binding *bindings = dev->pads[port][slot].bindings;
memmove(bindings+i, bindings+i+1, sizeof(Binding) * (dev->pads[port][slot].numBindings - i - 1)); int i = b - bindings;
dev->pads[port][slot].numBindings--; memmove(bindings + i, bindings + i + 1, sizeof(Binding) * (dev->pads[port][slot].numBindings - i - 1));
dev->pads[port][slot].numBindings--;
} }
void DeleteBinding(int port, int slot, Device *dev, ForceFeedbackBinding *b) { void DeleteBinding(int port, int slot, Device *dev, ForceFeedbackBinding *b)
ForceFeedbackBinding *bindings = dev->pads[port][slot].ffBindings; {
int i = b - bindings; ForceFeedbackBinding *bindings = dev->pads[port][slot].ffBindings;
memmove(bindings+i, bindings+i+1, sizeof(Binding) * (dev->pads[port][slot].numFFBindings - i - 1)); int i = b - bindings;
dev->pads[port][slot].numFFBindings--; memmove(bindings + i, bindings + i + 1, sizeof(Binding) * (dev->pads[port][slot].numFFBindings - i - 1));
dev->pads[port][slot].numFFBindings--;
} }
int BindCommand(Device *dev, unsigned int uid, unsigned int port, unsigned int slot, int command, int sensitivity, int turbo, int deadZone) { int BindCommand(Device *dev, unsigned int uid, unsigned int port, unsigned int slot, int command, int sensitivity, int turbo, int deadZone)
// Checks needed because I use this directly when loading bindings. {
if (port > 1 || slot>3) { // Checks needed because I use this directly when loading bindings.
return -1; if (port > 1 || slot > 3) {
} return -1;
if (!sensitivity) sensitivity = BASE_SENSITIVITY; }
if ((uid>>16) & (PSHBTN|TGLBTN)) { if (!sensitivity)
deadZone = 0; sensitivity = BASE_SENSITIVITY;
} if ((uid >> 16) & (PSHBTN | TGLBTN)) {
else if (!deadZone) { deadZone = 0;
if ((uid>>16) & PRESSURE_BTN) { } else if (!deadZone) {
deadZone = 1; if ((uid >> 16) & PRESSURE_BTN) {
} deadZone = 1;
else { } else {
deadZone = DEFAULT_DEADZONE; deadZone = DEFAULT_DEADZONE;
} }
} }
// Relative axes can have negative sensitivity. // Relative axes can have negative sensitivity.
else if (((uid>>16) & 0xFF) == RELAXIS) { else if (((uid >> 16) & 0xFF) == RELAXIS) {
sensitivity = abs(sensitivity); sensitivity = abs(sensitivity);
} }
VirtualControl *c = dev->GetVirtualControl(uid); VirtualControl *c = dev->GetVirtualControl(uid);
if (!c) return -1; if (!c)
// Add before deleting. Means I won't scroll up one line when scrolled down to bottom. return -1;
int controlIndex = c - dev->virtualControls; // Add before deleting. Means I won't scroll up one line when scrolled down to bottom.
int index = 0; int controlIndex = c - dev->virtualControls;
PadBindings *p = dev->pads[port]+slot; int index = 0;
p->bindings = (Binding*) realloc(p->bindings, (p->numBindings+1) * sizeof(Binding)); PadBindings *p = dev->pads[port] + slot;
for (index = p->numBindings; index > 0; index--) { p->bindings = (Binding *)realloc(p->bindings, (p->numBindings + 1) * sizeof(Binding));
if (p->bindings[index-1].controlIndex < controlIndex) break; for (index = p->numBindings; index > 0; index--) {
p->bindings[index] = p->bindings[index-1]; if (p->bindings[index - 1].controlIndex < controlIndex)
} break;
Binding *b = p->bindings+index; p->bindings[index] = p->bindings[index - 1];
p->numBindings++; }
b->command = command; Binding *b = p->bindings + index;
b->controlIndex = controlIndex; p->numBindings++;
b->turbo = turbo; b->command = command;
b->sensitivity = sensitivity; b->controlIndex = controlIndex;
b->deadZone = deadZone; b->turbo = turbo;
// Where it appears in listview. b->sensitivity = sensitivity;
//int count = ListBoundCommand(port, slot, dev, b); b->deadZone = deadZone;
// Where it appears in listview.
//int count = ListBoundCommand(port, slot, dev, b);
int newBindingIndex = index; int newBindingIndex = index;
index = 0; index = 0;
while (index < p->numBindings) { while (index < p->numBindings) {
if (index == newBindingIndex) { if (index == newBindingIndex) {
index ++; index++;
continue; continue;
} }
b = p->bindings + index; b = p->bindings + index;
int nuke = 0; int nuke = 0;
if (config.multipleBinding) { if (config.multipleBinding) {
if (b->controlIndex == controlIndex && b->command == command) if (b->controlIndex == controlIndex && b->command == command)
nuke = 1; nuke = 1;
} } else {
else { int uid2 = dev->virtualControls[b->controlIndex].uid;
int uid2 = dev->virtualControls[b->controlIndex].uid; if (b->controlIndex == controlIndex || (!((uid2 ^ uid) & 0xFFFFFF) && ((uid | uid2) & (UID_POV | UID_AXIS))))
if (b->controlIndex == controlIndex || (!((uid2^uid) & 0xFFFFFF) && ((uid|uid2) & (UID_POV | UID_AXIS)))) nuke = 1;
nuke = 1; }
} if (!nuke) {
if (!nuke) { index++;
index++; continue;
continue; }
} if (index < newBindingIndex) {
if (index < newBindingIndex) { newBindingIndex--;
newBindingIndex--; //count --;
//count --; }
} DeleteBinding(port, slot, dev, b);
DeleteBinding(port, slot, dev, b); }
} if (!config.multipleBinding) {
if (!config.multipleBinding) { for (int port2 = 0; port2 < 2; port2++) {
for (int port2=0; port2<2; port2++) { for (int slot2 = 0; slot2 < 4; slot2++) {
for (int slot2=0; slot2<4; slot2++) { if (port2 == (int)port && slot2 == (int)slot)
if (port2==(int)port && slot2 == (int)slot) continue; continue;
PadBindings *p = dev->pads[port2]+slot2; PadBindings *p = dev->pads[port2] + slot2;
for (int i=0; i < p->numBindings; i++) { for (int i = 0; i < p->numBindings; i++) {
Binding *b = p->bindings+i; Binding *b = p->bindings + i;
int uid2 = dev->virtualControls[b->controlIndex].uid; int uid2 = dev->virtualControls[b->controlIndex].uid;
if (b->controlIndex == controlIndex || (!((uid2^uid) & 0xFFFFFF) && ((uid|uid2) & (UID_POV | UID_AXIS)))) { if (b->controlIndex == controlIndex || (!((uid2 ^ uid) & 0xFFFFFF) && ((uid | uid2) & (UID_POV | UID_AXIS)))) {
DeleteBinding(port2, slot2, dev, b); DeleteBinding(port2, slot2, dev, b);
i--; i--;
} }
} }
} }
} }
} }
//return count; //return count;
return 0; return 0;
} }
// Ties together config data structure, config files, and general config // Ties together config data structure, config files, and general config
// dialog. // dialog.
const GeneralSettingsBool BoolOptionsInfo[] = { const GeneralSettingsBool BoolOptionsInfo[] = {
{L"Force Cursor Hide", 0 /*IDC_FORCE_HIDE*/, 0}, {L"Force Cursor Hide", 0 /*IDC_FORCE_HIDE*/, 0},
{L"Mouse Unfocus", 0 /*IDC_MOUSE_UNFOCUS*/, 1}, {L"Mouse Unfocus", 0 /*IDC_MOUSE_UNFOCUS*/, 1},
{L"Background", 0 /*IDC_BACKGROUND*/, 1}, {L"Background", 0 /*IDC_BACKGROUND*/, 1},
{L"Multiple Bindings", 0 /*IDC_MULTIPLE_BINDING*/, 0}, {L"Multiple Bindings", 0 /*IDC_MULTIPLE_BINDING*/, 0},
{L"DirectInput Game Devices", 0 /*IDC_G_DI*/, 1}, {L"DirectInput Game Devices", 0 /*IDC_G_DI*/, 1},
{L"XInput", 0 /*IDC_G_XI*/, 1}, {L"XInput", 0 /*IDC_G_XI*/, 1},
{L"DualShock 3", 0 /*IDC_G_DS3*/, 0}, {L"DualShock 3", 0 /*IDC_G_DS3*/, 0},
{L"Multitap 1", 0 /*IDC_MULTITAP1*/, 0}, {L"Multitap 1", 0 /*IDC_MULTITAP1*/, 0},
{L"Multitap 2", 0 /*IDC_MULTITAP2*/, 0}, {L"Multitap 2", 0 /*IDC_MULTITAP2*/, 0},
{L"Escape Fullscreen Hack", 0 /*IDC_ESCAPE_FULLSCREEN_HACK*/, 1}, {L"Escape Fullscreen Hack", 0 /*IDC_ESCAPE_FULLSCREEN_HACK*/, 1},
{L"Disable Screen Saver", 0 /*IDC_DISABLE_SCREENSAVER*/, 1}, {L"Disable Screen Saver", 0 /*IDC_DISABLE_SCREENSAVER*/, 1},
{L"Logging", 0 /*IDC_DEBUG_FILE*/, 0}, {L"Logging", 0 /*IDC_DEBUG_FILE*/, 0},
{L"Save State in Title", 0 /*IDC_SAVE_STATE_TITLE*/, 0}, //No longer required, PCSX2 now handles it - avih 2011-05-17 {L"Save State in Title", 0 /*IDC_SAVE_STATE_TITLE*/, 0}, //No longer required, PCSX2 now handles it - avih 2011-05-17
{L"GH2", 0 /*IDC_GH2_HACK*/, 0}, {L"GH2", 0 /*IDC_GH2_HACK*/, 0},
{L"Turbo Key Hack", 0 /*IDC_TURBO_KEY_HACK*/, 0}, {L"Turbo Key Hack", 0 /*IDC_TURBO_KEY_HACK*/, 0},
}; };
void CALLBACK PADsetSettingsDir( const char *dir ) void CALLBACK PADsetSettingsDir(const char *dir)
{ {
CfgHelper::SetSettingsDir(dir); CfgHelper::SetSettingsDir(dir);
} }
int SaveSettings(wchar_t *file=0) { int SaveSettings(wchar_t *file = 0)
CfgHelper cfg; {
CfgHelper cfg;
for (size_t i=0; i<sizeof(BoolOptionsInfo)/sizeof(BoolOptionsInfo[0]); i++) { for (size_t i = 0; i < sizeof(BoolOptionsInfo) / sizeof(BoolOptionsInfo[0]); i++) {
cfg.WriteBool(L"General Settings", BoolOptionsInfo[i].name, config.bools[i]); cfg.WriteBool(L"General Settings", BoolOptionsInfo[i].name, config.bools[i]);
} }
cfg.WriteInt(L"General Settings", L"Close Hacks", config.closeHacks); cfg.WriteInt(L"General Settings", L"Close Hacks", config.closeHacks);
cfg.WriteInt(L"General Settings", L"Keyboard Mode", config.keyboardApi); cfg.WriteInt(L"General Settings", L"Keyboard Mode", config.keyboardApi);
cfg.WriteInt(L"General Settings", L"Mouse Mode", config.mouseApi); cfg.WriteInt(L"General Settings", L"Mouse Mode", config.mouseApi);
for (int port=0; port<2; port++) { for (int port = 0; port < 2; port++) {
for (int slot=0; slot<4; slot++) { for (int slot = 0; slot < 4; slot++) {
wchar_t temp[50]; wchar_t temp[50];
wsprintf(temp, L"Pad %i %i", port, slot); wsprintf(temp, L"Pad %i %i", port, slot);
cfg.WriteInt(temp, L"Mode", config.padConfigs[port][slot].type); cfg.WriteInt(temp, L"Mode", config.padConfigs[port][slot].type);
cfg.WriteInt(temp, L"Auto Analog", config.padConfigs[port][slot].autoAnalog); cfg.WriteInt(temp, L"Auto Analog", config.padConfigs[port][slot].autoAnalog);
} }
} }
if (!dm) if (!dm)
return 0; return 0;
for (int i=0; i<dm->numDevices; i++) { for (int i = 0; i < dm->numDevices; i++) {
wchar_t id[50]; wchar_t id[50];
wchar_t temp[50], temp2[1000]; wchar_t temp[50], temp2[1000];
wsprintfW(id, L"Device %i", i); wsprintfW(id, L"Device %i", i);
Device *dev = dm->devices[i]; Device *dev = dm->devices[i];
wchar_t *name = dev->displayName; wchar_t *name = dev->displayName;
while (name[0] == '[') { while (name[0] == '[') {
wchar_t *name2 = wcschr(name, ']'); wchar_t *name2 = wcschr(name, ']');
if (!name2) break; if (!name2)
name = name2+1; break;
while (iswspace(name[0])) name++; name = name2 + 1;
} while (iswspace(name[0]))
name++;
}
cfg.WriteStr(id, L"Display Name", name); cfg.WriteStr(id, L"Display Name", name);
cfg.WriteStr(id, L"Instance ID", dev->instanceID); cfg.WriteStr(id, L"Instance ID", dev->instanceID);
if (dev->productID) { if (dev->productID) {
cfg.WriteStr(id, L"Product ID", dev->productID); cfg.WriteStr(id, L"Product ID", dev->productID);
} }
cfg.WriteInt(id, L"API", dev->api); cfg.WriteInt(id, L"API", dev->api);
cfg.WriteInt(id, L"Type", dev->type); cfg.WriteInt(id, L"Type", dev->type);
int ffBindingCount = 0; int ffBindingCount = 0;
int bindingCount = 0; int bindingCount = 0;
for (int port=0; port<2; port++) { for (int port = 0; port < 2; port++) {
for (int slot=0; slot<4; slot++) { for (int slot = 0; slot < 4; slot++) {
for (int j=0; j<dev->pads[port][slot].numBindings; j++) { for (int j = 0; j < dev->pads[port][slot].numBindings; j++) {
Binding *b = dev->pads[port][slot].bindings+j; Binding *b = dev->pads[port][slot].bindings + j;
VirtualControl *c = &dev->virtualControls[b->controlIndex]; VirtualControl *c = &dev->virtualControls[b->controlIndex];
wsprintfW(temp, L"Binding %i", bindingCount++); wsprintfW(temp, L"Binding %i", bindingCount++);
wsprintfW(temp2, L"0x%08X, %i, %i, %i, %i, %i, %i", c->uid, port, b->command, b->sensitivity, b->turbo, slot, b->deadZone); wsprintfW(temp2, L"0x%08X, %i, %i, %i, %i, %i, %i", c->uid, port, b->command, b->sensitivity, b->turbo, slot, b->deadZone);
cfg.WriteStr(id, temp, temp2); cfg.WriteStr(id, temp, temp2);
} }
for (int j=0; j<dev->pads[port][slot].numFFBindings; j++) { for (int j = 0; j < dev->pads[port][slot].numFFBindings; j++) {
ForceFeedbackBinding *b = dev->pads[port][slot].ffBindings+j; ForceFeedbackBinding *b = dev->pads[port][slot].ffBindings + j;
ForceFeedbackEffectType *eff = &dev->ffEffectTypes[b->effectIndex]; ForceFeedbackEffectType *eff = &dev->ffEffectTypes[b->effectIndex];
wsprintfW(temp, L"FF Binding %i", ffBindingCount++); wsprintfW(temp, L"FF Binding %i", ffBindingCount++);
wsprintfW(temp2, L"%s %i, %i, %i", eff->effectID, port, b->motor, slot); wsprintfW(temp2, L"%s %i, %i, %i", eff->effectID, port, b->motor, slot);
for (int k=0; k<dev->numFFAxes; k++) { for (int k = 0; k < dev->numFFAxes; k++) {
ForceFeedbackAxis *axis = dev->ffAxes + k; ForceFeedbackAxis *axis = dev->ffAxes + k;
AxisEffectInfo *info = b->axes + k; AxisEffectInfo *info = b->axes + k;
//wsprintfW(wcschr(temp2,0), L", %i, %i", axis->id, info->force); //wsprintfW(wcschr(temp2,0), L", %i, %i", axis->id, info->force);
// Not secure because I'm too lazy to compute the remaining size // Not secure because I'm too lazy to compute the remaining size
wprintf(wcschr(temp2, 0), L", %i, %i", axis->id, info->force); wprintf(wcschr(temp2, 0), L", %i, %i", axis->id, info->force);
} }
cfg.WriteStr(id, temp, temp2); cfg.WriteStr(id, temp, temp2);
} }
} }
} }
} }
return 0; return 0;
} }
int LoadSettings(int force, wchar_t *file) { int LoadSettings(int force, wchar_t *file)
if (dm && !force) return 0; {
if (dm && !force)
return 0;
// Could just do ClearDevices() instead, but if I ever add any extra stuff, // Could just do ClearDevices() instead, but if I ever add any extra stuff,
// this will still work. // this will still work.
UnloadConfigs(); UnloadConfigs();
dm = new InputDeviceManager(); dm = new InputDeviceManager();
CfgHelper cfg; CfgHelper cfg;
for (size_t i=0; i<sizeof(BoolOptionsInfo)/sizeof(BoolOptionsInfo[0]); i++) { for (size_t i = 0; i < sizeof(BoolOptionsInfo) / sizeof(BoolOptionsInfo[0]); i++) {
config.bools[i] = cfg.ReadBool(L"General Settings", BoolOptionsInfo[i].name, BoolOptionsInfo[i].defaultValue); config.bools[i] = cfg.ReadBool(L"General Settings", BoolOptionsInfo[i].name, BoolOptionsInfo[i].defaultValue);
} }
config.closeHacks = (u8)cfg.ReadInt(L"General Settings", L"Close Hacks"); config.closeHacks = (u8)cfg.ReadInt(L"General Settings", L"Close Hacks");
if (config.closeHacks&1) config.closeHacks &= ~2; if (config.closeHacks & 1)
config.closeHacks &= ~2;
config.keyboardApi = (DeviceAPI)cfg.ReadInt(L"General Settings", L"Keyboard Mode", LNX_KEYBOARD); config.keyboardApi = (DeviceAPI)cfg.ReadInt(L"General Settings", L"Keyboard Mode", LNX_KEYBOARD);
if (!config.keyboardApi) config.keyboardApi = LNX_KEYBOARD; if (!config.keyboardApi)
config.mouseApi = (DeviceAPI) cfg.ReadInt(L"General Settings", L"Mouse Mode"); config.keyboardApi = LNX_KEYBOARD;
config.mouseApi = (DeviceAPI)cfg.ReadInt(L"General Settings", L"Mouse Mode");
for (int port=0; port<2; port++) { for (int port = 0; port < 2; port++) {
for (int slot=0; slot<4; slot++) { for (int slot = 0; slot < 4; slot++) {
wchar_t temp[50]; wchar_t temp[50];
wsprintf(temp, L"Pad %i %i", port, slot); wsprintf(temp, L"Pad %i %i", port, slot);
config.padConfigs[port][slot].type = (PadType) cfg.ReadInt(temp, L"Mode", Dualshock2Pad); config.padConfigs[port][slot].type = (PadType)cfg.ReadInt(temp, L"Mode", Dualshock2Pad);
config.padConfigs[port][slot].autoAnalog = cfg.ReadBool(temp, L"Auto Analog"); config.padConfigs[port][slot].autoAnalog = cfg.ReadBool(temp, L"Auto Analog");
} }
} }
int i=0; int i = 0;
int multipleBinding = config.multipleBinding; int multipleBinding = config.multipleBinding;
// Disabling multiple binding only prevents new multiple bindings. // Disabling multiple binding only prevents new multiple bindings.
config.multipleBinding = 1; config.multipleBinding = 1;
while (1) { while (1) {
wchar_t id[50]; wchar_t id[50];
wchar_t temp[50], temp2[1000], temp3[1000], temp4[1000]; wchar_t temp[50], temp2[1000], temp3[1000], temp4[1000];
wsprintfW(id, L"Device %i", i++); wsprintfW(id, L"Device %i", i++);
if (!cfg.ReadStr(id, L"Display Name", temp2) || !temp2[0] || if (!cfg.ReadStr(id, L"Display Name", temp2) || !temp2[0] ||
!cfg.ReadStr(id, L"Instance ID", temp3) || !temp3[0]) { !cfg.ReadStr(id, L"Instance ID", temp3) || !temp3[0]) {
if (i >= 100) break; if (i >= 100)
continue; break;
} continue;
wchar_t *id2 = 0; }
if (cfg.ReadStr(id, L"Product ID", temp4) && temp4[0]) wchar_t *id2 = 0;
id2 = temp4; if (cfg.ReadStr(id, L"Product ID", temp4) && temp4[0])
id2 = temp4;
int api = cfg.ReadInt(id, L"API"); int api = cfg.ReadInt(id, L"API");
int type = cfg.ReadInt(id, L"Type"); int type = cfg.ReadInt(id, L"Type");
if (!api || !type) continue; if (!api || !type)
continue;
Device *dev = new Device((DeviceAPI)api, (DeviceType)type, temp2, temp3, id2); Device *dev = new Device((DeviceAPI)api, (DeviceType)type, temp2, temp3, id2);
dev->attached = 0; dev->attached = 0;
dm->AddDevice(dev); dm->AddDevice(dev);
int j = 0; int j = 0;
int last = 0; int last = 0;
while (1) { while (1) {
wsprintfW(temp, L"Binding %i", j++); wsprintfW(temp, L"Binding %i", j++);
if (!cfg.ReadStr(id, temp, temp2)) { if (!cfg.ReadStr(id, temp, temp2)) {
if (j >= 100) { if (j >= 100) {
if (!last) break; if (!last)
last = 0; break;
} last = 0;
continue; }
} continue;
last = 1; }
unsigned int uid; last = 1;
int port, command, sensitivity, turbo, slot = 0, deadZone = 0; unsigned int uid;
int w = 0; int port, command, sensitivity, turbo, slot = 0, deadZone = 0;
char string[1000]; int w = 0;
while (temp2[w]) { char string[1000];
string[w] = (char)temp2[w]; while (temp2[w]) {
w++; string[w] = (char)temp2[w];
} w++;
string[w] = 0; }
int len = sscanf(string, " %u , %i , %i , %i , %i , %i , %i", &uid, &port, &command, &sensitivity, &turbo, &slot, &deadZone); string[w] = 0;
if (len >= 5 && type) { int len = sscanf(string, " %u , %i , %i , %i , %i , %i , %i", &uid, &port, &command, &sensitivity, &turbo, &slot, &deadZone);
VirtualControl *c = dev->GetVirtualControl(uid); if (len >= 5 && type) {
if (!c) c = dev->AddVirtualControl(uid, -1); VirtualControl *c = dev->GetVirtualControl(uid);
if (c) { if (!c)
BindCommand(dev, uid, port, slot, command, sensitivity, turbo, deadZone); c = dev->AddVirtualControl(uid, -1);
} if (c) {
} BindCommand(dev, uid, port, slot, command, sensitivity, turbo, deadZone);
} }
j = 0; }
while (1) { }
wsprintfW(temp, L"FF Binding %i", j++); j = 0;
if (!cfg.ReadStr(id, temp, temp2)) { while (1) {
if (j >= 10) { wsprintfW(temp, L"FF Binding %i", j++);
if (!last) break; if (!cfg.ReadStr(id, temp, temp2)) {
last = 0; if (j >= 10) {
} if (!last)
continue; break;
} last = 0;
last = 1; }
int port, slot, motor; continue;
int w = 0; }
char string[1000]; last = 1;
char effect[1000]; int port, slot, motor;
while (temp2[w]) { int w = 0;
string[w] = (char)temp2[w]; char string[1000];
w++; char effect[1000];
} while (temp2[w]) {
string[w] = 0; string[w] = (char)temp2[w];
// wcstok not in ntdll. More effore than its worth to shave off w++;
// whitespace without it. }
if (sscanf(string, " %s %i , %i , %i", effect, &port, &motor, &slot) == 4) { string[w] = 0;
char *s = strchr(strchr(strchr(string, ',')+1, ',')+1, ','); // wcstok not in ntdll. More effore than its worth to shave off
if (!s) continue; // whitespace without it.
s++; if (sscanf(string, " %s %i , %i , %i", effect, &port, &motor, &slot) == 4) {
w = 0; char *s = strchr(strchr(strchr(string, ',') + 1, ',') + 1, ',');
while (effect[w]) { if (!s)
temp2[w] = effect[w]; continue;
w++; s++;
} w = 0;
temp2[w] = 0; while (effect[w]) {
ForceFeedbackEffectType *eff = dev->GetForcefeedbackEffect(temp2); temp2[w] = effect[w];
if (!eff) { w++;
// At the moment, don't record effect types. }
// Only used internally, anyways, so not an issue. temp2[w] = 0;
dev->AddFFEffectType(temp2, temp2, EFFECT_CONSTANT); ForceFeedbackEffectType *eff = dev->GetForcefeedbackEffect(temp2);
// eff = &dev->ffEffectTypes[dev->numFFEffectTypes-1]; if (!eff) {
} // At the moment, don't record effect types.
// Only used internally, anyways, so not an issue.
dev->AddFFEffectType(temp2, temp2, EFFECT_CONSTANT);
// eff = &dev->ffEffectTypes[dev->numFFEffectTypes-1];
}
#if 0 #if 0
ForceFeedbackBinding *b; ForceFeedbackBinding *b;
CreateEffectBinding(dev, temp2, port, slot, motor, &b); CreateEffectBinding(dev, temp2, port, slot, motor, &b);
@ -437,45 +455,47 @@ int LoadSettings(int force, wchar_t *file) {
} }
} }
#endif #endif
} }
} }
} }
config.multipleBinding = multipleBinding; config.multipleBinding = multipleBinding;
//TODO RefreshEnabledDevicesAndDisplay(1); //TODO RefreshEnabledDevicesAndDisplay(1);
RefreshEnabledDevices(1); // XXX For the moment only a subfonction RefreshEnabledDevices(1); // XXX For the moment only a subfonction
return 0; return 0;
} }
void UnloadConfigs() { void UnloadConfigs()
if (dm) { {
delete dm; if (dm) {
dm = 0; delete dm;
} dm = 0;
}
} }
void RefreshEnabledDevices(int updateDeviceList) { void RefreshEnabledDevices(int updateDeviceList)
// Clears all device state. {
static int lastXInputState = -1; // Clears all device state.
if (updateDeviceList || lastXInputState != config.gameApis.xInput) { static int lastXInputState = -1;
EnumDevices(config.gameApis.xInput); if (updateDeviceList || lastXInputState != config.gameApis.xInput) {
lastXInputState = config.gameApis.xInput; EnumDevices(config.gameApis.xInput);
} lastXInputState = config.gameApis.xInput;
}
for (int i=0; i<dm->numDevices; i++) { for (int i = 0; i < dm->numDevices; i++) {
Device *dev = dm->devices[i]; Device *dev = dm->devices[i];
// XXX windows magic? // XXX windows magic?
if (!dev->attached && dev->displayName[0] != '[') { if (!dev->attached && dev->displayName[0] != '[') {
wchar_t *newName = (wchar_t*) malloc(sizeof(wchar_t) * (wcslen(dev->displayName) + 12)); wchar_t *newName = (wchar_t *)malloc(sizeof(wchar_t) * (wcslen(dev->displayName) + 12));
wsprintfW(newName, L"[Detached] %s", dev->displayName); wsprintfW(newName, L"[Detached] %s", dev->displayName);
free(dev->displayName); free(dev->displayName);
dev->displayName = newName; dev->displayName = newName;
} }
dm->EnableDevice(i); dm->EnableDevice(i);
#if 0 // windows magic? #if 0 // windows magic?
if ((dev->type == KEYBOARD && dev->api == IGNORE_KEYBOARD) || if ((dev->type == KEYBOARD && dev->api == IGNORE_KEYBOARD) ||
(dev->type == KEYBOARD && dev->api == config.keyboardApi) || (dev->type == KEYBOARD && dev->api == config.keyboardApi) ||
(dev->type == MOUSE && dev->api == config.mouseApi) || (dev->type == MOUSE && dev->api == config.mouseApi) ||
@ -496,13 +516,14 @@ void RefreshEnabledDevices(int updateDeviceList) {
dm->DisableDevice(i); dm->DisableDevice(i);
} }
#endif #endif
} }
} }
void Configure() { void Configure()
// Can end up here without PADinit() being called first. {
LoadSettings(); // Can end up here without PADinit() being called first.
// Can also end up here after running emulator a bit, and possibly LoadSettings();
// disabling some devices due to focus changes, or releasing mouse. // Can also end up here after running emulator a bit, and possibly
RefreshEnabledDevices(0); // disabling some devices due to focus changes, or releasing mouse.
RefreshEnabledDevices(0);
} }

View File

@ -22,91 +22,91 @@
wxString CfgHelper::m_path = L"inis/LilyPad.ini"; wxString CfgHelper::m_path = L"inis/LilyPad.ini";
void CfgHelper::SetSettingsDir(const char* dir) void CfgHelper::SetSettingsDir(const char *dir)
{ {
m_path = wxString::FromAscii(dir) + L"/LilyPad.ini"; m_path = wxString::FromAscii(dir) + L"/LilyPad.ini";
} }
CfgHelper::CfgHelper() CfgHelper::CfgHelper()
{ {
m_config = new wxFileConfig(L"", L"", m_path, L"", wxCONFIG_USE_LOCAL_FILE); m_config = new wxFileConfig(L"", L"", m_path, L"", wxCONFIG_USE_LOCAL_FILE);
} }
CfgHelper::~CfgHelper() CfgHelper::~CfgHelper()
{ {
delete m_config; delete m_config;
} }
void CfgHelper::setIni(const wchar_t* Section) void CfgHelper::setIni(const wchar_t *Section)
{ {
m_config->SetPath(wxsFormat(L"/%s", Section)); m_config->SetPath(wxsFormat(L"/%s", Section));
} }
void CfgHelper::WriteBool(const wchar_t* Section, const wchar_t* Name, bool Value) void CfgHelper::WriteBool(const wchar_t *Section, const wchar_t *Name, bool Value)
{ {
setIni(Section); setIni(Section);
m_config->Write(Name, Value); m_config->Write(Name, Value);
} }
void CfgHelper::WriteInt(const wchar_t* Section, const wchar_t* Name, int Value) void CfgHelper::WriteInt(const wchar_t *Section, const wchar_t *Name, int Value)
{ {
setIni(Section); setIni(Section);
m_config->Write(Name, Value); m_config->Write(Name, Value);
} }
void CfgHelper::WriteFloat(const wchar_t* Section, const wchar_t* Name, float Value) void CfgHelper::WriteFloat(const wchar_t *Section, const wchar_t *Name, float Value)
{ {
setIni(Section); setIni(Section);
m_config->Write(Name, (double)Value); m_config->Write(Name, (double)Value);
} }
void CfgHelper::WriteStr(const wchar_t* Section, const wchar_t* Name, const wxString& Data) void CfgHelper::WriteStr(const wchar_t *Section, const wchar_t *Name, const wxString &Data)
{ {
setIni(Section); setIni(Section);
m_config->Write(Name, Data); m_config->Write(Name, Data);
} }
bool CfgHelper::ReadBool(const wchar_t *Section,const wchar_t* Name, bool Default) bool CfgHelper::ReadBool(const wchar_t *Section, const wchar_t *Name, bool Default)
{ {
bool ret; bool ret;
setIni(Section); setIni(Section);
m_config->Read(Name, &ret, Default); m_config->Read(Name, &ret, Default);
return ret; return ret;
} }
int CfgHelper::ReadInt(const wchar_t* Section, const wchar_t* Name,int Default) int CfgHelper::ReadInt(const wchar_t *Section, const wchar_t *Name, int Default)
{ {
int ret; int ret;
setIni(Section); setIni(Section);
m_config->Read(Name, &ret, Default); m_config->Read(Name, &ret, Default);
return ret; return ret;
} }
float CfgHelper::ReadFloat(const wchar_t* Section, const wchar_t* Name, float Default) float CfgHelper::ReadFloat(const wchar_t *Section, const wchar_t *Name, float Default)
{ {
double ret; double ret;
setIni(Section); setIni(Section);
m_config->Read(Name, &ret, (double)Default); m_config->Read(Name, &ret, (double)Default);
return (float)ret; return (float)ret;
} }
int CfgHelper::ReadStr(const wchar_t* Section, const wchar_t* Name, wchar_t* Data, const wchar_t* Default) int CfgHelper::ReadStr(const wchar_t *Section, const wchar_t *Name, wchar_t *Data, const wchar_t *Default)
{ {
setIni(Section); setIni(Section);
wcscpy(Data, m_config->Read(Name, Default).wc_str()); wcscpy(Data, m_config->Read(Name, Default).wc_str());
return wcslen(Data); return wcslen(Data);
} }
int CfgHelper::ReadStr(const wchar_t* Section, const wchar_t* Name, wxString& Data, const wchar_t* Default) int CfgHelper::ReadStr(const wchar_t *Section, const wchar_t *Name, wxString &Data, const wchar_t *Default)
{ {
setIni(Section); setIni(Section);
Data = m_config->Read(Name, Default); Data = m_config->Read(Name, Default);
return Data.size(); return Data.size();
} }

View File

@ -20,29 +20,29 @@
#include "Global.h" #include "Global.h"
#include <wx/fileconf.h> #include <wx/fileconf.h>
extern void CfgSetSettingsDir(const char* dir); extern void CfgSetSettingsDir(const char *dir);
class CfgHelper { class CfgHelper
wxFileConfig* m_config; {
static wxString m_path; wxFileConfig *m_config;
static wxString m_path;
void setIni(const wchar_t* Section); void setIni(const wchar_t *Section);
public: public:
CfgHelper(); CfgHelper();
~CfgHelper(); ~CfgHelper();
void WriteBool(const wchar_t* Section, const wchar_t* Name, bool Value); void WriteBool(const wchar_t *Section, const wchar_t *Name, bool Value);
void WriteInt(const wchar_t* Section, const wchar_t* Name, int Value); void WriteInt(const wchar_t *Section, const wchar_t *Name, int Value);
void WriteFloat(const wchar_t* Section, const wchar_t* Name, float Value); void WriteFloat(const wchar_t *Section, const wchar_t *Name, float Value);
void WriteStr(const wchar_t* Section, const wchar_t* Name, const wxString& Data); void WriteStr(const wchar_t *Section, const wchar_t *Name, const wxString &Data);
bool ReadBool(const wchar_t *Section,const wchar_t* Name, bool Default = false); bool ReadBool(const wchar_t *Section, const wchar_t *Name, bool Default = false);
int ReadStr(const wchar_t* Section, const wchar_t* Name, wxString& Data, const wchar_t* Default = 0); int ReadStr(const wchar_t *Section, const wchar_t *Name, wxString &Data, const wchar_t *Default = 0);
int ReadStr(const wchar_t* Section, const wchar_t* Name, wchar_t* Data, const wchar_t* Default = 0); int ReadStr(const wchar_t *Section, const wchar_t *Name, wchar_t *Data, const wchar_t *Default = 0);
int ReadInt(const wchar_t* Section, const wchar_t* Name,int Default = 0); int ReadInt(const wchar_t *Section, const wchar_t *Name, int Default = 0);
float ReadFloat(const wchar_t* Section, const wchar_t* Name, float Default = 0.0f); float ReadFloat(const wchar_t *Section, const wchar_t *Name, float Default = 0.0f);
static void SetSettingsDir(const char* dir);
static void SetSettingsDir(const char *dir);
}; };

View File

@ -20,189 +20,191 @@
#include "Linux/JoyEvdev.h" #include "Linux/JoyEvdev.h"
#include "Linux/bitmaskros.h" #include "Linux/bitmaskros.h"
JoyEvdev::JoyEvdev(int fd, bool ds3, const wchar_t *id) : Device(LNX_JOY, OTHER, id, id), m_fd(fd) { JoyEvdev::JoyEvdev(int fd, bool ds3, const wchar_t *id)
// XXX LNX_JOY => DS3 or ??? : Device(LNX_JOY, OTHER, id, id)
, m_fd(fd)
{
// XXX LNX_JOY => DS3 or ???
m_abs.clear(); m_abs.clear();
m_btn.clear(); m_btn.clear();
m_rel.clear(); m_rel.clear();
int last = 0; int last = 0;
uint8_t abs_bitmap[nUcharsForNBits(ABS_CNT)] = {0}; uint8_t abs_bitmap[nUcharsForNBits(ABS_CNT)] = {0};
uint8_t btn_bitmap[nUcharsForNBits(KEY_CNT)] = {0}; uint8_t btn_bitmap[nUcharsForNBits(KEY_CNT)] = {0};
uint8_t rel_bitmap[nUcharsForNBits(REL_CNT)] = {0}; uint8_t rel_bitmap[nUcharsForNBits(REL_CNT)] = {0};
// Add buttons // Add buttons
if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(btn_bitmap)), btn_bitmap) >= 0) { if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(btn_bitmap)), btn_bitmap) >= 0) {
for (int bit = BTN_MISC; bit < KEY_CNT; bit++) { for (int bit = BTN_MISC; bit < KEY_CNT; bit++) {
if (testBit(bit, btn_bitmap)) { if (testBit(bit, btn_bitmap)) {
AddPhysicalControl(PSHBTN, last, 0); AddPhysicalControl(PSHBTN, last, 0);
m_btn.push_back(bit); m_btn.push_back(bit);
last++; last++;
} }
} }
} }
// Add Absolute axis // Add Absolute axis
if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmap)), abs_bitmap) >= 0) { if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmap)), abs_bitmap) >= 0) {
for (int bit = 0; bit < ABS_CNT; bit++) { for (int bit = 0; bit < ABS_CNT; bit++) {
ControlType type = ABSAXIS; // FIXME DS3 ControlType type = ABSAXIS; // FIXME DS3
if (testBit(bit, abs_bitmap)) { if (testBit(bit, abs_bitmap)) {
input_absinfo info; input_absinfo info;
if (ioctl(m_fd, EVIOCGABS(bit), &info) < 0) { if (ioctl(m_fd, EVIOCGABS(bit), &info) < 0) {
fprintf(stderr, "Invalid IOCTL EVIOCGID\n"); fprintf(stderr, "Invalid IOCTL EVIOCGID\n");
continue; continue;
} }
AddPhysicalControl(ABSAXIS, last, 0); AddPhysicalControl(ABSAXIS, last, 0);
last++; last++;
if (std::abs(info.value - 127) < 2) { if (std::abs(info.value - 127) < 2) {
fprintf(stderr, "HALF Axis info %d=>%d, current %d, flat %d, resolution %d\n", info.minimum, info.maximum, info.value, info.flat, info.resolution); fprintf(stderr, "HALF Axis info %d=>%d, current %d, flat %d, resolution %d\n", info.minimum, info.maximum, info.value, info.flat, info.resolution);
// Half axis must be split into 2 parts... // Half axis must be split into 2 parts...
AddPhysicalControl(ABSAXIS, last, 0); AddPhysicalControl(ABSAXIS, last, 0);
last++; last++;
m_abs.push_back(abs_info(bit, info.minimum, info.value, type)); m_abs.push_back(abs_info(bit, info.minimum, info.value, type));
m_abs.push_back(abs_info(bit, info.value, info.maximum, type)); m_abs.push_back(abs_info(bit, info.value, info.maximum, type));
} else { } else {
fprintf(stderr, "FULL Axis info %d=>%d, current %d, flat %d, resolution %d\n", info.minimum, info.maximum, info.value, info.flat, info.resolution); fprintf(stderr, "FULL Axis info %d=>%d, current %d, flat %d, resolution %d\n", info.minimum, info.maximum, info.value, info.flat, info.resolution);
m_abs.push_back(abs_info(bit, info.minimum, info.maximum, type)); m_abs.push_back(abs_info(bit, info.minimum, info.maximum, type));
} }
} }
} }
} }
// Add relative axis // Add relative axis
if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmap)), rel_bitmap) >= 0) { if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmap)), rel_bitmap) >= 0) {
for (int bit = 0; bit < REL_CNT; bit++) { for (int bit = 0; bit < REL_CNT; bit++) {
if (testBit(bit, rel_bitmap)) { if (testBit(bit, rel_bitmap)) {
AddPhysicalControl(RELAXIS, last, last); AddPhysicalControl(RELAXIS, last, last);
m_rel.push_back(bit); m_rel.push_back(bit);
last++; last++;
fprintf(stderr, "Add relative nb %d\n", bit); fprintf(stderr, "Add relative nb %d\n", bit);
} }
} }
} }
fprintf(stderr, "New device created. Found axe:%zu, buttons:%zu, m_rel:%zu\n\n", m_abs.size(), m_btn.size(), m_rel.size()); fprintf(stderr, "New device created. Found axe:%zu, buttons:%zu, m_rel:%zu\n\n", m_abs.size(), m_btn.size(), m_rel.size());
} }
JoyEvdev::~JoyEvdev() { JoyEvdev::~JoyEvdev()
close(m_fd); {
close(m_fd);
} }
int JoyEvdev::Activate(InitInfo* args) { int JoyEvdev::Activate(InitInfo *args)
AllocState(); {
AllocState();
uint16_t size = m_abs.size()+m_rel.size()+m_btn.size(); uint16_t size = m_abs.size() + m_rel.size() + m_btn.size();
memset(physicalControlState, 0, sizeof(int)*size); memset(physicalControlState, 0, sizeof(int) * size);
active = 1; active = 1;
return 1; return 1;
} }
int JoyEvdev::Update() { int JoyEvdev::Update()
{
struct input_event events[32]; struct input_event events[32];
int len; int len;
int status = 0; int status = 0;
//fprintf(stderr, "Update was called\n"); //fprintf(stderr, "Update was called\n");
// Do a big read to reduce kernel validation // Do a big read to reduce kernel validation
while ((len = read(m_fd, events, (sizeof events))) > 0) { while ((len = read(m_fd, events, (sizeof events))) > 0) {
int evt_nb = len / sizeof(input_event); int evt_nb = len / sizeof(input_event);
//fprintf(stderr, "Poll %d events available\n", evt_nb); //fprintf(stderr, "Poll %d events available\n", evt_nb);
for (int i = 0; i < evt_nb; i++) { for (int i = 0; i < evt_nb; i++) {
switch(events[i].type) { switch (events[i].type) {
case EV_ABS: case EV_ABS: {
{ for (size_t idx = 0; idx < m_abs.size(); idx++) {
for (size_t idx = 0; idx < m_abs.size(); idx++) { if (m_abs[idx].code == events[i].code) {
if (m_abs[idx].code == events[i].code) { // XXX strict or not ?
// XXX strict or not ? if ((events[i].value >= m_abs[idx].min) && (events[i].value <= m_abs[idx].max)) {
if ((events[i].value >= m_abs[idx].min) && (events[i].value <= m_abs[idx].max)) { // XXX FIX shitty api
// XXX FIX shitty api int scale = m_abs[idx].scale(events[i].value);
int scale = m_abs[idx].scale(events[i].value); fprintf(stderr, "axis value %d scaled to %d\n", events[i].value, scale);
fprintf(stderr, "axis value %d scaled to %d\n", events[i].value, scale); physicalControlState[idx + m_btn.size()] = scale;
physicalControlState[idx + m_btn.size()] = scale; status = 1;
status = 1; }
} }
} }
} } break;
} case EV_KEY: {
break; for (size_t idx = 0; idx < m_btn.size(); idx++) {
case EV_KEY: if (m_btn[idx] == events[i].code) {
{ fprintf(stderr, "Event KEY:%d detected with value %d\n", events[i].code, events[i].value);
for (size_t idx = 0; idx < m_btn.size(); idx++) { physicalControlState[idx] = FULLY_DOWN * events[i].value;
if (m_btn[idx] == events[i].code) { status = 1;
fprintf(stderr, "Event KEY:%d detected with value %d\n", events[i].code, events[i].value); break;
physicalControlState[idx] = FULLY_DOWN * events[i].value; }
status = 1; }
break;
}
}
} } break;
break; case EV_REL:
case EV_REL: // XXX
// XXX break;
break; default:
default: break;
break; }
} }
} }
} return status;
return status;
} }
static std::wstring CorrectJoySupport(int fd) { static std::wstring CorrectJoySupport(int fd)
struct input_id id; {
if (ioctl(fd, EVIOCGID, &id) < 0) { struct input_id id;
fprintf(stderr, "Invalid IOCTL EVIOCGID\n"); if (ioctl(fd, EVIOCGID, &id) < 0) {
return L""; fprintf(stderr, "Invalid IOCTL EVIOCGID\n");
} return L"";
}
char dev_name[128]; char dev_name[128];
if (ioctl(fd, EVIOCGNAME(128), dev_name) < 0) { if (ioctl(fd, EVIOCGNAME(128), dev_name) < 0) {
fprintf(stderr, "Invalid IOCTL EVIOCGNAME\n"); fprintf(stderr, "Invalid IOCTL EVIOCGNAME\n");
return L""; return L"";
} }
fprintf(stderr, "Found input device => bustype:%x, vendor:%x, product:%x, version:%x\n", id.bustype, id.vendor, id.product, id.version); fprintf(stderr, "Found input device => bustype:%x, vendor:%x, product:%x, version:%x\n", id.bustype, id.vendor, id.product, id.version);
fprintf(stderr, "\tName:%s\n", dev_name); fprintf(stderr, "\tName:%s\n", dev_name);
std::string s(dev_name); std::string s(dev_name);
return std::wstring(s.begin(), s.end()); return std::wstring(s.begin(), s.end());
} }
void EnumJoystickEvdev() { void EnumJoystickEvdev()
// Technically it must be done with udev but another lib for {
// avoid a loop is too much for me (even if udev is mandatory // Technically it must be done with udev but another lib for
// so maybe later) // avoid a loop is too much for me (even if udev is mandatory
int found_devices = 0; // so maybe later)
std::string input_root("/dev/input/event"); int found_devices = 0;
for (int i = 0; i < 32; i++) { std::string input_root("/dev/input/event");
std::string dev = input_root + std::to_string(i); for (int i = 0; i < 32; i++) {
std::string dev = input_root + std::to_string(i);
int fd = open(dev.c_str(), O_RDWR | O_NONBLOCK); int fd = open(dev.c_str(), O_RDWR | O_NONBLOCK);
if (fd < 0) { if (fd < 0) {
continue; continue;
} }
std::wstring id = CorrectJoySupport(fd);
if (id.size() != 0) {
bool ds3 = id.find(L"PLAYSTATION(R)3") != std::string::npos;
if (ds3) {
fprintf(stderr, "DS3 device detected !!!\n");
}
dm->AddDevice(new JoyEvdev(fd, ds3, id.c_str()));
} else if (fd >= 0)
close(fd);
}
std::wstring id = CorrectJoySupport(fd);
if (id.size() != 0) {
bool ds3 = id.find(L"PLAYSTATION(R)3") != std::string::npos;
if (ds3) {
fprintf(stderr, "DS3 device detected !!!\n");
}
dm->AddDevice(new JoyEvdev(fd, ds3, id.c_str()));
} else if (fd >= 0)
close(fd);
}
} }

View File

@ -23,55 +23,62 @@
#include <fcntl.h> #include <fcntl.h>
#include <linux/input.h> #include <linux/input.h>
struct abs_info { struct abs_info
uint16_t code; {
int32_t min; uint16_t code;
int32_t max; int32_t min;
int32_t max;
int32_t factor; int32_t factor;
int32_t translation; int32_t translation;
abs_info(int32_t _code, int32_t _min, int32_t _max, ControlType type) : code(_code), min(_min), max(_max) { abs_info(int32_t _code, int32_t _min, int32_t _max, ControlType type)
translation = 0; : code(_code)
// Note: ABSAXIS ranges from -64K to 64K , min(_min)
// Note: PSHBTN ranges from 0 to 64K , max(_max)
if ((min == 0) && (max == 255)) { {
if (type == ABSAXIS) { translation = 0;
translation = 128; // Note: ABSAXIS ranges from -64K to 64K
factor = FULLY_DOWN/128; // Note: PSHBTN ranges from 0 to 64K
} else { if ((min == 0) && (max == 255)) {
factor = FULLY_DOWN/256; if (type == ABSAXIS) {
} translation = 128;
} else if ((min == -1) && (max == 1)) { factor = FULLY_DOWN / 128;
factor = FULLY_DOWN; } else {
} else if ((min == 0) && (std::abs(max - 127) < 2)) { factor = FULLY_DOWN / 256;
translation = 64; }
factor = -FULLY_DOWN/64; } else if ((min == -1) && (max == 1)) {
} else if ((max == 255) && (std::abs(min - 127) < 2)) { factor = FULLY_DOWN;
translation = 64+128; } else if ((min == 0) && (std::abs(max - 127) < 2)) {
factor = FULLY_DOWN/64; translation = 64;
} else { factor = -FULLY_DOWN / 64;
fprintf(stderr, "Scale not supported\n"); } else if ((max == 255) && (std::abs(min - 127) < 2)) {
factor = 0; translation = 64 + 128;
} factor = FULLY_DOWN / 64;
} } else {
fprintf(stderr, "Scale not supported\n");
factor = 0;
}
}
int scale(int32_t value) { int scale(int32_t value)
return (value - translation) * factor; {
} return (value - translation) * factor;
}
}; };
class JoyEvdev : public Device { class JoyEvdev : public Device
int m_fd; {
std::vector<abs_info> m_abs; int m_fd;
std::vector<uint16_t> m_btn; std::vector<abs_info> m_abs;
std::vector<uint16_t> m_rel; std::vector<uint16_t> m_btn;
std::vector<uint16_t> m_rel;
public: public:
JoyEvdev(int fd, bool ds3, const wchar_t *id); JoyEvdev(int fd, bool ds3, const wchar_t *id);
~JoyEvdev(); ~JoyEvdev();
int Activate(InitInfo* args); int Activate(InitInfo *args);
int Update(); int Update();
}; };
void EnumJoystickEvdev(); void EnumJoystickEvdev();

View File

@ -20,19 +20,20 @@
// actually it is even more but it is enough to distinguish different key // actually it is even more but it is enough to distinguish different key
#define MAX_KEYCODE (0xFF) #define MAX_KEYCODE (0xFF)
LinuxKeyboard::LinuxKeyboard() : LinuxKeyboard::LinuxKeyboard()
Device(LNX_KEYBOARD, KEYBOARD, L"displayName", L"instanceID", L"deviceID") : Device(LNX_KEYBOARD, KEYBOARD, L"displayName", L"instanceID", L"deviceID")
{ {
for (int i=0; i<MAX_KEYCODE; i++) { for (int i = 0; i < MAX_KEYCODE; i++) {
AddPhysicalControl(PSHBTN, i, i); AddPhysicalControl(PSHBTN, i, i);
} }
} }
int LinuxKeyboard::Activate(InitInfo* args) { int LinuxKeyboard::Activate(InitInfo *args)
// Always active {
active = 1; // Always active
active = 1;
AllocState(); AllocState();
#if 0 #if 0
for (int vkey=5; vkey<256; vkey++) { for (int vkey=5; vkey<256; vkey++) {
@ -44,35 +45,37 @@ int LinuxKeyboard::Activate(InitInfo* args) {
physicalControlState[vkey] = 0; physicalControlState[vkey] = 0;
} }
#endif #endif
// Every button released // Every button released
memset(physicalControlState, 0, sizeof(int)*MAX_KEYCODE); memset(physicalControlState, 0, sizeof(int) * MAX_KEYCODE);
return 1; return 1;
} }
int LinuxKeyboard::Update() { int LinuxKeyboard::Update()
keyEvent event; {
int status = 0; keyEvent event;
while (R_GetQueuedKeyEvent(&event)) { int status = 0;
switch (event.evt) { while (R_GetQueuedKeyEvent(&event)) {
case KeyPress: switch (event.evt) {
physicalControlState[MAX_KEYCODE & event.key] = FULLY_DOWN; case KeyPress:
status = 1; physicalControlState[MAX_KEYCODE & event.key] = FULLY_DOWN;
break; status = 1;
case KeyRelease: break;
physicalControlState[MAX_KEYCODE & event.key] = 0; case KeyRelease:
status = 1; physicalControlState[MAX_KEYCODE & event.key] = 0;
break; status = 1;
default: break;
//fprintf(stderr, "Unsupported event %x\n", event.evt); default:
//assert(0); //fprintf(stderr, "Unsupported event %x\n", event.evt);
break; //assert(0);
} break;
} }
}
return status; // XXX ???? return status; // XXX ????
} }
void EnumLnx() { void EnumLnx()
dm->AddDevice(new LinuxKeyboard()); {
dm->AddDevice(new LinuxKeyboard());
} }

View File

@ -19,11 +19,12 @@
#include "InputManager.h" #include "InputManager.h"
#include "KeyboardQueue.h" #include "KeyboardQueue.h"
class LinuxKeyboard : public Device { class LinuxKeyboard : public Device
public: {
LinuxKeyboard(); public:
int Activate(InitInfo* args); LinuxKeyboard();
int Update(); int Activate(InitInfo *args);
int Update();
}; };
void EnumLnx(); void EnumLnx();

View File

@ -32,30 +32,35 @@ static u8 R_lastQueuedEvent = 0;
static u8 R_nextQueuedEvent = 0; static u8 R_nextQueuedEvent = 0;
static keyEvent R_queuedEvents[R_EVENT_QUEUE_LEN]; static keyEvent R_queuedEvents[R_EVENT_QUEUE_LEN];
void R_QueueKeyEvent(const keyEvent &evt) { void R_QueueKeyEvent(const keyEvent &evt)
std::lock_guard<std::mutex> lock(core_event);
R_queuedEvents[R_lastQueuedEvent] = evt;
R_lastQueuedEvent = (R_lastQueuedEvent + 1) % R_EVENT_QUEUE_LEN;
// In case someone has a severe Parkingson's disease
assert(R_nextQueuedEvent != R_lastQueuedEvent);
}
int R_GetQueuedKeyEvent(keyEvent *event) {
if (R_lastQueuedEvent == R_nextQueuedEvent) return 0;
std::lock_guard<std::mutex> lock(core_event);
*event = R_queuedEvents[R_nextQueuedEvent];
R_nextQueuedEvent = (R_nextQueuedEvent + 1) % R_EVENT_QUEUE_LEN;
return 1;
}
void R_ClearKeyQueue() {
R_lastQueuedEvent = R_nextQueuedEvent;
}
EXPORT_C_(void) PADWriteEvent(keyEvent &evt)
{ {
R_QueueKeyEvent(evt); std::lock_guard<std::mutex> lock(core_event);
R_queuedEvents[R_lastQueuedEvent] = evt;
R_lastQueuedEvent = (R_lastQueuedEvent + 1) % R_EVENT_QUEUE_LEN;
// In case someone has a severe Parkingson's disease
assert(R_nextQueuedEvent != R_lastQueuedEvent);
}
int R_GetQueuedKeyEvent(keyEvent *event)
{
if (R_lastQueuedEvent == R_nextQueuedEvent)
return 0;
std::lock_guard<std::mutex> lock(core_event);
*event = R_queuedEvents[R_nextQueuedEvent];
R_nextQueuedEvent = (R_nextQueuedEvent + 1) % R_EVENT_QUEUE_LEN;
return 1;
}
void R_ClearKeyQueue()
{
R_lastQueuedEvent = R_nextQueuedEvent;
}
EXPORT_C_(void)
PADWriteEvent(keyEvent &evt)
{
R_QueueKeyEvent(evt);
} }
#endif #endif

View File

@ -21,20 +21,20 @@
*/ */
/* Number of bits for 1 unsigned char */ /* Number of bits for 1 unsigned char */
#define nBitsPerUchar (sizeof(unsigned char) * 8) #define nBitsPerUchar (sizeof(unsigned char) * 8)
/* Number of unsigned chars to contain a given number of bits */ /* Number of unsigned chars to contain a given number of bits */
#define nUcharsForNBits(nBits) ((((nBits)-1)/nBitsPerUchar)+1) #define nUcharsForNBits(nBits) ((((nBits)-1) / nBitsPerUchar) + 1)
/* Index=Offset of given bit in 1 unsigned char */ /* Index=Offset of given bit in 1 unsigned char */
#define bitOffsetInUchar(bit) ((bit)%nBitsPerUchar) #define bitOffsetInUchar(bit) ((bit) % nBitsPerUchar)
/* Index=Offset of the unsigned char associated to the bit /* Index=Offset of the unsigned char associated to the bit
at the given index=offset */ at the given index=offset */
#define ucharIndexForBit(bit) ((bit)/nBitsPerUchar) #define ucharIndexForBit(bit) ((bit) / nBitsPerUchar)
/* Value of an unsigned char with bit set at given index=offset */ /* Value of an unsigned char with bit set at given index=offset */
#define ucharValueForBit(bit) (((unsigned char)(1))<<bitOffsetInUchar(bit)) #define ucharValueForBit(bit) (((unsigned char)(1)) << bitOffsetInUchar(bit))
/* Test the bit with given index=offset in an unsigned char array */ /* Test the bit with given index=offset in an unsigned char array */
#define testBit(bit, array) ((array[ucharIndexForBit(bit)] >> bitOffsetInUchar(bit)) & 1) #define testBit(bit, array) ((array[ucharIndexForBit(bit)] >> bitOffsetInUchar(bit)) & 1)

View File

@ -26,44 +26,48 @@
ExtraWndProcResult RawInputWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *output); ExtraWndProcResult RawInputWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *output);
int GetRawKeyboards(HWND hWnd) { int GetRawKeyboards(HWND hWnd)
RAWINPUTDEVICE Rid; {
Rid.hwndTarget = hWnd; RAWINPUTDEVICE Rid;
Rid.hwndTarget = hWnd;
Rid.dwFlags = 0; Rid.dwFlags = 0;
Rid.usUsagePage = 0x01; Rid.usUsagePage = 0x01;
Rid.usUsage = 0x06; Rid.usUsage = 0x06;
return RegisterRawInputDevices(&Rid, 1, sizeof(Rid)); return RegisterRawInputDevices(&Rid, 1, sizeof(Rid));
} }
void ReleaseRawKeyboards() { void ReleaseRawKeyboards()
RAWINPUTDEVICE Rid; {
Rid.hwndTarget = 0; RAWINPUTDEVICE Rid;
Rid.hwndTarget = 0;
Rid.dwFlags = RIDEV_REMOVE; Rid.dwFlags = RIDEV_REMOVE;
Rid.usUsagePage = 0x01; Rid.usUsagePage = 0x01;
Rid.usUsage = 0x06; Rid.usUsage = 0x06;
RegisterRawInputDevices(&Rid, 1, sizeof(Rid)); RegisterRawInputDevices(&Rid, 1, sizeof(Rid));
} }
int GetRawMice(HWND hWnd) { int GetRawMice(HWND hWnd)
RAWINPUTDEVICE Rid; {
Rid.hwndTarget = hWnd; RAWINPUTDEVICE Rid;
Rid.hwndTarget = hWnd;
Rid.dwFlags = RIDEV_NOLEGACY | RIDEV_CAPTUREMOUSE; Rid.dwFlags = RIDEV_NOLEGACY | RIDEV_CAPTUREMOUSE;
Rid.usUsagePage = 0x01; Rid.usUsagePage = 0x01;
Rid.usUsage = 0x02; Rid.usUsage = 0x02;
return RegisterRawInputDevices(&Rid, 1, sizeof(Rid)); return RegisterRawInputDevices(&Rid, 1, sizeof(Rid));
} }
void ReleaseRawMice() { void ReleaseRawMice()
RAWINPUTDEVICE Rid; {
Rid.hwndTarget = 0; RAWINPUTDEVICE Rid;
Rid.hwndTarget = 0;
Rid.dwFlags = RIDEV_REMOVE; Rid.dwFlags = RIDEV_REMOVE;
Rid.usUsagePage = 0x01; Rid.usUsagePage = 0x01;
Rid.usUsage = 0x02; Rid.usUsage = 0x02;
RegisterRawInputDevices(&Rid, 1, sizeof(Rid)); RegisterRawInputDevices(&Rid, 1, sizeof(Rid));
} }
// Count of active raw keyboard devices. // Count of active raw keyboard devices.
@ -72,234 +76,256 @@ static int rawKeyboardActivatedCount = 0;
// Same for mice. // Same for mice.
static int rawMouseActivatedCount = 0; static int rawMouseActivatedCount = 0;
class RawInputKeyboard : public WindowsKeyboard { class RawInputKeyboard : public WindowsKeyboard
{
public: public:
HANDLE hDevice; HANDLE hDevice;
RawInputKeyboard(HANDLE hDevice, wchar_t *name, wchar_t *instanceID=0) : WindowsKeyboard(RAW, name, instanceID) { RawInputKeyboard(HANDLE hDevice, wchar_t *name, wchar_t *instanceID = 0)
this->hDevice = hDevice; : WindowsKeyboard(RAW, name, instanceID)
} {
this->hDevice = hDevice;
}
int Activate(InitInfo *initInfo) { int Activate(InitInfo *initInfo)
Deactivate(); {
Deactivate();
hWndProc = initInfo->hWndProc; hWndProc = initInfo->hWndProc;
active = 1; active = 1;
if (!rawKeyboardActivatedCount++) { if (!rawKeyboardActivatedCount++) {
if (!rawMouseActivatedCount) if (!rawMouseActivatedCount)
hWndProc->Eat(RawInputWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES); hWndProc->Eat(RawInputWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
if (!GetRawKeyboards(hWndProc->hWndEaten)) { if (!GetRawKeyboards(hWndProc->hWndEaten)) {
Deactivate(); Deactivate();
return 0; return 0;
} }
} }
InitState(); InitState();
return 1; return 1;
} }
void Deactivate() { void Deactivate()
FreeState(); {
if (active) { FreeState();
active = 0; if (active) {
rawKeyboardActivatedCount --; active = 0;
if (!rawKeyboardActivatedCount) { rawKeyboardActivatedCount--;
ReleaseRawKeyboards(); if (!rawKeyboardActivatedCount) {
if (!rawMouseActivatedCount) ReleaseRawKeyboards();
hWndProc->ReleaseExtraProc(RawInputWndProc); if (!rawMouseActivatedCount)
} hWndProc->ReleaseExtraProc(RawInputWndProc);
} }
} }
}
}; };
class RawInputMouse : public WindowsMouse { class RawInputMouse : public WindowsMouse
{
public: public:
HANDLE hDevice; HANDLE hDevice;
RawInputMouse(HANDLE hDevice, wchar_t *name, wchar_t *instanceID=0, wchar_t *productID=0) : WindowsMouse(RAW, 0, name, instanceID, productID) { RawInputMouse(HANDLE hDevice, wchar_t *name, wchar_t *instanceID = 0, wchar_t *productID = 0)
this->hDevice = hDevice; : WindowsMouse(RAW, 0, name, instanceID, productID)
} {
this->hDevice = hDevice;
}
int Activate(InitInfo *initInfo) { int Activate(InitInfo *initInfo)
Deactivate(); {
Deactivate();
hWndProc = initInfo->hWndProc; hWndProc = initInfo->hWndProc;
active = 1; active = 1;
// Have to be careful with order. At worst, one unmatched call to ReleaseRawMice on // Have to be careful with order. At worst, one unmatched call to ReleaseRawMice on
// EatWndProc fail. In all other cases, no unmatched initialization/cleanup // EatWndProc fail. In all other cases, no unmatched initialization/cleanup
// lines. // lines.
if (!rawMouseActivatedCount++) { if (!rawMouseActivatedCount++) {
GetMouseCapture(hWndProc->hWndEaten); GetMouseCapture(hWndProc->hWndEaten);
if (!rawKeyboardActivatedCount) if (!rawKeyboardActivatedCount)
hWndProc->Eat(RawInputWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES); hWndProc->Eat(RawInputWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
if (!GetRawMice(hWndProc->hWndEaten)) { if (!GetRawMice(hWndProc->hWndEaten)) {
Deactivate(); Deactivate();
return 0; return 0;
} }
} }
AllocState(); AllocState();
return 1; return 1;
} }
void Deactivate() { void Deactivate()
FreeState(); {
if (active) { FreeState();
active = 0; if (active) {
rawMouseActivatedCount --; active = 0;
if (!rawMouseActivatedCount) { rawMouseActivatedCount--;
ReleaseRawMice(); if (!rawMouseActivatedCount) {
ReleaseMouseCapture(); ReleaseRawMice();
if (!rawKeyboardActivatedCount) { ReleaseMouseCapture();
hWndProc->ReleaseExtraProc(RawInputWndProc); if (!rawKeyboardActivatedCount) {
} hWndProc->ReleaseExtraProc(RawInputWndProc);
} }
} }
} }
}
}; };
ExtraWndProcResult RawInputWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *output) { ExtraWndProcResult RawInputWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *output)
if (uMsg == WM_INPUT) { {
if (GET_RAWINPUT_CODE_WPARAM (wParam) == RIM_INPUT) { if (uMsg == WM_INPUT) {
RAWINPUT in; if (GET_RAWINPUT_CODE_WPARAM(wParam) == RIM_INPUT) {
unsigned int size = sizeof(RAWINPUT); RAWINPUT in;
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, &in, &size, sizeof(RAWINPUTHEADER)) > 0) { unsigned int size = sizeof(RAWINPUT);
for (int i=0; i<dm->numDevices; i++) { if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, &in, &size, sizeof(RAWINPUTHEADER)) > 0) {
Device *dev = dm->devices[i]; for (int i = 0; i < dm->numDevices; i++) {
if (dev->api != RAW || !dev->active) continue; Device *dev = dm->devices[i];
if (in.header.dwType == RIM_TYPEKEYBOARD && dev->type == KEYBOARD) { if (dev->api != RAW || !dev->active)
RawInputKeyboard* rik = (RawInputKeyboard*)dev; continue;
if (rik->hDevice != in.header.hDevice) continue; if (in.header.dwType == RIM_TYPEKEYBOARD && dev->type == KEYBOARD) {
RawInputKeyboard *rik = (RawInputKeyboard *)dev;
if (rik->hDevice != in.header.hDevice)
continue;
u32 uMsg = in.data.keyboard.Message; u32 uMsg = in.data.keyboard.Message;
if (!(in.data.keyboard.VKey>>8)) if (!(in.data.keyboard.VKey >> 8))
rik->UpdateKey((u8) in.data.keyboard.VKey, (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN)); rik->UpdateKey((u8)in.data.keyboard.VKey, (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN));
} } else if (in.header.dwType == RIM_TYPEMOUSE && dev->type == MOUSE) {
else if (in.header.dwType == RIM_TYPEMOUSE && dev->type == MOUSE) { RawInputMouse *rim = (RawInputMouse *)dev;
RawInputMouse* rim = (RawInputMouse*)dev; if (rim->hDevice != in.header.hDevice)
if (rim->hDevice != in.header.hDevice) continue; continue;
if (in.data.mouse.usFlags) { if (in.data.mouse.usFlags) {
// Never been set for me, and specs on what most of them // Never been set for me, and specs on what most of them
// actually mean is sorely lacking. Also, specs erroneously // actually mean is sorely lacking. Also, specs erroneously
// indicate MOUSE_MOVE_RELATIVE is a flag, when it's really // indicate MOUSE_MOVE_RELATIVE is a flag, when it's really
// 0... // 0...
continue; continue;
} }
unsigned short buttons = in.data.mouse.usButtonFlags & 0x3FF; unsigned short buttons = in.data.mouse.usButtonFlags & 0x3FF;
int button = 0; int button = 0;
while (buttons) { while (buttons) {
if (buttons & 3) { if (buttons & 3) {
// 2 is up, 1 is down. Up takes precedence over down. // 2 is up, 1 is down. Up takes precedence over down.
rim->UpdateButton(button, !(buttons & 2)); rim->UpdateButton(button, !(buttons & 2));
} }
button++; button++;
buttons >>= 2; buttons >>= 2;
} }
if (in.data.mouse.usButtonFlags & RI_MOUSE_WHEEL) { if (in.data.mouse.usButtonFlags & RI_MOUSE_WHEEL) {
rim->UpdateAxis(2, ((short)in.data.mouse.usButtonData)/WHEEL_DELTA); rim->UpdateAxis(2, ((short)in.data.mouse.usButtonData) / WHEEL_DELTA);
} }
if (in.data.mouse.lLastX || in.data.mouse.lLastY) { if (in.data.mouse.lLastX || in.data.mouse.lLastY) {
rim->UpdateAxis(0, in.data.mouse.lLastX); rim->UpdateAxis(0, in.data.mouse.lLastX);
rim->UpdateAxis(1, in.data.mouse.lLastY); rim->UpdateAxis(1, in.data.mouse.lLastY);
} }
} }
} }
} }
} }
} } else if (uMsg == WM_ACTIVATE) {
else if (uMsg == WM_ACTIVATE) { for (int i = 0; i < dm->numDevices; i++) {
for (int i=0; i<dm->numDevices; i++) { Device *dev = dm->devices[i];
Device *dev = dm->devices[i]; if (dev->api != RAW || dev->physicalControlState == 0)
if (dev->api != RAW || dev->physicalControlState == 0) continue; continue;
memset(dev->physicalControlState, 0, sizeof(int) * dev->numPhysicalControls); memset(dev->physicalControlState, 0, sizeof(int) * dev->numPhysicalControls);
} }
} } else if (uMsg == WM_SIZE && rawMouseActivatedCount) {
else if (uMsg == WM_SIZE && rawMouseActivatedCount) { // Doesn't really matter for raw mice, as I disable legacy stuff, but shouldn't hurt.
// Doesn't really matter for raw mice, as I disable legacy stuff, but shouldn't hurt. WindowsMouse::WindowResized(hWnd);
WindowsMouse::WindowResized(hWnd); }
}
return CONTINUE_BLISSFULLY; return CONTINUE_BLISSFULLY;
} }
void EnumRawInputDevices() { void EnumRawInputDevices()
int count = 0; {
if (GetRawInputDeviceList(0, (unsigned int*)&count, sizeof(RAWINPUTDEVICELIST)) != (UINT)-1 && count > 0) { int count = 0;
wchar_t *instanceID = (wchar_t *) malloc(41000*sizeof(wchar_t)); if (GetRawInputDeviceList(0, (unsigned int *)&count, sizeof(RAWINPUTDEVICELIST)) != (UINT)-1 && count > 0) {
wchar_t *keyName = instanceID + 11000; wchar_t *instanceID = (wchar_t *)malloc(41000 * sizeof(wchar_t));
wchar_t *displayName = keyName + 10000; wchar_t *keyName = instanceID + 11000;
wchar_t *productID = displayName + 10000; wchar_t *displayName = keyName + 10000;
wchar_t *productID = displayName + 10000;
RAWINPUTDEVICELIST *list = (RAWINPUTDEVICELIST*) malloc(sizeof(RAWINPUTDEVICELIST) * count); RAWINPUTDEVICELIST *list = (RAWINPUTDEVICELIST *)malloc(sizeof(RAWINPUTDEVICELIST) * count);
int keyboardCount = 1; int keyboardCount = 1;
int mouseCount = 1; int mouseCount = 1;
count = GetRawInputDeviceList(list, (unsigned int*)&count, sizeof(RAWINPUTDEVICELIST)); count = GetRawInputDeviceList(list, (unsigned int *)&count, sizeof(RAWINPUTDEVICELIST));
// Not necessary, but reminder that count is -1 on failure. // Not necessary, but reminder that count is -1 on failure.
if (count > 0) { if (count > 0) {
for (int i=0; i<count; i++) { for (int i = 0; i < count; i++) {
if (list[i].dwType != RIM_TYPEKEYBOARD && list[i].dwType != RIM_TYPEMOUSE) continue; if (list[i].dwType != RIM_TYPEKEYBOARD && list[i].dwType != RIM_TYPEMOUSE)
continue;
UINT bufferLen = 10000; UINT bufferLen = 10000;
int nameLen = GetRawInputDeviceInfo(list[i].hDevice, RIDI_DEVICENAME, instanceID, &bufferLen); int nameLen = GetRawInputDeviceInfo(list[i].hDevice, RIDI_DEVICENAME, instanceID, &bufferLen);
if (nameLen >= 4) { if (nameLen >= 4) {
// nameLen includes terminating null. // nameLen includes terminating null.
nameLen--; nameLen--;
// Strip out GUID parts of instanceID to make it a generic product id, // Strip out GUID parts of instanceID to make it a generic product id,
// and reformat it to point to registry entry containing device description. // and reformat it to point to registry entry containing device description.
wcscpy(productID, instanceID); wcscpy(productID, instanceID);
wchar_t *temp = 0; wchar_t *temp = 0;
for (int j=0; j<3; j++) { for (int j = 0; j < 3; j++) {
wchar_t *s = wcschr(productID, '#'); wchar_t *s = wcschr(productID, '#');
if (!s) break; if (!s)
*s = '\\'; break;
if (j==2) { *s = '\\';
*s = 0; if (j == 2) {
} *s = 0;
if (j==1) temp = s; }
} if (j == 1)
temp = s;
}
wsprintfW(keyName, L"SYSTEM\\CurrentControlSet\\Enum%s", productID+3); wsprintfW(keyName, L"SYSTEM\\CurrentControlSet\\Enum%s", productID + 3);
if (temp) *temp = 0; if (temp)
int haveDescription = 0; *temp = 0;
HKEY hKey; int haveDescription = 0;
if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyName, 0, KEY_QUERY_VALUE, &hKey)) { HKEY hKey;
DWORD type; if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyName, 0, KEY_QUERY_VALUE, &hKey)) {
DWORD len = 10000 * sizeof(wchar_t); DWORD type;
if (ERROR_SUCCESS == RegQueryValueExW(hKey, L"DeviceDesc", 0, &type, (BYTE*)displayName, &len) && DWORD len = 10000 * sizeof(wchar_t);
len && type == REG_SZ) { if (ERROR_SUCCESS == RegQueryValueExW(hKey, L"DeviceDesc", 0, &type, (BYTE *)displayName, &len) &&
wchar_t *temp2 = wcsrchr(displayName, ';'); len && type == REG_SZ) {
if (!temp2) temp2 = displayName; wchar_t *temp2 = wcsrchr(displayName, ';');
else temp2++; if (!temp2)
// Could do without this, but more effort than it's worth. temp2 = displayName;
wcscpy(keyName, temp2); else
haveDescription = 1; temp2++;
} // Could do without this, but more effort than it's worth.
RegCloseKey(hKey); wcscpy(keyName, temp2);
} haveDescription = 1;
if (list[i].dwType == RIM_TYPEKEYBOARD) { }
if (!haveDescription) wsprintfW(displayName, L"Raw Keyboard %i", keyboardCount++); RegCloseKey(hKey);
else wsprintfW(displayName, L"Raw KB: %s", keyName); }
dm->AddDevice(new RawInputKeyboard(list[i].hDevice, displayName, instanceID)); if (list[i].dwType == RIM_TYPEKEYBOARD) {
} if (!haveDescription)
else if (list[i].dwType == RIM_TYPEMOUSE) { wsprintfW(displayName, L"Raw Keyboard %i", keyboardCount++);
if (!haveDescription) wsprintfW(displayName, L"Raw Mouse %i", mouseCount++); else
else wsprintfW(displayName, L"Raw MS: %s", keyName); wsprintfW(displayName, L"Raw KB: %s", keyName);
dm->AddDevice(new RawInputMouse(list[i].hDevice, displayName, instanceID, productID)); dm->AddDevice(new RawInputKeyboard(list[i].hDevice, displayName, instanceID));
} } else if (list[i].dwType == RIM_TYPEMOUSE) {
} if (!haveDescription)
} wsprintfW(displayName, L"Raw Mouse %i", mouseCount++);
} else
free(list); wsprintfW(displayName, L"Raw MS: %s", keyName);
free(instanceID); dm->AddDevice(new RawInputMouse(list[i].hDevice, displayName, instanceID, productID));
dm->AddDevice(new RawInputKeyboard(0, L"Simulated Keyboard")); }
dm->AddDevice(new RawInputMouse(0, L"Simulated Mouse")); }
} }
}
free(list);
free(instanceID);
dm->AddDevice(new RawInputKeyboard(0, L"Simulated Keyboard"));
dm->AddDevice(new RawInputMouse(0, L"Simulated Mouse"));
}
} }

View File

@ -18,68 +18,91 @@
#include "Global.h" #include "Global.h"
#include "VKey.h" #include "VKey.h"
wchar_t *GetVKStringW(unsigned char vk) { wchar_t *GetVKStringW(unsigned char vk)
int flag; {
static wchar_t t[20]; int flag;
switch(vk) { static wchar_t t[20];
case 0x0C: return L"Clear"; switch (vk) {
case 0x13: return L"Pause"; case 0x0C:
return L"Clear";
case 0x13:
return L"Pause";
case 0x21:// return "Page Up"; case 0x21: // return "Page Up";
case 0x22:// return "Page Down"; case 0x22: // return "Page Down";
case 0x23:// return "End"; case 0x23: // return "End";
case 0x24:// return "Home"; case 0x24: // return "Home";
case 0x25:// return "Left"; case 0x25: // return "Left";
case 0x26:// return "Up"; case 0x26: // return "Up";
case 0x27:// return "Right"; case 0x27: // return "Right";
case 0x28:// return "Down"; case 0x28: // return "Down";
case 0x2D:// return "Insert"; case 0x2D: // return "Insert";
case 0x2E:// return "Delete"; case 0x2E: // return "Delete";
case 0x5B:// return "Left Windows"; case 0x5B: // return "Left Windows";
case 0x5C:// return "Right Windows"; case 0x5C: // return "Right Windows";
case 0x5D:// return "Application"; case 0x5D: // return "Application";
case 0x6F:// return "Num /"; case 0x6F: // return "Num /";
flag = 1<<24; flag = 1 << 24;
break; break;
case 0x29: return L"Select"; case 0x29:
case 0x2A: return L"Print"; return L"Select";
case 0x2B: return L"Execute"; case 0x2A:
case 0x2C: return L"Prnt Scrn"; return L"Print";
case 0x2F: return L"Help"; case 0x2B:
return L"Execute";
case 0x2C:
return L"Prnt Scrn";
case 0x2F:
return L"Help";
case 0x6C: return L"|"; case 0x6C:
case 0x90: return L"Num Lock"; return L"|";
case 0x90:
return L"Num Lock";
case 0xA0: return L"Left Shift"; case 0xA0:
case 0xA1: return L"Right Shift"; return L"Left Shift";
case 0xA2: return L"Left Ctrl"; case 0xA1:
case 0xA3: return L"Right Ctrl"; return L"Right Shift";
case 0xA4: return L"Left Alt"; case 0xA2:
case 0xA5: return L"Right Alt"; return L"Left Ctrl";
case 0xA3:
return L"Right Ctrl";
case 0xA4:
return L"Left Alt";
case 0xA5:
return L"Right Alt";
case 0xA6: return L"Back"; case 0xA6:
case 0xA7: return L"Forward"; return L"Back";
case 0xA8: return L"Refresh"; case 0xA7:
case 0xA9: return L"Stop"; return L"Forward";
case 0xAA: return L"Search"; case 0xA8:
case 0xAB: return L"Favorites"; return L"Refresh";
case 0xAC: return L"Browser"; case 0xA9:
return L"Stop";
case 0xAA:
return L"Search";
case 0xAB:
return L"Favorites";
case 0xAC:
return L"Browser";
case 0xFA: return L"Play"; case 0xFA:
case 0xFB: return L"Zoom"; return L"Play";
default: case 0xFB:
flag = 0; return L"Zoom";
break; default:
} flag = 0;
int res = MapVirtualKey(vk, MAPVK_VK_TO_VSC); break;
if (res && GetKeyNameText((res<<16) | flag, t, 20)) { }
// don't trust windows int res = MapVirtualKey(vk, MAPVK_VK_TO_VSC);
t[19] = 0; if (res && GetKeyNameText((res << 16) | flag, t, 20)) {
} // don't trust windows
else { t[19] = 0;
wsprintfW(t, L"Key %i", vk); } else {
} wsprintfW(t, L"Key %i", vk);
return t; }
return t;
} }

View File

@ -21,45 +21,51 @@
#include "WindowsKeyboard.h" #include "WindowsKeyboard.h"
#include "KeyboardQueue.h" #include "KeyboardQueue.h"
WindowsKeyboard::WindowsKeyboard(DeviceAPI api, wchar_t *displayName, wchar_t *instanceID, wchar_t *deviceID) : WindowsKeyboard::WindowsKeyboard(DeviceAPI api, wchar_t *displayName, wchar_t *instanceID, wchar_t *deviceID)
Device(api, KEYBOARD, displayName, instanceID, deviceID) { : Device(api, KEYBOARD, displayName, instanceID, deviceID)
for (int i=0; i<256; i++) { {
AddPhysicalControl(PSHBTN, i, i); for (int i = 0; i < 256; i++) {
} AddPhysicalControl(PSHBTN, i, i);
}
} }
wchar_t *WindowsKeyboard::GetPhysicalControlName(PhysicalControl *control) { wchar_t *WindowsKeyboard::GetPhysicalControlName(PhysicalControl *control)
int id = control->id; {
if (control->type == PSHBTN && id >= 0 && id < 256) { int id = control->id;
wchar_t *w = GetVKStringW(id); if (control->type == PSHBTN && id >= 0 && id < 256) {
if (w) return w; wchar_t *w = GetVKStringW(id);
} if (w)
return Device::GetPhysicalControlName(control); return w;
}
return Device::GetPhysicalControlName(control);
} }
void WindowsKeyboard::UpdateKey(int vkey, int state) { void WindowsKeyboard::UpdateKey(int vkey, int state)
if (vkey > 7 && vkey < 256) { {
int newState = state * FULLY_DOWN; if (vkey > 7 && vkey < 256) {
if (newState != physicalControlState[vkey]) { int newState = state * FULLY_DOWN;
// Check for alt-F4 to avoid toggling skip mode incorrectly. if (newState != physicalControlState[vkey]) {
if (vkey != VK_F4 || !(physicalControlState[VK_MENU] || physicalControlState[VK_RMENU] || physicalControlState[VK_LMENU])) { // Check for alt-F4 to avoid toggling skip mode incorrectly.
int event = KEYPRESS; if (vkey != VK_F4 || !(physicalControlState[VK_MENU] || physicalControlState[VK_RMENU] || physicalControlState[VK_LMENU])) {
if (!newState) event = KEYRELEASE; int event = KEYPRESS;
QueueKeyEvent(vkey, event); if (!newState)
} event = KEYRELEASE;
} QueueKeyEvent(vkey, event);
physicalControlState[vkey] = newState; }
} }
physicalControlState[vkey] = newState;
}
} }
void WindowsKeyboard::InitState() { void WindowsKeyboard::InitState()
AllocState(); {
for (int vkey=5; vkey<256; vkey++) { AllocState();
int value = (unsigned short)(((short)GetAsyncKeyState(vkey))>>15); for (int vkey = 5; vkey < 256; vkey++) {
value += value&1; int value = (unsigned short)(((short)GetAsyncKeyState(vkey)) >> 15);
if (vkey == VK_CONTROL || vkey == VK_MENU || vkey == VK_SHIFT) { value += value & 1;
value = 0; if (vkey == VK_CONTROL || vkey == VK_MENU || vkey == VK_SHIFT) {
} value = 0;
physicalControlState[vkey] = value; }
} physicalControlState[vkey] = value;
}
} }

View File

@ -16,12 +16,13 @@
*/ */
// Shared functionality for WM and RAW keyboards. // Shared functionality for WM and RAW keyboards.
class WindowsKeyboard : public Device { class WindowsKeyboard : public Device
{
public: public:
WindowsKeyboard(DeviceAPI api, wchar_t *displayName, wchar_t *instanceID=0, wchar_t *deviceID=0); WindowsKeyboard(DeviceAPI api, wchar_t *displayName, wchar_t *instanceID = 0, wchar_t *deviceID = 0);
wchar_t *GetPhysicalControlName(PhysicalControl *control); wchar_t *GetPhysicalControlName(PhysicalControl *control);
void UpdateKey(int vkey, int state); void UpdateKey(int vkey, int state);
// Calls AllocState() and initializes to current keyboard state using // Calls AllocState() and initializes to current keyboard state using
// GetAsyncKeyState(). // GetAsyncKeyState().
void InitState(); void InitState();
}; };

View File

@ -32,160 +32,162 @@ class WindowsMessagingMouse;
static WindowsMessagingKeyboard *wmk = 0; static WindowsMessagingKeyboard *wmk = 0;
static WindowsMessagingMouse *wmm = 0; static WindowsMessagingMouse *wmm = 0;
class WindowsMessagingKeyboard : public WindowsKeyboard { class WindowsMessagingKeyboard : public WindowsKeyboard
{
public: public:
WindowsMessagingKeyboard()
: WindowsKeyboard(WM, L"WM Keyboard")
{
}
WindowsMessagingKeyboard() : WindowsKeyboard(WM, L"WM Keyboard") { int Activate(InitInfo *initInfo)
} {
// Redundant. Should match the next line.
// Deactivate();
if (wmk)
wmk->Deactivate();
int Activate(InitInfo *initInfo) { hWndProc = initInfo->hWndProc;
// Redundant. Should match the next line.
// Deactivate();
if (wmk) wmk->Deactivate();
hWndProc = initInfo->hWndProc; if (!wmm)
hWndProc->Eat(WindowsMessagingWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
if (!wmm) wmk = this;
hWndProc->Eat(WindowsMessagingWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES); InitState();
wmk = this; active = 1;
InitState(); return 1;
}
active = 1; void Deactivate()
return 1; {
} if (active) {
if (!wmm)
void Deactivate() { hWndProc->ReleaseExtraProc(WindowsMessagingWndProc);
if (active) { wmk = 0;
if (!wmm) active = 0;
hWndProc->ReleaseExtraProc(WindowsMessagingWndProc); FreeState();
wmk = 0; }
active = 0; }
FreeState();
}
}
void CheckKey(int vkey) { void CheckKey(int vkey)
UpdateKey(vkey, 1&(((unsigned short)GetAsyncKeyState(vkey))>>15)); {
} UpdateKey(vkey, 1 & (((unsigned short)GetAsyncKeyState(vkey)) >> 15));
}
}; };
class WindowsMessagingMouse : public WindowsMouse { class WindowsMessagingMouse : public WindowsMouse
{
public: public:
WindowsMessagingMouse()
: WindowsMouse(WM, 1, L"WM Mouse")
{
}
WindowsMessagingMouse() : WindowsMouse(WM, 1, L"WM Mouse") { int Activate(InitInfo *initInfo)
} {
// Redundant. Should match the next line.
// Deactivate();
if (wmm)
wmm->Deactivate();
hWndProc = initInfo->hWndProc;
int Activate(InitInfo *initInfo) { if (!wmk)
// Redundant. Should match the next line. hWndProc->Eat(WindowsMessagingWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
// Deactivate();
if (wmm) wmm->Deactivate();
hWndProc = initInfo->hWndProc;
if (!wmk) GetMouseCapture(hWndProc->hWndEaten);
hWndProc->Eat(WindowsMessagingWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
GetMouseCapture(hWndProc->hWndEaten); active = 1;
active = 1; wmm = this;
AllocState();
wmm = this; return 1;
AllocState(); }
return 1; void Deactivate()
} {
if (active) {
void Deactivate() { if (!wmk)
if (active) { hWndProc->ReleaseExtraProc(WindowsMessagingWndProc);
if (!wmk) ReleaseMouseCapture();
hWndProc->ReleaseExtraProc(WindowsMessagingWndProc); wmm = 0;
ReleaseMouseCapture(); active = 0;
wmm = 0; FreeState();
active = 0; }
FreeState(); }
}
}
}; };
ExtraWndProcResult WindowsMessagingWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *output) { ExtraWndProcResult WindowsMessagingWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *output)
if (wmk) { {
if (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN || uMsg == WM_KEYUP || uMsg == WM_SYSKEYUP) { if (wmk) {
if (wParam == VK_SHIFT) { if (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN || uMsg == WM_KEYUP || uMsg == WM_SYSKEYUP) {
wmk->CheckKey(VK_RSHIFT); if (wParam == VK_SHIFT) {
wmk->CheckKey(VK_LSHIFT); wmk->CheckKey(VK_RSHIFT);
} wmk->CheckKey(VK_LSHIFT);
else if (wParam == VK_CONTROL) { } else if (wParam == VK_CONTROL) {
wmk->CheckKey(VK_RCONTROL); wmk->CheckKey(VK_RCONTROL);
wmk->CheckKey(VK_LCONTROL); wmk->CheckKey(VK_LCONTROL);
} } else if (wParam == VK_MENU) {
else if (wParam == VK_MENU) { wmk->CheckKey(VK_RMENU);
wmk->CheckKey(VK_RMENU); wmk->CheckKey(VK_LMENU);
wmk->CheckKey(VK_LMENU); } else
} wmk->UpdateKey(wParam, (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN));
else return NO_WND_PROC;
wmk->UpdateKey(wParam, (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN)); }
return NO_WND_PROC; // Needed to prevent default handling of keys in some situations.
} else if (uMsg == WM_CHAR || uMsg == WM_UNICHAR) {
// Needed to prevent default handling of keys in some situations. return NO_WND_PROC;
else if (uMsg == WM_CHAR || uMsg == WM_UNICHAR) { } else if (uMsg == WM_ACTIVATE) {
return NO_WND_PROC; // Not really needed, but doesn't hurt.
} memset(wmk->physicalControlState, 0, sizeof(int) * wmk->numPhysicalControls);
else if (uMsg == WM_ACTIVATE) { }
// Not really needed, but doesn't hurt. }
memset(wmk->physicalControlState, 0, sizeof(int) * wmk->numPhysicalControls); if (wmm) {
} if (uMsg == WM_MOUSEMOVE) {
} POINT p;
if (wmm) { GetCursorPos(&p);
if (uMsg == WM_MOUSEMOVE) { // Need check to prevent cursor movement cascade.
POINT p; if (p.x != wmm->center.x || p.y != wmm->center.y) {
GetCursorPos(&p); wmm->UpdateAxis(0, p.x - wmm->center.x);
// Need check to prevent cursor movement cascade. wmm->UpdateAxis(1, p.y - wmm->center.y);
if (p.x != wmm->center.x || p.y != wmm->center.y) {
wmm->UpdateAxis(0, p.x - wmm->center.x);
wmm->UpdateAxis(1, p.y - wmm->center.y);
SetCursorPos(wmm->center.x, wmm->center.y); SetCursorPos(wmm->center.x, wmm->center.y);
} }
return NO_WND_PROC; return NO_WND_PROC;
} } else if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP) {
else if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP) { wmm->UpdateButton(0, uMsg == WM_LBUTTONDOWN);
wmm->UpdateButton(0, uMsg == WM_LBUTTONDOWN); return NO_WND_PROC;
return NO_WND_PROC; } else if (uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONUP) {
} wmm->UpdateButton(1, uMsg == WM_RBUTTONDOWN);
else if (uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONUP) { return NO_WND_PROC;
wmm->UpdateButton(1, uMsg == WM_RBUTTONDOWN); } else if (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONUP) {
return NO_WND_PROC; wmm->UpdateButton(2, uMsg == WM_MBUTTONDOWN);
} return NO_WND_PROC;
else if (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONUP) { } else if (uMsg == WM_XBUTTONDOWN || uMsg == WM_XBUTTONUP) {
wmm->UpdateButton(2, uMsg == WM_MBUTTONDOWN); wmm->UpdateButton(3 + ((wParam >> 16) == XBUTTON2), uMsg == WM_XBUTTONDOWN);
return NO_WND_PROC; return NO_WND_PROC;
} } else if (uMsg == WM_MOUSEWHEEL) {
else if (uMsg == WM_XBUTTONDOWN || uMsg == WM_XBUTTONUP) { wmm->UpdateAxis(2, ((int)wParam >> 16) / WHEEL_DELTA);
wmm->UpdateButton(3+((wParam>>16) == XBUTTON2), uMsg == WM_XBUTTONDOWN); return NO_WND_PROC;
return NO_WND_PROC; } else if (uMsg == WM_MOUSEHWHEEL) {
} wmm->UpdateAxis(3, ((int)wParam >> 16) / WHEEL_DELTA);
else if (uMsg == WM_MOUSEWHEEL) { return NO_WND_PROC;
wmm->UpdateAxis(2, ((int)wParam>>16)/WHEEL_DELTA); } else if (uMsg == WM_SIZE && wmm->active) {
return NO_WND_PROC; WindowsMouse::WindowResized(hWnd);
} }
else if (uMsg == WM_MOUSEHWHEEL) { // Taken care of elsewhere. When binding, killing focus means stop reading input.
wmm->UpdateAxis(3, ((int)wParam>>16)/WHEEL_DELTA); // When running PCSX2, I release all mouse and keyboard input elsewhere.
return NO_WND_PROC; /*else if (uMsg == WM_KILLFOCUS) {
}
else if (uMsg == WM_SIZE && wmm->active) {
WindowsMouse::WindowResized(hWnd);
}
// Taken care of elsewhere. When binding, killing focus means stop reading input.
// When running PCSX2, I release all mouse and keyboard input elsewhere.
/*else if (uMsg == WM_KILLFOCUS) {
wmm->Deactivate(); wmm->Deactivate();
}//*/ }//*/
} }
return CONTINUE_BLISSFULLY; return CONTINUE_BLISSFULLY;
} }
void EnumWindowsMessagingDevices() { void EnumWindowsMessagingDevices()
dm->AddDevice(new WindowsMessagingKeyboard()); {
dm->AddDevice(new WindowsMessagingMouse()); dm->AddDevice(new WindowsMessagingKeyboard());
dm->AddDevice(new WindowsMessagingMouse());
} }

View File

@ -23,71 +23,80 @@
POINT WindowsMouse::origCursorPos; POINT WindowsMouse::origCursorPos;
POINT WindowsMouse::center; POINT WindowsMouse::center;
WindowsMouse::WindowsMouse(DeviceAPI api, int hWheel, wchar_t *displayName, wchar_t *instanceID, wchar_t *deviceID) : WindowsMouse::WindowsMouse(DeviceAPI api, int hWheel, wchar_t *displayName, wchar_t *instanceID, wchar_t *deviceID)
Device(api, MOUSE, displayName, instanceID, deviceID) { : Device(api, MOUSE, displayName, instanceID, deviceID)
int i; {
for (i=0; i<5; i++) { int i;
AddPhysicalControl(PSHBTN, i, i); for (i = 0; i < 5; i++) {
} AddPhysicalControl(PSHBTN, i, i);
}
for (i=0; i<3+hWheel; i++) { for (i = 0; i < 3 + hWheel; i++) {
AddPhysicalControl(RELAXIS, i+5, i+5); AddPhysicalControl(RELAXIS, i + 5, i + 5);
} }
} }
wchar_t *WindowsMouse::GetPhysicalControlName(PhysicalControl *control) { wchar_t *WindowsMouse::GetPhysicalControlName(PhysicalControl *control)
wchar_t *names[9] = { {
L"L Button", wchar_t *names[9] = {
L"R Button", L"L Button",
L"M Button", L"R Button",
L"Mouse 4", L"M Button",
L"Mouse 5", L"Mouse 4",
L"X Axis", L"Mouse 5",
L"Y Axis", L"X Axis",
L"Y Wheel", L"Y Axis",
L"X Wheel" L"Y Wheel",
}; L"X Wheel"};
if (control->id < 9) return names[control->id]; if (control->id < 9)
return Device::GetPhysicalControlName(control); return names[control->id];
return Device::GetPhysicalControlName(control);
} }
void WindowsMouse::UpdateButton(unsigned int button, int state) { void WindowsMouse::UpdateButton(unsigned int button, int state)
if (button > 4) return; {
physicalControlState[button] = (state << 16); if (button > 4)
return;
physicalControlState[button] = (state << 16);
} }
void WindowsMouse::UpdateAxis(unsigned int axis, int delta) { void WindowsMouse::UpdateAxis(unsigned int axis, int delta)
if (axis > 3) return; {
// 1 mouse pixel = 1/8th way down. if (axis > 3)
physicalControlState[5+axis] += (delta<<(16 - 3*(axis < 2))); return;
// 1 mouse pixel = 1/8th way down.
physicalControlState[5 + axis] += (delta << (16 - 3 * (axis < 2)));
} }
void WindowsMouse::WindowResized(HWND hWnd) { void WindowsMouse::WindowResized(HWND hWnd)
RECT r; {
GetWindowRect(hWnd, &r); RECT r;
ClipCursor(&r); GetWindowRect(hWnd, &r);
center.x = (r.left + r.right)/2; ClipCursor(&r);
center.y = (r.top + r.bottom)/2; center.x = (r.left + r.right) / 2;
SetCursorPos(center.x, center.y); center.y = (r.top + r.bottom) / 2;
SetCursorPos(center.x, center.y);
} }
void WindowsMouse::GetMouseCapture(HWND hWnd) { void WindowsMouse::GetMouseCapture(HWND hWnd)
SetCapture(hWnd); {
ShowCursor(0); SetCapture(hWnd);
ShowCursor(0);
GetCursorPos(&origCursorPos); GetCursorPos(&origCursorPos);
RECT r; RECT r;
GetWindowRect(hWnd, &r); GetWindowRect(hWnd, &r);
ClipCursor(&r); ClipCursor(&r);
center.x = (r.left + r.right)/2; center.x = (r.left + r.right) / 2;
center.y = (r.top + r.bottom)/2; center.y = (r.top + r.bottom) / 2;
SetCursorPos(center.x, center.y); SetCursorPos(center.x, center.y);
} }
void WindowsMouse::ReleaseMouseCapture() { void WindowsMouse::ReleaseMouseCapture()
ClipCursor(0); {
ReleaseCapture(); ClipCursor(0);
ShowCursor(1); ReleaseCapture();
SetCursorPos(origCursorPos.x, origCursorPos.y); ShowCursor(1);
SetCursorPos(origCursorPos.x, origCursorPos.y);
} }

View File

@ -16,26 +16,27 @@
*/ */
// Shared functionality for WM and RAW keyboards. // Shared functionality for WM and RAW keyboards.
class WindowsMouse : public Device { class WindowsMouse : public Device
{
public: public:
// Used by GetMouseCapture()/ReleaseMouseCapture() // Used by GetMouseCapture()/ReleaseMouseCapture()
// Static because can have multiple raw mice active at once, // Static because can have multiple raw mice active at once,
// and only get/release capture once. // and only get/release capture once.
static POINT origCursorPos; static POINT origCursorPos;
static POINT center; static POINT center;
static void GetMouseCapture(HWND hWnd); static void GetMouseCapture(HWND hWnd);
static void WindowResized(HWND hWnd); static void WindowResized(HWND hWnd);
static void ReleaseMouseCapture(); static void ReleaseMouseCapture();
// hWheel variable lets me display no horizontal wheel for raw input, just to make it clear // hWheel variable lets me display no horizontal wheel for raw input, just to make it clear
// that it's not supported. // that it's not supported.
WindowsMouse(DeviceAPI api, int hWheel, wchar_t *displayName, wchar_t *instanceID=0, wchar_t *deviceID=0); WindowsMouse(DeviceAPI api, int hWheel, wchar_t *displayName, wchar_t *instanceID = 0, wchar_t *deviceID = 0);
wchar_t *GetPhysicalControlName(PhysicalControl *control); wchar_t *GetPhysicalControlName(PhysicalControl *control);
// State is 0 for up, 1 for down. // State is 0 for up, 1 for down.
void UpdateButton(unsigned int button, int state); void UpdateButton(unsigned int button, int state);
// 0/1 are x/y. 2 is vert wheel, 3 is horiz wheel. // 0/1 are x/y. 2 is vert wheel, 3 is horiz wheel.
// Delta is in my micro units. change of (1<<16) is 1 full unit, with // Delta is in my micro units. change of (1<<16) is 1 full unit, with
// the default sensitivity. // the default sensitivity.
void UpdateAxis(unsigned int axis, int delta); void UpdateAxis(unsigned int axis, int delta);
}; };

View File

@ -20,128 +20,136 @@
WndProcEater::WndProcEater() WndProcEater::WndProcEater()
{ {
hWndEaten = 0; hWndEaten = 0;
eatenWndProc = 0; eatenWndProc = 0;
extraProcs = 0; extraProcs = 0;
numExtraProcs = 0; numExtraProcs = 0;
hMutex = CreateMutex(0, 0, L"LilyPad"); hMutex = CreateMutex(0, 0, L"LilyPad");
} }
WndProcEater::~WndProcEater() throw() WndProcEater::~WndProcEater() throw()
{ {
if (hMutex) { if (hMutex) {
ReleaseMutex(hMutex); ReleaseMutex(hMutex);
CloseHandle(hMutex); CloseHandle(hMutex);
} }
} }
void WndProcEater::ReleaseExtraProc(ExtraWndProc proc) { void WndProcEater::ReleaseExtraProc(ExtraWndProc proc)
// Probably isn't needed, but just in case... {
if (hMutex) WaitForSingleObject(hMutex, 100); // Probably isn't needed, but just in case...
if (hMutex)
WaitForSingleObject(hMutex, 100);
//printf( "(Lilypad) Regurgitating! -> 0x%x\n", proc ); //printf( "(Lilypad) Regurgitating! -> 0x%x\n", proc );
for (int i=0; i<numExtraProcs; i++) { for (int i = 0; i < numExtraProcs; i++) {
if (extraProcs[i].proc == proc) { if (extraProcs[i].proc == proc) {
extraProcs[i] = extraProcs[--numExtraProcs]; extraProcs[i] = extraProcs[--numExtraProcs];
break; break;
} }
} }
if (!numExtraProcs && eatenWndProc) { if (!numExtraProcs && eatenWndProc) {
free(extraProcs); free(extraProcs);
extraProcs = 0; extraProcs = 0;
// As numExtraProcs is 0, won't cause recursion if called from Release(). // As numExtraProcs is 0, won't cause recursion if called from Release().
Release(); Release();
} }
} }
void WndProcEater::Release() { void WndProcEater::Release()
while (numExtraProcs) ReleaseExtraProc(extraProcs[0].proc); {
if (hWndEaten && IsWindow(hWndEaten)) { while (numExtraProcs)
RemoveProp(hWndEaten, L"LilyHaxxor"); ReleaseExtraProc(extraProcs[0].proc);
SetWindowLongPtr(hWndEaten, GWLP_WNDPROC, (LONG_PTR)eatenWndProc); if (hWndEaten && IsWindow(hWndEaten)) {
hWndEaten = 0; RemoveProp(hWndEaten, L"LilyHaxxor");
eatenWndProc = 0; SetWindowLongPtr(hWndEaten, GWLP_WNDPROC, (LONG_PTR)eatenWndProc);
} hWndEaten = 0;
eatenWndProc = 0;
}
} }
LRESULT WndProcEater::_OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) LRESULT WndProcEater::_OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ {
if( hWnd != hWndEaten ) if (hWnd != hWndEaten)
fprintf( stderr, "Totally mismatched window handles on OverrideWndProc!\n" ); fprintf(stderr, "Totally mismatched window handles on OverrideWndProc!\n");
ExtraWndProcResult res = CONTINUE_BLISSFULLY; ExtraWndProcResult res = CONTINUE_BLISSFULLY;
LRESULT out = 0; LRESULT out = 0;
// Here because want it for binding, even when no keyboard mode is selected. // Here because want it for binding, even when no keyboard mode is selected.
if (uMsg == WM_GETDLGCODE) { if (uMsg == WM_GETDLGCODE) {
return DLGC_WANTALLKEYS | CallWindowProc(eatenWndProc, hWnd, uMsg, wParam, lParam); return DLGC_WANTALLKEYS | CallWindowProc(eatenWndProc, hWnd, uMsg, wParam, lParam);
} }
for (int i=0; i<numExtraProcs; i++) { for (int i = 0; i < numExtraProcs; i++) {
// Note: Second bit of deviceUpdateQueued is only set when I receive a device change // Note: Second bit of deviceUpdateQueued is only set when I receive a device change
// notification, which is handled in the GS thread in one of the extraProcs, so this // notification, which is handled in the GS thread in one of the extraProcs, so this
// is all I need to prevent bad things from happening while updating devices. No mutex needed. // is all I need to prevent bad things from happening while updating devices. No mutex needed.
// if ((deviceUpdateQueued&2) && (extraProcs[i].flags & EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES)) continue; // if ((deviceUpdateQueued&2) && (extraProcs[i].flags & EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES)) continue;
ExtraWndProcResult res2 = extraProcs[i].proc(hWnd, uMsg, wParam, lParam, &out); ExtraWndProcResult res2 = extraProcs[i].proc(hWnd, uMsg, wParam, lParam, &out);
if (res2 != res) { if (res2 != res) {
if (res2 == CONTINUE_BLISSFULLY_AND_RELEASE_PROC) { if (res2 == CONTINUE_BLISSFULLY_AND_RELEASE_PROC) {
ReleaseExtraProc(extraProcs[i].proc); ReleaseExtraProc(extraProcs[i].proc);
i--; i--;
} } else if (res2 > res)
else if (res2 > res) res = res2; res = res2;
} }
} }
if (res != NO_WND_PROC) { if (res != NO_WND_PROC) {
if (out == WM_DESTROY) { if (out == WM_DESTROY) {
Release(); Release();
} }
if (res == CONTINUE_BLISSFULLY) if (res == CONTINUE_BLISSFULLY)
out = CallWindowProc(eatenWndProc, hWnd, uMsg, wParam, lParam); out = CallWindowProc(eatenWndProc, hWnd, uMsg, wParam, lParam);
else if (res == USE_DEFAULT_WND_PROC) else if (res == USE_DEFAULT_WND_PROC)
out = DefWindowProc(hWnd, uMsg, wParam, lParam); out = DefWindowProc(hWnd, uMsg, wParam, lParam);
} }
return out; return out;
} }
static LRESULT CALLBACK OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) static LRESULT CALLBACK OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ {
WndProcEater* obj = (WndProcEater*)GetProp(hWnd, L"LilyHaxxor"); WndProcEater *obj = (WndProcEater *)GetProp(hWnd, L"LilyHaxxor");
return (obj == NULL) ? return (obj == NULL) ?
DefWindowProc(hWnd, uMsg, wParam, lParam) : DefWindowProc(hWnd, uMsg, wParam, lParam) :
obj->_OverrideWndProc( hWnd, uMsg, wParam, lParam ); obj->_OverrideWndProc(hWnd, uMsg, wParam, lParam);
} }
bool WndProcEater::SetWndHandle(HWND hWnd) bool WndProcEater::SetWndHandle(HWND hWnd)
{ {
if(hWnd == hWndEaten) return true; if (hWnd == hWndEaten)
return true;
//printf( "(Lilypad) (Re)-Setting window handle! -> this=0x%08x, hWnd=0x%08x\n", this, hWnd ); //printf( "(Lilypad) (Re)-Setting window handle! -> this=0x%08x, hWnd=0x%08x\n", this, hWnd );
Release(); Release();
SetProp(hWnd, L"LilyHaxxor", (HANDLE)this); SetProp(hWnd, L"LilyHaxxor", (HANDLE) this);
eatenWndProc = (WNDPROC) SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)OverrideWndProc); eatenWndProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)OverrideWndProc);
hWndEaten = (eatenWndProc) ? hWnd : 0; hWndEaten = (eatenWndProc) ? hWnd : 0;
return !!hWndEaten; return !!hWndEaten;
} }
void WndProcEater::Eat(ExtraWndProc proc, DWORD flags) { void WndProcEater::Eat(ExtraWndProc proc, DWORD flags)
{
// check if Subclassing failed to init during SetWndHandle // check if Subclassing failed to init during SetWndHandle
if (!hWndEaten) return; if (!hWndEaten)
return;
// Probably isn't needed, but just in case... // Probably isn't needed, but just in case...
if (hMutex) WaitForSingleObject(hMutex, 100); if (hMutex)
WaitForSingleObject(hMutex, 100);
//printf( "(Lilypad) EatingWndProc! -> 0x%x\n", proc ); //printf( "(Lilypad) EatingWndProc! -> 0x%x\n", proc );
extraProcs = (ExtraWndProcInfo*) realloc(extraProcs, sizeof(ExtraWndProcInfo)*(numExtraProcs+1)); extraProcs = (ExtraWndProcInfo *)realloc(extraProcs, sizeof(ExtraWndProcInfo) * (numExtraProcs + 1));
extraProcs[numExtraProcs].proc = proc; extraProcs[numExtraProcs].proc = proc;
extraProcs[numExtraProcs].flags = flags; extraProcs[numExtraProcs].flags = flags;
numExtraProcs++; numExtraProcs++;
} }

View File

@ -15,45 +15,46 @@
* with PCSX2. If not, see <http://www.gnu.org/licenses/>. * with PCSX2. If not, see <http://www.gnu.org/licenses/>.
*/ */
#define EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES 1 #define EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES 1
/* Need this to let window be subclassed multiple times but still clean up nicely. /* Need this to let window be subclassed multiple times but still clean up nicely.
*/ */
enum ExtraWndProcResult { enum ExtraWndProcResult {
CONTINUE_BLISSFULLY, CONTINUE_BLISSFULLY,
// Calls ReleaseExtraProc without messing up order. // Calls ReleaseExtraProc without messing up order.
CONTINUE_BLISSFULLY_AND_RELEASE_PROC, CONTINUE_BLISSFULLY_AND_RELEASE_PROC,
USE_DEFAULT_WND_PROC, USE_DEFAULT_WND_PROC,
NO_WND_PROC NO_WND_PROC
}; };
typedef ExtraWndProcResult (*ExtraWndProc)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *out); typedef ExtraWndProcResult (*ExtraWndProc)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *out);
struct ExtraWndProcInfo { struct ExtraWndProcInfo
ExtraWndProc proc; {
DWORD flags; ExtraWndProc proc;
DWORD flags;
}; };
class WndProcEater class WndProcEater
{ {
public: public:
HWND hWndEaten; HWND hWndEaten;
WNDPROC eatenWndProc; WNDPROC eatenWndProc;
ExtraWndProcInfo* extraProcs; ExtraWndProcInfo *extraProcs;
int numExtraProcs; int numExtraProcs;
HANDLE hMutex; HANDLE hMutex;
public: public:
WndProcEater(); WndProcEater();
virtual ~WndProcEater() throw(); virtual ~WndProcEater() throw();
bool SetWndHandle(HWND hWnd); bool SetWndHandle(HWND hWnd);
void Eat(ExtraWndProc proc, DWORD flags); void Eat(ExtraWndProc proc, DWORD flags);
void ReleaseExtraProc(ExtraWndProc proc); void ReleaseExtraProc(ExtraWndProc proc);
void Release(); void Release();
LRESULT _OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); LRESULT _OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
}; };
extern WndProcEater hWndGSProc; extern WndProcEater hWndGSProc;

View File

@ -27,43 +27,43 @@
typedef struct typedef struct
{ {
float SCP_UP; float SCP_UP;
float SCP_RIGHT; float SCP_RIGHT;
float SCP_DOWN; float SCP_DOWN;
float SCP_LEFT; float SCP_LEFT;
float SCP_LX; float SCP_LX;
float SCP_LY; float SCP_LY;
float SCP_L1; float SCP_L1;
float SCP_L2; float SCP_L2;
float SCP_L3; float SCP_L3;
float SCP_RX; float SCP_RX;
float SCP_RY; float SCP_RY;
float SCP_R1; float SCP_R1;
float SCP_R2; float SCP_R2;
float SCP_R3; float SCP_R3;
float SCP_T; float SCP_T;
float SCP_C; float SCP_C;
float SCP_X; float SCP_X;
float SCP_S; float SCP_S;
float SCP_SELECT; float SCP_SELECT;
float SCP_START; float SCP_START;
float SCP_PS; float SCP_PS;
} SCP_EXTN; } SCP_EXTN;
// This way, I don't require that XInput junk be installed. // This way, I don't require that XInput junk be installed.
typedef void(CALLBACK *_XInputEnable)(BOOL enable); typedef void(CALLBACK *_XInputEnable)(BOOL enable);
typedef DWORD(CALLBACK *_XInputGetStateEx)(DWORD dwUserIndex, XINPUT_STATE* pState); typedef DWORD(CALLBACK *_XInputGetStateEx)(DWORD dwUserIndex, XINPUT_STATE *pState);
typedef DWORD(CALLBACK *_XInputGetExtended)(DWORD dwUserIndex, SCP_EXTN* pPressure); typedef DWORD(CALLBACK *_XInputGetExtended)(DWORD dwUserIndex, SCP_EXTN *pPressure);
typedef DWORD(CALLBACK *_XInputSetState)(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration); typedef DWORD(CALLBACK *_XInputSetState)(DWORD dwUserIndex, XINPUT_VIBRATION *pVibration);
_XInputEnable pXInputEnable = 0; _XInputEnable pXInputEnable = 0;
_XInputGetStateEx pXInputGetStateEx = 0; _XInputGetStateEx pXInputGetStateEx = 0;
@ -73,215 +73,230 @@ _XInputSetState pXInputSetState = 0;
static int xInputActiveCount = 0; static int xInputActiveCount = 0;
// Completely unncessary, really. // Completely unncessary, really.
__forceinline int ShortToAxis(int v) { __forceinline int ShortToAxis(int v)
// If positive and at least 1 << 14, increment. {
v += (!((v>>15)&1)) & ((v>>14)&1); // If positive and at least 1 << 14, increment.
// Just double. v += (!((v >> 15) & 1)) & ((v >> 14) & 1);
return v * 2; // Just double.
return v * 2;
} }
class XInputDevice : public Device { class XInputDevice : public Device
// Cached last vibration values by pad and motor. {
// Need this, as only one value is changed at a time. // Cached last vibration values by pad and motor.
int ps2Vibration[2][4][2]; // Need this, as only one value is changed at a time.
// Minor optimization - cache last set vibration values int ps2Vibration[2][4][2];
// When there's no change, no need to do anything. // Minor optimization - cache last set vibration values
XINPUT_VIBRATION xInputVibration; // When there's no change, no need to do anything.
XINPUT_VIBRATION xInputVibration;
public: public:
int index; int index;
XInputDevice(int index, wchar_t *displayName) : Device(XINPUT, OTHER, displayName) { XInputDevice(int index, wchar_t *displayName)
memset(ps2Vibration, 0, sizeof(ps2Vibration)); : Device(XINPUT, OTHER, displayName)
memset(&xInputVibration, 0, sizeof(xInputVibration)); {
this->index = index; memset(ps2Vibration, 0, sizeof(ps2Vibration));
int i; memset(&xInputVibration, 0, sizeof(xInputVibration));
for (i=0; i<17; i++) { // Skip empty bit this->index = index;
AddPhysicalControl(PRESSURE_BTN, i + (i > 10), 0); int i;
} for (i = 0; i < 17; i++) { // Skip empty bit
for (; i<21; i++) { AddPhysicalControl(PRESSURE_BTN, i + (i > 10), 0);
AddPhysicalControl(ABSAXIS, i + 2, 0); }
} for (; i < 21; i++) {
AddFFAxis(L"Slow Motor", 0); AddPhysicalControl(ABSAXIS, i + 2, 0);
AddFFAxis(L"Fast Motor", 1); }
AddFFEffectType(L"Constant Effect", L"Constant", EFFECT_CONSTANT); AddFFAxis(L"Slow Motor", 0);
} AddFFAxis(L"Fast Motor", 1);
AddFFEffectType(L"Constant Effect", L"Constant", EFFECT_CONSTANT);
}
wchar_t *GetPhysicalControlName(PhysicalControl *c) { wchar_t *GetPhysicalControlName(PhysicalControl *c)
const static wchar_t *names[] = { {
L"D-pad Up", const static wchar_t *names[] = {
L"D-pad Down", L"D-pad Up",
L"D-pad Left", L"D-pad Down",
L"D-pad Right", L"D-pad Left",
L"Start", L"D-pad Right",
L"Back", L"Start",
L"Left Thumb", L"Back",
L"Right Thumb", L"Left Thumb",
L"Left Shoulder", L"Right Thumb",
L"Right Shoulder", L"Left Shoulder",
L"Guide", L"Right Shoulder",
L"A", L"Guide",
L"B", L"A",
L"X", L"B",
L"Y", L"X",
L"Left Trigger", L"Y",
L"Right Trigger", L"Left Trigger",
L"Left Thumb X", L"Right Trigger",
L"Left Thumb Y", L"Left Thumb X",
L"Right Thumb X", L"Left Thumb Y",
L"Right Thumb Y", L"Right Thumb X",
}; L"Right Thumb Y",
unsigned int i = (unsigned int) (c - physicalControls); };
if (i < 21) { unsigned int i = (unsigned int)(c - physicalControls);
return (wchar_t*)names[i]; if (i < 21) {
} return (wchar_t *)names[i];
return Device::GetPhysicalControlName(c); }
} return Device::GetPhysicalControlName(c);
}
int Activate(InitInfo *initInfo) { int Activate(InitInfo *initInfo)
if (active) Deactivate(); {
if (!xInputActiveCount) { if (active)
pXInputEnable(1); Deactivate();
} if (!xInputActiveCount) {
xInputActiveCount++; pXInputEnable(1);
active = 1; }
AllocState(); xInputActiveCount++;
return 1; active = 1;
} AllocState();
return 1;
}
int Update() { int Update()
if (!active) return 0; {
XINPUT_STATE state; if (!active)
if (ERROR_SUCCESS != pXInputGetStateEx(index, &state)) { return 0;
Deactivate(); XINPUT_STATE state;
return 0; if (ERROR_SUCCESS != pXInputGetStateEx(index, &state)) {
} Deactivate();
SCP_EXTN pressure; return 0;
if (!pXInputGetExtended || (ERROR_SUCCESS != pXInputGetExtended(index, &pressure))) { }
int buttons = state.Gamepad.wButtons; SCP_EXTN pressure;
for (int i = 0; i < 15; i++) { if (!pXInputGetExtended || (ERROR_SUCCESS != pXInputGetExtended(index, &pressure))) {
physicalControlState[i] = ((buttons >> physicalControls[i].id) & 1) << 16; int buttons = state.Gamepad.wButtons;
} for (int i = 0; i < 15; i++) {
physicalControlState[15] = (int)(state.Gamepad.bLeftTrigger * 257.005); physicalControlState[i] = ((buttons >> physicalControls[i].id) & 1) << 16;
physicalControlState[16] = (int)(state.Gamepad.bRightTrigger * 257.005); }
physicalControlState[17] = ShortToAxis(state.Gamepad.sThumbLX); physicalControlState[15] = (int)(state.Gamepad.bLeftTrigger * 257.005);
physicalControlState[18] = ShortToAxis(state.Gamepad.sThumbLY); physicalControlState[16] = (int)(state.Gamepad.bRightTrigger * 257.005);
physicalControlState[19] = ShortToAxis(state.Gamepad.sThumbRX); physicalControlState[17] = ShortToAxis(state.Gamepad.sThumbLX);
physicalControlState[20] = ShortToAxis(state.Gamepad.sThumbRY); physicalControlState[18] = ShortToAxis(state.Gamepad.sThumbLY);
} else { physicalControlState[19] = ShortToAxis(state.Gamepad.sThumbRX);
physicalControlState[0] = (int)(pressure.SCP_UP * FULLY_DOWN); physicalControlState[20] = ShortToAxis(state.Gamepad.sThumbRY);
physicalControlState[1] = (int)(pressure.SCP_DOWN * FULLY_DOWN); } else {
physicalControlState[2] = (int)(pressure.SCP_LEFT * FULLY_DOWN); physicalControlState[0] = (int)(pressure.SCP_UP * FULLY_DOWN);
physicalControlState[3] = (int)(pressure.SCP_RIGHT * FULLY_DOWN); physicalControlState[1] = (int)(pressure.SCP_DOWN * FULLY_DOWN);
physicalControlState[4] = (int)(pressure.SCP_START * FULLY_DOWN); physicalControlState[2] = (int)(pressure.SCP_LEFT * FULLY_DOWN);
physicalControlState[5] = (int)(pressure.SCP_SELECT * FULLY_DOWN); physicalControlState[3] = (int)(pressure.SCP_RIGHT * FULLY_DOWN);
physicalControlState[6] = (int)(pressure.SCP_L3 * FULLY_DOWN); physicalControlState[4] = (int)(pressure.SCP_START * FULLY_DOWN);
physicalControlState[7] = (int)(pressure.SCP_R3 * FULLY_DOWN); physicalControlState[5] = (int)(pressure.SCP_SELECT * FULLY_DOWN);
physicalControlState[8] = (int)(pressure.SCP_L1 * FULLY_DOWN); physicalControlState[6] = (int)(pressure.SCP_L3 * FULLY_DOWN);
physicalControlState[9] = (int)(pressure.SCP_R1 * FULLY_DOWN); physicalControlState[7] = (int)(pressure.SCP_R3 * FULLY_DOWN);
physicalControlState[10] = (int)(pressure.SCP_PS * FULLY_DOWN); physicalControlState[8] = (int)(pressure.SCP_L1 * FULLY_DOWN);
physicalControlState[11] = (int)(pressure.SCP_X * FULLY_DOWN); physicalControlState[9] = (int)(pressure.SCP_R1 * FULLY_DOWN);
physicalControlState[12] = (int)(pressure.SCP_C * FULLY_DOWN); physicalControlState[10] = (int)(pressure.SCP_PS * FULLY_DOWN);
physicalControlState[13] = (int)(pressure.SCP_S * FULLY_DOWN); physicalControlState[11] = (int)(pressure.SCP_X * FULLY_DOWN);
physicalControlState[14] = (int)(pressure.SCP_T * FULLY_DOWN); physicalControlState[12] = (int)(pressure.SCP_C * FULLY_DOWN);
physicalControlState[15] = (int)(pressure.SCP_L2 * FULLY_DOWN); physicalControlState[13] = (int)(pressure.SCP_S * FULLY_DOWN);
physicalControlState[16] = (int)(pressure.SCP_R2 * FULLY_DOWN); physicalControlState[14] = (int)(pressure.SCP_T * FULLY_DOWN);
physicalControlState[17] = (int)(pressure.SCP_LX * FULLY_DOWN); physicalControlState[15] = (int)(pressure.SCP_L2 * FULLY_DOWN);
physicalControlState[18] = (int)(pressure.SCP_LY * FULLY_DOWN); physicalControlState[16] = (int)(pressure.SCP_R2 * FULLY_DOWN);
physicalControlState[19] = (int)(pressure.SCP_RX * FULLY_DOWN); physicalControlState[17] = (int)(pressure.SCP_LX * FULLY_DOWN);
physicalControlState[20] = (int)(pressure.SCP_RY * FULLY_DOWN); physicalControlState[18] = (int)(pressure.SCP_LY * FULLY_DOWN);
} physicalControlState[19] = (int)(pressure.SCP_RX * FULLY_DOWN);
return 1; physicalControlState[20] = (int)(pressure.SCP_RY * FULLY_DOWN);
} }
return 1;
}
void SetEffects(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force) { void SetEffects(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force)
ps2Vibration[port][slot][motor] = force; {
int newVibration[2] = {0,0}; ps2Vibration[port][slot][motor] = force;
for (int p=0; p<2; p++) { int newVibration[2] = {0, 0};
for (int s=0; s<4; s++) { for (int p = 0; p < 2; p++) {
for (int i=0; i<pads[p][s].numFFBindings; i++) { for (int s = 0; s < 4; s++) {
// Technically should also be a *65535/BASE_SENSITIVITY, but that's close enough to 1 for me. for (int i = 0; i < pads[p][s].numFFBindings; i++) {
ForceFeedbackBinding *ffb = &pads[p][s].ffBindings[i]; // Technically should also be a *65535/BASE_SENSITIVITY, but that's close enough to 1 for me.
newVibration[0] += (int)((ffb->axes[0].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255); ForceFeedbackBinding *ffb = &pads[p][s].ffBindings[i];
newVibration[1] += (int)((ffb->axes[1].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255); newVibration[0] += (int)((ffb->axes[0].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255);
} newVibration[1] += (int)((ffb->axes[1].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255);
} }
} }
newVibration[0] = abs(newVibration[0]); }
if (newVibration[0] > 65535) { newVibration[0] = abs(newVibration[0]);
newVibration[0] = 65535; if (newVibration[0] > 65535) {
} newVibration[0] = 65535;
newVibration[1] = abs(newVibration[1]); }
if (newVibration[1] > 65535) { newVibration[1] = abs(newVibration[1]);
newVibration[1] = 65535; if (newVibration[1] > 65535) {
} newVibration[1] = 65535;
if (newVibration[0] || newVibration[1] || newVibration[0] != xInputVibration.wLeftMotorSpeed || newVibration[1] != xInputVibration.wRightMotorSpeed) { }
XINPUT_VIBRATION newv = {(WORD)newVibration[0], (WORD)newVibration[1]}; if (newVibration[0] || newVibration[1] || newVibration[0] != xInputVibration.wLeftMotorSpeed || newVibration[1] != xInputVibration.wRightMotorSpeed) {
if (ERROR_SUCCESS == pXInputSetState(index, &newv)) { XINPUT_VIBRATION newv = {(WORD)newVibration[0], (WORD)newVibration[1]};
xInputVibration = newv; if (ERROR_SUCCESS == pXInputSetState(index, &newv)) {
} xInputVibration = newv;
} }
} }
}
void SetEffect(ForceFeedbackBinding *binding, unsigned char force) { void SetEffect(ForceFeedbackBinding *binding, unsigned char force)
PadBindings pBackup = pads[0][0]; {
pads[0][0].ffBindings = binding; PadBindings pBackup = pads[0][0];
pads[0][0].numFFBindings = 1; pads[0][0].ffBindings = binding;
SetEffects(0, 0, binding->motor, 255); pads[0][0].numFFBindings = 1;
pads[0][0] = pBackup; SetEffects(0, 0, binding->motor, 255);
} pads[0][0] = pBackup;
}
void Deactivate() { void Deactivate()
memset(&xInputVibration, 0, sizeof(xInputVibration)); {
memset(ps2Vibration, 0, sizeof(ps2Vibration)); memset(&xInputVibration, 0, sizeof(xInputVibration));
pXInputSetState(index, &xInputVibration); memset(ps2Vibration, 0, sizeof(ps2Vibration));
pXInputSetState(index, &xInputVibration);
FreeState(); FreeState();
if (active) { if (active) {
if (!--xInputActiveCount) { if (!--xInputActiveCount) {
pXInputEnable(0); pXInputEnable(0);
} }
active = 0; active = 0;
} }
} }
~XInputDevice() { ~XInputDevice()
} {
}
}; };
void EnumXInputDevices() { void EnumXInputDevices()
wchar_t temp[30]; {
if (!pXInputSetState) { wchar_t temp[30];
// Also used as flag to indicute XInput not installed, so if (!pXInputSetState) {
// don't repeatedly try to load it. // Also used as flag to indicute XInput not installed, so
if (pXInputEnable) return; // don't repeatedly try to load it.
if (pXInputEnable)
return;
// Prefer XInput 1.3 since SCP only has an XInput 1.3 wrapper right now. // Prefer XInput 1.3 since SCP only has an XInput 1.3 wrapper right now.
// Also use LoadLibrary and not LoadLibraryEx for XInput 1.3, since some // Also use LoadLibrary and not LoadLibraryEx for XInput 1.3, since some
// Windows 7 systems have issues with it. // Windows 7 systems have issues with it.
// FIXME: Missing FreeLibrary call. // FIXME: Missing FreeLibrary call.
HMODULE hMod = LoadLibrary(L"xinput1_3.dll"); HMODULE hMod = LoadLibrary(L"xinput1_3.dll");
if (hMod == nullptr && IsWindows8OrGreater()) { if (hMod == nullptr && IsWindows8OrGreater()) {
hMod = LoadLibraryEx(L"XInput1_4.dll", nullptr, LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32); hMod = LoadLibraryEx(L"XInput1_4.dll", nullptr, LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32);
} }
if (hMod) { if (hMod) {
if ((pXInputEnable = (_XInputEnable) GetProcAddress(hMod, "XInputEnable")) && if ((pXInputEnable = (_XInputEnable)GetProcAddress(hMod, "XInputEnable")) &&
((pXInputGetStateEx = (_XInputGetStateEx) GetProcAddress(hMod, (LPCSTR)100)) || // Try Ex version first ((pXInputGetStateEx = (_XInputGetStateEx)GetProcAddress(hMod, (LPCSTR)100)) || // Try Ex version first
(pXInputGetStateEx = (_XInputGetStateEx) GetProcAddress(hMod, "XInputGetState")))) { (pXInputGetStateEx = (_XInputGetStateEx)GetProcAddress(hMod, "XInputGetState")))) {
pXInputGetExtended = (_XInputGetExtended)GetProcAddress(hMod, "XInputGetExtended"); pXInputGetExtended = (_XInputGetExtended)GetProcAddress(hMod, "XInputGetExtended");
pXInputSetState = (_XInputSetState) GetProcAddress(hMod, "XInputSetState"); pXInputSetState = (_XInputSetState)GetProcAddress(hMod, "XInputSetState");
} }
} }
if (!pXInputSetState) { if (!pXInputSetState) {
pXInputEnable = (_XInputEnable)-1; pXInputEnable = (_XInputEnable)-1;
return; return;
} }
} }
pXInputEnable(1); pXInputEnable(1);
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
wsprintfW(temp, L"XInput Pad %i", i); wsprintfW(temp, L"XInput Pad %i", i);
dm->AddDevice(new XInputDevice(i, temp)); dm->AddDevice(new XInputDevice(i, temp));
} }
pXInputEnable(0); pXInputEnable(0);
} }

View File

@ -57,39 +57,39 @@
/* /*
* Device and/or Interface Class codes * Device and/or Interface Class codes
*/ */
#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */ #define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */
#define USB_CLASS_AUDIO 1 #define USB_CLASS_AUDIO 1
#define USB_CLASS_COMM 2 #define USB_CLASS_COMM 2
#define USB_CLASS_HID 3 #define USB_CLASS_HID 3
#define USB_CLASS_PRINTER 7 #define USB_CLASS_PRINTER 7
#define USB_CLASS_MASS_STORAGE 8 #define USB_CLASS_MASS_STORAGE 8
#define USB_CLASS_HUB 9 #define USB_CLASS_HUB 9
#define USB_CLASS_DATA 10 #define USB_CLASS_DATA 10
#define USB_CLASS_VENDOR_SPEC 0xff #define USB_CLASS_VENDOR_SPEC 0xff
/* /*
* Descriptor types * Descriptor types
*/ */
#define USB_DT_DEVICE 0x01 #define USB_DT_DEVICE 0x01
#define USB_DT_CONFIG 0x02 #define USB_DT_CONFIG 0x02
#define USB_DT_STRING 0x03 #define USB_DT_STRING 0x03
#define USB_DT_INTERFACE 0x04 #define USB_DT_INTERFACE 0x04
#define USB_DT_ENDPOINT 0x05 #define USB_DT_ENDPOINT 0x05
#define USB_DT_HID 0x21 #define USB_DT_HID 0x21
#define USB_DT_REPORT 0x22 #define USB_DT_REPORT 0x22
#define USB_DT_PHYSICAL 0x23 #define USB_DT_PHYSICAL 0x23
#define USB_DT_HUB 0x29 #define USB_DT_HUB 0x29
/* /*
* Descriptor sizes per descriptor type * Descriptor sizes per descriptor type
*/ */
#define USB_DT_DEVICE_SIZE 18 #define USB_DT_DEVICE_SIZE 18
#define USB_DT_CONFIG_SIZE 9 #define USB_DT_CONFIG_SIZE 9
#define USB_DT_INTERFACE_SIZE 9 #define USB_DT_INTERFACE_SIZE 9
#define USB_DT_ENDPOINT_SIZE 7 #define USB_DT_ENDPOINT_SIZE 7
#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ #define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
#define USB_DT_HUB_NONVAR_SIZE 7 #define USB_DT_HUB_NONVAR_SIZE 7
/* ensure byte-packed structures */ /* ensure byte-packed structures */
@ -97,159 +97,168 @@
/* All standard descriptors have these 2 fields in common */ /* All standard descriptors have these 2 fields in common */
struct usb_descriptor_header { struct usb_descriptor_header
unsigned char bLength; {
unsigned char bDescriptorType; unsigned char bLength;
unsigned char bDescriptorType;
}; };
/* String descriptor */ /* String descriptor */
struct usb_string_descriptor { struct usb_string_descriptor
unsigned char bLength; {
unsigned char bDescriptorType; unsigned char bLength;
unsigned short wData[1]; unsigned char bDescriptorType;
unsigned short wData[1];
}; };
/* HID descriptor */ /* HID descriptor */
struct usb_hid_descriptor { struct usb_hid_descriptor
unsigned char bLength; {
unsigned char bDescriptorType; unsigned char bLength;
unsigned short bcdHID; unsigned char bDescriptorType;
unsigned char bCountryCode; unsigned short bcdHID;
unsigned char bNumDescriptors; unsigned char bCountryCode;
unsigned char bNumDescriptors;
}; };
/* Endpoint descriptor */ /* Endpoint descriptor */
#define USB_MAXENDPOINTS 32 #define USB_MAXENDPOINTS 32
struct usb_endpoint_descriptor { struct usb_endpoint_descriptor
unsigned char bLength; {
unsigned char bDescriptorType; unsigned char bLength;
unsigned char bEndpointAddress; unsigned char bDescriptorType;
unsigned char bmAttributes; unsigned char bEndpointAddress;
unsigned short wMaxPacketSize; unsigned char bmAttributes;
unsigned char bInterval; unsigned short wMaxPacketSize;
unsigned char bRefresh; unsigned char bInterval;
unsigned char bSynchAddress; unsigned char bRefresh;
unsigned char bSynchAddress;
unsigned char *extra; /* Extra descriptors */ unsigned char *extra; /* Extra descriptors */
int extralen; int extralen;
}; };
#define USB_ENDPOINT_ADDRESS_MASK 0x0f /* in bEndpointAddress */ #define USB_ENDPOINT_ADDRESS_MASK 0x0f /* in bEndpointAddress */
#define USB_ENDPOINT_DIR_MASK 0x80 #define USB_ENDPOINT_DIR_MASK 0x80
#define USB_ENDPOINT_TYPE_MASK 0x03 /* in bmAttributes */ #define USB_ENDPOINT_TYPE_MASK 0x03 /* in bmAttributes */
#define USB_ENDPOINT_TYPE_CONTROL 0 #define USB_ENDPOINT_TYPE_CONTROL 0
#define USB_ENDPOINT_TYPE_ISOCHRONOUS 1 #define USB_ENDPOINT_TYPE_ISOCHRONOUS 1
#define USB_ENDPOINT_TYPE_BULK 2 #define USB_ENDPOINT_TYPE_BULK 2
#define USB_ENDPOINT_TYPE_INTERRUPT 3 #define USB_ENDPOINT_TYPE_INTERRUPT 3
/* Interface descriptor */ /* Interface descriptor */
#define USB_MAXINTERFACES 32 #define USB_MAXINTERFACES 32
struct usb_interface_descriptor { struct usb_interface_descriptor
unsigned char bLength; {
unsigned char bDescriptorType; unsigned char bLength;
unsigned char bInterfaceNumber; unsigned char bDescriptorType;
unsigned char bAlternateSetting; unsigned char bInterfaceNumber;
unsigned char bNumEndpoints; unsigned char bAlternateSetting;
unsigned char bInterfaceClass; unsigned char bNumEndpoints;
unsigned char bInterfaceSubClass; unsigned char bInterfaceClass;
unsigned char bInterfaceProtocol; unsigned char bInterfaceSubClass;
unsigned char iInterface; unsigned char bInterfaceProtocol;
unsigned char iInterface;
struct usb_endpoint_descriptor *endpoint; struct usb_endpoint_descriptor *endpoint;
unsigned char *extra; /* Extra descriptors */ unsigned char *extra; /* Extra descriptors */
int extralen; int extralen;
}; };
#define USB_MAXALTSETTING 128 /* Hard limit */ #define USB_MAXALTSETTING 128 /* Hard limit */
struct usb_interface { struct usb_interface
struct usb_interface_descriptor *altsetting; {
struct usb_interface_descriptor *altsetting;
int num_altsetting; int num_altsetting;
}; };
/* Configuration descriptor information.. */ /* Configuration descriptor information.. */
#define USB_MAXCONFIG 8 #define USB_MAXCONFIG 8
struct usb_config_descriptor { struct usb_config_descriptor
unsigned char bLength; {
unsigned char bDescriptorType; unsigned char bLength;
unsigned short wTotalLength; unsigned char bDescriptorType;
unsigned char bNumInterfaces; unsigned short wTotalLength;
unsigned char bConfigurationValue; unsigned char bNumInterfaces;
unsigned char iConfiguration; unsigned char bConfigurationValue;
unsigned char bmAttributes; unsigned char iConfiguration;
unsigned char MaxPower; unsigned char bmAttributes;
unsigned char MaxPower;
struct usb_interface *interface; struct usb_interface *interface;
unsigned char *extra; /* Extra descriptors */ unsigned char *extra; /* Extra descriptors */
int extralen; int extralen;
}; };
/* Device descriptor */ /* Device descriptor */
struct usb_device_descriptor { struct usb_device_descriptor
unsigned char bLength; {
unsigned char bDescriptorType; unsigned char bLength;
unsigned short bcdUSB; unsigned char bDescriptorType;
unsigned char bDeviceClass; unsigned short bcdUSB;
unsigned char bDeviceSubClass; unsigned char bDeviceClass;
unsigned char bDeviceProtocol; unsigned char bDeviceSubClass;
unsigned char bMaxPacketSize0; unsigned char bDeviceProtocol;
unsigned short idVendor; unsigned char bMaxPacketSize0;
unsigned short idProduct; unsigned short idVendor;
unsigned short bcdDevice; unsigned short idProduct;
unsigned char iManufacturer; unsigned short bcdDevice;
unsigned char iProduct; unsigned char iManufacturer;
unsigned char iSerialNumber; unsigned char iProduct;
unsigned char bNumConfigurations; unsigned char iSerialNumber;
unsigned char bNumConfigurations;
}; };
struct usb_ctrl_setup { struct usb_ctrl_setup
unsigned char bRequestType; {
unsigned char bRequest; unsigned char bRequestType;
unsigned short wValue; unsigned char bRequest;
unsigned short wIndex; unsigned short wValue;
unsigned short wLength; unsigned short wIndex;
unsigned short wLength;
}; };
/* /*
* Standard requests * Standard requests
*/ */
#define USB_REQ_GET_STATUS 0x00 #define USB_REQ_GET_STATUS 0x00
#define USB_REQ_CLEAR_FEATURE 0x01 #define USB_REQ_CLEAR_FEATURE 0x01
/* 0x02 is reserved */ /* 0x02 is reserved */
#define USB_REQ_SET_FEATURE 0x03 #define USB_REQ_SET_FEATURE 0x03
/* 0x04 is reserved */ /* 0x04 is reserved */
#define USB_REQ_SET_ADDRESS 0x05 #define USB_REQ_SET_ADDRESS 0x05
#define USB_REQ_GET_DESCRIPTOR 0x06 #define USB_REQ_GET_DESCRIPTOR 0x06
#define USB_REQ_SET_DESCRIPTOR 0x07 #define USB_REQ_SET_DESCRIPTOR 0x07
#define USB_REQ_GET_CONFIGURATION 0x08 #define USB_REQ_GET_CONFIGURATION 0x08
#define USB_REQ_SET_CONFIGURATION 0x09 #define USB_REQ_SET_CONFIGURATION 0x09
#define USB_REQ_GET_INTERFACE 0x0A #define USB_REQ_GET_INTERFACE 0x0A
#define USB_REQ_SET_INTERFACE 0x0B #define USB_REQ_SET_INTERFACE 0x0B
#define USB_REQ_SYNCH_FRAME 0x0C #define USB_REQ_SYNCH_FRAME 0x0C
#define USB_TYPE_STANDARD (0x00 << 5) #define USB_TYPE_STANDARD (0x00 << 5)
#define USB_TYPE_CLASS (0x01 << 5) #define USB_TYPE_CLASS (0x01 << 5)
#define USB_TYPE_VENDOR (0x02 << 5) #define USB_TYPE_VENDOR (0x02 << 5)
#define USB_TYPE_RESERVED (0x03 << 5) #define USB_TYPE_RESERVED (0x03 << 5)
#define USB_RECIP_DEVICE 0x00 #define USB_RECIP_DEVICE 0x00
#define USB_RECIP_INTERFACE 0x01 #define USB_RECIP_INTERFACE 0x01
#define USB_RECIP_ENDPOINT 0x02 #define USB_RECIP_ENDPOINT 0x02
#define USB_RECIP_OTHER 0x03 #define USB_RECIP_OTHER 0x03
/* /*
* Various libusb API related stuff * Various libusb API related stuff
*/ */
#define USB_ENDPOINT_IN 0x80 #define USB_ENDPOINT_IN 0x80
#define USB_ENDPOINT_OUT 0x00 #define USB_ENDPOINT_OUT 0x00
/* Error codes */ /* Error codes */
#define USB_ERROR_BEGIN 500000 #define USB_ERROR_BEGIN 500000
/* /*
* This is supposed to look weird. This file is generated from autoconf * This is supposed to look weird. This file is generated from autoconf
@ -261,49 +270,54 @@ struct usb_ctrl_setup {
/* struct usb_device; */ /* struct usb_device; */
/* struct usb_bus; */ /* struct usb_bus; */
struct usb_device { struct usb_device
struct usb_device *next, *prev; {
struct usb_device *next, *prev;
char filename[LIBUSB_PATH_MAX]; char filename[LIBUSB_PATH_MAX];
struct usb_bus *bus; struct usb_bus *bus;
struct usb_device_descriptor descriptor; struct usb_device_descriptor descriptor;
struct usb_config_descriptor *config; struct usb_config_descriptor *config;
void *dev; /* Darwin support */ void *dev; /* Darwin support */
unsigned char devnum; unsigned char devnum;
unsigned char num_children; unsigned char num_children;
struct usb_device **children; struct usb_device **children;
}; };
struct usb_bus { struct usb_bus
struct usb_bus *next, *prev; {
struct usb_bus *next, *prev;
char dirname[LIBUSB_PATH_MAX]; char dirname[LIBUSB_PATH_MAX];
struct usb_device *devices; struct usb_device *devices;
unsigned long location; unsigned long location;
struct usb_device *root_dev; struct usb_device *root_dev;
}; };
/* Version information, Windows specific */ /* Version information, Windows specific */
struct usb_version { struct usb_version
struct { {
int major; struct
int minor; {
int micro; int major;
int nano; int minor;
} dll; int micro;
struct { int nano;
int major; } dll;
int minor; struct
int micro; {
int nano; int major;
} driver; int minor;
int micro;
int nano;
} driver;
}; };
@ -324,92 +338,92 @@ typedef struct usb_dev_handle usb_dev_handle;
extern "C" { extern "C" {
#endif #endif
/* Function prototypes */ /* Function prototypes */
/* usb.c */ /* usb.c */
usb_dev_handle *usb_open(struct usb_device *dev); usb_dev_handle *usb_open(struct usb_device *dev);
int usb_close(usb_dev_handle *dev); int usb_close(usb_dev_handle *dev);
int usb_get_string(usb_dev_handle *dev, int index, int langid, char *buf, int usb_get_string(usb_dev_handle *dev, int index, int langid, char *buf,
size_t buflen); size_t buflen);
int usb_get_string_simple(usb_dev_handle *dev, int index, char *buf, int usb_get_string_simple(usb_dev_handle *dev, int index, char *buf,
size_t buflen); size_t buflen);
/* descriptors.c */ /* descriptors.c */
int usb_get_descriptor_by_endpoint(usb_dev_handle *udev, int ep, int usb_get_descriptor_by_endpoint(usb_dev_handle *udev, int ep,
unsigned char type, unsigned char index, unsigned char type, unsigned char index,
void *buf, int size); void *buf, int size);
int usb_get_descriptor(usb_dev_handle *udev, unsigned char type, int usb_get_descriptor(usb_dev_handle *udev, unsigned char type,
unsigned char index, void *buf, int size); unsigned char index, void *buf, int size);
/* <arch>.c */ /* <arch>.c */
int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size, int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size,
int timeout); int timeout);
int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size, int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size,
int timeout);
int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, int size,
int timeout);
int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size,
int timeout);
int usb_control_msg(usb_dev_handle *dev, int requesttype, int request,
int value, int index, char *bytes, int size,
int timeout); int timeout);
int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, int size, int usb_set_configuration(usb_dev_handle *dev, int configuration);
int timeout); int usb_claim_interface(usb_dev_handle *dev, int interface);
int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size, int usb_release_interface(usb_dev_handle *dev, int interface);
int timeout); int usb_set_altinterface(usb_dev_handle *dev, int alternate);
int usb_control_msg(usb_dev_handle *dev, int requesttype, int request, int usb_resetep(usb_dev_handle *dev, unsigned int ep);
int value, int index, char *bytes, int size, int usb_clear_halt(usb_dev_handle *dev, unsigned int ep);
int timeout); int usb_reset(usb_dev_handle *dev);
int usb_set_configuration(usb_dev_handle *dev, int configuration);
int usb_claim_interface(usb_dev_handle *dev, int interface);
int usb_release_interface(usb_dev_handle *dev, int interface);
int usb_set_altinterface(usb_dev_handle *dev, int alternate);
int usb_resetep(usb_dev_handle *dev, unsigned int ep);
int usb_clear_halt(usb_dev_handle *dev, unsigned int ep);
int usb_reset(usb_dev_handle *dev);
char *usb_strerror(void); char *usb_strerror(void);
void usb_init(void); void usb_init(void);
void usb_set_debug(int level); void usb_set_debug(int level);
int usb_find_busses(void); int usb_find_busses(void);
int usb_find_devices(void); int usb_find_devices(void);
struct usb_device *usb_device(usb_dev_handle *dev); struct usb_device *usb_device(usb_dev_handle *dev);
struct usb_bus *usb_get_busses(void); struct usb_bus *usb_get_busses(void);
/* Windows specific functions */ /* Windows specific functions */
#define LIBUSB_HAS_INSTALL_SERVICE_NP 1 #define LIBUSB_HAS_INSTALL_SERVICE_NP 1
int usb_install_service_np(void); int usb_install_service_np(void);
void CALLBACK usb_install_service_np_rundll(HWND wnd, HINSTANCE instance, void CALLBACK usb_install_service_np_rundll(HWND wnd, HINSTANCE instance,
LPSTR cmd_line, int cmd_show);
#define LIBUSB_HAS_UNINSTALL_SERVICE_NP 1
int usb_uninstall_service_np(void);
void CALLBACK usb_uninstall_service_np_rundll(HWND wnd, HINSTANCE instance,
LPSTR cmd_line, int cmd_show); LPSTR cmd_line, int cmd_show);
#define LIBUSB_HAS_UNINSTALL_SERVICE_NP 1 #define LIBUSB_HAS_INSTALL_DRIVER_NP 1
int usb_uninstall_service_np(void); int usb_install_driver_np(const char *inf_file);
void CALLBACK usb_uninstall_service_np_rundll(HWND wnd, HINSTANCE instance, void CALLBACK usb_install_driver_np_rundll(HWND wnd, HINSTANCE instance,
LPSTR cmd_line, int cmd_show); LPSTR cmd_line, int cmd_show);
#define LIBUSB_HAS_INSTALL_DRIVER_NP 1 #define LIBUSB_HAS_TOUCH_INF_FILE_NP 1
int usb_install_driver_np(const char *inf_file); int usb_touch_inf_file_np(const char *inf_file);
void CALLBACK usb_install_driver_np_rundll(HWND wnd, HINSTANCE instance, void CALLBACK usb_touch_inf_file_np_rundll(HWND wnd, HINSTANCE instance,
LPSTR cmd_line, int cmd_show); LPSTR cmd_line, int cmd_show);
#define LIBUSB_HAS_TOUCH_INF_FILE_NP 1 #define LIBUSB_HAS_INSTALL_NEEDS_RESTART_NP 1
int usb_touch_inf_file_np(const char *inf_file); int usb_install_needs_restart_np(void);
void CALLBACK usb_touch_inf_file_np_rundll(HWND wnd, HINSTANCE instance,
LPSTR cmd_line, int cmd_show);
#define LIBUSB_HAS_INSTALL_NEEDS_RESTART_NP 1 const struct usb_version *usb_get_version(void);
int usb_install_needs_restart_np(void);
const struct usb_version *usb_get_version(void); int usb_isochronous_setup_async(usb_dev_handle *dev, void **context,
unsigned char ep, int pktsize);
int usb_bulk_setup_async(usb_dev_handle *dev, void **context,
unsigned char ep);
int usb_interrupt_setup_async(usb_dev_handle *dev, void **context,
unsigned char ep);
int usb_isochronous_setup_async(usb_dev_handle *dev, void **context, int usb_submit_async(void *context, char *bytes, int size);
unsigned char ep, int pktsize); int usb_reap_async(void *context, int timeout);
int usb_bulk_setup_async(usb_dev_handle *dev, void **context, int usb_reap_async_nocancel(void *context, int timeout);
unsigned char ep); int usb_cancel_async(void *context);
int usb_interrupt_setup_async(usb_dev_handle *dev, void **context, int usb_free_async(void **context);
unsigned char ep);
int usb_submit_async(void *context, char *bytes, int size);
int usb_reap_async(void *context, int timeout);
int usb_reap_async_nocancel(void *context, int timeout);
int usb_cancel_async(void *context);
int usb_free_async(void **context);
#ifdef __cplusplus #ifdef __cplusplus
@ -418,4 +432,3 @@ extern "C" {
#endif #endif
#endif /* __USB_H__ */ #endif /* __USB_H__ */