ScpControl/Bluetooth/BthConnection.cs (176 lines of code) (raw):

using System; using System.Net.NetworkInformation; using System.Reflection; using log4net; using ScpControl.Bluetooth.Ds4; using ScpControl.Shared.Core; using ScpControl.Utilities; namespace ScpControl.Bluetooth { public class BthConnection : IEquatable<BthConnection>, IComparable<BthConnection> { #region IComparable<ScpBthConnection> Members public virtual int CompareTo(BthConnection other) { return HciHandle.CompareTo(other.HciHandle); } #endregion #region Public methods public byte[] SetConnectionType(L2CAP.PSM connectionType, byte lsb, byte msb, ushort dcid = 0) { switch (connectionType) { case L2CAP.PSM.HID_Command: _l2CapCommandHandle[0] = new BthHandle(lsb, msb); _l2CapCommandHandle[1] = new BthHandle(Dcid++); return _l2CapCommandHandle[1].Bytes; case L2CAP.PSM.HID_Interrupt: CanStartService = true; _l2CapInterruptHandle[0] = new BthHandle(lsb, msb); _l2CapInterruptHandle[1] = new BthHandle(Dcid++); return _l2CapInterruptHandle[1].Bytes; case L2CAP.PSM.HID_Service: IsServiceStarted = true; CanStartService = false; _l2CapServiceHandle[0] = new BthHandle(lsb, msb); _l2CapServiceHandle[1] = new BthHandle(dcid); return _l2CapServiceHandle[1].Bytes; } throw new ArgumentException("Invalid L2CAP Connection Type"); } public byte[] SetConnectionType(L2CAP.PSM connectionType, byte[] handle) { return SetConnectionType(connectionType, handle[0], handle[1]); } public override string ToString() { return string.Format("{0} - {1}", DeviceAddress.AsFriendlyName(), _remoteName); } #endregion #region Private/protected fields protected static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static ushort _dcid = 0x40; private readonly BthHandle[] _l2CapCommandHandle = new BthHandle[2]; private readonly BthHandle[] _l2CapInterruptHandle = new BthHandle[2]; private readonly BthHandle[] _l2CapServiceHandle = new BthHandle[2]; private DsModel _model = DsModel.DS3; private string _remoteName = string.Empty; #endregion #region Ctors public BthConnection() { } public BthConnection(BthHandle hciHandle) { HciHandle = hciHandle; DeviceAddress = PhysicalAddress.None; } #endregion #region Public properties public BthHandle HciHandle { get; private set; } public PhysicalAddress DeviceAddress { get; set; } public virtual string RemoteName { get { return _remoteName; } set { _remoteName = value; if (!string.IsNullOrEmpty(_remoteName) && _remoteName.Equals(BthDs4.GenuineProductName)) _model = DsModel.DS4; } } public bool CanStartHid { get; set; } public bool CanStartService { get; set; } public bool IsServiceStarted { get; set; } public bool IsStarted { get; set; } public bool IsFake { get; set; } public virtual DsModel Model { get { return _model; } } /// <summary> /// Gets or sets the global Destination Channel Identifier. /// </summary> public static ushort Dcid { get { return _dcid; } set { _dcid = (ushort) (value < 0xFFFF ? value : 0x40); } } #endregion #region Channel identifier helper methods /// <summary> /// Destination Channel Identifier. /// </summary> /// <remarks> /// Used as the device local end point for an L2CAP transmission. It represents the channel endpoint on the device /// receiving the message. It is a device local name only. See also SCID. /// </remarks> /// <param name="lsb"></param> /// <param name="msb"></param> /// <returns></returns> public virtual byte[] Get_DCID(byte lsb, byte msb) { if (_l2CapCommandHandle[0].Equals(lsb, msb)) { return _l2CapCommandHandle[1].Bytes; } if (_l2CapInterruptHandle[0].Equals(lsb, msb)) { return _l2CapInterruptHandle[1].Bytes; } if (_l2CapServiceHandle[0].Equals(lsb, msb)) { return _l2CapServiceHandle[1].Bytes; } throw new Exception("L2CAP DCID Not Found"); } /// <summary> /// Destination Channel Identifier. /// </summary> /// <remarks> /// Used as the device local end point for an L2CAP transmission. It represents the channel endpoint on the device /// receiving the message. It is a device local name only. See also SCID. /// </remarks> /// <param name="connectionType"></param> /// <returns></returns> public virtual byte[] Get_DCID(L2CAP.PSM connectionType) { switch (connectionType) { case L2CAP.PSM.HID_Command: return _l2CapCommandHandle[1].Bytes; case L2CAP.PSM.HID_Interrupt: return _l2CapInterruptHandle[1].Bytes; case L2CAP.PSM.HID_Service: return _l2CapServiceHandle[1].Bytes; } throw new Exception("Invalid L2CAP Connection Type"); } /// <summary> /// Source Channel Identifier. /// </summary> /// <remarks> /// Used in the L2CAP layer to indicate the channel endpoint on the device sending the L2CAP message. It is a /// device local name only. /// </remarks> /// <param name="lsb">Least significant byte.</param> /// <param name="msb">Most significant byte.</param> /// <returns></returns> public byte[] Get_SCID(byte lsb, byte msb) { if (_l2CapCommandHandle[1] != null && _l2CapCommandHandle[1].Equals(lsb, msb)) { return _l2CapCommandHandle[0].Bytes; } if (_l2CapInterruptHandle[1] != null && _l2CapInterruptHandle[1].Equals(lsb, msb)) { return _l2CapInterruptHandle[0].Bytes; } if (_l2CapServiceHandle[1] != null && _l2CapServiceHandle[1].Equals(lsb, msb)) { return _l2CapServiceHandle[0].Bytes; } throw new Exception("L2CAP SCID Not Found"); } public byte[] Get_SCID(byte[] buffer) { return Get_SCID(buffer[0], buffer[1]); } /// <summary> /// Source Channel Identifier. /// </summary> /// <remarks> /// Used in the L2CAP layer to indicate the channel endpoint on the device sending the L2CAP message. It is a /// device local name only. /// </remarks> /// <param name="connectionType"></param> /// <returns>Source Channel Identifier.</returns> public byte[] Get_SCID(L2CAP.PSM connectionType) { switch (connectionType) { case L2CAP.PSM.HID_Command: return _l2CapCommandHandle[0].Bytes; case L2CAP.PSM.HID_Interrupt: return _l2CapInterruptHandle[0].Bytes; case L2CAP.PSM.HID_Service: return _l2CapServiceHandle[0].Bytes; } throw new Exception("Invalid L2CAP Connection Type"); } #endregion #region IEquatable<ScpBthConnection> Members public virtual bool Equals(BthConnection other) { return HciHandle.Equals(other.HciHandle); } public virtual bool Equals(byte lsb, byte msb) { return HciHandle.Equals(lsb, msb); } public virtual bool Equals(byte[] other) { return HciHandle.Equals(other); } #endregion } }