2012/01/31

[nfc]NFCID (2)

風邪っぽいので、短めの話を選んだ。
「みんなでNFCのお勉強」シリーズ(シリーズ?)。
NFCIDについてだ。

NFCIDというのは、NFCのIDだ。
0, 1, 2, 3とt, iがある。
tとiは、普通付けない。
tは「Target」で、iは「Initiator」だ。
カードエミュレーションやDEPするときのように、どっち側のNFCIDかを区別したいときに付けるだけなので、そんなに気にしなくてよい。
以下、自作の資料に書いていたものを参考に書いているので、間違ってたらすまん。

NFCID0は、NFC-B。
4byte固定。

NFCID1は、NFC-A。SENS_RESの上位2ビットでサイズが決まる。
single : 4byte
double : 7byte
triple : 10byte
4byteのUIDは、ユニークではない。
Mifare 1Kは4byteだったが、Ultralightは7byteだった。
「18092では4byte固定になっている」と当時の私は書いている(Digital Protocol - 4.6.3.2)。
NFCID1 CLnは、カスケードレベル、というものらしい。
名前は聞くが、どういうものかはまだ調べていない。
4byte固定らしい。

NFCID2は、NFC-F。8byte固定。
先頭の2byteでサポートするプロトコルがわかる。
01 FE : NFC-DEPサポート(NFCIP-1)。3~8byteはランダム。
02 FE : Tag Type3サポート。3~8byteはランダム。
03 FE : FeliCa Plug。
それ以外 : Tag Type3サポート。1~8byteはプロプライエタリ(FN管理?)。
なお、システムが複数あるものは、システムごとにNFCID2がある。
共通領域とサイバー領域とか。

NFCID3は、NFC-DEPで使う。10byte固定。
NFC-Fの場合は、10byte中先頭8byteはNFCID2で、残り2byteは0とか。

NFCID1の4byte版はユニークじゃない、となっている。
NFCID2もユニークではない、というのはどこかで読んだのだが、忘れた。
FeliCa Networks社の用語集だったか・・・と思ってサイトを見たら、今日更新されてた。
そして用語集はなくなっていた・・・。
とりあえず、技術情報ページのリンクを載せておく。
SDB-200がある!と思ったが、ツールだけなのね。
まあ、個人で買えるとは思わんが。。

技術情報のページではやはりよくわからなかったので、SONYの技術サイトにある「FeliCa技術方式の各種コードについて」をリンクしよう(English)。

私としても、NFCID2(IDm)でのみのカード識別はやめていただきたい。
怖いからだ。
あくまであれは、PCD(リーダライタ)がPICC(カード)に一時的にアクセスするために取得する
だってねぇ、あれは私でも同じIDmを持つカード機能を作ることができてしまうくらい簡単なものなのだ。
やったことないけど、FeliCa Liteくらいならフルエミュレーションできるんじゃなかろうか。
もしIDmのみで重要な情報(家の鍵代わりとか)を運用しているメーカーなどがあって、鍵が破られてしまうようなことがあると、私のような善人が疑われてしまう可能性があるのだ。
そうなるのは、いやなので、やーやー言っているのだ。
ほら、技術的に可能であったら、技術者としてはやってしまいたくなるではないか。
倫理の問題でもあるのだけど、なるべくなら「そういう状況」が存在しない方がよい。
食欲や睡眠欲と違って、知識欲ってのは何か底が深くて怖いからね。

なんだかんだ言って、長くなってしまった。
私の今回の収穫は、FeliCa Networks社の技術情報サイトだ。
FALP受信をやっていて、サブコマンド一覧にないデータが出てきていたのだ。
まあ、わかったからといってFALP受信ができるようになるわけではないのだけど、知識欲が満たされたので満足だ。

2012/01/29

[felica]TSN

小ネタだ。

ポーリングコマンドで、TSNが指定できる。
Time Slot Numberだ。

ポーリングコマンドではPOL_RESを送信して、カードからPOL_REQを受信する。
RF領域に複数のカードがあった場合、POL_RESに対して複数のPOL_REQが返ってくる。
もし同じタイミングで返信したり、片方が返信している最中にもう片方が返信すると、無線データが壊れてしまう。

NFC-Fでは(FeliCaでは、なのかも)、POL_REQにTSNを指定し、この値+1のタイムスロットを返信時間として使っていいことにしている。
仕様書では、返信開始までが2.417ms、そこからタイムスロット1つが1.208msと書かれている。
この時間は、212kHz*512と、212kHz*256に相当する。FeliCaの遅い周波数は212kbpsなので、それをタイマにしているのだろう。

タイムスロットの例を見ると、POL_RESがずれて返信されていた。
ということは、これを使えば複数枚の結果を受けとることができるんじゃなかろうか?


そう思って試してみたが、常に同じカードの結果が1つだけ返ってきた。

推測だが、

  • 返信するタイムスロットはランダムではなく、カードで固定になっている
  • InListPassiveTargetは最初に返ってきたPOL_RESの結果を返す

というところじゃないだろうか。

よく見れば、InListPassiveTargetのNbTgは0か1ではないか。
2枚以上ってのはないことになる。
うーむ。

PN533でもそうだったので、市販のR/Wチップでは複数枚に対応する必要がないってことで機能削減されていると考えた方がよさそうだ。
なんとかできると面白いかなー、と思ったのだがね。

[android]AppWidgetを複数扱う

EjectSD、というAndroidのアプリを公開している。
何をするものかというと、SDカードのマウント/アンマウントをするAppWidgetだ。
デスクトップに置く際、マウントポイントを設定してもらい、アイコンをタッチすると、マウント/アンマウント動作をするというものだ。

 

シンプルといえばシンプルなのだが、ここに至るまでは面倒だった。
Acer A500で作っていたのだが、マウント/アンマウントのインテントが飛んでこないのだ。
それより面倒だったのは、SDカードのマウントポイントがよくわからないこと。
getExternalStorageDirectory()で取ってこれる、ということになっているのだが、いろいろとメモリの配置などの関係から、このAPIでは期待するパスが取って来れないことがあるのだ。

そこら辺を適当に処理して、今に至っている。

しかし、最近はSDカードだけでなく、USBメモリもさせることが多い。
要望として「両方なんとかしたい」というものがあった。
まあ、そうだろうねぇ。

一番簡単な対策は、別名にしたアプリをもう1つ公開することだ。
アイコンも別の形にすれば、見分けは付くだろう。
ただこの方法は、あんまり格好がよろしくない。
なんというか「負けた」感じがするのだ。

そんなわけで、土日で複数扱えるように対応していた。


簡単だろうと思っていたのだが、あまり把握していないこともあって、難儀した。

まず、パスの入力。
ListPreferenceを使っているのだが、これはデフォルトのプリファレンスに保存する。
これをAppWidgetごとにしなくてはならない。
考えたあげく、デフォルトのプリファレンスが書き換わったときのListenerで個別に書き写す、というやり方にした。
格好が悪い。。。

 

それ以上に困ったのは、アイコンの更新。
クリックしたアイコンの処理だけしたいのだが、なんか上書きされている。
これは検索するといろいろ情報が出てきた。
出てきたのだが、まねするとインテントが受け取れなくなった。。。

まねしたのは、AppWidgetのIDをURIとしてsetData()する方法だったのだが、インテントフィルタをちゃんと書いてなかったので受け取れなかった(のだろう)。
めんどくさかったので、putExtras()でやるようにした。

 

そして、マウント/アンマウントインテントの受け取り。
mountやumountすると、その結果がインテントでブロードキャストされる。
それをonReceive()で受けとるのだが、そのインテントには当然AppWidgetのID情報など載っていない。
どうしたもんだか・・・と考えたが、もう全部のインスタンスを更新することにした。
AppWidgetManager.getInstance(context).getAppWidgetIds(componentName)としてIDの配列を受け取り、全部に対してupdateAppWidget()してやった。
onUpdate()の中では、IMountService.getVolumeState(path)でマウント状態を取得してアイコンを差し替えている。

 

残るは、過去との互換。
EjectSDはデフォルトのプリファレンス、今回は個別のプリファレンスだ。
うまく切り替えられるように作るべきか・・・と迷ったが、あきらめた。
別のアプリにしてしまった。
パスが1つでいいのなら、前ので十分だしね。


今回、A500がandroid3.2になってからだったが、MOUNTやUNMOUNTのインテントが飛んでくるようになった。
特にインテントフィルタ周りは何もしていないのだが・・・。

2012/01/28

[rcs620s]RC-S620/S簡易ドキュメントを読む

SONY技術情報サイトにある、RC-S620/S簡易ドキュメント2本。
簡易説明の説明なんか書いても仕方ないかなー、と思ったが、自分のために書いておこう。


RC-S620/S 製品仕様書<簡易版>

p.3

用語について書かれている。
「コントローラ」というのは、リーダライタを制御するパソコンのような意味だ。
シリアルでコマンドを送受信してやらないといけない機器、ということですな。

 

2.ハードウェア仕様

RC-S620/Sの持つ機能や、どうやって接続したらいいかが書かれている。
最初に迷うのは、フラットケーブルが片面なのだけど、どっちに挿せばいいの?だと思う。
間違うと、壊す・・・ことはないが、通信できないので困る。

これは、「2.6 外形寸法」を見るとよい。p.13だ。
左側に、コネクタ側から見た図がある。
破線がコネクタ接点と書かれているので、金属板側に接点があるのだ。

1ピンの位置も確認しておくこと。
私はこの確認が不十分で、1台壊してしまった。

もう1つ注意する点がある。
RC-S620/Sをカードにかざす面は基板がある側だ、ということ。
金属面ではないのだ。
見た目上、金属面にカードをかざしたくなるが、そこは我慢だ。
なんでそうなっているかというと、機器に組み込む際、金属面からネジを打ち込むからだ。
だからおそらく、金属面側は電波が漏れないようにカバーされているんじゃないだろうか。
ともかく、基板側にカードをかざすこと。

「2.3 UART通信仕様」も知っておかないと通信できまい。
なしなしの115200bpsだ。
通信速度を変更したい場合は、RC-S620/Sにボーレート変更のコマンドを送信しなくてはならないのだが、そのコマンドは説明がなかったと思う。
まあ、困らないと思うのでそのままでいいんじゃないかね。

2.4.2に電気的特性がある。
電池で駆動させたいときには、気になるだろう。
もちょっと消費電力が落ちてくれればなー、という気はするが、そういうときにはソフトパワーダウンさせるよりも、電源ごとOFFにして使うときに初期化し直した方がいいだろう。


RC-S620/S コマンドリファレンスマニュアル<簡易版>

p.7

基本ルール。
コントローラから送信したコマンドに対するレスポンスは返すけれども、勝手に送りつけることはないよ、ということ。

p.8

ここから、RC-S620/Sへ送信するフレーム形式が書かれている。
また、RC-S620/Sから送信されるフレーム形式も同じフォーマットだ
ここの「データ部」が、コマンドだったりレスポンスだったりする。

NormalフレームとExtendedフレームがある。
Normalフレームはデータ部が256byteまで、Extendedフレームはデータ部が265byteまで。
私なんかは、たった9byteしか変わらないならNormalだけでいいやん、と思っているのだが、なかなかそうもいかない事情がある。

PreambleとかPostambleとか出てくるが、これは通信パケットでよく使われる言葉だ。
カード側の仕様書にも、同じようにPreambleなどが出てきたと思うが、あれは無線側なので有線側とは関係がない。

p.10

ACKフレーム。
Acknowledgeのことだが、だいたいどこでも「ACK」(あっく)と呼ぶみたいだ。
いろいろな意味があるので、読んで把握すべし。

 

p.11 通信プロトコル

ここから、どうやってフレームをやりとりするのかの説明になる。
エラーが戻る、戻らないなどは、どの層の通信にエラーがあるかで変わってくる。

p.12 データリンクレベル

データリンクレベルでは、p.8から書かれていたフレームのフォーマットが正しければよい。
正しければ、データ部を見ずにACKフレームを返す。
つまり、ACKが返ってこないということは、フレームが間違っているということになる。
自分でコマンドを送信する際は、まずACK返信の有無を確認すること。
ACKを返さないパターンは、p.13に書かれている。

RC-S620/Sは、コマンドを受信してから最大でも3.5msで応答を返す。
コントローラ側でタイムアウトを設定したい場合は、これに通信速度*(コマンド長+ACK長)の時間を加えたものになるであろう。

ACKを返してきてからレスポンスが返ってくるまでの時間は、コマンド依存だ。
すぐ返すものもあれば、何かあるまで返さないものもある。

p.14に、RC-S620/Sのタイムアウト時間が書かれている。
データ部からポストアンブルまでの時間なので、データ部長+2byte。
Normalフレームの場合、データ部は最大256byte。
通信速度が115200bpsの場合、1byteはUART10bitなので86us。258byteなら22.1ms。
よほどたらたらと送信しない限りは大丈夫なはずだ。

p.15 アプリケーションレベル

アプリレベルのコマンドを処理している間に、ホストからACKか異なるコマンドを送信すると、現在実行しているコマンドを中断するので、詳細を確認すべし。
ACKで中断させた場合は、1ms以上待ってから次のコマンドを送信すること。

アプリレベルの場合、シンタックスエラーを返すことがある。
もちろん、データ部が間違っているからである。

 

p.16 モード

今までは通信レベルの話だったが、ここはRC-S620/Sが持つ状態について書かれている。
全部で7つのモードがあるので、意識すべし。
ここでは0と6についてしか書かれていないが、RC-S620/Sを購入後に入手する資料では、他のモードについても書かれている。

このドキュメントは、モード6の「Initiatorモード」のみ書かれている。
Initiatorというのは、カード側にコマンドを送信する方である。
カード側は、Target、と呼ばれる。

 

p.18 コマンド一覧

ここからは、データ部に詰めるコマンドとそのレスポンスについて書かれている。
自分でプログラムを作る場合、送信は「コマンド部を作成するところ」と「データ部からフレームを作成するところ」を作り、受信は「フレームからデータ部を抜き出す」「データ部を解析する」を作ることになるだろう。

このドキュメントでは、4つのコマンドが説明されている。

  • RFConfiguration
  • Reset
  • InListPassiveTarget
  • CommunicateThruEX

最初の2つは、RC-S620/Sの初期化や状態を戻すのに使われる。

InListPassiveTargetは、いわゆる「ポーリング」を行う。
「Passive Target」というのは「受動的なTarget」ということで、普通はカードを指す。
このコマンドを使って、モードを0から6に変化させる。
この動作を「Targetを捕捉する」ということもある(Type-Bは捕捉するタイプではないという話を聞いた)。

CommunicateThruEXは、捕捉したTargetにコマンドを送信するコマンドだ。
例えばFeliCa Liteカードのデータを読みたいなら、InListPassiveTargetでカードを捕捉し、CommunicateThruEXで"Read Without Encryption"を送信することになる。
そうすると、CommunicateThruEXのレスポンスに"Read Without Encryption"のレスポンスが載ってくる。

各コマンドの詳細は、省略する。
FeliCa Developers' BlogのRC-S620/Sサンプルのソースを読むと、どういう順番でコマンドを使えばよいか、コマンドの作り方、フレームの作り方など、基本的な部分はわかる。

Resetは、レスポンスが返ってきた時点でリセットされるのではなく、その次にコントローラからのACKを受信したときに行われるので、注意しよう。

InListPassiveTargetは「結局Initiator Data部に何を書けばいいのよ」と思われそうだ。
私の認識では、BrTyによって無線送信速度とTargetを決め、Targetの種類によってInitiator部をどう使うかR/Wが決めてうまいこと無線コマンドを送信している。
例えばFeliCaの場合、POL_REQという無線コマンドを送信するのだが、そのパケットをInitiatorDataに書いてやる。

[0] 0x00 (POL_REQコマンド)
[1] SystemCodeの上位
[2] SystemCodeの下位
[3] Request Code
[4] TimeSlot

とりあえず実行するなら「0x00 0xFF 0xFF 0x00 0x00」でよい。
詳細は、FeliCa LiteやFeliCa Standardのユーザーズマニュアルにある「Pollingコマンド」の説明を読むとよい。

もちろん、InListPassiveTargetでType-AやType-Bも見つけることができるので、興味がある方は探してみるとよいだろう。

CommunicateThruEXは、ちょっと特殊なコマンドだ。
R/Wに送るコマンドの中に、Targetへ送るコマンドを含める。
そのため、Target側のタイムアウトも考慮しなくてはならず、パラメータにTimeoutがある。
FeliCa Developers' Blogのサンプルでは、FeliCa携帯電話にURLをPUSHするようになっているが、PUSHするデータは携帯電話(=Target)に送信するため、CommunicateThruEXを使っている。
このコマンドは、Targetへのデータ(DataOut)に255byteまで載せることができる。そのときのコマンド長は259byte。256byteを超えてしまうので、Extendedフレームが必要になるのだ。


ざーっと流して読んでいったが、なんとなくわかっただろうか。

R/Wのドキュメントはだいたいこんな作りになっているので、見慣れるとPN533のドキュメントなども読むことができる。
慣れておくとよいだろう。

touchanote

Gigazineに、TouchanoteというNFCサービス(と呼んでよいのかな?)の記事があった。

http://gigazine.net/news/20120127-nfc-evernote-touchanote/

勢いで、10枚買った。
それでも800円以内だ。

何も考えずに買ったけれども、おそらくType-Aだろう。
Type-Aなら、MifareのUltralightかなぁ。

 

まあ、私はAndroidとかは持ってないんだけどね。

ざっと考えつくのは、引っ越し荷物を自分で梱包したときだ。
どの箱に何が入っていたのか・・・。

 

ねむすぎるので、ねます。

[rw]リーダライタRC-S620/Sへアクセス

私はNFCリーダライタとして、SONYのRC-S370とRC-S620/Sを持っている。

RC-S370は、USB接続である。
そのため、通信するにはドライバが必要になる。

RC-S620/Sは、組み込み用なのでケーブルなどは特殊ではあるが、シリアル接続である。
よって、シリアルをうまく扱いさえすれば、ドライバを書かずにアクセスできる。

SONYのリーダライタだけでなく、他のリーダライタも似たような感じだと思う。
通信の方法と、通信データがわかれば、どうにかして使うことができる。


私は、RC-S620/SにCP2102を接続して、パソコンとつなげている。
シリアルになれば、プログラムを書くのが比較的楽になる。

いや、動作を見たいだけであれば、プログラムを書く必要もない。
RC-S620/Sのプロトコルをバイナリファイルで作成して、TeraTermなどで送信するだけでいいのだ。
プロトコルが正しければ、リーダライタは応答を返してくれる。
正しくなければ、おそらく無応答だ。
無応答なのは、セキュリティのためだろうね。


と、この流れでプロトコルの話までしたいところだが、そうはいかない。
RC-S620/Sのドキュメントには、プロトコルのことは載っていないのだ。
簡易マニュアルにはいくつか書かれているが、それを説明してもしかたあるまい。

この1年で、NFCドライバをいくつか見てきたので、書かれていないプロトコルもいくつかわかっている。
が、そういうものを記事に書くのは、ちょっと気が引けるのだ。
PN533ならプロトコルのドキュメントが入手できるならいいけど、PaSoRiなどは入手できないからだ(私も持ってないよ)。

入手できないからこそ説明するんじゃないか!と言われそうだが、曖昧な情報を流すのもいやなものなのだ。
それに、著作権とかいろいろと関係しそうな気がするので、及び腰になってしまう。

まあ、私も1年くらいかけてずいぶんとわかった気がするので、興味がある方も1年くらい眺めていれば、習わぬ経を読む、ではないけど身についてくると思う。

2012/01/27

[nfc]NFC開発をするときに安くやりたい(ドキュメント編 - 3)

FeliCa

PaSoRiやRC-S620/S、FeliCa Liteを使うのであれば、FeliCaの技術情報を見ておいた方がよい。
http://www.sony.co.jp/Products/felica/business/tech-support/index.html
PaSoRiで使われているR/Wのコマンド仕様はあまり出ていないのだが、ここにある「RC-S620/Sコマンドリファレンスマニュアル」がもっとも有用であろう。
最近は情報がいろいろと出てきているので、今後に期待である。
RC-S620/Sを購入するとドキュメントを請求できるので、やっておいた方がよい。
RC-S956のコマンドについては有償になるため入手できないが、ピン配置やコマンド一覧くらいは載っているのだ。
また、DoCoMoやSBMの技術情報も面白いかもしれない。
「おサイフケータイ」という言葉についても知っておくとよいかも。


NXP

Androidに搭載されているPN544などで有名な、NXP。
もちろんNFCだけでなく、半導体全般をやっている。
巨大だ。
そして、公開されている情報も多い。
型番がわかれば、ネットで検索すれば出てくるくらいである。
PaSoRiやRC-S620/SなどのRC-S956系チップが搭載されたR/Wを使う場合、同じICバージョンのPN533を参考にするとよいだろう。
http://www.nxp.com/documents/user_manual/157830_PN533_um080103.pdf
もちろん、異なるコマンドもあるが、参考になる。
コマンドが異なるかどうかは、やってみるのが一番簡単だ。

いろいろとリンクを載せたかったのだが、メインで見ているのは上記2社だった。
あとは、随時検索している。
「NFCの情報」とひとことで言っても、種類がいろいろある。
私が主に知りたいのは、NFCカード(PICC)やR/W(PCD)の制御方法だ。
SDK for NFC Starter KitやAndroid APIのように、アクセスできるようにしたライブラリの情報を知りたい人もいる。
NFCカードに書き込まれたデータ(NDEFなど)に興味を持つ人もいる。
そしてそれらを使ったサービスに興味がある人もいる。
私が検索した感じでは、サービス関係の結果が多かったように思う。
まあ、お金などに関係するから、興味を持つ人が多いのだろう。
Androidに搭載されるようになったことで、開発側の人も興味を持つ人が増え、それにつれて情報がたくさん出てくるようになった。
私にとっては、それが一番嬉しい。
そしてだんだんと、自分でNFCアプリを作ってサービスも提供するような人が出てきた。
あまりサービスに興味を持っていない私であるが、「安くやりたい」の効果が一番大きいのはサービスの開発だと思う。
サーバは安く構築できる時代になったし、携帯電話に搭載されて敷居が下がり、環境はかなり整ってきた。
「カードをかざす」という行為自体も、敷居が下がったと思う。
次は我々の番だ、ということかもしれませんな。

FeliCa LiteとNFC-F

FeliCa Liteという、FeliCaのカードがある。
FeliCaのカードの一種というよりも、FeliCa Liteというカードと認識した方がよい。

 

NFC Forumのドキュメント「NFCForum-TS-Type3-Tag_1.1」によると、NFC-FのType3タグで使用できるコマンドは3つである。

  • Polling
  • Check
  • Update

FeliCa Liteユーザーズマニュアルでは、こうなっている。

  • Polling
  • Read Without Encryption
  • Write Without Encryption

名前は違うが、同じ機能だ。


FeliCa Liteカードは、そのままでは「FeliCa Lite」だ。
これを「NFC-F」にするには、MCブロックを書き換えなくてはならない。

簡単なのは、ツールを使うことである。
http://www.sony.co.jp/Products/felica/business/products/tagreader.html

また、カードを使うときの捕捉方法も気にしなくてはならない。
日本語版の資料が見つからなかった・・・。
http://www.sony.net/Products/felica/business/tech-support/index.html#NFC01

