internal static MacSerialDevice TryCreate(NativeMethods.io_string_t path) { var d = new MacSerialDevice() { _path = path }; var handle = NativeMethods.IORegistryEntryFromPath(0, ref path).ToIOObject(); if (!handle.IsSet) { return(null); } using (handle) { d._fileSystemName = NativeMethods.IORegistryEntryGetCFProperty_String(handle, NativeMethods.kIOCalloutDeviceKey); if (d._fileSystemName == null) { return(null); } } return(d); }
internal void Init(NativeMethods.io_string_t path) { IntPtr handle; int retryCount = 0, maxRetries = 10; while (true) { var newPath = path.Clone(); using (var service = NativeMethods.IORegistryEntryFromPath(0, ref newPath).ToIOObject()) { string error; if (service.IsSet) { handle = NativeMethods.IOHIDDeviceCreate(IntPtr.Zero, service); if (handle != IntPtr.Zero) { var ret = NativeMethods.IOHIDDeviceOpen(handle); if (ret == NativeMethods.IOReturn.Success) { break; } NativeMethods.CFRelease(handle); // TODO: Only count up if IOReturn is ExclusiveAccess or Offline. error = string.Format("Unable to open HID class device (error {1}): {0}", newPath.ToString(), ret); } else { error = string.Format("HID class device not found: {0}", newPath.ToString()); } } else { error = string.Format("HID class device path not found: {0}", newPath.ToString()); } if (++retryCount == maxRetries) { throw DeviceException.CreateIOException(Device, error); } Debug.WriteLine(string.Format("Retrying ({0})", error)); Thread.Sleep(100); } } _handle = handle; HandleInitAndOpen(); _readThread.Start(); _writeThread.Start(); }
internal void Init(NativeMethods.io_string_t path, MacHidDevice device) { IntPtr handle; using (var service = NativeMethods.IORegistryEntryFromPath(0, ref path).ToIOObject()) { handle = NativeMethods.IOHIDDeviceCreate(IntPtr.Zero, service); if (handle == IntPtr.Zero) { throw new IOException("HID class device not found."); } if (NativeMethods.IOReturn.Success != NativeMethods.IOHIDDeviceOpen(handle)) { NativeMethods.CFRelease(handle); throw new IOException("Unable to open HID class device."); } } _device = device; _handle = handle; HandleInitAndOpen(); _readThread.Start(); _writeThread.Start(); }
internal static MacHidDevice TryCreate(NativeMethods.io_string_t path) { var d = new MacHidDevice() { _path = path }; var service = NativeMethods.IORegistryEntryFromPath(0, ref path).ToIOObject(); if (!service.IsSet) { return(null); } using (service) { int?vid = NativeMethods.IORegistryEntryGetCFProperty_Int(service, NativeMethods.kIOHIDVendorIDKey); int?pid = NativeMethods.IORegistryEntryGetCFProperty_Int(service, NativeMethods.kIOHIDProductIDKey); int?version = NativeMethods.IORegistryEntryGetCFProperty_Int(service, NativeMethods.kIOHIDVersionNumberKey); if (vid == null || pid == null || version == null) { return(null); } // TODO: Craft the report descriptor from IOHIDElements so we can support it below OS X 10.8... // Also, our report sizes aren't correct for the no-report-ID case without this... d._vid = (int)vid; d._pid = (int)pid; d._version = (int)version; d._maxInput = NativeMethods.IORegistryEntryGetCFProperty_Int(service, NativeMethods.kIOHIDMaxInputReportSizeKey) ?? 0; d._maxOutput = NativeMethods.IORegistryEntryGetCFProperty_Int(service, NativeMethods.kIOHIDMaxOutputReportSizeKey) ?? 0; d._maxFeature = NativeMethods.IORegistryEntryGetCFProperty_Int(service, NativeMethods.kIOHIDMaxFeatureReportSizeKey) ?? 0; d._manufacturer = NativeMethods.IORegistryEntryGetCFProperty_String(service, NativeMethods.kIOHIDManufacturerKey); d._productName = NativeMethods.IORegistryEntryGetCFProperty_String(service, NativeMethods.kIOHIDProductKey); d._serialNumber = NativeMethods.IORegistryEntryGetCFProperty_String(service, NativeMethods.kIOHIDSerialNumberKey); d._reportDescriptor = NativeMethods.IORegistryEntryGetCFProperty_Data(service, NativeMethods.kIOHIDReportDescriptorKey); if (d._maxInput == 0 && d._maxOutput == 0 && d._maxFeature == 0) { return(null); } // Does this device use Report IDs? Let's find out. d._reportsUseID = false; bool hasInput = false, hasOutput = false, hasFeature = false; using (var device = NativeMethods.IOHIDDeviceCreate(IntPtr.Zero, service).ToCFType()) { if (!device.IsSet) { return(null); } using (var elementArray = NativeMethods.IOHIDDeviceCopyMatchingElements(device, IntPtr.Zero).ToCFType()) { if (!elementArray.IsSet) { return(null); } int elementCount = checked ((int)NativeMethods.CFArrayGetCount(elementArray)); for (int elementIndex = 0; elementIndex < elementCount; elementIndex++) { var element = NativeMethods.CFArrayGetValueAtIndex(elementArray, (IntPtr)elementIndex); if (element == IntPtr.Zero) { continue; } var elementType = NativeMethods.IOHIDElementGetType(element); switch (elementType) { case NativeMethods.IOHIDElementType.InputMisc: case NativeMethods.IOHIDElementType.InputButton: case NativeMethods.IOHIDElementType.InputAxis: case NativeMethods.IOHIDElementType.InputScanCodes: hasInput = true; break; case NativeMethods.IOHIDElementType.Output: hasOutput = true; break; case NativeMethods.IOHIDElementType.Feature: hasFeature = true; break; } if (NativeMethods.IOHIDElementGetReportID(element) != 0) { d._reportsUseID = true; } } } } if (!d._reportsUseID) { // It does not use Report IDs. MacOS's maximums do not include said Report ID. if (d._maxInput != 0) { d._maxInput++; } if (d._maxOutput != 0) { d._maxOutput++; } if (d._maxFeature != 0) { d._maxFeature++; } } if (!hasInput) { d._maxInput = 0; } if (!hasOutput) { d._maxOutput = 0; } if (!hasFeature) { d._maxFeature = 0; } } return(d); }