jdmouse - SONY VAIO jogdial event handler

Kunihiko IMAI <bak@d2.dion.ne.jp>

2002/11/16

1. 機能

2. インストール

3. コマンドラインオプション

4. つかいかた

5. カスタマイズ


1. 機能

jdmouse は SONY VAIO シリーズのジョグダイヤル・アプリケーションキーなどを使うためのプログラムです.

以下,PCG-C1XE 上で実装・確認した機能です.

ジョグダイヤル

X 上でホイールマウスのホイールとして使用することができます.

CAPTURE ボタン

CAPTURE ボタンで登録したプログラムを実行することができます. CAPTURE ボタンは浅押し・深押しを判別します.

バックライト

バックライトの明るさを調整することができます.

サウンドボリューム

サウンドデバイスのメインボリュームを調整することができます.

Fn キー

Fn キー+ファンクションキーなどとのイベントで,登録したプログラムを実行します.

以下,プログラムのカスタマイズにより実装(できるだろうと思う)される機能です.

アプリケーションキー・BACK キー

どの機種に搭載されているかはわからないのですが,ドライバのヘッダファイルにそれらしきマクロがあるので,きっとあるのでしょう.

2. インストール

2.1 sonypi デバイスドライバ

まず,sonypi デバイスドライバの設定をします. このドライバは,標準の Linux カーネル (2.4.6 以降)に附属しています. ドライバのインストールについて詳しくは,/usr/src/linux/Documentation/sonypi.txt に説明があります.

ハードウェアの直接制御は,このドライバが行ないます. jdmouse プログラムは,このドライバを通じて,イベントの取得やバックライトの制御等を行なっています.

カーネル

make *config のメニューの中では,「Character devices」−「Sony Vaio Programmable I/O Control Device support」になります. モジュールとしてコンパイルし,ドライバファイルをインストールします.

/etc/modules.conf

まず,sonypi デバイスドライバで使用するマイナー番号を決める必要があります. cat /proc/misc を実行し,240 〜 255 のうちで,空いている番号を調べ,この中から sonypi デバイスドライバ用のマイナー番号を選んで下さい.

そして,

alias char-major-10-マイナー番号 sonypi
options sonypi minor=マイナー番号 (その他オプション)
と /etc/modules.conf ファイルに追加します.

たとえば,250 番を sonypi デバイスドライバに割り当てる場合,

alias char-major-10-250 sonypi
options sonypi minor=250
とします.

options sonypi …の行に追加できる(というか,するべき)オプションは(カーネル 2.4.19 の場合)

minor

デバイスファイルのマイナー番号を指定します. sonypi ドライバにはまだ正式なデバイス番号が割り当てられていないようで,このようなオプションがあります. デフォルト(未指定時)は -1 (自動割り当て)です.

ここでは,240 〜 255 の値を指定することをお勧めします. というのは,この範囲は linux では「Reserved for local use」という割り当てになっているので,他のドライバとかち合う可能性が少ないからです.

自動割り当てとした場合,63 番に割り当てられることが多いようです. これは,「ドライバを組み込んだ時に空いている番号を割り振ってもらう」という登録方法です. このため,他にも自動割り当てを受けているドライバが存在する場合,番号の対応が狂ってしまいます.

camera

C1 シリーズのようにカメラを搭載している場合は camera=1 を追加して下さい. デフォルトは 0 (カメラなし)です.

fnkeyinit

VAIO のモデルによっては,fnkeyinit=1 を指定しないと Fn キーイベントが有効にならないモデルがある,そうです. (というか,私の持っている C1XE がこれに該当するようです.) ただし,この場合,カーネルの ACPI サポートは無効にしておく必要があります.

デフォルトは 0 です.

C1XE の場合このオプションを有効にすると,Fn+ESC,Fn+F12 のサスペンドやハイバネートが効かなくなってしまいます. ここらはマシンの利用状態に応じていろいろ悩んで下さい :-)

verbose

未知のイベントをカーネルメッセージとして出力するそうです. デフォルトは 0 (メッセージ出力無し)です.

これは 0 で良いでしょう.

compat

以前の sonypi ドライバとの互換性のある動作をするためのスイッチだそうです. デフォルトは 0 です.

これも 0 で良いでしょう.

nojogdial

ジョグダイヤルの無い機種の場合,nojogdial=1 を指定すると,(デバイスドライバ側で)イベントをより正しく判断するようになるそうです. デフォルトは 0 (ジョグダイヤルあり)です.

ジョグダイヤルの無い機種では nojogdial=1 を指定しておくと良いでしょう.

デバイスファイルの作成

デバイスドライバと通信するためのファイルエントリを作成します. メジャー番号は 10 (misc device),マイナー番号は, /etc/modules.conf の節で使うと決めた番号です.

例えば,マイナー番号が 250 の場合は

mknod /dev/jdmouse c 10 250
と実行します.

2.2 FIFO の作成

jdmouse プログラムから X サーバへの通信は,FIFO (ネームドパイプ)を用います. この FIFO を

mkfifo /dev/jdmouse
と作成してやります.

2.3 XFree86 の設定

XFree86 4.x の場合です.

/etc/X11/XF86Config-4 を以下のように変更し,X を再起動します.

Section "ServerLayout"
        …
        InputDevice    "Mouse99" "SendCoreEvents"        # この行追加
        …
EndSection
…
# ここから
Section "InputDevice"
        Identifier  "Mouse99"
        Driver      "mouse"
        Option      "Device" "/dev/jdmouse"
        Option      "Protocol" "IMPS/2"
        Option      "ZAxisMapping" "4 5"
        Option      "AlwaysCore"
EndSection
#ここまで追加

2.4 jdmouse プログラム

とりあえずコンパイル済みの jdmouse プログラムも同梱しています. コンパイル環境は Linux-2.4.19, VineLinux 2.6 です. プログラムとしては,基本的な枯れた機能しか使っていないので,再コンパイルしなくても動作するとは思います.

コンパイルする時は,src ディレクトリで

make clean
make
でおっけー,です.

インストールスクリプトは特に用意していないので,適当にパスの通っているディレクトリにコピーして下さい.

3. コマンドラインオプション

jdmouse プログラムのコマンドラインオプションです.

-d

デバッグモード. イベント番号などを標準出力に出力します. イベント番号の調査や動作確認に使用することができるでしょう.

-s ファイル名

sonypi デバイスドライバのデバイスファイル名. デフォルトは /dev/sonypi. 通常は指定する必要はないでしょう.

-m ファイル名

マウスイベントを出力する FIFO ファイル名. デフォルトは /dev/jdmouse. これも通常は指定する必要はないでしょう.

-x ファイル名

サウンドカードのミキサデバイスファイル名. デフォルトは /dev/mixer. これも通常は指定する必要はないでしょう.

-h

使い方を出力して終了.

コマンドラインでいろいろカスタマイズできるといいのかもしれませんが,機能を増やしたら結構複雑になってきたので,ほとんどの機能についてはコンパイル時決め打ちということにしてしまいました.

4. つかいかた

デフォルトの動作は以下の通りです.

4.1 ジョグダイヤル

上下の回転は,ホイールマウスのホイールの上下回転になります. クリックは,マウスの左ボタンクリックになります.

また,サウンドのマスターボリューム調整やバックライト輝度調整時は,ホイールの上下が値の上下になります. この場合はホイールとしては機能しません.

4.2 CAPTURE ボタン

浅押しで mpg123 プログラムを一時停止させます. もう一度浅押しで再開します.

深押しでは,DPMS を強制的に起動し,画面を消灯します.

4.3 Fn + F3

サウンドのマスターボリュームのミュート・ミュート解除を繰り返します.

4.4 Fn + F4

ジョグダイヤルでサウンドのマスターボリュームの調整ができます. ウィンドウズとは違って,画面中央にアイコンは出てきません. あしからず.

で,調整を終了し,ジョグダイヤルは再びマウスホイールとして動作するようになります. また,Fn + F5 で,バックライトの輝度調整に入り,サウンドの調整はこの時点で終了します.

おそらく「今現在,調整モードかどうかわかんない」という状態になってしまうと思います. そういう場合は,マウスポインタをルートウィンドウ上に持っていき,ジョグダイヤルをクリックしてみましょう. これで確実に調整モードから脱することができます. vi での ESC, Emacs での C-g みたいなもんです.

4.5 Fn + F5

ジョグダイヤルでバックライトの輝度調整ができます. 調整状態からの脱出法などは,サウンドのマスターボリュームの調整と同様です.

4.6 Fn + F6

バックライト輝度の最大値と最小値の設定を繰り返します.

5. カスタマイズ

ソースファイルを直接編集することによってカスタマイズする,ということにしました.

カスタマイズ項目をコマンドラインオプションで持つには複雑過ぎるし,設定ファイルから読み込むことにすると,パーサが必要だし. パーサなんか入れた日には「飴より笹のほうが高く付く」ようなプログラムになってしまいます.

この手のプログラムは,軽快なのがいちばん.

以上,「ソース直接編集」の言い訳でした.

5.1 初級編

プログラム先頭の /* ----- configure section begin ----- *//* ----- configure section end ----- */ で囲まれた区間を編集,です :-)

それでは,各項目の説明を.

ファイル名関係

通常は変更する必要はないでしょう.

#define SONYPI "/dev/sonypi"

sonypi ドライバのデバイスファイル名のデフォルト値.

#define MOUSE "/dev/jdmouse"

マウスイベント出力 FIFO ファイル名のデフォルト値.

#define MIXER "/dev/mixer"

サウンドデバイスのミキサのデバイスファイル名のデフォルト値.

イベント関係

