VNC server


「Install/uninstall の前に」の項まですっとばしたほうが身のためかもしんないが ...

WinVNC と vncserver

WinVNC (vncserver on Windows) はコンソールの Windows デスクトップそのものを VNC で飛ばす。 vncserver (on unix) は X サーバーそのもので、独立なデスクトップをつくり出す。

zaurus-vncserver は前者と同様、PDA の液晶画面そのものを VNC に渡す。 一方、後者に相当するものが qt-embedded-free の中 ... というか、libqte の中に入ってはずなんだけど、 もちろん実機の libqte からは外されている。これを qpe に static link すると 独立 vnc サーバーの出来上がり ... なんだが、なんだけど色がヘンやぁ。あうぅ (いちお動くには動いてる。予想外に遅いけど; Jan 19, 2003)。

ここでは、とりあえず一つ目のだけ。

libvnc

... なんつー便利なもんがあるらしい。 しっかり tight encoding までサポートしてる。 よって zaurus-vncserver は tight encoding まで使えるが、 libqte 内のほうは raw/copyrect encoding だけである。
... だからどーだという訳ではないが。

タッチパネル

タッチパネルデバイスの本体は /dev/sharp_ts だが、 Qte/Qtopia 側は /dev/ts を使っている。 ふつー後者は前者への symlink になっているが、ペンイベントのスヌープのために tssimd が奪う。

/dev/tssim, /dev/ts という二つの fifo を使って、

Viewer 側からのマウスイベントの流れ:

vncviewer → vncserver -(/dev/tssim)→ tssimd -(/dev/ts)→ qtopia

カーネル側からのタッチパネルイベントの流れ:

kernel -(/dev/sharp_ts)→ tssimd -(/dev/ts)→ qtopia

になっている。 tssimd は /dev/tssim, /dev/sharp_ts の二つのペンイベントを混ぜて /dev/ts に流している。

キャリブレーション

カーネルにはタッチパネルのキャリブレーションのための ioctl がある。 ... が、Qtopia の「タッチパネル調整」 (ちなみに「タッチパネル調整」は独立したバイナリでなく、qpe の内部コマンドである) というやつは、それを使っておらず、 qpe (qte server) 内で自前でキャリブレーション用の matrix を作っている。 ここで微妙な問題が生まれる。

Qtopia 内でキャリブレーションしているから、 qtopia がペンイベントを受ける入口になる /dev/ts のデータは qtopia からみてキャリブレーションしてないナマのデータである。 他方、vncviewer 側からのマウスイベントは、キャリブレーション済みのデータが流れてくる。

つまり tssimd は qtopia 内で修正したあとで正しいデータになるように /dev/ts へデータを流さなければならない。 /dev/sharp_ts の ioctl を使ってくれれば /dev/sharp_ts/dev/ts もキャリブレーション済みのデータが流れることになり、 tssimd は何の変換も要らなくなるのに ...

「タッチパネル調整」はキャリブレーションデータを /etc/pointercal に入れる。 整数が 7 つ書かれただけの単純なフォーマットで、その数字を順に a, b, c, d, e, f, s とすると、 raw data を (x, y)、calibrated data を (X, Y) として、

X =  (a * x + b * y + c) / s;
Y =  (d * x + e * y + f) / s;
になる。おおカーネル内の変換式よりカッコええ(つか、これがふつー)と思いきや、 必ず b = d = 0 なのでカーネル内と一緒である。もうアホかと(以下略)。

本題にもどる。VNC viewer 側から受け取ったマウスイベントを 上のデータで逆変換して /dev/ts に流す訳なのだが ... いまんとこ tssimd が /etc/pointercal を読むのは tssimd の起動時だけなので、 起動後に「タッチパネル調整」でキャリブレーションをとりなおしても VNC viewer 側には反映されないし、 VNC viewer 上で「タッチパネル調整」使ってキャリブレーションすると (VNC viewer 上ではきっちり合うようになるだろうけど)本体側のペンは少々ずれるようになるはずだ。 まあ、本体側でキャリブレーションしてから

# /etc/rc.d/init.d/fbvncinput reload
すれば直る(よーするに tssimd を再起動すれば直る)話ではあるけど。

フレームバッファ

もとの zaurus-fbvncserver がサポートしていた iPAQ, SL5x00 は共に内部的に 320x240, 16bpp の framebuffer をもつ。これを VNC で送るさいに 240x320 の向きに直している。 framebuffer からは 32bit (2 pixel) で読み込み、横倒して rfb 向けに bit order の入れ換えなどしつつ rfbbuffer へ 16bit 単位で書いている。 アセンブラで書いてあるが、わざわざアセンブラで書くほどのトリッキーなことはしてない。 よほど gcc の吐くコードの質が低いんだろーなぁ。

A300 の場合、240x320,16bpp の素直な framebuffer である。... ので、 せっかくなので 32bit (2 pixel) で読み込み、 bit order の入れ換えなどしつつ 32bit (2 pixel) で書き込んでいる。 このビットマスクが 2 pixel 単位なんで、いちいち再計算するのも手間なんで決め打ちしているが、 A300 の16bpp 専用だからかまうまい (クライアント側には左右されない)。

これが busy-loop の負荷軽減に劇的に効くと思いきや、いやちゃんとレスポンスに劇的に効いてんだけど、 ... 単に loop を回る速度が速くなるだけで、 CPU 負荷の絶対値そのものは別んとこで規定されているのであった。うーむ。

なお、ここで決め打ちしてるんで、C700 では絶対に動かない。 B500 でも動かないだろう。どーやら B は SL5x00 的な 320x240 landscape の framebuffer 持ってるよーなんで。 汎用コードはソースに含まれてるから、動くようにすることはできると思うが、 B にしても C にしても fbset -i の result すら分からなくては対応しようもなかろ。

キーボード

ハードキー周りを調べて ここにおく。

カーネルは keycode を持たないが、Qte はキーボードを raw mode で扱うので、必要なのは scancode だけ。 そしてハードキーにない scancode も libqte は受け付けるので、 じつは sla300-0.1 の時点で kbdsim.o を経由してキーボード入力できるのだった ...

# mknod /dev/kbdsim c 61 0
# insmod /usr/local/sbin/kbdsim.o
して入力できることを確認。 ってことは、tssimd の起動と一緒に insmod でつっこむようにしとけばいいやね。

このとき、もともと F1 〜 F5 からハードキー相当の scancode が出せるようになっているが、 その scancode が SLA300 と SL5000 で違うので、それも修正。

これで VNC server minimal が完成。 fancy 化は ... ま、気がむいたら。だってさー こんな風 にマシンそのものを絵とするのって画面が狭くなるのがとっても嫌 :-)

kbdsim.o

さて、その kbdsim.o のこと。 /dev/kbdsim から受け取ったデータを そのままカーネルの handle_scancode() に突っ込んでるだけという簡単なドライバだが、 2 バイト単位でしか受け取らない。 scancode 列のファイルを作って
# cat scacode.seq > /deb/kbdsim
なんてすると、バッファの許せるかぎり大きな単位で /dev/kbdsim に書き込みにいくので反応しない。
int onekey(int c){
    unsigned char buf[2];
    FILE *fp = fopen("/dev/kbdsim", "w");
    if(fp == NULL) return -1;
    buf[0] = c; buf[1] = 1;
    fwrite(buf, 2, 1, fp); fflush(fp);  // キーダウンイベント
    buf[0] = c + 0x80; buf[1] = 0;
    fwrite(buf, 2, 1, fp); fflush(fp);  // キーアップイベント
    fclose(fp);
    return 0;
}
みたいに 2 バイト単位で flush() してやると カーネルはキーボードからの入力として認識するようになる。 scancode が 2 バイト以上になるケースで kbdsim.o が正しく動くのかってーと、 ... 実は確認してない(マテ)。
fbvncserver は keysym2scancode のテーブルを使って VNC keysym から scancode に直し、 /dev/kbdsim に突っ込んでいるのだが、2 バイト以上のシーケンスを突っ込んでる keysym もあるから、これで動くに違いない ...

Install/uninstall の前に

tssimd を起動/停止したのち、再び qpe からタッチパネルを使えるようにするためには qpe を再起動する必要があるが、 タッチパネルを使えない状態では手で qpe を再起動することができない。 menu キーからカーソルで「(システム全体の)再起動」を選ぶことはできるが、 これはすこしたるい。

このため、zaurus-fbvncserver を install した瞬間に postinst が、 uninstall した時には prerm が qpe を問答無用で再起動している。

使い方

Install すると自動的に qpe が再起動し、tssimd が動きだす。 さらに "vnc server minimal" を叩くと、server が起動される。 "vnc server halt" で server が down する(tssimd は動いたまま)。 tssimd を止めるにはパッケージを除くか、
# /etc/rc.d/init.d/fbvncinput stop 
# kill -TERM 'qpeのpid'
などとする。

viewer 側からは

% vncviewer sla300:5900
などとして起動する。

Viewer からの(ソフトキーボードを経由しない) 直接のキーボード入力も可能で、 さらにその viewer 側キーボードの F1 〜 F5 は各々 HOME, CANCEL, OK, MENU, ACTION キーに相当する。

そのほかは こちら へどーぞ。

スクリーンショット

zaurus-vncserver は frame buffer を busy-loop で監視してるだけに CPU 喰いで、デフォルトで 50% ほど。 コマンドラインオプションで増減が効くが、もちろんペンのレスポンスとのトレードオフである。 viewer 側から手書き入力なんつーことをしないのであれば、 fbvncserver -i 50 (イベントを 50ms 毎にまとめる; デフォルトは 30ms 毎) などとして、CPU 負荷を下げることができる。 実用としては fbvncserver -i 100 で起動するのが習慣になってんな。これで 18% 前後。 ここまで下げると timidity 鳴らしながら VNC server が使える。 ... ああ、もちろん viewer からの接続がなければ CPU は喰わない。セキュリティを気にしなければ fbvncserver を立ち上げっぱなしでも無問題。
zaurus-vnc server

パッケージとソース

vncserver 本体以外に zlib が必要だ。

Known Bugs

追記

Viewer マシンからのキーボード入力について修正 (Jan. 19, 2003)。

... てゆーか、そろそろ使い方のページを一つ上の層に置くことにするや ... なんか making と manual がごっちゃになってるし。

おまけ

scancode を /dev/kbdsim に送るだけの command を置いた。
# ksim scancode
などとして使う。ksim 40 でホームキー、ksim 29 でメニューキーと同等。 ksim 109 するとちゃんと電源も切れる。 詳細は qt-embedded の src/kernel/qkeyborard_qws.cppQWSServer::KeyMap keyM[] や fbvncserver の keysym2scancode.c を参照のこと ── と書いてすめばいいんだが、なんかびみょ〜に SL5x00 と違うな。

? がついてるのは SL5x00 の scancode には存在するものの A300 の libqte への入力が確認できてないもの(つーか、動作しないようにみえるもの):

Scancode ノーマル SHIFT 前置 Fn前置 SHFT+Fn
1-26 a 〜 z A 〜 Z
27 SHIFT
28 Return
29 MENU キー (F11)
30 Fn キー (F22) CTRL
31 BackSpace
32 F31? backquote
33 フロントライトキー
34 Esc/CANCEL キー
35 上矢印
36 右矢印
37 左矢印
38 下矢印
39 OK キー (F33)
40 HOME キー (F12)
41-49 1 〜 9
50 0
58-59 - +
60 CAPSLOCK
61-64 @ ? , .
65 Tab Backslash?
66 CUT?
67 COPY?
68 PASTE?
69-80 / ' ; " : # $ % _ & * (
81 DEL ~ [
83-85 =
84 ) ] ]
85 ~
86-87 < > { }
88 F9
89 F10
90 F13?
91 ACTION キー
92 Space |
94 !
103 META ALT
109 電源キー
110 F13?
112 NUMLOCK?
114 左矢印
115 EuroSign?
117 SYNC キー (F32)

... で、だ。backslash が入力できない (shift + 65 にない) ようにみえるんだが ...
cut, copy, paste も動作しないのはいいとして。 それに、うぅ、F25 (漢字キー) も入力できないんか...

これはつまり、 A300 のシリアルや IrDA に外部キーボードをつなげて linux から使えるようにしても (外部キーボード用 Inputmethods plugin を用意しないかぎり) Qt/E に対して漢字キーと backslash が入力できないという意味でもある。

おまけへの追記

shift + 65 の位置に backslash があるにはある。 そういう意味では SL5x000 からキーマップテーブル keyM[] は変わってないようだが、 TAB に対する shift が A300 では殺されてるっぽい。むぅ。

ほんものの追記、その 2

C700 版が登場した。

ほんものの追記、その 3

Feb 9, ようやくカーネルを 1.20J ベースへ移行。 1.20 の隠れた目玉である framebuffer への cache の為か、 fbvncserver -i 30 でも CPU usage 6% 以下、この上で timidity 2.11 が実用になる。

fbvncserver だと /dev/fb0 の read cache はまともに効いてくるもんねぇ。


[日記へ] [目次へ]