天天看點

Window7 USB HID 即插即用觸摸屏 原始資料擷取

源頭

這是一個擦PG的活,由于前期和甲方沒有溝通好,導緻甲方Vxworks沒辦法讀USB  HID觸摸屏的資料,然後同僚攤手就繞到我這來了。我的第一想法是甲方技術能力不足,USB Host擷取不到正确資料怪我咯?在後面的聯系中才知道甲方也是個二包,現在是真正的甲方提出這個要求,他們也沒轍了。幫人幫到底送佛送到西,行吧。

分析

1、第一個想法是用一塊stm32做一個USB host然後通過網口把觸控資料轉發出去,但衆所周知USB調試是個坑,而且USB host的項目并沒有做過除了讀U盤外的東西,心裡還是比較沒底的,作為保留方案。

2、第二個想法是用Windows或者Linux現成的HID驅動,将枚舉過程省略掉,直接進入通訊階段,先把系統的觸摸接口屏蔽掉,然後把資料抓出來轉發。這個方案看上去比較容易,但後面才知道有一個坑。

實踐

第一個方案就壓根沒有去操作,因為懶的。

第二個方案先是用的 Win10 平台測試,用CreateFile接口想去開觸屏裝置,但是似乎觸屏和滑鼠鍵盤是系統獨占的裝置,沒辦法打開,另外 Win10 的觸摸屏屏蔽隻能在裝置管理器中将HID裝置禁用,這個就麻煩了,如果禁用了HID裝置,那麼顯而易見程式也是擷取不到任何資料的。然後做結構的上司默默走過說,Win7可以在控制台裡關掉。遂找了台Win7,真可以在觸摸設定裡關掉(上司我改行畫圖得了)。是以Win10要做這個事情還真是不太容易,WinXP又不支援多點觸摸,是以幹這事要辦簡單點還真的Win7來幹。至于CreateFile打不開裝置的問題,我第一個想法就是git,然後就有了如下操作。

開發

git上找到個項目HidLibrary(c#),(既然是擦XX的活幹了就行)源碼都沒看,直接看的example test,調用非常容易。基本過程就是掃出連接配接上的HID裝置清單,找出相比對的裝置,打開裝置并注冊消息函數,在資料擷取到後該咋滴咋滴就行。

以下是打開觸摸屏裝置的動作,其中拔出和插入的操作委托與git上的test一緻,實測在打開裝置拔出再插入後能自動打開裝置:

private void RefreshDevices()
{
    _deviceList = HidDevices.Enumerate().ToArray();
    if (_deviceList.Length > 0)
    {
        foreach(HidDevice device in _deviceList)
        {
            //Console.WriteLine(device.Attributes.VendorId);
            //Console.WriteLine(device.Attributes.ProductId);
            //Console.WriteLine();

            if (device.Attributes.VendorId == VendorID && device.Attributes.ProductId == ProductID)
            {
                if (_selectedDevice != null)
                _selectedDevice.CloseDevice();

                _selectedDevice = device;
                _selectedDevice.OpenDevice();
                _selectedDevice.MonitorDeviceEvents = true;
                _selectedDevice.Inserted += Device_Inserted;
                _selectedDevice.Removed += Device_Removed;
                _selectedDevice.ReadReport(ReadProcess);
                return;
            }
        }

        MessageBox.Show("探測不到指定的觸摸屏裝置。");
        return;
    }

    MessageBox.Show("探測不到任何HID裝置。");
    return;
}
           

裝置的互動通過委托來觸發:

public delegate void ReadHandlerDelegate(HidReport report);

private void ReadProcess(HidReport report)
{
    BeginInvoke(new ReadHandlerDelegate(ReadHandler), new object[] { report });
}

private void ReadHandler(HidReport report)
{
    this.Invoke(new Action(() =>
    {
        AppendToTextBox(report.Data);
    }));

    _selectedDevice.ReadReport(ReadProcess);
}
           

具體的資料操作就放在AppendToTextBox中了。

具體的觸屏資料就不貼了,跟着描述符定義即可。

至此這個活就幹完了,想了想過程,第一是自己想複雜了,第二是操作中确實對一些系統特性不夠熟悉,不過好在半天就解決了問題,沒有在Win10上耽擱太久(上司我要學畫圖)。