2014年7月30日

[ble]ClientとServer

1ヶ月も経たないのに、もう忘れてしまった・・・。
が、あのときは調べるだけで手一杯だった。
今度は、吸収する番だ!

 

image

MasterとCentral、SlaveとPeripheralについては、同じになると思っている。

Core_v4.1の図で、Initiatingになった方がMaster、Advertisingになった方がSlave。
Vol.6 Part Bの図。

image

 

こちらは、Vol.3 Part Cの図。
AがInitiatedしているので、Masterと言えよう。あるいは、AがInitiatedしたいので、L2CAPではMasterになるというのか。

image

 

それに対して、ServerとClientは意味合いが異なる。
Vol.3 Part Gの図を見るとよいか。

image

だいたい上記の作りにする場合、SensorがPeripheralでComputerがCenterになるだろう。
でも、データを持っているのはSensorの方で、Computerはそれを取得しに行くことになる。
つまり、SensorがServerで、ComputerがClientだ。

でもこれが、Sensorとなっている方がComputerの状態を定期的に監視してブザーを鳴らすデバイスだったらどうだろうか。
やはりSensorとなっている方はPeripheralでComputerはCentralになるだろうけど、データを持っているのはComputerで、Sensorがそれを取得しに行くことだろう。
そうなると、SensorがClientで、ComputerがServerだ。

ってことでいいんだよね。

2014年7月29日

[nfc]HCEがキーワードらしい

http://itpro.nikkeibp.co.jp/atcl/news/14/072400197/

2014年のキーワードは、HCEらしい。
まあ、もう2014年も半分が終わったのに・・・とか言っても仕方が無い。
それに、どのクオーターで数えるのかは人それぞれなので、細かいことは捨て置け。

私は、HCEっていうのはAndroidの機能名だと思っていた。
TgInitAsTargetコマンドとかでR/Wをターゲット状態にしたとき、そのコマンドをさばくのはホストだ。
だから、カードエミュレーションする≒ホストがカードエミュレーションする、という認識だったのだ。
もちろん、モバイルのFeliCaチップのようなセキュアエレメントを使うようになっているものは、チップとセキュアエレメントが勝手に通信しあって解決してしまう。
そこがセキュアエレメントのセキュアエレメントたるゆえんだ。

HCEすると、ホストが全部やるので、データはつーつーになる。
だから極端に言えば、適当なところでメモリを抜き取ると、通信したデータが取得できるだろう。
でもまあ、そんなことをいえば、HTTPSとかの通信だってどこかでメモリに落としてるんだから、拾おうと思えば拾えるんじゃないかと思う。
課題は色々あるんだけど、私はあまりセキュリティに詳しくないせいもあって、楽観的だ。
なんとかなるんじゃないのー、という感じ。
いや、詳しくなった方がいいんだろうけど、もう私の許容範囲を超えてますわ。

 

そういうのはよいとして、HCEってなんだろう?というのがもやもやとしている。
私の認識は、今のところ、こう。

  • NFC Forumのカードエミュレーション
    • 特に機能を限定せず、タグ以外のものがカードエミュレーションすること全般を呼んでいる
  • AndroidのHCE
    • 今までCardEmulation機能をユーザに提供していなかったAndroidが、Type4かつSEなしで可エードエミュレーションできるようになった
  • NFC ForumのHCE
    • SE必須となっていた内容についてカードエミュレーションすること?

私はNFC Forumのメンバーじゃ無いので、内部でどういう話が進んでいるのかはわからない。
非メンバーが見ることができる技術仕様書には、SEが絡みそうな話は出てきてなかったと思う。
だから、NFC ForumがHCEの話をすると「?」と思ってしまうのだった。

http://nfc-forum.org/newsroom/nfc-forum-statement-regarding-host-card-emulation-hce/
こちらを読むと、NCIにHCE実装について書いてあるようだ。
NCIは・・・読んでない・・・。

ただ興味深いのは、上記リンクにはNFC-A, B, FのようなNFC Forumの区分ではなく、ISO 14443やJIS X6319-4のような規格名になっていることだ。
ISO 14443は見たことがないのだが、JIS X6319-4はこちらから見ることができる。
X6319だと、Read w/o Encryptionとか、Write w/o Encryptionじゃない、ReadやWriteというコマンドがある。
これは、認証しないと使えないコマンドで、確か通信経路も含めて符号化されるんじゃ無かったっけ。

