//---- internal void SdkInit() { bool init = _api.Btsdk_IsSDKInitialized(); bool conn = _api.Btsdk_IsServerConnected(); // Ok to call if '!init'? if (init && conn) { return; } BtSdkError ret = _api.Btsdk_Init(); //Debug.WriteLine("BlueSoleil Btsdk_Init: " + BluesoleilUtils.BtSdkErrorToString(ret)); BluesoleilUtils.CheckAndThrow(ret, "Btsdk_Init"); #if DEBUG // When Radio is Off, Init succeeds when called but IsSDKInitialized // still returns false! That persists until the radio's turned on. bool initAfter = _api.Btsdk_IsSDKInitialized(); bool connAfter = _api.Btsdk_IsServerConnected(); // Ok to call if '!init'? if (!initAfter || !connAfter) { bool ready = _api.Btsdk_IsBluetoothReady(); Debug.Assert(!ready, "Not init&&conn, but NOT ready..."); Debug.Assert(!init, "Not init&&conn, but NOT !init..."); Debug.Assert(conn, "Not init&&conn, but NOT conn..."); } #endif _needsDispose = true; }
//---- internal static BluesoleilDeviceInfo CreateFromGivenAddress(BluetoothAddress addr, BluesoleilFactory factory) { UInt32 hDev; byte[] bd_addr = BluesoleilUtils.FromBluetoothAddress(addr); bool remembered; hDev = factory.Api.Btsdk_GetRemoteDeviceHandle(bd_addr); if (hDev != StackConsts.BTSDK_INVALID_HANDLE) { remembered = true; } else { // Presumably this means that the device isn't known. // Does this add it forever? -- no??? hDev = factory.Api.Btsdk_AddRemoteDevice(bd_addr); if (hDev == StackConsts.BTSDK_INVALID_HANDLE) { BluesoleilUtils.CheckAndThrow(BtSdkError.SDK_UNINIT, "Btsdk_Get/AddRemoteDevice"); } remembered = false; } var result = new BluesoleilDeviceInfo(hDev, factory); result._remembered = remembered; Debug.Assert(addr.Equals(result.DeviceAddress), "Address changed in create! was: " + addr + ", now: " + result.DeviceAddress); return(result); }
internal void CloseAnyLiveConnections() { ICollection <BTCONNHDL> hConnList; lock (_liveConns) { hConnList = _liveConns.Keys; } int count = 0, okCount = 0;; foreach (var hConn in hConnList) { var ret = _api.Btsdk_Disconnect(hConn); Debug.WriteLineIf(ret != BtSdkError.OK, "KillAllConnections: Disconnect: " + BluesoleilUtils.BtSdkErrorToString(ret)); ++count; if (ret == BtSdkError.OK) { ++okCount; } }//for try { Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "BlueSoleil CloseAnyLiveConnections: count: {0}, okCount: {1}", count, okCount)); } catch (ObjectDisposedException) { } }
//---- void ConnectRfcommPreAllocateComPort(UInt16 svcClass16, UInt32 hDev, out UInt32 hConn, out byte channel, out int comPort //, out UInt32 comSerialNum ) { UInt32 comSerialNum; // UInt32 comSerialNum0; BtSdkError ret; UInt32 osComPort; // const UInt32 UsageTypeConst = 1; const StackConsts.COMM_SET flags = StackConsts.COMM_SET.Record | StackConsts.COMM_SET.UsageType; const UInt16 BTSDK_CLS_SERIAL_PORT = 0x1101; const int Timeout = 2200; // comSerialNum0 = _factory.Api.Btsdk_GetASerialNum(); comSerialNum = comSerialNum0; Debug.Assert(comSerialNum != 0, "INFO comSerialNum == 0 wierd maybe???"); bool success = _factory.Api.Btsdk_PlugInVComm(comSerialNum, out osComPort, UsageTypeConst, flags, Timeout); Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Btsdk_GetASerialNum comSerialNum: {0}, Btsdk_PlugInVComm success: {1}, osComPort: {2}", comSerialNum0, success, osComPort)); if (!success) { BluesoleilUtils.CheckAndThrow(BtSdkError.OPERATION_FAILURE, "Btsdk_PlugInVComm"); } comPort = checked ((int)osComPort); ret = _factory.Api.Btsdk_InitCommObj(checked ((byte)osComPort), BTSDK_CLS_SERIAL_PORT); Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Btsdk_InitCommObj ret: {0}", ret)); BluesoleilUtils.CheckAndThrow(ret, "Btsdk_InitCommObj"); // bool connSuccess = false; try { var sppStru = new Structs.BtSdkSPPConnParamStru(osComPort); ret = _factory.Api.Btsdk_ConnectEx(hDev, svcClass16, ref sppStru, out hConn); Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "ret: {0}, hConn: 0x{1:X}", ret, hConn)); BluesoleilUtils.CheckAndThrow(ret, "Btsdk_ConnectEx"); _hDev = hDev; // channel = 0; // unknown Console.WriteLine("Connect remote SPP Service with local COM{0}\n", osComPort); connSuccess = true; } finally { if (!connSuccess) { FreeComIndex(_factory, comPort, comSerialNum0); } } }
//---- private void ConnectRfcomm(BluetoothEndPoint remoteEP, UInt32 hDev, out UInt32 hConn, out byte channel, out int comPort) { Structs.BtSdkAppExtSPPAttrStru sppAttr = new Structs.BtSdkAppExtSPPAttrStru(remoteEP); // Debug.WriteLine("Gonna Btsdk_ConnectAppExtSPPService with: " + sppAttr.ToString()); BtSdkError ret = _factory.Api.Btsdk_ConnectAppExtSPPService(hDev, ref sppAttr, out hConn); Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "ret: {0}, hConn: 0x{1:X}, with: {2}", ret, hConn, sppAttr.ToString())); _hDev = hDev; BluesoleilUtils.CheckAndThrow(ret, "Btsdk_ConnectAppExtSPPService"); // var comNumGetClientPort = _factory.Api.Btsdk_GetClientPort(hConn); Debug.WriteLine("comNumGetClientPort: " + comNumGetClientPort); // if (sppAttr.rf_svr_chnl != 0) { Debug.Assert(sppAttr.com_index != 0, "Argghhhh com_index is zero! (When rf_svr_chnl isn't)."); channel = sppAttr.rf_svr_chnl; comPort = sppAttr.com_index; } else { // Some profiles are handled specifically OBEX, etc etc // so they don't create a COM port when that Debug.Assert(sppAttr.com_index == 0, "Don't expect a COM port to be created in this (fail) case."); // // Connecting to SPP 0x1101 also returns no com port in the // struct but a COM port is connected for it. Btsdk_GetClientPort // DOES return the correct port see whether we're in that case. if (comNumGetClientPort != 0) { comPort = comNumGetClientPort; channel = 0; // Unknown! } else { // Highly likely an OPP/etc connection was made, and not a RFCOMM // connection, and thus no COM port we can use. :-( So fail! Trace.WriteLine(string.Format(CultureInfo.InvariantCulture, "BlueSoleil seems no RFCOMM connection made, closing. (channel: {0}, COM: {1})", sppAttr.rf_svr_chnl, sppAttr.com_index)); // (Note: Add a dummy record so RemoveLiveConnection works ok). int liveCountB = _factory.AddConnection(hConn, NullBluesoleilConnection.Instance); Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "BlueSoleilClient.Connect non-RFCOMM LiveConns count: {0}.", liveCountB)); var retD = _factory.Api.Btsdk_Disconnect(hConn); BluesoleilUtils.Assert(retD, "Close non-RFCOMM connection"); throw BluesoleilUtils.ErrorConnectIsNonRfcomm(); } } //System.Windows.Forms.MessageBox.Show("BlueSoleil created port: '" + comPort + "'."); }
internal BluesoleilRadio(BluesoleilFactory fcty) { _fcty = fcty; _fcty.SdkInit(); BtSdkError retAddr, ret; byte[] bd_addr = new byte[StackConsts.BTSDK_BDADDR_LEN]; ret = retAddr = _fcty.Api.Btsdk_GetLocalDeviceAddress(bd_addr); BluesoleilUtils.Assert(retAddr, "Btsdk_GetLocalDeviceAddress"); if (ret == BtSdkError.OK) { _addr = BluesoleilUtils.ToBluetoothAddress(bd_addr); } else { _addr = BluetoothAddress.None; } // byte[] arr = new byte[500]; UInt16 len = checked ((UInt16)arr.Length); ret = _fcty.Api.Btsdk_GetLocalName(arr, ref len); if (retAddr == BtSdkError.OK) { BluesoleilUtils.Assert(ret, "Btsdk_GetLocalName"); } if (ret == BtSdkError.OK) { _name = BluesoleilUtils.FromNameString(arr, len); } else { _name = string.Empty; } // uint cod; ret = _fcty.Api.Btsdk_GetLocalDeviceClass(out cod); //BluesoleilUtils.CheckAndThrow(ret); if (retAddr == BtSdkError.OK) { Debug.Assert(ret == BtSdkError.OK, "Btsdk_GetLocalDeviceClass ret: " + ret); } _cod = new ClassOfDevice(cod); // _lmp = new Structs.BtSdkLocalLMPInfoStru(HciVersion.Unknown); ret = _fcty.Api.Btsdk_GetLocalLMPInfo(ref _lmp); if (retAddr == BtSdkError.OK) { BluesoleilUtils.Assert(ret, "Btsdk_GetLocalLMPInfo"); } }
internal static void FreeComIndex(BluesoleilFactory factory, int comNum, uint comSerialNum) { Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "BluesoleilClient.FreeComIndex IN: comNum: {0}, comSerialNum: {1}", comNum, comSerialNum)); BtSdkError ret; var comNum8 = checked ((byte)comNum); ret = factory.Api.Btsdk_DeinitCommObj(comNum8); BluesoleilUtils.Assert(ret, "Btsdk_DeinitCommObj"); factory.Api.Btsdk_PlugOutVComm(comSerialNum, StackConsts.COMM_SET.Record); Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "BluesoleilClient.FreeComIndex OUT: Btsdk_DeinitCommObj ret: {0}", ret)); }
internal void Dispose(bool disposing) { if (!_needsDispose) { return; } // CloseAnyLiveConnections(); // _needsDispose = false; BtSdkError ret = _api.Btsdk_Done(); BluesoleilUtils.Assert(ret, "Btsdk_Done"); }
internal void RegisterCallbacksOnce() { if (_inquiryResultIndFunc != null) { return; } BtSdkError ret; Structs.BtSdkCallbackStru val; // _inquiryResultIndFunc = _inquiryHandler.HandleInquiryResultInd; val = new Structs.BtSdkCallbackStru(_inquiryResultIndFunc); Debug.Assert(val._type == StackConsts.CallbackType.INQUIRY_RESULT_IND); ret = Api.Btsdk_RegisterCallback4ThirdParty(ref val); BluesoleilUtils.CheckAndThrow(ret, "Btsdk_RegisterCallback4ThirdParty"); // _inquiryCompleteIndFunc = HandleInquiryComplete; val = new Structs.BtSdkCallbackStru(_inquiryCompleteIndFunc); Debug.Assert(val._type == StackConsts.CallbackType.INQUIRY_COMPLETE_IND); ret = Api.Btsdk_RegisterCallback4ThirdParty(ref val); BluesoleilUtils.CheckAndThrow(ret, "Btsdk_RegisterCallback4ThirdParty"); // //---- _pinReqIndFunc = _sec.HandlePinReqInd; val = new Structs.BtSdkCallbackStru(_pinReqIndFunc); Debug.Assert(val._type == StackConsts.CallbackType.PIN_CODE_IND); ret = Api.Btsdk_RegisterCallback4ThirdParty(ref val); BluesoleilUtils.CheckAndThrow(ret, "Btsdk_RegisterCallback4ThirdParty"); // //---- _connectionEventIndFunc = _records.HandleConnectionEventInd; val = new Structs.BtSdkCallbackStru(_connectionEventIndFunc); Debug.Assert(val._type == StackConsts.CallbackType.CONNECTION_EVENT_IND); ret = Api.Btsdk_RegisterCallback4ThirdParty(ref val); BluesoleilUtils.CheckAndThrow(ret, "Btsdk_RegisterCallback4ThirdParty"); // _statusCallback = HandleReceiveBluetoothStatusInfo; ret = Api.Btsdk_RegisterGetStatusInfoCB4ThirdParty(ref _statusCallback); BluesoleilUtils.CheckAndThrow(ret, "Btsdk_RegisterGetStatusInfoCB4ThirdParty"); ret = Api.Btsdk_SetStatusInfoFlag(StackConsts.BTSDK_BLUETOOTH_STATUS_FLAG); BluesoleilUtils.CheckAndThrow(ret, "Btsdk_SetStatusInfoFlag"); }
internal IAsyncResult BeginInquiry(int maxDevices, TimeSpan inquiryLength, AsyncCallback callback, object state, BluetoothClient.LiveDiscoveryCallback liveDiscoHandler, object liveDiscoState, DiscoDevsParams args) { _fcty.SdkInit(); _fcty.RegisterCallbacksOnce(); // byte maxDurations; byte maxNum; CommonDiscoveryBluetoothClient.ConvertBthInquiryParams(maxDevices, inquiryLength, out maxNum, out maxDurations); return(BeginInquiry(maxDevices, inquiryLength, callback, state, liveDiscoHandler, liveDiscoState, delegate() { BtSdkError ret = _fcty.Api.Btsdk_StartDeviceDiscovery( AnyClass, maxNum, maxDurations); BluesoleilUtils.CheckAndThrow(ret, "Btsdk_StartDeviceDiscovery"); }, args)); }
void GetInfo(ref BluetoothAddress addr) { BtSdkError ret; var props = new Structs.BtSdkRemoteDevicePropertyStru(); ret = _factory.Api.Btsdk_GetRemoteDeviceProperty(_hDev, out props); BluesoleilUtils.CheckAndThrow(ret, "Btsdk_GetRemoteDeviceProperty"); // if ((props.mask & Structs.BtSdkRemoteDevicePropertyStru.Mask.Handle) != 0) { Debug.Assert(_hDev == props.dev_hdl, "hDev"); } else { Debug.Fail("Handle unknown?!?"); } if ((props.mask & Structs.BtSdkRemoteDevicePropertyStru.Mask.Address) != 0) { addr = BluesoleilUtils.ToBluetoothAddress(props.bd_addr); } if ((props.mask & Structs.BtSdkRemoteDevicePropertyStru.Mask.Class) != 0) { _cod = new ClassOfDevice(props.dev_class); } if ((props.mask & Structs.BtSdkRemoteDevicePropertyStru.Mask.Name) != 0) { Debug.Assert(props.name.Length == StackConsts.BTSDK_DEVNAME_LEN, "props.name.Length: " + props.name.Length + ", BTSDK_DEVNAME_LEN: " + StackConsts.BTSDK_DEVNAME_LEN); string name = BluesoleilUtils.FromNameString(props.name); _cachedName = name; } if ((props.mask & Structs.BtSdkRemoteDevicePropertyStru.Mask.LmpInfo) != 0) { var fs = (LmpFeatures)BitConverter.ToInt64(props.lmp_info.lmp_feature, 0); var v = new RadioVersions(props.lmp_info.lmp_version, props.lmp_info.lmp_subversion, fs, props.lmp_info.manuf_name); _versions = v; } //props. }
public void SetMode(bool?connectable, bool?discoverable) { BtSdkError ret; ret = _fcty.Api.Btsdk_StartBluetooth(); BluesoleilUtils.Assert(ret, "Radio.set_Mode Start"); StackConsts.DiscoveryMode mask; // Always need to get, to get pairable etc. ret = _fcty.Api.Btsdk_GetDiscoveryMode(out mask); BluesoleilUtils.Assert(ret, "Radio.set_Mode Get"); if (ret != BtSdkError.OK) { mask = StackConsts.BTSDK_DISCOVERY_DEFAULT_MODE; } // switch (connectable) { case true: mask |= StackConsts.DiscoveryMode.BTSDK_CONNECTABLE; break; case false: mask &= ~StackConsts.DiscoveryMode.BTSDK_CONNECTABLE; break; // null NOP } switch (discoverable) { case true: mask |= StackConsts.DiscoveryMode.BTSDK_GENERAL_DISCOVERABLE; break; case false: mask &= ~StackConsts.DiscoveryMode.BTSDK_GENERAL_DISCOVERABLE; break; // null NOP } ret = _fcty.Api.Btsdk_SetDiscoveryMode(mask); BluesoleilUtils.Assert(ret, "Radio.set_Mode Set"); }
private static string ParseServiceName(ref Structs.BtSdkRemoteServiceAttrStru attrs) { string nameUtf8 = BluesoleilUtils.FixedLengthArrayToStringUtf8(attrs.svc_name); string nameUL = Encoding.Unicode.GetString(attrs.svc_name); nameUL = nameUL.Trim('\0'); #if DEBUG string nameUB = Encoding.BigEndianUnicode.GetString(attrs.svc_name); nameUB = nameUB.Trim('\0'); Debug.Assert(nameUL.Length == nameUB.Length, "Our simple check of length doesn't work for Unicode little-endian vs big-endian, the lengths are the same." + " BUT different here!! nameUL.Length: " + nameUL.Length + ", nameUB.Length: " + nameUB.Length); #endif // string name = nameUtf8; if (nameUL.Length > name.Length) { name = nameUL; } // As described in DEBUG above, can't do this!! if (nameUB.Length > name.Length) name = nameUB; return(name); }
public ServiceRecord[] GetServiceRecords(Guid service) { BtSdkError ret; var search = new Structs.BtSdkSDPSearchPatternStru[1]; search[0] = new Structs.BtSdkSDPSearchPatternStru(service); UInt32[] recordHandles = new uint[MaxServiceRecordsLookup]; int num = recordHandles.Length; // Fetch the matching records (the handles of). int numSearch = search.Length; ret = _factory.Api.Btsdk_BrowseRemoteServicesEx(_hDev, search, numSearch, recordHandles, ref num); if (ret == BtSdkError.NO_SERVICE) // None { return(new ServiceRecord[0]); } BluesoleilUtils.CheckAndThrow(ret, "Btsdk_BrowseRemoteServicesEx"); // Fetch the records' attributes and convert to our format. var results = new List <ServiceRecord>(); for (int i = 0; i < num; ++i) { var hRcd = recordHandles[i]; var attrs = new Structs.BtSdkRemoteServiceAttrStru( StackConsts.AttributeLookup.ServiceName | StackConsts.AttributeLookup.ExtAttributes); // Use 'Get' here and not 'Refresh' as the 'Browse' call above // should have retrieved the attributes. ret = _factory.Api.Btsdk_GetRemoteServiceAttributes(hRcd, ref attrs); BluesoleilUtils.CheckAndThrow(ret, "Btsdk_RefreshRemoteServiceAttributes"); Debug.Assert(attrs.dev_hdl == _hDev); // IBluesoleilApi hackApi = _factory.Api; ServiceRecord sr = CreateServiceRecord(ref attrs, hackApi); results.Add(sr); } return(results.ToArray()); }
private BluesoleilDeviceInfo(UInt32 hDev, BluesoleilFactory factory) { if (factory == null) { throw new ArgumentNullException("factory"); } _factory = factory; BtSdkError ret; _hDev = hDev; // byte[] bd_addr = new byte[StackConsts.BTSDK_BDADDR_LEN]; ret = factory.Api.Btsdk_GetRemoteDeviceAddress(_hDev, bd_addr); BluesoleilUtils.CheckAndThrow(ret, "Btsdk_GetRemoteDeviceAddress"); if (ret != BtSdkError.OK) // Not known/present(?). { return; } _addr = BluesoleilUtils.ToBluetoothAddress(bd_addr); // uint cod; ret = factory.Api.Btsdk_GetRemoteDeviceClass(_hDev, out cod); if (ret != BtSdkError.OK) // Not known/present(?). { return; } _cod = new ClassOfDevice(cod); // ret = _factory.Api.Btsdk_IsDevicePaired(_hDev, out _paired); Debug.Assert(ret == BtSdkError.OK, "Btsdk_IsDevicePaired ret: " + ret); // _connected = _factory.Api.Btsdk_IsDeviceConnected(_hDev); // GetInfo(ref _addr); }
internal static ServiceRecord CreateServiceRecord(ref Structs.BtSdkRemoteServiceAttrStru attrs, IBluesoleilApi api) { ServiceRecordBuilder bldr = new ServiceRecordBuilder(); //-- Guid sc = BluetoothService.CreateBluetoothUuid(attrs.svc_class); bldr.AddServiceClass(sc); //-- string name = ParseServiceName(ref attrs); if (name.Length != 0) { bldr.ServiceName = name; } // byte?port = null; var extras = new List <ServiceAttribute>(); Debug.Assert(attrs.status == 0, "attrs.status: 0x" + attrs.status.ToString("X")); if (attrs.ext_attributes != IntPtr.Zero) { if (sc == BluetoothService.HumanInterfaceDevice) { var hidInfo = (Structs.BtSdkRmtHidSvcExtAttrStru_HACK)Marshal.PtrToStructure( attrs.ext_attributes, typeof(Structs.BtSdkRmtHidSvcExtAttrStru_HACK)); Debug.Assert(Marshal.SizeOf(typeof(Structs.BtSdkRmtHidSvcExtAttrStru_HACK)) == Marshal.SizeOf(hidInfo), "SizeOf x2"); Debug.Assert(hidInfo.size == Marshal.SizeOf(typeof(Structs.BtSdkRmtHidSvcExtAttrStru_HACK)) + Structs.BtSdkRmtHidSvcExtAttrStru_HACK.StackMiscountsPaddingSize, "Different sizes! hidInfo.size: " + hidInfo.size + ", SizeOf(): " + Marshal.SizeOf(typeof(Structs.BtSdkRmtHidSvcExtAttrStru_HACK))); // TO-DO Human Interface (HID) record: Use "mask" field, it's undocumented, check for real life values // With test SdpCreateAHumanInputDeviceRecordsAllTwoOfThree // which adds two out of three of {DeviceReleaseNumber,DeviceSubclass,CountryCode} // mask==0. So mask apparently applies to other fields! // So we check these three values for zero // and discard them if so! Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "HID.mask: {0:X}", hidInfo.mask)); var list = new List <ServiceAttribute>(); if (hidInfo.deviceReleaseNumber != 0) { list.Add( new ServiceAttribute(HidProfileAttributeId.DeviceReleaseNumber, new ServiceElement(ElementType.UInt16, hidInfo.deviceReleaseNumber))); } if (hidInfo.deviceSubclass != 0) { list.Add( new ServiceAttribute(HidProfileAttributeId.DeviceSubclass, new ServiceElement(ElementType.UInt8, hidInfo.deviceSubclass))); } if (hidInfo.countryCode != 0) { list.Add( new ServiceAttribute(HidProfileAttributeId.CountryCode, new ServiceElement(ElementType.UInt8, hidInfo.countryCode))); } // TO-DO HID other... extras.AddRange(list); } else if (sc == BluetoothService.PnPInformation) { var deviceInfo = (Structs.BtSdkRmtDISvcExtAttrStru)Marshal.PtrToStructure( attrs.ext_attributes, typeof(Structs.BtSdkRmtDISvcExtAttrStru)); Debug.Assert(Marshal.SizeOf(typeof(Structs.BtSdkRmtDISvcExtAttrStru)) == Marshal.SizeOf(deviceInfo), "SizeOf x2"); Debug.Assert(deviceInfo.size == Marshal.SizeOf(typeof(Structs.BtSdkRmtDISvcExtAttrStru)) + Structs.BtSdkRmtDISvcExtAttrStru.StackMiscountsPaddingSize, "Different sizes! deviceInfo.size: " + deviceInfo.size + ", Marshal.SizeOf: " + Marshal.SizeOf(typeof(Structs.BtSdkRmtDISvcExtAttrStru))); // TO-DO Device Info (PnP) record: Use "mask" field, it's undocumented, check for real life values //Debug.Assert(deviceInfo.mask == 0, "Is mask field in BtSdkRmtDISvcExtAttrStru ever set!!!, is here:" + deviceInfo.mask); Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "PnP/DI.mask: {0:X}", deviceInfo.mask)); // Like above (PnP) we see mask==0 for the fields we handle // here (six of). So we check these values // for zero and discard them if so! var list = new List <ServiceAttribute>(); if (deviceInfo.spec_id != 0) { list.Add( new ServiceAttribute(DeviceIdProfileAttributeId.SpecificationId, new ServiceElement(ElementType.UInt16, deviceInfo.spec_id))); } if (deviceInfo.vendor_id != 0) { list.Add( new ServiceAttribute(DeviceIdProfileAttributeId.VendorId, new ServiceElement(ElementType.UInt16, deviceInfo.vendor_id))); } if (deviceInfo.product_id != 0) { list.Add( new ServiceAttribute(DeviceIdProfileAttributeId.ProductId, new ServiceElement(ElementType.UInt16, deviceInfo.product_id))); } if (deviceInfo.version != 0) { list.Add( new ServiceAttribute(DeviceIdProfileAttributeId.Version, new ServiceElement(ElementType.UInt16, deviceInfo.version))); } if (true /* Zero means False here!! */) { list.Add( new ServiceAttribute(DeviceIdProfileAttributeId.PrimaryRecord, new ServiceElement(ElementType.Boolean, deviceInfo.primary_record))); } if (deviceInfo.vendor_id_source != 0) { list.Add( new ServiceAttribute(DeviceIdProfileAttributeId.VendorIdSource, new ServiceElement(ElementType.UInt16, deviceInfo.vendor_id_source))); } // TO-DO URLs... extras.AddRange(list); } else { // On testing we see this never working! For one device // with an ImagingResponder record the size of 0x18 and // not 0x8 as per definition, and the port value is wrong. // And for its PhonebookAccessPse record the size is // correctly 0x8, but again the port value is wrong! // var sppInfo = (Structs.BtSdkRmtSPPSvcExtAttrStru)Marshal.PtrToStructure( attrs.ext_attributes, typeof(Structs.BtSdkRmtSPPSvcExtAttrStru)); Debug.Assert(sppInfo.size == Marshal.SizeOf(typeof(Structs.BtSdkRmtSPPSvcExtAttrStru)), "Different sizes!"); port = sppInfo.server_channel; } api.Btsdk_FreeMemory(attrs.ext_attributes); }//if (attrs.ext_attributes != NULL) // Use a different API to try and get the RFCOMM port number as // the previous API is quite rubbish at doing that!! var svcB = new Structs.BtSdkAppExtSPPAttrStru(sc); var retSpp = api.Btsdk_SearchAppExtSPPService(attrs.dev_hdl, ref svcB); if (retSpp == BtSdkError.NO_SERVICE) // error { } else if (retSpp != BtSdkError.OK) // error { Debug.WriteLine("GetSvcRcds Btsdk_SearchAppExtSPPService ret: " + BluesoleilUtils.BtSdkErrorToString(retSpp)); } else // success { if (svcB.rf_svr_chnl != 0) { byte newPort = svcB.rf_svr_chnl; if (port.HasValue) { Debug.Assert(port.Value == newPort, "port: " + port.Value + ", newPort: " + newPort); } else { port = newPort; } } if (svcB.sdp_record_handle != 0) { bldr.AddCustomAttribute(new ServiceAttribute( UniversalAttributeId.ServiceRecordHandle, ServiceElement.CreateNumericalServiceElement(ElementType.UInt32, svcB.sdp_record_handle))); } #if DEBUG Debug.Assert(svcB.service_class_128 == sc, "svcSpp.service_class_128: " + svcB.service_class_128 + ", sc: " + sc); var snSpp = BluesoleilUtils.FromNameString(svcB.svc_name, StackConsts.BTSDK_SERVICENAME_MAXLENGTH); if (snSpp == null) { Debug.Assert(name == null || name.Length == 0, "svcSpp.svc_name: null" + ", name: " + name); } else if (snSpp.Length == 1) { // SearchAppExtSPPService doesn't handle Unicode // but Btsdk_BrowseRemoteServicesEx etc does. Debug.Assert(snSpp[0] == name[0], "svcSpp.svc_name: " + snSpp + ", name: " + name); } else { Debug.Assert(snSpp == name, "svcSpp.svc_name: " + snSpp + ", bldr.ServiceName: " + name); } #endif } // if (port.HasValue) { } else { bldr.ProtocolType = BluetoothProtocolDescriptorType.None; } if (extras.Count != 0) { bldr.AddCustomAttributes(extras); } // const ServiceAttributeId FakeDescr = (ServiceAttributeId)(-1); bldr.AddCustomAttribute(new ServiceAttribute(FakeDescr, new ServiceElement(ElementType.TextString, "<partial BlueSoleil decode>"))); ServiceRecord sr = bldr.ServiceRecord; if (port.HasValue) { Debug.Assert(bldr.ProtocolType == BluetoothProtocolDescriptorType.Rfcomm, "type=" + bldr.ProtocolType); ServiceRecordHelper.SetRfcommChannelNumber(sr, port.Value); } else { bldr.ProtocolType = BluetoothProtocolDescriptorType.None; } return(sr); }