製造業 スマートDX推進課 スマート工場DIY日記

製造業で働いているごく普通の社内SEです。日々の活動で生まれた成果物を共有します。

【C# .NET Framework 4.8】USB機器を解析して自作アプリに取り込む【Wireshook】

テスターのデモ機を渡され 「USB接続できるから、抵抗値の検査アプリ作って」と言われ調べてみると
専用アプリでしかデータを取り込めないご様子。

仕様を見るとリアルタイムでExcel出力が出来るので、そこから取り込むことは可能だが、、、
バグの原因にしかならないので、直接データを取得を行いたい。

という訳で、USBのやり取りを傍受し、解析してC#のプログラムに取り込みました。
何かの参考になれば幸いです。

解析にはWireshookを使用

まずは Wiredhook をインストールします。同時に USBPcap もインストール。
インストール手順はこちらが参考になります。

community.cisco.com

 

Wireshook を開き、早速USBの通信を傍受します。

USBの通信データは USBPcap1USBcap2 に入ってきます。どちらかを開いてみます。
今回は「USBcap2」の方を開いてみました。

 

USBマウスを繋いでいたので、マウスをすごい勢いでデータを受信しています。
マウスのデータを取得しないよう、フィルタを掛けます。

 

Source 2.3.1Destination 2.3.1 が表示されないよう、フィルタに追記

!(usb.src == "2.3.1") && !(usb.dst == "2.3.1")

Enter を押すとフィルタが適用され、マウスのデータが非表示になります。

これでスッキリしたので、目的のテスター測定値取得の通信を探ってみます。
テスター記録専用アプリの記録開始をONにしてみました。

 

上記のような通信が記録されました。
中身を確認してみましょう。

 

どうやら SET_REPORT Request で測定値の取得リクエストを送り URB_INTERRUPT in で測定値を受信しているようです。

Data FragmentHID Data で送受信内容が確認できます。

これをプログラムに取り込んでみたいと思います。

テストコード

今回使用するライブラリが .NET Framework しか対応していない為、プロジェクト作成の際にご注意ください。

HidLibrary』を使用しますので、NuGet パッケージマネージャー よりインストールしてください。

using System;
using System.Linq;
using System.Windows.Forms;

namespace USB_TEST
{
    public partial class Form1 : Form
    {
        const int VendorId = 0x11AD;
        const int ProductId = 0x0700;
        HidLibrary.HidDevice _device;

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            _device = HidLibrary.HidDevices.Enumerate(VendorId, ProductId).FirstOrDefault();
            _device.OpenDevice();

            _device.ReadReport(OnReport, 100);
            _device.WriteReport(
                new HidLibrary.HidReport(3)
                {
                    Data = new byte[] { 0x00, 0x82, 0x66 }
                });
        }

        void OnReport(HidLibrary.HidReport report)
        {
            this.Invoke((MethodInvoker)(() =>
            {
                textBox1.Text = func_convert(report.Data);
            }));
_device?.ReadReport(OnReport, 100); } } }

button1 クリックでデータ取得し、 textBox1 に測定結果を格納というテストコードです。
func_convert は受信データの処理を行ってますが、関係ないので割愛します。

テストコード解説

        const int VendorId = 0x11AD;
        const int ProductId = 0x0700;

該当のUSB機器の Vendor IDProduct ID を格納しておきます。

Vendor IDProduct ID の調べ方は
[デバイスマネージャー]から 該当のUSB機器を探し
[右クリック]→[プロパティ]→[詳細]→[ハードウェアID]

今回の場合は
VID (Vendor ID) = 0x11AD
PID (Product ID) = 0x0700

ドライバー削除や更新をすると、VIDPIDが変わる可能性がある為、ご注意ください。
VIDPIDなしでUSB機器を検索する方法はありますので、情報探してみてください。

 

            _device = HidLibrary.HidDevices.Enumerate(VendorId, ProductId).FirstOrDefault();
            _device.OpenDevice();

Vendor IDProduct ID を指定して、デバイスをオープンします。

 

            _device.ReadReport(OnReport, 100);
            _device.WriteReport(
                new HidLibrary.HidReport(3)
                {
                    Data = new byte[] { 0x00, 0x82, 0x66 }
                });

USB機器から受信した際のコールバック関数を指定します。

その後、USB機器にデータ(レポート)を送ります。

データ は byte配列 に格納します。今回の場合はこの部分になります。

 

        void OnReport(HidLibrary.HidReport report)
        {
            this.Invoke((MethodInvoker)(() =>
            {
                textBox1.Text = func_convert(report.Data);
            }));
            _device?.ReadReport(OnReport);
        }

USB機器からのコールバック関数です。

report.Data に受信内容が byte配列 で入ってきます。
func_convert(); は受信データの処理なので割愛します。

_device.ReadReport(OnReport, 100);

最後に再度コールバックを登録します。引数2はタイムアウトです。

あとがき

HIDデバイスの通信方法を調べると、大体が WinAPI を使用する方法で
1から作ると面倒臭いので、HidLibrary を使用しました。

.NET用の HIDライブラリ は恐らくなくて、UWP だと HID が簡単に実装出来るらしいので、恐らくそれを使えという事なんだと思います。