PageRenderTime 41ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/InTheHand.Net.Personal/InTheHand.Net.Personal/Net.Bluetooth.Widcomm/WidcommBluetoothFactory.cs

#
C# | 366 lines | 297 code | 36 blank | 33 comment | 42 complexity | 0faa4e3b0c54659746b1056f692b3bcd MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. // 32feet.NET - Personal Area Networking for .NET
  2. //
  3. // InTheHand.Net.Bluetooth.Widcomm.WidcommBluetoothFactoryBase
  4. //
  5. // Copyright (c) 2008-2010 In The Hand Ltd, All rights reserved.
  6. // This source code is licensed under the In The Hand Community License - see License.txt
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Text;
  10. using InTheHand.Net.Sockets;
  11. using System.Diagnostics;
  12. using InTheHand.Net.Bluetooth.Factory;
  13. using System.Threading;
  14. using InTheHand.SystemCore;
  15. namespace InTheHand.Net.Bluetooth.Widcomm
  16. {
  17. abstract class WidcommBluetoothFactoryBase : BluetoothFactory
  18. {
  19. internal abstract WidcommBtInterface GetWidcommBtInterface();
  20. internal abstract WidcommRfcommStreamBase GetWidcommRfcommStream();
  21. internal abstract WidcommRfcommStreamBase GetWidcommRfcommStreamWithoutRfcommIf();
  22. internal abstract IRfcommPort GetWidcommRfcommPort();
  23. internal abstract IRfCommIf GetWidcommRfCommIf();
  24. internal abstract ISdpService GetWidcommSdpService();
  25. internal abstract void EnsureLoaded();
  26. //
  27. internal abstract WidcommPortSingleThreader GetSingleThreader();
  28. internal abstract bool IsWidcommSingleThread();
  29. #region Resource Cleanup records
  30. internal void AddPort(WidcommRfcommStreamBase port)
  31. {
  32. lock (_livePorts) {
  33. _livePorts.Add(port);
  34. }
  35. }
  36. internal void RemovePort(WidcommRfcommStreamBase port)
  37. {
  38. bool found;
  39. lock (_livePorts) {
  40. found = _livePorts.Remove(port);
  41. }
  42. Debug.WriteLine(WidcommUtils.GetTime4Log()
  43. + ": RemovePort found it: " + found);
  44. }
  45. internal WidcommRfcommStreamBase[] GetPortList()
  46. {
  47. lock (_livePorts) {
  48. var a = _livePorts.ToArray();
  49. Debug.WriteLine(WidcommUtils.GetTime4Log() + ": GetPortList returned " + a.Length + " ports.");
  50. return a;
  51. }
  52. }
  53. List<WidcommRfcommStreamBase> _livePorts = new List<WidcommRfcommStreamBase>();
  54. #endregion
  55. [Obsolete("_untested_")]
  56. internal virtual void AddThingsToKeepAlive<TObject>(TObject o)
  57. where TObject : class
  58. { }
  59. }
  60. sealed class WidcommBluetoothFactory : WidcommBluetoothFactoryBase
  61. {
  62. static IBtIf s_btIf;
  63. static WidcommBtInterface s_btInterface;
  64. static WidcommBluetoothSecurity m_btSecurity;
  65. static WidcommPortSingleThreader _st;
  66. internal volatile bool _seenStackDownEvent;
  67. List<object> _thingsToKeepAlive = new List<object>();
  68. public WidcommBluetoothFactory()
  69. {
  70. DoPowerDownUpReset = true;
  71. //throw if device doesn't support the stack
  72. #if NETCF
  73. bool supp = System.IO.File.Exists("\\Windows\\BTSdkCE50.dll");
  74. if(!supp)
  75. supp = System.IO.File.Exists("\\Windows\\BTSdkCE30.dll");
  76. if (!supp)
  77. throw new PlatformNotSupportedException("Broadcom Bluetooth stack not supported (radio).");
  78. #endif
  79. EnsureLoaded();
  80. // Check radio is connected.
  81. this.GetPrimaryRadio();
  82. }
  83. public bool DoPowerDownUpReset { get; set; }
  84. internal override void EnsureLoaded()
  85. {
  86. Debug.WriteLine(WidcommUtils.GetTime4Log() + ": WcBtFcty EnsureLoaded ENTRY (for v.L)");
  87. if (_st != null) {
  88. if (WidcommBtInterface.IsWidcommSingleThread(_st)) { // DEBUG
  89. }
  90. }
  91. lock (typeof(WidcommBluetoothFactory)) {
  92. Debug.WriteLine(WidcommUtils.GetTime4Log() + ": WcBtFcty EnsureLoaded IN lock");
  93. // In case Widcomm is forced to shutdown when CBtIf is extant we monitor
  94. // for the stack-down event so we can force reload next time
  95. // we're used.
  96. var seenStackDownEvent = _seenStackDownEvent;
  97. _seenStackDownEvent = false;
  98. if (seenStackDownEvent) {
  99. Debug.WriteLine(WidcommUtils.GetTime4Log() + ": WcBtFcty seenStackDownEvent");
  100. if (!DoPowerDownUpReset) {
  101. Utils.MiscUtils.Trace_WriteLine("Ignoring stack/radio shutdown due to DoPowerDownUpReset=false.");
  102. } else {
  103. Utils.MiscUtils.Trace_WriteLine("Restarting due to stack/radio shutdown.");
  104. bool respectLocks = true;
  105. // -- Shutdown --
  106. ThreadStart doDispose = () => Dispose(true, respectLocks);
  107. var st = GetSingleThreader();
  108. if (st != null && !WidcommBtInterface.IsWidcommSingleThread(st)) {
  109. respectLocks = false;
  110. var c = st.AddCommand(new WidcommPortSingleThreader.MiscNoReturnCommand(
  111. doDispose));
  112. c.WaitCompletion();
  113. MemoryBarrier();
  114. } else {
  115. doDispose();
  116. }
  117. Debug.WriteLine(WidcommUtils.GetTime4Log() + ": WcBtFcty done Dispose");
  118. Debug.Assert(s_btIf == null, "After Dispose but NOT s_btIf == null");
  119. Debug.Assert(s_btInterface == null, "After Dispose but NOT s_btInterface == null");
  120. Thread.Sleep(5000);
  121. }
  122. }
  123. //-- Create --
  124. // CBtIf: MUST ONLY be ONE of these, and must be FIRST created!
  125. // "Only one object of this class should be instantiated by the application."
  126. // "This class must be instantiated before any other DK classes are used"
  127. if (s_btIf == null) {
  128. #if KILL_SINGLE_THREAD_AT_DISPOSAL
  129. Debug.Assert(_st == null);
  130. #endif
  131. if (_st == null) _st = new WidcommPortSingleThreader();
  132. Debug.Assert(GetSingleThreader() != null);
  133. IBtIf btIf;
  134. Func<IBtIf> f = () => new WidcommBtIf(this);
  135. var st = GetSingleThreader();
  136. if (st != null && !WidcommBtInterface.IsWidcommSingleThread(st)) {
  137. var c = st.AddCommand(new WidcommPortSingleThreader.MiscReturnCommand<IBtIf>(
  138. f));
  139. btIf = c.WaitCompletion();
  140. } else {
  141. btIf = f();
  142. }
  143. Debug.WriteLine(WidcommUtils.GetTime4Log() + ": WcBtFcty done new WidcommBtIf");
  144. if (st != null) {
  145. btIf = new WidcommStBtIf(this, btIf);
  146. Utils.MiscUtils.Trace_WriteLine("IBtIf using WidcommStBtIf.");
  147. }
  148. Debug.Assert(s_btInterface == null);
  149. WidcommBtInterface btInterface = new WidcommBtInterface(btIf, this);
  150. // Don't set these until we're sure that initialisation has
  151. // all completed successfully.
  152. s_btIf = btIf;
  153. s_btInterface = btInterface;
  154. } else {
  155. Debug.Assert(s_btInterface != null, "One set but not the other!");
  156. }
  157. }//lock
  158. Debug.WriteLine(WidcommUtils.GetTime4Log() + ": WcBtFcty EnsureLoaded EXIT");
  159. }
  160. //-----
  161. protected override void Dispose(bool disposing)
  162. {
  163. Dispose(disposing, true);
  164. }
  165. private void Dispose(bool disposing, bool respectLocks)
  166. {
  167. IDisposable iface;
  168. IDisposable st;
  169. //lock (typeof(WidcommBluetoothFactory))
  170. bool gotLock = false;
  171. try {
  172. if (respectLocks) {
  173. Monitor.Enter(typeof(WidcommBluetoothFactory));
  174. gotLock = true;
  175. }
  176. iface = (IDisposable)s_btInterface;
  177. s_btIf = null;
  178. s_btInterface = null;
  179. m_btSecurity = null;
  180. #if KILL_SINGLE_THREAD_AT_DISPOSAL
  181. st = _st;
  182. _st = null;
  183. #else
  184. st = null;
  185. #endif
  186. if (disposing) {
  187. _thingsToKeepAlive.Clear();
  188. }
  189. } finally {
  190. if (gotLock) {
  191. Monitor.Exit(typeof(WidcommBluetoothFactory));
  192. }
  193. }
  194. if (iface != null)
  195. iface.Dispose();
  196. if (st != null) // Must NOT dispose this first!
  197. st.Dispose();
  198. }
  199. //-----
  200. [Obsolete("_untested_")]
  201. internal override void AddThingsToKeepAlive<TObject>(TObject o)
  202. {
  203. lock (typeof(WidcommBluetoothFactory)) {
  204. _thingsToKeepAlive.Add(o);
  205. }
  206. }
  207. //-----
  208. internal override WidcommPortSingleThreader GetSingleThreader()
  209. {
  210. return _st;
  211. }
  212. internal override bool IsWidcommSingleThread()
  213. {
  214. var st = GetSingleThreader();
  215. return WidcommPortSingleThreader.IsWidcommSingleThread(st);
  216. }
  217. //-----
  218. protected override IBluetoothClient GetBluetoothClient()
  219. {
  220. EnsureLoaded();
  221. return new WidcommBluetoothClient(this);
  222. }
  223. protected override IBluetoothClient GetBluetoothClient(System.Net.Sockets.Socket acceptedSocket)
  224. {
  225. throw new NotSupportedException("Cannot create a BluetoothClient from a Socket on the Widcomm stack.");
  226. }
  227. protected override IBluetoothClient GetBluetoothClientForListener(CommonRfcommStream strm)
  228. {
  229. return new WidcommBluetoothClient((WidcommRfcommStreamBase)strm, this);
  230. }
  231. protected override IBluetoothClient GetBluetoothClient(BluetoothEndPoint localEP)
  232. {
  233. EnsureLoaded();
  234. return new WidcommBluetoothClient(localEP, this);
  235. }
  236. protected override IL2CapClient GetL2CapClient()
  237. {
  238. EnsureLoaded();
  239. return new WidcommL2CapClient(this);
  240. }
  241. //----------------
  242. protected override IBluetoothListener GetBluetoothListener()
  243. {
  244. EnsureLoaded();
  245. return new WidcommBluetoothListener(this);
  246. }
  247. //----------------
  248. internal override WidcommBtInterface GetWidcommBtInterface()
  249. {
  250. EnsureLoaded();
  251. return s_btInterface;
  252. }
  253. internal override WidcommRfcommStreamBase GetWidcommRfcommStream()
  254. {
  255. EnsureLoaded();
  256. return new WidcommRfcommStream(GetWidcommRfcommPort(), GetWidcommRfCommIf(), this);
  257. }
  258. internal override WidcommRfcommStreamBase GetWidcommRfcommStreamWithoutRfcommIf()
  259. {
  260. EnsureLoaded();
  261. return new WidcommRfcommStream(GetWidcommRfcommPort(), null, this);
  262. }
  263. internal override IRfcommPort GetWidcommRfcommPort()
  264. {
  265. EnsureLoaded();
  266. // Handling of single threadedness is done within WidcommRfcommStream.
  267. return new WidcommRfcommPort();
  268. }
  269. internal override IRfCommIf GetWidcommRfCommIf()
  270. {
  271. EnsureLoaded();
  272. IRfCommIf inst = new WidcommRfCommIf();
  273. if (GetSingleThreader() != null) {
  274. inst = new WidcommStRfCommIf(this, inst);
  275. Utils.MiscUtils.Trace_WriteLine("IRfCommIf using WidcommStRfCommIf.");
  276. }
  277. return inst;
  278. }
  279. protected override IBluetoothDeviceInfo GetBluetoothDeviceInfo(BluetoothAddress address)
  280. {
  281. EnsureLoaded();
  282. return WidcommBluetoothDeviceInfo.CreateFromGivenAddress(address, this);
  283. }
  284. //----------------
  285. protected override IBluetoothRadio GetPrimaryRadio()
  286. {
  287. EnsureLoaded();
  288. return new WidcommBluetoothRadio(this);
  289. }
  290. protected override IBluetoothRadio[] GetAllRadios()
  291. {
  292. EnsureLoaded();
  293. // Widcomm supports only one radio.
  294. return new IBluetoothRadio[] { GetPrimaryRadio() };
  295. }
  296. //----------------
  297. internal override ISdpService GetWidcommSdpService()
  298. {
  299. EnsureLoaded();
  300. return new SdpService();
  301. }
  302. //----------------
  303. protected override IBluetoothSecurity GetBluetoothSecurity()
  304. {
  305. EnsureLoaded();
  306. if (m_btSecurity == null) {
  307. m_btSecurity = new WidcommBluetoothSecurity(this);
  308. }
  309. return m_btSecurity;
  310. }
  311. //----------------
  312. internal static WidcommBluetoothFactoryBase GetWidcommIfExists()
  313. {
  314. foreach (var cur in BluetoothFactory.Factories) {
  315. var curWf = cur as WidcommBluetoothFactoryBase;
  316. if (curWf != null) {
  317. return curWf;
  318. }
  319. }
  320. throw new InvalidOperationException("No Widcomm.");
  321. }
  322. //----------------
  323. private static void MemoryBarrier()
  324. {
  325. #if ! PocketPC
  326. Thread.MemoryBarrier();
  327. #endif
  328. }
  329. }
  330. }