summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Guiter <olivier.guiter@linux.intel.com>2011-07-05 11:10:53 +0200
committerMarcel Holtmann <marcel@holtmann.org>2011-10-20 23:54:05 -0700
commit45ff948c2522ddb40ce65f0b63e01abaf39c4afc (patch)
tree46111bc52095c18445b1ac036fed9473ce8379b3
parentdcd53ead634d7117b9349f6a90da992c521e4ceb (diff)
downloadneard-45ff948c2522ddb40ce65f0b63e01abaf39c4afc.tar.gz
neard-45ff948c2522ddb40ce65f0b63e01abaf39c4afc.tar.bz2
neard-45ff948c2522ddb40ce65f0b63e01abaf39c4afc.zip
nfctype1: NFC type 1 tag initial support
Only the static memory model is supported.
-rw-r--r--Makefile.plugins12
-rwxr-xr-xbootstrap-configure1
-rw-r--r--configure.ac6
-rwxr-xr-xplugins/nfctype1.c216
4 files changed, 235 insertions, 0 deletions
diff --git a/Makefile.plugins b/Makefile.plugins
index f511b54..597331e 100644
--- a/Makefile.plugins
+++ b/Makefile.plugins
@@ -3,6 +3,18 @@ plugin_cflags = -fvisibility=hidden -I$(srcdir)/gdbus \
@DBUS_CFLAGS@ @GLIB_CFLAGS@
plugin_ldflags = -no-undefined -module -avoid-version
+if NFCTYPE1
+if NFCTYPE1_BUILTIN
+builtin_modules += nfctype1
+builtin_sources += plugins/nfctype1.c
+else
+plugin_LTLIBRARIES += plugins/nfctype1.la
+plugin_objects += $(plugins_nfctype1_la_OBJECTS)
+plugins_nfctype1_la_CFLAGS = $(plugin_cflags)
+plugins_nfctype1_la_LDFLAGS = $(plugin_ldflags)
+endif
+endif
+
if NFCTYPE2
if NFCTYPE2_BUILTIN
builtin_modules += nfctype2
diff --git a/bootstrap-configure b/bootstrap-configure
index 0339672..7477bb4 100755
--- a/bootstrap-configure
+++ b/bootstrap-configure
@@ -7,5 +7,6 @@ fi
./bootstrap && \
./configure --enable-maintainer-mode \
--enable-debug \
+ --enable-nfctype1=builtin \
--enable-nfctype2=builtin \
--prefix=/usr $*
diff --git a/configure.ac b/configure.ac
index 74d845a..f9372b5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -82,6 +82,12 @@ AC_ARG_ENABLE(test, AC_HELP_STRING([--enable-test],
[enable test/example scripts]), [enable_test=${enableval}])
AM_CONDITIONAL(TEST, test "${enable_test}" = "yes")
+AC_ARG_ENABLE(nfctype1,
+ AC_HELP_STRING([--enable-nfctype1], [enable NFC forum type 1 tags support]),
+ [enable_nfctype1=${enableval}], [enable_nfctype1="no"])
+AM_CONDITIONAL(NFCTYPE1, test "${enable_nfctype1}" != "no")
+AM_CONDITIONAL(NFCTYPE1_BUILTIN, test "${enable_nfctype1}" = "builtin")
+
AC_ARG_ENABLE(nfctype2,
AC_HELP_STRING([--enable-nfctype2], [enable NFC forum type 2 tags support]),
[enable_nfctype2=${enableval}], [enable_nfctype2="no"])
diff --git a/plugins/nfctype1.c b/plugins/nfctype1.c
new file mode 100755
index 0000000..d9c2954
--- /dev/null
+++ b/plugins/nfctype1.c
@@ -0,0 +1,216 @@
+/*
+ *
+ * neard - Near Field Communication manager
+ *
+ * Copyright (C) 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdint.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/socket.h>
+
+#include <linux/socket.h>
+#include <linux/nfc.h>
+
+#include <near/plugin.h>
+#include <near/log.h>
+#include <near/types.h>
+#include <near/adapter.h>
+#include <near/target.h>
+#include <near/tag.h>
+#include <near/ndef.h>
+#include <near/tlv.h>
+
+#define CMD_READ_ALL 0x00 // Read all bytes (incl: HR)
+
+#define OFFSET_STATUS_CMD 0x00
+#define OFFSET_HEADER_ROM 0x01
+
+#define HR0_TYPE1_STATIC 0x11
+
+#define LEN_STATUS_BYTE 0x01 /* Status byte */
+#define LEN_SPEC_BYTES (LEN_STATUS_BYTE + 0x02) /* HRx */
+#define LEN_UID_BYTES (LEN_STATUS_BYTE + 0x07) /* UID bytes */
+#define LEN_CC_BYTES 0x04 /* Capab. container */
+
+#define TYPE1_MAGIC 0xe1
+
+#define TAG_T1_DATA_CC(data) ((data) + LEN_SPEC_BYTES + LEN_UID_BYTES )
+#define TAG_T1_DATA_LENGTH(cc) ((cc)[2] * 8 - LEN_CC_BYTES)
+#define TAG_T1_DATA_NFC(cc) ((cc)[0] & TYPE1_MAGIC)
+
+struct type1_cmd {
+ uint8_t cmd;
+ uint8_t offset;
+ uint8_t data[];
+} __attribute__((packed));
+
+struct type1_tag {
+ uint32_t adapter_idx;
+ uint16_t current_block;
+
+ near_tag_read_cb cb;
+ struct near_tag *tag;
+};
+
+struct recv_cookie {
+ uint32_t adapter_idx;
+ uint32_t target_idx;
+ near_tag_read_cb cb;
+};
+
+static int meta_recv(uint8_t *resp, int length, void *data)
+{
+ struct recv_cookie *cookie = data;
+ struct near_tag *tag;
+ struct type1_tag *t1_tag;
+ uint8_t *cc;
+ int err;
+
+ DBG("%d", length);
+
+ if (length < 0) {
+ err = length;
+ goto out;
+ }
+
+ /* First byte is cmd status */
+ if (resp[OFFSET_STATUS_CMD] != 0) {
+ DBG("Command failed: 0x%x",resp[OFFSET_STATUS_CMD]);
+ err = -EIO;
+ goto out;
+ }
+
+ /* Check Magic NFC tag */
+ cc = TAG_T1_DATA_CC(resp);
+
+ if (TAG_T1_DATA_NFC(cc) == 0) {
+ DBG("Not a valid NFC magic tag: 0x%x",cc[0]);
+ err = -EINVAL;
+ goto out;
+ }
+
+ /* Associate the DATA length to the tag */
+ tag = near_target_add_tag(cookie->adapter_idx, cookie->target_idx,
+ TAG_T1_DATA_LENGTH(cc));
+ if (tag == NULL) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ t1_tag = g_try_malloc0(sizeof(struct type1_tag));
+ if (t1_tag == NULL) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ t1_tag->adapter_idx = cookie->adapter_idx;
+ t1_tag->cb = cookie->cb;
+ t1_tag->tag = tag;
+
+ /* Save the UID */
+ near_tag_set_uid(tag, resp + LEN_SPEC_BYTES, LEN_UID_BYTES);
+
+ /* Check Static or Dynamic memory model */
+ if (resp[OFFSET_HEADER_ROM] == HR0_TYPE1_STATIC) {
+ err = near_tlv_parse(t1_tag->tag, t1_tag->cb,
+ cc + LEN_CC_BYTES, TAG_T1_DATA_LENGTH(cc));
+ near_adapter_disconnect(t1_tag->adapter_idx);
+ }
+ else
+ err = -EOPNOTSUPP ;
+
+out:
+ g_free(cookie);
+
+ if (err < 0 && cookie->cb)
+ cookie->cb(cookie->adapter_idx, err);
+
+ return err;
+}
+
+/* First step: READALL to read a maximum of 124 bytes
+ * This cmd is common to static and dynamic targets
+ * This should allow to get the HR0 byte
+ */
+static int nfctype1_read_all(uint32_t adapter_idx, uint32_t target_idx,
+ near_tag_read_cb cb)
+{
+ struct type1_cmd t1_cmd;
+ struct recv_cookie *cookie;
+
+ DBG("");
+
+ t1_cmd.cmd = CMD_READ_ALL; /* Read ALL cmd give 124 bytes */
+ t1_cmd.offset = 0; /* NA */
+
+ cookie = g_try_malloc0(sizeof(struct recv_cookie));
+ cookie->adapter_idx = adapter_idx;
+ cookie->target_idx = target_idx;
+ cookie->cb = cb;
+
+ return near_adapter_send(adapter_idx, (uint8_t *)&t1_cmd, sizeof(t1_cmd),
+ meta_recv, cookie);
+}
+
+static int nfctype1_read_tag(uint32_t adapter_idx,
+ uint32_t target_idx, near_tag_read_cb cb)
+{
+ int err;
+
+ DBG("");
+
+ err = near_adapter_connect(adapter_idx, target_idx, NFC_PROTO_JEWEL);
+ if (err < 0) {
+ near_error("Could not connect %d", err);
+
+ return err;
+ }
+
+ err = nfctype1_read_all(adapter_idx, target_idx, cb);
+ if (err < 0)
+ near_adapter_disconnect(adapter_idx);
+
+ return err;
+}
+
+static struct near_tag_driver type1_driver = {
+ .type = NEAR_TAG_NFC_TYPE1,
+ .read_tag = nfctype1_read_tag,
+};
+
+static int nfctype1_init(void)
+{
+ DBG("");
+
+ return near_tag_driver_register(&type1_driver);
+}
+
+static void nfctype1_exit(void)
+{
+ DBG("");
+
+ near_tag_driver_unregister(&type1_driver);
+}
+
+NEAR_PLUGIN_DEFINE(nfctype1, "NFC Forum Type 1 tags support", VERSION,
+ NEAR_PLUGIN_PRIORITY_HIGH, nfctype1_init, nfctype1_exit)