2013/12/22

[nfc]HCEのサンプルを作った

ようやく、HCEのサンプルを作った。

https://github.com/hirokuma/HceSample

URI(スマートポスターじゃなく)のつもり。
動作は、Windows8.1 + RC-S380 + FeliCaランチャーで確認。
なんでかわからないけど、FeliCaランチャーが起動していないとだめなのだ。
NFPで動くんだったら関係なさそうなのだけど、なんだろうね?

NDEFのシーケンスで、NFC HACKSに載っている範囲でしか見てないから、Type 4A全般のエミュレーションにはなっていない。
最初は、こちらを見ながら作ろうとしていたのだが、途中でNFC Forumの仕様書を見始めたので、たぶん別物になったんじゃないだろうか。
http://www.slideshare.net/hieroadgjmptw/hcetype4

最初のSelectで、NDEF applicationの名前を行うので、そこで一致したら「NDEFアクセス中」みたいなフラグを立てるようにした。
ここらへんが、まだType 4Aのしくみをわかっていないので、そういう捌き方で良いのかはっきりしてない。
まあ、動くからいいか・・・。

うちではこれ以上の動作確認ができないので、ここまでかな。


あと、月刊NDEFも久々に作りました。
カードエミュレーション特集。
http://www.slideshare.net/hiro99ma/ndef-2013-12

記憶をたどりながら書いたので、あまり説明にこだわってなく、こざっぱりした感じになったんじゃないかな。
まあ、大半は昨日酒を飲みながら書いているので、ちょっと心配ではあるが・・・まあ大丈夫だろう。

2013/12/19

[nfc]HCEの動作確認をしたい (5)

実は・・・今週のHCE記事だが、日曜日に書きためたものを4日に分けてスケジュール投稿する、ということをしてみた。
5日目の今日は、12/18の2時半くらいに書いている。
目がしょぼしょぼだ・・・。


さて、4回目では、Windows8.1 + PaSoRi RC-S380を使って、Type4のまねをしているNexus7のHCE動作を見てもらおうとしたが失敗したところであった。

何がいかんかというと、よくわからんバイナリを受信して、よくわからんバイナリを返している、という部分だ。
バイナリデータがある限り、我々は解析をしなくてはならない。
ましてや、NFC HACKSという本があるのに、解析しないでいることができようか(いや、解析せずにはいられない)?

そんなわけで、HACK#17「NFC Forum Type 4 Tag」を開いた。
ふむ、よく聞く「T=CL」というのは通称だったんだ、とか、EFファイルってSIMカードの構造もそうだったよな、などと思い返しつつ読んでいると、まねしようとしていたNDEFメッセージの読み込みシーケンスがそのまま書いてあった。

ふむふむ、スライドに書かれているバイナリ値は、直接やりとりしている値ではなく、意味があるところだけ抜き出しているのだな。
ならば、そのまま送るだけではダメなのは当然だ。

プログラムはスライドを参考に、データはNFC HACKSを参考にして、こんなプログラムにした。
(これはこれで省略もあるがね。)

import android.nfc.cardemulation.HostApduService;
import android.os.Bundle;
import android.util.Log;
public class HostSampleService extends HostApduService {
    static enum CardStatus {
        INIT,
        CCFILE,
        REQ_DATA,
        OPEN,
        LEN,
        RET_DATA
    }
    final static byte[] SUCCESS = { (byte)0x90, (byte)0x00 };
    final static byte[] REQ_DATA = {
        (byte)0x00, (byte)0x0f,    //CCLEN
        (byte)0x20,          //Mapping Version
        (byte)0x00, (byte)0x40,    //MLe
        (byte)0x00, (byte)0x40,    //MLc
        //TLV(NDEF File Control)
        (byte)0x04,         //Tag
        (byte)0x06,          //LEN
        (byte)0xe1, (byte)0x04,    //signature
        (byte)0x00, (byte)0x32,    //max ndef size
        (byte)0x00,         //read access permission
        (byte)0x00,          //write access permission
        
        //success
        (byte)0x90, (byte)0x00
    };
    final static byte[] LEN = { (byte)0x00, (byte)0x03 };
    final static byte[] RET_DATA = {
        (byte)0x00, (byte)0x03,    //LEN
        //message
        (byte)0xd0, (byte)0x00, (byte)0x00,    //empty
        
        //success
        (byte)0x90, (byte)0x00
    };
    private final static String TAG = "HostSampleService";
    private CardStatus mCardStatus = CardStatus.INIT;
    @Override
    public void onDeactivated(int reason) {
        mCardStatus = CardStatus.INIT;
    }
    @Override
    public byte[] processCommandApdu(byte[] commandApdu, Bundle extras) {
        for (int i = 0; i < commandApdu.length; i++) {
            Log.d(TAG, Integer.toHexString(commandApdu[i] & 0xff));
        }
        switch (mCardStatus) {
            case INIT:
                Log.d(TAG, "init");
                mCardStatus = CardStatus.CCFILE;
                return SUCCESS;
            case CCFILE:
                Log.d(TAG, "ccfile");
                mCardStatus = CardStatus.REQ_DATA;
                return SUCCESS;
            case REQ_DATA:
                Log.d(TAG, "reqdata");
                mCardStatus = CardStatus.OPEN;
                return REQ_DATA;
            case OPEN:
                Log.d(TAG, "open");
                mCardStatus = CardStatus.LEN;
                return SUCCESS;
            case LEN:
                Log.d(TAG, "len");
                mCardStatus = CardStatus.RET_DATA;
                return LEN;
            case RET_DATA:
                Log.d(TAG, "retdata");
                mCardStatus = CardStatus.INIT;
                return RET_DATA;
            default:
                return SUCCESS;
        }
    }
}

 

これをNexus7に焼いて、PaSoRiに近づけると、Windows8.1からあのNDEFタグ検知したときに聞こえるあの音がしているではないか!

NDEFの中身がEmptyなので動作はしないけれども、ここにURIとか書いておけばトースト表示してくれるんじゃないだろうか。
興味はあるが、今回はやめておこう。
もっと気力があるときにやらないとな。

2013/12/18

[nfc]HCEの動作確認をしたい (4)

さて、ちゃんとHCEの動作確認をするには、受け側がちゃんと動かないといかんだろうということはわかってきた。
めんどうだが、Starter KitとNFC HACKSを読みながらがんばるしかないか・・・。

 

が、ふと考えると、うちにはWindows8.1があった。
この子は、NFPをサポートしている(PaSoRi RC-S380持ってるし)。
ならば、かざせば動いてくれるんじゃないか??

気をよくしてつなげてみたのだが、Nexus7をかざしても、あのタグをかざしたときのような音が出ない。
うーむ・・・。

あ、NFPって、たしかNDEFしか反応せんやん。。。
HCEもカードエミュレーションだから、ソフト的にNDEF値を返さないと反応しないような気がする。


http://www.slideshare.net/hieroadgjmptw/hcetype4

こちらを参考にしながら、同じシーケンスでアクセスしに来るという前提で、決め決めのデータを返すアプリに仕立てた。
スライドのp.24で端末が返しているデータね。

やっぱり・・・そういうのは無謀よね。
要求するデータサイズなんかも違うだろうし、受信パケットを見ずにやるってのは、さすがにだめなようだ。

12-16 00:54:18.171: D/dalvikvm(1205): GC_CONCURRENT freed 377K, 20% free 10581K/13168K, paused 3ms+3ms, total 62ms
12-16 00:54:18.171: D/dalvikvm(1205): WAIT_FOR_CONCURRENT_GC blocked 28ms
12-16 00:54:20.443: D/BrcmNfcJni(1098): RoutingManager::stackCallback: event=0x18
12-16 00:54:20.443: D/HostEmulationManager(1098): notifyHostEmulationActivated
12-16 00:54:20.453: D/BrcmNfcJni(1098): RoutingManager::stackCallback: event=0x17
12-16 00:54:20.453: D/BrcmNfcJni(1098): RoutingManager::stackCallback: NFA_CE_DATA_EVT; h=0x302; data len=13
12-16 00:54:20.453: D/HostEmulationManager(1098): notifyHostEmulationData
12-16 00:54:20.453: D/HostEmulationManager(1098): Binding to service ComponentInfo{com.blogpost.hiro99ma.hcesample/com.blogpost.hiro99ma.hcesample.HostSampleService}
12-16 00:54:20.473: D/HostEmulationManager(1098): Waiting for new service.
12-16 00:54:20.473: D/HostEmulationManager(1098): Service bound
12-16 00:54:20.483: D/HostSampleService(19005): init
12-16 00:54:20.483: D/HostEmulationManager(1098): Sending data
12-16 00:54:20.483: D/HostEmulationManager(1098): notifyHostEmulationData
12-16 00:54:20.493: D/HostSampleService(19005): ccfile
12-16 00:54:20.493: D/HostEmulationManager(1098): Sending data
12-16 00:54:20.493: D/BrcmNfcJni(1098): RoutingManager::stackCallback: event=0x17
12-16 00:54:20.493: D/BrcmNfcJni(1098): RoutingManager::stackCallback: NFA_CE_DATA_EVT; h=0x302; data len=5
12-16 00:54:20.503: D/HostEmulationManager(1098): notifyHostEmulationData
12-16 00:54:20.503: D/HostSampleService(19005): reqdata
12-16 00:54:20.503: D/HostEmulationManager(1098): Sending data
12-16 00:54:25.047: D/BrcmNfcJni(1098): RoutingManager::stackCallback: event=0x19
12-16 00:54:25.047: D/HostEmulationManager(1098): notifyHostEmulationDeactivated
12-16 00:54:25.047: D/HostEmulationManager(1098): Unbinding from service ComponentInfo{com.blogpost.hiro99ma.hcesample/com.blogpost.hiro99ma.hcesample.HostSampleService}
12-16 00:54:25.057: E/BrcmNfcNfa(1098): UICC[0x0] is not activated

と思って、受信したバイト列をログに出すようにしたのだけど、シーケンスと同じだった。
シーケンス表の上から6行目の「(はい、これ~)」を送信しているところで、AndroidがDeactivateしている。

うーん、やっぱり、意味がわかってデータを送信していないので、なぜだめなのかがわからん。

2013/12/17

[nfc]HCEの動作確認をしたい (3)

さて、前回はNexus7でHCEが動いているので動作が少し違うという確認をした。
まだHCEっぽい動きはさせていないのだが、HCEサンプルの有無でPaSoRiの取得するSAK(SEL_RES)が変わったので、Android BeamではなくHCEが動いていると考えてよいだろう。

少し気になるのは、画面消灯時は動作せず、ロック画面だと動作するという動きについてだ。
Android Developerに説明がある。

  • スクリーンがオフになったら、アプリのNFC制御は止める。HCEも同じ。
  • HCEサービスは、ロックスクリーンでも動作できる。
    android:requireDeviceUnlockという属性で制御できる。
    デフォルトでは、デバイスのアンロックは不要でサービスは動く。
  • requireDeviceUnlockをtrueにすると、アンロックさせないとかざしてもHCEサービスは動かず、Androidがユーザにプロンプトを出す。

ということのようだ。
この動作は、私の確認した動作と一致している。
画面が消灯していると、HCEサンプルを動かしていても反応しないのだ。

HCEサンプルでは、requireDeviceUnlockはfalse(デフォルト値と同じ)になっている。
でも、trueだったとしても、動きは同じになるだろう。
なぜなら、Androidがプロンプトを出すかどうかは、AIDが動いているHCEアプリたちと一致するかどうかを判断してからになるからだ。

 

まだ、その部分まで受け側のアプリを作り込んでいないから、ダイアログが出るところを確認できない。
Android4.4 + enableReaderMode()で試すのが手っ取り早いのだろうが、手元に端末がない。
それに、せっかくならPaSoRiを使っておきたいのだよ、私は。
(RC-S390のSDKが一般向けに出ないかな、ぶつぶつ)。

2013/12/16

[nfc]HCEの動作確認をしたい (2)

前回、PaSoRi + NFC Starter KitでNFC-Aの応答部分で捉まえるようにして、HCEサンプルを動かしたNexus7(2013)をかざしてみたが、HCEサンプルがあってもなくてもブレークポイントに止まる、という話をした。

でも、ね。
実は違いがあるのだ。
それは、ロック画面での動作である。

ご存じの通り、Androidではロック画面中はSNEPなどをしないようになっている。
HCEサンプルを入れない状態だと、Nexus7をPaSoRiにかざしても何もならない。
が、HCEサンプルを入れた状態だと、かざすとブレークポイントに止まるのだ!

そのときのSEL_RESは、0x20。
NFC-DEP/LLCP/SNEPしてるときは、0x60。
b7~b0という表現をすれば、SAKのb6=1になってるかどうかの違いみたいだ。

SAKのビット割り当てがどうなっているかというと、これはNXPの資料がよいだろう。
AN10833[pdf]のp.10に、SAKのビットについて記載がある。

image

こちらの表は、b8~b1の割り当てだが、見る箇所はわかるだろう。
b7=1、b3=0であれば、ISO 18092なのだ。

すっきりした。

2013/12/15

[nfc]HCEの動作確認をしたい (1)

AndroidのHCEだが、サンプル通りに作ったり、ネットで見た通りに作ったりしているが、とにかく動作確認ができない。
ブライテクノBlogさんの記事を見ると、もう1台Android4.4の端末を用意して、Android Beamを無効にするAPIがあるので、それを使ってR/Wにすればよいよ、とある。
hiero_adgjmptwさんのスライドもあり、これを見ればAndroid側は間違えずに済むだろう。
ではやってみよう、と思ったのだが、今月は私の手元にNexus7(2013)が1台だけしかないことを忘れていた・・・。

あきらめるのもなんだし、そもそもうちにはPaSoRiという立派なR/Wがあるのだ。
これを使わない手はなかろう。


PaSoRiを使うので、Windows + SDK for NFC Starter Kitでやることにした。
Type4Aがどんなのかわからないにしても、ライブラリがうまいことやってくれるだろう。

ベースは、以前作ったライブラリで良いだろう。
https://github.com/hirokuma/NfcStarterKitWrap
いくらType4Aといえども、元はNFC-Aだ。
ポーリング動作については変わらないはず。

C#で新規プロジェクトを作り、追加で既存のプロジェクトを選び、NfcStarterKitWrapを選択。
そして、参照させよう。
フォームにボタンを1つつけ、イベントハンドラを用意する。

namespace Type4Rw
{
    public partial class Type4Rw : Form
    {
        private NfcStarterKitWrap.nfc mFNS = new NfcStarterKitWrap.nfc();
        public Type4Rw()
        {
            if (!mFNS.init(this))
            {
                MessageBox.Show("SDK for NFC Starter Kit fail");
                Environment.Exit(0);
                return;
            }
            InitializeComponent();
        }
        private void buttonPolling_Click(object sender, EventArgs e)
        {
            bool b = mFNS.pollingA();
            if (b)
            {
                MessageBox.Show("OK!");
            }
        }
    }
}

そして、NfcStarterKitWrap.csのdetectNfcA()という関数があるので、ブレークポイントを張る。
最初にエラーチェックがあるので、そのあとがよいだろう。

止めようとしているのは、NFC-Aを検知したときのコールバック関数。
さて、Nexus7をかざすと止まるだろうか?・・・・止まった。

NFCID1は4byte。値はランダムっぽい。
ATSサイズは5バイトらしいのだけど、ATSって配列は1byte分しかない。値は0x05。
SEL_RESは0x60、SENS_RESは0x0400。

SENS_RESは、NFCID1のサイズなんかを表している。
SEL_RES(SAK)はかざしたタグの特徴。
昔整理した表だと、こうなっていた。

image

b5=1で、他が0なので、ISO 14443-4(RATS+PSS)、のようだ。
RATSは、Request Answer To Select Request、のことらしい。
PPSは、Protocol and Parameter Selection、のことらしい。
おっ、いったか?

いや、念のために、HCEサービスを止めて試しておかねば。
さて、かざしてみると・・・止まった(;_;)。

