ラズパイ ZERO WH(stretch)のHID化


動機

ネットにある情報は2年前の情報でOS(jessie)やカーネルも古く(4.4など)、新しい情報もなかった。
今のOS(stretch)とカーネル(4.19.56)で試した結果無事成功したので、バージョンが・・・で二の足を踏んでいる人の後押しになりたかった。

対象

  • 新しいOSとカーネルでラズパイをHID化しマウス・キーボードの操作をしたいと目論んでいる人。

省いている説明

  1. USB OTGでのラズパイのセットアップ
  2. gitなど各ツールの細かい使い方

検証環境

  • ラズパイ

    • OS: strech
    pi@pizerowh:dev$ lsb_release -a
    No LSB modules are available.
    Distributor ID: Raspbian
    Description:  Raspbian GNU/Linux 9.9 (stretch)
    Release:  9.9
    Codename: stretch
    
    • Kernel: 4.19.56
    pi@pizerowh:~$ uname -a
    Linux pizerowh 4.19.56+ #1242 Wed Jun 26 17:24:44 BST 
    2019 armv6l GNU/Linux
    

手順

  • 以下のページを参考にセットアップを進める
  • 必要に応じてapt update & upgrade
  • HID化

    • セットアップ時にセットした下記の設定を削除し、USB経由でのインターネット接続の設定を削除する。
    // cmdline.txtから以下を削除。
    modules-load=dwc2,g_ether
    // これをしないと、デバイスは作成できても
    // 他の端末につないでも認識されない&コマンドを送った時にコマンドがハングする。
    
    pi@pizerowh:dev$ ls -l hidg0
    crw------- 1 root root 240, 0  6月 28 09:44 hidg0
    
    ※ カーネルバージョンを4.19.56にしてもデバイスが生えた事を確認。
    
    • 他の端末にUSBで接続しUSBデバイスとして認識している事を確認。自分の場合は別のラズパイに接続しlsusbで確認した。lsusbで表示されるのはhid.sh内の下記名称が表示される。
 echo 0x0104 > idProduct # Multifunction Composite Gadget <- このコメントの文字。
  • 後は、zeroから/dev/hidg0に向けてコマンドを送り、他の端末のテキストエディタやターミナルに文字が表示されればOK。

マルチファンクション化

  • 1USBに複数の機能をもたせるための設定を行うことも可能。
    • 複合機の接続は1本のケーブルだけど、コピーとスキャナなど複数の機能を提供しているとかのイメージ。
  • やり方としては、複数のFunctionとReportDescriptorをセットすることで可能。

手順

  • キーボードもしくはマウスのどちらかの設定をベースに両方のファンクションを合わせる。
#!/bin/bash
# Snippet from https://github.com/girst/hardpass-sendHID/blob/master/README.md . In which, the following notice was left:

# this is a stripped down version of https://github.com/ckuethe/usbarmory/wiki/USB-Gadgets - I don't claim any rights

modprobe libcomposite
cd /sys/kernel/config/usb_gadget/
mkdir -p g1
cd g1
echo 0x1d6b > idVendor # Linux Foundation
echo 0x0104 > idProduct # Multifunction Composite Gadget
echo 0x0100 > bcdDevice # v1.0.0
echo 0x0200 > bcdUSB # USB2
mkdir -p strings/0x409
echo "deadbeef01234567890" > strings/0x409/serialnumber
echo "blabla inc." > strings/0x409/manufacturer
echo "Generic USB mouse and Keyboard" > strings/0x409/product

# For Mouse
N="usb0"
mkdir -p functions/hid.$N
echo 2 > functions/hid.$N/protocol
echo 1 > functions/hid.$N/subclass
echo 8 > functions/hid.$N/report_length
echo -ne \\x05\\x01\\x09\\x02\\xa1\\x01\\x09\\x01\\xa1\\x00\\x05\\x09\\x19\\x01\\x29\\x03\\x15\\x00\\x25\\x01\\x95\\x03\\x75\\x01\\x81\\x02\\x95\\x01\\x75\\x05\\x81\\x01\\x05\\x01\\x09\\x30\\x09\\x31\\x15\\x81\\x25\\x7f\\x75\\x08\\x95\\x02\\x81\\x06\\xc0\\xc0 > functions/hid.$N/report_desc


# For Keyboard
NN="usb1"
mkdir -p functions/hid.$NN
echo 1 > functions/hid.$NN/protocol
echo 1 > functions/hid.$NN/subclass
echo 8 > functions/hid.$NN/report_length
echo -ne \\x05\\x01\\x09\\x06\\xa1\\x01\\x05\\x07\\x19\\xe0\\x29\\xe7\\x15\\x00\\x25\\x01\\x75\\x01\\x95\\x08\\x81\\x02\\x95\\x01\\x75\\x08\\x81\\x03\\x95\\x05\\x75\\x01\\x05\\x08\\x19\\x01\\x29\\x05\\x91\\x02\\x95\\x01\\x75\\x03\\x91\\x03\\x95\\x06\\x75\\x08\\x15\\x00\\x25\\x65\\x05\\x07\\x19\\x00\\x29\\x65\\x81\\x00\\xc0 >> functions/hid.$NN/report_desc

C=1
mkdir -p configs/c.$C/strings/0x409
echo "Config $C: ECM network" > configs/c.$C/strings/0x409/configuration
echo 250 > configs/c.$C/MaxPower

ln -s functions/hid.$N configs/c.$C/
ln -s functions/hid.$NN configs/c.$C/

ls /sys/class/udc > UDC
  • 作成したshellを実行すると以下の設定になる。接続された側のlsusbで確認するとInterface Descriptorが2つ存在している。
pi@raspberrypi1:~ $ lsusb
Bus 001 Device 030: ID 1d6b:0104 Linux Foundation Multifunction Composite Gadget
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. SMC9514 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
pi@raspberrypi1:~ $ lsusb -s001:030 -v

Bus 001 Device 030: ID 1d6b:0104 Linux Foundation Multifunction Composite Gadget
Couldn't open device, some information will be missing
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0        64
  idVendor           0x1d6b Linux Foundation
  idProduct          0x0104 Multifunction Composite Gadget
  bcdDevice            1.00
  iManufacturer           1
  iProduct                2
  iSerial                 3
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           73
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          4
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              250mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      1 Boot Interface Subclass
      bInterfaceProtocol      1 Keyboard
      iInterface              5
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.01
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      50
         Report Descriptors:
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval               4
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval               4
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      1 Boot Interface Subclass
      bInterfaceProtocol      2 Mouse
      iInterface              7
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.01
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      63
         Report Descriptors:
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval               4
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval               4
pi@raspberrypi1:~ $

参考リンク