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"); } }