Перечисление USB-устройств через их USB-класс

Я пытаюсь динамически перечислить USB-устройства, подключенные к компьютеру, которые соответствуют определенному UsbDeviceClass

Информация о классе USB-устройств, которые я пытаюсь перечислить в диспетчере устройств, следующая

Информация диспетчера устройств

В идеале он должен иметь возможность перечислять порты Com, поскольку устройства, которые я ищу в списке, в частности, это Arduinos.

DeviceInformationCollection usbDeviceInfoCollection = await DeviceInformation.FindAllAsync(UsbDevice.GetDeviceClassSelector(new UsbDeviceClass()
{
    ClassCode = 0x02,
    SubclassCode = 0x02,
    ProtocolCode = 0x01
}));
Debug.WriteLineIf(usbDeviceInfoCollection.Count == 1, "1 USB device found");
Debug.WriteLineIf(usbDeviceInfoCollection.Count != 1, usbDeviceInfoCollection.Count + " USB devices found");

for (int i = 0; i < usbDeviceInfoCollection.Count; i++)
{
    Debug.WriteLine("USB Device " + (i + 1));
    Debug.WriteLine("ID: " + usbDeviceInfoCollection[i].Id);
    Debug.WriteLine("Name: " + usbDeviceInfoCollection[i].Name);
    Debug.WriteLine("Properties: " + usbDeviceInfoCollection[i].Properties);
    Debug.WriteLine("");
}

В приведенном выше коде показано, как я пытался достичь этого, но до сих пор мне не повезло. Это связано с тем, что когда программа запускается, она возвращает 0 устройств при подключении устройства.

Я также попытался использовать предопределенный класс UsbDeviceClasses.CdcControl, но также не достиг нужных результатов.

Буду признателен за то, как правильно это сделать.


Также, поскольку это проект UWP, я включил возможности ниже, чтобы он мог обнаружить устройства, в которых я хочу.

<DeviceCapability Name="serialcommunication">
  <Device Id="any">
    <Function Type="name:serialPort"/>
  </Device>
</DeviceCapability>

Пример вывода информации Arduino из небольшого изменения программы с использованием DeviceInformation.FindAllAsync() без UsbDeviceClass в качестве jsanalytics.

Device 1354
EnclosureLocation: Windows.Devices.Enumeration.EnclosureLocation
ID: \\?\USB#VID_2341&PID_0243#9543231323835131B172#{86e0d1e0-8089-11d0-9ce4-08003e301f73}
IsDefault: False
IsEnabled: True
Kind: DeviceInterface
Name: Genuino Uno (COM6)
Pairing: Windows.Devices.Enumeration.DeviceInformationPairing
Properties: System.__ComObject

Изображение реестра

введите описание изображения здесь


Обновите, эту страницу о более конкретных возможностях USB, которые включают name:cdcControl, classId:02 * *. Тем не менее, я все еще не могу его перечислить через подключенные устройства, например, это удаленное приложение arduino; Windows Remote Arduino Experience.


Быстрое редактирование для уточнения. Я не могу подключиться к устройству, я просто не могу перечислить устройства, которые являются подклассом 02 подкласса 02. 01. Можно подключиться к моему устройству, указав VID и PID, но в этом текущем случае, который не соответствует точке.

Ответы

Ответ 1

Обновление 8:

Arduino устройства могут быть эффективно перечислены путем создания подходящей строки запроса AQS с нуля. См. Создайте селектор устройств.

private async void Page_Loaded(object sender, RoutedEventArgs e)
{
    var aqs = "System.ItemNameDisplay:~<\"Arduino\"";
    MyDeviceList.ItemsSource = await DeviceInformation.FindAllAsync(aqs);
}

введите описание изображения здесь


Обновление 7:

Обратитесь к драйверам класса USB-устройств, включенным в Windows.

Класс 2 (CDC = класс устройств связи)/ Подкласс 2 (ACM = Абстрактная модель управления) не, характерные для устройств Arduino.

Чтобы иметь возможность перечислять устройство по классу/подклассу, это конкретное устройство должно определить свой собственный Специальный класс поставщика (0xff) и соответствующий подкласс, как, например, устройства Android, как показано выше. Либо ваше устройство не делает этого, либо неправильно настроено.


Обновление 6:

Посмотрите здесь: Универсальные образцы Windows.

В частности, вас может заинтересовать:

SerialArduino

CustomSerialDeviceAccess

CustomUsbDeviceAccess

Все они перечисляют/добавляют устройства с помощью обработки событий, а не пытаются перечислить все. Опять же, CustomSerialDeviceAccess перечисляет и подключается к моему устройству Android без проблем. введите описание изображения здесь


Обновить 5: в ответ на раздел комментариев

1) Мне не нужно было явно добавлять какие-либо специальные возможности в манифест приложения, чтобы он работал.

2) Образ вашего реестра показывает PID = 0043, который не тот, который мы хотим.

3) На изображении отображается только первая запись для PID = 0243, которая нужна нам, но не показывает, как многие после этого.

4) Очевидно, что 2/2/1 не является правильным вариантом, поскольку для не не существует, или Android или что-то еще.

5) Вы попробовали мое предложение на Обновить 3? Enum DeviceClass имеет 7 опций. Вы пробовали их всех?

6) Возможно, вам понадобится объединить предложения от Обновить 3 и Обновить 4.


Обновление 4:

Вы также можете указать свою собственную логику:

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
    }

    private async void Page_Loaded(object sender, RoutedEventArgs e)
    {
        MyDeviceList.ItemsSource = await GetCustomDeviceList();
    }

    private async Task<List<DeviceInformation>> GetCustomDeviceList()
    {
        var list = await DeviceInformation.FindAllAsync();

        var customList = new List<DeviceInformation>();

        foreach (DeviceInformation di in list)
            if (IsMyDevice(di))
                customList.Add(di);

        return customList;
    }

    private bool IsMyDevice(DeviceInformation di)
    {
        // Your custom logic here
        return di.Name.Contains("SM-G55") && di.Id.Contains("ADB");
    }
}

Обновление 3:

Следующий альтернативный вызов возвращает все 3 устройства, подключенные одновременно к нашей машине: телефон Android, считыватель Kindle и флэш-накопитель:

MyDeviceList.ItemsSource = await DeviceInformation.FindAllAsync(DeviceClass.PortableStorageDevice);

Если DeviceClass.PortableStorageDevice не работает для вас, попробуйте другие параметры enum и сообщите нам о результатах. Здесь наш:

введите описание изображения здесь


Обновление 2:

В HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB у нас есть 4 записи для нашего устройства: VID = 04E8 и PID = 6860, как показано ниже. Покажите то же самое для своего устройства. В вашем случае VID = 2341 и PID = 0243. Пожалуйста, покажите нам, сколько записей у вас в вашем реестре и какие соответствующие комбинации класс/подкласс/протокол.

введите описание изображения здесь


Обновление 1:

Остерегайтесь нескольких записей реестра для одного и того же устройства с различными комбинациями класса/подкласса/протокола. Помимо того, что мы уже упоминали ранее, мы обнаружили еще 3 записи, связанные с одним и тем же устройством, ни один из которых не возвращает желаемый результат, в том числе тот самый, который вы используете:

0/0/0:

USB\DevClass_00 & SubClass_00 & Prot_00 USB\DevClass_00 & SubClass_00 USB\DevClass_00 USB\КОМПОЗИТ

2/2/1: (То же самое вы используете)

USB\Class_02 & SubClass_02 & Prot_01 USB\Class_02 & SubClass_02 USB\Class_02 USB\SAMSUNG_MOBILE & Modem USB\Vid_04E8 & Pid_6860 & MI_01 USB\Vid_04E8 & Pid_6860 & Class_02 & SubClass_02 & Prot_01 USB\SAMSUNG_MOBILE & Class_02 & SubClass_02 & Prot_01

6/1/1:

USB\MS_COMP_MTP USB\Class_06 & SubClass_01 & Prot_01 USB\Class_06 & SubClass_01 USB\Class_06 USB\Vid_04E8 & Pid_6860 & MI_00 USB\Vid_04E8 & Pid_6860 & Class_06 & SubClass_01 & Prot_01 USB\SAMSUNG_MOBILE & Class_06 & SubClass_01 & Prot_01


Убедитесь, что для вашего устройства есть правильный класс, подкласс и протокол, который вы можете получить из реестра /strong > , как описано ЗДЕСЬ. См. 3-й пункт в разделе Примечания. Вот интересующий фрагмент:

Класс устройства, подкласс и коды протокола, вы можете получить это информацию из записи реестра CompatibleIds, найденной под Параметры устройства.

Ваш код работает без проблем с Android-устройством. Ниже соответствующей информации реестра, которая была использована. Если вы перейдете к HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB, вы должны узнать свое устройство Arduino и получить необходимую информацию.

Имя ключа:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\VID_04E8&PID_6860&ADB

CompatibleIDs:

USB\Class_ff&SubClass_42&Prot_01
USB\Class_ff&SubClass_42
USB\Class_ff
USB\SAMSUNG_MOBILE&ADB
USB\Vid_04E8&Pid_6860&MI_03
USB\Vid_04E8&Pid_6860&Class_ff&SubClass_42&Prot_01
USB\SAMSUNG_MOBILE&Class_ff&SubClass_42&Prot_01

XAML:

<Page
    x:Class="App40.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App40"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" 
    Loaded="Page_Loaded">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <ScrollViewer>
            <ItemsControl x:Name="MyDeviceList">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Border BorderBrush="White"  BorderThickness="1">
                            <StackPanel>
                                <TextBlock Text="{Binding Name}"/>
                                <ItemsControl ItemsSource="{Binding Properties}"/>
                            </StackPanel>
                        </Border>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </ScrollViewer>
    </Grid>
</Page>

CS:

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
    }

    private async void Page_Loaded(object sender, RoutedEventArgs e)
    {
        MyDeviceList.ItemsSource = await DeviceInformation.FindAllAsync(UsbDevice.GetDeviceClassSelector(new UsbDeviceClass()
        {
            ClassCode = 0xff,
            SubclassCode = 0x42,
            ProtocolCode = 0x01
        }));
    }
}

введите описание изображения здесь

Ответ 2

Вы можете перечислить внешнее USB-устройство, сначала вам нужно добавить это разрешение в файл Package.appxmanifest.

 <uap:Capability Name="removableStorage" />

Затем напишите этот код в своем приложении.

    var removableDevices = KnownFolders.RemovableDevices;
    var externalDrives = await removableDevices.GetFoldersAsync();
    foreach (var item in externalDrives)
      {
          var name = item.DisplayName;
      }

Теперь для списка обновления перезапустите код.