NFC Forumの、非会員で見ることができる技術仕様書には、データの保護を行うための符号化については取り決めが無い。
だからかねー、というところだ。
私の予想では、LLCPSでセキュアなP2Pをする方向になるかと思ってたけど、やはり既存の資産は優先されますわな。

2014年7月27日

[ble][nrf51]Write w/o Encで書き込んだUUIDをiBeaconする

FeliCa PlugからUUIDを書き込み、そのUUIDでAdvertisingというかiBeaconというかをするようにできた。
https://github.com/hirokuma/nrf51822_felicaplug/commit/3b8bb6329223354209f7531836184650a800d30b

今朝まで、なぜかAdvertisingさせようとするとHardFaultしていたのだが、なぜか直った・・・。
Eclipseかgdbか・・・。

ブロック0に1ブロック書き込みすると、そのデータをそのままUUIDとしてiBeaconのデータを投げる。
Major, Minor, RSSIなどは固定だ。
もう1ブロック増やして、そこも可変にしてもよいのだけど、手元に1ブロックアクセスするNFCアプリしか作っていなかったので、もういいや。

なんでこんなもん作ったかというと、FLASH書き込みを行わずに外部からUUIDを書き換えられると便利かも、と思ったからだ。
iBeaconアプリの評価とかによいかもね。

image

まあ、私自身はiBeaconにあまり興味を持ってないのだけど、OSが動作確認に使えるという点では便利だ。
SNEP実装したときにAndroid Beamで動作確認するような、そんな感じだ。

image

LEDは3つ。
搬送波検知が左、Advertising中が真ん中、エラー発生が右。
まあ、本当に運用するならAdvertising中のLEDは無しだな。

 

さて、簡単そうなところは動かせたので、次はGATTとかそういうやつかな。

AutoHotkey

Windowsでキーカスタマイズするのに、AutoHotkeyを使っている。

最近になって思うのだが、作業を便利にするのはいいとしても、キーカスタマイズはあまりやらない方がよいな、と。
一度キーカスタマイズしてその環境に慣れてしまうと、他の環境でも同じキーカスタマイズにしないとストレスがたまってくる。

  • 一時的に他のPCを使うとき、疲れる
  • 一時的に人にPCを貸すとき、びくびくする
  • PCをセットアップするのに時間がかかる
  • 気に入るカスタマイズが見つかるまで、いろいろ試して時間がかかる

などなど、弊害多数。
にもかかわらず・・・一度やって慣れてしまうと、もうだめなのだ・・・。

以前までは、窓使いの憂鬱とか、猫まねきとかを使ってたんだけど、Windows7になってから使えなかったので、AutoHotkeyに乗り換えた次第だ。
レジストリの書き換えが無いので、アプリさえ立ち上げなければ元の環境に戻れるというのが助かる。
CtrlとCapsLockの変更については、このツールではできなかった気がする。

^h::Send,{backspace}
$^f::Send,{right}
^b::Send,{left}
^n::Send,{down}
^p::Send,{up}
sc029::Send,{Esc}
^+f::Send,^{f}

私はEmacsは使えないのだけど、カーソルをCtrlキーのキーバインドで実現できるのは気に入ったので、そこだけ採用した。

そうすると、検索をCtrl+Fに割り当てているソフトが使いにくくなる。
では、ほとんど使わないCtrl+Shift+Fを押すとCtrl+Fになるようにしておこう、というのが上記だ。
$^fと$を付けないと、^+fによる^fがrightに置き換えられてしまうようだ。

2014年7月26日

[nrf51]FeliCa Plugの時間

ロジアナが来たので、FeliCa Plugの通信速度などを計測。
SPIは1Mbpsにしている。

image

最初の2byteから184us空いてデータ受信をしている。
これは、FeliCa Plugが送ってくるデータサイズがわからないので、1byte目のコマンドと、2byte目のブロック数を読んでから全体の受信サイズを決めているところなので、そこの間だ。
まあ、本当はブロックリストエレメントが2byteなのか3byteなのかをさばかないといけないのだけど・・・省略した。
だって、2byteのブロックエレメントくらいしか使わんやん!

そのあとは、nRF51 SDKに任せているところだ。
データ間隔は12.2usというところか。
最初の2byteだけ連続しているのは、SPIの送受信ともに余裕バッファが1つあるので、そこに貯める間隔が早くなっているだけのようだ。3byte目までの時間が空いているのは、結局そこが空くまで待つからだろう。

そんなわけで、時間的にもそんなに悪くない作りになったんじゃないのかな。
ここまでの成果は、githubにも上げてます。

