2016/08/27

[nfc]iPhoneに載るのか?

前に、NFC Forumの記事を読んで、iPhoneにFeliCaってのは考えづらいよなぁ、という感想で終わらせた。
hiro99ma blog: [nfc]NFC Forumジャパンミーティングの記事がよくわからん

 

が、最近、こういう記事がちらほら見られた。

iPhoneがおサイフケータイ(FeliCa) に対応か。Apple Payが間もなく日本上陸 - Engadget Japanese

ほう。
もし載るのだったら、ジャパンミーティングの報告よりもずいぶん前から話が進んでいたのだろう。

 

ただまあ、こういうのは、蓋を開けるまでわからないからねぇ。。。
とりあえず私は懐疑派で、もし出てきたら「やっぱり勘が外れたのかぁ」と思うことにしよう。

RC-S390もそうだし、wenaもそうなのだけど、iOSがけっこう優先されているな、と思ったのだ。
優先されているというか、AndroidでもできそうなのにiOSしか対応していないな、と。
まあ、関係あるのか知らんけどね。


もし載せるのだったら、今と同じ、オンボードでチップを載せることになるのかな。
モバイルFeliCaチップと、あとはメモリとアンテナか。

カード型は読み取られるだけだから電源はいらないけど、モバイル型はチップを動かすので電源がいる。
詳しくないけど、R/W機能がないなら、出力はそこまでがんばらなくても良さそうだから、今のままでよいのかな?
そして、チャージをアプリから行うしくみがいるので、そういうSDKも販売していたと思う。
ハードの改造もいるし、アプリの開発もいるのだ。

 

新しく電子マネーを携帯端末で使えるようにしようとしたら、そういう端末側だけじゃなくて、店舗で読み取ってもらうR/W作ったり配布したり、サーバだとかセキュリティとか、たぶんうじゃうじゃやることがあるのだろう。
そういうのは大変なので、あまりやっているところがないのだと思う。

そこら辺を、もし海外の業者がやるんだったらどうなるのか、という一例として見るのが面白いのかもしれんです。

2016/08/26

[c/c++]私のC言語 (6) - 整形

C言語は、書き方が自由だ。
スペースだったりタブだったり、改行を入れたり入れなかったり。
インデントだって、けっこう人それぞれだ。

それはそれでよいと思うのだが、自分のスタイルじゃないソースコードを読むのは、けっこう苦痛である。
そういうとき、整形ツールで整形させるとよいだろう。

私は、これを使っている。
http://astyle.sourceforge.net/

 

たとえば、括弧の位置については、こういうオプションがある。
http://astyle.sourceforge.net/astyle.html#_Bracket_Style_Options
私はk&rかなぁ、と思ったが、stroustrupとの違いは何だろう?
namespaceやclassはk&rでは対象外と言うことかな。

1行でも括弧を付けてほしいので、これをつける。
http://astyle.sourceforge.net/astyle.html#_add-brackets

スペースかハードタブかは、お好みだな。
私の最近の流行りは、スペースだ。
http://astyle.sourceforge.net/astyle.html#_Tab_Options

2016/08/25

[c/c++]私のC言語 (5) - FFF

私は、だいたい実装するとユニットテストをしている。

実機ではなかなか通しにくいルートだけど、通ったときの動作は見ておきたい、という場合によいし、コードを書き換えた後でテストを通し、前との違いを比較する場合にも良い。

テストを作るのは面倒で時間はかかるのだが、自分の書いたものが期待通りかどうかを知るためにもやっておきたいものだ。

gccはカバレッジを取るためのビルドができるので、通ったことがないかどうかを目視しやすい。
一度通ったルートはカウントアップされるだけなので、このときにここを通った、というのには向かないのだが、それを知りたければ1つだけテストを書いて実行すれば良いだけだ。


意図通りのルートを通したいとなると、標準関数やドライバも意図通りの値を返してほしい。
が、それは難しいので、スタブやらモックやらを作る。
私は、それをFFFというフレームワークを使ってやっている。

meekrosoft/fff: A testing micro framework for creating function test doubles

