// Called every time a new input report has arrived protected virtual void On_Report(object sender, EventArgs e) { DS4Device device = (DS4Device)sender; int ind = -1; for (int i = 0, arlength = DS4_CONTROLLER_COUNT; ind == -1 && i < arlength; i++) { DS4Device tempDev = DS4Controllers[i]; if (tempDev != null && device == tempDev) { ind = i; } } if (ind != -1) { if (getFlushHIDQueue(ind)) { device.FlushHID(); } string devError = tempStrings[ind] = device.error; if (!string.IsNullOrEmpty(devError)) { device.getUiContext()?.Post(new SendOrPostCallback(delegate(object state) { LogDebug(devError); }), null); } if (inWarnMonitor[ind]) { int flashWhenLateAt = getFlashWhenLateAt(); if (!lag[ind] && device.Latency >= flashWhenLateAt) { lag[ind] = true; device.getUiContext()?.Post(new SendOrPostCallback(delegate(object state) { LagFlashWarning(ind, true); }), null); } else if (lag[ind] && device.Latency < flashWhenLateAt) { lag[ind] = false; device.getUiContext()?.Post(new SendOrPostCallback(delegate(object state) { LagFlashWarning(ind, false); }), null); } } else { if (DateTime.UtcNow - device.firstActive > TimeSpan.FromSeconds(5)) { inWarnMonitor[ind] = true; } } device.getCurrentState(CurrentState[ind]); DS4State cState = CurrentState[ind]; DS4State pState = device.getPreviousStateRef(); //device.getPreviousState(PreviousState[ind]); //DS4State pState = PreviousState[ind]; if (!device.firstReport && device.IsAlive()) { device.firstReport = true; device.getUiContext()?.Post(new SendOrPostCallback(delegate(object state) { OnDeviceStatusChanged(this, ind); }), null); } else if (pState.Battery != cState.Battery || device.oldCharging != device.isCharging()) { byte tempBattery = currentBattery[ind] = cState.Battery; bool tempCharging = charging[ind] = device.isCharging(); device.getUiContext()?.Post(new SendOrPostCallback(delegate(object state) { OnBatteryStatusChange(this, ind, tempBattery, tempCharging); }), null); } if (getEnableTouchToggle(ind)) { CheckForTouchToggle(ind, cState, pState); } cState = Mapping.SetCurveAndDeadzone(ind, cState); if (!recordingMacro && (!string.IsNullOrEmpty(tempprofilename[ind]) || containsCustomAction(ind) || containsCustomExtras(ind) || getProfileActionCount(ind) > 0)) { Mapping.MapCustom(ind, cState, MappedState[ind], ExposedState[ind], touchPad[ind], this); cState = MappedState[ind]; } if (!useDInputOnly[ind]) { x360Bus.Parse(cState, processingData[ind].Report, ind); // We push the translated Xinput state, and simultaneously we // pull back any possible rumble data coming from Xinput consumers. if (x360Bus.Report(processingData[ind].Report, processingData[ind].Rumble)) { byte Big = processingData[ind].Rumble[3]; byte Small = processingData[ind].Rumble[4]; if (processingData[ind].Rumble[1] == 0x08) { setRumble(Big, Small, ind); } } } if (_udpServer != null) { _udpServer.NewReportIncoming(GetPadDetailForIdx(ind), CurrentState[ind]); } // Output any synthetic events. Mapping.Commit(ind); // Update the GUI/whatever. DS4LightBar.updateLightBar(device, ind, cState, ExposedState[ind], touchPad[ind]); } }