diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..887c86e --- /dev/null +++ b/.travis.yml @@ -0,0 +1,20 @@ +dist: trusty +sudo: required +language: python +python: + - "3.4" + - "3.5" +# command to install dependencies +before_install: + - sudo apt-get -qq update + - sudo apt-get install -y libnfc5 debhelper python3-all python3-setuptools +install: + - python3 setup.py install + - pip install codecov + - pip install stdeb +# command to run tests +script: + - nosetests --with-coverage +after_success: + - bash <(curl -s https://codecov.io/bash) + - python3 setup.py --command-packages=stdeb.command bdist_deb diff --git a/README b/README.md similarity index 58% rename from README rename to README.md index b8d0b8c..a994a59 100644 --- a/README +++ b/README.md @@ -1,24 +1,37 @@ -Pynfc - Python bindings for libnfc -================================== +# Pynfc - Python bindings for libnfc -Requirements ------------- +## Requirements -libnfc >= 1.7.0 -python >= 2.6 < 3.0 +* libnfc >= 1.7.0 +* python >= 2.6 < 3.5 (tested with 2.7 and 3.5) -Building --------- +## Building The bindings are constructed at runtime using ctypes. Just ensure the library is correctly installed. -Examples --------- +## Instalation -There is an example program included for conducting simple mifare authentication: +``` +sudo apt-get install -y libnfc5 debhelper python3-all python3-setuptools +git clone git@github.com:ppatrik/pynfc.git +cd pynfc +python3 setup.py install +``` + +Now you can import pynfc in your projects + +```py +import pynfc as nfc; +``` -python mifareauth.py +## Examples +### Mifareauth + +There is an example program included for conducting simple mifare authentication: + +```bash +> python mifareauth.py Example output (bulk of the raw hex excised for space): Connect to reader: True @@ -33,11 +46,19 @@ T -> R: A2 7F 33 EE TR == Next(TN, 96): True R -> T: 8F A4 FA D1 T -> R: CA 9E 73 93 +``` This indicates that it successfully authenticated to the requested block. -Documentation -------------- +### NTags +```bash +python -m pynfc.ntag_read +``` + +This will test whether can do password protection and remove the password all together in the end. + + +## Documentation The pynfc bindings should offer an intuitive, yet pythonic way of calling the standard libnfc API. @@ -48,3 +69,4 @@ As much as possible all libnfc commands are mirrored in the created nfc object. Please note whilst this does implement the full range of features found in libnfc, their use in python may be difficult or tricky to use. Pynfc requires much more development and time dedicated to it, before it will be useful as a production tool. +The NTagReadWrite class offers a more Pythonic and high-level interface, geared towards NXP NTags 213, 215 and 216 but should be extendable/generalized to other tag types as well. diff --git a/pynfc/__init__.py b/pynfc/__init__.py new file mode 100644 index 0000000..1886608 --- /dev/null +++ b/pynfc/__init__.py @@ -0,0 +1,2 @@ +from .ntag_read import * +from .pynfc import * diff --git a/src/mifareauth.py b/pynfc/mifareauth.py similarity index 80% rename from src/mifareauth.py rename to pynfc/mifareauth.py index 750424f..26de5f6 100644 --- a/src/mifareauth.py +++ b/pynfc/mifareauth.py @@ -15,19 +15,24 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. import time import logging import ctypes import string import nfc +import binascii + def hex_dump(string): """Dumps data as hexstrings""" return ' '.join(["%0.2X" % ord(x) for x in string]) -### NFC device setup +# NFC device setup + + class NFCReader(object): MC_AUTH_A = 0x60 MC_AUTH_B = 0x61 @@ -54,13 +59,18 @@ def __init__(self, logger): def run(self): """Starts the looping thread""" + # import ipdb; ipdb.set_trace() + # break 119 + # break 240 + # break 208 self.__context = ctypes.pointer(nfc.nfc_context()) nfc.nfc_init(ctypes.byref(self.__context)) loop = True try: self._clean_card() conn_strings = (nfc.nfc_connstring * 10)() - devices_found = nfc.nfc_list_devices(self.__context, conn_strings, 10) + devices_found = nfc.nfc_list_devices( + self.__context, conn_strings, 10) if devices_found >= 1: self.__device = nfc.nfc_open(self.__context, conn_strings[0]) try: @@ -74,7 +84,7 @@ def run(self): time.sleep(5) except (KeyboardInterrupt, SystemExit): loop = False - except IOError, e: + except IOError as e: self.log("Exception: " + str(e)) loop = True # not str(e).startswith("NFC Error whilst polling") # except Exception, e: @@ -104,12 +114,16 @@ def _poll_loop(self): if res < 0: raise IOError("NFC Error whilst polling") elif res >= 1: + print("_poll_loop: res = {}. nt.nti.nai.szUidLen = {}".format(res, nt.nti.nai.szUidLen)) uid = None - if nt.nti.nai.szUidLen == 4: - uid = "".join([chr(nt.nti.nai.abtUid[i]) for i in range(4)]) + uidLen = 7 + if nt.nti.nai.szUidLen == uidLen: + # uid = "".join([chr(nt.nti.nai.abtUid[i]) for i in range(uidLen)]) + uid = bytearray([nt.nti.nai.abtUid[i] for i in range(uidLen)]) + print("_poll_loop: uid = {}".format(binascii.hexlify(uid))) if uid: - if not ((self._card_uid and self._card_present and uid == self._card_uid) and \ - time.mktime(time.gmtime()) <= self._card_last_seen + self.card_timeout): + if not ((self._card_uid and self._card_present and uid == self._card_uid) and + time.mktime(time.gmtime()) <= self._card_last_seen + self.card_timeout): self._setup_device() self.read_card(uid) self._card_uid = uid @@ -128,8 +142,9 @@ def select_card(self): Returns the UID of the card selected """ nt = nfc.nfc_target() - _ = nfc.nfc_initiator_select_passive_target(self.__device, self.__modulations[0], None, 0, ctypes.byref(nt)) - uid = "".join([chr(nt.nti.nai.abtUid[i]) for i in range(nt.nti.nai.szUidLen)]) + _ = nfc.nfc_initiator_select_passive_target( + self.__device, self.__modulations[0], None, 0, ctypes.byref(nt)) + uid = bytearray([nt.nti.nai.abtUid[i] for i in range(nt.nti.nai.szUidLen)]) return uid def _setup_device(self): @@ -168,7 +183,8 @@ def __write_block(self, block, data): if nfc.nfc_device_set_property_bool(self.__device, nfc.NP_EASY_FRAMING, True) < 0: raise Exception("Error setting Easy Framing property") if len(data) > 16: - raise ValueError("Data value to be written cannot be more than 16 characters.") + raise ValueError( + "Data value to be written cannot be more than 16 characters.") abttx = (ctypes.c_uint8 * 18)() abttx[0] = self.MC_WRITE abttx[1] = block @@ -178,7 +194,7 @@ def __write_block(self, block, data): return nfc.nfc_initiator_transceive_bytes(self.__device, ctypes.pointer(abttx), len(abttx), ctypes.pointer(abtrx), len(abtrx), 0) - def _authenticate(self, block, uid, key = "\xff\xff\xff\xff\xff\xff", use_b_key = False): + def _authenticate(self, block, uid, key="\xff\xff\xff\xff\xff\xff", use_b_key=False): """Authenticates to a particular block using a specified key""" if nfc.nfc_device_set_property_bool(self.__device, nfc.NP_EASY_FRAMING, True) < 0: raise Exception("Error setting Easy Framing property") @@ -186,26 +202,27 @@ def _authenticate(self, block, uid, key = "\xff\xff\xff\xff\xff\xff", use_b_key abttx[0] = self.MC_AUTH_A if not use_b_key else self.MC_AUTH_B abttx[1] = block for i in range(6): - abttx[i + 2] = ord(key[i]) + abttx[i + 2] = key[i] for i in range(4): - abttx[i + 8] = ord(uid[i]) + abttx[i + 8] = uid[i] abtrx = (ctypes.c_uint8 * 250)() - return nfc.nfc_initiator_transceive_bytes(self.__device, ctypes.pointer(abttx), len(abttx), + transceived = nfc.nfc_initiator_transceive_bytes(self.__device, ctypes.pointer(abttx), len(abttx), ctypes.pointer(abtrx), len(abtrx), 0) + return transceived - def auth_and_read(self, block, uid, key = "\xff\xff\xff\xff\xff\xff"): + def auth_and_read(self, block, uid, key="\xff\xff\xff\xff\xff\xff"): """Authenticates and then reads a block Returns '' if the authentication failed """ # Reselect the card so that we can reauthenticate - self.select_card() + # self.select_card() res = self._authenticate(block, uid, key) if res >= 0: return self._read_block(block) return '' - def auth_and_write(self, block, uid, data, key = "\xff\xff\xff\xff\xff\xff"): + def auth_and_write(self, block, uid, data, key="\xff\xff\xff\xff\xff\xff"): """Authenticates and then writes a block """ @@ -217,14 +234,19 @@ def auth_and_write(self, block, uid, data, key = "\xff\xff\xff\xff\xff\xff"): def read_card(self, uid): """Takes a uid, reads the card and return data for use in writing the card""" - key = "\xff\xff\xff\xff\xff\xff" - print "Reading card", uid.encode("hex") + key = bytearray([0xff] * 6) + # print("Reading card", uid.encode("hex")) self._card_uid = self.select_card() self._authenticate(0x00, uid, key) block = 0 + + all_data = [] for block in range(64): data = self.auth_and_read(block, uid, key) - print block, data.encode("hex"), "".join([ x if x in string.printable else "." for x in data]) + # print(block, data.encode("hex"), "".join( + # [x if x in string.printable else "." for x in data])) + all_data += [data] + print("read_card: '{}'".format(''.join(all_data))) def write_card(self, uid, data): """Accepts data of the recently read card with UID uid, and writes any changes necessary to it""" diff --git a/pynfc/ntag_read.py b/pynfc/ntag_read.py new file mode 100755 index 0000000..52fd9dc --- /dev/null +++ b/pynfc/ntag_read.py @@ -0,0 +1,690 @@ +#! /usr/bin/env python3 + +from . import pynfc as nfc +import ctypes +import binascii +import enum +import logging +# from builtins import bytes +import math + +def bin(i): + return "0b{0:08b}".format(i) + +class TagType(object): + NTAG_213 = {"name":"NTAG_213", "user_memory_start": 4, "user_memory_end": 39} # 4 is the first page of the user memory, 39 is the last + NTAG_215 = {"name":"NTAG_215", "user_memory_start": 4, "user_memory_end": 129} # 4 is the first page of the user memory, 129 is the last + NTAG_216 = {"name":"NTAG_216", "user_memory_start": 4, "user_memory_end": 225} # 4 is the first page of the user memory, 255 is the last + +capability_byte_type_map = {0x12: TagType.NTAG_213, + 0x3e: TagType.NTAG_215, + 0x6D: TagType.NTAG_216} + + +class UnknownTagTypeException(Exception): + def __init__(self, message, capability_byte): + super(UnknownTagTypeException, self).__init__(message) + + self.capability_byte = capability_byte + + +SET_CONNSTRING = 'You may need to $ export LIBNFC_DEFAULT_DEVICE="pn532_uart:/dev/ttyUSB0" ' \ + 'or edit /etc/nfc/libnfc.conf and set device.connstring in case of a failure' + +class Commands(enum.Enum): + MC_GET_VERSION = 0x60 + MC_READ = 0x30 + MC_FAST_READ = 0x3a + MC_WRITE = 0xA2 + MC_COMPATIBILITY_WRITE = 0xA0 + MC_READ_CNT = 0x39 + MC_PWD_AUTH = 0x1b + MC_READ_SIG = 0x3c + + +class NTagInfo(object): + BYTES_PER_PAGE = 4 + + +class NTagReadWrite(object): + """ + Allows to read/write to an NTag 21x device. + Tested with a Adafruit PN532 breakout board connected via serial over an FTDI cable + """ + card_timeout = 10 + + def __init__(self, logger=logging.getLogger("ntag_read_write")): + """Initialize a ReadWrite object + :param logger: logging.Logger""" + self.logger = logger + + mods = [(nfc.NMT_ISO14443A, nfc.NBR_106)] + self.modulations = (nfc.nfc_modulation * len(mods))() + for i in range(len(mods)): + self.modulations[i].nmt = mods[i][0] + self.modulations[i].nbr = mods[i][1] + + self.open() + + def open(self): + """Open a connection with an NTag. Initializes pynfc context, the device. + Call this after a close()""" + self.context = ctypes.pointer(nfc.nfc_context()) + self.logger.info("Created NFC library context") + nfc.nfc_init(ctypes.byref(self.context)) + self.logger.info("Initializing NFC library") + + conn_strings = (nfc.nfc_connstring * 10)() + devices_found = nfc.nfc_list_devices(self.context, conn_strings, 10) + # import ipdb; ipdb.set_trace() + self.logger.info("{} devices found".format(devices_found)) + + if not devices_found: + self.logger.error("No devices found") + raise IOError("No devices found. " + SET_CONNSTRING) + else: + self.logger.info("Using conn_string[0] = {} to get a device. {}".format(conn_strings[0].value, SET_CONNSTRING)) + + self.device = nfc.nfc_open(self.context, conn_strings[0]) + + try: + _ = self.device.contents # This fails with a ValueError in case the device could not be opened + + self.logger.info("Opened device {}, initializing NFC initiator".format(self.device)) + _ = nfc.nfc_initiator_init(self.device) + self.logger.info("NFC initiator initialized") + except ValueError as error: + raise IOError("Could not open device on connstring {conn}: {err}".format(conn=conn_strings[0].value, err=error)) + + def list_targets(self, max_targets=10): + """ + List the targets detected by the device + :param max_targets: amount of targets to maximally find + :return: list of bytes with the found UIDs + """ + targets = (nfc.nfc_target * max_targets)() + count = nfc.nfc_initiator_list_passive_targets(self.device, self.modulations[0], targets, len(targets)) + + uids = [] + for index in range(count): + uidLen = 7 + uid = bytes([targets[index].nti.nai.abtUid[i] for i in range(uidLen)]) + uids += [uid] + + return uids + + def count_targets(self): + """ + Count the amount of targets near the device + :return: number of targets near + """ + nt = nfc.nfc_target() + + count = nfc.nfc_initiator_poll_target(self.device, self.modulations, len(self.modulations), 1, 1, ctypes.byref(nt)) + + return max(count, 0) # Count goes to -90 if there are no targets somehow + + def setup_target(self): + """ + Find a target if there is one and returns the target's UID + :return: UID of the found target + :rtype bytes + """ + nt = nfc.nfc_target() + + res = nfc.nfc_initiator_poll_target(self.device, self.modulations, len(self.modulations), 10, 2, ctypes.byref(nt)) + + if res < 0: + raise IOError("NFC Error whilst polling") + + uidLen = 7 + uid = bytes([nt.nti.nai.abtUid[i] for i in range(uidLen)]) + + # setup device + if nfc.nfc_device_set_property_bool(self.device, nfc.NP_ACTIVATE_CRYPTO1, True) < 0: + raise Exception("Error setting Crypto1 enabled") + if nfc.nfc_device_set_property_bool(self.device, nfc.NP_INFINITE_SELECT, False) < 0: + raise Exception("Error setting Single Select option") + if nfc.nfc_device_set_property_bool(self.device, nfc.NP_AUTO_ISO14443_4, False) < 0: + raise Exception("Error setting No Auto ISO14443-A jiggery pokery") + if nfc.nfc_device_set_property_bool(self.device, nfc.NP_HANDLE_PARITY, True) < 0: + raise Exception("Error setting Easy Framing property") + + return uid + + def set_easy_framing(self, enable=True): + if nfc.nfc_device_set_property_bool(self.device, nfc.NP_EASY_FRAMING, enable) < 0: + raise Exception("Error setting Easy Framing property") + + def transceive_bytes(self, transmission, receive_length): + """ + Send the bytes in the send + :param device: The device *via* which to transmit the bytes + :param transmission: Data or command to send: + :type transmission bytes + :param receive_length: how many bytes to receive? + :type receive_length int + :return: whatever was received back. Should be nothing actually + """ + + abttx = (ctypes.c_uint8 * len(transmission))() # command length + for index, byte in enumerate(transmission): + abttx[index] = byte + + abtrx = (ctypes.c_uint8 * receive_length)() # 16 is the minimum + res = nfc.nfc_initiator_transceive_bytes(self.device, + ctypes.pointer(abttx), len(abttx), + ctypes.pointer(abtrx), len(abtrx), + 0) + if res < 0: + raise IOError("Error reading data") + + data = bytes(abtrx[:res]) + return data + + def read_page(self, page): + """Read the bytes at the given page""" + received_data = self.transceive_bytes(bytes([int(Commands.MC_READ.value), page]), 16) + data = received_data[:NTagInfo.BYTES_PER_PAGE] # Only the first 4 bytes as a page is 4 bytes + return data + + def determine_tag_type(self): + """ + According to the NTAG213/215/216 specification, the Capability Container byte 2 contains the memory size of the tag + This is written during tag production. The capability Container is on page 3 + The exact definitions are stated in table 4 of the datasheet: + + Table 4. NDEF memory size + IC | Value in byte 2 | NDEF memory size + --------+-----------------+----------------- + NTAG213 | 12h | 144 byte + NTAG215 | 3Eh | 496 byte + NTAG216 | 6Dh | 872 byte + """ + uid = self.setup_target() + + self.set_easy_framing() + + capability_container = self.read_page(3) + capability_byte = capability_container[2] + + try: + tag_type = capability_byte_type_map[capability_byte] + + return tag_type, uid + except KeyError as key_error: + raise UnknownTagTypeException("Tag has capability byte value {byte}, " + "which is unknown. Known keys are {keys}".format(byte=capability_byte, + keys=list(capability_byte_type_map.keys())), + capability_byte) + + def read_user_memory(self, tag_type): + """Read the complete user memory, ie. the actual content of the tag. + Configuration bytes surrounding the user memory is omitted""" + start = tag_type['user_memory_start'] + end = tag_type['user_memory_end'] + 1 # + 1 because the Python range generator excluded the last value + + user_memory = [] + + for page in range(start, end): + user_memory += list(self.read_page(page)) + + return bytes(user_memory) + + def fast_read_user_memory(self, tag_type): + """Read the complete user memory, ie. the actual content of the tag. + Configuration bytes surrounding the user memory is omitted""" + start_page = tag_type['user_memory_start'] + end_page = tag_type['user_memory_end'] + 1 # + 1 because the Python range generator excluded the last value + + user_memory = [] + for page in range(start_page, end_page, 4): + received_data = self.transceive_bytes(bytes([int(Commands.MC_READ.value), page]), 4*NTagInfo.BYTES_PER_PAGE) + data = received_data[:] # Only the first 4 bytes as a page is 4 bytes + user_memory += data + + return bytes(user_memory[:(end_page - start_page)*NTagInfo.BYTES_PER_PAGE]) # As we take 4 page steps, the last bytes and pages are out of range (and thus 0x00) + + def read_ndef_message_bytes(self, tag_type): + first_page = self.read_page(tag_type["user_memory_start"]) + tag_field = first_page[0] + + # 0x03 indicates NDEF message. See NFC Forum spec "Type 2 Tag Operation Specification" table 2 for others + if tag_field == 0x03: + length_format = first_page[1] + if length_format == 0xFF: + length = int.from_bytes(first_page[2:4], byteorder='big') + else: + length = length_format + + user_memory = [] + start = tag_type["user_memory_start"] + 1 + end = tag_type["user_memory_start"] + 1 + math.ceil(length/4) + for page in range(start, end): + user_memory += list(self.read_page(page)) + return bytes(user_memory) + else: + raise ValueError("Tag does not contain NDEF message. Tag indicates {tag} in first byte".format(tag=tag_field)) + + def write_block(self, block, data): + """Writes a block of data to an NTag + Raises an exception on error + """ + self.set_easy_framing(True) + + if len(data) > 16: + raise ValueError( "Data value to be written cannot be more than 16 bytes.") + + abttx = bytearray(18) # 18 is 1 byte for command, 1 byte for block/page address, 16 for actual data + abttx[0] = int(Commands.MC_COMPATIBILITY_WRITE.value) + abttx[1] = block + for index, byte in enumerate(data): + abttx[index + 2] = byte + + recv = self.transceive_bytes(bytes(abttx), 250) + return recv + + def write_page(self, page, data, debug=False): + if debug: + print("Write page {:3}: {}".format(page, data)) + if len(data) > NTagInfo.BYTES_PER_PAGE: + raise ValueError( "Data value to be written cannot be more than 4 bytes.") + return self.write_block(page, data) + + def write_user_memory(self, data, tag_type, debug=False): + """Read the complete user memory, ie. the actual content of the tag. + Configuration bytes surrounding the user memory are omitted, given the correct tag type. + Otherwise, we cannot know where user memory start and ends""" + start = tag_type['user_memory_start'] + end = tag_type['user_memory_end'] + 1 # + 1 because the Python range generator excluded the last value + mem_size = (end-start) + + page_contents = [data[i:i+NTagInfo.BYTES_PER_PAGE] for i in range(0, len(data), NTagInfo.BYTES_PER_PAGE)] + content_size = len(page_contents) + + if content_size > mem_size: + raise ValueError("{type} user memory ({mem_size} 4-byte pages) too small for content ({content_size} 4-byte pages)". + format(type=tag_type, mem_size=mem_size, content_size=content_size)) + + self.logger.info("Writing {} pages".format(len(page_contents))) + for page, content in zip(range(start, end), page_contents): + self.write_page(page, content, debug) + + @staticmethod + def _make_tag_length_header_for_value(data): + """Any value written to a NFC Forum Type 2 Tag (which NTag's are), + needs to be packed in a TLV structure of 3 fields, indicating Tag (type), Length, Value + - The Tag-field will indicate those bytes must be interpreted as an NDEF message. + - The Length is simply the number of message-bytes. + - The Value will be the bytes of the message, in case of an NDEF message. + + There are various Tags possible, value 0x03 indicates an NDEF message. + See Table 2 of the NFC Forum spec "Type 2 Tag Operation Specification", NFCForum-TS-Type-2-Tag_1.1 + for the other tag values. + + The lengths can be in 2 formats: one byte and three consecutive bytes. + - One byte is for length between 0x00 and 0xFE length + - Three consecutive bytes is for lengths between 0x00FF and 0xFFFE. + The first byte of the length-field is then set to 0xFF + """ + tag = 0x03 # NDEF message + + length = len(data) + if length <= 0xFE: + return bytes([tag, length]) + elif length <= 0xFFFE: + length_bytes = length.to_bytes(2, byteorder='big') + return bytes([tag, 0xFF]) + length_bytes + else: + raise ValueError("Length {len} of data cannot be encoded according to " + "NFC Forum spec 'Type 2 Tag Operation Specification'".format(len=length)) + + def write_ndef_message_bytes(self, message_bytes, *args, **kwargs): + tag_content = self._make_tag_length_header_for_value(message_bytes) + message_bytes + + self.write_user_memory(tag_content, *args, **kwargs) + + def authenticate(self, password, acknowledge=b'\x00\x00'): + """After issuing this command correctly, the tag goes into the Authenticated-state, + during which the protected bytes can be written + :param password the 4-byte password with which the tag is protected + :type password bytes + :param acknowledge the 2 Password ACKnowledge bytes. If these are received, the password was correct + :returns whether the password was correct or not + :rtype bool""" + + # With easy framing enabled, there will be an "Application level error". + # With easy-framing disabled, 'Chip error: "Timeout" (01), returned error: "RF Transmission Error" (-20))' + # The PWD_AUTH command can have a timeout of max. 5ms. + # With the timeout in tranceive_bytes set to: + # 0ms: "Chip error: "Timeout" (01), returned error: "RF Transmission Error" (-20))", + # 1ms, "libnfc.bus.uart Timeout!" even before authenticating, its simply too short + # 5ms, "libnfc.bus.uart Timeout!" even before authenticating, its simply too short + # 10ms, "libnfc.bus.uart Timeout!" + # 100ms: "Chip error: "Timeout" (01), returned error: "RF Transmission Error" (-20))", + # Which would indicate the wait for the UART is long enough (also the default). + # But, this sets the timeout for the communication between host and PN532, not between PN532 and NTag. + # On the other hand, this 5ms is the same for reading, to there should not be a need to set a different timeout + # for PN532-to-NTag communication. + self.set_easy_framing(False) + + if len(password) != 4: + raise ValueError( "Password must be 4 bytes") + + if len(acknowledge) != 2: + raise ValueError( "Password ACKnowledge must be 2 bytes") + + cmd = int(Commands.MC_PWD_AUTH.value) + + ctypes_key = (ctypes.c_uint8 * len(password))() # command length + for index, byte in enumerate(password): + ctypes_key[index] = byte + + crc = (ctypes.c_uint8 * 2)() + + nfc.iso14443a_crc(ctypes.pointer(ctypes_key), len(password), ctypes.pointer(crc)) + + abttx = bytes([cmd]) + password + + recv = self.transceive_bytes(bytes(abttx), 16) + + return recv == acknowledge + + def enable_uid_mirror(self, tag_type, page, byte_in_page): + """ + An NTAG 21x has the option to mirror its UID to a place in the user memory. + This can be useful for signatures, which can then sign over something unique tied to the tag. + + The mirror configuration page consists of 4 bytes: + - CFG0: MIRROR, rfui, MIRROR_PAGE, AUTH0 + + The MIRROR-byte consists of some bitfields: + - 7,6: MIRROR_CONF: Set to 01 for UID ASCII Mirror + - 5,4: MIRROR_BYTE: The 2 bits define the byte position within the page defined by the MIRROR_PAGE byte (beginning of ASCII mirror) + - 3 : RFUI + - 2 : STRG_MOD_EN: STRG MOD_EN defines the modulation mode. 0 disables, 1 enables + - 1,0: RFUI + + The AUTH0-byte defines the page address from which the password verification is required. + This is set through the set_password-method. + + :param tag_type: Which type of tag are we dealing with? Used to figure out where the config pages are + :param page: On which page must the UID be mirrored? + :type page int + :param byte_in_page: On which byte in that page must the UID be mirrored. + :type byte_in_page int + :return: + """ + cfg0_page = tag_type['user_memory_end'] + 2 + cfg0_orig = self.read_page(cfg0_page) + + + mirror = 0b01000000 + mirror |= (byte_in_page) << 4 + + # MIRROR rfui MIRROR_PAGE AUTH0 + cfg0 = [mirror, 0b00000000, page, cfg0_orig[3]] + + self.write_page(cfg0_page, cfg0) + + def check_uid_mirror(self, tag_type): + """Return to which page and byte_in_page the UID mirroring is configured. + If it is not enabled, return None + + :param tag_type: Which type of tag are we dealing with? Used to figure out where the config pages are + :returns tuple (mirror_page, byte_in_page) in case UID mirroring is enabled, None if not enabled.""" + cfg0_page = tag_type['user_memory_end'] + 2 + + config_page = self.read_page(cfg0_page) + mirror, _, mirror_page, auth0 = config_page + + mirroring_enabled = mirror & 0b01000000 > 0 + + mirror_byte_mask = 0b00110000 + byte_in_page = (mirror & mirror_byte_mask) >> 4 + + if mirroring_enabled: + return mirror_page, byte_in_page + else: + return None + + def set_password(self, tag_type, password=b'\xff\xff\xff\xff', acknowledge=b'\x00\x00', max_attempts=None, + also_read=False, auth_from=0xFF, lock_config=False, enable_counter=False, protect_counter=False): + """ + + The AUTH0-byte (byte 3 on page 0x29/0x83/0xE3 for resp Ntag 213,215,216) defines the page address from which the password verification is required. + 0xFF effectively disables it + + The ACCESS-byte (byte 0 on page 0x2A/0x84/0xE4 for resp Ntag 213,215,216) consists of some bitfields: + - 7: PROT: 0 = write access is password protected, 1 = read and write are is password protected + - 6: CGFLCK: Write locking bit for the user configuration + - 5: RFUI (reserved for future use) + - 4: NFC_CNT_EN: NFC counter configuration + - 3: NFC_CNT_PWD_PROT: NFC counter password protection + - 2,1,0: AUTHLIM: Limitation of negative password verification attempts + + The PACK-bytes in the PACK-page have a 16-bit password acknowledge used during the password verification process + + Password protected is needed to prevent the user from accidentally writing the tag with a NFC enabled phone. + With a password, writing is still possible but needs to be deliberate. + The password must thus protect writing only, but for the whole tag so the start page in AUTH0 must be 0 + There's no need to lock the user configuration (i.e. these bytes generated here), so CGFLCK=0 + """ + cfg0_page = tag_type['user_memory_end'] + 2 + cfg1_page = cfg0_page + 1 + pwd_page = cfg1_page + 1 + pack_page = pwd_page + 1 + + cfg0 = bytearray(self.read_page(cfg0_page)) + # [MIRROR, rfui, MIRROR_PAGE, AUTH0], so we overwrite + cfg0[3] = auth_from + + access = 0b00000000 + + prot = 0b10000000 if also_read else 0b00000000 + access |= prot + + cfglck = 0b01000000 if lock_config else 0b00000000 + access |= cfglck + + nfc_cnt_en = 0b00010000 if enable_counter else 0b00000000 + access |= nfc_cnt_en + + nfc_cnt_pwd_prot = 0b00001000 if protect_counter else 0b00000000 + access |= nfc_cnt_pwd_prot + + if max_attempts and max_attempts > 7: + raise ValueError("Max_attempts can be set to 7 at most (0b111) ") + + authlim = max_attempts if max_attempts != None else 0b000 # 3 bit field, at the end of the byte so no shifting is needed + access |= authlim + + # ACCESS, rfui, rfui, rfui + cfg1 = [access, 0b00000000, 0b00000000, 0b00000000] + + # Password + pwd = password + + # [PACK, PACK, rfui, rfui + pack = acknowledge + bytes([0b00000000, 0b00000000]) # unused + + self.write_page(pack_page, pack) + self.write_page(pwd_page, pwd) + self.write_page(cfg1_page, cfg1) + self.write_page(cfg0_page, cfg0) + + def close(self): + """Close connection to the target NTag and de-initialize the pynfc context. + After a failed read/write due to password protection, call close(), then open() and then do the authenticate() call""" + nfc.nfc_idle(self.device) + nfc.nfc_close(self.device) + nfc.nfc_exit(self.context) + + +def test_passwords(): + # Below, we'll test and demonstrate the behavior of password protection against writing + # The tag is supposed to start with no password protection configured, as the factory default is. + # This is also how the tag should end, eventually + # + # 1: The test starts by writing to a page, which should be OK because there is not password protection. + # 2: This is verified by reading the data again + # + # 3: Then, we set a password, after which we close the connection so make sure we start over with the tag in its idle state + # 3a: Check that we can still read + # + # 4: Without authenticating with the password, we try writing again. This should fail, as we are not authenticated + # 5: We verify that the write was unsuccessful: the page should still have its old content + # + # 6: We authenticate ourselves + # + # 7: And try to write again, which should be allowed since we are now authenticated + # 8: Again, this is verified + # + # 9: Lastly, we clear the password and the protection to their default states, so the test is repeatable. + # 1 + try: + read_writer.write_page(testpage, bytes([0xff, 0xff, 0xff, 0xff])) # With no password set, this page is writable + print(" OK 1: Can write page when no password set") + except OSError as e: + print("ERROR 1: Could not write test page: {err}".format(err=e)) + exit() + + # 2 + try: + current_test_content = read_writer.read_page(testpage) + if current_test_content != bytes([0xff, 0xff, 0xff, 0xff]): + print("ERROR: The test page was not written") + print(" OK 2: Can read page when no password set") + except OSError as e: + print("ERROR 2: Could not read test page: {err}".format(err=e)) + exit() + + # 3 + try: + read_writer.set_password(tt, password=password, acknowledge=ack, auth_from=testpage) + print(" OK 3: password protection set") + except OSError as e: + print("ERROR 3: Could not set a password") + + # Close and reopen this connection, so we definitely need to re-authenticate + read_writer.close() + read_writer.open() + read_writer.setup_target() + # 3a + try: + current_test_content = read_writer.read_page(testpage) + if current_test_content != bytes([0xff, 0xff, 0xff, 0xff]): + print("ERROR 3b: The test page was changed after setting password but before writing") + print(" OK 3b: Can read page after setting password") + + except OSError as e: + print("ERROR 3b: Could not read test page after setting password: {err}".format(err=e)) + exit() + + # 4 + try: + read_writer.write_page(testpage, bytes( + [0x00, 0x00, 0x00, 0x00])) # After setting the password protection, the page cannot be written anymore + except OSError as e: + print( + " OK 4: Could (correctly) not write test page, because we just set a password and now this page is password locked: {err}".format( + err=e)) + + # 5 + try: + current_test_content = read_writer.read_page(testpage) + if current_test_content != bytes([0xff, 0xff, 0xff, 0xff]): + print("ERROR 5: The test page was changed while password protected and not authenticated") + if current_test_content == bytes([0x00, 0x00, 0x00, 0x00]): + print("\tThe test page was overwritten with what we wrote without authentication") + else: + print(" OK 5: the test page could not be written after a password was required and not authenticated") + except OSError as e: + print("ERROR 5: Could not read test page: {err}".format(err=e)) + # exit() + # Close and reopen this connection, so we definitely need to re-authenticate + read_writer.close() + read_writer.open() + read_writer.setup_target() + # 6 + try: + read_writer.authenticate(password=password, acknowledge=ack) + print(" OK 6: authentication successful") + except OSError as e: + print("ERROR 6: Could not authenticate: {err}".format(err=e)) + + # 7 + try: + read_writer.write_page(testpage, + bytes([0xaa, 0xaa, 0xaa, 0xaa])) # After authenticating ourselves, its writeable again + print(" OK 7: write after authentication successful") + except OSError as e: + print("ERROR 7: Could not write test page: {err}".format(err=e)) + + # 8 + try: + current_test_content = read_writer.read_page(testpage) + if current_test_content != bytes([0xaa, 0xaa, 0xaa, 0xaa]): + print("ERROR 8: The test page was not written after authentication") + print(" OK 8: read after writing with authentication successful") + except OSError as e: + print("ERROR 8: Could not read test page: {err}".format(err=e)) + exit() + + # 9 + try: + read_writer.set_password(tt) # Default arguments set to default state, clearing the password + print(" OK 9: password cleared") + except OSError as e: + print("ERROR 9: Could not clear password") + + # import ipdb; ipdb.set_trace() + read_writer.close() + del read_writer + print("Test completed") + +import time, contextlib +@contextlib.contextmanager +def stopwatch(label=None): + start = time.time() + yield + end = time.time() + dt = end - start + if label: + print("{} takes ".format(label), end="") + print(dt) + + +def test_fast_read(): + um_norm = read_writer.read_user_memory(tt) + um_fast = read_writer.fast_read_user_memory(tt) + assert um_norm in um_fast + assert len(um_norm) == len(um_fast) + assert um_norm == um_fast + + +if __name__ == "__main__": + logger = logging.getLogger("ntag_read_write") + + read_writer = NTagReadWrite(logger) + + uids = read_writer.list_targets() + if len(uids) > 1: + print("Found {count} uids: {uids}. Please remove all but one from the device".format(count=len(uids), uids=uids)) + exit(-1) + + tt = TagType.NTAG_216 + testpage = 200 # Must be available on the chosen tag type. + + password = bytes([1, 2, 3, 4]) + ack = bytes([0xaa, 0xaa]) + + + uid = read_writer.setup_target() + print("uid = {}".format(binascii.hexlify(uid))) + + read_writer.set_easy_framing() + + # test_passwords() + + test_fast_read() \ No newline at end of file diff --git a/src/nfc.py b/pynfc/pynfc.py similarity index 75% rename from src/nfc.py rename to pynfc/pynfc.py index e1d5e22..3e61c4d 100644 --- a/src/nfc.py +++ b/pynfc/pynfc.py @@ -10,7 +10,9 @@ # Begin preamble -import ctypes, os, sys +import ctypes +import os +import sys from ctypes import cast, c_int, c_int16, c_int32, c_uint8, c_uint32, c_int64, c_char, c_char_p, c_size_t, c_void_p, sizeof, Structure, Union, CFUNCTYPE _int_types = (c_int16, c_int32) @@ -25,12 +27,14 @@ del t del _int_types + class c_void(Structure): # c_void_p is a buggy return type, converting to int, so # POINTER(None) == c_void_p is actually written as # POINTER(c_void), so it can be treated as a real pointer. _fields_ = [('dummy', c_int)] + def POINTER(obj): p = ctypes.POINTER(obj) @@ -46,20 +50,29 @@ def from_param(cls, x): return p + class UserString: + def __init__(self, seq): - if isinstance(seq, basestring): + if isinstance(seq, str): self.data = seq elif isinstance(seq, UserString): self.data = seq.data[:] else: self.data = str(seq) + def __str__(self): return str(self.data) + def __repr__(self): return repr(self.data) + def __int__(self): return int(self.data) - def __long__(self): return long(self.data) + + def __long__(self): return int(self.data) + def __float__(self): return float(self.data) + def __complex__(self): return complex(self.data) + def __hash__(self): return hash(self.data) def __cmp__(self, string): @@ -67,40 +80,50 @@ def __cmp__(self, string): return cmp(self.data, string.data) else: return cmp(self.data, string) + def __contains__(self, char): return char in self.data def __len__(self): return len(self.data) + def __getitem__(self, index): return self.__class__(self.data[index]) + def __getslice__(self, start, end): - start = max(start, 0); end = max(end, 0) + start = max(start, 0) + end = max(end, 0) return self.__class__(self.data[start:end]) def __add__(self, other): if isinstance(other, UserString): return self.__class__(self.data + other.data) - elif isinstance(other, basestring): + elif isinstance(other, str): return self.__class__(self.data + other) else: return self.__class__(self.data + str(other)) + def __radd__(self, other): - if isinstance(other, basestring): + if isinstance(other, str): return self.__class__(other + self.data) else: return self.__class__(str(other) + self.data) + def __mul__(self, n): return self.__class__(self.data * n) __rmul__ = __mul__ + def __mod__(self, args): return self.__class__(self.data % args) # the following methods are defined in alphabetical order: def capitalize(self): return self.__class__(self.data.capitalize()) + def center(self, width, *args): return self.__class__(self.data.center(width, *args)) - def count(self, sub, start = 0, end = sys.maxint): + + def count(self, sub, start=0, end=sys.maxsize): return self.data.count(sub, start, end) - def decode(self, encoding = None, errors = None): # XXX improve this? + + def decode(self, encoding=None, errors=None): # XXX improve this? if encoding: if errors: return self.__class__(self.data.decode(encoding, errors)) @@ -108,7 +131,8 @@ def decode(self, encoding = None, errors = None): # XXX improve this? return self.__class__(self.data.decode(encoding)) else: return self.__class__(self.data.decode()) - def encode(self, encoding = None, errors = None): # XXX improve this? + + def encode(self, encoding=None, errors=None): # XXX improve this? if encoding: if errors: return self.__class__(self.data.encode(encoding, errors)) @@ -116,57 +140,97 @@ def encode(self, encoding = None, errors = None): # XXX improve this? return self.__class__(self.data.encode(encoding)) else: return self.__class__(self.data.encode()) - def endswith(self, suffix, start = 0, end = sys.maxint): + + def endswith(self, suffix, start=0, end=sys.maxsize): return self.data.endswith(suffix, start, end) - def expandtabs(self, tabsize = 8): + + def expandtabs(self, tabsize=8): return self.__class__(self.data.expandtabs(tabsize)) - def find(self, sub, start = 0, end = sys.maxint): + + def find(self, sub, start=0, end=sys.maxsize): return self.data.find(sub, start, end) - def index(self, sub, start = 0, end = sys.maxint): + + def index(self, sub, start=0, end=sys.maxsize): return self.data.index(sub, start, end) + def isalpha(self): return self.data.isalpha() + def isalnum(self): return self.data.isalnum() - def isdecimal(self): return self.data.isdecimal() #pylint: disable-msg=E1103 + + def isdecimal( + self): return self.data.isdecimal() # pylint: disable-msg=E1103 + def isdigit(self): return self.data.isdigit() + def islower(self): return self.data.islower() - def isnumeric(self): return self.data.isnumeric() #pylint: disable-msg=E1103 + + def isnumeric( + self): return self.data.isnumeric() # pylint: disable-msg=E1103 + def isspace(self): return self.data.isspace() + def istitle(self): return self.data.istitle() + def isupper(self): return self.data.isupper() + def join(self, seq): return self.data.join(seq) + def ljust(self, width, *args): return self.__class__(self.data.ljust(width, *args)) + def lower(self): return self.__class__(self.data.lower()) - def lstrip(self, chars = None): return self.__class__(self.data.lstrip(chars)) + + def lstrip(self, chars=None): return self.__class__( + self.data.lstrip(chars)) + def partition(self, sep): return self.data.partition(sep) - def replace(self, old, new, maxsplit = -1): + + def replace(self, old, new, maxsplit=-1): return self.__class__(self.data.replace(old, new, maxsplit)) - def rfind(self, sub, start = 0, end = sys.maxint): + + def rfind(self, sub, start=0, end=sys.maxsize): return self.data.rfind(sub, start, end) - def rindex(self, sub, start = 0, end = sys.maxint): + + def rindex(self, sub, start=0, end=sys.maxsize): return self.data.rindex(sub, start, end) + def rjust(self, width, *args): return self.__class__(self.data.rjust(width, *args)) + def rpartition(self, sep): return self.data.rpartition(sep) - def rstrip(self, chars = None): return self.__class__(self.data.rstrip(chars)) - def split(self, sep = None, maxsplit = -1): + + def rstrip(self, chars=None): return self.__class__( + self.data.rstrip(chars)) + + def split(self, sep=None, maxsplit=-1): return self.data.split(sep, maxsplit) - def rsplit(self, sep = None, maxsplit = -1): + + def rsplit(self, sep=None, maxsplit=-1): return self.data.rsplit(sep, maxsplit) - def splitlines(self, keepends = 0): return self.data.splitlines(keepends) - def startswith(self, prefix, start = 0, end = sys.maxint): + + def splitlines(self, keepends=0): return self.data.splitlines(keepends) + + def startswith(self, prefix, start=0, end=sys.maxsize): return self.data.startswith(prefix, start, end) - def strip(self, chars = None): return self.__class__(self.data.strip(chars)) + + def strip(self, chars=None): return self.__class__(self.data.strip(chars)) + def swapcase(self): return self.__class__(self.data.swapcase()) + def title(self): return self.__class__(self.data.title()) + def translate(self, *args): return self.__class__(self.data.translate(*args)) + def upper(self): return self.__class__(self.data.upper()) + def zfill(self, width): return self.__class__(self.data.zfill(width)) + class MutableString(UserString): + """mutable string objects Python strings are immutable objects. This has the advantage, that @@ -181,52 +245,66 @@ class MutableString(UserString): errors that would be very hard to track down. A faster and better solution is to rewrite your program using lists.""" - def __init__(self, string = ""): + + def __init__(self, string=""): self.data = string + def __hash__(self): raise TypeError("unhashable type (it is mutable)") + def __setitem__(self, index, sub): if index < 0: index += len(self.data) - if index < 0 or index >= len(self.data): raise IndexError + if index < 0 or index >= len(self.data): + raise IndexError self.data = self.data[:index] + sub + self.data[index + 1:] + def __delitem__(self, index): if index < 0: index += len(self.data) - if index < 0 or index >= len(self.data): raise IndexError + if index < 0 or index >= len(self.data): + raise IndexError self.data = self.data[:index] + self.data[index + 1:] + def __setslice__(self, start, end, sub): - start = max(start, 0); end = max(end, 0) + start = max(start, 0) + end = max(end, 0) if isinstance(sub, UserString): self.data = self.data[:start] + sub.data + self.data[end:] - elif isinstance(sub, basestring): + elif isinstance(sub, str): self.data = self.data[:start] + sub + self.data[end:] else: self.data = self.data[:start] + str(sub) + self.data[end:] + def __delslice__(self, start, end): - start = max(start, 0); end = max(end, 0) + start = max(start, 0) + end = max(end, 0) self.data = self.data[:start] + self.data[end:] + def immutable(self): return UserString(self.data) + def __iadd__(self, other): if isinstance(other, UserString): self.data += other.data - elif isinstance(other, basestring): + elif isinstance(other, str): self.data += other else: self.data += str(other) return self + def __imul__(self, n): self.data *= n return self + class String(MutableString, Union): _fields_ = [('raw', POINTER(c_char)), ('data', c_char_p)] - def __init__(self, obj = ""): - if isinstance(obj, (str, unicode, UserString)): + def __init__(self, obj=""): + if isinstance(obj, (str, UserString)): self.data = str(obj) else: self.raw = obj @@ -264,7 +342,8 @@ def from_param(cls, obj): return String.from_param(obj._as_parameter_) from_param = classmethod(from_param) -def ReturnString(obj, func = None, arguments = None): + +def ReturnString(obj, func=None, arguments=None): return String.from_param(obj) # As of ctypes 1.0, ctypes does not support custom error-checking @@ -274,23 +353,30 @@ def ReturnString(obj, func = None, arguments = None): # # Non-primitive return values wrapped with UNCHECKED won't be # typechecked, and will be converted to c_void_p. + + def UNCHECKED(type): if (hasattr(type, "_type_") and isinstance(type._type_, str) - and type._type_ != "P"): + and type._type_ != "P"): return type else: return c_void_p # ctypes doesn't have direct support for variadic functions, so we have to write # our own wrapper class + + class _variadic_function(object): + def __init__(self, func, restype, argtypes): self.func = func self.func.restype = restype self.argtypes = argtypes + def _as_parameter_(self): # So we can pass this variadic function as a function pointer return self.func + def __call__(self, *args): fixed_args = [] i = 0 @@ -341,18 +427,24 @@ def __call__(self, *args): # POSSIBILITY OF SUCH DAMAGE. # ---------------------------------------------------------------------------- -import os.path, re, sys, glob +import os.path +import re +import sys +import glob import platform import ctypes import ctypes.util + def _environ_path(name): if name in os.environ: return os.environ[name].split(":") else: return [] + class LibraryLoader(object): + def __init__(self): self.other_dirs = [] @@ -361,6 +453,7 @@ def load_library(self, libname): paths = self.getpaths(libname) for path in paths: + print(path) if os.path.exists(path): return self.load(path) @@ -377,7 +470,7 @@ def load(self, path): return ctypes.CDLL(path, ctypes.RTLD_GLOBAL) else: return ctypes.cdll.LoadLibrary(path) - except OSError, e: + except OSError as e: raise ImportError(e) def getpaths(self, libname): @@ -390,16 +483,18 @@ def getpaths(self, libname): yield path path = ctypes.util.find_library(libname) - if path: yield path + if path: + yield path def getplatformpaths(self, libname): return [] # Darwin (Mac OS X) + class DarwinLibraryLoader(LibraryLoader): name_formats = ["lib%s.dylib", "lib%s.so", "lib%s.bundle", "%s.dylib", - "%s.so", "%s.bundle", "%s"] + "%s.so", "%s.bundle", "%s"] def getplatformpaths(self, libname): if os.path.pathsep in libname: @@ -422,7 +517,8 @@ def getdirs(self, libname): within a bundle (OS X .app). ''' - dyld_fallback_library_path = _environ_path("DYLD_FALLBACK_LIBRARY_PATH") + dyld_fallback_library_path = _environ_path( + "DYLD_FALLBACK_LIBRARY_PATH") if not dyld_fallback_library_path: dyld_fallback_library_path = [os.path.expanduser('~/lib'), '/usr/local/lib', '/usr/lib'] @@ -439,7 +535,7 @@ def getdirs(self, libname): dirs.append(".") dirs.append(os.path.dirname(__file__)) - if hasattr(sys, 'frozen') and sys.frozen == 'macosx_app': #pylint: disable-msg=E1101 + if hasattr(sys, 'frozen') and sys.frozen == 'macosx_app': # pylint: disable-msg=E1101 dirs.append(os.path.join( os.environ['RESOURCEPATH'], '..', @@ -451,6 +547,7 @@ def getdirs(self, libname): # Posix + class PosixLibraryLoader(LibraryLoader): _ld_so_cache = None @@ -464,18 +561,21 @@ def _create_ld_so_cache(self): directories = [] for name in ("LD_LIBRARY_PATH", - "SHLIB_PATH", # HPUX - "LIBPATH", # OS/2, AIX - "LIBRARY_PATH", # BE/OS - ): + "SHLIB_PATH", # HPUX + "LIBPATH", # OS/2, AIX + "LIBRARY_PATH", # BE/OS + ): if name in os.environ: directories.extend(os.environ[name].split(os.pathsep)) directories.extend(self.other_dirs) directories.append(".") directories.append(os.path.dirname(__file__)) - try: directories.extend([dir.strip() for dir in open('/etc/ld.so.conf')]) - except IOError: pass + try: + directories.extend([dir.strip() + for dir in open('/etc/ld.so.conf')]) + except IOError: + pass unix_lib_dirs_list = ['/lib', '/usr/lib', '/lib64', '/usr/lib64'] if sys.platform.startswith('linux'): @@ -484,10 +584,12 @@ def _create_ld_so_cache(self): bitage = platform.architecture()[0] if bitage.startswith('32'): # Assume Intel/AMD x86 compat - unix_lib_dirs_list += ['/lib/i386-linux-gnu', '/usr/lib/i386-linux-gnu'] + unix_lib_dirs_list += ['/lib/i386-linux-gnu', + '/usr/lib/i386-linux-gnu'] elif bitage.startswith('64'): # Assume Intel/AMD x86 compat - unix_lib_dirs_list += ['/lib/x86_64-linux-gnu', '/usr/lib/x86_64-linux-gnu'] + unix_lib_dirs_list += ['/lib/x86_64-linux-gnu', + '/usr/lib/x86_64-linux-gnu'] else: # guess... unix_lib_dirs_list += glob.glob('/lib/*linux-gnu') @@ -521,25 +623,32 @@ def getplatformpaths(self, libname): self._create_ld_so_cache() result = self._ld_so_cache.get(libname) - if result: yield result + if result: + yield result path = ctypes.util.find_library(libname) - if path: yield os.path.join("/lib", path) + if path: + yield os.path.join("/lib", path) # Windows + class _WindowsLibrary(object): + def __init__(self, path): self.cdll = ctypes.cdll.LoadLibrary(path) self.windll = ctypes.windll.LoadLibrary(path) def __getattr__(self, name): - try: return getattr(self.cdll, name) + try: + return getattr(self.cdll, name) except AttributeError: - try: return getattr(self.windll, name) + try: + return getattr(self.windll, name) except AttributeError: raise + class WindowsLibraryLoader(LibraryLoader): name_formats = ["%s.dll", "lib%s.dll", "%slib.dll"] @@ -591,6 +700,7 @@ def getplatformpaths(self, libname): loader = loaderclass.get(sys.platform, PosixLibraryLoader)() + def add_library_search_dirs(other_dirs): loader.other_dirs = other_dirs @@ -612,70 +722,86 @@ def add_library_search_dirs(other_dirs): # No modules # /usr/include/nfc/nfc-types.h: 42 + + class struct_nfc_context(Structure): _pack_ = 1 -nfc_context = struct_nfc_context # /usr/include/nfc/nfc-types.h: 42 +nfc_context = struct_nfc_context # /usr/include/nfc/nfc-types.h: 42 # /usr/include/nfc/nfc-types.h: 47 + + class struct_nfc_device(Structure): _pack_ = 1 -nfc_device = struct_nfc_device # /usr/include/nfc/nfc-types.h: 47 +nfc_device = struct_nfc_device # /usr/include/nfc/nfc-types.h: 47 # /usr/include/nfc/nfc-types.h: 52 + + class struct_nfc_driver(Structure): _pack_ = 1 -nfc_driver = struct_nfc_driver # /usr/include/nfc/nfc-types.h: 52 +nfc_driver = struct_nfc_driver # /usr/include/nfc/nfc-types.h: 52 -nfc_connstring = c_char * 1024 # /usr/include/nfc/nfc-types.h: 57 +nfc_connstring = c_char * 1024 # /usr/include/nfc/nfc-types.h: 57 -enum_anon_18 = c_int # /usr/include/nfc/nfc-types.h: 137 +enum_anon_18 = c_int # /usr/include/nfc/nfc-types.h: 137 -NP_TIMEOUT_COMMAND = 0 # /usr/include/nfc/nfc-types.h: 137 +NP_TIMEOUT_COMMAND = 0 # /usr/include/nfc/nfc-types.h: 137 -NP_TIMEOUT_ATR = (NP_TIMEOUT_COMMAND + 1) # /usr/include/nfc/nfc-types.h: 137 +NP_TIMEOUT_ATR = (NP_TIMEOUT_COMMAND + 1) # /usr/include/nfc/nfc-types.h: 137 -NP_TIMEOUT_COM = (NP_TIMEOUT_ATR + 1) # /usr/include/nfc/nfc-types.h: 137 +NP_TIMEOUT_COM = (NP_TIMEOUT_ATR + 1) # /usr/include/nfc/nfc-types.h: 137 -NP_HANDLE_CRC = (NP_TIMEOUT_COM + 1) # /usr/include/nfc/nfc-types.h: 137 +NP_HANDLE_CRC = (NP_TIMEOUT_COM + 1) # /usr/include/nfc/nfc-types.h: 137 -NP_HANDLE_PARITY = (NP_HANDLE_CRC + 1) # /usr/include/nfc/nfc-types.h: 137 +NP_HANDLE_PARITY = (NP_HANDLE_CRC + 1) # /usr/include/nfc/nfc-types.h: 137 -NP_ACTIVATE_FIELD = (NP_HANDLE_PARITY + 1) # /usr/include/nfc/nfc-types.h: 137 +NP_ACTIVATE_FIELD = (NP_HANDLE_PARITY + 1) # /usr/include/nfc/nfc-types.h: 137 -NP_ACTIVATE_CRYPTO1 = (NP_ACTIVATE_FIELD + 1) # /usr/include/nfc/nfc-types.h: 137 +# /usr/include/nfc/nfc-types.h: 137 +NP_ACTIVATE_CRYPTO1 = (NP_ACTIVATE_FIELD + 1) -NP_INFINITE_SELECT = (NP_ACTIVATE_CRYPTO1 + 1) # /usr/include/nfc/nfc-types.h: 137 +# /usr/include/nfc/nfc-types.h: 137 +NP_INFINITE_SELECT = (NP_ACTIVATE_CRYPTO1 + 1) -NP_ACCEPT_INVALID_FRAMES = (NP_INFINITE_SELECT + 1) # /usr/include/nfc/nfc-types.h: 137 +# /usr/include/nfc/nfc-types.h: 137 +NP_ACCEPT_INVALID_FRAMES = (NP_INFINITE_SELECT + 1) -NP_ACCEPT_MULTIPLE_FRAMES = (NP_ACCEPT_INVALID_FRAMES + 1) # /usr/include/nfc/nfc-types.h: 137 +# /usr/include/nfc/nfc-types.h: 137 +NP_ACCEPT_MULTIPLE_FRAMES = (NP_ACCEPT_INVALID_FRAMES + 1) -NP_AUTO_ISO14443_4 = (NP_ACCEPT_MULTIPLE_FRAMES + 1) # /usr/include/nfc/nfc-types.h: 137 +# /usr/include/nfc/nfc-types.h: 137 +NP_AUTO_ISO14443_4 = (NP_ACCEPT_MULTIPLE_FRAMES + 1) -NP_EASY_FRAMING = (NP_AUTO_ISO14443_4 + 1) # /usr/include/nfc/nfc-types.h: 137 +NP_EASY_FRAMING = (NP_AUTO_ISO14443_4 + 1) # /usr/include/nfc/nfc-types.h: 137 -NP_FORCE_ISO14443_A = (NP_EASY_FRAMING + 1) # /usr/include/nfc/nfc-types.h: 137 +# /usr/include/nfc/nfc-types.h: 137 +NP_FORCE_ISO14443_A = (NP_EASY_FRAMING + 1) -NP_FORCE_ISO14443_B = (NP_FORCE_ISO14443_A + 1) # /usr/include/nfc/nfc-types.h: 137 +# /usr/include/nfc/nfc-types.h: 137 +NP_FORCE_ISO14443_B = (NP_FORCE_ISO14443_A + 1) -NP_FORCE_SPEED_106 = (NP_FORCE_ISO14443_B + 1) # /usr/include/nfc/nfc-types.h: 137 +# /usr/include/nfc/nfc-types.h: 137 +NP_FORCE_SPEED_106 = (NP_FORCE_ISO14443_B + 1) -nfc_property = enum_anon_18 # /usr/include/nfc/nfc-types.h: 137 +nfc_property = enum_anon_18 # /usr/include/nfc/nfc-types.h: 137 -enum_anon_19 = c_int # /usr/include/nfc/nfc-types.h: 150 +enum_anon_19 = c_int # /usr/include/nfc/nfc-types.h: 150 -NDM_UNDEFINED = 0 # /usr/include/nfc/nfc-types.h: 150 +NDM_UNDEFINED = 0 # /usr/include/nfc/nfc-types.h: 150 -NDM_PASSIVE = (NDM_UNDEFINED + 1) # /usr/include/nfc/nfc-types.h: 150 +NDM_PASSIVE = (NDM_UNDEFINED + 1) # /usr/include/nfc/nfc-types.h: 150 -NDM_ACTIVE = (NDM_PASSIVE + 1) # /usr/include/nfc/nfc-types.h: 150 +NDM_ACTIVE = (NDM_PASSIVE + 1) # /usr/include/nfc/nfc-types.h: 150 -nfc_dep_mode = enum_anon_19 # /usr/include/nfc/nfc-types.h: 150 +nfc_dep_mode = enum_anon_19 # /usr/include/nfc/nfc-types.h: 150 # /usr/include/nfc/nfc-types.h: 174 + + class struct_anon_20(Structure): _pack_ = 1 @@ -702,9 +828,11 @@ class struct_anon_20(Structure): ('ndm', nfc_dep_mode), ] -nfc_dep_info = struct_anon_20 # /usr/include/nfc/nfc-types.h: 174 +nfc_dep_info = struct_anon_20 # /usr/include/nfc/nfc-types.h: 174 # /usr/include/nfc/nfc-types.h: 187 + + class struct_anon_21(Structure): _pack_ = 1 @@ -725,9 +853,11 @@ class struct_anon_21(Structure): ('abtAts', c_uint8 * 254), ] -nfc_iso14443a_info = struct_anon_21 # /usr/include/nfc/nfc-types.h: 187 +nfc_iso14443a_info = struct_anon_21 # /usr/include/nfc/nfc-types.h: 187 # /usr/include/nfc/nfc-types.h: 199 + + class struct_anon_22(Structure): _pack_ = 1 @@ -746,9 +876,11 @@ class struct_anon_22(Structure): ('abtSysCode', c_uint8 * 2), ] -nfc_felica_info = struct_anon_22 # /usr/include/nfc/nfc-types.h: 199 +nfc_felica_info = struct_anon_22 # /usr/include/nfc/nfc-types.h: 199 # /usr/include/nfc/nfc-types.h: 214 + + class struct_anon_23(Structure): _pack_ = 1 @@ -765,9 +897,11 @@ class struct_anon_23(Structure): ('ui8CardIdentifier', c_uint8), ] -nfc_iso14443b_info = struct_anon_23 # /usr/include/nfc/nfc-types.h: 214 +nfc_iso14443b_info = struct_anon_23 # /usr/include/nfc/nfc-types.h: 214 # /usr/include/nfc/nfc-types.h: 230 + + class struct_anon_24(Structure): _pack_ = 1 @@ -786,9 +920,11 @@ class struct_anon_24(Structure): ('abtAtr', c_uint8 * 33), ] -nfc_iso14443bi_info = struct_anon_24 # /usr/include/nfc/nfc-types.h: 230 +nfc_iso14443bi_info = struct_anon_24 # /usr/include/nfc/nfc-types.h: 230 # /usr/include/nfc/nfc-types.h: 238 + + class struct_anon_25(Structure): _pack_ = 1 @@ -799,9 +935,11 @@ class struct_anon_25(Structure): ('abtUID', c_uint8 * 8), ] -nfc_iso14443b2sr_info = struct_anon_25 # /usr/include/nfc/nfc-types.h: 238 +nfc_iso14443b2sr_info = struct_anon_25 # /usr/include/nfc/nfc-types.h: 238 # /usr/include/nfc/nfc-types.h: 248 + + class struct_anon_26(Structure): _pack_ = 1 @@ -816,9 +954,11 @@ class struct_anon_26(Structure): ('btFabCode', c_uint8), ] -nfc_iso14443b2ct_info = struct_anon_26 # /usr/include/nfc/nfc-types.h: 248 +nfc_iso14443b2ct_info = struct_anon_26 # /usr/include/nfc/nfc-types.h: 248 # /usr/include/nfc/nfc-types.h: 257 + + class struct_anon_27(Structure): _pack_ = 1 @@ -831,9 +971,11 @@ class struct_anon_27(Structure): ('btId', c_uint8 * 4), ] -nfc_jewel_info = struct_anon_27 # /usr/include/nfc/nfc-types.h: 257 +nfc_jewel_info = struct_anon_27 # /usr/include/nfc/nfc-types.h: 257 # /usr/include/nfc/nfc-types.h: 272 + + class union_anon_28(Union): _pack_ = 1 @@ -858,51 +1000,53 @@ class union_anon_28(Union): ('ndi', nfc_dep_info), ] -nfc_target_info = union_anon_28 # /usr/include/nfc/nfc-types.h: 272 +nfc_target_info = union_anon_28 # /usr/include/nfc/nfc-types.h: 272 -enum_anon_29 = c_int # /usr/include/nfc/nfc-types.h: 284 +enum_anon_29 = c_int # /usr/include/nfc/nfc-types.h: 284 -NBR_UNDEFINED = 0 # /usr/include/nfc/nfc-types.h: 284 +NBR_UNDEFINED = 0 # /usr/include/nfc/nfc-types.h: 284 -NBR_106 = (NBR_UNDEFINED + 1) # /usr/include/nfc/nfc-types.h: 284 +NBR_106 = (NBR_UNDEFINED + 1) # /usr/include/nfc/nfc-types.h: 284 -NBR_212 = (NBR_106 + 1) # /usr/include/nfc/nfc-types.h: 284 +NBR_212 = (NBR_106 + 1) # /usr/include/nfc/nfc-types.h: 284 -NBR_424 = (NBR_212 + 1) # /usr/include/nfc/nfc-types.h: 284 +NBR_424 = (NBR_212 + 1) # /usr/include/nfc/nfc-types.h: 284 -NBR_847 = (NBR_424 + 1) # /usr/include/nfc/nfc-types.h: 284 +NBR_847 = (NBR_424 + 1) # /usr/include/nfc/nfc-types.h: 284 -nfc_baud_rate = enum_anon_29 # /usr/include/nfc/nfc-types.h: 284 +nfc_baud_rate = enum_anon_29 # /usr/include/nfc/nfc-types.h: 284 -enum_anon_30 = c_int # /usr/include/nfc/nfc-types.h: 299 +enum_anon_30 = c_int # /usr/include/nfc/nfc-types.h: 299 -NMT_ISO14443A = 1 # /usr/include/nfc/nfc-types.h: 299 +NMT_ISO14443A = 1 # /usr/include/nfc/nfc-types.h: 299 -NMT_JEWEL = (NMT_ISO14443A + 1) # /usr/include/nfc/nfc-types.h: 299 +NMT_JEWEL = (NMT_ISO14443A + 1) # /usr/include/nfc/nfc-types.h: 299 -NMT_ISO14443B = (NMT_JEWEL + 1) # /usr/include/nfc/nfc-types.h: 299 +NMT_ISO14443B = (NMT_JEWEL + 1) # /usr/include/nfc/nfc-types.h: 299 -NMT_ISO14443BI = (NMT_ISO14443B + 1) # /usr/include/nfc/nfc-types.h: 299 +NMT_ISO14443BI = (NMT_ISO14443B + 1) # /usr/include/nfc/nfc-types.h: 299 -NMT_ISO14443B2SR = (NMT_ISO14443BI + 1) # /usr/include/nfc/nfc-types.h: 299 +NMT_ISO14443B2SR = (NMT_ISO14443BI + 1) # /usr/include/nfc/nfc-types.h: 299 -NMT_ISO14443B2CT = (NMT_ISO14443B2SR + 1) # /usr/include/nfc/nfc-types.h: 299 +NMT_ISO14443B2CT = (NMT_ISO14443B2SR + 1) # /usr/include/nfc/nfc-types.h: 299 -NMT_FELICA = (NMT_ISO14443B2CT + 1) # /usr/include/nfc/nfc-types.h: 299 +NMT_FELICA = (NMT_ISO14443B2CT + 1) # /usr/include/nfc/nfc-types.h: 299 -NMT_DEP = (NMT_FELICA + 1) # /usr/include/nfc/nfc-types.h: 299 +NMT_DEP = (NMT_FELICA + 1) # /usr/include/nfc/nfc-types.h: 299 -nfc_modulation_type = enum_anon_30 # /usr/include/nfc/nfc-types.h: 299 +nfc_modulation_type = enum_anon_30 # /usr/include/nfc/nfc-types.h: 299 -enum_anon_31 = c_int # /usr/include/nfc/nfc-types.h: 308 +enum_anon_31 = c_int # /usr/include/nfc/nfc-types.h: 308 -N_TARGET = 0 # /usr/include/nfc/nfc-types.h: 308 +N_TARGET = 0 # /usr/include/nfc/nfc-types.h: 308 -N_INITIATOR = (N_TARGET + 1) # /usr/include/nfc/nfc-types.h: 308 +N_INITIATOR = (N_TARGET + 1) # /usr/include/nfc/nfc-types.h: 308 -nfc_mode = enum_anon_31 # /usr/include/nfc/nfc-types.h: 308 +nfc_mode = enum_anon_31 # /usr/include/nfc/nfc-types.h: 308 # /usr/include/nfc/nfc-types.h: 317 + + class struct_anon_32(Structure): _pack_ = 1 @@ -915,9 +1059,11 @@ class struct_anon_32(Structure): ('nbr', nfc_baud_rate), ] -nfc_modulation = struct_anon_32 # /usr/include/nfc/nfc-types.h: 317 +nfc_modulation = struct_anon_32 # /usr/include/nfc/nfc-types.h: 317 # /usr/include/nfc/nfc-types.h: 326 + + class struct_anon_33(Structure): _pack_ = 1 @@ -930,7 +1076,7 @@ class struct_anon_33(Structure): ('nm', nfc_modulation), ] -nfc_target = struct_anon_33 # /usr/include/nfc/nfc-types.h: 326 +nfc_target = struct_anon_33 # /usr/include/nfc/nfc-types.h: 326 # /usr/include/nfc/nfc.h: 80 if hasattr(_libs['nfc'], 'nfc_init'): @@ -971,7 +1117,8 @@ class struct_anon_33(Structure): # /usr/include/nfc/nfc.h: 88 if hasattr(_libs['nfc'], 'nfc_list_devices'): nfc_list_devices = _libs['nfc'].nfc_list_devices - nfc_list_devices.argtypes = [POINTER(nfc_context), POINTER(nfc_connstring), c_size_t] + nfc_list_devices.argtypes = [ + POINTER(nfc_context), POINTER(nfc_connstring), c_size_t] nfc_list_devices.restype = c_size_t # /usr/include/nfc/nfc.h: 89 @@ -988,38 +1135,47 @@ class struct_anon_33(Structure): # /usr/include/nfc/nfc.h: 93 if hasattr(_libs['nfc'], 'nfc_initiator_init_secure_element'): - nfc_initiator_init_secure_element = _libs['nfc'].nfc_initiator_init_secure_element + nfc_initiator_init_secure_element = _libs[ + 'nfc'].nfc_initiator_init_secure_element nfc_initiator_init_secure_element.argtypes = [POINTER(nfc_device)] nfc_initiator_init_secure_element.restype = c_int # /usr/include/nfc/nfc.h: 94 if hasattr(_libs['nfc'], 'nfc_initiator_select_passive_target'): - nfc_initiator_select_passive_target = _libs['nfc'].nfc_initiator_select_passive_target - nfc_initiator_select_passive_target.argtypes = [POINTER(nfc_device), nfc_modulation, POINTER(c_uint8), c_size_t, POINTER(nfc_target)] + nfc_initiator_select_passive_target = _libs[ + 'nfc'].nfc_initiator_select_passive_target + nfc_initiator_select_passive_target.argtypes = [POINTER( + nfc_device), nfc_modulation, POINTER(c_uint8), c_size_t, POINTER(nfc_target)] nfc_initiator_select_passive_target.restype = c_int # /usr/include/nfc/nfc.h: 95 if hasattr(_libs['nfc'], 'nfc_initiator_list_passive_targets'): - nfc_initiator_list_passive_targets = _libs['nfc'].nfc_initiator_list_passive_targets - nfc_initiator_list_passive_targets.argtypes = [POINTER(nfc_device), nfc_modulation, POINTER(nfc_target), c_size_t] + nfc_initiator_list_passive_targets = _libs[ + 'nfc'].nfc_initiator_list_passive_targets + nfc_initiator_list_passive_targets.argtypes = [ + POINTER(nfc_device), nfc_modulation, POINTER(nfc_target), c_size_t] nfc_initiator_list_passive_targets.restype = c_int # /usr/include/nfc/nfc.h: 96 if hasattr(_libs['nfc'], 'nfc_initiator_poll_target'): nfc_initiator_poll_target = _libs['nfc'].nfc_initiator_poll_target - nfc_initiator_poll_target.argtypes = [POINTER(nfc_device), POINTER(nfc_modulation), c_size_t, c_uint8, c_uint8, POINTER(nfc_target)] + nfc_initiator_poll_target.argtypes = [POINTER(nfc_device), POINTER( + nfc_modulation), c_size_t, c_uint8, c_uint8, POINTER(nfc_target)] nfc_initiator_poll_target.restype = c_int # /usr/include/nfc/nfc.h: 97 if hasattr(_libs['nfc'], 'nfc_initiator_select_dep_target'): - nfc_initiator_select_dep_target = _libs['nfc'].nfc_initiator_select_dep_target - nfc_initiator_select_dep_target.argtypes = [POINTER(nfc_device), nfc_dep_mode, nfc_baud_rate, POINTER(nfc_dep_info), POINTER(nfc_target), c_int] + nfc_initiator_select_dep_target = _libs[ + 'nfc'].nfc_initiator_select_dep_target + nfc_initiator_select_dep_target.argtypes = [POINTER( + nfc_device), nfc_dep_mode, nfc_baud_rate, POINTER(nfc_dep_info), POINTER(nfc_target), c_int] nfc_initiator_select_dep_target.restype = c_int # /usr/include/nfc/nfc.h: 98 if hasattr(_libs['nfc'], 'nfc_initiator_poll_dep_target'): nfc_initiator_poll_dep_target = _libs['nfc'].nfc_initiator_poll_dep_target - nfc_initiator_poll_dep_target.argtypes = [POINTER(nfc_device), nfc_dep_mode, nfc_baud_rate, POINTER(nfc_dep_info), POINTER(nfc_target), c_int] + nfc_initiator_poll_dep_target.argtypes = [POINTER( + nfc_device), nfc_dep_mode, nfc_baud_rate, POINTER(nfc_dep_info), POINTER(nfc_target), c_int] nfc_initiator_poll_dep_target.restype = c_int # /usr/include/nfc/nfc.h: 99 @@ -1030,62 +1186,76 @@ class struct_anon_33(Structure): # /usr/include/nfc/nfc.h: 100 if hasattr(_libs['nfc'], 'nfc_initiator_transceive_bytes'): - nfc_initiator_transceive_bytes = _libs['nfc'].nfc_initiator_transceive_bytes - nfc_initiator_transceive_bytes.argtypes = [POINTER(nfc_device), POINTER(c_uint8), c_size_t, POINTER(c_uint8), c_size_t, c_int] + nfc_initiator_transceive_bytes = _libs[ + 'nfc'].nfc_initiator_transceive_bytes + nfc_initiator_transceive_bytes.argtypes = [POINTER(nfc_device), POINTER( + c_uint8), c_size_t, POINTER(c_uint8), c_size_t, c_int] nfc_initiator_transceive_bytes.restype = c_int # /usr/include/nfc/nfc.h: 101 if hasattr(_libs['nfc'], 'nfc_initiator_transceive_bits'): nfc_initiator_transceive_bits = _libs['nfc'].nfc_initiator_transceive_bits - nfc_initiator_transceive_bits.argtypes = [POINTER(nfc_device), POINTER(c_uint8), c_size_t, POINTER(c_uint8), POINTER(c_uint8), c_size_t, POINTER(c_uint8)] + nfc_initiator_transceive_bits.argtypes = [POINTER(nfc_device), POINTER( + c_uint8), c_size_t, POINTER(c_uint8), POINTER(c_uint8), c_size_t, POINTER(c_uint8)] nfc_initiator_transceive_bits.restype = c_int # /usr/include/nfc/nfc.h: 102 if hasattr(_libs['nfc'], 'nfc_initiator_transceive_bytes_timed'): - nfc_initiator_transceive_bytes_timed = _libs['nfc'].nfc_initiator_transceive_bytes_timed - nfc_initiator_transceive_bytes_timed.argtypes = [POINTER(nfc_device), POINTER(c_uint8), c_size_t, POINTER(c_uint8), c_size_t, POINTER(c_uint32)] + nfc_initiator_transceive_bytes_timed = _libs[ + 'nfc'].nfc_initiator_transceive_bytes_timed + nfc_initiator_transceive_bytes_timed.argtypes = [POINTER(nfc_device), POINTER( + c_uint8), c_size_t, POINTER(c_uint8), c_size_t, POINTER(c_uint32)] nfc_initiator_transceive_bytes_timed.restype = c_int # /usr/include/nfc/nfc.h: 103 if hasattr(_libs['nfc'], 'nfc_initiator_transceive_bits_timed'): - nfc_initiator_transceive_bits_timed = _libs['nfc'].nfc_initiator_transceive_bits_timed - nfc_initiator_transceive_bits_timed.argtypes = [POINTER(nfc_device), POINTER(c_uint8), c_size_t, POINTER(c_uint8), POINTER(c_uint8), c_size_t, POINTER(c_uint8), POINTER(c_uint32)] + nfc_initiator_transceive_bits_timed = _libs[ + 'nfc'].nfc_initiator_transceive_bits_timed + nfc_initiator_transceive_bits_timed.argtypes = [POINTER(nfc_device), POINTER( + c_uint8), c_size_t, POINTER(c_uint8), POINTER(c_uint8), c_size_t, POINTER(c_uint8), POINTER(c_uint32)] nfc_initiator_transceive_bits_timed.restype = c_int # /usr/include/nfc/nfc.h: 104 if hasattr(_libs['nfc'], 'nfc_initiator_target_is_present'): - nfc_initiator_target_is_present = _libs['nfc'].nfc_initiator_target_is_present - nfc_initiator_target_is_present.argtypes = [POINTER(nfc_device), nfc_target] + nfc_initiator_target_is_present = _libs[ + 'nfc'].nfc_initiator_target_is_present + nfc_initiator_target_is_present.argtypes = [ + POINTER(nfc_device), nfc_target] nfc_initiator_target_is_present.restype = c_int # /usr/include/nfc/nfc.h: 107 if hasattr(_libs['nfc'], 'nfc_target_init'): nfc_target_init = _libs['nfc'].nfc_target_init - nfc_target_init.argtypes = [POINTER(nfc_device), POINTER(nfc_target), POINTER(c_uint8), c_size_t, c_int] + nfc_target_init.argtypes = [ + POINTER(nfc_device), POINTER(nfc_target), POINTER(c_uint8), c_size_t, c_int] nfc_target_init.restype = c_int # /usr/include/nfc/nfc.h: 108 if hasattr(_libs['nfc'], 'nfc_target_send_bytes'): nfc_target_send_bytes = _libs['nfc'].nfc_target_send_bytes - nfc_target_send_bytes.argtypes = [POINTER(nfc_device), POINTER(c_uint8), c_size_t, c_int] + nfc_target_send_bytes.argtypes = [ + POINTER(nfc_device), POINTER(c_uint8), c_size_t, c_int] nfc_target_send_bytes.restype = c_int # /usr/include/nfc/nfc.h: 109 if hasattr(_libs['nfc'], 'nfc_target_receive_bytes'): nfc_target_receive_bytes = _libs['nfc'].nfc_target_receive_bytes - nfc_target_receive_bytes.argtypes = [POINTER(nfc_device), POINTER(c_uint8), c_size_t, c_int] + nfc_target_receive_bytes.argtypes = [ + POINTER(nfc_device), POINTER(c_uint8), c_size_t, c_int] nfc_target_receive_bytes.restype = c_int # /usr/include/nfc/nfc.h: 110 if hasattr(_libs['nfc'], 'nfc_target_send_bits'): nfc_target_send_bits = _libs['nfc'].nfc_target_send_bits - nfc_target_send_bits.argtypes = [POINTER(nfc_device), POINTER(c_uint8), c_size_t, POINTER(c_uint8)] + nfc_target_send_bits.argtypes = [ + POINTER(nfc_device), POINTER(c_uint8), c_size_t, POINTER(c_uint8)] nfc_target_send_bits.restype = c_int # /usr/include/nfc/nfc.h: 111 if hasattr(_libs['nfc'], 'nfc_target_receive_bits'): nfc_target_receive_bits = _libs['nfc'].nfc_target_receive_bits - nfc_target_receive_bits.argtypes = [POINTER(nfc_device), POINTER(c_uint8), c_size_t, POINTER(c_uint8)] + nfc_target_receive_bits.argtypes = [ + POINTER(nfc_device), POINTER(c_uint8), c_size_t, POINTER(c_uint8)] nfc_target_receive_bits.restype = c_int # /usr/include/nfc/nfc.h: 114 @@ -1138,26 +1308,32 @@ class struct_anon_33(Structure): # /usr/include/nfc/nfc.h: 122 if hasattr(_libs['nfc'], 'nfc_device_get_supported_modulation'): - nfc_device_get_supported_modulation = _libs['nfc'].nfc_device_get_supported_modulation - nfc_device_get_supported_modulation.argtypes = [POINTER(nfc_device), nfc_mode, POINTER(POINTER(nfc_modulation_type))] + nfc_device_get_supported_modulation = _libs[ + 'nfc'].nfc_device_get_supported_modulation + nfc_device_get_supported_modulation.argtypes = [ + POINTER(nfc_device), nfc_mode, POINTER(POINTER(nfc_modulation_type))] nfc_device_get_supported_modulation.restype = c_int # /usr/include/nfc/nfc.h: 123 if hasattr(_libs['nfc'], 'nfc_device_get_supported_baud_rate'): - nfc_device_get_supported_baud_rate = _libs['nfc'].nfc_device_get_supported_baud_rate - nfc_device_get_supported_baud_rate.argtypes = [POINTER(nfc_device), nfc_modulation_type, POINTER(POINTER(nfc_baud_rate))] + nfc_device_get_supported_baud_rate = _libs[ + 'nfc'].nfc_device_get_supported_baud_rate + nfc_device_get_supported_baud_rate.argtypes = [ + POINTER(nfc_device), nfc_modulation_type, POINTER(POINTER(nfc_baud_rate))] nfc_device_get_supported_baud_rate.restype = c_int # /usr/include/nfc/nfc.h: 126 if hasattr(_libs['nfc'], 'nfc_device_set_property_int'): nfc_device_set_property_int = _libs['nfc'].nfc_device_set_property_int - nfc_device_set_property_int.argtypes = [POINTER(nfc_device), nfc_property, c_int] + nfc_device_set_property_int.argtypes = [ + POINTER(nfc_device), nfc_property, c_int] nfc_device_set_property_int.restype = c_int # /usr/include/nfc/nfc.h: 127 if hasattr(_libs['nfc'], 'nfc_device_set_property_bool'): nfc_device_set_property_bool = _libs['nfc'].nfc_device_set_property_bool - nfc_device_set_property_bool.argtypes = [POINTER(nfc_device), nfc_property, c_uint8] + nfc_device_set_property_bool.argtypes = [ + POINTER(nfc_device), nfc_property, c_uint8] nfc_device_set_property_bool.restype = c_int # /usr/include/nfc/nfc.h: 130 @@ -1174,8 +1350,10 @@ class struct_anon_33(Structure): # /usr/include/nfc/nfc.h: 132 if hasattr(_libs['nfc'], 'iso14443a_locate_historical_bytes'): - iso14443a_locate_historical_bytes = _libs['nfc'].iso14443a_locate_historical_bytes - iso14443a_locate_historical_bytes.argtypes = [POINTER(c_uint8), c_size_t, POINTER(c_size_t)] + iso14443a_locate_historical_bytes = _libs[ + 'nfc'].iso14443a_locate_historical_bytes + iso14443a_locate_historical_bytes.argtypes = [ + POINTER(c_uint8), c_size_t, POINTER(c_size_t)] iso14443a_locate_historical_bytes.restype = POINTER(c_uint8) # /usr/include/nfc/nfc.h: 134 @@ -1196,8 +1374,10 @@ class struct_anon_33(Structure): # /usr/include/nfc/nfc.h: 136 if hasattr(_libs['nfc'], 'nfc_device_get_information_about'): - nfc_device_get_information_about = _libs['nfc'].nfc_device_get_information_about - nfc_device_get_information_about.argtypes = [POINTER(nfc_device), POINTER(POINTER(c_char))] + nfc_device_get_information_about = _libs[ + 'nfc'].nfc_device_get_information_about + nfc_device_get_information_about.argtypes = [ + POINTER(nfc_device), POINTER(POINTER(c_char))] nfc_device_get_information_about.restype = c_int # /usr/include/nfc/nfc.h: 139 @@ -1227,10 +1407,14 @@ class struct_anon_33(Structure): str_nfc_target.restype = c_int # /usr/include/nfc/nfc-emulation.h: 43 + + class struct_nfc_emulator(Structure): _pack_ = 1 # /usr/include/nfc/nfc-emulation.h: 53 + + class struct_nfc_emulation_state_machine(Structure): _pack_ = 1 @@ -1250,14 +1434,16 @@ class struct_nfc_emulation_state_machine(Structure): 'data', ] struct_nfc_emulation_state_machine._fields_ = [ - ('io', CFUNCTYPE(UNCHECKED(c_int), POINTER(struct_nfc_emulator), POINTER(c_uint8), c_size_t, POINTER(c_uint8), c_size_t)), + ('io', CFUNCTYPE(UNCHECKED(c_int), POINTER(struct_nfc_emulator), + POINTER(c_uint8), c_size_t, POINTER(c_uint8), c_size_t)), ('data', POINTER(None)), ] # /usr/include/nfc/nfc-emulation.h: 58 if hasattr(_libs['nfc'], 'nfc_emulate_target'): nfc_emulate_target = _libs['nfc'].nfc_emulate_target - nfc_emulate_target.argtypes = [POINTER(nfc_device), POINTER(struct_nfc_emulator), c_int] + nfc_emulate_target.argtypes = [ + POINTER(nfc_device), POINTER(struct_nfc_emulator), c_int] nfc_emulate_target.restype = c_int # /usr/include/nfc/nfc-types.h: 36 @@ -1267,6 +1453,8 @@ class struct_nfc_emulation_state_machine(Structure): pass # /usr/include/nfc/nfc.h: 62 + + def __has_attribute(x): return 0 @@ -1354,15 +1542,15 @@ def __has_attribute(x): except: pass -nfc_context = struct_nfc_context # /usr/include/nfc/nfc-types.h: 42 +nfc_context = struct_nfc_context # /usr/include/nfc/nfc-types.h: 42 -nfc_device = struct_nfc_device # /usr/include/nfc/nfc-types.h: 47 +nfc_device = struct_nfc_device # /usr/include/nfc/nfc-types.h: 47 -nfc_driver = struct_nfc_driver # /usr/include/nfc/nfc-types.h: 52 +nfc_driver = struct_nfc_driver # /usr/include/nfc/nfc-types.h: 52 -nfc_emulator = struct_nfc_emulator # /usr/include/nfc/nfc-emulation.h: 43 +nfc_emulator = struct_nfc_emulator # /usr/include/nfc/nfc-emulation.h: 43 -nfc_emulation_state_machine = struct_nfc_emulation_state_machine # /usr/include/nfc/nfc-emulation.h: 53 +# /usr/include/nfc/nfc-emulation.h: 53 +nfc_emulation_state_machine = struct_nfc_emulation_state_machine # No inserted files - diff --git a/src/setup.py b/setup.py similarity index 88% rename from src/setup.py rename to setup.py index db5633f..111483c 100644 --- a/src/setup.py +++ b/setup.py @@ -23,11 +23,12 @@ setup( name = "pynfc", - version = "1.7.0_alpha1", + version = "1.7.1", description = "Python bindings for libnfc", author = "Mike Auty", - data_files = [('examples', ['mifareauth.py'])], + data_files = [('examples', ['pynfc/mifareauth.py', 'pynfc/ntag_read.py'])], license = "GPL-2", - py_modules = ['pynfc', 'pycrypto1', 'py14443a'] + packages=['pynfc'], + requires=[] )