160
160
help="keep tag memory (when --loop is set)")
161
161
parser.add_argument(
162
162
"-s", dest="size", type=int, default="1024",
163
help="ndef data area size (default: %(default)s)")
163
help="minimum ndef data area size (default: %(default)s)")
164
164
parser.add_argument(
165
165
"-p", dest="preserve", metavar="FILE", type=argparse.FileType('wb'),
166
166
help="preserve tag memory when released")
185
185
parser.add_argument(
186
186
"--bitrate", choices=["212", "424"], default="212",
187
187
help="bitrate to listen (default: %(default)s)")
189
"--ver", metavar="STR", default="1.0",
190
help="ndef mapping version number (default: %(default)s)")
192
"--nbr", metavar="INT", type=int, default=8,
193
help="max write blocks at once (default: %(default)s)")
195
"--nbw", metavar="INT", type=int, default=12,
196
help="max read blocks at once (default: %(default)s)")
198
"--max", metavar="INT", type=int,
199
help="maximum number of blocks (default: computed)")
201
"--rfu", metavar="INT", type=int, default=0,
202
help="value to set for reserved bytes (default: %(default)s)")
204
"--wf", metavar="INT", type=int, default=0,
205
help="write-flag attribute value (default: %(default)s)")
207
"--rw", metavar="INT", type=int, default=1,
208
help="read-write flag attribute value (default: %(default)s)")
210
"--crc", metavar="INT", type=int,
211
help="checksum attribute value (default: computed)")
189
213
class TagTool(CommandLineInterface):
190
214
def __init__(self):
406
430
self.options.data = ""
408
if not (hasattr(self.options, "ndef_data_area") and self.options.keep):
432
if not (hasattr(self.options, "tt3_data") and self.options.keep):
409
433
if self.options.input:
410
self.options.ndef_data_area = \
411
bytearray(16) + bytearray(self.options.data) + \
412
bytearray(max(0, self.options.size-len(self.options.data)))
413
#elif self.options.preserve:
414
# log.info("reading tag data from {0!r}"
415
# .format(self.options.preserve.name))
416
# data = self.options.preserve.read()
417
# if len(data) % 16 != 0:
418
# log.warning("memory data truncated to 16 byte boundary")
419
# self.options.ndef_data_area = bytearray(data)
434
ndef_data_size = len(self.options.data)
435
ndef_area_size = ((ndef_data_size + 15) // 16) * 16
436
ndef_area_size = max(ndef_area_size, self.options.size)
437
ndef_data_area = bytearray(self.options.data) + \
438
bytearray(ndef_area_size - ndef_data_size)
421
self.options.ndef_data_area = bytearray(16 + self.options.size)
440
ndef_data_area = bytearray(self.options.size)
423
442
# set attribute data
424
443
attr = nfc.tag.tt3.NdefAttributeData()
426
attr.nbr, attr.nbw = (12, 8)
427
attr.capacity = len(self.options.ndef_data_area) - 16
428
attr.writeable = True
444
attr.version = self.options.ver
445
attr.nbr, attr.nbw = self.options.nbr, self.options.nbw
446
attr.capacity = len(ndef_data_area)
447
if self.options.max is not None:
448
attr.capacity = self.options.max * 16
449
attr.rfu = 4 * [self.options.rfu]
450
attr.wf = self.options.wf
451
attr.rw = self.options.rw
429
452
attr.length = len(self.options.data)
430
self.options.ndef_data_area[0:16] = str(attr)
453
attr.writing = bool(self.options.wf)
454
attr.writeable = bool(self.options.rw)
455
attribute_data = bytearray(str(attr))
456
if self.options.crc is not None:
457
attribute_data[14] = self.options.crc / 256
458
attribute_data[15] = self.options.crc % 256
460
log.info(nfc.tag.tt3.NdefAttributeData(attribute_data).pretty())
461
self.options.tt3_data = attribute_data + ndef_data_area
432
463
idm = bytearray.fromhex(self.options.idm)
433
464
pmm = bytearray.fromhex(self.options.pmm)
441
472
def emulate_tag_stop(self, tag):
442
473
if self.options.preserve:
443
474
self.options.preserve.seek(0)
444
self.options.preserve.write(self.options.ndef_data_area)
475
self.options.preserve.write(self.options.tt3_data)
445
476
log.info("wrote tag memory to file '{0}'"
446
477
.format(self.options.preserve.name))
448
479
def emulate_tt3_tag(self, tag, command):
449
480
def ndef_read(block_number, rb, re):
450
481
log.debug("tt3 read block #{0}".format(block_number))
451
if block_number < len(self.options.ndef_data_area) / 16:
482
if block_number < len(self.options.tt3_data) / 16:
452
483
first, last = block_number*16, (block_number+1)*16
453
block_data = self.options.ndef_data_area[first:last]
484
block_data = self.options.tt3_data[first:last]
454
485
return block_data
455
486
def ndef_write(block_number, block_data, wb, we):
456
487
log.debug("tt3 write block #{0}".format(block_number))
457
if block_number < len(self.options.ndef_data_area) / 16:
488
if block_number < len(self.options.tt3_data) / 16:
458
489
first, last = block_number*16, (block_number+1)*16
459
self.options.ndef_data_area[first:last] = block_data
490
self.options.tt3_data[first:last] = block_data
462
493
tag.add_service(0x0009, ndef_read, ndef_write)