DualShockPadMeta GetPadDetailForIdx(int padIdx)
        {
            var meta = new DualShockPadMeta();

            meta.PadId = (byte)padIdx;
            meta.Model = DsModel.DS4;

            var d = DS4Controllers[padIdx];

            if (d == null)
            {
                meta.PadMacAddress  = null;
                meta.PadState       = DsState.Disconnected;
                meta.ConnectionType = DsConnection.None;
                meta.Model          = DsModel.None;
                meta.BatteryStatus  = 0;
                meta.IsActive       = false;

                return(meta);
            }

            bool isValidSerial = false;

            if (d.isValidSerial())
            {
                string stringMac = d.getMacAddress();
                if (stringMac != null)
                {
                    stringMac = stringMac.Replace(":", "").Trim();
                    if (stringMac.Length > 0)
                    {
                        meta.PadMacAddress = System.Net.NetworkInformation.PhysicalAddress.Parse(stringMac);
                        isValidSerial      = true;

                        if (d.isSynced() || d.IsAlive())
                        {
                            meta.PadState = DsState.Connected;
                        }
                        else
                        {
                            meta.PadState = DsState.Reserved;
                        }
                    }
                }
            }

            if (!isValidSerial)
            {
                meta.PadMacAddress = null;
                meta.PadState      = DsState.Disconnected;
            }

            meta.ConnectionType = (d.getConnectionType() == ConnectionType.USB) ? DsConnection.Usb : DsConnection.Bluetooth;
            meta.IsActive       = !d.isDS4Idle();

            if (d.isCharging() && d.getBattery() >= 100)
            {
                meta.BatteryStatus = DsBattery.Charged;
            }
            else
            {
                if (d.getBattery() >= 95)
                {
                    meta.BatteryStatus = DsBattery.Full;
                }
                else if (d.getBattery() >= 70)
                {
                    meta.BatteryStatus = DsBattery.High;
                }
                else if (d.getBattery() >= 50)
                {
                    meta.BatteryStatus = DsBattery.Medium;
                }
                else if (d.getBattery() >= 20)
                {
                    meta.BatteryStatus = DsBattery.Low;
                }
                else if (d.getBattery() >= 5)
                {
                    meta.BatteryStatus = DsBattery.Dying;
                }
                else
                {
                    meta.BatteryStatus = DsBattery.None;
                }
            }

            return(meta);
        }
Exemple #2
0
        private void ProcessIncoming(byte[] localMsg, IPEndPoint clientEP)
        {
            try
            {
                int currIdx = 0;
                if (localMsg[0] != 'D' || localMsg[1] != 'S' || localMsg[2] != 'U' || localMsg[3] != 'C')
                {
                    return;
                }
                else
                {
                    currIdx += 4;
                }

                uint protocolVer = BitConverter.ToUInt16(localMsg, currIdx);
                currIdx += 2;

                if (protocolVer > MaxProtocolVersion)
                {
                    return;
                }

                uint packetSize = BitConverter.ToUInt16(localMsg, currIdx);
                currIdx += 2;

                if (packetSize < 0)
                {
                    return;
                }

                packetSize += 16; //size of header
                if (packetSize > localMsg.Length)
                {
                    return;
                }
                else if (packetSize < localMsg.Length)
                {
                    byte[] newMsg = new byte[packetSize];
                    Array.Copy(localMsg, newMsg, packetSize);
                    localMsg = newMsg;
                }

                uint crcValue = BitConverter.ToUInt32(localMsg, currIdx);
                //zero out the crc32 in the packet once we got it since that's whats needed for calculation
                localMsg[currIdx++] = 0;
                localMsg[currIdx++] = 0;
                localMsg[currIdx++] = 0;
                localMsg[currIdx++] = 0;

                uint crcCalc = Crc32Algorithm.Compute(localMsg);
                if (crcValue != crcCalc)
                {
                    return;
                }

                uint clientId = BitConverter.ToUInt32(localMsg, currIdx);
                currIdx += 4;

                uint messageType = BitConverter.ToUInt32(localMsg, currIdx);
                currIdx += 4;

                if (messageType == (uint)MessageType.DSUC_VersionReq)
                {
                    byte[] outputData = new byte[8];
                    int    outIdx     = 0;
                    Array.Copy(BitConverter.GetBytes((uint)MessageType.DSUS_VersionRsp), 0, outputData, outIdx, 4);
                    outIdx += 4;
                    Array.Copy(BitConverter.GetBytes((ushort)MaxProtocolVersion), 0, outputData, outIdx, 2);
                    outIdx += 2;
                    outputData[outIdx++] = 0;
                    outputData[outIdx++] = 0;

                    SendPacket(clientEP, outputData, 1001);
                }
                else if (messageType == (uint)MessageType.DSUC_ListPorts)
                {
                    int numPadRequests = BitConverter.ToInt32(localMsg, currIdx);
                    currIdx += 4;
                    if (numPadRequests < 0 || numPadRequests > NUMBER_SLOTS)
                    {
                        return;
                    }

                    int requestsIdx = currIdx;
                    for (int i = 0; i < numPadRequests; i++)
                    {
                        byte currRequest = localMsg[requestsIdx + i];
                        if (currRequest >= NUMBER_SLOTS)
                        {
                            return;
                        }
                    }

                    byte[] outputData = new byte[16];
                    for (byte i = 0; i < numPadRequests; i++)
                    {
                        byte             currRequest = localMsg[requestsIdx + i];
                        DualShockPadMeta padData     = new DualShockPadMeta();
                        portInfoGet(currRequest, ref padData);

                        int outIdx = 0;
                        Array.Copy(BitConverter.GetBytes((uint)MessageType.DSUS_PortInfo), 0, outputData, outIdx, 4);
                        outIdx += 4;

                        outputData[outIdx++] = (byte)padData.PadId;
                        outputData[outIdx++] = (byte)padData.PadState;
                        outputData[outIdx++] = (byte)padData.Model;
                        outputData[outIdx++] = (byte)padData.ConnectionType;

                        byte[] addressBytes = null;
                        if (padData.PadMacAddress != null)
                        {
                            addressBytes = padData.PadMacAddress.GetAddressBytes();
                        }

                        if (addressBytes != null && addressBytes.Length == 6)
                        {
                            outputData[outIdx++] = addressBytes[0];
                            outputData[outIdx++] = addressBytes[1];
                            outputData[outIdx++] = addressBytes[2];
                            outputData[outIdx++] = addressBytes[3];
                            outputData[outIdx++] = addressBytes[4];
                            outputData[outIdx++] = addressBytes[5];
                        }
                        else
                        {
                            outputData[outIdx++] = 0;
                            outputData[outIdx++] = 0;
                            outputData[outIdx++] = 0;
                            outputData[outIdx++] = 0;
                            outputData[outIdx++] = 0;
                            outputData[outIdx++] = 0;
                        }

                        outputData[outIdx++] = (byte)padData.BatteryStatus;
                        outputData[outIdx++] = 0;

                        SendPacket(clientEP, outputData, 1001);
                    }
                }
                else if (messageType == (uint)MessageType.DSUC_PadDataReq)
                {
                    byte            regFlags = localMsg[currIdx++];
                    byte            idToReg  = localMsg[currIdx++];
                    PhysicalAddress macToReg = null;
                    {
                        byte[] macBytes = new byte[6];
                        Array.Copy(localMsg, currIdx, macBytes, 0, macBytes.Length);
                        currIdx += macBytes.Length;
                        macToReg = new PhysicalAddress(macBytes);
                    }

                    lock (clients)
                    {
                        if (clients.ContainsKey(clientEP))
                        {
                            clients[clientEP].RequestPadInfo(regFlags, idToReg, macToReg);
                        }
                        else
                        {
                            var clientTimes = new ClientRequestTimes();
                            clientTimes.RequestPadInfo(regFlags, idToReg, macToReg);
                            clients[clientEP] = clientTimes;
                        }
                    }
                }
            }
            catch (Exception /*e*/) { }
        }
