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); }
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); }
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); }
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 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"); }
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); }
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"); }
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); }
//---- 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); }
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); }
//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); }
//-- #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); } }
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"); } }
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); }
//---- 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; }
}//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)); }
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); }); }
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; } }
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); } } }
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_ + ")"); } } }
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 } }
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(); }