Linux デスクトップ (Fedora) で ELECOM 大玉トラックボール (M-HT1DRBK) を使っており、これまで4年間愛用してきた。

先日、ホイールが接触不良になってしまったので同じ製品を再購入したところ、以前まで動いていたボタンが、新しいマウスでは認識されなくなってしまった。

いろいろ調べた結果、最終的にはカーネルモジュールの改造により全てのボタンの復旧に成功した。今回、USB デバイスやカーネルモジュールに関する開発は初めての経験だったので、理解した内容に調査の記録を添えて記事にしてみた。

環境

  • ELECOM HUGE TrackBall Mouse (M-HT1DRBK)
  • Fedora Linux 37 (Workstation Edition) 6.0.18-300.fc37.x86_64
  • GNOME 43.2

1. Elecom HUGE TrackBall Mouse

ELECOM HUGE TrackBall Mouse は優れた製品だ。

大玉が転がしやすい

そもそもトラックボールマウスの便利な点は、マウス本体の位置は固定で、ボールだけ動かして操作できるところだ。マウスの位置が一定なので視線を動かすことなく操作できるし、場所も取らない。若干、マウスカーソル位置の微調整がしにくいのが欠点だが、この大玉トラックボールは、大玉のおかげで細かい操作が比較的容易である。2本指・3本指で転がせるところが良い。

触っていて気持ち良い

感触も良い。最も重要なボールが程良く指にフィットして回し易い。 パームレストの絶妙な弾力は掌の骨を支えてくれるので疲れにくい。 指で押していても硬くもなく柔らかくもない、妙に品のあるプニプニ感が楽しい。

8 ボタンが機能的

私はこのトラックボールを Fedora に繋いで使用している。 8 ボタンあるので、通常の右クリック、左クリック、中クリックに加え、

  • ボタン 4, 5 をワークスペースの切り替え
  • 別のボタン 6, 7 をディスプレイの輝度増減
  • ボタン 8 を Delete キー

へ割り当てている。とても便利だ。割り当てには xbindkeys を使っている。 xbindkeys の設定は記事の末尾に書いた。

ホイールボタンが弱点

実はただ1つ弱点がある。ホイールボタンクリックの耐久性だ。 ホイールボタンクリックを多用するとすぐに、ホイールが接触不良になり、スクロールが “滑る” ようになってしまうようだ。

いま手元にあるのは 3 台目。 1 台目は 4 年間問題なく使っていたが、仕事の関係でホイールボタンクリックを頻繁に使うようになったところ、直ぐに壊れた。 2 台目は 2022 年の 9 月に買った。検証も兼ねて 1 台目と同様にホイールボタンクリックを多用してみたところ、僅か 3 ヶ月後でまともにスクロールできなくなってしまった。保証期間内だったので交換してもらい、年末に 3 台目が届いた。

ホイールボタンクリックはもう使わないと決めた。 少し惜しいが、無くても困るものではない。それよりもホイールが効かないことの方が問題だ。

交換したらボタン 6, 7, 8 が効かなくなった

届いた新品を早速使ってみると、どういうわけか、ボタン 6, 7, 8 が効かない。 クリックしてみても、全く何も起きない状態だ。

不良品を疑って Windows で使ってみると問題無く動くようだ。 Windows では エレコム マウスアシスタント で設定する必要があるが、設定さえすれば動く。とりあえず故障ではなさそうだ。

なぜ Fedora では、1 台目、2 台目は問題無いのに、3 台目だけ正しく動かないのか。 不思議だ。安くないマウスなので使えないのは悔しい。でも必ず原因があるはず。 頑張って謎を解き明かしていくことにした。

2. X Server に通知されるイベント

手始めにマウスから通知されるイベントを調べてみた。 こういう時は典型的に Xev か /dev/input/event* を使う。

Xev から試した。xev は X11 のウィンドウを立ち上げ、 拾ったイベントを全てコンソールにダンプする便利なコマンドである。

結果、ボタン 6, 7, 8 に関する情報が全く上がってきていないことがわかった。 何度クリックしてみても無反応だ。

新しいマウスではイベント無し

左クリックすると何か出てくるが…

ButtonPress event, serial 39, synthetic NO, window 0x3e00001,
    root 0x1e7, subw 0x0, time 280169677, (90,62), root:(2060,149),
    state 0x0, button 1, same_screen YES

ButtonRelease event, serial 39, synthetic NO, window 0x3e00001,
    root 0x1e7, subw 0x0, time 280169767, (90,62), root:(2060,149),
    state 0x100, button 1, same_screen YES

ボタン 8 をクリックしても何も起きない。

(沈黙)

古いマウスはイベントあり

左クリックではボタン 1 の同じ出力:

ButtonPress event, serial 37, synthetic NO, window 0x3e00001,
    root 0x1e7, subw 0x0, time 281249870, (105,85), root:(2075,172),
    state 0x0, button 1, same_screen YES

ButtonRelease event, serial 37, synthetic NO, window 0x3e00001,
    root 0x1e7, subw 0x0, time 281249917, (105,85), root:(2075,172),
    state 0x100, button 1, same_screen YES

そしてボタン 8 でも何か出た。 xbindkeys を使ってマッピングしているので keycode 119 が出力された。

LeaveNotify event, serial 37, synthetic NO, window 0x3e00001,
    root 0x1e7, subw 0x0, time 281250414, (105,85), root:(2075,172),
    mode NotifyGrab, detail NotifyAncestor, same_screen YES,
    focus YES, state 0

MappingNotify event, serial 37, synthetic NO, window 0x0,
    request MappingKeyboard, first_keycode 8, count 248

KeyPress event, serial 37, synthetic NO, window 0x3e00001,
    root 0x1e7, subw 0x0, time 281250418, (105,85), root:(2075,172),
    state 0x0, keycode 119 (keysym 0xffff, Delete), same_screen YES,
    XLookupString gives 1 bytes: (7f) ""
    XmbLookupString gives 1 bytes: (7f) ""
    XFilterEvent returns: False

