2012年7月2日

[snep]nfcpy v.s. 自作SNEP(PUT/Initiator)

nfcpyをtarget、自作SNEPをinitiatorにして、自分からSNEP PUTさせた。
週末の作業はこれでおしまい。

   1: $ python snep-test-server.py -d nfc.llcp --mode=initiator
   2: enable debug output for module 'nfc.llcp'
   3: searching for a usable reader
   4: searching for a usb bus reader
   5: path match for 'usb' (or no path given)
   6: trying usb:bus-0:\\.\libusb0-0001--0x054c-0x02e1
   7: import nfc.dev.rcs956_usb
   8: chipset is a PN533 version 1.48
   9: using Sony RC-S370/P at usb:bus-0:\\.\libusb0-0001--0x054c-0x02e1
  10: activated a p2p target in 424 kbps active mode
  11: llc cfg {'recv-lto': 2000, 'send-miu': 128, 'send-agf': True, 'send-lto': 1000, 'send-lsc': 2, 'recv-miu': 1024, 'send-wks': 17, 'rcvd-ver': (1, 0)}
  12: LLCP Link established, I'm the DEP Initiator
  13: Local LLCP Settings
  14:   LLCP Version: 1.1
  15:   Link Timeout: 1000 ms
  16:   Max Inf Unit: 1024 octet
  17:   Service List: 0000000000010011
  18: Remote LLCP Settings
  19:   LLCP Version: 1.0
  20:   Link Timeout: 2000 ms
  21:   Max Inf Unit: 128 octet
  22:   Service List: 0000000000010001
  23: snep server bound to port 4
  24: snep server bound to port 16
  25: SEND  0 ->  0 SYMM
  26: RECV  4 ->  1 CONN MIU=128 RW=1 SN=urn:nfc:sn:snep
  27: DLC (4,None) LISTEN enqueue CONNECT PDU
  28: accepting CONNECT from SAP 4
  29: DLC (4,None) LISTEN dequeue CC PDU
  30: SEND  4 ->  4 CC   MIU=128 RW=2
  31: new data link connection (4 <=== 4)
  32: serving snep client on remote sap 4
  33: RECV  4 ->  4 I    N(S)=0 N(R)=0 LEN=17 SDU=10020000000bd101045402656e75656e6f
  34: DLC (4,4) ESTABLISHED enqueue I PDU
  35: default snep server got put request
  36: ndef message length is 11 octets
  37: DLC (4,4) ESTABLISHED voluntary ack DLC  4 <->  4 ESTABLISHED RW(R)=1 V(S)=0 V(SA)=0 RW(L)=2 V(R)=1 V(RA)=0
  38: type is 'urn:nfc:wkt:T', id is ''
  39: DLC (4,4) ESTABLISHED send() DLC  4 <->  4 ESTABLISHED RW(R)=1 V(S)=0 V(SA)=0 RW(L)=2 V(R)=1 V(RA)=1
  40: SEND  4 ->  4 RR   N(R)=1
  41: RECV  4 ->  4 RR   N(R)=0
  42: DLC (4,4) ESTABLISHED enqueue RR PDU
  43: DLC (4,4) ESTABLISHED dequeue I PDU
  44: SEND  4 ->  4 I    N(S)=0 N(R)=1 LEN=6 SDU=108100000000
  45: RECV  4 ->  4 DISC
  46: DLC (4,4) ESTABLISHED enqueue DISC PDU
  47: DLC (4,4) CLOSE_WAIT dequeue DM PDU
  48: DLC (4,4) CLOSE_WAIT close()
  49: SEND  4 ->  4 DM   REASON=0
  50: DLC (4,4) SHUTDOWN close()
  51: in exchange => IOError [Errno 10] rf field not activated in time by active mode peer
  52: shutdown on link disruption
  53: closing service access point 16
  54: shutdown socket DLC 16 <-> None LISTEN RW(R)=None V(S)=0 V(SA)=0 RW(L)=2 V(R)=0 V(RA)=0
  55: DLC (None,None) LISTEN close()
  56: closing service access point 4
  57: nfc.llcp.Error: [EPIPE] Broken pipe
  58: shutdown socket DLC  4 <-> None LISTEN RW(R)=None V(S)=0 V(SA)=0 RW(L)=2 V(R)=0 V(RA)=0
  59: DLC (None,None) SHUTDOWN close()
  60: DLC (None,None) LISTEN close()
  61: closing service access point 1
  62: nfc.llcp.Error: [EPIPE] Broken pipe
  63: closing service access point 0
  64: DLC (None,None) SHUTDOWN close()
  65: llc run thread terminated
  66: shutdown requested
  67: I was the Initiator

まあ、ここに至るまでに何度か失敗しているのだけど、それはいいとしよう。

nfcpyが、終わっても搬送波を出しっ放しになるのが気にくわない。
何か処理が足りてないのだろうか?
エラーっぽいのは、L.51で「搬送波が出てないぞ-」っていわれているところくらいだ。
Active communication modeでやってるからだろうか?

 

   1: activated as p2p target in 424 kbps passive mode
   2: llc cfg {'recv-lto': 2000, 'send-miu': 128, 'send-agf': True, 'send-lto': 1000, 'send-lsc': 2, 'recv-miu': 1024, 'send-wks': 19, 'rcvd-ver': (1, 0)}
   3: LLCP Link established, I'm the DEP Target
   4: Local LLCP Settings
   5:   LLCP Version: 1.1
   6:   Link Timeout: 1000 ms
   7:   Max Inf Unit: 1024 octet
   8:   Service List: 0000000000010011
   9: Remote LLCP Settings
  10:   LLCP Version: 1.0
  11:   Link Timeout: 2000 ms
  12:   Max Inf Unit: 128 octet
  13:   Service List: 0000000000010011
  14: snep server bound to port 4
  15: snep server bound to port 16
  16: RECV  4 ->  1 CONN MIU=128 RW=1 SN=urn:nfc:sn:snep
  17: DLC (4,None) LISTEN enqueue CONNECT PDU
  18: accepting CONNECT from SAP 4
  19: DLC (4,None) LISTEN dequeue CC PDU
  20: new data link connection (4 <=== 4)
  21: SEND  4 ->  4 CC   MIU=128 RW=2
  22: serving snep client on remote sap 4
  23: RECV  4 ->  4 I    N(S)=0 N(R)=0 LEN=21 SDU=10020000000fd101085402656e6869726f39396d61
  24: DLC (4,4) ESTABLISHED enqueue I PDU
  25: default snep server got put request
  26: ndef message length is 15 octets
  27: DLC (4,4) ESTABLISHED voluntary ack DLC  4 <->  4 ESTABLISHED RW(R)=1 V(S)=0 V(SA)=0 RW(L)=2 V(R)=1 V(RA)=0
  28: type is 'urn:nfc:wkt:T', id is ''
  29: SEND  4 ->  4 RR   N(R)=1
  30: DLC (4,4) ESTABLISHED send() DLC  4 <->  4 ESTABLISHED RW(R)=1 V(S)=0 V(SA)=0 RW(L)=2 V(R)=1 V(RA)=1
  31: RECV  4 ->  4 RR   N(R)=0
  32: DLC (4,4) ESTABLISHED enqueue RR PDU
  33: DLC (4,4) ESTABLISHED dequeue I PDU
  34: SEND  4 ->  4 I    N(S)=0 N(R)=1 LEN=6 SDU=108100000000
  35: RECV  4 ->  4 DISC
  36: DLC (4,4) ESTABLISHED enqueue DISC PDU
  37: DLC (4,4) CLOSE_WAIT dequeue DM PDU
  38: DLC (4,4) CLOSE_WAIT close()
  39: SEND  4 ->  4 DM   REASON=0
  40: DLC (4,4) SHUTDOWN close()
  41: libusb0-dll:err [_usb_reap_async] timeout error
  42:  
  43: send_response: IOError no response from pn53x
  44: shutdown on link disruption
  45: closing service access point 16
  46: shutdown socket DLC 16 <-> None LISTEN RW(R)=None V(S)=0 V(SA)=0 RW(L)=2 V(R)=0 V(RA)=0
  47: DLC (None,None) LISTEN close()
  48: closing service access point 4
  49: nfc.llcp.Error: [EPIPE] Broken pipe
  50: shutdown socket DLC  4 <-> None LISTEN RW(R)=None V(S)=0 V(SA)=0 RW(L)=2 V(R)=0 V(RA)=0
  51: DLC (None,None) SHUTDOWN close()
  52: DLC (None,None) LISTEN close()
  53: closing service access point 1
  54: nfc.llcp.Error: [EPIPE] Broken pipe
  55: closing service access point 0
  56: DLC (None,None) SHUTDOWN close()
  57: llc run thread terminated
  58: shutdown requested
  59: I was the Target

これはこれで終わるんだけど、もう1回実行するとR/Wがアプリケーションレベルのエラーを返している。

