Mercurial > code > home > repos > homeauto
changeset 1200:fe97a15ddd6e
more nim progress on rfid reader
Ignore-this: 762e256b911e74db2b2103b509250e9f
darcs-hash:cfda5d2da1483a6126d473a42c0cec994561e2ec
author | drewp <drewp@bigasterisk.com> |
---|---|
date | Thu, 21 Feb 2019 09:58:56 -0800 |
parents | 87283af13f15 |
children | 3a420f34a54f |
files | service/rfid_pn532/Dockerfile service/rfid_pn532/Dockerfile.pi service/rfid_pn532/index.html service/rfid_pn532/makefile service/rfid_pn532/nfc-nim/freefare.h service/rfid_pn532/nfc-nim/nfc.h service/rfid_pn532/nim.cfg service/rfid_pn532/rfid.nim service/rfid_pn532/tags.nim |
diffstat | 9 files changed, 1387 insertions(+), 15 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/service/rfid_pn532/Dockerfile Thu Feb 21 09:58:56 2019 -0800 @@ -0,0 +1,18 @@ +FROM bang6:5000/base_nim_x86 + +WORKDIR /opt + +RUN apt-get install -y libnfc5 libfreefare0 libnfc-dev libfreefare-dev && \ + ln -sf libnfc.so.5 /usr/lib/x86_64-linux-gnu/libnfc.so && \ + ln -sf libfreefare.so.0 /usr/lib/x86_64-linux-gnu/libfreefare.so + +COPY *.nim *.cfg ./ +COPY nfc-nim/ nfc-nim/ + +RUN nim c -d:nimDebugDlOpen rfid.nim + +ENV LIBNFC_DEFAULT_DEVICE="pn532_i2c:/dev/i2c-1" + +EXPOSE 10012 + +CMD ["./rfid"]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/service/rfid_pn532/Dockerfile.pi Thu Feb 21 09:58:56 2019 -0800 @@ -0,0 +1,21 @@ +FROM bang6:5000/base_nim_pi + +WORKDIR /opt + +RUN apt-get install -y libnfc5 libfreefare0 libnfc-dev libfreefare-dev && \ + ln -sf libnfc.so.5 /usr/lib/arm-linux-gnueabihf/libnfc.so && \ + ln -sf libfreefare.so.0 /usr/lib/arm-linux-gnueabihf/libfreefare.so + +COPY *.nim *.cfg ./ +COPY nfc-nim/ nfc-nim/ + +RUN nim c -d:nimDebugDlOpen rfid.nim + +ENV LIBNFC_DEFAULT_DEVICE="pn532_i2c:/dev/i2c-1" + +EXPOSE 10012 + +# i2c may not read right. might need to run 'pigs m 2 0; pigs m 3 0' first, or restart pigpiod? + +CMD ["./rfid"] +# LIBNFC_DEFAULT_DEVICE="pn532_i2c:/dev/i2c-1" mifare-classic-read-ndef -o /tmp/card
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/service/rfid_pn532/index.html Thu Feb 21 09:58:56 2019 -0800 @@ -0,0 +1,128 @@ +<!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> + requirejs.config({ + paths: { + "streamed-graph": "/rdf/streamed-graph", + "quadstore": "/rdf/quadstore", + "async-module": "/lib/async/80f1793/async", + "async": "/lib/async/80f1793/async", + "jsonld-module": "/lib/jsonld.js/0.4.11/js/jsonld", + "jsonld": "/lib/jsonld.js/0.4.11/js/jsonld", + "rdfstore": "/lib/rdf_store/0.9.7/dist/rdfstore", + "moment": "/lib/moment.min", + "underscore": "/lib/underscore-1.5.2.min", + } + }); + </script> + <script> + window.NS = { + dev: 'http://projects.bigasterisk.com/device/', + room: 'http://projects.bigasterisk.com/room/', + rdfs: 'http://www.w3.org/2000/01/rdf-schema#', + sensor: 'http://bigasterisk.com/homeauto/sensor/', + }; + </script> + <link rel="import" href="/lib/polymer/1.0.9/iron-ajax/iron-ajax.html"> + <link rel="import" href="/rdf/streamed-graph.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"> + </head> + <body> + <dom-module id="rfid-control"> + <style> + button { + min-width: 60px; + min-height: 40px; + } + table { + border-collapse: collapse; + } + + td, th { + border: 1px solid gray; + } + </style> + <template> + <div> + <streamed-graph url="graph/events" graph="{{graph}}"></streamed-graph> + <!-- also get a graph of users so we can look up cards --> + </div> + + <iron-ajax id="rewrite" url="rewrite" method="POST"></iron-ajax> + + Current 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> + + </template> + <script> + HTMLImports.whenReady(function () { + Polymer({ + is: 'rfid-control', + 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> + <rfid-control></rfid-control> + </body> +</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/service/rfid_pn532/makefile Thu Feb 21 09:58:56 2019 -0800 @@ -0,0 +1,43 @@ +SERVICE=rfid_pn532 + +nfc-nim/nfc.nim: nfc-nim/nfc.h + c2nim/c2nim nfc-nim/nfc.h + +nfc-nim/freefare.nim: nfc-nim/freefare.h + c2nim/c2nim nfc-nim/freefare.h + +freefare_demo: freefare_demo.nim nfc-nim/nfc.nim nfc-nim/freefare.nim + nim-0.19.4/bin/nim c -d:nimDebugDlOpen freefare_demo.nim + +freefare_demo_run: freefare_demo + ./freefare_demo + +rfid: rfid.nim graphserver.nim nfc-nim/nfc.nim nfc-nim/freefare.nim + nim-0.19.4/bin/nim c -d:nimDebugDlOpen rfid.nim + +rfid_local_run: rfid + ./rfid + + +build_image: + rm -rf tmp_ctx + mkdir -p tmp_ctx + cp -a Dockerfile *.nim *.cfg nfc-nim tmp_ctx + docker build --network=host -t bang6:5000/$(SERVICE)_x86:latest tmp_ctx + docker push bang6:5000/$(SERVICE)_x86:latest + rm -rf tmp_ctx + + +build_image_pi: + rm -rf tmp_ctx + mkdir -p tmp_ctx + cp -a Dockerfile.pi *.nim *.cfg nfc-nim tmp_ctx + docker build --file Dockerfile.pi --network=host -t bang6:5000/$(SERVICE)_pi:latest tmp_ctx + docker push bang6:5000/$(SERVICE)_pi:latest + rm -rf tmp_ctx + +shell: build_image + docker run --name rfid_shell --rm -it --cap-add SYS_PTRACE --net=host bang6:5000/$(SERVICE)_x86:latest /bin/bash + +local_run: build_image + docker run --name rfid_local --rm -it --net=host bang6:5000/$(SERVICE)_x86:latest
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/service/rfid_pn532/nfc-nim/freefare.h Thu Feb 21 09:58:56 2019 -0800 @@ -0,0 +1,578 @@ + +#ifdef C2NIM +#define freefareLib "libfreefare.so.0.0.0" +#define nfcHeader "nfc/nfc.h" +#define freefareHeader "freefare.h" +# mangle uint8_t uint8 +# mangle uint16_t uint16 +# mangle uint32_t uint32 +# mangle int32_t int32 +# mangle ssize_t int32 +# mangle off_t uint32 +# prefix nfc_ +# dynlib freefareLib +# cdecl +# header nfcHeader +# header freefareHeader +#@ +import nfc +@# +#endif + + + +#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, +}; + +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); +enum 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/rfid_pn532/nfc-nim/nfc.h Thu Feb 21 09:58:56 2019 -0800 @@ -0,0 +1,523 @@ +/*- + * 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/> + */ + +#ifdef C2NIM +#define nfcLib "libnfc.so.5.0.1" +# mangle uint8_t uint8 +# mangle uint32_t uint32 +# prefix nfc_ +# dynlib nfcLib +# cdecl +#endif + +/** + * @file nfc.h + * @brief libnfc interface + * + * Provide all usefull functions (API) to handle NFC devices. + */ + + +# 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/rfid_pn532/nim.cfg Thu Feb 21 09:58:56 2019 -0800 @@ -0,0 +1,3 @@ +path="/opt" +cincludes="/usr/include" +threads="on"
--- a/service/rfid_pn532/rfid.nim Tue Feb 19 12:08:22 2019 -0800 +++ b/service/rfid_pn532/rfid.nim Thu Feb 21 09:58:56 2019 -0800 @@ -1,18 +1,36 @@ # make rfid && make build_image_pi # docker pull bang6:5000/rfid_pn532_pi && docker run --rm -it --name rfid --net=host --privileged bang6:5000/rfid_pn532_pi +# i2c keeps dropping. kernel from 1.20180313 to 1.201811112.1 + import nfc-nim/freefare import strformat import strutils import graphserver import tags +import threadpool +import sets -var nn = newNfcDevice() +type CardEvent = object of RootObj + uid: cstring + body: cstring + appeared: bool +type CardEventChannel = Channel[CardEvent] + + +var events: CardEventChannel -while true: - echo "loop" +type TagWatcher = object of RootObj + dev: NfcDevice + nearbyUids: var HashSet[cstring] - nn.forAllTags proc (tag: NfcTag) = +proc initTagWatcher(): var TagWatcher = + result.nearbyUids.init() + +proc oneScan(self: TagWatcher) = + var nearThisPass = initSet[cstring]() + + self.dev.forAllTags proc (tag: NfcTag) = if tag.tagType() == freefare.MIFARE_CLASSIC_1K: echo &"found mifare 1k" else: @@ -21,21 +39,61 @@ echo &" uid {tag.uid()}" + nearThisPass.incl(tag.uid()) + + if tag.uid() in self.nearbyUids: + return + tag.connect() try: echo &" block1: {tag.readBlock(1).escape}" + events.send(CardEvent(uid: tag.uid(), body: tag.readBlock(1), + appeared: true)) #tag.writeBlock(1, toBlock("helloworld")) finally: tag.disconnect() - if false: - var data: freefare.MifareClassicBlock - data[0] = cast[cuchar](5) - data[1] = cast[cuchar](6) - data[2] = cast[cuchar](7) - tag.writeBlock(1, data) + for uid in self.nearbyUids.difference(nearThisPass): + events.send(CardEvent(uid: uid, appeared: false)) + + self.nearbyUids = nearThisPass + + +proc scanTags(self: TagWatcher) = + self.dev = newNfcDevice() + try: + while true: + self.oneScan() + finally: + self.dev.destroy() -nn.destroy() + +proc watchForever*(self: TagWatcher) {.thread.} = + while true: + try: + self.scanTags() + except IOError: + echo "IOError: restarting nfc now" + + +proc tagsToGraph() {.thread.} = + while true: + echo "wait for event" + echo &"ev {events.recv()}" + -let server = newGraphServer(port = 10012) -server.run() +proc main() = + events.open() + + var tw = initTagWatcher() + var thr: Thread[void] + thr.createThread(tw.watchForever) + + var t2: Thread[void] + t2.createThread(tagsToGraph) + + + let server = newGraphServer(port = 10012) + server.run() + +main()
--- a/service/rfid_pn532/tags.nim Tue Feb 19 12:08:22 2019 -0800 +++ b/service/rfid_pn532/tags.nim Thu Feb 21 09:58:56 2019 -0800 @@ -22,7 +22,7 @@ proc check(ret: int, msg: string) = check(ret == 0, &"{msg} ({ret})") -type NfcDevice = ref object of RootObj +type NfcDevice* = ref object of RootObj context: ptr nfc.context dev*: ptr nfc.device @@ -69,7 +69,7 @@ # freefare lib wants to free all the tag memory, so process them in a # callback and don't keep them outside that. -proc forAllTags*(self: var NfcDevice, onTag: (NfcTag) -> void) = +proc forAllTags*(self: NfcDevice, onTag: (NfcTag) -> void) = var ret = getTags(self.dev) var tagList = cast[TagArray](ret) for tagp in tagList: