Feature Report я не использую, а примеров хватает в этом самом проекте.
Вот так у меня делается енумерация:
Код
private void RefreshDevices()
{
devices.Clear();
if ((selectedDevice != null) && selectedDevice.IsOpen)
selectedDevice.CloseDevice();
foreach (HidDevice dev in HidDevices.Enumerate(0x1FC9, 0x204F))
{
MyUsbDevice newDevice = new MyUsbDevice();
newDevice.device = dev;
newDevice.hasSerial = false;
newDevice.serialId = "";
devices.Add(newDevice);
}
foreach (MyUsbDevice dev in devices)
{
if (!dev.hasSerial)
{
dev.device.OpenDevice();
DeviceReadSerial(dev);
dev.device.CloseDevice();
}
}
comboBox1.Items.Clear();
int index = 0;
foreach (MyUsbDevice dev in devices)
{
if (dev.hasSerial)
{
UsbDeviceInfo inf = new UsbDeviceInfo();
inf.index = index;
inf.info = "Redut RS-232 #" + dev.serialId;
comboBox1.Items.Add(inf);
}
index++;
}
if (comboBox1.Items.Count > 0) comboBox1.SelectedIndex = 0;
}
Как видно, енумерация непростая: на одном VID/PID могут сидеть несколько девайсов, поэтому дополнительно запрашивается инфа о номере устройства.
Вот примерно так по мнению автора проекта обслуживается устройство:
Код
private void Devices_SelectedIndexChanged(object sender, EventArgs e)
{
UsbDeviceInfo item = (UsbDeviceInfo)comboBox1.SelectedItem;
int index = item.index;
try
{
MyUsbDevice dev = devices[index];
selectedDevice = dev.device;
selectedDevice.OpenDevice();
Output.AppendText(">USB device opened\r\n");
selectedDevice.MonitorDeviceEvents = true;
selectedDevice.Inserted += Device_Inserted;
selectedDevice.Removed += Device_Removed;
selectedDevice.ReadReport(ReadProcess);
}
catch (Exception)
{
RefreshDevices();
}
}
private void ReadProcess(HidReport report)
{
BeginInvoke(new ReadHandlerDelegate(ReadHandler), new object[] { report });
}
private void ReadHandler(HidReport report)
{
if(selectedDevice == null)
return;
if(!selectedDevice.IsOpen)
return;
if(!selectedDevice.IsConnected)
return;
//configuration packet
if (report.Data[0] == 2)
{
int length = report.Data[1];
Output.AppendText("<data: 02 " + length);
for (int i = 0; i < length; i++)
{
Output.AppendText("" + (char)(report.Data[i + 2]));
}
Output.AppendText("\r\n");
}
//virtual UART packet
if (report.Data[0] == 0)
{
int length = report.Data[1];
Output.AppendText("<data: 00 " + length);
String data = "";
for (int i = 0; i < length; i++)
{
data += (char)(report.Data[i + 2]);
}
Output.AppendText(data);
Output.AppendText("\r\n");
if(Linked)
serialPort1.Write(report.Data, 2, length);
}
//Redut packet
if (report.Data[0] == 1)
{
int length = report.Data[1];
Output.AppendText("<data: 01 " + length);
for (int i = 0; i < length; i++)
{
Output.AppendText(String.Format("{0:X2}", report.Data[i + 2]));
}
Output.AppendText("\r\n");
if (Linked)
{
serialPort1.Write(report.Data, 2, length);
Output.AppendText(">port: ");
for (int i = 0; i < length; i++)
{
Output.AppendText(String.Format("{0:X2}", report.Data[i + 2]));
}
Output.AppendText("\r\n");
}
}
selectedDevice.ReadReport(ReadProcess);
}
private void Device_Inserted()
{
if (InvokeRequired)
{
BeginInvoke(new Action(Device_Inserted));
return;
}
if (selectedDevice == null)
return;
if (!selectedDevice.IsOpen)
selectedDevice.OpenDevice();
selectedDevice.ReadReport(ReadProcess);
if (Linked)
{
if (!serialPort1.IsOpen)
{
serialPort1.Open();
//serialPort1.DiscardInBuffer();
//serialPort1.DiscardOutBuffer();
Output.AppendText(">Serial port opened\r\n");
}
}
Output.AppendText(">Connected\r\n");
}
private void Device_Removed()
{
if (InvokeRequired)
{
BeginInvoke(new Action(Device_Removed));
return;
}
if (Linked)
{
serialPort1.Close();
}
Output.AppendText(">Disconnected\r\n");
if (selectedDevice != null)
{
selectedDevice.CloseDevice();
Output.AppendText(">Serial port closed\r\n");
}
}
Не очень удобно, но вполне работоспособно.