//---- 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 static extern BtSdkError Btsdk_ConnectAppExtSPPService(BTDEVHDL dev_hdl, ref Structs.BtSdkAppExtSPPAttrStru psvc, out BTCONNHDL conn_hdl);
internal static extern BtSdkError Btsdk_SearchAppExtSPPService(BTDEVHDL dev_hdl, ref Structs.BtSdkAppExtSPPAttrStru psvc);
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); }
BtSdkError IBluesoleilApi.Btsdk_ConnectAppExtSPPService(uint dev_hdl, ref Structs.BtSdkAppExtSPPAttrStru psvc, out uint conn_hdl) { return(NativeMethods.Btsdk_ConnectAppExtSPPService(dev_hdl, ref psvc, out conn_hdl)); }
//byte Btsdk_GetAvailableExtSPPCOMPort([MarshalAs(UnmanagedType.U1)] bool bIsForLocalSPPService); BtSdkError IBluesoleilApi.Btsdk_SearchAppExtSPPService(BTDEVHDL dev_hdl, ref Structs.BtSdkAppExtSPPAttrStru psvc) { return(NativeMethods.Btsdk_SearchAppExtSPPService(dev_hdl, ref psvc)); }