NativeMethods.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. #region License
  2. /* Copyright 2012-2013 James F. Bellinger <http://www.zer7.com/software/hidsharp>
  3. Permission to use, copy, modify, and/or distribute this software for any
  4. purpose with or without fee is hereby granted, provided that the above
  5. copyright notice and this permission notice appear in all copies.
  6. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  7. WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  8. MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  9. ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  10. WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  11. ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  12. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
  13. #endregion
  14. using System;
  15. using System.Linq;
  16. using System.Runtime.InteropServices;
  17. using System.Text;
  18. namespace HidSharp.Platform.MacOS
  19. {
  20. static class NativeMethods
  21. {
  22. const string CoreFoundation = "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation";
  23. const string CoreServices = "/System/Library/Frameworks/CoreServices.framework/CoreServices";
  24. const string IOKit = "/System/Library/Frameworks/IOKit.framework/IOKit";
  25. public static readonly IntPtr kCFRunLoopDefaultMode = CFStringCreateWithCharacters("kCFRunLoopDefaultMode");
  26. public static readonly IntPtr kIOHIDVendorIDKey = CFStringCreateWithCharacters("VendorID");
  27. public static readonly IntPtr kIOHIDProductIDKey = CFStringCreateWithCharacters("ProductID");
  28. public static readonly IntPtr kIOHIDVersionNumberKey = CFStringCreateWithCharacters("VersionNumber");
  29. public static readonly IntPtr kIOHIDManufacturerKey = CFStringCreateWithCharacters("Manufacturer");
  30. public static readonly IntPtr kIOHIDProductKey = CFStringCreateWithCharacters("Product");
  31. public static readonly IntPtr kIOHIDSerialNumberKey = CFStringCreateWithCharacters("SerialNumber");
  32. public static readonly IntPtr kIOHIDLocationIDKey = CFStringCreateWithCharacters("LocationID");
  33. public static readonly IntPtr kIOHIDMaxInputReportSizeKey = CFStringCreateWithCharacters("MaxInputReportSize");
  34. public static readonly IntPtr kIOHIDMaxOutputReportSizeKey = CFStringCreateWithCharacters("MaxOutputReportSize");
  35. public static readonly IntPtr kIOHIDMaxFeatureReportSizeKey = CFStringCreateWithCharacters("MaxFeatureReportSize");
  36. public delegate void IOHIDCallback(IntPtr context, IOReturn result, IntPtr sender);
  37. public delegate void IOHIDDeviceCallback(IntPtr context, IOReturn result, IntPtr sender, IntPtr device);
  38. public delegate void IOHIDReportCallback(IntPtr context, IOReturn result, IntPtr sender,
  39. IOHIDReportType type, uint reportID, IntPtr report, IntPtr reportLength);
  40. public enum OSErr : short
  41. {
  42. noErr = 0,
  43. gestaltUnknownErr = -5550,
  44. gestaltUndefSelectorErr = -5551,
  45. gestaltDupSelectorErr = -5552,
  46. gestaltLocationErr = -5553
  47. }
  48. public enum OSType : uint
  49. {
  50. gestaltSystemVersion = (byte)'s' << 24 | (byte)'y' << 16 | (byte)'s' << 8 | (byte)'v' << 0,
  51. gestaltSystemVersionMajor = (byte)'s' << 24 | (byte)'y' << 16 | (byte)'s' << 8 | (byte)'1' << 0,
  52. gestaltSystemVersionMinor = (byte)'s' << 24 | (byte)'y' << 16 | (byte)'s' << 8 | (byte)'2' << 0,
  53. gestaltSystemVersionBugFix = (byte)'s' << 24 | (byte)'y' << 16 | (byte)'s' << 8 | (byte)'3' << 0
  54. }
  55. public enum IOOptionBits
  56. {
  57. None = 0
  58. }
  59. public enum IOHIDReportType
  60. {
  61. Input = 0,
  62. Output,
  63. Feature
  64. }
  65. public enum IOReturn
  66. {
  67. Success = 0
  68. }
  69. public struct io_string_t
  70. {
  71. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
  72. public byte[] Value;
  73. public override bool Equals(object obj)
  74. {
  75. return obj is io_string_t && this == (io_string_t)obj;
  76. }
  77. public override int GetHashCode()
  78. {
  79. return Value.Length >= 1 ? Value[0] : -1;
  80. }
  81. public override string ToString()
  82. {
  83. return Encoding.UTF8.GetString(Value.TakeWhile(ch => ch != 0).ToArray());
  84. }
  85. public static bool operator ==(io_string_t io1, io_string_t io2)
  86. {
  87. return io1.Value.SequenceEqual(io2.Value);
  88. }
  89. public static bool operator !=(io_string_t io1, io_string_t io2)
  90. {
  91. return !(io1 == io2);
  92. }
  93. }
  94. public enum CFNumberType
  95. {
  96. Int = 9
  97. }
  98. public struct CFRange
  99. {
  100. public IntPtr Start, Length;
  101. }
  102. public struct IOObject : IDisposable
  103. {
  104. public int Handle { get; set; }
  105. public bool IsSet { get { return Handle != 0; } }
  106. void IDisposable.Dispose()
  107. {
  108. if (IsSet) { IOObjectRelease(Handle); Handle = 0; }
  109. }
  110. public static implicit operator int(IOObject self)
  111. {
  112. return self.Handle;
  113. }
  114. }
  115. public struct CFType : IDisposable
  116. {
  117. public IntPtr Handle { get; set; }
  118. public bool IsSet { get { return Handle != IntPtr.Zero; } }
  119. void IDisposable.Dispose()
  120. {
  121. if (IsSet) { CFRelease(Handle); Handle = IntPtr.Zero; }
  122. }
  123. public static implicit operator IntPtr(CFType self)
  124. {
  125. return self.Handle;
  126. }
  127. }
  128. public static CFType ToCFType(this IntPtr handle)
  129. {
  130. return new CFType() { Handle = handle };
  131. }
  132. public static IOObject ToIOObject(this int handle)
  133. {
  134. return new IOObject() { Handle = handle };
  135. }
  136. [DllImport(CoreServices)]
  137. public static extern OSErr Gestalt(OSType selector, out IntPtr response);
  138. [DllImport(CoreFoundation)]
  139. public static extern uint CFGetTypeID(IntPtr type);
  140. [DllImport(CoreFoundation)]
  141. public static extern uint CFNumberGetTypeID();
  142. [DllImport(CoreFoundation)]
  143. public static extern uint CFStringGetTypeID();
  144. [DllImport(CoreFoundation)]
  145. public static extern IntPtr CFDictionaryCreateMutable(IntPtr allocator, IntPtr capacity,
  146. IntPtr keyCallbacks, IntPtr valueCallbacks);
  147. public static IntPtr CFDictionaryCreateMutable()
  148. {
  149. return CFDictionaryCreateMutable(IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
  150. }
  151. [DllImport(CoreFoundation)]
  152. public static extern void CFDictionarySetValue(IntPtr dict, IntPtr key, IntPtr value);
  153. [DllImport(CoreFoundation)]
  154. public static extern IntPtr CFNumberCreate(IntPtr allocator, CFNumberType type, ref int value);
  155. public static IntPtr CFNumberCreate(int value)
  156. {
  157. return CFNumberCreate(IntPtr.Zero, CFNumberType.Int, ref value);
  158. }
  159. [DllImport(CoreFoundation)]
  160. [return: MarshalAs(UnmanagedType.I1)]
  161. public static extern bool CFNumberGetValue(IntPtr number, CFNumberType type, out int value);
  162. public static int? CFNumberGetValue(IntPtr number)
  163. {
  164. int value;
  165. return number != IntPtr.Zero && CFGetTypeID(number) == CFNumberGetTypeID() &&
  166. CFNumberGetValue(number, CFNumberType.Int, out value) ? (int?)value : null;
  167. }
  168. [DllImport(CoreFoundation, CharSet=CharSet.Unicode)]
  169. public static extern IntPtr CFStringCreateWithCharacters(IntPtr allocator, char[] buffer, IntPtr length);
  170. public static IntPtr CFStringCreateWithCharacters(string str)
  171. {
  172. return CFStringCreateWithCharacters(IntPtr.Zero, str.ToCharArray(), (IntPtr)str.Length);
  173. }
  174. [DllImport(CoreFoundation, CharSet=CharSet.Unicode)]
  175. public static extern void CFStringGetCharacters(IntPtr str, CFRange range, char[] buffer);
  176. public static string CFStringGetCharacters(IntPtr str)
  177. {
  178. if (str == IntPtr.Zero || CFGetTypeID(str) != CFStringGetTypeID()) { return null; }
  179. char[] buffer = new char[(int)CFStringGetLength(str)];
  180. CFStringGetCharacters(str, new CFRange() { Start = (IntPtr)0, Length = (IntPtr)buffer.Length }, buffer);
  181. return new string(buffer);
  182. }
  183. [DllImport(CoreFoundation)]
  184. public static extern IntPtr CFStringGetLength(IntPtr str);
  185. [DllImport(CoreFoundation)]
  186. public static extern void CFRunLoopRun();
  187. [DllImport(CoreFoundation)]
  188. public static extern IntPtr CFRunLoopGetCurrent();
  189. [DllImport(CoreFoundation)]
  190. public static extern void CFRunLoopStop(IntPtr runLoop);
  191. [DllImport(CoreFoundation)]
  192. public static extern void CFRelease(IntPtr obj);
  193. [DllImport(CoreFoundation)]
  194. public static extern void CFRetain(IntPtr obj);
  195. [DllImport(CoreFoundation)]
  196. public static extern IntPtr CFSetGetCount(IntPtr set);
  197. [DllImport(CoreFoundation)]
  198. public static extern void CFSetGetValues(IntPtr set, IntPtr[] values);
  199. [DllImport(IOKit)]
  200. public static extern IntPtr IOHIDDeviceCreate(IntPtr allocator, int service);
  201. [DllImport(IOKit)]
  202. public static extern IOReturn IOHIDDeviceOpen(IntPtr device, IOOptionBits options = IOOptionBits.None);
  203. [DllImport(IOKit)]
  204. public static extern void IOHIDDeviceRegisterInputReportCallback(IntPtr device, IntPtr report, IntPtr reportLength,
  205. IOHIDReportCallback callback, IntPtr context);
  206. [DllImport(IOKit)]
  207. public static extern void IOHIDDeviceRegisterRemovalCallback(IntPtr device, IOHIDCallback callback, IntPtr context);
  208. [DllImport(IOKit)]
  209. public static extern IOReturn IOHIDDeviceGetReport(IntPtr device, IOHIDReportType type, IntPtr reportID, IntPtr report, ref IntPtr reportLength);
  210. [DllImport(IOKit)]
  211. public static extern IOReturn IOHIDDeviceSetReport(IntPtr device, IOHIDReportType type, IntPtr reportID, IntPtr report, IntPtr reportLength);
  212. [DllImport(IOKit)]
  213. public static extern void IOHIDDeviceScheduleWithRunLoop(IntPtr device, IntPtr runLoop, IntPtr runLoopMode);
  214. [DllImport(IOKit)]
  215. public static extern void IOHIDDeviceUnscheduleFromRunLoop(IntPtr device, IntPtr runLoop, IntPtr runLoopMode);
  216. [DllImport(IOKit)]
  217. public static extern IOReturn IOHIDDeviceClose(IntPtr device, IOOptionBits options = IOOptionBits.None);
  218. [DllImport(IOKit)]
  219. public static extern int IOIteratorNext(int iterator);
  220. [DllImport(IOKit)]
  221. public static extern IOReturn IOObjectRetain(int @object);
  222. [DllImport(IOKit)]
  223. public static extern IOReturn IOObjectRelease(int @object);
  224. [DllImport(IOKit)]
  225. public static extern IntPtr IORegistryEntryCreateCFProperty(int entry, IntPtr strKey, IntPtr allocator, IOOptionBits options = IOOptionBits.None);
  226. public static int? IORegistryEntryGetCFProperty_Int(int entry, IntPtr strKey)
  227. {
  228. using (var property = IORegistryEntryCreateCFProperty(entry, strKey, IntPtr.Zero).ToCFType())
  229. {
  230. return CFNumberGetValue(property);
  231. }
  232. }
  233. public static string IORegistryEntryGetCFProperty_String(int entry, IntPtr strKey)
  234. {
  235. using (var property = IORegistryEntryCreateCFProperty(entry, strKey, IntPtr.Zero).ToCFType())
  236. {
  237. return CFStringGetCharacters(property);
  238. }
  239. }
  240. [DllImport(IOKit)]
  241. public static extern int IORegistryEntryFromPath(int masterPort, ref io_string_t path);
  242. [DllImport(IOKit)] // plane = IOService
  243. public static extern IOReturn IORegistryEntryGetPath(int entry, [MarshalAs(UnmanagedType.LPStr)] string plane, out io_string_t path);
  244. [DllImport(IOKit)]
  245. public static extern IOReturn IOServiceGetMatchingServices(int masterPort, IntPtr matching, out int iterator);
  246. [DllImport(IOKit)] // name = IOHIDDevice
  247. public static extern IntPtr IOServiceMatching([MarshalAs(UnmanagedType.LPStr)] string name);
  248. }
  249. }