2012/12/29

[android]Type3 Tagヘッダのソースを見たが、よくわからん

Nexus7で、FeliCa Liteに書いたNDEFメッセージが113~127byteだとNDEFデータをうまく読み込んでくれない件について、見てわかるものかどうかわからないが、とりあえずソースファイルを見てみよう。
Type3 Tagのヘッダを解析する部分だけでいいはずだ。
NDEFの解析は、きっと共通でやってるだろう。やっていてくれ。。。

 

Type3 Tagについては明日の鍵さんを参照してくだされ。
NDEFメッセージ長が関係するのは、メッセージ長を表すLnと、それによって変化するチェックサムくらいだ。


Androidでは、基本的なデータ解析をframeworksではなくexternalsにあるlibnfc-nxpで行っている。
ファイル名から予想して、external\libnfc-nxp\src\phFriNfc_FelicaMap.hから見ていこう。

 

Lnは3byteなので、これを使ってるんじゃなかろうか。

/* Macro for LEN Byte Calculation*/
#define PH_NFCFRI_NDEFMAP_FELI_CAL_LEN_BYTES(Byte1,Byte2,Byte3,DataLen)\
do\
{ \
    (DataLen) = (Byte1); \
    (DataLen) = (DataLen) << (16);\
    (DataLen) += (Byte2);\
    (DataLen) = (DataLen) << (8);\
    (DataLen) += (Byte3);\
}while(0)

どうでもいいんだけど、2行目って16じゃなくて8よね。。。

0x12, 0x34, 0x56ってデータだったら、

DataLen = 0x12;
DataLen = 0x12 << 16;  → 0x120000
Datalen += 0x34; → 0x120034
DataLen = 0x120034 << 8; → 0x12003400;
DataLen += 0x56; →0x12003456;

ってなるやん。

どうでもいいっていうのは、FeliCa Liteは256byteもデータがないので、0x00, 0x00, 0x??、という値になるから今回は関係ないや、ということである。
他の部分でも同じように書いている箇所があるが、そっちは知らない。

 

私だと

(DataLen) = ((Byte1) << 16 | (Byte2) << 8 | (Byte3));

って書くけど、なんか分けて書いた方が利点があるのかな?

 

ざっと眺めてみたけど、やっぱりよくわからんな。
ソースだけから追うのはちょっとつらい。

一応、android側(java側)も見ておくか。


NDEFメッセージがnullだ、とわかったのpackages\apps\Nfc\src\com\android\nfc\NfcDispatcher.javaの出力からだ。
dispatchTag()のLog.d()だ。

messageがnullになるのは、

  • Ndef.get(tag)がnull
  • Ndef.get(tag)は非nullで、Ndef.get(tag).getCachedNdefMessage()がnull

のどちらかだ。

やはり追うのがめんどくさいな。


それにしても・・・libnfc-nxpには無意味なマクロがあるな・・・。
さっきのマクロの上に2つ違うマクロがあるんだけど、

/* Macros to find major and minor T3T version numbers*/
#define PH_NFCFRI_NDEFMAP_FELI_GET_MAJOR_T3T_VERNO(a)\
do\
{\
    (((a) & (0xf0))>>(4))\
}while (0)
 
#define PH_NFCFRI_NDEFMAP_FELI_GET_MINOR_T3T_VERNO(a)\
do\
{\
    ((a) & (0x0f))\
}while (0)

 

do-whileで囲むのはいいんだけど、値を取得するつもりで使ったらコンパイルエラーになるやん。
まあ、誰も使ってないんだけどさ。

[nfc]AndroidはType 3 TagのNDEFメッセージが113~127byteだと認識してくれない

NDEF Writerを使って、FeliCa Liteに書き込んだ。

image

設定
・Abbreviation : https://www.
・URL : google.co.jp/
・Title : aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab
・Type : 3

 

これをうちのNexus7のTagInfoというアプリで見ると、こうなる。

image

 

Titleの、一番最後の「b」を削ったデータを書き込んだNFCカードをTagInfoで見ると、こうなる。

image

 

Current message sizeが112byteということは、"b"がついたのは113byteだろう(UTF-8だから)。
これは113~127byteまでこの状態で、128byteになると認識してくれる。

image

なんじゃこりゃ?

 

では、NTAG203というType2 Tagのカードに書いてみよう。

image

 

読める・・・。

ということは、これはType 3 Tagのヘッダ部分を解析する箇所にバグがあるんじゃないか?ということになる。

ソース見たらわかるかな?


ちなみに、AndroidアプリにあったKDDIのTag Readerで同じように113byteのSmartPosterを書き込んだが、書き込みできるけれども読み込めなかった。
やっぱり何か問題があるように思う。

2012/12/28

[nfc]NDEFクイズの続き - Android側か?

ここ数日試しているNDEFのデータがある。

私の手動解析では、問題ない。
nfcpy解析でも、問題ない。

では、Android側か?


そんなわけで、今回は別のツールを使うことにした。
こういうときは、SonyさんのNDEF Writerだ。

Androidでは、NDEFペイロードのパースはアプリがやることになっている、と先生がいっておられた。
であれば、今回の現象は私が作ったNDEFデータだけでなく、他のでも発生するはずだ。

NDEF WriterはSmartPosterのNDEFを作るWindowsアプリ(というか、AIRアプリか)。
これで、じりじりと試す。

 

FeliCa Liteで試したところ、NDEFメッセージ長(Type 3 TagのLn値)が112byteまではOK、113~127byteまでNG、128byteはOKとなった。

NDEFパーサのバグなら、Type2 Tagでも発生するだろう。
FeliCa Liteだけで発生するなら、Type3 Tagのヘッダ解析にバグがあるのか。
Nexus7などで発生してNexus10で発生しないなら、libnfc-nxpが持つバグってことになるんじゃなかろうか(たしかNexus10は、Broadcomだったかと)。

 

Type3 TagのLnは3byteのビッグエンディアンデータ。
だから、読んだときは自分でint値か何かに変換しているのだろう。

 

112    0x70    0111_0000  OK
113    0x71    0111_0001  NG
114    0x72    0111_0010  NG
・・・
126    0x7E    0111_1110  NG
127    0x7F    0111_1111  NG
128    0x80    1000_0000  OK

 

Javaは確かunsignedがないから、そこら辺でミスがあるのでは・・・と思ったが、よくわからんかった。

今日はもう眠たいし、明日は飲み会があるので頭が回らないだろうから、あとは他の人にお任せしよう・・・。

2012/12/26

[nfc]NDEFクイズの続き - nfcpy

前回、NDEFクイズと銘打って、自分で作ったNDEFデータをAndroidがNDEFとわかってくれない資料を載せた。

とはいえ、他力本願になりすぎるのも寂しい。
もうちょっと調べておこう。


使ったのは、nfcpy。
私はpythonの使い方はわからないけれども、nfcpyはなんとか使えている。
というのも、サンプルプログラムだけで十分事足りているからだ。

今回は、read_ndef.pyというサンプルを使って、NDEFデータを解析してもらうことにした。

まず、Androidで読んだ方のデータを解析する。

NDEF container present
  version   = 1.0
  writeable = yes
  capacity  = 208 byte
  data size = 113 byte
  0000: 91 02 0a 48 73 12 d1 02 04 61 63 01 01 30 00 5a ...Hs....ac..0.Z
  0010: 17 46 01 61 70 70 6c 69 63 61 74 69 6f 6e 2f 76 .F.application/v
  0020: 6e 64 2e 77 66 61 2e 77 73 63 30 44 00 10 4a 00 nd.wfa.wsc0D..J.
  0030: 01 10 10 0e 00 31 10 26 00 01 01 10 45 00 0a 31 .....1.&....E..1
  0040: 32 33 34 35 36 37 38 39 30 10 03 00 02 00 20 10 234567890..... .
  0050: 0f 00 02 00 08 10 27 00 04 31 32 33 34 10 20 00 ......'..1234. .
  0060: 06 aa bb cc dd ee ff 10 49 00 06 00 37 2a 00 01 ........I...7*..
  0070: 20
Connection Handover Select Message
urn:nfc:wkt:Hs,,12110204616301013000
  1st carrier is Wi-Fi (Simple Config)
    power    = active
Traceback (most recent call last):
  File "read_ndef.py", line 220, in <module>
    main()
  File "read_ndef.py", line 170, in main
    print_handover_select(message)
  File "read_ndef.py", line 86, in print_handover_select
    cfg = WiFiConfigData.fromstring(config_data)
  File "/cygdrive/e/Prog/no_backup/nfcpy/nfc/ndef/WiFiSimpleConfig.py", line 150, in fromstring
    raise ValueError("expected Version1 attribute")
ValueError: expected Version1 attribute

下の方に、バージョン属性がない、みたいなエラーが出ている。
なるほど、Carrier Configuration Recordのペイロードにデータ長を置いたのがよくなかったようだ。
これはBluetoothのOOBデータ例をまねしたから置いたのだった。

それを外してやりなおすと、うまくいった。


では、同じようにOOBデータ長を外した大きいデータを書き込んで調べてみよう。

NDEF container present
  version   = 1.0
  writeable = yes
  capacity  = 208 byte
  data size = 121 byte
  0000: 91 02 0a 48 73 12 d1 02 04 61 63 01 01 30 00 5a ...Hs....ac..0.Z
  0010: 17 4e 01 61 70 70 6c 69 63 61 74 69 6f 6e 2f 76 .N.application/v
  0020: 6e 64 2e 77 66 61 2e 77 73 63 30 10 4a 00 01 10 nd.wfa.wsc0.J...
  0030: 10 0e 00 3b 10 26 00 01 01 10 45 00 0e 31 32 33 ...;.&....E..123
  0040: 34 35 36 37 38 39 30 31 32 33 34 10 03 00 02 00 45678901234.....
  0050: 20 10 0f 00 02 00 08 10 27 00 0a 31 32 33 34 35  .......'..12345
  0060: 36 37 38 39 30 10 20 00 06 aa bb cc dd ee ff 10 67890. .........
  0070: 49 00 06 00 37 2a 00 01 20                      I...7*..
Connection Handover Select Message
urn:nfc:wkt:Hs,,12110204616301013000
  1st carrier is Wi-Fi (Simple Config)
    power    = active
    version  = 1.0
    network  = 12345678901234
    password = 1234567890
    macaddr  = aa:bb:cc:dd:ee:ff
    security = WPA2-Personal / AES

 

あれ・・・読めてる・・・。
では、Androidでは・・・読めない。

 

うーん、謎は深まるばかりである。

2012/12/24

[nfc]NDEFクイズ !

[Q]
以下のデータをFeliCa Liteに書き込むと、Nexus7はNDEFとして認識してくれました。

[00] 10 04 01 00 0D 00 00 00 |........|
 .   00 00 01 00 00 70 00 93 |.....p..|
[01] 91 02 0A 48 73 12 D1 02 |...Hs...|
 .   04 61 63 01 01 30 00 5A |.ac..0.Z|
[02] 17 45 01 61 70 70 6C 69 |.E.appli|
 .   63 61 74 69 6F 6E 2F 76 |cation/v|
[03] 6E 64 2E 77 66 61 2E 77 |nd.wfa.w|
 .   73 63 30 43 00 10 4A 00 |sc0C..J.|
[04] 01 10 10 0E 00 30 10 26 |.....0.&|
 .   00 01 01 10 45 00 09 31 |....E..1|
[05] 32 33 34 35 36 37 38 39 |23456789|
 .   10 03 00 02 00 20 10 0F |..... ..|
[06] 00 02 00 08 10 27 00 04 |.....'..|
 .   31 32 33 34 10 20 00 06 |1234. ..|
[07] AA BB CC DD EE FF 10 49 |.......I|
 .   00 06 00 37 2A 00 01 20 |...7*.. |
[08] 00 00 00 00 00 00 00 00 |........|
 .   00 00 00 00 00 00 00 00 |........|
[09] 00 00 00 00 00 00 00 00 |........|
 .   00 00 00 00 00 00 00 00 |........|
[0A] 00 00 00 00 00 00 00 00 |........|
 .   00 00 00 00 00 00 00 00 |........|
[0B] 00 00 00 00 00 00 00 00 |........|
 .   00 00 00 00 00 00 00 00 |........|
[0C] 00 00 00 00 00 00 00 00 |........|
 .   00 00 00 00 00 00 00 00 |........|
[0D] 00 00 00 00 00 00 00 00 |........|
 .   00 00 00 00 00 00 00 00 |........|
[0E] FF FF FF FF FF FF FF FF |........|
 .   FF FF FF FF FF FF FF FF |........|
[80] 00 00 00 00 00 00 00 00 |........|
 *   00 00 00 00 00 00 00 00 |........|
[81] 00 00 00 00 00 00 00 00 |........|
 *   00 00 00 00 00 00 00 00 |........|
[82] 01 27 00 5D 19 FE 4B 78 |.'.]..Kx|
 *   12 34 00 00 00 00 00 00 |.4......|
[83] 01 27 00 5D 19 FE 4B 78 |.'.]..Kx|
 *   00 F0 00 00 02 06 03 00 |........|
[84] 00 00 00 00 00 00 00 00 |........|
 *   00 00 00 00 00 00 00 00 |........|
[85] 88 B4 00 00 00 00 00 00 |........|
 *   00 00 00 00 00 00 00 00 |........|
[86] 00 01 00 00 00 00 00 00 |........|
 *   00 00 00 00 00 00 00 00 |........|
[87] 00 00 00 00 00 00 00 00 |........|
 *   00 00 00 00 00 00 00 00 |........|
[88] FF:FF FF:01:07 00 00 00
 ..  00 00 00 00 00 00 00 00
 .:read & write, *:read-only

 

しかし、次のデータを書き込むとNDEFとして認識しませんでした。

[00] 10 04 01 00 0D 00 00 00 |........|
 .   00 00 01 00 00 71 00 94 |.....q..|
[01] 91 02 0A 48 73 12 D1 02 |...Hs...|
 .   04 61 63 01 01 30 00 5A |.ac..0.Z|
[02] 17 46 01 61 70 70 6C 69 |.F.appli|
 .   63 61 74 69 6F 6E 2F 76 |cation/v|
[03] 6E 64 2E 77 66 61 2E 77 |nd.wfa.w|
 .   73 63 30 44 00 10 4A 00 |sc0D..J.|
[04] 01 10 10 0E 00 31 10 26 |.....1.&|
 .   00 01 01 10 45 00 0A 31 |....E..1|
[05] 32 33 34 35 36 37 38 39 |23456789|
 .   30 10 03 00 02 00 20 10 |0..... .|
[06] 0F 00 02 00 08 10 27 00 |......'.|
 .   04 31 32 33 34 10 20 00 |.1234. .|
[07] 06 AA BB CC DD EE FF 10 |........|
 .   49 00 06 00 37 2A 00 01 |I...7*..|
[08] 20 00 00 00 00 00 00 00 | .......|
 .   00 00 00 00 00 00 00 00 |........|
[09] 00 00 00 00 00 00 00 00 |........|
 .   00 00 00 00 00 00 00 00 |........|
[0A] 00 00 00 00 00 00 00 00 |........|
 .   00 00 00 00 00 00 00 00 |........|
[0B] 00 00 00 00 00 00 00 00 |........|
 .   00 00 00 00 00 00 00 00 |........|
[0C] 00 00 00 00 00 00 00 00 |........|
 .   00 00 00 00 00 00 00 00 |........|
[0D] 00 00 00 00 00 00 00 00 |........|
 .   00 00 00 00 00 00 00 00 |........|
