Example #1
0
        private static IEnumerable <string> EnumerateDevicePath(Guid guid)
        {
            var devicePathList = new List <string>();
            var hDevInfo       = SetupApi.SetupDiGetClassDevs(ref guid, IntPtr.Zero, IntPtr.Zero, SetupApi.DIGCF_PRESENT | SetupApi.DIGCF_DEVICEINTERFACE);

            var spid = new SetupApi.SP_DEVICE_INTERFACE_DATA();

            spid.cbSize = Marshal.SizeOf(spid);
            int memberindex = 0;

            while (SetupApi.SetupDiEnumDeviceInterfaces(hDevInfo, IntPtr.Zero, ref guid, memberindex, ref spid))
            {
                int bufferSize = 0;
                SetupApi.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref spid, IntPtr.Zero, 0, ref bufferSize, IntPtr.Zero);

                var buffer = Marshal.AllocHGlobal(bufferSize);
                Marshal.WriteInt32(buffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);

                var da = new SetupApi.SP_DEVINFO_DATA();
                da.cbSize = Marshal.SizeOf(da);

                SetupApi.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref spid, buffer, bufferSize, ref bufferSize, ref da);
                IntPtr pDevicePathName = new IntPtr(buffer.ToInt64() + 4);
                string pathName        = Marshal.PtrToStringUni(pDevicePathName);

                Marshal.FreeHGlobal(buffer);
                buffer = IntPtr.Zero;
                memberindex++;

                Console.WriteLine(pathName);
                devicePathList.Add(pathName);
            }

            return(devicePathList);
        }
Example #2
0
        /// <summary>
        /// Gets a list of <see cref="WinUsbRegistry"/> classes for the specified interface guid.
        /// </summary>
        /// <param name="deviceInterfaceGuid">The DeviceInterfaceGUID to search for.</param>
        /// <param name="deviceRegistryList">A list of device paths associated with the <paramref name="deviceInterfaceGuid"/>.</param>
        /// <returns>True of one or more device paths was found.</returns>
        /// <remarks>
        /// Each <see cref="WinUsbRegistry"/> in the <paramref name="deviceRegistryList"/> represents a seperate WinUSB device (interface).
        /// </remarks>
        public static bool GetWinUsbRegistryList(Guid deviceInterfaceGuid, out List <WinUsbRegistry> deviceRegistryList)
        {
            deviceRegistryList = new List <WinUsbRegistry>();

            int devicePathIndex = 0;

            SetupApi.SP_DEVICE_INTERFACE_DATA    interfaceData = SetupApi.SP_DEVICE_INTERFACE_DATA.Empty;
            SetupApi.DeviceInterfaceDetailHelper detailHelper;

            SetupApi.SP_DEVINFO_DATA devInfoData = SetupApi.SP_DEVINFO_DATA.Empty;

            // [1]
            IntPtr deviceInfo = SetupApi.SetupDiGetClassDevs(ref deviceInterfaceGuid, null, IntPtr.Zero, SetupApi.DICFG.PRESENT | SetupApi.DICFG.DEVICEINTERFACE);

            if (deviceInfo != IntPtr.Zero)
            {
                while ((SetupApi.SetupDiEnumDeviceInterfaces(deviceInfo, null, ref deviceInterfaceGuid, devicePathIndex, ref interfaceData)))
                {
                    int length = 1024;
                    detailHelper = new SetupApi.DeviceInterfaceDetailHelper(length);
                    bool bResult = SetupApi.SetupDiGetDeviceInterfaceDetail(deviceInfo, ref interfaceData, detailHelper.Handle, length, out length, ref devInfoData);
                    if (bResult)
                    {
                        WinUsbRegistry regInfo = new WinUsbRegistry();

                        SetupApi.getSPDRPProperties(deviceInfo, ref devInfoData, regInfo.mDeviceProperties);

                        // Use the actual winusb device path for SYMBOLIC_NAME_KEY. This will be used to open the device.
                        regInfo.mDeviceProperties.Add(SYMBOLIC_NAME_KEY, detailHelper.DevicePath);
#if VERY_DEBUG
                        Debug.WriteLine(detailHelper.DevicePath);
#endif

                        regInfo.mDeviceInterfaceGuids = new Guid[] { deviceInterfaceGuid };

                        StringBuilder sbDeviceID = new StringBuilder(1024);
                        if (SetupApi.CM_Get_Device_ID(devInfoData.DevInst, sbDeviceID, sbDeviceID.Capacity, 0) == SetupApi.CR.SUCCESS)
                        {
                            regInfo.mDeviceProperties[DEVICE_ID_KEY] = sbDeviceID.ToString();
                        }
                        deviceRegistryList.Add(regInfo);
                    }

                    devicePathIndex++;
                }
            }
            if (devicePathIndex == 0)
            {
                UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "GetDevicePathList", typeof(SetupApi));
            }

            if (deviceInfo != IntPtr.Zero)
            {
                SetupApi.SetupDiDestroyDeviceInfoList(deviceInfo);
            }

            return(devicePathIndex > 0);
        }
