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); }
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); }
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); }
//-- #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); } }
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); } }
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); } } }
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 } }