2012/01/26

[nfc]カードを手に入れる

リーダライタを買い、パソコンでアクセスできるようにしたとしよう。

次にほしいのは、読み取るカードであろう。
最近の人であれば、NFCチップが入った携帯電話を持っているかもしれない。

しかし、何台も持っているわけじゃなかろうし、パッシブなカードがあっても困るものではなかろう。


日本であれば、とりあえずSuicaみたいな交通カードが手軽だろう。
入手しやすいし、乗り物に乗ることもできる。
私はnimocaを持っている。nimocaはいいぞー。

いいのだが、セキュリティが厳しいので、あまり自由に扱えない。
書き込みもやりたいなら、別のカードがあった方がよい。

 

会社によっては、社員証がNFCカードということもあろう。
私は2つ社員証があるが、どちらもNFCだ。
しかし、社員証に間違って書き込んで壊してしまうと、弁償ものだろう。
「安くやりたい」のであれば、そういった危険は排除すべきだ。

 

となると、自由に使えるカードを購入する、という手段が残る。
お金はかけたくないのだが、仕方あるまい。

私は、スイッチサイエンス社から購入した。

http://www.switch-science.com/products/list.php?category_id=52

けちくさいので、FeliCa Liteカードを2枚だけ買っている。
もっと買えばよかったような気もするが、たくさんあっても仕方ないといえば仕方ない。

FeliCa LiteはNFC-Fカードにもなれるが、他のTechnologyも試したかろう。
それなら、Mifareだろうか。taspoもあるかもしれんが、私はタバコを吸わんのでわからん。
私はMifare 1Kを10枚と、Mifare Ultralightを1枚買った。
Amazon・・・だったと思う。
orange tagsさんだ。

Type-Bのカードは、住基カードとかIC免許証くらいしか思いつかない。
海外ではかなり使われているようなのだがね。
BはAやFとはしくみが違うらしいので、まだ動かしたことがない。

 

携帯電話に搭載されているならば、それはなかなか役に立つ。
私の場合はP906iという携帯電話を持っているのだが、PaSoRiから無線が出てるかどうかの確認に使うことができる。
無線の領域に入ると、LEDが点灯するからだ。
いやいや、携帯電話は便利なものだ。

PaSoRiも、旧タイプは搬送波を出すとき(検出?)にLEDが点灯したものだが、今はコストダウンのために黒PaSoRiになってしまった。
惜しい。


数回にわたって「安くやるには」と目標としてやってきたのだが、カードについてはいいアイデアが浮かばなかった。

FeliCaのハッカソンなんかにいくともらえた、という話を聞いたこともあるので、開発の勉強になるしカードももらえるし、で行ってみるといいのかも。

ACR-122UというR/W (2)

APDUについて書こうと思ったが、今日は読む時間が取れなかった。

ACR-122Uの送受信データを見せてもらった。
PN533系のコマンドに似ているが、PN533には0x60というコマンドはない。
話によると、ACR-122UはPN532が搭載されているということであった。
PN532のドキュメントを見ると、0x60はInAutoPollというコマンドで、引数で指定したターゲットをポーリングするコマンドのようだった。
ほほう。

PN533やRC-S956(PaSoRi)とPN532は、コマンドが多少異なる。
PN533とRC-S956は、GetFirmwareVersionで取得するとわかるが、同じようなバージョンである。
PaSoRiやRC-S620/Sを使いたい人は、PN533のドキュメントを見ると良かろうというのは、そういうことなのである。

 

昨日気にしていたPseudo APDUだが、タグやR/Wに対して直接コマンドを送信するために使うようである。
4byteの識別子のようなもの "FF 00 00 00"と、送信するデータ長、そしてデータで構成される。
libnfcのACSドライバは、このモード(Direct Transmit)しか使っていない。

 

今日は読まないが、PC/SC Workgroupのドキュメントがあったので、リンクだけ置いておく。
http://www.pcscworkgroup.com/specifications/specdownload.php


日本語でしか書いていないブログだが、英語圏の人に読んでもらってるとは思っていなかった。
ありがたいものである。

日本語なら自由に書けるのだが、英語の読み書きは非常に苦手としている。
応答がおかしかったとしても、気にしないでください。

2012/01/25

[nfc]NFC開発をするときに安くやりたい(ドキュメント編 - 2)

JIS

実は、NFCについて日本語の規格書がある。
それが、JISのドキュメントだ。
まずは、こちらのページを見ていただこう。
http://www.jisc.go.jp/app/pager?id=31259&%23jps.JPSH0090D:JPSO0023:/JPS/JPSO0090.jsp=&AKKNB_vJISJISNO=X6319-4
JISの規格書は、なんと制約付きではあるものの、無料で読めるのだ(保存も印刷もできん)。
上のリンクは、X6319-4という規格のものだ。
Adobe Readerでしか、私は読めなかった。
なんでいきなりこのリンクかというと、このURL自体はどこかでリンクされていたものなのだ。
本来は、JISの検索ページから、キーワードを入力して検索し、PDFを読むようになっている。
そしてそのURLは一時的なもののようで、リンクしてもだめだったのだ。

前置きはこれくらいにして、日本語で読むことができる規格書という意味で、しかも無料で読めるということもあり、ここはとっかかりとしてはいいんじゃなかろうか。
では、何を読むとよいだろうか?
先ほどのX6319-4もよいが、私はこれを勧めたい。
  • JIS X5211
実はこれ、NFCIP-1なのだ。
JIS規格番号からJISを検索に「X5211」と入力して検索してみよう。
「システム間の通信及び情報交換-近距離通信用インタフェース及びプロトコル(NFCIP-1)」というものが出てくるはずだ。
PDFを開くと、右上に「ISO/IEC 18092」とある。
つまりまあ、3つとも同じようなものを指すわけだ。
それなりに長い文書だが、これを読むとNFC Forumの「Digital Protocol」の半分くらいを読んだと思ってもいいんじゃないだろうか。
日本語だとわかりにくいときは、案外と英語版を読むとわかりやすかったりするので、両方見比べながら読むとよいだろう。
それに、これもまた全部は読まなくていいだろう。
無線の仕様なんかは、興味ないと思う。

X5211というか、JISの文書は見出しのフォントがあまり目立ってないので、読みにくい。
つらつらと読んでいたら、いつのまにかType-AじゃなくてFeliCaの章に入っていた、ということがあった。
ECMAの方が見やすさとしては上かも。

今日の補足:無線


私の本職は、FeliCaやNFCはまったく関係がない(FeliCaはちょっとやったことがあるか)。
しかし、偶然というか何というか、無線関係のお仕事をやっている。
メーカー勤めじゃないので、今はそういう仕事をしているというところだ。
わからんわからん、関係ない関係ないと思っていたが、仕事のおかげでNFCのドキュメントに書いてある無線部分がわかるようになってきた。
何が関係するかわからないものである。

無線(RFって略す。Radio Frequency。高周波、という方が多いのかな)の回路はよくわからないのはあいかわらずだが、ソフトでどういう風に制御するものなのかがわかってきた(気がする)。
NFC-A, B, F、ともに13.56MHz帯の周波数を使うが、それだけじゃなくて通信速度も合わせないとどうにもならない。
電波は、空気中をものすごく飛び交っている。
その中から、周波数が一致するものを取り出す。取り出すだけだと単なる1/0なので、その1/0がどういう速度で送られているかを調べる。
だいたいは、周波数と通信速度が一致したものを見つけ出すことになる。
NFC-A, Bは106Kbpsで、NFC-Fは212Kbpsと424Kbps。
符号化に「マンチェスタ」というのが出てくる。
これは、暗号化のためやデータ圧縮のためではなく、通信の性能?をいじするためのようだ。
8b10bとか、そんな通信のための符号化があるようなのだ。
「1と0が適度にばらつかないと、周波数が偏る」って説明してもらった。
X5211のp.11に図があるが、1bitを0→1や1→0の変化で表すようになっている。
つまり、1bitのデータを2bitで表現しているのだ。
だから、実際のビットレートはさらに半分になっていると思われる。

ほかにも、キャリア、とか、センス、とかいろいろあるが、それぞれ本当に意味があるのだ。
無線をやって、実感できたのはここ1年の収穫だと思う。
まあ、それがNFCに役立ってるかどうかは知らんが、少なくとも用語に怯えることはなくなったので、よしとしよう。

ACR-122UというR/W (1)

ACR-122Uとは、Advanced Card Systems社が販売しているNFC Reader/Writerである。
コメントで情報をいただいたので、まとめてみよう。


購入は、ベルギーのtouchatag社や、香港のACRからできるらしい。
タグが10個ついて、39.95ドルとなっている(税別)。
今日は1ドル=77.6円くらいなので、3100円くらいになる。

FeliCa Liteのカードは、350円くらい。
PaSoRi+FeliCa Lite x 10 = 2300 + 350 x 10 = 5800円。


ACR-122Uについては、メーカーのサイトから情報を入手できる。

日本語
English

技術資料のPDFもあるので、探す手間が省ける。


私は詳しくないのだが、本体がCCIDとPC/SCに対応しているらしい。
(PaSoRiもPC/SCドライバがあり、Type-Bへのアクセスができる。)
Personal Comuputer /Smart Card。WindowsでICカードを利用するための標準API仕様とのことだ

CCIDは、Chip/Smart Card Interface Devicesという仕様らしい
これも、Windows/Microsoftの仕様ということだろうか。

ACR-122Uは、Windows、Linux、Macなどのドライバが提供されている。
SDKは、Windowsのようだ。


いただいたコメントで気になったのは "pseudo-APDU"というもの。
Application Protocol Data Unit。

http://acs.com.hk/drivers/eng/API_ACR122U.pdf
p.5に、ACR-122Uと通信するときのフローチャートがある。
PCとは、PCSCで通信することになる。

p.6以降に、PICCと通信するときのインターフェースが記載されている。
PICCというのは、Proximity IC Cardの略で、今回はNFCカードのことになる。
このコマンドが、他社のR/Wとはかなり異なる。
PC/SC対応によるものかもしれないが、私は普段、R/Wに有線プロトコル(wired-protocol)を送信してアクセスしているので、気になった。

 

コメントによると、FeliCaのアプリ層プロトコルは、4byteの"疑似APDU"ヘッダを追加するとのこと。
先ほどのPDFでは、p.22にFeliCaタグアクセスについて記載されている。


今日は、ここまで。
次回、Pesudo APDUがどういうものか見ていこう。

2012/01/24

[nfc]NFC開発をするときに安くやりたい(ドキュメント編 - 1)

NFC Forum

簡単に手に入るのは、NFC Forumからだろう。
メンバーのみのページもあるが、非メンバーもダウンロードできる。
簡単な登録はいるけれども、メールアドレスくらいだし、メールが来たことはない(たぶん)。
英語だけなのでいやになるかもしれないが、全部読まなくてよいと思う。
いるとこだけで十分ではないかね。
それでもどれか選べといわれたら、Digital Protocolのドキュメントかなぁ。
でも、これもちょっと分量が多いし、初めてにしては取っつきにくい。




今日の補足:用語の種類


これからいくつかドキュメントの話をするが、用語が全て統一されているわけではないことは覚えておいた方がよいだろう。
例えばFeliCaに「IDm」って識別子があるが、NFC Forumでは「NFCID2」と呼ばれる。
SAKとSEL_RES、みたいなものもあるし、自分で対照表を作っておくといいのかも。
でもまあ、無線のプロトコルを直接扱わない限りは、そこまで気にしなくてもよいのだが。

もう少し補足:エアプロトコル


それと、NFC Forumで規定しているのは、あくまで無線(RF)上のプロトコルだ。
私は、エアプロトコル、と呼んでいる。
PaSoRiのようなリーダライタをパソコンからアクセスする場合は、有線のプロトコルでやらないといけない。
ワイヤードプロトコル、と呼んでもいいかもしれん。
リーダライタの上に置いたカードに無線を飛ばしたいのであれば、リーダライタに有線プロトコルを使ってエアプロトコルを指示しなくてはならないし、その応答も有線プロトコルのフォーマットになっているので、それを解析しなくてはならない。



最後に補足:規格


ひとことで「NFC」というが、これは単に「近接型無線通信」くらいの意味しかない。
「NFCの規格」というと、これがまたたくさんある。
2大規格書は、これだろう。
  • ISO/IEC-14443
  • ISO/IEC-18092
14443は、Type-A、Type-Bの規格書らしい。
なぜ「らしい」かというと、読んだことがないからだ。
無料のが見つからなかったのでね。
どうも世の中で「NFC」というと、Type-AのMifareを指しているようにみえる。
taspoもType-Aだ(持ってないけど)。
Type-Bは、運転免許証や住基カードで使われている(持ってないけど)。
当時は、Mifareを吸収したフィリップス社と、Type-Bをやってたモトローラ社が、14443の中心となったという記事を読んだ。1994年くらいか。
FeliCaもここに入ろうとしたけど、なんかだめだった。
ちなみにフィリップス社から分離したのが、NXPだ。
HPとアジレントの関係みたいなものかな。

それから、FeliCaとフィリップス社が、18092の中心となった。
18092を整理したのか何かわからないけど、「NFCIP-1」と呼ばれている。
まあ、18092もNFCIP-1も同じものと思っていいんじゃなかろうか。
ECMA-340なんかも、NFCIP-1みたいだし。
国際規格は、なんかどれも似たようなものが多くて、紛らわしい。

気付いたかもしれんが、Type-Aは14443も18092も、どっちも入っているのだ。
そういう意味では「NFCといえばType-A」というのもあながち間違いではない。
Type-Aっていっておけばどっちにも当てはまる、という意味でだが。

NFC Forumのドキュメントは、どっちも組み込んでいる。
Android Beamなどで使われているDEP(LLCPやSNEP)は、18092側の規格だ。
(その代わり、AndroidのAPIとして使えるのは14443のDEPだけど。)

いかん、長くなってしまった。
規格の流れは自信がないので、言葉多くなってしまうな。
次回は気分を変えて、JISのドキュメントにしよう。

2012/01/22

[nfc]パソコンでNFC開発をするときに安くやりたい(ハード編)

Windows

Windowsといっても、いろいろある。
すまんが、私はXP 32bitしか持ってないのだ。最新のことはよくわからん。
パソコンにNFCのリーダライタがあればいいが、ないと思う。
安いのは、SONYのPaSoRi。今はRC-S370がいいんじゃないか。
PaSoRiは、FeliCaだけでなく、NFC-A/Bもいける(もちろん、NFC-Fも)。
Amazonで2300円くらい。
デバイスだけでなく、カード側もほしいかもしれん。
まあ、カード側はパソコンとは別になるので、あとにしよう。
リーダライタが入手できたら、次はソフト開発環境だ。
ソフト側は、選択肢が少ない。
まあ、SONYのSDK for NFC Starter Kitが普通の選択肢だろう。
Starter Kitは商用利用できないが、無償だ。
これは、PaSoRiでリーダライタ機能と、アドホック機能(PUSH、FALP)を提供するライブラリとドキュメントだ。
(FALPは、フィーチャーフォンからのFALP受信はできなかった。)
ビルド環境がいる。
Starter Kitには、Adobe/AIRでやるものと、C++などでやるものがある。
すまんが、Adobe/AIRはよくわからんので、割愛させてもらう。
C++などは、MicrosoftのVisual Studio Expressを使うと良かろう。
ユーザ登録がいるが、無償で使うことができる。
これだけでは、まだ不十分だ。
NFCに関するドキュメントがいる。
まあ、これもパソコンには関係がないので、あとだ。

Linux

さて、Linuxの場合はいろいろと事情が異なる。
PaSoRiのライブラリが提供されていないので、普通の手段ではPaSoRiが使えないのだ。
libusbという、LinuxでUSBを使うためのライブラリがある。
これを利用したlibpafeというPaSoRiライブラリがある。
FALPはできないが、リーダライタ機能は動く。
PaSoRiに特化していたと思うので、NFC-AやBは無理だろう。
完成度として高いのは、nfcpyだと思っている(使ったことないけど)。
Pythonでアクセスするのだ。
これは、たぶんSONYの人がやっているところで、PaSoRiもいける。
libnfcもある。
これもPaSoRiがだいたい使える。
ビルド環境は、gccでよい。


PaSoRiを使わず、別の手段を考えてみよう。
組込み用途のRC-S620/Sを使うのだ。
どこから入手するんだ?ということになるが、スイッチサイエンス社がよいだろう。
RC-S620/S本体と、接続しやすくする基板、RC-S620/Sは3.3V/5VのUARTなのでレベルコンバートしてシリアルに変換するようなものがあればよい。こんなのとか。
RC-S370もRC-S620/Sも、FeliCaチップとしては同じRC-S956というものが載っている。
RC-S956は、コマンドを送信すると、うまいこと処理をしてレスポンスを返してくれる。
そのコマンドとレスポンスの経路が、RC-S370だとUSBだし、RC-S620/Sだとシリアルというだけのことだ。
SDK for NFC Starter Kitなどのライブラリは、その経路を隠蔽して使いやすくしてくれていると考えればよい。
つまり、隠蔽するところも自作してしまえば、別にRC-S370だろうとRC-S620/Sだろうと関係はないのだ。
つまり、WindowsもLinuxもないことになる。
RC-S620/Sは、自分でコマンドを送信しなくてはならない。
SONYから簡易コマンド仕様が出ているので、これを利用する。
サンプルがほしいかもしれないが、パソコン向けではなくArduino向けがある。
読むのはそんなに難しくないので、ここを足がかりにするとよいだろう。

私はどうしているかというと、自分でRC-S956用のライブラリを作り、libusbを使ってPaSoRiにアクセスしたり、シリアルでRC-S620/Sにアクセスしたりしている。
「それよりも、リーダライタはSONY製以外にないの?」と思ったかもしれん。
私もそう思って探したのだが、安いのは探せなかったのだ。
実は選択肢はあるのだ。
ACR-122とか。これはlibnfcでも一応対応はしているらしい。
ACR-122は、タグとセットでtouchatagというところで販売されているとのこと(Tyson Keyさん情報)。
NFC開発スターターキットとか。Amazonでも売ってた。
でも、PaSoRiよりは高いのだ。
もちろん、情報もセットで売られているので、「どこから始めたらいいんだろう」と迷う時間は大幅に削減される。
仕事だったり、急ぎだったりするなら有用だと思う。
ただ、個人の趣味でやるのなら、あまりお金はかけずにやりたいではないか。
そしてできれば、ライブラリでは提供していないようなすべての機能を使いつくしたい。
そういう意味では、OpenPCDってのは究極かもね。

とはいえ・・・それをやっていると、NFCサービスというものになかなか近づかない。
FeliCaとかMifareのカードにアクセスしたいだけなのに、USBがどうの、シリアルがどうの、リーダライタの仕様がどうの・・・などとはやりたくなかろう。
なので、そういうところは他の人に任せて、自分の好きな分野をやるのによい近道を探すといいんじゃなかろうか。
まあ、NFCの規格は知っておいた方がいいと思うので、次回はドキュメント編をやろう。
(いつになるかわからんが・・・。)

[qt]QListWidgetへのアイテム追加

Qtでリスト形式の表示をさせたい場合、DesignerのUI一覧を見ると「Item Views(Model-Based)」と「Item Widgets(Item-Based)」の2つがある。

そう書くと混乱しそうだが、それぞれ別のclassなので大丈夫だ。

  • Item Views(Model-Based)・・・List View・・・QListView
  • Item Widgets(Item-Based)・・・List Widget・・・QListWidget

Qt本の「10章 アイテムビュークラス」によると、少量のデータを表示させるようなよくある場合には「QListWidget」を使い、大量のデータを使うなど工夫がいるような場合はデータモデルと「QListView」を組み合わせてMVCをやんなさい、ということらしい。

QListWidgetのヘッダファイルを見るとわかるが、QListViewを継承している。
今回は、このQListWidgetにアイテムを追加してみよう。


QListWidgetクラスに対してQListWidgetItemクラスがあり、表示されるのは追加されたQListWidgetItemになるそうだ。

追加しそうなメンバ関数の名前は、こんなのだ。

  • addItem()
  • addItems()
  • insertItem()
  • insertItems()
  • setCurrentItem()
  • setItemWidget()

addItem系は、末尾に追加。
insertItem系は、指定した行に追加。
setCurrentItem()は、現在のQListWidgetItemの差し替え。
setItemWidget()は・・・よくわからん。指定されたアイテムに表示させたいウィジェットを設定する?とかなんとか。

 

アプリを起動したときに、既にリストに文字列が入っているような場合は、addItem()とかaddItems()でいいんじゃなかろうかね。
文字列だけなら、QListWidgetItemインスタンスを作らずとも、QStringを指定できて楽そうだ。


では、addItems()でやってみよう。
これは引数として、const QStringList&を渡すことになっている。

QStringListを初期値入りで作るなら、コンストラクタでやってしまえるようだ。
複数データを設定する場合は、

  • QStringList(const QList<QString>&)
  • QStringList(std::initializer_list<QString>)

この2つがある。

QListを初期値入りで作るなら、

  • QList(std::initializer_list<T>)

std::initializer_listってのがあるらしい。
昔はなかったような気がするが、時代に乗り遅れたのか・・・。

初期値入りにこだわったのは、ちょっとしたツールくらいだったら文字列固定で済むことが多いからだ。
どっかのリソースから引っ張ってこないといかんのなら、QStringListに<<していってもいいだろう。
CSVみたいにセパレータが決まっているなら、1行をQStringで読み込み、split(",")などとするとコンマ区切りでアイテムを追加してくれるみたいだ。


ここを読み、C++11対応。
initializer_listはC++11なのだ。だから知らんのだ。
http://labs.qt.nokia.co.jp/2011/06/09/cpp0x-in-qt.html

proファイルに、以下を追加。

QMAKE_CXXFLAGS += -std=c++0x

・・・ビルドエラーになった。
::swprintfと::vswprintfがわからんとおっしゃる。

stdio.hをインクルードする前に、undefすることで対策できるらしい。
http://stackoverflow.com/questions/3445312/swprintf-and-vswprintf-not-declared

確かに、通った。
通ったけど、納得いかん。
全ファイルにundefなんか、わざわざ書きたくないぞ。

makeのオプションに-Uってのがあるので、それでよいのか。
http://stackoverflow.com/questions/6699734/qt-creator-compilation-error-swprintf-and-vswprintf-has-not-been-declared

 

mingwの問題だとは思うが、直った方がうれしいですな。


std::initializer_list<T>は、そんなに難しくないみたいだ。

#include <initializer_list>
 
std::initializer_list<QString> ilist = {
    "str1", "str2", "str3", ...
};
ui->listWidget->addItems(ilist);

 

QStringListインスタンスを作らずとも、std::initializer_listから直接いけた。
うーむ。

これはおそらく、『プログラミング言語C++ 第3版』の「11.3.3 初期設定」と「11.4.1 曖昧さ」から読み取れるんじゃなかろうかと思う。

「11.3.3 初期設定」には、こうある。

単一の引数を取るコンストラクタは、その引数の方からコンストラクタの型への変換方法を規定する。

QStringListにはstd::initializer_list<T>を1つだけ引数に取るコンストラクタがある。
だから、これはコンストラクタであると同時に変換方法でもあるのだ。
また、こうもある。

つまり、引数を1つ取るコンストラクタは、明示的に呼び出されるとは限らない。

本には例が載っているのだが、そこら辺は読んでおくれ。
明示的なだけでなく、暗黙で呼び出されることもあるという話だ。
まあ、わざわざ

char c = (char)0;

みたいなのはめんどくさいよな。

「11.4.1 曖昧さ」には、ルールとしてこうある。

文法上認められているユーザー定義の暗黙の変換は、1レベルだけである。

なので、たどりたどってわけがわからないコンストラクタが呼び出されることはなく、型変換が発生する可能性があるコンストラクタだけ探してみればよいことになる。


心配性なので、デバッガで確認した。
うん、addItems()のときにQStringList(std::initializer_list<QString>)が呼び出されている。
確認できて、安心した。

 

QStringListにはコンストラクタが追加されたので、わざわざinitializer_listを使わずともよさそうだ。

QStringList str = {
    "str1", "str2", "str3", ...
};
ui->listWidget->addItems(str);

2012/01/20

[無駄話]初心を思い出さねば

鉄は熱いうちに食え、という(いわない)。
Qt熱が熱いうちに、いろいろと作って覚えてしまわねば。
私は体で覚えるタイプみたいなので、効率が悪くてもたくさん作るしかない。
ちなみに学生の時は、紙に何度も書いて覚えました。

さて、Qtのボタンとかラインエディタとかは使ったので、新たに何か使おう、と思い立った。
選んだのは、リスト。
選択肢が表示されていて、それをクリックして選択できる、あれだ。
私が最近使っていた統合開発環境は、Visual C# 2010 Expressだった。
あれもGUIで画面設計ができる。
便利なことに、例えばリストであれば、リストを画面にD&Dで載せ、そこにプロパティ値として項目を入力できるのだ。
簡単なアプリの場合にはそれでいいのだけど、データが可変だったりすると、データベースに置かれていない限りは自分で実装しないといけない(のだと思う・・・)。

Qtは、そういうプロパティはない。
タイトルなどはプロパティとして設定できるが、項目のようなものはソース上に実装することになる。
C#もそうなのだが、別にGUI開発環境がなくても、テキストエディタでソースを全部書いてしまえばちゃんと画面を作ることができる。
どこまでをGUI設計画面でもできるようにするか、という違いがあるのだな。
そこら辺が見えるところが面白い。
そういえばC#を初めて使ったときも「おお、GUIでここまで入力できるんだ」と感心した覚えがある。
初心に帰れば、Qt Creatorもかなり便利だ。

ふっと思ったのだが、GUI画面で文言入力できるのって、どうなんだろう。
簡単に思いつくのが、言語変更。
日本語が「おはようございます」なのに、英語が「hello」だったら、全然幅が異なる。
そんなのに全部対応することを考えるくらいなら、自動レイアウト調整に任せて、文言は一覧表で管理したくなる。
C#だと、.configファイルなどにまとめるんだっけ。
Qtだと、tr("xxx")というように囲むことで、Linguistを使って抽出することができたような気がする。

ともかく。
人間だけでやる、ツールだけでやる、そんな一方的なやり方じゃなくていいだろう。
人間がやった方がいいなら、人間がやり、ツールの方がいいなら、ツールがやる。
それでいいじゃないですか。。。
まとまりがなくなったが、私が今回思ったのは「データはソース側に書いた方がメンテナンスしやすいかも」ということだ。
仕事でC#でツールをよく作るのだが、その反省という意味もある。

2012/01/18

[qt]SAKの解析をするアプリを作ってみた

SAKというのは、SEL_RESのことだ。
NXPのドキュメントに沿って、解析・・・というほどでもない。
このくらいのアプリなら、Qt初心者に最適だろう、と思って作ってみた。

うん、ほどよかった。
解析部分だけ、載せておこう。
Qtっぽいのは、QStringを返す部分だけだがね・・・。

QString analyzeSak(int hex)
{
    uint8_t sak = (uint8_t)(hex & 0xff);
 
    if(sak & 0x02) {
        return "RFU";
    }
    if(sak & 0x08) {
        if(sak & 0x10) {
            return "MIFARE 4K";
        } else {
            if(sak & 0x01) {
                return "MIFARE Mini";
            } else {
                return "MIFARE 1K";
            }
        }
    } else {
        if(sak & 0x10) {
            if(sak & 0x01) {
                return "MIFARE Plus 4K(SL2)";
            } else {
                return "MIFARE Plus 2K(SL2)";
            }
        } else {
            if(sak & 0x20) {
                return "ISO/IEC 14443-4";
            } else {
                return "MIFARE UL";
            }
        }
    }
 
    return "unknown";
}

 

GUI側は、16進数になる文字列しか受け付けないようにしたり、メニューバーにActionをつけたりとか、華々しい(?)ことをしている。
それでも、コード量は少ないな。

もちろん、C#でも同じことはできるし、開発環境はすぐれていると思う。
でも、Qtだと「組んでる」という気分になれるので、楽しい。
技を覚えていきたいところだ。

2012/01/17

SDK for NFC Starter Kitサンプルのまとめ

今まで、SDK for NFC Starter Kitでサンプルを作ってきた。
まとめだ。
番外編だけど新作もあるよ。

ファイルはすべてgithubにあります。
https://github.com/hirokuma/NfcStarterKitWrap


NFCIDを読む

記事 : http://hiro99ma.blogspot.com/2012/01/nfcsdk-for-nfc-starter-kitnfcid.html





FeliCa Liteを読み書き

記事 : http://hiro99ma.blogspot.com/2012/01/nfcsdk-for-nfc-starter-kitfelica-lite.html



Mifare Ultralightを読み書き

記事 : http://hiro99ma.blogspot.com/2012/01/mifaremifare-ultralight.html



Mifare Classic 1Kを読み書き

記事 : http://hiro99ma.blogspot.com/2012/01/mifaresdk-for-nfc-starter-kitmifare.html


FeliCa Liteの一次発行寸前までやってみる

記事 : http://hiro99ma.blogspot.com/2012/01/nfcsdk-for-nfc-starter-kit.html





そして新作。

モバイルFeliCaにURLをPUSHする

30分くらいで作るつもりが、1時間近くかかってしまった。
最近やってたサンプルがMifareだったので、送信するコマンドの先頭に「データ長」を追加するのを忘れてたのだ。



なんで急にまとめ記事を書いたかというと・・・気分転換だ。
本業の進みが悪いので、自分がやってきたことを見てみたかったのだ。
ああ、自己満足だよ・・・。

2012/01/15

Comodo + gdbでSIGSEGVになる場合

Qtでデバッグしようとすると、guard32.dllでSIGSEGVになる。

ということは、ずいぶん前に記事にしていた。私も忘れていた。
対処していたはずなのだが、Comodoのアップデートかなにかで、guard32.dllが復活していた。
またいつ復活するかわからないことを思うと、別の対策をしておきたい。


どうやら、ComodoファイアウォールとGDBの組み合わせで発生するらしいのだ。
ならばComodoをやめればいいんだけど・・・これよりもよさそうなファイアウォールが見つからないのだな。

この対策を入れると、出なくなった。
http://forums.comodo.com/defense-sandbox-help-cis/gdb-problem-solved-t47299.0.html;msg487021#msg487021

ここまでやらんといかんのか・・・という感じではあるが、Qtのプロジェクトは同じ配下に作成するので、まあ悪くはない。
Defender+は無効にしているけど、それだけではだめってことなんだろうねぇ。

[qt]Qt Designerで作成したスロットを消すときは、ヘッダファイルから宣言を消す

Quitメニューを作った。
これを選択したときに、MainWindowのcloseスロットが呼ばれるようにした。

・・・と思ってアクションエディタから「スロットへ移動...」とし、シグナルとしてtriggered()を選択すると、メンバ関数ができた。
いや、やりたいのはこれじゃないのだ・・・。

 

メンバ関数を削除して、シグナル/スロットエディタで追加した。
Quitメニューで右クリックしても、スロットを選択できそうな選択肢が出てこないのだ。
まあ、デザイン画面ではアクションを割り当てるのみで、アクションがどういうふうに動くのかはシグナル/スロットエディタなどで設定するということなのだろう。

 

それはよかったのだが、コンパイルするとエラーになった。
on_action_Quit_triggered()がない、と怒られた。
あー、これはさっき削除したメンバ関数だな。
エラーになったのはmocファイルなので、qmakeか何かが自動生成している部分だ。
だから、mocファイルを変更しても意味がない。
一度作ったスロットをやめるにはどうしたらいいのだろうか?


これは、ヘッダファイルの「private slots:」にあるon_action_Quit_triggered()を削除する必要がある。
mocはヘッダファイルから情報を集めてくるから、そういうことになるのだ。

 

GUIのツールは便利なのだが、一度行った操作の取り消し方法も把握しておかないと自由に使えないからな。


本当は、Quitアクションをメニューに追加するのではなく、メニューの項目(FileとかEditとかみたいな項目)をQuitにし、押したらアプリが終了するようにしたかったのだ。

GUIで操作する限りでは、いきなりアクションを割り当てることはできないように思う。
メニューの項目はQMenuで、アクションはQAction。
メニューはQMenuBar。
QMenuBarには、addMenu()もaddAction()もあるなぁ。
しかし、ウィジェット一覧にはActionがないし、アクションエディタからメニューバーにD&Dしても拒否される。

コンストラクタにこんな行を追加した。

ui->menuBar->addAction(ui->action_Quit);

こうすると、期待する動作になった。
そういうものか。

 

Qt Creatorのテキストエディタは、メンバ関数などのサポート情報がTipsとして表示されるのだが、QMenuBar::addAction()にある3つのオーバーライド定義のうち、2つしか表示されなかった。
上記のメンバ関数は、表示されなかったメンバ関数なのだ。

QMenuBarという文字列の上でF2キーを押すと、qmenubar.hが表示された。
こんな定義になっている。

#ifdef Q_NO_USING_KEYWORD
void addAction(QAction *action) { QWidget::addAction(action); }
#else
using QWidget::addAction;
#endif
QAction *addAction(const QString &text);
QAction *addAction(const QString &text, const QObject *receiver, const char* member);

#ifdefがあるソースでは、Tipsが表示されないのかもしれない。

気になるのは「Q_NO_USING_KEYWORD」というもの。
「キーボードを使わない」という定義だろうか?
まあ、QWidget::addAction()があるので、そちらが呼ばれたと考えてもよいのではあるが、気になる。

ちがうちがう。
キーワード、だ。
global.hに定義が見られるのでコメントを読むと、どうもコンパイラによってはusingをうまく処理できないものがあるから、ifdefでわざわざ対応しているということらしい。
それならば、納得だ。

[qt]Qt Designerで生成されたオブジェクト名を一度削除した名前に変更したい

とりあえず何か自作のアプリを作ろうとでもしないと、Qtを覚えそうにない。
SAKからカード種別をチェックするような、簡単なアプリを作ろうとしている。

MainWindowを作成し、メニューに「Quit」を追加。
うーん、なんか気に入らないので、削除。
あー、でもあった方がいいかも、と思い直して、追加。
そんなことをしていると「action_Quit_2」というオブジェクト名になってしまった。

1つしかないから、「action_Quit」でいいのだが。
そう思って編集しようとしたが、だめ。

どうも、Designer上で削除しても、uiファイルには残っているようだ。
だからリネームしようとしても、同じ名前のオブジェクトがあるため変更できない、と。

 

テキストエディタでuiファイルを開いて修正すれば、直った。
しかしそれもスマートじゃないよなー、と思ってDesignerを見ていくと、アクションエディタにaction_Quitが残っていた。
これっぽい。

action_Quitを削除し、残ったaction_Quit_2を「action_Quit」にリネームすると、直った。
そういうものだってことで。

[qt]サイズ調整する際には、親ウィンドウも含めたレイアウトが必要

Qt Creatorを使っていて、よくわからないことがある。
それは「サイズ調整」の動作だ。
ウィジェットを配置して、さあウィンドウのサイズを自動調整だ、と実行すると、変なサイズになってしまう。

 

image

image

ああ・・・


しかしQt日本語サイトでの説明も、同じような感じで使っているのだが、ちゃんとサイズが合うようだ。
http://labs.qt.nokia.co.jp/2010/08/19/qt-designer.html

確かめよう。

image

image

あ、うまくいった!

 

何が違うかというと、レイアウトだ。
最初の例では、レイアウトを使用していない。
また、レイアウトを使用する場合でも、中に配置したウィジェットに対してはレイアウトを使用しているのだが、親ウィンドウにはレイアウトを設定していなかったのだ。


組込みでアプリを作る場合は、画面サイズも固定されていることが多いので、自動調整する処理自体を省いて高速化させたいこともあろう。
レイアウトすらも削って、軽量化させたいかもしれない。

そう思って、自動調整後にレイアウトを削除してみた。
・・・うーん、ウィジェットの幅(ウィンドウじゃなくて)が変わるなあ。
QWidgetのgeometryが元に戻ってしまうようだ。
レイアウト削除してもgeometryを残す方法はないものかねぇ。

NFCキーボード

これはほしいかも、と思った。
ELECOMさんが展示会で発表したらしい、スマートフォン向けのNFCキーボードだ。

http://www.elecom.co.jp/news/201201/nfc/

スマートフォンは持っていないのだけどね。

これはきっと、DEPを使って実現しているはず。
おそらくAndroid向けだろう。
となると、IsoDepか・・・いや、ここはLLCPでconnectlessを使ってるんじゃないだろうか。

DEPが動くマシンを探していたのだが、これがちょうどそうなるんじゃないだろうか、と期待している。


というところに水を差すわけではないが、受ける側のソフトさえ作ってしまえば、PaSoRiなんかでも同じことができるはずだ。

もちろん、もちろんアイデアを作って製品として作り上げたELECOMさんに敬意を表しています。

ただ、アイデアが外に出た以上、実現することもできてしまうわけで・・・。

 

AndroidのAPIを見てみたが、LLCPってないんだな。
Android Beam/NDEF Pushで使っていて、アプリには解放していないということか。

となると、IsoDepを使うしかないのかな。
プロトコルスタックはIsoDepの上位にアプリが作成すること、となっているので、自前でやるしかないのか。

うーん、それだと魅力が少ないなあ。
IsoDepもPaSoRiで実現できるだろうけど、ちょっとなぁ。

[git]cygwinではfilemode=falseをglobal設定にしても、localでtrueになるみたいだ

私は既存のファイルをgithubに上げる際、Windowsではこんな順番で作業している。
  1. githubでリポジトリを作る
  2. 既存フォルダをcygwinで開く
  3. git init
  4. git add *
  5. git commit -m 'first commit'
  6. git remote ・・・(githubの手順に従うだけ)
その後は、TortoiseGitを使ってcommit/pushするのだが、いつも初回は全ファイルがcommit対象になってしまう。
これはどうやら、filemodeがtrueになっていて、ファイル属性が変更された、とみなされてしまうかららしい。
それはいいのだが、私はglobal設定でfilemode=falseとしている。
なんでいつもtrueになるんだろう?

検索すると、こんな話がされていた。
http://git.661346.n2.nabble.com/ignoring-file-modes-completely-td5995724.html
どうやら、chmod()をサポートする環境では、自動的にfilemode=trueになってしまうらしい。
うーん、globalは無視されるのか・・・。

解決方法は、cygwinでgit initせず、TortoiseGitでリポジトリ作成すること、だった。

2012/01/14

[mifare]Mifareのアクセスコンディション

前の記事でもちょろっと書いたが、Mifareのアクセスコンディションはめんどくさい。
しかし、読めばわかるので忘れないように書いておこう。
アクセスコンディションへの書き込みはまだやってないので、間違ってたらごめんなさい。

説明をするよりも、解析ツールを作った。
Excelだ。
https://sites.google.com/site/hiro99ma/home/experiment/card_security/type/MifareAccessCondition.xls

入力するところは薄い黄色セル、結果は青文字にしている。
あまり特殊なことはせず、仕様書にあるとおりに解析しただけだ。

Access conditionからAccess bitsを算出

自分でアクセスコンディションを設定したい場合は、C1, C2, C3に値を書き込むと、すぐ下のbyte6, 7, 8にアクセスコンディション値が出てくる。

Access bitsからAccess conditionを逆算

アクセスコンディション値を解析したい場合は、下側にあbyte6, 7, 8に書き込むと、黄色い表に結果が出てくる。
下の方に、OKとかNGとかが出てくる表がある。
これはチェック用で、byte6, 7, 8の値に矛盾があるとNGが出てくる。



neverは「不可」と解釈した。
Sector Trailの書き込み属性を「不可」にすると、きっともう書き込みができないのだろうと思う。
最初はneverを「認証不要」だと思っていたので、「なんで毎回Authenticationがいるんだ」と悩んでいた。
まあ、そういうこともある。
なお、byte6~8はアクセスコンディションで、byte9はユーザ用である。
なので、鍵バージョンの管理なんかに使うといいんじゃないだろうかね。

FeliCa Liteの運用と同じように考えると、鍵はreadを不可にし、writeのみ許可にしておくのがよいかと思う。
writeも不可にするといいのかもしれないが、何らかの理由で鍵が漏れてしまった場合のことを考えると、再度カードを作り直すよりも、鍵だけ書き直すようになるのではなかろうか。

[mifare]SDK for NFC Starter KitでMifare Classic 1Kに読み書きする

最後のサンプルになるだろうか。
SDK for NFC Starter KitでMifare Classic 1Kに読み書きするサンプルだ。
 
github
https://github.com/hirokuma/NfcStarterKitWrap/tree/master/ClassicReadWrite

さて、Mifare ClassicはUltralightとは結構異なる。
ドキュメントは、このあたりがよかろうか。
探せばたくさん出てくるので、検索してくだされ。
http://www.nxp.com/documents/data_sheet/MF1S50YYX.pdf
コマンドはだいたい同じなのだが、Writeは0xA0になる。
16byte書き込みだ。
つまり、メモリマップも異なるということである。
セクタとブロックで管理されていて、セクタは0~15、ブロックは0~3。
ブロック3は特殊用途で、鍵などが管理されている。
コマンドで指定する場合はセクタとブロックではなく、アドレスを指定する。
アドレスは、セクタ*4+ブロックになる(資料がどっかいった)。
そして、ReadやWriteをする前にAuthentication(認証)が必要だ。
この部分も汎用的に作ろうとしたのだが、読めば読むほど大変なことがわかった。
Classicカードは出荷状態では「鍵A or B認証」で、鍵は「FF FF FF FF FF FF」になっている。
・・・らしいのだが、出荷時は「transport configuration」なるものになっているらしく、鍵Bは使えないらしい。
なので、鍵Aを使って認証する。
そこを起点としてデータアクセスして、鍵AやBの設定などを行うことになる。


鍵情報はブロック3に入っている。
つまり・・・アドレスは連続しているけれどもブロック3で分断されることになる。
NDEFなんかはどうするんだろうね?
各セクタにはブロックが4つあり、それぞれ認証方法を設定することができる。
ドキュメントの、Access conditions、というやつだ。
ここが非常にめんどくさいと思う。
Access conditionは、ブロック3(sector trail、と呼ばれる)の6~8byteにある。
この3byteの各ビットが意味を持っていて、解析すると各ブロックのC1, C2, C3というデータが得られる。
このC1, C2, C3というデータの組とアクセス方法を対照する表があり、そこから指定したブロックをどのように認証させればよいかがわかる、という手順になっている。
例えば出荷状態では、6~8byteは「FF 07 80」という値になっている。
これを解析すると、以下の情報が得られる。
C1
C2
C3
ブロック0
0
0
0
ブロック1
0
0
0
ブロック2
0
0
0
Sector Trail
0
0
1
対照表は、ブロック0~2とSector Trailの2つがある。
ブロック0~2は全部0なのでドキュメントのTable 8を見ると、「read・・・key A|B」「write・・・key A|B」となる。
つまり、鍵AかBで認証すればよい、とわかる(ただtransport configurationなので鍵Bは使えない)。
Sector TrailはTable 7から、鍵Aのreadには認証がいらないけれどもreadは不可で、それ以外には鍵Aでの認証が必要とわかる。
しかし、これもtransport configurationなので鍵Aで認証が必要、と書かれている。
疑わしいので、鍵B「FF FF FF FF FF FF」で認証させてみたが、エラーになった。
まあ、書いてあるんだからそうなんだろうけどさ。

小心者なので、まだSector Trailに書き込むのはやってない。
また今回は取り上げないが、ブロック0~2はデータブロックとしてだけではなく、value blockという使い方もできる。
ドキュメントにはだいたいやれることが書かれていると思うので、SDK for NFC Starter Kitで遊んでみるとよいであろう。

[mifare]Mifare Ultralightに書き込めるか?

Qtをやる、といっておきながら、ちょっと気になることが残っていた。
SDK for NFC starter Kitのサンプルに、Mifare Ultralightへの読み込みサンプルはついていた。
では、書き込みはどうやるのだろうか?
週末なので、調べておこう。
すべての解釈は「私が知っている範囲で」という一文が省略されているものと考えておくれ。

Mifareは種類がたくさんある。
Wikipedia(日本語)では、以下となっている。これは規格的な見方になるか。
  • Mifare Standard
  • Mifare T=CL
  • Mifare DESFire
  • Mifare DESFire8
  • Mifare Plus
本家Wikipedia(英語)では、こうなっている。これは製品ということになるか。
記載が充実している。
  • Mifare Classic
  • Mifare Ultralight
  • Mifare Ultralight C
  • Mifare DESFire
  • Mifare DESFire EV1
  • Mifare Plus
  • Mifare SAM AV2
mifare.netの歴史では、以下となっている。
  • Mifare Classic 1k
  • Mifare Pro
  • Mifare ProX
  • Mifare Ultralight
  • SmartMX
  • Mifare Classic 4k
  • Mifare DESFire
  • Mifare DESFireSAM
  • Mifare DESFire EV1
  • Mifare Ultralight C
  • Mifare Plus
  • Mifare SAM AV2
ざっと見通したい場合は、英語版Wikipediaの項目がよくまとまっていると思った。



私の手元にあるのは、Mifare Classic 1kとMifare Ultralight。
この2種類は、ISO14443規格とは微妙に外れているらしい。
外れているというか、暗号化に関してはNXP独自のもの、と書かれている。
Ultralightは、Classicのセキュリティ部分(と、ちょっと異なるコマンド)が除外されている、とある。
なので、UltralightはほぼISO14443規格に沿っているということであろう。
SDK for NFC Starter KitがUltralightだけになっているのも、そのあたりの事情であろう。
これをFeliCaにあててみると、Mifare Classic = FeliCa Standard、Mifare Ultralight = FeliCa Lite、という構図になろうか。



では、R/Wの立場からClassicとUltralightを見てみよう。
カードの見分け方は、SENS_RES(ATQA)とSEL_RES(SAK)で行う。
取得は、InListPassiveTargetコマンドを使う。送信するのは、SENS_REQ。
そうするとSENS_RESに、SENS_RES、SEL_RES、NFCID1(UID)が戻ってくる。
カードの種類だけであれば、SEL_RESを見るとよい。
どうやって見分けるかという情報は、NFC Forumドキュメントにはなく、NXPの以下を読む必要があろう。
http://www.nxp.com/documents/application_note/130830.pdf
これのp.7に、SAKの各ビットがもつ意味をフローチャートで記載してある。
なお、LSBは「bit1」になっているので要注意だ。ISO14443のドキュメントがそうなっているらしい。
全ビットに意味があるのであれば値一致で判別できそうなのだが、意味がよくわからないのでフローチャート通りに確認していくしかなさそうだ。
とりあえず、表にしてみた。「-」のところはN/Aだ。
b7 b6 b5 b4 b3 b2 b1 b0 Result
- - - - - - 1 - RFU
- - - 1 1 - 0 - Mifare 4K
- - - 0 1 - 0 0 Mifare 1K
- - - 0 1 - 0 1 Mifare Mini
- - 0 0 0 - 0 - Mifare Ultralight
- - 1 0 0 - 0 - ISO14443-4(RATS+PSS)
- - - 1 0 - 0 0 Mifare Plus 2K SL2
- - - - 0 - 0 1 Mifare Plus 4K SL2
ISO14443-3対応かどうかだけみたいのであれば、bit5だけ見ればよい(p.6参照)。
bit5、というのは、ドキュメントで言うところの「bit6」ね。
SENS_REQというのはNFC Forumでの名前なので、ISO14443では別の名前なのかも(REQA ?)。
SENS_RESやSEL_RESはNFC Forumでの名前で、ATQAやSAKはNXPドキュメントに書かれている名称だ。

では、ようやく本題のUltralightを見ていこう。
カードの仕様は、以下のドキュメントに記載されている。
http://www.classic.nxp.com/acrobat_download2/other/identification/M028634_MF0ICU1_Functional_Spec_V3.4.pdf
サポートしているコマンドは、以下。
  • REQA(0x26)
  • WUPA(0x52)
  • Anticollision CL1(0x93)
  • Select CL1(0x93)
  • Anticollision CL2(0x95)
  • Select CL2(0x95)
  • Read(0x30)
  • Halt(0x50)
  • Write(0xa2)
  • Compatibility write(0xa0)
NFC ForumのType2 Tagでは、以下のコマンドになっている。
  • READ(0x30)
  • WRITE(0xa2)
  • SECTOR SELECT(0xc2)
0xc2 ?
Ultralightのコマンドにないのであせったが、SECTOR SELECTは1KBずつに分けられたセクタを選択するコマンドのようだ。
Ultralightは64byteなので、コマンドが不要ということだろう。
書き込みコマンドが2種類ある。
0xa2と0xa0。
NFC Forumは0xa2。
0xa0の方は過去との互換用か何からしく、引数に16byte指定できるものの書き込まれるのは最初の4byteだけらしい。
なので、使うコマンドは0xa2でよかろう。
よく見ると、Writeコマンド0xa2も4byteしかデータが渡せない。
メモリマップを見ると、4byte×16ページ=64byteなのだった。
そのうち2ページはシリアル番号(UID)で、もう2ページもLockとかOTPとかで使われている。
実際に使えるページは12ページで、48byte分みたいだな。
(LockとOTPもユーザエリアとして使用できるとあるが、意味を持っているのでね。)
注意点としては、Writeはレスポンスを返さない、ということかな。

というわけで、SDK for NFC Starter Kitでのサンプルを作成。

githubにも置いた。
https://github.com/hirokuma/NfcStarterKitWrap/tree/master/UltralightReadWrite
ラッパがだんだん充実してきたので、作るのが楽になってきた。
タイムアウト時間などを調整したり、アクセスする部分を別スレッドに移動させたりするとアプリ的にはいいんだろうけどね。

2012/01/13

ある程度のAndroidバージョンからIMountServiceでのアンマウントができなくなる

少し前(といっても、結構前になるのか)にリリースしているAndroidウィジェットのEject SD。
単にSDカードをマウント/アンマウントさせるだけのウィジェットであるが、そこそこ評判がよい。
何をもって「評判がよい」としたかというと、アンインストール数が少ないという理由だ。
1500件くらいダウンロードしてもらって、まだ400件くらい残っているのだ。
いつも生き残っているのが数件になっている私のアプリの中では、ものすごくがんばっている。

 

しかし、どの人もアプリが動いたかというと、そうでもない。
今日はコメントで「2.3.6で動かなかった」という報告があった。
報告があるのは、非常にありがたい。

対策をしたいところだが、このウィジェットはAndroidの公式APIを使っていない。
なので、バージョンの違いに弱いのだ。
4.0で動かなかったのは確認したのだけど、まさか2.3.6とは。

他の人で、同じ機種で動いたというレポートももらった。
うーん、機種とバージョンは同じだったのだけど、あれはAndroidバージョンじゃないのでよくわからん。
でも、普通に考えると、同一機種でAndroidバージョンが異なると、機種自体のバージョンも変わりそうなものだがなあ。

not visible、と書いているから、アプリ一覧に出てこんというだけかも。
ウィジェットも、アプリ一覧に表示させるようにしておいた方が混乱がないような気がしてきた。
HOMEアプリを公開したときも、一覧に出てこない、って言われたしね。

私としては、アプリ一覧のアイコンが増えるのが好きではないので、ウィジェットやHOMEのように一覧に出さなくていいものは、出てきてほしくないのだ。
しかし、わかりやすさは必要だな。

説明文に追記した。

After install, register Widget to desktop.

なんか怪しい英語だけど、なんとなくわかってくれるんじゃなかろうかね。

2012/01/09

[qt]シグナルとスロット

シグナル、というと、Linuxのsignalを考えてしまうかもしれない。
しかしQtのシグナルは別のものである。
そして、Qtのシグナルは重要というか何というか、基本をなすしくみなのでちゃんと理解しておきたい。

参考URL:
http://labs.qt.nokia.co.jp/2010/06/17/signals-and-slots.html

GUIのウィジェットに関して言えば、シグナルは「イベント」みたいなものだ。
ボタンをクリックした、とか、テキストが変更された、とか。

自分でボタンを作ると考えた場合、クリックはこんな感じで対処しそうだ。

  1. ボタンはclassにする
  2. 汎用的にしたいので、クリックしたときに呼び出される処理をコンストラクタなどでコールバック登録する
  3. 専用のボタンなら、派生クラスを作ってクリックイベントは自分で実装

しかし、コールバック登録するということは、その関数がstaticになってないといかん。
いかんことはないだろうけど、メンバ関数をコールバック登録する方法がよくわからんので、やりたくない。

  1. Qtの場合、イベントが発生するときに「シグナルを送信」する。
  2. 送信されたシグナルは、「接続されたスロット」に通知される。
  3. シグナルとスロットの接続は動的に行い、メンバ関数(スロット)を指定する。

delegateみたいな感じだろうか。


シグナルの送信は、簡単だ。
メンバ関数定義はpublicとかprivateではなく「signals」に置く。
送信時は、キーワードemitを付けて呼び出すだけ。関数本体は書かない。

受けとるスロットも、似たようなものだ。
メンバ関数定義は「slots」に置く。これはpublic slotsやprivate slotsにできる。
シグナルとスロットの接続は、QObject::connect()を使う。

なんで関数本体がないシグナル定義が呼び出せるかというと、moc、というコンパイラが別にあるからだ。
メタオブジェクトコンパイラ、の略らしい。
「メタオブジェクト」というものがよくわからないが、Qt用のclass定義を読み込んでcppソースをつくるのだ。
その中で、シグナル関数も生成されている。

これは一例。

// SIGNAL 0
void Employee::salaryChanged(int _t1)
{
void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
QMetaObject::activate(this, &staticMetaObject, 0, _a);
}

mocが作るcppには、これ以外にもいろいろと生成している。
どうやってQt用のclass定義を見分けているかというと、おそらくQ_OBJECTマクロだ。
「Qt用のclass定義先頭に"Q_OBJECT"と書け」というルールなのだ。

mocがこそっとstaticメンバ関数を生成しているので、おそらくこんな流れになっているんじゃなかろうか。

  1. 「イベント送信」により、QMetaObject::activate()が呼ばれる
  2. activate()の引数で渡されたstaticMetaObjectには、mocが生成したstaticメンバ関数が書かれているので、それを呼び出す。
  3. staticメンバ関数内でうまいことやって、接続されたスロットを呼び出す。

staticメンバ関数を見ると、引数によって呼び先がシグナルかスロットかに分岐している。
シグナルを呼べるようになっているのは、シグナルとシグナルを接続できるようになっているからだろうか。

引数確認のためにstrcmp()で文字列化された接続先スロットを確認するなど、そこそこ軽くはない処理になっている。
オーバーヘッドをなくしたい場合は、プロファイラで比重が重たいところを探して、そこが安全であればチェックをコメントアウトしていく、というようなことをやっていかないかんのかもしれない。



こんな感じで、これからしばらくQtをやっていく。
目標は、こんな感じの会話ができること、だ。

依頼人:「○○なアプリを作ってください」
私:「・・・Qtで・・・作ることになるが」
依頼人:「もちろん構いません」
私:「報酬はスイス銀行に振り込んでくれ・・・」

いや、スイス銀行はどうでもいいのだ。口座持ってないし。
今の私は、アプリを作るプラットフォームを持っていない。
Androidで作ることもあるし、VC#で作ることもある。
でも、AndroidはJavaで苦手だし、VC#はWindows限定に近くなってしまう。
作って組込みアプリにするとなると、C/C++が望ましい。

[qt]Qt 4.8 Windows版をインストールしてみよう

先月のInterface誌にQtのことが載っていた。
そうだ、Qtしよう!

と思い立ったわけではないのだが、新年も始まったことだしちょうどいいんではなかろうか。


現在のQt最新版は、4.8である。4.8.0、が正式なのかな。
しかし、ダウンロードページにいくと、Qt 4.7.4、と書いてある(2012/01/08現在)。
うーむ。

ダウンロードページの構成は、

  • Qt SDK
  • Qt Library
  • Qt Creator

の順で並んでいる。
Qt Libraryの方には、4.8.0がある。

では、これをインストールしてみる。
ウィザード形式で進んでいくのだが、途中で「MinGWがない」と言われた。
4.8.0をインストールするに当たって、以前インストールしていたQt SDKをアンインストールしていたのだ。
MinGWは、4.8.0のダウンロード先にリンクが貼ってある
先にそっちを展開しておいた方がいいかもしれん。

インストールすると、こんなメニューになった。

image

Designerは、こんな画面。

image

Qt Creatorも似たような感じだったような気がしたので、インストールした。
2.4.0だ。

image

Designerが画面作成のみに対して、Qt Creatorはプロジェクト管理を兼ねている。


「Qt 4.8.0 (Build Debug Libraries)」を実行すると、perlがないといわれた。
cygwinが入っているので、qtvers.batにcygwin\binを追加してやると、うまく進んでいる。

しかし、30分くらいしてエラーとなった。
mingw32-makeしているところなのだが、includeするのにVC6のファイルを読んでいる。
(そう、私はVC6を持っているのだ。)

VC6をインストールすると、環境変数includeにVC6のパスを書き込んでいる。
どうやら、それを-Iで見ているようだ。
就職してから、フリーのコンパイラが出てくるまでの間に私を育ててくれたVC6だが、そろそろ別れを告げるときが来たのかもしれない。

 

あまり考えずに実行させているけど、これはQtのライブラリ内をデバッグできるようにする作業だと思う。

 

んで、環境変数includeを消してからビルドし直しているけど、1時間しても終わらないので、この記事を投稿してしまいます。
終わってから結果まで書きたかったのだけど、疲れました。。。


酒を飲みながら待ってたけど、まだ終わらん。
何となくプロセスを見てみたのだが、結構深いな。

image

まあ、別に深いから悪いってことはないのだけど。

Windows XP SP3 32bitなので、64bit CPUかつメモリ6GBを生かし切れていないのは確かだ。
というよりも、私がQtの中までデバッグするかっていうと、しないと思う。
なら、このビルドは意味がないんじゃないの?という気がしなくもない。

が、ビルドすることに意味がある、ともいえる。
気持ちの問題だな。