ZeroPlusでダウンロードする無料の解析プロトコル

ようやく、ZeroPlusで何をダウンロードすればよいかわかった・・・。
ロジアナ本体はわかるとして、無料のプロトコル解析の方だ。
追加でダウンロードするものについては説明があるんだけど、無料の方がわからんかったのだ。

image

これをインストールすればよい。

ロジアナを買いました

ロジアナを買うと、テンションが上がりますな。

http://akizukidenshi.com/catalog/g/gM-04426/

スタンドアローンじゃなくて、PCと接続するタイプ。
サンプリングレートは100Hz~100MHzとあるので、私の扱う範囲では問題なし。
何より、お値段が手頃。
プロトコル解析にも対応していて、無料で25プロトコルまで追加ダウンロードできる。
(この、25個という制限に気付かないところだった・・・。)

で、ここで作業が止まっている。。。
秋月から買ったZeroPlusにはインストールメディアが入っておらず、ダウンロードするようになっている。
んで、サイトからダウンロードするのだけど、Logic AnalyzerとProtocol Analyzerがあり、ロジアナ本体はLogic Analyzerをダウンロードして使えたのだが、プロトコルの解析はProtocol Analyzerをダウンロードするようだ。
ではとダウンロードしたのだが・・・うちのAvastがウイルス検知してしまった。

誤検知かどうかっていうのを素人が判断するのは難しいと思う。
ZeroPlusはけっこうメジャーなので大丈夫な気はするが、私がダウンロードした瞬間はダメなソフトになっていたのかもしれない。
とりあえず、Microsoftのセキュリティソフトに変更して試してみよう。
あー、こんなので私の週末は終わるのかー

2014年7月25日

FeliCa Linkがスイッチサイエンスさんから発売

とうとう来ましたねぇ。
個人購入できるFeliCa Linkですよ、奥さん。
やはり、ここはスイッチサイエンスさんだった。
そっけないページとは裏腹に、在庫を多数用意しているところに本気さを感じるのは私だけか。


さて、FeliCa Linkについて購入前の復習をしておきましょう。

まず型番から。
RC-S730はアンテナ付きのモジュール、RC-S967はチップ単体。
私のように使うだけの人は、RC-S730になる。
ちなみに「RC-S370」は、少し前までメインだったPaSoRiの型番なので、注意しよう。

そして、機能についてみていこう・・・・あれ。
あれっれれれれれれれr????

さっき、モジュールとチップのことを書いたが、FeliCa Linkのチップは2つあり、1つはRC-S967/1V、もう1つがRC-S967/2V。
違いは、1Vか2Vかだ。
RC-S730に載っているのは1Vの方らしい。
1Vと2Vの違いは・・・リーダライタ機能の有無!

私のね・・・私の思っていたFeliCa Linkというのは、こんなに小さいのにR/Wまで載ってるなんてすごい!!だったのよ。
それがねー、ちょっとテンション下がったわー。
まあ、それは私の理解不足が原因だし、R/Wまでやろうとすると大変なのはなんとなくわかるんだけど。
でも私は夢を描いていたのだよ・・・。

まあ、無い物ねだりは、よそう。
FeliCa LinkのRC-S730とRC-S967/1Vには、リーダライタ機能は無い、と。
でもね・・・。


でもね、NFC-DEPはあるんだよ。
リーダライタができるんだからDEPもできるよなー、と思ってたけど、なくてもできるのだ。
ドキュメントに「イニシエータとしてのNFC-DEP通信はリーダ/ライタモードで行います」とあるから、RC-S730とかではターゲットとしてNFC-DEPになるのだろう。

んー、では、RC-S730同士ではNFC-DEPできないのだろうか?
できないのだろう。
ここ数年、SONYの技術資料を読んでいてわかってきたのだが、「できない」というのは書かないのだ。
こういう使い方はするな、というのはあるし、細かい部分になると ”これはできない”という記載もあったりするが、基本的に「これはできない」ということを書いていないのだ。
そこら辺が、SONYチップが敬遠される理由の一つかもしれん。クロノトリガーの話じゃないけど、あれくらいは書かないとな、といつも思う。

あ、「9.4 リーダ/ ライタモード付FeliCa Link同士の通信」という章があるので、そういう意味では今までのよりは親切かも。
しかし、この章のタイトルから「リーダ/ライタモードがついていないFeliCa Link同士ではNFC-DEPできない」ということを読み取るスキルが必要になるんだけどね。
ちなみに、普通に読み取るなら「両方にリーダ/ライタモードがついていると注意することがあるけど、そうでなければ注意しなくてよいよね」だ。

