tag: Add reader callback support
authorSamuel Ortiz <sameo@linux.intel.com>
Wed, 8 Jun 2011 14:09:13 +0000 (16:09 +0200)
committerMarcel Holtmann <marcel@holtmann.org>
Fri, 21 Oct 2011 06:54:04 +0000 (23:54 -0700)
include/tag.h
plugins/nfctype2.c
src/adapter.c
src/near.h
src/tag.c

index 3b09f52..0d9280b 100644 (file)
 #define        NEAR_TAG_NFC_DEP     0x10
 #define        NEAR_TAG_NFC_UNKNOWN 0xff
 
+typedef void (*near_tag_read_cb) (uint32_t adapter_idx, int status);
+
 struct near_tag_driver {
        uint16_t type;
 
-       int (*read_tag)(uint32_t adapter_idx, uint32_t target_idx);
+       int (*read_tag)(uint32_t adapter_idx, uint32_t target_idx,
+                                               near_tag_read_cb cb);
 };
 
 struct near_tag;
index 3d541ed..214f2de 100644 (file)
@@ -67,8 +67,10 @@ struct type2_cmd {
 } __attribute__((packed));
 
 struct type2_tag {
+       uint32_t adapter_idx;
        uint16_t current_block;
 
+       near_tag_read_cb cb;
        struct near_tag *tag;
 };
 
@@ -120,7 +122,7 @@ static uint8_t *tlv_data(uint8_t *data)
        return data + 1 + l_length;
 }
 
-static int data_parse(struct near_tag *tag, uint8_t *data, uint16_t length)
+static int data_parse(struct type2_tag *tag, uint8_t *data, uint16_t length)
 {
        uint8_t *tlv = data, t;
 
@@ -135,13 +137,17 @@ static int data_parse(struct near_tag *tag, uint8_t *data, uint16_t length)
                case TLV_NDEF:
                        DBG("NDEF found %d bytes long", tlv_length(tlv));
 
-                       near_tag_add_ndef(tag, tlv_data(tlv), tlv_length(tlv));
+                       near_tag_add_ndef(tag->tag, tlv_data(tlv),
+                                               tlv_length(tlv));
 
                        break;
                case TLV_END:
-                       return 0;
+                       break;
                }
 
+               if (t == TLV_END)
+                       break;
+
                tlv = next_tlv(tlv);
 
                if (tlv - data >= length)
@@ -150,6 +156,9 @@ static int data_parse(struct near_tag *tag, uint8_t *data, uint16_t length)
 
        DBG("Done");
 
+       if (tag->cb)
+               tag->cb(tag->adapter_idx, 0);
+
        return 0;
 }
 
@@ -187,7 +196,7 @@ static int data_recv(uint8_t *resp, int length, void *data)
 
                DBG("Done reading");
 
-               data_parse(tag->tag, nfc_data, data_length);
+               data_parse(tag, nfc_data, data_length);
 
                g_free(tag);
 
@@ -226,9 +235,15 @@ static int data_read(struct type2_tag *tag)
                                        data_recv, 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)
 {
-        uint32_t *target_idx = data;
+        struct recv_cookie *cookie = data;
        struct near_tag *tag;
        struct type2_tag *t2_tag;
        uint8_t *cc;
@@ -253,13 +268,20 @@ static int meta_recv(uint8_t *resp, int length, void *data)
                goto out;
        }
 
-       tag = near_target_get_tag(*target_idx, TAG_DATA_LENGTH(cc));
+       tag = near_target_get_tag(cookie->target_idx, TAG_DATA_LENGTH(cc));
        if (tag == NULL) {
                err = -ENOMEM;
                goto out;
        }
 
        t2_tag = g_try_malloc0(sizeof(struct type2_tag));
+       if (t2_tag == NULL) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       t2_tag->adapter_idx = cookie->adapter_idx;
+       t2_tag->cb = cookie->cb;
        t2_tag->tag = tag;
 
        near_tag_set_uid(tag, resp + NFC_HEADER_SIZE, 8);