2012/01/08

[nfc]SDK for NFC Starter KitでFeliCa Liteに読み書きする

SDK for NFC Starter Kitをちょっと使ってみたい、という人に向けて、FeliCa Lite用のサンプルを作りました。
https://github.com/hirokuma/NfcStarterKitWrap

PaSoRi(RC-S370)とFeliCa Liteがあれば、試せます。

ソース解説

主なソースファイルは、以下になります。
  • FelicaLiteReadWrite.cs
  • FelicaLite.cs
  • NfcStarterKit.cs
  • felica_nfc_dll_wrapper_basic.cs
ライブラリにあたるものは、青文字の3ファイル。
一番下にあるfelica_nfc_dll_wrapper_basic.csは、SDK for NFC Starter Kitに付属していたサンプルに手を加えた程度のものです。

NFCStarterKit.cs

Windowメッセージ処理と、SDK for NFC Starter Kitを使うときの基本処理を置いています。
これもまた、SDK for NFC Starter Kitのサンプルからけっこうな部分を持ってきています。
追加しているのは、NfcF_Read()とNfcF_Write()。
ここでFeliCa Liteに読み書きをしています。
bool NfcF_Read(ref byte[] buf, UInt16[] block, byte block_num, byte[] svc)

変更すればFeliCa Standardも読めるはずです。
サービス数を1固定にしているところが「NfcF」としている理由です。
サービス数が1固定なので、ブロックリストを返す関数CreateBlockList2()の第2引数が0になってます。
(先頭のサービスコードを使用する、という意味。)
svc[]はリトルエンディアンなので、ご注意を。
bool NfcF_Write(byte[] buf, UInt16[] block, byte block_num, byte[] svc)

Writeも同様。
サービス数は1固定です。

FelicaLite.cs

NfcStarterKit.csを、もう少しFeliCa Liteにカスタマイズしたクラス。
NfcF_Read()やNfcF_Write()のサービスコードは固定だし、書き込めるブロック数は1つだけなので、そこら辺を省略できるようにしてます。
bool Read(ref byte[] buf, UInt16 block)
bool Write(byte[] buf, UInt16 block)

そうそう、読み込みはNfcF_Read()内でバッファを確保して返すので、第1引数はnullが突っ込まれた変数とかでよいです。
それ以外は、1次発行向けの処理ばかりです。



コマンド解説

詳細はFeliCa Liteユーザーズマニュアルをダウンロードして参照してください。
・・・だけだと味気ないので、少し書いておきます。
まず注意点からですが、FeliCaLibNfcThru()でNFC-Fコマンドを使う場合にはバッファの先頭がバッファ長になります。
Mifareコマンドの場合はコマンドから始まるので、ちょっとはまりました。
なんで違うのか調べていたのですが「そういうものだから」という結論になりました。
NFC Forumの「Digital Protocol」ドキュメントに、NFC-A, B, Fの「Data and Payload Format」があるのですが、NFC-AとBはペイロードから始まっていて、NFC-Fはデータ長から始まっています。
せっかくライブラリになってるんだから吸収してくれてもいいんじゃないの、と思わなくもないですが、将来的な何かを気にしたのかもしれません。

Read without Encryption

「without」ということで、認証無しの読み込みができます。
もちろん、withoutなしのReadコマンドもあるのですが、使い方はよく知りません。
without有無の違いですが、認証されたところを読めるかどうかです。
携帯電話に搭載されているFeliCaチップは大部分が認証されたデータになっていますが、ところどころwithoutで読めるところもあります(確か)。
このコマンド、NFC Forumでは「CHECK」という名前になっています。
注意点は、サービスコードリストはリトルエンディアンで、ブロックリストはビッグエンディアンというところ。
サービスコードは、とりあえずRead Onlyのにしておけばいいでしょう。
Read/Writeでもいいけど、その場合はWriteできないブロックへのアクセスに失敗します。
FeliCa Liteの場合は最大で4ブロックまで同時に読めます。

Write without Encryption

Read w/o Encryptionとほぼ同じです。
書き込めるのは1ブロックのみ。
サービスコードは、当然Read/Writeです。

ステータスフラグ

結果にはステータスフラグが載ってくるので、それをチェックします。
ステータスフラグ1が0x00かどうかだけ見れば事足りるでしょう。
FeliCaのデータはEEPROMに保存されていると思うので、10万回か100万回くらい書き込みをすると「もうだめ」ということになると思います。
ステータス2の「致命的」なのは、そんな現象じゃないでしょうかね。
これはもう、ハードウェアの限界なので、交換しかなくなります。

ポーリング

読み書きする前に、カードを「捕捉する」という動作が必要になります。
それがポーリングです。
ポーリングについてはライブラリでサポートされているので、自前でコマンドを打たなくても大丈夫。

[nfc]SDK for NFC Starter Kitで片側認証の個別化カード鍵まで書き込む

SDK for NFC Starter Kitで、FeliCa Liteの一次発行寸前までやるアプリを作ってみた。
具体的には、「FeliCa Liteユーザーズマニュアル」の7.3.6までだ。
https://github.com/hirokuma/NfcStarterKitWrap/tree/master/FelicaLiteIssuance

あれから、ご飯も食べずにやってました。。。
というよりも、これをやらないとご飯なし、という感じで。
自分を追い立てないとねぇ。

個別化カード鍵の計算が、あまり自信ない。
前回、どうやって動作確認をしたのか覚えていないのだ。。。
.NETには3DESの暗号化クラスがあるのだけど、標準個別化カード鍵アルゴリズムに沿って使おうとすると「鍵が弱い」という例外が発生してしまい、使うことができなかった。
あれこれ検索した結果、結局は、DES暗号化→DES復号化→DES暗号化、と3DESを自分でやることになった。
7.3.5章の「カード鍵の確認」は成功しているので、うまくいっているような気がするのだけど。
まあ、おかしかったら言うてください。
約6時間か・・・。
つかれたー



まだご飯を食べていないけど、ソースを整理してgithubに置きました。
git://github.com/hirokuma/FelicaLiteIssuance.git

2012/01/07

[nfc]SDK for NFC Starter KitでNFCIDを読む

SDK for NFC Starter Kitで、MifareやFeliCaのNFCIDを取得するアプリを作ってみた。
さっきのの強化版みたいな位置づけのように見えるが、ここに至るまで結構苦労した。
https://github.com/hirokuma/NfcStarterKitWrap

何を苦労したかというと、C#がよくわからんかったことだ。
付属のC#サンプルを分解すればいいだろう、くらいに思っていたのだが、ウィンドウを自前で表示することですこし違いがあったようだ。
Pollingボタンを押すとウィンドウが非アクティブになるのは、メッセージ取得用にListenerWindowをShowDialogさせているから。
もっといい方法があるとは思うのだけど、よくわからん。



あんまりやる気がなかったが、ここまで作ったのでFeliCa Liteの発行ができそうなアプリまで作りますか。
.NETには3DESクラスがあるようなので、何とかなるかもしれん。

[nfc]SDK for NFC Starter KitでMifareを読む

SDK for NFC Starter KitでMifareを読むサンプルを改造した。
https://github.com/hirokuma/NfcStarterKitWrap/tree/master/UltralightReadWrite

「そんなの、サンプルについとうやん」と言われそうだが、まあ待っておくれ。
サンプルにあったものをそのままVisual Studio 10 Expressで実行すると動かなかったので、修正したのだ。
また、Mifare Classicが読めなかったので、SEL_RESで見分けてAuthenticationするようにしている。
認証されていないMifare Classicであればいいんじゃないだろうか。
サンプルがC#コンソールアプリだったので、これもそうなっている。
185行目にブレークポイントを張ってから実行するとよかろう。

今回、カード側のサンプルを初めて読んだのだが、Polling以外はCommunicateThruEXでやるんだな。
となると、NFCのプロトコルにある程度通じている必要がある。
サンプルがMifare Ultralightであるのも、NFC-Aの規格に合わせたためであろう。
FeliCa StandardがNFC対象外であるように、Mifare ClassicはNFC対象外なのだ。
対象外、と書くと語弊があるかもしれない。
FeliCa StandardやMifare ClassicはNFCIP1やNFC Forumの規格の派生にあたる。
NFC規格がサポートしていない認証などが入っているのだ。

SourceMonitorが相対パス指定できるようになっていた

SourceMonitorというツールがある。
静的解析ツールではなく、メトリクス評価というのかしらんが、構造的な評価をしてくれる。
splintのC++版があればいいのだけど見当たらないし、フリーの静的解析ツールもないので、まずは構造的な評価を行うだけにしている。
というと何か難しそうなのだが、とりあえずSourceMonitorにかけてみるとよいだろう。
sourcemonitor
これは、RC-S620/Sとのやりとりをするクラスにかけてみた例だ。
私が見てるのは、Max Complexityくらい。
この関数が複雑になってますよ、という指標になる。
複雑になっているところはバグが潜みやすいので、見直してみるといいかもしれん。
コメント比率なんかも出るので、ソースファイル管理者であればいちいちソースを全部見なくても、「お前、コメントが少ないぞー」と担当者に指摘することができそうだ。
プロジェクトであれば、指摘する閾値を決めておくとよいだろう。
そうせんと「どこまで改善すればいいんだ」という目安がなくて、作業者がなえてしまう。

そんなSourceMonitorだが、以前はソースファイルの位置が絶対パス指定だけだった。
これが非常にやっかいで、せっかくSourceMonitorプロジェクトを作ったとしても同じパスに置かないと使えないため、複数作業者で共有しにくかったのだ。
久しぶりにサイトを見てみると、v3.2になっていた。
そして、SourceMonitorプロジェクトファイルからの相対パスが指定できるようになっていた。
これはありがたい。
ダウンロードするなら、v3.2.4.222がよい。
標準だとv.3.2.3.218なのだが、optionで表示フォントを設定しても記憶してくれないのだ。

もう1つほしい機能があるのだが、それはなかった。
何かというと、プリプロセス処理だ。
SourceMonitorは解析するに当たってプリプロセスを見てくれない。
#if-#elseなんかがある場合は、#if~#elseまでしか見ないのだ。
詳細は、ヘルプファイルで確認してほしい。
The metrics in C++ source files can be ambiguous when conditional compilation is used to define different versions of a substructure. Therefore, SourceMonitor ignores all conditional #else clauses and counts metrics only in the code that lies between the #if... and #else preprocessor directives.
なので、#ifを多用している場合はSourceMonitorにかける前に、プリプロセス展開したソースファイルを出力するようなmakeなりなんなりを用意しておき、そのファイルに対してSourceMonitorをかけた方がよいだろう。
gccだと、-Eでよかったような。
統合環境でビルドするようなものでも、プリプロセス展開するようなオプションがあると思うので探してみるとよいかな。
プリプロセス展開する専用ツールもあったと思うが、ほどよいのが見つからなかった。興味がある方は探してみるとよいでしょう。

[qt]QtからUSBアクセスするクラスはなさそうだ

ざっと見た感じだが、QtからUSBをアクセスする標準クラスはないように見える。
シリアルポートなんかもないようだ。
まあ、グラフィックみたいに基本的に1つしかないことが保証しやすいものはいいけど、USBやシリアルポートのように、あったりなかったり複数あったりするようなものは難しいところだ。

 

USBならば、libusbを経由させれば何とかできそうに思う。
検索してもだいたいそんな感じだった。
Windowsだけであれば、WinUSBという選択もあろう。

 

意外と難しいのが、シリアルポート。
Windowsだと「COM3」のようなポートになっているが、Linuxだと「/dev/ttyS2」のようになる。
(Macは使ったことがないので知らない。)
この名前がハードウェアと一意で決定するのであればいいけれども、そうもいかない。
libnfcでは「自動検索」か「ユーザ指定」という形にしているが、そういう解決方法しかなさそうだ。