ええと,#define … のオプションを無効にするには,行頭に // を追加して下さい. ただし,#define 名前 値 とある部分は無効にしてはいけません. 「C なんてわかんな〜い」という方のために,念のため :-)

#define ILLUGAL_PARTIAL_RELEASE

CAPTURE ボタンで半離し(深く押し込んでから半分離す)の時に発生するイベントの設定. これを設定すると,SONYPI_EVENT_PKEY_P1 のイベントも CAPTURE ボタンの半離しと認識されます.

私の C1XE では,この時に SONYPI_EVENT_CAPTURE_PARTIALRELEASED ではなく,なぜか SONYPI_EVENT_PKEY_P1 のイベントが発生してしまうため,現物合わせ,です. jdmouse -d を実行してみて,CAPTURE ボタン半離しで 10 ではなく 32 と出力される場合は,指定して下さい.

#define BACKLIGHT_STEP 25

バックライト輝度をジョグダイヤルで調整する場合の,1 ステップ毎の値の増減値. この値を大きくすると,ジョグダイヤルの回転に対し輝度の増減が大きくなります.

#define SOUNDVOLUME_STEP 8

サウンドボリューム調整時の 1 ステップ毎の値の増減値. この値を大きくすると,ジョグダイヤルの回転に対し,音量のの増減が大きくなります.

ジョグダイヤルのクリック

ジョグダイヤルのクリックをマウスのどのボタンに割り当てるか設定します. JOGDIAL_CLICK_BUTTON1, JOGDIAL_CLICK_BUTTON2, JOGDIAL_CLICK_BUTTON3 のうちのいずれか 1 つだけを有効にして下さい.

JOGDIAL_CLICK_BUTTON1

マウス左ボタン

JOGDIAL_CLICK_BUTTON2

(正しく設定された X では)マウスの真ん中ボタン,もしくはマウスの左右ボタンの同時押し,もしくはホイールのクリック.

JOGDIAL_CLICK_BUTTON3

マウス右ボタン.

CAPTURE ボタンの動作

*capture_half_command[] は CAPTURE ボタン半押し,*capture_deep_command[] は,CAPTURE ボタン深押しのときに実行されるコマンドを設定しています.

複数のコマンドがある場合,ボタンの押下ごとにコマンドが順番に実行されます. デフォルトの例では

const char *capture_half_command[] = {
        "killall -STOP mpg123",
        "killall -CONT mpg123",
        "",
};
となっていますが,この場合,
  1. 最初に CAPTURE ボタンを半押ししたときは killall -STOP mpg123
  2. 次に CAPTURE ボタンを半押ししたときは killall -CONT mpg123
  3. その次に CAPTURE ボタンを半押ししたときは killall -STOP mpg123
  4. そのまた次に CAPTURE ボタンを半押ししたときは killall -CONT mpg123
  5. 以下同文
という動作をします.

また,特に「いつも同じコマンドを実行して欲しい」という場合は

const char *capture_deep_command[] = {
        "xset dpms force off",
        "",
};
と,コマンド行を 1 行だけ登録することで実現できます.

なお,最後の "", は必ず入れて下さい. プログラム中では「コマンド行はこれでおしまい」という目印にしています.

5.2 中級編

ここでは例として「Fn+1 で画面の背景色を変更する」という機能を追加してみます. #ifdef CYCLIC_EXAMPLE で囲まれた部分を参照してみて下さい.

と,これだけで終わらせるのもそっけないので,説明しましょう.

プログラム先頭部

ここらは CAPTURE ボタンの動作 と同様,イベントの発生毎に順番にコマンドを実行します.

const char *fn_1_command[] = {
        "xsetroot -solid gray",
        "xsetroot -solid seagreen4",
        "xsetroot -solid black",
        "",
};

イベント判定部

プログラム最後の方の switch 文の中です.

#ifdef CYCLIC_EXAMPLE
                case SONYPI_EVENT_FNKEY_1: {
                        static int index = 0;

                        index = cyclic_command ( index, fn_1_command );
                        break;
                }
#endif

case のラベル値には,sonypi ドライバから渡されるイベント番号を指定します. このマクロは /usr/include/linux/sonypi.h に定義されています.

ここでは,{ } で条件式の無いブロックを切って,このブロックの中でのみ有効な静的変数 index を定義しています. これだと,プログラムの他の部分との変数名の整合性を心配すること無く,変数を使用することができます.

cyclic_command という関数は,前の方に定義されていますが,動作は

  1. fn_1_commnand 配列の index で指定されたコマンドラインを実行
  2. index を 1 増分する
  3. 増分した結果,index の示すコマンドラインが空文字列だったら index を 0 に設定する
  4. 返り値として index を返す
という動作になります.

と,まぁ,理屈はともかく,イベントに対して任意のコマンドを実行する,という処理をこれだけの変更で追加することができます.

5.3 上級編

ネタが無いなぁ…

まぁ,自身の問題意識と発想を元に,好きなようにプログラムをいじって下さい. というあたりでお茶を濁そう :-)