예제 #1
0
        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);
        }
예제 #2
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);
        }
예제 #3
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);
        }
예제 #4
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);
            }
        }
예제 #5
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);
            }
        }
예제 #6
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);
                }
            }
        }
예제 #7
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
            }
        }