KeyRelease event, serial 38, synthetic NO, window 0x3e00001,
    root 0x1e7, subw 0x0, time 281250440, (105,85), root:(2075,172),
    state 0x0, keycode 119 (keysym 0xffff, Delete), same_screen YES,
    XLookupString gives 1 bytes: (7f) ""
    XFilterEvent returns: False

EnterNotify event, serial 38, synthetic NO, window 0x3e00001,
    root 0x1e7, subw 0x0, time 281250469, (105,85), root:(2075,172),
    mode NotifyUngrab, detail NotifyAncestor, same_screen YES,
    focus YES, state 0

KeymapNotify event, serial 38, synthetic NO, window 0x0,
    keys:  4294967271 0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
           0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0

3. デバイスファイル

次に /dev/input/event でイベント情報を眺めてみた。 Linux Input Subsystem では、接続したデバイスが全てファイルのように見える。/dev/input/event を evdev と呼ぶ。

eventN が各デバイスへ対応するので、まず新旧それぞれマウスがどのデバイスか確認した。

$ ls -l /dev/input/by-id/
合計 0
lrwxrwxrwx. 1 root root 9  1月 13 03:55 usb-ELECOM_TrackBall_Mouse_HUGE_TrackBall-event-mouse -> ../event6
lrwxrwxrwx. 1 root root 9  1月 13 03:55 usb-ELECOM_TrackBall_Mouse_HUGE_TrackBall-mouse -> ../mouse1
lrwxrwxrwx. 1 root root 9  1月 13 03:55 usb-Getech_HUGE_TrackBall-event-mouse -> ../event2
lrwxrwxrwx. 1 root root 9  1月 13 03:55 usb-Getech_HUGE_TrackBall-mouse -> ../mouse0
  • usb-ELECOM_TrackBall_Mouse_HUGE_TrackBall-event-mouse -> ../event6 が古いマウスで、
  • usb-Getech_HUGE_TrackBall-event-mouse -> ../event2 が新しいマウス。

なぜかデバイスの名前が新旧で少し異なっている。 ELECOM は当然わかる。Getech とは何だろう。外注にでもなったのだろうか。

上記それぞれのデバイスファイルで出力されるイベントをダンプした。 結果、やはり新しいマウスではボタン 8 のイベントが得られなかった。 クリックしても何も起きず、無いことになっているように思われる。

この調査でも特に原因を掴めなかったが、 ELECOM と Getech という違いがあることだけはわかった。

新しいマウスではイベント無し

左クリックすると何か出てくるが…

> sudo cat /dev/input/event2 | hexdump
0000000 eefc 63c3 0000 0000 0ad2 0003 0000 0000
0000010 0004 0004 0001 0009 eefc 63c3 0000 0000
0000020 0ad2 0003 0000 0000 0001 0110 0001 0000
0000030 eefc 63c3 0000 0000 0ad2 0003 0000 0000
0000040 0000 0000 0000 0000 eefc 63c3 0000 0000
0000050 9173 0004 0000 0000 0004 0004 0001 0009
0000060 eefc 63c3 0000 0000 9173 0004 0000 0000
0000070 0001 0110 0000 0000 eefc 63c3 0000 0000
0000080 9173 0004 0000 0000 0000 0000 0000 0000
^C⏎

ボタン 8 をクリックしても何も起きない:

(沈黙)

古いマウスではイベントあり

左クリックすると何か出てくる:

> sudo cat /dev/input/event6 | hexdump
0000000 f044 63c3 0000 0000 5480 0004 0000 0000
0000010 0004 0004 0001 0009 f044 63c3 0000 0000
0000020 5480 0004 0000 0000 0001 0110 0001 0000
0000030 f044 63c3 0000 0000 5480 0004 0000 0000
0000040 0000 0000 0000 0000 f044 63c3 0000 0000
0000050 ac47 0005 0000 0000 0004 0004 0001 0009
0000060 f044 63c3 0000 0000 ac47 0005 0000 0000
0000070 0001 0110 0000 0000 f044 63c3 0000 0000
0000080 ac47 0005 0000 0000 0000 0000 0000 0000

ボタン 8 をクリックしてもログが出力される:

0000090 f046 63c3 0000 0000 b402 0009 0000 0000
00000a0 0004 0004 0008 0009 f046 63c3 0000 0000
00000b0 b402 0009 0000 0000 0001 0117 0001 0000
00000c0 f046 63c3 0000 0000 b402 0009 0000 0000
00000d0 0000 0000 0000 0000 f046 63c3 0000 0000
00000e0 5036 000a 0000 0000 0004 0004 0008 0009
00000f0 f046 63c3 0000 0000 5036 000a 0000 0000
0000100 0001 0117 0000 0000 f046 63c3 0000 0000
0000110 5036 000a 0000 0000 0000 0000 0000 0000
^C⏎

さて困った…。

4. 入力デバイス情報の表示

あまり期待せず /proc/bus/input/devices を眺めてみた。 これを cat すると、PC に接続している入力デバイスのリストを表示できる。

結果、新旧マウスで大きく異なるリストが得られた。 しかしこれが何を意味するのかわからない。

なお、この記事を書いている現在もわかっていない。

新しいマウスではデバイス4つ?

新しいマウスを接続するとデバイスが 4 つも追加された。

I: Bus=0003 Vendor=056e Product=011c Version=0110
N: Name="Getech HUGE TrackBall Mouse"
P: Phys=usb-0000:01:00.0-4/input0
S: Sysfs=/devices/pci0000:00/0000:00:01.3/0000:01:00.0/usb1/1-4/1-4:1.0/0003:056E:011C.0005/input/input25
U: Uniq=
H: Handlers=mouse0 event2
B: PROP=0
B: EV=17
B: KEY=1f0000 0 0 0 0
B: REL=1943
B: MSC=10

I: Bus=0003 Vendor=056e Product=011c Version=0110
N: Name="Getech HUGE TrackBall"
P: Phys=usb-0000:01:00.0-4/input0
S: Sysfs=/devices/pci0000:00/0000:00:01.3/0000:01:00.0/usb1/1-4/1-4:1.0/0003:056E:011C.0005/input/input26
U: Uniq=
H: Handlers=event3
B: PROP=0
B: EV=100001

