試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

PSX-CV02上のPlayStation 2コントローラの振動機能をGNU/Linux上で用いるための試行錯誤(Linux 2.6.31.5時点・第4回)

PSX-CV02上のPlayStation 2コントローラの振動機能をGNU/Linux上で用いるための試行錯誤(Linux 2.6.31.5時点・第3回)」の続き。

重大な問題(不具合)?

fftestでのテストは成功したかのように見えたが、jstest-gtkなどでボタンや軸の操作状況が確認できる状態でfftestを実行してみたところ、重大な問題が発覚した。
「ANALOG」のボタンを押してランプが点灯している状態でfftestで振動を行うと、条件によって(?)、振動が行われている間、押してもいないボタンが押されたかのように特定のボタンの番号の色が変わってしまう。つまり、アナログモードのときに振動が起こると、振動が止まるまでの間、押していない特定のボタンが勝手にランダムに押されることになってしまうことがある。ボタンによって非常に高速な連打になることもあれば、たまに押されることになることもある。コントローラをIのポートに入れてもIIのポートに入れてもこの現象は起こる。
更に厄介なのが、この現象は常に発生するわけではなく、PCの電源を入れた後の起動(再起動後ではない)でログイン後にすぐテストをすると高確率でこの現象が発生せず、全く問題なく動作すること。しかし、再起動をしなくても、何かの拍子にこの問題が起こるようになってしまうことがある。
残念ながら、現時点ではこの問題については原因の見当が付かず、どうすることもできない。ソフトウェア的な(デバイスドライバ側の)問題なのかどうかもよく分からない。ゲームなどで振動機能を使いたいときにはPCの電源を入れてログインした後すぐにそれを起動するということである程度は対処可能だが、根本的な解決にはならない。「GNU/Linux上のジョイパッドデバイスにおける軸とボタンの割り当て変更について(2009/7/16現在)」の要領でボタンの割り当てを変えたりもしたが、変えた先のボタンが押されるようになってしまい、何も変わらなかった。
この問題とは別に、「ANALOG」のランプが消えている場合に振動のテストをしてもたまに振動をしないことがあるが、「ANALOG」のボタンを押すと振動が行われるようだ。しかし、このときにランプを点けると「勝手にボタンが押されたようになる」現象がほぼ確実に起こるようで、どちらも内部の状態としては同じなのかもしれない。

「ffset -g」でメッセージが発生するも正常に動作?

$ ffset /dev/input/$(ls -d /sys/class/input/js0/device/event* | sed 's:/sys/class/input/js[0-9]*/device/\(event[0-9]*\)/:\1:') -g [gain値]

のようにしてffset-gオプションによりgain値というものを調整する(値を100より小さくする)と、強さが可変なほうの作動装置による振動(fftestでは4番のテスト)を弱くすることができるのだが、この値を変更したときにdmesgの出力に

