neard 0.7
authorOlivier Guiter <olivier.guiter@linux.intel.com>
Wed, 10 Oct 2012 10:22:12 +0000 (12:22 +0200)
committerOlivier Guiter <olivier.guiter@linux.intel.com>
Wed, 10 Oct 2012 10:22:12 +0000 (12:22 +0200)
With this release we got 2 new additions:

- Android Jelly Bean (4.1.1) handover support: Android JB implements Bluetooth
  handover support through SNEP. Although this is not following the NFC Forum
  handover specs (And is violating the SNEP specs as well), we have no choice
  but supporting it since JB is (or will be) the most deployed OS supporting
  NFC handover.
  We have to support both handover services (The NFC Forum one and JB one) and
  for that matter we introduced an fallback service name for each p2p plugin.
  So the handover one first tries the urn:nfc:sn:handover service and falls
  back to urn:nfc:sn:snep if the peer does not provide a regular handover
  service.
  This seems to work well and we now support both NFC Forum and Android JB
  handover flawlessly.

- MIFARE tag support improvements: Thanks to Dorota Moskal (Tieto) our MIFARE
  support improved quite a bit. We now have MIFARE Classic writing support and
  we also have a presence check implementation for it. Dorota also implemented
  the read only support for those tags and she has still a few patches pending
  for MIFARE formatting and custom authentication keys handling.

12 files changed:
ChangeLog
configure.ac
include/adapter.h
packaging/neard.changes
packaging/neard.spec
plugins/mifare.c
plugins/nfctype1.c
plugins/nfctype2.c
plugins/nfctype3.c
plugins/nfctype4.c
src/adapter.c
src/tag.c

index c1b2f76..8dd8047 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+ver 0.7
+       Added support for Android Jelly Bean handover.
+       Added a Bluetooth handover automated script.
+       Added MIFARE Classic writing support.
+       Added MIFARE read only check support.
+       Added MIFARE check presence support.
+       Fixed a tag writing related double free.
+       Fixed tag plugins memory leaks.
+       Fixed tag plugins callback calls code paths.
+       Fixed URI NDEF writing.
+
 ver 0.6
        Added tag formatting support for Type 1, 3 an 4.
        Added blank tag detection for Type 1, 3 and 4.
index 36e2b17..d8a4faf 100644 (file)
@@ -1,5 +1,5 @@
 AC_PREREQ(2.60)
-AC_INIT(neard, 0.6)
+AC_INIT(neard, 0.7)
 
 AM_INIT_AUTOMAKE([foreign subdir-objects color-tests])
 AM_CONFIG_HEADER(config.h)
index faf32ba..e547d3d 100644 (file)
 #include <unistd.h>
 
 typedef int (*near_recv)(uint8_t *resp, int length, void *data);
+typedef int (*near_release)(int err, void *data);
 
 int near_adapter_connect(uint32_t idx, uint32_t target_idx, uint8_t protocol);
 int near_adapter_disconnect(uint32_t idx);
-int near_adapter_send(uint32_t idx, uint8_t *buf, size_t length, near_recv rx_cb, void *data);
+int near_adapter_send(uint32_t idx, uint8_t *buf, size_t length,
+                       near_recv rx_cb, void *data, near_release data_rel);
 int near_adapter_recv(uint32_t idx, uint8_t *buf, size_t length);
 
 #endif
index 8f959f7..2c17a82 100644 (file)
@@ -1,2 +1,5 @@
+* Wed Oct 10 2012 Olivier < olivier.guiter@intel.com> - 0.7
+- Upgrade to version 0.7
 * Tue Aug 28 2012 Arron < arron.wang@intel.com> - 0.6
 - Upgrade to version 0.6
+
index d695cd8..f494b6c 100644 (file)
@@ -2,8 +2,8 @@
 %define kernel_target adaptation-intel-automotive
 Name:      neard
 Summary:    Near Field Communication Manager
-Version:    0.6
-Release:    7
+Version:    0.7
+Release:    1
 Group:      System Environment/Daemons
 License:    GPLv2
 Source0:    http://www.kernel.org/pub/linux/network/nfc/%{name}-%{version}.tar.bz2
index 72120fe..b2249e2 100644 (file)
@@ -110,6 +110,14 @@ static uint8_t MAD_NFC_key[] = {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7};
 
 #define NFC_1ST_BLOCK          0x04    /* Sectors from 1 are for NFC */
 
+#define ACC_BITS_LEN            3
+
+/* Access bits for data blocks mask */
+static uint8_t DATA_access_mask[] = {0x77, 0x77, 0x77};
+
+/* Write with key A access bits configuration */
+static uint8_t WRITE_with_key_A[] = {0x77, 0x07, 0x00};
+
 /* MAD1 sector structure. Start at block 0x00 */
 struct MAD_1 {
        uint8_t man_info[16];
@@ -142,7 +150,6 @@ struct mifare_cookie {
        struct near_tag *tag;
        near_tag_io_cb cb;
        near_recv next_far_func;
-       int (*command)(void *data); /* read or write after unlocking sector */
 
        /* For MAD access */
        struct MAD_1 *mad_1;
@@ -166,6 +173,13 @@ struct mifare_cookie {
        /* For write only */
        struct near_ndef_message *ndef; /* message to write */
        size_t ndef_length;             /* message length */
+
+       /* For access check */
+       int (*acc_check_function)(void *data);  /* acc check fnc */
+       uint8_t *acc_bits_mask;                 /* blocks to check */
+       uint8_t *acc_rights;                    /* condition */
+       int (*acc_denied_fct)(void *data);/* fnc to call on access denial */
+       GSList *acc_sect;                 /* sector from g_sect_list to check */
 };
 
 struct type2_cmd {
@@ -253,8 +267,7 @@ static int mifare_unlock_sector(int block_id,
 
        return near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd,
                sizeof(cmd) - NFC_NFCID1_MAXSIZE + cookie->nfcid1_len,
-               next_far_fct,
-               cookie);
+               next_far_fct, cookie, mifare_release);
 }
 
 /*
@@ -276,9 +289,64 @@ static int mifare_read_block(uint8_t block_id,
        cmd.cmd = MF_CMD_READ; /* MIFARE READ */
        cmd.block = block_id;
 
-       return near_adapter_send(mf_ck->adapter_idx,
-                       (uint8_t *) &cmd, 2,
-                       far_func, data);
+       return near_adapter_send(mf_ck->adapter_idx, (uint8_t *) &cmd, 2,
+                                       far_func, mf_ck, mifare_release);
+}
+
+/*
+ * Check access rights
+ * Function processes sector trailer received from tag and checks access rights.
+ * In case specified access isn't granted it calls appropriate
+ * access denial function.
+ * If access is granted, previous action (e.g. read, write) is continued.
+ */
+static int mifare_check_rights_cb(uint8_t *resp, int length, void *data)
+{
+       struct mifare_cookie *mf_ck = data;
+       int err;
+       uint8_t *c;
+       int i;
+
+       if (length < 0) {
+               err = length;
+               goto out_err;
+       }
+
+       /* skip reader byte and key A */
+        c = resp + 1 + MAD_KEY_LEN;
+
+       for (i = 0; i < ACC_BITS_LEN; i++) {
+               if ((c[i] & mf_ck->acc_bits_mask[i]) != mf_ck->acc_rights[i]) {
+                       (*mf_ck->acc_denied_fct)(data);
+                       return 0;
+               }
+       }
+
+       /* Continue previous action (read/write) */
+       err = (*mf_ck->rws_next_fct)(resp, length, data);
+
+       if (err < 0)
+               goto out_err;
+
+       return err;
+
+out_err:
+       return mifare_release(err, mf_ck);
+}
+
+/* Calls to mifare_read_block to get sector trailer */
+static int mifare_check_rights(uint8_t *resp, int length, void *data)
+{
+       struct mifare_cookie *mf_ck = data;
+       int err;
+
+       err = mifare_read_block(mf_ck->rws_block_start, mf_ck,
+                       mifare_check_rights_cb);
+
+       if (err < 0)
+               return mifare_release(err, mf_ck);
+
+       return err;
 }
 
 static int mifare_read_sector_cb(uint8_t *resp, int length, void *data)
@@ -331,7 +399,7 @@ static int mifare_read_sector_unlocked(uint8_t *resp, int length, void *data)
 
        if (length < 0) {
                err = length;
-               return err;
+               goto out_err;
        }
        /* And run the read process on the first block of the sector */
        err = mifare_read_block(mf_ck->rws_block_start, data,
@@ -342,7 +410,7 @@ static int mifare_read_sector_unlocked(uint8_t *resp, int length, void *data)
        return err;
 
 out_err:
-       return err;
+       return mifare_release(err, mf_ck);
 }
 
 /*
@@ -409,7 +477,7 @@ static int mifare_read_NFC_loop(uint8_t *resp, int length, void *data)
 
        if (length < 0) {
                err = length;
-               return err;
+               goto out_err;
        }
 
        /* ptr to the next read ptr */
@@ -420,7 +488,7 @@ static int mifare_read_NFC_loop(uint8_t *resp, int length, void *data)
 
 
        /* Additional sectors to read ? */;
-       if (mf_ck->g_sect_list->next != NULL) {
+       if (mf_ck->g_sect_list != NULL && mf_ck->g_sect_list->next != NULL) {
 
                err = mifare_read_sector(data,  /* cookie */
                        mf_ck->nfc_data,                /* where to store */
@@ -459,7 +527,7 @@ out_err:
 }
 
 /* Prepare read NFC loop */
-static int mifare_read_NFC(void *data)
+static int mifare_read_NFC(uint8_t *resp, int length, void *data)
 {
        struct mifare_cookie *mf_ck = data;
        int err;
@@ -493,6 +561,8 @@ static int mifare_process_MADs(void *data)
        int i;
        int global_tag_size = 0;
        int ioffset;
+       uint8_t *tag_data;
+       size_t data_size;
 
        DBG("");
 
@@ -502,9 +572,20 @@ static int mifare_process_MADs(void *data)
                goto out_err;
        }
 
-       for (i = 0; i < MAD_V1_AIDS_LEN; i++) {
+       /* Skip non-NFC sectors at the beginning of the tag, if any */
+       for (i = 0 ; i < MAD_V1_AIDS_LEN; i++) {
+               if (mf_ck->mad_1->aids[i] == NFC_AID_TAG)
+                       break;
+       }
+
+       /*
+        * NFC sectors have to be continuous,
+        * so only some sectors at the beginning and at the end of tag
+        * can be non-NFC.
+        */
+       for (; i < MAD_V1_AIDS_LEN; i++) {
                if (mf_ck->mad_1->aids[i] != NFC_AID_TAG)
-                       continue;
+                       goto done_mad;
 
                /* Save in the global list */
                mf_ck->g_sect_list = g_slist_append(mf_ck->g_sect_list,
@@ -517,9 +598,20 @@ static int mifare_process_MADs(void *data)
        if (mf_ck->mad_2 == NULL)
                goto done_mad;
 
-       for (i = 0; i < MAD_V2_AIDS_LEN; i++) {
+       /*
+        * If all sectors from MAD1 were non-NFC,
+        * skip initial non-NFC sectors from MAD2
+        */
+       i = 0;
+
+       if (global_tag_size == 0)
+               for (; i < MAD_V2_AIDS_LEN; i++)
+                       if (mf_ck->mad_2->aids[i] == NFC_AID_TAG)
+                               break;
+
+       for (; i < MAD_V2_AIDS_LEN; i++) {
                if (mf_ck->mad_2->aids[i] != NFC_AID_TAG)
-                       continue;
+                       goto done_mad;
 
                mf_ck->g_sect_list = g_slist_append( mf_ck->g_sect_list,
                                                GINT_TO_POINTER(ioffset + i));
@@ -530,24 +622,40 @@ static int mifare_process_MADs(void *data)
        }
 
 done_mad:
+       if (global_tag_size == 0) {
+
+               /* no NFC sectors - mark tag as blank */
+               near_error("TAG Global size: [%d], not valid NFC tag.",
+                               global_tag_size);
+               return -ENODEV;
+       }
+
        /* n sectors, each sector is 3 blocks, each block is 16 bytes */
        DBG("TAG Global size: [%d]", global_tag_size);
 
-       err = near_tag_add_data(mf_ck->adapter_idx,
-                                               mf_ck->target_idx,
-                                               NULL, /* Empty */
-                                               global_tag_size);
-       if (err < 0)
-               goto out_err;
-
        mf_ck->tag = near_tag_get_tag(mf_ck->adapter_idx, mf_ck->target_idx);
        if (mf_ck->tag == NULL) {
                err = -ENOMEM;
                goto out_err;
        }
 
-       /* Time to read or write the NFC data */
-       err = mf_ck->command(mf_ck);
+       /* don't allocate new data before writing */
+       tag_data = near_tag_get_data(mf_ck->tag, &data_size);
+       if (tag_data == NULL) {
+               err = near_tag_add_data(mf_ck->adapter_idx,
+                                               mf_ck->target_idx,
+                                               NULL, /* Empty */
+                                               global_tag_size);
+
+               if (err < 0)
+                       goto out_err;
+       }
+
+       /* Check access rights */
+       err = mf_ck->acc_check_function(data);
+
+       if (err < 0)
+               goto out_err;
 
        return err;
 
@@ -656,6 +764,52 @@ out_err:
        return mifare_release(err, mf_ck);
 }
 
+/* If first NFC sector isn't writable, mark whole tag as read only */
+static int is_read_only(void *data)
+{
+       struct mifare_cookie *mf_ck = data;
+
+       DBG("Tag is read only");
+
+       near_tag_set_ro(mf_ck->tag, TRUE);
+
+       /* Continue previous action (read) */
+       (*mf_ck->rws_next_fct)(NULL, 0, data);
+
+       return 0;
+}
+
+
+static int mifare_check_read_only(void *data)
+{
+       struct mifare_cookie *mf_ck = data;
+       int err;
+
+       DBG("");
+
+       /*
+        * As authorisation with key B is not supported,
+        * in case writing with key A is not permitted, tag is read-only
+        */
+       mf_ck->acc_bits_mask = DATA_access_mask;
+       mf_ck->acc_rights = WRITE_with_key_A;
+
+       /* Check acces rights of first NFC sector */
+       mf_ck->rws_block_start = NFC_1ST_BLOCK + STD_BLK_PER_SECT;
+       /* Afterwards read tag */
+       mf_ck->rws_next_fct = mifare_read_NFC;
+       /* In case of writing access denial, set read only */
+       mf_ck->acc_denied_fct = is_read_only;
+
+       err = mifare_unlock_sector(mf_ck->rws_block_start,
+                       mifare_check_rights, mf_ck);
+
+       if (err < 0)
+               return mifare_release(err, mf_ck);
+
+       return err;
+}
+
 /*
  * MIFARE: entry point:
  * Read all the MAD sectors (0x00, 0x10) to get the Application Directory
@@ -693,7 +847,9 @@ int mifare_read(uint32_t adapter_idx, uint32_t target_idx,
        cookie->adapter_idx = adapter_idx;
        cookie->target_idx = target_idx;
        cookie->cb = cb;
-       cookie->command = mifare_read_NFC;
+
+       /* check access rights - while reading just check read only */
+       cookie->acc_check_function = mifare_check_read_only;
 
        /*
         * Need to unlock before reading
@@ -716,13 +872,16 @@ static int check_presence(uint8_t *resp, int length, void *data)
 
        DBG("%d", length);
 
-       if (length < 0)
+       if (length < 0) {
                err = -EIO;
+               goto out;
+       }
 
        if (cookie->cb)
                cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
 
-       return err;
+out:
+       return mifare_release(err, cookie);
 }
 
 int mifare_check_presence(uint32_t adapter_idx, uint32_t target_idx,
@@ -731,7 +890,6 @@ int mifare_check_presence(uint32_t adapter_idx, uint32_t target_idx,
        struct mifare_cmd cmd;
        struct mifare_cookie *cookie;
        uint8_t *key_ref = MAD_public_key;
-       int err;
 
        DBG("");
 
@@ -772,21 +930,11 @@ int mifare_check_presence(uint32_t adapter_idx, uint32_t target_idx,
        /* add the UID */
        memcpy(&cmd.nfcid, cookie->nfcid1, cookie->nfcid1_len);
 
-       err = near_adapter_send(cookie->adapter_idx,
+       return near_adapter_send(cookie->adapter_idx,
                        (uint8_t *) &cmd,
                        sizeof(cmd) - NFC_NFCID1_MAXSIZE + cookie->nfcid1_len,
                        check_presence,
-                       cookie);
-
-       if (err < 0)
-               goto out_err;
-
-       return err;
-
-out_err:
-       mifare_release(err, cookie);
-
-       return err;
+                       cookie, mifare_release);
 }
 
 /*
@@ -817,7 +965,7 @@ static int mifare_write_block(uint8_t block_id, void *data,
 
        return near_adapter_send(mf_ck->adapter_idx,
                                (uint8_t *) &cmd, sizeof(cmd),
-                               far_func, data);
+                               far_func, data, NULL);
 }
 
 static int mifare_correct_length_cb(uint8_t *resp, int length, void *data)
@@ -885,10 +1033,23 @@ static int mifare_write_sector_cb(uint8_t *resp, int length, void *data)
 static int mifare_write_sector_unlocked(uint8_t *resp, int length, void *data)
 {
        struct mifare_cookie *mf_ck = data;
+       int err;
+
+       if (length < 0) {
+               err = length;
+               goto out_err;
+       }
 
        /* Run the write process on the first block of the sector */
-       return mifare_write_block(mf_ck->rws_block_start, data,
-                                       mifare_write_sector_cb);
+       err = mifare_write_block(mf_ck->rws_block_start, data,
+                       mifare_write_sector_cb);
+
+       if (err < 0)
+               goto out_err;
+       return err;
+
+out_err:
+       return mifare_release(err, mf_ck);
 }
 
 /*
@@ -993,6 +1154,127 @@ static int mifare_write_NFC(void *data)
        return err;
 }
 
+static int mifare_check_rights_loop(uint8_t *resp, int length, void *data)
+{
+       struct mifare_cookie *mf_ck = data;
+       int err;
+       int sector_id;
+
+       if (mf_ck->acc_sect->next != NULL) {
+
+               mf_ck->acc_sect = mf_ck->acc_sect->next;
+               sector_id = GPOINTER_TO_INT(mf_ck->acc_sect->data);
+
+               if (sector_id < T4K_BOUNDARY)
+                       mf_ck->rws_block_start = sector_id * 4
+                                                       + STD_BLK_PER_SECT;
+               else
+                       mf_ck->rws_block_start = T4K_BLK_OFF + EXT_BLK_PER_SECT
+                               + (sector_id - T4K_BOUNDARY) * 16;
+
+               err = mifare_unlock_sector(mf_ck->rws_block_start,
+                               mifare_check_rights, mf_ck);
+       } else {
+               /* Full access granted, start writing */
+               err = mifare_write_NFC(data);
+       }
+
+       if (err < 0)
+               return mifare_release(err, mf_ck);
+
+       return err;
+}
+
+
+/*
+ * If one of NFC sectors isn't writable,
+ * tag size for writing is smaller than actual memory size,
+ * so calculate it and check if it is enough for ndef message.
+ */
+static int writing_not_permitted(void *data)
+{
+       struct mifare_cookie *mf_ck = data;
+       unsigned int new_tag_size = 0;
+       int sector_id;
+       int i;
+
+       sector_id = GPOINTER_TO_INT(mf_ck->acc_sect->data);
+       DBG("Writing sector %i not permitted", sector_id);
+
+       /* Read only sector found, calculate new tag size */
+       if (sector_id <= MAD_V1_AIDS_LEN) {
+               for (i = GPOINTER_TO_INT(mf_ck->g_sect_list->data);
+                               i < sector_id; i++)
+                       new_tag_size += SECTOR_SIZE;
+       } else {
+               /* Start from first NFC sector */
+               for (i = GPOINTER_TO_INT(mf_ck->g_sect_list->data);
+                               i <= MAD_V1_AIDS_LEN; i++)
+                       new_tag_size += SECTOR_SIZE;
+
+               /*
+                * If any of previous sector was NFC, skip MAD2
+                * If not, leave "i" as it was
+                */
+               if (i < MAD2_SECTOR)
+                       i = MAD2_SECTOR + 1;
+
+               for (; i < sector_id; i++) {
+                       if (i < T4K_BOUNDARY)
+                               new_tag_size += SECTOR_SIZE;
+                       else
+                               new_tag_size += BIG_SECTOR_SIZE;
+               }
+       }
+
+       DBG("TAG writable sectors' size: [%d].", new_tag_size);
+
+       /* Check if there's enough space on tag */
+       if (new_tag_size < mf_ck->ndef->length) {
+               near_error("Not enough space on tag");
+
+               if (mf_ck->cb)
+                       mf_ck->cb(mf_ck->adapter_idx,
+                                       mf_ck->target_idx, -ENOSPC);
+
+               mifare_release(0, data);
+               return -ENOSPC;
+       }
+
+       /* Enough space on tag, continue writing */
+       mifare_write_NFC(data);
+
+       return 0;
+}
+
+static int mifare_check_rights_NFC(void *data)
+{
+       struct mifare_cookie *mf_ck = data;
+       int err;
+
+       DBG("");
+
+       /*
+        * As authorisation with key B is not supported,
+        * in case writing with key A is not permitted, tag is read-only
+        */
+       mf_ck->acc_bits_mask = DATA_access_mask;
+       mf_ck->acc_rights = WRITE_with_key_A;
+
+       mf_ck->acc_sect = mf_ck->g_sect_list;
+       mf_ck->rws_block_start = NFC_1ST_BLOCK + STD_BLK_PER_SECT;
+       mf_ck->rws_next_fct = mifare_check_rights_loop;
+
+       mf_ck->acc_denied_fct = writing_not_permitted;
+       err = mifare_unlock_sector(mf_ck->rws_block_start,
+                       mifare_check_rights, mf_ck);
+
+       if (err < 0)
+               return mifare_release(err, mf_ck);
+
+       return err;
+}
+
 int mifare_write(uint32_t adapter_idx, uint32_t target_idx,
                        struct near_ndef_message *ndef,
                        near_tag_io_cb cb, enum near_tag_sub_type tgt_subtype)
@@ -1035,11 +1317,17 @@ int mifare_write(uint32_t adapter_idx, uint32_t target_idx,
        cookie->target_idx = target_idx;
        cookie->cb = cb;
 
-       cookie->command = mifare_write_NFC;
        cookie->ndef = ndef;
        /* Save ndef length */
        cookie->ndef_length = cookie->ndef->data[1];
        cookie->ndef->data[1] = 0;
+
+       /*
+        * Check if all sectors are writable
+        * if not, message may be too long to be written
+        */
+       cookie->acc_check_function = mifare_check_rights_NFC;
+
        /*
         * Mifare Classic Tag needs to be unlocked before writing
         * This will check if public keys are allowed (NDEF could be "readable")
index 4042429..936bf89 100644 (file)
@@ -128,6 +128,9 @@ static int t1_cookie_release(int err, void *data)
        if (cookie == NULL)
                return err;
 
+       if (cookie->cb != NULL)
+               cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
+
        if (cookie->ndef)
                g_free(cookie->ndef->data);
 
@@ -146,14 +149,10 @@ static int data_recv(uint8_t *resp, int length, void *data)
        uint8_t *tagdata;
        size_t data_length;
 
-       int err;
-
        DBG("%d", length);
 
-       if (length < 0) {
-               err = length;
-               goto out_err;
-       }
+       if (length < 0)
+               return length;
 
        length = length - LEN_STATUS_BYTE;  /* ignore first byte */
 
@@ -172,11 +171,9 @@ static int data_recv(uint8_t *resp, int length, void *data)
                t1_cmd.cmd = CMD_READ_SEGS;
                t1_cmd.addr = (t1_tag->current_seg << 4) & 0xFF;
 
-               err = near_adapter_send(t1_tag->adapter_idx,
+               return near_adapter_send(t1_tag->adapter_idx,
                                (uint8_t *) &t1_cmd, sizeof(t1_cmd),
-                               data_recv, t1_tag);
-               if (err < 0)
-                       goto out_err;
+                               data_recv, t1_tag, NULL);
        } else { /* This is the end */
                GList *records;
 
@@ -185,14 +182,11 @@ static int data_recv(uint8_t *resp, int length, void *data)
                records = near_tlv_parse(tagdata, data_length);
                near_tag_add_records(t1_tag->tag, records, t1_tag->cb, 0);
 
-               err = 0;
-
                /* free memory */
                g_free(t1_tag);
-       }
 
-out_err:
-       return err;
+               return 0;
+       }
 }
 
 /*
@@ -240,7 +234,7 @@ static int read_dynamic_tag(uint8_t *cc, int length, void *data)
 
        return near_adapter_send(t1_tag->adapter_idx,
                        (uint8_t *)&t1_cmd, sizeof(t1_cmd),
-                       data_recv, t1_tag);
+                       data_recv, t1_tag, NULL);
 }
 
 static int meta_recv(uint8_t *resp, int length, void *data)
@@ -338,6 +332,11 @@ static int meta_recv(uint8_t *resp, int length, void *data)
        } else if ((resp[OFFSET_HEADER_ROM] & 0xF0) == HR0_TYPE2_HIGH) {
                near_tag_set_memory_layout(tag, NEAR_TAG_MEMORY_DYNAMIC);
                err = read_dynamic_tag(cc, length, t1_tag);
+               /*
+                * As reading isn't complete,
+                * callback shouldn't be called while freeing the cookie
+                */
+               cookie->cb = NULL;
        } else {
                err = -EOPNOTSUPP;
        }