一応フォローするなら、「1.6.4 NFC-DEPモード」に「FeliCa LinkはNFC-DEP通信のターゲットとして動作します」と書いてある。
ただ、私に言わせれば、それは「NFC-DEPモード」ではなく「NFC-DEPターゲットモード」だ。


と、最後は文句を書いていたような感じになったが、FeliCa Plugと同じくらいのチップの値段でNFC-DEPターゲットになることができるとなると、用途は広がるんじゃなかろうか。
できれば、LLCP、いやSNEPまでサポートしてほしかったのだが、そこまでは難しいということですかね。

2014年7月24日

[nrf51]今のFeliCa Plugの動き

現在実装できているところまでのFeliCa Plugがどう動くか、簡単に説明しておこう。
ソースファイルなどは、こちら。
https://github.com/hirokuma/nrf51822_felicaplug/tree/e43719514679f0515670656c582036a15e37e2af

ドキュメントフォルダの、FeliCa Plugの説明をがんばってるつもり。
Excelファイルは、これから作ろうとしているものについてなので、astaファイルを見るのがよいだろう。
だいたい、どういうことをしないといけないかとか、どこでどのくらい待つとかがわかるんじゃなかろうか。

これを実装して、FeliCa Plugを接続し、R/Wで読み込みを行うと、こういうデータになる。

image

注意としては、IDmだろうか。
私はスイッチサイエンスさんから購入したFeliCa Plugを使っているので、FeliCa Plugへの初期パラメータはこうしている。

static const uint8_t k_InitVal[] = {
    /* 各種設定パラメータ */
    0x03,                    /* データ転送設定 : FT転送設定        */
                            /* システムコード : 0x12FC            */
    /* 最大応答時間パラメータ */
    0xff, 0xff,                /* Read w/o Enctyption  : 255        */
                            /* Write w/o Enctyption : 255        */
    /* データフォーマットコード */
    0x00, 0x1c,                /* Switch Science社から購入の場合    */
    /* ユーザー設定パラメータ */
    'k', 'u', 'm', 'a'
};

データフォーマットコードが、スイッチサイエンスさんの場合は上記の値になっている。
そして、ユーザー設定パラメータは、とりあえず「kuma」にしてみた。

だから、IDmが

  • 03 FE : FeliCa Plugの値
  • 00 1C : データフォーマットコード
  • 6B 75 6D 61 : kuma

になっている。
まあ、03 FEで始まるのはFeliCa Plugだけということになってるから、気になる人はユーザー設定パラメータはランダム値にしておいてもいいかも。

Read w/o Encryptionで返す値は、無条件で0x00~0x0Fまでになっている。
これはfelica_plug.cのrecv_rwe()を見てもらえばわかるだろう。
Write w/o Encryptionしても、かならずステータスフラグは正常を返すようにしている。同じくrecv_wwe()。

ここまで動けば、あとはBLEを使うだけだ。
さてさて、どう料理しましょうかね。

2014年7月23日

[nrf51]バグにも、よいバグと悪いバグがあってな・・・

FeliCa PlugからのSPI受信ができずに悩み続けた私。
原因を突き止めるべく、ロジアナの購入にまで踏み切った。
しかし、購入までには時間があるため、もちろんデバッグを続けていた。

のろのろ考えていると、隅にいた老人が声をかけてきた。
彼は紐を持った震える指で複雑で美しい結び目を作りながら、静かに話すのだった。

「バグには・・・バグにも、といった方がよいかな。
 バグにも、よいバグと悪いバグがあってな。」

私は彼が何を言い出すのかさっぱりわからなかったが、この薄気味悪い老人と話すのがよいか逃げるのがよいか決めかねていた。
というのも、薄気味悪い見かけとは違い、目はとても知的で澄んでいたためだ。
それがわかっただけに、さらに私は彼を薄気味悪く感じた。

そんな様子に気付いたかどうかわからなかったが、彼は続けた。
「よいバグなんてない、そう思ってるだろう?
 バグはすべて悪だ、と。
 わしも、若い頃にはそう思ったもんじゃ。
 君と違ってわしは血気盛んな方でな。
 まあ、今のこの姿からは想像もつかんと思うが」
そういうと、予想した以上に不気味な笑い声を静かに上げた。
立ち去ろうと思えばその瞬間だったのだろうが、私は彼が何を言い出すのか気になり、足を止めてしまった。

