SSブログ

Mac用USBデバイス-106 USB Desimpの実装を始める [Mac用USBデバイス工作]

さーて、なにをやってたっけ? まず、思い出すことから始めないと。
敬愛する偉大なバカボンのパパを忘れないための僕の座右の銘、
「忘れようとしても思い出せない」
意味わからんわ、自分でも。

なにをやっていたかを思い出す

EZ-USBのチップを乗せた実験用ボードを去年買った。これをMac用のUSB機器として開発にWindowsをいっさい使わずにMacだけでできるようにしようという目標を立てた。
EZ-USBをMacから動かすために、かなりの時間を使ってMacOS Xから外部デバイスを扱うためのAPIであるI/O Kitを勉強した。ホストであるMacでどうやってプログラミングをすればいいかは大まかにはわかったし、I/O Kitの思想自身はなかなか面白いこともわかった。ついでにFireWireの制御もできるようになった。

EZ-USB側のホストの要求に対して応答するためのプログラミングもざっくりまとめた。Mac上で作業ができるように、EZ-USBが持っている8051CPUのオブジェクトが吐けるコンパイラであるsdccをMacにインストールしてXcodeから使えるようにすることはそれほど大変ではなかった。
しかしEZ-USBボードを実際にUSB機器としてホストであるMacに認識させるためにはデスクリプタという構造体をUSB経由でホストに返せなければならないが、これが便利なOSを積んでいるわけではないEZ-USBの8051CPUができるようにするためにはかなりの手間がかかることがわかった。
しかしデスクリプタはサイズは大きいけれど定型的なので、デスクリプタを返す8051のコードを自動生成するアプリは書けるだろう、そのMacで動くアプリを書こうと考えた。
先日まで、USB Desimpと名付けたそのアプリのUIが書きやすいようにCocoaバインディングを勉強した。
やっと今日からUSB Desimpの実装を始めることにする。

5.4  USB Desimpの実装

アプリは前も考えたようにドキュメントスタイルで、ユーザインターフェイスからデスクリプタの内容を定義する部分と、内容ができたらそれをsdcc用のソースとして出力する部分を作ることになる。まずMVCのモデルから、しかも表示にまつわる部分だけを先に考える。

接頭辞はUDI(Usb Descirptor Implementer)にしよう。まんま。

5.4.1  デスクリプタフィールドの実装

デスクリプタを実装する前にそれぞれのフィールドを表すクラスを定義しよう。UDIFieldとする。それぞれのデスクリプタはこのUDIFieldを要素に持つNSArrayを持つことになる。NSArrayに入れるのはUIのマスタディテールインターフェイスで、ディテール側(マスタ側で選択されたデスクリプタの中身を表示)にもNSOutlineViewを使いたいから。

本来、デスクリプタフィールドは階層構造にはなっていないのでNSTableViewでよくて、NSOutlineViewを使う必要はない。ところが
  • bitmap(詰め込みフラグ)
  • index(文字列)
の設定は下の階層構造がないと入力が不便になる。

bitmapは1ビットのON/OFFフラグや数ビットで何通りか場合分けしたりというのが1バイトの中につまっていてその数字を入力させるのではなく、意味を表示させてユーザに選択させる必要がある。

また文字列はLANGIDによって個数が変化するため、やはり下の階層を作って配列のように入力させる必要がある。

そうするとNSTableViewではうまくいかないということになる。少なくともNSTableViewでは下の階層を表示するためにある行は表示のためのNSCellのサブクラスを差し替える必要があり、それはすなわちNSOutlineViewと同じような動作をさせることになる。

インスタンス変数は
@interface UDIField : NSObject <NSCopying> {
    NSString    *name;
    NSString    *type;
    BOOL        autoFill;   //  If YES, the field is not editable.
    id          value;      //  its class depend on the type
    NSArray     *selections;
    id          selectionValue;
    id          children;  //  for divided bitmap fields or strings
}
...
このくらい。nameはUIに表示させるフィールド名(bLength、bcdUSBなど)、typeはその型(整数、BCDなど)autoFillはユーザが入力する必要のないフィールド例えばデスクリプタのバイト長など。valueはフィールドの値、selectionsというNSArrayは何通りかしかないようなフィールド、例えばbcdUSB(リリースナンバ)などはポップアップメニューを表示してそれを選択させるようにするため。selectionValueは選択肢がある場合にどれが選択されているかを指すポインタ。こんなもんかな。

NSCopyingプロトコルをアドプトしているのは、ドキュメントとして保存できるようにするため。

これを設定するために
+ (id)fieldWithName:(NSString *)fieldName
               tpye:(NSString *)fieldType
           autoFill:(BOOL)yn
           andValue:(id)defaultValue;

+(id)fieldSelectionWithName:(id)fieldName
               andSelections:(id)selectionValues;
こんなクラスメソッドを作る。これをずらっとフィールドの数だけ並べる。って、これはえらい大変やがな。これをプログラマチックに書いたらデバイスデスクリプタだけでも13個のフィールドがある。これはさすがにうんざりするし、絶対デバグで死ぬ。
nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

献立06/07献立06/08 ブログトップ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。