@@ -348,9 +347,6 @@ static int meta_recv(uint8_t *resp, int length, void *data)
 out_err:
        DBG("err %d", err);
 
-       if (err < 0 && cookie->cb)
-               cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
-
        return t1_cookie_release(err, cookie);
 }
 
@@ -391,14 +387,11 @@ static int rid_resp(uint8_t *resp, int length, void *data)
 
        return near_adapter_send(cookie->adapter_idx,
                                (uint8_t *)&t1_cmd, sizeof(t1_cmd),
-                               meta_recv, cookie);
+                               meta_recv, cookie, t1_cookie_release);
 
 out_err:
        DBG("err %d", err);
 
-       if (err < 0 && cookie->cb)
-               cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
-
        return t1_cookie_release(err, cookie);
 }
 
@@ -407,7 +400,6 @@ static int nfctype1_read_meta(uint32_t adapter_idx, uint32_t target_idx,
 {
        struct type1_cmd cmd;
        struct t1_cookie *cookie;
-       int err;
 
        DBG("");
 
@@ -426,19 +418,16 @@ static int nfctype1_read_meta(uint32_t adapter_idx, uint32_t target_idx,
                memcpy(cmd.uid, uid, UID_LENGTH);
                memcpy(cookie->uid, uid, UID_LENGTH);
 
-               err = near_adapter_send(adapter_idx, (uint8_t *) &cmd,
-                                               sizeof(cmd), meta_recv, cookie);
+               return near_adapter_send(adapter_idx, (uint8_t *) &cmd,
+                                               sizeof(cmd), meta_recv, cookie,
+                                               t1_cookie_release);
        } else {
                cmd.cmd = CMD_RID;
 
-               err = near_adapter_send(adapter_idx, (uint8_t *) &cmd,
-                                               sizeof(cmd), rid_resp, cookie);
+               return near_adapter_send(adapter_idx, (uint8_t *) &cmd,
+                                               sizeof(cmd), rid_resp, cookie,
+                                               t1_cookie_release);
        }
-
-       if (err < 0)
-               t1_cookie_release(err, cookie);
-
-       return err;
 }
 
 /* First step: RID to get the tag UID */
@@ -485,8 +474,6 @@ static int write_nmn_e1_resp(uint8_t *resp, int length, void *data)
 
        DBG("Done writing");
 
-       cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
-
        return t1_cookie_release(err, cookie);
 }
 
@@ -502,7 +489,8 @@ static int write_nmn_e1(struct t1_cookie *cookie)
        memcpy(cmd.uid, cookie->uid, UID_LENGTH);
 
        return near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd,
-                                       sizeof(cmd), write_nmn_e1_resp, cookie);
+                                       sizeof(cmd), write_nmn_e1_resp, cookie,
+                                       t1_cookie_release);
 }
 
 static int data_write_resp(uint8_t *resp, int length, void *data)
@@ -541,16 +529,14 @@ static int data_write_resp(uint8_t *resp, int length, void *data)
        cookie->current_byte++;
 
        err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd,
-                                       sizeof(cmd), data_write_resp, cookie);
+                                       sizeof(cmd), data_write_resp, cookie,
+                                       NULL);
        if (err < 0)
                goto out_err;
 
        return 0;
 
 out_err:
-       if (err < 0 && cookie->cb)
-               cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
-
        return t1_cookie_release(err, cookie);
 }
 
@@ -567,7 +553,8 @@ static int data_write(uint32_t adapter_idx, uint32_t target_idx,
        uid = near_tag_get_nfcid(adapter_idx, target_idx, &uid_length);
        if (uid == NULL || uid_length != UID_LENGTH) {
                near_error("Invalid type 1 UID");
-               return -EINVAL;
+               err = -EINVAL;
+               goto out_err;
        }
 
        cmd.cmd  = CMD_WRITE_E;
@@ -579,7 +566,7 @@ static int data_write(uint32_t adapter_idx, uint32_t target_idx,
        if (cookie == NULL) {
                g_free(uid);
                err = -ENOMEM;
-               return err;
+               goto out_err;
        }
 
        cookie->adapter_idx = adapter_idx;
@@ -592,15 +579,14 @@ static int data_write(uint32_t adapter_idx, uint32_t target_idx,
 
        g_free(uid);
 
-       err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd,
-                                       sizeof(cmd), data_write_resp, cookie);
-       if (err < 0)
-               goto out_err;
-
-       return 0;
-
+       return near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd,
+                                       sizeof(cmd), data_write_resp, cookie,
+                                       t1_cookie_release);
 out_err:
-       return t1_cookie_release(err, cookie);
+       if (cb != NULL)
+               cb(adapter_idx, target_idx, err);
+
+       return err;
 }
 
 /*
@@ -618,15 +604,20 @@ static int nfctype1_write(uint32_t adapter_idx, uint32_t target_idx,
                                near_tag_io_cb cb)
 {
        struct near_tag *tag;
+       int err;
 
        DBG("");
 
-       if (ndef == NULL || cb == NULL)
-               return -EINVAL;
+       if (ndef == NULL || cb == NULL) {
+               err = -EINVAL;
+               goto out_err;
+       }
 
        tag = near_tag_get_tag(adapter_idx, target_idx);
-       if (tag == NULL)
-               return -EINVAL;
+       if (tag == NULL) {
+               err = -EINVAL;
+               goto out_err;
+       }
 
        /* This check is valid for only static tags.
         * Max data length on Type 1 Tag including TLV's
@@ -634,11 +625,23 @@ static int nfctype1_write(uint32_t adapter_idx, uint32_t target_idx,
        if (near_tag_get_memory_layout(tag) == NEAR_TAG_MEMORY_STATIC) {
                if ((ndef->length + 3) > TYPE1_STATIC_MAX_DATA_SIZE) {
                        near_error("not enough space on tag");
-                       return -ENOSPC;
+                       err = -ENOSPC;
+                       goto out_err;
                }
        }
 
        return data_write(adapter_idx, target_idx, ndef, cb);
+
+       if (err < 0)
+               goto out_err;
+
+       return 0;
+
+out_err:
+       if (cb != NULL)
+               cb(adapter_idx, target_idx, err);
+
+       return err;
 }
 
 static int check_presence(uint8_t *resp, int length, void *data)
@@ -651,10 +654,6 @@ static int check_presence(uint8_t *resp, int length, void *data)
        if (length < 0)
                err = -EIO;
 
-       if (cookie->cb)
-               cookie->cb(cookie->adapter_idx,
-                               cookie->target_idx, err);
-
        return t1_cookie_release(err, cookie);
 }
 
@@ -664,7 +663,6 @@ static int nfctype1_check_presence(uint32_t adapter_idx,
        struct type1_cmd t1_cmd;
        struct t1_cookie *cookie;
        uint8_t *uid, uid_length;
-       int err;
 
        DBG("");
 
@@ -689,15 +687,9 @@ static int nfctype1_check_presence(uint32_t adapter_idx,
        cookie->target_idx = target_idx;
        cookie->cb = cb;
 
-       err = near_adapter_send(adapter_idx, (uint8_t *) &t1_cmd,
-                               sizeof(t1_cmd), check_presence, cookie);
-       if (err < 0)
-               goto out_err;
-
-       return 0;
-
-out_err:
-       return t1_cookie_release(err, cookie);
+       return near_adapter_send(adapter_idx, (uint8_t *) &t1_cmd,
+                               sizeof(t1_cmd), check_presence, cookie,
+                               t1_cookie_release);
 }
 
 static int format_resp(uint8_t *resp, int length, void *data)
@@ -723,12 +715,9 @@ static int format_resp(uint8_t *resp, int length, void *data)
                cookie->current_byte++;
                memcpy(cmd.uid, cookie->uid, UID_LENGTH);
 
-               err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd,
-                                       sizeof(cmd), format_resp, cookie);
-               if (err < 0)
-                       goto out_err;
-
-               return 0;
+               return near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd,
+                                       sizeof(cmd), format_resp, cookie,
+                                       t1_cookie_release);
        } else {
                tag = near_tag_get_tag(cookie->adapter_idx, cookie->target_idx);
                if (tag == NULL) {
@@ -741,9 +730,6 @@ static int format_resp(uint8_t *resp, int length, void *data)
        }
 
 out_err:
-       if (cookie->cb)
-               cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
-
        return t1_cookie_release(err, cookie);
 }
 
@@ -798,7 +784,8 @@ static int nfctype1_format(uint32_t adapter_idx, uint32_t target_idx,
        g_free(uid);
 
        err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd,
-                                       sizeof(cmd), format_resp, cookie);
+                               sizeof(cmd), format_resp, cookie,
+                               t1_cookie_release);
        if (err < 0)
                goto out_err;
 
index 62f6d0e..b5f3ea7 100644 (file)
@@ -113,6 +113,9 @@ static int t2_cookie_release(int err, void *data)
        if (cookie == NULL)
                return err;
 
+       if (cookie->cb != NULL)
+               cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
+
        if (cookie->ndef)
                g_free(cookie->ndef->data);
 
@@ -176,7 +179,7 @@ static int data_recv(uint8_t *resp, int length, void *data)
 
        return near_adapter_send(adapter_idx,
                                (uint8_t *) &cmd, CMD_READ_SIZE,
-                                       data_recv, tag);
+                                       data_recv, tag, NULL);
 }
 
 static int data_read(struct type2_tag *tag)
@@ -194,8 +197,8 @@ static int data_read(struct type2_tag *tag)
        adapter_idx = near_tag_get_adapter_idx(tag->tag);
 
        return near_adapter_send(adapter_idx,
-                               (uint8_t *) &cmd, CMD_READ_SIZE,
-                                       data_recv, tag);
+                                       (uint8_t *) &cmd, CMD_READ_SIZE,
+                                       data_recv, tag, NULL);
 }
 
 static int meta_recv(uint8_t *resp, int length, void *data)
@@ -263,15 +266,17 @@ static int meta_recv(uint8_t *resp, int length, void *data)
        if (err < 0)
                goto out_tag;
 
+       /*
+        * As reading isn't complete,
+        * callback shouldn't be called while freeing the cookie
+        */
+       cookie->cb = NULL;
        return t2_cookie_release(err, cookie);
 
 out_tag:
        g_free(t2_tag);
 
 out_err:
-       if (err < 0 && cookie->cb)
-               cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
-
        return t2_cookie_release(err, cookie);
 }
 
@@ -280,7 +285,6 @@ static int nfctype2_read_meta(uint32_t adapter_idx, uint32_t target_idx,
 {
        struct type2_cmd cmd;
        struct t2_cookie *cookie;
-       int err;
 
        DBG("");
 
@@ -295,18 +299,13 @@ static int nfctype2_read_meta(uint32_t adapter_idx, uint32_t target_idx,
        cookie->target_idx = target_idx;
        cookie->cb = cb;
 
-       err = near_adapter_send(adapter_idx, (uint8_t *) &cmd, CMD_READ_SIZE,
-                                                       meta_recv, cookie);
-       if (err < 0)
-               g_free(cookie);
-
-       return err;
+       return near_adapter_send(adapter_idx, (uint8_t *) &cmd, CMD_READ_SIZE,
+                                       meta_recv, cookie, t2_cookie_release);
 }
 
 static int nfctype2_read(uint32_t adapter_idx,
                                uint32_t target_idx, near_tag_io_cb cb)
 {
-       int err;
        enum near_tag_sub_type tgt_subtype;
 
        DBG("");
@@ -315,23 +314,18 @@ static int nfctype2_read(uint32_t adapter_idx,
 
        switch (tgt_subtype) {
        case NEAR_TAG_NFC_T2_MIFARE_ULTRALIGHT:
-               err = nfctype2_read_meta(adapter_idx, target_idx, cb);
-               break;
+               return nfctype2_read_meta(adapter_idx, target_idx, cb);
 
        /* Specific Mifare read access */
        case NEAR_TAG_NFC_T2_MIFARE_CLASSIC_1K:
        case NEAR_TAG_NFC_T2_MIFARE_CLASSIC_4K:
-               err = mifare_read(adapter_idx, target_idx,
+               return mifare_read(adapter_idx, target_idx,
                        cb, tgt_subtype);
-               break;
 
        default:
                DBG("Unknown Tag Type 2 subtype %d", tgt_subtype);
-               err = -1;
-               break;
+               return -1;
        }
-
-       return err;
 }
 
 static int data_write_resp(uint8_t *resp, int length, void *data)
@@ -350,9 +344,6 @@ static int data_write_resp(uint8_t *resp, int length, void *data)
        if (cookie->ndef->offset > cookie->ndef->length) {
                DBG("Done writing");
 
-               if (cookie->cb)
-                       cookie->cb(cookie->adapter_idx, cookie->target_idx, 0);
-
                return t2_cookie_release(0, cookie);
        }
 
@@ -371,18 +362,11 @@ static int data_write_resp(uint8_t *resp, int length, void *data)
                cookie->ndef->offset = cookie->ndef->length + 1;
        }
 
-       err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd,
-                                       sizeof(cmd), data_write_resp, cookie);
-
-       if (err < 0)
-               goto out_err;
-
-       return 0;
+       return near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd,
+                                       sizeof(cmd), data_write_resp, cookie,
+                                       t2_cookie_release);
 
 out_err:
-       if (err < 0 && cookie->cb)
-               cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
-
        return t2_cookie_release(err, cookie);
 }
 
@@ -397,8 +381,12 @@ static int data_write(uint32_t adapter_idx, uint32_t target_idx,
        DBG("");
 
        cookie = g_try_malloc0(sizeof(struct t2_cookie));
-       if (cookie == NULL)
-               return -ENOMEM;
+       if (cookie == NULL) {
+               err = -ENOMEM;
+               if (cb != NULL)
+                       cb(adapter_idx, target_idx, err);
+               return err;
+       }
 
        cookie->adapter_idx = adapter_idx;
        cookie->target_idx = target_idx;
@@ -412,16 +400,9 @@ static int data_write(uint32_t adapter_idx, uint32_t target_idx,
        cookie->ndef->offset += BLOCK_SIZE;
        cookie->current_block++;
 
-       err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd,
-                                       sizeof(cmd), data_write_resp, cookie);
-
-       if (err < 0)
-               goto out_err;
-
-       return 0;
-
-out_err:
-       return t2_cookie_release(err, cookie);
+       return near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd,
+                                       sizeof(cmd), data_write_resp, cookie,
+                                       t2_cookie_release);
 }
 
 static int nfctype2_write(uint32_t adapter_idx, uint32_t target_idx,
@@ -434,12 +415,16 @@ static int nfctype2_write(uint32_t adapter_idx, uint32_t target_idx,
 
        DBG("");
 
-       if (ndef == NULL || cb == NULL)
-               return -EINVAL;
+       if (ndef == NULL || cb == NULL) {
+               err = -EINVAL;
+               goto out_err;
+       }
 
        tag = near_tag_get_tag(adapter_idx, target_idx);
-       if (tag == NULL)
-               return -EINVAL;
+       if (tag == NULL) {
+               err = -EINVAL;
+               goto out_err;
+       }
 
        tgt_subtype = near_tag_get_subtype(adapter_idx, target_idx);
 
@@ -453,24 +438,30 @@ static int nfctype2_write(uint32_t adapter_idx, uint32_t target_idx,
                if (near_tag_get_memory_layout(tag) == NEAR_TAG_MEMORY_STATIC) {
                        if ((ndef->length + 3) > NDEF_MAX_SIZE) {
                                near_error("not enough space on tag");
-                               return -ENOSPC;
+                               err = -ENOSPC;
+                               goto out_err;
                        }
                }
 
-               err = data_write(adapter_idx, target_idx, ndef, cb);
-               break;
-               /* Specific Mifare write access */
+               return data_write(adapter_idx, target_idx, ndef, cb);
+
+       /* Specific Mifare write access */
        case NEAR_TAG_NFC_T2_MIFARE_CLASSIC_1K:
        case NEAR_TAG_NFC_T2_MIFARE_CLASSIC_4K:
-               err = mifare_write(adapter_idx, target_idx, ndef,
+               return mifare_write(adapter_idx, target_idx, ndef,
                                cb, tgt_subtype);
-               break;
        default:
                DBG("Unknown TAG Type 2 subtype %d", tgt_subtype);
                err = -EINVAL;
-               break;
+               goto out_err;
        }
 
+       return 0;
+
+out_err:
+       if (cb != NULL)
+               cb(adapter_idx, target_idx, err);
+
        return err;
 }
 
@@ -484,10 +475,6 @@ static int check_presence(uint8_t *resp, int length, void *data)
        if (length < 0)
                err = -EIO;
 
-       if (cookie->cb)
-               cookie->cb(cookie->adapter_idx,
-                               cookie->target_idx, err);
-
        return t2_cookie_release(err, cookie);
 }
 
@@ -497,7 +484,6 @@ static int nfctype2_check_presence(uint32_t adapter_idx, uint32_t target_idx,
        struct type2_cmd cmd;
        struct t2_cookie *cookie;
        enum near_tag_sub_type tgt_subtype;
-       int err;
 
        DBG("");
 
@@ -516,29 +502,21 @@ static int nfctype2_check_presence(uint32_t adapter_idx, uint32_t target_idx,
                cookie->target_idx = target_idx;
                cookie->cb = cb;
 
-               err = near_adapter_send(adapter_idx, (uint8_t *) &cmd,
-                               CMD_READ_SIZE, check_presence, cookie);
-               if (err < 0)
-                       goto out_err;
+               return near_adapter_send(adapter_idx, (uint8_t *) &cmd,
+                                       CMD_READ_SIZE, check_presence, cookie,
+                                       t2_cookie_release);
 
-               break;
        /* Specific Mifare check presence */
        case NEAR_TAG_NFC_T2_MIFARE_CLASSIC_1K:
        case NEAR_TAG_NFC_T2_MIFARE_CLASSIC_4K:
-               err = mifare_check_presence(adapter_idx, target_idx,
+               return mifare_check_presence(adapter_idx, target_idx,
                                                        cb, tgt_subtype);
-               break;
 
        default:
                DBG("Unknown TAG Type 2 subtype %d", tgt_subtype);
-               err = -1;
-               break;
-       }
 
-       return err;
-
-out_err:
-       return t2_cookie_release(err, cookie);
+               return -1;
+       }
 }
 
 static int format_resp(uint8_t *resp, int length, void *data)
@@ -564,9 +542,6 @@ static int format_resp(uint8_t *resp, int length, void *data)
        near_tag_set_blank(tag, FALSE);
 
 out_err:
-       if (cookie->cb)
-               cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
-
        return t2_cookie_release(err, cookie);
 }
 