I: Bus=0003 Vendor=056e Product=011c Version=0110
N: Name="Getech HUGE TrackBall Consumer Control"
P: Phys=usb-0000:01:00.0-4/input0
S: Sysfs=/devices/pci0000:00/0000:00:01.3/0000:01:00.0/usb1/1-4/1-4:1.0/0003:056E:011C.0005/input/input27
U: Uniq=
H: Handlers=kbd event4
B: PROP=0
B: EV=1f
B: KEY=306ff 0 0 483ffff17aff32d bfd4444600000000 1 130c730b17c000 267bfad9415fed 9e168000004400 10000002
B: REL=1040
B: ABS=100000000
B: MSC=10

I: Bus=0003 Vendor=056e Product=011c Version=0110
N: Name="Getech HUGE TrackBall System Control"
P: Phys=usb-0000:01:00.0-4/input0
S: Sysfs=/devices/pci0000:00/0000:00:01.3/0000:01:00.0/usb1/1-4/1-4:1.0/0003:056E:011C.0005/input/input28
U: Uniq=
H: Handlers=kbd event5
B: PROP=0
B: EV=13
B: KEY=c000 10000000000000 0
B: MSC=10

古いマウスではデバイス1つ

古いマウスだと 1 つだけしか追加されない。

I: Bus=0003 Vendor=056e Product=010d Version=0111
N: Name="ELECOM TrackBall Mouse HUGE TrackBall"
P: Phys=usb-0000:01:00.0-4/input0
S: Sysfs=/devices/pci0000:00/0000:00:01.3/0000:01:00.0/usb1/1-4/1-4:1.0/0003:056E:010D.0008/input/input36
U: Uniq=
H: Handlers=kbd mouse1 event6
B: PROP=0
B: EV=10001f
B: KEY=306ff 0 0 483ffff17aff32d bfd4444600000000 ff0001 130c730b17c000 267bfad941dfed 9e168000004400 10000002
B: REL=1943
B: ABS=100000000
B: MSC=10

5. USB デバイス情報の表示

わからないので色々試してみる。 lsusb コマンドを使うと PC に接続している USB デバイスのリストを表示できる。

表示を眺めてみると、 製造者が ELECOM TrackBall Mouse から Getech に変わっているのが再度確認できた。

さらに両者の USB バージョンが異なっていることに気付いた。 古いマウスは USB 2.0 だが、新しいマウスは USB 1.1 だ。 なんとバージョンダウンしている。USB 1.1 とは随分古い。やはりコスト削減なのだろうか…!?

新しいマウスは USB 1.1

Bus 001 Device 016: ID 056e:011c Elecom Co., Ltd HUGE TrackBall
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass            0
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0        64
  idVendor           0x056e Elecom Co., Ltd
  idProduct          0x011c
  bcdDevice            1.00
  iManufacturer           1 Getech
  iProduct                2 HUGE TrackBall
  iSerial                 0
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x0022
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0xa0
      (Bus Powered)
      Remote Wakeup
    MaxPower               98mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      1 Boot Interface Subclass
      bInterfaceProtocol      2 Mouse
      iInterface              0
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.10
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength     215
         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               2
Device Status:     0x0000
  (Bus Powered)

古いマウスは USB 2.0

Bus 001 Device 017: ID 056e:010d Elecom Co., Ltd M-HT1DRBK HUGE Wireless Optical TrackBall
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0         8
  idVendor           0x056e Elecom Co., Ltd
  idProduct          0x010d M-HT1DRBK HUGE Wireless Optical TrackBall
  bcdDevice            1.00
  iManufacturer           2 ELECOM TrackBall Mouse
  iProduct                1 HUGE TrackBall
  iSerial                 0
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x0022
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0xa0
      (Bus Powered)
      Remote Wakeup
    MaxPower               98mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      1 Boot Interface Subclass
      bInterfaceProtocol      2 Mouse
      iInterface              0
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.11
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength     213
         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              10
Device Status:     0x0000
  (Bus Powered)

6. hid_elecom カーネルモジュールを見つけた

Web 検索を続けていると、 カーネルモジュールの1つに hid_elecom というものを見つけた。

名前の通り ELECOM デバイス用のドライバがあるようだ。これは怪しい。 ドライバの問題ならば、ここまでの調査のようにイベントが全く出力されないのも辻褄が合う。

modinfo

カーネルモジュールの情報は modinfo コマンドを使って表示できる。

$ modinfo hid_elecom
filename:       /lib/modules/6.0.18-300.fc37.x86_64/kernel/drivers/hid/hid-elecom.ko.xz
license:        GPL
alias:          hid:b0003g*v0000056Ep0000010D
alias:          hid:b0003g*v0000056Ep0000010C
alias:          hid:b0003g*v0000056Ep000000FF
alias:          hid:b0003g*v0000056Ep000000FE
alias:          hid:b0003g*v0000056Ep000000FD
alias:          hid:b0003g*v0000056Ep000000FC
alias:          hid:b0003g*v0000056Ep000000FB
alias:          hid:b0003g*v0000056Ep000000E6
alias:          hid:b0005g*v0000056Ep00000061
depends:
retpoline:      Y
intree:         Y
name:           hid_elecom
vermagic:       6.0.15-200.fc36.x86_64 SMP preempt mod_unload
sig_id:         PKCS#7
signer:         Fedora kernel signing key
sig_key:        5F:B9:19:B5:04:35:78:A0:6F:26:1B:53:86:24:C0:4F:66:A5:50:CF
sig_hashalgo:   sha256
signature:      4A:DC:C6:3D:48:89:18:5C:F9:E0:31:89:83:EE:FA:3D:66:54:1E:D2:
                6C:F6:D7:80:2D:3E:09:5C:D1:A5:7A:84:96:2A:19:B0:06:AF:C1:59:
                54:B7:0F:F6:C8:5D:4A:CD:94:3D:53:BF:0E:C8:2E:32:3C:19:CE:D3:
                01:A7:F5:E0:08:2F:17:D3:C7:EE:77:46:51:41:3A:EE:25:D5:5F:81:
                5B:68:18:17:35:C1:F5:8C:3A:89:84:3B:01:BF:5B:17:27:83:26:8C:
                38:88:40:AE:A4:3B:7E:4E:88:F2:73:91:4E:5D:69:95:03:3C:14:1D:
                8F:86:C6:F7:BF:BF:A9:D7:AF:6B:C8:EA:93:8C:7B:A5:FB:41:A8:19:
                06:81:39:35:89:CB:BD:18:65:62:6C:32:CD:B3:60:E0:AF:3A:82:1C:
                4E:84:D9:D4:D5:58:A7:2C:70:39:20:49:B3:C2:B0:D6:05:84:8E:F5:
                5A:85:32:94:CF:E6:35:36:2E:24:46:06:E4:9F:52:C8:80:BC:C7:97:
                02:34:14:05:E8:73:D2:8B:1A:44:0C:AF:17:05:44:5C:0A:79:9A:75:
                F5:C6:D0:32:DD:9B:01:A3:62:68:60:73:59:89:FC:A5:FB:A9:A2:13:
                1C:D0:13:B7:EC:74:2E:CC:07:8A:FE:8C:B4:02:FB:B0:E1:9F:86:6A:
                AF:42:05:5A:01:EC:54:FA:29:2B:54:B8:93:1B:A6:DD:A8:7D:0C:59:
                79:D9:87:9C:1E:9E:E9:9D:5B:EF:24:94:BB:A7:D3:92:7B:CE:E3:36:
                D6:E0:38:A2:EC:E0:FB:45:B3:54:03:CB:58:48:54:0B:55:1B:59:09:
                B0:A9:1D:4E:36:42:54:F7:9D:C8:8B:25:8E:51:95:13:D8:F8:9A:CC:
                4E:DB:39:71:2F:6F:4C:F0:C3:03:4C:04:DD:DE:A4:B6:CD:88:EF:5F:
                72:0A:E0:A1:5C:BE:92:ED:AE:80:6A:32:22:45:F3:FE:C2:02:6A:76:
                14:F4:12:47:BA:89:5A:14:CF:C7:4E:29:B3:8F:52:1E:27:C7:B7:88:
                96:B7:CF:1A:44:10:12:77:EA:09:D4:29:3D:95:01:A9:A0:2D:FE:31:
                40:D4:34:F0:30:72:A6:63:47:38:BE:01:1A:60:CB:C1:D2:09:98:35:
                0E:9D:75:4C:70:F9:2D:24:1B:AC:CB:8B:D8:55:FC:11:29:05:E8:97:
                A7:41:FA:A0:62:46:43:EE:DB:15:BE:02:EC:A9:B0:85:EF:79:5B:44:
                F9:FB:C8:EA:97:66:20:7C:5E:87:5C:49:19:C4:2D:02:32:71:46:0A:
                B4:7A:67:4D:84:F4:2F:32:A3:30:B1:5C

modprobe

カーネルモジュールのロード、アンロードには modprobe コマンドを使用する。

試しに hid_elecom をアンロードしてみたところ、古いマウスで動かなくなった:

# modprobe -r hid_elecom

再びロードすると復活した:

# modprobe hid_elecom

古いマウスが動作するのは hid_elecom のおかげということがわかった。

一方で新しいマウスはロード・アンロードに関わらず動作した。 新しいマウスには hid_elecom が適用されていなそうだ。 或いは適用されていたとしても、 ELECOM と Getech の違いで hid_elecom が対応できていない可能性がある。

何やら問題の尻尾を掴んだ気がする。

7. デバイス挿入時のカーネルログ

カーネルのログを見てみよう。 dmesg -w コマンドでログを流しながら USB の Bluetooth レシーバの抜き差しをしてみた。

結果、古いマウスは hid-elecom が効いているが、 新しいマウスには適用されず、 一般的な USB デバイス向けのドライバである hid-generic だけが 使われていることが分かった。

新しいマウスは hid-generic

ログ末尾に hid-generic とある。hid-elecom ドライバは適用されなかったと読める。

12月 29 00:23:45 fg-ryz kernel: usb 1-3: new full-speed USB device number 32 using xhci_hcd
12月 29 00:23:45 fg-ryz kernel: usb 1-3: New USB device found, idVendor=056e, idProduct=011c, bcdDevice= 1.00
12月
 29 00:23:45 fg-ryz kernel: usb 1-3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
12月 29 00:23:45 fg-ryz kernel: usb 1-3: Product: HUGE TrackBall
12月 29 00:23:45 fg-ryz kernel: usb 1-3: Manufacturer: Getech
12月 29 00:23:45 fg-ryz kernel: input: Getech HUGE TrackBall Mouse as /devices/pci0000:00/0000:00:01.3/0000:01:00.0/usb1/1-3/1-3:1.0/0003:056E:011C.001F/input/input104
12月 29 00:23:45 fg-ryz kernel: input: Getech HUGE TrackBall as /devices/pci0000:00/0000:00:01.3/0000:01:00.0/usb1/1-3/1-3:1.0/0003:056E:011C.001F/input/input105
12月 29 00:23:45 fg-ryz kernel: input: Getech HUGE TrackBall Consumer Control as /devices/pci0000:00/0000:00:01.3/0000:01:00.0/usb1/1-3/1-3:1.0/0003:056E:011C.001F/input/input106
12月 29 00:23:45 fg-ryz kernel: input: Getech HUGE TrackBall System Control as /devices/pci0000:00/0000:00:01.3/0000:01:00.0/usb1/1-3/1-3:1.0/0003:056E:011C.001F/input/input107
12月 29 00:23:45 fg-ryz kernel: hid-generic 0003:056E:011C.001F: input,hiddev98,hidraw4: USB HID v1.10 Mouse [Getech HUGE TrackBall] on usb-0000:01:00.0-3/input0

古いマウスは elecom

ログ末尾は elecom になっており、hid_elecom ドライバが適用されたと考られる。 加えて最後から 3 行目 Fixing up Elecom mouse button count というログを出力している。 ドライバで何らかの補正を行った形跡だ。

