DreamCheekyBTN.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Threading;
  5. using HidSharp;
  6. namespace DreamCheekyUSB {
  7. public class DreamCheekyBTN : IDisposable {
  8. #region Constant and readonly values
  9. protected HidDeviceLoader Loader;
  10. protected HidStream Stream;
  11. public HidDevice HidBTN;
  12. public const int DEFAULT_VENDOR_ID = 0x1D34;
  13. //Default Vendor ID for Dream Cheeky devices
  14. public const int DEFAULT_PRODUCT_ID = 0x0008;
  15. //Default for Ironman USB stress button
  16. public static class Messages {
  17. public const byte BUTTON_PRESSED = 0x1C;
  18. }
  19. //Initialization values and test colors
  20. public static readonly byte[] CmdStatus = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 };
  21. #endregion
  22. private AutoResetEvent WriteEvent = new AutoResetEvent(false);
  23. private System.Timers.Timer t = new System.Timers.Timer(100);
  24. //Timer for checking USB status every 100ms
  25. private Action Timer_Callback;
  26. private bool LidOpen;
  27. protected byte ActivatedMessage;
  28. #region Constructors
  29. /// <summary>
  30. /// Default constructor. Will used VendorID=0x1D34 and ProductID=0x0008. Will throw exception if no device is found.
  31. /// </summary>
  32. /// <param name="deviceIndex">Zero based device index if you have multiple devices plugged in.</param>
  33. public DreamCheekyBTN(int deviceIndex = 0) : this(DEFAULT_VENDOR_ID, DEFAULT_PRODUCT_ID, deviceIndex) {
  34. }
  35. /// <summary>
  36. /// Create object using VendorID and ProductID. Will throw exception if no USBLED is found.
  37. /// </summary>
  38. /// <param name="vendorID">Example to 0x1D34</param>
  39. /// <param name="productID">Example to 0x0008</param>
  40. /// <param name="deviceIndex">Zero based device index if you have multiple devices plugged in.</param>
  41. public DreamCheekyBTN(int vendorID, int productID, int deviceIndex = 0) {
  42. var loader = new HidDeviceLoader();
  43. var devices = new List<HidDevice>(loader.GetDevices(vendorID, productID));
  44. if (deviceIndex >= devices.Count) {
  45. throw new ArgumentOutOfRangeException("deviceIndex", String.Format("VID={0},PID={1},DeviceIndex={2} is invalid. There are only {3} devices connected.", vendorID, productID, deviceIndex, devices.Count));
  46. }
  47. HidBTN = devices[deviceIndex];
  48. if (!init()) {
  49. throw new Exception(String.Format("Cannot find USB HID Device with VendorID=0x{0:X4} and ProductID=0x{1:X4}", vendorID, productID));
  50. }
  51. ActivatedMessage = Messages.BUTTON_PRESSED;
  52. }
  53. /// <summary>
  54. /// Create object using Device path. Example: DreamCheekyBTN(@"\\?\hid#vid_1d34&pid_0008#6&1067c3dc&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}").
  55. /// </summary>
  56. /// <param name="devicePath">Example: @"\\?\hid#vid_1d34&pid_0008#6&1067c3dc&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}"</param>
  57. public DreamCheekyBTN(string devicePath) {
  58. var loader = new HidDeviceLoader();
  59. var devices = loader.GetDevices();
  60. foreach (var device in devices) {
  61. if (device.DevicePath == devicePath) {
  62. HidBTN = device;
  63. }
  64. }
  65. if (!init()) {
  66. throw new Exception(String.Format("Cannot find USB HID Device with DevicePath={0}", devicePath));
  67. }
  68. ActivatedMessage = Messages.BUTTON_PRESSED;
  69. }
  70. /// <summary>
  71. /// Private init function for constructors.
  72. /// </summary>
  73. /// <returns>True if success, false otherwise.</returns>
  74. private bool init() {
  75. WriteEvent.Reset();
  76. t.AutoReset = true;
  77. t.Elapsed += t_Elapsed;
  78. t.Enabled = false;
  79. t.Stop();
  80. if (HidBTN == default(HidDevice)) {
  81. return false; //Device not found, return false.
  82. }
  83. Stream = HidBTN.Open();
  84. //Device is valid
  85. Trace.WriteLine("Init HID device: " + HidBTN.ProductName + "\r\n");
  86. return true;
  87. }
  88. public void Dispose() {
  89. if (t != null) {
  90. t.Dispose();
  91. t = null;
  92. }
  93. Timer_Callback = null;
  94. if (Stream != default(HidStream)) {
  95. Stream.Close();
  96. Stream.Dispose();
  97. Stream = default(HidStream);
  98. }
  99. }
  100. ~DreamCheekyBTN() {
  101. Dispose();
  102. }
  103. #endregion
  104. public bool ButtonState { get; private set; }
  105. private static bool IsUnix() {
  106. var platform = Environment.OSVersion.Platform;
  107. return (platform == PlatformID.MacOSX) || (platform == PlatformID.Unix);
  108. }
  109. public void Write(byte[] data) {
  110. //Trace.WriteLine("\r\nWriteing Data=" + BitConverter.ToString(data));
  111. if (IsUnix()) {
  112. Stream.Write(data);
  113. } else {
  114. var windowsData = new byte[9];
  115. data.CopyTo(windowsData, 1);
  116. Stream.Write(windowsData);
  117. }
  118. }
  119. public byte[] Read() {
  120. return Stream.Read();
  121. }
  122. public bool GetStatus() {
  123. Write(CmdStatus);
  124. var data = Read();
  125. var bigRedBtn = this as DreamCheekyBigRedBTN;
  126. if (bigRedBtn != null) {
  127. if (LidOpen && bigRedBtn.LidIsClosed()) {
  128. LidOpen = false;
  129. Console.WriteLine("{0}: Lid closed...", DateTime.Now.ToLongTimeString());
  130. }
  131. if (!LidOpen && bigRedBtn.LidIsOpen()) {
  132. LidOpen = true;
  133. Console.WriteLine("{0}: Lid opened...", DateTime.Now.ToLongTimeString());
  134. }
  135. }
  136. return data[0] == ActivatedMessage;
  137. }
  138. public void RegisterCallback(Action callback) {
  139. Timer_Callback = callback;
  140. t.Enabled = true;
  141. t.Start();
  142. }
  143. void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
  144. if (GetStatus()) {
  145. if (!ButtonState) { //Only toggle if button not already set
  146. ButtonState = true;
  147. Timer_Callback();
  148. }
  149. } else {
  150. ButtonState = false; //Reset state
  151. }
  152. }
  153. }
  154. }