@@ -621,7 +596,7 @@ static int nfctype2_format(uint32_t adapter_idx, uint32_t target_idx,
        memcpy(cmd.data, (uint8_t *) t2_cc, BLOCK_SIZE);
 
        err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd,
-                                       sizeof(cmd), format_resp, cookie);
+                               sizeof(cmd), format_resp, cookie, NULL);
 
 out_err:
        if (err < 0) {
index ffb401a..0fb444b 100644 (file)
@@ -144,6 +144,9 @@ static int t3_cookie_release(int err, void *data)
        if (cookie == NULL)
                return err;
 
+       if (cookie->cb != NULL)
+               cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
+
        if (cookie->ndef != NULL)
                g_free(cookie->ndef->data);
 
@@ -195,19 +198,17 @@ static void prepare_read_block(uint8_t cur_block,
 /* common: Simple checks on received frame */
 static int check_recv_frame(uint8_t *resp, uint8_t reply_code)
 {
-       int err = 0;
-
        if (resp[OFS_NFC_STATUS] != 0) {
                DBG("NFC Command failed: 0x%x", resp[OFS_NFC_STATUS]);
-               err = -EIO;
+               return -EIO;
        }
 
        if (resp[OFS_CMD_RESP] != reply_code) {
                DBG("Felica cmd failed: 0x%x", resp[OFS_CMD_RESP]);
-               err = -EIO;
+               return -EIO;
        }
 
-       return err;
+       return 0;
 }
 
 static int data_recv(uint8_t *resp, int length, void *data)
@@ -261,7 +262,7 @@ static int data_recv(uint8_t *resp, int length, void *data)
                                tag->IDm, &cmd);
 
        err = near_adapter_send(adapter_idx, (uint8_t *) &cmd, cmd.len,
-                               data_recv, tag);
+                               data_recv, tag, NULL);
 
        if (err < 0)
                goto out_err;
@@ -293,7 +294,7 @@ static int data_read(struct type3_tag *tag)
 
        return near_adapter_send(adapter_idx,
                                        (uint8_t *) &cmd, cmd.len,
-                                       data_recv, tag);
+                                       data_recv, tag, NULL);
 }
 
 /* Read block 0 to retrieve the data length */
@@ -365,14 +366,16 @@ static int nfctype3_recv_block_0(uint8_t *resp, int length, void *data)
 
        err = data_read(t3_tag);
 
-out_err:
-       if (err < 0) {
-               if (cookie->cb)
-                       cookie->cb(cookie->adapter_idx, cookie->target_idx,
-                                                                       err);
+       /*
+        * As reading isn't complete,
+        * callback shouldn't be called while freeing the cookie
+        */
+       if (err == 0)
+               cookie->cb = NULL;
 
+out_err:
+       if (err < 0)
                g_free(t3_tag);
-       }
 
        return t3_cookie_release(err, cookie);
 }
@@ -397,17 +400,13 @@ static int poll_ndef_system_code(uint8_t *resp, int length, void *data)
        prepare_read_block(META_BLOCK_START, cookie->IDm, &cmd);
 
        err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd,
-                               cmd.len, nfctype3_recv_block_0, cookie);
+                               cmd.len, nfctype3_recv_block_0, cookie, NULL);
        if (err < 0)
                goto out_err;
 
        return 0;
 
 out_err:
-       if (err < 0 && cookie->cb)
-               cookie->cb(cookie->adapter_idx,
-                               cookie->target_idx, err);
-
        return t3_cookie_release(err, cookie);
 }
 
@@ -449,10 +448,6 @@ static int check_sys_op_in_mc_block(uint8_t *resp, int length, void *data)
                near_tag_set_ic_type(tag, cookie->ic_type);
                near_tag_set_blank(tag, TRUE);
 
-               if (cookie->cb)
-                       cookie->cb(cookie->adapter_idx,
-                                       cookie->target_idx, 0);
-
                return t3_cookie_release(0, cookie);
        } else {
                /* CMD POLL */
@@ -465,7 +460,7 @@ static int check_sys_op_in_mc_block(uint8_t *resp, int length, void *data)
                cmd.len = LEN_CMD + LEN_CMD_LEN + 4 ;
 
                err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd,
-                       cmd.len , poll_ndef_system_code, cookie);
+                       cmd.len , poll_ndef_system_code, cookie, NULL);
        }
 
        if (err < 0)
@@ -474,9 +469,6 @@ static int check_sys_op_in_mc_block(uint8_t *resp, int length, void *data)
        return 0;
 
 out_err:
-       if (err < 0 && cookie->cb)
-               cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
-
        return t3_cookie_release(err, cookie);
 }
 
@@ -508,7 +500,7 @@ static int receive_system_code(uint8_t *resp, int length, void *data)
                prepare_read_block(FELICA_LITE_MC_BLOCK, cookie->IDm, &cmd);
                err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd,
                                        cmd.len, check_sys_op_in_mc_block,
-                                       cookie);
+                                       cookie, NULL);
                break;
 
        case FELICA_LITE_S_IC_TYPE:
@@ -523,7 +515,8 @@ static int receive_system_code(uint8_t *resp, int length, void *data)
                cmd.len = LEN_CMD + LEN_CMD_LEN + 4 ;
 
                err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd,
-                                       cmd.len, poll_ndef_system_code, cookie);
+                                       cmd.len, poll_ndef_system_code, cookie,
+                                       NULL);
        }
 
        if (err < 0)
@@ -532,9 +525,6 @@ static int receive_system_code(uint8_t *resp, int length, void *data)
        return 0;
 
 out_err:
-       if (err < 0 && cookie->cb)
-               cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
-
        return t3_cookie_release(err, cookie);
 }
 
@@ -543,7 +533,6 @@ static int nfctype3_read(uint32_t adapter_idx,
 {
        struct type3_cmd cmd;
        struct t3_cookie *cookie;
-       int err;
 
        DBG("");
 
@@ -565,12 +554,9 @@ static int nfctype3_read(uint32_t adapter_idx,
        cookie->target_idx = target_idx;
        cookie->cb = cb;
 
-       err = near_adapter_send(adapter_idx, (uint8_t *) &cmd,
-                               cmd.len, receive_system_code, cookie);
-       if (err < 0)
-               g_free(cookie);
-
-       return err;
+       return near_adapter_send(adapter_idx, (uint8_t *) &cmd, cmd.len,
+                                       receive_system_code, cookie,
+                                       t3_cookie_release);
 }
 
 static int update_attr_block_cb(uint8_t *resp, int length, void *data)
@@ -592,9 +578,6 @@ static int update_attr_block_cb(uint8_t *resp, int length, void *data)
        DBG("Done writing");
 
 out_err:
-       if (cookie->cb)
-               cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
-
        return t3_cookie_release(err, cookie);
 }
 
@@ -621,7 +604,8 @@ static int update_attr_block(struct t3_cookie *cookie)
        prepare_write_block(cookie->IDm, &cmd, 0, cookie->attr);
 
        return near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd, cmd.len,
-                                               update_attr_block_cb, cookie);
+                                       update_attr_block_cb, cookie,
+                                       t3_cookie_release);
 }
 
 static int data_write_resp(uint8_t *resp, int length, void *data)
@@ -665,16 +649,13 @@ static int data_write_resp(uint8_t *resp, int length, void *data)
        cookie->ndef->offset += BLOCK_SIZE;
 
        err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd, cmd.len,
-                                               data_write_resp, cookie);
+                                               data_write_resp, cookie, NULL);
        if (err < 0)
                goto out_err;
 
        return 0;
 
 out_err:
-       if (err < 0 && cookie->cb)
-               cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
-
        return t3_cookie_release(err, cookie);
 }
 
