changeset 725:1ecceb2e92a3

rename rfid_pn532_py Ignore-this: 89356f780bb5df4d9ec639c44d2a3a67
author drewp@bigasterisk.com
date Wed, 05 Feb 2020 16:40:46 -0800
parents 2866c155eb07
children b14020802f8a
files service/cardReader/Dockerfile.pi service/cardReader/Dockerfile.pyfreefare.pi service/cardReader/Dockerfile.pyfreefare.x86 service/cardReader/Dockerfile.x86 service/cardReader/build_ctypes_modules.sh service/cardReader/index.html service/cardReader/local.conf service/cardReader/makefile service/cardReader/pyfreefare/freefare.h service/cardReader/pyfreefare/nfc.h service/cardReader/requirements.txt service/cardReader/rfid-console.html service/cardReader/rfid.py service/cardReader/tags.py service/cardReader/tags_test.py service/rfid_pn532_py/Dockerfile.pi service/rfid_pn532_py/Dockerfile.pyfreefare.pi service/rfid_pn532_py/Dockerfile.pyfreefare.x86 service/rfid_pn532_py/Dockerfile.x86 service/rfid_pn532_py/build_ctypes_modules.sh service/rfid_pn532_py/index.html service/rfid_pn532_py/local.conf service/rfid_pn532_py/makefile service/rfid_pn532_py/pyfreefare/freefare.h service/rfid_pn532_py/pyfreefare/nfc.h service/rfid_pn532_py/requirements.txt service/rfid_pn532_py/rfid-console.html service/rfid_pn532_py/rfid.py service/rfid_pn532_py/tags.py service/rfid_pn532_py/tags_test.py
diffstat 30 files changed, 1743 insertions(+), 1743 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/service/cardReader/Dockerfile.pi	Wed Feb 05 16:40:46 2020 -0800
@@ -0,0 +1,17 @@
+FROM bang6:5000/base_pi
+
+WORKDIR /opt
+RUN apt-get install -y libnfc5 libfreefare0 libnfc-dev libfreefare-dev python3-nose2 libffi-dev
+COPY pyfreefare-build-pi ./pyfreefare-build
+
+COPY requirements.txt .
+RUN pip3 install -Ur requirements.txt
+# not sure why this doesn't work from inside requirements.txt
+RUN pip3 install -U 'https://github.com/drewp/cyclone/archive/python3.zip'
+
+COPY *.py *.html  ./
+
+ENV PYTHONPATH=/opt/pyfreefare-build
+EXPOSE 10012
+
+CMD ["/usr/bin/python3", "rfid.py"]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/service/cardReader/Dockerfile.pyfreefare.pi	Wed Feb 05 16:40:46 2020 -0800
@@ -0,0 +1,10 @@
+FROM bang6:5000/base_pi
+
+WORKDIR /opt
+
+RUN apt-get install -y python-clang-5.0 libclang-5.0-dev libnfc5 libfreefare0 libnfc-dev libfreefare-dev 
+RUN pip install git+https://github.com/drewp/ctypeslib.git@enable-modules-flag
+
+COPY build_ctypes_modules.sh ./
+
+CMD ["/bin/sh", "/opt/build_ctypes_modules.sh"]
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/service/cardReader/Dockerfile.pyfreefare.x86	Wed Feb 05 16:40:46 2020 -0800
@@ -0,0 +1,10 @@
+FROM bang6:5000/base_x86
+
+WORKDIR /opt
+
+RUN apt-get install -y python-clang-5.0 libclang-5.0-dev libnfc5 libfreefare0 libnfc-dev libfreefare-dev 
+RUN pip install git+https://github.com/drewp/ctypeslib.git@enable-modules-flag
+
+COPY build_ctypes_modules.sh ./
+
+CMD ["/bin/sh", "/opt/build_ctypes_modules.sh"]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/service/cardReader/Dockerfile.x86	Wed Feb 05 16:40:46 2020 -0800
@@ -0,0 +1,18 @@
+FROM bang6:5000/base_x86
+
+WORKDIR /opt
+RUN apt-get install -y libnfc5 libfreefare0 libnfc-dev libfreefare-dev 
+RUN apt-get install -y python3-nose2
+COPY pyfreefare-build-x86 ./pyfreefare-build
+
+COPY requirements.txt .
+RUN pip3 install -r requirements.txt
+# not sure why this doesn't work from inside requirements.txt
+RUN pip3 install -U 'https://github.com/drewp/cyclone/archive/python3.zip'
+
+COPY *.py *.html  ./
+
+ENV PYTHONPATH=/opt/pyfreefare-build
+EXPOSE 10012
+
+CMD ["/usr/bin/python3", "rfid.py", "-v"]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/service/cardReader/build_ctypes_modules.sh	Wed Feb 05 16:40:46 2020 -0800
@@ -0,0 +1,14 @@
+#!/bin/sh
+set -x
+proc=`uname --processor`
+if [ "$proc" = "armv7l" ]; then
+    ARCH=arm-linux-gnueabihf
+    TARGET=armv7l
+else
+    ARCH=x86_64-linux-gnu
+    TARGET=x86_64-Linux
+fi
+CARGS="-I/usr/include/${ARCH} -I/usr/lib/llvm-5.0/lib/clang/5.0.1/include -I/usr/lib/llvm-5.0/lib/"
+clang2py -o /opt/pyfreefare-build/nfc.py --target ${TARGET} --clang-args="${CARGS}" -l /usr/lib/${ARCH}/libnfc.so --comments /opt/pyfreefare/nfc.h
+
+PYTHONPATH=/opt/pyfreefare-build clang2py -o /opt/pyfreefare-build/freefare.py --target ${TARGET} --clang-args="${CARGS}" -l /usr/lib/${ARCH}/libfreefare.so --comments --module nfc /opt/pyfreefare/freefare.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/service/cardReader/index.html	Wed Feb 05 16:40:46 2020 -0800
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+  <head>
+    <title>rfid</title>
+    <meta charset="utf-8" />
+    <meta name="mobile-web-app-capable" content="yes">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <script src="/lib/polymer/1.0.9/webcomponentsjs/webcomponents.min.js"></script>
+    <script src="/lib/require/require-2.3.3.js"></script>
+    <script src="/rdf/common_paths_and_ns.js"></script>
+    <link rel="import" href="rfid-console.html">
+    <style>
+     .served-resources {
+         margin-top: 4em;
+         border-top: 1px solid gray;
+         padding-top: 1em;
+     }
+     .served-resources a {
+         padding-right: 2em;
+     }
+    </style>
+  </head>
+  <body>
+    <rfid-console></rfid-console>
+
+    <template id="t" is="dom-bind">
+      <streamed-graph url="graph/events" graph="{{graph}}"></streamed-graph>
+      <div id="out"></div>
+      <script type="module" src="/rdf/streamed_graph_view.js"></script>
+    </template>
+
+    <div class="served-resources">
+      <a href="stats/">/stats/</a>
+      <a href="graph">/graph</a>
+      <a href="graph/events">/graph/events</a>
+      <a href="output" >(post) /output</a>
+      <a href="rewrite">(post) /rewrite</a>
+    </div>
+  </body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/service/cardReader/local.conf	Wed Feb 05 16:40:46 2020 -0800
@@ -0,0 +1,37 @@
+daemon  off;
+pid /dev/null;
+error_log stderr;
+#worker_processes  1;
+
+events {
+  worker_connections  1024;
+}
+
+http {
+  types {
+    text/html                 html;
+    text/css                  css;
+    image/gif                 gif;
+    image/jpeg                jpeg jpg;
+    application/x-javascript  js;
+    image/png                 png;
+  }
+
+  server {
+    listen 8888;
+    
+    access_log off;
+    
+    location / {
+      proxy_pass http://bang;
+      proxy_set_header Host bigasterisk.com;
+      proxy_buffering off;
+    }
+    location /frontDoor/rfid/ {
+      proxy_pass http://localhost:10012;
+      proxy_set_header Host $http_host;
+      proxy_buffering off;
+      rewrite /frontDoor/rfid(.*) $1 break;
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/service/cardReader/makefile	Wed Feb 05 16:40:46 2020 -0800
@@ -0,0 +1,54 @@
+SERVICE=rfid_pn532_py
+JOB=rfid
+PORT=10012
+RUNHOST=frontdoor
+
+pyfreefare-build-x86/nfc.py: Dockerfile.pyfreefare.x86 pyfreefare/nfc.h pyfreefare/freefare.h build_ctypes_modules.sh
+	docker build --file Dockerfile.pyfreefare.x86 -t pyfreefare_build_x86:latest .
+	docker run --rm --net=host \
+          -v `pwd`/pyfreefare:/opt/pyfreefare \
+          -v `pwd`/pyfreefare-build-x86:/opt/pyfreefare-build \
+          --name pyfreefare_build pyfreefare_build_x86:latest
+
+pyfreefare-build-pi/nfc.py: Dockerfile.pyfreefare.pi pyfreefare/nfc.h pyfreefare/freefare.h build_ctypes_modules.sh
+	docker build --file Dockerfile.pyfreefare.pi -t pyfreefare_build_pi:latest .
+	docker run --rm --net=host \
+          -v `pwd`/pyfreefare:/opt/pyfreefare \
+          -v `pwd`/pyfreefare-build-pi:/opt/pyfreefare-build \
+          --name pyfreefare_build pyfreefare_build_pi:latest
+
+#pyfreefare/nfc.py pyfreefare/freefare.py
+test_tags: tags.py tags_test.py 
+	PYTHONPATH=pyfreefare-build-x86 nose2-3 tags_test
+
+
+build_image_x86: pyfreefare-build-x86/nfc.py pyfreefare-build-x86/freefare.py Dockerfile.x86
+	rm -rf tmp_ctx
+	mkdir -p tmp_ctx
+	cp -a Dockerfile.x86 ../../lib/*.py *.py *.txt *.html pyfreefare-build-x86 tmp_ctx
+	docker build --network=host --file Dockerfile.x86 -t bang6:5000/$(SERVICE)_x86:latest tmp_ctx
+	docker push bang6:5000/$(SERVICE)_x86:latest
+
+build_image_pi: pyfreefare-build-pi/nfc.py pyfreefare-build-pi/freefare.py Dockerfile.pi
+	rm -rf tmp_ctx
+	mkdir -p tmp_ctx
+	cp -a Dockerfile.pi ../../lib/*.py *.py *.txt *.html pyfreefare-build-pi tmp_ctx
+	docker build --network=host --file Dockerfile.pi -t bang6:5000/$(SERVICE)_pi:latest tmp_ctx
+	docker push bang6:5000/$(SERVICE)_pi:latest
+
+run_local_x86: build_image_x86
+	docker run -it --rm --privileged --net=host --hostname=testhost --cap-add=SYS_PTRACE --name $(JOB)_run bang6:5000/$(SERVICE)_x86:latest python3 rfid.py -v
+
+
+# test on pi:
+# docker pull bang6:5000/rfid_pn532_py_pi:latest && docker run -it --rm --privileged --name rfid_shell bang6:5000/rfid_pn532_py_pi:latest nose2-3 tags_test
+
+fresh_sudo:
+	sudo -v
+redeploy: fresh_sudo build_image_pi
+	sudo /my/proj/ansible/playbook -l $(RUNHOST) -t rfid
+	supervisorctl -s http://$(RUNHOST):9001/ restart $(JOB)_$(PORT)
+
+nginx_local:
+	nginx -c `pwd`/local.conf
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/service/cardReader/pyfreefare/freefare.h	Wed Feb 05 16:40:46 2020 -0800
@@ -0,0 +1,557 @@
+
+#ifndef __FREEFARE_H__
+#define __FREEFARE_H__
+
+#include <sys/types.h>
+
+#include <stdint.h>
+
+#include <nfc/nfc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+enum freefare_tag_type {
+    FELICA,
+    MIFARE_MINI,
+    MIFARE_CLASSIC_1K,
+    MIFARE_CLASSIC_4K,
+    MIFARE_DESFIRE,
+//    MIFARE_PLUS_S2K,
+//    MIFARE_PLUS_S4K,
+//    MIFARE_PLUS_X2K,
+//    MIFARE_PLUS_X4K,
+    MIFARE_ULTRALIGHT,
+    MIFARE_ULTRALIGHT_C,
+    NTAG_21x,
+};
+  typedef enum freefare_tag_type freefare_tag_type;
+  
+struct freefare_tag;
+typedef struct freefare_tag *FreefareTag;
+
+/* Replace any MifareTag by the generic FreefareTag. */
+typedef struct freefare_tag *MifareTag;
+
+struct mifare_desfire_key;
+typedef struct mifare_desfire_key *MifareDESFireKey;
+
+struct ntag21x_key;
+typedef struct ntag21x_key *NTAG21xKey;
+
+typedef uint8_t MifareUltralightPageNumber;
+typedef unsigned char MifareUltralightPage[4];
+
+FreefareTag	*freefare_get_tags(nfc_device *device);
+FreefareTag	 freefare_tag_new(nfc_device *device, nfc_target target);
+freefare_tag_type freefare_get_tag_type(FreefareTag tag);
+const char	*freefare_get_tag_friendly_name(FreefareTag tag);
+char		*freefare_get_tag_uid(FreefareTag tag);
+void		 freefare_free_tag(FreefareTag tag);
+void		 freefare_free_tags(FreefareTag *tags);
+bool		 freefare_selected_tag_is_present(nfc_device *device);
+
+const char	*freefare_strerror(FreefareTag tag);
+int		 freefare_strerror_r(FreefareTag tag, char *buffer, size_t len);
+void		 freefare_perror(FreefareTag tag, const char *string);
+
+
+
+  // bool		 felica_taste(nfc_device *device, nfc_target target);
+
+  // #define FELICA_SC_RW 0x0009
+// #define FELICA_SC_RO 0x000b
+// 
+// FreefareTag	 felica_tag_new(nfc_device *device, nfc_target target);
+// void		 felica_tag_free(FreefareTag tag);
+// 
+// ssize_t		 felica_read(FreefareTag tag, uint16_t service, uint8_t block, uint8_t *data, size_t length);
+// ssize_t		 felica_read_ex(FreefareTag tag, uint16_t service, uint8_t block_count, uint8_t blocks[], uint8_t *data, size_t length);
+// ssize_t		 felica_write(FreefareTag tag, uint16_t service, uint8_t block, uint8_t *data, size_t length);
+// ssize_t		 felica_write_ex(FreefareTag tag, uint16_t service, uint8_t block_count, uint8_t blocks[], uint8_t *data, size_t length);
+// 
+// 
+// 
+// bool		 mifare_ultralight_taste(nfc_device *device, nfc_target target);
+// bool		 mifare_ultralightc_taste(nfc_device *device, nfc_target target);
+// FreefareTag	 mifare_ultralight_tag_new(nfc_device *device, nfc_target target);
+// FreefareTag	 mifare_ultralightc_tag_new(nfc_device *device, nfc_target target);
+// void		 mifare_ultralight_tag_free(FreefareTag tag);
+// void		 mifare_ultralightc_tag_free(FreefareTag tag);
+// 
+// int		 mifare_ultralight_connect(FreefareTag tag);
+// int		 mifare_ultralight_disconnect(FreefareTag tag);
+// 
+// int		 mifare_ultralight_read(FreefareTag tag, const MifareUltralightPageNumber page, MifareUltralightPage *data);
+// int		 mifare_ultralight_write(FreefareTag tag, const MifareUltralightPageNumber page, const MifareUltralightPage data);
+// 
+// int		 mifare_ultralightc_authenticate(FreefareTag tag, const MifareDESFireKey key);
+// int		 mifare_ultralightc_set_key(FreefareTag tag, MifareDESFireKey key);
+// bool		 is_mifare_ultralight(FreefareTag tag);
+// bool		 is_mifare_ultralightc(FreefareTag tag);
+// bool		 is_mifare_ultralightc_on_reader(nfc_device *device, nfc_iso14443a_info nai);
+// 
+// 
+// 
+// bool		 ntag21x_taste(nfc_device *device, nfc_target target);
+// uint8_t		 ntag21x_last_error(FreefareTag tag);
+// 
+// /* NTAG21x access features */
+// #define NTAG_PROT 0x80
+// #define NTAG_CFGLCK 0x40
+// #define NTAG_NFC_CNT_EN 0x20
+// #define NTAG_NFC_CNT_PWD_PROT 0x10
+// #define NTAG_AUTHLIM 0x07
+// 
+// enum ntag_tag_subtype {
+//     NTAG_UNKNOWN,
+//     NTAG_213,
+//     NTAG_215,
+//     NTAG_216
+// };
+// 
+// FreefareTag	 ntag21x_tag_new(nfc_device *device, nfc_target target);
+// FreefareTag	 ntag21x_tag_reuse(FreefareTag tag);  /* Copy data from Ultralight tag to new NTAG21x, don't forget to free your old tag */
+// NTAG21xKey	 ntag21x_key_new(const uint8_t data[4], const uint8_t pack[2]); /* Create new key */
+// void		 ntag21x_key_free(NTAG21xKey key);  /* Clear key from memory */
+// void		 ntag21x_tag_free(FreefareTag tag);
+// int		 ntag21x_connect(FreefareTag tag);
+// int		 ntag21x_disconnect(FreefareTag tag);
+// int		 ntag21x_get_info(FreefareTag tag);  /* Get all information about tag (size,vendor ...) */
+// enum  ntag_tag_subtype ntag21x_get_subtype(FreefareTag tag);  /* Get subtype of tag */
+// uint8_t		 ntag21x_get_last_page(FreefareTag tag);  /* Get last page address based on gathered info from function above */
+// int		 ntag21x_read_signature(FreefareTag tag, uint8_t *data); /* Get tag signature */
+// int		 ntag21x_set_pwd(FreefareTag tag, uint8_t data[4]);  /* Set password */
+// int		 ntag21x_set_pack(FreefareTag tag, uint8_t data[2]);  /* Set pack */
+// int		 ntag21x_set_key(FreefareTag tag, const NTAG21xKey key); /* Set key */
+// int		 ntag21x_set_auth(FreefareTag tag, uint8_t byte); /* Set AUTH0 byte (from which page starts password protection) */
+// int		 ntag21x_get_auth(FreefareTag tag, uint8_t *byte); /* Get AUTH0 byte */
+// int		 ntag21x_access_enable(FreefareTag tag, uint8_t byte); /* Enable access feature in ACCESS byte */
+// int		 ntag21x_access_disable(FreefareTag tag, uint8_t byte); /* Disable access feature in ACCESS byte */
+// int		 ntag21x_get_access(FreefareTag tag, uint8_t *byte); /* Get ACCESS byte */
+// int		 ntag21x_check_access(FreefareTag tag, uint8_t byte, bool *result); /* Check if access feature is enabled */
+// int		 ntag21x_get_authentication_limit(FreefareTag tag, uint8_t *byte); /* Get authentication limit */
+// int		 ntag21x_set_authentication_limit(FreefareTag tag, uint8_t byte); /* Set authentication limit (0x00 = disabled, [0x01,0x07] = valid range, > 0x07 invalid range) */
+// int		 ntag21x_read(FreefareTag tag, uint8_t page, uint8_t *data); /* Read 16 bytes starting from page */
+// int		 ntag21x_read4(FreefareTag tag, uint8_t page, uint8_t *data); /* Read 4 bytes on page */
+// int		 ntag21x_fast_read(FreefareTag tag, uint8_t start_page, uint8_t end_page, uint8_t *data); /* Read n*4 bytes from range [start_page,end_page] */
+// int		 ntag21x_fast_read4(FreefareTag tag, uint8_t page, uint8_t *data); /* Fast read certain page */
+// int		 ntag21x_read_cnt(FreefareTag tag, uint8_t *data);  /* Read 3-byte NFC counter if enabled else it returns error */
+// int		 ntag21x_write(FreefareTag tag, uint8_t page, uint8_t data[4]);  /* Write 4 bytes to page */
+// int		 ntag21x_compatibility_write(FreefareTag tag, uint8_t page, uint8_t data[4]);  /* Writes 4 bytes to page with mifare classic write */
+// int		 ntag21x_authenticate(FreefareTag tag, const NTAG21xKey key);  /* Authenticate with tag */
+// bool		 is_ntag21x(FreefareTag tag);  /* Check if tag type is NTAG21x */
+// bool		 ntag21x_is_auth_supported(nfc_device *device, nfc_iso14443a_info nai);  /* Check if tag supports 21x commands */
+// 
+// 
+// 
+// bool             mifare_mini_taste(nfc_device *device, nfc_target target);
+// bool		 mifare_classic1k_taste(nfc_device *device, nfc_target target);
+// bool		 mifare_classic4k_taste(nfc_device *device, nfc_target target);
+// FreefareTag      mifare_mini_tag_new(nfc_device *device, nfc_target target);
+// FreefareTag	 mifare_classic1k_tag_new(nfc_device *device, nfc_target target);
+// FreefareTag	 mifare_classic4k_tag_new(nfc_device *device, nfc_target target);
+void		 mifare_classic_tag_free(FreefareTag tag);
+// 
+typedef unsigned char MifareClassicBlock[16];
+
+typedef uint8_t MifareClassicSectorNumber;
+typedef unsigned char MifareClassicBlockNumber;
+
+typedef enum { MFC_KEY_A, MFC_KEY_B } MifareClassicKeyType;
+typedef unsigned char MifareClassicKey[6];
+
+/* NFC Forum public key */
+extern const MifareClassicKey mifare_classic_nfcforum_public_key_a;
+
+int		 mifare_classic_connect(FreefareTag tag);
+int		 mifare_classic_disconnect(FreefareTag tag);
+
+int		 mifare_classic_authenticate(FreefareTag tag, const MifareClassicBlockNumber block, const MifareClassicKey key, const MifareClassicKeyType key_type);
+int		 mifare_classic_read(FreefareTag tag, const MifareClassicBlockNumber block, MifareClassicBlock *data);
+int		 mifare_classic_init_value(FreefareTag tag, const MifareClassicBlockNumber block, const int32_t value, const MifareClassicBlockNumber adr);
+int		 mifare_classic_read_value(FreefareTag tag, const MifareClassicBlockNumber block, int32_t *value, MifareClassicBlockNumber *adr);
+int		 mifare_classic_write(FreefareTag tag, const MifareClassicBlockNumber block, const MifareClassicBlock data);
+
+int		 mifare_classic_increment(FreefareTag tag, const MifareClassicBlockNumber block, const uint32_t amount);
+int		 mifare_classic_decrement(FreefareTag tag, const MifareClassicBlockNumber block, const uint32_t amount);
+int		 mifare_classic_restore(FreefareTag tag, const MifareClassicBlockNumber block);
+int		 mifare_classic_transfer(FreefareTag tag, const MifareClassicBlockNumber block);
+
+int		 mifare_classic_get_trailer_block_permission(FreefareTag tag, const MifareClassicBlockNumber block, const uint16_t permission, const MifareClassicKeyType key_type);
+int		 mifare_classic_get_data_block_permission(FreefareTag tag, const MifareClassicBlockNumber block, const unsigned char permission, const MifareClassicKeyType key_type);
+
+int		 mifare_classic_format_sector(FreefareTag tag, const MifareClassicSectorNumber sector);
+
+void		 mifare_classic_trailer_block(MifareClassicBlock *block, const MifareClassicKey key_a, uint8_t ab_0, uint8_t ab_1, uint8_t ab_2, uint8_t ab_tb, const uint8_t gpb, const MifareClassicKey key_b);
+
+MifareClassicSectorNumber mifare_classic_block_sector(MifareClassicBlockNumber block);
+MifareClassicBlockNumber  mifare_classic_sector_first_block(MifareClassicSectorNumber sector);
+size_t		 mifare_classic_sector_block_count(MifareClassicSectorNumber sector);
+MifareClassicBlockNumber  mifare_classic_sector_last_block(MifareClassicSectorNumber sector);
+
+#define C_000 0
+#define C_001 1
+#define C_010 2
+#define C_011 3
+#define C_100 4
+#define C_101 5
+#define C_110 6
+#define C_111 7
+#define C_DEFAULT 255
+
+/* MIFARE Classic Access Bits */
+#define MCAB_R 0x8
+#define MCAB_W 0x4
+#define MCAB_D 0x2
+#define MCAB_I 0x1
+
+#define MCAB_READ_KEYA         0x400
+#define MCAB_WRITE_KEYA        0x100
+#define MCAB_READ_ACCESS_BITS  0x040
+#define MCAB_WRITE_ACCESS_BITS 0x010
+#define MCAB_READ_KEYB         0x004
+#define MCAB_WRITE_KEYB        0x001
+// 
+// struct mad_aid {
+//     uint8_t application_code;
+//     uint8_t function_cluster_code;
+// };
+// typedef struct mad_aid MadAid;
+// 
+// struct mad;
+// typedef struct mad *Mad;
+// 
+// /* MAD Public read key A */
+// extern const MifareClassicKey mad_public_key_a;
+// 
+// /* AID - Adminisration codes */
+// extern const MadAid mad_free_aid;
+// extern const MadAid mad_defect_aid;
+// extern const MadAid mad_reserved_aid;
+// extern const MadAid mad_card_holder_aid;
+// extern const MadAid mad_not_applicable_aid;
+// 
+// /* NFC Forum AID */
+// extern const MadAid mad_nfcforum_aid;
+// 
+// Mad		 mad_new(const uint8_t version);
+// Mad		 mad_read(FreefareTag tag);
+// int		 mad_write(FreefareTag tag, Mad mad, const MifareClassicKey key_b_sector_00, const MifareClassicKey key_b_sector_10);
+// int		 mad_get_version(Mad mad);
+// void		 mad_set_version(Mad mad, const uint8_t version);
+// MifareClassicSectorNumber mad_get_card_publisher_sector(Mad mad);
+// int		 mad_set_card_publisher_sector(Mad mad, const MifareClassicSectorNumber cps);
+// int		 mad_get_aid(Mad mad, const MifareClassicSectorNumber sector, MadAid *aid);
+// int		 mad_set_aid(Mad mad, const MifareClassicSectorNumber sector, MadAid aid);
+// bool		 mad_sector_reserved(const MifareClassicSectorNumber sector);
+// void		 mad_free(Mad mad);
+// 
+// MifareClassicSectorNumber *mifare_application_alloc(Mad mad, const MadAid aid, const size_t size);
+// ssize_t		 mifare_application_read(FreefareTag tag, Mad mad, const MadAid aid, void *buf, size_t nbytes, const MifareClassicKey key, const MifareClassicKeyType key_type);
+// ssize_t		 mifare_application_write(FreefareTag tag, Mad mad, const MadAid aid, const void *buf, size_t nbytes, const MifareClassicKey key, const MifareClassicKeyType key_type);
+// int		 mifare_application_free(Mad mad, const MadAid aid);
+// 
+// MifareClassicSectorNumber *mifare_application_find(Mad mad, const MadAid aid);
+// 
+// 
+// 
+// bool		 mifare_desfire_taste(nfc_device *device, nfc_target target);
+// 
+// /* File types */
+// 
+// enum mifare_desfire_file_types {
+//     MDFT_STANDARD_DATA_FILE             = 0x00,
+//     MDFT_BACKUP_DATA_FILE               = 0x01,
+//     MDFT_VALUE_FILE_WITH_BACKUP         = 0x02,
+//     MDFT_LINEAR_RECORD_FILE_WITH_BACKUP = 0x03,
+//     MDFT_CYCLIC_RECORD_FILE_WITH_BACKUP = 0x04
+// };
+// 
+// /* Communication mode */
+// 
+// #define MDCM_PLAIN      0x00
+// #define MDCM_MACED      0x01
+// #define MDCM_ENCIPHERED 0x03
+// 
+// /* Mifare DESFire master key settings
+// bit 7 - 4: Always 0.
+// bit 3: PICC master key settings frozen = 0 (WARNING - this is irreversible); PICC master key settings changeable when authenticated with PICC master key = 1
+// bit 2: PICC master key authentication required for creating or deleting applications = 0; Authentication not required = 1
+// bit 1: PICC master key authentication required for listing of applications or reading key settings = 0; Free listing of applications and reading key settings = 1
+// bit 0: PICC master key frozen (reversible with configuration change or when formatting card) = 0; PICC master key changeable = 1
+// */
+// 
+// #define MDMK_SETTINGS(picc_master_key_settings_changeable,free_create_delete_application,free_listing_apps_and_key_settings,picc_master_key_changeable) ( \
+// 	(picc_master_key_settings_changeable << 3) | \
+// 	(free_create_delete_application << 2) | \
+// 	(free_listing_apps_and_key_settings << 1) | \
+// 	(picc_master_key_changeable) \
+// 																			)
+// 
+// /* Mifare DESFire EV1 Application crypto operations */
+// 
+// #define APPLICATION_CRYPTO_DES    0x00
+// #define APPLICATION_CRYPTO_3K3DES 0x40
+// #define APPLICATION_CRYPTO_AES    0x80
+// 
+// /* Mifare DESFire Application settings
+//  * bit 7 - 4: Number of key needed to change application keys (key 0 - 13; 0 = master key; 14 = key itself required for key change; 15 = all keys are frozen)
+//  * bit 3: Application configuration frozen = 0; Application configuration changeable when authenticated with application master key = 1
+//  * bit 2: Application master key authentication required for create/delete files = 0; Authentication not required = 1
+//  * bit 1: GetFileIDs, GetFileSettings and GetKeySettings behavior: Master key authentication required = 0; No authentication required = 1
+//  * bit 0 = Application master key frozen = 0; Application master key changeable = 1
+//  */
+// 
+// #define MDAPP_SETTINGS(key_no_for_key_changing,config_changeable,free_create_delete_files,free_listing_contents,app_master_key_changeable) ( \
+// 	(key_no_for_key_changing << 4) | \
+// 	(config_changeable << 3) | \
+// 	(free_create_delete_files << 2) | \
+// 	(free_listing_contents << 1) | \
+// 	(app_master_key_changeable) \
+// 																	   )
+// 
+// /* Access right */
+// 
+// #define MDAR(read,write,read_write,change_access_rights) (    \
+// 	(read << 12) | \
+// 	(write << 8) | \
+// 	(read_write << 4) | \
+// 	(change_access_rights) \
+// 							 )
+// 
+// #define MDAR_READ(ar)       (((ar) >> 12) & 0x0f)
+// #define MDAR_WRITE(ar)      (((ar) >>  8) & 0x0f)
+// #define MDAR_READ_WRITE(ar) (((ar) >>  4) & 0x0f)
+// #define MDAR_CHANGE_AR(ar)  ((ar)         & 0x0f)
+// 
+// #define MDAR_KEY0  0x0
+// #define MDAR_KEY1  0x1
+// #define MDAR_KEY2  0x2
+// #define MDAR_KEY3  0x3
+// #define MDAR_KEY4  0x4
+// #define MDAR_KEY5  0x5
+// #define MDAR_KEY6  0x6
+// #define MDAR_KEY7  0x7
+// #define MDAR_KEY8  0x8
+// #define MDAR_KEY9  0x9
+// #define MDAR_KEY10 0xa
+// #define MDAR_KEY11 0xb
+// #define MDAR_KEY12 0xc
+// #define MDAR_KEY13 0xd
+// #define MDAR_FREE  0xE
+// #define MDAR_DENY  0xF
+// 
+// /* Status and error codes */
+// 
+// #define	OPERATION_OK		0x00
+// #define	NO_CHANGES		0x0C
+// #define	OUT_OF_EEPROM_ERROR	0x0E
+// #define	ILLEGAL_COMMAND_CODE	0x1C
+// #define	INTEGRITY_ERROR		0x1E
+// #define	NO_SUCH_KEY		0x40
+// #define	LENGTH_ERROR		0x7E
+// #define	PERMISSION_ERROR	0x9D
+// #define	PARAMETER_ERROR		0x9E
+// #define	APPLICATION_NOT_FOUND	0xA0
+// #define	APPL_INTEGRITY_ERROR	0xA1
+// #define	AUTHENTICATION_ERROR	0xAE
+// #define	ADDITIONAL_FRAME	0xAF
+// #define	BOUNDARY_ERROR		0xBE
+// #define	PICC_INTEGRITY_ERROR	0xC1
+// #define	COMMAND_ABORTED		0xCA
+// #define	PICC_DISABLED_ERROR	0xCD
+// #define	COUNT_ERROR		0xCE
+// #define	DUPLICATE_ERROR		0xDE
+// #define	EEPROM_ERROR		0xEE
+// #define	FILE_NOT_FOUND		0xF0
+// #define	FILE_INTEGRITY_ERROR	0xF1
+// 
+// /* Error code managed by the library */
+// 
+// #define CRYPTO_ERROR            0x01
+// #define TAG_INFO_MISSING_ERROR	0xBA
+// #define UNKNOWN_TAG_TYPE_ERROR	0xBB
+// 
+// struct mifare_desfire_aid;
+// typedef struct mifare_desfire_aid *MifareDESFireAID;
+// 
+// struct mifare_desfire_df {
+//     uint32_t aid;
+//     uint16_t fid;
+//     uint8_t df_name[16];
+//     size_t df_name_len;
+// };
+// typedef struct mifare_desfire_df MifareDESFireDF;
+// 
+// MifareDESFireAID mifare_desfire_aid_new(uint32_t aid);
+// MifareDESFireAID mifare_desfire_aid_new_with_mad_aid(MadAid mad_aid, uint8_t n);
+// uint32_t	 mifare_desfire_aid_get_aid(MifareDESFireAID aid);
+// 
+// uint8_t		 mifare_desfire_last_pcd_error(FreefareTag tag);
+// uint8_t		 mifare_desfire_last_picc_error(FreefareTag tag);
+// 
+// #pragma pack (push)
+// #pragma pack (1)
+// struct mifare_desfire_version_info {
+//     struct {
+// 	uint8_t vendor_id;
+// 	uint8_t type;
+// 	uint8_t subtype;
+// 	uint8_t version_major;
+// 	uint8_t version_minor;
+// 	uint8_t storage_size;
+// 	uint8_t protocol;
+//     } hardware;
+//     struct {
+// 	uint8_t vendor_id;
+// 	uint8_t type;
+// 	uint8_t subtype;
+// 	uint8_t version_major;
+// 	uint8_t version_minor;
+// 	uint8_t storage_size;
+// 	uint8_t protocol;
+//     } software;
+//     uint8_t uid[7];
+//     uint8_t batch_number[5];
+//     uint8_t production_week;
+//     uint8_t production_year;
+// };
+// #pragma pack (pop)
+// 
+// struct mifare_desfire_file_settings {
+//     uint8_t file_type;
+//     uint8_t communication_settings;
+//     uint16_t access_rights;
+//     union {
+// 	struct {
+// 	    uint32_t file_size;
+// 	} standard_file;
+// 	struct {
+// 	    int32_t lower_limit;
+// 	    int32_t upper_limit;
+// 	    int32_t limited_credit_value;
+// 	    uint8_t limited_credit_enabled;
+// 	} value_file;
+// 	struct {
+// 	    uint32_t record_size;
+// 	    uint32_t max_number_of_records;
+// 	    uint32_t current_number_of_records;
+// 	} linear_record_file;
+//     } settings;
+// };
+// 
+// FreefareTag	 mifare_desfire_tag_new(nfc_device *device, nfc_target target);
+// void		 mifare_desfire_tag_free(FreefareTag tags);
+// 
+// int		 mifare_desfire_connect(FreefareTag tag);
+// int		 mifare_desfire_disconnect(FreefareTag tag);
+// 
+// int		 mifare_desfire_authenticate(FreefareTag tag, uint8_t key_no, MifareDESFireKey key);
+// int		 mifare_desfire_authenticate_iso(FreefareTag tag, uint8_t key_no, MifareDESFireKey key);
+// int		 mifare_desfire_authenticate_aes(FreefareTag tag, uint8_t key_no, MifareDESFireKey key);
+// int		 mifare_desfire_change_key_settings(FreefareTag tag, uint8_t settings);
+// int		 mifare_desfire_get_key_settings(FreefareTag tag, uint8_t *settings, uint8_t *max_keys);
+// int		 mifare_desfire_change_key(FreefareTag tag, uint8_t key_no, MifareDESFireKey new_key, MifareDESFireKey old_key);
+// int		 mifare_desfire_get_key_version(FreefareTag tag, uint8_t key_no, uint8_t *version);
+// int		 mifare_desfire_create_application(FreefareTag tag, MifareDESFireAID aid, uint8_t settings, uint8_t key_no);
+// int		 mifare_desfire_create_application_3k3des(FreefareTag tag, MifareDESFireAID aid, uint8_t settings, uint8_t key_no);
+// int		 mifare_desfire_create_application_aes(FreefareTag tag, MifareDESFireAID aid, uint8_t settings, uint8_t key_no);
+// 
+// int		 mifare_desfire_create_application_iso(FreefareTag tag, MifareDESFireAID aid, uint8_t settings, uint8_t key_no, int want_iso_file_identifiers, uint16_t iso_file_id, uint8_t *iso_file_name, size_t iso_file_name_len);
+// int		 mifare_desfire_create_application_3k3des_iso(FreefareTag tag, MifareDESFireAID aid, uint8_t settings, uint8_t key_no, int want_iso_file_identifiers, uint16_t iso_file_id, uint8_t *iso_file_name, size_t iso_file_name_len);
+// int		 mifare_desfire_create_application_aes_iso(FreefareTag tag, MifareDESFireAID aid, uint8_t settings, uint8_t key_no, int want_iso_file_identifiers, uint16_t iso_file_id, uint8_t *iso_file_name, size_t iso_file_name_len);
+// 
+// int		 mifare_desfire_delete_application(FreefareTag tag, MifareDESFireAID aid);
+// int		 mifare_desfire_get_application_ids(FreefareTag tag, MifareDESFireAID *aids[], size_t *count);
+// int		 mifare_desfire_get_df_names(FreefareTag tag, MifareDESFireDF *dfs[], size_t *count);
+// void		 mifare_desfire_free_application_ids(MifareDESFireAID aids[]);
+// int		 mifare_desfire_select_application(FreefareTag tag, MifareDESFireAID aid);
+// int		 mifare_desfire_format_picc(FreefareTag tag);
+// int		 mifare_desfire_get_version(FreefareTag tag, struct mifare_desfire_version_info *version_info);
+// int		 mifare_desfire_free_mem(FreefareTag tag, uint32_t *size);
+// int		 mifare_desfire_set_configuration(FreefareTag tag, bool disable_format, bool enable_random_uid);
+// int		 mifare_desfire_set_default_key(FreefareTag tag, MifareDESFireKey key);
+// int		 mifare_desfire_set_ats(FreefareTag tag, uint8_t *ats);
+// int		 mifare_desfire_get_card_uid(FreefareTag tag, char **uid);
+// int		 mifare_desfire_get_card_uid_raw(FreefareTag tag, uint8_t uid[7]);
+// int		 mifare_desfire_get_file_ids(FreefareTag tag, uint8_t **files, size_t *count);
+// int		 mifare_desfire_get_iso_file_ids(FreefareTag tag, uint16_t **files, size_t *count);
+// int		 mifare_desfire_get_file_settings(FreefareTag tag, uint8_t file_no, struct mifare_desfire_file_settings *settings);
+// int		 mifare_desfire_change_file_settings(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights);
+// int		 mifare_desfire_create_std_data_file(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t file_size);
+// int		 mifare_desfire_create_std_data_file_iso(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t file_size, uint16_t iso_file_id);
+// int		 mifare_desfire_create_backup_data_file(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t file_size);
+// int		 mifare_desfire_create_backup_data_file_iso(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t file_size, uint16_t iso_file_id);
+// int		 mifare_desfire_create_value_file(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, int32_t lower_limit, int32_t upper_limit, int32_t value, uint8_t limited_credit_enable);
+// int		 mifare_desfire_create_linear_record_file(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t record_size, uint32_t max_number_of_records);
+// int		 mifare_desfire_create_linear_record_file_iso(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t record_size, uint32_t max_number_of_records, uint16_t iso_file_id);
+// int		 mifare_desfire_create_cyclic_record_file(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t record_size, uint32_t max_number_of_records);
+// int		 mifare_desfire_create_cyclic_record_file_iso(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t record_size, uint32_t max_number_of_records, uint16_t iso_file_id);
+// int		 mifare_desfire_delete_file(FreefareTag tag, uint8_t file_no);
+// 
+// ssize_t		 mifare_desfire_read_data(FreefareTag tag, uint8_t file_no, off_t offset, size_t length, void *data);
+// ssize_t		 mifare_desfire_read_data_ex(FreefareTag tag, uint8_t file_no, off_t offset, size_t length, void *data, int cs);
+// ssize_t		 mifare_desfire_write_data(FreefareTag tag, uint8_t file_no, off_t offset, size_t length, const void *data);
+// ssize_t		 mifare_desfire_write_data_ex(FreefareTag tag, uint8_t file_no, off_t offset, size_t length, const void *data, int cs);
+// int		 mifare_desfire_get_value(FreefareTag tag, uint8_t file_no, int32_t *value);
+// int		 mifare_desfire_get_value_ex(FreefareTag tag, uint8_t file_no, int32_t *value, int cs);
+// int		 mifare_desfire_credit(FreefareTag tag, uint8_t file_no, int32_t amount);
+// int		 mifare_desfire_credit_ex(FreefareTag tag, uint8_t file_no, int32_t amount, int cs);
+// int		 mifare_desfire_debit(FreefareTag tag, uint8_t file_no, int32_t amount);
+// int		 mifare_desfire_debit_ex(FreefareTag tag, uint8_t file_no, int32_t amount, int cs);
+// int		 mifare_desfire_limited_credit(FreefareTag tag, uint8_t file_no, int32_t amount);
+// int		 mifare_desfire_limited_credit_ex(FreefareTag tag, uint8_t file_no, int32_t amount, int cs);
+// ssize_t		 mifare_desfire_write_record(FreefareTag tag, uint8_t file_no, off_t offset, size_t length, void *data);
+// ssize_t		 mifare_desfire_write_record_ex(FreefareTag tag, uint8_t file_no, off_t offset, size_t length, void *data, int cs);
+// ssize_t		 mifare_desfire_read_records(FreefareTag tag, uint8_t file_no, off_t offset, size_t length, void *data);
+// ssize_t		 mifare_desfire_read_records_ex(FreefareTag tag, uint8_t file_no, off_t offset, size_t length, void *data, int cs);
+// int		 mifare_desfire_clear_record_file(FreefareTag tag, uint8_t file_no);
+// int		 mifare_desfire_commit_transaction(FreefareTag tag);
+// int		 mifare_desfire_abort_transaction(FreefareTag tag);
+// 
+// MifareDESFireKey mifare_desfire_des_key_new(const uint8_t value[8]);
+// MifareDESFireKey mifare_desfire_3des_key_new(const uint8_t value[16]);
+// MifareDESFireKey mifare_desfire_des_key_new_with_version(const uint8_t value[8]);
+// MifareDESFireKey mifare_desfire_3des_key_new_with_version(const uint8_t value[16]);
+// MifareDESFireKey mifare_desfire_3k3des_key_new(const uint8_t value[24]);
+// MifareDESFireKey mifare_desfire_3k3des_key_new_with_version(const uint8_t value[24]);
+// MifareDESFireKey mifare_desfire_aes_key_new(const uint8_t value[16]);
+// MifareDESFireKey mifare_desfire_aes_key_new_with_version(const uint8_t value[16], uint8_t version);
+// uint8_t		 mifare_desfire_key_get_version(MifareDESFireKey key);
+// void		 mifare_desfire_key_set_version(MifareDESFireKey key, uint8_t version);
+// void		 mifare_desfire_key_free(MifareDESFireKey key);
+// 
+// uint8_t		*tlv_encode(const uint8_t type, const uint8_t *istream, uint16_t isize, size_t *osize);
+// uint8_t		*tlv_decode(const uint8_t *istream, uint8_t *type, uint16_t *size);
+// size_t		tlv_record_length(const uint8_t *istream, size_t *field_length_size, size_t *field_value_size);
+// uint8_t		*tlv_append(uint8_t *a, uint8_t *b);
+// 
+// typedef enum mifare_key_type {
+//     MIFARE_KEY_DES,
+//     MIFARE_KEY_2K3DES,
+//     MIFARE_KEY_3K3DES,
+//     MIFARE_KEY_AES128,
+// 
+//     MIFARE_KEY_LAST = MIFARE_KEY_AES128
+// } MifareKeyType;
+// 
+// struct mifare_key_deriver;
+// typedef struct mifare_key_deriver *MifareKeyDeriver;
+// 
+// MifareKeyDeriver mifare_key_deriver_new_an10922(MifareDESFireKey master_key, MifareKeyType output_key_type);
+// int		 mifare_key_deriver_begin(MifareKeyDeriver deriver);
+// int		 mifare_key_deriver_update_data(MifareKeyDeriver deriver, const uint8_t *data, size_t len);
+// int		 mifare_key_deriver_update_uid(MifareKeyDeriver deriver, FreefareTag tag);
+// int		 mifare_key_deriver_update_aid(MifareKeyDeriver deriver, MifareDESFireAID aid);
+// int		 mifare_key_deriver_update_cstr(MifareKeyDeriver deriver, const char *cstr);
+// MifareDESFireKey mifare_key_deriver_end(MifareKeyDeriver deriver);
+// int		 mifare_key_deriver_end_raw(MifareKeyDeriver deriver, uint8_t* diversified_bytes, size_t data_max_len);
+// void		 mifare_key_deriver_free(MifareKeyDeriver state);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif /* !__FREEFARE_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/service/cardReader/pyfreefare/nfc.h	Wed Feb 05 16:40:46 2020 -0800
@@ -0,0 +1,516 @@
+/*-
+ * Free/Libre Near Field Communication (NFC) library
+ *
+ * Libnfc historical contributors:
+ * Copyright (C) 2009      Roel Verdult
+ * Copyright (C) 2009-2013 Romuald Conty
+ * Copyright (C) 2010-2012 Romain Tartière
+ * Copyright (C) 2010-2013 Philippe Teuwen
+ * Copyright (C) 2012-2013 Ludovic Rousseau
+ * See AUTHORS file for a more comprehensive list of contributors.
+ * Additional contributors of this file:
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+
+/**
+ * @file nfc.h
+ * @brief libnfc interface
+ *
+ * Provide all usefull functions (API) to handle NFC devices.
+ */
+
+
+typedef unsigned char uint8_t;
+
+#  include <sys/time.h>
+
+#  include <stdint.h>
+#  include <stdbool.h>
+
+/*-
+ * Free/Libre Near Field Communication (NFC) library
+ *
+ * Libnfc historical contributors:
+ * Copyright (C) 2009      Roel Verdult
+ * Copyright (C) 2009-2013 Romuald Conty
+ * Copyright (C) 2010-2012 Romain Tartière
+ * Copyright (C) 2010-2013 Philippe Teuwen
+ * Copyright (C) 2012-2013 Ludovic Rousseau
+ * See AUTHORS file for a more comprehensive list of contributors.
+ * Additional contributors of this file:
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file nfc-types.h
+ * @brief Define NFC types
+ */
+
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+
+#define NFC_BUFSIZE_CONNSTRING 1024
+
+
+/**
+ * NFC context
+ */
+struct nfc_context;
+typedef struct nfc_context nfc_context;
+
+/**
+ * NFC device
+ */
+struct nfc_device;
+typedef struct nfc_device nfc_device;
+
+/**
+ * NFC device driver
+ */
+struct nfc_driver;
+typedef struct nfc_driver nfc_driver;
+
+/**
+ * Connection string
+ */
+typedef char nfc_connstring[NFC_BUFSIZE_CONNSTRING];
+
+/**
+ * Properties
+ */
+typedef enum {
+  /**
+   * Default command processing timeout
+   * Property value's (duration) unit is ms and 0 means no timeout (infinite).
+   * Default value is set by driver layer
+   */
+  NP_TIMEOUT_COMMAND,
+  /**
+   * Timeout between ATR_REQ and ATR_RES
+   * When the device is in initiator mode, a target is considered as mute if no
+   * valid ATR_RES is received within this timeout value.
+   * Default value for this property is 103 ms on PN53x based devices.
+   */
+  NP_TIMEOUT_ATR,
+  /**
+   * Timeout value to give up reception from the target in case of no answer.
+   * Default value for this property is 52 ms).
+   */
+  NP_TIMEOUT_COM,
+  /** Let the PN53X chip handle the CRC bytes. This means that the chip appends
+  * the CRC bytes to the frames that are transmitted. It will parse the last
+  * bytes from received frames as incoming CRC bytes. They will be verified
+  * against the used modulation and protocol. If an frame is expected with
+  * incorrect CRC bytes this option should be disabled. Example frames where
+  * this is useful are the ATQA and UID+BCC that are transmitted without CRC
+  * bytes during the anti-collision phase of the ISO14443-A protocol. */
+  NP_HANDLE_CRC,
+  /** Parity bits in the network layer of ISO14443-A are by default generated and
+   * validated in the PN53X chip. This is a very convenient feature. On certain
+   * times though it is useful to get full control of the transmitted data. The
+   * proprietary MIFARE Classic protocol uses for example custom (encrypted)
+   * parity bits. For interoperability it is required to be completely
+   * compatible, including the arbitrary parity bits. When this option is
+   * disabled, the functions to communicating bits should be used. */
+  NP_HANDLE_PARITY,
+  /** This option can be used to enable or disable the electronic field of the
+   * NFC device. */
+  NP_ACTIVATE_FIELD,
+  /** The internal CRYPTO1 co-processor can be used to transmit messages
+   * encrypted. This option is automatically activated after a successful MIFARE
+   * Classic authentication. */
+  NP_ACTIVATE_CRYPTO1,
+  /** The default configuration defines that the PN53X chip will try indefinitely
+   * to invite a tag in the field to respond. This could be desired when it is
+   * certain a tag will enter the field. On the other hand, when this is
+   * uncertain, it will block the application. This option could best be compared
+   * to the (NON)BLOCKING option used by (socket)network programming. */
+  NP_INFINITE_SELECT,
+  /** If this option is enabled, frames that carry less than 4 bits are allowed.
+   * According to the standards these frames should normally be handles as
+   * invalid frames. */
+  NP_ACCEPT_INVALID_FRAMES,
+  /** If the NFC device should only listen to frames, it could be useful to let
+   * it gather multiple frames in a sequence. They will be stored in the internal
+   * FIFO of the PN53X chip. This could be retrieved by using the receive data
+   * functions. Note that if the chip runs out of bytes (FIFO = 64 bytes long),
+   * it will overwrite the first received frames, so quick retrieving of the
+   * received data is desirable. */
+  NP_ACCEPT_MULTIPLE_FRAMES,
+  /** This option can be used to enable or disable the auto-switching mode to
+   * ISO14443-4 is device is compliant.
+   * In initiator mode, it means that NFC chip will send RATS automatically when
+   * select and it will automatically poll for ISO14443-4 card when ISO14443A is
+   * requested.
+   * In target mode, with a NFC chip compliant (ie. PN532), the chip will
+   * emulate a 14443-4 PICC using hardware capability */
+  NP_AUTO_ISO14443_4,
+  /** Use automatic frames encapsulation and chaining. */
+  NP_EASY_FRAMING,
+  /** Force the chip to switch in ISO14443-A */
+  NP_FORCE_ISO14443_A,
+  /** Force the chip to switch in ISO14443-B */
+  NP_FORCE_ISO14443_B,
+  /** Force the chip to run at 106 kbps */
+  NP_FORCE_SPEED_106,
+} nfc_property;
+
+// Compiler directive, set struct alignment to 1 uint8_t for compatibility
+#  pragma pack(1)
+
+/**
+ * @enum nfc_dep_mode
+ * @brief NFC D.E.P. (Data Exchange Protocol) active/passive mode
+ */
+typedef enum {
+  NDM_UNDEFINED = 0,
+  NDM_PASSIVE,
+  NDM_ACTIVE,
+} nfc_dep_mode;
+
+/**
+ * @struct nfc_dep_info
+ * @brief NFC target information in D.E.P. (Data Exchange Protocol) see ISO/IEC 18092 (NFCIP-1)
+ */
+typedef struct {
+  /** NFCID3 */
+  uint8_t  abtNFCID3[10];
+  /** DID */
+  uint8_t  btDID;
+  /** Supported send-bit rate */
+  uint8_t  btBS;
+  /** Supported receive-bit rate */
+  uint8_t  btBR;
+  /** Timeout value */
+  uint8_t  btTO;
+  /** PP Parameters */
+  uint8_t  btPP;
+  /** General Bytes */
+  uint8_t  abtGB[48];
+  size_t  szGB;
+  /** DEP mode */
+  nfc_dep_mode ndm;
+} nfc_dep_info;
+
+/**
+ * @struct nfc_iso14443a_info
+ * @brief NFC ISO14443A tag (MIFARE) information
+ */
+typedef struct {
+  uint8_t  abtAtqa[2];
+  uint8_t  btSak;
+  size_t  szUidLen;
+  uint8_t  abtUid[10];
+  size_t  szAtsLen;
+  uint8_t  abtAts[254]; // Maximal theoretical ATS is FSD-2, FSD=256 for FSDI=8 in RATS
+} nfc_iso14443a_info;
+
+/**
+ * @struct nfc_felica_info
+ * @brief NFC FeLiCa tag information
+ */
+typedef struct {
+  size_t  szLen;
+  uint8_t  btResCode;
+  uint8_t  abtId[8];
+  uint8_t  abtPad[8];
+  uint8_t  abtSysCode[2];
+} nfc_felica_info;
+
+/**
+ * @struct nfc_iso14443b_info
+ * @brief NFC ISO14443B tag information
+ */
+typedef struct {
+  /** abtPupi store PUPI contained in ATQB (Answer To reQuest of type B) (see ISO14443-3) */
+  uint8_t abtPupi[4];
+  /** abtApplicationData store Application Data contained in ATQB (see ISO14443-3) */
+  uint8_t abtApplicationData[4];
+  /** abtProtocolInfo store Protocol Info contained in ATQB (see ISO14443-3) */
+  uint8_t abtProtocolInfo[3];
+  /** ui8CardIdentifier store CID (Card Identifier) attributted by PCD to the PICC */
+  uint8_t ui8CardIdentifier;
+} nfc_iso14443b_info;
+
+/**
+ * @struct nfc_iso14443bi_info
+ * @brief NFC ISO14443B' tag information
+ */
+typedef struct {
+  /** DIV: 4 LSBytes of tag serial number */
+  uint8_t abtDIV[4];
+  /** Software version & type of REPGEN */
+  uint8_t btVerLog;
+  /** Config Byte, present if long REPGEN */
+  uint8_t btConfig;
+  /** ATR, if any */
+  size_t szAtrLen;
+  uint8_t  abtAtr[33];
+} nfc_iso14443bi_info;
+
+/**
+ * @struct nfc_iso14443b2sr_info
+ * @brief NFC ISO14443-2B ST SRx tag information
+ */
+typedef struct {
+  uint8_t abtUID[8];
+} nfc_iso14443b2sr_info;
+
+/**
+ * @struct nfc_iso14443b2ct_info
+ * @brief NFC ISO14443-2B ASK CTx tag information
+ */
+typedef struct {
+  uint8_t abtUID[4];
+  uint8_t btProdCode;
+  uint8_t btFabCode;
+} nfc_iso14443b2ct_info;
+
+/**
+ * @struct nfc_jewel_info
+ * @brief NFC Jewel tag information
+ */
+typedef struct {
+  uint8_t  btSensRes[2];
+  uint8_t  btId[4];
+} nfc_jewel_info;
+
+/**
+ * @union nfc_target_info
+ * @brief Union between all kind of tags information structures.
+ */
+typedef union {
+  nfc_iso14443a_info nai;
+  nfc_felica_info nfi;
+  nfc_iso14443b_info nbi;
+  nfc_iso14443bi_info nii;
+  nfc_iso14443b2sr_info nsi;
+  nfc_iso14443b2ct_info nci;
+  nfc_jewel_info nji;
+  nfc_dep_info ndi;
+} nfc_target_info;
+
+/**
+ * @enum nfc_baud_rate
+ * @brief NFC baud rate enumeration
+ */
+typedef enum {
+  NBR_UNDEFINED = 0,
+  NBR_106,
+  NBR_212,
+  NBR_424,
+  NBR_847,
+} nfc_baud_rate;
+
+/**
+ * @enum nfc_modulation_type
+ * @brief NFC modulation type enumeration
+ */
+typedef enum {
+  NMT_ISO14443A = 1,
+  NMT_JEWEL,
+  NMT_ISO14443B,
+  NMT_ISO14443BI, // pre-ISO14443B aka ISO/IEC 14443 B' or Type B'
+  NMT_ISO14443B2SR, // ISO14443-2B ST SRx
+  NMT_ISO14443B2CT, // ISO14443-2B ASK CTx
+  NMT_FELICA,
+  NMT_DEP,
+} nfc_modulation_type;
+
+/**
+ * @enum nfc_mode
+ * @brief NFC mode type enumeration
+ */
+typedef enum {
+  N_TARGET,
+  N_INITIATOR,
+} nfc_mode;
+
+/**
+ * @struct nfc_modulation
+ * @brief NFC modulation structure
+ */
+typedef struct {
+  nfc_modulation_type nmt;
+  nfc_baud_rate nbr;
+} nfc_modulation;
+
+/**
+ * @struct nfc_target
+ * @brief NFC target structure
+ */
+typedef struct {
+  nfc_target_info nti;
+  nfc_modulation nm;
+} nfc_target;
+
+// Reset struct alignment to default
+#  pragma pack()
+
+
+/* Library initialization/deinitialization */
+void nfc_init(nfc_context **context);
+void nfc_exit(nfc_context *context);
+int nfc_register_driver(const nfc_driver *driver);
+
+/* NFC Device/Hardware manipulation */
+nfc_device *nfc_open(nfc_context *context, const nfc_connstring connstring);
+void nfc_close(nfc_device *pnd);
+int nfc_abort_command(nfc_device *pnd);
+size_t nfc_list_devices(nfc_context *context, nfc_connstring connstrings[], size_t connstrings_len);
+int nfc_idle(nfc_device *pnd);
+
+/* NFC initiator: act as "reader" */
+int nfc_initiator_init(nfc_device *pnd);
+int nfc_initiator_init_secure_element(nfc_device *pnd);
+int nfc_initiator_select_passive_target(nfc_device *pnd, const nfc_modulation nm, const uint8_t *pbtInitData, const size_t szInitData, nfc_target *pnt);
+int nfc_initiator_list_passive_targets(nfc_device *pnd, const nfc_modulation nm, nfc_target ant[], const size_t szTargets);
+int nfc_initiator_poll_target(nfc_device *pnd, const nfc_modulation *pnmTargetTypes, const size_t szTargetTypes, const uint8_t uiPollNr, const uint8_t uiPeriod, nfc_target *pnt);
+int nfc_initiator_select_dep_target(nfc_device *pnd, const nfc_dep_mode ndm, const nfc_baud_rate nbr, const nfc_dep_info *pndiInitiator, nfc_target *pnt, const int timeout);
+int nfc_initiator_poll_dep_target(nfc_device *pnd, const nfc_dep_mode ndm, const nfc_baud_rate nbr, const nfc_dep_info *pndiInitiator, nfc_target *pnt, const int timeout);
+int nfc_initiator_deselect_target(nfc_device *pnd);
+int nfc_initiator_transceive_bytes(nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx, uint8_t *pbtRx, const size_t szRx, int timeout);
+int nfc_initiator_transceive_bits(nfc_device *pnd, const uint8_t *pbtTx, const size_t szTxBits, const uint8_t *pbtTxPar, uint8_t *pbtRx, const size_t szRx, uint8_t *pbtRxPar);
+int nfc_initiator_transceive_bytes_timed(nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx, uint8_t *pbtRx, const size_t szRx, uint32_t *cycles);
+int nfc_initiator_transceive_bits_timed(nfc_device *pnd, const uint8_t *pbtTx, const size_t szTxBits, const uint8_t *pbtTxPar, uint8_t *pbtRx, const size_t szRx, uint8_t *pbtRxPar, uint32_t *cycles);
+int nfc_initiator_target_is_present(nfc_device *pnd, const nfc_target *pnt);
+
+/* NFC target: act as tag (i.e. MIFARE Classic) or NFC target device. */
+int nfc_target_init(nfc_device *pnd, nfc_target *pnt, uint8_t *pbtRx, const size_t szRx, int timeout);
+int nfc_target_send_bytes(nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx, int timeout);
+int nfc_target_receive_bytes(nfc_device *pnd, uint8_t *pbtRx, const size_t szRx, int timeout);
+int nfc_target_send_bits(nfc_device *pnd, const uint8_t *pbtTx, const size_t szTxBits, const uint8_t *pbtTxPar);
+int nfc_target_receive_bits(nfc_device *pnd, uint8_t *pbtRx, const size_t szRx, uint8_t *pbtRxPar);
+
+/* Error reporting */
+const char *nfc_strerror(const nfc_device *pnd);
+int nfc_strerror_r(const nfc_device *pnd, char *buf, size_t buflen);
+void nfc_perror(const nfc_device *pnd, const char *s);
+int nfc_device_get_last_error(const nfc_device *pnd);
+
+/* Special data accessors */
+const char *nfc_device_get_name(nfc_device *pnd);
+const char *nfc_device_get_connstring(nfc_device *pnd);
+int nfc_device_get_supported_modulation(nfc_device *pnd, const nfc_mode mode,  const nfc_modulation_type **const supported_mt);
+int nfc_device_get_supported_baud_rate(nfc_device *pnd, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br);
+
+/* Properties accessors */
+int nfc_device_set_property_int(nfc_device *pnd, const nfc_property property, const int value);
+int nfc_device_set_property_bool(nfc_device *pnd, const nfc_property property, const bool bEnable);
+
+/* Misc. functions */
+void iso14443a_crc(uint8_t *pbtData, size_t szLen, uint8_t *pbtCrc);
+void iso14443a_crc_append(uint8_t *pbtData, size_t szLen);
+void iso14443b_crc(uint8_t *pbtData, size_t szLen, uint8_t *pbtCrc);
+void iso14443b_crc_append(uint8_t *pbtData, size_t szLen);
+uint8_t *iso14443a_locate_historical_bytes(uint8_t *pbtAts, size_t szAts, size_t *pszTk);
+
+void nfc_free(void *p);
+const char *nfc_version(void);
+int nfc_device_get_information_about(nfc_device *pnd, char **buf);
+
+/* String converter functions */
+const char *str_nfc_modulation_type(const nfc_modulation_type nmt);
+const char *str_nfc_baud_rate(const nfc_baud_rate nbr);
+int str_nfc_target(char **buf, const nfc_target *pnt, bool verbose);
+
+/* Error codes */
+/** @ingroup error
+ * @hideinitializer
+ * Success (no error)
+ */
+#define NFC_SUCCESS			 0
+/** @ingroup error
+ * @hideinitializer
+ * Input / output error, device may not be usable anymore without re-open it
+ */
+#define NFC_EIO				-1
+/** @ingroup error
+ * @hideinitializer
+ * Invalid argument(s)
+ */
+#define NFC_EINVARG			-2
+/** @ingroup error
+ * @hideinitializer
+ *  Operation not supported by device
+ */
+#define NFC_EDEVNOTSUPP			-3
+/** @ingroup error
+ * @hideinitializer
+ * No such device
+ */
+#define NFC_ENOTSUCHDEV			-4
+/** @ingroup error
+ * @hideinitializer
+ * Buffer overflow
+ */
+#define NFC_EOVFLOW			-5
+/** @ingroup error
+ * @hideinitializer
+ * Operation timed out
+ */
+#define NFC_ETIMEOUT			-6
+/** @ingroup error
+ * @hideinitializer
+ * Operation aborted (by user)
+ */
+#define NFC_EOPABORTED			-7
+/** @ingroup error
+ * @hideinitializer
+ * Not (yet) implemented
+ */
+#define NFC_ENOTIMPL			-8
+/** @ingroup error
+ * @hideinitializer
+ * Target released
+ */
+#define NFC_ETGRELEASED			-10
+/** @ingroup error
+ * @hideinitializer
+ * Error while RF transmission
+ */
+#define NFC_ERFTRANS			-20
+/** @ingroup error
+ * @hideinitializer
+ * MIFARE Classic: authentication failed
+ */
+#define NFC_EMFCAUTHFAIL		-30
+/** @ingroup error
+ * @hideinitializer
+ * Software error (allocation, file/pipe creation, etc.)
+ */
+#define NFC_ESOFT			-80
+/** @ingroup error
+ * @hideinitializer
+ * Device's internal chip error
+ */
+#define NFC_ECHIP			-90
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/service/cardReader/requirements.txt	Wed Feb 05 16:40:46 2020 -0800
@@ -0,0 +1,7 @@
+docopt
+rdflib-jsonld==0.4.0
+rdflib==4.2.2
+https://projects.bigasterisk.com/rdfdb/rdfdb-0.8.0.tar.gz
+git+http://github.com/drewp/scales.git@448d59fb491b7631877528e7695a93553bfaaa93#egg=scales
+influxdb==3.0.0
+https://github.com/drewp/cyclone/archive/python3.zip
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/service/cardReader/rfid-console.html	Wed Feb 05 16:40:46 2020 -0800
@@ -0,0 +1,90 @@
+<link rel="import" href="/lib/polymer/1.0.9/iron-ajax/iron-ajax.html">
+<link rel="import" href="/lib/polymer/1.0.9/polymer/polymer.html">
+<link rel="import" href="/rdf/rdf-oneshot.html">
+<link rel="import" href="/rdf/rdf-uri.html">
+<link rel="import" href="/rdf/streamed-graph.html">
+
+<dom-module id="rfid-console">
+  <style>
+   button {
+       min-width: 60px;
+       min-height: 40px;
+   }
+   table {
+       border-collapse: collapse;
+   }
+   
+   td, th {
+       border: 1px solid gray;
+   }
+  </style>
+  <template>
+    
+    <iron-ajax id="rewrite" url="rewrite" method="POST"></iron-ajax>
+    
+    Current RFID reads: 
+    <table>
+      <tr><th>Card UID</th><th>Card text</th><th></th></tr>
+      <template is="dom-repeat" items="{{currentReads}}">
+        <tr>
+          <td>{{item.uidDisplay}}</td>
+          <td>{{item.text}}</td>
+          <td>
+            <div id="form">
+              <button on-click="rewrite">Rewrite</button>
+            </div>
+          </td>
+        </tr>
+      </template>
+    </table>
+
+    <div>
+      <streamed-graph url="graph/events" graph="{{graph}}"></streamed-graph>
+      <!-- also get a graph of users so we can look up cards -->
+    </div>
+  </template>
+  <script>
+   Polymer({
+     is: 'rfid-console',
+     properties: {
+       graph: { type: Object, notify: true, observer: "_onGraph" },
+       currentReads: { type: Array, value: [] },
+     },
+     behaviors: [BigastUri],
+     _onGraph: function(graph) {
+       if (!graph.graph) return;
+       const env = graph.graph.store.rdf;
+
+       this.splice('currentReads', 0, this.currentReads.length);
+       graph.graph.quadStore.quads(
+         {subject: env.createNamedNode('room:frontDoorWindowRfid'),
+          predicate: env.createNamedNode('room:reading'),
+         },
+         (q) => {
+           graph.graph.quadStore.quads(
+             {subject: q.object,
+              predicate: env.createNamedNode('room:cardText'),
+             },
+             (q2) => {
+               this.push(
+                 'currentReads', {
+                   'cardUid': q.object,
+                   'uidDisplay': q.object.toString().replace(/.*\//, ""),
+                   'text': q2.object.toString()
+                 });
+             });
+         });
+     },
+     rewrite: function(ev) {
+       const cardUid = ev.model.item.cardUid;
+
+       // ask for user first
+
+       this.$.rewrite.contentType = "application/json";
+       this.$.rewrite.body = {'cardUid': cardUid.toString(),
+                              'user': "some foaf"};
+       this.$.rewrite.generateRequest();
+     }
+   });
+  </script>
+</dom-module>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/service/cardReader/rfid.py	Wed Feb 05 16:40:46 2020 -0800
@@ -0,0 +1,230 @@
+import os
+os.environ['LIBNFC_DEFAULT_DEVICE'] = "pn532_uart:/dev/ttyUSB0"
+
+from docopt import docopt
+from rdfdb.patch import Patch
+from patchablegraph import PatchableGraph, CycloneGraphHandler, CycloneGraphEventsHandler
+from rdflib import Namespace, URIRef, Literal, Graph
+from rdflib.parser import StringInputSource
+from twisted.internet import reactor, task, defer
+import cyclone.web
+from cyclone.httpclient import fetch
+import cyclone
+import logging, time, json, random, string, traceback
+from logsetup import log, enableTwistedLog
+from greplin import scales
+from greplin.scales.cyclonehandler import StatsHandler
+from export_to_influxdb import InfluxExporter
+from tags import NfcDevice, FakeNfc, NfcError, AuthFailedError
+
+ROOM = Namespace('http://projects.bigasterisk.com/room/')
+
+ctx = ROOM['frontDoorWindowRfidCtx']
+
+STATS = scales.collection('/root',
+                          scales.PmfStat('cardReadPoll'),
+                          scales.IntStat('newCardReads'),
+)
+
+class OutputPage(cyclone.web.RequestHandler):
+    def put(self):
+        arg = self.request.arguments
+        if arg.get('s') and arg.get('p'):
+            self._onQueryStringStatement(arg['s'][-1], arg['p'][-1], self.request.body)
+        else:
+            self._onGraphBodyStatements(self.request.body, self.request.headers)
+    post = put
+    def _onQueryStringStatement(self, s, p, body):
+        subj = URIRef(s)
+        pred = URIRef(p)
+        turtleLiteral = self.request.body
+        try:
+            obj = Literal(float(turtleLiteral))
+        except ValueError:
+            obj = Literal(turtleLiteral)
+        self._onStatements([(subj, pred, obj)])
+
+    def _onGraphBodyStatements(self, body, headers):
+        g = Graph()
+        g.parse(StringInputSource(body), format='nt')
+        if not g:
+            raise ValueError("expected graph body")
+        self._onStatements(list(g.triples((None, None, None))))
+    post = put
+
+    def _onStatements(self, stmts):
+        # write rfid to new key, etc.
+        if len(stmts) > 0 and stmts[0][1] == ROOM['keyContents']:
+            return
+        log.warn("ignoring %s", stmts)
+
+def uidUri(card_id):
+    return URIRef('http://bigasterisk.com/rfidCard/%s' % card_id)
+
+BODY_VERSION = "1"
+def randomBody():
+    return BODY_VERSION + '*' + ''.join(random.choice(string.ascii_uppercase) for n in range(16 - 2))
+
+def looksLikeBigasterisk(text):
+    return text.startswith(BODY_VERSION + "*")
+
+class Rewrite(cyclone.web.RequestHandler):
+    def post(self):
+        agent = URIRef(self.request.headers['x-foaf-agent'])
+        body = json.loads(self.request.body)
+
+        _, uid = reader.read_id()
+        log.info('current card id: %r %r', _, uid)
+        if uid is None:
+            self.set_status(404, "no card present")
+            # maybe retry a few more times since the card might be nearby
+            return
+
+        text = randomBody()
+        log.info('%s rewrites %s to %s, to be owned by %s',
+                 agent, uid, text, body['user'])
+
+        #reader.KEY = private.rfid_key
+        reader.write(uid, text)
+        log.info('done with write')
+
+
+sensor = ROOM['frontDoorWindowRfid']
+
+class ReadLoop(object):
+    def __init__(self, reader, masterGraph, overwrite_any_tag):
+        self.reader = reader
+        self.masterGraph = masterGraph
+        self.overwrite_any_tag = overwrite_any_tag
+        self.log = {} # cardIdUri : most recent seentime
+
+        self.pollPeriodSecs = .1
+        self.expireSecs = 5
+
+        # now=False avoids a serious bug where the first read error
+        # could happen before reactor.run() is called, and then the
+        # error fails to crash the reactor and get us restarted.
+        task.LoopingCall(self.poll).start(self.pollPeriodSecs, now=False)
+
+    @STATS.cardReadPoll.time()
+    def poll(self):
+        now = time.time()
+
+        self.flushOldReads(now)
+
+        try:
+            for tag in self.reader.getTags(): # blocks for a bit
+                uid = tag.uid()
+                log.debug('detected tag uid=%r', uid)
+                cardIdUri = uidUri(uid)
+
+                is_new = cardIdUri not in self.log
+                self.log[cardIdUri] = now
+                if is_new:
+                    STATS.newCardReads += 1
+                    tag.connect()
+                    try:
+                        textLit = Literal(tag.readBlock(1).rstrip('\x00'))
+                        if self.overwrite_any_tag and not looksLikeBigasterisk(textLit):
+                            log.info("block 1 was %r; rewriting it", textLit)
+                            tag.writeBlock(1, randomBody())
+                            textLit = Literal(tag.readBlock(1).rstrip('\x00'))
+                    finally:
+                        # This might not be appropriate to call after
+                        # readBlock fails. I am getting double
+                        # exceptions.
+                        tag.disconnect()
+                    self.startCardRead(cardIdUri, textLit)
+        except AuthFailedError as e:
+            log.error(e)
+        except (NfcError, OSError) as e:
+            traceback.print_exc()
+            log.error(e)
+            reactor.stop()
+
+    def flushOldReads(self, now):
+        for uri in list(self.log):
+            if self.log[uri] < now - self.expireSecs:
+                self.endCardRead(uri)
+                del self.log[uri]
+
+    def startCardRead(self, cardUri, text):
+        self.masterGraph.patch(Patch(addQuads=[
+            (sensor, ROOM['reading'], cardUri, ctx),
+            (cardUri, ROOM['cardText'], text, ctx)],
+                                     delQuads=[]))
+        log.info('%s :cardText %s .', cardUri.n3(), text.n3())
+        self._sendOneshot([(sensor, ROOM['startReading'], cardUri),
+                            (cardUri, ROOM['cardText'], text)])
+
+    def endCardRead(self, cardUri):
+        log.debug(f'{cardUri} has been gone for {self.expireSecs} sec')
+        delQuads = []
+        for spo in self.masterGraph._graph.triples(
+                (sensor, ROOM['reading'], cardUri)):
+            delQuads.append(spo + (ctx,))
+        for spo in self.masterGraph._graph.triples(
+                (cardUri, ROOM['cardText'], None)):
+            delQuads.append(spo + (ctx,))
+
+        self.masterGraph.patch(Patch(addQuads=[], delQuads=delQuads))
+
+    def _sendOneshot(self, oneshot):
+        body = (' '.join('%s %s %s .' % (s.n3(), p.n3(), o.n3())
+                         for s,p,o in oneshot)).encode('utf8')
+        url = b'http://bang:9071/oneShot'
+        d = fetch(method=b'POST',
+                  url=url,
+                  headers={b'Content-Type': [b'text/n3']},
+                  postdata=body,
+                  timeout=5)
+        def err(e):
+            log.info('oneshot post to %r failed:  %s',
+                     url, e.getErrorMessage())
+        d.addErrback(err)
+
+
+
+if __name__ == '__main__':
+    arg = docopt("""
+    Usage: rfid.py [options]
+
+    -v                    Verbose
+    --overwrite_any_tag   Rewrite any unknown tag with a new random body
+    -n                    Fake reader
+    """)
+    log.setLevel(logging.INFO)
+    if arg['-v']:
+        enableTwistedLog()
+        log.setLevel(logging.DEBUG)
+        log.info(f'cyclone {cyclone.__version__}')
+        defer.setDebugging(True)
+
+    masterGraph = PatchableGraph()
+    reader = NfcDevice() if not arg['-n'] else FakeNfc()
+
+    ie=InfluxExporter(Graph())
+    ie.exportStats(STATS, ['root.cardReadPoll.count',
+                           'root.cardReadPoll.95percentile',
+                           'root.newCardReads',
+                       ],
+                    period_secs=10,
+                    retain_days=7,
+    )
+
+    loop = ReadLoop(reader, masterGraph, overwrite_any_tag=arg['--overwrite_any_tag'])
+
+    port = 10012
+    reactor.listenTCP(port, cyclone.web.Application([
+        (r"/(|.+\.html)", cyclone.web.StaticFileHandler,
+         {"path": ".", "default_filename": "index.html"}),
+        (r"/graph/rfid", CycloneGraphHandler, {'masterGraph': masterGraph}),
+        (r"/graph/rfid/events", CycloneGraphEventsHandler,
+         {'masterGraph': masterGraph}),
+        (r'/output', OutputPage),
+        (r'/rewrite', Rewrite),
+        (r'/stats/(.*)', StatsHandler, {'serverName': 'rfid'}),
+        ], masterGraph=masterGraph, debug=arg['-v']), interface='::')
+    log.warn('serving on %s', port)
+
+    reactor.run()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/service/cardReader/tags.py	Wed Feb 05 16:40:46 2020 -0800
@@ -0,0 +1,115 @@
+import time
+from ctypes import pointer, byref, c_ubyte, cast, c_char_p
+import nfc, freefare
+import logging
+log = logging.getLogger('tags')
+
+class FakeNfc(object):
+    def getTags(self):
+        return []
+
+    
+class NfcDevice(object):
+    def __init__(self):
+        self.context = pointer(nfc.nfc_context())
+        nfc.nfc_init(byref(self.context))
+        self.dev = None
+
+        conn_strings = (nfc.nfc_connstring * 10)()
+        t0, _, t2 = nfc.nfc_list_devices.argtypes
+        nfc.nfc_list_devices.argtypes = [t0, type(conn_strings), t2]
+        log.info("nfc_list_devices:")
+        devices_found = nfc.nfc_list_devices(self.context, conn_strings, 10)
+        log.info(f'{devices_found} connection strings')
+        for i in range(devices_found):
+            log.info(f'  dev {i}: {cast(conn_strings[i], c_char_p).value}')
+        if devices_found < 1:
+            raise IOError("no devices")
+            
+        log.debug("open dev")
+        self.dev = nfc.nfc_open(self.context, conn_strings[0])
+        if not self.dev or nfc.nfc_device_get_last_error(self.dev):
+            raise IOError(f'nfc.open failed on {cast(conn_strings[0], c_char_p).value}')
+
+    def __del__(self):
+        if self.dev:
+            nfc.nfc_close(self.dev)
+        nfc.nfc_exit(self.context)
+
+    def getTags(self):
+        log.debug("getting tags")
+        t0 = time.time()
+        # see https://github.com/nfc-tools/libfreefare/blob/master/libfreefare/freefare.c
+        # for how this might waste time on felica tags
+        ret = freefare.freefare_get_tags(self.dev)
+        if not ret:
+            raise IOError("freefare_get_tags returned null")
+        try:
+            log.debug(f"found tags in {time.time() - t0}")
+            for t in ret:
+                if not t:
+                    break
+                yield NfcTag(t)
+        finally:
+            freefare.freefare_free_tags(ret)
+
+pubkey = b'\xff\xff\xff\xff\xff\xff'
+
+class NfcError(Exception):
+    def __init__(self, code, strerror):
+        Exception.__init__(self, "%s [%s]" % (strerror, code))
+        self.code = code
+
+class AuthFailedError(NfcError): pass
+
+class NfcTag(object):
+    def __init__(self, tag): #FreefareTag
+        self.tag = tag
+
+    def _check(self, ret: int):
+        if ret == 0:
+            return
+
+        msg = cast(freefare.freefare_strerror(self.tag), c_char_p).value
+        if msg == b'Mifare Authentication Failed':
+            # return code is -1 (!). I was excpecting
+            # AUTHENTICATION_ERROR=0xAE or something.
+            raise AuthFailedError(ret, msg)        
+            
+        raise NfcError(ret, msg)
+        
+    def tagType(self) -> str:
+        typeNum = freefare.freefare_get_tag_type(self.tag)
+        return freefare.freefare_tag_type__enumvalues[typeNum]
+
+    def uid(self) -> str:
+        return cast(freefare.freefare_get_tag_uid(self.tag),
+                    c_char_p).value.decode('ascii')
+
+    def connect(self):
+        self._check(freefare.mifare_classic_connect(self.tag))
+
+    def disconnect(self):
+        self._check(freefare.mifare_classic_disconnect(self.tag))
+
+    def readBlock(self, blockNumber: int) -> bytes:
+        blockNum = freefare.MifareClassicBlockNumber(blockNumber)
+        self._check(freefare.mifare_classic_authenticate(
+            self.tag, blockNum, (c_ubyte*6)(*pubkey), freefare.MFC_KEY_A))
+  
+        data = freefare.MifareClassicBlock()
+        self._check(freefare.mifare_classic_read(self.tag, blockNum, pointer(data)))
+        return ''.join(map(chr, data)) # with trailing nulls
+
+    def writeBlock(self, blockNumber: int, data: str):
+        blocknum = freefare.MifareClassicBlockNumber(blockNumber)
+        self._check(freefare.mifare_classic_authenticate(
+          self.tag, blocknum, (c_ubyte*6)(*pubkey), freefare.MFC_KEY_A))
+  
+        dataBytes = data.encode('utf8')
+        if len(dataBytes) > 16:
+            raise ValueError('too long')
+        dataBlock = (c_ubyte*16)(*dataBytes)
+        
+        self._check(freefare.mifare_classic_write(self.tag, blocknum, dataBlock))
+        log.info(f"  wrote block {blocknum}: {dataBlock}")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/service/cardReader/tags_test.py	Wed Feb 05 16:40:46 2020 -0800
@@ -0,0 +1,28 @@
+import unittest
+import tags
+import time
+import os
+os.environ['LIBNFC_DEFAULT_DEVICE'] = "pn532_i2c:/dev/i2c-1"
+import logging
+logging.basicConfig(level=logging.DEBUG)
+log = logging.getLogger()
+
+class TestNfc(unittest.TestCase):
+    def test_open_close(self):
+        n = tags.NfcDevice()
+        del n
+        
+    def test_update_tag(self): # writes to the current tag!
+        n = tags.NfcDevice()
+        for t in n.getTags():
+            print('tag', t)
+            print('  tagType', t.tagType())
+            print('  uid %r' % t.uid())
+            t.connect()
+            try:
+                print('  block 1', t.readBlock(1))
+                print('write')
+                t.writeBlock(1, 'hello %s' % int(time.time()))
+                print('  block 1', t.readBlock(1))
+            finally:
+                t.disconnect()
--- a/service/rfid_pn532_py/Dockerfile.pi	Wed Feb 05 16:39:08 2020 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-FROM bang6:5000/base_pi
-
-WORKDIR /opt
-RUN apt-get install -y libnfc5 libfreefare0 libnfc-dev libfreefare-dev python3-nose2 libffi-dev
-COPY pyfreefare-build-pi ./pyfreefare-build
-
-COPY requirements.txt .
-RUN pip3 install -Ur requirements.txt
-# not sure why this doesn't work from inside requirements.txt
-RUN pip3 install -U 'https://github.com/drewp/cyclone/archive/python3.zip'
-
-COPY *.py *.html  ./
-
-ENV PYTHONPATH=/opt/pyfreefare-build
-EXPOSE 10012
-
-CMD ["/usr/bin/python3", "rfid.py"]
--- a/service/rfid_pn532_py/Dockerfile.pyfreefare.pi	Wed Feb 05 16:39:08 2020 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-FROM bang6:5000/base_pi
-
-WORKDIR /opt
-
-RUN apt-get install -y python-clang-5.0 libclang-5.0-dev libnfc5 libfreefare0 libnfc-dev libfreefare-dev 
-RUN pip install git+https://github.com/drewp/ctypeslib.git@enable-modules-flag
-
-COPY build_ctypes_modules.sh ./
-
-CMD ["/bin/sh", "/opt/build_ctypes_modules.sh"]
\ No newline at end of file
--- a/service/rfid_pn532_py/Dockerfile.pyfreefare.x86	Wed Feb 05 16:39:08 2020 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-FROM bang6:5000/base_x86
-
-WORKDIR /opt
-
-RUN apt-get install -y python-clang-5.0 libclang-5.0-dev libnfc5 libfreefare0 libnfc-dev libfreefare-dev 
-RUN pip install git+https://github.com/drewp/ctypeslib.git@enable-modules-flag
-
-COPY build_ctypes_modules.sh ./
-
-CMD ["/bin/sh", "/opt/build_ctypes_modules.sh"]
--- a/service/rfid_pn532_py/Dockerfile.x86	Wed Feb 05 16:39:08 2020 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-FROM bang6:5000/base_x86
-
-WORKDIR /opt
-RUN apt-get install -y libnfc5 libfreefare0 libnfc-dev libfreefare-dev 
-RUN apt-get install -y python3-nose2
-COPY pyfreefare-build-x86 ./pyfreefare-build
-
-COPY requirements.txt .
-RUN pip3 install -r requirements.txt
-# not sure why this doesn't work from inside requirements.txt
-RUN pip3 install -U 'https://github.com/drewp/cyclone/archive/python3.zip'
-
-COPY *.py *.html  ./
-
-ENV PYTHONPATH=/opt/pyfreefare-build
-EXPOSE 10012
-
-CMD ["/usr/bin/python3", "rfid.py", "-v"]
--- a/service/rfid_pn532_py/build_ctypes_modules.sh	Wed Feb 05 16:39:08 2020 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-#!/bin/sh
-set -x
-proc=`uname --processor`
-if [ "$proc" = "armv7l" ]; then
-    ARCH=arm-linux-gnueabihf
-    TARGET=armv7l
-else
-    ARCH=x86_64-linux-gnu
-    TARGET=x86_64-Linux
-fi
-CARGS="-I/usr/include/${ARCH} -I/usr/lib/llvm-5.0/lib/clang/5.0.1/include -I/usr/lib/llvm-5.0/lib/"
-clang2py -o /opt/pyfreefare-build/nfc.py --target ${TARGET} --clang-args="${CARGS}" -l /usr/lib/${ARCH}/libnfc.so --comments /opt/pyfreefare/nfc.h
-
-PYTHONPATH=/opt/pyfreefare-build clang2py -o /opt/pyfreefare-build/freefare.py --target ${TARGET} --clang-args="${CARGS}" -l /usr/lib/${ARCH}/libfreefare.so --comments --module nfc /opt/pyfreefare/freefare.h
--- a/service/rfid_pn532_py/index.html	Wed Feb 05 16:39:08 2020 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-<!doctype html>
-<html>
-  <head>
-    <title>rfid</title>
-    <meta charset="utf-8" />
-    <meta name="mobile-web-app-capable" content="yes">
-    <meta name="viewport" content="width=device-width, initial-scale=1">
-    <script src="/lib/polymer/1.0.9/webcomponentsjs/webcomponents.min.js"></script>
-    <script src="/lib/require/require-2.3.3.js"></script>
-    <script src="/rdf/common_paths_and_ns.js"></script>
-    <link rel="import" href="rfid-console.html">
-    <style>
-     .served-resources {
-         margin-top: 4em;
-         border-top: 1px solid gray;
-         padding-top: 1em;
-     }
-     .served-resources a {
-         padding-right: 2em;
-     }
-    </style>
-  </head>
-  <body>
-    <rfid-console></rfid-console>
-
-    <template id="t" is="dom-bind">
-      <streamed-graph url="graph/events" graph="{{graph}}"></streamed-graph>
-      <div id="out"></div>
-      <script type="module" src="/rdf/streamed_graph_view.js"></script>
-    </template>
-
-    <div class="served-resources">
-      <a href="stats/">/stats/</a>
-      <a href="graph">/graph</a>
-      <a href="graph/events">/graph/events</a>
-      <a href="output" >(post) /output</a>
-      <a href="rewrite">(post) /rewrite</a>
-    </div>
-  </body>
-</html>
--- a/service/rfid_pn532_py/local.conf	Wed Feb 05 16:39:08 2020 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-daemon  off;
-pid /dev/null;
-error_log stderr;
-#worker_processes  1;
-
-events {
-  worker_connections  1024;
-}
-
-http {
-  types {
-    text/html                 html;
-    text/css                  css;
-    image/gif                 gif;
-    image/jpeg                jpeg jpg;
-    application/x-javascript  js;
-    image/png                 png;
-  }
-
-  server {
-    listen 8888;
-    
-    access_log off;
-    
-    location / {
-      proxy_pass http://bang;
-      proxy_set_header Host bigasterisk.com;
-      proxy_buffering off;
-    }
-    location /frontDoor/rfid/ {
-      proxy_pass http://localhost:10012;
-      proxy_set_header Host $http_host;
-      proxy_buffering off;
-      rewrite /frontDoor/rfid(.*) $1 break;
-    }
-  }
-}
--- a/service/rfid_pn532_py/makefile	Wed Feb 05 16:39:08 2020 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-SERVICE=rfid_pn532_py
-JOB=rfid
-PORT=10012
-RUNHOST=frontdoor
-
-pyfreefare-build-x86/nfc.py: Dockerfile.pyfreefare.x86 pyfreefare/nfc.h pyfreefare/freefare.h build_ctypes_modules.sh
-	docker build --file Dockerfile.pyfreefare.x86 -t pyfreefare_build_x86:latest .
-	docker run --rm --net=host \
-          -v `pwd`/pyfreefare:/opt/pyfreefare \
-          -v `pwd`/pyfreefare-build-x86:/opt/pyfreefare-build \
-          --name pyfreefare_build pyfreefare_build_x86:latest
-
-pyfreefare-build-pi/nfc.py: Dockerfile.pyfreefare.pi pyfreefare/nfc.h pyfreefare/freefare.h build_ctypes_modules.sh
-	docker build --file Dockerfile.pyfreefare.pi -t pyfreefare_build_pi:latest .
-	docker run --rm --net=host \
-          -v `pwd`/pyfreefare:/opt/pyfreefare \
-          -v `pwd`/pyfreefare-build-pi:/opt/pyfreefare-build \
-          --name pyfreefare_build pyfreefare_build_pi:latest
-
-#pyfreefare/nfc.py pyfreefare/freefare.py
-test_tags: tags.py tags_test.py 
-	PYTHONPATH=pyfreefare-build-x86 nose2-3 tags_test
-
-
-build_image_x86: pyfreefare-build-x86/nfc.py pyfreefare-build-x86/freefare.py Dockerfile.x86
-	rm -rf tmp_ctx
-	mkdir -p tmp_ctx
-	cp -a Dockerfile.x86 ../../lib/*.py *.py *.txt *.html pyfreefare-build-x86 tmp_ctx
-	docker build --network=host --file Dockerfile.x86 -t bang6:5000/$(SERVICE)_x86:latest tmp_ctx
-	docker push bang6:5000/$(SERVICE)_x86:latest
-
-build_image_pi: pyfreefare-build-pi/nfc.py pyfreefare-build-pi/freefare.py Dockerfile.pi
-	rm -rf tmp_ctx
-	mkdir -p tmp_ctx
-	cp -a Dockerfile.pi ../../lib/*.py *.py *.txt *.html pyfreefare-build-pi tmp_ctx
-	docker build --network=host --file Dockerfile.pi -t bang6:5000/$(SERVICE)_pi:latest tmp_ctx
-	docker push bang6:5000/$(SERVICE)_pi:latest
-
-run_local_x86: build_image_x86
-	docker run -it --rm --privileged --net=host --hostname=testhost --cap-add=SYS_PTRACE --name $(JOB)_run bang6:5000/$(SERVICE)_x86:latest python3 rfid.py -v
-
-
-# test on pi:
-# docker pull bang6:5000/rfid_pn532_py_pi:latest && docker run -it --rm --privileged --name rfid_shell bang6:5000/rfid_pn532_py_pi:latest nose2-3 tags_test
-
-fresh_sudo:
-	sudo -v
-redeploy: fresh_sudo build_image_pi
-	sudo /my/proj/ansible/playbook -l $(RUNHOST) -t rfid
-	supervisorctl -s http://$(RUNHOST):9001/ restart $(JOB)_$(PORT)
-
-nginx_local:
-	nginx -c `pwd`/local.conf
-
--- a/service/rfid_pn532_py/pyfreefare/freefare.h	Wed Feb 05 16:39:08 2020 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,557 +0,0 @@
-
-#ifndef __FREEFARE_H__
-#define __FREEFARE_H__
-
-#include <sys/types.h>
-
-#include <stdint.h>
-
-#include <nfc/nfc.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif // __cplusplus
-
-enum freefare_tag_type {
-    FELICA,
-    MIFARE_MINI,
-    MIFARE_CLASSIC_1K,
-    MIFARE_CLASSIC_4K,
-    MIFARE_DESFIRE,
-//    MIFARE_PLUS_S2K,
-//    MIFARE_PLUS_S4K,
-//    MIFARE_PLUS_X2K,
-//    MIFARE_PLUS_X4K,
-    MIFARE_ULTRALIGHT,
-    MIFARE_ULTRALIGHT_C,
-    NTAG_21x,
-};
-  typedef enum freefare_tag_type freefare_tag_type;
-  
-struct freefare_tag;
-typedef struct freefare_tag *FreefareTag;
-
-/* Replace any MifareTag by the generic FreefareTag. */
-typedef struct freefare_tag *MifareTag;
-
-struct mifare_desfire_key;
-typedef struct mifare_desfire_key *MifareDESFireKey;
-
-struct ntag21x_key;
-typedef struct ntag21x_key *NTAG21xKey;
-
-typedef uint8_t MifareUltralightPageNumber;
-typedef unsigned char MifareUltralightPage[4];
-
-FreefareTag	*freefare_get_tags(nfc_device *device);
-FreefareTag	 freefare_tag_new(nfc_device *device, nfc_target target);
-freefare_tag_type freefare_get_tag_type(FreefareTag tag);
-const char	*freefare_get_tag_friendly_name(FreefareTag tag);
-char		*freefare_get_tag_uid(FreefareTag tag);
-void		 freefare_free_tag(FreefareTag tag);
-void		 freefare_free_tags(FreefareTag *tags);
-bool		 freefare_selected_tag_is_present(nfc_device *device);
-
-const char	*freefare_strerror(FreefareTag tag);
-int		 freefare_strerror_r(FreefareTag tag, char *buffer, size_t len);
-void		 freefare_perror(FreefareTag tag, const char *string);
-
-
-
-  // bool		 felica_taste(nfc_device *device, nfc_target target);
-
-  // #define FELICA_SC_RW 0x0009
-// #define FELICA_SC_RO 0x000b
-// 
-// FreefareTag	 felica_tag_new(nfc_device *device, nfc_target target);
-// void		 felica_tag_free(FreefareTag tag);
-// 
-// ssize_t		 felica_read(FreefareTag tag, uint16_t service, uint8_t block, uint8_t *data, size_t length);
-// ssize_t		 felica_read_ex(FreefareTag tag, uint16_t service, uint8_t block_count, uint8_t blocks[], uint8_t *data, size_t length);
-// ssize_t		 felica_write(FreefareTag tag, uint16_t service, uint8_t block, uint8_t *data, size_t length);
-// ssize_t		 felica_write_ex(FreefareTag tag, uint16_t service, uint8_t block_count, uint8_t blocks[], uint8_t *data, size_t length);
-// 
-// 
-// 
-// bool		 mifare_ultralight_taste(nfc_device *device, nfc_target target);
-// bool		 mifare_ultralightc_taste(nfc_device *device, nfc_target target);
-// FreefareTag	 mifare_ultralight_tag_new(nfc_device *device, nfc_target target);
-// FreefareTag	 mifare_ultralightc_tag_new(nfc_device *device, nfc_target target);
-// void		 mifare_ultralight_tag_free(FreefareTag tag);
-// void		 mifare_ultralightc_tag_free(FreefareTag tag);
-// 
-// int		 mifare_ultralight_connect(FreefareTag tag);
-// int		 mifare_ultralight_disconnect(FreefareTag tag);
-// 
-// int		 mifare_ultralight_read(FreefareTag tag, const MifareUltralightPageNumber page, MifareUltralightPage *data);
-// int		 mifare_ultralight_write(FreefareTag tag, const MifareUltralightPageNumber page, const MifareUltralightPage data);
-// 
-// int		 mifare_ultralightc_authenticate(FreefareTag tag, const MifareDESFireKey key);
-// int		 mifare_ultralightc_set_key(FreefareTag tag, MifareDESFireKey key);
-// bool		 is_mifare_ultralight(FreefareTag tag);
-// bool		 is_mifare_ultralightc(FreefareTag tag);
-// bool		 is_mifare_ultralightc_on_reader(nfc_device *device, nfc_iso14443a_info nai);
-// 
-// 
-// 
-// bool		 ntag21x_taste(nfc_device *device, nfc_target target);
-// uint8_t		 ntag21x_last_error(FreefareTag tag);
-// 
-// /* NTAG21x access features */
-// #define NTAG_PROT 0x80
-// #define NTAG_CFGLCK 0x40
-// #define NTAG_NFC_CNT_EN 0x20
-// #define NTAG_NFC_CNT_PWD_PROT 0x10
-// #define NTAG_AUTHLIM 0x07
-// 
-// enum ntag_tag_subtype {
-//     NTAG_UNKNOWN,
-//     NTAG_213,
-//     NTAG_215,
-//     NTAG_216
-// };
-// 
-// FreefareTag	 ntag21x_tag_new(nfc_device *device, nfc_target target);
-// FreefareTag	 ntag21x_tag_reuse(FreefareTag tag);  /* Copy data from Ultralight tag to new NTAG21x, don't forget to free your old tag */
-// NTAG21xKey	 ntag21x_key_new(const uint8_t data[4], const uint8_t pack[2]); /* Create new key */
-// void		 ntag21x_key_free(NTAG21xKey key);  /* Clear key from memory */
-// void		 ntag21x_tag_free(FreefareTag tag);
-// int		 ntag21x_connect(FreefareTag tag);
-// int		 ntag21x_disconnect(FreefareTag tag);
-// int		 ntag21x_get_info(FreefareTag tag);  /* Get all information about tag (size,vendor ...) */
-// enum  ntag_tag_subtype ntag21x_get_subtype(FreefareTag tag);  /* Get subtype of tag */
-// uint8_t		 ntag21x_get_last_page(FreefareTag tag);  /* Get last page address based on gathered info from function above */
-// int		 ntag21x_read_signature(FreefareTag tag, uint8_t *data); /* Get tag signature */
-// int		 ntag21x_set_pwd(FreefareTag tag, uint8_t data[4]);  /* Set password */
-// int		 ntag21x_set_pack(FreefareTag tag, uint8_t data[2]);  /* Set pack */
-// int		 ntag21x_set_key(FreefareTag tag, const NTAG21xKey key); /* Set key */
-// int		 ntag21x_set_auth(FreefareTag tag, uint8_t byte); /* Set AUTH0 byte (from which page starts password protection) */
-// int		 ntag21x_get_auth(FreefareTag tag, uint8_t *byte); /* Get AUTH0 byte */
-// int		 ntag21x_access_enable(FreefareTag tag, uint8_t byte); /* Enable access feature in ACCESS byte */
-// int		 ntag21x_access_disable(FreefareTag tag, uint8_t byte); /* Disable access feature in ACCESS byte */
-// int		 ntag21x_get_access(FreefareTag tag, uint8_t *byte); /* Get ACCESS byte */
-// int		 ntag21x_check_access(FreefareTag tag, uint8_t byte, bool *result); /* Check if access feature is enabled */
-// int		 ntag21x_get_authentication_limit(FreefareTag tag, uint8_t *byte); /* Get authentication limit */
-// int		 ntag21x_set_authentication_limit(FreefareTag tag, uint8_t byte); /* Set authentication limit (0x00 = disabled, [0x01,0x07] = valid range, > 0x07 invalid range) */
-// int		 ntag21x_read(FreefareTag tag, uint8_t page, uint8_t *data); /* Read 16 bytes starting from page */
-// int		 ntag21x_read4(FreefareTag tag, uint8_t page, uint8_t *data); /* Read 4 bytes on page */
-// int		 ntag21x_fast_read(FreefareTag tag, uint8_t start_page, uint8_t end_page, uint8_t *data); /* Read n*4 bytes from range [start_page,end_page] */
-// int		 ntag21x_fast_read4(FreefareTag tag, uint8_t page, uint8_t *data); /* Fast read certain page */
-// int		 ntag21x_read_cnt(FreefareTag tag, uint8_t *data);  /* Read 3-byte NFC counter if enabled else it returns error */
-// int		 ntag21x_write(FreefareTag tag, uint8_t page, uint8_t data[4]);  /* Write 4 bytes to page */
-// int		 ntag21x_compatibility_write(FreefareTag tag, uint8_t page, uint8_t data[4]);  /* Writes 4 bytes to page with mifare classic write */
-// int		 ntag21x_authenticate(FreefareTag tag, const NTAG21xKey key);  /* Authenticate with tag */
-// bool		 is_ntag21x(FreefareTag tag);  /* Check if tag type is NTAG21x */
-// bool		 ntag21x_is_auth_supported(nfc_device *device, nfc_iso14443a_info nai);  /* Check if tag supports 21x commands */
-// 
-// 
-// 
-// bool             mifare_mini_taste(nfc_device *device, nfc_target target);
-// bool		 mifare_classic1k_taste(nfc_device *device, nfc_target target);
-// bool		 mifare_classic4k_taste(nfc_device *device, nfc_target target);
-// FreefareTag      mifare_mini_tag_new(nfc_device *device, nfc_target target);
-// FreefareTag	 mifare_classic1k_tag_new(nfc_device *device, nfc_target target);
-// FreefareTag	 mifare_classic4k_tag_new(nfc_device *device, nfc_target target);
-void		 mifare_classic_tag_free(FreefareTag tag);
-// 
-typedef unsigned char MifareClassicBlock[16];
-
-typedef uint8_t MifareClassicSectorNumber;
-typedef unsigned char MifareClassicBlockNumber;
-
-typedef enum { MFC_KEY_A, MFC_KEY_B } MifareClassicKeyType;
-typedef unsigned char MifareClassicKey[6];
-
-/* NFC Forum public key */
-extern const MifareClassicKey mifare_classic_nfcforum_public_key_a;
-
-int		 mifare_classic_connect(FreefareTag tag);
-int		 mifare_classic_disconnect(FreefareTag tag);
-
-int		 mifare_classic_authenticate(FreefareTag tag, const MifareClassicBlockNumber block, const MifareClassicKey key, const MifareClassicKeyType key_type);
-int		 mifare_classic_read(FreefareTag tag, const MifareClassicBlockNumber block, MifareClassicBlock *data);
-int		 mifare_classic_init_value(FreefareTag tag, const MifareClassicBlockNumber block, const int32_t value, const MifareClassicBlockNumber adr);
-int		 mifare_classic_read_value(FreefareTag tag, const MifareClassicBlockNumber block, int32_t *value, MifareClassicBlockNumber *adr);
-int		 mifare_classic_write(FreefareTag tag, const MifareClassicBlockNumber block, const MifareClassicBlock data);
-
-int		 mifare_classic_increment(FreefareTag tag, const MifareClassicBlockNumber block, const uint32_t amount);
-int		 mifare_classic_decrement(FreefareTag tag, const MifareClassicBlockNumber block, const uint32_t amount);
-int		 mifare_classic_restore(FreefareTag tag, const MifareClassicBlockNumber block);
-int		 mifare_classic_transfer(FreefareTag tag, const MifareClassicBlockNumber block);
-
-int		 mifare_classic_get_trailer_block_permission(FreefareTag tag, const MifareClassicBlockNumber block, const uint16_t permission, const MifareClassicKeyType key_type);
-int		 mifare_classic_get_data_block_permission(FreefareTag tag, const MifareClassicBlockNumber block, const unsigned char permission, const MifareClassicKeyType key_type);
-
-int		 mifare_classic_format_sector(FreefareTag tag, const MifareClassicSectorNumber sector);
-
-void		 mifare_classic_trailer_block(MifareClassicBlock *block, const MifareClassicKey key_a, uint8_t ab_0, uint8_t ab_1, uint8_t ab_2, uint8_t ab_tb, const uint8_t gpb, const MifareClassicKey key_b);
-
-MifareClassicSectorNumber mifare_classic_block_sector(MifareClassicBlockNumber block);
-MifareClassicBlockNumber  mifare_classic_sector_first_block(MifareClassicSectorNumber sector);
-size_t		 mifare_classic_sector_block_count(MifareClassicSectorNumber sector);
-MifareClassicBlockNumber  mifare_classic_sector_last_block(MifareClassicSectorNumber sector);
-
-#define C_000 0
-#define C_001 1
-#define C_010 2
-#define C_011 3
-#define C_100 4
-#define C_101 5
-#define C_110 6
-#define C_111 7
-#define C_DEFAULT 255
-
-/* MIFARE Classic Access Bits */
-#define MCAB_R 0x8
-#define MCAB_W 0x4
-#define MCAB_D 0x2
-#define MCAB_I 0x1
-
-#define MCAB_READ_KEYA         0x400
-#define MCAB_WRITE_KEYA        0x100
-#define MCAB_READ_ACCESS_BITS  0x040
-#define MCAB_WRITE_ACCESS_BITS 0x010
-#define MCAB_READ_KEYB         0x004
-#define MCAB_WRITE_KEYB        0x001
-// 
-// struct mad_aid {
-//     uint8_t application_code;
-//     uint8_t function_cluster_code;
-// };
-// typedef struct mad_aid MadAid;
-// 
-// struct mad;
-// typedef struct mad *Mad;
-// 
-// /* MAD Public read key A */
-// extern const MifareClassicKey mad_public_key_a;
-// 
-// /* AID - Adminisration codes */
-// extern const MadAid mad_free_aid;
-// extern const MadAid mad_defect_aid;
-// extern const MadAid mad_reserved_aid;
-// extern const MadAid mad_card_holder_aid;
-// extern const MadAid mad_not_applicable_aid;
-// 
-// /* NFC Forum AID */
-// extern const MadAid mad_nfcforum_aid;
-// 
-// Mad		 mad_new(const uint8_t version);
-// Mad		 mad_read(FreefareTag tag);
-// int		 mad_write(FreefareTag tag, Mad mad, const MifareClassicKey key_b_sector_00, const MifareClassicKey key_b_sector_10);
-// int		 mad_get_version(Mad mad);
-// void		 mad_set_version(Mad mad, const uint8_t version);
-// MifareClassicSectorNumber mad_get_card_publisher_sector(Mad mad);
-// int		 mad_set_card_publisher_sector(Mad mad, const MifareClassicSectorNumber cps);
-// int		 mad_get_aid(Mad mad, const MifareClassicSectorNumber sector, MadAid *aid);
-// int		 mad_set_aid(Mad mad, const MifareClassicSectorNumber sector, MadAid aid);
-// bool		 mad_sector_reserved(const MifareClassicSectorNumber sector);
-// void		 mad_free(Mad mad);
-// 
-// MifareClassicSectorNumber *mifare_application_alloc(Mad mad, const MadAid aid, const size_t size);
-// ssize_t		 mifare_application_read(FreefareTag tag, Mad mad, const MadAid aid, void *buf, size_t nbytes, const MifareClassicKey key, const MifareClassicKeyType key_type);
-// ssize_t		 mifare_application_write(FreefareTag tag, Mad mad, const MadAid aid, const void *buf, size_t nbytes, const MifareClassicKey key, const MifareClassicKeyType key_type);
-// int		 mifare_application_free(Mad mad, const MadAid aid);
-// 
-// MifareClassicSectorNumber *mifare_application_find(Mad mad, const MadAid aid);
-// 
-// 
-// 
-// bool		 mifare_desfire_taste(nfc_device *device, nfc_target target);
-// 
-// /* File types */
-// 
-// enum mifare_desfire_file_types {
-//     MDFT_STANDARD_DATA_FILE             = 0x00,
-//     MDFT_BACKUP_DATA_FILE               = 0x01,
-//     MDFT_VALUE_FILE_WITH_BACKUP         = 0x02,
-//     MDFT_LINEAR_RECORD_FILE_WITH_BACKUP = 0x03,
-//     MDFT_CYCLIC_RECORD_FILE_WITH_BACKUP = 0x04
-// };
-// 
-// /* Communication mode */
-// 
-// #define MDCM_PLAIN      0x00
-// #define MDCM_MACED      0x01
-// #define MDCM_ENCIPHERED 0x03
-// 
-// /* Mifare DESFire master key settings
-// bit 7 - 4: Always 0.
-// bit 3: PICC master key settings frozen = 0 (WARNING - this is irreversible); PICC master key settings changeable when authenticated with PICC master key = 1
-// bit 2: PICC master key authentication required for creating or deleting applications = 0; Authentication not required = 1
-// bit 1: PICC master key authentication required for listing of applications or reading key settings = 0; Free listing of applications and reading key settings = 1
-// bit 0: PICC master key frozen (reversible with configuration change or when formatting card) = 0; PICC master key changeable = 1
-// */
-// 
-// #define MDMK_SETTINGS(picc_master_key_settings_changeable,free_create_delete_application,free_listing_apps_and_key_settings,picc_master_key_changeable) ( \
-// 	(picc_master_key_settings_changeable << 3) | \
-// 	(free_create_delete_application << 2) | \
-// 	(free_listing_apps_and_key_settings << 1) | \
-// 	(picc_master_key_changeable) \
-// 																			)
-// 
-// /* Mifare DESFire EV1 Application crypto operations */
-// 
-// #define APPLICATION_CRYPTO_DES    0x00
-// #define APPLICATION_CRYPTO_3K3DES 0x40
-// #define APPLICATION_CRYPTO_AES    0x80
-// 
-// /* Mifare DESFire Application settings
-//  * bit 7 - 4: Number of key needed to change application keys (key 0 - 13; 0 = master key; 14 = key itself required for key change; 15 = all keys are frozen)
-//  * bit 3: Application configuration frozen = 0; Application configuration changeable when authenticated with application master key = 1
-//  * bit 2: Application master key authentication required for create/delete files = 0; Authentication not required = 1
-//  * bit 1: GetFileIDs, GetFileSettings and GetKeySettings behavior: Master key authentication required = 0; No authentication required = 1
-//  * bit 0 = Application master key frozen = 0; Application master key changeable = 1
-//  */
-// 
-// #define MDAPP_SETTINGS(key_no_for_key_changing,config_changeable,free_create_delete_files,free_listing_contents,app_master_key_changeable) ( \
-// 	(key_no_for_key_changing << 4) | \
-// 	(config_changeable << 3) | \
-// 	(free_create_delete_files << 2) | \
-// 	(free_listing_contents << 1) | \
-// 	(app_master_key_changeable) \
-// 																	   )
-// 
-// /* Access right */
-// 
-// #define MDAR(read,write,read_write,change_access_rights) (    \
-// 	(read << 12) | \
-// 	(write << 8) | \
-// 	(read_write << 4) | \
-// 	(change_access_rights) \
-// 							 )
-// 
-// #define MDAR_READ(ar)       (((ar) >> 12) & 0x0f)
-// #define MDAR_WRITE(ar)      (((ar) >>  8) & 0x0f)
-// #define MDAR_READ_WRITE(ar) (((ar) >>  4) & 0x0f)
-// #define MDAR_CHANGE_AR(ar)  ((ar)         & 0x0f)
-// 
-// #define MDAR_KEY0  0x0
-// #define MDAR_KEY1  0x1
-// #define MDAR_KEY2  0x2
-// #define MDAR_KEY3  0x3
-// #define MDAR_KEY4  0x4
-// #define MDAR_KEY5  0x5
-// #define MDAR_KEY6  0x6
-// #define MDAR_KEY7  0x7
-// #define MDAR_KEY8  0x8
-// #define MDAR_KEY9  0x9
-// #define MDAR_KEY10 0xa
-// #define MDAR_KEY11 0xb
-// #define MDAR_KEY12 0xc
-// #define MDAR_KEY13 0xd
-// #define MDAR_FREE  0xE
-// #define MDAR_DENY  0xF
-// 
-// /* Status and error codes */
-// 
-// #define	OPERATION_OK		0x00
-// #define	NO_CHANGES		0x0C
-// #define	OUT_OF_EEPROM_ERROR	0x0E
-// #define	ILLEGAL_COMMAND_CODE	0x1C
-// #define	INTEGRITY_ERROR		0x1E
-// #define	NO_SUCH_KEY		0x40
-// #define	LENGTH_ERROR		0x7E
-// #define	PERMISSION_ERROR	0x9D
-// #define	PARAMETER_ERROR		0x9E
-// #define	APPLICATION_NOT_FOUND	0xA0
-// #define	APPL_INTEGRITY_ERROR	0xA1
-// #define	AUTHENTICATION_ERROR	0xAE
-// #define	ADDITIONAL_FRAME	0xAF
-// #define	BOUNDARY_ERROR		0xBE
-// #define	PICC_INTEGRITY_ERROR	0xC1
-// #define	COMMAND_ABORTED		0xCA
-// #define	PICC_DISABLED_ERROR	0xCD
-// #define	COUNT_ERROR		0xCE
-// #define	DUPLICATE_ERROR		0xDE
-// #define	EEPROM_ERROR		0xEE
-// #define	FILE_NOT_FOUND		0xF0
-// #define	FILE_INTEGRITY_ERROR	0xF1
-// 
-// /* Error code managed by the library */
-// 
-// #define CRYPTO_ERROR            0x01
-// #define TAG_INFO_MISSING_ERROR	0xBA
-// #define UNKNOWN_TAG_TYPE_ERROR	0xBB
-// 
-// struct mifare_desfire_aid;
-// typedef struct mifare_desfire_aid *MifareDESFireAID;
-// 
-// struct mifare_desfire_df {
-//     uint32_t aid;
-//     uint16_t fid;
-//     uint8_t df_name[16];
-//     size_t df_name_len;
-// };
-// typedef struct mifare_desfire_df MifareDESFireDF;
-// 
-// MifareDESFireAID mifare_desfire_aid_new(uint32_t aid);
-// MifareDESFireAID mifare_desfire_aid_new_with_mad_aid(MadAid mad_aid, uint8_t n);
-// uint32_t	 mifare_desfire_aid_get_aid(MifareDESFireAID aid);
-// 
-// uint8_t		 mifare_desfire_last_pcd_error(FreefareTag tag);
-// uint8_t		 mifare_desfire_last_picc_error(FreefareTag tag);
-// 
-// #pragma pack (push)
-// #pragma pack (1)
-// struct mifare_desfire_version_info {
-//     struct {
-// 	uint8_t vendor_id;
-// 	uint8_t type;
-// 	uint8_t subtype;
-// 	uint8_t version_major;
-// 	uint8_t version_minor;
-// 	uint8_t storage_size;
-// 	uint8_t protocol;
-//     } hardware;
-//     struct {
-// 	uint8_t vendor_id;
-// 	uint8_t type;
-// 	uint8_t subtype;
-// 	uint8_t version_major;
-// 	uint8_t version_minor;
-// 	uint8_t storage_size;
-// 	uint8_t protocol;
-//     } software;
-//     uint8_t uid[7];
-//     uint8_t batch_number[5];
-//     uint8_t production_week;
-//     uint8_t production_year;
-// };
-// #pragma pack (pop)
-// 
-// struct mifare_desfire_file_settings {
-//     uint8_t file_type;
-//     uint8_t communication_settings;
-//     uint16_t access_rights;
-//     union {
-// 	struct {
-// 	    uint32_t file_size;
-// 	} standard_file;
-// 	struct {
-// 	    int32_t lower_limit;
-// 	    int32_t upper_limit;
-// 	    int32_t limited_credit_value;
-// 	    uint8_t limited_credit_enabled;
-// 	} value_file;
-// 	struct {
-// 	    uint32_t record_size;
-// 	    uint32_t max_number_of_records;
-// 	    uint32_t current_number_of_records;
-// 	} linear_record_file;
-//     } settings;
-// };
-// 
-// FreefareTag	 mifare_desfire_tag_new(nfc_device *device, nfc_target target);
-// void		 mifare_desfire_tag_free(FreefareTag tags);
-// 
-// int		 mifare_desfire_connect(FreefareTag tag);
-// int		 mifare_desfire_disconnect(FreefareTag tag);
-// 
-// int		 mifare_desfire_authenticate(FreefareTag tag, uint8_t key_no, MifareDESFireKey key);
-// int		 mifare_desfire_authenticate_iso(FreefareTag tag, uint8_t key_no, MifareDESFireKey key);
-// int		 mifare_desfire_authenticate_aes(FreefareTag tag, uint8_t key_no, MifareDESFireKey key);
-// int		 mifare_desfire_change_key_settings(FreefareTag tag, uint8_t settings);
-// int		 mifare_desfire_get_key_settings(FreefareTag tag, uint8_t *settings, uint8_t *max_keys);
-// int		 mifare_desfire_change_key(FreefareTag tag, uint8_t key_no, MifareDESFireKey new_key, MifareDESFireKey old_key);
-// int		 mifare_desfire_get_key_version(FreefareTag tag, uint8_t key_no, uint8_t *version);
-// int		 mifare_desfire_create_application(FreefareTag tag, MifareDESFireAID aid, uint8_t settings, uint8_t key_no);
-// int		 mifare_desfire_create_application_3k3des(FreefareTag tag, MifareDESFireAID aid, uint8_t settings, uint8_t key_no);
-// int		 mifare_desfire_create_application_aes(FreefareTag tag, MifareDESFireAID aid, uint8_t settings, uint8_t key_no);
-// 
-// int		 mifare_desfire_create_application_iso(FreefareTag tag, MifareDESFireAID aid, uint8_t settings, uint8_t key_no, int want_iso_file_identifiers, uint16_t iso_file_id, uint8_t *iso_file_name, size_t iso_file_name_len);
-// int		 mifare_desfire_create_application_3k3des_iso(FreefareTag tag, MifareDESFireAID aid, uint8_t settings, uint8_t key_no, int want_iso_file_identifiers, uint16_t iso_file_id, uint8_t *iso_file_name, size_t iso_file_name_len);
-// int		 mifare_desfire_create_application_aes_iso(FreefareTag tag, MifareDESFireAID aid, uint8_t settings, uint8_t key_no, int want_iso_file_identifiers, uint16_t iso_file_id, uint8_t *iso_file_name, size_t iso_file_name_len);
-// 
-// int		 mifare_desfire_delete_application(FreefareTag tag, MifareDESFireAID aid);
-// int		 mifare_desfire_get_application_ids(FreefareTag tag, MifareDESFireAID *aids[], size_t *count);
-// int		 mifare_desfire_get_df_names(FreefareTag tag, MifareDESFireDF *dfs[], size_t *count);
-// void		 mifare_desfire_free_application_ids(MifareDESFireAID aids[]);
-// int		 mifare_desfire_select_application(FreefareTag tag, MifareDESFireAID aid);
-// int		 mifare_desfire_format_picc(FreefareTag tag);
-// int		 mifare_desfire_get_version(FreefareTag tag, struct mifare_desfire_version_info *version_info);
-// int		 mifare_desfire_free_mem(FreefareTag tag, uint32_t *size);
-// int		 mifare_desfire_set_configuration(FreefareTag tag, bool disable_format, bool enable_random_uid);
-// int		 mifare_desfire_set_default_key(FreefareTag tag, MifareDESFireKey key);
-// int		 mifare_desfire_set_ats(FreefareTag tag, uint8_t *ats);
-// int		 mifare_desfire_get_card_uid(FreefareTag tag, char **uid);
-// int		 mifare_desfire_get_card_uid_raw(FreefareTag tag, uint8_t uid[7]);
-// int		 mifare_desfire_get_file_ids(FreefareTag tag, uint8_t **files, size_t *count);
-// int		 mifare_desfire_get_iso_file_ids(FreefareTag tag, uint16_t **files, size_t *count);
-// int		 mifare_desfire_get_file_settings(FreefareTag tag, uint8_t file_no, struct mifare_desfire_file_settings *settings);
-// int		 mifare_desfire_change_file_settings(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights);
-// int		 mifare_desfire_create_std_data_file(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t file_size);
-// int		 mifare_desfire_create_std_data_file_iso(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t file_size, uint16_t iso_file_id);
-// int		 mifare_desfire_create_backup_data_file(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t file_size);
-// int		 mifare_desfire_create_backup_data_file_iso(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t file_size, uint16_t iso_file_id);
-// int		 mifare_desfire_create_value_file(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, int32_t lower_limit, int32_t upper_limit, int32_t value, uint8_t limited_credit_enable);
-// int		 mifare_desfire_create_linear_record_file(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t record_size, uint32_t max_number_of_records);
-// int		 mifare_desfire_create_linear_record_file_iso(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t record_size, uint32_t max_number_of_records, uint16_t iso_file_id);
-// int		 mifare_desfire_create_cyclic_record_file(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t record_size, uint32_t max_number_of_records);
-// int		 mifare_desfire_create_cyclic_record_file_iso(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t record_size, uint32_t max_number_of_records, uint16_t iso_file_id);
-// int		 mifare_desfire_delete_file(FreefareTag tag, uint8_t file_no);
-// 
-// ssize_t		 mifare_desfire_read_data(FreefareTag tag, uint8_t file_no, off_t offset, size_t length, void *data);
-// ssize_t		 mifare_desfire_read_data_ex(FreefareTag tag, uint8_t file_no, off_t offset, size_t length, void *data, int cs);
-// ssize_t		 mifare_desfire_write_data(FreefareTag tag, uint8_t file_no, off_t offset, size_t length, const void *data);
-// ssize_t		 mifare_desfire_write_data_ex(FreefareTag tag, uint8_t file_no, off_t offset, size_t length, const void *data, int cs);
-// int		 mifare_desfire_get_value(FreefareTag tag, uint8_t file_no, int32_t *value);
-// int		 mifare_desfire_get_value_ex(FreefareTag tag, uint8_t file_no, int32_t *value, int cs);
-// int		 mifare_desfire_credit(FreefareTag tag, uint8_t file_no, int32_t amount);
-// int		 mifare_desfire_credit_ex(FreefareTag tag, uint8_t file_no, int32_t amount, int cs);
-// int		 mifare_desfire_debit(FreefareTag tag, uint8_t file_no, int32_t amount);
-// int		 mifare_desfire_debit_ex(FreefareTag tag, uint8_t file_no, int32_t amount, int cs);
-// int		 mifare_desfire_limited_credit(FreefareTag tag, uint8_t file_no, int32_t amount);
-// int		 mifare_desfire_limited_credit_ex(FreefareTag tag, uint8_t file_no, int32_t amount, int cs);
-// ssize_t		 mifare_desfire_write_record(FreefareTag tag, uint8_t file_no, off_t offset, size_t length, void *data);
-// ssize_t		 mifare_desfire_write_record_ex(FreefareTag tag, uint8_t file_no, off_t offset, size_t length, void *data, int cs);
-// ssize_t		 mifare_desfire_read_records(FreefareTag tag, uint8_t file_no, off_t offset, size_t length, void *data);
-// ssize_t		 mifare_desfire_read_records_ex(FreefareTag tag, uint8_t file_no, off_t offset, size_t length, void *data, int cs);
-// int		 mifare_desfire_clear_record_file(FreefareTag tag, uint8_t file_no);
-// int		 mifare_desfire_commit_transaction(FreefareTag tag);
-// int		 mifare_desfire_abort_transaction(FreefareTag tag);
-// 
-// MifareDESFireKey mifare_desfire_des_key_new(const uint8_t value[8]);
-// MifareDESFireKey mifare_desfire_3des_key_new(const uint8_t value[16]);
-// MifareDESFireKey mifare_desfire_des_key_new_with_version(const uint8_t value[8]);
-// MifareDESFireKey mifare_desfire_3des_key_new_with_version(const uint8_t value[16]);
-// MifareDESFireKey mifare_desfire_3k3des_key_new(const uint8_t value[24]);
-// MifareDESFireKey mifare_desfire_3k3des_key_new_with_version(const uint8_t value[24]);
-// MifareDESFireKey mifare_desfire_aes_key_new(const uint8_t value[16]);
-// MifareDESFireKey mifare_desfire_aes_key_new_with_version(const uint8_t value[16], uint8_t version);
-// uint8_t		 mifare_desfire_key_get_version(MifareDESFireKey key);
-// void		 mifare_desfire_key_set_version(MifareDESFireKey key, uint8_t version);
-// void		 mifare_desfire_key_free(MifareDESFireKey key);
-// 
-// uint8_t		*tlv_encode(const uint8_t type, const uint8_t *istream, uint16_t isize, size_t *osize);
-// uint8_t		*tlv_decode(const uint8_t *istream, uint8_t *type, uint16_t *size);
-// size_t		tlv_record_length(const uint8_t *istream, size_t *field_length_size, size_t *field_value_size);
-// uint8_t		*tlv_append(uint8_t *a, uint8_t *b);
-// 
-// typedef enum mifare_key_type {
-//     MIFARE_KEY_DES,
-//     MIFARE_KEY_2K3DES,
-//     MIFARE_KEY_3K3DES,
-//     MIFARE_KEY_AES128,
-// 
-//     MIFARE_KEY_LAST = MIFARE_KEY_AES128
-// } MifareKeyType;
-// 
-// struct mifare_key_deriver;
-// typedef struct mifare_key_deriver *MifareKeyDeriver;
-// 
-// MifareKeyDeriver mifare_key_deriver_new_an10922(MifareDESFireKey master_key, MifareKeyType output_key_type);
-// int		 mifare_key_deriver_begin(MifareKeyDeriver deriver);
-// int		 mifare_key_deriver_update_data(MifareKeyDeriver deriver, const uint8_t *data, size_t len);
-// int		 mifare_key_deriver_update_uid(MifareKeyDeriver deriver, FreefareTag tag);
-// int		 mifare_key_deriver_update_aid(MifareKeyDeriver deriver, MifareDESFireAID aid);
-// int		 mifare_key_deriver_update_cstr(MifareKeyDeriver deriver, const char *cstr);
-// MifareDESFireKey mifare_key_deriver_end(MifareKeyDeriver deriver);
-// int		 mifare_key_deriver_end_raw(MifareKeyDeriver deriver, uint8_t* diversified_bytes, size_t data_max_len);
-// void		 mifare_key_deriver_free(MifareKeyDeriver state);
-
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-#endif /* !__FREEFARE_H__ */
--- a/service/rfid_pn532_py/pyfreefare/nfc.h	Wed Feb 05 16:39:08 2020 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,516 +0,0 @@
-/*-
- * Free/Libre Near Field Communication (NFC) library
- *
- * Libnfc historical contributors:
- * Copyright (C) 2009      Roel Verdult
- * Copyright (C) 2009-2013 Romuald Conty
- * Copyright (C) 2010-2012 Romain Tartière
- * Copyright (C) 2010-2013 Philippe Teuwen
- * Copyright (C) 2012-2013 Ludovic Rousseau
- * See AUTHORS file for a more comprehensive list of contributors.
- * Additional contributors of this file:
- *
- * This program is free software: you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation, either version 3 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-
-
-/**
- * @file nfc.h
- * @brief libnfc interface
- *
- * Provide all usefull functions (API) to handle NFC devices.
- */
-
-
-typedef unsigned char uint8_t;
-
-#  include <sys/time.h>
-
-#  include <stdint.h>
-#  include <stdbool.h>
-
-/*-
- * Free/Libre Near Field Communication (NFC) library
- *
- * Libnfc historical contributors:
- * Copyright (C) 2009      Roel Verdult
- * Copyright (C) 2009-2013 Romuald Conty
- * Copyright (C) 2010-2012 Romain Tartière
- * Copyright (C) 2010-2013 Philippe Teuwen
- * Copyright (C) 2012-2013 Ludovic Rousseau
- * See AUTHORS file for a more comprehensive list of contributors.
- * Additional contributors of this file:
- *
- * This program is free software: you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation, either version 3 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- */
-/**
- * @file nfc-types.h
- * @brief Define NFC types
- */
-
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <stdio.h>
-
-
-#define NFC_BUFSIZE_CONNSTRING 1024
-
-
-/**
- * NFC context
- */
-struct nfc_context;
-typedef struct nfc_context nfc_context;
-
-/**
- * NFC device
- */
-struct nfc_device;
-typedef struct nfc_device nfc_device;
-
-/**
- * NFC device driver
- */
-struct nfc_driver;
-typedef struct nfc_driver nfc_driver;
-
-/**
- * Connection string
- */
-typedef char nfc_connstring[NFC_BUFSIZE_CONNSTRING];
-
-/**
- * Properties
- */
-typedef enum {
-  /**
-   * Default command processing timeout
-   * Property value's (duration) unit is ms and 0 means no timeout (infinite).
-   * Default value is set by driver layer
-   */
-  NP_TIMEOUT_COMMAND,
-  /**
-   * Timeout between ATR_REQ and ATR_RES
-   * When the device is in initiator mode, a target is considered as mute if no
-   * valid ATR_RES is received within this timeout value.
-   * Default value for this property is 103 ms on PN53x based devices.
-   */
-  NP_TIMEOUT_ATR,
-  /**
-   * Timeout value to give up reception from the target in case of no answer.
-   * Default value for this property is 52 ms).
-   */
-  NP_TIMEOUT_COM,
-  /** Let the PN53X chip handle the CRC bytes. This means that the chip appends
-  * the CRC bytes to the frames that are transmitted. It will parse the last
-  * bytes from received frames as incoming CRC bytes. They will be verified
-  * against the used modulation and protocol. If an frame is expected with
-  * incorrect CRC bytes this option should be disabled. Example frames where
-  * this is useful are the ATQA and UID+BCC that are transmitted without CRC
-  * bytes during the anti-collision phase of the ISO14443-A protocol. */
-  NP_HANDLE_CRC,
-  /** Parity bits in the network layer of ISO14443-A are by default generated and
-   * validated in the PN53X chip. This is a very convenient feature. On certain
-   * times though it is useful to get full control of the transmitted data. The
-   * proprietary MIFARE Classic protocol uses for example custom (encrypted)
-   * parity bits. For interoperability it is required to be completely
-   * compatible, including the arbitrary parity bits. When this option is
-   * disabled, the functions to communicating bits should be used. */
-  NP_HANDLE_PARITY,
-  /** This option can be used to enable or disable the electronic field of the
-   * NFC device. */
-  NP_ACTIVATE_FIELD,
-  /** The internal CRYPTO1 co-processor can be used to transmit messages
-   * encrypted. This option is automatically activated after a successful MIFARE
-   * Classic authentication. */
-  NP_ACTIVATE_CRYPTO1,
-  /** The default configuration defines that the PN53X chip will try indefinitely
-   * to invite a tag in the field to respond. This could be desired when it is
-   * certain a tag will enter the field. On the other hand, when this is
-   * uncertain, it will block the application. This option could best be compared
-   * to the (NON)BLOCKING option used by (socket)network programming. */
-  NP_INFINITE_SELECT,
-  /** If this option is enabled, frames that carry less than 4 bits are allowed.
-   * According to the standards these frames should normally be handles as
-   * invalid frames. */
-  NP_ACCEPT_INVALID_FRAMES,
-  /** If the NFC device should only listen to frames, it could be useful to let
-   * it gather multiple frames in a sequence. They will be stored in the internal
-   * FIFO of the PN53X chip. This could be retrieved by using the receive data
-   * functions. Note that if the chip runs out of bytes (FIFO = 64 bytes long),
-   * it will overwrite the first received frames, so quick retrieving of the
-   * received data is desirable. */
-  NP_ACCEPT_MULTIPLE_FRAMES,
-  /** This option can be used to enable or disable the auto-switching mode to
-   * ISO14443-4 is device is compliant.
-   * In initiator mode, it means that NFC chip will send RATS automatically when
-   * select and it will automatically poll for ISO14443-4 card when ISO14443A is
-   * requested.
-   * In target mode, with a NFC chip compliant (ie. PN532), the chip will
-   * emulate a 14443-4 PICC using hardware capability */
-  NP_AUTO_ISO14443_4,
-  /** Use automatic frames encapsulation and chaining. */
-  NP_EASY_FRAMING,
-  /** Force the chip to switch in ISO14443-A */
-  NP_FORCE_ISO14443_A,
-  /** Force the chip to switch in ISO14443-B */
-  NP_FORCE_ISO14443_B,
-  /** Force the chip to run at 106 kbps */
-  NP_FORCE_SPEED_106,
-} nfc_property;
-
-// Compiler directive, set struct alignment to 1 uint8_t for compatibility
-#  pragma pack(1)
-
-/**
- * @enum nfc_dep_mode
- * @brief NFC D.E.P. (Data Exchange Protocol) active/passive mode
- */
-typedef enum {
-  NDM_UNDEFINED = 0,
-  NDM_PASSIVE,
-  NDM_ACTIVE,
-} nfc_dep_mode;
-
-/**
- * @struct nfc_dep_info
- * @brief NFC target information in D.E.P. (Data Exchange Protocol) see ISO/IEC 18092 (NFCIP-1)
- */
-typedef struct {
-  /** NFCID3 */
-  uint8_t  abtNFCID3[10];
-  /** DID */
-  uint8_t  btDID;
-  /** Supported send-bit rate */
-  uint8_t  btBS;
-  /** Supported receive-bit rate */
-  uint8_t  btBR;
-  /** Timeout value */
-  uint8_t  btTO;
-  /** PP Parameters */
-  uint8_t  btPP;
-  /** General Bytes */
-  uint8_t  abtGB[48];
-  size_t  szGB;
-  /** DEP mode */
-  nfc_dep_mode ndm;
-} nfc_dep_info;
-
-/**
- * @struct nfc_iso14443a_info
- * @brief NFC ISO14443A tag (MIFARE) information
- */
-typedef struct {
-  uint8_t  abtAtqa[2];
-  uint8_t  btSak;
-  size_t  szUidLen;
-  uint8_t  abtUid[10];
-  size_t  szAtsLen;
-  uint8_t  abtAts[254]; // Maximal theoretical ATS is FSD-2, FSD=256 for FSDI=8 in RATS
-} nfc_iso14443a_info;
-
-/**
- * @struct nfc_felica_info
- * @brief NFC FeLiCa tag information
- */
-typedef struct {
-  size_t  szLen;
-  uint8_t  btResCode;
-  uint8_t  abtId[8];
-  uint8_t  abtPad[8];
-  uint8_t  abtSysCode[2];
-} nfc_felica_info;
-
-/**
- * @struct nfc_iso14443b_info
- * @brief NFC ISO14443B tag information
- */
-typedef struct {
-  /** abtPupi store PUPI contained in ATQB (Answer To reQuest of type B) (see ISO14443-3) */
-  uint8_t abtPupi[4];
-  /** abtApplicationData store Application Data contained in ATQB (see ISO14443-3) */
-  uint8_t abtApplicationData[4];
-  /** abtProtocolInfo store Protocol Info contained in ATQB (see ISO14443-3) */
-  uint8_t abtProtocolInfo[3];
-  /** ui8CardIdentifier store CID (Card Identifier) attributted by PCD to the PICC */
-  uint8_t ui8CardIdentifier;
-} nfc_iso14443b_info;
-
-/**
- * @struct nfc_iso14443bi_info
- * @brief NFC ISO14443B' tag information
- */
-typedef struct {
-  /** DIV: 4 LSBytes of tag serial number */
-  uint8_t abtDIV[4];
-  /** Software version & type of REPGEN */
-  uint8_t btVerLog;
-  /** Config Byte, present if long REPGEN */
-  uint8_t btConfig;
-  /** ATR, if any */
-  size_t szAtrLen;
-  uint8_t  abtAtr[33];
-} nfc_iso14443bi_info;
-
-/**
- * @struct nfc_iso14443b2sr_info
- * @brief NFC ISO14443-2B ST SRx tag information
- */
-typedef struct {
-  uint8_t abtUID[8];
-} nfc_iso14443b2sr_info;
-
-/**
- * @struct nfc_iso14443b2ct_info
- * @brief NFC ISO14443-2B ASK CTx tag information
- */
-typedef struct {
-  uint8_t abtUID[4];
-  uint8_t btProdCode;
-  uint8_t btFabCode;
-} nfc_iso14443b2ct_info;
-
-/**
- * @struct nfc_jewel_info
- * @brief NFC Jewel tag information
- */
-typedef struct {
-  uint8_t  btSensRes[2];
-  uint8_t  btId[4];
-} nfc_jewel_info;
-
-/**
- * @union nfc_target_info
- * @brief Union between all kind of tags information structures.
- */
-typedef union {
-  nfc_iso14443a_info nai;
-  nfc_felica_info nfi;
-  nfc_iso14443b_info nbi;
-  nfc_iso14443bi_info nii;
-  nfc_iso14443b2sr_info nsi;
-  nfc_iso14443b2ct_info nci;
-  nfc_jewel_info nji;
-  nfc_dep_info ndi;
-} nfc_target_info;
-
-/**
- * @enum nfc_baud_rate
- * @brief NFC baud rate enumeration
- */
-typedef enum {
-  NBR_UNDEFINED = 0,
-  NBR_106,
-  NBR_212,
-  NBR_424,
-  NBR_847,
-} nfc_baud_rate;
-
-/**
- * @enum nfc_modulation_type
- * @brief NFC modulation type enumeration
- */
-typedef enum {
-  NMT_ISO14443A = 1,
-  NMT_JEWEL,
-  NMT_ISO14443B,
-  NMT_ISO14443BI, // pre-ISO14443B aka ISO/IEC 14443 B' or Type B'
-  NMT_ISO14443B2SR, // ISO14443-2B ST SRx
-  NMT_ISO14443B2CT, // ISO14443-2B ASK CTx
-  NMT_FELICA,
-  NMT_DEP,
-} nfc_modulation_type;
-
-/**
- * @enum nfc_mode
- * @brief NFC mode type enumeration
- */
-typedef enum {
-  N_TARGET,
-  N_INITIATOR,
-} nfc_mode;
-
-/**
- * @struct nfc_modulation
- * @brief NFC modulation structure
- */
-typedef struct {
-  nfc_modulation_type nmt;
-  nfc_baud_rate nbr;
-} nfc_modulation;
-
-/**
- * @struct nfc_target
- * @brief NFC target structure
- */
-typedef struct {
-  nfc_target_info nti;
-  nfc_modulation nm;
-} nfc_target;
-
-// Reset struct alignment to default
-#  pragma pack()
-
-
-/* Library initialization/deinitialization */
-void nfc_init(nfc_context **context);
-void nfc_exit(nfc_context *context);
-int nfc_register_driver(const nfc_driver *driver);
-
-/* NFC Device/Hardware manipulation */
-nfc_device *nfc_open(nfc_context *context, const nfc_connstring connstring);
-void nfc_close(nfc_device *pnd);
-int nfc_abort_command(nfc_device *pnd);
-size_t nfc_list_devices(nfc_context *context, nfc_connstring connstrings[], size_t connstrings_len);
-int nfc_idle(nfc_device *pnd);
-
-/* NFC initiator: act as "reader" */
-int nfc_initiator_init(nfc_device *pnd);
-int nfc_initiator_init_secure_element(nfc_device *pnd);
-int nfc_initiator_select_passive_target(nfc_device *pnd, const nfc_modulation nm, const uint8_t *pbtInitData, const size_t szInitData, nfc_target *pnt);
-int nfc_initiator_list_passive_targets(nfc_device *pnd, const nfc_modulation nm, nfc_target ant[], const size_t szTargets);
-int nfc_initiator_poll_target(nfc_device *pnd, const nfc_modulation *pnmTargetTypes, const size_t szTargetTypes, const uint8_t uiPollNr, const uint8_t uiPeriod, nfc_target *pnt);
-int nfc_initiator_select_dep_target(nfc_device *pnd, const nfc_dep_mode ndm, const nfc_baud_rate nbr, const nfc_dep_info *pndiInitiator, nfc_target *pnt, const int timeout);
-int nfc_initiator_poll_dep_target(nfc_device *pnd, const nfc_dep_mode ndm, const nfc_baud_rate nbr, const nfc_dep_info *pndiInitiator, nfc_target *pnt, const int timeout);
-int nfc_initiator_deselect_target(nfc_device *pnd);
-int nfc_initiator_transceive_bytes(nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx, uint8_t *pbtRx, const size_t szRx, int timeout);
-int nfc_initiator_transceive_bits(nfc_device *pnd, const uint8_t *pbtTx, const size_t szTxBits, const uint8_t *pbtTxPar, uint8_t *pbtRx, const size_t szRx, uint8_t *pbtRxPar);
-int nfc_initiator_transceive_bytes_timed(nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx, uint8_t *pbtRx, const size_t szRx, uint32_t *cycles);
-int nfc_initiator_transceive_bits_timed(nfc_device *pnd, const uint8_t *pbtTx, const size_t szTxBits, const uint8_t *pbtTxPar, uint8_t *pbtRx, const size_t szRx, uint8_t *pbtRxPar, uint32_t *cycles);
-int nfc_initiator_target_is_present(nfc_device *pnd, const nfc_target *pnt);
-
-/* NFC target: act as tag (i.e. MIFARE Classic) or NFC target device. */
-int nfc_target_init(nfc_device *pnd, nfc_target *pnt, uint8_t *pbtRx, const size_t szRx, int timeout);
-int nfc_target_send_bytes(nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx, int timeout);
-int nfc_target_receive_bytes(nfc_device *pnd, uint8_t *pbtRx, const size_t szRx, int timeout);
-int nfc_target_send_bits(nfc_device *pnd, const uint8_t *pbtTx, const size_t szTxBits, const uint8_t *pbtTxPar);
-int nfc_target_receive_bits(nfc_device *pnd, uint8_t *pbtRx, const size_t szRx, uint8_t *pbtRxPar);
-
-/* Error reporting */
-const char *nfc_strerror(const nfc_device *pnd);
-int nfc_strerror_r(const nfc_device *pnd, char *buf, size_t buflen);
-void nfc_perror(const nfc_device *pnd, const char *s);
-int nfc_device_get_last_error(const nfc_device *pnd);
-
-/* Special data accessors */
-const char *nfc_device_get_name(nfc_device *pnd);
-const char *nfc_device_get_connstring(nfc_device *pnd);
-int nfc_device_get_supported_modulation(nfc_device *pnd, const nfc_mode mode,  const nfc_modulation_type **const supported_mt);
-int nfc_device_get_supported_baud_rate(nfc_device *pnd, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br);
-
-/* Properties accessors */
-int nfc_device_set_property_int(nfc_device *pnd, const nfc_property property, const int value);
-int nfc_device_set_property_bool(nfc_device *pnd, const nfc_property property, const bool bEnable);
-
-/* Misc. functions */
-void iso14443a_crc(uint8_t *pbtData, size_t szLen, uint8_t *pbtCrc);
-void iso14443a_crc_append(uint8_t *pbtData, size_t szLen);
-void iso14443b_crc(uint8_t *pbtData, size_t szLen, uint8_t *pbtCrc);
-void iso14443b_crc_append(uint8_t *pbtData, size_t szLen);
-uint8_t *iso14443a_locate_historical_bytes(uint8_t *pbtAts, size_t szAts, size_t *pszTk);
-
-void nfc_free(void *p);
-const char *nfc_version(void);
-int nfc_device_get_information_about(nfc_device *pnd, char **buf);
-
-/* String converter functions */
-const char *str_nfc_modulation_type(const nfc_modulation_type nmt);
-const char *str_nfc_baud_rate(const nfc_baud_rate nbr);
-int str_nfc_target(char **buf, const nfc_target *pnt, bool verbose);
-
-/* Error codes */
-/** @ingroup error
- * @hideinitializer
- * Success (no error)
- */
-#define NFC_SUCCESS			 0
-/** @ingroup error
- * @hideinitializer
- * Input / output error, device may not be usable anymore without re-open it
- */
-#define NFC_EIO				-1
-/** @ingroup error
- * @hideinitializer
- * Invalid argument(s)
- */
-#define NFC_EINVARG			-2
-/** @ingroup error
- * @hideinitializer
- *  Operation not supported by device
- */
-#define NFC_EDEVNOTSUPP			-3
-/** @ingroup error
- * @hideinitializer
- * No such device
- */
-#define NFC_ENOTSUCHDEV			-4
-/** @ingroup error
- * @hideinitializer
- * Buffer overflow
- */
-#define NFC_EOVFLOW			-5
-/** @ingroup error
- * @hideinitializer
- * Operation timed out
- */
-#define NFC_ETIMEOUT			-6
-/** @ingroup error
- * @hideinitializer
- * Operation aborted (by user)
- */
-#define NFC_EOPABORTED			-7
-/** @ingroup error
- * @hideinitializer
- * Not (yet) implemented
- */
-#define NFC_ENOTIMPL			-8
-/** @ingroup error
- * @hideinitializer
- * Target released
- */
-#define NFC_ETGRELEASED			-10
-/** @ingroup error
- * @hideinitializer
- * Error while RF transmission
- */
-#define NFC_ERFTRANS			-20
-/** @ingroup error
- * @hideinitializer
- * MIFARE Classic: authentication failed
- */
-#define NFC_EMFCAUTHFAIL		-30
-/** @ingroup error
- * @hideinitializer
- * Software error (allocation, file/pipe creation, etc.)
- */
-#define NFC_ESOFT			-80
-/** @ingroup error
- * @hideinitializer
- * Device's internal chip error
- */
-#define NFC_ECHIP			-90
-
--- a/service/rfid_pn532_py/requirements.txt	Wed Feb 05 16:39:08 2020 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-docopt
-rdflib-jsonld==0.4.0
-rdflib==4.2.2
-https://projects.bigasterisk.com/rdfdb/rdfdb-0.8.0.tar.gz
-git+http://github.com/drewp/scales.git@448d59fb491b7631877528e7695a93553bfaaa93#egg=scales
-influxdb==3.0.0
-https://github.com/drewp/cyclone/archive/python3.zip
--- a/service/rfid_pn532_py/rfid-console.html	Wed Feb 05 16:39:08 2020 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-<link rel="import" href="/lib/polymer/1.0.9/iron-ajax/iron-ajax.html">
-<link rel="import" href="/lib/polymer/1.0.9/polymer/polymer.html">
-<link rel="import" href="/rdf/rdf-oneshot.html">
-<link rel="import" href="/rdf/rdf-uri.html">
-<link rel="import" href="/rdf/streamed-graph.html">
-
-<dom-module id="rfid-console">
-  <style>
-   button {
-       min-width: 60px;
-       min-height: 40px;
-   }
-   table {
-       border-collapse: collapse;
-   }
-   
-   td, th {
-       border: 1px solid gray;
-   }
-  </style>
-  <template>
-    
-    <iron-ajax id="rewrite" url="rewrite" method="POST"></iron-ajax>
-    
-    Current RFID reads: 
-    <table>
-      <tr><th>Card UID</th><th>Card text</th><th></th></tr>
-      <template is="dom-repeat" items="{{currentReads}}">
-        <tr>
-          <td>{{item.uidDisplay}}</td>
-          <td>{{item.text}}</td>
-          <td>
-            <div id="form">
-              <button on-click="rewrite">Rewrite</button>
-            </div>
-          </td>
-        </tr>
-      </template>
-    </table>
-
-    <div>
-      <streamed-graph url="graph/events" graph="{{graph}}"></streamed-graph>
-      <!-- also get a graph of users so we can look up cards -->
-    </div>
-  </template>
-  <script>
-   Polymer({
-     is: 'rfid-console',
-     properties: {
-       graph: { type: Object, notify: true, observer: "_onGraph" },
-       currentReads: { type: Array, value: [] },
-     },
-     behaviors: [BigastUri],
-     _onGraph: function(graph) {
-       if (!graph.graph) return;
-       const env = graph.graph.store.rdf;
-
-       this.splice('currentReads', 0, this.currentReads.length);
-       graph.graph.quadStore.quads(
-         {subject: env.createNamedNode('room:frontDoorWindowRfid'),
-          predicate: env.createNamedNode('room:reading'),
-         },
-         (q) => {
-           graph.graph.quadStore.quads(
-             {subject: q.object,
-              predicate: env.createNamedNode('room:cardText'),
-             },
-             (q2) => {
-               this.push(
-                 'currentReads', {
-                   'cardUid': q.object,
-                   'uidDisplay': q.object.toString().replace(/.*\//, ""),
-                   'text': q2.object.toString()
-                 });
-             });
-         });
-     },
-     rewrite: function(ev) {
-       const cardUid = ev.model.item.cardUid;
-
-       // ask for user first
-
-       this.$.rewrite.contentType = "application/json";
-       this.$.rewrite.body = {'cardUid': cardUid.toString(),
-                              'user': "some foaf"};
-       this.$.rewrite.generateRequest();
-     }
-   });
-  </script>
-</dom-module>
--- a/service/rfid_pn532_py/rfid.py	Wed Feb 05 16:39:08 2020 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,230 +0,0 @@
-import os
-os.environ['LIBNFC_DEFAULT_DEVICE'] = "pn532_uart:/dev/ttyUSB0"
-
-from docopt import docopt
-from rdfdb.patch import Patch
-from patchablegraph import PatchableGraph, CycloneGraphHandler, CycloneGraphEventsHandler
-from rdflib import Namespace, URIRef, Literal, Graph
-from rdflib.parser import StringInputSource
-from twisted.internet import reactor, task, defer
-import cyclone.web
-from cyclone.httpclient import fetch
-import cyclone
-import logging, time, json, random, string, traceback
-from logsetup import log, enableTwistedLog
-from greplin import scales
-from greplin.scales.cyclonehandler import StatsHandler
-from export_to_influxdb import InfluxExporter
-from tags import NfcDevice, FakeNfc, NfcError, AuthFailedError
-
-ROOM = Namespace('http://projects.bigasterisk.com/room/')
-
-ctx = ROOM['frontDoorWindowRfidCtx']
-
-STATS = scales.collection('/root',
-                          scales.PmfStat('cardReadPoll'),
-                          scales.IntStat('newCardReads'),
-)
-
-class OutputPage(cyclone.web.RequestHandler):
-    def put(self):
-        arg = self.request.arguments
-        if arg.get('s') and arg.get('p'):
-            self._onQueryStringStatement(arg['s'][-1], arg['p'][-1], self.request.body)
-        else:
-            self._onGraphBodyStatements(self.request.body, self.request.headers)
-    post = put
-    def _onQueryStringStatement(self, s, p, body):
-        subj = URIRef(s)
-        pred = URIRef(p)
-        turtleLiteral = self.request.body
-        try:
-            obj = Literal(float(turtleLiteral))
-        except ValueError:
-            obj = Literal(turtleLiteral)
-        self._onStatements([(subj, pred, obj)])
-
-    def _onGraphBodyStatements(self, body, headers):
-        g = Graph()
-        g.parse(StringInputSource(body), format='nt')
-        if not g:
-            raise ValueError("expected graph body")
-        self._onStatements(list(g.triples((None, None, None))))
-    post = put
-
-    def _onStatements(self, stmts):
-        # write rfid to new key, etc.
-        if len(stmts) > 0 and stmts[0][1] == ROOM['keyContents']:
-            return
-        log.warn("ignoring %s", stmts)
-
-def uidUri(card_id):
-    return URIRef('http://bigasterisk.com/rfidCard/%s' % card_id)
-
-BODY_VERSION = "1"
-def randomBody():
-    return BODY_VERSION + '*' + ''.join(random.choice(string.ascii_uppercase) for n in range(16 - 2))
-
-def looksLikeBigasterisk(text):
-    return text.startswith(BODY_VERSION + "*")
-
-class Rewrite(cyclone.web.RequestHandler):
-    def post(self):
-        agent = URIRef(self.request.headers['x-foaf-agent'])
-        body = json.loads(self.request.body)
-
-        _, uid = reader.read_id()
-        log.info('current card id: %r %r', _, uid)
-        if uid is None:
-            self.set_status(404, "no card present")
-            # maybe retry a few more times since the card might be nearby
-            return
-
-        text = randomBody()
-        log.info('%s rewrites %s to %s, to be owned by %s',
-                 agent, uid, text, body['user'])
-
-        #reader.KEY = private.rfid_key
-        reader.write(uid, text)
-        log.info('done with write')
-
-
-sensor = ROOM['frontDoorWindowRfid']
-
-class ReadLoop(object):
-    def __init__(self, reader, masterGraph, overwrite_any_tag):
-        self.reader = reader
-        self.masterGraph = masterGraph
-        self.overwrite_any_tag = overwrite_any_tag
-        self.log = {} # cardIdUri : most recent seentime
-
-        self.pollPeriodSecs = .1
-        self.expireSecs = 5
-
-        # now=False avoids a serious bug where the first read error
-        # could happen before reactor.run() is called, and then the
-        # error fails to crash the reactor and get us restarted.
-        task.LoopingCall(self.poll).start(self.pollPeriodSecs, now=False)
-
-    @STATS.cardReadPoll.time()
-    def poll(self):
-        now = time.time()
-
-        self.flushOldReads(now)
-
-        try:
-            for tag in self.reader.getTags(): # blocks for a bit
-                uid = tag.uid()
-                log.debug('detected tag uid=%r', uid)
-                cardIdUri = uidUri(uid)
-
-                is_new = cardIdUri not in self.log
-                self.log[cardIdUri] = now
-                if is_new:
-                    STATS.newCardReads += 1
-                    tag.connect()
-                    try:
-                        textLit = Literal(tag.readBlock(1).rstrip('\x00'))
-                        if self.overwrite_any_tag and not looksLikeBigasterisk(textLit):
-                            log.info("block 1 was %r; rewriting it", textLit)
-                            tag.writeBlock(1, randomBody())
-                            textLit = Literal(tag.readBlock(1).rstrip('\x00'))
-                    finally:
-                        # This might not be appropriate to call after
-                        # readBlock fails. I am getting double
-                        # exceptions.
-                        tag.disconnect()
-                    self.startCardRead(cardIdUri, textLit)
-        except AuthFailedError as e:
-            log.error(e)
-        except (NfcError, OSError) as e:
-            traceback.print_exc()
-            log.error(e)
-            reactor.stop()
-
-    def flushOldReads(self, now):
-        for uri in list(self.log):
-            if self.log[uri] < now - self.expireSecs:
-                self.endCardRead(uri)
-                del self.log[uri]
-
-    def startCardRead(self, cardUri, text):
-        self.masterGraph.patch(Patch(addQuads=[
-            (sensor, ROOM['reading'], cardUri, ctx),
-            (cardUri, ROOM['cardText'], text, ctx)],
-                                     delQuads=[]))
-        log.info('%s :cardText %s .', cardUri.n3(), text.n3())
-        self._sendOneshot([(sensor, ROOM['startReading'], cardUri),
-                            (cardUri, ROOM['cardText'], text)])
-
-    def endCardRead(self, cardUri):
-        log.debug(f'{cardUri} has been gone for {self.expireSecs} sec')
-        delQuads = []
-        for spo in self.masterGraph._graph.triples(
-                (sensor, ROOM['reading'], cardUri)):
-            delQuads.append(spo + (ctx,))
-        for spo in self.masterGraph._graph.triples(
-                (cardUri, ROOM['cardText'], None)):
-            delQuads.append(spo + (ctx,))
-
-        self.masterGraph.patch(Patch(addQuads=[], delQuads=delQuads))
-
-    def _sendOneshot(self, oneshot):
-        body = (' '.join('%s %s %s .' % (s.n3(), p.n3(), o.n3())
-                         for s,p,o in oneshot)).encode('utf8')
-        url = b'http://bang:9071/oneShot'
-        d = fetch(method=b'POST',
-                  url=url,
-                  headers={b'Content-Type': [b'text/n3']},
-                  postdata=body,
-                  timeout=5)
-        def err(e):
-            log.info('oneshot post to %r failed:  %s',
-                     url, e.getErrorMessage())
-        d.addErrback(err)
-
-
-
-if __name__ == '__main__':
-    arg = docopt("""
-    Usage: rfid.py [options]
-
-    -v                    Verbose
-    --overwrite_any_tag   Rewrite any unknown tag with a new random body
-    -n                    Fake reader
-    """)
-    log.setLevel(logging.INFO)
-    if arg['-v']:
-        enableTwistedLog()
-        log.setLevel(logging.DEBUG)
-        log.info(f'cyclone {cyclone.__version__}')
-        defer.setDebugging(True)
-
-    masterGraph = PatchableGraph()
-    reader = NfcDevice() if not arg['-n'] else FakeNfc()
-
-    ie=InfluxExporter(Graph())
-    ie.exportStats(STATS, ['root.cardReadPoll.count',
-                           'root.cardReadPoll.95percentile',
-                           'root.newCardReads',
-                       ],
-                    period_secs=10,
-                    retain_days=7,
-    )
-
-    loop = ReadLoop(reader, masterGraph, overwrite_any_tag=arg['--overwrite_any_tag'])
-
-    port = 10012
-    reactor.listenTCP(port, cyclone.web.Application([
-        (r"/(|.+\.html)", cyclone.web.StaticFileHandler,
-         {"path": ".", "default_filename": "index.html"}),
-        (r"/graph/rfid", CycloneGraphHandler, {'masterGraph': masterGraph}),
-        (r"/graph/rfid/events", CycloneGraphEventsHandler,
-         {'masterGraph': masterGraph}),
-        (r'/output', OutputPage),
-        (r'/rewrite', Rewrite),
-        (r'/stats/(.*)', StatsHandler, {'serverName': 'rfid'}),
-        ], masterGraph=masterGraph, debug=arg['-v']), interface='::')
-    log.warn('serving on %s', port)
-
-    reactor.run()
--- a/service/rfid_pn532_py/tags.py	Wed Feb 05 16:39:08 2020 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-import time
-from ctypes import pointer, byref, c_ubyte, cast, c_char_p
-import nfc, freefare
-import logging
-log = logging.getLogger('tags')
-
-class FakeNfc(object):
-    def getTags(self):
-        return []
-
-    
-class NfcDevice(object):
-    def __init__(self):
-        self.context = pointer(nfc.nfc_context())
-        nfc.nfc_init(byref(self.context))
-        self.dev = None
-
-        conn_strings = (nfc.nfc_connstring * 10)()
-        t0, _, t2 = nfc.nfc_list_devices.argtypes
-        nfc.nfc_list_devices.argtypes = [t0, type(conn_strings), t2]
-        log.info("nfc_list_devices:")
-        devices_found = nfc.nfc_list_devices(self.context, conn_strings, 10)
-        log.info(f'{devices_found} connection strings')
-        for i in range(devices_found):
-            log.info(f'  dev {i}: {cast(conn_strings[i], c_char_p).value}')
-        if devices_found < 1:
-            raise IOError("no devices")
-            
-        log.debug("open dev")
-        self.dev = nfc.nfc_open(self.context, conn_strings[0])
-        if not self.dev or nfc.nfc_device_get_last_error(self.dev):
-            raise IOError(f'nfc.open failed on {cast(conn_strings[0], c_char_p).value}')
-
-    def __del__(self):
-        if self.dev:
-            nfc.nfc_close(self.dev)
-        nfc.nfc_exit(self.context)
-
-    def getTags(self):
-        log.debug("getting tags")
-        t0 = time.time()
-        # see https://github.com/nfc-tools/libfreefare/blob/master/libfreefare/freefare.c
-        # for how this might waste time on felica tags
-        ret = freefare.freefare_get_tags(self.dev)
-        if not ret:
-            raise IOError("freefare_get_tags returned null")
-        try:
-            log.debug(f"found tags in {time.time() - t0}")
-            for t in ret:
-                if not t:
-                    break
-                yield NfcTag(t)
-        finally:
-            freefare.freefare_free_tags(ret)
-
-pubkey = b'\xff\xff\xff\xff\xff\xff'
-
-class NfcError(Exception):
-    def __init__(self, code, strerror):
-        Exception.__init__(self, "%s [%s]" % (strerror, code))
-        self.code = code
-
-class AuthFailedError(NfcError): pass
-
-class NfcTag(object):
-    def __init__(self, tag): #FreefareTag
-        self.tag = tag
-
-    def _check(self, ret: int):
-        if ret == 0:
-            return
-
-        msg = cast(freefare.freefare_strerror(self.tag), c_char_p).value
-        if msg == b'Mifare Authentication Failed':
-            # return code is -1 (!). I was excpecting
-            # AUTHENTICATION_ERROR=0xAE or something.
-            raise AuthFailedError(ret, msg)        
-            
-        raise NfcError(ret, msg)
-        
-    def tagType(self) -> str:
-        typeNum = freefare.freefare_get_tag_type(self.tag)
-        return freefare.freefare_tag_type__enumvalues[typeNum]
-
-    def uid(self) -> str:
-        return cast(freefare.freefare_get_tag_uid(self.tag),
-                    c_char_p).value.decode('ascii')
-
-    def connect(self):
-        self._check(freefare.mifare_classic_connect(self.tag))
-
-    def disconnect(self):
-        self._check(freefare.mifare_classic_disconnect(self.tag))
-
-    def readBlock(self, blockNumber: int) -> bytes:
-        blockNum = freefare.MifareClassicBlockNumber(blockNumber)
-        self._check(freefare.mifare_classic_authenticate(
-            self.tag, blockNum, (c_ubyte*6)(*pubkey), freefare.MFC_KEY_A))
-  
-        data = freefare.MifareClassicBlock()
-        self._check(freefare.mifare_classic_read(self.tag, blockNum, pointer(data)))
-        return ''.join(map(chr, data)) # with trailing nulls
-
-    def writeBlock(self, blockNumber: int, data: str):
-        blocknum = freefare.MifareClassicBlockNumber(blockNumber)
-        self._check(freefare.mifare_classic_authenticate(
-          self.tag, blocknum, (c_ubyte*6)(*pubkey), freefare.MFC_KEY_A))
-  
-        dataBytes = data.encode('utf8')
-        if len(dataBytes) > 16:
-            raise ValueError('too long')
-        dataBlock = (c_ubyte*16)(*dataBytes)
-        
-        self._check(freefare.mifare_classic_write(self.tag, blocknum, dataBlock))
-        log.info(f"  wrote block {blocknum}: {dataBlock}")
--- a/service/rfid_pn532_py/tags_test.py	Wed Feb 05 16:39:08 2020 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-import unittest
-import tags
-import time
-import os
-os.environ['LIBNFC_DEFAULT_DEVICE'] = "pn532_i2c:/dev/i2c-1"
-import logging
-logging.basicConfig(level=logging.DEBUG)
-log = logging.getLogger()
-
-class TestNfc(unittest.TestCase):
-    def test_open_close(self):
-        n = tags.NfcDevice()
-        del n
-        
-    def test_update_tag(self): # writes to the current tag!
-        n = tags.NfcDevice()
-        for t in n.getTags():
-            print('tag', t)
-            print('  tagType', t.tagType())
-            print('  uid %r' % t.uid())
-            t.connect()
-            try:
-                print('  block 1', t.readBlock(1))
-                print('write')
-                t.writeBlock(1, 'hello %s' % int(time.time()))
-                print('  block 1', t.readBlock(1))
-            finally:
-                t.disconnect()