Represents a generic Bluetooth client device.
Inheritance: ScpControl.Bluetooth.BthConnection, IDsDevice
Esempio n. 1
0
 private void OnInitialised(BthDevice connection)
 {
     if (OnDeviceArrival(connection))
     {
         connection.HidReportReceived += OnHidReportReceived;
         connection.Start();
     }
 }
Esempio n. 2
0
 private void OnInitialised(BthDevice Connection)
 {
     if (LogArrival(Connection))
     {
         Connection.Report += On_Report;
         Connection.Start();
     }
 }
Esempio n. 3
0
        private BthDevice Add(byte lsb, byte msb, string name)
        {
            BthDevice connection = null;

            if (_connected.Count < 4)
            {
                if (name == "Wireless Controller")
                {
                    connection = new BthDs4(this, _localMac, lsb, msb);
                }
                else
                {
                    connection = new BthDs3(this, _localMac, lsb, msb);
                }

                _connected[connection.HciHandle] = connection;
            }

            return(connection);
        }
Esempio n. 4
0
        private BthDevice Add(byte lsb, byte msb, string name)
        {
            BthDevice connection = null;

            if (_connected.Count < 4)
            {
                // TODO: weak check, maybe improve in future
                if (name.Equals(BthDs4.GenuineProductName, StringComparison.OrdinalIgnoreCase))
                {
                    connection = new BthDs4(this, _localMac, lsb, msb);
                }
                else
                {
                    connection = new BthDs3(this, _localMac, lsb, msb);
                }

                _connected[connection.HciHandle] = connection;
            }

            return(connection);
        }
Esempio n. 5
0
        /// <summary>
        ///     Parses an incoming DualShock 4 HID report .
        /// </summary>
        /// <param name="connection">The device handle the input buffer was received for.</param>
        /// <param name="buffer">The HID report in bytes.</param>
        /// <param name="transfered">The transfered bytes count.</param>
        private void ParseBufferDs4(BthDevice connection, byte[] buffer, int transfered)
        {
            byte[] L2_DCID, L2_SCID;

            if (buffer[6] == 0x01 && buffer[7] == 0x00) // Control Channel
            {
                if (Enum.IsDefined(typeof(L2CAP.Code), buffer[8]))
                {
                    var Event = (L2CAP.Code)buffer[8];

                    switch (Event)
                    {
                        case L2CAP.Code.L2CAP_Command_Reject:

                            Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
                            break;

                        case L2CAP.Code.L2CAP_Connection_Request:

                            Log.DebugFormat(">> {0} [{1:X2}] PSM [{2:X2}]", Event, buffer[8], buffer[12]);

                            L2_SCID = new byte[2] { buffer[14], buffer[15] };
                            L2_DCID = connection.SetConnectionType((L2CAP.PSM)buffer[12], L2_SCID);

                            if (L2CAP.PSM.HID_Interrupt == (L2CAP.PSM)buffer[12])
                            {
                                connection.IsStarted = true;
                            }

                            L2CAP_Connection_Response(connection.HciHandle.Bytes, buffer[9], L2_SCID, L2_DCID, 0x00);
                            Log.DebugFormat("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Connection_Response,
                                (byte)L2CAP.Code.L2CAP_Connection_Response);

                            L2CAP_Configuration_Request(connection.HciHandle.Bytes, _hidReportId++, L2_SCID);
                            Log.DebugFormat("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Configuration_Request,
                                (byte)L2CAP.Code.L2CAP_Configuration_Request);
                            break;

                        case L2CAP.Code.L2CAP_Connection_Response:

                            Log.DebugFormat(">> {0} [{1:X2}] [{2:X2}]", Event, buffer[8], buffer[16]);
                            break;

                        case L2CAP.Code.L2CAP_Configuration_Request:

                            Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);

                            L2_SCID = connection.Get_SCID(buffer[12], buffer[13]);

                            L2CAP_Configuration_Response(connection.HciHandle.Bytes, buffer[9], L2_SCID);
                            Log.DebugFormat("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Configuration_Response,
                                (byte)L2CAP.Code.L2CAP_Configuration_Response);

                            if (connection.IsServiceStarted)
                            {
                                connection.CanStartHid = true;
                            }
                            break;

                        case L2CAP.Code.L2CAP_Configuration_Response:

                            Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);

                            if (connection.IsStarted)
                            {
                                OnInitialised(connection);
                            }
                            break;

                        case L2CAP.Code.L2CAP_Disconnection_Request:

                            Log.DebugFormat(">> {0} [{1:X2}] Handle [{2:X2}{3:X2}]", Event, buffer[8], buffer[15],
                                buffer[14]);

                            L2_SCID = new byte[2] { buffer[14], buffer[15] };

                            L2CAP_Disconnection_Response(connection.HciHandle.Bytes, buffer[9], L2_SCID, L2_SCID);
                            Log.DebugFormat("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Disconnection_Response,
                                (byte)L2CAP.Code.L2CAP_Disconnection_Response);
                            break;

                        case L2CAP.Code.L2CAP_Disconnection_Response:

                            Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
                            break;

                        case L2CAP.Code.L2CAP_Echo_Request:

                            Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
                            break;

                        case L2CAP.Code.L2CAP_Echo_Response:

                            Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
                            break;

                        case L2CAP.Code.L2CAP_Information_Request:

                            Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
                            break;

                        case L2CAP.Code.L2CAP_Information_Response:

                            Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
                            break;
                    }
                }
            }
            else if (buffer[8] == 0xA1 && buffer[9] == 0x11 && transfered == 87)
            {
                // HID report received, parse content and extract gamepad data
                connection.ParseHidReport(buffer);
            }
            else if (connection.InitHidReport(buffer))
            {
                connection.CanStartHid = true;
            }
        }