RC-S956にはResetというコマンドがあって、それを実行すると状態が初期化される。
それを実行してやれば直りそうなんだけどなぁ。
最初のRFConfigurationで怒られてるからその前にResetすればよさそうなのだけど、pn53xのコンストラクタで呼び出して、そのあとrcs956のコンストラクタに戻ってくるようになってるみたい。
Resetコマンドはpn53xには存在しないから投げるようにはできていない。
コンストラクタでこけるから、そのあとに進めない。

でも、見た感じだとrcs956のclose()でResetしてるようだから、それが呼び出せていないだけかもしれん。


ごにょごにょと書いたが、nfcpyを動かそうとしているわけじゃないので、深入りしない。
自作SNEP/LLCPの実装が間違っているという可能性も十分ある。

だから、別の環境でも動かしてみたいのよねぇ。
環境というのは、nfcpyじゃなくて、ということ。

 

まあ、今度考えよう。

2012年7月1日

Android BEAMで渡している情報を調べよう

わかる範囲で、Android BEAMが渡しているNDEFの情報を調べよう。

http://d.hatena.ne.jp/touchRL/20111208/1323270209

  • Google map : U
  • YoutTube動画 : U
  • 標準ブラウザ : U
  • アプリ : U, EXTERNAL(urn:nfc:ext:android.com:pkg)

 

けっこう探したけど、このページくらいしかAndroid BEAMでのNDEFを調べた情報がなかった。

たぶん、受信側はNDEFを普通に扱うだけで、BEAMだから、とかカードだからとかは区別していないのではなかろうか。


NDEFレコードのタイプについて。

http://developer.android.com/guide/topics/connectivity/nfc/nfc.html#creating-records

  • Absolute URI
  • MIME Media
  • Well-Known : TEXT
  • Well-Known : URI
  • External

ん、Well-KnownじゃないURIもあるのか。
NDEFのTNF(Type Named Format)を振り返ってみよう。

  • 0x00 : Empty
  • 0x01 : Well-Known
  • 0x02 : Media-Type (RFC 2046)
  • 0x03 : Absolute URI (RFC 3986)
  • 0x04 : external
  • 0x05 : unknown
  • 0x06 : unchanged
  • 0x07 : reserved

なるほど、Absolute URIもMedia-TypeもNDEFにもともとあるのだな。
バイナリは扱えないのかと思っていたけど、Media-Typeってのを使えばファイルなんかも取り扱えそうだ。

サンプルが見てみたいと思って探したところ、DoCoMoの資料がよさそうだった。


Android 4.1からBEAMが拡張されて…という記載を見つけたんだけど、Media-Typeを画像とか動画とかにしてしまえば送ることができそうな気がするけど、そういうわけでもないのかな。

大きいファイルとか転送するとつらいよな、と思って禁止してたりするのかもしれんね。

[snep]nfcpy v.s. 自作SNEP (PUT/Target)

勝負!

   1: $ python snep-test-server.py -d nfc.llcp --mode=initiator
   2: enable debug output for module 'nfc.llcp'
   3: searching for a usable reader
   4: searching for a usb bus reader
   5: path match for 'usb' (or no path given)
   6: trying usb:bus-0:\\.\libusb0-0001--0x054c-0x02e1
   7: import nfc.dev.rcs956_usb
   8: chipset is a PN533 version 1.48
   9: using Sony RC-S370/P at usb:bus-0:\\.\libusb0-0001--0x054c-0x02e1
  10: activated a p2p target in 424 kbps active mode
  11: llc cfg {'recv-lto': 2000, 'send-miu': 128, 'send-agf': True, 'send-lto': 1000, 'send-lsc': 2, 'recv-miu': 1024, 'send-wks': 17, 'rcvd-ver': (1, 0)}
  12: LLCP Link established, I'm the DEP Initiator
  13: Local LLCP Settings
  14:   LLCP Version: 1.1
  15:   Link Timeout: 1000 ms
  16:   Max Inf Unit: 1024 octet
  17:   Service List: 0000000000010011
  18: Remote LLCP Settings
  19:   LLCP Version: 1.0
  20:   Link Timeout: 2000 ms
  21:   Max Inf Unit: 128 octet
  22:   Service List: 0000000000010001
  23: snep server bound to port 4
  24: snep server bound to port 16
  25: SEND  0 ->  0 SYMM
  26: RECV  4 ->  1 CONN MIU=128 RW=1 SN=urn:nfc:sn:snep
  27: DLC (4,None) LISTEN enqueue CONNECT PDU
  28: accepting CONNECT from SAP 4
  29: DLC (4,None) LISTEN dequeue CC PDU
  30: SEND  4 ->  4 CC   MIU=128 RW=2
  31: new data link connection (4 <=== 4)
  32: serving snep client on remote sap 4
  33: RECV  4 ->  4 I    N(S)=0 N(R)=0 LEN=21 SDU=10020000000fd101085402656e6869726f39396d61
  34: DLC (4,4) ESTABLISHED enqueue I PDU
  35: default snep server got put request
  36: ndef message length is 15 octets
  37: type is 'urn:nfc:wkt:T', id is ''
  38: DLC (4,4) ESTABLISHED voluntary ack DLC  4 <->  4 ESTABLISHED RW(R)=1 V(S)=0 V(SA)=0 RW(L)=2 V(R)=1 V(RA)=0
  39: DLC (4,4) ESTABLISHED send() DLC  4 <->  4 ESTABLISHED RW(R)=1 V(S)=0 V(SA)=0 RW(L)=2 V(R)=1 V(RA)=1
  40: SEND  4 ->  4 RR   N(R)=1
  41: RECV  4 ->  4 RR   N(R)=0
  42: DLC (4,4) ESTABLISHED enqueue RR PDU
  43: DLC (4,4) ESTABLISHED dequeue I PDU
  44: SEND  4 ->  4 I    N(S)=0 N(R)=1 LEN=6 SDU=108100000000
  45: RECV  4 ->  4 DISC
  46: DLC (4,4) ESTABLISHED enqueue DISC PDU
  47: DLC (4,4) CLOSE_WAIT dequeue DM PDU
  48: DLC (4,4) CLOSE_WAIT close()
  49: SEND  4 ->  4 DM   REASON=0
  50: DLC (4,4) SHUTDOWN close()
  51: in exchange => IOError [Errno 10] rf field not activated in time by active mode peer
  52: shutdown on link disruption
  53: closing service access point 16
  54: shutdown socket DLC 16 <-> None LISTEN RW(R)=None V(S)=0 V(SA)=0 RW(L)=2 V(R)=0 V(RA)=0
  55: DLC (None,None) LISTEN close()
  56: closing service access point 4
  57: nfc.llcp.Error: [EPIPE] Broken pipe
  58: shutdown socket DLC  4 <-> None LISTEN RW(R)=None V(S)=0 V(SA)=0 RW(L)=2 V(R)=0 V(RA)=0
  59: DLC (None,None) SHUTDOWN close()
  60: DLC (None,None) LISTEN close()
  61: closing service access point 1
  62: nfc.llcp.Error: [EPIPE] Broken pipe
  63: closing service access point 0
  64: DLC (None,None) SHUTDOWN close()
  65: llc run thread terminated
  66: shutdown requested
  67: I was the Initiator

というわけで、受け取ってくれたようだ。
よかったよかった。

 

こちらから送ったのは、L.33のSDU。
「hiro99ma」という文字列だ。

L.40でnfcpyがRRを送っているので、こっちもL.41でRRを送っている。
じゃあもう送りたいデータはないんだね、とL.44でnfcpyがSNEP応答を送っている。0x81はSUCCESS。
私たちもう終わりね、とL.45でDISCを送っている。
終わりましょう、とnfcpyがL.49でDMを送って、おしまい。

nstだと、SNEP応答で0x81をもらったあとも、1回だけRRを投げて確認するようになっているみたいだ。
SNEPの仕様としては、LLCPの動作にまで言及はしていないので、これはこれでいいのかもしれん。

 

Initiatorとしての動作確認や、GETなどが残っているけど、一段落ですわ。

Android BEAMの情報を集めよう

あまり熱心に見ていないAndroid BEAMだが、そろそろ情報を集めよう。
記事だけだと、Android BEAMのカバーする範囲がわからないので、とりあえず集めるだけ集めてみる。


概要

  • 最初(Android 2.3.3?)は、NPP(NDEF Push Protocol)だった
  • Android 4.0からは、SNEP(Simple NDEF Exchange Protocol)を優先して、だめだったらNPPを使っている
  • Android 4.1では、SSP(Simple Secure Paring)[pdf]が使える。
    どうでもいいけど、BluetoothにはSPP(Serial Port Profile)もあるので紛らわしい
  • データとしては、こういうものを送ることができるようだ
    • リンク
    • アプリ(Android Marketへのリンク?)
    • アドレス
    • 写真(Android 4.1から。画像ファイル?)
    • 動画(Android 4.1から。動画ファイル?)

 

動作

  • 送信したいアプリが、NDEFメッセージを作る
  • 受信対象となるデバイスが現れたらコールバックするしくみがあるので、そのタイミングでNDEFメッセージを作りに行けばよいのかな。
  • データを送信するアクティビティはフォアグラウンドにいないとだめ。
    ということは、サービスみたいに裏で動くものからは送信できないのかな?
  • 送受信対象となるためには、スクリーンがロックしてたらだめ。
    「ロック」は、指でうにょうにょって操作しないと解除されない、あの画面かな。
  • もちろん、NFCを有効にしてないとだめだろう。
    飛行機モードにしてると、NFCは有効にならないはず(ソースで見る限り)
  • Tech Boosterさんの画像を見ると、送信側は画面が切り替わるようだ。
    ソースファイル名も「SendUi.java」だし。
    受信側は、受信されるまで同じ画面なのか(インテントを受信したときの動きっぽい)。

最近わかったことも書いておこう。

  • 送信側がTargetになると思い込んでいたが、実際はTargetとInitiatorを交互に繰り返しているようである。
  • ということは、InitiatorかTargetかは送信の主とは関係がなさそうだ。
  • LLCPのCONNECT PDUを送信した方が、SNEP PUTをするようだ。

 

そんなわけで、簡単にAndroid BEAMで送信したいのであれば、

  • InitiatorとなってATR_REQ送信するか、TargetとなってATR_RES返信するかのどっちかを実装。
  • NFC-DEPの実装。InitiatorでもTargetでもいいけど、ほぼフル実装。
  • LLCPの実装。Connection-orientedでSNEPが使える程度。
  • SNEPの実装。SNEP PUTが使えればよい。

くらいがあればいいんじゃないだろうか。

[nfc]SNEPの階段を上るしかないのか

近距離での通信をやりたくてNFCを始めた私。
NFC-DEPが動き、LLCPも何となく実装した。
しかし、それでもまだ足りないというのか!


というのが、残るSNEPだ。

NFC Forumでは、NFC端末同士の通信も規定している。
NFC端末同士を向かい合わせるので、Peer to Peer、お互いがじっと見つめ合うようなイメージだろうか。
まあ、コンピュータ用語やん、といわれればそれまでだが。

 

NFCを使って通信するとなると、少なくともアンテナの部分を向かい合わせるようにせんといかん。
アンテナからデバイスまでがすごーく長いという作り方もあるかもしれんけど、NFCで「外付けアンテナ」ってのは聞いたことがないので、普通はNFCデバイスと一体化しているのだろう。

端末同士を向かい合わせると、操作するのがめんどうになる。
ぶれると嫌なので、タッチパネルですらあまり触りたくないところだ。
「NFCチャット」なんて意味がないこともやらないだろうし(直接話せよ、ということで)。


となると、向かい合わせると短時間のうちに何もせずとも通信が終わる、という形が望ましい。
そういう使い方となると、片方が送信、片方が受信、という立場になるのが簡単だ。
承認をもらうのは、事前か事後か、というくらいで済むし。


そう思ったかどうかは知らないけれども、SNEPは非常にシンプルだ。
基本的に、NDEFをPUTするか、NDEFをGETするか。

ここまで実装しないと、LLCPの使い道がないのだ。
もちろん、LLCPは下位層だけに拡張性が考えられているのだが、自分でプロトコルを作ってまでやりとりをしたいと思わないし、NFC ForumならNDEFをやりとりする以外なかろう。

そうなると、SNEPを実装するしかない、と思うのだ。
まあ、ついでだしね。

互換性テスト

NFCのプロトコルを実装している。
デバイスに対する制御は、デバイスが反応するからわかる。
しかしアプリケーションレベルになると、相手がいないとわからない。
何がわからないかというと、自分の実装で相手がちゃんと動いてくれるかどうかがわからないのだ。

今やってるLLCPはアプリケーションレベルなので、そういう心配をしている。
実際にnfcpyとやりとりしても動かないので、さらに心配になってきた。

 

こういう「他の人とつながるデバイス」というのは、同じような問題があるので、だいたい「互換性テスト」というような試験項目がある。
これこれが、こうこう動かないとだめですよ、みたいな試験だ。
それで100%保証ができるというわけではないけど、このくらいは動いて当然、というような試験だ。

 

NFC Forumにも、そういう試験項目はあるようだが、メンバーの人しか見られない。
http://certification.nfc-forum.org/nfc-forum-device-requirements

うーん、残念。
PaSoRiで動くNFC ForumのLLCP準拠ソフトがあればいいんだけどなあ。