//Remove udp client from the list void UdpClientRemoveFromList(UdpEndPointDetails udpClient) { try { vUdpClients.Remove(udpClient); UdpClientDisconnect(udpClient); } catch (Exception ex) { Debug.WriteLine("Failed removing udp client from list (L): " + ex.Message); } }
//Check incoming gyro dsu client async Task <bool> GyroDsuClientHandler(UdpEndPointDetails endPoint, byte[] incomingBytes) { try { //Check gyro dsuc header if (incomingBytes[0] != 'D' && incomingBytes[1] != 'S' && incomingBytes[2] != 'U' && incomingBytes[3] != 'C') { return(false); } //Debug.WriteLine("Gyro dsu client connected: " + endPoint.IPEndPoint.Address + ":" + endPoint.IPEndPoint.Port); //Get gyro message type DsuMessageType messageType = (DsuMessageType)BitConverter.ToUInt32(incomingBytes, 16); //Check gyro message type if (messageType == DsuMessageType.DSUC_PadDataReq) { //Get gyro controller id byte controllerId = incomingBytes[21]; //Update gyro dsu client endpoints if (controllerId == 0) { vController0.GyroDsuClientEndPoint = endPoint; } if (controllerId == 1) { vController1.GyroDsuClientEndPoint = endPoint; } if (controllerId == 2) { vController2.GyroDsuClientEndPoint = endPoint; } if (controllerId == 3) { vController3.GyroDsuClientEndPoint = endPoint; } } else if (messageType == DsuMessageType.DSUC_ListPorts) { //Send controller information to dsu client await SendGyroInformation(endPoint, 0, vController0.Connected()); await SendGyroInformation(endPoint, 1, vController1.Connected()); await SendGyroInformation(endPoint, 2, vController2.Connected()); await SendGyroInformation(endPoint, 3, vController3.Connected()); } return(true); } catch { } return(false); }
async Task ReceivedUdpSocketHandlerThread(UdpEndPointDetails endPoint, byte[] receivedBytes) { try { //Get the source server ip and port //Debug.WriteLine("Received udp socket from: " + endPoint.IPEndPoint.Address.ToString() + ":" + endPoint.IPEndPoint.Port); //Check incoming gyro dsu bytes if (await GyroDsuClientHandler(endPoint, receivedBytes)) { return; } } catch { } }
//Handle received socket data public static async Task ReceivedSocketHandler(TcpClient tcpClient, UdpEndPointDetails endPoint, byte[] receivedBytes) { try { async void TaskAction() { try { await ReceivedSocketHandlerThread(tcpClient, receivedBytes); } catch { } } await AVActions.TaskStart(TaskAction); } catch { } }
//Udp client disconnect public void UdpClientDisconnect(UdpEndPointDetails udpClient) { try { Debug.WriteLine("Disconnecting and disposing udp client (C)"); udpClient.Active = false; udpClient.IPEndPoint = null; udpClient.LastConnection = 0; udpClient = null; } catch (Exception ex) { Debug.WriteLine("Failed disconnecting udp client (C): " + ex.Message); udpClient = null; } }
//Udp receive loop async Task UdpReceiveLoop() { try { while (!vTask_UdpReceiveLoop.TaskStopRequest) { try { UdpReceiveResult receiveResult = await vUdpServer.ReceiveAsync(); byte[] receivedBytes = receiveResult.Buffer; if (receivedBytes.Length > 0) { //Debug.WriteLine("Received bytes from udp client (S): " + receivedBytes.Length); //Add udp endpoint to client list UdpEndPointDetails updDetailsExisting = vUdpClients.Where(x => x.IPEndPoint.Address.ToString() == receiveResult.RemoteEndPoint.Address.ToString() && x.IPEndPoint.Port == receiveResult.RemoteEndPoint.Port).FirstOrDefault(); if (updDetailsExisting == null) { Debug.WriteLine("Added new udp client endpoint: " + receiveResult.RemoteEndPoint.Address + ":" + receiveResult.RemoteEndPoint.Port); UdpEndPointDetails updDetailsNew = new UdpEndPointDetails(); updDetailsNew.Active = true; updDetailsNew.IPEndPoint = receiveResult.RemoteEndPoint; updDetailsNew.LastConnection = GetSystemTicksMs(); vUdpClients.Add(updDetailsNew); //Signal that bytes have arrived await EventBytesReceived(null, updDetailsNew, receivedBytes); } else { //Debug.WriteLine("Updated existing udp client endpoint: " + receiveResult.RemoteEndPoint.Address + ":" + receiveResult.RemoteEndPoint.Port); updDetailsExisting.LastConnection = GetSystemTicksMs(); //Signal that bytes have arrived await EventBytesReceived(null, updDetailsExisting, receivedBytes); } } } catch { } } } catch { } }
//Reset controller status to defaults public void ResetControllerStatus() { try { Debug.WriteLine("Reset the controller status for controller: " + NumberId); //Controller Status Activated = false; //Battery Status BatteryCurrent = new ControllerBattery(); BatteryPrevious = new ControllerBattery(); //Time Variables PrevInputTicks = 0; LastInputTicks = 0; LastActiveTicks = 0; //Controller Details Details = null; BlockOutput = false; //Controller Tasks InputVirtualOverlapped = new NativeOverlapped() { EventHandle = CreateEvent(IntPtr.Zero, true, false, null) }; OutputVirtualOverlapped = new NativeOverlapped() { EventHandle = CreateEvent(IntPtr.Zero, true, false, null) }; InputControllerTask = new AVTaskDetails(); OutputControllerTask = new AVTaskDetails(); OutputVirtualTask = new AVTaskDetails(); OutputGyroTask = new AVTaskDetails(); //WinUsb Device Variables WinUsbDevice = null; //Hid Device Variables HidDevice = null; //Gyro Dsu Client Variables GyroDsuClientPacketNumber = 0; GyroDsuClientEndPoint = null; //Device In and Output InputButtonCountLoop1 = 0; InputButtonCountTotal1 = 80; InputButtonCountLoop2 = 0; InputButtonCountTotal2 = 80; InputButtonCountLoop3 = 0; InputButtonCountTotal3 = 80; InputHeaderOffsetFinished = false; InputHeaderOffsetByte = 0; InputButtonOffsetFinished = false; InputButtonOffsetByte = 0; InputReport = null; OutputReport = null; XInputData = new XUSB_INPUT_REPORT(); XOutputData = new XUSB_OUTPUT_REPORT(); XOutputCurrentRumbleHeavy = 0; XOutputCurrentRumbleLight = 0; XOutputPreviousRumbleHeavy = 0; XOutputPreviousRumbleLight = 0; //Controller Input InputCurrent = new ControllerInput(); SupportedCurrent = new ControllerSupported(); } catch { } }
async Task SendGyroInformation(UdpEndPointDetails endPoint, int numberId, bool connected) { try { //Check if client endpoint is set if (endPoint == null || !endPoint.Active) { return; } //Debug.WriteLine("Sending controller " + numberId + " information to dsu client."); //Set message header byte[] sendBytes = new byte[32]; sendBytes[0] = (byte)'D'; sendBytes[1] = (byte)'S'; sendBytes[2] = (byte)'U'; sendBytes[3] = (byte)'S'; //Set message protocol byte[] protocolBytes = BitConverter.GetBytes(1001); sendBytes[4] = protocolBytes[0]; sendBytes[5] = protocolBytes[1]; //Set message length byte[] lengthBytes = BitConverter.GetBytes(sendBytes.Length - 16); sendBytes[6] = lengthBytes[0]; sendBytes[7] = lengthBytes[1]; //Set message type byte[] typeBytes = BitConverter.GetBytes((uint)DsuMessageType.DSUS_PortInfo); sendBytes[16] = typeBytes[0]; sendBytes[17] = typeBytes[1]; sendBytes[18] = typeBytes[2]; sendBytes[19] = typeBytes[3]; //Set controller status sendBytes[20] = (byte)numberId; sendBytes[21] = connected ? (byte)DsuState.Connected : (byte)DsuState.Disconnected; sendBytes[22] = (byte)DsuModel.DualShock4; sendBytes[23] = (byte)DsuConnectionType.None; //Set mac address sendBytes[24] = 0; sendBytes[25] = 0; sendBytes[26] = 0; sendBytes[27] = 0; sendBytes[28] = 0; sendBytes[29] = (byte)numberId; //Set battery status sendBytes[30] = (byte)DsuBattery.None; //Compute and set CRC32 hash byte[] checksum = ComputeHashCRC32(sendBytes, false); sendBytes[8] = checksum[0]; sendBytes[9] = checksum[1]; sendBytes[10] = checksum[2]; sendBytes[11] = checksum[3]; //Send bytes to dsu client if (!await vArnoldVinkSockets.UdpClientSendBytes(endPoint.IPEndPoint, sendBytes, vArnoldVinkSockets.vSocketTimeout)) { Debug.WriteLine("Failed to send information bytes to dsu client."); } } catch { } }