// The following procedure works with the USB device driver; upon finding all instances of USB devices
        // that match the requested Guid, the procedure checks the corresponding registry keys to find the unique
        // serial number to show to the user; the serial number is decided by the device driver at installation
        // time and stored in a registry key whose name is the hash of the laser etched security key of the device
        private static IEnumerable<PortDefinition> EnumeratePorts( Guid guid )
        {
            var devInfo = NativeMethods.SetupDiGetClassDevs( ref guid, null, 0, NativeMethods.DIGCF_DEVICEINTERFACE | NativeMethods.DIGCF_PRESENT );

            if( devInfo == NativeMethods.INVALID_HANDLE_VALUE )
                yield break;

            try
            {
                var interfaceData = new NativeMethods.SP_DEVICE_INTERFACE_DATA( );
                interfaceData.cbSize = Marshal.SizeOf( interfaceData );

                var index = 0;

                while( NativeMethods.SetupDiEnumDeviceInterfaces( devInfo, 0, ref guid, index++, ref interfaceData ) )
                {
                    PortDefinition pd = null;
                    try
                    {
                        var detail = new NativeMethods.SP_DEVICE_INTERFACE_DETAIL_DATA( );
                        // explicit size of unmanaged structure must be provided, because it does not include transfer buffer
                        // for whatever reason on 64 bit machines the detail size is 8 rather than 5, likewise the interfaceData.cbSize
                        // is 32 rather than 28 for non 64bit machines, therefore, we make the detemination of the size based 
                        // on the interfaceData.cbSize (kind of hacky but it works).
                        detail.cbSize = interfaceData.cbSize == 32 ? 8 : 5;

                        // get device interface details to allow opening the port for querying the friendly name
                        if( !NativeMethods.SetupDiGetDeviceInterfaceDetail( devInfo, ref interfaceData, ref detail, Marshal.SizeOf( detail ) * 2, 0, 0 ) )
                            continue;

                        var port = detail.DevicePath.ToLower( );

                        using( var s = new WinUsb_AsyncUsbStream( port ) )
                        {
                            var displayName = s.RetrieveStringFromDevice( USB_DISPLAY_STRING_INDEX );

                            var hash = s.RetrieveStringFromDevice( USB_FRIENDLY_STRING_INDEX );
                            if( ( displayName == null ) || ( hash == null ) )
                                yield break;

                            displayName += "_" + hash;
                            pd = PortDefinition.CreateInstanceForWinUsb( displayName, port );
                            if( !pd.Properties.Contains( DeviceHash ) )
                                pd.Properties.Add( DeviceHash, hash );
                        }
                    }
                    catch(IOException)
                    {
                        // go to next device
                    }
                    if( pd != null )
                        yield return pd;
                }
            }
            finally
            {
                NativeMethods.SetupDiDestroyDeviceInfoList( devInfo );
            }
        }