Android Beamを止めたとしても、LLCPとかは動いてるんだろう。
Nexus7(2012)だとNFC-FでしかLLCPなどをしていないように思っていたのだが、手元にないので自信がなくなってきた。

ともかく、R/W側ももうちょっとちゃんとType4Aとしてのシーケンスを流してやらないと、HCEが動いているかどうかの確認はできなさそうだ。
先は長いなぁ。

2013/12/08

[nfc]nfc.scサービス

最初に書いておきますが・・・1時間くらいかけて調べながら書いた後、ネットに上げようとしたら「保存できません」と言われて、泣く泣く再起動しました・・・。


nfc.scは、ブリリアントサービスさんのサービス。
ベータ版だからか、ブリリアントサービスさんのページからは飛べなかった。
NFCの開発者ブログもそうだけど、こういうのって難しいですな。
すぐに仕事と結びつくなら経費割り当てて更新するけど、会社ブログの1つとなると、効果が見えにくいし

現場の人は忙しくて更新が怠りがちになる、という。
しかも、更新する前に(きっと)文面のチェックとかもあるだろうから、その文面をチェックする人も忙しくて・・とか、なんかいろいろと想像してしまう。

でも、新しいサービスを始めたのにホームページに載ってなかったら、「あら、中で何があってるんだろう」なんてあらぬ想像をしてしまったり。

まあ、そういうのは置いておくとしよう。


さて、nfc.scのページだが・・・。
何ができるページか、まとまったところがわかりづらい。
たぶん、「開発したい」のところだろう。

FAQのページもあるのだが、NFCでできることとnfc.scでできることが混ざっている。
これは、大項目を分けた方がよいだろう。
あと、規約的なページは、それぞれ別個にしないと、利用者に嫌がられると思う。
更新日もわからないと、利用する側としては使いづらいか(利用する側は、サービス提供側のルール変更が困ると思う)。

メニューの順番も「使いたい」と「開発したい」がわかりづらいか。
だって、nfc.scは「開発者向け」と書いているのに、先に「使いたい」と書かれると誰向けなのかわからん。
βだろうとなんだろうと、使う人へはサービスを作ったサイトでやるだろうから、このページを経由するのは考えにくい。
そう思えば、「使いたい」メニューは不要なんじゃないかと思う。「開発したい」の下にぶら下げるか、メニューの順番を右にずらすか。

とにかく、nfc.scでできること、という内容がどこに書かれているかわからなかった。


大きく、提供してくれるのは2つのサービスだ。

  • アプリで使えるライブラリ(今のところAndroidのみ)
  • クラウド環境

私みたいに、アプリの実装は何とかできなくもないけど・・・という人には非常にありがたい。
NFCを使う利点は、基本的にユーザが「かざす」という操作をしたことを受け取れることだ。
画面をタップしても同じことはできるんだけど、それを「タグを読む」という動作でやることで、いくつかの制約が生まれてくる。

  • タップした端末の情報がわかる
  • 端末の位置情報がわからなくても、タグ側に位置情報があれば伝えられる

制約というか、端末の情報取得ができるって方になってしまったな。
まあ、情報抜き取りは嫌われるし、情報取得の制限はOSでできそうだけど、タグに書いてある情報を伝えるというくらいはできるだろう。
そこに、なるべく個人を絡めて、個人の情報というか、傾向的な情報を得たいところだろう。
性別、年齢、最寄り駅・・・いろいろ範囲はあるので、説明して、範囲を選んでもらえればよいのではなかろうかね。

情報の提供範囲が狭くなると、サービスの提供ができなかったり、他の人と同じサービスを受けられなかったりするだろうけど、もう、どうしようもないのではなかろうか。
自分の情報がどのくらいの価値になっているかもわかるだろうし。
「無料」ってのが、何を提供して無料になってるかは、知っておいた方がよさそうだ。


便利そうではあるが、どうしたらよいのか、というのが今のところの印象だ。
クラウドとかに詳しければ使ってみるかもしれんが、使う側としてはライブラリがあったとしても、その前にドキュメントがないと使うのが怖いのかも。

やはり、1つ実例を挙げた方が良いのかも。

[ble]iPad mini oldとNexus7 2013のCONNECT_REQを比較

前回、周波数ホッピングの計算について調べた。
Nexus7でキャプチャできなかったのは、このホッピングがアルゴリズム通りになっていないからではないか?という推測があるんだけど、どうなんだろう。

まずは、チャンネルマップを取得するCONNECT_REQを見比べよう。

iPad mini old
image_thumb[5]

Nexus7 2013 (WiFiあり)
image

Nexus7 2013 (WiFiなし)
image

WiFiの有無でHopが違う!と思ったが、どうもランダムっぽい。
Core_V4.0 p.2207によると、5~16のランダム値とのこと。

とりあえず、チャンネルマップは違うようだ。
これはAPIレベルなのか、OSレベルなのか・・・。
あまりアプリで意識するものでもなさそうだから、OSというかドライバというか、その辺でやってるんじゃなかろうかね(調べてない)。

あと、タイムアウトってのも違うみたいだ。
iOSは720msで、Androidは7000ms。
これがconnSupervisionTimeoutで、教えてもらったところでは「切断と判断する時間」らしい。


Androidがunusedにしているチャネルも調べておこう。
9~18chに相当するはずなので、2422~2438MHz(2426MHzはAdvertisingの38ch)。
さて、ここに何があるのか・・・。

いろんなものとぶつかっているので、今さらそこだけ避ける具体的な理由が思い当たらん。
通常のBluetoothとかかなぁ・・・。