Esempio n. 6
0
        /// <summary>
        ///     Parses an incoming DualShock 3 HID report .
        /// </summary>
        /// <param name="connection">The device handle the input buffer was received for.</param>
        /// <param name="buffer">The HID report in bytes.</param>
        /// <param name="transfered">The transfered bytes count.</param>
        private void ParseBufferDs3(BthDevice connection, byte[] buffer, int transfered)
        {
            byte[] L2_DCID;
            byte[] L2_SCID;

            if (buffer[6] == 0x01 && buffer[7] == 0x00) // Control Channel
            {
                if (Enum.IsDefined(typeof (L2CAP.Code), buffer[8]))
                {
                    var Event = (L2CAP.Code) buffer[8];

                    switch (Event)
                    {
                        case L2CAP.Code.L2CAP_Command_Reject:

                            Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
                            break;

                        case L2CAP.Code.L2CAP_Connection_Request:

                            Log.DebugFormat(">> {0} [{1:X2}] PSM [{2:X2}]", Event, buffer[8], buffer[12]);

                            L2_SCID = new byte[2] {buffer[14], buffer[15]};
                            L2_DCID = connection.SetConnectionType((L2CAP.PSM) buffer[12], L2_SCID);

                            L2CAP_Connection_Response(connection.HciHandle.Bytes, buffer[9], L2_SCID,
                                L2_DCID, 0x00);
                            Log.DebugFormat("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Connection_Response,
                                (byte) L2CAP.Code.L2CAP_Connection_Response);

                            L2CAP_Configuration_Request(connection.HciHandle.Bytes, _hidReportId++, L2_SCID);
                            Log.DebugFormat("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Configuration_Request,
                                (byte) L2CAP.Code.L2CAP_Configuration_Request);
                            break;

                        case L2CAP.Code.L2CAP_Connection_Response:

                            Log.DebugFormat(">> {0} [{1:X2}] [{2:X2}]", Event, buffer[8], buffer[16]);

                            if (buffer[16] == 0) // Success
                            {
                                L2_SCID = new byte[2] {buffer[12], buffer[13]};
                                L2_DCID = new byte[2] {buffer[14], buffer[15]};

                                var DCID = (ushort) (buffer[15] << 8 | buffer[14]);

                                connection.SetConnectionType(L2CAP.PSM.HID_Service, L2_SCID[0], L2_SCID[1], DCID);

                                L2CAP_Configuration_Request(connection.HciHandle.Bytes, _hidReportId++, L2_SCID);
                                Log.DebugFormat("<< {0} [{1:X2}]",
                                    L2CAP.Code.L2CAP_Configuration_Request,
                                    (byte) L2CAP.Code.L2CAP_Configuration_Request);
                            }
                            break;

                        case L2CAP.Code.L2CAP_Configuration_Request:

                            Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);

                            L2_SCID = connection.Get_SCID(buffer[12], buffer[13]);

                            L2CAP_Configuration_Response(connection.HciHandle.Bytes, buffer[9], L2_SCID);
                            Log.DebugFormat("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Configuration_Response,
                                (byte) L2CAP.Code.L2CAP_Configuration_Response);

                            if (connection.IsServiceStarted)
                            {
                                connection.CanStartHid = true;
                                connection.InitHidReport(buffer);
                            }
                            break;

                        case L2CAP.Code.L2CAP_Configuration_Response:

                            Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);

                            if (connection.CanStartService)
                            {
                                if (connection.ServiceByPass)
                                {
                                    Log.DebugFormat(">> ServiceByPass [{0} - {1}]", connection.Local,
                                        connection.RemoteName);

                                    connection.CanStartService = false;
                                    OnInitialised(connection);
                                }
                                else
                                {
                                    var DCID = BthConnection.Dcid++;
                                    Log.DebugFormat("DCID = {0}", DCID);

                                    L2_DCID = new byte[2] {(byte) ((DCID >> 0) & 0xFF), (byte) ((DCID >> 8) & 0xFF)};

                                    if (!connection.IsFake)
                                    {
                                        L2CAP_Connection_Request(connection.HciHandle.Bytes,
                                            _hidReportId++,
                                            L2_DCID,
                                            L2CAP.PSM.HID_Service);
                                        Log.DebugFormat("<< {0} [{1:X2}] PSM [{2:X2}]",
                                            L2CAP.Code.L2CAP_Connection_Request,
                                            (byte) L2CAP.Code.L2CAP_Connection_Request,
                                            (byte) L2CAP.PSM.HID_Service);
                                    }
                                    else
                                    {
                                        connection.CanStartService = false;
                                        OnInitialised(connection);
                                    }
                                }
                            }
                            break;

                        case L2CAP.Code.L2CAP_Disconnection_Request:

                            Log.DebugFormat(">> {0} [{1:X2}] Handle [{2:X2}{3:X2}]", Event, buffer[8],
                                buffer[15], buffer[14]);

                            L2_SCID = new byte[2] {buffer[14], buffer[15]};

                            L2CAP_Disconnection_Response(connection.HciHandle.Bytes, buffer[9], L2_SCID,
                                L2_SCID);
                            Log.DebugFormat("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Disconnection_Response,
                                (byte) L2CAP.Code.L2CAP_Disconnection_Response);
                            break;

                        case L2CAP.Code.L2CAP_Disconnection_Response:

                            Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);

                            if (connection.CanStartHid)
                            {
                                connection.IsServiceStarted = false;
                                OnInitialised(connection);
                            }
                            break;

                        case L2CAP.Code.L2CAP_Echo_Request:

                            Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
                            break;

                        case L2CAP.Code.L2CAP_Echo_Response:

                            Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
                            break;

                        case L2CAP.Code.L2CAP_Information_Request:

                            Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
                            break;

                        case L2CAP.Code.L2CAP_Information_Response:

                            Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
                            break;
                    }
                }
            }
            else if (buffer[8] == 0xA1 && buffer[9] == 0x01 && transfered == 58)
            {
                // HID report received, parse content and extract gamepad data
                connection.ParseHidReport(buffer);
            }
            else if (connection.InitHidReport(buffer))
            {
                connection.CanStartHid = true;

                L2_DCID = connection.Get_DCID(L2CAP.PSM.HID_Service);
                L2_SCID = connection.Get_SCID(L2CAP.PSM.HID_Service);

                L2CAP_Disconnection_Request(connection.HciHandle.Bytes, _hidReportId++, L2_SCID, L2_DCID);
                Log.DebugFormat("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Disconnection_Request,
                    (byte) L2CAP.Code.L2CAP_Disconnection_Request);
            }
        }