「でも、な。
 『これは悪いバグだ!』というのはあるじゃろう?
 見た瞬間に身の毛が総立つような、腐臭が漂ってくるような、そんなバグじゃ。

 ということは、じゃ。
 相対的に、よいバグというものもある、という証明にならんじゃろうか?」
なんとなく彼の言い分がわかったので、思わず聞いてしまった。
「爺さんが見たことある悪いバグって、どんなのだい?」

その声を聞いた瞬間だった。
老人から漂っていた不気味な雰囲気は消え去り、代わりに別の雰囲気をまとっていた。
こういえばよかろうか、悪魔的な、と。
予想できる以上に悪魔的な笑い声を続けた後、聞こえるか聞こえないかの声で囁いた。
「これじゃよ」

それは、私が見ていたディスプレイを指していた。
そしてその目線は、GPIOの割り込みハンドラ処理に注がれていた。
気になってそこを見ると・・・。

「あああああああああああ!!!!」

私は叫び声かうめき声かわからない音を放ちながら崩れ落ち、血の涙を流し始めた。
画面には、GPIOからの割込が立ったビットを受ける変数をビットマスク値で&&している様子が浮かび上がっていた。
それも、全部の条件式に。

血の涙を流し終わったときには、隅の老人は消えていた。悪魔的な雰囲気だけを残して。


えーっと、『隅の老人』はこんなお話じゃないのでご安心を。
では、バグの説明に入ります。

まずバグのコードを。

static void gpiote_event_handler(uint32_t event_pins_low_to_high, uint32_t event_pins_high_to_low)
{
    //立ち上がり
    if (event_pins_low_to_high && GPIOTE_MASK_IRQ) {
        fp_irq_assert();
    }
    if (event_pins_low_to_high && GPIOTE_MASK_RFDET) {
        LED_OFF(PIN_LED);
        fp_stop();
    }
    //立ち下がり
    if (event_pins_high_to_low && GPIOTE_MASK_RFDET) {
        LED_ON(PIN_LED);
        fp_rfdet_assert();
    }
}

これはGPIOTEの割り込みハンドラ。
GPIO Task Eventという名前なのだが、登録したGPIOピンに変化があったとき、event_pins_low_to_highには立ち上がりのピンが、event_pins_high_to_lowには立ち下がりのピンが、それぞれビットで入ってくる。
0x00000014だったら、bit2とbit4に1が立っているので、GPIO2とGPIO4に変化があった、という見方だ。

FeliCa PlugからのGPIO制御で割込監視するものとしては、/RFDETとIRQがある。
/RFDETはアクティブLOWで、搬送波検知を示す。
IRQはアクティブHIGHで、受信データ要求を示す。

おおよその使い方としては、こうなる。

  1. 搬送波が来るまで、省電力で待つ
  2. nRFDETがアサートしたら、FeliCa Plugの初期設定をして、コマンド待ち受け状態にする
  3. IRQがアサートしたら、FeliCa Plugからコマンド受信する(コマンド受信中にIRQはネゲートする)
  4. コマンドがRead w/o EncryptionかWrite w/o Encryptionか判断し、戻り値を返す
  5. 搬送波が無くなるまで、3~5を繰り返す

そして、上記の実装で動いていたのは、3のアサートしたら、までだった。
というのも、IRQが立ち上がってevent_pins_low_to_highに値が入ると、まず最初のif文に入り、fp_irq_assert()が実行される。
これは(if文の書き方はさておき)期待通りの処理だ。
しかし次のif文、ここにも入ってしまい、fp_stop()が呼ばれ、すべてのFeliCa Plugへの処理を取りやめてしまっていた。
入る理由は簡単で、&&でつなげていて、右も左も値が入っているからだ。
あーー、恥ずかしい・・・。

正解は、こう。

static void gpiote_event_handler(uint32_t event_pins_low_to_high, uint32_t event_pins_high_to_low)
{
    //立ち上がり
    if (event_pins_low_to_high & GPIOTE_MASK_IRQ) {
        fp_irq_assert();
    }
    if (event_pins_low_to_high & GPIOTE_MASK_RFDET) {
        LED_OFF(PIN_LED);
        fp_stop();
    }
    //立ち下がり
    if (event_pins_high_to_low & GPIOTE_MASK_RFDET) {
        LED_ON(PIN_LED);
        fp_rfdet_assert();
    }
}

「||」と「|」は間違えないけど、「&&」と「&」は間違えやすい気がする。
なんでだろう?
「if (abc & MASK == 0)」みたいな優先順位の間違いはしなくなったのにねぇ。