------------[ cut here ]------------
WARNING: at kernel/softirq.c:143 local_bh_enable+0x7b/0xa0()
Hardware name: MS-7270
Modules linked in: sit tunnel4 snd_seq_midi fuse snd_usb_audio ipt_IFWLOG ipt_psd xt_time xt_connlimit xt_realm iptable_raw xt_comment xt_recent xt_policy ipt_ULOG ipt_REJECT ipt_REDIRECT ipt_NETMAP ipt_MASQUERADE ipt_ECN ipt_ecn ipt_CLUSTERIP ipt_ah ipt_addrtype nf_nat_tftp nf_nat_snmp_basic nf_nat_sip nf_nat_pptp nf_nat_proto_gre nf_nat_irc nf_nat_h323 nf_nat_ftp nf_nat_amanda ts_kmp nf_conntrack_amanda nf_conntrack_sane nf_conntrack_tftp nf_conntrack_sip nf_conntrack_proto_sctp nf_conntrack_pptp nf_conntrack_proto_gre nf_conntrack_netlink nf_conntrack_netbios_ns nf_conntrack_irc nf_conntrack_h323 nf_conntrack_ftp ipt_set ipt_SET ip_set_nethash ip_set_iptreemap ip_set_iptree ip_set_ipporthash ip_set_portmap ip_set_macipmap ip_set_ipmap ip_set_iphash ip_set xt_tcpmss xt_pkttype xt_physdev xt_owner xt_NFQUEUE xt_NFLOG nfnetlink_log xt_multiport xt_MARK xt_mark xt_mac xt_limit xt_length xt_iprange xt_helper xt_hashlimit xt_DSCP xt_dscp xt_dccp xt_conntrack xt_CONNMARK xt_connmark xt_CLASSIFY ipt_LOG xt_tcpudp xt_state iptable_nat nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_conntrack iptable_mangle nfnetlink iptable_filter ip_tables x_tables af_packet nvidia(P) vboxnetadp vboxnetflt ipv6 vboxdrv w83627ehf hwmon_vid binfmt_misc squashfs loop reiserfs jfs xfs exportfs cpufreq_ondemand cpufreq_conservative cpufreq_powersave powernow_k8 freq_table snd_hda_codec_realtek snd_hda_intel snd_usb_lib snd_hda_codec snd_rawmidi snd_hwdep snd_seq_dummy snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device snd_pcm_oss snd_pcm snd_timer amd64_edac_mod snd_mixer_oss i2c_ali1535 processor snd i2c_ali15x3 joydev button edac_core thermal hid_pl serio_raw i2c_core pcspkr ff_memless k8temp uli526x soundcore evdev snd_page_alloc sr_mod alim15x3 pata_ali ata_generic ide_pci_generic ide_gd_mod ide_core pata_acpi ahci libata sd_mod scsi_mod crc_t10dif ext3 jbd uhci_hcd ohci_hcd ehci_hcd usbhid hid usbcore [last unloaded: scsi_wait_scan]
Pid: 25580, comm: ffset Tainted: P           2.6.31.5-1mnb-custom #1
Call Trace:
 [<ffffffff8104d22b>] warn_slowpath_common+0x7b/0xc0
 [<ffffffff8104d284>] warn_slowpath_null+0x14/0x20
 [<ffffffff810532bb>] local_bh_enable+0x7b/0xa0
 [<ffffffffa01cad69>] ml_ff_set_gain+0x59/0x60 [ff_memless]
 [<ffffffff8125f0b8>] input_ff_event+0x88/0x90
 [<ffffffff8125d5a9>] input_handle_event+0x79/0x470
 [<ffffffff8125eb20>] input_inject_event+0x70/0x80
 [<ffffffffa01a83e3>] evdev_write+0x83/0xf0 [evdev]
 [<ffffffff81174126>] ? security_file_permission+0x16/0x20
 [<ffffffff810f28f6>] vfs_write+0xb6/0x190
 [<ffffffff810f32f1>] sys_write+0x51/0x90
 [<ffffffff81010ebf>] system_call_fastpath+0x16/0x1b
---[ end trace 4e86b97026f36a03 ]---

のようなメッセージが出ることがある(上はそのままコピペしたもの)。しかし、強さは指定した通りに変わるため、動作に大きな問題があるわけではない。また、特にこの値を変更して使う必要も基本的にはないので、使う上での影響は小さい。

変更部分のまとめ

結局、ここまでに変更した部分は製品のIDに関する修正が主になっており、ほとんどがLinuxのソースツリーにあるものを利用しただけという形となった。ただ、上のような問題があるため、この変更部分については別の人が改善しやすいようにパブリックドメインとして公開することにする。
下はkernel.org配布のLinux 2.6.31.13のソースツリーを用いて差分を取ったものとなる。
[任意]ファイル名: linux-2.6.31.13-psx_cv02.patch ライセンス: パブリックドメイン

diff -ur linux-2.6.31.13.orig/drivers/hid/hid-core.c linux-2.6.31.13/drivers/hid/hid-core.c
--- linux-2.6.31.13.orig/drivers/hid/hid-core.c
+++ linux-2.6.31.13/drivers/hid/hid-core.c
@@ -1276,6 +1276,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x1006) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
diff -ur linux-2.6.31.13.orig/drivers/hid/hid-pl.c linux-2.6.31.13/drivers/hid/hid-pl.c
--- linux-2.6.31.13.orig/drivers/hid/hid-pl.c
+++ linux-2.6.31.13/drivers/hid/hid-pl.c
@@ -180,7 +180,7 @@
 	int ret;
 
 	if (id->driver_data)
-		hdev->quirks |= HID_QUIRK_MULTI_INPUT;
+		hdev->quirks |= HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS;
 
 	ret = hid_parse(hdev);
 	if (ret) {
@@ -207,6 +207,8 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR),
 		.driver_data = 1 }, /* Twin USB Joystick */
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003), },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x1006),
+		.driver_data = 1 }, /* Twin USB Joystick */
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, pl_devices);

関連記事:

使用したバージョン:

  • Linux 2.6.31.5-1mnb
  • input-utils(jstestやfftestなどのパッケージ) 20061008