diff --git a/plugins/LilyPad/Config.cpp b/plugins/LilyPad/Config.cpp index 002d6d6d4e..de70012a45 100644 --- a/plugins/LilyPad/Config.cpp +++ b/plugins/LilyPad/Config.cpp @@ -1503,10 +1503,9 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l } dm->Update(&info); dm->PostRead(); - Sleep(100); - dm->Update(&info); - dm->PostRead(); dev->SetEffect(ffb, 255); + Sleep(200); + dm->Update(&info); SetTimer(hWnd, 1, 3000, 0); } } @@ -1848,12 +1847,15 @@ INT_PTR CALLBACK GeneralDialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, L if (IsDlgButtonChecked(hWnd, IDC_G_DS3) && !config.gameApis.dualShock3) { if (IDOK != MessageBoxA(hWnd, - "This open will attempt to connect directly to any connected\n" + "This option will attempt to connect directly to any connected\n" "DualShock 3 devices. It is completely experimental, and based\n" "on no published specs.\n" + "\n" "Furthermore, It uses libusb to Initialize DS3 pads. Libusb can\n" "do odd things to USB and non-USB devices when it enumerates them.\n" + "\n" "I have no idea if it works with bluetooth or not.\n" + "\n" "Are you sure you wish to continue?", "Warning", MB_OKCANCEL | MB_ICONWARNING)) { CheckDlgButton(hWnd, IDC_G_DS3, BST_UNCHECKED); } diff --git a/plugins/LilyPad/DualShock3.cpp b/plugins/LilyPad/DualShock3.cpp index 53a312744f..7b307d7973 100644 --- a/plugins/LilyPad/DualShock3.cpp +++ b/plugins/LilyPad/DualShock3.cpp @@ -7,8 +7,16 @@ #define VID 0x054c #define PID 0x0268 -#define CHECK_DELAY 5 -time_t lastDS3Check = 0; +// Unresponsive period required before calling DS3Check(). +#define DEVICE_CHECK_DELAY 2 +// Unresponsive period required before calling DS3Enum(). Note that enum is always called on first check. +#define DEVICE_ENUM_DELAY 10 + +// Delay between when DS3Check() and DS3Enum() actually do stuff. +#define DOUBLE_CHECK_DELAY 1 +#define DOUBLE_ENUM_DELAY 20 +unsigned int lastDS3Check = 0; +unsigned int lastDS3Enum = 0; typedef void (__cdecl *_usb_init)(void); typedef int (__cdecl *_usb_close)(usb_dev_handle *dev); @@ -34,7 +42,6 @@ HMODULE hModLibusb = 0; int DualShock3Possible(); void EnumDualShock3s(); - void UninitLibUsb() { if (hModLibusb) { FreeLibrary(hModLibusb); @@ -61,15 +68,31 @@ void TryInitDS3(usb_device *dev) { } } -void DS3Check() { +void DS3Enum() { + unsigned int t = (unsigned int) time(0); + if (t - lastDS3Enum < DOUBLE_ENUM_DELAY) { + return; + } + lastDS3Enum = t; pusb_find_busses(); pusb_find_devices(); +} + +void DS3Check() { + unsigned int t = (unsigned int) time(0); + if (t - lastDS3Check < DOUBLE_CHECK_DELAY) { + return; + } + if (!lastDS3Check) { + DS3Enum(); + } + lastDS3Check = t; + usb_bus *bus = pusb_get_busses(); while (bus) { TryInitDS3(bus->devices); bus = bus->next; } - lastDS3Check = time(0); } int InitLibUsb() { @@ -156,32 +179,33 @@ public: OVERLAPPED writeop; int writeCount; + unsigned int dataLastReceived; + int writeQueued; int StartRead() { - readop.Offset = readop.OffsetHigh = 0; int res = ReadFile(hFile, &getState, sizeof(getState), 0, &readop); return (res || GetLastError() == ERROR_IO_PENDING); } int StartWrite() { - writeop.Offset = writeop.OffsetHigh = 0; - for (int i=0; i<2; i++) { - if ((i^writeCount)&1) { - sendState.motors[i].duration = 0x4F; - int force = vibration[i^1] * 256/FULLY_DOWN; - if (force > 255) force = 255; - sendState.motors[i].force = (unsigned char) force; - } - else { - sendState.motors[i].force = 0; - sendState.motors[i].duration = 0; - } + 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; } + writeCount++; int res = WriteFile(hFile, &sendState, sizeof(sendState), 0, &writeop); return (res || GetLastError() == ERROR_IO_PENDING); } - DualShock3Device(int index, wchar_t *name, wchar_t *path) : Device(DS3, OTHER, name, path) { + DualShock3Device(int index, wchar_t *name, wchar_t *path) : Device(DS3, OTHER, name, path, L"DualShock 3") { writeCount = 0; memset(&readop, 0, sizeof(readop)); memset(&writeop, 0, sizeof(writeop)); @@ -240,22 +264,17 @@ public: } int Activate(void *d) { - if (!lastDS3Check) { - DS3Check(); - } - else { - lastDS3Check = time(0) - CHECK_DELAY+3; - } if (active) Deactivate(); + // Give grace period before get mad. + dataLastReceived = (unsigned int) time(0); 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() || !StartWrite()) { + !StartRead()) { Deactivate(); return 0; } - writeQueued = 1; active = 1; AllocState(); return 1; @@ -270,6 +289,7 @@ public: while (1) { DWORD res = WaitForMultipleObjects(2, h, 0, 0); if (res == WAIT_OBJECT_0) { + dataLastReceived = (unsigned int) time(0); // Do stuff. if (!StartRead()) { Deactivate(); @@ -305,12 +325,19 @@ public: Deactivate(); return 0; } - } + }//*/ } else { - time_t test = time(0); - if (test - lastDS3Check >= CHECK_DELAY) { + unsigned int delta = (unsigned int) time(0) - dataLastReceived; + if (delta >= DEVICE_CHECK_DELAY) { + if (delta >= DEVICE_ENUM_DELAY) { + DS3Enum(); + } DS3Check(); + if (!writeQueued) { + StartWrite(); + writeQueued = 1; + } } } break; diff --git a/plugins/LilyPad/LilyPad.cpp b/plugins/LilyPad/LilyPad.cpp index 417156102d..646d7ce558 100644 --- a/plugins/LilyPad/LilyPad.cpp +++ b/plugins/LilyPad/LilyPad.cpp @@ -153,9 +153,15 @@ public: // Flags for which controls (buttons or axes) are locked, if any. DWORD lockedState; - // Last vibration value. Only used so as not to call vibration + // Last vibration value sent to controller. + // Only used so as not to call vibration // functions when old and new values are both 0. - u8 vibrateVal[2]; + u8 currentVibrate[2]; + + // Next vibrate val to send to controller. If next and current are + // both 0, nothing is sent to the controller. Otherwise, it's sent + // on every update. + u8 nextVibrate[2]; // Used to keep track of which pads I'm running. // Note that initialized pads *can* be disabled. @@ -457,6 +463,18 @@ void Update(unsigned int port, unsigned int slot) { dm->PostRead(); { + for (int port=0; port<2; port++) { + for (int slot=0; slot<4; slot++) { + for (int motor=0; motor<2; motor++) { + // TODO: Probably be better to send all of these at once. + if (pads[port][slot].nextVibrate[motor] | pads[port][slot].currentVibrate[motor]) { + pads[port][slot].currentVibrate[motor] = pads[port][slot].nextVibrate[motor]; + dm->SetEffect(port,slot, motor, pads[port][slot].nextVibrate[motor]); + } + } + } + } + for (int port=0; port<2; port++) { for (int slot=0; slot<4; slot++) { pads[port][slot].stateUpdated = 1; @@ -561,10 +579,7 @@ void CALLBACK PADupdate(int port) { } inline void SetVibrate(int port, int slot, int motor, u8 val) { - if (val || pads[port][slot].vibrateVal[motor]) { - dm->SetEffect(port,slot, motor, val); - pads[port][slot].vibrateVal[motor] = val; - } + pads[port][slot].nextVibrate[motor] = val; } u32 CALLBACK PS2EgetLibType(void) {