2
# -*- coding: latin-1 -*-
3
# -----------------------------------------------------------------------------
4
# Copyright 2011 Stephen Tiedemann <stephen.tiedemann@googlemail.com>
6
# Licensed under the EUPL, Version 1.1 or - as soon they
7
# will be approved by the European Commission - subsequent
8
# versions of the EUPL (the "Licence");
9
# You may not use this work except in compliance with the
11
# You may obtain a copy of the Licence at:
13
# http://www.osor.eu/eupl
15
# Unless required by applicable law or agreed to in
16
# writing, software distributed under the Licence is
17
# distributed on an "AS IS" basis,
18
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
20
# See the Licence for the specific language governing
21
# permissions and limitations under the Licence.
22
# -----------------------------------------------------------------------------
25
log = logging.getLogger()
33
sys.path.insert(1, os.path.split(sys.path[0])[0])
38
terminate = threading.Event()
40
def make_printable(data):
41
printable = string.digits + string.letters + string.punctuation + ' '
42
return ''.join([c if c in printable else '.' for c in data])
44
def format_data(data):
46
for i in range(0, len(data), 16):
47
s.append(" %04x: " % i)
48
s[-1] += ' '.join(["%02x" % ord(c) for c in data[i:i+16]]) + ' '
49
s[-1] += (8 + 16*3 - len(s[-1])) * ' '
50
s[-1] += make_printable(data[i:i+16])
53
class NdefPushServer(nfc.npp.NPPServer):
55
super(NdefPushServer, self).__init__()
57
def process(self, ndef_message_data):
58
log.info("ndef push server got message")
60
sys.stdout.write(ndef_message_data)
63
print ndef_message_data.encode("hex")
64
log.info(format_data(ndef_message_data))
65
ndef_message = nfc.ndef.Message(ndef_message_data)
66
log.info("NDEF records:")
67
for index, record in enumerate(ndef_message):
68
record_type = record.type
69
record_name = record.name
70
record_data = make_printable(record.data)
71
log.info(" [%d] type = %s" %(index, record_type))
72
log.info(" [%d] name = %s" %(index, record_name))
73
log.info(" [%d] data = %s" %(index, record_data))
74
if options.onemessage is True:
78
llcp_config = {'recv-miu': options.link_miu, 'send-lto': 1000}
79
if options.quirks == "android":
80
llcp_config['send-agf'] = False
82
for device in options.device:
83
try: clf = nfc.ContactlessFrontend(device); break
84
except LookupError: pass
89
general_bytes = nfc.llcp.startup(llcp_config)
90
peer = llcp_connect(clf, general_bytes)
91
if peer is None: break
93
nfc.llcp.activate(peer)
95
ndef_push_server = NdefPushServer()
96
ndef_push_server.start()
97
while nfc.llcp.connected() and not terminate.is_set():
99
except KeyboardInterrupt:
100
log.info("aborted by user")
104
log.info("I was the " + peer.role)
105
if options.loopmode is False:
110
def llcp_connect(clf, general_bytes):
113
if options.mode == "target" or options.mode is None:
114
listen_time = 250 + ord(os.urandom(1))
115
peer = clf.listen(listen_time, general_bytes)
116
if isinstance(peer, nfc.DEP):
117
if peer.general_bytes.startswith("Ffm"):
119
if options.mode == "initiator" or options.mode is None:
120
peer = clf.poll(general_bytes)
121
if isinstance(peer, nfc.DEP):
122
if peer.general_bytes.startswith("Ffm"):
123
if options.quirks == "android":
124
# Google Nexus S does not receive the first
125
# packet if we send immediately.
128
except KeyboardInterrupt:
129
log.info("aborted by user")
131
if __name__ == '__main__':
132
from optparse import OptionParser, OptionGroup
133
usage = "Usage: %prog [options] > message.ndef"
134
parser = OptionParser(usage)
135
parser.add_option("-b", default=False,
136
action="store_true", dest="binary",
137
help="write binary ndef to stdout")
138
parser.add_option("-1", default=False,
139
action="store_true", dest="onemessage",
140
help="terminate when an ndef message arrived")
141
parser.add_option("-l", default=False,
142
action="store_true", dest="loopmode",
143
help="run in endless loop (Ctrl-C to abort)")
144
parser.add_option("-q", default=True,
145
action="store_false", dest="verbose",
146
help="be quiet, only print errors")
147
parser.add_option("-d", type="string", default=[],
148
action="append", dest="debug", metavar="MODULE",
149
help="print debug messages for MODULE")
150
parser.add_option("-f", type="string",
151
action="store", dest="logfile",
152
help="write log messages to LOGFILE")
153
parser.add_option("--device", type="string", default=[],
154
action="append", dest="device", metavar="SPEC",
155
help="use only device(s) according to SPEC: "\
156
"usb[:vendor[:product]] (vendor and product in hex) "\
157
"usb[:bus[:dev]] (bus and device number in decimal) "\
158
"tty[:(usb|com)[:port]] (usb virtual or com port)")
159
parser.add_option("--mode", type="choice", default=None,
160
choices=["target", "initiator"],
161
action="store", dest="mode",
162
help="restrict mode to 'target' or 'initiator'")
163
parser.add_option("--link-miu", type="int", default=1024,
164
action="store", dest="link_miu", metavar="MIU",
165
help="set maximum information unit size to MIU")
166
parser.add_option("--quirks", type="string",
167
action="store", dest="quirks", metavar="choice",
168
help="quirks mode, choices are 'android'")
171
options, args = parser.parse_args()
173
verbosity = logging.INFO if options.verbose else logging.ERROR
174
logging.basicConfig(level=verbosity, format='%(message)s')
177
logfile_format = '%(asctime)s %(levelname)-5s [%(name)s] %(message)s'
178
logfile = logging.FileHandler(options.logfile, "w")
179
logfile.setFormatter(logging.Formatter(logfile_format))
180
logfile.setLevel(logging.DEBUG)
181
logging.getLogger('').addHandler(logfile)
183
import inspect, os, os.path
184
nfcpy_path = os.path.dirname(inspect.getfile(nfc))
185
for name in os.listdir(nfcpy_path):
186
if os.path.isdir(os.path.join(nfcpy_path, name)):
187
logging.getLogger("nfc."+name).setLevel(verbosity)
188
elif name.endswith(".py") and name != "__init__.py":
189
logging.getLogger("nfc."+name[:-3]).setLevel(verbosity)
192
logging.getLogger('').setLevel(logging.DEBUG)
193
logging.getLogger('nfc').setLevel(logging.DEBUG)
194
for module in options.debug:
195
log.info("enable debug output for module '{0}'".format(module))
196
logging.getLogger(module).setLevel(logging.DEBUG)
198
if len(options.device) == 0:
199
# search and use first
200
options.device = ["",]