@@ -267,29 +289,36 @@ static int meta_recv(uint8_t *resp, int length, void *data)
        err = data_read(t2_tag);
 
 out:
-       g_free(data);
+       g_free(cookie);
+
+       if (err < 0 && cookie->cb)
+               cookie->cb(cookie->adapter_idx, err);
 
        return err;
 }
 
-static int nfctype2_read_meta(uint32_t adapter_idx, uint32_t target_idx)
+static int nfctype2_read_meta(uint32_t adapter_idx, uint32_t target_idx,
+                                                       near_tag_read_cb cb)
 {
        struct type2_cmd cmd;
-       uint32_t *idx;
+       struct recv_cookie *cookie;
        
        DBG("");
 
        cmd.cmd = CMD_READ;
        cmd.block = META_BLOCK_START;
 
-       idx = g_try_malloc0(sizeof(uint32_t));
-       *idx = target_idx;
+       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 *)&cmd, sizeof(cmd), meta_recv, idx);
+       return near_adapter_send(adapter_idx, (uint8_t *)&cmd, sizeof(cmd),
+                                                       meta_recv, cookie);
 }
 
 static int nfctype2_read_tag(uint32_t adapter_idx,
-                                       uint32_t target_idx)
+                               uint32_t target_idx, near_tag_read_cb cb)
 {
        int err;
 
@@ -302,7 +331,7 @@ static int nfctype2_read_tag(uint32_t adapter_idx,
                return err;
        }
 
-       err = nfctype2_read_meta(adapter_idx, target_idx);
+       err = nfctype2_read_meta(adapter_idx, target_idx, cb);
        if (err < 0)
                near_adapter_disconnect(adapter_idx);
 
index eade985..626bbe9 100644 (file)
@@ -341,6 +341,22 @@ void __near_adapter_remove(struct near_adapter *adapter)
        g_hash_table_remove(adapter_hash, GINT_TO_POINTER(adapter->idx));
 }
 
+static void tag_read_cb(uint32_t adapter_idx, int status)
+{
+       struct near_adapter *adapter;
+
+       DBG("%d", status);
+
+       if (status < 0)
+               return;
+
+       adapter = g_hash_table_lookup(adapter_hash, GINT_TO_POINTER(adapter_idx));
+       if (adapter == NULL)
+               return;
+
+       target_changed(adapter);
+}
+
 int __near_adapter_add_target(uint32_t idx, struct near_target *target)
 {
        struct near_adapter *adapter;
@@ -360,9 +376,7 @@ int __near_adapter_add_target(uint32_t idx, struct near_target *target)
 
        polling_changed(adapter);
 
-       target_changed(adapter);
-
-       __near_tag_read(target);
+       __near_tag_read(target, tag_read_cb);
 
        return 0;
 }
index 9b081fa..2edfd6b 100644 (file)
@@ -107,7 +107,7 @@ void __near_target_cleanup(void);
 struct near_tag *__near_tag_new(uint32_t adapter_idx, uint32_t target_idx,
                                size_t data_length);
 void __near_tag_free(struct near_tag *tag);
-int __near_tag_read(struct near_target *target);
+int __near_tag_read(struct near_target *target, near_tag_read_cb cb);
 
 int __near_netlink_get_adapters(void);
 int __near_netlink_start_poll(int idx, uint32_t protocols);
index b3851a6..446435a 100644 (file)
--- a/src/tag.c
+++ b/src/tag.c
@@ -154,7 +154,7 @@ void near_tag_driver_unregister(struct near_tag_driver *driver)
        driver_list = g_list_remove(driver_list, driver);
 }
 
-int __near_tag_read(struct near_target *target)
+int __near_tag_read(struct near_target *target,near_tag_read_cb cb)
 {
        GList *list;
        uint16_t type;
@@ -178,7 +178,7 @@ int __near_tag_read(struct near_target *target)
                        target_idx = __near_target_get_idx(target);
                        adapter_idx = __near_target_get_adapter_idx(target);
 
-                       return driver->read_tag(adapter_idx, target_idx);
+                       return driver->read_tag(adapter_idx, target_idx, cb);
                }
        }