Esempio n. 7
0
        private void L2CAP_DS4(BthDevice connection, byte[] buffer, int transfered)
        {
            byte[] L2_DCID, L2_SCID;

            var Event = L2CAP.Code.L2CAP_Reserved;

            if (buffer[6] == 0x01 && buffer[7] == 0x00) // Control Channel
            {
                if (Enum.IsDefined(typeof(L2CAP.Code), buffer[8]))
                {
                    Event = (L2CAP.Code)buffer[8];

                    switch (Event)
                    {
                    case L2CAP.Code.L2CAP_Command_Reject:

                        Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
                        break;

                    case L2CAP.Code.L2CAP_Connection_Request:

                        Log.DebugFormat(">> {0} [{1:X2}] PSM [{2:X2}]", Event, buffer[8], buffer[12]);

                        L2_SCID = new byte[2] {
                            buffer[14], buffer[15]
                        };
                        L2_DCID = connection.Set((L2CAP.PSM)buffer[12], L2_SCID);

                        if (L2CAP.PSM.HID_Interrupt == (L2CAP.PSM)buffer[12])
                        {
                            connection.IsStarted = true;
                        }

                        L2CAP_Connection_Response(connection.HciHandle.Bytes, buffer[9], L2_SCID, L2_DCID, 0x00);
                        Log.DebugFormat("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Connection_Response,
                                        (byte)L2CAP.Code.L2CAP_Connection_Response);

                        L2CAP_Configuration_Request(connection.HciHandle.Bytes, _hidReportId++, L2_SCID);
                        Log.DebugFormat("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Configuration_Request,
                                        (byte)L2CAP.Code.L2CAP_Configuration_Request);
                        break;

                    case L2CAP.Code.L2CAP_Connection_Response:

                        Log.DebugFormat(">> {0} [{1:X2}] [{2:X2}]", Event, buffer[8], buffer[16]);
                        break;

                    case L2CAP.Code.L2CAP_Configuration_Request:

                        Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);

                        L2_SCID = connection.Get_SCID(buffer[12], buffer[13]);

                        L2CAP_Configuration_Response(connection.HciHandle.Bytes, buffer[9], L2_SCID);
                        Log.DebugFormat("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Configuration_Response,
                                        (byte)L2CAP.Code.L2CAP_Configuration_Response);

                        if (connection.IsServiceStarted)
                        {
                            connection.CanStartHid = true;
                        }
                        break;

                    case L2CAP.Code.L2CAP_Configuration_Response:

                        Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);

                        if (connection.IsStarted)
                        {
                            OnInitialised(connection);
                        }
                        break;

                    case L2CAP.Code.L2CAP_Disconnection_Request:

                        Log.DebugFormat(">> {0} [{1:X2}] Handle [{2:X2}{3:X2}]", Event, buffer[8], buffer[15],
                                        buffer[14]);

                        L2_SCID = new byte[2] {
                            buffer[14], buffer[15]
                        };

                        L2CAP_Disconnection_Response(connection.HciHandle.Bytes, buffer[9], L2_SCID, L2_SCID);
                        Log.DebugFormat("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Disconnection_Response,
                                        (byte)L2CAP.Code.L2CAP_Disconnection_Response);
                        break;

                    case L2CAP.Code.L2CAP_Disconnection_Response:

                        Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
                        break;

                    case L2CAP.Code.L2CAP_Echo_Request:

                        Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
                        break;

                    case L2CAP.Code.L2CAP_Echo_Response:

                        Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
                        break;

                    case L2CAP.Code.L2CAP_Information_Request:

                        Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
                        break;

                    case L2CAP.Code.L2CAP_Information_Response:

                        Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
                        break;

                    default:
                        break;
                    }
                }
            }
            else if (buffer[8] == 0xA1 && buffer[9] == 0x11)
            {
                connection.Parse(buffer);
            }
            else if (connection.InitReport(buffer))
            {
                connection.CanStartHid = true;
            }
        }
        /// <summary>
        ///     Parses an incoming DualShock 3 HID report.
        /// </summary>
        /// <param name="connection">The device handle the input buffer was received for.</param>
        /// <param name="packet">The L2CAP data packet.</param>
        private void ParseBufferDs3(BthDevice connection, L2CapDataPacket packet)
        {
            byte[] L2_DCID;
            byte[] L2_SCID;

            if (packet.IsControlChannel) // Control Channel
            {
                if (packet.IsValidSignallingCommandCode)
                {
                    var Event = packet.SignallingCommandCode;

                    switch (Event)
                    {
                            #region L2CAP_Command_Reject

                        case L2CAP.Code.L2CAP_Command_Reject:

                            Log.DebugFormat(">> {0}", Event);
                            break;

                            #endregion

                            #region L2CAP_Connection_Request

                        case L2CAP.Code.L2CAP_Connection_Request:

                            Log.DebugFormat(">> {0} with PSM [{1}] [CID: {2}]", Event,
                                packet.ProtocolServiceMultiplexer,
                                packet.ChannelId);

                            L2_SCID = packet.SourceChannelIdentifier;

                            // set HID command channel for current connection
                            L2_DCID = connection.SetConnectionType(packet.ProtocolServiceMultiplexer, L2_SCID);

                            // send response with connection pending
                            L2CAP_Connection_Response(connection.HciHandle.Bytes,
                                packet.ChannelId, L2_SCID, L2_DCID,
                                L2CAP.ConnectionResponseResult.ConnectionPending,
                                L2CAP.ConnectionResponseStatus.AuthorisationPending);

                            Log.DebugFormat("<< {0} [CID: {1}]", L2CAP.Code.L2CAP_Connection_Response,
                                packet.ChannelId);

                            // send response with connection successful
                            L2CAP_Connection_Response(connection.HciHandle.Bytes,
                                packet.ChannelId, L2_SCID, L2_DCID,
                                L2CAP.ConnectionResponseResult.ConnectionSuccessful);

                            Log.DebugFormat("<< {0} [CID: {1}]", L2CAP.Code.L2CAP_Connection_Response,
                                packet.ChannelId);

                            // send configuration request
                            L2CAP_Configuration_Request(connection.HciHandle.Bytes, _l2CapDataIdentifier++, L2_SCID);

                            Log.DebugFormat("<< {0} [CID: {1}]", L2CAP.Code.L2CAP_Configuration_Request,
                                _l2CapDataIdentifier - 1);
                            break;

                            #endregion

                            #region L2CAP_Connection_Response

                        case L2CAP.Code.L2CAP_Connection_Response:

                            Log.DebugFormat(">> {0} [Result: {1}] [CID: {2}]", Event, packet.Result, packet.ChannelId);

                            var result = packet.Result;

                            L2_SCID = packet.SourceChannelIdentifier;
                            Log.DebugFormat("-- L2_SCID = [{0:X2}, {1:X2}]", L2_SCID[0], L2_SCID[1]);

                            L2_DCID = packet.DestinationChannelIdentifier;
                            Log.DebugFormat("-- L2_DCID = [{0:X2}, {1:X2}]", L2_DCID[0], L2_DCID[1]);

                            // interpret result
                            switch ((L2CAP.ConnectionResponseResult) result)
                            {
                                case L2CAP.ConnectionResponseResult.ConnectionSuccessful:

                                    // destination channel identifier
                                    var DCID = packet.DestinationChannelIdentifierUInt16;
                                    Log.DebugFormat("-- DCID (shifted) = {0:X4}", DCID);

                                    // set HID service channel for current connection
                                    connection.SetConnectionType(L2CAP.PSM.HID_Service, L2_SCID[0], L2_SCID[1], DCID);

                                    // send configuration request
                                    L2CAP_Configuration_Request(connection.HciHandle.Bytes, _l2CapDataIdentifier++,
                                        L2_SCID);

                                    Log.DebugFormat("<< {0} [CID: {1}]",
                                        L2CAP.Code.L2CAP_Configuration_Request,
                                        packet.ChannelId);
                                    break;
                                case L2CAP.ConnectionResponseResult.ConnectionPending:

                                    Log.InfoFormat("-- Connection pending for pad {0}",
                                        connection.PadId.ToString().ToLower());
                                    break;
                                case L2CAP.ConnectionResponseResult.ConnectionRefusedPsmNotNupported:

                                    Log.ErrorFormat(
                                        "Requested Protocol Service Multiplexer not supported on device {0}",
                                        connection.Remote);
                                    break;
                                case L2CAP.ConnectionResponseResult.ConnectionRefusedSecurityBlock:

                                    Log.ErrorFormat("Connection refused for security reasons on device {0}",
                                        connection.Remote);
                                    break;
                                case L2CAP.ConnectionResponseResult.ConnectionRefusedNoResourcesAvailable:

                                    Log.ErrorFormat("Connection failed for device {0}: no resources available",
                                        connection.Remote);
                                    break;

                                default:
                                    Log.WarnFormat("Unknown result: {0}", result);
                                    break;
                            }

                            break;

                            #endregion

                            #region L2CAP_Configuration_Request

                        case L2CAP.Code.L2CAP_Configuration_Request:

                            Log.DebugFormat(">> {0} [CID: {1}]", Event, packet.ChannelId);

                            L2_SCID = connection.Get_SCID(packet.SourceChannelIdentifier);

                            L2CAP_Configuration_Response(connection.HciHandle.Bytes,
                                packet.ChannelId, L2_SCID);
                            Log.DebugFormat("<< {0} [CID: {1}]", L2CAP.Code.L2CAP_Configuration_Response,
                                packet.ChannelId);

                            if (connection.IsServiceStarted)
                            {
                                connection.CanStartHid = true;
                                connection.InitHidReport(packet.RawBytes);
                            }
                            break;

                            #endregion

                            #region L2CAP_Configuration_Response

                        case L2CAP.Code.L2CAP_Configuration_Response:

                            Log.DebugFormat(">> {0} [CID: {1}]", Event, packet.ChannelId);

                            Log.DebugFormat("-- MTU = {0}", packet.MaximumTransmissionUnit);

                            if (connection.CanStartService)
                            {
                                L2_DCID = L2CapDataPacket.UInt16ToBytes(BthConnection.Dcid++);

                                if (!connection.IsFake)
                                {
                                    L2CAP_Connection_Request(connection.HciHandle.Bytes, _l2CapDataIdentifier++, L2_DCID,
                                        L2CAP.PSM.HID_Service);
                                    Log.DebugFormat("<< {0} with PSM [{1}] [CID: {2}]",
                                        L2CAP.Code.L2CAP_Connection_Request,
                                        L2CAP.PSM.HID_Service,
                                        _l2CapDataIdentifier - 1);
                                }
                                else
                                {
                                    connection.SetConnectionType(L2CAP.PSM.HID_Service, L2_DCID);
                                    connection.CanStartService = false;
                                    OnInitialised(connection);
                                }
                            }
                            break;

                            #endregion

                            #region L2CAP_Disconnection_Request

                        case L2CAP.Code.L2CAP_Disconnection_Request:

                            Log.DebugFormat(">> {0} Handle [{1}]", Event, packet.SourceChannelIdentifier);

                            L2_SCID = packet.SourceChannelIdentifier;

                            L2CAP_Disconnection_Response(connection.HciHandle.Bytes,
                                packet.ChannelId, L2_SCID, L2_SCID);

                            Log.DebugFormat("<< {0}", L2CAP.Code.L2CAP_Disconnection_Response);
                            break;

                            #endregion

                            #region L2CAP_Disconnection_Response

                        case L2CAP.Code.L2CAP_Disconnection_Response:

                            Log.DebugFormat(">> {0}", Event);

                            if (connection.CanStartHid)
                            {
                                connection.IsServiceStarted = false;
                                OnInitialised(connection);
                            }
                            break;

                            #endregion

                            #region L2CAP_Echo_Request

                        case L2CAP.Code.L2CAP_Echo_Request:

                            Log.DebugFormat(">> {0}", Event);
                            break;

                            #endregion

                            #region L2CAP_Echo_Response

                        case L2CAP.Code.L2CAP_Echo_Response:

                            Log.DebugFormat(">> {0}", Event);
                            break;

                            #endregion

                            #region L2CAP_Information_Request

                        case L2CAP.Code.L2CAP_Information_Request:

                            Log.DebugFormat(">> {0}", Event);
                            break;

                            #endregion

                            #region L2CAP_Information_Response

                        case L2CAP.Code.L2CAP_Information_Response:

                            Log.DebugFormat(">> {0}", Event);
                            break;

                            #endregion
                    }
                }
            }
            else if (packet.IsHidInputReport)
            {
                // HID report received, parse content and extract gamepad data
                connection.ParseHidReport(packet.RawBytes);
            }
            else if (connection.InitHidReport(packet.RawBytes))
            {
                connection.CanStartHid = true;

                L2_DCID = connection.Get_DCID(L2CAP.PSM.HID_Service);
                L2_SCID = connection.Get_SCID(L2CAP.PSM.HID_Service);

                L2CAP_Disconnection_Request(connection.HciHandle.Bytes, _l2CapDataIdentifier++, L2_SCID, L2_DCID);

                Log.DebugFormat("<< {0}", L2CAP.Code.L2CAP_Disconnection_Request);
            }
        }