12月 29 00:22:30 fg-ryz kernel: usb 1-4: new low-speed USB device number 31 using xhci_hcd
12月 29 00:22:31 fg-ryz kernel: usb 1-4: New USB device found, idVendor=056e, idProduct=010d, bcdDevice= 1.00
12月 29 00:22:31 fg-ryz kernel: usb 1-4: New USB device strings: Mfr=2, Product=1, SerialNumber=0
12月 29 00:22:31 fg-ryz kernel: usb 1-4: Product: HUGE TrackBall
12月 29 00:22:31 fg-ryz kernel: usb 1-4: Manufacturer: ELECOM TrackBall Mouse
12月 29 00:22:31 fg-ryz kernel: elecom 0003:056E:010D.001E: Fixing up Elecom mouse button count
12月 29 00:22:31 fg-ryz kernel: input: ELECOM TrackBall Mouse HUGE TrackBall as /devices/pci0000:00/0000:00:01.3/0000:01:00.0/usb1/1-4/1-4:1.0/0003:056E:010D.001E/input/input103
12月 29 00:22:31 fg-ryz kernel: elecom 0003:056E:010D.001E: input,hiddev96,hidraw0: USB HID v1.11 Mouse [ELECOM TrackBall Mouse HUGE TrackBall] on usb-0000:01:00.0-4/input0

8. デバイステーブルを見る

なぜ同じ製品なのにドライバが適用されたり、されなかったりするのか。 その答えはカーネルの hid-elecom.c を読むとピンと来た。

下記はソースコードの引用。 MODULE_DEVICE_TABLE は、デバイスのベンダ ID・デバイス ID とドライバのテーブルを生成するマクロ。

static const struct hid_device_id elecom_devices[] = {
	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XGL20DLBK) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3URBK) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT3DRBK) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1URBK) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1DRBK) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK) },
	{ }
};
MODULE_DEVICE_TABLE(hid, elecom_devices);

ここで同じくカーネルの hid-ids.c を当たると USB_DEVICE_ID_ELECOM_M_HT1DRBK0x010d と定義されている。

改めて先程の dmesg から得られたデバイス情報を見てみると

  • 古いマウスでは idVendor=056e, idProduct=010d になっている一方、
  • 新しいマウスでは idVendor=056e, idProduct=011c

である。だから新しいマウスはドライバのテーブルに登録されていないために、 hid-elecom も適用されていないと考えられる。

ところで実は、ここまででも既にデバイステーブルが出現している。 modinfo hid_elecom コマンドの結果にそれは含まれている。 alias を探すと 0000056Ep0000010D という行が見つかる。

alias:          hid:b0003g*v0000056Ep0000010D
alias:          hid:b0003g*v0000056Ep0000010C
alias:          hid:b0003g*v0000056Ep000000FF
alias:          hid:b0003g*v0000056Ep000000FE
alias:          hid:b0003g*v0000056Ep000000FD
alias:          hid:b0003g*v0000056Ep000000FC
alias:          hid:b0003g*v0000056Ep000000FB
alias:          hid:b0003g*v0000056Ep000000E6
alias:          hid:b0005g*v0000056Ep00000061

一方で 011c の行は無い。だから下記の行を追加できれば攻略なわけだ。

alias:          hid:b0003g*v0000056Ep0000011C

なおデバイステーブルについてもう少し掘り下げて書くと、 上記の状態で depmod することにより /lib/modules/6.0.18-300.fc37.x86_64/modules.alias の中にエイリアスが追記される。

カーネルは、マウスが PC に接続されたことを検出したら、 エイリアスを探してカーネルモジュールをロードする。

だいぶゴールに近付いてきた気がする。

9. レポートディスクリプタの書き換え

しかし結論からいくと単に 011c を追記するだけでは足りなかった。 そもそも hid-elecom が行っていることは何だったか。 hid-generic だと何が不足なのか。その答えも hid-elecom.c に書かれている。

コメントによると ELECOM のマウスがボタン数を正しく通知しないので、 通知内容を後から書き換えているとのことだ。

本記事の冒頭にて、マウスの故障を調べるために Windows で実験した場合、 「エレコム マウスアシスタント」が必要だったと話した。 このソフトウェアが無い Linux では ELECCOM のマウスが正常に動作しないのだ。

/*
 * Certain ELECOM mice misreport their button count meaning that they only work
 * correctly with the ELECOM mouse assistant software which is unavailable for
 * Linux. A four extra INPUT reports and a FEATURE report are described by the
 * report descriptor but it does not appear that these enable software to
 * control what the extra buttons map to. The only simple and straightforward
 * solution seems to involve fixing up the report descriptor.
 */
#define MOUSE_BUTTONS_MAX 8
static void mouse_button_fixup(struct hid_device *hdev,
			       __u8 *rdesc, unsigned int rsize,
			       unsigned int button_bit_count,
			       unsigned int padding_bit,
			       unsigned int button_report_size,
			       unsigned int button_usage_maximum,
			       int nbuttons)
{
	if (rsize < 32 || rdesc[button_bit_count] != 0x95 ||
	    rdesc[button_report_size] != 0x75 ||
	    rdesc[button_report_size + 1] != 0x01 ||
	    rdesc[button_usage_maximum] != 0x29 || rdesc[padding_bit] != 0x75)
		return;
	hid_info(hdev, "Fixing up Elecom mouse button count\n");
	nbuttons = clamp(nbuttons, 0, MOUSE_BUTTONS_MAX);
	rdesc[button_bit_count + 1] = nbuttons;
	rdesc[button_usage_maximum + 1] = nbuttons;
	rdesc[padding_bit + 1] = MOUSE_BUTTONS_MAX - nbuttons;
}

プログラムでは、レポートディスクリプタを書き換えている。 レポートディスクリプタとは、USB の規格で定義され、 HID デバイスが送信するデータ (Report) の形式を説明するデータだ。

レポートディスクリプタを一撃でダンプして調べられるツールが存在する。 usbhid-dumphidrd-convert だ。

ツールの実行に必要なので、各マウスを接続したアドレスを再確認しておく。

  • 古いマウス (0x010d) は 001:013 に、
  • 新しいマウス (0x011c) は 001:017

接続していることが lsusb で調べられた。