http://www.ekouhou.net/%E5%91%A8%E6%B3%A2%E6%95%B0%E3%82%92%E9%81%B8%E6%8A%9E%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E5%8F%8A%E3%81%B3%E6%96%B9%E6%B3%95/disp-A,2012-530455.html

 

なんにせよ、キャプチャできないんだから、アルゴリズム通りになってないかどうかって判断できないんだな・・・。

[ble]BLEのホッピング

Bluetoothは、1つの周波数を使って通信するのではなく、ある程度の範囲の周波数をチャネルに区切り、動的にチャネルを切り替えながら通信を行うらしい。
これを「ホッピング」などと呼ぶそうだ。
あまりわかっていないので、調べておこう。

Core_V4.1[pdf]が出てるけど・・・まだCore_V4.0[pdf]の資料で見ていきます。


BLEは、チャネルが40(0~39)ある。
そのうち、37, 38, 39chはAdvertising専用。
残りの0~36chがデータ通信用。

image

(Core_V4.0[pdf] p.2199)

RFのチャネル番号と、Data/Advertisingのチャネル番号は異なるようだ。
以下は、Data/Advertisingのチャネル番号で表現しよう。

 

PDUの種類も、Advertising channel用とData channel用の2種類に分かれている。
今回調べたいものは通信中だから、Data channel用のPDUになる。


channel selection algorithm

image

(Core_V4.0 p.2239)

 

image

(Core_V4.0 p.2212)

 

Data channelは37個あるが、それは状態を持っているようだ。
状態のテーブルがあって、"used"とか"unused"とかが割り当てられている感じがする。
次に使うチャネル番号を決めるときは"unused"となっているものの中から選んでいくけど、37回やると全部"used"になってしまうから、計算式で計算されたチャネル番号の状態を"unused"に戻していく。
それを「channel selection algorithm」と呼んでいるのだろう。

channelについては、「4.5.8.1 Channel Classification」に説明があった。
Data channelは「used channels」(used for the connection)と「unused channels」(not used for the connection)があり、これを「channel map」と呼んでいるそうだ。
used=使ってよい、unused=使うな、という意味か。
そして、used channelsの最小数は2、とある。つまり、最低でも2ch分は空いていないといかんということか。

このmap情報は、Link層が管理していて、masterが用意し、slaveはそれを受けとって使うそうだ。
最初は、CONNECT_REQ PDUに載せ、変更するときはLL_CHANNEL_MAP_REQ PDUを使うみたい。

 

数式としては以下の2つだけだ。

unmappedChannel = (lastUnmappedChannel + hopIncrement) % 37  ... (1)
remappingIndex = unmappedChannel % numUsedChannels ... (2)

"unmappedChannel"は、現在のところ未割り当てになってるチャネル番号。
上記の計算で、次に未割り当てにするチャネル番号を決める。
"lastUnmappedChannel"は、文字通り、最後に「unmapped」にしたチャネル番号で、最初は0。

1イベントが終わったら、式(1)でunmappedChannelを計算する。
unmappedChannelの状態が"used"だったら、そのチャネル番号をData channelとして使う。
状態が"unused"だったら、式(2)でremappingIndexを計算。

この"remappingIndex"は状態のテーブルとは別で、"used"になってるチャネル番号のものを集めたテーブル用の番号だ。
そのテーブルからremappingIndexのところにあるチャネル番号をData channelとして使うことになる。

 

訳してみたが、あってるだろうか?
実際に計算してみよう。
37チャネルでやると大変だから、5チャネルにしてやってみるか。
hopIncrement=1にしておこう。

mapped 0 1 2 3 4
state used used unused unused used

まず、最初はlastUnmappedChannelが0なので、0chを使う。

mapped 0 1 2 3 4
state used used unused unused used

0chが終わったので、計算。

unmappedChannel = (0 + 1) % 5 = 1

次は1chを使う。

mapped 0 1 2 3 4
state used used unused unused used

1chが終わったので、計算。

unmappedChannel = (1 + 1) % 5 = 2

あら大変、2chは「unused」だ。
このときは式(2)を使う。

remappingIndex = 2 % 3 = 2

remap 0 1 2
ch 0ch 1ch 4ch

remappingテーブルの2番目は4chなので、次は4chを使う。

mapped 0 1 2 3 4
state used used unused unused used

4chが終わったので、計算。

unmappedChannel = (4 + 1) % 5 = 0

また0chに戻る。


そんなわけで、ホッピングするチャネルを知るためには、masterからslaveに渡されるチャネルマップとhopIncrementを取得すれば良いことになる。

CONNECT_REQ PDUなるものがあるらしいので、見ておこう。
これは接続時のものなので、Advertising用のPDUだ。

image

(Core_V4.0 p.2206)

image

(Core_V4.0 p.2207)

ここの、ChMとHopがそうだ。
5octで40bitだから、それぞれに1/0を立てていくんだろう。

では、SensorTagで実際にキャプチャしてみよう(iPad mini old)。


image

最初が1Fだから、3bit分抜かれている。Advertising用だろうな。
37~39chなので一番最後だが、Bluetoothは並びがLittle Endianだから、先頭のb7~5ビットに0が入っているのだろう。
hopIncrementは8。

image

8 --> 16 --> 24 --> 32、ときて、次は40だけど37でmoduloして余りが3だから、3ch。

うん、解釈は間違ってないようだ。

