【Ubuntu】USB-HIDを認識させて、デバイスドライバの開発が出来るようにする（デュアルブート）


Ubuntuでデバイスドライバ開発するときの話。

最近のデバイスドライバ開発は、UEFIや度重なるアップデートにより、
何でもありという状況ではなくなっている。

USB-HIDを認識させるところまで、
結構苦労したのでまとめておく。

# 動作環境

いくつかPC依存の設定を弄るため、動作環境を並べておく。
なお、今回は仮想環境構築ではなく、デュアルブートでの再現である点に注意。

|項目|説明|
|---|---|
|PC|ASUS ExpertBook B1500CEAE（ノートPC)|
|OS|**Ubuntu 20.04**(諸事情あり、最新ではありません)|
|周辺機器の操作|タッチパッド&組み込みキーボード(**作業中はUSBを遮断するので、状況に応じてBluetoothなどを使う**※１)|
|接続するデバイス|LPC1343搭載ボード（※２）|

## 補足

※１：USBマウスを使える方法があれば教えてください（無線・有線問わず）

※２：この記事で使用したボードをそのまま分解して、USB接続しただけのものです。

https://qiita.com/belre/items/9512379324b6c2699cc7

# セキュアブートに関すること

昨今のデバイスドライバでは、いわゆるバッタ物による情報漏えいやウイルス感染、なりすまし等を防ぐために、
BIOSには、**セキュアブート**という仕組みが動作している。

従って、通常の条件では、そもそもデバイスドライバの開発が出来ない点に注意しなくてはならない。

※プリントスクリーンではないので画質悪目

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281173/feae8e87-928f-86c2-0cd5-bac4f5d40b0d.png)

BIOSの設定に入り、セキュアブートをOFFにする。

ちなみに、この状態でWindowsやMacのデュアルブートを動かそうとすると、
無事に起動できない点は注意。

# コーディング作業

## lsusbによるVendorIDとProductIDの調査


基本的にはHIDデバイスとして認識するもの全般で同じことが言えると思います。
このボードは、ARMのCortexシリーズを搭載しているので、同系統であれば同じ動きをする可能性は高い。
なお、この記事では認識だけを試すので、idVendorとidProductだけわかればいい。

``
lsusb
``

![Screenshot from 2022-11-19 16-47-56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281173/fc063b02-d930-ede5-c951-0c80765ae0a1.png)

``
lsusb -v -s 9
``

![Screenshot from 2022-11-19 16-48-55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281173/7586c301-7992-4bd0-a63c-6e007f8b2df7.png)


## コーディング

デバイスドライバはここを参考に少し派生して組み直した。

https://um6ra1.blog.fc2.com/blog-entry-9.html

私が勉強で使っているUSBデバイスカーネルモジュールのソースコード

https://github.com/belre/Balancer2/tree/master-ubuntu/cmake-cpp/usb_register_test/simple_usb_recog

Makefile、myBeuatoDriver.cが本体のディレクトリ。

myBeuatoDriver.cに、先程調べたVendorIdとProductIdを貼り付ける。

ビルドするときは、ワークディレクトリでcdで移動して

```
$ make
```

としてビルドすると、カーネルモジュールフォーマットファイル(.ko)が作成される。

![Screenshot from 2022-11-19 17-27-06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281173/d02ac55a-e5da-babd-ad1a-8554517aa913.png)

# パーミッション関連

myBeuatoDriver.cの一部に、

```
struct usb_class_driver skel_class = {
	.name = "usb/BeuatoCtrl%d",
	.fops = &skel_fops,
	.minor_base = MINOR_BASE
};
```

という表記があり、ここにおける.nameはデバイス名を表す。

この状態でUSBが接続されると、/dev/BeuatoCtrl〜(〜：数字)として登録される(予定である)が、
実はこのままUSBをプラグインすると、パーミッションが600となってしまい、
開発ができなくなる。

そこで、接続されたときに

```
$ sudo chmod 777 /dev/BeuatoCtrl0
```

と書いてしまうのも手だが、いちいちこの設定をするのは面倒なので、udevの設定を変える。


## /etc/udev/rules.dの設定

```
$ cd /etc/udev/rules.d
```

すると、いくつかのudevのデバイス登録時の管理ルールが規定されているのが分かる。
この管理ルールはすべてのファイルが非同期で設定されるが、ユーザの設定としてオリジナルの設定を作ることも可能。
ということで、

```
$ sudo vim 10-beuato.driver.rules
```

として、

```10-beuato-driver.rules
ATTRS{idVendor}=="1962", ATTRS{idProduct}=="2080", KERNEL=="BeuatoCtrl*", (改行)
ENV{ID_MM_DEVICE_IGNORE}="1", MODE="777"
```

と追記することで、idVendor, idProductが一定の条件で、カーネルの名前として展開されるものがBeuatoCtrl〜のときは、常にパーミッションが777となるようになる。

なお、ID_MM_DEVICE_IGNOREというのも追加されているが、これはudevデーモンの管理対象外のモジュールとしてください、ということを表すものである。詳しくはこちらなど

https://qiita.com/kwi/items/b322e28f27f64623bf69


# HIDデバイスの認識に関すること

## udevデーモンを遮断しない場合

普通に接続すると、自動でudevデーモンが働き、
カーネルにhiddevやhidrawと言った名前のデバイスが現れる。

![Screenshot from 2022-11-19 17-42-37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281173/ca9cb221-eeaf-b0e1-1a81-0eb4684160f4.png)

このhiddevやhidrawはudevデーモンの認識機能(usbhid)が働いているために起きる。
このドライバはusbhid由来のものであり、直接ここからUSBでのデータ通信を行うことは出来ない。

## udevの一部の動作(usbhid)の遮断

こうしたHIDデバイスの認識を抑制するためには、一時的にusbの自動認識(usbhid)を遮断する必要がある。

ただし、この操作自体はカーネルの動作に重篤な影響を及ぼしかねないので、開発中以外では多用することは望ましくない。

```
$ sudo rmmod usbhid    # usbhidの遮断
```

※インストールする場合は、以下のサイトを参照にすると回答が書いてある・・・が、今回作ったMakefileがinstallに現状対応させていないので、参考までに・・・。

https://stackoverflow.com/questions/25175960/which-drivers-are-used-by-usb-mouse-in-linux-kernel


またこのコマンドを実行すると、HIDデバイスとして認識されているものも同時に停止する。
この例はマウスやキーボードなどであり、影響を及ぼすので注意が必要。
その設定を戻すには、

```
$ cd /lib/modules/$(uname -r)/kernel/drivers/hid/usbhid
$ sudo insmod usbmouse.ko     # USBマウスの復活
$ sudo insmod usbkbd.ko       # USBキーボードの復活 
```

## usbhidをリビルドしたあとのボードの認識状態(dmesg)

先程の勉強用ソースコードに戻り

```
$ sudo insmod myBeuatoDriver.ko
```

と入力し、

改めてUSB抜き差しする。そして、dmesgを使用すると

![Screenshot from 2022-11-19 17-18-32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281173/bf48f3f1-d623-ed92-4a8d-5560ad39d5bf.png)

myBeuatoDriver.cの
skel_probe関数が実行されたことが確認できた。