$ lsusb
Bus 001 Device 017: ID 056e:011c Elecom Co., Ltd HUGE TrackBall
Bus 001 Device 013: ID 056e:010d Elecom Co., Ltd M-HT1DRBK HUGE Wireless Optical TrackBall

古いマウスのレポートディスクリプタを読む

古いマウスのレポートディスクリプタは既に補正されてしまっているが、 補正前の状態を見たい。そこで、先に hid_elecom を除去してしまう。

$ sudo modprobe -r hid_elecom
$ sudo mv /lib/modules/$(uname -r)/kernel/drivers/hid/hid-elecom.ko.xz{,.bak}
$ sudo depmod
$ lsmod | grep hid_elecom

そしてレポートディスクリプタを出力:

$ sudo usbhid-dump -a001:013 -i0 | grep -v : | xxd -r -p | hidrd-convert -o code
0x05, 0x01,         /*  Usage Page (Desktop),               */
0x09, 0x02,         /*  Usage (Mouse),                      */
0xA1, 0x01,         /*  Collection (Application),           */
0x09, 0x01,         /*      Usage (Pointer),                */
0xA1, 0x00,         /*      Collection (Physical),          */
0x85, 0x01,         /*          Report ID (1),              */
0x95, 0x05,         /*          Report Count (5),           */ => 正しくは 8
0x75, 0x01,         /*          Report Size (1),            */
0x05, 0x09,         /*          Usage Page (Button),        */
0x19, 0x01,         /*          Usage Minimum (01h),        */
0x29, 0x05,         /*          Usage Maximum (05h),        */ => 正しくは 8
0x15, 0x00,         /*          Logical Minimum (0),        */
0x25, 0x01,         /*          Logical Maximum (1),        */
0x81, 0x02,         /*          Input (Variable),           */
0x95, 0x01,         /*          Report Count (1),           */
0x75, 0x03,         /*          Report Size (3),            */ => 0 にして捨てる
0x81, 0x01,         /*          Input (Constant),           */
0x75, 0x10,         /*          Report Size (16),           */
0x95, 0x02,         /*          Report Count (2),           */
0x05, 0x01,         /*          Usage Page (Desktop),       */
0x09, 0x30,         /*          Usage (X),                  */
0x09, 0x31,         /*          Usage (Y),                  */
0x16, 0x00, 0x80,   /*          Logical Minimum (-32768),   */
0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
0x81, 0x06,         /*          Input (Variable, Relative), */
0xC0,               /*      End Collection,                 */
# 長いので省略, ホイール等が続く

読み方としては、Report Count, Report Size, Usage, Logical で設定を更新していき、 Input で Report データ用のフィールドを作成する感じ。 これらの順番は入れ替えることができる。

例えば Report Count (8), Report Size (1), Input と来たら 1 bit のフィールドを 8 個生成する。 1 bit (ON/OFF) の入力を 8 個受信するという意味になる。 つまり 8 個のボタンに対応できるようになるわけだ。

これが Report Count (5) だと 5 個分のボタンの情報しか受け取れないため、 残り 3 個のボタンが効かなくなってしまう。

古いマウスのレポートディスクリプタでは、 実際に 5 ボタンとして通知されているので、 カーネルモジュールにて 8 ボタンへ書き換えているのだ。

書き換え対象のバイト数をハードコーディングで指定したものが、 ソースコード中に現れる下記のパラメータである。

12: button bit count
30: padding bit count
14: button report size
20: button usage maximum

おお、読めた。

新しいマウスのレポート

ついに新しいマウス (0x011c) へ挑む。今度は 001:013 を調べる。

$ sudo usbhid-dump -a001:013 -i0 | grep -v : | xxd -r -p | hidrd-convert -o code
0x05, 0x01,         /*  Usage Page (Desktop),               */
0x09, 0x02,         /*  Usage (Mouse),                      */
0xA1, 0x01,         /*  Collection (Application),           */
0x09, 0x01,         /*      Usage (Pointer),                */
0xA1, 0x00,         /*      Collection (Physical),          */
0x85, 0x01,         /*          Report ID (1),              */
0x05, 0x09,         /*          Usage Page (Button),        */
0x19, 0x01,         /*          Usage Minimum (01h),        */
0x29, 0x05,         /*          Usage Maximum (05h),        */ => 正しくは 8
0x15, 0x00,         /*          Logical Minimum (0),        */
0x25, 0x01,         /*          Logical Maximum (1),        */
0x95, 0x08,         /*          Report Count (8),           */ => 正しい
0x75, 0x01,         /*          Report Size (1),            */
0x81, 0x02,         /*          Input (Variable),           */
0x95, 0x01,         /*          Report Count (1),           */
0x75, 0x00,         /*          Report Size (0),            */ => 捨てる
0x81, 0x01,         /*          Input (Constant),           */
0x05, 0x01,         /*          Usage Page (Desktop),       */
0x09, 0x30,         /*          Usage (X),                  */
0x09, 0x31,         /*          Usage (Y),                  */
0x16, 0x00, 0x80,   /*          Logical Minimum (-32768),   */
0x26, 0xFF, 0x7F,   /*          Logical Maximum (32767),    */
0x75, 0x10,         /*          Report Size (16),           */
0x95, 0x02,         /*          Report Count (2),           */
0x81, 0x06,         /*          Input (Variable, Relative), */
0xC0,               /*      End Collection,                 */
# 長いので省略, ホイール等が続く

こちらは 17 Byte 目のみが間違いだ。 よってここだけ書き換えてあげるようにパラメータを設定した。

22: button bit count
30: padding bit count
24: button report size
16: button usage maximum

10. カーネルモジュールのカスタマイズ

いよいよ準備は整った。ここまでで理解したことを元に、 新しいマウスに対応したカーネルモジュールをビルドする。

以下の手順は Fedora 前提になっている。改めて眺めると、最小の手順ではないかもしれない。 ビルドを試みる方は ドキュメント を見ながら適当に頑張って欲しい。

依存ライブラリとソースコードの取得

まず冒頭にも記したカーネルのバージョンを再掲:

$ uname -r
6.0.18-300.fc37.x86_64