@@ -693,9 +674,14 @@ static int data_write(uint32_t adapter_idx, uint32_t target_idx,
        DBG("");
 
        cookie = g_try_malloc0(sizeof(struct t3_cookie));
+
        if (cookie == NULL) {
                err = -ENOMEM;
-               goto out_err;
+
+               if (cb != NULL)
+                       cb(adapter_idx, target_idx, err);
+
+               return err;
        }
 
        cookie->adapter_idx = adapter_idx;
@@ -705,26 +691,22 @@ static int data_write(uint32_t adapter_idx, uint32_t target_idx,
        cookie->current_block = 0;
 
        idm = near_tag_get_idm(tag, &len);
-       if (idm == NULL) {
-               err = -EINVAL;
-               goto out_err;
-       }
+       if (idm == NULL)
+               return t3_cookie_release(-EINVAL, cookie);
 
        memcpy(cookie->IDm, idm, len);
 
        attr = near_tag_get_attr_block(tag, &len);
-       if (attr == NULL) {
-               err = -EINVAL;
-               goto out_err;
-       }
+       if (attr == NULL)
+               return t3_cookie_release(-EINVAL, cookie);
 
        memcpy(cookie->attr, attr, len);
        nmaxb = (((uint16_t) (cookie->attr[3])) << 8) | cookie->attr[4];
 
        if (cookie->ndef->length > (nmaxb * BLOCK_SIZE)) {
                near_error("not enough space on tag");
-               err = -ENOSPC;
-               goto out_err;
+
+               return t3_cookie_release(-ENOSPC, cookie);
        }
 
        cookie->attr[9] = 0x0F; /* writing data in progress */
@@ -740,15 +722,9 @@ static int data_write(uint32_t adapter_idx, uint32_t target_idx,
                                                        cookie->attr);
        cookie->current_block++;
 
-       err = near_adapter_send(adapter_idx, (uint8_t *) &cmd, cmd.len,
-                                               data_write_resp, cookie);
-       if (err < 0)
-               goto out_err;
-
-       return 0;
-
-out_err:
-       return t3_cookie_release(err, cookie);
+       return near_adapter_send(adapter_idx, (uint8_t *) &cmd, cmd.len,
+                                       data_write_resp, cookie,
+                                       t3_cookie_release);
 }
 
 static int nfctype3_write(uint32_t adapter_idx, uint32_t target_idx,
@@ -756,17 +732,28 @@ static int nfctype3_write(uint32_t adapter_idx, uint32_t target_idx,
                                near_tag_io_cb cb)
 {
        struct near_tag *tag;
+       int err;
 
        DBG("");
 
-       if (ndef == NULL || cb == NULL)
-               return -EINVAL;
+       if (ndef == NULL || cb == NULL) {
+               err = -EINVAL;
+               goto out_err;
+       }
 
        tag = near_tag_get_tag(adapter_idx, target_idx);
-       if (tag == NULL)
-               return -EINVAL;
+       if (tag == NULL) {
+               err = -EINVAL;
+               goto out_err;
+       }
+
+       err = data_write(adapter_idx, target_idx, ndef, tag, cb);
 
-       return data_write(adapter_idx, target_idx, ndef, tag, cb);
+out_err:
+       if (cb != NULL)
+               cb(adapter_idx, target_idx, err);
+
+       return err;
 }
 
 static int check_presence(uint8_t *resp, int length, void *data)
@@ -779,10 +766,6 @@ static int check_presence(uint8_t *resp, int length, void *data)
        if (length < 0)
                err = -EIO;
 
-       if (cookie->cb)
-               cookie->cb(cookie->adapter_idx,
-                               cookie->target_idx, err);
-
        return t3_cookie_release(err, cookie);
 }
 
@@ -791,7 +774,6 @@ static int nfctype3_check_presence(uint32_t adapter_idx,
 {
        struct type3_cmd cmd;
        struct t3_cookie *cookie;
-       int err;
 
        DBG("");
 
@@ -813,16 +795,9 @@ static int nfctype3_check_presence(uint32_t adapter_idx,
        cookie->target_idx = target_idx;
        cookie->cb = cb;
 
-       err = near_adapter_send(adapter_idx, (uint8_t *) &cmd,
-                               cmd.len, check_presence, cookie);
-
-       if (err < 0)
-               goto out_err;
-
-       return 0;
-
-out_err:
-       return t3_cookie_release(err, cookie);
+       return near_adapter_send(adapter_idx, (uint8_t *) &cmd,
+                               cmd.len, check_presence, cookie,
+                               t3_cookie_release);
 }
 
 static int format_resp(uint8_t *resp, int length, void *data)
@@ -856,9 +831,6 @@ static int format_resp(uint8_t *resp, int length, void *data)
        DBG("Formatting is done");
 
 out_err:
-       if (cookie->cb)
-               cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
-
        return t3_cookie_release(err, cookie);
 }
 
@@ -905,16 +877,13 @@ static int write_attr_block(uint8_t *resp, int length , void *data)
                                                cookie->attr);
 
        err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd,
-                               cmd.len, format_resp, cookie);
+                               cmd.len, format_resp, cookie, NULL);
        if (err < 0)
                goto out_err;
 
        return 0;
 
 out_err:
-       if (err < 0 && cookie->cb)
-               cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
-
        return t3_cookie_release(err, cookie);
 }
 
@@ -950,16 +919,13 @@ static int write_mc_block(uint8_t *resp, int length, void *data)
        prepare_write_block(cookie->IDm, &cmd, FELICA_LITE_MC_BLOCK,
                                cookie->mc_block);
        err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd,
-                               cmd.len, write_attr_block, cookie);
+                               cmd.len, write_attr_block, cookie, NULL);
        if (err < 0)
                goto out_err;
 
        return 0;
 
 out_err:
-       if (err < 0 && cookie->cb)
-               cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
-
        return t3_cookie_release(err, cookie);
 }
 
@@ -971,7 +937,6 @@ static int nfctype3_format(uint32_t adapter_idx,
        struct t3_cookie *cookie;
        uint8_t ic_type;
        uint8_t *idm, len;
-       int err;
 
        DBG("");
 
@@ -993,23 +958,17 @@ static int nfctype3_format(uint32_t adapter_idx,
        cookie->ic_type = ic_type;
 
        idm = near_tag_get_idm(tag, &len);
-       if (idm == NULL) {
-               err = -EINVAL;
-               goto out_err;
-       }
+       if (idm == NULL)
+               return t3_cookie_release(-EINVAL, cookie);
 
        memcpy(cookie->IDm, idm, len);
 
        prepare_read_block(FELICA_LITE_MC_BLOCK, cookie->IDm, &cmd);
-       err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd,
-                               cmd.len, write_mc_block, cookie);
-       if (err < 0)
-               goto out_err;
 
-       return 0;
+       return near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd, cmd.len,
+                                       write_mc_block, cookie,
+                                       t3_cookie_release);
 