Example #3
0
        private string GetPath(IntPtr deviceInfoList, SetupApi.SP_DEVICE_INTERFACE_DATA deviceInfo)
        {
            var deviceInterfaceDetailData = IntPtr.Zero;

            uint needed;

            if (!SetupApi.SetupDiGetDeviceInterfaceDetail(deviceInfoList, ref deviceInfo,
                                                          IntPtr.Zero, 0,
                                                          out needed, IntPtr.Zero))
            {
                var error = Marshal.GetLastWin32Error();

                if (error != 122)
                {
                    return(string.Empty);
                }
            }


            var spDeviceInterfaceData = new SetupApi.SP_DEVICE_INTERFACE_DATA();

            spDeviceInterfaceData.cbSize = Marshal.SizeOf(spDeviceInterfaceData);

            try {
                deviceInterfaceDetailData = Marshal.AllocHGlobal((int)(8 + needed));
                var size = IntPtr.Size == 8 ? 8 : 6;
                Marshal.WriteInt32(deviceInterfaceDetailData, size);
                if (!SetupApi.SetupDiGetDeviceInterfaceDetail(deviceInfoList, ref deviceInfo,
                                                              deviceInterfaceDetailData, needed, out needed, IntPtr.Zero))
                {
                    var error = Marshal.GetLastWin32Error();
                }

                var pStr = IntPtr.Add(deviceInterfaceDetailData, sizeof(uint));
                var path = Marshal.PtrToStringUni(pStr);

                return(path);
            } finally {
                Marshal.FreeHGlobal(deviceInterfaceDetailData);
            }
        }