依存ライブラリ一式をインストール。

$ sudo dnf install fedpkg fedora-packager rpmdevtools ncurses-devel pesign grubby

Building a custom kernel - Fedora Project Wiki を参考に、カーネルのソースコードを Git で取得する。 巨大なツリーをダウンロードするため時間がかかる。

$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
$ cd linux
$ git remote add -f stable git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
$ git checkout v6.0.18

急ぎ (?) なら XZ を直接ダウンロード することもできる。これだとすぐ終わる。

カーネルモジュールのビルド

あとは hid-elecom.ko のみビルドすれば十分。他は折角ダウンロードしたがスルー。

$ cd drivers/hid
$ make -C /lib/modules/$(uname -r)/build M=$(pwd) hid-elecom.ko

一度ビルドできたら好きなだけプログラムを書いていく。 必要な編集は下記の通りだ。

diff --git a/drivers/hid/hid-elecom.c b/drivers/hid/hid-elecom.c
index e59e9911fc37..c441bb7d0dac 100644
--- a/drivers/hid/hid-elecom.c
+++ b/drivers/hid/hid-elecom.c
@@ -89,7 +89,7 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
        case USB_DEVICE_ID_ELECOM_M_DT1URBK:
        case USB_DEVICE_ID_ELECOM_M_DT1DRBK:
        case USB_DEVICE_ID_ELECOM_M_HT1URBK:
-       case USB_DEVICE_ID_ELECOM_M_HT1DRBK:
+       case USB_DEVICE_ID_ELECOM_M_HT1DRBK_010D:
                /*
                 * Report descriptor format:
                 * 12: button bit count
@@ -99,6 +99,16 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                 */
                mouse_button_fixup(hdev, rdesc, *rsize, 12, 30, 14, 20, 8);
                break;
+       case USB_DEVICE_ID_ELECOM_M_HT1DRBK_011C:
+               /*
+                * Report descriptor format:
+                * 22: button bit count
+                * 30: padding bit count
+                * 24: button report size
+                * 16: button usage maximum
+                */
+               mouse_button_fixup(hdev, rdesc, *rsize, 22, 30, 24, 16, 8);
+               break;
        }
        return rdesc;
 }
@@ -112,7 +122,8 @@ static const struct hid_device_id elecom_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1URBK) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1DRBK) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK_010D) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK_011C) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, elecom_devices);
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 82713ef3aaa6..86692aecf36d 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -429,7 +429,8 @@
 #define USB_DEVICE_ID_ELECOM_M_DT1URBK 0x00fe
 #define USB_DEVICE_ID_ELECOM_M_DT1DRBK 0x00ff
 #define USB_DEVICE_ID_ELECOM_M_HT1URBK 0x010c
-#define USB_DEVICE_ID_ELECOM_M_HT1DRBK 0x010d
+#define USB_DEVICE_ID_ELECOM_M_HT1DRBK_010D    0x010d
+#define USB_DEVICE_ID_ELECOM_M_HT1DRBK_011C    0x011c

 #define USB_VENDOR_ID_DREAM_CHEEKY     0x1d34
 #define USB_DEVICE_ID_DREAM_CHEEKY_WN  0x0004

11. カーネルモジュールのインストール

カーネルモジュールの置き換え

ビルドに成功したら XZ にして /lib/modules/$version 配下のモジュールを置き換える。

もちろん、先にバックアップを取っておくと安心できる。

$ sudo cp /lib/modules/$(uname -r)/kernel/drivers/hid/hid-elecom.ko.xz{,.bak}

カーネルモジュールを置き換える。

$ xz hid-elecom.ko
$ sudo install hid-elecom.ko.xz /lib/modules/$(uname -r)/kernel/drivers/hid/hid-elecom.ko.xz

カーネルモジュールのロード

Modprobe でロードできるようにしたい。 そのために depmod コマンドでモジュールのリストを更新する。 厳密に言うと depmod するのはエイリアスを更新した時のみで十分なはず。

$ sudo depmod

そして modprobe でアンロード & ロードする。

$ sudo modprobe -r hid-elecom
$ sudo modprobe hid_elecom

ついに動いた!!

カスタマイズしたカーネルモジュールをロードした瞬間から、 新しいマウスのボタンが全て動くようになった。

やったぜ!!

modinfo してみた:

$ modinfo hid_elecom
filename:       /lib/modules/6.0.18-300.fc37.x86_64/kernel/drivers/hid/hid-elecom.ko.xz
license:        GPL
alias:          hid:b0003g*v0000056Ep0000011C
alias:          hid:b0003g*v0000056Ep0000010D
alias:          hid:b0003g*v0000056Ep0000010C
alias:          hid:b0003g*v0000056Ep000000FF
alias:          hid:b0003g*v0000056Ep000000FE
alias:          hid:b0003g*v0000056Ep000000FD
alias:          hid:b0003g*v0000056Ep000000FC
alias:          hid:b0003g*v0000056Ep000000FB
alias:          hid:b0003g*v0000056Ep000000E6
alias:          hid:b0005g*v0000056Ep00000061
depends:
retpoline:      Y
name:           hid_elecom
vermagic:       6.0.18-300.fc37.x86_64 SMP preempt mod_unload

初心に返って xev してみた:

$ xev
LeaveNotify event, serial 38, synthetic NO, window 0x3800001,
    root 0x1e7, subw 0x0, time 7382825, (153,140), root:(2123,227),
    mode NotifyGrab, detail NotifyAncestor, same_screen YES,
    focus YES, state 0

KeyPress event, serial 38, synthetic NO, window 0x3800001,
    root 0x1e7, subw 0x0, time 7382829, (153,140), root:(2123,227),
    state 0x0, keycode 119 (keysym 0xffff, Delete), same_screen YES,
    XLookupString gives 1 bytes: (7f) ""
    XmbLookupString gives 1 bytes: (7f) ""
    XFilterEvent returns: False

KeyRelease event, serial 38, synthetic NO, window 0x3800001,
    root 0x1e7, subw 0x0, time 7382835, (153,140), root:(2123,227),
    state 0x0, keycode 119 (keysym 0xffff, Delete), same_screen YES,
    XLookupString gives 1 bytes: (7f) ""
    XFilterEvent returns: False