-out_err:
-       return t3_cookie_release(err, cookie);
 }
 
 static struct near_tag_driver type1_driver = {
index 8a00e3d..27985e4 100644 (file)
@@ -158,6 +158,27 @@ struct t4_cookie {
        uint16_t memory_size;
 };
 
+static int t4_cookie_release(int err, void *data)
+{
+       struct t4_cookie *cookie = data;
+
+       DBG("%p", cookie);
+
+       if (cookie == NULL)
+               return err;
+
+       if (err < 0 && cookie->cb)
+               cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
+
+       if (cookie->ndef)
+               g_free(cookie->ndef->data);
+
+       g_free(cookie->ndef);
+       g_free(cookie);
+
+       return err;
+}
+
 /* ISO functions: This code prepares APDU */
 static int ISO_send_cmd(uint8_t class,
                        uint8_t instruction,
@@ -207,10 +228,9 @@ static int ISO_send_cmd(uint8_t class,
                        cmd->data[cmd_data_length] = 0;
        }
 
-       err = near_adapter_send(in_rcv->adapter_idx, (uint8_t *) cmd,
-                                       total_cmd_length, cb, in_rcv);
-       if (err < 0)
-               g_free(in_rcv);
+       return near_adapter_send(in_rcv->adapter_idx, (uint8_t *) cmd,
+                                       total_cmd_length, cb, in_rcv,
+                                       t4_cookie_release);
 
 out_err:
        /* On exit, clean memory */
@@ -274,44 +294,22 @@ static int ISO_Update(uint16_t offset, uint8_t nlen,
                        cookie);
 }
 
-static int t4_cookie_release(int err, void *data)
-{
-       struct t4_cookie *cookie = data;
-
-       DBG("%p", cookie);
-
-       if (cookie == NULL)
-               return err;
-
-       if (err < 0 && cookie->cb)
-               cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
-
-       if (cookie->ndef)
-               g_free(cookie->ndef->data);
-
-       g_free(cookie->ndef);
-       g_free(cookie);
-
-       return err;
-}
-
 static int data_read_cb(uint8_t *resp, int length, void *data)
 {
        struct t4_cookie *cookie = data ;
        uint8_t *nfc_data;
        size_t data_length, length_read, current_length;
        uint16_t remain_bytes;
-       int err = 0;
 
        DBG("%d", length);
 
        if (length < 0)
-               return t4_cookie_release(err, cookie);
+               return t4_cookie_release(length, cookie);
 
        if (APDU_STATUS(resp + length - 2) != APDU_OK) {
                DBG("Fail read_cb SW:x%04x", APDU_STATUS(resp + length - 2));
-               err = -EIO;
-               return t4_cookie_release(err, cookie);
+
+               return t4_cookie_release(-EIO, cookie);
        }
 
        nfc_data = near_tag_get_data(cookie->tag, &data_length);
@@ -334,26 +332,18 @@ static int data_read_cb(uint8_t *resp, int length, void *data)
                records = near_ndef_parse(nfc_data, data_length);
                near_tag_add_records(cookie->tag, records, cookie->cb, 0);
 
-               err = 0;
-               goto out_err;
+               return t4_cookie_release(0, cookie);
        }
 
        cookie->read_data += length ;
        remain_bytes = (data_length - cookie->read_data);
 
        if (remain_bytes >= cookie->r_apdu_max_size)
-               err = ISO_ReadBinary(cookie->read_data + 2,
+               return ISO_ReadBinary(cookie->read_data + 2,
                                cookie->r_apdu_max_size, data_read_cb, cookie);
        else
-               err = ISO_ReadBinary(cookie->read_data + 2,
+               return ISO_ReadBinary(cookie->read_data + 2,
                                (uint8_t) remain_bytes, data_read_cb, cookie);
-       if (err < 0)
-               goto out_err;
-
-       return err;
-
-out_err:
-       return t4_cookie_release(err, cookie);
 }
 
 static int t4_readbin_NDEF_ID(uint8_t *resp, int length, void *data)
@@ -364,28 +354,24 @@ static int t4_readbin_NDEF_ID(uint8_t *resp, int length, void *data)
 
        DBG("%d", length);
 
-       if (length < 0) {
-               err = length;
-               goto out_err;
-       }
+       if (length < 0)
+               return t4_cookie_release(length, cookie);
 
        if (APDU_STATUS(resp + length - 2) != APDU_OK) {
                DBG("Fail SW:x%04x", APDU_STATUS(resp + length - 2));
-               err = -EIO;
-               goto out_err;
+
+               return t4_cookie_release(-EIO, cookie);
        }
 
        /* Add data to the tag */
        err = near_tag_add_data(cookie->adapter_idx, cookie->target_idx, NULL,
                                g_ntohs(*((uint16_t *)(resp + NFC_STATUS_BYTE_LEN))));
        if (err < 0)
-               goto out_err;
+               return t4_cookie_release(err, cookie);
 
        tag = near_tag_get_tag(cookie->adapter_idx, cookie->target_idx);
-       if (tag == NULL) {
-               err = -ENOMEM;
-               goto out_err;
-       }
+       if (tag == NULL)
+               return t4_cookie_release(-ENOMEM, cookie);
 
        near_tag_set_max_ndef_size(tag, cookie->max_ndef_size);
        near_tag_set_c_apdu_max_size(tag, cookie->c_apdu_max_size);
@@ -406,74 +392,54 @@ static int t4_readbin_NDEF_ID(uint8_t *resp, int length, void *data)
         */
 
        /* Read 1st block */
-       err = ISO_ReadBinary(2, cookie->r_apdu_max_size - 2,
+       return ISO_ReadBinary(2, cookie->r_apdu_max_size - 2,
                        data_read_cb, cookie);
-       if (err < 0)
-               goto out_err;
-
-       return err;
-
-out_err:
-       return t4_cookie_release(err, cookie);
 }
 
 static int t4_select_NDEF_ID(uint8_t *resp, int length, void *data)
 {
        struct t4_cookie *cookie = data;
-       int err;
 
        DBG("%d", length);
 
-       if (length < 0) {
-               err = length;
-               goto out_err;
-       }
+       if (length < 0)
+               return t4_cookie_release(length, cookie);
 
        /* Check for APDU error */
        if (APDU_STATUS(resp + STATUS_WORD_1) != APDU_OK) {
                DBG("Fail SW:x%04x", APDU_STATUS(resp + STATUS_WORD_1));
-               err = -EIO;
-               goto out_err;
+
+               return t4_cookie_release(-EIO, cookie);
        }
 
        /* Read 0x0f bytes, to grab the NDEF msg length */
-       err = ISO_ReadBinary(0, LEN_ISO_CC_READ_SIZE,
+       return ISO_ReadBinary(0, LEN_ISO_CC_READ_SIZE,
                                        t4_readbin_NDEF_ID, cookie);
-       if (err < 0)
-               goto out_err;
-
-       return err;
-
-out_err:
-       return t4_cookie_release(err, cookie);
 }
 
 static int t4_readbin_cc(uint8_t *resp, int length, void *data)
 {
        struct t4_cookie *cookie = data;
        struct type4_cc *read_cc;
-       int err;
 
        DBG("%d", length);
 
-       if (length < 0) {
-               err = length;
-               goto out_err;
-       }
+       if (length < 0)
+               return t4_cookie_release(length, cookie);
 
        /* Check APDU error ( the two last bytes of the resp) */
        if (APDU_STATUS(resp + length - 2) != APDU_OK) {
                DBG("Fail SW:x%04x", APDU_STATUS(resp + length - 2));
-               err = -EIO;
-               goto out_err;
+
+               return t4_cookie_release(-EIO, cookie);
        }
 
        /* -2 for status word and -1 is for NFC first byte... */
        read_cc = g_try_malloc0(length - 2 - NFC_STATUS_BYTE_LEN);
        if (read_cc == NULL) {
                DBG("Mem alloc failed");
-               err = -ENOMEM;
-               goto out_err;
+
+               return t4_cookie_release(-ENOMEM, cookie);
        }
 
        memcpy(read_cc, &resp[1], length - 2 - NFC_STATUS_BYTE_LEN) ;
@@ -487,22 +453,15 @@ static int t4_readbin_cc(uint8_t *resp, int length, void *data)
        /* TODO 5.1.2: Must ignore proprietary blocks (x05)... */
        if (read_cc->tlv_fc.tag != 0x4) {
                DBG("NDEF File Control tag not found");
-               err = -EINVAL;
-               goto out_err;
+
+               return t4_cookie_release(-EINVAL, cookie);
        }
 
        /* save rw conditions */
        cookie->write_access = read_cc->tlv_fc.write_access;
 
-       err = ISO_Select((uint8_t *) &read_cc->tlv_fc.file_id,
+       return ISO_Select((uint8_t *) &read_cc->tlv_fc.file_id,
                        LEN_ISO_CC_FILEID, 0, t4_select_NDEF_ID, cookie);
-       if (err < 0)
-               goto out_err;
-
-       return err;
-
-out_err:
-       return t4_cookie_release(err, cookie);
 }
 
 static int t4_select_cc(uint8_t *resp, int length, void *data)
@@ -512,10 +471,8 @@ static int t4_select_cc(uint8_t *resp, int length, void *data)
 
        DBG("%d", length);
 
-       if (length < 0) {
-               err = length;
-               goto out_err;
-       }
+       if (length < 0)
+               return t4_cookie_release(length, cookie);
 
        /* Check for APDU error */
        if (APDU_STATUS(resp + STATUS_WORD_1) != APDU_OK) {
@@ -525,14 +482,12 @@ static int t4_select_cc(uint8_t *resp, int length, void *data)
                err = near_tag_add_data(cookie->adapter_idx, cookie->target_idx,
                                        NULL, 1 /* dummy length */);
                if (err < 0)
-                       goto out_err;
+                       return t4_cookie_release(err, cookie);
 
                cookie->tag = near_tag_get_tag(cookie->adapter_idx,
                                                cookie->target_idx);
-               if (cookie->tag == NULL) {
-                       err = -ENOMEM;
-                       goto out_err;
-               }
+               if (cookie->tag == NULL)
+                       return t4_cookie_release(-ENOMEM, cookie);
 
                near_tag_set_blank(cookie->tag, TRUE);
 
@@ -542,111 +497,74 @@ static int t4_select_cc(uint8_t *resp, int length, void *data)
                return t4_cookie_release(0, cookie);
        }
 
-       err = ISO_ReadBinary(0, LEN_ISO_CC_READ_SIZE, t4_readbin_cc, cookie);
-       if (err < 0)
-               goto out_err;
-
-       return err;
-
-out_err:
-       return t4_cookie_release(err, cookie);
+       return ISO_ReadBinary(0, LEN_ISO_CC_READ_SIZE, t4_readbin_cc, cookie);
 }
 
 static int t4_select_file_by_name_v1(uint8_t *resp, int length, void *data)
 {
        struct t4_cookie *cookie = data;
-       int err;
 
        DBG("%d", length);
 
-       if (length < 0) {
-               err = length;
-               goto out_err;
-       }
+       if (length < 0)
+               return t4_cookie_release(length, cookie);
 
        /* Check for APDU error */
        if (APDU_STATUS(resp + STATUS_WORD_1) != APDU_OK) {
                DBG("V1 Fail SW:x%04x", APDU_STATUS(resp + STATUS_WORD_1));
-               err = -EIO;
-               goto out_err;
-       }
 
-       if (resp[NFC_STATUS] != 0) {
-               err = -EIO;
-               goto out_err;
+               return t4_cookie_release(-EIO, cookie);
        }
 
+       if (resp[NFC_STATUS] != 0)
+               return t4_cookie_release(-EIO, cookie);
+
        /* Jump to select phase */
-       err = ISO_Select(iso_cc_fileid, LEN_ISO_CC_FILEID, 0,
+       return ISO_Select(iso_cc_fileid, LEN_ISO_CC_FILEID, 0,
                                t4_select_cc, cookie);
-       if (err < 0)
-               goto out_err;
-
-       return err;
-
-out_err:
-       return t4_cookie_release(err, cookie);
 }
 
 static int t4_select_file_by_name_v2(uint8_t *resp, int length, void *data)
 {
        struct t4_cookie *cookie = data;
-       int err;
 
        DBG("%d", length);
 
-       if (length < 0) {
-               err = length;
-               goto out_err;
-       }
+       if (length < 0)
+               t4_cookie_release(length, cookie);
 
        /* Check for APDU error - Not found */
        if (APDU_STATUS(resp + STATUS_WORD_1) == APDU_NOT_FOUND) {
                DBG("Fallback to V1");
-               err = ISO_Select(iso_appname_v1, ARRAY_SIZE(iso_appname_v1),
-                               0x4, t4_select_file_by_name_v1, cookie);
-               if (err < 0)
-                       goto out_err;
 
-               return err;
+               return ISO_Select(iso_appname_v1, ARRAY_SIZE(iso_appname_v1),
+                                       0x4, t4_select_file_by_name_v1, cookie);
        }
 
        if (APDU_STATUS(resp + STATUS_WORD_1) != APDU_OK) {
                DBG("V2 Fail SW:x%04x", APDU_STATUS(resp + STATUS_WORD_1));
-               err = -EIO;
-               goto out_err;
-       }
 
-       if (resp[NFC_STATUS] != 0) {
-               err = -EIO;
-               goto out_err;
+               return t4_cookie_release(-EIO, cookie);
        }
 
-       /* Jump to select phase */
-       err = ISO_Select(iso_cc_fileid, LEN_ISO_CC_FILEID, 0,
-                       t4_select_cc, cookie);
-       if (err < 0)
-               goto out_err;
-
-       return err;
+       if (resp[NFC_STATUS] != 0)
+               return t4_cookie_release(-EIO, cookie);
 
-out_err:
-       return t4_cookie_release(err, cookie);
+       /* Jump to select phase */
+       return ISO_Select(iso_cc_fileid, LEN_ISO_CC_FILEID, 0, t4_select_cc,
+                                                                       cookie);
 }
 
 static int nfctype4_read(uint32_t adapter_idx,
                uint32_t target_idx, near_tag_io_cb cb)
 {
        struct t4_cookie *cookie;
-       int err;
 
        DBG("");
 
        cookie = g_try_malloc0(sizeof(struct t4_cookie));
-       if (cookie == NULL) {
-               err = -ENOMEM;
-               goto out_err;
-       }
+       if (cookie == NULL)
+               return -ENOMEM;
 
        cookie->adapter_idx = adapter_idx;
        cookie->target_idx = target_idx;
@@ -655,15 +573,8 @@ static int nfctype4_read(uint32_t adapter_idx,
        cookie->read_data = 0;
 
        /* Check for V2 type 4 tag */
-       err = ISO_Select(iso_appname_v2, ARRAY_SIZE(iso_appname_v2),
-                       0x4, t4_select_file_by_name_v2, cookie);
-       if (err < 0)
-               goto out_err;
-
-       return err;
-
-out_err:
-       return t4_cookie_release(err, cookie);
+       return ISO_Select(iso_appname_v2, ARRAY_SIZE(iso_appname_v2),
+                               0x4, t4_select_file_by_name_v2, cookie);
 }
 
 static int data_write_cb(uint8_t *resp, int length, void *data)
@@ -674,14 +585,13 @@ static int data_write_cb(uint8_t *resp, int length, void *data)
        DBG("%d", length);
 
        if (length < 0)
-               return t4_cookie_release(err, cookie);
+               return t4_cookie_release(length, cookie);
 
        if (APDU_STATUS(resp + length - 2) != APDU_OK) {
                near_error("write failed SWx%04x",
                                APDU_STATUS(resp + length - 2));
-               err = -EIO;
 
-               return t4_cookie_release(err, cookie);
+               return t4_cookie_release(-EIO, cookie);
        }
 
        if (cookie->ndef->offset >= cookie->ndef->length) {
@@ -723,9 +633,14 @@ static int data_write(uint32_t adapter_idx, uint32_t target_idx,
        int err;
 
        cookie = g_try_malloc0(sizeof(struct t4_cookie));
+
        if (cookie == NULL) {
                err = -ENOMEM;
-               goto out_err;
+
+               if (cb != NULL)
+                       cb(adapter_idx, target_idx, err);
+
+               return err;
        }
 
        cookie->adapter_idx = adapter_idx;
@@ -739,8 +654,8 @@ static int data_write(uint32_t adapter_idx, uint32_t target_idx,
 
        if (cookie->max_ndef_size < cookie->ndef->length) {
                near_error("not enough space on tag to write data");
-               err = -ENOMEM;
-               goto out_err;
+
+               return t4_cookie_release(-ENOMEM, cookie);
        }
 
        if ((cookie->ndef->length - cookie->ndef->offset) >
@@ -771,17 +686,28 @@ static int nfctype4_write(uint32_t adapter_idx, uint32_t target_idx,
                        struct near_ndef_message *ndef, near_tag_io_cb cb)
 {
        struct near_tag *tag;
+       int err;
 
        DBG("");
 
-       if (ndef == NULL || cb == NULL)
-               return -EINVAL;
+       if (ndef == NULL || cb == NULL) {
+               err = -EINVAL;
+               goto out_err;
+       }
 
        tag = near_tag_get_tag(adapter_idx, target_idx);
-       if (tag == NULL)
-               return -EINVAL;
+       if (tag == NULL) {
+               err = -EINVAL;
+               goto out_err;
+       }
+
+       err = data_write(adapter_idx, target_idx, ndef, tag, cb);
 
-       return data_write(adapter_idx, target_idx, ndef, tag, cb);
+out_err:
+       if (cb != NULL)
+               cb(adapter_idx, target_idx, err);
+
+       return err;
 }
 
 static int check_presence(uint8_t *resp, int length, void *data)
@@ -805,15 +731,12 @@ static int nfctype4_check_presence(uint32_t adapter_idx,
                uint32_t target_idx, near_tag_io_cb cb)
 {
        struct t4_cookie *cookie;
-       int err;
 
        DBG("");
 
        cookie = g_try_malloc0(sizeof(struct t4_cookie));
-       if (cookie == NULL) {
-               err = -ENOMEM;
-               goto out_err;
-       }
+       if (cookie == NULL)
+               return -ENOMEM;
 
        cookie->adapter_idx = adapter_idx;
        cookie->target_idx = target_idx;
@@ -822,34 +745,24 @@ static int nfctype4_check_presence(uint32_t adapter_idx,
        cookie->read_data = 0;
 
        /* Check for V2 type 4 tag */
-       err = ISO_Select(iso_appname_v2, ARRAY_SIZE(iso_appname_v2),
-                       0x4, check_presence, cookie);
-       if (err < 0)
-               goto out_err;
-
-       return err;
-
-out_err:
-       return t4_cookie_release(err, cookie);
+       return ISO_Select(iso_appname_v2, ARRAY_SIZE(iso_appname_v2),
+                               0x4, check_presence, cookie);
 }
 
 static int select_ndef_file(uint8_t *resp, int length, void *data)
 {
        struct t4_cookie *cookie = data;
-       int err = 0;
 
        DBG("%d", length);
 
-       if (length < 0) {
-               err = length;
-               goto out_err;
-       }
+       if (length < 0)
+               return t4_cookie_release(length, cookie);
 
        if (APDU_STATUS(resp + STATUS_WORD_1) != APDU_OK) {
                near_error("select ndef file resp failed %02X",
                                        resp[length - 1]);
-               err = -EIO;
-               goto out_err;
+
+               return t4_cookie_release(-EIO, cookie);
        }
 
        DBG("ndef file selected");
@@ -857,8 +770,7 @@ static int select_ndef_file(uint8_t *resp, int length, void *data)
        if (cookie->cb)
                cookie->cb(cookie->adapter_idx, cookie->target_idx, 0);
 
-out_err:
-       return t4_cookie_release(err, cookie);
+       return t4_cookie_release(0, cookie);
 }
 
 static int read_cc_file(uint8_t *resp, int length, void *data)
@@ -931,15 +843,15 @@ static int select_cc_file(uint8_t *resp, int length, void *data)
 
        if (length < 0) {
                near_error("CC file select resp failed %d", length);
-               err = length;
-               goto out_err;
+
+               return t4_cookie_release(length, cookie);
        }
 
        if (APDU_STATUS(resp + STATUS_WORD_1) != APDU_OK) {
                near_error("CC file select response %02X",
                                                resp[length - 1]);
-               err = -EIO;
-               goto out_err;
+
+               return t4_cookie_release(-EIO, cookie);
        }
 
        err = ISO_ReadBinary(0, LEN_ISO_CC_READ_SIZE, read_cc_file, cookie);
@@ -961,15 +873,15 @@ static int select_iso_appname_v2(uint8_t *resp, int length, void *data)
 
        if (length < 0) {
                near_error("iso app select resp failed %d", length);
-               err = length;
-               goto out_err;
+
+               return t4_cookie_release(length, cookie);
        }
 
        if (resp[NFC_STATUS] != 0x00) {
                near_error("iso app select response %02X",
                                        resp[length - 1]);
-               err = -EIO;
-               goto out_err;
+
+               return t4_cookie_release(-EIO, cookie);
        }
 
        err = ISO_Select(iso_cc_fileid, LEN_ISO_CC_FILEID, 0,
@@ -995,22 +907,20 @@ static int format_resp(uint8_t *resp, int length, void *data)
 
        if (length < 0) {
                near_error("write data to ndef file resp failed %d", length);
-               err = length;
-               goto out_err;
+
+               return t4_cookie_release(length, cookie);
        }
 
        if (APDU_STATUS(resp + 1) != PICC_LEVEL_APDU_OK) {
                near_error("wrtie data to ndef file response %02X",
                                                resp[length - 1]);
-               err = -EIO;
-               goto out_err;
+
+               return t4_cookie_release(-EIO, cookie);
        }
 
        tag = near_tag_get_tag(cookie->adapter_idx, cookie->target_idx);
-       if (tag == NULL) {
-               err = -EINVAL;
-               goto out_err;
-       }
+       if (tag == NULL)
+               return t4_cookie_release(-EINVAL, cookie);
 
        DBG("Formatting is done");
        near_tag_set_blank(tag, FALSE);
@@ -1029,7 +939,7 @@ static int format_resp(uint8_t *resp, int length, void *data)
                goto out_err;
        }
 
-       return 0;
+       return err;
 
 out_err:
        return t4_cookie_release(err, cookie);
@@ -1429,8 +1339,8 @@ static int get_version_frame3(uint8_t *resp, int length, void *data)
 
        if (length < 0) {
                near_error("get version2 resp failed %d", length);
-               err = length;
-               goto out_err;
+
+               return t4_cookie_release(length, cookie);
        }
 
        if (resp[4] == 0x01 /* Major Version */
@@ -1442,18 +1352,16 @@ static int get_version_frame3(uint8_t *resp, int length, void *data)
                                        select_application, cookie);
                if (err < 0) {
                        near_error("get version3 req failed %d", err);
-                       goto out_err;
+
+                       return t4_cookie_release(err, cookie);
                }
        } else {
                near_error("get version2 response %02X", resp[length - 1]);
-               err = -EIO;
-               goto out_err;
+
+               return t4_cookie_release(-EIO, cookie);
        }
 
        return 0;
-
-out_err:
-       return t4_cookie_release(err, cookie);
 }
 
 static int get_version_frame2(uint8_t *resp, int length, void *data)
@@ -1465,8 +1373,8 @@ static int get_version_frame2(uint8_t *resp, int length, void *data)
 
        if (length < 0) {
                near_error(" get version resp failed %d", length);
-               err = length;
-               goto out_err;
+
+               return t4_cookie_release(length, cookie);
        }
 
        if (resp[4] == 0x01 /* Major Version */
@@ -1483,18 +1391,16 @@ static int get_version_frame2(uint8_t *resp, int length, void *data)
                                        get_version_frame3, cookie);
                if (err < 0) {
                        near_error("get version2 req failed %d", err);
-                       goto out_err;
+
+                       return t4_cookie_release(err, cookie);
                }
        } else {
                near_error("get version response %02X", resp[length - 1]);
-               err = -EIO;
-               goto out_err;
+
+               return t4_cookie_release(-EIO, cookie);
        }
 
        return 0;
-
-out_err:
-       return t4_cookie_release(err, cookie);
 }
 
 /* Steps to format Type 4 (MIFARE DESFire EV1) tag as per AN1104.pdf from nxp.
index ca80ed6..fc10d29 100644 (file)
@@ -1044,7 +1044,7 @@ int near_adapter_disconnect(uint32_t idx)
 }
 
 int near_adapter_send(uint32_t idx, uint8_t *buf, size_t length,
-                       near_recv cb, void *data)
+                       near_recv cb, void *data, near_release data_rel)
 {
        struct near_adapter *adapter;
        struct near_adapter_ioreq *req = NULL;
@@ -1053,16 +1053,22 @@ int near_adapter_send(uint32_t idx, uint8_t *buf, size_t length,
        DBG("idx %d", idx);
 
        adapter = g_hash_table_lookup(adapter_hash, GINT_TO_POINTER(idx));
-       if (adapter == NULL)
-               return -ENODEV;
+       if (adapter == NULL) {
+               err = -ENODEV;
+               goto out_err;
+       }
 
-       if (adapter->tag_sock == -1 || adapter->tag_link == NULL)
-               return -ENOLINK;
+       if (adapter->tag_sock == -1 || adapter->tag_link == NULL) {
+               err = -ENOLINK;
+               goto out_err;
+       }
 
        if (cb != NULL && adapter->watch != 0) {
                req = g_try_malloc0(sizeof(*req));
-               if (req == NULL)
-                       return -ENOMEM;
+               if (req == NULL) {
+                       err = -ENOMEM;
+                       goto out_err;
+               }
 
                DBG("req %p cb %p data %p", req, cb, data);
 
@@ -1089,6 +1095,9 @@ out_err:
                                g_list_delete_link(adapter->ioreq_list, last);
        }
 
+       if (data_rel != NULL)
+               return (*data_rel)(err, data);
+
        return err;
 }
 
index 2a46837..d38658d 100644 (file)
--- a/src/tag.c
+++ b/src/tag.c
@@ -326,7 +326,7 @@ static DBusMessage *write_ndef(DBusConnection *conn,
 {
        struct near_tag *tag = data;
        struct near_ndef_message *ndef, *ndef_with_header = NULL;
-       int err;
+       int tlv_len_size, err;
 
        DBG("conn %p", conn);
 
@@ -348,22 +348,38 @@ static DBusMessage *write_ndef(DBusConnection *conn,
        switch (tag->type) {
        case NFC_PROTO_JEWEL:
        case NFC_PROTO_MIFARE:
+               if (ndef->length < 0xff)
+                       tlv_len_size = 3;
+               else
+                       tlv_len_size = 5;
+
                ndef_with_header = g_try_malloc0(sizeof(
                                        struct near_ndef_message));
                if (ndef_with_header == NULL)
                        goto fail;
 
                ndef_with_header->offset = 0;
-               ndef_with_header->length = ndef->length + 3;
-               ndef_with_header->data = g_try_malloc0(ndef->length + 3);
+               ndef_with_header->length = ndef->length + tlv_len_size;
+               ndef_with_header->data =
+                               g_try_malloc0(ndef->length + tlv_len_size);
                if (ndef_with_header->data == NULL)
                        goto fail;
 
                ndef_with_header->data[0] = TLV_NDEF;
-               ndef_with_header->data[1] = ndef->length;
-               memcpy(ndef_with_header->data + 2, ndef->data, ndef->length);
-               ndef_with_header->data[ndef->length + 2] = TLV_END;
 
+               if (ndef->length < 0xff) {
+                       ndef_with_header->data[1] = ndef->length;
+               } else {
+                       ndef_with_header->data[1] = 0xff;
+                       ndef_with_header->data[2] =
+                                       (uint8_t)(ndef->length >> 8);
+                       ndef_with_header->data[3] = (uint8_t)(ndef->length);
+               }
+
+               memcpy(ndef_with_header->data + tlv_len_size - 1, ndef->data,
+                               ndef->length);
+               ndef_with_header->data[ndef->length + tlv_len_size - 1] =
+                                                                       TLV_END;
                break;
 
        case NFC_PROTO_FELICA: