| B級なHello Kittyのパソコンフレンズの研究 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [rev.1.2] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Sorry, this page is written in Japanese(ISO-2022-JP). | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
![]() |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 更新履歴 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
目次 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
■はじめにふと店で気になるものを見つけ,安かったのとUSBの研究もしてみたかったので 「Hello Kittyのパソコンフレンズ」(3,980円也)を購入してみました. Windows
95/98のみ対応だったので,BeOSでも動かせるようにしてみました. ■セット内容箱の中身は次のようになっています.
コネクタはRS232CとUSB type Aの2種類あって,いずれも片方の端はキティ本体と 接続される専用コネクタとなっています. ■ハードウェアの研究中身を解剖してみると,メインのチップは2つあります. 1つは富士通製の8ビットマイコン(MB89191)と, もう1つはCYPRESS製のUSBマイコン(CY7C63001A)が使われていました. 富士通製のマイコンはRS232C制御用,CYPRESS製マイコンはUSB用のようです. (これほどはっきり分けているのも珍しい気がします.1つのマイコンでRS232C I/Fと USB I/Fを持ってるヤツにしなかった理由は何なのだろう? やっぱり価格なのかな? それとも富士通製品を使わなければならなかった台所事情なのか...) さて,富士通製のマイコンは4kBのマスクROMと128バイトのRAMを内部に持ち, CYPRESS製のマイコンは4kBのEPROMと128バイトのRAMを内部に持っています. 双方とも限られたメモリしか持っていないので,キティの発する音声データは これらのマイコンの中には入っておらず,アヤシゲな樹脂封入されたチップを 実装した小さな別基板に持っていると考えられます. (これはちょっと残念.別のデータを使うことができれば別の筐体の中に回路のみを 入れて{動く|しゃべる}マスコットとして使えたのですが...) 次にコネクタのI/Fについて調べてみました. (専用コネクタに関してはどちらが1番ピンか分からなかったので,勝手に 番号をつけました)
こうして見ると,RS232CとUSBはGNDこそ共用しているものの,他の信号線は まったく排他的に利用しています. となると,RS232Cでしか使わない信号線(RTSやDTR)をプルアップすることで, 本体側のRS232CとUSBのどちらにつながっているかを判別しているのかと 思っていたのですが. 結局RTSはRS232CとUSBの自動判定用途に使っていないことが判明しました. 実際,RS232Cで接続したまま,RTSをLにして,コマンド送信すると キティから発声させることはできました. ただし,RTSをLにしていると,キティはコマンドのACKやボタンをクリックしたときの データを送ってくれなくなります. すなわち,ハードウェアフロー制御にもしっかり対応していたのでした. まぁまともなRS232C用マイコンですので,当たり前といえば当たり前でしたね. さて,このRS232C/USB自動判別機能については,調査しても見返りとして得られる 利益が少なそうなので調査を棚上げにしておきます. (USBの研究を進めていくと自然に解決されるかもしれません) 次にキティのロボとしての動作ですが,以下の動作をします(マニュアルより抜粋).
また,キティの特筆すべき点は音声でしゃべることです. 次の発声・発音をします.
余談ですが,研究員は「またね」と「あれ〜?」と「すてきすてき」の声が とても気に入っています.(^^; なお,WindowsソフトであるHello Kitty Stationをインストールすると, PCの音源を使って以下の発声をさせることができます.
これらの音のデータはすばらしいことにwav形式で C:\Program Files\MascotRobot\Kitty\Data\Soundにあります. また,グラフィックのデータもbmp形式で C:\Program Files\MascotRobot\Kitty\Graphic\Soundにあります. これらのデータをBeOSで使って良いものかどうかは不明です. (個人の利用の範囲であれば...という気もしますが,データの著作権は 富士通パソコンシステムズさんにありますので,気になる方はそちらに 問い合わせてみてください.研究員は問い合わせておりません.(^^;) さて,研究員はUSBについては勉強が不足しているので,今回はRS232C側について 研究してみました. 2001/05/12: USBの解析は一部完了しました.2001/11/16: USBの解析は完了しました. ■コマンドの解説キティをRS232CでWindows 98ノートPC(COMPAQ ARMADA M300)に接続し, どのようなデータが送受信されているのか調べてみました. 調査には以前購入してお蔵入りしていた秋月電子製RS232Cラインモニタ (AKIRS232Cラインモニター)のキットを蔵から引きずり出してせっせと半田づけして 利用しました. ただし,このラインモニタの作り方が悪かったのか,電源用のACアダプタとして 利用しているのがCOMAQ Contura AERO用のACアダプタ(17V)が悪いのか, うまくデータが取れないときがあるようです. したがって,以下のデータの中にもウソが混じっている場合も考えられますので, 十分ご注意ください.(ウソ発見は大歓迎です) まず,データ以外の信号線についてですが, Windows98で動作するソフトウェアであるHello Kitty Stationを起動した後では, RTSはHにアサートされ,DTRはLにネゲートされて固定されています. (RTSは元々半二重通信のデータ送受信制御(いわゆるハードウェアフロー制御)の 目的で使います.Hに固定してていいんだろうか. まぁ所詮キティからは1バイトずつしか送られてこないし, ハードウェアフロー制御使う必要はキティにはないといえばないですね(笑)) ハードウェアフローの話が出たので,ここでRS232Cの送受信に利用する パラメータについて説明します. キティ本体との通信はB技研調べでは,以下のようになっています.
次にコマンドの送受信です. Hello Kitty Stationを起動した際に,serialキティ本体に対して 何らかのコンフィギュレーションを行なうようです. ラインモニタを用いて,Hello Kitty
Station起動の際のデータ送受信を 観察してみると,次のようなシーケンスでした.
むぅ,これを見るとPC側からデータを送信する前にserialキティからデータが 送られてきています.ということは,serialキティはRS232Cポートに接続されたことを 自動判別して,データを送信するのかもしれません. また,RTSがHになったのを検出してデータを送信しているのかもしれません. しかし,残念ながらB技研にはそのあたりを詳しく調べる手立てがありません. もしまっとうなRS232Cラインモニタで調べていただける方がいましたら, 教えてくださいませ.(_o_) さて,上記のHello Kitty Station起動時シーケンスや,Hello Kitty Stationの キーボード/マウス設定での動作確認時のシーケンスを細かく調べ, 以下のコマンド表を得ました.なお,コマンド名は適当に付けました.
これらのコマンドを組み合わせてPC側から送信することで,serialキティは 例えば「あれー?」と発声しながら首をかしげて,さらに首を元に戻す,という 動作をすることができます. (コマンド送信シーケンスは0x67 0x44 0x40) ここで,発声はかなり時間のかかる動作ですので,適当にwaitを入れないと, 発声途中で次の発声コマンドを送信すると,発声が替わってしまいます. BeOSでwaitを入れるにはsnooze()を用います. なお,発声途中で腕振りなどの動作をさせても発声とは関係ないので, waitを入れる必要はありません. また,ボタンイネーブルコマンドを送信した後で,serialキティの2つのボタンを押下すると serialキティからデータが送信されます. 送信されるデータは以下のとおり.
■USBプロトコルの解析さて,USBプロトコルを解析してみました. BeOSのusbkitのinfoでディスクリプタを覗いてみると次のようになっています.
[Device]
Class .................. 0
Subclass ............... 0
Protocol ............... 0
Vendor ID .............. 0x04c5
Product ID ............. 0x1010
Version ................ 0x0100
Manufacturer String .... "Fujitsu"
Product String ......... "Mascot Robot"
Serial Number .......... ""
[Configuration 0]
[Interface 0]
Class .............. 0
Subclass ........... 0
Protocol ........... 0
[Endpoint 0]
MaxPacketSize .... 8
Interval ......... 10
Type ............. Interrupt
Direction ........ Input
ここで注目すべきはデフォルトのコントロールエンドポイントを除いて エンドポイントが1つ(Endpoint 0)しかないということです.
しかもこれはInput方向(デバイス(USBキティ)→ホスト(PC))です. これはキティのボタンクリックに対応してUSBキティからPCにデータを
送る(実際は[Endpoint 0]ディスクリプタに記述されているとおりにPCが インターバル10(msec)でポーリングして受信する)ためのものだと考えられます. で,秘密兵器を某所よりお借りして,キティのUSBプロトコルをsnoopし, USBキティを動かしたり,顔を赤らめさせたりボタンクリックを受信したりする
プロトコルを解析しました. まず,USBキティを認識します. 通常のUSBデバイスと同様に,USBデバイスとして認識するには Control InエンドポイントにGET_DESCRIPTOR標準リクエスト(デバイスディスクリプタ)を送ってやり, デバイスディスクリプタの最低バイト数分(8バイト)要求します(Windows 2000などでは バイト数が64バイトとか255バイトとか多めの数を要求したりしています). すなわち,Control Inエンドポイントに80 06 00 01 00 00 08 00を送ります. (このデータの意味の詳細はUSB 1.1仕様書,9.3 USB Device Requestを参照のこと)
[Device] Class .................. 0 Subclass ............... 0 Protocol ............... 0 Vendor ID .............. 0x04c5 Product ID ............. 0x1010 Version ................ 0x0100にあたる部分が読み出せています. 次にデバイスにSET_ADDRESSします. 例えば,使っていないアドレスとしてUSBキティに対して,2をSET_ADDRESSします. すなわち,Control Inエンドポイントに00 05 02 00 00 00 00を送ります. (SET_ADDRESSに関しては,USB 1.1仕様書,9.4.6 Set Addressを参照のこと)
1つ目のGET_DESCRIPTORで,デバイスディスクリプタが18バイトあることがわかっているので, 次に,再度デバイスディスクリプタ全部(0x12=18バイト)を取得します. すなわち,Control Inエンドポイントに80 06 00 01 00 00 12 00を送ります.
[Device] Class .................. 0 Subclass ............... 0 Protocol ............... 0 Vendor ID .............. 0x04c5 Product ID ............. 0x1010 Version ................ 0x0100が読み出せています.(前半部分は重複あり) 次に,コンフィギュレーションディスクリプタを取得します. コンフィギュレーションディスクリプタは全部で何バイトあるか現時点ではわかっていないので, Control InエンドポイントにGET_DESCRIPTOR標準リクエスト(コンフィギュレーションディスクリプタ)を送ってやり, 最小限の9バイトを要求します. すなわち,Control Inエンドポイントに80 06 00 02 00 00 09 00を送ります. (GET_DESCRIPTORに関しては,USB 1.1仕様書,9.4.3 Get Descriptorを参照のこと)
一旦最小限のコンフィギュレーションディスクリプタを取得した後は, コンフィギュレーションを示すディスクリプタをすべて取得します. 上のGET_DESCRIPTORでwTotalLength=0x19(25バイト)という情報が取得できているので, 次に再度GET_DESCRIPTORで25バイトの取得を要求します. すなわち,Control Inエンドポイントに80 06 00 02 00 00 19 00を送ります.
[Configuration 0]
[Interface 0]
Class .............. 0
Subclass ........... 0
Protocol ........... 0
[Endpoint 0]
MaxPacketSize .... 8
Interval ......... 10
Type ............. Interrupt
Direction ........ Input
の部分が読み出せています. usbkitのinfoで読める情報として,Manufacuturer StringやProduct Stringがありますが, これらは文字列ディスクリプタを読み出してやれば取得できます. 文字列ディスクリプタに関しては, Manufacturer Stringはインデクス1を指定し, Product Stringはインデクス2を指定し, Control Inエンドポイントに対してGET_DESCRIPTOR標準リクエスト(文字列ディスクリプタ)を送ってやることで取得できます (ここでは詳細な説明は省略します). さて,キモのUSBキティを動かすための情報ですが, これにはControl Inエンドポイントに対して,ベンダリクエストを送ってやり, USBキティから返ってくるデータを取得することで実行されます. 具体的には,Control Inエンドポイントに対して, C2 03 2C 00 xx 00 08 00を送ってやることで 実行されます(xxに入る部分が以下に示すコマンドです).
コマンドを送信した後に, データステージで受信する8バイトのデータのフォーマットを解析すると 次のようになっていました(解析した結果ですので,研究員の想像の部分があります).
キティのボタンクリックに関する情報は, 上のコマンドで0x32(ボタンデータ読み取り)を実行し, 返ってくるデータから判断すればいいようです. (取りこぼすことがまれにあります) 解析した結果では,ボタンデータ読み取りを実行したときに, 返ってくるデータには以下のものがありました.
■実践研究さて,お待たせしました.実践研究です. 2001/11/16: USBキティを追加したので,serialと混同しないようにUSBはUSBキティ,serialはserialキティと区別しました 例題1: serialキティを赤面させるHello Kitty Stationで赤面動作を確認したときのコマンドシーケンスは
でした. なぜか[かしげ(戻し),腕ふり(腕おろし)]と[赤面(消灯)]を2回繰り返していますね. ここらへんは適当に(もしくはやたら保守的に)実装されているような気がします. さて,実際に試してみましょう. 初期化シーケンスとして,以下のコマンドを送信しますが,初期化の前に 1回以上のデータ読み込みを行なうとよいようです. ■初期化シーケンス
あぁ,何て楽勝な初期化シーケンスでしょう♪ では,まずはserial1のみに対応したでっちあげソフトで試してみましょう. ここでは,初期化シーケンスを叩いて,赤面させっぱなしにしてみます. コマンドとコマンドの間にsnooze()を入れていますが,この値は適当です.
/*
Hello Kitty Example 1
*/
#include <DeviceKit.h>
#include <stdio.h>
int main(void)
{
BSerialPort serial1;
int seq = 0;
char buf;
serial1.SetBlocking(false);
serial1.SetDataRate(B_9600_BPS);
serial1.SetDataBits(B_DATA_BITS_8);
serial1.SetStopBits(B_STOP_BITS_1);
serial1.SetFlowControl(B_NOFLOW_CONTROL);
serial1.SetParityMode(B_NO_PARITY);
serial1.SetTimeout(1000);
serial1.ClearInput();
serial1.ClearOutput();
serial1.SetRTS(true);
serial1.SetDTR(false);
if ( serial1.Open("serial1") <=0 ) {
printf("serial1 Open Error\n");
return -1;
}
serial1.SetRTS(true);
serial1.SetDTR(false);
serial1.ClearInput();
serial1.ClearOutput();
if (serial1.Read(buf,1) == 1) {
seq++;
printf("%02d: KITTY 0x%02x\n", seq, buf & 0xff);
}
serial1.SetBlocking(true);
// read 1 byte before intialize
if (serial1.Read(buf,1) == 1) {
printf("%02d: KITTY 0x%02x\n", seq, buf & 0xff);
seq++;
}
snooze(1000000);
// initialize command send
buf = 0x20; serial1.Write(buf, 1);
printf("%02d: PC 0x%02x\n", seq, buf & 0xff);
seq++;
// read ACK
if (serial1.Read(buf,1) == 1) {
printf("%02d: KITTY 0x%02x\n", seq, buf & 0xff);
seq++;
}
// button enable command send
buf = 0x28; serial1.Write(buf, 1);
printf("%02d: PC 0x%02x\n", seq, buf & 0xff);
seq++;
// read ACK
if (serial1.Read(buf,1) == 1) {
printf("%02d: KITTY 0x%02x\n", seq, buf & 0xff);
seq++;
}
// sekimen OFF
buf = 0x50; serial1.Write(buf, 1);
printf("%02d: PC 0x%02x\n", seq, buf & 0xff);
seq++;
// read ACK
if (serial1.Read(buf,1) == 1) {
printf("%02d: KITTY 0x%02x\n", seq, buf & 0xff);
seq++;
}
// sekimen ON
buf = 0x58; serial1.Write(buf, 1);
printf("%02d: PC 0x%02x\n", seq, buf & 0xff);
seq++;
// read ACK
if (serial1.Read(buf,1) == 1) {
printf("%02d: KITTY 0x%02x\n", seq, buf & 0xff);
seq++;
}
serial1.Close();
}
うーん,書いていてあまりにも簡単なので,これ以上書くのがバカらしく なってきました. ということで,例題1はここまでです. 例題2: serialキティデバイスドライバ次に,デバイスドライバとして,serialキティをopen(), ioctl()で制御することを 考えました.これも適当にでっちあげてみました. 手動でインストールするには,/boot/home/config/add-ons/kernel/drivers/binに ドライバ本体(kitty_driver)をコピーし,/boot/home/config/add-ons/kernel/drivers/dev/misc/にドライバ本体へのシンボリックリンクを置いてください. (この説明でわからない人はすなおにバイナリをインストールしてください)[2000/10/20 デバイスドライバ1.0から本体へのシンボリックリンクを/dev/miscへ変更しました.] さて,要はシリアルですので,serial1ならI/Oポート0x3f8とかserial2なら I/Oポート0x2f8とかでアクセスできるわけです. で,9600bps, データビット8ビット,ストップビット1ビット,ノンパリに 強引に設定してから,コマンドを送信してやればよいわけですね. で,設計としては,serial1のみに対応し,
[2000/10/20 ドライバ1.0にて更新] で,設計としては,serial1のみに対応(ソース変更により対応可)し,
確認はしていませんが,デバッグ出力をONにしていると まともに動かない可能性があります. また,ver.1.0から2重起動をチェックするようになりましたので, キティデバイスドライバをopenしているアプリがある場合,2つ目以降の アプリがキティデバイスドライバをopenしようとした場合,openに失敗します. さて,ドライバの動作ですが,結局,ioctl()での制御ONLYで, プリミティブなコマンドの送信のみできます.
#define B_KITTY_FACE_LED_ON 0x58 // ASCII 'X'
#define B_KITTY_FACE_LED_OFF 0x50 // ASCII 'P'
#define B_KITTY_BUTTON_ENABLE 0x28 // ASCII '('
#define B_KITTY_BUTTON_DISABLE 0x20 // ASCII ' ' (SPACE)
#define B_KITTY_STEADY_POSITION 0x40 // ASCII '@'
#define B_KITTY_QUESTION 0x44 // ASCII 'D'
#define B_KITTY_HAND_UP 0x48 // ASCII 'H'
#define B_KITTY_HELLO 0x60 // ASCII 'a'
#define B_KITTY_JAPANESE_HELLO 0x61 // ASCII 'a'
#define B_KITTY_SEE_YA 0x62 // ASCII 'b'
#define B_KITTY_LOTO 0x63 // ASCII 'c'
#define B_KITTY_BINGO 0x64 // ASCII 'd'
#define B_KITTY_FANTASTIC 0x65 // ASCII 'e'
#define B_KITTY_LUCKY 0x66 // ASCII 'f'
#define B_KITTY_OH_NO 0x67 // ASCII 'g'
#define B_KITTY_TIMER 0x68 // ASCII 'h'
#define B_KITTY_ITS_TIME 0x69 // ASCII 'i'
#define B_KITTY_PI 0x6A // ASCII 'j'
#define B_KITTY_PIRORI 0x6B // ASCII 'k'
#define B_KITTY_PIPIPI 0x6C // ASCII 'l'
#define B_KITTY_PIRORI2 0x6D // ASCII 'm'
#define B_KITTY_PIPIPI2 0x6E // ASCII 'n'
#define B_KITTY_PIRORI3 0x6F // ASCII 'o'
で,こちらがserialキティドライバを利用して,ioctlで制御するアプリのサンプルです.
例題2は「あれ〜?」と発声させるだけのシンプルなアプリです. 例題3は標準入力(キーボード)からキー入力を1文字読み込んで,それに対応した コマンドでserialキティを動かすだけのアプリです. キー入力は上記ASCII文字に対応しています. (というか,どんな入力でもserialキティに送りつけてしまう極悪アプリです) あまりの簡単さなので,もはや,説明など不要でしょう. 例題4: USBキティデバイスドライバさて,USBの解析も終ったので,USBキティを制御するドライバをでっちあげました. ioctl()による制御コマンドは同じですが,open()するデバイス名が違っています. (serialキティは/dev/misc/kittyに,USBキティは/dev/misc/usb_kittyになります) 設計としては,USBのどのポートでもOKで対応し(このへんはusbdが管理してくれている),
■おわりにキティデバイスドライバを利用するのはしごく簡単です. open()して,ioctl()するだけですので, BeWare作者の方,キティデバイスドライバを使って 新たなユーザインタフェースの境地を開拓してみませんか? 個人的には,biffとかのユーザ通知型のアプリとか,メーラとかの ユーザインタフェースに適していると思います. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [B技研TOPへ戻る] [B級なBeOSの研究へ戻る] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Copyright (c) 1998, 1999 Shuichi NAKAMURA All
rights reserevd. You can link this page freely. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||