Exemple #1
0
        internal BluetopiaPacketDebug(BluetopiaFactory fcty, Stream pcapFile)
        {
            _fcty    = fcty;
            _Handler = HandleDebug;
            var ret = NativeMethods.BSC_RegisterDebugCallback(_fcty.StackId, _Handler, 0);

            BluetopiaUtils.Assert(ret, "BSC_RegisterDebugCallback");
            //
            var hundNs = DateTime.UtcNow.Ticks;
            var msec   = Environment.TickCount;

            _tickTimeOffset = hundNs - msec * HundredNsInMsec;
#if RAW_FILE
            _dest = File.Create(@"\packets.dat");
#endif
            _destPcap = pcapFile;
            WritePcapGlobalHeader(_destPcap);
            //
#if DEBUG
            byte testIsByteRange = checked ((byte)StackConsts.HCI_PacketType.__HCIAdditional);
            _sharedBuf[0] = testIsByteRange; // shut-up compiler
#if !NETCF                                   // :-(
            Debug.Assert(new IntPtr(OffsetOfData) == Marshal.OffsetOf(
                             typeof(Structs.HCI_Packet), "_startOf_HCIPacketData"));
#endif
#endif
        }
        protected override void DoOpenClient(int scn, BluetoothAddress addressToConnect)
        {
            _fcty.CancelAllQueryNames();
            var addrX = BluetopiaUtils.BluetoothAddressAsInteger(addressToConnect);
            int hConn = _fcty.Api.SPP_Open_Remote_Port(_fcty.StackId, addrX, (uint)scn,
                                                       _callbackAAAA, 0);
            var ret = (BluetopiaError)hConn;
            int i;

            for (i = 0; i < 5 && ret == BluetopiaError.RFCOMM_UNABLE_TO_CONNECT_TO_REMOTE_DEVICE; ++i)
            {
                // Sometimes see this error here, my guess is that the baseband
                // connection used by the SDP Query is closing right when as we
                // wanted to connect, so we fail to initiate the connect.  In
                // the debugger when we retry it succeeds, so retry.
                if (i > 0)
                {
                    Thread.Sleep(100);        // Try right away, then after 100ms sleeps
                }
                hConn = _fcty.Api.SPP_Open_Remote_Port(_fcty.StackId, addrX, (uint)scn,
                                                       _callbackAAAA, 0);
                ret = (BluetopiaError)hConn;
            }
            if (i > 0)
            {
                Debug.WriteLine("Auto-retry " + i + " after RFCOMM_UNABLE_TO_CONNECT_TO_REMOTE_DEVICE for SPP_Open_Remote_Port");
            }
            BluetopiaUtils.CheckAndThrow(ret, "SPP_Open_Remote_Port");
            _hPortClient = checked ((uint)ret);
        }
        //NEW protected new internal IAsyncResult BeginConnect(BluetoothEndPoint bep, //string pin,
        //    AsyncCallback asyncCallback, Object state)
        //{
        //    //_hackRemoteAddress = bep.Address;
        //    //_hackRemotePort = checked((byte)bep.Port);
        //    return base.BeginConnect(bep, asyncCallback, state);
        //}
        #endregion

        #region Write
        protected override void DoWrite(byte[] p_data, ushort len_to_write, out ushort p_len_written)
        {
            int writeLen = _fcty.Api.SPP_Data_Write(_fcty.StackId, PortHandle, len_to_write, p_data);
            var ret      = (BluetopiaError)writeLen;

            BluetopiaUtils.CheckAndThrow(ret, "SPP_Data_Write");
            p_len_written = checked ((ushort)writeLen);
        }
Exemple #4
0
        private void ReadName()
        {
            byte[] arr = new byte[StackConsts.MAX_NAME_LENGTH];
            var    ret = _fcty.Api.GAP_Query_Local_Device_Name(_fcty.StackId,
                                                               arr.Length, arr);

            BluetopiaUtils.CheckAndThrow(ret, "GAP_Query_Local_Device_Name");
            _name = BluetopiaUtils.FromNameString(arr);
        }
        protected override void DoOpenServer(int scn)
        {
            int hConn = _fcty.Api.SPP_Open_Server_Port(_fcty.StackId, (uint)scn,
                                                       _callbackAAAA, 0);
            var ret = (BluetopiaError)hConn;

            BluetopiaUtils.CheckAndThrow(ret, "SPP_Open_Remote_Port");
            Debug.WriteLine("SPP_Open_Remote_Port portId: " + ret);
            _hPortServer = checked ((uint)ret);
        }
        void IBluetopiaSecurity.InitStack()
        {
            var ret = _factory.Api.GAP_Set_Pairability_Mode(_factory.StackId,
                                                            StackConsts.GAP_Pairability_Mode.PairableMode);

            BluetopiaUtils.CheckAndThrow(ret, "GAP_Set_Pairability_Mode");
            ret = _factory.Api.GAP_Register_Remote_Authentication(
                _factory.StackId, _AuthenticateCallback, 0);
            BluetopiaUtils.CheckAndThrow(ret, "GAP_Register_Remote_Authentication");
        }
        internal static BluetopiaDeviceInfo CreateFromInquiry(
            Structs.GAP_Inquiry_Entry_Event_Data data, BluetopiaFactory factory)
        {
            var bdi = new BluetopiaDeviceInfo(factory,
                                              BluetopiaUtils.ToBluetoothAddress(data.BD_ADDR));

            bdi._cod = BluetopiaUtils.ToClassOfDevice(data.Class_of_Device);
            bdi._blockFindNameForNow = true;
            bdi._clockOffsetEtc      = new ClockOffsetEtc(data);
            return(bdi);
        }
Exemple #8
0
        public void HciAddScoConnection()
        {
            var pt = StackConsts.HCI_PACKET_SCO_TYPE__AllThree;

            //
            StackConsts.HCI_ERROR_CODE statusCode;
            var ret = NativeMethods.HCI_Add_SCO_Connection(_fcty.StackId,
                                                           _hConn.Value, pt, out statusCode);

            BluetopiaUtils.CheckAndThrow(ret, "HCI_Add_SCO_Connection");
            Debug.WriteLine("HCI_Add_SCO_Connection status: " + statusCode);
        }
Exemple #9
0
        internal BluetopiaError QueryName(BluetopiaDeviceInfo device,
                                          bool mayUseCached, bool mayQueryName)
        {
            const int CancelBlockingTimeSeconds = 2;

            lock (_lockDevices) {
                if (mayUseCached)
                {
                    BluetopiaDeviceInfo prev;
                    var got = _knownDevices.TryGetValue(device.DeviceAddress, out prev);
                    if (prev != null && prev.HasDeviceName)
                    {
                        device.SetName(prev.DeviceName);
                        return(BluetopiaError.OK);
                    }
                }
                //
                if (!mayQueryName)
                {
                    return(BluetopiaError.OK);
                }
                var since = DateTime.UtcNow - _lastCancelAllQueryNames;
                if (since.TotalSeconds < CancelBlockingTimeSeconds)
                {
                    Debug.WriteLine("QueryName blocked");
                    return(BluetopiaError.OK);
                }
                else     //DEBUG
                {
                }
                List <BluetopiaDeviceInfo> instList;
                var exists = _nameQueryList.TryGetValue(device.DeviceAddress, out instList);
                if (instList == null)
                {
                    Debug.Assert(!exists, "Null Value!?!");
                    instList = new List <BluetopiaDeviceInfo>();
                    _nameQueryList.Add(device.DeviceAddress, instList);
                }
                if (instList.Contains(device))
                {
                    // Already querying...
                    return(BluetopiaError.OK);
                }
                instList.Add(device);
            }//lock
            var ret = _api.GAP_Query_Remote_Device_Name(this.StackId,
                                                        BluetopiaUtils.BluetoothAddressAsInteger(device.DeviceAddress),
                                                        _HandleNameLookup, 0);

            BluetopiaUtils.WriteLineIfError(ret, "GAP_Query_Remote_Device_Name");
            return(ret);
        }
Exemple #10
0
        public BluetopiaPlaying()
        {
            _hciCb = FnCallback;
            _fcty  = BluetoothFactory.GetTheFactoryOfTypeOrDefault <BluetopiaFactory>();
            if (_fcty == null)
            {
                throw new InvalidOperationException("No Bluetopia stack.");
            }
            var ret = NativeMethods.HCI_Register_Event_Callback(_fcty.StackId,
                                                                _hciCb, 0);

            BluetopiaUtils.CheckAndThrow(ret, "HCI_Register_Event_Callback");
        }
Exemple #11
0
        private BluetopiaError RespondWithNoLinkKey(long addrI)
        {
            BluetopiaError ret;
            var            rsp = new Structs.GAP_Authentication_Information(
                StackConsts.GAP_Authentication_Type_t.atLinkKey);

            Debug.Assert(rsp._Authentication_Data_Length == 0, "!Null is zero len.");
            Debug.WriteLine("  Sending Auth Response: -ve (no linkkey)");
            ret = _factory.Api.GAP_Authentication_Response(
                _factory.StackId, addrI, ref rsp);
            Debug.Assert(BluetopiaUtils.IsSuccess(ret),
                         "GAP_Authentication_Response Negative=Non-data ret: " + ret);
            return(ret);
        }
        private Structs.SPP_Event_Data EventConnectInd(Structs.SPP_Event_Data SPP_Event_Data)
        {
            var data = (Structs.SPP_Open_Port_Indication_Data)
                       Marshal.PtrToStructure(SPP_Event_Data.pEventData,
                                              typeof(Structs.SPP_Open_Port_Indication_Data));

            Debug.WriteLine("EventConnectInd portId: " + data.SerialPortID);
            Debug.Assert(_hPortServer.Value == data.SerialPortID, "thought this should be the same id");
            _serverIndAddress = BluetopiaUtils.ToBluetoothAddress(data.BD_ADDR);
            ThreadPool.QueueUserWorkItem(delegate {
                HandleCONNECTED("INDICATE");
            });
            return(SPP_Event_Data);
        }
Exemple #13
0
        public void DeleteServiceRecord()
        {
            if (!_hSR.HasValue)
            {
                //throw new InvalidOperationException("No record was created.");
                Debug.Fail("Delete -- No record was created.");
                return;
            }
            var hSR = _hSR.Value;

            _hSR = null;
            var ret = _fcty.Api.SDP_Delete_Service_Record(_fcty.StackId, hSR);

            BluetopiaUtils.Assert(ret, "SDP_Delete_Service_Record");
        }
Exemple #14
0
        public void HciCreateConnection(BluetoothAddress address)
        {
            byte   psrm = 0; byte psm = 0; ushort co = 0;
            byte   ars = 1;
            ushort pt  = 0xFFFF;

            //
            StackConsts.HCI_ERROR_CODE statusCode;
            var ret = NativeMethods.HCI_Create_Connection(_fcty.StackId,
                                                          BluetopiaUtils.BluetoothAddressAsInteger(address), pt,
                                                          psrm, psm, co, ars, out statusCode);

            BluetopiaUtils.CheckAndThrow(ret, "HCI_Create_Connection");
            Debug.WriteLine("HCI_Create_Connection status: " + statusCode);
        }
Exemple #15
0
        //----
        public new void CreateServiceRecord(ServiceRecord record)
        {
            if (record == null)
            {
                throw new ArgumentNullException("record");
            }
            if (_hSR.HasValue)
            {
                throw new InvalidOperationException("One at a time please.");
            }
            //
            ServiceElement svcIdListElement;
            var            newList = new List <ServiceAttribute>(Math.Max(record.Count - 1, 0));

            foreach (var cur in record)
            {
                if (cur.Id == UniversalAttributeId.ServiceClassIdList)
                {
                    svcIdListElement = cur.Value;
                }
                else
                {
                    newList.Add(cur);
                }
            }
            var newRecord = new ServiceRecord(newList);

            Debug.Assert(!newRecord.Contains(UniversalAttributeId.ServiceClassIdList), "DOES!! contain SvcIdList");
            // Add the list of UUIDs
            var el            = record.GetAttributeById(UniversalAttributeId.ServiceClassIdList).Value;
            var classList     = el.GetValueAsElementList();
            var svcIdListList = new Structs.SDP_UUID_Entry_Bytes[classList.Count];

            for (int i = 0; i < svcIdListList.Length; ++i)
            {
                svcIdListList[i] = Structs.SDP_UUID_Entry_Bytes.Create(classList[i]);
            }
            Debug.Assert(svcIdListList.Length != 0, "Docs: 'the number of UUID Entries'...'CANNOT be zero'.");
            //
            int hSR = _fcty.Api.SDP_Create_Service_Record(_fcty.StackId,
                                                          checked ((uint)svcIdListList.Length), svcIdListList);
            var ret = (BluetopiaError)hSR;

            BluetopiaUtils.CheckAndThrowZeroIsIllegal(ret, "SDP_Create_Service_Record");
            _hSR = unchecked ((uint)hSR);
            //
            int count = base.CreateServiceRecord(newRecord, s_dummy);
        }
Exemple #16
0
        private BluetopiaError RespondWithLinkKey(long addrI, byte[] key)
        {
            BluetopiaError ret;
            var            rsp = new Structs.GAP_Authentication_Information(
                StackConsts.GAP_Authentication_Type_t.atLinkKey,
                key, _factory.ApiVersion);

            Debug.Assert(rsp._Authentication_Data_Length != 0, "Zero len LinkKeys not allowed.");
            Debug.WriteLine("  Sending Auth Response: LinkKey)");
            Debug.WriteLine("    len: " + rsp._Authentication_Data_Length);
            ret = _factory.Api.GAP_Authentication_Response(
                _factory.StackId, addrI, ref rsp);
            Debug.Assert(BluetopiaUtils.IsSuccess(ret),
                         "GAP_Authentication_Response Negative=Non-data ret: " + ret);
            return(ret);
        }
Exemple #17
0
        //private void RespondWithPinCode_Runner(object state)
        //{
        //    RespondWithPinCode((ResponderInfo)state);
        //}

        private BluetopiaError RespondWithPinCode(ResponderInfo rspInfo)
        {
            BluetopiaError ret;
            var            rsp = new Structs.GAP_Authentication_Information(
                StackConsts.GAP_Authentication_Type_t.atPINCode,
                rspInfo.PPItem._pin, _factory.ApiVersion);

            //, "Zero len Pins not allowed.
            Debug.WriteLine("  Sending Auth Response: PinCode");
            Debug.WriteLine("    " + rsp.DebugToString());
            ret = _factory.Api.GAP_Authentication_Response(
                _factory.StackId, rspInfo.AddrI, ref rsp);
            Debug.Assert(BluetopiaUtils.IsSuccess(ret),
                         "GAP_Authentication_Response: " + ret);
            return(ret);
        }
Exemple #18
0
        //--
        #region IBluetoothSecurity Members

        public bool PairRequest(BluetoothAddress device, string pin)
        {
            // Verify and store the pin
            // TODO null PIN
            PinPairItem pairItem = SetPinPairItem_willLock(device, pin);
            // Add event etc.
            ManualResetEvent waitComplete;

            lock (_pins) {
                if (pairItem._eventForPairRequest != null)
                {
                    // HACK handle overlapping requests.  Fail the former?
                    pairItem.success = false;
                    pairItem._eventForPairRequest.Set();
                }
                waitComplete = new ManualResetEvent(false);
                pairItem._eventForPairRequest = waitComplete;
            }
            // Run
            BluetopiaError ret;
            var            foo = false;

            if (foo)
            {
                ret = _factory.Api.GAP_Authenticate_Remote_Device(
                    _factory.StackId, BluetopiaUtils.BluetoothAddressAsInteger(device), _AuthenticateCallback, 0);
            }
            else
            {
                ret = _factory.Api.GAP_Initiate_Bonding(_factory.StackId,
                                                        BluetopiaUtils.BluetoothAddressAsInteger(device),
                                                        StackConsts.GAP_Bonding_Type.Dedicated,
                                                        _AuthenticateCallback, 0);
            }
            if (!BluetopiaUtils.IsSuccess(ret))
            {
                return(false);
            }
            // Need to wait for completion.
            const int timeout = 3 * 60 * 1000;

            waitComplete.WaitOne(timeout, false);
            lock (_pins) {
                RemovePinPairItem__mustByInLock(device, pin, waitComplete);
                return(pairItem.success == true);
            }
        }
Exemple #19
0
 public void SetMode(bool?connectable, bool?discoverable)
 {
     if (connectable.HasValue)
     {
         var ret = _fcty.Api.GAP_Set_Connectability_Mode(_fcty.StackId,
                                                         connectable.Value ? StackConsts.GAP_Connectability_Mode.ConnectableMode
                                 : StackConsts.GAP_Connectability_Mode.NonConnectableMode);
         BluetopiaUtils.CheckAndThrow(ret, "GAP_Set_Connectability_Mode");
     }
     if (discoverable.HasValue)
     {
         var ret = _fcty.Api.GAP_Set_Discoverability_Mode(_fcty.StackId,
                                                          discoverable.Value ? StackConsts.GAP_Discoverability_Mode.GeneralDiscoverableMode
                                 : StackConsts.GAP_Discoverability_Mode.NonDiscoverableMode, 0);
         BluetopiaUtils.CheckAndThrow(ret, "GAP_Set_Discoverability_Mode");
     }
 }
Exemple #20
0
        internal BluetopiaRadio(BluetopiaFactory factory)
        {
            _fcty = factory;
            byte[] bd_addr = new byte[StackConsts.BD_ADDR_SIZE];
            var    ret     = _fcty.Api.GAP_Query_Local_BD_ADDR(_fcty.StackId, bd_addr);

            BluetopiaUtils.CheckAndThrow(ret, "GAP_Query_Local_BD_ADDR");
            _addr = BluetopiaUtils.ToBluetoothAddress(bd_addr);
            //
            ReadName();
            //
            uint cod;

            ret = _fcty.Api.GAP_Query_Class_Of_Device(_fcty.StackId, out cod);
            BluetopiaUtils.CheckAndThrow(ret, "GAP_Query_Class_Of_Device");
            _cod = new ClassOfDevice(cod);
        }
Exemple #21
0
        //----
        protected sealed override void WriteAttribute(ServiceAttribute attr, byte[] buffer, ref int offset)
        {
            bool doneKnown = WriteWellKnownAttribute(attr);

            if (doneKnown)
            {
                return;
            }
            //
            base.WriteAttribute(attr, buffer, ref offset);
            //
            var e   = _element;
            var ret = AddAttribute(e);

            BluetopiaUtils.CheckAndThrow(ret, "SDP_Add_Attribute");
            _element = null;
        }
Exemple #22
0
        }//class

        internal IAsyncResult BeginInquiry(int maxDevices, TimeSpan inquiryLength,
                                           AsyncCallback callback, object state,
                                           BluetoothClient.LiveDiscoveryCallback liveDiscoHandler, object liveDiscoState,
                                           DiscoDevsParams args)
        {
            CancelAllQueryNames();
            return(_inquiryHandler.BeginInquiry(maxDevices, inquiryLength,
                                                callback, state,
                                                liveDiscoHandler, liveDiscoState,
                                                delegate() {
                BluetopiaError ret = Api.GAP_Perform_Inquiry(StackId,
                                                             StackConsts.GAP_Inquiry_Type.GeneralInquiry,
                                                             0, 0, checked ((uint)inquiryLength.Seconds),
                                                             checked ((uint)maxDevices),
                                                             _inquiryEventCallback, 0);
                BluetopiaUtils.CheckAndThrow(ret, "Btsdk_StartDeviceDiscovery");
            }, args));
        }
Exemple #23
0
        void HandleNameLookup2(uint BluetoothStackID,
                               ref Structs.GAP_Event_Data GAP_Event_Data, uint CallbackParameter)
        {
            Debug.Assert(GAP_Event_Data.Event_Data_Type == StackConsts.GAP_Event_Type.Remote_Name_Result,
                         "Unexpected event type: " + GAP_Event_Data.Event_Data_Type);
            //
            Structs.GAP_Remote_Name_Event_Data data;
            //
            data = (Structs.GAP_Remote_Name_Event_Data)Marshal.PtrToStructure(
                GAP_Event_Data.pData, typeof(Structs.GAP_Remote_Name_Event_Data));
            var addr = BluetopiaUtils.ToBluetoothAddress(data._Remote_Device);

            Debug.WriteLine("GAP_Remote_Name_Event_Data: status: " + data._Remote_Name_Status
                            + ", addr: " + addr);
            if (data._Remote_Name_Status != 0)
            {
                return;
            }
            // TODO ThreadPool??? but need to marshal data._Remote_Name first.
            List <BluetopiaDeviceInfo> queryList;

            lock (_lockDevices) {
                var got  = _nameQueryList.TryGetValue(addr, out queryList);
                var gotR = _nameQueryList.Remove(addr);
            }
            // TO-DO  if (list == null) return;
            var arr  = Widcomm.WidcommUtils.GetByteArrayNullTerminated(data._Remote_Name, 250);
            var name = BluetopiaUtils.FromNameString(arr);

            Debug.WriteLine("  name: " + name);
            if (queryList == null)
            {
                return;                    // duplicate above exit.
            }
            ThreadPool.QueueUserWorkItem(
                delegate {
                foreach (var cur in queryList)
                {
                    cur.SetName(name);
                }
                //_inquiryHandler.GotNameManually(addr, name);
                AddNamedKnownDevice(addr, name);
            });
        }
Exemple #24
0
        void ReadVersionsOnce()
        {
            if (_readVersions)
            {
                return;
            }
            _readVersions = true; // Just do once even if error
            BluetopiaError ret;

            try {
                StackConsts.HCI_ERROR_CODE hciStatus;
                ret = _fcty.Api.HCI_Read_Local_Version_Information(_fcty.StackId,
                                                                   out hciStatus, out _hciVersion, out _hciRev,
                                                                   out _lmpVersion, out _manuf, out _lmpSubver);
            } catch (MissingMethodException) { // Function added later to the SDK.
                ret = BluetopiaError.UNSUPPORTED_PLATFORM_ERROR;
            }
            BluetopiaUtils.Assert(ret, "HCI_Read_Local_Version_Information");
            if (!BluetopiaUtils.IsSuccess(ret))
            {
                _hciVersion = HciVersion.Unknown;
                _lmpVersion = LmpVersion.Unknown;
                _manuf      = Manufacturer.Unknown;
                _hciRev     = _lmpSubver = 0;
            }
            var arr = new byte[8];

            try {
                StackConsts.HCI_ERROR_CODE hciStatus;
                ret = _fcty.Api.HCI_Read_Local_Supported_Features(_fcty.StackId,
                                                                  out hciStatus, arr);
            } catch (MissingMethodException) { // Function added later to the SDK.
                ret = BluetopiaError.UNSUPPORTED_PLATFORM_ERROR;
            }
            BluetopiaUtils.Assert(ret, "HCI_Read_Local_Version_Information");
            if (BluetopiaUtils.IsSuccess(ret))
            {
                _lmpFeatures = (LmpFeatures)BitConverter.ToInt64(arr, 0);
            }
            else
            {
                _lmpFeatures = LmpFeatures.None;
            }
        }
Exemple #25
0
        internal void CancelAllQueryNames()
        {
            ICollection <BluetoothAddress> addrList;

            lock (_lockDevices) {
                _lastCancelAllQueryNames = DateTime.UtcNow;
                addrList = _nameQueryList.Keys;
                _nameQueryList.Clear();
            }
            Debug.WriteLine(string.Format(CultureInfo.InvariantCulture,
                                          "CancelAllQueryNames: {0} devices.", addrList.Count));
            foreach (var cur in addrList)
            {
                var ret = NativeMethods.GAP_Cancel_Query_Remote_Device_Name(
                    this.StackId, BluetopiaUtils.BluetoothAddressAsInteger(cur));
                BluetopiaUtils.Assert(ret, "GAP_Cancel_Query_Remote_Device_Name");
            }
            if (addrList.Count > 0)
            {
                // Help wait for cancellation to complete?
                Thread.Sleep(250);
            }
        }
Exemple #26
0
        internal IAsyncResult BeginQuery(BluetoothAddress device, Guid svcClass,
                                         bool rfcommOnly,
                                         AsyncCallback asyncCallback, object state)
        {
            int id0 = Interlocked.Increment(ref _callbackCount);
            var id  = unchecked ((uint)id0);
            var ar  = new AsyncResultGsr(asyncCallback, state, id);

            // Attribute range/etc
            Structs.SDP_Attribute_ID_List_Entry[] attrIdListArr;
            var attrIdAll     = Structs.SDP_Attribute_ID_List_Entry.CreateRange(0, 0xFFFF);
            var attrIdSvcList = Structs.SDP_Attribute_ID_List_Entry.CreateItem(
                UniversalAttributeId.ServiceClassIdList);
            var attrIdProto = Structs.SDP_Attribute_ID_List_Entry.CreateItem(
                UniversalAttributeId.ProtocolDescriptorList);

            if (rfcommOnly)
            {
                attrIdListArr = new[] { attrIdSvcList, attrIdProto };
            }
            else
            {
                attrIdListArr = new[] { attrIdAll };
            }
            // UUID
            var uuidArg = new Structs.SDP_UUID_Entry(svcClass);

            Structs.SDP_UUID_Entry[] uuidArr = new[] { uuidArg };
            AsyncResultGsr           old;

            old = MyInterlockedCompareExchange <AsyncResultGsr>(ref _ar, ar, null);
            if (old != null)
            {
                throw new NotImplementedException("One at a time please.");
            }
            bool trySuccess = false;

            try {
                // Call
                _fcty.CancelAllQueryNames();
                int hRequest = _fcty.Api.SDP_Service_Search_Attribute_Request(_fcty.StackId,
                                                                              BluetopiaUtils.BluetoothAddressAsInteger(device),
                                                                              (uint)uuidArr.Length, uuidArr,
                                                                              (uint)attrIdListArr.Length, attrIdListArr,
                                                                              _callback, id);
                var ret = (BluetopiaError)hRequest;
                int i;
                for (i = 0; i < 5 && ret == BluetopiaError.ATTEMPTING_CONNECTION_TO_DEVICE; ++i)
                {
                    // See BluetopiaRfcommStream.DoOpenClient... Assuming here a
                    // previous baseband connection was closing right when as we
                    // wanted to connect, so retry.
                    if (i > 0)
                    {
                        Thread.Sleep(100);        // Try right away, then after 100ms sleeps
                    }
                    hRequest = _fcty.Api.SDP_Service_Search_Attribute_Request(_fcty.StackId,
                                                                              BluetopiaUtils.BluetoothAddressAsInteger(device),
                                                                              (uint)uuidArr.Length, uuidArr,
                                                                              (uint)attrIdListArr.Length, attrIdListArr,
                                                                              _callback, id);
                    ret = (BluetopiaError)hRequest;
                }
                if (i > 0)
                {
                    Debug.WriteLine("Auto-retry " + i + " after ATTEMPTING_CONNECTION_TO_DEVICE for SDP_Service_Search_Attribute_Request");
                }
                BluetopiaUtils.CheckAndThrowZeroIsIllegal(ret, "SDP_Service_Search_Attribute_Request");
                trySuccess = true;
                return(ar);
            } finally {
                if (!trySuccess)
                {
                    // If we got here it must be our value in the variable!
                    var replaced = MyInterlockedExchange(ref _ar, null);
                    Debug.Assert(replaced != null);
                    Debug.Assert(replaced == ar);
                }
            }
        }
        protected override void DoPortClose(bool disposing)
        {
            // We have the event handle now run all our code on a threadpool
            // thread so there can't be any deadlock, but leave this
            //    // We saw an apparent deadlock
            //    // ThreadB: BTPS->HandleSpp_Event_Callback->HandleCONNECT_ERR -> Monitor.Enter
            //    // ThreadA: MeThreadPool->...
            //    //   ->CommonRfcommStream.Dispose [Holding Monitor]->DoPortClose->SPP_Close_Port
            //    ThreadPool.QueueUserWorkItem(PortClose_Runner, disposing);
            //}
            //
            //void PortClose_Runner(object state)
            //{
            //    bool disposing = (bool)state;
            if (_hPortClient.HasValue)
            {
                var portId = _hPortClient.Value;
                _hPortClient = null;
                var ret = _fcty.Api.SPP_Close_Port(_fcty.StackId, portId);
                if (m_state_ == State.PeerDidClose)
                {
                    // Get here in two cases: real-PeerDidClose *and* Timeout!
                    // So *need* to close the latter case so will get a SUCCESS then.
                    Debug.Assert(ret == BluetopiaError.INVALID_PARAMETER, "INFO: SPP_Close_Port expecting IP (state: " + m_state_ + ")");
                }
                else if (m_state_ == State.Closed)
                {
                    // Likely the Finalizer thread called us at the same time
                    // as an app thread did, so there's a race on accessing/overwriting
                    // _hPortClient.  Just spat the error.
                    // Ideally we'd solve  the race by Interlock.Exchang-ing
                    // _hPortClient or by locking.  But closing twice is not
                    // really a problem.
                    Debug.Assert(ret == BluetopiaError.RFCOMM_INVALID_DLCI, "INFO: SPP_Close_Port expecting RID (state: " + m_state_ + ")");

                    /*
                     *  The thread 0x85ac1746 has exited with code 0 (0x0).
                     *  The thread 0x85ac1746 has exited with code 0 (0x0).
                     *  CONNECT_ERR DEBUGID, m_state: Connected, m_arConnect (null)
                     *  HandlePortEvent: closed when open.
                     *  14:56:38: RemovePort from CloseInternal (state: Connected)
                     *  Function: InTheHand.Net.Bluetooth.StonestreetOne.BluetopiaRfcommStream.DoPortClose(bool), Thread: 0x85AC1746 <No Name>; m_state_: Connected
                     ** Function: InTheHand.Net.Bluetooth.StonestreetOne.BluetopiaRfcommStream.DoPortClose(bool), Thread: 0x8711DFC6 GC Finalizer Thread; m_state_: Closed
                     ** The thread '<No Name>' (0x8711dfc6) has exited with code 0 (0x0).
                     */
                }
                else
                {
                    BluetopiaUtils.Assert(ret, "SPP_Close_Port expecting OK (state: " + m_state_ + ")");
                }
            }
            if (_hPortServer.HasValue)
            {
                var portId = _hPortServer.Value;
                _hPortServer = null;
                var ret = _fcty.Api.SPP_Close_Server_Port(_fcty.StackId, portId);
                if (m_state_ == State.PeerDidClose)
                {
                    // Get here in two cases: real-PeerDidClose *and* Timeout!
                    // So *need* to close the latter case so will get a SUCCESS then.
                    Debug.Assert(ret == BluetopiaError.INVALID_PARAMETER, "SPP_Close_Server_Port expecting IP  (state: " + m_state_ + ")");
                }
                else if (m_state_ == State.Closed)
                {
                    // Likely the Finalizer thread called us at the same time
                    // as an app thread did, so there's a race on accessing/overwriting
                    // _hPortClient.  Just splat the assert.  See above.
                    Debug.Assert(ret == BluetopiaError.RFCOMM_INVALID_DLCI, "INFO: SPP_Close_Server_Port expecting RID (state: " + m_state_ + ")");
                }
                else
                {
                    BluetopiaUtils.Assert(ret, "SPP_Close_Server_Port expecting OK (state: " + m_state_ + ")");
                }
            }
        }
Exemple #28
0
        private void HandleAuthenticate_Callback2(uint BluetoothStackID,
                                                  ref Structs.GAP_Event_Data GAP_Event_Data, uint CallbackParameter)
        {
            //Debug.WriteLine("Authenticate_Callback Event_Data_Type: " + GAP_Event_Data.Event_Data_Type);
            Debug.Assert(GAP_Event_Data.Event_Data_Type == StackConsts.GAP_Event_Type.Authentication,
                         "Unexpected Authenticate_Callback Event_Data_Type: " + GAP_Event_Data.Event_Data_Type);
            if (GAP_Event_Data.Event_Data_Type == StackConsts.GAP_Event_Type.Authentication)
            {
                var data = (Structs.GAP_Authentication_Event_Data__Status)
                           Marshal.PtrToStructure(GAP_Event_Data.pData,
                                                  typeof(Structs.GAP_Authentication_Event_Data__Status));
                var addr8 = new byte[8];
                data._Remote_Device.CopyTo(addr8, 0);
                var addrI = BitConverter.ToInt64(addr8, 0);
                var addr  = BluetopiaUtils.ToBluetoothAddress(addr8);
#if DEBUG
                var addrI2 = BluetopiaUtils.BluetoothAddressAsInteger(addr);
                Trace.Assert(addrI == addrI2, "addrI: + " + addrI + " != addrI2: " + addrI2);
#endif
                Debug.WriteLine("Authenticate_Callback: type: " + data._GAP_Authentication_Event_Type
                                + ", addr: " + addr.ToString());
                if (data._GAP_Authentication_Event_Type == StackConsts.GAP_Authentication_Event_Type
                    .AuthenticationStatus)
                {
                    Debug.WriteLine("  Status: " + data.GetAuthenticationStatus(_factory.ApiVersion) + ")");
                }
                //
                PinPairItem ppItem;
                byte[]      key = null;
                ppItem = GetPinPairItem_willLock(addr); // Got Pin?
                // Use LinkKey if not PairRequest active.
                if (ppItem == null || ppItem._eventForPairRequest == null)
                {
                    lock (_pins) { // Got LinkKey?
                        var got = _keys.TryGetValue(addr, out key);
                        Debug.Assert(!got || (key != null));
                    }
                }
                if (ppItem == null && key == null)
                {
                    Debug.WriteLine("  No Pin or LinkKey for that device, exiting.");
                    return;
                }
                Debug.WriteLine("  Have Pin: " + (ppItem != null) + ", LinkKey: " + (key != null));
                //
                BluetopiaError ret;
                switch (data._GAP_Authentication_Event_Type)
                {
                case StackConsts.GAP_Authentication_Event_Type.LinkKeyRequest:
                    if (key == null)
                    {
                        ret = RespondWithNoLinkKey(addrI);
                    }
                    else
                    {
                        ret = RespondWithLinkKey(addrI, key);
                    }
                    break;

                case StackConsts.GAP_Authentication_Event_Type.PINCodeRequest:
                    if (ppItem == null)
                    {
                        break;
                    }
                    // Respond with Pin
                    Debug.Assert(ppItem != null, "Would have exited above if not a known device.");
                    var rspndrInfo = new ResponderInfo {
                        AddrI = addrI, PPItem = ppItem
                    };
                    ret = RespondWithPinCode(rspndrInfo);
                    break;

                case StackConsts.GAP_Authentication_Event_Type.AuthenticationStatus:
                    if (ppItem == null)
                    {
                        break;
                    }
                    // Success or Fail??
                    Debug.Assert(ppItem != null, "Would have exited above if not a known device.");
                    lock (_pins) {
                        ppItem.status  = data.GetAuthenticationStatus(_factory.ApiVersion);
                        ppItem.success = (ppItem.status
                                          == StackConsts.HCI_ERROR_CODE.NO_ERROR);
                        ppItem._eventForPairRequest.Set();
                    }
                    break;

                case StackConsts.GAP_Authentication_Event_Type.LinkKeyCreation:
                    // Store the LinkKey for the next time we connect -- the stack doesn't!
                    var authInfoKey = (Structs.GAP_Authentication_Event_Data__LinkKey)
                                      Marshal.PtrToStructure(GAP_Event_Data.pData,
                                                             typeof(Structs.GAP_Authentication_Event_Data__LinkKey));
                    AddOrUpdateLinkKey_willLock(addr, authInfoKey.GetLinkKey(_factory.ApiVersion));
                    break;
                }//switch
            }
        }
Exemple #29
0
        internal BluetopiaFactory(IBluetopiaApi api, IBluetopiaSecurity optionalSecurityInstance)
        {
            if (api == null)
            {
                throw new ArgumentNullException("api");
            }
            _api = api;
            //
            _inquiryHandler       = new BluetopiaInquiry(this);
            _inquiryEventCallback = _inquiryHandler.HandleInquiryEvent;
            _HandleNameLookup     = HandleNameLookup;
            //
            //int handle = _api.BSC_Initialize((byte[])InitData.Clone(), 0);
            Utils.MiscUtils.Trace_WriteLine(
                "Calling BSC_Initialize with:" + InitData2.ToString());
            int handle = _api.BSC_Initialize(ref InitData2, 0);
            //TEST--CheckStructBytes(ref InitData2, (byte[])InitData.Clone());
            var ret = (BluetopiaError)handle;

            if (!BluetopiaUtils.IsSuccessZeroIsIllegal(ret))
            {
                KillBtExplorerExe();  // Since one app at a time!
                // _Quickly_ try to init, as BTExplorer.exe restarts automatically!
                handle = _api.BSC_Initialize(ref InitData2, 0);
                ret    = (BluetopiaError)handle;
            }
            if (!BluetopiaUtils.IsSuccessZeroIsIllegal(ret))
            {
                Utils.MiscUtils.Trace_WriteLine("Stonestreet One Bluetopia failed to init: "
                                                + BluetopiaUtils.ErrorToString(ret));
            }
            BluetopiaUtils.CheckAndThrowZeroIsIllegal(ret, "BSC_Initialize");
            _stackId = checked ((uint)handle);
            //
            if (optionalSecurityInstance != null)
            {
                _sec = optionalSecurityInstance;
            }
            else
            {
                _sec = new BluetopiaSecurity(this);
            }
            _sec.InitStack();
            //
            //
            var packetDebug = false;
            var eap         = BluetoothFactoryConfig.GetEntryAssemblyPath();

            if (eap != null)   // null if we're under unit-test or...
            {
                var dir      = Path.GetDirectoryName(eap);
                var filename = Path.Combine(dir, "DoPacketDebug.txt");
                if (File.Exists(filename))
                {
                    packetDebug = true;
                }
            }
            if (packetDebug)
            {
                _pdebug = new BluetopiaPacketDebug(this);
            }
            //
            InitApiVersion();
        }