[0E] FF FF FF FF FF FF FF FF |........|
 .   FF FF FF FF FF FF FF FF |........|
[80] 00 00 00 00 00 00 00 00 |........|
 *   00 00 00 00 00 00 00 00 |........|
[81] 00 00 00 00 00 00 00 00 |........|
 *   00 00 00 00 00 00 00 00 |........|
[82] 01 27 00 5D 19 FE 4B 78 |.'.]..Kx|
 *   12 34 00 00 00 00 00 00 |.4......|
[83] 01 27 00 5D 19 FE 4B 78 |.'.]..Kx|
 *   00 F0 00 00 02 06 03 00 |........|
[84] 00 00 00 00 00 00 00 00 |........|
 *   00 00 00 00 00 00 00 00 |........|
[85] 88 B4 00 00 00 00 00 00 |........|
 *   00 00 00 00 00 00 00 00 |........|
[86] 00 01 00 00 00 00 00 00 |........|
 *   00 00 00 00 00 00 00 00 |........|
[87] 00 00 00 00 00 00 00 00 |........|
 *   00 00 00 00 00 00 00 00 |........|
[88] FF:FF FF:01:07 00 00 00
 ..  00 00 00 00 00 00 00 00
 .:read & write, *:read-only

 

さあ、なぜでしょう?

(OKテキストNGテキスト)

※ヒント:私もまだわかっていません・・・。


2つのNDEFレコードがあり、そのうち後者のサイズを+1したのだ。
Type3 Tagヘッダの長さも+1され、チェックサムも+1されてる。

成功している方は、こういう風に見えている。

# NFC data set information:
Current message size: 112 bytes
Maximum message size: 208 bytes
NFC data set access: Read & Write
 
# Handover Select record:
type: "Hs"
 
payload length: 10 bytes
payload data:
[0000] 12 D1 02 04 61 63 01 01 |....ac..|
[0008] 30 00                   |0.      |
 
# Wi-Fi Simple Configuration record:
ID: "0"
type: "application/vnd.wfa.wsc"
 
payload length: 69 bytes
payload data:
[0000] 43 00 10 4A 00 01 10 10 |C..J....|
[0008] 0E 00 30 10 26 00 01 01 |..0.&...|
[0010] 10 45 00 09 31 32 33 34 |.E..1234|
[0018] 35 36 37 38 39 10 03 00 |56789...|
[0020] 02 00 20 10 0F 00 02 00 |.. .....|
[0028] 08 10 27 00 04 31 32 33 |..'..123|
[0030] 34 10 20 00 06 00 1B 8B |4. .....|
[0038] B4 39 69 10 49 00 06 00 |.9i.I...|
[0040] 37 2A 00 01 20          |7*..    |

増やしたのは、Wi-Fi Simple Configuration recordの方。
こんなデータ(Excel。分析アドインがいると思う)を書き込んでるつもり。

NXPのTagInfoアプリを使って読んでいる。
そっち側の制限かと思ったが、そもそもAndroidがNDEFとして見てくれない。
いや、その言い方は正確じゃないな。
正しくは、メッセージがあるNDEFとして見てくれない、だ。
logcatで、NfcDispatcherはNDEFと思っているけれども、messageがnullだといっていたのだ。
intentもNDEFとして上がってこないのよねぇ。。。

 

自分で見る限りは大丈夫なように見えるけど、なんかダメなんだろう。
Androidって、NDEFの解析っぽいのはlibnfc-nxpでやってるせいか、あまりログが出ないのだな。

ペイロードの解析はしないと思うので、間違っているならNDEFレコードのヘッダ部分か、Type3のヘッダ部分だろう。
ちなみに、データサイズを-1しても-5くらいしてもOKだが、+1や+2したらダメだった。
ちょうどこのOKデータが境目なのだ。

 

なんか、ひどくくだらないところを見落としてるんだろうな・・・。
正解者には何も出ませんが、助けてくれー、というところです。