Example #4
0
        public KeyboardController()
        {
            // Get HID GUID.
            Hid.HidD_GetHidGuid(out Guid hidGuid);

            List <HidDevice> devs      = new List <HidDevice>();
            IntPtr           classDevs = SetupApi.SetupDiGetClassDevs(ref hidGuid, IntPtr.Zero, IntPtr.Zero, DiGetClassFlags.Present | DiGetClassFlags.DeviceInterface);

            try
            {
                // Enumerate HID devices.
                for (uint index = 0;; ++index)
                {
                    SP_DEVICE_INTERFACE_DATA deviceInterfaceData = new SP_DEVICE_INTERFACE_DATA {
                        cbSize = (uint)Marshal.SizeOf <SP_DEVICE_INTERFACE_DATA>()
                    };
                    if (!SetupApi.SetupDiEnumDeviceInterfaces(classDevs, IntPtr.Zero, ref hidGuid, index, ref deviceInterfaceData))
                    {
                        break;                         // End of list.
                    }
                    SP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData = new SP_DEVICE_INTERFACE_DETAIL_DATA {
                        cbSize = IntPtr.Size == 8 ? 8U : (uint)(4 + Marshal.SystemDefaultCharSize)
                    };
                    SP_DEVINFO_DATA deviceInfoData = new SP_DEVINFO_DATA {
                        cbSize = (uint)Marshal.SizeOf <SP_DEVINFO_DATA>()
                    };
                    if (SetupApi.SetupDiGetDeviceInterfaceDetail(classDevs, ref deviceInterfaceData, ref deviceInterfaceDetailData, 256U, out uint requiredSize, ref deviceInfoData))
                    {
                        // Found one.
                        // Try to open device.
                        string         devPath   = deviceInterfaceDetailData.DevicePath;
                        SafeFileHandle devHandle = Kernel32.CreateFile(devPath, Kernel32.GENERIC_READ | Kernel32.GENERIC_WRITE,
                                                                       Kernel32.FILE_SHARE_READ | Kernel32.FILE_SHARE_WRITE, IntPtr.Zero, Kernel32.CREATE_NEW | Kernel32.CREATE_ALWAYS, Kernel32.FILE_FLAG_OVERLAPPED, IntPtr.Zero);

                        // Get HID attributes.
                        HIDD_ATTRIBUTES attributes = default;
                        HIDP_CAPS       caps;
                        Hid.HidD_GetAttributes(devHandle, ref attributes);

                        // Match against Gigabyte keyboard product IDs.
                        if (!supportedKeyboards.TryGetValue(attributes.VendorID, out ushort[] pids))
Example #5
0
        /// <summary>
        /// Gets a list of WinUSB device paths for the specified interface guid.
        /// </summary>
        /// <param name="deviceInterfaceGuid">The DeviceInterfaceGUID to search for.</param>
        /// <param name="devicePathList">A list of device paths associated with the <paramref name="deviceInterfaceGuid"/>.</param>
        /// <returns>True of one or more device paths was found.</returns>
        /// <remarks>
        /// Each device path string in the <paramref name="devicePathList"/> represents a seperate WinUSB device (interface).
        /// </remarks>
        /// <seealso cref="GetWinUsbRegistryList"/>
        public static bool GetDevicePathList(Guid deviceInterfaceGuid, out List <String> devicePathList)
        {
            devicePathList = new List <string>();
            int devicePathIndex = 0;

            SetupApi.SP_DEVICE_INTERFACE_DATA    interfaceData = SetupApi.SP_DEVICE_INTERFACE_DATA.Empty;
            SetupApi.DeviceInterfaceDetailHelper detailHelper;

            IntPtr deviceInfo = SetupApi.SetupDiGetClassDevs(ref deviceInterfaceGuid, null, IntPtr.Zero, SetupApi.DICFG.PRESENT | SetupApi.DICFG.DEVICEINTERFACE);

            if (deviceInfo != IntPtr.Zero)
            {
                while ((SetupApi.SetupDiEnumDeviceInterfaces(deviceInfo, null, ref deviceInterfaceGuid, devicePathIndex, ref interfaceData)))
                {
                    int length = 1024;
                    detailHelper = new SetupApi.DeviceInterfaceDetailHelper(length);
                    bool bResult = SetupApi.SetupDiGetDeviceInterfaceDetail(deviceInfo, ref interfaceData, detailHelper.Handle, length, out length, null);
                    if (bResult)
                    {
                        devicePathList.Add(detailHelper.DevicePath);
                    }

                    devicePathIndex++;
                }
            }
            if (devicePathIndex == 0)
            {
                UsbError.Error(ErrorCode.Win32Error, Marshal.GetLastWin32Error(), "GetDevicePathList", typeof(SetupApi));
            }

            if (deviceInfo != IntPtr.Zero)
            {
                SetupApi.SetupDiDestroyDeviceInfoList(deviceInfo);
            }

            return(devicePathIndex > 0);
        }
Example #6
0
        public static bool FindHidDevices(ref List <string> DevicePathNames)
        {
            Debug.WriteLine("findHidDevices() -> Method called");

            // Initialize the internal variables required for performing the search
            var  bufferSize       = 0;
            var  detailDataBuffer = IntPtr.Zero;
            bool deviceFound;
            var  deviceInfoSet = new IntPtr();
            var  lastDevice    = false;
            int  listIndex;
            var  deviceInterfaceData = new SpDeviceInterfaceData();

            // Get the required GUID
            var systemHidGuid = new Guid();

            Hid.HidD_GetHidGuid(ref systemHidGuid);
            Debug.WriteLine(string.Format("findHidDevices() -> Fetched GUID for HID devices ({0})", systemHidGuid.ToString()));

            try
            {
                // Here we populate a list of plugged-in devices matching our class GUID (DIGCF_PRESENT specifies that the list
                // should only contain devices which are plugged in)
                Debug.WriteLine("findHidDevices() -> Using SetupDiGetClassDevs to get all devices with the correct GUID");
                deviceInfoSet = SetupApi.SetupDiGetClassDevs(ref systemHidGuid, IntPtr.Zero, IntPtr.Zero, Constants.DigcfPresent | Constants.DigcfDeviceinterface);

                // Reset the deviceFound flag and the memberIndex counter
                deviceFound = false;
                listIndex   = 0;

                deviceInterfaceData.cbSize = Marshal.SizeOf(deviceInterfaceData);

                // Look through the retrieved list of class GUIDs looking for a match on our interface GUID
                do
                {
                    //Debug.WriteLine("usbGenericHidCommunication:findHidDevices() -> Enumerating devices");
                    var success = SetupApi.SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref systemHidGuid, listIndex, ref deviceInterfaceData);

                    if (!success)
                    {
                        //Debug.WriteLine("usbGenericHidCommunication:findHidDevices() -> No more devices left - giving up");
                        lastDevice = true;
                    }
                    else
                    {
                        // The target device has been found, now we need to retrieve the device path so we can open
                        // the read and write handles required for USB communication

                        // First call is just to get the required buffer size for the real request
                        SetupApi.SetupDiGetDeviceInterfaceDetail
                            (deviceInfoSet,
                            ref deviceInterfaceData,
                            IntPtr.Zero,
                            0,
                            ref bufferSize,
                            IntPtr.Zero);

                        // Allocate some memory for the buffer
                        detailDataBuffer = Marshal.AllocHGlobal(bufferSize);
                        Marshal.WriteInt32(detailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);

                        // Second call gets the detailed data buffer
                        //Debug.WriteLine("usbGenericHidCommunication:findHidDevices() -> Getting details of the device");
                        SetupApi.SetupDiGetDeviceInterfaceDetail
                            (deviceInfoSet,
                            ref deviceInterfaceData,
                            detailDataBuffer,
                            bufferSize,
                            ref bufferSize,
                            IntPtr.Zero);

                        // Skip over cbsize (4 bytes) to get the address of the devicePathName.
                        var pDevicePathName = new IntPtr(detailDataBuffer.ToInt32() + 4);

                        // Get the String containing the devicePathName.
                        DevicePathNames.Add(Marshal.PtrToStringAuto(pDevicePathName));

                        //Debug.WriteLine(string.Format("usbGenericHidCommunication:findHidDevices() -> Found matching device (memberIndex {0})", memberIndex));
                        deviceFound = true;
                    }
                    listIndex += 1;
                }while (lastDevice != true);
            }
            catch (Exception)
            {
                // Something went badly wrong... output some debug and return false to indicated device discovery failure
                Debug.WriteLine("findHidDevices() -> EXCEPTION: Something went south whilst trying to get devices with matching GUIDs - giving up!");
                return(false);
            }
            finally
            {
                // Clean up the unmanaged memory allocations
                if (detailDataBuffer != IntPtr.Zero)
                {
                    // Free the memory allocated previously by AllocHGlobal.
                    Marshal.FreeHGlobal(detailDataBuffer);
                }

                if (deviceInfoSet != IntPtr.Zero)
                {
                    SetupApi.SetupDiDestroyDeviceInfoList(deviceInfoSet);
                }
            }

            if (deviceFound)
            {
                Debug.WriteLine(string.Format("findHidDevices() -> Found {0} devices with matching GUID", (DevicePathNames.Count).ToString(CultureInfo.InvariantCulture)));
            }
            else
            {
                Debug.WriteLine("findHidDevices() -> No matching devices found");
            }

            return(deviceFound);
        }
Example #7
0
        public static bool FindHidDevices(ref string[] listOfDevicePathNames, ref int numberOfDevicesFound)
        {
            TmoShare.WriteLog("DeviceDiscovery:findHidDevices() -> 开始查找所有HID设备");

            // Initialise the internal variables required for performing the search
            var  bufferSize       = 0;
            var  detailDataBuffer = IntPtr.Zero;
            bool deviceFound;
            var  deviceInfoSet = new IntPtr();
            var  lastDevice    = false;
            int  listIndex;
            var  deviceInterfaceData = new SpDeviceInterfaceData();

            // Get the required GUID
            var systemHidGuid = new Guid();

            Hid.HidD_GetHidGuid(ref systemHidGuid);
            TmoShare.WriteLog(string.Format("DeviceDiscovery:findHidDevices() -> 找到HID设备全局 GUID {0}", systemHidGuid));

            try
            {
                // Here we populate a list of plugged-in devices matching our class GUID (DIGCF_PRESENT specifies that the list
                // should only contain devices which are plugged in)
                TmoShare.WriteLog("DeviceDiscovery:findHidDevices() -> 获取所有HID设备句柄");
                deviceInfoSet = SetupApi.SetupDiGetClassDevs(ref systemHidGuid, IntPtr.Zero, IntPtr.Zero, Constants.DigcfPresent | Constants.DigcfDeviceinterface);

                // Reset the deviceFound flag and the memberIndex counter
                deviceFound = false;
                listIndex   = 0;

                deviceInterfaceData.cbSize = Marshal.SizeOf(deviceInterfaceData);

                // Look through the retrieved list of class GUIDs looking for a match on our interface GUID
                do
                {
                    TmoShare.WriteLog("DeviceDiscovery:findHidDevices() -> 获取设备信息");
                    var success = SetupApi.SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref systemHidGuid, listIndex, ref deviceInterfaceData);

                    if (!success)
                    {
                        TmoShare.WriteLog("DeviceDiscovery:findHidDevices() -> 已经找到最后一个-停止");
                        lastDevice = true;
                    }
                    else
                    {
                        // The target device has been found, now we need to retrieve the device path so we can open
                        // the read and write handles required for USB communication

                        // First call is just to get the required buffer size for the real request
                        SetupApi.SetupDiGetDeviceInterfaceDetail
                            (deviceInfoSet,
                            ref deviceInterfaceData,
                            IntPtr.Zero,
                            0,
                            ref bufferSize,
                            IntPtr.Zero);

                        // Allocate some memory for the buffer
                        detailDataBuffer = Marshal.AllocHGlobal(bufferSize);
                        Marshal.WriteInt32(detailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);

                        // Second call gets the detailed data buffer
                        TmoShare.WriteLog("DeviceDiscovery:findHidDevices() -> 获取设备详细信息");
                        SetupApi.SetupDiGetDeviceInterfaceDetail
                            (deviceInfoSet,
                            ref deviceInterfaceData,
                            detailDataBuffer,
                            bufferSize,
                            ref bufferSize,
                            IntPtr.Zero);

                        // Skip over cbsize (4 bytes) to get the address of the devicePathName.
                        var pDevicePathName = new IntPtr(detailDataBuffer.ToInt32() + 4);

                        // Get the String containing the devicePathName.
                        listOfDevicePathNames[listIndex] = Marshal.PtrToStringAuto(pDevicePathName).ToUpper();

                        TmoShare.WriteLog(string.Format("DeviceDiscovery:findHidDevices() -> 将找到的设备添加进列表 (索引 {0})", listIndex));
                        deviceFound = true;
                        listIndex++;
                    }
                }while (lastDevice != true);
            }
            catch (Exception ex)
            {
                // Something went badly wrong... output some debug and return false to indicated device discovery failure
                TmoShare.WriteLog("DeviceDiscovery:findHidDevices() -> 发生异常: " + ex.Message);
                return(false);
            }
            finally
            {
                // Clean up the unmanaged memory allocations
                if (detailDataBuffer != IntPtr.Zero)
                {
                    // Free the memory allocated previously by AllocHGlobal.
                    Marshal.FreeHGlobal(detailDataBuffer);
                }

                if (deviceInfoSet != IntPtr.Zero)
                {
                    SetupApi.SetupDiDestroyDeviceInfoList(deviceInfoSet);
                }
            }

            if (deviceFound)
            {
                TmoShare.WriteLog(String.Format("DeviceDiscovery:findHidDevices() -> 一共找到{0}个HID设备", listIndex));
                numberOfDevicesFound = listIndex;
            }
            else
            {
                TmoShare.WriteLog("DeviceDiscovery:findHidDevices() -> 没有找到HID设备");
            }

            return(deviceFound);
        }
Example #8
0
        private string FindDevicePath()
        {
            var hidGuid        = HidGuid;
            var deviceInfoList = SetupApi.SetupDiGetClassDevs(ref hidGuid, null, IntPtr.Zero, DIGCF.DeviceInterface | DIGCF.Present);

            if (IntPtr.Zero == deviceInfoList)
            {
                return(null);
            }

            try {
                for (uint i = 0; ; i++)
                {
                    var deviceInterfaceData = new SP_DEVICE_INTERFACE_DATA();
                    deviceInterfaceData.cbSize = (uint)Marshal.SizeOf(deviceInterfaceData);
                    if (!SetupApi.SetupDiEnumDeviceInterfaces(deviceInfoList, IntPtr.Zero, ref hidGuid, i, ref deviceInterfaceData))
                    {
                        break;                         // end of the list
                    }
                    var deviceInfoData = new SP_DEVINFO_DATA();
                    deviceInfoData.cbSize = (uint)Marshal.SizeOf(deviceInfoData);
                    if (!SetupApi.SetupDiEnumDeviceInfo(deviceInfoList, i, ref deviceInfoData))
                    {
                        continue;
                    }

                    const uint bufferSize     = 1048;
                    var        propertyBuffer = Marshal.AllocHGlobal((int)bufferSize);
                    try {
                        uint requiredSize;
                        uint propRegDataType;
                        if (!SetupApi.SetupDiGetDeviceRegistryProperty(
                                deviceInfoList, ref deviceInfoData, SPDRP.HardwareId, out propRegDataType,
                                propertyBuffer, bufferSize, out requiredSize)
                            )
                        {
                            continue;
                        }

                        var deviceId = Marshal.PtrToStringAuto(propertyBuffer, (int)requiredSize);
                        if (String.IsNullOrEmpty(deviceId) ||
                            !deviceId.ToUpperInvariant().Contains(_deviceIdUpper)
                            )
                        {
                            continue;
                        }

                        var deviceInterfaceDetailData = new SP_DEVICE_INTERFACE_DETAIL_DATA {
                            cbSize = IntPtr.Size == 8 ? 8 : (uint)(4 + Marshal.SystemDefaultCharSize)
                        };
                        var interfaceDetailOk = SetupApi.SetupDiGetDeviceInterfaceDetail(
                            deviceInfoList, ref deviceInterfaceData, ref deviceInterfaceDetailData,
                            SP_DEVICE_INTERFACE_DETAIL_DATA.BUFFER_SIZE, out requiredSize, ref deviceInfoData);

                        if (interfaceDetailOk)
                        {
                            return(deviceInterfaceDetailData.devicePath);
                        }
                    }
                    finally {
                        Marshal.FreeHGlobal(propertyBuffer);
                    }
                }
            }
            finally {
                SetupApi.SetupDiDestroyDeviceInfoList(deviceInfoList);
            }
            return(null);
        }
Example #9
0
        public static List <string> FindAllHidDevices()
        {
            var listOfDevicePathNames = new List <string>();
            var detailDataBuffer      = IntPtr.Zero;
            int listIndex             = 0;
            var deviceInterfaceData   = new SpDeviceInterfaceData();

            int lasterror = 0;

            // Get the required HID class GUID
            var systemHidGuid = new Guid();

            Hid.HidD_GetHidGuid(ref systemHidGuid);

            IntPtr deviceInfoSet = SetupDiGetClassDevs(ref systemHidGuid);

            deviceInterfaceData.cbSize = Marshal.SizeOf(deviceInterfaceData);

            try
            {
                // Look through the retrieved list of class GUIDs looking for a match on our interface GUID
                // SetupDiEnumDeviceInterfaces will return false if it fails for any reason, including when no more items are left
                // so we need to keep looping until the last thrown error is ERROR_NO_MORE_ITEMS
                // Note: we post increment lastIndex so each subsequent call refers to a new device
                while (SetupApi.SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref systemHidGuid, listIndex++, ref deviceInterfaceData) || (lasterror = Marshal.GetLastWin32Error()) != Constants.ERROR_NO_MORE_ITEMS)
                {
                    if (lasterror != 0)
                    {
                        // SetupDiEnumDeviceInterfaces failed and it wasn't ERROR_NO_MORE_ITEMS as this would have stopped the loop
                        Debug.WriteLine("SetupDiEnumDeviceInterfaces failed for run {0} with error {1}", listIndex, lasterror);
                        continue;
                    }

                    int bufferSize = 0;

                    // The target device has been found, now we need to retrieve the device path so we can open
                    // the read and write handles required for USB communication

                    // First call fails with ERROR_INSUFFICIENT_BUFFER and is used just to get the required buffer size for the real request
                    var success = SetupApi.SetupDiGetDeviceInterfaceDetail(
                        deviceInfoSet,
                        ref deviceInterfaceData,
                        IntPtr.Zero,
                        0,
                        ref bufferSize,
                        IntPtr.Zero
                        );

                    // Allocate some memory for the buffer
                    detailDataBuffer = Marshal.AllocHGlobal(bufferSize);
                    Marshal.WriteInt32(detailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);

                    // Second call gets the detailed data buffer
                    success = SetupApi.SetupDiGetDeviceInterfaceDetail(
                        deviceInfoSet,
                        ref deviceInterfaceData,
                        detailDataBuffer,
                        bufferSize,
                        ref bufferSize,
                        IntPtr.Zero
                        );

                    if (!success)
                    {
                        Debug.WriteLine("SetupDiGetDeviceInterfaceDetail failed for run {0} with error {1}", listIndex, Marshal.GetLastWin32Error());
                        continue;
                    }

                    // Skip over cbsize (4 bytes) to get the address of the devicePathName.
                    var pDevicePathName = IntPtr.Add(detailDataBuffer, 4);

                    // Get the String containing the devicePathName.
                    listOfDevicePathNames.Add(Marshal.PtrToStringAuto(pDevicePathName));
                }
            }
            catch (Exception)
            {
                // Something went badly wrong...
                listOfDevicePathNames.Clear();
            }
            finally
            {
                // Clean up the unmanaged memory allocations and free resources held by the windows API
                Marshal.FreeHGlobal(detailDataBuffer);
                SetupApi.SetupDiDestroyDeviceInfoList(deviceInfoSet);
            }

            return(listOfDevicePathNames);
        }
Example #10
0
        public static IEnumerable <UsbController> GetControllers()
        {
            var hostGUID = new Guid(UsbConstants.GUID_DEVINTERFACE_HUBCONTROLLER);

            var h = SetupApi.SetupDiGetClassDevs(ref hostGUID, default(int), IntPtr.Zero, UsbConstants.DIGCF_PRESENT | UsbConstants.DIGCF_DEVICEINTERFACE);

            if (h.ToInt32() != UsbConstants.INVALID_HANDLE_VALUE)
            {
                var ptrBuf = Marshal.AllocHGlobal(UsbConstants.BUFFER_SIZE);

                var i       = default(int);
                var success = default(bool);
                do
                {
                    var host = new UsbController(null)
                    {
                        ControllerIndex = i,
                    };

                    var dia = new SpDeviceInterfaceData();
                    dia.cbSize = Marshal.SizeOf(dia);

                    success = SetupApi.SetupDiEnumDeviceInterfaces(h, IntPtr.Zero, ref hostGUID, i, ref dia);
                    if (success)
                    {
                        var da = new SpDevinfoData();
                        da.cbSize = Marshal.SizeOf(da);

                        var didd = new SpDeviceInterfaceDetailData
                        {
                            cbSize = 4 + Marshal.SystemDefaultCharSize,
                        };

                        var nRequiredSize = default(int);
                        var nBytes        = UsbConstants.BUFFER_SIZE;

                        if (SetupApi.SetupDiGetDeviceInterfaceDetail(h, ref dia, ref didd, nBytes, ref nRequiredSize, ref da))
                        {
                            host.ControllerDevicePath = didd.DevicePath;

                            var requiredSize = default(int);
                            var regType      = UsbConstants.REG_SZ;

                            if (SetupApi.SetupDiGetDeviceRegistryProperty(h, ref da, UsbConstants.SPDRP_DEVICEDESC, ref regType, ptrBuf, UsbConstants.BUFFER_SIZE, ref requiredSize))
                            {
                                host.ControllerDeviceDesc = Marshal.PtrToStringAuto(ptrBuf);
                            }
                            if (SetupApi.SetupDiGetDeviceRegistryProperty(h, ref da, UsbConstants.SPDRP_DRIVER, ref regType, ptrBuf, UsbConstants.BUFFER_SIZE, ref requiredSize))
                            {
                                host.ControllerDriverKeyName = Marshal.PtrToStringAuto(ptrBuf);
                            }
                        }

                        yield return(host);
                    }
                    i++;
                }while (success);

                Marshal.FreeHGlobal(ptrBuf);
                SetupApi.SetupDiDestroyDeviceInfoList(h);
            }
        }
Example #11
0
        public static UsbDevice FindDriveLetter(string driveName)
        {
            UsbDevice foundDevice = null;
            var       instanceID  = string.Empty;

            var devNum = UsbLogic.GetDeviceNumber($@"\\.\{driveName.TrimEnd('\\')}");

            if (devNum < default(int))
            {
                return(foundDevice);
            }

            var diskGUID = new Guid(UsbConstants.GUID_DEVINTERFACE_DISK);

            var h = SetupApi.SetupDiGetClassDevs(ref diskGUID, default(int), IntPtr.Zero, UsbConstants.DIGCF_PRESENT | UsbConstants.DIGCF_DEVICEINTERFACE);

            if (h.ToInt32() != UsbConstants.INVALID_HANDLE_VALUE)
            {
                var i       = default(int);
                var success = true;
                do
                {
                    var dia = new SpDeviceInterfaceData();
                    dia.cbSize = Marshal.SizeOf(dia);

                    success = SetupApi.SetupDiEnumDeviceInterfaces(h, IntPtr.Zero, ref diskGUID, i, ref dia);
                    if (success)
                    {
                        var da = new SpDevinfoData();
                        da.cbSize = Marshal.SizeOf(da);

                        var didd = new SpDeviceInterfaceDetailData
                        {
                            cbSize = 4 + Marshal.SystemDefaultCharSize,
                        };

                        var nRequiredSize = default(int);
                        int nBytes        = UsbConstants.BUFFER_SIZE;
                        if (SetupApi.SetupDiGetDeviceInterfaceDetail(h, ref dia, ref didd, nBytes, ref nRequiredSize, ref da))
                        {
                            if (UsbLogic.GetDeviceNumber(didd.DevicePath) == devNum)
                            {
                                SetupApi.CM_Get_Parent(out IntPtr ptrPrevious, da.DevInst, default(int));

                                var ptrInstanceBuf = Marshal.AllocHGlobal(nBytes);
                                SetupApi.CM_Get_Device_ID(ptrPrevious, ptrInstanceBuf, nBytes, default(int));
                                instanceID = Marshal.PtrToStringAuto(ptrInstanceBuf);

                                Marshal.FreeHGlobal(ptrInstanceBuf);
                                break;
                            }
                        }
                    }
                    i++;
                } while (success);
                SetupApi.SetupDiDestroyDeviceInfoList(h);
            }

            if (instanceID.StartsWith("USB\\"))
            {
                foundDevice = UsbLogic.FindDeviceByInstanceID(instanceID, driveName);
            }

            return(foundDevice);
        }
Example #12
0
        private void _DeviceSearchThread()
        {
            _Logger.Info("Started");
            while (_Running)
            {
                var loopStart = DateTime.Now;

                #region Device enumeration

                var devices = new List <UsbDevice>();

                var detailDataBuffer = IntPtr.Zero;
                var deviceInfoSet    = IntPtr.Zero;
                try
                {
                    int listIndex           = 0;
                    int lastError           = 0;
                    var deviceInterfaceData = new SpDeviceInterfaceData();

                    var systemHidGuid = new Guid();
                    Hid.HidD_GetHidGuid(ref systemHidGuid);
                    deviceInfoSet = SetupApi.SetupDiGetClassDevs(ref systemHidGuid, IntPtr.Zero, IntPtr.Zero, Constants.DigcfPresent | Constants.DigcfDeviceinterface);
                    deviceInterfaceData.cbSize = Marshal.SizeOf(deviceInterfaceData);

                    while (SetupApi.SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref systemHidGuid, listIndex++, ref deviceInterfaceData) || (lastError = Marshal.GetLastWin32Error()) != Constants.ERROR_NO_MORE_ITEMS)
                    {
                        if (lastError == 0)
                        {
                            int bufferSize = 0;
                            SetupApi.SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref deviceInterfaceData, IntPtr.Zero, 0, ref bufferSize, IntPtr.Zero);
                            detailDataBuffer = Marshal.AllocHGlobal(bufferSize);
                            Marshal.WriteInt32(detailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);
                            if (SetupApi.SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref deviceInterfaceData, detailDataBuffer, bufferSize, ref bufferSize, IntPtr.Zero))
                            {
                                var pDevicePathName = IntPtr.Add(detailDataBuffer, 4);
                                var devicePath      = Marshal.PtrToStringAuto(pDevicePathName);

                                // Get device capabilities (to determine usage page)
                                using (var hidHandle = Kernel32.CreateFile(devicePath, 0, Constants.FileShareRead | Constants.FileShareWrite, IntPtr.Zero, Constants.OpenExisting, 0, 0))
                                {
                                    var preparsedData = IntPtr.Zero;
                                    try
                                    {
                                        preparsedData = new IntPtr();
                                        Hid.HidD_GetPreparsedData(hidHandle, ref preparsedData);
                                        var caps = new HidpCaps();
                                        Hid.HidP_GetCaps(preparsedData, ref caps);

                                        var attrs = new HiddAttributes();
                                        Hid.HidD_GetAttributes(hidHandle, ref attrs);

                                        // Only add the device if it has our VID, PID, and RAW usage page
                                        var deviceClass = FindDeviceClass(attrs.VendorID, attrs.ProductID, attrs.VersionNumber, caps.UsagePage);
                                        if (deviceClass != null)
                                        {
                                            var manufacturer = new StringBuilder(STRING_SIZE_LIMIT);
                                            var product      = new StringBuilder(STRING_SIZE_LIMIT);
                                            var serial       = new StringBuilder(STRING_SIZE_LIMIT);
                                            Hid.HidD_GetManufacturerString(hidHandle, manufacturer, STRING_SIZE_LIMIT);
                                            Hid.HidD_GetProductString(hidHandle, product, STRING_SIZE_LIMIT);
                                            Hid.HidD_GetSerialNumberString(hidHandle, serial, STRING_SIZE_LIMIT);
                                            var device = new UsbDevice(new DeviceInstance(deviceClass, devicePath, manufacturer.ToString(), product.ToString(), serial.ToString()), caps);
                                            devices.Add(device);
                                        }
                                    }
                                    finally
                                    {
                                        // Free up the memory before finishing
                                        if (preparsedData != IntPtr.Zero)
                                        {
                                            Hid.HidD_FreePreparsedData(preparsedData);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    _Logger.Error(ex, "Error scanning for devices:");
                    devices.Clear();
                }
                finally
                {
                    // Clean up the unmanaged memory allocations and free resources held by the windows API
                    if (detailDataBuffer != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(detailDataBuffer);
                    }
                    if (deviceInfoSet != IntPtr.Zero)
                    {
                        SetupApi.SetupDiDestroyDeviceInfoList(deviceInfoSet);
                    }
                }

                var addedDevices   = devices.Except(_CurrentDevices);
                var removedDevices = _CurrentDevices.Except(devices);

                _CurrentDevices = devices;

                if (DeviceRemoved != null)
                {
                    foreach (var dev in removedDevices)
                    {
                        _Logger.Info("Device removed: {0}", dev);
                        DeviceRemoved(this, new DeviceEventArgs(dev.Instance));
                    }
                }
                if (DeviceAdded != null)
                {
                    foreach (var dev in addedDevices)
                    {
                        _Logger.Info("Device added: {0}", dev);
                        DeviceAdded(this, new DeviceEventArgs(dev.Instance));
                    }
                }

                #endregion

                #region Active device I/O

                // If we receive a request to change the active device while we are processing messages, we need to stop immediately because they are about to become invalid
                {
                    byte[] msg;
                    while (true)
                    {
                        byte[] response = null;

                        // Block until SetActiveDevice finishes
                        lock (_LockObject)
                        {
                            // If we created a new message queue in the call to SetActiveDevice, this will return false and we'll break out of the loop
                            if (_ActiveDevice == null || !_MessageQueue.TryDequeue(out msg))
                            {
                                break;
                            }
                            try
                            {
                                response = SendDeviceRequest(_ActiveDevice, msg);
                            }
                            catch (Exception ex)
                            {
                                _Logger.Error(ex, "Error communicating with device: {0} (0x{1:X8})", ex.Message, ex.HResult);
                            }
                        }

                        if (response != null)
                        {
                            ProcessResponse(msg, response);
                        }
                        else
                        {
                            _Logger.Error("Failed to read data from device. req = {0}", FormatByteArray(msg));
                        }
                    }
                }

                // Get LED config (it may have changed)
                {
                    byte[] response = null;
                    byte[] msg      = CreateSimpleMessage(hid_pkt_req.HID_PKT_REQ_CONFIG_LED_GET);

                    // Block until SetActiveDevice finishes
                    lock (_LockObject)
                    {
                        if (_ActiveDevice != null)
                        {
                            try
                            {
                                response = SendDeviceRequest(_ActiveDevice, msg);
                            }
                            catch (Exception ex)
                            {
                                _Logger.Error(ex, "Error communicating with device: {0} (0x{1:X8})", ex.Message, ex.HResult);
                            }
                        }
                    }

                    if (response != null)
                    {
                        ProcessResponse(msg, response);
                    }
                }

                // Get LED status
                {
                    byte[] response = null;
                    byte[] msg      = new byte[2];
                    msg[0] = (byte)hid_pkt_req.HID_PKT_REQ_LED_STATUS;
                    msg[1] = 0;

                    var ledStatuses = new List <LedColor>();

                    do
                    {
                        lock (_LockObject)
                        {
                            if (_ActiveDevice != null)
                            {
                                try
                                {
                                    response = SendDeviceRequest(_ActiveDevice, msg);
                                }
                                catch (Exception ex)
                                {
                                    _Logger.Error(ex, "Error communicating with device: {0} (0x{1:X8})", ex.Message, ex.HResult);
                                }
                            }
                        }

                        if (response != null)
                        {
                            // Parse response
                            for (byte i = 0; i < response[1] && i < 10; i++)
                            {
                                var led = new LedColor(
                                    response[i * 3 + 2],
                                    response[i * 3 + 3],
                                    response[i * 3 + 4]
                                    );
                                ledStatuses.Add(led);
                            }

                            msg[1] += 10;
                        }
                    } while (response != null && response[0] == (byte)hid_pkt_res.HID_PKT_RES_MORE);

                    LedStatusReceived?.Invoke(this, new LedStatusReceivedEventArgs(ledStatuses));
                }

                #endregion

                // Wait until the entire loop execution is at least 100ms
                var loopTime = DateTime.Now - loopStart;
                if (loopTime < LOOP_DELAY)
                {
                    var waitTime = LOOP_DELAY - loopTime;
                    Thread.Sleep(waitTime);
                }
            }
        }