[ble]WiFiを切ったらキャプチャできたが、納得できん

前回の続き。
SensorTagとNexus7間の通信をうまくキャプチャできない件について。
結果として、できるようになったみたいだ。

 

構成

 

現象

  • SensorTagとNexus7間は、うまくいってるようだ
  • BLE Snifferのキャプチャが、途中で止まる
    • Advertisingは取れている
    • connectすると、しばらく取れている
    • 数秒以内に正常なキャプチャができなくなる。取れるのはエラーのときだけ。

 

というわけだ。
iPad mini oldのときは問題ないので???だ。

 

どうにもわからんかったので、FacebookのWF-BTLEというグループに聞いた。
いくつか推測してもらって、その中に「AndroidのWiFiが邪魔してるのでは?」というのがあった。
まさかそんなことがねぇ、などと疑いつつもやってみると・・・取れるじゃないの奥さん

詳しい人だなあ、と思って見てみると、http://reinforce-lab.github.io/の人だった。
なるほど。


じゃあ、iPad mini oldでうまくキャプチャできているところにNexus7を近づけたら同じ現象が起きるはず、とやってみたが、こいつはうまくいっている。
うーん、これはこれで納得がいかない。

教えてもらったところでは、L2CAPで使えないチャネルをスキップするという情報交換ができるらしい。
それが機能していて、CC2540Dongleもそれを使っているのかいな。
Androidではそれを無視して送るとか・・・でもアプリは取れてるし・・・。

スニファがBLEで使うチャネルを同時にすべてスキャンできてキャプチャするなら関係ないんだろうけど、たぶんそんなことはできないだろうから、そういう推測になるかなあ。
もしできるんなら、Advertisingだけ取れて、connectしたら3分の1の確率でしか取得できない、なんてことはないはずだ。

 

では、次に調べるのは、BLEがどうやってホッピングしているか、というところだろう。
次はこのチャネル使います、という指定をしないと、うまく取得できないはずだ。

2013/12/05

[ble]うまくキャプチャできてない

眠たいので、画像だけ。

iOS(iPad mini old)とSensorTag

image

image

image

ちょっと乱れてるけど、だいたい取れてそうだ。

 

Android(Nexus7 2013)とSensorTag

image

image

image

まともそうに見えるが、最後はぐちゃぐちゃだ。
画面左下にパケット数が出ているが、AndroidはぐちゃぐちゃになってからはCRCエラー時のパケットしか出てこず、パケット数はあまり増えていかない。
iOSだと、順調に増えている。

うーん、この違いは何だ?

ちなみに、Android/iOSで動かしているアプリは、どちらもTIから取ってきたものだ。
だから、作りに違いがあるとはあまり考えにくい。

パケットの取りこぼしも考えたが、Advertisingのときは普通に取れてるから、考えづらいと思う。
まあ、ドングル側の作りがあまりよくない、とかもあるかもしれないけど、それならiOSだって同じ現象が起きてよさそうだ。

ってことは、何か別の理由があるのだろうけど、それっぽい説明が思いつかない。

2013/12/01

[ble]Androidでアプリを動かすとsnifferがうまくいかない

わからんシリーズだ。

TIのBLE SmartRF Sniffer(名前はうろ覚え)を使ってパケットキャプチャをしようとしている。
Androidの方が慣れているから、Androidにアプリを入れて、SensorTagとの通信をキャプチャしようとしていたのだが、うまくいかない。

  • Advertisingまでは取れるが、connectすると止まる。
  • connectしても続いているが、少しするとホッピングするチャネルがぐちゃぐちゃになって、止まる。

だいたいこのどちらかだ。
iPad miniと通信した場合は、そんなことはなさそうな感じがする。
SensorTagは違いが無いから、OSの差なのか?

とはいえ、どちらもアプリとしてはちゃんと動いているのだ。
うーん、訳がわからん。。。

これで「PCの性能があまりよくないから」とかだと、嫌だなぁ。

[ble][st]SensorTagのデータの見方

SensorTagのデータをBLE Snifferで見ると、こんな感じで出てくる。

image

Data Typeが「Empty PDU」なものの中に、ときどきそれ以外のものが出てくる。
「L2CAP-S」となっているものが、だいたいデータっぽい。

前半のデータは、あんまり気にしなくてよさそうだ。
DirectionはSlaveからMasterへ。つまりSensorTagが送ってきているデータだ。
image

真ん中が、本体。
image

OpCode 0x1Bは、Notificationとして送信された値という意味。image

0x004Bは、ハンドル。
これは、SensorTAgのGATT一覧表[pdf]に載っている。
image

温度=0xf615、気圧=0x8d49、でよいのかな?
センサの値をそのまま送ってるだけだろうから、各センサのデータシートを読まないと変換できん。
ちなみに、パケットの生データはこんな感じだ。

2F AD 9A AF 0A 0B 07 00 04 00 1B 4B 00 15 F6 49 8D 56 DC 8E


では、Androidのソースを少し見ておこうかね。
ここに一覧があるけど・・・なんでWindows版とかLinux版にわかれてるんだ?
あ、インストーラだ・・・。
Windows版をダウンロードしたのに、中にはexeとtarが入ってて、tarを解凍するとLinux版のインストーラらしきものが入っていた。
ナンダコレハ。。。

Windowsのインストーラを起動すると、勝手にフォルダ掘ってファイルコピーしやがった。
しかも、Androidのプロジェクトzipだし。
インストーラじゃなくていいやん!
腹が立ったので、zipとpdfだけコピーしてアンインストールした(pdfはライセンスの説明だけみたい)。

[ble]TIのSmartRF Packet Sniffer BLEはトリガとしてAdvertisingがいる?

BLE Device Monitorはあきらめ、素直にSnifferアプリを使うことにした。

http://processors.wiki.ti.com/index.php/BLE_sniffer_guide

SmartTagがiOSアプリと通信している様子を見てみようとしたのだが、何も出てこない。
アプリには刻々とデータが表示されているので、通信していないはずはない。
なのにー、なーぜー・・・。

SmartTagの横が電源ONみたいなものなのだが、押すと出てくる。
では、とモニタを止めて、また再開させると、やはり出てこない。
ADV_CONNECT_REQに書いてあるInitAを打ち込んでみたが、それでも出てこない。

ということは、モニタの開始トリガとしてAdvertisingを捉まえる必要があると言うことかな?

Advertising Channelを38にしてやってみたが、やはりボタンを押す必要があった。
ボタンさえ押せば、Channelの設定には関係なくパケットが見えるようである。
ってことは、Radio Configurationはあまり気にしなくてもよさそうだ(いまのところ)。

 

・・・と思ったけど、ときどきボタンを押してもすぐに終わってしまうことがある。
うーん、よくわからん。

CRCエラーが結構発生しているが、これはスニファが拾いきれなかったとかかな。

[ble]TI SensorTagの情報を集めよう

集めよう。
SensorTagに紙が入ってて、そこにURLが書いてあるんだけど、打ってもつながらない・・・。

とりあえず、ここから。
http://www.tij.co.jp/ww/wireless_connectivity/sensortag/index.shtml?DCMP=advertorial201309&HQS=SensorTag-bs-tech-adv-jp

iOSとかAndroidとかのソースがダウンロードできる。
AppStoreからインストールしたんだけど、OADファイルでFWアップデートできるってでてきた。
なんだ、それは?
http://www.ti.com/tool/sensortag-sw

 

BLE Device Monitorなるものがあるらしい。
USBドングルがいるって書いてあるが、今回買ったやつでいいのかな。
http://processors.wiki.ti.com/index.php/BLE_Device_Monitor_User_Guide

と思ってやってみたが、COMポートで接続するらしい。
説明を見ると、ドングルを挿すとCOMポートが見えるはずだから・・・とあるんだけど、私のところはCebal controlled devicesとして見えている。
うーむ。

http://e2e.ti.com/support/low_power_rf/f/538/t/163044.aspx
どうも、デフォルトではスニファ用のファームが焼いてあるから、焼き変えろってことらしい。
で、その方法は・・・?
CC-Debuggerなるものがいるんか・・・。
開発キットで買うとついてきたんだけど、そうしなかったからな。

 

知識が乏しい私としては、BLE Device Monitorの方が楽そうなのだが、仕方ない。
新しく買われる方は、ファームウェア開発するしないだけじゃなく、BLE Monitor用のファームを使いたいかどうかも考えてから買った方がよいでしょうな。

[ble]CC2541 SensorTagとCC2540EMK-USBが届いた

BLEをRC-S390だけで調べるのは難しいと思ったので、仕様がわかるキットを買うことにした。
TIのCC2541 SensorTagが安いということだったので、それを1つ。
あと、BLEのパケットを読むのに使えるというCC2540EMK-USBを1つ。

DigiKeyで28日に注文したのに、30日にはもう届いていた!
そ、そんなに早いのか??
1ヶ月くらいかかるイメージだったので、びっくりだ。

image

image

上の写真がSensorTagだが、同封の紙に「技適に通ってない」と書かれている。
が、心配しなくてもよい。
これについては、こちらが詳しい(というよりは、これを読んだので買った)。
http://xiangcai.at.webry.info/201311/article_8.html

念のため、基板に書いてある番号で検索した。
適合した機器の検索サイトに出てきたんだから、大丈夫だ。
http://www.tele.soumu.go.jp/giteki/SearchServlet?pageID=jg01_01&PC=007&TC=N&PK=1&FN=349ul&SN=%94%46%8F%D8&LN=6&R1=*****&R2=*****

電脳羊さんのサイトで、基板をケースに入れるときに「爪を折らないように」と書いてあるが、やってみて、確かに折りそうになった。
透明なふたがあるんだけど、なんか引っかかるようにできていて、かぱっとはいかないのだ。


CC2540EMK-USBは、TIの開発キットを買うとそっちにもついてくる。
なのに入っていない方を買ったのは、開発キットの方はチップ側のソフトを焼き込まないといかんらしく、それにはIARの開発環境しかない、ということだった。
30日までは無料なんだけど、そっから先は買わんといかんらしい。
制限無く無料の方はリンクサイズに制限がかかるらしく、それではBLEのライブラリが載らないんだとか。
http://vibrosoft.net/archives/56

ソフトは、こちらからダウンロード。
http://www.ti.com/tool/packet-sniffer

インストールして、EMKをPCに挿して、アプリ起動。
選択ダイアログが出てきた。

image

 

Startを押すと、取得画面らしきものが開く。
三角の再生ボタンっぽいものをクリックすると、おお、なんか取得してるみたいだ。

image

SensorTagの電池を抜いても何か取得してるのであせったが、RC-S390の電源が入っていたようだ。
RC-S390のボタンを2秒押しして、LEDが1秒点灯したら電源OFFだ。
そうやって電源を全部落とすと、ログを取得しなくなった。

