private IORegistryEntryFromPath ( int masterPort, io_string_t &path ) : int | ||
masterPort | int | |
path | io_string_t | |
Résultat | int |
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(); }
protected override bool TryCreateDevice(object key, out HidDevice device, out object creationState) { creationState = null; var path = (NativeMethods.io_string_t)key; var hidDevice = new MacHidDevice(path); using (var handle = NativeMethods.IORegistryEntryFromPath(0, ref path).ToIOObject()) { if (!handle.IsSet || !hidDevice.GetInfo(handle)) { device = null; return(false); } device = hidDevice; return(true); } }
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); }
public override unsafe string GetDeviceString(int index) { ushort stringIndex(byte index) => (ushort)((((byte)NativeMethods.DESCRIPTOR_TYPE.STRING) << 8) | index); void closeDev(NativeMethods.IOUSBDeviceStruct182 **usbDev) { (*usbDev)->USBDeviceClose(usbDev); (*usbDev)->Release(usbDev); } // Setup the packet for retrieving supported langId var setup = new NativeMethods.IOUSBDevRequest { bmRequestType = (byte)NativeMethods.ENDPOINT_DIRECTION.IN, bRequest = (byte)NativeMethods.STANDARD_REQUEST.GET_DESCRIPTOR, wValue = stringIndex(0), wIndex = 0, wLength = 255 }; int kernRet = NativeMethods.IOMasterPort(0, out uint masterPort); if (kernRet != 0) { throw new Exception($"Failed to get IOMasterPort: {kernRet:X}"); } // Determine USB device from HID path var hidEntry = NativeMethods.IORegistryEntryFromPath(masterPort, ref _path).ToIOObject(); int deviceEntry = 0; IntPtr kIOUSBDeviceInterfaceID = NativeMethods.kIOUSBDeviceInterfaceID; if (hidEntry.IsSet) { NativeMethods.IORegistryEntryGetParentEntry(hidEntry, "IOService", out var interfaceEntry); if (interfaceEntry != 0) { NativeMethods.IORegistryEntryGetParentEntry(interfaceEntry, "IOService", out deviceEntry); } } if (deviceEntry == 0) { throw new Exception("Failed retrieving USB Device"); } var err = NativeMethods.IOCreatePlugInInterfaceForService(deviceEntry, NativeMethods.kIOUSBDeviceUserClientTypeID, NativeMethods.kIOCFPluginInterfaceID, out var pluginInterface, out var score); if (err != NativeMethods.IOReturn.Success) { throw new Exception($"Plugin Interface creation failed. 0x{err:X}"); } (*pluginInterface)->QueryInterface(pluginInterface, NativeMethods.CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), out var usbDevPtr); (*pluginInterface)->Release(pluginInterface); if (usbDevPtr != null) { var usbDev = (NativeMethods.IOUSBDeviceStruct182 * *)usbDevPtr; err = (*usbDev)->USBDeviceOpen(usbDev); if (err != NativeMethods.IOReturn.Success) { (*usbDev)->Release(usbDev); throw new DeviceIOException(this, $"Failed to open USB device: 0x{err:X}"); } fixed(char *sbuf = new char[255]) { setup.pData = sbuf; err = (*usbDev)->DeviceRequest(usbDev, &setup); if (err != NativeMethods.IOReturn.Success) { closeDev(usbDev); throw new DeviceIOException(this, $"DeviceRequest failed: 0x{err:X}"); } var buf = (byte *)setup.pData; ushort langId = (ushort)(buf[2] | buf[3] << 8); for (int i = 0; i < 255; i++) { buf[i] = 0; } // Retrieve string setup.wIndex = langId; setup.wValue = stringIndex((byte)index); (*usbDev)->DeviceRequest(usbDev, &setup); if (err != NativeMethods.IOReturn.Success) { closeDev(usbDev); throw new DeviceIOException(this, $"DeviceRequest failed: 0x{err:X}"); } var deviceString = new StringBuilder(255); var ssbuf = (char *)setup.pData; for (int i = 1; i < 255; i++) { var c = ssbuf[i]; if (c == 0) { break; } else { deviceString.Append(c); } } closeDev(usbDev); return(deviceString.ToString()); } } else { throw new DeviceIOException(this, $"USB Device interface retrieval failed"); } }