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

View File

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

View File

@ -25,121 +25,121 @@
Device *dev;
INT_PTR CALLBACK DiagDialog(HWND hWnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam) {
int i;
HWND hWndList = GetDlgItem(hWnd, IDC_LIST);
static int fullRefresh;
if (dev) {
switch (uMsg) {
case WM_INITDIALOG:
{
fullRefresh = 1;
SetWindowText(hWnd, dev->displayName);
LVCOLUMNW c;
c.mask = LVCF_TEXT | LVCF_WIDTH;
c.cx = 151;
c.pszText = L"Control";
ListView_InsertColumn(hWndList, 0, &c);
c.cx = 90;
c.pszText = L"Value";
ListView_InsertColumn(hWndList, 1, &c);
ListView_DeleteAllItems(hWndList);
LVITEM item;
item.mask = LVIF_TEXT;
item.iSubItem = 0;
for (i=0; i<dev->numVirtualControls; i++) {
item.pszText = dev->GetVirtualControlName(dev->virtualControls+i);
item.iItem = i;
ListView_InsertItem(hWndList, &item);
}
SetTimer(hWnd, 1, 200, 0);
}
//break;
case WM_TIMER:
{
hWndButtonProc.SetWndHandle(hWndList);
InitInfo info = {0, 1, hWnd, &hWndButtonProc};
dm->Update(&info);
LVITEMW item;
item.mask = LVIF_TEXT;
item.iSubItem = 1;
//ShowWindow(hWndList, 0);
//LockWindowUpdate(hWndList);
if (!dev->active) {
item.pszText = L"?";
for (i=0; i<dev->numVirtualControls; i++) {
item.iItem = i;
ListView_SetItem(hWndList, &item);
}
fullRefresh = 1;
}
else {
for (i=0; i<dev->numVirtualControls; i++) {
if (fullRefresh || dev->virtualControlState[i] != dev->oldVirtualControlState[i]) {
INT_PTR CALLBACK DiagDialog(HWND hWnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam)
{
int i;
HWND hWndList = GetDlgItem(hWnd, IDC_LIST);
static int fullRefresh;
if (dev) {
switch (uMsg) {
case WM_INITDIALOG: {
fullRefresh = 1;
SetWindowText(hWnd, dev->displayName);
LVCOLUMNW c;
c.mask = LVCF_TEXT | LVCF_WIDTH;
c.cx = 151;
c.pszText = L"Control";
ListView_InsertColumn(hWndList, 0, &c);
c.cx = 90;
c.pszText = L"Value";
ListView_InsertColumn(hWndList, 1, &c);
ListView_DeleteAllItems(hWndList);
LVITEM item;
item.mask = LVIF_TEXT;
item.iSubItem = 0;
for (i = 0; i < dev->numVirtualControls; i++) {
item.pszText = dev->GetVirtualControlName(dev->virtualControls + i);
item.iItem = i;
ListView_InsertItem(hWndList, &item);
}
SetTimer(hWnd, 1, 200, 0);
}
//break;
case WM_TIMER: {
hWndButtonProc.SetWndHandle(hWndList);
InitInfo info = {0, 1, hWnd, &hWndButtonProc};
dm->Update(&info);
LVITEMW item;
item.mask = LVIF_TEXT;
item.iSubItem = 1;
//ShowWindow(hWndList, 0);
//LockWindowUpdate(hWndList);
if (!dev->active) {
item.pszText = L"?";
for (i = 0; i < dev->numVirtualControls; i++) {
item.iItem = i;
ListView_SetItem(hWndList, &item);
}
fullRefresh = 1;
} else {
for (i = 0; i < dev->numVirtualControls; i++) {
if (fullRefresh || dev->virtualControlState[i] != dev->oldVirtualControlState[i]) {
VirtualControl *c = dev->virtualControls + i;
wchar_t temp[50];
int val = dev->virtualControlState[i];
if (c->uid & (UID_POV)) {
wsprintfW(temp, L"%i", val);
}
else {
wchar_t *sign = L"";
if (val < 0) {
sign = L"-";
val = -val;
}
if ((c->uid& UID_AXIS) && val) {
val = val;
}
val = (int)floor(0.5 + val * 1000.0 / (double)FULLY_DOWN);
wsprintfW(temp, L"%s%i.%03i", sign, val/1000, val%1000);
}
item.pszText = temp;
item.iItem = i;
ListView_SetItem(hWndList, &item);
}
}
dm->PostRead();
fullRefresh = 0;
}
//LockWindowUpdate(0);
//ShowWindow(hWndList, 1);
//UpdateWindow(hWnd);
}
break;
case WM_NOTIFY:
{
NMLVKEYDOWN *n = (NMLVKEYDOWN *) lParam;
// Don't always get the notification when testing DirectInput non-keyboard devices.
// 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) break;
break;
case WM_CLOSE:
KillTimer(hWnd, 1);
dm->ReleaseInput();
// Prevents reaching this branch again.
dev = 0;
EndDialog(hWnd, 1);
break;
default:
break;
}
}
return 0;
VirtualControl *c = dev->virtualControls + i;
wchar_t temp[50];
int val = dev->virtualControlState[i];
if (c->uid & (UID_POV)) {
wsprintfW(temp, L"%i", val);
} else {
wchar_t *sign = L"";
if (val < 0) {
sign = L"-";
val = -val;
}
if ((c->uid & UID_AXIS) && val) {
val = val;
}
val = (int)floor(0.5 + val * 1000.0 / (double)FULLY_DOWN);
wsprintfW(temp, L"%s%i.%03i", sign, val / 1000, val % 1000);
}
item.pszText = temp;
item.iItem = i;
ListView_SetItem(hWndList, &item);
}
}
dm->PostRead();
fullRefresh = 0;
}
//LockWindowUpdate(0);
//ShowWindow(hWndList, 1);
//UpdateWindow(hWnd);
} break;
case WM_NOTIFY: {
NMLVKEYDOWN *n = (NMLVKEYDOWN *)lParam;
// Don't always get the notification when testing DirectInput non-keyboard devices.
// 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)
break;
break;
case WM_CLOSE:
KillTimer(hWnd, 1);
dm->ReleaseInput();
// Prevents reaching this branch again.
dev = 0;
EndDialog(hWnd, 1);
break;
default:
break;
}
}
return 0;
}
void Diagnose(int id, HWND hWnd) {
// init = 0;
dev = dm->devices[id];
for (int i=0; i<dm->numDevices; i++) {
if (i != id) dm->DisableDevice(i);
// Shouldn't be needed.
else dm->EnableDevice(i);
}
DialogBox(hInst, MAKEINTRESOURCE(IDD_DIAG), hWnd, DiagDialog);
ClearKeyQueue();
void Diagnose(int id, HWND hWnd)
{
// init = 0;
dev = dm->devices[id];
for (int i = 0; i < dm->numDevices; i++) {
if (i != id)
dm->DisableDevice(i);
// Shouldn't be needed.
else
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 lastDS3Enum = 0;
typedef void (__cdecl *_usb_init)(void);
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 void(__cdecl *_usb_init)(void);
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 usb_dev_handle *(__cdecl *_usb_open)(struct usb_device *dev);
typedef int (__cdecl *_usb_find_busses)(void);
typedef int (__cdecl *_usb_find_devices)(void);
typedef int(__cdecl *_usb_find_busses)(void);
typedef int(__cdecl *_usb_find_devices)(void);
typedef struct usb_bus *(__cdecl *_usb_get_busses)(void);
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_close pusb_close;
@ -62,408 +62,435 @@ _usb_control_msg pusb_control_msg;
HMODULE hModLibusb = 0;
void UninitLibUsb() {
if (hModLibusb) {
FreeLibrary(hModLibusb);
hModLibusb = 0;
}
void UninitLibUsb()
{
if (hModLibusb) {
FreeLibrary(hModLibusb);
hModLibusb = 0;
}
}
void TryInitDS3(usb_device *dev) {
while (dev) {
if (dev->descriptor.idVendor == VID && dev->descriptor.idProduct == PID) {
usb_dev_handle *handle = pusb_open(dev);
if (handle) {
char junk[20];
// This looks like HidD_GetFeature with a feature report id of 0xF2 to me and a length of 17.
// That doesn't work, however, and 17 is shorter than the report length.
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++) {
TryInitDS3(dev->children[i]);
}
}
dev = dev->next;
}
void TryInitDS3(usb_device *dev)
{
while (dev) {
if (dev->descriptor.idVendor == VID && dev->descriptor.idProduct == PID) {
usb_dev_handle *handle = pusb_open(dev);
if (handle) {
char junk[20];
// This looks like HidD_GetFeature with a feature report id of 0xF2 to me and a length of 17.
// That doesn't work, however, and 17 is shorter than the report length.
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++) {
TryInitDS3(dev->children[i]);
}
}
dev = dev->next;
}
}
void DS3Enum(unsigned int time) {
if (time - lastDS3Enum < DOUBLE_ENUM_DELAY) {
return;
}
lastDS3Enum = time;
pusb_find_busses();
pusb_find_devices();
void DS3Enum(unsigned int time)
{
if (time - lastDS3Enum < DOUBLE_ENUM_DELAY) {
return;
}
lastDS3Enum = time;
pusb_find_busses();
pusb_find_devices();
}
void DS3Check(unsigned int time) {
if (time - lastDS3Check < DOUBLE_CHECK_DELAY) {
return;
}
if (!lastDS3Check) {
DS3Enum(time);
}
lastDS3Check = time;
void DS3Check(unsigned int time)
{
if (time - lastDS3Check < DOUBLE_CHECK_DELAY) {
return;
}
if (!lastDS3Check) {
DS3Enum(time);
}
lastDS3Check = time;
usb_bus *bus = pusb_get_busses();
while (bus) {
TryInitDS3(bus->devices);
bus = bus->next;
}
usb_bus *bus = pusb_get_busses();
while (bus) {
TryInitDS3(bus->devices);
bus = bus->next;
}
}
int InitLibUsb() {
if (hModLibusb) {
return 1;
}
hModLibusb = LoadLibraryA("C:\\windows\\system32\\libusb0.dll");
if (hModLibusb) {
if ((pusb_init = (_usb_init) GetProcAddress(hModLibusb, "usb_init")) &&
(pusb_close = (_usb_close) GetProcAddress(hModLibusb, "usb_close")) &&
(pusb_get_string_simple = (_usb_get_string_simple) GetProcAddress(hModLibusb, "usb_get_string_simple")) &&
(pusb_open = (_usb_open) GetProcAddress(hModLibusb, "usb_open")) &&
(pusb_find_busses = (_usb_find_busses) GetProcAddress(hModLibusb, "usb_find_busses")) &&
(pusb_find_devices = (_usb_find_devices) GetProcAddress(hModLibusb, "usb_find_devices")) &&
(pusb_get_busses = (_usb_get_busses) GetProcAddress(hModLibusb, "usb_get_busses")) &&
(pusb_control_msg = (_usb_control_msg) GetProcAddress(hModLibusb, "usb_control_msg"))) {
pusb_init();
return 1;
}
UninitLibUsb();
}
return 0;
int InitLibUsb()
{
if (hModLibusb) {
return 1;
}
hModLibusb = LoadLibraryA("C:\\windows\\system32\\libusb0.dll");
if (hModLibusb) {
if ((pusb_init = (_usb_init)GetProcAddress(hModLibusb, "usb_init")) &&
(pusb_close = (_usb_close)GetProcAddress(hModLibusb, "usb_close")) &&
(pusb_get_string_simple = (_usb_get_string_simple)GetProcAddress(hModLibusb, "usb_get_string_simple")) &&
(pusb_open = (_usb_open)GetProcAddress(hModLibusb, "usb_open")) &&
(pusb_find_busses = (_usb_find_busses)GetProcAddress(hModLibusb, "usb_find_busses")) &&
(pusb_find_devices = (_usb_find_devices)GetProcAddress(hModLibusb, "usb_find_devices")) &&
(pusb_get_busses = (_usb_get_busses)GetProcAddress(hModLibusb, "usb_get_busses")) &&
(pusb_control_msg = (_usb_control_msg)GetProcAddress(hModLibusb, "usb_control_msg"))) {
pusb_init();
return 1;
}
UninitLibUsb();
}
return 0;
}
int DualShock3Possible() {
return InitLibUsb();
int DualShock3Possible()
{
return InitLibUsb();
}
#include <pshpack1.h>
struct MotorState {
unsigned char duration;
unsigned char force;
struct MotorState
{
unsigned char duration;
unsigned char force;
};
struct LightState {
// 0xFF makes it stay on.
unsigned char duration;
// Have to make one or the other non-zero to turn on light.
unsigned char dunno[2];
// 0 is fully lit.
unsigned char dimness;
// Have to make non-zero to turn on light.
unsigned char on;
struct LightState
{
// 0xFF makes it stay on.
unsigned char duration;
// Have to make one or the other non-zero to turn on light.
unsigned char dunno[2];
// 0 is fully lit.
unsigned char dimness;
// Have to make non-zero to turn on light.
unsigned char on;
};
// Data sent to DS3 to set state.
struct DS3Command {
unsigned char id;
unsigned char unsure;
// Small is first, then big.
MotorState motors[2];
unsigned char noClue[4];
// 2 is pad 1 light, 4 is pad 2, 8 is pad 3, 16 is pad 4. No clue about the others.
unsigned char lightFlags;
// Lights are in reverse order. pad 1 is last.
LightState lights[4];
unsigned char dunno[18];
struct DS3Command
{
unsigned char id;
unsigned char unsure;
// Small is first, then big.
MotorState motors[2];
unsigned char noClue[4];
// 2 is pad 1 light, 4 is pad 2, 8 is pad 3, 16 is pad 4. No clue about the others.
unsigned char lightFlags;
// Lights are in reverse order. pad 1 is last.
LightState lights[4];
unsigned char dunno[18];
};
#include <poppack.h>
int CharToAxis(unsigned char c) {
int v = (int)c + ((unsigned int)c >> 7);
return ((c-128) * FULLY_DOWN)>>7;
int CharToAxis(unsigned char c)
{
int v = (int)c + ((unsigned int)c >> 7);
return ((c - 128) * FULLY_DOWN) >> 7;
}
int CharToButton(unsigned char c) {
int v = (int)c + ((unsigned int)c >> 7);
return (v * FULLY_DOWN)>>8;
int CharToButton(unsigned char c)
{
int v = (int)c + ((unsigned int)c >> 7);
return (v * FULLY_DOWN) >> 8;
}
class DualShock3Device : public Device {
// Cached last vibration values by pad and motor.
// Need this, as only one value is changed at a time.
int ps2Vibration[2][4][2];
int vibration[2];
class DualShock3Device : public Device
{
// Cached last vibration values by pad and motor.
// Need this, as only one value is changed at a time.
int ps2Vibration[2][4][2];
int vibration[2];
public:
int index;
HANDLE hFile;
DS3Command sendState;
unsigned char getState[49];
OVERLAPPED readop;
OVERLAPPED writeop;
int writeCount;
int lastWrite;
int index;
HANDLE hFile;
DS3Command sendState;
unsigned char getState[49];
OVERLAPPED readop;
OVERLAPPED writeop;
int writeCount;
int lastWrite;
unsigned int dataLastReceived;
unsigned int dataLastReceived;
int writeQueued;
int writing;
int writeQueued;
int writing;
int StartRead() {
int res = ReadFile(hFile, &getState, sizeof(getState), 0, &readop);
return (res || GetLastError() == ERROR_IO_PENDING);
}
int StartRead()
{
int res = ReadFile(hFile, &getState, sizeof(getState), 0, &readop);
return (res || GetLastError() == ERROR_IO_PENDING);
}
void QueueWrite() {
// max of 2 queued writes allowed, one for either motor.
if (writeQueued < 2) {
writeQueued++;
StartWrite();
}
}
void QueueWrite()
{
// max of 2 queued writes allowed, one for either motor.
if (writeQueued < 2) {
writeQueued++;
StartWrite();
}
}
int StartWrite() {
if (!writing && writeQueued) {
lastWrite = GetTickCount();
writing++;
writeQueued--;
sendState.motors[0].duration = 0x50;
sendState.motors[1].duration = 0x50;
int StartWrite()
{
if (!writing && writeQueued) {
lastWrite = GetTickCount();
writing++;
writeQueued--;
sendState.motors[0].duration = 0x50;
sendState.motors[1].duration = 0x50;
int bigForce = vibration[0] * 256/FULLY_DOWN;
if (bigForce > 255) bigForce = 255;
sendState.motors[1].force = (unsigned char) bigForce;
sendState.motors[0].force = (unsigned char) (vibration[1] >= FULLY_DOWN/2);
// Can't seem to have them both non-zero at once.
if (sendState.motors[writeCount&1].force) {
sendState.motors[(writeCount&1)^1].force = 0;
sendState.motors[(writeCount&1)^1].duration = 0;
}
int bigForce = vibration[0] * 256 / FULLY_DOWN;
if (bigForce > 255)
bigForce = 255;
sendState.motors[1].force = (unsigned char)bigForce;
sendState.motors[0].force = (unsigned char)(vibration[1] >= FULLY_DOWN / 2);
// Can't seem to have them both non-zero at once.
if (sendState.motors[writeCount & 1].force) {
sendState.motors[(writeCount & 1) ^ 1].force = 0;
sendState.motors[(writeCount & 1) ^ 1].duration = 0;
}
writeCount++;
int res = WriteFile(hFile, &sendState, sizeof(sendState), 0, &writeop);
return (res || GetLastError() == ERROR_IO_PENDING);
}
return 1;
}
writeCount++;
int res = WriteFile(hFile, &sendState, sizeof(sendState), 0, &writeop);
return (res || GetLastError() == ERROR_IO_PENDING);
}
return 1;
}
DualShock3Device(int index, wchar_t *name, wchar_t *path) : Device(DS3, OTHER, name, path, L"DualShock 3") {
writeCount = 0;
writing = 0;
writeQueued = 0;
memset(&readop, 0, sizeof(readop));
memset(&writeop, 0, sizeof(writeop));
memset(&sendState, 0, sizeof(sendState));
sendState.id = 1;
int temp = (index&4);
sendState.lightFlags = (1 << (temp+1));
sendState.lights[3-temp].duration = 0xFF;
sendState.lights[3-temp].dunno[0] = 1;
sendState.lights[3-temp].on = 1;
memset(ps2Vibration, 0, sizeof(ps2Vibration));
vibration[0] = vibration[1] = 0;
this->index = index;
int i;
for (i=0; i<16; i++) {
if (i != 14 && i != 15 && i != 8 && i != 9) {
AddPhysicalControl(PRESSURE_BTN, i, 0);
}
else {
AddPhysicalControl(PSHBTN, i, 0);
}
}
for (; i<23; i++) {
AddPhysicalControl(ABSAXIS, i, 0);
}
AddFFAxis(L"Big Motor", 0);
AddFFAxis(L"Small Motor", 1);
AddFFEffectType(L"Constant Effect", L"Constant", EFFECT_CONSTANT);
hFile = INVALID_HANDLE_VALUE;
}
DualShock3Device(int index, wchar_t *name, wchar_t *path)
: Device(DS3, OTHER, name, path, L"DualShock 3")
{
writeCount = 0;
writing = 0;
writeQueued = 0;
memset(&readop, 0, sizeof(readop));
memset(&writeop, 0, sizeof(writeop));
memset(&sendState, 0, sizeof(sendState));
sendState.id = 1;
int temp = (index & 4);
sendState.lightFlags = (1 << (temp + 1));
sendState.lights[3 - temp].duration = 0xFF;
sendState.lights[3 - temp].dunno[0] = 1;
sendState.lights[3 - temp].on = 1;
memset(ps2Vibration, 0, sizeof(ps2Vibration));
vibration[0] = vibration[1] = 0;
this->index = index;
int i;
for (i = 0; i < 16; i++) {
if (i != 14 && i != 15 && i != 8 && i != 9) {
AddPhysicalControl(PRESSURE_BTN, i, 0);
} else {
AddPhysicalControl(PSHBTN, i, 0);
}
}
for (; i < 23; i++) {
AddPhysicalControl(ABSAXIS, i, 0);
}
AddFFAxis(L"Big Motor", 0);
AddFFAxis(L"Small Motor", 1);
AddFFEffectType(L"Constant Effect", L"Constant", EFFECT_CONSTANT);
hFile = INVALID_HANDLE_VALUE;
}
wchar_t *GetPhysicalControlName(PhysicalControl *c) {
const static wchar_t *names[] = {
L"Square",
L"Cross",
L"Circle",
L"Triangle",
L"R1",
L"L1",
L"R2",
L"L2",
L"R3",
L"L3",
L"Left",
L"Down",
L"Right",
L"Up",
L"Start",
L"Select",
L"L-Stick X",
L"L-Stick Y",
L"R-Stick X",
L"R-Stick Y",
L"Left/Right Tilt",
L"Forward/Back Tilt",
L"???",
};
unsigned int i = (unsigned int) (c - physicalControls);
if (i < sizeof(names)/sizeof(names[0])) {
return (wchar_t*)names[i];
}
return Device::GetPhysicalControlName(c);
}
wchar_t *GetPhysicalControlName(PhysicalControl *c)
{
const static wchar_t *names[] = {
L"Square",
L"Cross",
L"Circle",
L"Triangle",
L"R1",
L"L1",
L"R2",
L"L2",
L"R3",
L"L3",
L"Left",
L"Down",
L"Right",
L"Up",
L"Start",
L"Select",
L"L-Stick X",
L"L-Stick Y",
L"R-Stick X",
L"R-Stick Y",
L"Left/Right Tilt",
L"Forward/Back Tilt",
L"???",
};
unsigned int i = (unsigned int)(c - physicalControls);
if (i < sizeof(names) / sizeof(names[0])) {
return (wchar_t *)names[i];
}
return Device::GetPhysicalControlName(c);
}
int Activate(InitInfo *initInfo) {
if (active) Deactivate();
// Give grace period before get mad.
lastWrite = dataLastReceived = GetTickCount();
readop.hEvent = CreateEvent(0, 0, 0, 0);
writeop.hEvent = CreateEvent(0, 0, 0, 0);
hFile = CreateFileW(instanceID, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
if (!readop.hEvent || !writeop.hEvent || hFile == INVALID_HANDLE_VALUE ||
!StartRead()) {
Deactivate();
return 0;
}
active = 1;
AllocState();
return 1;
}
int Activate(InitInfo *initInfo)
{
if (active)
Deactivate();
// Give grace period before get mad.
lastWrite = dataLastReceived = GetTickCount();
readop.hEvent = CreateEvent(0, 0, 0, 0);
writeop.hEvent = CreateEvent(0, 0, 0, 0);
hFile = CreateFileW(instanceID, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
if (!readop.hEvent || !writeop.hEvent || hFile == INVALID_HANDLE_VALUE ||
!StartRead()) {
Deactivate();
return 0;
}
active = 1;
AllocState();
return 1;
}
int Update() {
if (!active) return 0;
HANDLE h[2] = {
readop.hEvent,
writeop.hEvent
};
unsigned int time = GetTickCount();
if (time - lastWrite > UPDATE_INTERVAL) {
QueueWrite();
}
while (1) {
DWORD res = WaitForMultipleObjects(2, h, 0, 0);
if (res == WAIT_OBJECT_0) {
dataLastReceived = time;
if (!StartRead()) {
Deactivate();
return 0;
}
int Update()
{
if (!active)
return 0;
HANDLE h[2] = {
readop.hEvent,
writeop.hEvent};
unsigned int time = GetTickCount();
if (time - lastWrite > UPDATE_INTERVAL) {
QueueWrite();
}
while (1) {
DWORD res = WaitForMultipleObjects(2, h, 0, 0);
if (res == WAIT_OBJECT_0) {
dataLastReceived = time;
if (!StartRead()) {
Deactivate();
return 0;
}
physicalControlState[0] = CharToButton(getState[25]);
physicalControlState[1] = CharToButton(getState[24]);
physicalControlState[2] = CharToButton(getState[23]);
physicalControlState[3] = CharToButton(getState[22]);
physicalControlState[4] = CharToButton(getState[21]);
physicalControlState[5] = CharToButton(getState[20]);
physicalControlState[6] = CharToButton(getState[19]);
physicalControlState[7] = CharToButton(getState[18]);
physicalControlState[10] = CharToButton(getState[17]);
physicalControlState[11] = CharToButton(getState[16]);
physicalControlState[12] = CharToButton(getState[15]);
physicalControlState[13] = CharToButton(getState[14]);
physicalControlState[8] = ((getState[2]&4)/4) * FULLY_DOWN;
physicalControlState[9] = ((getState[2]&2)/2) * FULLY_DOWN;
physicalControlState[15] = ((getState[2]&1)/1) * FULLY_DOWN;
physicalControlState[14] = ((getState[2]&8)/8) * FULLY_DOWN;
physicalControlState[16] = CharToAxis(getState[6]);
physicalControlState[17] = CharToAxis(getState[7]);
physicalControlState[18] = CharToAxis(getState[8]);
physicalControlState[19] = CharToAxis(getState[9]);
physicalControlState[20] = CharToAxis(getState[42]+128);
physicalControlState[21] = CharToAxis(getState[44]+128);
physicalControlState[22] = CharToAxis(getState[46]+128);
continue;
}
else if (res == WAIT_OBJECT_0+1) {
writing = 0;
if (!writeQueued && (vibration[0] | vibration[1])) {
QueueWrite();
}
if (!StartWrite()) {
Deactivate();
return 0;
}
}
else {
if (time-dataLastReceived >= DEVICE_CHECK_DELAY) {
if (time-dataLastReceived >= DEVICE_ENUM_DELAY) {
DS3Enum(time);
}
DS3Check(time);
QueueWrite();
}
}
break;
}
return 1;
}
physicalControlState[0] = CharToButton(getState[25]);
physicalControlState[1] = CharToButton(getState[24]);
physicalControlState[2] = CharToButton(getState[23]);
physicalControlState[3] = CharToButton(getState[22]);
physicalControlState[4] = CharToButton(getState[21]);
physicalControlState[5] = CharToButton(getState[20]);
physicalControlState[6] = CharToButton(getState[19]);
physicalControlState[7] = CharToButton(getState[18]);
physicalControlState[10] = CharToButton(getState[17]);
physicalControlState[11] = CharToButton(getState[16]);
physicalControlState[12] = CharToButton(getState[15]);
physicalControlState[13] = CharToButton(getState[14]);
physicalControlState[8] = ((getState[2] & 4) / 4) * FULLY_DOWN;
physicalControlState[9] = ((getState[2] & 2) / 2) * FULLY_DOWN;
physicalControlState[15] = ((getState[2] & 1) / 1) * FULLY_DOWN;
physicalControlState[14] = ((getState[2] & 8) / 8) * FULLY_DOWN;
physicalControlState[16] = CharToAxis(getState[6]);
physicalControlState[17] = CharToAxis(getState[7]);
physicalControlState[18] = CharToAxis(getState[8]);
physicalControlState[19] = CharToAxis(getState[9]);
physicalControlState[20] = CharToAxis(getState[42] + 128);
physicalControlState[21] = CharToAxis(getState[44] + 128);
physicalControlState[22] = CharToAxis(getState[46] + 128);
continue;
} else if (res == WAIT_OBJECT_0 + 1) {
writing = 0;
if (!writeQueued && (vibration[0] | vibration[1])) {
QueueWrite();
}
if (!StartWrite()) {
Deactivate();
return 0;
}
} else {
if (time - dataLastReceived >= DEVICE_CHECK_DELAY) {
if (time - dataLastReceived >= DEVICE_ENUM_DELAY) {
DS3Enum(time);
}
DS3Check(time);
QueueWrite();
}
}
break;
}
return 1;
}
void SetEffects(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force) {
ps2Vibration[port][slot][motor] = force;
vibration[0] = vibration[1] = 0;
for (int p=0; p<2; p++) {
for (int s=0; s<4; s++) {
for (int i=0; i<pads[p][s].numFFBindings; i++) {
// Technically should also be a *65535/BASE_SENSITIVITY, but that's close enough to 1 for me.
ForceFeedbackBinding *ffb = &pads[p][s].ffBindings[i];
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();
QueueWrite();
}
void SetEffects(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force)
{
ps2Vibration[port][slot][motor] = force;
vibration[0] = vibration[1] = 0;
for (int p = 0; p < 2; p++) {
for (int s = 0; s < 4; s++) {
for (int i = 0; i < pads[p][s].numFFBindings; i++) {
// Technically should also be a *65535/BASE_SENSITIVITY, but that's close enough to 1 for me.
ForceFeedbackBinding *ffb = &pads[p][s].ffBindings[i];
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();
QueueWrite();
}
void SetEffect(ForceFeedbackBinding *binding, unsigned char force) {
PadBindings pBackup = pads[0][0];
pads[0][0].ffBindings = binding;
pads[0][0].numFFBindings = 1;
SetEffects(0, 0, binding->motor, 255);
pads[0][0] = pBackup;
}
void SetEffect(ForceFeedbackBinding *binding, unsigned char force)
{
PadBindings pBackup = pads[0][0];
pads[0][0].ffBindings = binding;
pads[0][0].numFFBindings = 1;
SetEffects(0, 0, binding->motor, 255);
pads[0][0] = pBackup;
}
void Deactivate() {
if (hFile != INVALID_HANDLE_VALUE) {
CancelIo(hFile);
CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
}
if (readop.hEvent) {
CloseHandle(readop.hEvent);
}
if (writeop.hEvent) {
CloseHandle(writeop.hEvent);
}
writing = 0;
writeQueued = 0;
memset(ps2Vibration, 0, sizeof(ps2Vibration));
vibration[0] = vibration[1] = 0;
void Deactivate()
{
if (hFile != INVALID_HANDLE_VALUE) {
CancelIo(hFile);
CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
}
if (readop.hEvent) {
CloseHandle(readop.hEvent);
}
if (writeop.hEvent) {
CloseHandle(writeop.hEvent);
}
writing = 0;
writeQueued = 0;
memset(ps2Vibration, 0, sizeof(ps2Vibration));
vibration[0] = vibration[1] = 0;
FreeState();
active = 0;
}
FreeState();
active = 0;
}
~DualShock3Device() {
}
~DualShock3Device()
{
}
};
void EnumDualShock3s() {
if (!InitLibUsb()) return;
void EnumDualShock3s()
{
if (!InitLibUsb())
return;
HidDeviceInfo *foundDevs = 0;
HidDeviceInfo *foundDevs = 0;
int numDevs = FindHids(&foundDevs, VID, PID);
if (!numDevs) return;
int index = 0;
for (int i=0; i<numDevs; i++) {
if (foundDevs[i].caps.FeatureReportByteLength == 49 &&
foundDevs[i].caps.InputReportByteLength == 49 &&
foundDevs[i].caps.OutputReportByteLength == 49) {
wchar_t temp[100];
wsprintfW(temp, L"DualShock 3 #%i", index+1);
dm->AddDevice(new DualShock3Device(index, temp, foundDevs[i].path));
index++;
}
free(foundDevs[i].path);
}
free(foundDevs);
int numDevs = FindHids(&foundDevs, VID, PID);
if (!numDevs)
return;
int index = 0;
for (int i = 0; i < numDevs; i++) {
if (foundDevs[i].caps.FeatureReportByteLength == 49 &&
foundDevs[i].caps.InputReportByteLength == 49 &&
foundDevs[i].caps.OutputReportByteLength == 49) {
wchar_t temp[100];
wsprintfW(temp, L"DualShock 3 #%i", index + 1);
dm->AddDevice(new DualShock3Device(index, temp, foundDevs[i].path));
index++;
}
free(foundDevs[i].path);
}
free(foundDevs);
}

View File

@ -23,58 +23,62 @@
typedef uint32_t DWORD;
typedef uint16_t USHORT;
#ifndef __INTEL_COMPILER
typedef int64_t __int64;
typedef int64_t __int64;
#endif
#define MAX_PATH (256) // random value
#define MAX_PATH (256) // random value
#include <X11/keysym.h>
#define VK_SHIFT XK_Shift_L
#define VK_LSHIFT XK_Shift_L
#define VK_RSHIFT XK_Shift_R
#define VK_LMENU XK_Menu
#define VK_RMENU XK_Menu
#define VK_MENU XK_Menu
#define VK_CONTROL XK_Control_L
#define VK_TAB XK_Tab
#define VK_ESCAPE XK_Escape
#define VK_F4 XK_F4
#define VK_SHIFT XK_Shift_L
#define VK_LSHIFT XK_Shift_L
#define VK_RSHIFT XK_Shift_R
#define VK_LMENU XK_Menu
#define VK_RMENU XK_Menu
#define VK_MENU XK_Menu
#define VK_CONTROL XK_Control_L
#define VK_TAB XK_Tab
#define VK_ESCAPE XK_Escape
#define VK_F4 XK_F4
#include <cwchar>
#include <cstdarg>
template <typename Array>
void wsprintfW(Array& buf, const wchar_t *format, ...) {
va_list a;
va_start(a, format);
void wsprintfW(Array &buf, const wchar_t *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>
void wsprintf(Array& buf, const wchar_t *format, ...) {
va_list a;
va_start(a, format);
void wsprintf(Array &buf, const wchar_t *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) {
// I didn't find a way to put ignore case ...
return wcscmp(w1, 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);
}
#include <sys/time.h>
static inline unsigned int timeGetTime() {
struct timeval now;
gettimeofday(&now, NULL);
uint64_t ms = (now.tv_usec/1000) + ((uint64_t)now.tv_sec * 1000);
return (ms & 0xFFFFFFFF); // MS code is u32 ...
static inline unsigned int timeGetTime()
{
struct timeval now;
gettimeofday(&now, NULL);
uint64_t ms = (now.tv_usec / 1000) + ((uint64_t)now.tv_sec * 1000);
return (ms & 0xFFFFFFFF); // MS code is u32 ...
}
#include "Utilities/Dependencies.h"
@ -84,7 +88,7 @@ static inline unsigned int timeGetTime() {
#include <X11/Xutil.h>
extern Display *GSdsp;
extern Window GSwin;
extern Window GSwin;
#endif
@ -95,7 +99,7 @@ extern Window GSwin;
#ifdef _MSC_VER
#define EXPORT_C_(type) extern "C" type CALLBACK
#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
#ifdef _MSC_VER
@ -136,35 +140,60 @@ extern HINSTANCE hInst;
// Needed for config screen
void GetNameAndVersionString(wchar_t *out);
typedef struct {
unsigned char controllerType;
unsigned short buttonStatus;
unsigned char rightJoyX, rightJoyY, leftJoyX, leftJoyY;
unsigned char moveX, moveY;
unsigned char reserved[91];
typedef struct
{
unsigned char controllerType;
unsigned short buttonStatus;
unsigned char rightJoyX, rightJoyY, leftJoyX, leftJoyY;
unsigned char moveX, moveY;
unsigned char reserved[91];
} PadDataS;
EXPORT_C_(void) PADupdate(int pad);
EXPORT_C_(u32) PS2EgetLibType(void);
EXPORT_C_(u32) PS2EgetLibVersion2(u32 type);
EXPORT_C_(char*) PSEgetLibName();
EXPORT_C_(char*) PS2EgetLibName(void);
EXPORT_C_(void) PADshutdown();
EXPORT_C_(s32) PADinit(u32 flags);
EXPORT_C_(s32) PADopen(void *pDsp);
EXPORT_C_(void) PADclose();
EXPORT_C_(u8) PADstartPoll(int pad);
EXPORT_C_(u8) PADpoll(u8 value);
EXPORT_C_(u32) 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);
EXPORT_C_(void)
PADupdate(int pad);
EXPORT_C_(u32)
PS2EgetLibType(void);
EXPORT_C_(u32)
PS2EgetLibVersion2(u32 type);
EXPORT_C_(char *)
PSEgetLibName();
EXPORT_C_(char *)
PS2EgetLibName(void);
EXPORT_C_(void)
PADshutdown();
EXPORT_C_(s32)
PADinit(u32 flags);
EXPORT_C_(s32)
PADopen(void *pDsp);
EXPORT_C_(void)
PADclose();
EXPORT_C_(u8)
PADstartPoll(int pad);
EXPORT_C_(u8)
PADpoll(u8 value);
EXPORT_C_(u32)
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 <hidsdi.h>
int FindHids(HidDeviceInfo **foundDevs, int vid, int pid) {
GUID GUID_DEVINTERFACE_HID;
int numFoundDevs = 0;
*foundDevs = 0;
HidD_GetHidGuid(&GUID_DEVINTERFACE_HID);
HDEVINFO hdev = SetupDiGetClassDevs(&GUID_DEVINTERFACE_HID, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hdev != INVALID_HANDLE_VALUE) {
SP_DEVICE_INTERFACE_DATA devInterfaceData;
devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
for (int i=0; SetupDiEnumDeviceInterfaces(hdev, 0, &GUID_DEVINTERFACE_HID, i, &devInterfaceData); i++) {
int FindHids(HidDeviceInfo **foundDevs, int vid, int pid)
{
GUID GUID_DEVINTERFACE_HID;
int numFoundDevs = 0;
*foundDevs = 0;
HidD_GetHidGuid(&GUID_DEVINTERFACE_HID);
HDEVINFO hdev = SetupDiGetClassDevs(&GUID_DEVINTERFACE_HID, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hdev != INVALID_HANDLE_VALUE) {
SP_DEVICE_INTERFACE_DATA devInterfaceData;
devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
for (int i = 0; SetupDiEnumDeviceInterfaces(hdev, 0, &GUID_DEVINTERFACE_HID, i, &devInterfaceData); i++) {
DWORD size = 0;
SetupDiGetDeviceInterfaceDetail(hdev, &devInterfaceData, 0, 0, &size, 0);
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER || !size) continue;
SP_DEVICE_INTERFACE_DETAIL_DATA *devInterfaceDetails = (SP_DEVICE_INTERFACE_DETAIL_DATA *) malloc(size);
if (!devInterfaceDetails) continue;
DWORD size = 0;
SetupDiGetDeviceInterfaceDetail(hdev, &devInterfaceData, 0, 0, &size, 0);
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER || !size)
continue;
SP_DEVICE_INTERFACE_DETAIL_DATA *devInterfaceDetails = (SP_DEVICE_INTERFACE_DETAIL_DATA *)malloc(size);
if (!devInterfaceDetails)
continue;
devInterfaceDetails->cbSize = sizeof(*devInterfaceDetails);
SP_DEVINFO_DATA devInfoData;
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
devInterfaceDetails->cbSize = sizeof(*devInterfaceDetails);
SP_DEVINFO_DATA devInfoData;
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);
if (hfile != INVALID_HANDLE_VALUE) {
HIDD_ATTRIBUTES attributes;
attributes.Size = sizeof(attributes);
if (HidD_GetAttributes(hfile, &attributes)) {
if (attributes.VendorID == vid && attributes.ProductID == pid) {
PHIDP_PREPARSED_DATA pData;
HIDP_CAPS caps;
if (HidD_GetPreparsedData(hfile, &pData)) {
if (HidP_GetCaps(pData, &caps) == HIDP_STATUS_SUCCESS) {
if (numFoundDevs % 32 == 0) {
*foundDevs = (HidDeviceInfo*) realloc(*foundDevs, sizeof(HidDeviceInfo) * (32 + numFoundDevs));
}
HidDeviceInfo *dev = &foundDevs[0][numFoundDevs++];
dev->caps = caps;
dev->vid = attributes.VendorID;
dev->pid = attributes.ProductID;
dev->path = wcsdup(devInterfaceDetails->DevicePath);
}
HidD_FreePreparsedData(pData);
}
}
}
CloseHandle(hfile);
}
free(devInterfaceDetails);
}
SetupDiDestroyDeviceInfoList(hdev);
}
return numFoundDevs;
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) {
HIDD_ATTRIBUTES attributes;
attributes.Size = sizeof(attributes);
if (HidD_GetAttributes(hfile, &attributes)) {
if (attributes.VendorID == vid && attributes.ProductID == pid) {
PHIDP_PREPARSED_DATA pData;
HIDP_CAPS caps;
if (HidD_GetPreparsedData(hfile, &pData)) {
if (HidP_GetCaps(pData, &caps) == HIDP_STATUS_SUCCESS) {
if (numFoundDevs % 32 == 0) {
*foundDevs = (HidDeviceInfo *)realloc(*foundDevs, sizeof(HidDeviceInfo) * (32 + numFoundDevs));
}
HidDeviceInfo *dev = &foundDevs[0][numFoundDevs++];
dev->caps = caps;
dev->vid = attributes.VendorID;
dev->pid = attributes.ProductID;
dev->path = wcsdup(devInterfaceDetails->DevicePath);
}
HidD_FreePreparsedData(pData);
}
}
}
CloseHandle(hfile);
}
free(devInterfaceDetails);
}
SetupDiDestroyDeviceInfoList(hdev);
}
return numFoundDevs;
}

View File

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

View File

@ -34,64 +34,68 @@ static u8 lastQueuedEvent = 0;
static u8 nextQueuedEvent = 0;
static keyEvent queuedEvents[EVENT_QUEUE_LEN];
void QueueKeyEvent(int key, int event) {
void QueueKeyEvent(int key, int event)
{
#ifdef _MSC_VER
if (!csInitialized) {
csInitialized = 1;
InitializeCriticalSection(&cSection);
}
EnterCriticalSection(&cSection);
if (!csInitialized) {
csInitialized = 1;
InitializeCriticalSection(&cSection);
}
EnterCriticalSection(&cSection);
#else
std::lock_guard<std::mutex> lock(cSection);
std::lock_guard<std::mutex> lock(cSection);
#endif
// 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.
if (nextQueuedEvent == lastQueuedEvent ||
queuedEvents[nextQueuedEvent].key != VK_ESCAPE ||
queuedEvents[nextQueuedEvent].evt != KEYPRESS) {
// Clear queue on escape down, bringing escape to front. May do something
// with shift/ctrl/alt and F-keys, later.
if (event == KEYPRESS && key == VK_ESCAPE) {
nextQueuedEvent = lastQueuedEvent;
}
// 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.
if (nextQueuedEvent == lastQueuedEvent ||
queuedEvents[nextQueuedEvent].key != VK_ESCAPE ||
queuedEvents[nextQueuedEvent].evt != KEYPRESS) {
// Clear queue on escape down, bringing escape to front. May do something
// with shift/ctrl/alt and F-keys, later.
if (event == KEYPRESS && key == VK_ESCAPE) {
nextQueuedEvent = lastQueuedEvent;
}
queuedEvents[lastQueuedEvent].key = key;
queuedEvents[lastQueuedEvent].evt = event;
queuedEvents[lastQueuedEvent].key = key;
queuedEvents[lastQueuedEvent].evt = event;
lastQueuedEvent = (lastQueuedEvent + 1) % EVENT_QUEUE_LEN;
// If queue wrapped around, remove last element.
if (nextQueuedEvent == lastQueuedEvent) {
nextQueuedEvent = (nextQueuedEvent + 1) % EVENT_QUEUE_LEN;
}
}
lastQueuedEvent = (lastQueuedEvent + 1) % EVENT_QUEUE_LEN;
// If queue wrapped around, remove last element.
if (nextQueuedEvent == lastQueuedEvent) {
nextQueuedEvent = (nextQueuedEvent + 1) % EVENT_QUEUE_LEN;
}
}
#ifdef _MSC_VER
LeaveCriticalSection(&cSection);
LeaveCriticalSection(&cSection);
#endif
}
int GetQueuedKeyEvent(keyEvent *event) {
if (lastQueuedEvent == nextQueuedEvent) return 0;
int GetQueuedKeyEvent(keyEvent *event)
{
if (lastQueuedEvent == nextQueuedEvent)
return 0;
#ifdef _MSC_VER
EnterCriticalSection(&cSection);
EnterCriticalSection(&cSection);
#else
std::lock_guard<std::mutex> lock(cSection);
std::lock_guard<std::mutex> lock(cSection);
#endif
*event = queuedEvents[nextQueuedEvent];
nextQueuedEvent = (nextQueuedEvent + 1) % EVENT_QUEUE_LEN;
*event = queuedEvents[nextQueuedEvent];
nextQueuedEvent = (nextQueuedEvent + 1) % EVENT_QUEUE_LEN;
#ifdef _MSC_VER
LeaveCriticalSection(&cSection);
LeaveCriticalSection(&cSection);
#endif
return 1;
return 1;
}
void ClearKeyQueue() {
lastQueuedEvent = nextQueuedEvent;
void ClearKeyQueue()
{
lastQueuedEvent = nextQueuedEvent;
#ifdef _MSC_VER
if (csInitialized) {
DeleteCriticalSection(&cSection);
csInitialized = 0;
}
if (csInitialized) {
DeleteCriticalSection(&cSection);
csInitialized = 0;
}
#endif
}

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -20,29 +20,29 @@
#include "Global.h"
#include <wx/fileconf.h>
extern void CfgSetSettingsDir(const char* dir);
extern void CfgSetSettingsDir(const char *dir);
class CfgHelper {
wxFileConfig* m_config;
static wxString m_path;
class CfgHelper
{
wxFileConfig *m_config;
static wxString m_path;
void setIni(const wchar_t* Section);
void setIni(const wchar_t *Section);
public:
CfgHelper();
~CfgHelper();
public:
CfgHelper();
~CfgHelper();
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 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 WriteBool(const wchar_t *Section, const wchar_t *Name, bool 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 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);
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 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);
static void SetSettingsDir(const char* dir);
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, wchar_t *Data, const wchar_t *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);
static void SetSettingsDir(const char *dir);
};

View File

@ -20,189 +20,191 @@
#include "Linux/JoyEvdev.h"
#include "Linux/bitmaskros.h"
JoyEvdev::JoyEvdev(int fd, bool ds3, const wchar_t *id) : Device(LNX_JOY, OTHER, id, id), m_fd(fd) {
// XXX LNX_JOY => DS3 or ???
JoyEvdev::JoyEvdev(int fd, bool ds3, const wchar_t *id)
: Device(LNX_JOY, OTHER, id, id)
, m_fd(fd)
{
// XXX LNX_JOY => DS3 or ???
m_abs.clear();
m_btn.clear();
m_rel.clear();
int last = 0;
m_abs.clear();
m_btn.clear();
m_rel.clear();
int last = 0;
uint8_t abs_bitmap[nUcharsForNBits(ABS_CNT)] = {0};
uint8_t btn_bitmap[nUcharsForNBits(KEY_CNT)] = {0};
uint8_t rel_bitmap[nUcharsForNBits(REL_CNT)] = {0};
uint8_t abs_bitmap[nUcharsForNBits(ABS_CNT)] = {0};
uint8_t btn_bitmap[nUcharsForNBits(KEY_CNT)] = {0};
uint8_t rel_bitmap[nUcharsForNBits(REL_CNT)] = {0};
// Add buttons
if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(btn_bitmap)), btn_bitmap) >= 0) {
for (int bit = BTN_MISC; bit < KEY_CNT; bit++) {
if (testBit(bit, btn_bitmap)) {
AddPhysicalControl(PSHBTN, last, 0);
m_btn.push_back(bit);
last++;
}
}
}
// Add buttons
if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(btn_bitmap)), btn_bitmap) >= 0) {
for (int bit = BTN_MISC; bit < KEY_CNT; bit++) {
if (testBit(bit, btn_bitmap)) {
AddPhysicalControl(PSHBTN, last, 0);
m_btn.push_back(bit);
last++;
}
}
}
// Add Absolute axis
if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmap)), abs_bitmap) >= 0) {
for (int bit = 0; bit < ABS_CNT; bit++) {
ControlType type = ABSAXIS; // FIXME DS3
// Add Absolute axis
if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmap)), abs_bitmap) >= 0) {
for (int bit = 0; bit < ABS_CNT; bit++) {
ControlType type = ABSAXIS; // FIXME DS3
if (testBit(bit, abs_bitmap)) {
input_absinfo info;
if (ioctl(m_fd, EVIOCGABS(bit), &info) < 0) {
fprintf(stderr, "Invalid IOCTL EVIOCGID\n");
continue;
}
if (testBit(bit, abs_bitmap)) {
input_absinfo info;
if (ioctl(m_fd, EVIOCGABS(bit), &info) < 0) {
fprintf(stderr, "Invalid IOCTL EVIOCGID\n");
continue;
}
AddPhysicalControl(ABSAXIS, last, 0);
last++;
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);
AddPhysicalControl(ABSAXIS, last, 0);
last++;
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);
// Half axis must be split into 2 parts...
AddPhysicalControl(ABSAXIS, last, 0);
last++;
// Half axis must be split into 2 parts...
AddPhysicalControl(ABSAXIS, last, 0);
last++;
m_abs.push_back(abs_info(bit, info.minimum, info.value, type));
m_abs.push_back(abs_info(bit, info.value, info.maximum, type));
} 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);
m_abs.push_back(abs_info(bit, info.minimum, info.value, type));
m_abs.push_back(abs_info(bit, info.value, info.maximum, type));
} 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);
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
if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmap)), rel_bitmap) >= 0) {
for (int bit = 0; bit < REL_CNT; bit++) {
if (testBit(bit, rel_bitmap)) {
AddPhysicalControl(RELAXIS, last, last);
m_rel.push_back(bit);
last++;
// Add relative axis
if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmap)), rel_bitmap) >= 0) {
for (int bit = 0; bit < REL_CNT; bit++) {
if (testBit(bit, rel_bitmap)) {
AddPhysicalControl(RELAXIS, last, last);
m_rel.push_back(bit);
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() {
close(m_fd);
JoyEvdev::~JoyEvdev()
{
close(m_fd);
}
int JoyEvdev::Activate(InitInfo* args) {
AllocState();
int JoyEvdev::Activate(InitInfo *args)
{
AllocState();
uint16_t size = m_abs.size()+m_rel.size()+m_btn.size();
memset(physicalControlState, 0, sizeof(int)*size);
uint16_t size = m_abs.size() + m_rel.size() + m_btn.size();
memset(physicalControlState, 0, sizeof(int) * size);
active = 1;
return 1;
active = 1;
return 1;
}
int JoyEvdev::Update() {
int JoyEvdev::Update()
{
struct input_event events[32];
int len;
int status = 0;
//fprintf(stderr, "Update was called\n");
// Do a big read to reduce kernel validation
int len;
int status = 0;
//fprintf(stderr, "Update was called\n");
// Do a big read to reduce kernel validation
while ((len = read(m_fd, events, (sizeof events))) > 0) {
int evt_nb = len / sizeof(input_event);
//fprintf(stderr, "Poll %d events available\n", evt_nb);
for (int i = 0; i < evt_nb; i++) {
switch(events[i].type) {
case EV_ABS:
{
for (size_t idx = 0; idx < m_abs.size(); idx++) {
if (m_abs[idx].code == events[i].code) {
// XXX strict or not ?
if ((events[i].value >= m_abs[idx].min) && (events[i].value <= m_abs[idx].max)) {
// XXX FIX shitty api
int scale = m_abs[idx].scale(events[i].value);
fprintf(stderr, "axis value %d scaled to %d\n", events[i].value, scale);
physicalControlState[idx + m_btn.size()] = scale;
status = 1;
}
}
}
}
break;
case EV_KEY:
{
for (size_t idx = 0; idx < m_btn.size(); idx++) {
if (m_btn[idx] == events[i].code) {
fprintf(stderr, "Event KEY:%d detected with value %d\n", events[i].code, events[i].value);
physicalControlState[idx] = FULLY_DOWN * events[i].value;
status = 1;
break;
}
}
int evt_nb = len / sizeof(input_event);
//fprintf(stderr, "Poll %d events available\n", evt_nb);
for (int i = 0; i < evt_nb; i++) {
switch (events[i].type) {
case EV_ABS: {
for (size_t idx = 0; idx < m_abs.size(); idx++) {
if (m_abs[idx].code == events[i].code) {
// XXX strict or not ?
if ((events[i].value >= m_abs[idx].min) && (events[i].value <= m_abs[idx].max)) {
// XXX FIX shitty api
int scale = m_abs[idx].scale(events[i].value);
fprintf(stderr, "axis value %d scaled to %d\n", events[i].value, scale);
physicalControlState[idx + m_btn.size()] = scale;
status = 1;
}
}
}
} break;
case EV_KEY: {
for (size_t idx = 0; idx < m_btn.size(); idx++) {
if (m_btn[idx] == events[i].code) {
fprintf(stderr, "Event KEY:%d detected with value %d\n", events[i].code, events[i].value);
physicalControlState[idx] = FULLY_DOWN * events[i].value;
status = 1;
break;
}
}
}
break;
case EV_REL:
// XXX
break;
default:
break;
}
}
} break;
case EV_REL:
// XXX
break;
default:
break;
}
}
}
}
return status;
return status;
}
static std::wstring CorrectJoySupport(int fd) {
struct input_id id;
if (ioctl(fd, EVIOCGID, &id) < 0) {
fprintf(stderr, "Invalid IOCTL EVIOCGID\n");
return L"";
}
static std::wstring CorrectJoySupport(int fd)
{
struct input_id id;
if (ioctl(fd, EVIOCGID, &id) < 0) {
fprintf(stderr, "Invalid IOCTL EVIOCGID\n");
return L"";
}
char dev_name[128];
if (ioctl(fd, EVIOCGNAME(128), dev_name) < 0) {
fprintf(stderr, "Invalid IOCTL EVIOCGNAME\n");
return L"";
}
char dev_name[128];
if (ioctl(fd, EVIOCGNAME(128), dev_name) < 0) {
fprintf(stderr, "Invalid IOCTL EVIOCGNAME\n");
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, "\tName:%s\n", dev_name);
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);
std::string s(dev_name);
return std::wstring(s.begin(), s.end());
std::string s(dev_name);
return std::wstring(s.begin(), s.end());
}
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
// so maybe later)
int found_devices = 0;
std::string input_root("/dev/input/event");
for (int i = 0; i < 32; i++) {
std::string dev = input_root + std::to_string(i);
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
// so maybe later)
int found_devices = 0;
std::string input_root("/dev/input/event");
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);
if (fd < 0) {
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);
}
int fd = open(dev.c_str(), O_RDWR | O_NONBLOCK);
if (fd < 0) {
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);
}
}

View File

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

View File

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

View File

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

View File

@ -32,30 +32,35 @@ static u8 R_lastQueuedEvent = 0;
static u8 R_nextQueuedEvent = 0;
static keyEvent R_queuedEvents[R_EVENT_QUEUE_LEN];
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)
void R_QueueKeyEvent(const 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

View File

@ -21,20 +21,20 @@
*/
/* 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 */
#define nUcharsForNBits(nBits) ((((nBits)-1)/nBitsPerUchar)+1)
#define nUcharsForNBits(nBits) ((((nBits)-1) / nBitsPerUchar) + 1)
/* 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
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 */
#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 */
#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);
int GetRawKeyboards(HWND hWnd) {
RAWINPUTDEVICE Rid;
Rid.hwndTarget = hWnd;
int GetRawKeyboards(HWND hWnd)
{
RAWINPUTDEVICE Rid;
Rid.hwndTarget = hWnd;
Rid.dwFlags = 0;
Rid.usUsagePage = 0x01;
Rid.usUsage = 0x06;
return RegisterRawInputDevices(&Rid, 1, sizeof(Rid));
Rid.dwFlags = 0;
Rid.usUsagePage = 0x01;
Rid.usUsage = 0x06;
return RegisterRawInputDevices(&Rid, 1, sizeof(Rid));
}
void ReleaseRawKeyboards() {
RAWINPUTDEVICE Rid;
Rid.hwndTarget = 0;
void ReleaseRawKeyboards()
{
RAWINPUTDEVICE Rid;
Rid.hwndTarget = 0;
Rid.dwFlags = RIDEV_REMOVE;
Rid.usUsagePage = 0x01;
Rid.usUsage = 0x06;
RegisterRawInputDevices(&Rid, 1, sizeof(Rid));
Rid.dwFlags = RIDEV_REMOVE;
Rid.usUsagePage = 0x01;
Rid.usUsage = 0x06;
RegisterRawInputDevices(&Rid, 1, sizeof(Rid));
}
int GetRawMice(HWND hWnd) {
RAWINPUTDEVICE Rid;
Rid.hwndTarget = hWnd;
int GetRawMice(HWND hWnd)
{
RAWINPUTDEVICE Rid;
Rid.hwndTarget = hWnd;
Rid.dwFlags = RIDEV_NOLEGACY | RIDEV_CAPTUREMOUSE;
Rid.usUsagePage = 0x01;
Rid.usUsage = 0x02;
return RegisterRawInputDevices(&Rid, 1, sizeof(Rid));
Rid.dwFlags = RIDEV_NOLEGACY | RIDEV_CAPTUREMOUSE;
Rid.usUsagePage = 0x01;
Rid.usUsage = 0x02;
return RegisterRawInputDevices(&Rid, 1, sizeof(Rid));
}
void ReleaseRawMice() {
RAWINPUTDEVICE Rid;
Rid.hwndTarget = 0;
void ReleaseRawMice()
{
RAWINPUTDEVICE Rid;
Rid.hwndTarget = 0;
Rid.dwFlags = RIDEV_REMOVE;
Rid.usUsagePage = 0x01;
Rid.usUsage = 0x02;
RegisterRawInputDevices(&Rid, 1, sizeof(Rid));
Rid.dwFlags = RIDEV_REMOVE;
Rid.usUsagePage = 0x01;
Rid.usUsage = 0x02;
RegisterRawInputDevices(&Rid, 1, sizeof(Rid));
}
// Count of active raw keyboard devices.
@ -72,234 +76,256 @@ static int rawKeyboardActivatedCount = 0;
// Same for mice.
static int rawMouseActivatedCount = 0;
class RawInputKeyboard : public WindowsKeyboard {
class RawInputKeyboard : public WindowsKeyboard
{
public:
HANDLE hDevice;
HANDLE hDevice;
RawInputKeyboard(HANDLE hDevice, wchar_t *name, wchar_t *instanceID=0) : WindowsKeyboard(RAW, name, instanceID) {
this->hDevice = hDevice;
}
RawInputKeyboard(HANDLE hDevice, wchar_t *name, wchar_t *instanceID = 0)
: WindowsKeyboard(RAW, name, instanceID)
{
this->hDevice = hDevice;
}
int Activate(InitInfo *initInfo) {
Deactivate();
int Activate(InitInfo *initInfo)
{
Deactivate();
hWndProc = initInfo->hWndProc;
hWndProc = initInfo->hWndProc;
active = 1;
if (!rawKeyboardActivatedCount++) {
if (!rawMouseActivatedCount)
hWndProc->Eat(RawInputWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
active = 1;
if (!rawKeyboardActivatedCount++) {
if (!rawMouseActivatedCount)
hWndProc->Eat(RawInputWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
if (!GetRawKeyboards(hWndProc->hWndEaten)) {
Deactivate();
return 0;
}
}
if (!GetRawKeyboards(hWndProc->hWndEaten)) {
Deactivate();
return 0;
}
}
InitState();
return 1;
}
InitState();
return 1;
}
void Deactivate() {
FreeState();
if (active) {
active = 0;
rawKeyboardActivatedCount --;
if (!rawKeyboardActivatedCount) {
ReleaseRawKeyboards();
if (!rawMouseActivatedCount)
hWndProc->ReleaseExtraProc(RawInputWndProc);
}
}
}
void Deactivate()
{
FreeState();
if (active) {
active = 0;
rawKeyboardActivatedCount--;
if (!rawKeyboardActivatedCount) {
ReleaseRawKeyboards();
if (!rawMouseActivatedCount)
hWndProc->ReleaseExtraProc(RawInputWndProc);
}
}
}
};
class RawInputMouse : public WindowsMouse {
class RawInputMouse : public WindowsMouse
{
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) {
this->hDevice = hDevice;
}
RawInputMouse(HANDLE hDevice, wchar_t *name, wchar_t *instanceID = 0, wchar_t *productID = 0)
: WindowsMouse(RAW, 0, name, instanceID, productID)
{
this->hDevice = hDevice;
}
int Activate(InitInfo *initInfo) {
Deactivate();
int Activate(InitInfo *initInfo)
{
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
// EatWndProc fail. In all other cases, no unmatched initialization/cleanup
// lines.
if (!rawMouseActivatedCount++) {
GetMouseCapture(hWndProc->hWndEaten);
if (!rawKeyboardActivatedCount)
hWndProc->Eat(RawInputWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
// Have to be careful with order. At worst, one unmatched call to ReleaseRawMice on
// EatWndProc fail. In all other cases, no unmatched initialization/cleanup
// lines.
if (!rawMouseActivatedCount++) {
GetMouseCapture(hWndProc->hWndEaten);
if (!rawKeyboardActivatedCount)
hWndProc->Eat(RawInputWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
if (!GetRawMice(hWndProc->hWndEaten)) {
Deactivate();
return 0;
}
}
if (!GetRawMice(hWndProc->hWndEaten)) {
Deactivate();
return 0;
}
}
AllocState();
return 1;
}
AllocState();
return 1;
}
void Deactivate() {
FreeState();
if (active) {
active = 0;
rawMouseActivatedCount --;
if (!rawMouseActivatedCount) {
ReleaseRawMice();
ReleaseMouseCapture();
if (!rawKeyboardActivatedCount) {
hWndProc->ReleaseExtraProc(RawInputWndProc);
}
}
}
}
void Deactivate()
{
FreeState();
if (active) {
active = 0;
rawMouseActivatedCount--;
if (!rawMouseActivatedCount) {
ReleaseRawMice();
ReleaseMouseCapture();
if (!rawKeyboardActivatedCount) {
hWndProc->ReleaseExtraProc(RawInputWndProc);
}
}
}
}
};
ExtraWndProcResult RawInputWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *output) {
if (uMsg == WM_INPUT) {
if (GET_RAWINPUT_CODE_WPARAM (wParam) == RIM_INPUT) {
RAWINPUT in;
unsigned int size = sizeof(RAWINPUT);
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, &in, &size, sizeof(RAWINPUTHEADER)) > 0) {
for (int i=0; i<dm->numDevices; i++) {
Device *dev = dm->devices[i];
if (dev->api != RAW || !dev->active) continue;
if (in.header.dwType == RIM_TYPEKEYBOARD && dev->type == KEYBOARD) {
RawInputKeyboard* rik = (RawInputKeyboard*)dev;
if (rik->hDevice != in.header.hDevice) continue;
ExtraWndProcResult RawInputWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *output)
{
if (uMsg == WM_INPUT) {
if (GET_RAWINPUT_CODE_WPARAM(wParam) == RIM_INPUT) {
RAWINPUT in;
unsigned int size = sizeof(RAWINPUT);
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, &in, &size, sizeof(RAWINPUTHEADER)) > 0) {
for (int i = 0; i < dm->numDevices; i++) {
Device *dev = dm->devices[i];
if (dev->api != RAW || !dev->active)
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;
if (!(in.data.keyboard.VKey>>8))
rik->UpdateKey((u8) in.data.keyboard.VKey, (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN));
}
else if (in.header.dwType == RIM_TYPEMOUSE && dev->type == MOUSE) {
RawInputMouse* rim = (RawInputMouse*)dev;
if (rim->hDevice != in.header.hDevice) continue;
if (in.data.mouse.usFlags) {
// Never been set for me, and specs on what most of them
// actually mean is sorely lacking. Also, specs erroneously
// indicate MOUSE_MOVE_RELATIVE is a flag, when it's really
// 0...
continue;
}
u32 uMsg = in.data.keyboard.Message;
if (!(in.data.keyboard.VKey >> 8))
rik->UpdateKey((u8)in.data.keyboard.VKey, (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN));
} else if (in.header.dwType == RIM_TYPEMOUSE && dev->type == MOUSE) {
RawInputMouse *rim = (RawInputMouse *)dev;
if (rim->hDevice != in.header.hDevice)
continue;
if (in.data.mouse.usFlags) {
// Never been set for me, and specs on what most of them
// actually mean is sorely lacking. Also, specs erroneously
// indicate MOUSE_MOVE_RELATIVE is a flag, when it's really
// 0...
continue;
}
unsigned short buttons = in.data.mouse.usButtonFlags & 0x3FF;
int button = 0;
while (buttons) {
if (buttons & 3) {
// 2 is up, 1 is down. Up takes precedence over down.
rim->UpdateButton(button, !(buttons & 2));
}
button++;
buttons >>= 2;
}
if (in.data.mouse.usButtonFlags & RI_MOUSE_WHEEL) {
rim->UpdateAxis(2, ((short)in.data.mouse.usButtonData)/WHEEL_DELTA);
}
if (in.data.mouse.lLastX || in.data.mouse.lLastY) {
rim->UpdateAxis(0, in.data.mouse.lLastX);
rim->UpdateAxis(1, in.data.mouse.lLastY);
}
}
}
}
}
}
else if (uMsg == WM_ACTIVATE) {
for (int i=0; i<dm->numDevices; i++) {
Device *dev = dm->devices[i];
if (dev->api != RAW || dev->physicalControlState == 0) continue;
memset(dev->physicalControlState, 0, sizeof(int) * dev->numPhysicalControls);
}
}
else if (uMsg == WM_SIZE && rawMouseActivatedCount) {
// Doesn't really matter for raw mice, as I disable legacy stuff, but shouldn't hurt.
WindowsMouse::WindowResized(hWnd);
}
unsigned short buttons = in.data.mouse.usButtonFlags & 0x3FF;
int button = 0;
while (buttons) {
if (buttons & 3) {
// 2 is up, 1 is down. Up takes precedence over down.
rim->UpdateButton(button, !(buttons & 2));
}
button++;
buttons >>= 2;
}
if (in.data.mouse.usButtonFlags & RI_MOUSE_WHEEL) {
rim->UpdateAxis(2, ((short)in.data.mouse.usButtonData) / WHEEL_DELTA);
}
if (in.data.mouse.lLastX || in.data.mouse.lLastY) {
rim->UpdateAxis(0, in.data.mouse.lLastX);
rim->UpdateAxis(1, in.data.mouse.lLastY);
}
}
}
}
}
} else if (uMsg == WM_ACTIVATE) {
for (int i = 0; i < dm->numDevices; i++) {
Device *dev = dm->devices[i];
if (dev->api != RAW || dev->physicalControlState == 0)
continue;
memset(dev->physicalControlState, 0, sizeof(int) * dev->numPhysicalControls);
}
} else if (uMsg == WM_SIZE && rawMouseActivatedCount) {
// Doesn't really matter for raw mice, as I disable legacy stuff, but shouldn't hurt.
WindowsMouse::WindowResized(hWnd);
}
return CONTINUE_BLISSFULLY;
return CONTINUE_BLISSFULLY;
}
void EnumRawInputDevices() {
int count = 0;
if (GetRawInputDeviceList(0, (unsigned int*)&count, sizeof(RAWINPUTDEVICELIST)) != (UINT)-1 && count > 0) {
wchar_t *instanceID = (wchar_t *) malloc(41000*sizeof(wchar_t));
wchar_t *keyName = instanceID + 11000;
wchar_t *displayName = keyName + 10000;
wchar_t *productID = displayName + 10000;
void EnumRawInputDevices()
{
int count = 0;
if (GetRawInputDeviceList(0, (unsigned int *)&count, sizeof(RAWINPUTDEVICELIST)) != (UINT)-1 && count > 0) {
wchar_t *instanceID = (wchar_t *)malloc(41000 * sizeof(wchar_t));
wchar_t *keyName = instanceID + 11000;
wchar_t *displayName = keyName + 10000;
wchar_t *productID = displayName + 10000;
RAWINPUTDEVICELIST *list = (RAWINPUTDEVICELIST*) malloc(sizeof(RAWINPUTDEVICELIST) * count);
int keyboardCount = 1;
int mouseCount = 1;
count = GetRawInputDeviceList(list, (unsigned int*)&count, sizeof(RAWINPUTDEVICELIST));
RAWINPUTDEVICELIST *list = (RAWINPUTDEVICELIST *)malloc(sizeof(RAWINPUTDEVICELIST) * count);
int keyboardCount = 1;
int mouseCount = 1;
count = GetRawInputDeviceList(list, (unsigned int *)&count, sizeof(RAWINPUTDEVICELIST));
// Not necessary, but reminder that count is -1 on failure.
if (count > 0) {
for (int i=0; i<count; i++) {
if (list[i].dwType != RIM_TYPEKEYBOARD && list[i].dwType != RIM_TYPEMOUSE) continue;
// Not necessary, but reminder that count is -1 on failure.
if (count > 0) {
for (int i = 0; i < count; i++) {
if (list[i].dwType != RIM_TYPEKEYBOARD && list[i].dwType != RIM_TYPEMOUSE)
continue;
UINT bufferLen = 10000;
int nameLen = GetRawInputDeviceInfo(list[i].hDevice, RIDI_DEVICENAME, instanceID, &bufferLen);
if (nameLen >= 4) {
// nameLen includes terminating null.
nameLen--;
UINT bufferLen = 10000;
int nameLen = GetRawInputDeviceInfo(list[i].hDevice, RIDI_DEVICENAME, instanceID, &bufferLen);
if (nameLen >= 4) {
// nameLen includes terminating null.
nameLen--;
// Strip out GUID parts of instanceID to make it a generic product id,
// and reformat it to point to registry entry containing device description.
wcscpy(productID, instanceID);
wchar_t *temp = 0;
for (int j=0; j<3; j++) {
wchar_t *s = wcschr(productID, '#');
if (!s) break;
*s = '\\';
if (j==2) {
*s = 0;
}
if (j==1) temp = s;
}
// Strip out GUID parts of instanceID to make it a generic product id,
// and reformat it to point to registry entry containing device description.
wcscpy(productID, instanceID);
wchar_t *temp = 0;
for (int j = 0; j < 3; j++) {
wchar_t *s = wcschr(productID, '#');
if (!s)
break;
*s = '\\';
if (j == 2) {
*s = 0;
}
if (j == 1)
temp = s;
}
wsprintfW(keyName, L"SYSTEM\\CurrentControlSet\\Enum%s", productID+3);
if (temp) *temp = 0;
int haveDescription = 0;
HKEY hKey;
if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyName, 0, KEY_QUERY_VALUE, &hKey)) {
DWORD type;
DWORD len = 10000 * sizeof(wchar_t);
if (ERROR_SUCCESS == RegQueryValueExW(hKey, L"DeviceDesc", 0, &type, (BYTE*)displayName, &len) &&
len && type == REG_SZ) {
wchar_t *temp2 = wcsrchr(displayName, ';');
if (!temp2) temp2 = displayName;
else temp2++;
// Could do without this, but more effort than it's worth.
wcscpy(keyName, temp2);
haveDescription = 1;
}
RegCloseKey(hKey);
}
if (list[i].dwType == RIM_TYPEKEYBOARD) {
if (!haveDescription) wsprintfW(displayName, L"Raw Keyboard %i", keyboardCount++);
else wsprintfW(displayName, L"Raw KB: %s", keyName);
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 wsprintfW(displayName, L"Raw MS: %s", keyName);
dm->AddDevice(new RawInputMouse(list[i].hDevice, displayName, instanceID, productID));
}
}
}
}
free(list);
free(instanceID);
dm->AddDevice(new RawInputKeyboard(0, L"Simulated Keyboard"));
dm->AddDevice(new RawInputMouse(0, L"Simulated Mouse"));
}
wsprintfW(keyName, L"SYSTEM\\CurrentControlSet\\Enum%s", productID + 3);
if (temp)
*temp = 0;
int haveDescription = 0;
HKEY hKey;
if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyName, 0, KEY_QUERY_VALUE, &hKey)) {
DWORD type;
DWORD len = 10000 * sizeof(wchar_t);
if (ERROR_SUCCESS == RegQueryValueExW(hKey, L"DeviceDesc", 0, &type, (BYTE *)displayName, &len) &&
len && type == REG_SZ) {
wchar_t *temp2 = wcsrchr(displayName, ';');
if (!temp2)
temp2 = displayName;
else
temp2++;
// Could do without this, but more effort than it's worth.
wcscpy(keyName, temp2);
haveDescription = 1;
}
RegCloseKey(hKey);
}
if (list[i].dwType == RIM_TYPEKEYBOARD) {
if (!haveDescription)
wsprintfW(displayName, L"Raw Keyboard %i", keyboardCount++);
else
wsprintfW(displayName, L"Raw KB: %s", keyName);
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
wsprintfW(displayName, L"Raw MS: %s", keyName);
dm->AddDevice(new RawInputMouse(list[i].hDevice, displayName, instanceID, productID));
}
}
}
}
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 "VKey.h"
wchar_t *GetVKStringW(unsigned char vk) {
int flag;
static wchar_t t[20];
switch(vk) {
case 0x0C: return L"Clear";
case 0x13: return L"Pause";
wchar_t *GetVKStringW(unsigned char vk)
{
int flag;
static wchar_t t[20];
switch (vk) {
case 0x0C:
return L"Clear";
case 0x13:
return L"Pause";
case 0x21:// return "Page Up";
case 0x22:// return "Page Down";
case 0x23:// return "End";
case 0x24:// return "Home";
case 0x25:// return "Left";
case 0x26:// return "Up";
case 0x27:// return "Right";
case 0x28:// return "Down";
case 0x2D:// return "Insert";
case 0x2E:// return "Delete";
case 0x5B:// return "Left Windows";
case 0x5C:// return "Right Windows";
case 0x5D:// return "Application";
case 0x6F:// return "Num /";
flag = 1<<24;
break;
case 0x21: // return "Page Up";
case 0x22: // return "Page Down";
case 0x23: // return "End";
case 0x24: // return "Home";
case 0x25: // return "Left";
case 0x26: // return "Up";
case 0x27: // return "Right";
case 0x28: // return "Down";
case 0x2D: // return "Insert";
case 0x2E: // return "Delete";
case 0x5B: // return "Left Windows";
case 0x5C: // return "Right Windows";
case 0x5D: // return "Application";
case 0x6F: // return "Num /";
flag = 1 << 24;
break;
case 0x29: return L"Select";
case 0x2A: return L"Print";
case 0x2B: return L"Execute";
case 0x2C: return L"Prnt Scrn";
case 0x2F: return L"Help";
case 0x29:
return L"Select";
case 0x2A:
return L"Print";
case 0x2B:
return L"Execute";
case 0x2C:
return L"Prnt Scrn";
case 0x2F:
return L"Help";
case 0x6C: return L"|";
case 0x90: return L"Num Lock";
case 0x6C:
return L"|";
case 0x90:
return L"Num Lock";
case 0xA0: return L"Left Shift";
case 0xA1: return L"Right Shift";
case 0xA2: return L"Left Ctrl";
case 0xA3: return L"Right Ctrl";
case 0xA4: return L"Left Alt";
case 0xA5: return L"Right Alt";
case 0xA0:
return L"Left Shift";
case 0xA1:
return L"Right Shift";
case 0xA2:
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 0xA7: return L"Forward";
case 0xA8: return L"Refresh";
case 0xA9: return L"Stop";
case 0xAA: return L"Search";
case 0xAB: return L"Favorites";
case 0xAC: return L"Browser";
case 0xA6:
return L"Back";
case 0xA7:
return L"Forward";
case 0xA8:
return L"Refresh";
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 0xFB: return L"Zoom";
default:
flag = 0;
break;
}
int res = MapVirtualKey(vk, MAPVK_VK_TO_VSC);
if (res && GetKeyNameText((res<<16) | flag, t, 20)) {
// don't trust windows
t[19] = 0;
}
else {
wsprintfW(t, L"Key %i", vk);
}
return t;
case 0xFA:
return L"Play";
case 0xFB:
return L"Zoom";
default:
flag = 0;
break;
}
int res = MapVirtualKey(vk, MAPVK_VK_TO_VSC);
if (res && GetKeyNameText((res << 16) | flag, t, 20)) {
// don't trust windows
t[19] = 0;
} else {
wsprintfW(t, L"Key %i", vk);
}
return t;
}

View File

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

View File

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

View File

@ -32,160 +32,162 @@ class WindowsMessagingMouse;
static WindowsMessagingKeyboard *wmk = 0;
static WindowsMessagingMouse *wmm = 0;
class WindowsMessagingKeyboard : public WindowsKeyboard {
class WindowsMessagingKeyboard : public WindowsKeyboard
{
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) {
// Redundant. Should match the next line.
// Deactivate();
if (wmk) wmk->Deactivate();
hWndProc = initInfo->hWndProc;
hWndProc = initInfo->hWndProc;
if (!wmm)
hWndProc->Eat(WindowsMessagingWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
if (!wmm)
hWndProc->Eat(WindowsMessagingWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
wmk = this;
InitState();
wmk = this;
InitState();
active = 1;
return 1;
}
active = 1;
return 1;
}
void Deactivate() {
if (active) {
if (!wmm)
hWndProc->ReleaseExtraProc(WindowsMessagingWndProc);
wmk = 0;
active = 0;
FreeState();
}
}
void Deactivate()
{
if (active) {
if (!wmm)
hWndProc->ReleaseExtraProc(WindowsMessagingWndProc);
wmk = 0;
active = 0;
FreeState();
}
}
void CheckKey(int vkey) {
UpdateKey(vkey, 1&(((unsigned short)GetAsyncKeyState(vkey))>>15));
}
void CheckKey(int vkey)
{
UpdateKey(vkey, 1 & (((unsigned short)GetAsyncKeyState(vkey)) >> 15));
}
};
class WindowsMessagingMouse : public WindowsMouse {
class WindowsMessagingMouse : public WindowsMouse
{
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) {
// Redundant. Should match the next line.
// Deactivate();
if (wmm) wmm->Deactivate();
hWndProc = initInfo->hWndProc;
if (!wmk)
hWndProc->Eat(WindowsMessagingWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
if (!wmk)
hWndProc->Eat(WindowsMessagingWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
GetMouseCapture(hWndProc->hWndEaten);
GetMouseCapture(hWndProc->hWndEaten);
active = 1;
active = 1;
wmm = this;
AllocState();
wmm = this;
AllocState();
return 1;
}
return 1;
}
void Deactivate() {
if (active) {
if (!wmk)
hWndProc->ReleaseExtraProc(WindowsMessagingWndProc);
ReleaseMouseCapture();
wmm = 0;
active = 0;
FreeState();
}
}
void Deactivate()
{
if (active) {
if (!wmk)
hWndProc->ReleaseExtraProc(WindowsMessagingWndProc);
ReleaseMouseCapture();
wmm = 0;
active = 0;
FreeState();
}
}
};
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 (wParam == VK_SHIFT) {
wmk->CheckKey(VK_RSHIFT);
wmk->CheckKey(VK_LSHIFT);
}
else if (wParam == VK_CONTROL) {
wmk->CheckKey(VK_RCONTROL);
wmk->CheckKey(VK_LCONTROL);
}
else if (wParam == VK_MENU) {
wmk->CheckKey(VK_RMENU);
wmk->CheckKey(VK_LMENU);
}
else
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) {
return NO_WND_PROC;
}
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;
GetCursorPos(&p);
// Need check to prevent cursor movement cascade.
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);
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 (wParam == VK_SHIFT) {
wmk->CheckKey(VK_RSHIFT);
wmk->CheckKey(VK_LSHIFT);
} else if (wParam == VK_CONTROL) {
wmk->CheckKey(VK_RCONTROL);
wmk->CheckKey(VK_LCONTROL);
} else if (wParam == VK_MENU) {
wmk->CheckKey(VK_RMENU);
wmk->CheckKey(VK_LMENU);
} else
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) {
return NO_WND_PROC;
} 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;
GetCursorPos(&p);
// Need check to prevent cursor movement cascade.
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);
}
return NO_WND_PROC;
}
else if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP) {
wmm->UpdateButton(0, uMsg == WM_LBUTTONDOWN);
return NO_WND_PROC;
}
else if (uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONUP) {
wmm->UpdateButton(1, uMsg == WM_RBUTTONDOWN);
return NO_WND_PROC;
}
else if (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONUP) {
wmm->UpdateButton(2, uMsg == WM_MBUTTONDOWN);
return NO_WND_PROC;
}
else if (uMsg == WM_XBUTTONDOWN || uMsg == WM_XBUTTONUP) {
wmm->UpdateButton(3+((wParam>>16) == XBUTTON2), uMsg == WM_XBUTTONDOWN);
return NO_WND_PROC;
}
else if (uMsg == WM_MOUSEWHEEL) {
wmm->UpdateAxis(2, ((int)wParam>>16)/WHEEL_DELTA);
return NO_WND_PROC;
}
else if (uMsg == WM_MOUSEHWHEEL) {
wmm->UpdateAxis(3, ((int)wParam>>16)/WHEEL_DELTA);
return NO_WND_PROC;
}
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) {
SetCursorPos(wmm->center.x, wmm->center.y);
}
return NO_WND_PROC;
} else if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP) {
wmm->UpdateButton(0, uMsg == WM_LBUTTONDOWN);
return NO_WND_PROC;
} else if (uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONUP) {
wmm->UpdateButton(1, uMsg == WM_RBUTTONDOWN);
return NO_WND_PROC;
} else if (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONUP) {
wmm->UpdateButton(2, uMsg == WM_MBUTTONDOWN);
return NO_WND_PROC;
} else if (uMsg == WM_XBUTTONDOWN || uMsg == WM_XBUTTONUP) {
wmm->UpdateButton(3 + ((wParam >> 16) == XBUTTON2), uMsg == WM_XBUTTONDOWN);
return NO_WND_PROC;
} else if (uMsg == WM_MOUSEWHEEL) {
wmm->UpdateAxis(2, ((int)wParam >> 16) / WHEEL_DELTA);
return NO_WND_PROC;
} else if (uMsg == WM_MOUSEHWHEEL) {
wmm->UpdateAxis(3, ((int)wParam >> 16) / WHEEL_DELTA);
return NO_WND_PROC;
} 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();
}//*/
}
return CONTINUE_BLISSFULLY;
}
return CONTINUE_BLISSFULLY;
}
void EnumWindowsMessagingDevices() {
dm->AddDevice(new WindowsMessagingKeyboard());
dm->AddDevice(new WindowsMessagingMouse());
void EnumWindowsMessagingDevices()
{
dm->AddDevice(new WindowsMessagingKeyboard());
dm->AddDevice(new WindowsMessagingMouse());
}

View File

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

View File

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

View File

@ -20,128 +20,136 @@
WndProcEater::WndProcEater()
{
hWndEaten = 0;
eatenWndProc = 0;
hWndEaten = 0;
eatenWndProc = 0;
extraProcs = 0;
numExtraProcs = 0;
extraProcs = 0;
numExtraProcs = 0;
hMutex = CreateMutex(0, 0, L"LilyPad");
hMutex = CreateMutex(0, 0, L"LilyPad");
}
WndProcEater::~WndProcEater() throw()
{
if (hMutex) {
ReleaseMutex(hMutex);
CloseHandle(hMutex);
}
if (hMutex) {
ReleaseMutex(hMutex);
CloseHandle(hMutex);
}
}
void WndProcEater::ReleaseExtraProc(ExtraWndProc proc) {
// Probably isn't needed, but just in case...
if (hMutex) WaitForSingleObject(hMutex, 100);
void WndProcEater::ReleaseExtraProc(ExtraWndProc proc)
{
// 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++) {
if (extraProcs[i].proc == proc) {
extraProcs[i] = extraProcs[--numExtraProcs];
break;
}
}
if (!numExtraProcs && eatenWndProc) {
free(extraProcs);
extraProcs = 0;
// As numExtraProcs is 0, won't cause recursion if called from Release().
Release();
}
for (int i = 0; i < numExtraProcs; i++) {
if (extraProcs[i].proc == proc) {
extraProcs[i] = extraProcs[--numExtraProcs];
break;
}
}
if (!numExtraProcs && eatenWndProc) {
free(extraProcs);
extraProcs = 0;
// As numExtraProcs is 0, won't cause recursion if called from Release().
Release();
}
}
void WndProcEater::Release() {
while (numExtraProcs) ReleaseExtraProc(extraProcs[0].proc);
if (hWndEaten && IsWindow(hWndEaten)) {
RemoveProp(hWndEaten, L"LilyHaxxor");
SetWindowLongPtr(hWndEaten, GWLP_WNDPROC, (LONG_PTR)eatenWndProc);
hWndEaten = 0;
eatenWndProc = 0;
}
void WndProcEater::Release()
{
while (numExtraProcs)
ReleaseExtraProc(extraProcs[0].proc);
if (hWndEaten && IsWindow(hWndEaten)) {
RemoveProp(hWndEaten, L"LilyHaxxor");
SetWindowLongPtr(hWndEaten, GWLP_WNDPROC, (LONG_PTR)eatenWndProc);
hWndEaten = 0;
eatenWndProc = 0;
}
}
LRESULT WndProcEater::_OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if( hWnd != hWndEaten )
fprintf( stderr, "Totally mismatched window handles on OverrideWndProc!\n" );
if (hWnd != hWndEaten)
fprintf(stderr, "Totally mismatched window handles on OverrideWndProc!\n");
ExtraWndProcResult res = CONTINUE_BLISSFULLY;
LRESULT out = 0;
// Here because want it for binding, even when no keyboard mode is selected.
if (uMsg == WM_GETDLGCODE) {
return DLGC_WANTALLKEYS | CallWindowProc(eatenWndProc, hWnd, uMsg, wParam, lParam);
}
ExtraWndProcResult res = CONTINUE_BLISSFULLY;
LRESULT out = 0;
// Here because want it for binding, even when no keyboard mode is selected.
if (uMsg == WM_GETDLGCODE) {
return DLGC_WANTALLKEYS | CallWindowProc(eatenWndProc, hWnd, uMsg, wParam, lParam);
}
for (int i=0; i<numExtraProcs; i++) {
// 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
// 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;
for (int i = 0; i < numExtraProcs; i++) {
// 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
// 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;
ExtraWndProcResult res2 = extraProcs[i].proc(hWnd, uMsg, wParam, lParam, &out);
if (res2 != res) {
if (res2 == CONTINUE_BLISSFULLY_AND_RELEASE_PROC) {
ReleaseExtraProc(extraProcs[i].proc);
i--;
}
else if (res2 > res) res = res2;
}
}
ExtraWndProcResult res2 = extraProcs[i].proc(hWnd, uMsg, wParam, lParam, &out);
if (res2 != res) {
if (res2 == CONTINUE_BLISSFULLY_AND_RELEASE_PROC) {
ReleaseExtraProc(extraProcs[i].proc);
i--;
} else if (res2 > res)
res = res2;
}
}
if (res != NO_WND_PROC) {
if (out == WM_DESTROY) {
Release();
}
if (res == CONTINUE_BLISSFULLY)
out = CallWindowProc(eatenWndProc, hWnd, uMsg, wParam, lParam);
else if (res == USE_DEFAULT_WND_PROC)
out = DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return out;
if (res != NO_WND_PROC) {
if (out == WM_DESTROY) {
Release();
}
if (res == CONTINUE_BLISSFULLY)
out = CallWindowProc(eatenWndProc, hWnd, uMsg, wParam, lParam);
else if (res == USE_DEFAULT_WND_PROC)
out = DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return out;
}
static LRESULT CALLBACK OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
WndProcEater* obj = (WndProcEater*)GetProp(hWnd, L"LilyHaxxor");
return (obj == NULL) ?
DefWindowProc(hWnd, uMsg, wParam, lParam) :
obj->_OverrideWndProc( hWnd, uMsg, wParam, lParam );
WndProcEater *obj = (WndProcEater *)GetProp(hWnd, L"LilyHaxxor");
return (obj == NULL) ?
DefWindowProc(hWnd, uMsg, wParam, lParam) :
obj->_OverrideWndProc(hWnd, uMsg, wParam, lParam);
}
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();
SetProp(hWnd, L"LilyHaxxor", (HANDLE)this);
Release();
SetProp(hWnd, L"LilyHaxxor", (HANDLE) this);
eatenWndProc = (WNDPROC) SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)OverrideWndProc);
hWndEaten = (eatenWndProc) ? hWnd : 0;
eatenWndProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)OverrideWndProc);
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
if (!hWndEaten) return;
// check if Subclassing failed to init during SetWndHandle
if (!hWndEaten)
return;
// 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) EatingWndProc! -> 0x%x\n", proc );
//printf( "(Lilypad) EatingWndProc! -> 0x%x\n", proc );
extraProcs = (ExtraWndProcInfo*) realloc(extraProcs, sizeof(ExtraWndProcInfo)*(numExtraProcs+1));
extraProcs[numExtraProcs].proc = proc;
extraProcs[numExtraProcs].flags = flags;
numExtraProcs++;
extraProcs = (ExtraWndProcInfo *)realloc(extraProcs, sizeof(ExtraWndProcInfo) * (numExtraProcs + 1));
extraProcs[numExtraProcs].proc = proc;
extraProcs[numExtraProcs].flags = flags;
numExtraProcs++;
}

View File

@ -15,45 +15,46 @@
* 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.
*/
enum ExtraWndProcResult {
CONTINUE_BLISSFULLY,
// Calls ReleaseExtraProc without messing up order.
CONTINUE_BLISSFULLY_AND_RELEASE_PROC,
USE_DEFAULT_WND_PROC,
NO_WND_PROC
CONTINUE_BLISSFULLY,
// Calls ReleaseExtraProc without messing up order.
CONTINUE_BLISSFULLY_AND_RELEASE_PROC,
USE_DEFAULT_WND_PROC,
NO_WND_PROC
};
typedef ExtraWndProcResult (*ExtraWndProc)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *out);
struct ExtraWndProcInfo {
ExtraWndProc proc;
DWORD flags;
struct ExtraWndProcInfo
{
ExtraWndProc proc;
DWORD flags;
};
class WndProcEater
{
public:
HWND hWndEaten;
WNDPROC eatenWndProc;
ExtraWndProcInfo* extraProcs;
int numExtraProcs;
HWND hWndEaten;
WNDPROC eatenWndProc;
ExtraWndProcInfo *extraProcs;
int numExtraProcs;
HANDLE hMutex;
HANDLE hMutex;
public:
WndProcEater();
virtual ~WndProcEater() throw();
WndProcEater();
virtual ~WndProcEater() throw();
bool SetWndHandle(HWND hWnd);
void Eat(ExtraWndProc proc, DWORD flags);
void ReleaseExtraProc(ExtraWndProc proc);
void Release();
bool SetWndHandle(HWND hWnd);
void Eat(ExtraWndProc proc, DWORD flags);
void ReleaseExtraProc(ExtraWndProc proc);
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;

View File

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

View File

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