さて、ようやくデータを見ながらの勉強ができそうだ。

オライリーさんからNFC HACKSが出た

http://www.oreilly.co.jp/books/9784873116242/

オライリーさんから、NFCの本が出た。
私が持っている「HACKS」シリーズは、BINARY HACKSだけだった。
が、今回、ちょっとだけレビューさせていただいたので、NFC HACKSを寄贈いただいたのだ!
わーい。
「hiro99ma」が初めて活字化された本としてプレミアが出るに違いない(出ません)。
まあ、私が書いたものは何もないんですけどね。。。

書いた人の一人(Atelier NODOKA)
http://www.atelier-nodoka.net/2013/11/oreilly-nfc-hacks/

レビュー記事(明日の鍵)
http://blog.tomorrowkey.jp/2013-11-27/review-of-nfc-hacks/


うちのサイトをNFC観点で見ていくとわかるのかもしれないが、基本的に興味があるのは「作り方」の部分。
仕様書から仕様を把握して、それを実装に落とす、というところまでが好きなようだ。

そんな私が興味を持ったのは、第2章。
特に、Type4とかISO-DEPには注目せざるを得ない。
そう、HCEがあるからだ。

HCEでできるのは、Type1でも2でも3でもなく、4らしいではないか。
Type2と3は日本でもよく使われるから解説記事があるけど、Type1と4はあまり例がないためか情報を見たことがない。
それが日本語で読めるのは非常にありがたい。
いや、NFC Forumからドキュメントは出てるんだけど、知ってる言語で書かれてる方が何かと、ねぇ。

 

また、DEP/LLCP/SNEPが載っているのも見逃せない。
DEPも、LLCPで使うNFC-DEPだけじゃなく、Type4で使う(と思ってるけど)ISO-DEPのことも書かれている。
NFC-DEPはISO/IEC-18092に載っていて、それはECMAからダウンロードもできるので無料で情報が得られるけど、ISO-DEPはISO/IEC-14443で、これはまだダウンロードできる仕様書を見つけられていない(あやしいのはあったけど)。
Androidでアプリを作るだけであれば意識しなくてもよいかもしれないが、とはいえAndroid APIにはIsoDepもあるので知っておいて損はないんじゃなかろうか。

 

まあ「アプリ作るだけならそこまで知らなくても」というのはあるかもしれないが、技術屋さんとしては訳がわからないものは気持ちがわるいではないか。
そこら辺がすっきりできるであろう(個人の感想です)。


AndroidとWindows NFP, PC/SCのことも書かれている。

まだAndroid 4.4が出る前なのでHCEのことは書かれていない。
が、それを待っていたらキクニさんの雨宿りしている人のマンガじゃないけど、いつまで経っても出せなくなるからな。

ただ、Secure Elementについては実装から追っていった情報が載っている(HCEはSecure Elementを使わない)。
SEは私は操作できないから興味が無いのだけど、仕事でやらんといかん人もおるかもしれん。
FeliCaもSIMベースに移行する予定だったと思うので、「Androidで国内端末だから関係ないや」という人もぼちぼち読んでいった方がよいかもしれませんな。

Androidアプリに詳しくはないが、NDEFの読み書きやAndroid Beamなどの基本機能の使い方(=実装の仕方)が書かれている。
NFCといえばAndroid端末、って気がするので一番ページ数が多いと思うかもしれないが、実は一番ページが多いのは2章の規格説明だったりする。

 

WindowsはNFPがWindows8から使えるので情報がよく出ているけど、PC/SCは縁遠かった。
が、AndroidでHCEが出てきてType4の振る舞いをする(らしい)となったとき、APDUなるものでアクセスする関係から、PC/SCの方も調べることがあった。
まあ、まだうまくはできてないんだけど、この本に例があるので、足がかりに読んでみようと思う。


ページ数は少ないが、5章のNFC応用サービスは興味深い。
私なんかは自分で作って満足するだけなんだけど、サービスに昇華させろ、といわれたら非常に困る。
考慮する点がわからんからだ。

この章は「セキュリティに配慮した」というタイトルにもあるように、NFCが持つ情報として考慮すべき事が書かれている。
これだけ押さえてれば大丈夫、というのはサービス内容によって変わるため無理だけど、書かれていることと照らし合わせながら、やりたいこととやれること/やらない方がいいことを洗い出していくといいんじゃなかろうか。


私は仕事でNFCしてるわけじゃないのだが、2年くらい細々と調べていたのでおおよそのことは知ってるつもりだったけど、いやあ、まだまだですわ。
でも、よくわからないときはこの本を見ればいいや、という使い方ができそうだ。

 

NFCって、それなりに特殊な分野だと思う。
通信して、メモリ持ってて、超近距離で、セキュリティも持ってて、とサービスにマッチしなければ使い道がないってくらい特殊だ。 
なので、「NFC使って何かやろう!」ってよりは「サービスを考えた結果、NFCってのが使えそうだ」というパターンが多いんじゃなかろうか。
そう考えると、NFC技術者って必要になってから生み出されることになりそう。
そういう人が「仕事でNFCってのをやらんといかんのだけど、何したらいいんだ?」という状況になったときには最適だろう。

また、今のうちにNFC技術者になっておけば、『お客様の中にNFC技術者の方は…』という状況の時に手を挙げられることになる。
なるのか・・・?
まあ、NFCやろうっていうときに、やったことある人とない人だったら、ある人を選ぶな。
そういう人になりたいときにも、よいかな。