検索して探すときは「fff fake」などで出てくるだろう。
使っている人の例もあるので、そっちの方がわかりやすいかも。

 


まず、githubからcloneしよう。
今の最新は3cd33edだ。
私の環境は、cygwinである。

こんなソースを書いたとしよう。
ソースファイルべた書きで済まぬ。。。

my_open(), my_close(), my_access()の3つがある。
my_open()とmy_close()UARTのオープン/クローズのイメージ。
my_access()は、コマンドを送信するとレスポンスが返ってくるデバイスがつながっていて、1回のコマンド送信に対してレスポンスを2回に分けてチェックしながら受信する、という想定だ。
ファイルディスクリプタは、static変数sfdで保持しておく。


#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

static int sfd = -1;

int my_open(const char *pTty)
{
    if (sfd != -1) {
        return -100;
    }

    int fd = open(pTty, O_RDWR);
    if (fd == -1) {
        return -1;
    }
    sfd = fd;
    return sfd;
}

void my_close(void)
{
    close(sfd);
    sfd = -1;
}

int my_access(void)
{
    const uint8_t WRT[] = { 0x00, 0x01, 0x02, 0x03, 0x04 };

    uint8_t buf[20];
    ssize_t sz;
   
    sz = write(sfd, WRT, sizeof(WRT));
    if (sz != sizeof(WRT)) {
        return -2;
    }

    sz = read(sfd, buf, 5);
    if ((sz != 5) || (buf[4] != 0xff)) {
        return -3;
    }
    sz = read(sfd, &buf[5], 3);
    if ((sz != 3) || (buf[7] != 0x35)) {
        return -4;
    }

    return 0;
}


まず、my_open()のテストをするとしよう。

最初にsfdが-1以外かどうかをチェックして、オープン済みなら終わらせる。
次にopen()を呼んで、戻り値が-1だったら、エラーとして終わる。
それ以外なら、sfdに保存して終わる。

というわけで、ここでやりたいのは、

  • sfdを-1以外にして、-100が返ってくるのを確認する
  • sfdを-1にして、open()が-1を返すようにし、-1が返ってくるのを確認する
  • sfdを-1にして、open()が-1以外を返すようにし、その値が返ってくるのを確認する

という3つだ。
これを、FFFを使ったテストコードにすると、こうなる。

TEST_F(test, open_1)
{
    sfd = 3;

    int fd = my_open("/dev/ttyS1");

    ASSERT_EQ(-100, fd);
}

TEST_F(test, open_2)
{
    sfd = -1;

    open_fake.return_val = -1;

    int fd = my_open("/dev/ttyS1");

    ASSERT_EQ(-1, fd);
}

TEST_F(test, open_3)
{
    sfd = -1;

    open_fake.return_val = 5;

    int fd = my_open("/dev/ttyS1");

    ASSERT_EQ(5, fd);
}

長くなるので省略しているが、これよりも前の部分がある。
実はそこで、テスト対象のソースファイルをincludeしている。
だから、直接sfdが扱えるのだ。
なんとなく邪道じゃろう?
でも、楽なのだよ。

open_fake.return_val、というのは、関数をモック化する手続きをしておくと、<関数名>_fakeという構造体ができるようになっていて、そのreturn_valという変数だ。
これに値を入れておくと、その値が戻り値になってくれる。

ASSERT_EQ()は、FFFではなくGoogle Testが提供するものだ。
FFFはGoogle Testと併用しやすくなっている。


では、my_access()みたいにread()を何度も呼び出すタイプはどうするか?
いくつかやりかたはあるのだが、戻り値も変える、引数で返す値も返るとなると、自分でモックを定義した方が簡単だと思っている。

たとえば、戻り値が0になるテストだと、こういう感じだ。

TEST_F(test, access_1)
{
    sfd = 5;

    class dummy {
    public:
        static ssize_t read(int fd, void *p, size_t sz) {
            static int count = 0;
            int ret = -1;
            uint8_t* buf = (uint8_t *)p;
            switch (count) {
            case 0:
                ret = 5;
                buf[4] = 0xff;
                break;
            case 1:
                ret = 3;
                buf[2] = 0x35;
                break;
            default:
                assert(0);
            }
            count++;
            return ret;
        }
    };

    write_fake.return_val = 5;
    read_fake.custom_fake = dummy::read;

    int ret = my_access();

    ASSERT_EQ(0, ret);
}

read_fake.custom_fakeはデフォルトがNULLで、その場合はreturn_valの値を返す(配列で順番に値を返してもらうようにもできる)。
設定すると、その関数が呼ばれる。

今回は、dummyクラスのread()を呼ぶようにしている。
普通の関数にしても良いのだが、テストごとに定義していると名前の重複が発生して面倒になりそうだから、こういう形にしている。


今回作ったものは、ここに置いた。
https://github.com/hirokuma/fff_examples

作ったのは、func., test_func.cppと、Makefileをいじっただけだ。
それ以外のものは、FFFからコピーしただけである。

慣れるまでは使いづらいかもしれないが、いくつか作って自分の作り方を蓄積させておくと、だんだん楽になっていくかもしれない。

[nrf52]大きいNDEFデータにすると不安定だ

nRF52832は、Type2 Tagとして動作することができる。

Type2 Tagとは、MIFARE Ultralightみたいなやつだ。
以下、ULと略す。
ちなみに、Ultralight Cというのもあって、そっちはセキュリティ機能があるらしい。
NXPに申請しないと資料をもらえないようなので、詳しくは知らない。

 

サンプルを動かして、AndroidアプリのNXP TagInfoで読み取った方はわかるだろうが、普通のタグに比べると読み取りに時間がかなりかかる。
これはタグのエミュレーションに時間がかかっているわけではなく、データが多いためだ。

たとえば、よく見かけるNTAG203では48ブロック分しかないのだが、nRF52832のnRF5 SDK v11.0.0では256ブロック分あるのだ。
1ブロック4バイトなので、1KB。

このサイズは、タグとしてはなかなかない。
MIFARE Classicは、1Kとか4Kとかが普通だったけど、Type2 Tagなんかは小さいものが多いのだ。

まあ、通常は使うブロックだけ読めばよいので、使い勝手に違いはないだろう。


せっかく大きいデータが使えるので、大きいデータを流してみよう。
大きいデータと言えば、やはり画像だろう。
PNGデータを作って、TNF=0x02、MediaTypeがimage/pngのNDEFデータを作ってみた。

が・・・Androidで読ませても、なんか毎回データが違う。

不安定なのか?と思い、Windows10 + PaSoRiで読込ませた。
幸いWindows10はNDEFを解釈してくれるので、画像ファイルとして保存してくれた。

が・・・。
こちらも、毎回結果が違う。

image

原因がどこら辺にあるのかはわからないけど、大きいデータは使わない方がよいということはわかった。

2016/08/24

[nrf52]Android 7じゃないとNFCペアリングはうまくいかないの?

Nordicブログには珍しく、新しいAndroidのことが記事になっていた。
うちのNexus5は対象から外れたらしいのだが、7用のドライバだけでも提供してくれたら自分でビルドして遊んでみるのだけどなぁ。

nRF52832 and Android Nougat – simple and secure touch-to-pair.

英語なので読み飛ばそうと思ったのだが、気になる一文を見つけた。

support for Bluetooth pairing with NFC using the out-of-band (OOB) method is included.

んん??
もうちょっと読んでみた。

In fact, we have had examples to do NFC pairing using the OOB method in our nRF5 SDK for quite a while and it worked with Android Nougat “out-of-the-box”.

「out of the box」は、Raspberry Piのところでも出てきたが、すぐに使える、という意味だ。
つまり、なんもせんでもAndroid 7だったらSDKに入っているNFCペアリングのサンプルが使えるよ、という意味だろう。

なんだよ、動かないってわかっていたのかよ!!

確かに、私の調べでも、Androidがタイミングを変えてくれない限りはどうしようもない、というところだったのだけど。。。
どこかで、Nexus5は対応しているような記述があったような気がしたのだが、今探しても見つからない。

うぅぅぅ。。。

 

とにかく、今までのでは動かない、というのは間違っていなかったので、それでよしとしよう。