USB HID上位机测试(C#)

目录

1、基本测试

1.1、通过Bus Hound可以看到设备列表

 1.2、 通过API获取到设备接口文件列表​

1.3、用BUS Hound收发测试

 2、C#上位机

2.1、打开设备

报告ReportID

2.2、发送数据

注意:

测试:

 2.3、异步接收

3、其他测试

3.1、中断端点时间测试


下位机这两天已经折腾出一个一二了,在配合上位机完整学习一下,下位机芯片是STM32F103VB

1、基本测试

1.1、通过Bus Hound可以看到设备列表

USB HID上位机测试(C#)_第1张图片

 1.2、 通过API获取到设备接口文件列表

USB HID上位机测试(C#)_第2张图片

 可以看出,每个接口有一个对应的操作对象,三个设备是可以独立操作的。

  • \\?\hid#vid_0480&pid_5750&mi_00#8&eff1a39&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
  • \\?\hid#vid_0480&pid_5750&mi_01#8&32d657fb&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}\kbd
  •  \\?\hid#vid_0480&pid_5750&mi_02#8&1b12cbb6&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}

用   mi_(接口编号)  区别,接口编号对应配置描述表里的接口编号,鼠标0,键盘1,自定义HID 2

 此处的复合设备是单独的接口操作的,就会产生对应的操作文件。如果是通过同一个接口,用报告描述符ID来产生的对个设备,将不会出现对个设备文件,操作时需要通过报告描述符ID来寻找设备。

1.3、用BUS Hound收发测试

bus hound 不会限制发送长度,下位机端也可以不用报告描述符来描述具体发送数据的意义及格式

 USB HID上位机测试(C#)_第3张图片

 2、C#上位机

C# HID上位机icon-default.png?t=LA92https://download.csdn.net/download/ai5945fei/43657670

参考:

【C#】HID API_beatfan的博客-CSDN博客https://blog.csdn.net/u010875635/article/details/73321066?spm=1035.2023.3001.6557&utm_medium=distribute.pc_relevant_bbs_down.none-task-blog-2~default~OPENSEARCH~default-5.nonecase&depth_1-utm_source=distribute.pc_relevant_bbs_down.none-task-blog-2~default~OPENSEARCH~default-5.nonecase其中做了些修改,感觉原先的有点小问题

2.1、打开设备

不建议去打开一些未知的设备,确定是谁再去打开,可以通过VID和PID,接口编号三个参数确定我们的目标设备。

public HID_RETURN OpenDevice(string deviceNme)
{
    if (deviceOpened == false)
    {
        IntPtr device = CreateFile(deviceNme,
                                    DESIREDACCESS.GENERIC_READ | DESIREDACCESS.GENERIC_WRITE,
                                    0,
                                    0,
                                    CREATIONDISPOSITION.OPEN_EXISTING,
                                    FLAGSANDATTRIBUTES.FILE_FLAG_OVERLAPPED,
                                    0);
        if (device != INVALID_HANDLE_VALUE)
        {
            HIDD_ATTRIBUTES attributes;
            IntPtr serialBuff = Marshal.AllocHGlobal(512);
            HidD_GetAttributes(device, out attributes);
            HidD_GetSerialNumberString(device, serialBuff, 512);
            string deviceStr = Marshal.PtrToStringAuto(serialBuff);
            Marshal.FreeHGlobal(serialBuff);

            IntPtr preparseData;
            HIDP_CAPS caps;
            HidD_GetPreparsedData(device, out preparseData);
            HidP_GetCaps(preparseData, out caps);
            HidD_FreePreparsedData(preparseData);
            outputReportLength = caps.OutputReportByteLength;
            inputReportLength = caps.InputReportByteLength;

            hidDevice = new FileStream(new SafeFileHandle(device, false), FileAccess.ReadWrite, inputReportLength, true);
            deviceOpened = true;
            BeginAsyncRead();

            hHubDevice = device;
            return HID_RETURN.SUCCESS;
        }

        return HID_RETURN.DEVICE_NOT_FIND;
    }
    else
        return HID_RETURN.DEVICE_OPENED;
}    

报告ReportID

测试发现:

  • 如果报告描述符有问题,则获取出来的caps对应值就为0,我开始没设置端点OUT的信息,caps.OutputReportByteLength就为0。
  • 实际的值会默认加上报告描述符描述表ReportID,首字节位置。默认为0,多报告表就对应变化。及caps.OutputReportByteLength = 1字节ReportID + 实际报告表描述的数据长度。
HIDP_CAPS caps;
HidP_GetCaps(preparseData, out caps);
outputReportLength = caps.OutputReportByteLength;
inputReportLength = caps.InputReportByteLength;

2.2、发送数据

public HID_RETURN Write(report r)
{
    if (deviceOpened)
    {
        try
        {
            byte[] buffer = new byte[outputReportLength];
            int txlen = r.reportBuff.Length;
            if (txlen > outputReportLength) txlen = outputReportLength;
            buffer[0] = r.reportID;
            Array.Copy(r.reportBuff, 0, buffer, 1, txlen);
            hidDevice.Write(buffer, 0, buffer.Length);
            hidDevice.Flush();//立即发送数据
            return HID_RETURN.SUCCESS;
        }
        catch
        {
            EventArgs ex = new EventArgs();
            OnDeviceRemoved(ex);//发出设备移除消息
            CloseDevice();
            return HID_RETURN.NO_DEVICE_CONECTED;
        }
    }
    return HID_RETURN.WRITE_FAILD;
}

注意:

  • 写入数据之后调用 hidDevice.Flush,数据才会立即发送,否则就会乱发送。
  • 发送数据的buffer的长度必须和outputReportLength一致,否则会报错,不知缘由。
  • buffer的首字节为ReportID,一个报告下默认为0。(如果有多个时,这个参数就有用了)

测试:

同时勾选两个上这两个

USB HID上位机测试(C#)_第4张图片

 

会发现106.3 发送8个字节,109是9个字节,加上了ReportID,下位机收到的也是8个字节。

 2.3、异步接收

private void ReadCompleted(IAsyncResult iResult)
{
    byte[] readBuff = (byte[])(iResult.AsyncState);
    try
    {
        hidDevice.EndRead(iResult);//读取结束,如果读取错误就会产生一个异常
        byte[] reportData = new byte[readBuff.Length - 1];
        for (int i = 1; i < readBuff.Length; i++)
            reportData[i - 1] = readBuff[i];
        report e = new report(readBuff[0], reportData);
        OnDataReceived(e); //发出数据到达消息
        if (!deviceOpened) return;
        BeginAsyncRead();//启动下一次读操作
    }
    catch  //读写错误,设备已经被移除
    {
        //MyConsole.WriteLine("设备无法连接,请重新插入设备");
        EventArgs ex = new EventArgs();
        OnDeviceRemoved(ex);//发出设备移除消息
        CloseDevice();
    }
}
  • 接收到的数据头字节也是ReportID,数据为其后的内容。
  • 如果上传的数据长度和报告描述表里规定的长度不一致,API也收不到数据,但是BusHound能监控到数据。(肯定是哪里有问题,后续再查)

3、其他测试

3.1、中断端点时间测试

连续发送两个包,查看发送时间间隔

private void button2_Click(object sender, EventArgs e)
{
    SendBytes(new byte[] { 0xA5, 0, 1, 0 });
    SendBytes(new byte[] { 0xA5, 0, 2, 0 });
}

OUT端点设置

USB HID上位机测试(C#)_第5张图片

 结果:

USB HID上位机测试(C#)_第6张图片

点击了两次,连续发送的两个包之间间隔是31ms,设置的端点中断时间为32ms


对比:改成10ms之后,对应间隔变成8ms左右

USB HID上位机测试(C#)_第7张图片

 修改之后,需要删除原来的设备重新安装设备这个值才会刷新,或者修改VID,PID也可以。否则PC会记录并使用以前的值。

 所以要是需要下发的数据块速接收到,将 bInterval: Polling Interval  改小即可。

你可能感兴趣的:(USB,USB上位机,C#)