Exemple #3
0
        public void NewReportIncoming(ref DualShockPadMeta padMeta, DS4State hidReport, byte[] outputData)
        {
            if (!running)
            {
                return;
            }

            var clientsList = new List <IPEndPoint>();
            var now         = DateTime.UtcNow;

            lock (clients)
            {
                var clientsToDelete = new List <IPEndPoint>();

                foreach (var cl in clients)
                {
                    const double TimeoutLimit = 5;

                    if ((now - cl.Value.AllPadsTime).TotalSeconds < TimeoutLimit)
                    {
                        clientsList.Add(cl.Key);
                    }
                    else if ((padMeta.PadId < cl.Value.PadIdsTime.Length) &&
                             (now - cl.Value.PadIdsTime[(byte)padMeta.PadId]).TotalSeconds < TimeoutLimit)
                    {
                        clientsList.Add(cl.Key);
                    }
                    else if (cl.Value.PadMacsTime.ContainsKey(padMeta.PadMacAddress) &&
                             (now - cl.Value.PadMacsTime[padMeta.PadMacAddress]).TotalSeconds < TimeoutLimit)
                    {
                        clientsList.Add(cl.Key);
                    }
                    else //check if this client is totally dead, and remove it if so
                    {
                        bool clientOk = false;
                        for (int i = 0; i < cl.Value.PadIdsTime.Length; i++)
                        {
                            var dur = (now - cl.Value.PadIdsTime[i]).TotalSeconds;
                            if (dur < TimeoutLimit)
                            {
                                clientOk = true;
                                break;
                            }
                        }
                        if (!clientOk)
                        {
                            foreach (var dict in cl.Value.PadMacsTime)
                            {
                                var dur = (now - dict.Value).TotalSeconds;
                                if (dur < TimeoutLimit)
                                {
                                    clientOk = true;
                                    break;
                                }
                            }

                            if (!clientOk)
                            {
                                clientsToDelete.Add(cl.Key);
                            }
                        }
                    }
                }

                foreach (var delCl in clientsToDelete)
                {
                    clients.Remove(delCl);
                }
                clientsToDelete.Clear();
                clientsToDelete = null;
            }

            if (clientsList.Count <= 0)
            {
                return;
            }

            unchecked
            {
                //byte[] outputData = new byte[100];
                int outIdx = BeginPacket(outputData, 1001);
                Array.Copy(BitConverter.GetBytes((uint)MessageType.DSUS_PadDataRsp), 0, outputData, outIdx, 4);
                outIdx += 4;

                outputData[outIdx++] = (byte)padMeta.PadId;
                outputData[outIdx++] = (byte)padMeta.PadState;
                outputData[outIdx++] = (byte)padMeta.Model;
                outputData[outIdx++] = (byte)padMeta.ConnectionType;
                {
                    byte[] padMac = padMeta.PadMacAddress.GetAddressBytes();
                    outputData[outIdx++] = padMac[0];
                    outputData[outIdx++] = padMac[1];
                    outputData[outIdx++] = padMac[2];
                    outputData[outIdx++] = padMac[3];
                    outputData[outIdx++] = padMac[4];
                    outputData[outIdx++] = padMac[5];
                }
                outputData[outIdx++] = (byte)padMeta.BatteryStatus;
                outputData[outIdx++] = padMeta.IsActive ? (byte)1 : (byte)0;

                Array.Copy(BitConverter.GetBytes((uint)hidReport.PacketCounter), 0, outputData, outIdx, 4);
                outIdx += 4;

                if (!ReportToBuffer(hidReport, outputData, ref outIdx))
                {
                    return;
                }
                else
                {
                    FinishPacket(outputData);
                }

                foreach (var cl in clientsList)
                {
                    //try { udpSock.SendTo(outputData, cl); }
                    int temp = 0;
                    poolLock.EnterWriteLock();
                    temp    = listInd;
                    listInd = ++listInd % ARG_BUFFER_LEN;
                    SocketAsyncEventArgs args = argsList[temp];
                    poolLock.ExitWriteLock();

                    _pool.Wait();
                    args.RemoteEndPoint = cl;
                    Array.Copy(outputData, args.Buffer, outputData.Length);
                    bool sentAsync = false;
                    try {
                        sentAsync = udpSock.SendToAsync(args);
                    }
                    catch (SocketException /*ex*/) { }
                    finally
                    {
                        if (!sentAsync)
                        {
                            CompletedSynchronousSocketEvent();
                        }
                    }
                }
            }

            clientsList.Clear();
            clientsList = null;
        }
        public void NewReportIncoming(DualShockPadMeta padMeta, DS4State hidReport)
        {
            if (!running)
            {
                return;
            }

            var clientsList = new List <IPEndPoint>();
            var now         = DateTime.UtcNow;

            lock (clients)
            {
                var clientsToDelete = new List <IPEndPoint>();

                foreach (var cl in clients)
                {
                    const double TimeoutLimit = 5;

                    if ((now - cl.Value.AllPadsTime).TotalSeconds < TimeoutLimit)
                    {
                        clientsList.Add(cl.Key);
                    }
                    else if ((padMeta.PadId < cl.Value.PadIdsTime.Length) &&
                             (now - cl.Value.PadIdsTime[(byte)padMeta.PadId]).TotalSeconds < TimeoutLimit)
                    {
                        clientsList.Add(cl.Key);
                    }
                    else if (cl.Value.PadMacsTime.ContainsKey(padMeta.PadMacAddress) &&
                             (now - cl.Value.PadMacsTime[padMeta.PadMacAddress]).TotalSeconds < TimeoutLimit)
                    {
                        clientsList.Add(cl.Key);
                    }
                    else                     //check if this client is totally dead, and remove it if so
                    {
                        bool clientOk = false;
                        for (int i = 0; i < cl.Value.PadIdsTime.Length; i++)
                        {
                            var dur = (now - cl.Value.PadIdsTime[i]).TotalSeconds;
                            if (dur < TimeoutLimit)
                            {
                                clientOk = true;
                                break;
                            }
                        }
                        if (!clientOk)
                        {
                            foreach (var dict in cl.Value.PadMacsTime)
                            {
                                var dur = (now - dict.Value).TotalSeconds;
                                if (dur < TimeoutLimit)
                                {
                                    clientOk = true;
                                    break;
                                }
                            }

                            if (!clientOk)
                            {
                                clientsToDelete.Add(cl.Key);
                            }
                        }
                    }
                }

                foreach (var delCl in clientsToDelete)
                {
                    clients.Remove(delCl);
                }
                clientsToDelete.Clear();
                clientsToDelete = null;
            }

            if (clientsList.Count <= 0)
            {
                return;
            }

            byte[] outputData = new byte[100];
            int    outIdx     = BeginPacket(outputData, 1001);

            Array.Copy(BitConverter.GetBytes((uint)MessageType.DSUS_PadDataRsp), 0, outputData, outIdx, 4);
            outIdx += 4;

            outputData[outIdx++] = (byte)padMeta.PadId;
            outputData[outIdx++] = (byte)padMeta.PadState;
            outputData[outIdx++] = (byte)padMeta.Model;
            outputData[outIdx++] = (byte)padMeta.ConnectionType;
            {
                byte[] padMac = padMeta.PadMacAddress.GetAddressBytes();
                outputData[outIdx++] = padMac[0];
                outputData[outIdx++] = padMac[1];
                outputData[outIdx++] = padMac[2];
                outputData[outIdx++] = padMac[3];
                outputData[outIdx++] = padMac[4];
                outputData[outIdx++] = padMac[5];
            }
            outputData[outIdx++] = (byte)padMeta.BatteryStatus;
            outputData[outIdx++] = padMeta.IsActive ? (byte)1 : (byte)0;

            Array.Copy(BitConverter.GetBytes((uint)hidReport.PacketCounter), 0, outputData, outIdx, 4);
            outIdx += 4;

            if (!ReportToBuffer(hidReport, outputData, ref outIdx))
            {
                return;
            }
            else
            {
                FinishPacket(outputData);
            }

            foreach (var cl in clientsList)
            {
                try { udpSock.SendTo(outputData, cl); }
                catch (SocketException ex) { }
            }
            clientsList.Clear();
            clientsList = null;
        }