// //- #define RADIO_MODESSS // using System; using System.Collections.Generic; using System.Text; using System.IO; using InTheHand.Net.Sockets; using InTheHand.Net.Bluetooth; using InTheHand.Net; using System.Threading; using System.Diagnostics; using Console = System.ValueType; // Block the use of Console, must use "console". using System.Reflection; using InTheHand.Net.Bluetooth.AttributeIds; using System.Runtime.InteropServices; using Microsoft.Win32; using System.Globalization; using System.Net; using System.ComponentModel; #if !ANDROID using System.IO.Ports; #endif using InTheHand.Net.Bluetooth.Factory; namespace ConsoleMenuTesting { partial class BluetoothTesting { public MenuSystem console; //HACK public MenuSystem console; Stream _peer; public BluetoothTesting() { } //---- WeakReferenceT _cli; class WeakReferenceT : WeakReference { public WeakReferenceT(T target) : base(target) { } public new T Target { get { return (T)base.Target; } set { base.Target = value; } } } //-------- #if false && ANDROID [MenuItem, SubMenu("PLAYING")] public void CheckAndroidNetworkStream() { var tmp = new MemoryStream(); var ns = new InTheHand.Net.Bluetooth.Droid.AndroidBthClient.AndroidNetworkStream(tmp); console.WriteLine("Done create AndroidNetworkStream."); ns.WriteByte(11); console.WriteLine("Done write to AndroidNetworkStream."); ns.Position = 0; var bi = ns.ReadByte(); console.WriteLine("Done read from AndroidNetworkStream."); } #endif #if true || DEBUG [MenuItem, SubMenu("TEST")] public void TestPause() { console.WriteLine("1111"); console.WriteLine("2222"); console.WriteLine("3333"); console.WriteLine("4444"); console.WriteLine("55555"); console.WriteLine("Before Pause"); console.Pause("Message"); console.WriteLine("After Pause"); } [MenuItem, SubMenu("TEST")] public void TestReadLine() { var i = console.ReadLine("foo\r\nbar"); if (i == null) { console.WriteLine("you input: "); } else { console.WriteLine("you input: [[{0}]], len: {1}", i, i.Length); } } [MenuItem, SubMenu("TEST")] public void TestReadBluetoothAddress() { var a = console.ReadBluetoothAddress("foo\r\nbar"); if (a == null) { console.WriteLine("you input: "); } else { console.WriteLine("you input: [[{0}]]", a); } } [MenuItem, SubMenu("TEST")] public void TestReadOptionalBluetoothAddress() { var a = console.ReadOptionalBluetoothAddress("foo\r\nbar"); if (a == null) { console.WriteLine("you input: "); } else { console.WriteLine("you input: [[{0}]]", a); } } [MenuItem, SubMenu("TEST")] public void TestReadOptionalInteger() { var i = console.ReadOptionalInteger("foobar"); if (i == null) { console.WriteLine("you input: "); } else { console.WriteLine("you input: [[{0}]]", i.Value); } } [MenuItem, SubMenu("TEST")] public void TestReadYesNo() { bool i = console.ReadYesNo("foobarYN (default: true)", true); console.WriteLine("you input: {0}", i); i = console.ReadYesNo("foobarYN (default: false)", false); console.WriteLine("you input: {0}", i); } [MenuItem, SubMenu("TEST")] public void TestReadYesNoCancel() { bool? i = console.ReadYesNoCancel("foobarYNC (default: true)", true); console.WriteLine("you input: {0}", i); i = console.ReadYesNoCancel("foobarYNC (default: false)", false); console.WriteLine("you input: {0}", i); i = console.ReadYesNoCancel("foobarYNC (default: cancel)", null); console.WriteLine("you input: {0}", i); } [MenuItem, SubMenu("TEST")] public void TestGetFilename() { var a = console.GetFilename(); if (a == null) { console.WriteLine("you input: "); } else { console.WriteLine("you input: [[{0}]]", a); } } #endif [MenuItem, SubMenu("Playing")] public void DoBthReadRemoteVersion() { var addr = console.ReadBluetoothAddress("remote"); var ba = addr.ToByteArray(); // byte lmpVersion; ushort lmpSubVersion, manuf0; byte[] lmpFeatures = new byte[20]; int ret = BthReadRemoteVersion(ba, out lmpVersion, out lmpSubVersion, out manuf0, lmpFeatures); console.WriteLine("ret: {0}=0x{0:X}", ret); var manuf = (Manufacturer)manuf0; console.WriteLine("lmpVersion: {0}, lmpSubVersion: {1}," + " manuf {2} {3}, lmpFeatures[0]: 0x{4:X}", lmpVersion, lmpSubVersion, manuf, manuf, lmpFeatures[0]); } private const string btdrtDll = "btdrt.dll"; [DllImport(btdrtDll, SetLastError = true)] public static extern int BthReadRemoteVersion(byte[] pba, out byte plmp_version, out ushort plmp_subversion, out ushort pmanufacturer, byte[] plmp_features); [MenuItem, SubMenu("BtLsnr")] public void SomeCustomUuids() { var list = new Guid[] { new Guid("{7630F141-6361-4e60-A8EE-237180DA9CE8}"), new Guid("{C7CB927D-8DBE-44f2-B671-3DF8D50C4E2F}"), new Guid("{59438E67-6094-4bbc-B500-511DE96BB535}"), new Guid("{C50AFF29-3C38-4fb7-AB32-D541AD835C34}"), }; foreach (var g in list) { console.WriteLine(g); } } //[MenuItem, SubMenu("TEST")] //TODO public void ExceptionNative() //{ // IntPtr p = new IntPtr(1); // var o = Marshal.PtrToStructure(p, typeof(Int64)); //} [MenuItem, SubMenu("TEST")] public void ExceptionManaged() { if (!console.ReadYesNo("Throw exception", false)) return; throw new RankException("test"); } [MenuItem, SubMenu("TEST")] public void ExceptionManagedOnDelegateAsyncInvoke() { Action dlgt = delegate(Version fake) { console.WriteLine("(Thread gonna throw...)"); throw new RankException("test"); }; if (!console.ReadYesNo("Throw exception", false)) return; var ar = DelegateExtension.BeginInvoke(dlgt, null, null, null); DelegateExtension.EndInvoke(dlgt, ar); } //---- [MenuItem, SubMenu("Playing")] public void Base64Decode() { string s = console.ReadLine("Base64 string"); console.WriteLine("Input Base64 string: '{0}'", s); byte[] arr = Convert.FromBase64String(s); var asStr = GetEncoding_forHTC().GetString(arr, 0, Math.Min(20, arr.Length)); console.WriteLine("asStr: '{0}'", asStr); } private static Encoding GetEncoding_forHTC() { var enc = (Encoding)Encoding.ASCII.Clone(); #if !NETCF enc.DecoderFallback = new System.Text.DecoderReplacementFallback("."); enc.EncoderFallback = new System.Text.EncoderReplacementFallback("."); #endif return enc; } [MenuItem, SubMenu("Playing")] public void Base64Encode() { string s = console.ReadLine("Input String"); console.WriteLine("Input string: '{0}'", s); var arr = GetEncoding_forHTC().GetBytes(s); var b64str = Convert.ToBase64String(arr); console.WriteLine("b64str: '{0}'", b64str); } //---- [MenuItem, SubMenu("Device Discovery")] public void Ebap_NotImplHandlers() { var bco2 = new BluetoothComponent(); bco2.DiscoverDevicesComplete += new EventHandler(bco2_DiscoverDevicesComplete); bco2.DiscoverDevicesProgress += new EventHandler(bco2_DiscoverDevicesProgress); bco2.DiscoverDevicesAsync(255, true, true, true, false, null); } void bco2_DiscoverDevicesProgress(object sender, DiscoverDevicesEventArgs e) { throw new NotImplementedException(); } void bco2_DiscoverDevicesComplete(object sender, DiscoverDevicesEventArgs e) { throw new NotImplementedException(); } [MenuItem, SubMenu("Device Discovery")] public void _EbapAsyncDiscoDevices() { bool discoOnly, auth, rembd, unk; GetDiscoveryFlags(console, out discoOnly, out auth, out rembd, out unk); // var cli = Create_BluetoothClient(); //cli.InquiryLength = TimeSpan.FromMinutes(1); BluetoothComponent bco = new BluetoothComponent(cli); #if NETCF //bco.SetSynchronizeInvoke((System.Windows.Forms.Control)console.InvokeeControl); #endif bco.DiscoverDevicesProgress += _DiscoDevicesAsync_ProgressCallback; bco.DiscoverDevicesComplete += _DiscoDevicesAsync_CompleteCallback; EventHandler startAction = delegate { bco.DiscoverDevicesAsync(255, auth, rembd, unk, discoOnly, 99); }; bool startOnUi = console.ReadYesNo("Start from UI thread", true); if (startOnUi) { console.UiInvoke(startAction); } else { startAction(null, EventArgs.Empty); } console.WriteLine("Started at {0} (UTC {1}).", GetTimeWallclockHR(), DateTime.UtcNow.ToLongTimeString()); console.Pause("After completion un-pause to continue"); } void _DiscoDevicesAsync_CompleteCallback(object sender, DiscoverDevicesEventArgs e) { Debug.Assert((int)e.UserState == 99); CheckSyncCtx(); console.WriteLine("At {0} {1}, ", GetTimeWallclockHR(), "Complete"); if (WriteAsyncCompletedState("DiscoDevicesAsync", e)) { console.WriteLine("DiscoDevicesAsync found {0} devices.", e.Devices.Length); _DiscoDevicesAsync_ShowDevices(e); } console.WriteLine("Complete."); } void _DiscoDevicesAsync_ProgressCallback(object sender, DiscoverDevicesEventArgs e) { var nowUtc = DateTime.UtcNow; Debug.Assert((int)e.UserState == 99); CheckSyncCtx(); console.WriteLine("At {0}, {1}, {2} devices:", GetTimeWallclockHR(), "async progress", e.Devices.Length); _DiscoDevicesAsync_ShowDevices(e); } private void _DiscoDevicesAsync_ShowDevices(DiscoverDevicesEventArgs e) { foreach (var dev in e.Devices) { console.WriteLine("* {0} {1}, last seen: {2}", dev.DeviceAddress, ToStringQuotedOrNull(dev.DeviceName), dev.LastSeen == DateTime.MinValue ? "NEVER" : dev.LastSeen.ToString("o")); } } private bool WriteAsyncCompletedState(string name, AsyncCompletedEventArgs e) { if (e.Cancelled) { console.WriteLine("Cancelled: " + name); } else if (e.Error != null) { console.WriteLine("Error in: " + name + ", error: {0}.", Exception_FirstLine(e.Error)); } else { console.WriteLine("Successful Completion of: " + name); return true; } return false; } private void CheckSyncCtx() { bool? bad = console.InvokeRequired; if (bad == true) { console.WriteLine("Event not called on the UI thread!!!!"); } } //-------- BluetoothRadio m_factoryRadio; BluetoothPublicFactory m_factory; // TODO Should BluetoothPublicFactory have a Primary/AllRadios property? /// /// --can return null-- /// /// BluetoothRadio Get_BluetoothRadio() { if (m_factory == null) return BluetoothRadio.GetPrimaryRadio(); BluetoothRadio radio = m_factoryRadio; if (radio == null) throw new InvalidOperationException("No active radios."); //ClassOfDevice checkNonNull = radio.ClassOfDevice; return radio; } BluetoothDeviceInfo Create_BluetoothDeviceInfo(BluetoothAddress addr) { if (m_factory == null) return new BluetoothDeviceInfo(addr); return m_factory.CreateBluetoothDeviceInfo(addr); } BluetoothClient Create_BluetoothClient() { if (m_factory == null) return new BluetoothClient(); return m_factory.CreateBluetoothClient(); } private BluetoothClient Create_BluetoothClient(BluetoothEndPoint localEndPoint) { if (m_factory == null) return new BluetoothClient(localEndPoint); return m_factory.CreateBluetoothClient(localEndPoint); } BluetoothListener Create_BluetoothListener(Guid svc) { if (m_factory == null) return new BluetoothListener(svc); return m_factory.CreateBluetoothListener(svc); } BluetoothListener Create_BluetoothListener(Guid svc, ServiceRecord record) { if (m_factory == null) return new BluetoothListener(svc, record); return m_factory.CreateBluetoothListener(svc, record); } BluetoothListener Create_BluetoothListener(BluetoothEndPoint ep) { if (m_factory == null) return new BluetoothListener(ep); return m_factory.CreateBluetoothListener(ep); } BluetoothListener Create_BluetoothListener(BluetoothEndPoint ep, ServiceRecord record) { if (m_factory == null) return new BluetoothListener(ep, record); return m_factory.CreateBluetoothListener(ep, record); } ObexWebRequest Create_ObexWebRequest(Uri requestUri) { if (m_factory == null) return new ObexWebRequest(requestUri); return m_factory.CreateObexWebRequest(requestUri); } ObexWebRequest Create_ObexWebRequest(string scheme, BluetoothAddress target, string path) { if (m_factory == null) return new ObexWebRequest(target, path); return m_factory.CreateObexWebRequest(scheme, target, path); } ObexListener Create_ObexListener_Bluetooth() { if (m_factory == null) return new ObexListener(ObexTransport.Bluetooth); return m_factory.CreateObexListener(); } #if !ANDROID L2CapListener Create_L2CapListener(Guid svc) { //if (m_factory == null) return new L2CapListener(svc); //return m_factory.CreateL2CapListener(svc); } private L2CapListener Create_L2CapListener(BluetoothEndPoint localEndPoint) { //if (m_factory == null) return new L2CapListener(localEndPoint); //return m_factory.CreateL2CapListener(localEndPoint); } #endif [MenuItem] public void SetStack_Factory() { BluetoothRadio[] list = BluetoothRadio_GetAllAndDump(); if (list.Length == 0) { console.WriteLine("No radios found!"); m_factory = null; m_factoryRadio = null; } int? choice; do { choice = console.ReadOptionalInteger(string.Format("Which stack for factory (1-{0}), 0 for \"new\"-direct", list.Length)); if (choice == null) choice = 0; } while (choice < 0 || choice > list.Length); if (choice == 0) { m_factory = null; m_factoryRadio = null; console.WriteLine("Selected #{0} 'new-direct'.", choice); } else { m_factoryRadio = list[choice.Value - 1]; m_factory = m_factoryRadio.StackFactory; console.WriteLine("Selected #{0}, stack: '{1}' address: {2}.", choice, m_factoryRadio.SoftwareManufacturer, m_factoryRadio.LocalAddress); } } //-------- private string GetTimeWallclockHR() { return DateTime.Now.TimeOfDay.ToString(); } private string GetTime() { return Environment.TickCount.ToString(); } void ErrorFromMiscCallback(IAsyncResult ar) { MiscCallback(ar); throw new RankException(); } void MiscCallback(IAsyncResult ar) { console.WriteLine("{1}: Callback called for \"{0}\"", ar.AsyncState, GetTime()); } void EmptyCallback(IAsyncResult ar) { if (ar.CompletedSynchronously) { } else { } } bool VerifyConnectionWrite() { if (_peer == null) { console.WriteLine("No connection!"); return false; } if (!_peer.CanWrite) { if (!console.ReadYesNo("NOT CanWrite, do operation anyway", false)) return false; } return true; } bool VerifyConnectionRead() { if (_peer == null) { console.WriteLine("No connection!"); return false; } if (!_peer.CanRead) { if (!console.ReadYesNo("NOT CanRead, do operation anyway", false)) return false; } return true; } //-------- [MenuItem, SubMenu("Data")] public void PrintStreamState() { if (_peer == null) { console.WriteLine("Stream is null."); } else { console.WriteLine("Stream has CanRead: {0}, CanWrite: {1}.", _peer.CanRead, _peer.CanWrite); } if (_cli == null) { console.WriteLine("BtClient is null."); } else { var cli = _cli.Target; if (cli == null) { console.WriteLine("BtClient has been GC'd away."); } else { console.WriteLine("BtClient has Connected: {0}.", cli.Connected); } } } [MenuItem, SubMenu("Data")] public void CloseStream() { if (_peer != null) { _peer.Close(); _peer = null; } } [MenuItem, SubMenu("Data")] public void CloseStream_ButDontNullIt() { if (_peer != null) { _peer.Close(); } } [MenuItem, SubMenu("Data")] public void NullStreamAndClient() { _peer = null; _cli = null; } [MenuItem, SubMenu("Data")] public void CloseClientIfExists() { if (_cli != null) { BluetoothClient cli = _cli.Target; if (cli != null) { cli.Close(); _cli = null; } else { console.WriteLine("The reference has been GC'd."); } } } private BluetoothListener ListenInit() { Guid svcClass = BluetoothService.Wap; console.WriteLine("Default UUID : {0}", svcClass); Guid? inputGuid = console.ReadOptionalBluetoothUuid("UUID", svcClass); if (inputGuid.HasValue) svcClass = inputGuid.Value; int? port = console.ReadOptionalInteger("Port number"); bool auth = console.ReadYesNo("Authenticate", false); bool encpt = console.ReadYesNo("Encrypt", false); bool setPin1, setPin2; string passcode; BluetoothAddress pinAddr; PromptForSetPin(console, out setPin1, out setPin2, out passcode, out pinAddr); string svcName = console.ReadLine("Service Name (optional)"); if (svcName != null && svcName.Length == 0) svcName = null; // BluetoothEndPoint lep; if (port == null) lep = new BluetoothEndPoint(BluetoothAddress.None, svcClass); else lep = new BluetoothEndPoint(BluetoothAddress.None, svcClass, port.Value); console.WriteLine("Going to listen on: {0}:{1}:{2}; auth: {3}, encrypt: {4}.", lep.Address, lep.Service, lep.Port, auth, encpt); // ServiceRecord sr = null; if (lep.Service == BluetoothService.DialupNetworking) { var bldr = new ServiceRecordBuilder(); bldr.AddServiceClass(lep.Service); bldr.AddServiceClass(BluetoothService.GenericNetworking); bldr.AddBluetoothProfileDescriptor(lep.Service, 1, 0); sr = bldr.ServiceRecord; console.WriteLine("Adding custom record: " + ServiceRecordUtilities.Dump(sr)); } BluetoothListener lsnr; if (sr == null) { lsnr = Create_BluetoothListener(lep); } else { lsnr = Create_BluetoothListener(lep, sr); } if (svcName != null) lsnr.ServiceName = svcName; // Assume false by default, so if NotImpl fails only if user says true. if (auth) lsnr.Authenticate = true; if (encpt) lsnr.Encrypt = true; if (setPin1) { Debug.Assert(pinAddr == null, "pinAddr == null"); //lsnr.SetPin(passcode); console.WriteLine("Soooorrrrry we don't support SetPin(String) on listener!!!!"); throw new NotSupportedException("MenuTesting"); } else if (setPin2) { Debug.Assert(pinAddr != null, "pinAddr != null"); lsnr.SetPin(pinAddr, passcode); } console.WriteLine("Starting Listener..."); lsnr.Start(); BluetoothEndPoint lepLsnr = (BluetoothEndPoint)lsnr.LocalEndPoint; console.WriteLine("Listening on endpoint: {0}", lepLsnr); return lsnr; } //[MenuItem, SubMenu("BtLsnr")] //public void ListenStartStopStart() //{ // Guid svcClass = BluetoothService.Wap; // console.WriteLine("Default UUID : {0}", svcClass); // Guid? inputGuid = console.ReadOptionalBluetoothUuid("UUID"); // if (inputGuid.HasValue) // svcClass = inputGuid.Value; // BluetoothListener lsnr = Create_BluetoothListener(svcClass); // lsnr.Start(); // lsnr.Stop(); // lsnr.Start(); // // // lsnr = null; // GC.Collect(); // GC.Collect(); // GC.WaitForPendingFinalizers(); //} [MenuItem, SubMenu("BtLsnr")] public void Listen() { BluetoothListener lsnr = ListenInit(); BluetoothClient cli; bool startStopStartEtc = console.ReadYesNo("Start-Stop-Start-Stop-Start-Finalize", false); if (startStopStartEtc) { lsnr.Stop(); lsnr.Start(); console.WriteLine("Stopped and restarted."); } bool @async = console.ReadYesNo("Async Accept", false); if (!@async) { bool callPending = console.ReadYesNo("Loop on Pending()", false); if (callPending) { int i = 0; while (!lsnr.Pending()) { console.WriteLine("Not Pending" + new string('.', (i + 3) % 3)); const int HalfSecond = 500; Thread.Sleep(HalfSecond); ++i; } console.WriteLine("Is Pending..."); } //bool closeNow = console.ReadYesNo("Hit return to proceed to EndConnect. Enter Y to call Close first.", false); console.WriteLine("calling Accept..."); cli = lsnr.AcceptBluetoothClient(); } else { console.WriteLine("Waiting for connection..."); IAsyncResult ar = lsnr.BeginAcceptBluetoothClient(MiscCallback, "BeginAcceptBluetoothClient"); console.WriteLine("(BeginAccept returned)"); bool startStopStartEtcAfter = console.ReadYesNo("Start-Stop-Start-Stop-Start-Finalize (will break *us*)", false); if (startStopStartEtcAfter) { lsnr.Stop(); lsnr.Start(); console.WriteLine("Stopped and restarted."); } #if !NETCF ManualResetEvent quit = console.NewManualResetEvent(false); int signalledIdx = WaitHandle.WaitAny(new WaitHandle[] { ar.AsyncWaitHandle, quit }); if (signalledIdx == 1) { // ?Do we want to test disposal or Finalization here? // lsnr.Stop() _peer = null; return; } #endif cli = lsnr.EndAcceptBluetoothClient(ar); } // _peer = cli.GetStream(); _cli = new WeakReferenceT(cli); console.WriteLine("Got connection from: '{0}' {1}", cli.RemoteMachineName, cli.RemoteEndPoint); PrintLocalEndpointIfAvailable(cli); console.Pause("Un-pause to continue; and close listener"); if (!startStopStartEtc) { lsnr.Stop(); } else { lsnr.Stop(); lsnr.Start(); // bool x = console.ReadYesNo("Do Async Accept (before Finalization)", false); IAsyncResult arLast = null; if (x) { arLast = lsnr.BeginAcceptBluetoothClient(MiscCallback, "BeginAcceptBluetoothClient"); console.WriteLine("(BeginAccept returned)"); } lsnr = null; GC.Collect(); GC.Collect(); GC.WaitForPendingFinalizers(); console.WriteLine("Stopped, restarted, and Finalized."); if (arLast != null) { console.WriteLine("arLastL: {0}", arLast.IsCompleted); // Can't call EndAccept as no lsnr reference! } } } [MenuItem, SubMenu("BtLsnr")] public void ListenAndImmediatelyClose() { ListenAndImmediatelySendAndClose_(null); } [MenuItem, SubMenu("BtLsnr")] public void ListenAndImmediatelySendOneByteAndClose() { ListenAndImmediatelySendAndClose_(new byte[] { (byte)'a' }); } void ListenAndImmediatelySendAndClose_(byte[] data) { BluetoothListener lsnr = ListenInit(); console.WriteLine("Waiting for connection..."); BluetoothClient cli = lsnr.AcceptBluetoothClient(); console.WriteLine("Got connection from: {0}!", cli.RemoteMachineName); _peer = cli.GetStream(); if (data != null) _peer.Write(data, 0, data.Length); _peer.Close(); _peer = null; console.WriteLine("Got connection from ({2}and closed it!): '{0}' {1}", cli.RemoteMachineName, cli.RemoteEndPoint, (data != null ? "sent " : string.Empty)); lsnr.Stop(); } [MenuItem, SubMenu("Data")] public void SendOneByteAndImmediatelyClose() { if (!VerifyConnectionWrite()) return; byte[] data = { (byte)'a' }; _peer.Write(data, 0, data.Length); _peer.Close(); } [MenuItem, SubMenu("BtLsnr")] public void ListenAcceptMultiple() { BluetoothListener lsnr = ListenInit(); ManualResetEvent quit = console.NewManualResetEvent(false); ListenAcceptMultipleState state = new ListenAcceptMultipleState(); state.lsnr = lsnr; state.quit = quit; bool keepOpen = console.ReadYesNo("Keep reference to all connections?", false); state.KeepAllConnections = keepOpen; state.ReadToEnd = console.ReadYesNo("ReadToEnd of all connections?", false); lsnr.BeginAcceptBluetoothClient(ListenAcceptMultiple_Callback, state); console.Pause("Un-pause to stop accepting"); quit.Set(); lsnr.Stop(); } struct ListenAcceptMultipleState { public BluetoothListener lsnr; public ManualResetEvent quit; public int num; // bool storeAllConnections; public List connList; public bool ReadToEnd; public bool KeepAllConnections { get { return storeAllConnections; } set { storeAllConnections = value; if (storeAllConnections && connList == null) { connList = new List(); } } } } struct ListenAcceptMultipleConnectionState { public BluetoothClient Cli; public int Id; } void ListenAcceptMultiple_Callback(IAsyncResult arCb) { ListenAcceptMultipleState state = (ListenAcceptMultipleState)arCb.AsyncState; BluetoothClient cli; try { cli = state.lsnr.EndAcceptBluetoothClient(arCb); if (state.KeepAllConnections) { state.connList.Add(cli); } } catch (ArgumentException ex) { console.WriteLine("Accept failed, due to quit? Exiting. " + Exception_FirstLine(ex)); return; } catch (ObjectDisposedException ex) { console.WriteLine("Accept failed, due to quit? Exiting. " + Exception_FirstLine(ex)); return; } Stream peer = cli.GetStream(); console.WriteLine("At " + DateTime.Now.ToLongTimeString() + " got connection #" + (state.num + 1) + " from: '{0}' {1}", cli.RemoteMachineName, cli.RemoteEndPoint); ++state.num; if (!IsSet(state.quit)) state.lsnr.BeginAcceptBluetoothClient(ListenAcceptMultiple_Callback, state); if (state.ReadToEnd) { ThreadPool.QueueUserWorkItem(ReadToEnd_Runner, new ListenAcceptMultipleConnectionState { Cli = cli, Id = state.num }); } if (_peer == null) { _peer = peer; console.WriteLine("Connection now active."); } } void ReadToEnd_Runner(object state) { var state2 = (ListenAcceptMultipleConnectionState)state; var conn = state2.Cli.GetStream(); var buf = new byte[1000]; while (true) { try { int readLen = conn.Read(buf, 0, buf.Length); console.WriteLine("Conn#{0}: Read '{1}' bytes", state2.Id, readLen); if (readLen == 0) break; } catch (Exception ex) { console.WriteLine("Conn#{0}: exception: {1}", state2.Id, Exception_FirstLine(ex)); break; } }//while console.WriteLine("Conn#{0}: Exit at {1}", state2.Id, DateTime.Now.ToLongTimeString()); } [MenuItem, SubMenu("SmokeTest")] public void NewBt_Endpoint() { var ep = new BluetoothEndPoint(BluetoothAddress.None, Guid.Empty); console.WriteLine("BluetoothEndPoint created successfully."); } [MenuItem, SubMenu("SmokeTest")] public void NewBtEndpoint_fromSocketAddress() { var ep = new BluetoothEndPoint(BluetoothAddress.Parse("002233445566"), BluetoothService.AttProtocol); console.WriteLine("BluetoothEndPoint created successfully."); var sa = ep.Serialize(); console.WriteLine("SocketAddress created successfully."); var ep2 = ep.Create(sa); console.WriteLine("BluetoothEndPoint created successfully."); } [MenuItem, SubMenu("SmokeTest")] public void NewBt_Cli() { using (BluetoothClient cli = Create_BluetoothClient()) { console.WriteLine("BluetoothClient created successfully."); console.ReadLine("BluetoothClient created. Continue to dispose"); } } [MenuItem, SubMenu("SmokeTest")] public void NewBt_Lsnr() { BluetoothListener lsnr = Create_BluetoothListener(BluetoothService.Wap); try { console.WriteLine("BluetoothListener created, now calling Start."); lsnr.Start(); console.ReadLine("Started. Continue to dispose"); } finally { if (lsnr != null) lsnr.Stop(); } } BluetoothAddress _simpleConnectAddress; [MenuItem, SubMenu("BtClient")] public void Connect_SimpleClosingFirst() { if (_peer != null && console.ReadYesNo("Close (possible) connection first", false)) { CloseStream(); } // BluetoothAddress addr; if (_simpleConnectAddress != null && console.ReadYesNo("Use server address: " + _simpleConnectAddress, true)) { addr = _simpleConnectAddress; } else { addr = console.ReadBluetoothAddress("Server's BluetoothAddress"); } ConnectSimpleClosingFirstPart2(addr); } void ConnectSimpleClosingFirstPart2(BluetoothAddress addr) { Guid svcClass = BluetoothService.Wap; BluetoothEndPoint rep = new BluetoothEndPoint(addr, svcClass); BluetoothClient cli = Create_BluetoothClient(); _simpleConnectAddress = addr; // console.WriteLine("Connecting to: {0}:{1}:{2} ...", rep.Address, rep.Service, rep.Port); cli.Connect(rep); console.WriteLine("Connected to : '{0}' {1}", cli.RemoteMachineName, cli.RemoteEndPoint); PrintLocalEndpointIfAvailable(cli); _peer = cli.GetStream(); _cli = new WeakReferenceT(cli); } [MenuItem, SubMenu("BtClient")] public void Connect() { BluetoothClient cli; Connect_(out cli); _peer = cli.GetStream(); _cli = new WeakReferenceT(cli); } #if NETCF [MenuItem, SubMenu("Playing")] public void BtpsScoWith_Connect() { var p = new InTheHand.Net.Bluetooth.StonestreetOne.BluetopiaPlaying(); Action makeConnect = delegate(BluetoothAddress address) { p.HciCreateConnection(address); }; // BluetoothClient cli; Connect_(out cli, makeConnect); _peer = cli.GetStream(); _cli = new WeakReferenceT(cli); ThreadPool.QueueUserWorkItem(state => Read_(40, false)); // p.HciAddScoConnection(); // var buf = Encoding.ASCII.GetBytes("ATD 07981152473\r"); _peer.Write(buf, 0, buf.Length); } [MenuItem, SubMenu("Playing")] public void BtpsRawHci() { var p = new InTheHand.Net.Bluetooth.StonestreetOne.BluetopiaPlaying(); Byte ogf = 0x3f; ushort ocf = 0; const byte FirstFragment = 0x80; const byte LastFragment = 0x40; const byte BccmdChannelId = 2; const byte PayloadDescriptor = BccmdChannelId | FirstFragment | LastFragment; // //const ushort xxBccmdGetReqxx = 0x0000; //const ushort xxBuildIdxx = 0x28_19; //const ushort xxBuildIdLoaderxx = 0x28_38; // int seqNum = Interlocked.Increment(ref csrSeqNum); Byte[] command = { PayloadDescriptor, //cmd 0x00, 0x00, //len 16,0, //SeqNum (byte)seqNum,0, // VarId 0x19,0x28, // Status 0,0, // Payload 0,0,0,0, 0,0,0,0, }; Byte lenCommand = checked((byte)command.Length); // int ret = p.HciSendRawCommand(ogf, ocf, lenCommand, command); console.WriteLine("HCI_Send_Raw_Command ret: {0}", ret); /* Frame 1: 23 bytes on wire (184 bits), 23 bytes captured (184 bits) 01:00:fc:13!c2:00:00:10: 00:01:00:19:28:00:00:00: 00:00:00:00:00:00:00 Frame 2: 36 bytes on wire (288 bits), 36 bytes captured (288 bits) 04:ff:21!c2:01:00:10:00: 01:00:19:28:00:00:7e:0d: 00:00:00:00:00:00:00:00: 00:00:00:00:00:00:00:00: 00:00:00:00 * Status = 0 * BuildID = 0x0d7e = 3454 * Which is the same as the value reported in Radio info. :-) */ } static int csrSeqNum; #endif readonly TimeSpan ConnectDuringDiscoveryPreConnectDelayMs = TimeSpan.FromSeconds(4); [MenuItem, SubMenu("BtClient")] public void Connect_WithInquiryRunning_APM() { TimeSpan delay = ConnectDuringDiscoveryPreConnectDelayMs; var givenDelay = console.ReadTimeSecondsOptional(" (default " + delay + ")"); if (givenDelay != null) { delay = givenDelay.Value; } BluetoothClient cliDD = Create_BluetoothClient(); IAsyncResult arDD = null; Action startDisco = delegate { arDD = cliDD.BeginDiscoverDevices(255, false, false, false, true, MiscCallback, "BeginDiscoverDevices"); Thread.Sleep(delay.Seconds); }; BluetoothClient cli; DateTime startT = DateTime.UtcNow; try { Connect_(out cli, startDisco); _peer = cli.GetStream(); _cli = new WeakReferenceT(cli); } finally { DateTime connectedT = DateTime.UtcNow; console.WriteLine("Started at: {0}", startT); console.WriteLine("Connect completed at: {0}, waiting for device discovery...", connectedT); var devices = cliDD.EndDiscoverDevices(arDD); DateTime endDdT = DateTime.UtcNow; console.WriteLine("End of DD at: {0}, with {1} devices.", endDdT, devices.Length); } } [MenuItem, SubMenu("BtClient")] public void Connect_WithInquiryRunning_EBAP() { TimeSpan delay = ConnectDuringDiscoveryPreConnectDelayMs; var givenDelay = console.ReadTimeSecondsOptional(" (default " + delay + ")"); if (givenDelay != null) { delay = givenDelay.Value; } BluetoothClient cliDD = Create_BluetoothClient(); var ddComplete = new ManualResetEvent(false); var btco = new BluetoothComponent(cliDD); btco.DiscoverDevicesProgress += _DiscoDevicesAsync_ProgressCallback; btco.DiscoverDevicesComplete += _DiscoDevicesAsync_CompleteCallback; btco.DiscoverDevicesComplete += (s, e) => ddComplete.Set(); Action startDisco = delegate { btco.DiscoverDevicesAsync(255, false, false, false, true, 99); Thread.Sleep(delay.Seconds); }; BluetoothClient cli; DateTime startT = DateTime.UtcNow; try { Connect_(out cli, startDisco); _peer = cli.GetStream(); _cli = new WeakReferenceT(cli); } finally { DateTime connectedT = DateTime.UtcNow; console.WriteLine("Started at: {0}", startT); console.WriteLine("Connect completed at: {0}, waiting for device discovery...", connectedT); ddComplete.WaitOne(); DateTime endDdT = DateTime.UtcNow; //console.WriteLine("End of DD at: {0}, with {1} devices.", endDdT, devices.Length); console.WriteLine("End of DD at: {0}.", endDdT); ddComplete.Close(); } } [MenuItem, SubMenu("BtClient")] public void Connect_FromInquiryCallback() { BluetoothClient cliDd = Create_BluetoothClient(); cliDd.BeginDiscoverDevices(255, true, true, true, false, Connect_FromInquiryCallback_DdCallback, cliDd); console.WriteLine("Running async DiscoverDevices..."); } void Connect_FromInquiryCallback_DdCallback(IAsyncResult ar) { console.WriteLine("DiscoverDevices completed..."); BluetoothClient cliDd = (BluetoothClient)ar.AsyncState; cliDd.EndDiscoverDevices(ar); // try { BluetoothClient cli; Connect_(out cli); _peer = cli.GetStream(); _cli = new WeakReferenceT(cli); } catch (Exception ex) { console.WriteLine("Connect_FromInquiryCallback error: " + ex); } } #if TEST_EARLY [MenuItem, SubMenu("BtClient")] public void Connect_GetStream2() { BluetoothClient cli; Connect_(out cli); peer = cli.GetStream2(); s_cli = new WeakReferenceT(cli); } #endif [MenuItem, SubMenu("BtClient")] public void ConnectSuccessfullyAnd_ImmediatelyClose() { ConnectSuccessfullyAndImmediatelySendAndClose_(null); } [MenuItem, SubMenu("BtClient")] public void ConnectSuccessfullyAndImmediatelySend_OneByteAndClose() { ConnectSuccessfullyAndImmediatelySendAndClose_(new byte[] { (byte)'b' }); } void ConnectSuccessfullyAndImmediatelySendAndClose_(byte[] data) { BluetoothClient cli; Connect_(out cli); _peer = cli.GetStream(); if (data != null) _peer.Write(data, 0, data.Length); _peer.Close(); _peer = null; _cli = null; } [MenuItem, SubMenu("BtClient")] public void ConnectMultiple_Devices() { int num = console.ReadInteger("How many connects?"); bool oaat = console.ReadYesNo("Do one-at-a-time (e.g. Widcomm SDP sync)?", false); BluetoothAddress[] addrList = new BluetoothAddress[num]; Guid[] svcClassList = new Guid[num]; int?[] portList = new int?[num]; BluetoothClient[] cliList = new BluetoothClient[num]; IAsyncResult[] arList = new IAsyncResult[num]; // for (int i = 0; i < num; ++i) { addrList[i] = console.ReadBluetoothAddress("Server #" + (i + 1) + "'s BluetoothAddress"); svcClassList[i] = BluetoothService.Wap; Guid? inputGuid = console.ReadOptionalBluetoothUuid("UUID", svcClassList[i]); if (inputGuid.HasValue) svcClassList[i] = inputGuid.Value; portList[i] = console.ReadOptionalInteger("Port number"); } // IAsyncResult waitForLast = null; for (int i = 0; i < num; ++i) { if (waitForLast != null) { console.Write("Waiting previous. "); bool signalled = waitForLast.AsyncWaitHandle.WaitOne(60 * 1000, false); if (!signalled) { throw new InvalidOperationException("Timed-out waiting for previous connect to complete."); } } BluetoothEndPoint rep; if (portList[i] == null) rep = new BluetoothEndPoint(addrList[i], svcClassList[i]); else rep = new BluetoothEndPoint(addrList[i], svcClassList[i], portList[i].Value); console.WriteLine("{4}: Connecting #{3} to: {0}:{1}:{2} ...", rep.Address, rep.Service, rep.Port, (i + 1), GetTime()); // cliList[i] = Create_BluetoothClient(); try { arList[i] = cliList[i].BeginConnect(rep, MiscCallback, "BeginConnect #" + (i + 1)); console.WriteLine("{0}: (BeginConnect returned)", GetTime()); if (oaat) { waitForLast = arList[i]; } } catch (System.Net.Sockets.SocketException ex) { console.WriteLine("{0}: BeginConnect failed: {1}", GetTime(), Exception_FirstLine(ex)); } }//for // WaitAll(arList); console.WriteLine("All signalled"); // for (int i = 0; i < cliList.Length; i++) { try { cliList[i].EndConnect(arList[i]); } catch (Exception ex) { console.WriteLine("Error for #{3}: ", (i + 1), Exception_FirstLine(ex)); } } console.WriteLine("All completed"); } private void WaitAll(IList arList) { WaitHandle[] whList = GetWaitHandles(arList); #if !NETCF bool signalled = WaitHandle.WaitAll(whList); #else bool signalled = WaitHandle_WaitAll_Hack(whList); #endif Debug.Assert(signalled, "Given infinite timeout, but returned NON-signalled!?!"); } private WaitHandle[] GetWaitHandles(IList arList) { Debug.Assert(arList != null, "ArgNullEx"); List output = new List(arList.Count); for (int i = 0; i < arList.Count; ++i) { if (arList[i] != null) output.Add(arList[i].AsyncWaitHandle); } return output.ToArray(); } #if NETCF bool WaitHandle_WaitAll_Hack(WaitHandle[] list) { bool sum = true; foreach (WaitHandle cur in list) { bool signalled = cur.WaitOne(); Debug.Assert(signalled, "NOT signalled"); sum = sum && signalled; } Debug.Assert(sum, "NOT signalled->sum"); return sum; } #endif void Connect_(out BluetoothClient cli) { Connect_(out cli, null); } void Connect_(out BluetoothClient cli, Action codeToRunJustBeforeConnect) { BluetoothAddress addr = console.ReadBluetoothAddress("Server's BluetoothAddress"); Guid svcClass = BluetoothService.Wap; Guid? inputGuid = console.ReadOptionalBluetoothUuid("UUID", svcClass); if (inputGuid.HasValue) svcClass = inputGuid.Value; int? port = console.ReadOptionalInteger("Port number"); bool auth = console.ReadYesNo("Authenticate", false); bool encpt = console.ReadYesNo("Encrypt", false); bool setPin1, setPin2; string passcode; BluetoothAddress pinAddr; PromptForSetPin(console, out setPin1, out setPin2, out passcode, out pinAddr); // BluetoothEndPoint lep; BluetoothAddress localAddrOptional = console.ReadOptionalBluetoothAddress("Local Bind() BluetoothAddress"); if (localAddrOptional != null) { const int DefaultLocalPort = 0; var localPort = console.ReadOptionalInteger("Local port (default: " + DefaultLocalPort + ")"); if (!localPort.HasValue) { localPort = DefaultLocalPort; } lep = new BluetoothEndPoint(localAddrOptional, BluetoothService.Empty, localPort.Value); } else { lep = null; } // #if FX4 bool taskAsync = console.ReadYesNo("Task-Async Connect?", false); #else bool taskAsync = false; #endif bool @async = taskAsync ? false : console.ReadYesNo("Async (APM) Connect?", false); bool asyncCallback = true;//not used but init anyway if (taskAsync || @async) { asyncCallback = console.ReadYesNo("Async Callback?", true); } // BluetoothEndPoint rep; if (port == null) rep = new BluetoothEndPoint(addr, svcClass); else rep = new BluetoothEndPoint(addr, svcClass, port.Value); console.WriteLine("Connecting to: {0}:{1}:{2} ...", rep.Address, rep.Service, rep.Port); // if (lep != null) { console.WriteLine("Binding to: {0}::{2} ...", lep.Address, lep.Service, lep.Port); cli = Create_BluetoothClient(lep); } else { cli = Create_BluetoothClient(); } // // For Auth & Encrypt assume false by default, so if NotImpl fails only if user says true. if (auth) cli.Authenticate = true; if (encpt) cli.Encrypt = true; if (setPin1) { Debug.Assert(pinAddr == null, "pinAddr == null"); cli.SetPin(passcode); } else if (setPin2) { Debug.Assert(pinAddr != null, "pinAddr != null"); cli.SetPin(pinAddr, passcode); } if (codeToRunJustBeforeConnect != null) { codeToRunJustBeforeConnect(addr); console.WriteLine("(Have run the code before connect)."); } if (taskAsync) { #if FX4 var task = cli.ConnectAsync(rep, "ConnectAsync"); if (asyncCallback) task.ContinueWith(MiscCallback); console.WriteLine("(ConnectAsync returned)"); bool closeNow = console.ReadYesNo("Respond when we should proceed to Wait. Enter Y to call Close first.", false); if (closeNow) { cli.Close(); } task.Wait(); #else throw new NotSupportedException("Task is FX4"); #endif } else if (@async) { AsyncCallback cb = null; if (asyncCallback) cb = MiscCallback; IAsyncResult ar = cli.BeginConnect(rep, cb, "BeginConnect"); console.WriteLine("(BeginConnect returned)"); #if NETCF // ReadYesNo will block the screen. :-( console.Pause("Paused after BeginConnect"); #endif bool closeNow = console.ReadYesNo("Respond when we should proceed to EndConnect. Enter Y to call Close first.", false); if (closeNow) { cli.Close(); } cli.EndConnect(ar); } else { cli.Connect(rep); } console.WriteLine("Connected to : '{0}' {1}", cli.RemoteMachineName, cli.RemoteEndPoint); PrintLocalEndpointIfAvailable(cli); } private void PrintLocalEndpointIfAvailable(BluetoothClient cli) { System.Net.Sockets.Socket sock = null; try { sock = cli.Client; } catch (NotSupportedException) { } catch (NotImplementedException) { } if (sock != null) { console.WriteLine("Local endpoint : {0}", sock.LocalEndPoint); } } private void PromptForSetPin(MenuSystem console, out bool setPin1, out bool setPin2, out string passcode, out BluetoothAddress pinAddr) { passcode = null; pinAddr = null; setPin1 = console.ReadYesNo("SetPin(string) [not for BtLsnr!]", false); if (setPin1) { setPin2 = false; } else { setPin2 = console.ReadYesNo("SetPin(address,string)", false); } if (setPin1 || setPin2) { passcode = console.ReadLine("Passcode"); } if (setPin2) { pinAddr = console.ReadBluetoothAddress("PIN address"); } } [MenuItem, SubMenu("BtClient")] public void ConnectMultiple_Times() { BluetoothAddress addr = console.ReadBluetoothAddress("Server's BluetoothAddress"); Guid svcClass = BluetoothService.Wap; Guid? inputGuid = console.ReadOptionalBluetoothUuid("UUID", svcClass); if (inputGuid.HasValue) svcClass = inputGuid.Value; int? port = console.ReadOptionalInteger("Port number"); // BluetoothEndPoint rep; if (port == null) rep = new BluetoothEndPoint(addr, svcClass); else rep = new BluetoothEndPoint(addr, svcClass, port.Value); console.WriteLine("Will connect to: {0}:{1}:{2} ...", rep.Address, rep.Service, rep.Port); // int count = console.ReadInteger("Connect how many times"); int? delay = console.ReadOptionalInteger("Delay between each (ms)"); // BluetoothClient cli = null; byte[] buf = { 0x61, 0x62, 0x63, 0x64 }; int countSuccess = 0; int countFail = 0; for (int i = 0; i < count; ++i) { try { if (delay.HasValue) { Thread.Sleep(delay.Value); } console.Write("Connecting #" + (i + 1) + "..."); cli = Create_BluetoothClient(); cli.LingerState = new System.Net.Sockets.LingerOption(true, 10); cli.Connect(rep); ++countSuccess; console.WriteLine("Connected"); using (Stream peerA = cli.GetStream()) { peerA.Write(buf, 0, buf.Length); } } catch (Exception ex) { ++countFail; console.Write("Failed: " + Exception_FirstLine(ex)); Debug.WriteLine("ConnMulti: " + ex); var exitOnError = false; if (exitOnError) { break; } } finally { if (cli != null) { cli.Close(); } } }//for console.WriteLine("Count success: {0}, fail {1}", countSuccess, countFail); } [MenuItem, SubMenu("Data")] public void SendForever() { if (!VerifyConnectionWrite()) return; int interSendPeriod = console.ReadInteger("Inter-send period in milliseconds"); byte[] buf = Encoding.ASCII.GetBytes("____abcdefghijklmnopqrstuvwxyz"); ManualResetEvent quit = console.NewManualResetEvent(false); Action send = delegate(Stream peer2) { int num = 0; while (true) { if (IsSet(quit)) break; string numString = num.ToString("d4"); Debug.Assert(numString.Length == 4, "numString.Length: " + numString.Length); unchecked { buf[0] = (byte)numString[0]; buf[1] = (byte)numString[1]; buf[2] = (byte)numString[2]; buf[3] = (byte)numString[3]; } peer2.Write(buf, 0, buf.Length); console.Write("."); if (IsSet(quit)) break; Thread.Sleep(interSendPeriod); ++num; }//while }; IAsyncResult ar = DelegateExtension.BeginInvoke(send, _peer, null, null); console.Pause("Un-pause to stop sending"); quit.Set(); DelegateExtension.EndInvoke(send, ar); } [MenuItem, SubMenu("Data")] public void ZeroLengthSend() { if (_peer == null) return; byte[] buf = new byte[2]; _peer.Write(buf, 0, 0); console.WriteLine("ZeroLengthSend"); } [MenuItem, SubMenu("Data")] public void ZeroLengthRead() { if (_peer == null) return; byte[] buf = new byte[2]; IAsyncResult ar = null; bool doNormalReadFirst = console.ReadYesNo("Do normal async read first", false); if (doNormalReadFirst) ar = _peer.BeginRead(buf, 0, 1, null, null); int readLen = _peer.Read(buf, 0, 0); console.WriteLine("Did ZeroLengthRead, got length: {0}", readLen); if (ar != null) { int readLen0 = _peer.EndRead(ar); console.WriteLine("The first read got {0} bytes.", readLen0); } } [MenuItem, SubMenu("Data")] public void Flush() { if (_peer == null) return; _peer.Flush(); } [MenuItem, SubMenu("Data")] public void SendOneAtATime() { if (!VerifyConnectionWrite()) return; byte[] buf = Encoding.ASCII.GetBytes("____abcdefghijklmnopqrstuvwxyz"); Action send = delegate(Stream peer2) { int num = 0; while (true) { string numString = num.ToString("d4"); Debug.Assert(numString.Length == 4, "numString.Length: " + numString.Length); unchecked { buf[0] = (byte)numString[0]; buf[1] = (byte)numString[1]; buf[2] = (byte)numString[2]; buf[3] = (byte)numString[3]; } peer2.Write(buf, 0, buf.Length); console.Write("."); if (!console.ReadYesNo("Send another", true)) break; }//while }; send.Invoke(_peer); } private static bool IsSet(ManualResetEvent quit) { bool signalled = quit.WaitOne(0, false); return signalled; } [MenuItem, SubMenu("Data")] public void SendCrLf() { if (_peer == null || !_peer.CanWrite) { console.WriteLine("No connection!"); return; } byte[] buf = Encoding.ASCII.GetBytes("\r\n"); _peer.Write(buf, 0, buf.Length); } [MenuItem, SubMenu("Playing")] public void Write_HCI_ReadLocalName_toStream() { byte[] ReadLocalName = { 0x01, /*hci*/ 0x14, 0x0c, 0x00 }; if (_peer == null || !_peer.CanWrite) { console.WriteLine("No connection!"); return; } byte[] buf = ReadLocalName; _peer.Write(buf, 0, buf.Length); } [MenuItem, SubMenu("Data")] public void SendAmountOneAtATime() { if (!VerifyConnectionWrite()) return; byte[] srcBuf = Encoding.ASCII.GetBytes("____abcdefghijklmnopqrstuvwxyz"); Action send = delegate(Stream peer2) { int num = 0; int lastAmount = 4096; byte[] buf = new byte[0]; while (true) { int? amount = console.ReadOptionalInteger("How big send (default: " + lastAmount + ")"); amount = amount ?? lastAmount; lastAmount = amount.Value; // if (buf.Length < amount) { buf = new byte[amount.Value]; } // string numString = num.ToString("d4"); Debug.Assert(numString.Length == 4, "numString.Length: " + numString.Length); unchecked { buf[0] = (byte)numString[0]; buf[1] = (byte)numString[1]; buf[2] = (byte)numString[2]; buf[3] = (byte)numString[3]; } peer2.Write(buf, 0, amount.Value); console.Write("."); if (!console.ReadYesNo("Send another", true)) break; }//while }; send.Invoke(_peer); } //-------- [MenuItem, SubMenu("Data")] public void Read() { if (!VerifyConnectionRead()) return; int? dumpTruncate = console.ReadOptionalInteger("Dump how much of receive (default None)"); bool binary = false; if (dumpTruncate == null) { dumpTruncate = 0; } if (dumpTruncate > 0) { binary = console.ReadYesNo("Dump in hex", false); } Read_(dumpTruncate, binary); } void Read_(int? dumpTruncate, bool binary) { byte[] buf = new byte[100]; ManualResetEvent quit = console.NewManualResetEvent(false); object lastReturn = "-never set-"; int totalRead = 0; Action dlgt = delegate(Stream peer2) { while (true) { if (IsSet(quit)) break; bool success = false; try { int readLen = peer2.Read(buf, 0, buf.Length); console.Write(" len='{0}'", readLen); success = true; lastReturn = readLen; totalRead += readLen; if (readLen == 0) { console.WriteLine(" EoS."); break; } if (dumpTruncate > 0) { string txt; if (!binary) { txt = Encoding.ASCII.GetString(buf, 0, Math.Min(readLen, dumpTruncate.Value)); } else { txt = BitConverter.ToString(buf, 0, Math.Min(readLen, dumpTruncate.Value)); txt = txt.Substring(0, Math.Min(txt.Length, dumpTruncate.Value)); } console.WriteLine("\"{0}\"", txt); } } finally { if (!success) { lastReturn = "Error"; console.WriteLine("Completed by Error!!!"); } } }//while }; IAsyncResult ar = DelegateExtension.BeginInvoke(dlgt, _peer, null, null); console.Pause("Un-pause to stop after next Read"); quit.Set(); DelegateExtension.EndInvoke(dlgt, ar); console.WriteLine("Last read returned: {0}", lastReturn); console.WriteLine("Total read : {0}", totalRead); } [MenuItem, SubMenu("Data")] public void ReadAndReflect() { if (!VerifyConnectionRead()) return; byte[] buf = new byte[100]; byte[] rsp = new byte[100]; ManualResetEvent quit = console.NewManualResetEvent(false); Action dlgt = delegate(Stream peer2) { while (true) { if (IsSet(quit)) break; int readLen = peer2.Read(buf, 0, buf.Length); console.Write(" len='{0}'", readLen); if (readLen == 0) { console.WriteLine(" EoS."); break; } SwapCase(buf, rsp, readLen); peer2.Write(rsp, 0, readLen); }//while }; IAsyncResult ar = DelegateExtension.BeginInvoke(dlgt, _peer, null, null); console.Pause("Un-pause to stop after next Read"); quit.Set(); DelegateExtension.EndInvoke(dlgt, ar); } private static void SwapCase(byte[] src, byte[] dst, int len) { for (int i = 0; i < len; ++i) { byte b = src[i]; char ch = (char)b; char upper = char.ToUpper(ch, System.Globalization.CultureInfo.InvariantCulture); char lower = char.ToLower(ch, System.Globalization.CultureInfo.InvariantCulture); char upperBack = char.ToLower(ch, System.Globalization.CultureInfo.InvariantCulture); char lowerBack = char.ToUpper(ch, System.Globalization.CultureInfo.InvariantCulture); if (lowerBack != ch && upperBack != ch) { // didn't round-trip, not a displayable(?) char, return as is. dst[i] = (byte)ch; } else if (lower == ch && upper == ch) { // didn't change, not a alphabetical char, return as is. dst[i] = (byte)ch; } else if (lower == ch) { // Is lower case, so return as upper case Debug.Assert(upper != ch, ((ushort)upper).ToString("X") + " != " + ((ushort)ch).ToString("X")); dst[i] = (byte)upper; } else { Debug.Assert(upper == ch); Debug.Assert(lower != ch, ((ushort)upper).ToString("X") + " != " + ((ushort)ch).ToString("X")); dst[i] = (byte)lower; } }//for } [MenuItem, SubMenu("Data")] public void SendObexPutInOnePacket() { if (!VerifyConnectionWrite()) return; byte[] bufValid = { /*PutFinal*/0x82, 0,41, /*Name*/0x01, 0,19, 0,(byte)'a', 0,(byte)'a', 0,(byte)'a', 0,(byte)'.', 0,(byte)'t', 0,(byte)'x', 0,(byte)'t', 0,0, /*EoB*/0x49, 0,19, 0,(byte)'a', 0,(byte)'a', 0,(byte)'a', 0,(byte)'.', 0,(byte)'t', 0,(byte)'x', 0,(byte)'t', 0,0 }; byte[] bufTruncatedInFront = { /*PutFinal*/0x82, 0, // !!!! }; byte[] bufTruncatedInRear = { /*PutFinal*/0x82, 0,41, /*Name*/0x01, 0,19, 0,(byte)'a', // !!!!! }; byte[] bufTruncateBeforeFinal = { /*Put-NON-Final*/0x02, 0,41, /*Name*/0x01, 0,19, 0,(byte)'a', 0,(byte)'a', 0,(byte)'a', 0,(byte)'.', 0,(byte)'t', 0,(byte)'x', 0,(byte)'t', 0,0, /*Body*/0x48, 0,19, 0,(byte)'a', 0,(byte)'a', 0,(byte)'a', 0,(byte)'.', 0,(byte)'t', 0,(byte)'x', 0,(byte)'t', 0,0 }; int? choice; while (true) { choice = console.ReadOptionalInteger( "1. Complete (one packet), 2. Truncated in front, 3. Truncated in back, 4. Truncated before final packet"); if (!choice.HasValue || (choice.Value >= 1 && choice.Value <= 4)) break; console.WriteLine("Invalid selection."); } byte[] buf; switch (choice) { case null: case 1: buf = bufValid; break; case 2: buf = bufTruncatedInFront; break; case 3: buf = bufTruncatedInRear; break; case 4: buf = bufTruncateBeforeFinal; break; default: throw new ArgumentException("Invalid selection: " + choice); } _peer.Write(buf, 0, buf.Length); _peer.Flush(); // just in case console.ReadLine("Waiting before closing the connection"); _peer.Close(); } //---- [MenuItem, SubMenu("Device Discovery")] public void AllDiscover() { BluetoothClient cli = Create_BluetoothClient(); DateTime startTime = DateTime.Now; BluetoothDeviceInfo[] devices = cli.DiscoverDevices(); DateTime endTime = DateTime.Now; DumpDeviceInfo(devices, startTime, endTime); } [MenuItem, SubMenu("Device Discovery")] public void AllApmDiscover() { BluetoothClient cli = Create_BluetoothClient(); const int DefaultTimeout = 30; TimeSpan? timeout = console.ReadTimeSecondsOptional("Set InquiryLength (default " + DefaultTimeout + "secs)"); if (timeout == null) { timeout = TimeSpan.FromSeconds(DefaultTimeout); } cli.InquiryLength = timeout.Value; EventHandler dlgt = delegate { DateTime startTime = DateTime.Now; DiscoState1 state = new DiscoState1(cli, startTime); IAsyncResult ar = cli.BeginDiscoverDevices(255, true, true, true, false, RestartDiscoCallback, state); }; #if NETCF bool fromUi = console.ReadYesNo("Start first discovery from UI thread?", false); #else bool fromUi = false; #endif if (fromUi) { console.UiInvoke(dlgt); } else { dlgt(null, null); } // console.Pause("Un-pause when discovery has completed"); } class DiscoState1 { public readonly BluetoothClient cli; public readonly DateTime startTime; public DiscoState1(BluetoothClient cli, DateTime startTime) { this.cli = cli; this.startTime = startTime; } } void SimpleDiscoCallback(IAsyncResult ar) { DiscoState1 state = (DiscoState1)ar.AsyncState; try { BluetoothDeviceInfo[] devices = state.cli.EndDiscoverDevices(ar); DateTime endTime = DateTime.Now; DumpDeviceInfoBrief(devices, state.startTime, endTime); } catch (Exception ex) { console.WriteLine("Discovery failed with: " + ex); } } void RestartDiscoCallback(IAsyncResult ar) { SimpleDiscoCallback(ar); bool startAgainInCallback = console.ReadYesNo("Start discovery again from callback", false); if (startAgainInCallback) { DiscoState1 state0 = (DiscoState1)ar.AsyncState; DiscoState1 state = new DiscoState1(state0.cli, DateTime.Now); IAsyncResult ar2 = state.cli.BeginDiscoverDevices(255, true, true, true, false, SimpleDiscoCallback, state); } } [MenuItem, SubMenu("Device Discovery")] public void ConcurrentlyTwoDiscoverApm() { var cli1 = Create_BluetoothClient(); var cli2 = Create_BluetoothClient(); IAsyncResult ar1 = cli1.BeginDiscoverDevices(255, true, true, true, false, null, null); IAsyncResult ar2 = cli2.BeginDiscoverDevices(255, true, true, true, false, null, null); console.WriteLine("Two started..."); bool signalled = _WaitAll(new WaitHandle[] { ar1.AsyncWaitHandle, ar2.AsyncWaitHandle }, 30 * 1000); if (!signalled) { console.WriteLine("Something horrible happened, at least one never/took too long to complete."); } else { var rslt1 = cli1.EndDiscoverDevices(ar1); var rslt2 = cli2.EndDiscoverDevices(ar2); console.WriteLine("They returned respectively: {0} and {1} devices.", rslt1.Length, rslt2.Length); } } [MenuItem, SubMenu("Device Discovery")] public void _RememberedDiscover() { BluetoothClient cli = Create_BluetoothClient(); DateTime startTime = DateTime.Now; BluetoothDeviceInfo[] devices = cli.DiscoverDevices(255, false, true, false); DateTime endTime = DateTime.Now; DumpDeviceInfo(devices, startTime, endTime); } [MenuItem, SubMenu("Device Discovery")] public void _FlagsDiscover() { DiscoverFlags_(false); } [MenuItem, SubMenu("Device Discovery")] void FlagsA_pmDiscover() { DiscoverFlags_(true); } private void GetDiscoveryFlags(MenuSystem console, out bool discoOnly, out bool auth, out bool rembd, out bool unk) { console.WriteLine("Discover which type of remote devices?"); discoOnly = console.ReadYesNo("discoverableOnly", false); unk = console.ReadYesNo("Unknown", false); rembd = console.ReadYesNo("Remembered", false); auth = console.ReadYesNo("Authenticated", false); } public void DiscoverFlags_(bool @async) { BluetoothClient cli = Create_BluetoothClient(); bool discoOnly, auth, rembd, unk; GetDiscoveryFlags(console, out discoOnly, out auth, out rembd, out unk); BluetoothDeviceInfo[] devices; // TimeSpan? timeout = console.ReadTimeSecondsOptional("InquiryLength"); if (timeout != null) { cli.InquiryLength = timeout.Value; } console.WriteLine("cli.InquiryLength is: {0}", cli.InquiryLength); int? maxDevices = console.ReadOptionalInteger("maxDevices (default 255)"); if (maxDevices == null) maxDevices = 255; console.WriteLine("maxDevices is: {0}", maxDevices); // DateTime startTime = DateTime.Now; if (@async) { bool doPause = console.ReadYesNo("Pause after BeginDD", false); bool errorCallback = console.ReadYesNo("Throw an Error from the Callback", false); AsyncCallback cb = errorCallback ? new AsyncCallback(ErrorFromMiscCallback) : MiscCallback; IAsyncResult ar = cli.BeginDiscoverDevices(255, auth, rembd, unk, discoOnly, cb, "BeginDiscoverDevices"); console.WriteLine("(BeginDiscoverDevices returned)"); if (doPause) console.Pause("Un-pause to continue to EndDD"); devices = cli.EndDiscoverDevices(ar); } else { devices = cli.DiscoverDevices(maxDevices.Value, auth, rembd, unk, discoOnly); } DateTime endTime = DateTime.Now; DumpDeviceInfo(devices, startTime, endTime); bool dispose = console.ReadYesNo("Dispose BtCli", true); if (dispose && cli != null) { cli.Dispose(); } } [MenuItem, SubMenu("Device Discovery")] public void _RunAllFlagCombinations() { BluetoothClient cli = Create_BluetoothClient(); DateTime startTime = DateTime.Now; bool discoOnly, authenticated, remembered, unknown; int flagSource = 0; while (true) { authenticated = (flagSource & 1) != 0; remembered = (flagSource & 2) != 0; unknown = (flagSource & 4) != 0; discoOnly = (flagSource & 8) != 0; // BluetoothDeviceInfo[] devices = cli.DiscoverDevices(255, authenticated, remembered, unknown, discoOnly); console.WriteLine("Got {0} results", devices.Length); // if (authenticated && remembered && unknown && discoOnly) break; // Have tested all cases of the original four flags. ++flagSource; Thread.Sleep(2000); // This sequence hangs on my W2k+Widcomm box -- does delaying help...? }//while //DateTime endTime = DateTime.Now; //DumpDeviceInfo(devices, startTime, endTime); console.WriteLine("All DiscoverDevices flag combinations run."); } const string vbCrLf = "\r\n"; void DumpDeviceInfo(BluetoothDeviceInfo[] devices, DateTime startTime, DateTime endTime) { System.Text.StringBuilder sb = new System.Text.StringBuilder(); DateTime localTime = startTime.ToLocalTime(); sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "Discovery process started at {0} UTC, {1} local, and ended at {2} UTC.", startTime, localTime, endTime); sb.Append(vbCrLf + vbCrLf); console.WriteLine(sb.ToString()); foreach (BluetoothDeviceInfo curDevice in devices) { sb.Length = 0; DumpDeviceInfo(sb, curDevice); console.WriteLine(sb.ToString()); } } void DumpDeviceInfoBrief(BluetoothDeviceInfo[] devices, DateTime startTime, DateTime endTime) { System.Text.StringBuilder sb = new System.Text.StringBuilder(); DateTime localTime = startTime.ToLocalTime(); sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "Discovery process started at {0} UTC, {1} local, and ended at {2} UTC.", startTime, localTime, endTime); console.WriteLine(sb.ToString()); foreach (BluetoothDeviceInfo curDevice in devices) { sb.Length = 0; DumpDeviceInfoBrief(sb, curDevice); console.WriteLine(sb.ToString()); } } private static void DumpDeviceInfoBrief(StringBuilder sb, BluetoothDeviceInfo curDevice) { sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "* {0}", ToStringQuotedOrNull(curDevice.DeviceName)); sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, ", Address: {0}", curDevice.DeviceAddress); } private static string DumpDeviceInfoBrief(BluetoothDeviceInfo curDevice) { System.Text.StringBuilder sb = new StringBuilder(); DumpDeviceInfoBrief(sb, curDevice); return sb.ToString(); } private static void DumpDeviceInfo(System.Text.StringBuilder sb, BluetoothDeviceInfo curDevice) { sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "* {0}", ToStringQuotedOrNull(curDevice.DeviceName)); sb.Append(vbCrLf); sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "Address: {0}", curDevice.DeviceAddress); sb.Append(vbCrLf); sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "Remembered: {2}, Authenticated: {0}, Connected: {1}", curDevice.Authenticated, curDevice.Connected, curDevice.Remembered); sb.Append(vbCrLf); sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "LastSeen: {0} ({2}), LastUsed: {1} ({3})", curDevice.LastSeen, curDevice.LastUsed, curDevice.LastSeen.Kind, curDevice.LastUsed.Kind); sb.Append(vbCrLf); DumpCodInfo(curDevice.ClassOfDevice, sb); Int32 rssi = curDevice.Rssi; if (rssi != Int32.MinValue) { sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "Rssi: {0} (0x{0:X})", rssi); } else { sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "Rssi: failed"); } sb.Append(vbCrLf); } private static string DumpDeviceInfo(BluetoothDeviceInfo curDevice) { System.Text.StringBuilder sb = new StringBuilder(); DumpDeviceInfo(sb, curDevice); return sb.ToString(); } static void DumpCodInfo(ClassOfDevice cod, System.Text.StringBuilder sb) { sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "CoD: (0x{0:X6})", cod.Value, cod); sb.Append(vbCrLf); sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, " Device: {0} (0x{1:X2}) / {2} (0x{3:X4})", cod.MajorDevice, (int)cod.MajorDevice, cod.Device, (int)cod.Device); sb.Append(vbCrLf); sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, " Service: {0} (0x{1:X2})", cod.Service, (int)cod.Service); sb.Append(vbCrLf); } #if !NO_WINFORMS [MenuItem, SubMenu("Device Discovery")] public void UiDiscovery() { bool discoOnly, auth, rembd, unk; GetDiscoveryFlags(console, out discoOnly, out auth, out rembd, out unk); InTheHand.Windows.Forms.SelectBluetoothDeviceDialog dlg = new InTheHand.Windows.Forms.SelectBluetoothDeviceDialog(); dlg.ShowAuthenticated = auth; dlg.ShowRemembered = rembd; dlg.ShowUnknown = unk; dlg.ShowDiscoverableOnly = discoOnly; if (console.ReadYesNo("set filter (always returns true)", false)) { dlg.DeviceFilter = FilterDevice; if (console.ReadYesNo("set filter to null now(!)", false)) { dlg.DeviceFilter = null; } } System.Windows.Forms.DialogResult rslt = System.Windows.Forms.DialogResult.None; EventHandler action = delegate { rslt = dlg.ShowDialog(); }; console.UiInvoke(action); console.WriteLine("DialogResult: {0}, Selected: {1}", rslt, dlg.SelectedDevice == null ? "(null)" : ("'" + dlg.SelectedDevice.DeviceName + "' " + dlg.SelectedDevice.DeviceAddress.ToString("C"))); } void X() { var dlg = new InTheHand.Windows.Forms.SelectBluetoothDeviceDialog(); dlg.DeviceFilter = FilterDevice; var rslt = dlg.ShowDialog(); //...... } bool FilterDevice(BluetoothDeviceInfo dev) { var ret = true; ret = console.ReadYesNo("Include this device " + dev.DeviceAddress + " " + dev.DeviceName, ret); return ret; } #endif //---- #if TEST_EARLY [MenuItem, SubMenu("SDP")] public void HackServiceDiscovery() { BluetoothAddress addr = console.ReadBluetoothAddress("SDP server BluetoothAddress"); try { BluetoothClient cli0 = new BluetoothClient(); // Don't dispose this to check its Finalization. InTheHand.Net.Bluetooth.Widcomm.ISdpDiscoveryRecordsBuffer recs = cli0.WidcommHack__GetServiceRecordsUnparsed(addr, BluetoothService.L2CapProtocol); console.WriteLine("recordCount: {0}", recs.RecordCount); // int[] ports = recs.Hack_GetPorts(); #if !NETCF string[] txtArr = Array.ConvertAll(ports, delegate(int cur) { return cur.ToString(); }); #else string[] txtArr = new string[ports.Length]; for (int i = 0; i < ports.Length; ++i) txtArr[i] = ports[i].ToString(); #endif string txt = string.Join(", ", txtArr); console.WriteLine("Ports: {0}", txt); // ServiceRecord[] recordArr = recs.GetServiceRecords(); foreach (ServiceRecord cur in recordArr) { console.WriteLine( ServiceRecordUtilities.Dump(cur)); } } catch (Exception ex) { console.WriteLine(ex); } } #endif [MenuItem, SubMenu("SDP")] public void Sdp_Query() { SdpQuery_(); } void SdpQuery_() { BluetoothAddress addr = console.ReadBluetoothAddress("SDP server BluetoothAddress"); Guid? svcClass1 = console.ReadOptionalBluetoothUuid("Search UUID (default L2CAP->all)", null); if (svcClass1 == null) { svcClass1 = BluetoothService.L2CapProtocol; } #if FX4 bool taskAsync = console.ReadYesNo("Task-Async Get", false); #else bool taskAsync = false; #endif bool @async = taskAsync ? false : console.ReadYesNo("Async Get", false); // BluetoothDeviceInfo bdi = Create_BluetoothDeviceInfo(addr); ServiceRecord[] recordArr; var svcClassList = new List { (Guid)svcClass1 }; var foo = false; if (foo) { var from = 0x1000; var to = 0x1100; svcClassList.Clear(); for (int cur = from; cur <= to; ++cur) { svcClassList.Add(BluetoothService.CreateBluetoothUuid(cur)); } } foreach (var svcClass in svcClassList) { string target = string.Format(CultureInfo.InvariantCulture, "{0} on {1}", (Guid)svcClass, bdi.DeviceAddress); if (taskAsync) { #if FX4 var task = bdi.GetServiceRecordsAsync((Guid)svcClass, "GetServiceRecordsAsync"); task.ContinueWith(MiscCallback); console.WriteLine("(GetServiceRecordsAsync returned)"); console.Pause("Un-pause when should continue to get Result"); recordArr = task.Result; task.Wait(); #else throw new NotSupportedException("Task is FX4"); #endif } else if (@async) { console.WriteLine("Calling BeginGetServiceRecords for " + target); IAsyncResult ar = bdi.BeginGetServiceRecords((Guid)svcClass, MiscCallback, "BeginGetServiceRecords"); console.WriteLine("BeginGetServiceRecords returned"); console.Pause("Un-pause when should continue to EndGetServiceRecords"); recordArr = bdi.EndGetServiceRecords(ar); } else { console.WriteLine("Calling GetServiceRecords for " + target); recordArr = bdi.GetServiceRecords((Guid)svcClass); } // SdpRecordDump(recordArr); } } private void SdpRecordDump(ICollection recordArr) { console.WriteLine("recordCount: {0}", recordArr.Count); int i = 1; foreach (ServiceRecord cur in recordArr) { console.WriteLine("{0})", i); try { console.WriteLine( ServiceRecordUtilities.Dump(cur)); } catch (Exception ex) { console.WriteLine("Error in Dump, trying DumpRaw ({0})", ex); console.WriteLine( ServiceRecordUtilities.DumpRaw(cur)); } console.WriteLine("----"); ++i; } } [MenuItem, SubMenu("SDP")] public void SdpQuery_Repeatedly() { BluetoothAddress addr = console.ReadBluetoothAddress("SDP server BluetoothAddress"); Guid? svcClass = console.ReadOptionalBluetoothUuid("Search UUID (default L2CAP->all)", null); if (svcClass == null) { svcClass = BluetoothService.L2CapProtocol; } // BluetoothDeviceInfo bdi = Create_BluetoothDeviceInfo(addr); string target = string.Format(CultureInfo.InvariantCulture, "{0} on {1}", (Guid)svcClass, bdi.DeviceAddress); int InterDelay = 500; // MyAction startQuery = null; bool stop = false; AsyncCallback _Callback = delegate(IAsyncResult ar) { try { bdi.EndGetServiceRecords(ar); console.Write("|"); Thread.Sleep(InterDelay); if (stop) { console.WriteLine("]"); } else { startQuery(); } } catch (Exception ex) { console.WriteLine(ex); } }; startQuery = delegate { bdi.BeginGetServiceRecords((Guid)svcClass, _Callback, null); console.Write("-"); }; // console.WriteLine("Calling first BeginGetServiceRecords for " + target); while (true) { stop = false; startQuery(); console.Pause("When to stop"); stop = true; var startAgain = console.ReadYesNo("Start again?", false); if (!startAgain) { break; } } } [MenuItem, SubMenu("SDP")] public void SdpQuery_Concurrent() { BluetoothAddress addrA = console.ReadBluetoothAddress("SDP server BluetoothAddress"); BluetoothAddress addrB; var another = console.ReadYesNoCancel("Different device | dupl. DBI | same BDI", null); BluetoothDeviceInfo bdiA = Create_BluetoothDeviceInfo(addrA); BluetoothDeviceInfo bdiB; if (another == true) { console.Write("Another target. "); addrB = console.ReadBluetoothAddress("SDP server BluetoothAddress"); bdiB = Create_BluetoothDeviceInfo(addrB); } else if (another == false) { console.Write("Dupl.BDI. "); bdiB = Create_BluetoothDeviceInfo(addrA); } else { console.Write("Same BDI. "); bdiB = bdiA; } // Guid? svcClass = console.ReadOptionalBluetoothUuid("Search UUID (default L2CAP->all)", null); if (svcClass == null) { svcClass = BluetoothService.L2CapProtocol; } // string target = string.Format(CultureInfo.InvariantCulture, "{0} on {1} and {2}", (Guid)svcClass, bdiA.DeviceAddress, bdiB.DeviceAddress); console.WriteLine(target); // bool repeat; do { console.Write("Starting..."); IAsyncResult arA, arB; try { arA = bdiA.BeginGetServiceRecords(svcClass.Value, MiscCallback, "A"); } catch (Exception ex) { arA = null; console.WriteLine("A @Begin " + " ex: " + ex); } try { arB = bdiB.BeginGetServiceRecords(svcClass.Value, MiscCallback, "B"); } catch (Exception ex) { arB = null; console.WriteLine("B @Begin " + " ex: " + ex); } console.Pause("when complete"); MyFunc doGetIsCompleted = delegate(IAsyncResult arX) { if (arX == null) return "NULL"; return arX.IsCompleted.ToString(); }; console.WriteLine("IsCompleted: A: {0}, B: {1}", doGetIsCompleted(arA), doGetIsCompleted(arB)); //-- MyAction doComplete = delegate(string name, BluetoothDeviceInfo devX, IAsyncResult arX) { ServiceRecord[] rs; try { rs = devX.EndGetServiceRecords(arX); console.WriteLine(name + " #r: " + rs.Length); } catch (Exception ex) { console.WriteLine(name + " ex: " + ex); } }; // Complete if they started if (arA != null) { doComplete("A", bdiA, arA); } if (arB != null) { doComplete("B", bdiB, arB); } // repeat = console.ReadYesNo("Do again on same BDIs?", false); } while (repeat); } delegate void MyAction(); delegate void MyAction(T0 p0); delegate void MyAction(T0 p0, T1 p1); delegate void MyAction(T0 p0, T1 p1, T2 p2); [MenuItem, SubMenu("SDP")] public void SdpCreateCustom() { ServiceRecord record = CreateAVariousRecord(); BluetoothListener lsnr = Create_BluetoothListener(BluetoothService.HealthDeviceSink, record); lsnr.Start(); console.Pause("Un-pause to stop the server"); lsnr.Stop(); } #if false [MenuItem, SubMenu("SDP")] public void SdpCreateCustomSimpleElements_Btps() { ServiceRecord record = CreateAVariousRecordWithSimpleElements(); // var c = InTheHand.Net.Bluetooth.StonestreetOne .BluetopiaSdpCreator.CreateTestable(); c.CreateServiceRecord(record); console.Pause("Un-pause to stop the server"); c.DeleteServiceRecord(); } [MenuItem, SubMenu("SDP")] public void SdpCreateCustom_Btps() { ServiceRecord record = CreateAVariousRecord(); // var c = InTheHand.Net.Bluetooth.StonestreetOne .BluetopiaSdpCreator.CreateTestable(); c.CreateServiceRecord(record); console.Pause("Un-pause to stop the server"); c.DeleteServiceRecord(); } #endif private static ServiceRecord CreateAVariousRecord() { MyFunc createId = delegate(ElementType etX) { return (ServiceAttributeId)0x4000 + checked((byte)etX); }; ServiceRecordBuilder bldr = new ServiceRecordBuilder(); bldr.AddServiceClass(BluetoothService.HealthDevice); var longquotes = false; if (longquotes) { bldr.ServiceName = new string('"', 40); // cmd> sdptool search --bdaddr 00:0a:3a:68:65:bb --xml ftp bldr.AddServiceClass(BluetoothService.ObexFileTransfer); } else { bldr.ServiceName = "alan"; } IList attrList = new List(); ElementType et_; CreateVariousSimpleElements(createId, attrList); et_ = ElementType.Uuid16; attrList.Add(new ServiceAttribute(createId(et_), new ServiceElement(et_, (UInt16)et_))); et_ = ElementType.Uuid32; attrList.Add(new ServiceAttribute(createId(et_), new ServiceElement(et_, (UInt32)et_))); et_ = ElementType.Uuid128; attrList.Add(new ServiceAttribute(createId(et_), new ServiceElement(et_, BluetoothService.CreateBluetoothUuid((int)et_)))); bldr.AddCustomAttributes(attrList); bldr.AddCustomAttributes(ElementsAndVariableAndFixedInDeepTree1()); ServiceRecord record = bldr.ServiceRecord; return record; } private static ServiceRecord CreateAVariousRecordWithSimpleElements() { MyFunc createId = delegate(ElementType etX) { return (ServiceAttributeId)0x4000 + checked((byte)etX); }; ServiceRecordBuilder bldr = new ServiceRecordBuilder(); bldr.AddServiceClass(BluetoothService.HealthDevice); // not optional :-( IList attrList = new List(); CreateVariousSimpleElements(createId, attrList); bldr.AddCustomAttributes(attrList); ServiceRecord record = bldr.ServiceRecord; return record; } private static void CreateVariousSimpleElements(MyFunc createId, IList attrList) { ElementType et_; #if SUPPORT_NIL et_ = ElementType.Nil; attrList.Add(new ServiceAttribute(createId(et_), new ServiceElement(et_, null))); #endif et_ = ElementType.Boolean; attrList.Add(new ServiceAttribute(createId(et_), new ServiceElement(et_, true))); ElementType[] weee = { ElementType.UInt8, ElementType.UInt16, ElementType.UInt32, ElementType.UInt64, //UInt128, ElementType.Int8, ElementType.Int16, ElementType.Int32, ElementType.Int64, //Int128, }; foreach (ElementType et in weee) { attrList.Add(new ServiceAttribute( createId(et), ServiceElement.CreateNumericalServiceElement(et, (uint)et))); } } public const String RecordBytes_OneString_StringValue = "abcd\u00e9fgh\u012dj"; public static IList ElementsAndVariableAndFixedInDeepTree1() { IList attrs = new List(); // String str = RecordBytes_OneString_StringValue; ServiceElement itemStr1 = new ServiceElement(ElementType.TextString, str); ServiceElement itemStr2 = new ServiceElement(ElementType.TextString, str); // Uri uri = new Uri("http://example.com/foo.txt"); ServiceElement itemUrl = new ServiceElement(ElementType.Url, uri); // ServiceElement itemF1 = new ServiceElement(ElementType.UInt16, (UInt16)0xfe12); ServiceElement itemF2 = new ServiceElement(ElementType.UInt16, (UInt16)0x1234); // IList leaves2 = new List(); leaves2.Add(itemStr1); leaves2.Add(itemUrl); leaves2.Add(itemF1); ServiceElement e2 = new ServiceElement(ElementType.ElementSequence, leaves2); // ServiceElement e1 = new ServiceElement(ElementType.ElementSequence, e2); // IList leaves0 = new List(); leaves0.Add(e1); leaves0.Add(itemStr2); leaves0.Add(itemF2); attrs.Add( new ServiceAttribute(0x0401, new ServiceElement(ElementType.ElementAlternative, leaves0))); return attrs; } [MenuItem, SubMenu("SDP")] public void SdpCreateHidAndPnpRecords() { ServiceRecord record = CreateAHumanInputDeviceRecord(); BluetoothListener lsnr = Create_BluetoothListener(BluetoothService.HealthDeviceSink, record); ServiceRecord record2 = CreateAHumanInputDeviceRecordB(); BluetoothListener lsnr2 = Create_BluetoothListener(BluetoothService.HealthDeviceSink, record2); ServiceRecord record3 = CreateAPnpRecord(); BluetoothListener lsnr3 = Create_BluetoothListener(BluetoothService.HealthDeviceSink, record3); lsnr.Start(); lsnr2.Start(); lsnr3.Start(); console.Pause("Un-pause to stop the server"); lsnr.Stop(); lsnr2.Stop(); lsnr3.Stop(); } [MenuItem, SubMenu("SDP")] public void SdpCreatePnpRecord() { ServiceRecord record = CreateAPnpRecord(); BluetoothListener lsnr = Create_BluetoothListener(BluetoothService.HealthDeviceSink, record); lsnr.Start(); console.Pause("Un-pause to stop the server"); lsnr.Stop(); } private ServiceRecord CreateAPnpRecord() { ServiceRecordBuilder bldr = new ServiceRecordBuilder(); // Listener needs this. :-( bldr.ProtocolType = BluetoothProtocolDescriptorType.GeneralObex; bldr.AddServiceClass(BluetoothService.PnPInformation); bldr.AddCustomAttribute(new ServiceAttribute(DeviceIdProfileAttributeId.SpecificationId, ServiceElement.CreateNumericalServiceElement(ElementType.UInt16, 1))); bldr.AddCustomAttribute(new ServiceAttribute(DeviceIdProfileAttributeId.VendorId, ServiceElement.CreateNumericalServiceElement(ElementType.UInt16, 2))); bldr.AddCustomAttribute(new ServiceAttribute(DeviceIdProfileAttributeId.ProductId, ServiceElement.CreateNumericalServiceElement(ElementType.UInt16, 3))); bldr.AddCustomAttribute(new ServiceAttribute(DeviceIdProfileAttributeId.Version, ServiceElement.CreateNumericalServiceElement(ElementType.UInt16, 4))); bldr.AddCustomAttribute(new ServiceAttribute(DeviceIdProfileAttributeId.PrimaryRecord, new ServiceElement(ElementType.Boolean, true))); bldr.AddCustomAttribute(new ServiceAttribute(DeviceIdProfileAttributeId.VendorIdSource, ServiceElement.CreateNumericalServiceElement(ElementType.UInt16, 6))); return bldr.ServiceRecord; } [MenuItem, SubMenu("SDP")] public void SdpCreateHumanInputDeviceRecord() { ServiceRecord record = CreateAHumanInputDeviceRecord(); BluetoothListener lsnr = Create_BluetoothListener(BluetoothService.HealthDeviceSink, record); ServiceRecord record2 = CreateAHumanInputDeviceRecordB(); BluetoothListener lsnr2 = Create_BluetoothListener(BluetoothService.HealthDeviceSink, record2); lsnr.Start(); lsnr2.Start(); console.Pause("Un-pause to stop the servers"); lsnr.Stop(); lsnr2.Stop(); } private ServiceRecord CreateAHumanInputDeviceRecord() { ServiceRecordBuilder bldr = new ServiceRecordBuilder(); // Listener needs this. :-( bldr.ProtocolType = BluetoothProtocolDescriptorType.GeneralObex; bldr.AddServiceClass(BluetoothService.HumanInterfaceDevice); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.DeviceReleaseNumber, ServiceElement.CreateNumericalServiceElement(ElementType.UInt16, 0x1000))); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.ParserVersion, ServiceElement.CreateNumericalServiceElement(ElementType.UInt16, 1))); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.DeviceSubclass, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 2))); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.CountryCode, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 3))); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.VirtualCable, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 4))); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.ReconnectInitiate, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 5))); //bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.DescriptorList, // new ServiceElement(ElementType.ElementSequence, // ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 6)))); //bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.LangIdBaseList, // new ServiceElement(ElementType.ElementSequence, // ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 7)))); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.SdpDisable, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 8))); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.BatteryPower, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 9))); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.RemoteWake, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 10))); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.BootDevice, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 14))); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.SupervisionTimeout, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 12))); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.NormallyConnectable, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 13))); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.ProfileVersion, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 11))); return bldr.ServiceRecord; } private ServiceRecord CreateAHumanInputDeviceRecordB() { ServiceRecordBuilder bldr = new ServiceRecordBuilder(); // Listener needs this. :-( bldr.ProtocolType = BluetoothProtocolDescriptorType.GeneralObex; bldr.AddServiceClass(BluetoothService.HumanInterfaceDevice); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.DeviceReleaseNumber, ServiceElement.CreateNumericalServiceElement(ElementType.UInt16, 0x1FFF))); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.ParserVersion, ServiceElement.CreateNumericalServiceElement(ElementType.UInt16, 0xFF1F))); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.DeviceSubclass, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 0x2F))); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.CountryCode, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 0x3F))); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.VirtualCable, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 0x4F))); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.ReconnectInitiate, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 0x5F))); //bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.DescriptorList, // new ServiceElement(ElementType.ElementSequence, // ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 6)))); //bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.LangIdBaseList, // new ServiceElement(ElementType.ElementSequence, // ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 7)))); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.SdpDisable, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 0x8F))); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.BatteryPower, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 0x9F))); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.RemoteWake, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 0x1F))); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.BootDevice, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 14))); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.SupervisionTimeout, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 12))); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.NormallyConnectable, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 13))); bldr.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.ProfileVersion, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 11))); return bldr.ServiceRecord; } [MenuItem, SubMenu("SDP")] private void SdpCreateAHumanInputDeviceRecordsAllTwoOfThree() { var create = new Converter(delegate { ServiceRecordBuilder bldrF = new ServiceRecordBuilder(); // Listener needs this. :-( bldrF.ProtocolType = BluetoothProtocolDescriptorType.GeneralObex; bldrF.AddServiceClass(BluetoothService.HumanInterfaceDevice); return bldrF; }); var attrA = new Action(delegate(ServiceRecordBuilder bldrF) { bldrF.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.DeviceReleaseNumber, ServiceElement.CreateNumericalServiceElement(ElementType.UInt16, 0x1FFF))); }); var attrC = new Action(delegate(ServiceRecordBuilder bldrF) { bldrF.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.DeviceSubclass, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 0x2F))); }); var attrB = new Action(delegate(ServiceRecordBuilder bldrF) { bldrF.AddCustomAttribute(new ServiceAttribute(HidProfileAttributeId.CountryCode, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 0x3F))); }); // ServiceRecordBuilder bldr; bldr = create(null); attrA(bldr); attrB(bldr); BluetoothListener lsnr = Create_BluetoothListener(BluetoothService.HealthDeviceSink, bldr.ServiceRecord); bldr = create(null); attrA(bldr); attrC(bldr); BluetoothListener lsnr2 = Create_BluetoothListener(BluetoothService.HealthDeviceSink, bldr.ServiceRecord); bldr = create(null); attrB(bldr); attrC(bldr); BluetoothListener lsnr3 = Create_BluetoothListener(BluetoothService.HealthDeviceSink, bldr.ServiceRecord); // lsnr.Start(); lsnr2.Start(); lsnr3.Start(); console.Pause("Un-pause to stop the server"); lsnr.Stop(); lsnr2.Stop(); lsnr3.Stop(); } [MenuItem, SubMenu("SDP")] public void SdpCreateTwoSppRecordsOneWithAvailAndBrowse() { var bldr = new ServiceRecordBuilder(); bldr.AddServiceClass(BluetoothService.WapClient); bldr.AddCustomAttribute(new ServiceAttribute( UniversalAttributeId.ServiceAvailability, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 255))); bldr.AddCustomAttribute(new ServiceAttribute( UniversalAttributeId.BrowseGroupList, new ServiceElement(ElementType.ElementSequence, new ServiceElement(ElementType.Uuid128, BluetoothService.PublicBrowseGroup)))); var sr = bldr.ServiceRecord; //DEBUGconsole.Write(ServiceRecordUtilities.Dump(sr)); var lsnr = Create_BluetoothListener( new BluetoothEndPoint(BluetoothAddress.None, BluetoothService.SerialPort, 22), sr); var lsnr2 = Create_BluetoothListener( new Guid("{E665C159-4721-4e73-8E97-9A8BE42423D9}")); // lsnr.Start(); lsnr2.Start(); console.Pause("Un-pause to stop the server"); lsnr.Stop(); lsnr2.Stop(); } [MenuItem, SubMenu("SDP")] public void SdpCreateAndDumpAnAvcrpRecord() { ServiceRecord record = CreateAnAvcrpCtRecord(); // string dump = ServiceRecordUtilities.Dump(record); console.WriteLine(dump); } internal static ServiceRecord CreateAnAvcrpCtRecord() { //const UInt16 SvcClass16Avcrp = 0x110E; const UInt16 SvcClass16AvcrpController_ = 0x110F; Guid SvcClass128AvcrpController = BluetoothService.CreateBluetoothUuid(SvcClass16AvcrpController_); // const UInt16 SvcClass16ProtocolL2CAP = 0x0100; Debug_Assert_CorrectShortUuid(SvcClass16ProtocolL2CAP, BluetoothService.L2CapProtocol); const UInt16 SvcClass16ProtocolAvctp = 0x0017; Debug_Assert_CorrectShortUuid(SvcClass16ProtocolAvctp, BluetoothService.AvctpProtocol); // const UInt16 PsmAvcrp = 0x0017; const UInt16 PsmAvcrpBrowsing = 0x001B; // const UInt16 Version = 0x0103; // 1.3....... // var layer0 = new ServiceElement(ElementType.ElementSequence, new ServiceElement(ElementType.Uuid16, SvcClass16ProtocolL2CAP), new ServiceElement(ElementType.UInt16, PsmAvcrp)); var layer1 = new ServiceElement(ElementType.ElementSequence, new ServiceElement(ElementType.Uuid16, SvcClass16ProtocolAvctp), new ServiceElement(ElementType.UInt16, Version)); ServiceElement pdl = new ServiceElement(ElementType.ElementSequence, layer0, layer1); // var apdlLayer0 = new ServiceElement(ElementType.ElementSequence, new ServiceElement(ElementType.Uuid16, SvcClass16ProtocolL2CAP), new ServiceElement(ElementType.UInt16, PsmAvcrpBrowsing)); var apdlLayer1 = new ServiceElement(ElementType.ElementSequence, new ServiceElement(ElementType.Uuid16, SvcClass16ProtocolAvctp), new ServiceElement(ElementType.UInt16, Version)); ServiceElement additionalPdlSubList0 = new ServiceElement(ElementType.ElementSequence, apdlLayer0, apdlLayer1); ServiceElement additionalPdl = new ServiceElement(ElementType.ElementSequence, additionalPdlSubList0); // ServiceRecordBuilder bldr = new ServiceRecordBuilder(); bldr.AddServiceClass(BluetoothService.AVRemoteControl); bldr.AddServiceClass(SvcClass128AvcrpController); // bldr.ProtocolType = BluetoothProtocolDescriptorType.None; bldr.AddCustomAttributes( new ServiceAttribute(UniversalAttributeId.ProtocolDescriptorList, pdl), new ServiceAttribute(UniversalAttributeId.AdditionalProtocolDescriptorLists, additionalPdl)); // bldr.AddBluetoothProfileDescriptor(BluetoothService.AVRemoteControl, 1, 4); // bldr.AddCustomAttribute(new ServiceAttribute(HandsFreeProfileAttributeId.SupportedFeatures, ServiceElement.CreateNumericalServiceElement(ElementType.UInt16, (int)(AvcrpSupportedFeatures.Category1 | AvcrpSupportedFeatures.Category2) ))); // bldr.ProviderName = "alanjmcf!!!!!!"; bldr.ServiceName = "avcrp tc!!!!!!"; return bldr.ServiceRecord; } [Conditional("DEBUG")] private static void Debug_Assert_CorrectShortUuid(UInt16 svcClass16, Guid svcClass) { Debug.Assert(svcClass.Equals(BluetoothService.CreateBluetoothUuid(svcClass16)), "Wrong integer value 0x" + svcClass16.ToString("X4") + ", extracted from: " + svcClass); } [Conditional("DEBUG")] private static void Debug_Assert_CorrectShortUuid(UInt32 svcClass32, Guid svcClass) { Debug.Assert(svcClass.Equals(BluetoothService.CreateBluetoothUuid(svcClass32)), "Wrong integer value 0x" + svcClass32.ToString("X8") + ", extracted from: " + svcClass); } [Flags] enum AvcrpSupportedFeatures : ushort { /// /// Category 1 /// Category1 = 0x01, /// /// Category 2 /// Category2 = 0x02, /// /// Category 3 /// Category3 = 0x04, /// /// Category 4 /// Category4 = 0x08, /// /// Player Application Settings /// /// - /// "Bit 0 should be set for this bit to be set." /// PlayerApplicationSettings = 0x10, /// /// Group Navigation /// /// - /// "Bit 0 should be set for this bit to be set." /// GroupNavigation = 0x20, /// /// Supports Browsing /// SupportsBrowsing = 0x40, /// /// Supports multiple media player applications /// SupportsMultipleMediaPlayerApplications = 0x20, // RFA } internal static ServiceRecord CreateAnAvcrpCtRecord_GuidForUuid16() { //Guid SvcClass128Avcrp = /*0x110E*/BluetoothService.AVRemoteControl; const UInt16 _SvcClass16AvcrpController = 0x110F; Guid SvcClass128AvcrpController = BluetoothService.CreateBluetoothUuid(_SvcClass16AvcrpController); // Guid SvcClass128ProtocolL2CAP = /*0x0100*/BluetoothService.L2CapProtocol; Guid SvcClass128ProtocolAvctp = /*0x0017*/BluetoothService.AvctpProtocol; // const UInt16 PsmAvcrp = 0x0017; const UInt16 PsmAvcrpBrowsing = 0x001B; // const UInt16 Version = 0x0103; // 1.3....... // var layer0 = new ServiceElement(ElementType.ElementSequence, new ServiceElement(ElementType.Uuid16, GetBluetoothUuid16(SvcClass128ProtocolL2CAP)), new ServiceElement(ElementType.UInt16, PsmAvcrp)); var layer1 = new ServiceElement(ElementType.ElementSequence, new ServiceElement(ElementType.Uuid16, GetBluetoothUuid16(SvcClass128ProtocolAvctp)), new ServiceElement(ElementType.UInt16, Version)); ServiceElement pdl = new ServiceElement(ElementType.ElementSequence, layer0, layer1); // var apdlLayer0 = new ServiceElement(ElementType.ElementSequence, new ServiceElement(ElementType.Uuid16, GetBluetoothUuid16(SvcClass128ProtocolL2CAP)), new ServiceElement(ElementType.UInt16, PsmAvcrpBrowsing)); var apdlLayer1 = new ServiceElement(ElementType.ElementSequence, new ServiceElement(ElementType.Uuid16, GetBluetoothUuid16(SvcClass128ProtocolAvctp)), new ServiceElement(ElementType.UInt16, Version)); ServiceElement additionalPdlSubList0 = new ServiceElement(ElementType.ElementSequence, apdlLayer0, apdlLayer1); ServiceElement additionalPdl = new ServiceElement(ElementType.ElementSequence, additionalPdlSubList0); // ServiceRecordBuilder bldr = new ServiceRecordBuilder(); bldr.AddServiceClass(BluetoothService.AVRemoteControl); bldr.AddServiceClass(SvcClass128AvcrpController); // bldr.ProtocolType = BluetoothProtocolDescriptorType.None; bldr.AddCustomAttributes( new ServiceAttribute(UniversalAttributeId.ProtocolDescriptorList, pdl), new ServiceAttribute(UniversalAttributeId.AdditionalProtocolDescriptorLists, additionalPdl)); // bldr.AddBluetoothProfileDescriptor(BluetoothService.AVRemoteControl, 1, 4); // bldr.AddCustomAttribute(new ServiceAttribute(HandsFreeProfileAttributeId.SupportedFeatures, ServiceElement.CreateNumericalServiceElement(ElementType.UInt16, (int)(AvcrpSupportedFeatures.Category1 | AvcrpSupportedFeatures.Category2) ))); // bldr.ProviderName = "alanjmcf!!!!!!"; bldr.ServiceName = "avcrp tc!!!!!!"; return bldr.ServiceRecord; } static UInt16 GetBluetoothUuid16(Guid sigServiceClass) { Int64 uuid32 = GetBluetoothUuid32(sigServiceClass); UInt16 uuid16; try { UInt32 uuid32Real = (UInt32)uuid32; uuid16 = (UInt16)uuid32Real; return uuid16; } catch (OverflowException oex) { throw new ArgumentException("The Service Class Guid does not have a UUID16 short form.", oex); } } static UInt32 GetBluetoothUuid32(Guid sigServiceClass) { byte[] ba = sigServiceClass.ToByteArray(); UInt32 uuid32 = BitConverter.ToUInt32(ba, 0); Guid recreated = BluetoothService.CreateBluetoothUuid(uuid32); if (!recreated.Equals(sigServiceClass)) throw new ArgumentException("The Service Class Guid is not a Bluetooth standard class."); return uuid32; } [MenuItem, SubMenu("SDP")] public void SdpDumpGiven() { console.WriteLine("Enter the record bytes, e.g. 0x36, 0x00, 0x53, 0x09, 0x00, 0x00, 0x0a ..."); console.WriteLine("Enter an empty line to finish."); var lineList = new List(); while (true) { //string line = "0x36, 0x00, 0x56, 0x36, 0x00, 0x53, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x00, 0x09, 0x00, "; string line = console.ReadLine(string.Empty); if (string.IsNullOrEmpty(line)) { break; } lineList.Add(line); } // const int GuessMaxLineLen = 16; var bytesList = new List(GuessMaxLineLen * lineList.Count); foreach (var curLine in lineList) { string[] arr = curLine.Split(','); bool sawBlank = false; foreach (var cur in arr) { if (sawBlank) { throw new FormatException("Found blank array entry in line."); } string v = cur.Trim(); byte b; if (v.Length == 0) { // Empty, allow if after last comma... sawBlank = true; continue; } if (v.StartsWith("0x", StringComparison.Ordinal)) { v = v.Substring(2); b = byte.Parse(v, NumberStyles.AllowHexSpecifier); } else { b = byte.Parse(v); } bytesList.Add(b); } } // byte[] raw = bytesList.ToArray(); var p = new ServiceRecordParser(); ServiceRecord rcd; try { rcd = p.Parse(raw); } catch (UriFormatException) { console.WriteLine("Record parse failed with UriFormatException," + " trying again with LazyUrlCreation=true."); p.LazyUrlCreation = true; rcd = p.Parse(raw); } SdpRecordDump(new ServiceRecord[] { rcd }); } [MenuItem, SubMenu("SDP")] public void FromJsr82ServerUri() { var line = console.ReadLine("JSR-82 uri"); var bldr = ServiceRecordBuilder.FromJsr82ServerUri(line); console.WriteLine(ServiceRecordUtilities.Dump(bldr.ServiceRecord)); } //-------- delegate TResult MyFunc(T0 p0); delegate TResult MyFunc(T0 p0, T1 p1); //---- [MenuItem, SubMenu("Data")] public void SendLots() { if (!VerifyConnectionWrite()) return; byte[] data = MakeLotsData(); Lots_CheckTheTest(ref data); bool @async = console.ReadYesNo("Async", true); if (@async) { IAsyncResult ar = _peer.BeginWrite(data, 0, data.Length, MiscCallback, "BeginWrite"); console.WriteLine("Started writing (async), len: {0}.", data.Length); _peer.EndWrite(ar); } else { _peer.Write(data, 0, data.Length); } console.WriteLine("Finished writing."); } [MenuItem, SubMenu("Data")] public void SendLots_InSizedChunks() { if (!VerifyConnectionWrite()) return; byte[] data = MakeLotsData(); Lots_CheckTheTest(ref data); IList dataList = SplitIntoChunks(data, 999); bool @async = console.ReadYesNo("Async", true); if (@async) { List arList = new List(dataList.Count); int total = 0; foreach (byte[] cur in dataList) { IAsyncResult ar = _peer.BeginWrite(cur, 0, cur.Length, EmptyCallback, "BeginWrite"); total += cur.Length; console.Write("."); arList.Add(ar); } console.WriteLine("Did BeginWrite all chunks ({2}, async), len: {0} is {1}.", total, data.Length, arList.Count); foreach (IAsyncResult cur in arList) { _peer.EndWrite(cur); } console.WriteLine("Did EndWrite all chunks."); } else { foreach (byte[] chunk in dataList) { console.WriteLine("chunk={0}", chunk.Length); _peer.Write(chunk, 0, chunk.Length); } } console.WriteLine("Finished writing."); } private void Lots_CheckTheTest(ref byte[] data) { bool testChecking1 = console.ReadYesNo("check the TEST, set one byte wrong", false); if (testChecking1) { data[1030000] ^= 255; } int hackOffset = 1040000; bool testChecking2 = console.ReadYesNo("check the TEST, add two bytes at " + hackOffset, false); if (testChecking2) { byte[] dataSlodged = new byte[data.Length + 2]; Array.Copy(data, 0, dataSlodged, 0, hackOffset); Array.Copy(data, hackOffset, dataSlodged, 2 + hackOffset, data.Length - hackOffset); data = dataSlodged; } } private IList SplitIntoChunks(byte[] data, int chunkSize) { int offset = 0; List chunkList = new List(data.Length / chunkSize + 1); while (offset < data.Length) { int curSize = Math.Min(chunkSize, data.Length - offset); byte[] cur = new byte[curSize]; Array.Copy(data, offset, cur, 0, cur.Length); offset += cur.Length; chunkList.Add(cur); } if (offset != data.Length) throw new InvalidOperationException("NOT offset==data.Length: " + offset + " vs " + data.Length); return chunkList; } private byte[] MakeLotsData() { byte[] data = new byte[1 * 1024 * 1024]; bool useRandom = console.ReadYesNo("Random data", true); if (useRandom) { Random r = new Random(999); r.NextBytes(data); } else { for (int i = 0; i < data.Length; ++i) { data[i] = unchecked((byte)i); if (data[i] == 0) // Don't allow zeros, to se if that bug occurs. data[i] = 255; } } return data; } [MenuItem, SubMenu("Data")] public void ReadLots() { if (!VerifyConnectionRead()) return; byte[] expectedData = MakeLotsData(); ReadLotsState state = new ReadLotsState(_peer, expectedData); state.data = new byte[expectedData.Length + 20]; ReadLotsStartNextRead(state); console.Pause("Un-pause to stop"); //lock (readLotsCurAr) { // readLotsCurAr. //} } IAsyncResult readLotsCurAr; private void ReadLotsStartNextRead(ReadLotsState state) { if (state.numCompletedSynchronously > ReadLotsState.MaxCompletedSynchronously) { // (There's lots of pending data and thus) We've CompletedSynchronously // *many* times, so there's a danger of stack overflow // (BeginRead->callback->BeginRead->callback->BeginRead->callback->...), // so start the next operation on a new thread. WaitCallback dlgt = delegate(object stateP) { ReadLotsState state0 = (ReadLotsState)stateP; state.numCompletedSynchronously = 0; ReadLotsStartNextRead(state); }; ThreadPool.QueueUserWorkItem(dlgt); return; } readLotsCurAr = state.peer.BeginRead(state.data, state.totalLen, state.data.Length - state.totalLen, ReadLotsReadCallBack, state); console.Write("-"); } class ReadLotsState { public ReadLotsState(Stream peer, byte[] expectedData) { this.peer = peer; this.expectedData = expectedData; } public Stream peer; public byte[] data; public int totalLen; // public byte[] expectedData; // public int numCompletedSynchronously; public const int MaxCompletedSynchronously = 50; } void ReadLotsReadCallBack(IAsyncResult ar) { ReadLotsState state = (ReadLotsState)ar.AsyncState; int readLen; try { readLen = state.peer.EndRead(ar); } catch (ObjectDisposedException) { console.WriteLine("Connection was closed during ReadLots."); console.WriteLine("???, hit return to continue."); return; } console.Write(">{1} ({0}) ", readLen, state.totalLen + readLen); ArraysEqual(state.expectedData, state.data, state.totalLen, readLen); state.totalLen += readLen; if (ar.CompletedSynchronously) ++state.numCompletedSynchronously; else state.numCompletedSynchronously = 0; if (state.totalLen == state.expectedData.Length) { console.WriteLine("got all!"); return; } // if (readLen == 0) { console.WriteLine("EoF, hit return to continue."); return; } ReadLotsStartNextRead(state); } private void ArraysEqual(byte[] expected, byte[] actual, int offset, int count) { for (int i = 0; i < count; ++i) { if (offset + i >= expected.Length) { console.WriteLine("!! ({0}+{1}=>) {2} >= {3}", offset, i, (offset + i), expected.Length); } if (offset + i >= actual.Length) { console.WriteLine("!! ({0}+{1}=>) {2} >= {3}", offset, i, (offset + i), actual.Length); } if (expected[offset + i] != actual[offset + i]) { console.WriteLine("wrong at {0}+{1}={2}", offset, i, offset + i); break; } } } //---- [MenuItem, SubMenu("Local")] public void GetAllRadios_OnUiThread() { EventHandler dlgt = delegate { #if ANDROID InTheHand.Net.Bluetooth.Droid.AndroidBthInquiry .MyActivity = (Android.App.Activity)console.InvokeeControl; #endif var rl = BluetoothRadio.GetAllRadios(); }; console.UiInvoke(dlgt); } [MenuItem, SubMenu("Local")] public void GetAllRadios() { BluetoothRadio_GetAllAndDump(); } [MenuItem, SubMenu("Local")] public void GetAllRadiosWith_Features() { BluetoothRadio_GetAllAndDump(true); } [MenuItem, SubMenu("Local")] public void Get_AllRadiosDumpRepeatedly() { BluetoothRadio[] list = BluetoothRadio.GetAllRadios(); do { DumpBluetoothRadios(list, false); } while (console.ReadYesNo("Dump again", false)); } BluetoothRadio[] BluetoothRadio_GetAllAndDump() { return BluetoothRadio_GetAllAndDump(false); } BluetoothRadio[] BluetoothRadio_GetAllAndDump(bool dumpFeatureList) { BluetoothRadio[] list; if (console.ReadYesNo("Get Method rather then Property", true)) { list = BluetoothRadio.GetAllRadios(); } else { list = BluetoothRadio.AllRadios; } DumpBluetoothRadios(list, dumpFeatureList); return list; } void DumpBluetoothRadios(BluetoothRadio[] list, bool dumpFeatureList) { if (list == null) console.WriteLine("AllRadios returned null!!!"); else if (list.Length == 0) console.WriteLine("AllRadios returned empty list."); int i = 1; foreach (BluetoothRadio r in list) { console.WriteLine("{0}) {1}", i, DumpBluetoothRadio(r, dumpFeatureList)); ++i; } } [MenuItem, SubMenu("Local")] public void GetPrimaryRadio() { GetPrimaryRadio_(false); } [MenuItem, SubMenu("Local")] public void Get_PrimaryRadioAndDumpRepeatedly() { GetPrimaryRadio_(true); } void GetPrimaryRadio_(bool offerRepeat) { BluetoothRadio r; if (console.ReadYesNo("Get Method rather then Property", true)) { r = BluetoothRadio.GetPrimaryRadio(); } else { r = BluetoothRadio.PrimaryRadio; } do { if (r == null) console.WriteLine("PrimaryRadio returned null."); else console.WriteLine(DumpBluetoothRadio(r, false)); } while (offerRepeat && console.ReadYesNo("Dump again", false)); } private static string DumpVersions(RadioVersions v) { if (v == null) throw new ArgumentNullException("radio"); using (StringWriter wtr = new StringWriter()) { wtr.WriteLine("LMP Version: " + v.LmpVersion + ", Subversion: " + v.LmpSubversion); wtr.WriteLine("Manufacturer: {0}", v.Manufacturer); wtr.WriteLine("LMP Features: {0}", v.LmpSupportedFeatures); return wtr.ToString(); } } private static string DumpBluetoothRadio(BluetoothRadio radio, bool dumpFeatureList) { if (radio == null) throw new ArgumentNullException("radio"); using (StringWriter wtr = new StringWriter()) { RadioMode mode = radio.Mode; // Warning: LocalAddress is null if the radio is powered-off. wtr.WriteLine("Radio, address: {0:C}", radio.LocalAddress); #if RADIO_MODESSS wtr.Write("Mode: " + mode.ToString()); wtr.WriteLine("; Modes: { " + radio.Modes.ToString() + " }"); #else wtr.WriteLine("Mode: " + mode.ToString()); #endif wtr.WriteLine("Name: " + ToStringQuotedOrNull(radio.Name)); wtr.WriteLine("HCI Version: " + radio.HciVersion + ", Revision: " + radio.HciRevision); wtr.WriteLine("LMP Version: " + radio.LmpVersion + ", Subversion: " + radio.LmpSubversion); if (dumpFeatureList) { wtr.WriteLine("LMP Features: " + radio.LmpFeatures); } wtr.WriteLine("ClassOfDevice: " + radio.ClassOfDevice.ToString() + ", device: " + radio.ClassOfDevice.Device.ToString() + " / service: " + radio.ClassOfDevice.Service.ToString()); wtr.WriteLine("Software: {0}, Hardware: {1}, status: {2}", radio.SoftwareManufacturer, radio.Manufacturer, radio.HardwareStatus); //try { // wtr.WriteLine("Handle: 0x{0:X}", radio.Handle); //} catch (Exception ex) { // wtr.WriteLine("Handle: failed with: '{0}'", ex.GetType().Name); //} wtr.WriteLine("Remote: '{0}'", radio.Remote); return wtr.ToString(); } } private static string DumpBluetoothRadioBrief(BluetoothRadio radio) { if (radio == null) throw new ArgumentNullException("radio"); using (StringWriter wtr = new StringWriter()) { RadioMode mode = radio.Mode; // Warning: LocalAddress is null if the radio is powered-off. //wtr.Write("Address: {0:C}, ", radio.LocalAddress); wtr.Write("Mode: " + mode.ToString()); #if RADIO_MODESSS wtr.Write("; Modes: { " + radio.Modes.ToString() + " }"); #endif //wtr.Write(", Name: " + radio.Name); return wtr.ToString(); } } [MenuItem, SubMenu("Local")] public void RepeatedlyGetPrimaryRadio() { int? initialDelay = console.ReadOptionalInteger("Initial delay (ms)"); int? interDelay = 250; int? userInterDelay = console.ReadOptionalInteger("Inter delay (ms) (default " + interDelay + ")"); if (userInterDelay.HasValue) interDelay = userInterDelay; int count = 20; int? userCount = console.ReadOptionalInteger("Optional count (default " + count + ")"); if (userCount.HasValue) count = userCount.Value; // if (initialDelay.HasValue) Thread.Sleep(initialDelay.Value); for (int i = 0; i < count; ++i) { console.WriteLine(Environment.TickCount.ToString() + ": "); try { BluetoothRadio r = BluetoothRadio.PrimaryRadio; if (r == null) { console.WriteLine("PrimaryRadio returned null."); } else { console.WriteLine(DumpBluetoothRadioBrief(r)); } } catch (Exception ex) { console.WriteLine("Error:" + Exception_FirstLine(ex)); Debug.WriteLine("RGPR: " + ex); } if (interDelay.HasValue) Thread.Sleep(interDelay.Value); }//for } [MenuItem, SubMenu("Local")] public void IsSupported() { bool? f = null; EventHandler dlgt = (o, e) => f = BluetoothRadio.IsSupported; bool ui = console.ReadYesNo("On UI thread?", false); if (!ui) dlgt(null, null); else console.UiInvoke(dlgt); console.WriteLine("IsSupported: {0}", f.Value); } //---- #if TEST_EARLY [MenuItem, SubMenu("BtLsnr")] public void WidcommHackListen() { BluetoothAddress addr = BluetoothAddress.None; //BluetoothAddress addr = console.ReadBluetoothAddress("Server's local BluetoothAddress"); Guid svcClass = BluetoothService.WapClient; console.WriteLine("Default UUID : {0}", svcClass); Guid? inputGuid = console.ReadOptionalBluetoothUuid("UUID"); if (inputGuid.HasValue) svcClass = inputGuid.Value; int? port = console.ReadOptionalInteger("Port number"); // BluetoothEndPoint rep; if (port == null) rep = new BluetoothEndPoint(addr, svcClass); else rep = new BluetoothEndPoint(addr, svcClass, port.Value); console.WriteLine("Connecting to: {0}:{1}:{2}", rep.Address, rep.Service, rep.Port); // InTheHand.Net.Bluetooth.Widcomm.WidcommBluetoothListener lsnr = new InTheHand.Net.Bluetooth.Widcomm.WidcommBluetoothListener(); lsnr.Construct(rep); lsnr.Start(); BluetoothClient conn = lsnr.AcceptBluetoothClient(); peer = conn.GetStream(); s_cli = new WeakReferenceT(conn); } #endif [MenuItem, SubMenu("GC")] public void RunFinalizersAfterGc() { RunFinalizersAfterGc_(); } internal static void RunFinalizersAfterGc_() { GC.Collect(); GC.WaitForPendingFinalizers(); } [MenuItem, SubMenu("GC")] public void RunGc() { RunGc_(); } internal static void RunGc_() { GC.Collect(); } #if !NETCF && !ANDROID [MenuItem, SubMenu("GC")] public void BeepOnFinalization() { JRichter.GCNotification.StartBeeper(); } #endif //---------- [MenuItem, SubMenu("OBEX")] public void _ObexWebRequest() { string addr = console.ReadLine("Address (IrDA / TCP/IP; hit return for BT)"); bool useUriCtor = true; BluetoothAddress addrBth; if (addr.Length == 0) { addrBth = console.ReadBluetoothAddress("Target Bluetooth device"); addr = addrBth.ToString(); useUriCtor = !console.ReadYesNo("Use BluetoothAddress+stringPath constructor", !useUriCtor); } else { // Often get a space after string on NETCF (remembered string) addr = addr.Trim(); addrBth = null; } string pathO; string fileSource; int? contentLen; if (console.ReadYesNo("Send dummy content", true)) { pathO = "/obexpush1.txt"; contentLen = console.ReadOptionalInteger("How much content (default ~60 bytes)"); fileSource = null; if (contentLen == null) contentLen = 60; } else { contentLen = null; fileSource = console.GetFilename(); pathO = Path.GetFileName(fileSource); pathO = "/" + pathO; } // int? timeout = console.ReadOptionalInteger("timeout (ms)"); // const string scheme = "obex"; Debug.Assert(pathO.StartsWith("/"), "NOT path starts with /"); var s = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}://{1}{2}", scheme, addr, pathO); Uri uri = new Uri(s); ObexWebRequest req; if (useUriCtor) { req = Create_ObexWebRequest(uri); } else { req = Create_ObexWebRequest(scheme, addrBth, pathO); } if (timeout != null) { req.Timeout = timeout.Value; } // if (contentLen != null) { WriteDummyContent(contentLen.Value, req); } else { req.ReadFile(fileSource); } console.WriteLine("Calling GetResponse with " + req.ContentLength + " bytes of content..."); ObexWebResponse rsp = (ObexWebResponse)req.GetResponse(); console.WriteLine("Response Code: {0} (0x{0:X})", rsp.StatusCode); } private static void WriteDummyContent(int contentLen, ObexWebRequest req) { using (Stream content = req.GetRequestStream()) { // Using a StreamWriter to write text to the stream... using (TextWriter wtr = new StreamWriter(content)) { int i = 0; while (content.Length < contentLen) { ++i; wtr.WriteLine("Hello World GetRequestStream {0}", // Write the time to the first line i == 1 ? DateTime.Now.ToString() : i.ToString()); wtr.Flush(); // push through to stream } // Set the Length header value req.ContentLength = content.Length; } } } #if !NETCF bool _touchedOwr; [MenuItem, SubMenu("OBEX")] public void WebClientPut() { if (!_touchedOwr) { bool ret = console.ReadYesNo("Touch ObexWebRequest to install protocol handler.", true); if (ret) { var x = new ObexWebRequest(new Uri("obex://127.0.0.1/foo.txt")); _touchedOwr = true; } } string addr = console.ReadLine("Address (IrDA / TCP/IP; hit return for BT)"); if (addr.Length == 0) { BluetoothAddress addrB = console.ReadBluetoothAddress("Target Bluetooth device"); addr = addrB.ToString(); } int? contentLen = console.ReadOptionalInteger("How much content (default ~60 bytes)"); if (contentLen == null) contentLen = 60; //NOT on NETCF! // UriBuilder bldr = new UriBuilder(); // bldr.Scheme = "obex"; // bldr.Path = "/obexpush1.txt"; // bldr.Host = addr.ToString(); Uri uri = new Uri(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}://{1}{2}", "obex", addr, "/obexpush1.txt")); // var cli = new WebClient(); cli.UploadProgressChanged += delegate(object sender, UploadProgressChangedEventArgs e) { console.WriteLine("Progress: {0}%, {1} of {2}", e.ProgressPercentage, e.BytesSent, e.TotalBytesToSend); }; cli.UploadDataCompleted += delegate(object sender, UploadDataCompletedEventArgs e) { WriteAsyncCompletedState("UploadData", e); }; byte[] data; using (var content = new MemoryStream()) { // Using a StreamWriter to write text to the stream... using (TextWriter wtr = new StreamWriter(content)) { int i = 0; while (content.Length < contentLen) { ++i; wtr.WriteLine("Hello World GetRequestStream {0}", // Write the time to the first line i == 1 ? DateTime.Now.ToString() : i.ToString()); wtr.Flush(); // push through to stream } // data = content.ToArray(); } } // Need method set! cli.UploadDataAsync(uri, "PUT", data); console.Pause("Un-pause after completion"); //console.WriteLine("Calling GetResponse with " + req.ContentLength + " bytes of content..."); //ObexWebResponse rsp = (ObexWebResponse)req.GetResponse(); //console.WriteLine("Response Code: {0} (0x{0:X})", rsp.StatusCode); } #endif [MenuItem, SubMenu("OBEX")] public void ObexWebRequest_GET() { string addr = console.ReadLine("Address (IrDA / TCP/IP; hit return for BT)"); if (addr.Length == 0) { BluetoothAddress addrB = console.ReadBluetoothAddress("Target Bluetooth device"); addr = addrB.ToString(); } string path = console.ReadLine("Path"); Uri uri = new Uri(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}://{1}/{2}", "obex-ftp", addr, path)); console.WriteLine("Using URL: '{0}'", uri); ObexWebRequest req = new ObexWebRequest(uri); req.Method = "GET"; ObexWebResponse rsp = (ObexWebResponse)req.GetResponse(); console.WriteLine("Response Code: {0} (0x{0:X})", rsp.StatusCode); var strm = rsp.GetResponseStream(); console.WriteLine(" ContentLength: {0}, Stream.Length: {1}", rsp.ContentLength, strm.Length); using (Stream rspData = strm) { StreamReader rdr = new StreamReader(rspData); console.WriteLine("data, first line: '{0}'", rdr.ReadLine()); } } [MenuItem, SubMenu("OBEX")] public void Obex_Listener() { m_lsnrStop = false; Interlocked.Exchange(ref m_lsnrId, 0); ObexListener lstnr = null; ObexTransport? proto = null; while (lstnr == null) { int? i = console.ReadOptionalInteger("Which ObexListener transport: 1. Bluetooth, 2. IrDA, 3. TCP/IP"); if (!i.HasValue || i.Value == 1) { proto = ObexTransport.Bluetooth; lstnr = Create_ObexListener_Bluetooth(); } else { while (!proto.HasValue) { switch (i) { case 2: proto = ObexTransport.IrDA; break; case 3: proto = ObexTransport.Tcp; break; default: // (No Trace.Fail on NETCFv2) Debug.Assert(false, "invalid input: " + i); break; } } lstnr = new ObexListener(proto.Value); } } console.WriteLine("Created {0} ObexListener.", proto); // var auth = console.ReadYesNoCancel("Authenticate value (or don't set)", null); if (auth.HasValue) { lstnr.Authenticate = auth.Value; } console.WriteLine("get_Authenticate value: '{0}'", lstnr.Authenticate); var encrypt = console.ReadYesNoCancel("Encrypt value (or don't set)", null); if (encrypt.HasValue) { lstnr.Encrypt = encrypt.Value; } console.WriteLine("get_Encrypt value: '{0}'", lstnr.Encrypt); // lstnr.Start(); console.WriteLine("OBEX listening"); console.WriteLine("get_Authenticate value: '{0}'", lstnr.Authenticate); console.WriteLine("get_Encrypt value: '{0}'", lstnr.Encrypt); int? count = console.ReadOptionalInteger("How many acceptors threads? (1 by default)"); if (count == null) { count = 1; } console.WriteLine("Starting acceptor..."); for (int i = 0; i < count; ++i) { ThreadPool.QueueUserWorkItem(ObexListener_Worker, lstnr); } try { console.Pause("Un-pause to continue; and close listener"); } finally { m_lsnrStop = true; lstnr.Stop(); } } private volatile bool m_lsnrStop; private int m_lsnrId; void ObexListener_Worker(object state) { int id = Interlocked.Increment(ref m_lsnrId); while (true) { ObexListener lstnr = (ObexListener)state; if (m_lsnrStop || !lstnr.IsListening) { break; } ObexListenerContext ctx = null; try { ctx = lstnr.GetContext(); if (ctx == null) { console.WriteLine("{0}: OBEX null context!", id); continue; } console.WriteLine("{0}: OBEX accepted lContext", id); ObexListenerRequest req = ctx.Request; console.WriteLine("{0}: OBEX lRequest url: {1}, ContentLength64: {2}", id, req.RawUrl, req.ContentLength64); var ms = (MemoryStream)req.InputStream; console.WriteLine("{0}: InputStream.Len: {1}", id, ms.Length); } catch (Exception ex) { console.WriteLine("{0}: OBEX ctx/req fault: {1}", id, ex); } ctx = null; }//while } //-------- #if TEST_EARLY [MenuItem, SubMenu("Security etc")] public void SetPain() { BluetoothAddress addr = console.ReadBluetoothAddress("Address"); string passphrase = console.ReadLine("Passphrase"); using (BluetoothClient cli = new BluetoothClient()) { InTheHand.Net.Bluetooth.Widcomm.BOND_RETURN_CODE ret = cli.WidcommHack__SetPinX(addr, passphrase); console.WriteLine("Bond returned: {0} = 0x{1:X}", ret, (int)ret); } } #endif private BluetoothPublicFactory GetStackFactory() { var r = Get_BluetoothRadio(); if (r == null) { console.WriteLine("No radios."); throw new InvalidOperationException("No radios."); } return r.StackFactory; } [MenuItem, SubMenu("Security etc")] public void PairRequest() { BluetoothAddress addr = console.ReadBluetoothAddress("Address"); string passphrase = console.ReadLine("Passphrase"); if (string.IsNullOrEmpty(passphrase)) { bool makeNull = console.ReadYesNo("Do you want to use a null/Nothing passphrase", true); passphrase = makeNull ? null : string.Empty; } InTheHand.Net.Bluetooth.Factory.IBluetoothSecurity sec = GetStackFactory().BluetoothSecurity; bool ret = sec.PairRequest(addr, passphrase); console.WriteLine("PairRequest returned: {0}", ret); } [MenuItem, SubMenu("Security etc")] public void RemoveDevice() { BluetoothAddress addr = console.ReadBluetoothAddress("Address"); InTheHand.Net.Bluetooth.Factory.IBluetoothSecurity sec = GetStackFactory().BluetoothSecurity; bool ret = sec.RemoveDevice(addr); console.WriteLine("RemoveDevice returned: {0}", ret); } [MenuItem, SubMenu("Security etc")] public void SetPin() { string passphrase = console.ReadLine("Passphrase"); if (string.IsNullOrEmpty(passphrase)) { bool makeNull = console.ReadYesNo("Do you want to use a null/Nothing passphrase", true); passphrase = makeNull ? null : string.Empty; } BluetoothAddress addr = console.ReadBluetoothAddress("Address"); InTheHand.Net.Bluetooth.Factory.IBluetoothSecurity sec = GetStackFactory().BluetoothSecurity; bool ret = sec.SetPin(addr, passphrase); console.WriteLine("SetPin returned: {0}", ret); } [MenuItem, SubMenu("Security etc")] public void RevokePin() { BluetoothAddress addr = console.ReadBluetoothAddress("Address"); string passphrase = console.ReadLine("Passphrase"); if (string.IsNullOrEmpty(passphrase)) { bool makeNull = console.ReadYesNo("Do you want to use a null/Nothing passphrase", true); passphrase = makeNull ? null : string.Empty; } InTheHand.Net.Bluetooth.Factory.IBluetoothSecurity sec = GetStackFactory().BluetoothSecurity; bool ret = sec.RevokePin(addr); console.WriteLine("RevokePin returned: {0}", ret); } //-------- [MenuItem, SubMenu("MultiStack")] public void ListenerOnStack1ClientOnStack2() { BluetoothRadio[] radios = BluetoothRadio_GetAllAndDump(); Debug.Assert(radios != null, "Should't return null!"); if (radios.Length < 2) { console.WriteLine("Fewer that two radios were found ({0}).", radios.Length); return; } // ListenerOnStackAClientOnStackB(radios[0], radios[1]); } [MenuItem, SubMenu("MultiStack")] public void ListenerOnStack2ClientOnStack1() { BluetoothRadio[] radios = BluetoothRadio_GetAllAndDump(); Debug.Assert(radios != null, "Should't return null!"); if (radios.Length < 2) { console.WriteLine("Fewer that two radios were found ({0}).", radios.Length); return; } // ListenerOnStackAClientOnStackB(radios[1], radios[0]); } public void ListenerOnStackAClientOnStackB(BluetoothRadio radioLsnr, BluetoothRadio radioCli) { BluetoothListener lsnr = radioLsnr.StackFactory.CreateBluetoothListener(BluetoothService.Wap); BluetoothClient conn = null; BluetoothClient cli = null; try { lsnr.Start(); #if APM_LSNR IAsyncResult arLsnr = lsnr.BeginAcceptBluetoothClient(MiscCallback, "ListenerOnStack1ClientOnStack2"); #else ManualResetEvent accepted = new ManualResetEvent(false); WaitCallback dlgt = delegate(object state) { BluetoothListener lsnr_ = (BluetoothListener)state; try { conn = lsnr_.AcceptBluetoothClient(); console.WriteLine("Server got connection from : '{0}' {1}", conn.RemoteMachineName, conn.RemoteEndPoint); PrintLocalEndpointIfAvailable(conn); } catch (Exception ex) { console.WriteLine("Accept failed with: " + ex); } finally { accepted.Set(); } }; conn = null; ThreadPool.QueueUserWorkItem(dlgt, lsnr); #endif BluetoothEndPoint lep = lsnr.LocalEndPoint; console.WriteLine("Listener active on SCN: {0}", lep.Port); // cli = radioCli.StackFactory.CreateBluetoothClient(); BluetoothEndPoint rep = new BluetoothEndPoint(radioLsnr.LocalAddress, BluetoothService.Empty, lep.Port); console.WriteLine("Gonna connect to: {0}", rep); console.Pause("Un-pause to connect!"); cli.Connect(rep); console.WriteLine("Client Connected to : '{0}' {1}", cli.RemoteMachineName, cli.RemoteEndPoint); PrintLocalEndpointIfAvailable(cli); // #if APM_LSNR console.WriteLine("Lsnr.Accept.IsCompleted: {0}", arLsnr.IsCompleted); conn = lsnr.EndAcceptBluetoothClient(arLsnr); #else console.WriteLine("waiting for Lsnr.Accept completion event."); accepted.WaitOne(); Debug.Assert(conn != null, "Should have veen set by thread!"); #endif console.WriteLine("All success"); console.Pause("Un-pause to exit (and close both)"); } finally { if (lsnr != null) lsnr.Stop(); if (conn != null) conn.Dispose(); if (cli != null) cli.Dispose(); } } [MenuItem, SubMenu("MultiStack")] public void ObexWebRequest_MultiAsync() { BluetoothRadio[] radios = BluetoothRadio_GetAllAndDump(); Debug.Assert(radios != null, "Should't return null!"); if (radios.Length < 1) { console.WriteLine("No radios found."); return; } // List addrList = new List(); for (int i = 0; i < radios.Length; ++i) { BluetoothAddress addr = console.ReadBluetoothAddress( "Target device for radio #" + (i + 1)); addrList.Add(addr); }//for bool bigSend = console.ReadYesNo("Send big (1MB) or small?", false); byte[] bigBuf = null; if (bigSend) { bigBuf = new byte[1024 * 1024]; #if !NETCF Array.ForEach(bigBuf, delegate(byte cur) { cur = (byte)'a'; }); #endif } List arList = new List(addrList.Count); for (int i = 0; i < radios.Length; ++i) { BluetoothAddress addr = addrList[i]; Uri uri = new Uri(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}://{1}{2}", "obex", addr, "/obexpush1.txt")); BluetoothPublicFactory factory = radios[i].StackFactory; ObexWebRequest req = factory.CreateObexWebRequest(uri); using (Stream content = req.GetRequestStream()) { // Using a StreamWriter to write text to the stream... if (bigSend) { content.Write(bigBuf, 0, bigBuf.Length); } else { using (TextWriter wtr = new StreamWriter(content)) { wtr.WriteLine("Hello World GetRequestStream"); wtr.WriteLine("Hello World GetRequestStream 2"); wtr.Flush(); // Set the Length header value req.ContentLength = content.Length; } } } IAsyncResult ar = req.BeginGetResponse(null, req); arList.Add(ar); }//for // console.WriteLine("Waiting for all requests to complete..."); WaitAll(arList); console.WriteLine("All requests completed..."); // for (int i = 0; i < radios.Length; ++i) { IAsyncResult cur = arList[i]; ObexWebRequest req = (ObexWebRequest)cur.AsyncState; console.WriteLine("- - - #{1} - - -", null, (i + 1)); try { ObexWebResponse rsp = (ObexWebResponse)req.EndGetResponse(cur); console.WriteLine("#{1}. Response Code: {0} (0x{0:X})", rsp.StatusCode, (i + 1)); } catch (Exception ex) { console.WriteLine("#{1}. Failed: {0}", ex, (i + 1)); } }//for } //---- [MenuItem, SubMenu("Data")] public void SetReadTimeout() { if (_peer == null) { console.WriteLine("no connection"); return; } console.WriteLine("ReadTimeout: {0}", _peer.ReadTimeout); int? to = console.ReadOptionalInteger("New value"); if (to.HasValue) _peer.ReadTimeout = to.Value; } [MenuItem, SubMenu("Data")] public void SetWriteTimeout() { if (_peer == null) { console.WriteLine("no connection"); return; } console.WriteLine("WriteTimeout: {0}", _peer.WriteTimeout); int? v = console.ReadOptionalInteger("New value"); if (v.HasValue) _peer.WriteTimeout = v.Value; } //---- Stream _tcpConn; [MenuItem, SubMenu("SOCKETS")] public void TcpConnect() { string hostname = console.ReadLine("hostname"); int port = console.ReadInteger("port"); System.Net.Sockets.TcpClient cli = new System.Net.Sockets.TcpClient(hostname, port); _tcpConn = cli.GetStream(); } [MenuItem, SubMenu("SOCKETS")] public void TcpClose() { if (_tcpConn != null) { _tcpConn.Close(); } _tcpConn = null; } //---- [MenuItem, SubMenu("DeviceInfo")] public void GetDeviceInfo() { BluetoothAddress addr = console.ReadBluetoothAddress("Device Address"); BluetoothDeviceInfo device = Create_BluetoothDeviceInfo(addr); bool again; do { console.WriteLine(DumpDeviceInfo(device)); RadioVersions v; try { #if true v = device.GetVersions(); #elif false var w = device.GetImpl(); if (w != null) { v = w.GetVersions(); } #endif } catch (Exception ex) { console.WriteLine("GetVersions error: " + Exception_FirstLine(ex)); var w32ex = ex as Win32Exception; if (w32ex != null) { console.WriteLine(" NativeErrorCode: " + w32ex.NativeErrorCode); } goto afterDisplayVersion; } if (v == null) { console.WriteLine("GetVersions returned null!!!!!!!!!!!!!"); } else { console.WriteLine(DumpVersions(v)); } afterDisplayVersion: // again = console.ReadYesNo("Display same one again", false); if (again) { var doSdp = console.ReadYesNo("Do SDP to", false); if (doSdp) { device.BeginGetServiceRecords(BluetoothService.L2CapProtocol, null, null); } } } while (again); } [MenuItem, SubMenu("DeviceInfo")] public void GetDeviceInfoAndConnect() { Action dlgtDevInfo = delegate(BluetoothAddress addrX) { BluetoothDeviceInfo device = Create_BluetoothDeviceInfo(addrX); console.WriteLine("name0: " + ToStringQuotedOrNull(device.DeviceName)); console.WriteLine("name1: " + ToStringQuotedOrNull(device.DeviceName)); }; Action dlgtConn = delegate(BluetoothAddress addrX) { Thread.Sleep(1500); console.WriteLine("Connecting..."); ConnectSimpleClosingFirstPart2(addrX); }; // BluetoothAddress addrDev0 = console.ReadBluetoothAddress("Device Address for DeviceInfo"); BluetoothAddress addrConn = console.ReadBluetoothAddress("Device Address for Connect"); long addrTmpl = addrDev0.ToInt64(); var arrArBdi = new IAsyncResult[4]; // new BluetoothClient(); // Init the stack in case the user forgot to do so before. var ar = DelegateExtension.BeginInvoke(dlgtConn, addrConn, null, null); for (int i = 0; i < arrArBdi.Length; ++i) { arrArBdi[i] = DelegateExtension.BeginInvoke(dlgtDevInfo, new BluetoothAddress(addrTmpl++), null, null); } try { DelegateExtension.EndInvoke(dlgtConn, ar); console.WriteLine("connect success"); } catch (System.Net.Sockets.SocketException) { console.WriteLine("connect fail"); } foreach (var curAr in arrArBdi) { DelegateExtension.EndInvoke(dlgtDevInfo, curAr); } } [MenuItem, SubMenu("DeviceInfo")] public void SetServiceState() { BluetoothAddress addr = console.ReadBluetoothAddress("Device Address"); Guid? svcClass = console.ReadOptionalBluetoothUuid("Service Class (default SPP)", null); if (svcClass == null) svcClass = BluetoothService.SerialPort; console.WriteLine("Service: {0}", svcClass); BluetoothDeviceInfo device = Create_BluetoothDeviceInfo(addr); console.WriteLine(DumpDeviceInfoBrief(device)); bool state = console.ReadYesNo("Enable/Disable the service", true); console.WriteLine("Will set the service to: " + state); device.SetServiceState(svcClass.Value, state, true); } [MenuItem, SubMenu("DeviceInfo")] public void GetInstalledServices() { BluetoothAddress addr = console.ReadBluetoothAddress("Device Address"); BluetoothDeviceInfo device = Create_BluetoothDeviceInfo(addr); console.WriteLine(DumpDeviceInfoBrief(device)); var guidList = device.InstalledServices; console.WriteLine("{0} of", guidList.Length); foreach (var cur in guidList) { var name = BluetoothService.GetName(cur); //var shortI = BluetoothService.CreateBluetoothUuid( console.WriteLine("* {0} aka {1}", cur, name); } } #if !ANDROID [MenuItem, SubMenu("WidcommPlaying")] public void WidcommIsPresentConnected() { BluetoothAddress addr = console.ReadBluetoothAddress("Device Address"); InTheHand.Net.Bluetooth.Widcomm.RemoteDeviceState state = new InTheHand.Net.Bluetooth.Widcomm.WidcommPlaying().FindIfPresentOrConnected(addr); console.WriteLine("state: {0}", state); } [MenuItem, SubMenu("WidcommPlaying")] public void DoPowerDownUpReset() { var p = new InTheHand.Net.Bluetooth.Widcomm.WidcommPlaying(); var prev = p.DoPowerDownUpReset; var set = console.ReadYesNoCancel(string.Format( "DoPowerDownUpReset current: {0}. Set to", prev), null); if (set.HasValue) { p.DoPowerDownUpReset = set.Value; } console.WriteLine("DoPowerDownUpReset set: {0}, was: {1}.", set, prev); } #endif //---- #if !ANDROID [MenuItem, SubMenu("Serial")] public void SerialPorts_List() { #if !NETCF SerialPortsListWmi(); #else SerialPortsListWmRegistry(); #endif //---- console.WriteLine("SerialPort.GetPortNames..."); string[] nameList = System.IO.Ports.SerialPort.GetPortNames(); console.WriteLine("SerialPort.GetPortNames: {0}", string.Join(", ", nameList)); } #if NETCF private void SerialPortsListWmRegistry() { //console.WriteLine("SerialPortsListWmRegistry"); using (var portsK = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\Bluetooth\Serial\Ports", false)) { if (portsK == null) { console.WriteLine("Bluetooth COM port configuration is missing."); return; } foreach (var devKeyName in portsK.GetSubKeyNames()) { BluetoothAddress addr; try { addr = BluetoothAddress.Parse(devKeyName); } catch (FormatException) { console.WriteLine("Error: key name is not a device address: '{0}'", devKeyName); continue; } console.WriteLine("DeviceID: {0} ", addr); using (var devKey = portsK.OpenSubKey(devKeyName)) { var portN0 = devKey.GetValue("Port"); var portN1 = portN0 as string; var portN = TruncateAtZeros(portN1); console.WriteLine("PortName: '{0}'", portN); } }//for } } string TruncateAtZeros(string value) { if (value == null) return null; string result = value; int idx = value.IndexOf((char)0); if (idx != -1) { result = value.Substring(0, idx); } #if DUMP_TRUNCATED_STRING_CONTENT if (value.Length != result.Length) { console.WriteLine("(Zero in string!! ({0}vs{1}))", value.Length, result.Length); // (No Array.ForEach etc in NETCF) StringBuilder bldr = new StringBuilder(); foreach (var ch in value.ToCharArray()) { if (char.IsControl(ch)) bldr.AppendFormat(CultureInfo.InvariantCulture, "\\x{0:x4}", (ushort)ch); else bldr.Append(ch); } console.WriteLine("([{0}])", bldr.ToString()); } #endif return result; } #endif #if !NETCF private void SerialPortsListWmi() { const string Win32_SerialPort = "Win32_SerialPort"; #if false // Either work console.WriteLine("Running query..."); System.Management.SelectQuery q = new System.Management.SelectQuery(Win32_SerialPort); System.Management.ManagementObjectSearcher s = new System.Management.ManagementObjectSearcher(q); #else console.WriteLine("Running WMI query..."); System.Management.ManagementObjectSearcher s = new System.Management.ManagementObjectSearcher( "SELECT DeviceID,PNPDeviceID FROM " + Win32_SerialPort); #endif console.WriteLine("Getting results..."); System.Management.ManagementObjectCollection list = s.Get(); console.WriteLine("Enumerating results..."); foreach (System.Management.ManagementBaseObject cur in list) { object id = cur.GetPropertyValue("DeviceID"); object pnpId = cur.GetPropertyValue("PNPDeviceID"); console.WriteLine("DeviceID: {0} ", id); console.WriteLine("PNPDeviceID: {0} ", pnpId); console.WriteLine(""); }//for } #endif SerialPort SerialPortCreate() { var nameNum = console.ReadOptionalInteger("Port -- if numerical 'COMx'"); string name; if (nameNum != null) { name = "COM" + nameNum.ToString(); } else { name = console.ReadLine("Port name"); } var bitrate = console.ReadOptionalInteger("Bit rate"); System.IO.Ports.SerialPort port; if (bitrate == null) { console.WriteLine("Connecting to port '{0}'.", name); port = new System.IO.Ports.SerialPort(name); } else { console.WriteLine("Connecting to port '{0}' at bitrate '{1}'.", name, bitrate.Value); port = new System.IO.Ports.SerialPort(name, bitrate.Value); } return port; } [MenuItem, SubMenu("Serial")] public void SerialPort_GetDefaults() { string name = console.ReadLine("(Serial) Device Name"); console.WriteLine("(Serial) Device Name: {0}", name); var cc = new Foo.COMMCONFIG(null); uint size = checked((uint)cc.dwSize); bool success = Foo.NativeMethods.GetDefaultCommConfig(name, ref cc, ref size); var gle = Marshal.GetLastWin32Error(); if (!success) { console.WriteLine("Failed: " + gle); return; } console.WriteLine("dwProviderSubType: {0}, baud: {1}, size: {2} (provider offset: {3}, size: {4})", cc.dwProviderSubType, cc.dcb.BaudRate, cc.dwSize, cc.dwProviderOffset, cc.dwProviderSize); } static class Foo { internal static class NativeMethods { [DllImport("kernel32.dll", SetLastError = true)] internal static extern bool GetDefaultCommConfig(string lpszName, [In, Out] ref COMMCONFIG lpCC, ref uint lpdwSize); } [StructLayout(LayoutKind.Sequential)] internal struct DCB { public Int32 DCBLength; public Int32 BaudRate; public Int32 fBitField; public Int16 wReserved; public Int16 XonLim; public Int16 XoffLim; public Byte ByteSize; public Byte Parity; public Byte StopBits; public Char XonChar; public Char XoffChar; public Char ErrorChar; public Char EofChar; public Char EvtChar; public Int32 wReserved1; } [StructLayout(LayoutKind.Sequential)] internal struct COMMCONFIG { public Int32 dwSize; public Int16 wVersion; public Int16 wReserved; public DCB dcb; public Int32 dwProviderSubType; public Int32 dwProviderOffset; public Int32 dwProviderSize; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 200/*e.g.*/)] public byte[] ProviderData; public COMMCONFIG(object fake) : this() { this.dwSize = Marshal.SizeOf(this); } } } [MenuItem, SubMenu("Serial")] public void SerialPortCo_nnect() { var port = SerialPortCreate(); port.Open(); _peer = port.BaseStream; } [MenuItem, SubMenu("Serial")] public void SerialPort_ConnectAlsoUsePortEvents() { var port = SerialPortCreate(); port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived); port.ErrorReceived += new SerialErrorReceivedEventHandler(port_ErrorReceived); port.PinChanged += new SerialPinChangedEventHandler(port_PinChanged); port.Open(); _peer = port.BaseStream; } void port_PinChanged(object sender, SerialPinChangedEventArgs e) { console.WriteLine("Port PinChanged: " + e.EventType); } void port_ErrorReceived(object sender, SerialErrorReceivedEventArgs e) { console.WriteLine("Port Error: " + e.EventType); } void port_DataReceived(object sender, SerialDataReceivedEventArgs e) { console.WriteLine("Port Rcv: " + e.EventType); } #endif [MenuItem, SubMenu("Serial")] public void OpenFileStream() { string name = console.ReadLine("File/port name"); _peer = new FileStream(name, FileMode.Open); } //---- #if !ANDROID #if NETCF InTheHand.Net.Ports.BluetoothSerialPort _btSerialPort; #endif InTheHand.Net.Bluetooth.Widcomm.WidcommSerialPort _wcSerialPort; [MenuItem, SubMenu("Serial")] public void BtWcSerialPortCliClose() { #if NETCF _btSerialPort.Close(); _btSerialPort = null; #endif _wcSerialPort.Close(); _wcSerialPort = null; } [MenuItem, SubMenu("Serial")] public void BtWcSerialPortCliNullNoDispose() { #if NETCF _btSerialPort = null; #endif _wcSerialPort = null; } #if NETCF [MenuItem, SubMenu("Serial")] public void BtSerialPortCliConnect() { var addr = console.ReadBluetoothAddress("target"); var addrWithSpp = new BluetoothEndPoint(addr, BluetoothService.SerialPort); var spp = InTheHand.Net.Ports .BluetoothSerialPort.CreateClient(addrWithSpp); console.WriteLine("Success: {0}", spp.PortName); _btSerialPort = spp; } #endif [MenuItem, SubMenu("Serial")] public void WcSerialPortCliConnect() { var addr = console.ReadBluetoothAddress("Target Device"); var count = console.ReadOptionalInteger("Repeat count"); console.WriteLine(null); Converter open = addrI => { var spp = InTheHand.Net.Bluetooth.Widcomm .WidcommSerialPort.CreateClient(addrI); console.WriteLine("Success: {0}", spp.PortName); return spp; }; // if (count == null) { _wcSerialPort = open(addr); } else { for (int i = 0; i < count; ++i) { using (var spp = open(addr)) { } }//for } } #endif //-------- [MenuItem, SubMenu("SOCKETS")] public void TestsSocketsAndSockaddr() { Converter createSocket = delegate(bool unspecificProto) { System.Net.Sockets.Socket s0; if (unspecificProto) s0 = new System.Net.Sockets.Socket( AddressFamily32.Bluetooth, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Unspecified); else s0 = new System.Net.Sockets.Socket( AddressFamily32.Bluetooth, System.Net.Sockets.SocketType.Stream, BluetoothProtocolType.RFComm); return s0; }; BluetoothEndPoint ep; System.Net.Sockets.Socket s; // int step = 0; console.WriteLine("#{0}, gonna createSocket(false)", ++step); s = createSocket(false); ep = new BluetoothEndPoint( BluetoothAddress.None, BluetoothService.ObexFileTransfer); console.WriteLine("#{0}, gonna Bind", ++step); // Bind None/FTP/None try { s.Bind(ep); } catch (Exception ex) { console.WriteLine(ex); } ep = new BluetoothEndPoint( BluetoothAddress.Parse("12345679abcd"), BluetoothService.ObexObjectPush); console.WriteLine("#{0}, gonna Connect", ++step); // Connect Foo/OPP/None try { s.Connect(ep); } catch (Exception ex) { console.WriteLine(ex); } // console.WriteLine("#{0}, gonna createSocket(false)", ++step); s = createSocket(false); ep = new BluetoothEndPoint( BluetoothAddress.None, BluetoothService.ObexFileTransfer, unchecked((Int32)0xF2345678)); console.WriteLine("#{0}, gonna Bind", ++step); // Bind None/FTP/Bar try { s.Bind(ep); } catch (Exception ex) { console.WriteLine("Excepted failure"); console.WriteLine(ex); } // ep = new BluetoothEndPoint( BluetoothAddress.None, BluetoothService.ObexFileTransfer, 0x45); console.WriteLine("#{0}, gonna Bind", ++step); // Bind None/FTP/Bar try { s.Bind(ep); } catch (Exception ex) { console.WriteLine(ex); } // ep = new BluetoothEndPoint( BluetoothAddress.Parse("12345679abcd"), BluetoothService.Fax, 0x45); console.WriteLine("#{0}, gonna Connect", ++step); // Connect Foo/OPP/Bar try { s.Connect(ep); } catch (Exception ex) { console.WriteLine(ex); } // console.WriteLine("#{0}, gonna createSocket(true)", ++step); try { s = createSocket(true); } catch (System.Net.Sockets.SocketException ex) { const int WSAEPROTOTYPE = 10041; #if NETCF if (ex.ErrorCode != WSAEPROTOTYPE) throw; #else if (ex.SocketErrorCode != System.Net.Sockets.SocketError.ProtocolType) throw; #endif Debug.Assert(ex.NativeErrorCode == WSAEPROTOTYPE); console.WriteLine("(Somewhat) expected failure; how to get 'Unspecified' behaviour supported?"); console.WriteLine(ex); } } [MenuItem, SubMenu("SOCKETS")] public void TryAllMsftSocketOptions() { var wr = _cli; BluetoothClient cli = null; if (wr == null || (cli = wr.Target) == null) { console.WriteLine("No BluetoothClient available, do a Connect/Accept."); return; } var sock = cli.Client; // Do one get option manually. { System.Net.Sockets.SocketOptionName option; #if NETCF option = BluetoothSocketOptionName.GetMtu; #else option = BluetoothSocketOptionName.XPMtu; #endif var v = sock.GetSocketOption(BluetoothSocketOptionLevel.RFComm, option); var i = (int)v; console.WriteLine("Option MTU value: {0}=0x{0:X}", i); } // Do all known options. var nameFiList = typeof(BluetoothSocketOptionName).GetFields( BindingFlags.Static | BindingFlags.Public); foreach (var curField in nameFiList) { var curOpt = (System.Net.Sockets.SocketOptionName)curField.GetValue(null); var curName = curField.Name; string txtOpt = (int)curOpt >= 0 ? ((int)curOpt).ToString() : "0x" + ((int)curOpt).ToString("X8"); console.Write("Option: {0,24} {1,11} : ", curName, txtOpt); try { var v = sock.GetSocketOption(BluetoothSocketOptionLevel.RFComm, curOpt); var i = (int)v; console.WriteLine("value: {0}=0x{0:X}", i); } catch (System.Net.Sockets.SocketException soex) { console.WriteLine("error: " + SocketException_Codes(soex)); } }//for } //-------- [MenuItem, SubMenu("DeviceInfo")] public void RssiRepeated() { console.WriteLine("Stack: {0}", Get_BluetoothRadio().SoftwareManufacturer); BluetoothAddress addr = console.ReadBluetoothAddress("Address of device to read RSSI for"); bool doSdp = console.ReadYesNo("Do concurrent repeated SDP Query", true); // _quitRepeatRssiing.Reset(); try { ThreadPool.QueueUserWorkItem(RepeatRssiing_ReadRssi, addr); if (doSdp) { // Doing SDP queries to force forming a connection. ThreadPool.QueueUserWorkItem(RepeatRssiing_DoSdp, addr); } console.WriteLine(null); console.Pause("Un-pause to stop RSSI-ing"); } finally { _quitRepeatRssiing.Set(); } } ManualResetEvent _quitRepeatRssiing = new ManualResetEvent(false); void RepeatRssiing_ReadRssi(object state) { BluetoothAddress addr = (BluetoothAddress)state; int delayMs = 1000; BluetoothDeviceInfo info = Create_BluetoothDeviceInfo(addr); int? lastRssi = null; while (!_quitRepeatRssiing.WaitOne(delayMs, false)) { int rssi = info.Rssi; console.Write("r"); if (rssi != lastRssi) { lastRssi = rssi; console.WriteLine(null); console.WriteLine("{0:T}: RSSI now: {1}", DateTime.Now, rssi); } }//while } void RepeatRssiing_DoSdp(object state) { Thread.Sleep(5000); // show rssi not available when not connected // BluetoothAddress addr = (BluetoothAddress)state; int delayMs = 1000; BluetoothDeviceInfo info = Create_BluetoothDeviceInfo(addr); while (!_quitRepeatRssiing.WaitOne(delayMs, false)) { ServiceRecord[] records = info.GetServiceRecords(BluetoothService.TcpProtocol); console.Write("s"); }//while } //-------- #if RADIO_MODESSS [MenuItem, SubMenu("Local")] public void SetModesss() { BluetoothRadio r = Get_BluetoothRadio(); if (r == null) { console.WriteLine("No radio(?)"); return; } console.WriteLine("Radio stack is: {0}", r.SoftwareManufacturer); var conno = console.ReadYesNoCancel("Connectable (on/off/leave)", null); var disco = console.ReadYesNoCancel("Discoverable (on/off/leave)", null); bool doit = console.ReadYesNo("Set radio mode to: c=" + conno + " d=" + disco, true); if (doit) { console.WriteLine("Setting Modes({0},{1})", conno, disco); r.SetMode(conno, disco); } } #endif [MenuItem, SubMenu("Local")] public void SetMode() { BluetoothRadio r = Get_BluetoothRadio(); if (r == null) { console.WriteLine("No radio(?)"); return; } console.WriteLine("Radio stack is: {0}", r.SoftwareManufacturer); int choice = console.ReadInteger("0. PowerOff, 1. Connectable, 2. Discoverable"); RadioMode mode = (RadioMode)choice; bool doit = console.ReadYesNo("Set radio mode to: " + mode, true); if (doit) { r.Mode = mode; } } [MenuItem, SubMenu("Local")] public void SetAllModes() { BluetoothRadio r_ = Get_BluetoothRadio(); if (r_ == null) { console.WriteLine("No radio(?)"); return; } console.WriteLine("Radio stack is: {0}", r_.SoftwareManufacturer); var doIt = console.ReadYesNo("Do Set All Modes", false); if (!doIt) return; // // o->c, o->d; c->o, c->d; d->o, d->c. var stateList = new RadioMode[] { RadioMode.PowerOff, RadioMode.Connectable, RadioMode.Connectable, RadioMode.Discoverable, RadioMode.PowerOff, RadioMode.Discoverable, RadioMode.Discoverable, RadioMode.Connectable, RadioMode.PowerOff, RadioMode.PowerOff, }; int i; var originalMode = r_.Mode; console.WriteLine("Running test, using same radio instance each time."); i = 0; var r0 = r_; foreach (var cur in stateList) { console.Write(" Set {0,12}, ", cur); var ts = RunAndTime(delegate { r0.Mode = cur; }); RadioMode? got = null; var tg = RunAndTime(delegate { got = r0.Mode; }); if (got != cur) console.Write("error at {0} expected {1} was {2}, ", i, cur, got); console.WriteLine("set: {0,-16}, get: {1,-16}", ts, tg); ++i; }//for console.WriteLine("Done {0} tests.", i); console.WriteLine("Do test again, using new radio instance each time."); i = 0; foreach (var cur in stateList) { var rx = Get_BluetoothRadio(); if (rx == null) { console.WriteLine("error at {0} radio is null!", i); goto next; } console.Write(" Set {0,12}, ", cur); var ts = RunAndTime(delegate { rx.Mode = cur; }); RadioMode? got = null; var tg = RunAndTime(delegate { got = rx.Mode; }); if (got != cur) console.Write("error at {0} expected {1} was {2}, ", i, cur, got); console.WriteLine("set: {0,-16}, get: {1,-16}", ts, tg); next: ++i; }//for console.WriteLine("Done {0} tests.", i); r_.Mode = originalMode; } [MenuItem, SubMenu("Local")] public void SetName() { BluetoothRadio r = Get_BluetoothRadio(); if (r == null) { console.WriteLine("No radio(?)"); return; } console.WriteLine("Radio stack is: {0}", r.SoftwareManufacturer); var name = console.ReadLine("New Name"); bool doit = console.ReadYesNo("Set radio name to: " + name, true); if (doit) { r.Name = name; } } //-------- [MenuItem, SubMenu("Data")] public void CloseLinger() { if (!VerifyConnectionWrite()) return; BluetoothClient cli = _cli.Target; if (cli == null) { console.WriteLine("No BtCli to set LingerState on!."); return; } cli.LingerState = new System.Net.Sockets.LingerOption(true, 30); // Write until buffers full List arList = new List(); byte[] buf = new byte[16 * 1024]; bool exitAfterNext = false; while (true) { IAsyncResult ar = _peer.BeginWrite(buf, 0, buf.Length, MiscCallback, "BeginWrite"); arList.Add(ar); console.Write("."); if (exitAfterNext) break; if (!ar.IsCompleted) { bool signalled = ar.AsyncWaitHandle.WaitOne(10000, false); if (!signalled) { exitAfterNext = true; } } }//while console.WriteLine("Did BeginWrite until full ({0} times).", arList.Count); // console.WriteLine("Now going to Close. Release receiver to not linger timeout."); console.Pause("Un-pause to Close"); console.WriteLine("Closing at {0}", GetTime()); DateTime startT = DateTime.UtcNow; try { _peer.Close(); string end = GetTime(); console.WriteLine("Close exited cleanly at {0} after {1}.", end, DateTime.UtcNow - startT); } catch (Exception ex) { // We throw Exception currently! string end = GetTime(); console.WriteLine("Close failed at {0} after {1} with: {2}", end, DateTime.UtcNow - startT, ex); } // int i = 0; console.Write("Write statuses (. or x, where x=exception): "); foreach (IAsyncResult cur in arList) { if (!cur.IsCompleted) { console.WriteLine("Write #{0} is not completed!", i + 1); } try { _peer.EndWrite(cur); console.Write("."); } catch (IOException) { console.Write("x"); } ++i; }//for console.WriteLine(null); console.WriteLine("Finished."); } //-------- [MenuItem, SubMenu("Playing")] public void HackShutdownAll() { InTheHand.Net.Bluetooth.Factory.BluetoothFactory.HackShutdownAll(); console.WriteLine("Done HackShutdownAll"); } //-------- #if NETCF [MenuItem, SubMenu("Playing")] public void HidEnable_NotCompletedTesting() { IntPtr h = CreateFile("BHI0:", 0, 0, IntPtr.Zero, CreateFile__OPEN_EXISTING, 0, IntPtr.Zero); if (h == IntPtr.Zero || h == (IntPtr)(-1)) { int err = Marshal.GetLastWin32Error(); console.WriteLine("CreateFile(BHI0:) returned: {0}, gle: {1} = 0x{1:X}", h, err); return; } console.WriteLine("CreateFile(BHI0:) SUCCESS"); //console.WriteLine("Skipping for now!!!!!!"); //return; //---- int tmp; BluetoothAddress addr = console.ReadBluetoothAddress("Device address"); byte[] addrBytes = addr.ToByteArray(); bool ret = DeviceIoControl(h, BTHHID_IOCTL_HIDConnect, addrBytes, addrBytes.Length, IntPtr.Zero, 0, out tmp, IntPtr.Zero); int err2 = Marshal.GetLastWin32Error(); console.WriteLine("DeviceIoControl(h, BTHHID_IOCTL_HIDConnect) ret: {0}", ret); if (!ret) { console.WriteLine("DeviceIoControl(h, BTHHID_IOCTL_HIDConnect) gle: {0} = 0x{0:X}", err2); } } // http://read.pudn.com//downloads123/sourcecode/embed/523853/BLUETOOTH/PROFILES/HID/BASE/hidioctl.h__.htm const int BTHHID_IOCTL_HIDConnect = 1; const int BTHHID_IOCTL_HIDVerify = 2; const int CreateFile__OPEN_EXISTING = 3; [System.Runtime.InteropServices.DllImport("coredll.dll", SetLastError = true)] static extern IntPtr CreateFile(string lpFileName, UInt32 dwDesiredAccess, UInt32 dwShareMode, IntPtr lpSecurityAttributes, UInt32 dwCreationDisposition, UInt32 dwFlagsAndAttributes, IntPtr hTemplateFile); [System.Runtime.InteropServices.DllImport("coredll.dll", SetLastError = true)] private static extern bool DeviceIoControl(IntPtr hDevice, int dwIoControlCode, byte[] lpInBuffer, int nInBufferSize, byte[] lpOutBuffer, int nOutBufferSize, out int lpBytesReturned, IntPtr lpOverlapped); [System.Runtime.InteropServices.DllImport("coredll.dll", SetLastError = true)] private static extern bool DeviceIoControl(IntPtr hDevice, int dwIoControlCode, byte[] lpInBuffer, int nInBufferSize, IntPtr lpOutBuffer, int nOutBufferSize, out int lpBytesReturned, IntPtr lpOverlapped); [System.Runtime.InteropServices.DllImport("coredll.dll", SetLastError = true)] private static extern bool DeviceIoControl(IntPtr hDevice, int dwIoControlCode, IntPtr lpInBuffer, int nInBufferSize, IntPtr lpOutBuffer, int nOutBufferSize, out int lpBytesReturned, IntPtr lpOverlapped); #endif #if NETCF [System.Runtime.InteropServices.DllImport("coredll.dll", SetLastError = true, CharSet = CharSet.Unicode)] private static extern int EnumDevices([Out]char[] devList, ref int bufLen); [MenuItem, SubMenu("Playing")] public void EnumDevices() { var buf = new char[4096]; int bufLen = buf.Length; // Docs don't say measured in bytes or wchars! Be conservative //const int ERROR_MORE_DATA = 234; var ret = EnumDevices(buf, ref bufLen); if (ret != 0) { console.WriteLine("!! EnumDevices failed: {0}", ret); } int dbgCharsUsed; var list = ParseDoubleNullTerminatedStrings(buf, out dbgCharsUsed); Debug.Assert(dbgCharsUsed * 2 == bufLen, "is measured in bytes"); var x = list.Count; const string Sep = ", "; var all = string.Join(Sep, list.ToArray()); console.WriteLine(all); // // TestParseDoubleNullTerminatedStrings(); } private static List ParseDoubleNullTerminatedStrings(char[] buf, out int dbgCharsUsed) { int idx = 0; var list = new List(); while (true) { if (buf[idx] == 0) { break; } var idxEnd = Array.IndexOf(buf, (char)0, idx); var len = idxEnd - idx; var str = new string(buf, idx, len); list.Add(str); idx = idxEnd + 1; } dbgCharsUsed = idx + 1; return list; } static void TestParseDoubleNullTerminatedStrings() { var buf = new char[30]; List list; const char NullChar = (char)0; // list = DoTestParse(new char[]{ 'a','b','c',NullChar, 'e','f',NullChar, 'm','n','o','p',NullChar, NullChar }); Assert_AreEqual(3, list.Count, "A Count"); Assert_AreEqual(3, list[0].Length, "A0 Len"); Assert_AreEqual("abc", list[0], "A0 Count"); Assert_AreEqual(2, list[1].Length, "A1 Len"); Assert_AreEqual("ef", list[1], "A1"); Assert_AreEqual(4, list[2].Length, "A2 Len"); Assert_AreEqual("mnop", list[2], "A2"); // // Null at start -- (like first is empty) list = DoTestParse(new char[]{ NullChar, NullChar }); Assert_AreEqual(0, list.Count, "00 B list.Count"); // // None -- NOT double null, is valid list = DoTestParse(new char[]{ NullChar,'*','*'}); Assert_AreEqual(0, list.Count, "C Count"); // // First is empty -- same as all empty list = DoTestParse(new char[]{ NullChar, 'e','f',NullChar, NullChar }); Assert_AreEqual(0, list.Count, "D Count"); // // Second is empty -- same as termination list = DoTestParse(new char[]{ 'a','b','c',NullChar, NullChar, 'm','n','o','p',NullChar, NullChar }); Assert_AreEqual(1, list.Count, "E Count"); Assert_AreEqual(3, list[0].Length, "E0 Len"); Assert_AreEqual("abc", list[0], "E0 Count"); } private static void FillWithRubbish(char[] buf) { for (int i = 0; i < buf.Length; ++i) buf[i] = 'z'; } private static void Assert_AreEqual(int expected, int actual, string name) { if (expected != actual) throw new RankException(name); } private static void Assert_AreEqual(string expected, string actual, string name) { if (expected != actual) throw new RankException(name); } private static List DoTestParse(char[] content) { char[] buf; // buf = new char[content.Length * 2]; FillWithRubbish(buf); content.CopyTo(buf, 0); int dbgUsed; var list = ParseDoubleNullTerminatedStrings(buf, out dbgUsed); //TODO assert on dbgUsed return list; #if false // buf = new char[content.Length]; FillWithRubbish(buf); content.CopyTo(buf, 0); list = ParseDoubleNullTerminatedStrings(buf, buf.Length); #endif } #endif //-------- #if !NETCF [MenuItem] public void Win32EventsNew() { var r = Get_BluetoothRadio(); // Better be MSFT+Win32 radio!!! using (var x = new BluetoothWin32Events(r)) { x.InRange += HandleWin32InRange; x.OutOfRange += HandleWin32OutOfRange; console.Pause("Continue to stop getting events"); } } [MenuItem] public void Win32EventsShared() { var r = Get_BluetoothRadio(); // Better be MSFT+Win32 radio!!! var x = BluetoothWin32Events.GetInstance(); try { x.InRange += HandleWin32InRange; x.OutOfRange += HandleWin32OutOfRange; console.Pause("Continue to stop getting events"); } finally { x.InRange -= HandleWin32InRange; x.OutOfRange -= HandleWin32OutOfRange; } } void HandleWin32InRange(object sender, BluetoothWin32RadioInRangeEventArgs e) { console.WriteLine("{0}: InRange {1} '{2}', now '{3}' was '{4}'.", GetTimeWallclockHR(), e.Device.DeviceAddress, e.Device.DeviceName, e.CurrentState, e.PreviousState); } void HandleWin32OutOfRange(object sender, BluetoothWin32RadioOutOfRangeEventArgs e) { console.WriteLine("{0}: OutOfRange {1} '{2}'.", GetTimeWallclockHR(), e.Device.DeviceAddress, e.Device.DeviceName); } #endif #if !NETCF && false [MenuItem, SubMenu("Playing")] public void AllIoctls() { console.WriteLine("Output is on Debug.Write..."); InTheHand.Net.Bluetooth.Msft.MsftPlaying.AllIoctls(); } [MenuItem, SubMenu("Playing")] public void AuthDeviceExFakeOob() { var device = console.ReadBluetoothAddress("target"); byte[] oobData; int ret; // oobData = new byte[16]; new Random().NextBytes(oobData); ret = InTheHand.Net.Bluetooth.Msft.MsftPlaying.AuthDeviceExFakeOob( device, oobData); console.WriteLine("ret: {0} = 0x{0:X}", ret); } [MenuItem, SubMenu("Playing")] public void AuthDeviceExFakeOob_ThreeWays() { var device = console.ReadBluetoothAddress("target"); byte[] oobData; int ret; // oobData = new byte[16]; new Random().NextBytes(oobData); ret = InTheHand.Net.Bluetooth.Msft.MsftPlaying.AuthDeviceExFakeOob( device, oobData); console.WriteLine("ret: {0} = 0x{0:X}", ret); // oobData = new byte[32]; ret = InTheHand.Net.Bluetooth.Msft.MsftPlaying.AuthDeviceExFakeOob( device, oobData); console.WriteLine("ret: {0} = 0x{0:X}", ret); // oobData = null; ret = InTheHand.Net.Bluetooth.Msft.MsftPlaying.AuthDeviceExFakeOob( device, oobData); console.WriteLine("ret: {0} = 0x{0:X}", ret); } #endif #if false [MenuItem, SubMenu("Playing")] public void BlueZSdpDumpSdpBlueZDbus() { var b = new ServiceRecordBuilder(); b.AddServiceClass(0x1105); b.AddServiceClass(BluetoothService.SerialPort); b.AddServiceClass(0x12345); // b.AddCustomAttribute(0x500, ElementType.Boolean, false); b.AddCustomAttribute(0x501, ElementType.Boolean, true); b.AddCustomAttribute(0x511, ElementType.Nil, null); // // UUID128 (AddServiceClass shortens automatically) b.AddCustomAttribute(0x1000, ElementType.Uuid128, BluetoothService.SerialPort); var g128 = new Guid("{54D39E6A-2AF2-47dd-BB14-59C476CF2848}"); b.AddCustomAttribute(0x1001, ElementType.Uuid128, g128); // b.AddCustomAttribute(0x6000 + (ushort)ElementType.UInt8, ElementType.UInt8, (int)ElementType.UInt8); b.AddCustomAttribute(0x6000 + (ushort)ElementType.UInt16, ElementType.UInt16, 0xfe00 + (int)ElementType.UInt16); b.AddCustomAttribute(0x6000 + (ushort)ElementType.UInt32, ElementType.UInt32, 0xfe00 + (int)ElementType.UInt32); b.AddCustomAttribute(0x6000 + (ushort)ElementType.UInt64, ElementType.UInt64, 0xfe00 + (int)ElementType.UInt64); var arr128 = new byte[16]; arr128[0] = 0xfe; arr128[15] = (byte)ElementType.UInt64; //b.AddCustomAttribute(0x6000 + (ushort)ElementType.UInt128, ElementType.UInt128, arr128); //b.AddCustomAttribute(new ServiceAttribute(0x6000 + (ushort)ElementType.UInt128, // new ServiceElement(ElementType.UInt128, arr128))); // b.AddCustomAttribute(0x7000 + (ushort)ElementType.Int8, ElementType.Int8, (int)ElementType.Int8); b.AddCustomAttribute(0x7000 + (ushort)ElementType.Int16, ElementType.Int16, 0x7e00 + (int)ElementType.Int16); b.AddCustomAttribute(0x7000 + (ushort)ElementType.Int32, ElementType.Int32, 0x7e00 + (int)ElementType.Int32); b.AddCustomAttribute(0x7000 + (ushort)ElementType.Int64, ElementType.Int64, 0x7e00 + (int)ElementType.Int64); // b.AddCustomAttribute(new ServiceAttribute(0x7000, new ServiceElement(ElementType.ElementAlternative, ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 1), ServiceElement.CreateNumericalServiceElement(ElementType.UInt8, 2)))); var foo = true; if (foo) { b.ServiceName = "foo"; } //---- var s = new BluezSdpXmlWriter().Write(b.ServiceRecord); console.WriteLine(s); //---- var rOut = new BluezSdpXmlReader().Read(s); console.WriteLine(ServiceRecordUtilities.Dump(rOut)); //================ // new BluezSdpReaderTests().One(); new BluezSdpReaderTests().Two_UnterminatedEntity(); } #endif //-------- public static string ToStringQuotedOrNull(T obj) { if (obj == null) return "(null)"; else return obj.ToString(); } static string Exception_FirstLine(Exception ex) { string line; using (StringReader rdr = new StringReader(ex.ToString())) { line = rdr.ReadLine(); } var soex = ex as System.Net.Sockets.SocketException; if (soex != null) { line += SocketException_Codes(soex); } return line; } static string SocketException_Codes(System.Net.Sockets.SocketException soex) { string line = null;// string.Empty; line += " (" + soex.ErrorCode; // int #if !NETCF line += " " + soex.SocketErrorCode; // Enum name #endif line += ")"; return line; } static bool _WaitAll(WaitHandle[] events, int timeout) { #if false && !NETCF return WaitHandle.WaitAll(events, timeout); #else var final = DateTime.UtcNow.AddMilliseconds(timeout); foreach (var curE in events) { TimeSpan curTo = final.Subtract(DateTime.UtcNow); if (curTo.CompareTo(TimeSpan.Zero) <= 0) { Debug.Fail("Should we expect to get here? Normally exit at !signalled below..."); return false; } bool signalled = curE.WaitOne((int)curTo.TotalMilliseconds, false); if (!signalled) { return false; } }//for return true; #endif } static TimeSpan RunAndTime(ThreadStart method) { var start = DateTime.UtcNow; method(); var time = DateTime.UtcNow - start; return time; } }//class }