Ubuntu 16.04 で XKB を使ってキーマップをカスタマイズする
いつも分からなくなるのでメモ
概要
こんなことがやりたくなったら、キーマップをカスタマイズすることになる。
- JIS 配列キーボードを使っているが、US 配列として使いたい
- Caps Lock を Control に割り当てたい
やり方は幾つかあるようだ。XKB を使う方法、.Xmodmap を編集する方法。
XKB の方が新しい仕組みなので、そっちでやる。
続きを読む自作OS Advent Calendar 2016 目次
これは 自作 OS Advent Calendar 2016 の 25 日目の記事です。 1 日目から 24 日目までの記事をまとめた目次になっています。
それぞれの記事のURLの後に書いてある一言紹介は、uchanによるものです。 記事の著者さんに確認を取っておらず、もしかしたら誤った内容の可能性があります。
OSの機能拡張
12/13 Yuma Ohgami
- 自作OS(OS5)の紹介とユーザーランド周りの機能追加について - へにゃぺんて@日々勉強のまとめ
- http://d.hatena.ne.jp/cupnes/20161213/1481575702
- はりぼてOS系ではない独自のOSで、こつこつ更新されているようです。ソースコードが2000行程度なので読みやすそう。
12/15 川合秀実
12/18 uchan_nos
- はりぼてOSでELFなアプリを起動する - uchan note
- http://uchan.hateblo.jp/entry/2016/12/18/173320
- はりぼてOSの完成版をベースに、ELFバイナリのアプリを読み込む機能を付けました。自分のOSをELF対応させるときには参考になると思います。
12/24 Mopp_jp
OS自作用の処理系いろいろ
12/2 hikalium
- Mac OSX におけるはりぼてOSの開発環境を(再)整備した話 - hikalium.com
- https://hikalium.com/page/note/20161202.md
- MacやLinuxではりぼてOSをコンパイルするにはいくつかの障壁があります。この記事ではそれらの障壁を解決済みの開発環境一式を配布しています。 ここで配布している開発環境がはりぼてOS界での新しい標準になるでしょう。
12/3 kubo39
- D言語とOS開発と自作OS - kubo39's blog
- http://kubo39.hatenablog.com/entry/2016/12/03/D%E8%A8%80%E8%AA%9E%E3%81%A8OS%E9%96%8B%E7%99%BA%E3%81%A8%E8%87%AA%E4%BD%9COS
- D言語でOSを作り始めた話です。D言語でOSをビルドする際のチップスがいくつか紹介されています。これから先に期待!
12/8 uchan_nos
- Windows で GCC 6.2.0 をビルドするメモ - uchan note
- http://uchan.hateblo.jp/entry/2016/12/08/235344
- タイトルの通り、ビルドする手順を紹介しています。そんな頑張らないでLinux使おうよ、というのはその通りなのですが(笑)
12/10 Hiroyuki-Nagata
- Debian GNU/Linuxで自作OS - Qiita
- http://qiita.com/hiroyuki-nagata/items/0ad529d2966a292b93b2
- 著者がOS開発で使っているツールの紹介です。なんと、opennaskというアセンブラを独自開発しているとのこと。硬派です!
12/11 Hiroyuki-Nagata
- IA32(x86)汎用命令対応のアセンブラ実装方法(1) - Qiita
- http://qiita.com/hiroyuki-nagata/items/ec0f47df595631e41c5c
- アセンブラを実装する上で重要となる、x86のオペコードの構造の説明です。
12/12 Hiroyuki-Nagata
- IA32(x86)汎用命令対応のアセンブラ実装方法(2) - Qiita
- http://qiita.com/hiroyuki-nagata/items/42ba3d797f8e29726bde
- opennaskで使ったパーサParasolの紹介と、実装の難所としてModR/Mの話が載ってます。
12/16 kotetu
- RustでOSを書いてみる(環境構築編) - Qiita
- http://qiita.com/kotetuco/items/54af67d5663013ad0db7
- RustでOSを作るために必要な開発環境の紹介があります。Rustで書いたソースコードをブートローダから起動させるまでの手順が分かります。
BIOS/UEFI
12/4 neriring2
- はりぼてOSをUEFIで起動する/総集編 - 借り初めのひみつきち
- http://neriring.hatenablog.jp/entry/2016/12/04/180254
- タイトルの話もさることながら、近年はレガシーデバイスがサポートされなくなってOS開発が厳しいね、という話が興味深い(と同時にちょっと悲しい)です。
12/7 hikalium
- 仮想86モードでBIOSを呼び出した話 - hikalium.com
- https://hikalium.com/page/note/20161207.md
- UEFIの話があったかと思えば、こちらはUEFIなにそれ?という感じでガンガンBIOSを叩きまくる話です。コード例が豊富です。
12/14 liva_jy
- ディスクイメージをネットワークブートする – Raphine Project<サイト製作中>
- https://raphine.wordpress.com/2016/12/14/netboot/
- 開発マシンに立てた簡易HTTPサーバでOSイメージを配布し、ターゲットマシンでOSを起動させちゃうお話です。やってみたくなること間違い無し。
12/17 ナカタニ
- USBにosをインストールするツールをつかってみた - とりあえずやってみよう、そんな毎日
- http://hiyashicurry.blog106.fc2.com/blog-entry-15.html
- USB起動のLinuxを作るときの代表的なツールUNetbootinを利用してはりぼてOSを起動させてみた話です。
その他技術話
12/19 ナカタニ
- 画像ファイルのバイナリ情報とパレットのハナシ - とりあえずやってみよう、そんな毎日
- http://hiyashicurry.blog106.fc2.com/blog-entry-16.html
- ビットマップ画像のフォーマットの説明です。パレットの説明まであるのはなかなか珍しい気がします。
12/20 liva_jy
- 256コアマシン向けのOSを作る – Raphine Project<サイト製作中>
- https://raphine.wordpress.com/2016/12/23/develop_many_core_os/
- 第三世代Xeon Phi Knights Landingで動くOSを作っちゃおうという話です。っていっても普通の人はそんなデバイス買えません(><)
12/21 liva_jy
- 時折飛んでくる原因不明な#GPをgdbで原因究明した備忘録 – Raphine Project<サイト製作中>
- https://raphine.wordpress.com/2016/12/22/solve_unexpected_gpf/
- QEMUの内部の関数にブレークを仕掛けてデバッグしちゃおうという話です。なるほど、そういうデバッグ手法もあったのか!
12/22 sk2sat
- 自作エミュレータで自作OSを動かしてみようとした話 - sksat’s diary
- http://sksat.hatenablog.com/entry/2016/12/21/231342
- タイトルからしてなんとも胸熱な本記事、エミュレータのこれからの進化に期待ですね。
12/23 Tkon_sec
- まだ記事がありません
エッセイ
12/1 uchan_nos
- osdev-jp という自作 OS のコミュニティを作りました - uchan note
- http://uchan.hateblo.jp/entry/2016/12/01/072700
- コミュニティの発足経緯、参加方法などについての記事です。
12/5 川合秀実
12/6 川合秀実
- セグメンテーションの夢はどうなったのか? - khfdpl-wiki
- http://khfdpl.osask.jp/wiki/?advcal20161206
- せっかくCPUにはセグメンテーションという素晴らしい機能があるのになぜ人々は見向きもしないのか。ページングと比較してセグメンテーションの素晴らしさを語ります。
12/9 川合秀実
- 手段としての自作OSのススメ - khfdpl-wiki
- http://khfdpl.osask.jp/wiki/?advcal20161209
- 何らかの目的を持ってOSを自作することの大切さを述べています。例えばセキュリティを研究するためにOSを作ってみるとか。
はりぼてOSでELFなアプリを起動する
これは 自作 OS Advent Calendar 2016 の 18 日目の記事です。
概要
『30 日でできる!OS 自作入門』 の「はりぼて OS」が対応している実行可能形式は HRB 形式です。 HRB という名の通り「はりぼて OS」独自の形式で、.text、.data、.bss セクションに相当するデータを含むことができます。
構造がシンプルなので、入門者にとっては実行可能形式を学ぶのに都合がいい形式であると思います。 しかし、独自形式ゆえ周辺のツールが整いづらく、実際に扱いやすい形式というわけでもありません。
本記事では、Linux 環境でスタンダードとなっている ELF 形式を「はりぼて OS」でも動かそうじゃないか、ということでやり方をご紹介します。 ELF 形式のアプリをロードして実行する方法(OS 側)、ELF 形式でアプリをコンパイルする方法(アプリ側)の 2 つの側面から解説します。
画像はいらすとやから頂いたエルフです。
続きを読むレベル変換の仕組み(オームの法則からMOS-FETを使ったレベル変換回路まで)
レベル変換
レベル変換とは、電圧の異なる信号線をつなぐ際に電圧を変換することです。
例えば Raspberry Pi という小さな Linux ボードコンピュータの電源電圧は 3.3V です。 そのため GPIO の入出力電圧も 3.3V となっており、電子工作でよくある 5V 駆動の装置を直接つなぐことができません。 著者は最近、秋月電子通商で売っている中で最安のキャラクタ液晶表示器 SC1602 を Raspberry Pi から制御しようと思ってレベル変換回路を作りました。
また、いわゆる「L チカ」といって LED を点滅させるだけの回路でも、LED によっては 3.5V 程度の電圧がないと十分に光らない品種があり (赤色 LED に比べ、青色 LED は高い電圧を求める傾向があります)、3.3V の出力では十分でないケースがあります。
レベル変換は低電圧側の回路から高電圧側の回路を制御するだけでなく、逆に高電圧側から低電圧側の回路を制御するのに用いる場合もあります。
ハードウェアエンジニアにとっては良く知られた回路ですが、ソフトウェア専門の人がちょっと電子工作しようとするとハマることが多いと思います。 この記事では、オームの法則を復習しつつ、レベル変換回路の基礎を見てみます。
続きを読むosdev-jp という自作 OS のコミュニティを作りました
これは 自作 OS Advent Calendar 2016 の初日の記事です。
自作 OS Advent Calendar といいつつ、初日は技術的なことは書かずにコミュニティの紹介をします。期待してくださった方にはすみません(^^;)
自作 OS コミュニティの昔と今
私が自作 OS というものを知ったのは 2003 年ごろのことです。 そのころ、ウェブには活発な自作 OS コミュニティがいくつかありました。 私は主に OSASK コミュニティで活動していましたが、周りには dev-j、OS-Wiki などの OS 系の情報サイトや Mona OS、MEG-OS もありました。
時は流れて 2016 年。 私はしばらく自作 OS から離れていましたが、あるきっかけでまた自作 OS 関連の活動を再開させようと思いました。
久しぶりの OS 熱に侵されながら、おぼろげな過去の記憶をもとに dev-j や OS-Wiki などを再訪してみました。 しかし、そこは荒れた荒野のような状態でした。 dev-j にいたっては、トップページさえ 403 エラーでアクセスできない状態になっています。
osdev-jp の紹介
そこで私は、自作 OS に再びかかわろうと思うきっかけを与えてくれた 2 人の若者 ―― @liva_jy さんと @hikalium さん ―― とともに osdev-jp というコミュニティを作ることにしました。
発足したのは 2016 年 3 月です。 発足当初、このコミュニティは(OS-Wiki のように)OS 関連の情報を集めるサイトの名前でした。 今は情報収集はあまり捗っていませんが、「自作 OS もくもく会」というオフ会を定期的に開催し、自作 OS 好きの人同士のつながりを作り出しています。
osdev-jp の主要なリソースは以下の通りです。
- GitHub : https://github.com/osdev-jp/
- リポジトリにはいくつかのサンプルコードがあり、GitHub Wiki にはメンバーが書いた記事が集約されています。
- osdev-jp Core Wiki : http://osdev-jp.readthedocs.io/ja/latest/
- コアメンバー(記事執筆時点で liva_jy, hikalium, uchan_nos の 3 人)が書いた、比較的体系立った記事が掲載されています。
- Vagrant や Visual Studio Code の記事は、自作 OS 以外の分野でも十分参考になる記事です。
- Slack : https://osdev-jp.slack.com/
- 自作 OS に興味のある方が参加しているチャットです。自作 OS もくもく会参加者を中心に 30 人ほど参加してくださっています。
- uchan_nos にメールアドレスを教えていただければ招待メッセージを送ります。
「自作 OS もくもく会」は今のところ 2 カ月に 1 回のペースで開催しています。 開催予告は GitHub Wiki の イベントカレンダー に載せていくつもりです。
nfcpy で複数の System Code を持つ NFC タグを扱う方法
Linux (Ubuntu 16.04) で nfcpy を使ってみました。落とし穴が多い気がしたので、ここにまとめます。 特に、複数の system code を持つような NFC タグの扱いが複雑ですので、詳しく説明します。
概要
Linux で NFC タグを読み書きするには nfcpy という Python ライブラリを使うのが割とよく用いられる方法のようです。 この記事では、nfcpy で NFC タグに記録されたブロックを取得する方法を説明します。
nfcpy に関する記事はいくつもあるのですが、どれも複数の System Code を持つ NFC カードの扱い方は書いてないようでした。 また、対応する nfcpy のバージョンが古かったりするので、この記事を書こうと思いました。
この記事で対象とする nfcpy のバージョンは 0.11.1 です。 また、動作検証は Sony 製の NFC リーダー・ライター PaSoRi RC-S380 を使って行いました。
nfcpy のインストール
公式ドキュメントは http://nfcpy.readthedocs.io/en/stable-0.11/ にあります。 (ただし、このドキュメントは少し古いです。現在 nfcpy は GitHub に移行したのですが、ドキュメントは lauchpad 時代のままです。)
nfcpy は PyPI に登録されているので、pip でインストールできます。 (nfcpy は現時点でまだ Python 3 系に対応してないので、pip3 は使わないでください。)
$ sudo pip install -U nfcpy
pip でインストールするとサンプルコードが手に入らないので、別途 GitHub からダウンロードします。
$ git clone git@github.com:nfcpy/nfcpy.git
$ cd nfcpy
$ git checkout stable/0.11
ここまでできたら、サンプルコードを実行して PaSoRi でタグを読み取ることができるはずです。
$ sudo examples/tagtool.py
[nfc.clf] searching for reader on path usb
[nfc.clf] using SONY RC-S380/P NFC Port-100 v1.11 at usb:002:013
** waiting for a tag **
Type3Tag 'FeliCa Standard (RC-S915)' ID=xxxxxxxxxxxxxxxx PMM=yyyyyyyyyyyyyyyy SYS=8108
NFC タグをタッチすると検出され、製造ID(IDm)、製造パラメータ(PMm)、システムコードが表示されます。(最終行)
おまけ:sudo を使わないで作業する方法
環境によって、USB 接続の NFC リーダーに一般ユーザが接続することができない場合があります。 毎回 sudo を使えば問題ないのですが、それは嫌だという方には公式ドキュメントで説明されている通り、回避策があります。
まず、一般ユーザで NFC リーダーが扱えないことを確認します。
$ examples/tagtool.py --device usb
[nfc.clf] searching for reader on path usb
[nfc.clf] no reader available on path usb
[main] no contactless reader found on usb
[main] no contactless reader available
この時点でちゃんとリーダーを検出できていれば、何もする必要はありません。 検出できないことが確認できたら、lsusb コマンドでデバイス ID を調べます。
$ lsusb
...
Bus 002 Device 013: ID 054c:06c3 Sony Corp.
...
それっぽいデバイスを見つけたら 054c:06c3
のところの番号を使って tagtool.py を実行しなおします。
$ examples/tagtool.py --device usb:054c:06c3
[nfc.clf] searching for reader on path usb:054c:06c3
[main] access denied for device with path usb:054c:06c3
[main] first match for path usb:054c:06c3 is usb:002:013
[main] usb:002:013 is owned by root but you are xxxxx
[main] members of the root group may use usb:002:013
[main] you may want to add a udev rule to access this device
[main] sudo sh -c 'echo SUBSYSTEM==\"usb\", ACTION==\"add\", ATTRS{idVendor}==\"054c\", ATTRS{idProduct}==\"06c3\", GROUP=\"plugdev\" >> /etc/udev/rules.d/nfcdev.rules'
[main] no contactless reader available
「指定した ID のデバイスは root の所有なのでアクセスできないよ」てなことが書いてあります。 下から 2 行目に解決策が提示されていますので、そのコマンドを実行します。
$ sudo sh -c 'echo SUBSYSTEM==\"usb\", ACTION==\"add\", ATTRS{idVendor}==\"054c\", ATTRS{idProduct}==\"06c3\", GROUP=\"plugdev\" >> /etc/udev/rules.d/nfcdev.rules'
マシンを再起動すれば、一般ユーザで使えるようになっているはずです。
NFC タグの中身を見てみる
nfcpy をインストールしたことですし、NFC タグの中身を表示するプログラムを作りましょう。 以下、NFC といいつつ FeliCa Standard を対象としたプログラムになっています。 他の規格のカードではうまく動かない可能性があります。
dump_simple.py は NFC タグ(の先頭 System)が持つサービスをすべて列挙するプログラムです。
import nfc
def check_services(tag, start, n):
services = [nfc.tag.tt3.ServiceCode(i >> 6, i & 0x3f)
for i in xrange(start, start+n)]
versions = tag.request_service(services)
for i in xrange(n):
if versions[i] == 0xffff: continue
print services[i], versions[i]
def on_connect(tag):
print tag
n = 32
for i in xrange(0, 0x10000, n):
check_services(tag, i, n)
def main():
with nfc.ContactlessFrontend('usb') as clf:
clf.connect(rdwr={'on-connect': on_connect})
if __name__ == '__main__':
main()
取りあえず実行してみます。サービスの全列挙には実行には時間がかかりますのでしばらく待ちましょう。
$ python dump_simple.py
Type3Tag 'FeliCa Standard (RC-S915)' ID=xxxxxxxxxxxxxxxx PMM=yyyyyyyyyyyyyyyy SYS=8108
Service Code 0000h (Service 0 Type 000000b) 4097
Service Code 0100h (Service 4 Type 000000b) 4097
...
プログラムを説明します。
nfc.ContactlessFrontend('usb')
で USB 接続の NFC リーダーを開きます。
clf.connect
で NFC リーダーを起動し、NFC タグのタッチ検出を開始します。
connect
の引数で、NFC タグがタッチされたときに呼び出すコールバック関数 on_connect
を指定します。
ドキュメントにはコールバック関数を設定しない(clf.connect(rdwr={})
)場合、NFC タグをタッチするまでブロックするような記述がありますが、実験したところブロックしませんでした。
きちんと on-connect
コールバックを設定する必要があるようです。
NFC タグがタッチされると on_connect
にはそのタグを表すオブジェクト tag
が渡ってきます。
以降、tag
を使って NFC タグと通信し、様々なデータを読み取っていきます。
dump_simple.py プログラムは、タッチした NFC タグが持つすべてのサービスを列挙します。
tag.request_service
にサービスコード(ServiceCode
)を渡すと、タグがそのサービスを持つかどうかを調べられます。
タグが指定したサービスを持つなら 0xffff 以外の値が返ってきます。
サービスコードは 16 ビットの値で、上位 10 ビットがサービス番号、下位 6 ビットが属性値です。
16 ビット値ですから、0 から 0x10000 までを調べればすべてのサービスを網羅できます。
for i in xrange(0, 0x10000, n)
はそういう意味です。
nfc.tag.tt3.ServiceCode(i >> 6, i & 0x3f)
は、16 ビットの整数 i
から ServiceCode
オブジェクトを生成するやり方です。
i >> 6
で上位 10 ビットを取り出します。i & 0x3f
で下位 6 ビットを取り出します。
tag.request_service
は複数のサービスを一度に指定することができます。
実際に check_services
関数では n
個の ServiceCode
のリストを作り、request_service
関数に渡しています。
1 つずつ調べるよりまとめて調べる方が速いので、32 個ずつ調べることにしたのです。
複数の System を扱う
dump_simple.py では System を切り替える処理を入れていなかったため、暗黙的に NFC タグの先頭の System を扱うことになります。 複数の System を持つタグの場合、明示的に扱う System を指定する処理が必要です。
今度は、すべての System を網羅的に調べるように改造した dump_all_systems.py を示します。
import nfc
def check_services(tag, start, n):
services = [nfc.tag.tt3.ServiceCode(i >> 6, i & 0x3f)
for i in xrange(start, start+n)]
versions = tag.request_service(services)
for i in xrange(n):
if versions[i] == 0xffff: continue
print services[i], versions[i]
def check_system(tag, system_code):
idm, pmm = tag.polling(system_code=system_code)
tag.idm, tag.pmm, tag.sys = idm, pmm, system_code
print tag
n = 32
for i in xrange(0, 0x10000, n):
check_services(tag, i, n)
def on_connect(tag):
system_codes = tag.request_system_code()
for s in system_codes:
check_system(tag, s)
def main():
with nfc.ContactlessFrontend('usb') as clf:
clf.connect(rdwr={'on-connect': on_connect})
if __name__ == '__main__':
main()
実行するとこんな感じになります。複数の SYS=
を調べているのが分かりますね。
$ python dump_all_systems.py
Type3Tag 'FeliCa Standard (RC-S915)' ID=xxxxxxxxxxxxxxxx PMM=yyyyyyyyyyyyyyyy SYS=8108
Service Code 0000h (Service 0 Type 000000b) 4097
Service Code 0100h (Service 4 Type 000000b) 4097
...
Type3Tag 'FeliCa Standard (RC-S915)' ID=xxxxxxxxxxxxxxxx PMM=yyyyyyyyyyyyyyyy SYS=FE00
Service Code 1748h (Service 93 Random RW with key) 4097
Service Code 174Bh (Service 93 Random RO w/o key) 5963
...
プログラムの変更のポイントはこんな感じです。
tag.request_system_code
関数で NFC タグが持っている System の一覧を得る- 今まで
on_connect
でやっていた処理をcheck_system
関数に移して、polling
処理を加えた
polling
の処理がミソとなる部分ですので、少し詳しく説明します。
ポーリングは、NFC リーダーが NFC タグを探す処理のことです。 ポーリング時に System Code を指定することで衝突防止を実現しています。 指定したコードと同じコードを持つ NFC タグだけがポーリングに反応することで、複数の NFC タグが探索範囲に存在しても衝突しないようになっています。
さて、tag.polling
関数に System Code を渡すと、そのコードを持つ NFC タグの IDm, PMm を取得できます。
取得した IDm と PMm、それからポーリングに使った System Code を tag.idm
, tag.pmm
, tag.sys
に設定することで、以降のデータ通信をその System に対して行えるようになります。
データブロックの読み込み
NFC タグがもつすべての System とすべてのサービスが分かったので、次はいよいよ任意のサービスが持つデータブロックを読み込んでみます。
dump_block.py
import nfc
from binascii import hexlify
def on_connect(tag):
idm, pmm = tag.polling(system_code=0xfe00)
tag.idm, tag.pmm, tag.sys = idm, pmm, 0xfe00
sc = nfc.tag.tt3.ServiceCode(93, 0x0b) # 174B
bc = nfc.tag.tt3.BlockCode(1, service=0)
data = tag.read_without_encryption([sc], [bc])
print 'str:', data
print 'hex:', hexlify(data)
def main():
with nfc.ContactlessFrontend('usb') as clf:
clf.connect(rdwr={'on-connect': on_connect})
if __name__ == '__main__':
main()
このプログラムはシステム 0xfe00 内のサービス 0x174B が持つブロック 1 のデータを読み込みます。 システムコードとサービスコードは、先ほどの探索で得た値を使っています。
このあたりは read_without_encryption のドキュメント に載っているサンプルを参考にしています。
ドキュメントにもありますが、BlockCode
の生成時に渡す service=0
はサービスコードそのものではなく、read_without_encryption
の引数 service_list
内でのインデックスです。
read_without_encryption([sc1, sc2, ..., scN], [...])
などと N 個のサービスを指定したとき、BlockCode
の service
は 0 から N-1 までの値を取れます。
1 つのサービスは 16 バイトの大きさのブロックを複数個持ち、サービスの中で 0 から連番が付いています。
| Service X |
| ---------|
| | Block 0 |
| ---------|
| | Block 1 |
| ---------|
| | ... |
サービスコードの下位 6 ビットは属性値で、次のようになっています。 この中で、パスワードなしで読み書きできるのは "w/o key" (without key = キーなし)となっているサービスだけです。 例えば 2 つのサービス "1748h" と "174Bh" のうち、読み取れるのは "174Bh" の方だけです。
ビット | 意味 |
---|---|
001000 | Random RW with key |
001001 | Random RW w/o key |
001010 | Random RO with key |
001011 | Random RO w/o key |
001100 | Cyclic RW with key |
001101 | Cyclic RW w/o key |
001110 | Cyclic RO with key |
001111 | Cyclic RO w/o key |
010000 | Purse Direct with key |
010001 | Purse Direct w/o key |
010010 | Purse Cashback with key |
010011 | Purse Cashback w/o key |
010100 | Purse Decrement with key |
010101 | Purse Decrement w/o key |
010110 | Purse Read Only with key |
010111 | Purse Read Only w/o key |