Esempio n. 9
0
        /// <summary>
        ///     Parses an incoming DualShock 4 HID report.
        /// </summary>
        /// <param name="connection">The device handle the input buffer was received for.</param>
        /// <param name="buffer">The HID report in bytes.</param>
        /// <param name="transfered">The transfered bytes count.</param>
        private void ParseBufferDs4(BthDevice connection, byte[] buffer, int transfered)
        {
            byte[] L2_DCID, L2_SCID;

            if (buffer[6] == 0x01 && buffer[7] == 0x00) // Control Channel
            {
                if (Enum.IsDefined(typeof(L2CAP.Code), buffer[8]))
                {
                    var Event = (L2CAP.Code)buffer[8];

                    switch (Event)
                    {
                        #region L2CAP_Command_Reject

                    case L2CAP.Code.L2CAP_Command_Reject:

                        Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
                        break;

                        #endregion

                        #region L2CAP_Connection_Request

                    case L2CAP.Code.L2CAP_Connection_Request:

                        Log.DebugFormat(">> {0} [{1:X2}] PSM [{2:X2}]", Event, buffer[8], buffer[12]);

                        L2_SCID = new byte[2] {
                            buffer[14], buffer[15]
                        };
                        L2_DCID = connection.SetConnectionType((L2CAP.PSM)buffer[12], L2_SCID);

                        if (L2CAP.PSM.HID_Interrupt == (L2CAP.PSM)buffer[12])
                        {
                            connection.IsStarted = true;
                        }

                        L2CAP_Connection_Response(connection.HciHandle.Bytes, buffer[9], L2_SCID, L2_DCID,
                                                  L2CAP.ConnectionResponseResult.ConnectionSuccessful);
                        Log.DebugFormat("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Connection_Response,
                                        (byte)L2CAP.Code.L2CAP_Connection_Response);

                        L2CAP_Configuration_Request(connection.HciHandle.Bytes, _l2CapDataIdentifier++, L2_SCID);
                        Log.DebugFormat("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Configuration_Request,
                                        (byte)L2CAP.Code.L2CAP_Configuration_Request);
                        break;

                        #endregion

                        #region L2CAP_Connection_Response

                    case L2CAP.Code.L2CAP_Connection_Response:

                        Log.DebugFormat(">> {0} [{1:X2}] [{2:X2}]", Event, buffer[8], buffer[16]);
                        break;

                        #endregion

                        #region L2CAP_Configuration_Request

                    case L2CAP.Code.L2CAP_Configuration_Request:

                        Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);

                        L2_SCID = connection.Get_SCID(buffer[12], buffer[13]);

                        L2CAP_Configuration_Response(connection.HciHandle.Bytes, buffer[9], L2_SCID);
                        Log.DebugFormat("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Configuration_Response,
                                        (byte)L2CAP.Code.L2CAP_Configuration_Response);

                        if (connection.IsServiceStarted)
                        {
                            connection.CanStartHid = true;
                        }
                        break;

                        #endregion

                        #region L2CAP_Configuration_Response

                    case L2CAP.Code.L2CAP_Configuration_Response:

                        Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);

                        if (connection.IsStarted)
                        {
                            OnInitialised(connection);
                        }
                        break;

                        #endregion

                        #region L2CAP_Disconnection_Request

                    case L2CAP.Code.L2CAP_Disconnection_Request:

                        Log.DebugFormat(">> {0} [{1:X2}] Handle [{2:X2}{3:X2}]", Event, buffer[8], buffer[15],
                                        buffer[14]);

                        L2_SCID = new byte[2] {
                            buffer[14], buffer[15]
                        };

                        L2CAP_Disconnection_Response(connection.HciHandle.Bytes, buffer[9], L2_SCID, L2_SCID);
                        Log.DebugFormat("<< {0} [{1:X2}]", L2CAP.Code.L2CAP_Disconnection_Response,
                                        (byte)L2CAP.Code.L2CAP_Disconnection_Response);
                        break;

                        #endregion

                        #region L2CAP_Disconnection_Response

                    case L2CAP.Code.L2CAP_Disconnection_Response:

                        Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
                        break;

                        #endregion

                        #region L2CAP_Echo_Request

                    case L2CAP.Code.L2CAP_Echo_Request:

                        Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
                        break;

                        #endregion

                        #region L2CAP_Echo_Response

                    case L2CAP.Code.L2CAP_Echo_Response:

                        Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
                        break;

                        #endregion

                        #region L2CAP_Information_Request

                    case L2CAP.Code.L2CAP_Information_Request:

                        Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
                        break;

                        #endregion

                        #region L2CAP_Information_Response

                    case L2CAP.Code.L2CAP_Information_Response:

                        Log.DebugFormat(">> {0} [{1:X2}]", Event, buffer[8]);
                        break;

                        #endregion
                    }
                }
            }
            else if (buffer[8] == 0xA1 && buffer[9] == 0x11 && transfered == 87)
            {
                // HID report received, parse content and extract gamepad data
                connection.ParseHidReport(buffer);
            }
            else if (buffer[8] == 0xA3 && buffer[9] == 0x5)             //calibration feature report
            {
                // calibration report received, extract the words and start normal output reports
                connection.ParseHidReport(buffer);
            }
            else if (connection.InitHidReport(buffer))
            {
                connection.CanStartHid = true;
            }
        }
