さて、改めて、ビルドして insmodすると、今度は ledcont に反応しました。バッチリsyslogにナニが来たか書き出されています。ioctl()は、一般的に、コマンド(int)と引数へのポインタ(void *)を渡します。コマンドとそれに必要な引数がわたってくる訳です。コマンドは整数なので、ただ表示しても内容はわかります。何か書くときには、0x40046b01が、読み出すときには0x80046b02が渡って来ています。問題は引数です。ただ、LEDの制御には32bitのビットフィールドデータをカーネル側では使っているので、運がよければ、それがそのままvoid*に乗っかって来ていないかと期待したのですが……ダメでした。
仕方がないので、void *の先にあるものを探ることにします。このとき、うっかりな所まで触ってしまえば、モジュールが例外を吐いて死んでしまいます。ちょっと緊張しながら、とりあえず、16byte位なら大丈夫だろう(根拠なし)ということで、16byteをダンプするようにしてやりました。すると、来る来る!
どうやら8byteが利用されているようです。(後ろ3byteについてはちょっと怪しいけれど)
コマンドの引数をあれこれ変えながら、試し続けて、どうやら、それぞれのフィールドの意味がつかめました。ただし、先に書いたように、後ろ3byteがナンに使われているのか分からなかったですが。ただ、ここに値が入るのは、cycle を変えるときと、x y zの三つの数値を指定するときだけで、linuxrcもchkraid1もこれは使っていないのでよしとします。このあたりの動作に互換性の微妙な怪しさが残りますがとりあえずはよしとします。僕は困りません。困らないことにします。読み出しのときにも同じ構造体を使うものと仮定しましたが、どうやらそれで良さそうでした。(違っていたら、これまた、例外吐いて死ぬかもしれなかった。)
ちょっと、ひやりとするようなこともしながらも、カーネルをポーティングするのに比べれば、全然気楽なのはいうまでもありません。何しろ、ちょっと位バグっていても、全体即死に簡単には直結しないからです。デバイスドライバのプログラムは楽しいなぁ(ばか)
コメント