EnterNotify event, serial 38, synthetic NO, window 0x3800001,
    root 0x1e7, subw 0x0, time 7382933, (153,140), root:(2123,227),
    mode NotifyUngrab, detail NotifyAncestor, same_screen YES,
    focus YES, state 0

KeymapNotify event, serial 38, synthetic NO, window 0x0,
    keys:  4294967271 0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
           0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0

完璧だ。なんと素晴しい。

最後にコピペ用にソースコード取得後のコマンドをまとめておく:

cd drivers/hid
make -C /lib/modules/$(uname -r)/build M=$(pwd) hid-elecom.ko
xz -f hid-elecom.ko
sudo install hid-elecom.ko.xz /lib/modules/$(uname -r)/kernel/drivers/hid/hid-elecom.ko.xz
sudo depmod
sudo modprobe -r hid-elecom
sudo modprobe hid-elecom

12. まとめ

ELECOM のトラックボールマウスを保証交換したところ、 交換前と見た目は同じでも中身が微妙に異なるデバイスが届いた。

本デバイスはボタンが 8 個あるにも関わらず、5 個として通知してくるため、 真面目に解釈すると追加のボタンが使用できない。

そこでカーネルモジュールで 8 ボタンと読み替えるようにしてあげたところ、 本当に全てのボタンが使用できるようになった。

8 ボタンを使えると実に便利だ。 Linux が USB マウスを認識する仕組みを知らないところから調査したが、 やればできるもんだ。とても満足した。

13. おまけ: Fedora カスタムカーネルのビルド

結果的には必要無かったが Fedora のカーネルをビルドしたりもしたので、 折角だから手順を書いておく。

$ fedpkg clone -a kernel
Cloning into 'kernel'...
remote: Enumerating objects: 9173, done.
remote: Counting objects: 100% (9173/9173), done.
remote: Compressing objects: 100% (1533/1533), done.
remote: Total 93720 (delta 8350), reused 8355 (delta 7639), pack-reused 84547
Receiving objects: 100% (93720/93720), 127.60 MiB | 3.09 MiB/s, done.
Resolving deltas: 100% (60548/60548), done.

$ cd kernel/
$ git switch f37
branch 'f37' set up to track 'origin/f37'.
Switched to a new branch 'f37'
$ dnf builddep kernel.spec

kernel.spec に書いた buildid が RPM のファイル名に付与される:

$ vim kernel.spec
$ grep "define buildid" kernel.spec
%define buildid .fuj

RPM を認証するための設定をする:

$ sudo bash -c "echo $USER >> /etc/pesign/users"
$ sudo cat /etc/pesign/users
pesign
fujii
$ sudo chmod 0755 /usr/libexec/pesign/pesign-authorize
$ sudo /usr/libexec/pesign/pesign-authorize

パッケージ生成:

$ fedpkg local

かなり時間がかかって最終的に RPM が生成された。

$ ls x86_64/
kernel-6.0.18-300.fuj.fc37.x86_64.rpm                      kernel-debug-modules-internal-6.0.18-300.fuj.fc37.x86_64.rpm
kernel-core-6.0.18-300.fuj.fc37.x86_64.rpm                 kernel-debuginfo-6.0.18-300.fuj.fc37.x86_64.rpm
kernel-debug-6.0.18-300.fuj.fc37.x86_64.rpm                kernel-debuginfo-common-x86_64-6.0.18-300.fuj.fc37.x86_64.rpm
kernel-debug-core-6.0.18-300.fuj.fc37.x86_64.rpm           kernel-devel-6.0.18-300.fuj.fc37.x86_64.rpm
kernel-debug-debuginfo-6.0.18-300.fuj.fc37.x86_64.rpm      kernel-devel-matched-6.0.18-300.fuj.fc37.x86_64.rpm
kernel-debug-devel-6.0.18-300.fuj.fc37.x86_64.rpm          kernel-modules-6.0.18-300.fuj.fc37.x86_64.rpm
kernel-debug-devel-matched-6.0.18-300.fuj.fc37.x86_64.rpm  kernel-modules-extra-6.0.18-300.fuj.fc37.x86_64.rpm
kernel-debug-modules-6.0.18-300.fuj.fc37.x86_64.rpm        kernel-modules-internal-6.0.18-300.fuj.fc37.x86_64.rpm
kernel-debug-modules-extra-6.0.18-300.fuj.fc37.x86_64.rpm

DNF を使ってインストール:

$ version="6.0.18-300.fuj.fc37.x86_64"
$ sudo dnf install --nogpgcheck \
    ./x86_64/kernel-core-$version.rpm \
    ./x86_64/kernel-modules-$version.rpm \
    ./x86_64/kernel-modules-extra-$version.rpm \
    ./x86_64/kernel-$version.rpm

邪魔になった時は DNF を使って削除できる:

$ sudo dnf remove kernel-core-$version

14. おまけ: .xbindkeysrc

.xbindkeysrc は下記のようにしている:

"xdotool key 'Super_R+Page_Up'"
  b:9

"xdotool key 'Super_R+Page_Down'"
  b:8

"~/.local/bin/brightness_add.sh 0.100"
  b:10

"~/.local/bin/brightness_add.sh -0.100"
  b:11

"xdotool key 'Delete'"
  b:12

15. 参考資料

  1. ELECOM 大玉トラックボール (M-HT1DRBK)
  2. エレコム マウスアシスタント
  3. Linux Input Subsystem
  4. GitHub - torvalds/linux: Linux kernel source tree
  5. GitHub - DIGImend/usbhid-dump: USB HID device dumping utility
  6. GitHub - DIGImend/hidrd: HID report descriptor I/O library and conversion tool
  7. Device Class Definition for HID 1.11 - USB-IF
  8. Building a custom kernel - Fedora Project Wiki
  9. カーネルモジュール - ArchWiki
  10. udevによる動的カーネルデバイス管理 - SUSE Linux Enterprise Server 15 SP1
  11. Linuxドライバのはなし|Wireless・のおと|サイレックス・テクノロジー株式会社