Esempio n. 10
0
        /// <summary>
        ///     Parses an incoming DualShock 3 HID report.
        /// </summary>
        /// <param name="connection">The device handle the input buffer was received for.</param>
        /// <param name="packet">The L2CAP data packet.</param>
        private void ParseBufferDs3(BthDevice connection, L2CapDataPacket packet)
        {
            byte[] L2_DCID;
            byte[] L2_SCID;

            if (packet.IsControlChannel) // Control Channel
            {
                if (packet.IsValidSignallingCommandCode)
                {
                    var Event = packet.SignallingCommandCode;

                    switch (Event)
                    {
                        #region L2CAP_Command_Reject

                    case L2CAP.Code.L2CAP_Command_Reject:

                        Log.DebugFormat(">> {0}", Event);
                        break;

                        #endregion

                        #region L2CAP_Connection_Request

                    case L2CAP.Code.L2CAP_Connection_Request:

                        Log.DebugFormat(">> {0} with PSM [{1}] [CID: {2}]", Event,
                                        packet.ProtocolServiceMultiplexer,
                                        packet.ChannelId);

                        L2_SCID = packet.SourceChannelIdentifier;

                        // set HID command channel for current connection
                        L2_DCID = connection.SetConnectionType(packet.ProtocolServiceMultiplexer, L2_SCID);

                        // send response with connection pending
                        L2CAP_Connection_Response(connection.HciHandle.Bytes,
                                                  packet.ChannelId, L2_SCID, L2_DCID,
                                                  L2CAP.ConnectionResponseResult.ConnectionPending,
                                                  L2CAP.ConnectionResponseStatus.AuthorisationPending);

                        Log.DebugFormat("<< {0} [CID: {1}]", L2CAP.Code.L2CAP_Connection_Response,
                                        packet.ChannelId);

                        // send response with connection successful
                        L2CAP_Connection_Response(connection.HciHandle.Bytes,
                                                  packet.ChannelId, L2_SCID, L2_DCID,
                                                  L2CAP.ConnectionResponseResult.ConnectionSuccessful);

                        Log.DebugFormat("<< {0} [CID: {1}]", L2CAP.Code.L2CAP_Connection_Response,
                                        packet.ChannelId);

                        // send configuration request
                        L2CAP_Configuration_Request(connection.HciHandle.Bytes, _l2CapDataIdentifier++, L2_SCID);

                        Log.DebugFormat("<< {0} [CID: {1}]", L2CAP.Code.L2CAP_Configuration_Request,
                                        _l2CapDataIdentifier - 1);
                        break;

                        #endregion

                        #region L2CAP_Connection_Response

                    case L2CAP.Code.L2CAP_Connection_Response:

                        Log.DebugFormat(">> {0} [Result: {1}] [CID: {2}]", Event, packet.Result, packet.ChannelId);

                        var result = packet.Result;

                        L2_SCID = packet.SourceChannelIdentifier;
                        Log.DebugFormat("-- L2_SCID = [{0:X2}, {1:X2}]", L2_SCID[0], L2_SCID[1]);

                        L2_DCID = packet.DestinationChannelIdentifier;
                        Log.DebugFormat("-- L2_DCID = [{0:X2}, {1:X2}]", L2_DCID[0], L2_DCID[1]);

                        // interpret result
                        switch ((L2CAP.ConnectionResponseResult)result)
                        {
                        case L2CAP.ConnectionResponseResult.ConnectionSuccessful:

                            // destination channel identifier
                            var DCID = packet.DestinationChannelIdentifierUInt16;
                            Log.DebugFormat("-- DCID (shifted) = {0:X4}", DCID);

                            // set HID service channel for current connection
                            connection.SetConnectionType(L2CAP.PSM.HID_Service, L2_SCID[0], L2_SCID[1], DCID);

                            // send configuration request
                            L2CAP_Configuration_Request(connection.HciHandle.Bytes, _l2CapDataIdentifier++,
                                                        L2_SCID);

                            Log.DebugFormat("<< {0} [CID: {1}]",
                                            L2CAP.Code.L2CAP_Configuration_Request,
                                            packet.ChannelId);
                            break;

                        case L2CAP.ConnectionResponseResult.ConnectionPending:

                            Log.DebugFormat("-- Connection pending for pad {0}",
                                            connection.PadId.ToString().ToLower());
                            break;

                        case L2CAP.ConnectionResponseResult.ConnectionRefusedPsmNotNupported:

                            Log.ErrorFormat(
                                "Requested Protocol Service Multiplexer not supported on device {0}",
                                connection.HostAddress);
                            break;

                        case L2CAP.ConnectionResponseResult.ConnectionRefusedSecurityBlock:

                            Log.ErrorFormat("Connection refused for security reasons on device {0}",
                                            connection.HostAddress);
                            break;

                        case L2CAP.ConnectionResponseResult.ConnectionRefusedNoResourcesAvailable:

                            Log.ErrorFormat("Connection failed for device {0}: no resources available",
                                            connection.HostAddress);
                            break;

                        default:
                            Log.WarnFormat("Unknown result: {0}", result);
                            break;
                        }

                        break;

                        #endregion

                        #region L2CAP_Configuration_Request

                    case L2CAP.Code.L2CAP_Configuration_Request:

                        Log.DebugFormat(">> {0} [CID: {1}]", Event, packet.ChannelId);

                        L2_SCID = connection.Get_SCID(packet.SourceChannelIdentifier);

                        L2CAP_Configuration_Response(connection.HciHandle.Bytes,
                                                     packet.ChannelId, L2_SCID);
                        Log.DebugFormat("<< {0} [CID: {1}]", L2CAP.Code.L2CAP_Configuration_Response,
                                        packet.ChannelId);

                        if (connection.IsServiceStarted)
                        {
                            connection.CanStartHid = true;
                            connection.InitHidReport(packet.RawBytes);
                        }
                        break;

                        #endregion

                        #region L2CAP_Configuration_Response

                    case L2CAP.Code.L2CAP_Configuration_Response:

                        Log.DebugFormat(">> {0} [CID: {1}]", Event, packet.ChannelId);

                        Log.DebugFormat("-- MTU = {0}", packet.MaximumTransmissionUnit);

                        if (connection.CanStartService)
                        {
                            L2_DCID = L2CapDataPacket.UInt16ToBytes(BthConnection.Dcid++);

                            if (!connection.IsFake)
                            {
                                L2CAP_Connection_Request(connection.HciHandle.Bytes, _l2CapDataIdentifier++, L2_DCID,
                                                         L2CAP.PSM.HID_Service);
                                Log.DebugFormat("<< {0} with PSM [{1}] [CID: {2}]",
                                                L2CAP.Code.L2CAP_Connection_Request,
                                                L2CAP.PSM.HID_Service,
                                                _l2CapDataIdentifier - 1);
                            }
                            else
                            {
                                connection.SetConnectionType(L2CAP.PSM.HID_Service, L2_DCID);
                                connection.CanStartService = false;
                                OnInitialised(connection);
                            }
                        }
                        break;

                        #endregion

                        #region L2CAP_Disconnection_Request

                    case L2CAP.Code.L2CAP_Disconnection_Request:

                        Log.DebugFormat(">> {0} Handle [{1}]", Event, packet.SourceChannelIdentifier);

                        L2_SCID = packet.SourceChannelIdentifier;

                        L2CAP_Disconnection_Response(connection.HciHandle.Bytes,
                                                     packet.ChannelId, L2_SCID, L2_SCID);

                        Log.DebugFormat("<< {0}", L2CAP.Code.L2CAP_Disconnection_Response);
                        break;

                        #endregion

                        #region L2CAP_Disconnection_Response

                    case L2CAP.Code.L2CAP_Disconnection_Response:

                        Log.DebugFormat(">> {0}", Event);

                        if (connection.CanStartHid)
                        {
                            connection.IsServiceStarted = false;
                            OnInitialised(connection);
                        }
                        break;

                        #endregion

                        #region L2CAP_Echo_Request

                    case L2CAP.Code.L2CAP_Echo_Request:

                        Log.DebugFormat(">> {0}", Event);
                        break;

                        #endregion

                        #region L2CAP_Echo_Response

                    case L2CAP.Code.L2CAP_Echo_Response:

                        Log.DebugFormat(">> {0}", Event);
                        break;

                        #endregion

                        #region L2CAP_Information_Request

                    case L2CAP.Code.L2CAP_Information_Request:

                        Log.DebugFormat(">> {0}", Event);
                        break;

                        #endregion

                        #region L2CAP_Information_Response

                    case L2CAP.Code.L2CAP_Information_Response:

                        Log.DebugFormat(">> {0}", Event);
                        break;

                        #endregion
                    }
                }
            }
            else if (packet.IsHidInputReport)
            {
                // HID report received, parse content and extract gamepad data
                connection.ParseHidReport(packet.RawBytes);
            }
            else if (connection.InitHidReport(packet.RawBytes))
            {
                connection.CanStartHid = true;

                L2_DCID = connection.Get_DCID(L2CAP.PSM.HID_Service);
                L2_SCID = connection.Get_SCID(L2CAP.PSM.HID_Service);

                L2CAP_Disconnection_Request(connection.HciHandle.Bytes, _l2CapDataIdentifier++, L2_SCID, L2_DCID);

                Log.DebugFormat("<< {0}", L2CAP.Code.L2CAP_Disconnection_Request);
            }
        }