示例#2
0
        // The following procedure works with the USB device driver; upon finding all instances of USB devices
        // that match the requested Guid, the procedure checks the corresponding registry keys to find the unique
        // serial number to show to the user; the serial number is decided by the device driver at installation
        // time and stored in a registry key whose name is the hash of the laser etched security key of the device
        private static void EnumeratePorts(Guid inquiriesInterface, string driverVersion, SortedList lst)
        {
            IntPtr devInfo = NativeMethods.SetupDiGetClassDevs(ref inquiriesInterface, null, 0, NativeMethods.DIGCF_DEVICEINTERFACE | NativeMethods.DIGCF_PRESENT);

            if (devInfo == NativeMethods.INVALID_HANDLE_VALUE)
            {
                return;
            }

            NativeMethods.SP_DEVICE_INTERFACE_DATA interfaceData = new NativeMethods.SP_DEVICE_INTERFACE_DATA(); interfaceData.cbSize = Marshal.SizeOf(interfaceData);

            int index = 0;

            while (NativeMethods.SetupDiEnumDeviceInterfaces(devInfo, 0, ref inquiriesInterface, index++, ref interfaceData))
            {
                NativeMethods.SP_DEVICE_INTERFACE_DETAIL_DATA detail = new NativeMethods.SP_DEVICE_INTERFACE_DETAIL_DATA();
                // explicit size of unmanaged structure must be provided, because it does not include transfer buffer
                // for whatever reason on 64 bit machines the detail size is 8 rather than 5, likewise the interfaceData.cbSize
                // is 32 rather than 28 for non 64bit machines, therefore, we make the detemination of the size based
                // on the interfaceData.cbSize (kind of hacky but it works).
                if (interfaceData.cbSize == 32)
                {
                    detail.cbSize = 8;
                }
                else
                {
                    detail.cbSize = 5;
                }


                if (NativeMethods.SetupDiGetDeviceInterfaceDetail(devInfo, ref interfaceData, ref detail, Marshal.SizeOf(detail) * 2, 0, 0))
                {
                    string port = detail.DevicePath.ToLower();

                    AsyncUsbStream s = null;

                    try
                    {
                        s = new AsyncUsbStream(port);

                        string displayName     = s.RetrieveStringFromDevice(IOCTL_SPOTUSB_DISPLAY_NAME);
                        string hash            = s.RetrieveStringFromDevice(IOCTL_SPOTUSB_DEVICE_HASH);
                        string operationalPort = s.RetrieveStringFromDevice(IOCTL_SPOTUSB_PORT_NAME);

                        if ((operationalPort == null) || (displayName == null) || (hash == null))
                        {
                            continue;
                        }

                        // convert  kernel format to user mode format
                        // kernel   : @"\??\USB#Vid_beef&Pid_0009#5&4162af8&0&1#{09343630-a794-10ef-334f-82ea332c49f3}"
                        // user     : @"\\?\usb#vid_beef&pid_0009#5&4162af8&0&1#{09343630-a794-10ef-334f-82ea332c49f3}"
                        StringBuilder operationalPortUser = new StringBuilder();
                        operationalPortUser.Append(@"\\?");
                        operationalPortUser.Append(operationalPort.Substring(3));

                        // change the display name if there is a collision (otherwise you will only be able to use one of the devices)
                        displayName += "_" + hash;
                        if (lst.ContainsKey(displayName))
                        {
                            int i = 2;
                            while (lst.ContainsKey(displayName + " (" + i + ")"))
                            {
                                i++;
                            }
                            displayName += " (" + i + ")";
                        }

                        PortDefinition pd = PortDefinition.CreateInstanceForUsb(displayName, operationalPortUser.ToString());

                        RetrieveProperties(hash, ref pd, s);

                        lst.Add(pd.DisplayName, pd);
                    }
                    catch
                    {
                    }
                    finally
                    {
                        if (s != null)
                        {
                            s.Close();
                        }
                    }
                }
            }

            NativeMethods.SetupDiDestroyDeviceInfoList(devInfo);
        }
        // The following procedure works with the USB device driver; upon finding all instances of USB devices
        // that match the requested Guid, the procedure checks the corresponding registry keys to find the unique
        // serial number to show to the user; the serial number is decided by the device driver at installation
        // time and stored in a registry key whose name is the hash of the laser etched security key of the device
        private static IEnumerable <PortDefinition> EnumeratePorts(Guid guid)
        {
            var devInfo = NativeMethods.SetupDiGetClassDevs(ref guid, null, 0, NativeMethods.DIGCF_DEVICEINTERFACE | NativeMethods.DIGCF_PRESENT);

            if (devInfo == NativeMethods.INVALID_HANDLE_VALUE)
            {
                yield break;
            }

            try
            {
                var interfaceData = new NativeMethods.SP_DEVICE_INTERFACE_DATA( );
                interfaceData.cbSize = Marshal.SizeOf(interfaceData);

                var index = 0;

                while (NativeMethods.SetupDiEnumDeviceInterfaces(devInfo, 0, ref guid, index++, ref interfaceData))
                {
                    PortDefinition pd = null;
                    try
                    {
                        var detail = new NativeMethods.SP_DEVICE_INTERFACE_DETAIL_DATA( );
                        // explicit size of unmanaged structure must be provided, because it does not include transfer buffer
                        // for whatever reason on 64 bit machines the detail size is 8 rather than 5, likewise the interfaceData.cbSize
                        // is 32 rather than 28 for non 64bit machines, therefore, we make the detemination of the size based
                        // on the interfaceData.cbSize (kind of hacky but it works).
                        detail.cbSize = interfaceData.cbSize == 32 ? 8 : 5;

                        // get device interface details to allow opening the port for querying the friendly name
                        if (!NativeMethods.SetupDiGetDeviceInterfaceDetail(devInfo, ref interfaceData, ref detail, Marshal.SizeOf(detail) * 2, 0, 0))
                        {
                            continue;
                        }

                        var port = detail.DevicePath.ToLower( );

                        using (var s = new WinUsb_AsyncUsbStream(port))
                        {
                            var displayName = s.RetrieveStringFromDevice(USB_DISPLAY_STRING_INDEX);

                            var hash = s.RetrieveStringFromDevice(USB_FRIENDLY_STRING_INDEX);
                            if ((displayName == null) || (hash == null))
                            {
                                yield break;
                            }

                            displayName += "_" + hash;
                            pd           = PortDefinition.CreateInstanceForWinUsb(displayName, port);
                            if (!pd.Properties.Contains(DeviceHash))
                            {
                                pd.Properties.Add(DeviceHash, hash);
                            }
                        }
                    }
                    catch (IOException)
                    {
                        // go to next device
                    }
                    if (pd != null)
                    {
                        yield return(pd);
                    }
                }
            }
            finally
            {
                NativeMethods.SetupDiDestroyDeviceInfoList(devInfo);
            }
        }
        // The following procedure works with the USB device driver; upon finding all instances of USB devices
        // that match the requested Guid, the procedure checks the corresponding registry keys to find the unique
        // serial number to show to the user; the serial number is decided by the device driver at installation
        // time and stored in a registry key whose name is the hash of the laser etched security key of the device
        private static void EnumeratePorts( Guid inquiriesInterface, string driverVersion, SortedList lst )
        {
            IntPtr devInfo = NativeMethods.SetupDiGetClassDevs( ref inquiriesInterface, null, 0, NativeMethods.DIGCF_DEVICEINTERFACE | NativeMethods.DIGCF_PRESENT );

            if(devInfo == NativeMethods.INVALID_HANDLE_VALUE)
            {
                return;
            }

            NativeMethods.SP_DEVICE_INTERFACE_DATA interfaceData = new NativeMethods.SP_DEVICE_INTERFACE_DATA(); interfaceData.cbSize = Marshal.SizeOf(interfaceData);
            
            int index = 0;

            while(NativeMethods.SetupDiEnumDeviceInterfaces( devInfo, 0, ref inquiriesInterface, index++, ref interfaceData ))
            {
                NativeMethods.SP_DEVICE_INTERFACE_DETAIL_DATA detail = new NativeMethods.SP_DEVICE_INTERFACE_DETAIL_DATA();
                // explicit size of unmanaged structure must be provided, because it does not include transfer buffer
                // for whatever reason on 64 bit machines the detail size is 8 rather than 5, likewise the interfaceData.cbSize
                // is 32 rather than 28 for non 64bit machines, therefore, we make the detemination of the size based 
                // on the interfaceData.cbSize (kind of hacky but it works).
                if( interfaceData.cbSize == 32 )
                {
                    detail.cbSize = 8;
                }
                else
                {
                    detail.cbSize = 5;
                }
                

                if(NativeMethods.SetupDiGetDeviceInterfaceDetail( devInfo, ref interfaceData, ref detail, Marshal.SizeOf(detail) * 2, 0, 0 ))
                {
                    string port = detail.DevicePath.ToLower();

                    AsyncUsbStream s = null;

                    try
                    {
                        s = new AsyncUsbStream( port );

                        string displayName     = s.RetrieveStringFromDevice( IOCTL_SPOTUSB_DISPLAY_NAME ); 
                        string hash            = s.RetrieveStringFromDevice( IOCTL_SPOTUSB_DEVICE_HASH  ); 
                        string operationalPort = s.RetrieveStringFromDevice( IOCTL_SPOTUSB_PORT_NAME    ); 

                        if((operationalPort == null) || (displayName == null) || (hash == null))
                        {
                            continue;
                        }

                        // convert  kernel format to user mode format                        
                        // kernel   : @"\??\USB#Vid_beef&Pid_0009#5&4162af8&0&1#{09343630-a794-10ef-334f-82ea332c49f3}"
                        // user     : @"\\?\usb#vid_beef&pid_0009#5&4162af8&0&1#{09343630-a794-10ef-334f-82ea332c49f3}"
                        StringBuilder operationalPortUser = new StringBuilder();
                        operationalPortUser.Append( @"\\?" );
                        operationalPortUser.Append( operationalPort.Substring( 3 ) );

                        // change the display name if there is a collision (otherwise you will only be able to use one of the devices)
                        displayName += "_" + hash;
                        if (lst.ContainsKey(displayName))
                        {
                            int i = 2;
                            while (lst.ContainsKey(displayName + " (" + i + ")"))
                            {
                                i++;
                            }
                            displayName += " (" + i + ")";
                        }

                        PortDefinition pd  = PortDefinition.CreateInstanceForUsb( displayName, operationalPortUser.ToString() );
                        
                        RetrieveProperties( hash, ref pd, s );

                        lst.Add( pd.DisplayName, pd );
                    }
                    catch
                    {
                    }
                    finally
                    {
                        if(s != null) s.Close();
                    }
                }
            }

            NativeMethods.SetupDiDestroyDeviceInfoList( devInfo );
        }