tag: Add D-Bus interface
authorSamuel Ortiz <sameo@linux.intel.com>
Wed, 18 Apr 2012 15:21:48 +0000 (17:21 +0200)
committerSamuel Ortiz <sameo@linux.intel.com>
Thu, 19 Apr 2012 11:08:32 +0000 (13:08 +0200)
Preparing for moving the Target D-Bus interface to Tag.

13 files changed:
doc/tag-api.txt [new file with mode: 0644]
include/dbus.h
include/tag.h
include/target.h
plugins/mifare.c
plugins/nfctype1.c
plugins/nfctype2.c
plugins/nfctype3.c
src/main.c
src/near.h
src/tag.c
src/target.c
test/dump-tag [new file with mode: 0755]

diff --git a/doc/tag-api.txt b/doc/tag-api.txt
new file mode 100644 (file)
index 0000000..f73175d
--- /dev/null
@@ -0,0 +1,139 @@
+Target hierarchy
+================
+
+Service                org.neard
+Interface      org.neard.Tag
+Object path    [variable prefix]/{nfc0}/{tag0, tag1...}
+
+Method         dict GetProperties()
+
+                       Returns all properties for the device. See the
+                       properties section for available properties.
+
+                       Possible Errors: org.neard.Error.DoesNotExist
+
+               void SetProperty(string name, variant value)
+
+                       Changes the value of the specified property. Only
+                       properties that are listed a read-write are changeable.
+                       On success this will emit a PropertyChanged signal.
+
+                       Possible Errors: org.neard.Error.DoesNotExist
+                                        org.neard.Error.InvalidArguments
+
+
+Signals                PropertyChanged(string name, variant value)
+
+                       This signal indicates a changed value of the given
+                       property.
+
+
+Properties     string Type [readonly]
+
+                       The NFC tag type.
+                       Possible values are "Type 1", "Type 2", "Type 3",
+                       "Type 4" and "NFC-DEP"
+
+               string Protocol [readonly]
+
+                       The tag radio protocol.
+                       Possible values are "Felica", "MIFARE", "Jewel",
+                       and "ISO-DEP".
+
+               array{object} Records [readonly]
+
+                       List of NDEF records object paths.
+                       This is only valid for tag type targets.
+
+               boolean ReadOnly [readonly]
+
+                       Give the current status of tag's read mode
+                       This is valid for tag type and device targets
+
+
+Record hierarchy
+================
+
+Service                org.neard
+Interface      org.neard.Record
+Object path    [variable prefix]/{nfc0}/{tag0|device}/{record0,record1,...}
+
+Method         dict GetProperties()
+
+                       Returns all properties for the record. Each record
+                        has it's type and properties.
+
+                        If type has "Text", possible properties are "Encoding",
+                        "Language" and "Representation".
+
+                        See the properties section for available properties.
+
+                       Possible Errors: org.neard.Error.DoesNotExist
+
+Properties     string Type [readonly]
+
+                       The NDEF record type name.
+
+                       Possible values are "SmartPoster", "Text", "URI",
+                       "HandoverRequest", "HandoverSelect", "HandoverCarrier".
+
+                string Encoding [readonly]
+
+                       The character encoding.
+
+                       Possible values are "UTF-8" or "UTF-16".
+                       This property is only valid for Text and SmartPoster's
+                       title records.
+
+                string Language [readonly]
+
+                       The ISO/IANA language code (For example "en" or "jp").
+
+                       This property is only valid for Text and SmartPoster's
+                       title records.
+
+                string Representation [readonly]
+
+                       The human readable representation of a text or
+                       title record.
+
+                       This property is only valid for Text and SmartPoster's
+                       title records.
+
+               string URI [readonly]
+
+                       The record URI (for example https://nfc-forum.org).
+
+                       This is the complete URI, including the scheme and
+                       the resource.
+                       This property is only valid for SmartPoster's URI records.
+
+               string MIMEType [readonly]
+
+                       The URI object MIME type.
+
+                       This is a description of the MIME type of the object
+                       the URI points at.
+                       This is not a mandatory field and is only valid for
+                       Smart Posters carrying a URI record.
+
+               uint32 Size [readonly]
+
+                       The URI object size.
+
+                       This is the size of the object the URI points at.
+                       It should be used by applications to decide if they can
+                       afford to fetch the object or not.
+                       This is not a mandatory field and is only valid for
+                       Smart Posters carrying a URI record.
+
+               string Action [readonly]
+
+                       The suggested course of action.
+
+                       This one is only valid for Smart Posters and is a
+                       suggestion only. It can be ignored, and the possible
+                       values are "Do" (for example launch the browser),
+                       "Save" (for example save the URI in the bookmarks folder,
+                       or "Edit" (for example open the URI in an URI editor for
+                       the user to modify it.
index 874e016..58bea9b 100644 (file)
@@ -31,6 +31,7 @@
 
 #define NFC_ADAPTER_INTERFACE  NFC_SERVICE ".Adapter"
 #define NFC_TARGET_INTERFACE   NFC_SERVICE ".Target"
+#define NFC_TAG_INTERFACE      NFC_SERVICE ".Tag"
 #define NFC_RECORD_INTERFACE   NFC_SERVICE ".Record"
 
 typedef void (* near_dbus_append_cb_t) (DBusMessageIter *iter,
index 3521667..24a9d6d 100644 (file)
@@ -28,7 +28,7 @@
 
 #define NFC_HEADER_SIZE 1
 
-enum near_target_sub_type {
+enum near_tag_sub_type {
        NEAR_TAG_NFC_T2_MIFARE_ULTRALIGHT = 0,  // SAK 0x00
        NEAR_TAG_NFC_T2_MIFARE_CLASSIC_1K,      // SAK:0x08
        NEAR_TAG_NFC_T2_MIFARE_MINI,            // SAK 0x09
index 77038f7..94d70e9 100644 (file)
@@ -34,7 +34,7 @@ struct near_tag *near_target_add_tag(uint32_t adapter_idx, uint32_t target_idx,
                                        uint8_t *data, size_t data_length);
 struct near_tag *near_target_get_tag(uint32_t adapter_idx, uint32_t target_idx);
 
-enum near_target_sub_type near_target_get_subtype(uint32_t adapter_idx,
+enum near_tag_sub_type near_target_get_subtype(uint32_t adapter_idx,
                                uint32_t target_idx);
 uint8_t *near_target_get_nfcid(uint32_t adapter_idx, uint32_t target_idx,
                                uint8_t *nfcid_len);
index 3732fe7..9a223bd 100644 (file)
@@ -47,7 +47,7 @@
 
 /* Prototype */
 int mifare_read_tag(uint32_t adapter_idx, uint32_t target_idx,
-               near_tag_io_cb cb, enum near_target_sub_type tgt_subtype);
+               near_tag_io_cb cb, enum near_tag_sub_type tgt_subtype);
 
 /* MIFARE command set */
 #define MF_CMD_WRITE           0xA2
@@ -491,8 +491,6 @@ done_mad:
                goto out_err;
        }
 
-       near_tag_set_uid(mf_ck->tag, mf_ck->nfcid1, mf_ck->nfcid1_len);
-
        /* Time to read the NFC data */
        err = mifare_read_NFC(mf_ck);
 
@@ -611,7 +609,7 @@ out_err:
  * On reading, we ignore the CRC.
  */
 int mifare_read_tag(uint32_t adapter_idx, uint32_t target_idx,
-               near_tag_io_cb cb, enum near_target_sub_type tgt_subtype)
+               near_tag_io_cb cb, enum near_tag_sub_type tgt_subtype)
 {
        struct mifare_cookie *cookie;
        int err;
index 48eeb15..7b5c733 100644 (file)
@@ -255,9 +255,6 @@ static int meta_recv(uint8_t *resp, int length, void *data)
        t1_tag->cb = cookie->cb;
        t1_tag->tag = tag;
 
-       /* Save the UID */
-       near_tag_set_uid(tag, resp + LEN_SPEC_BYTES, LEN_UID_BYTES);
-
        /*s Set the ReadWrite flag */
        if (TAG_T1_WRITE_FLAG(cc) == TYPE1_NOWRITE_ACCESS)
                near_tag_set_ro(tag, TRUE);
index 3fda5b6..71ef4a2 100644 (file)
@@ -41,7 +41,7 @@
 #include <near/tlv.h>
 
 extern int mifare_read_tag(uint32_t adapter_idx, uint32_t target_idx,
-               near_tag_io_cb cb, enum near_target_sub_type tgt_subtype);
+               near_tag_io_cb cb, enum near_tag_sub_type tgt_subtype);
 
 #define CMD_READ         0x30
 #define CMD_WRITE        0xA2
@@ -213,8 +213,6 @@ static int meta_recv(uint8_t *resp, int length, void *data)
        t2_tag->cb = cookie->cb;
        t2_tag->tag = tag;
 
-       near_tag_set_uid(tag, resp + NFC_HEADER_SIZE, 8);
-
        /* Set the ReadWrite flag */
        if (TAG_T2_WRITE_FLAG(cc) == TYPE2_NOWRITE_ACCESS)
                near_tag_set_ro(tag, TRUE);
@@ -264,7 +262,7 @@ static int nfctype2_read_tag(uint32_t adapter_idx,
                                uint32_t target_idx, near_tag_io_cb cb)
 {
        int err;
-       enum near_target_sub_type tgt_subtype;
+       enum near_tag_sub_type tgt_subtype;
 
        DBG("");
 
@@ -390,7 +388,7 @@ static int nfctype2_write_tag(uint32_t adapter_idx, uint32_t target_idx,
                                near_tag_io_cb cb)
 {
        struct near_tag *tag;
-       enum near_target_sub_type tgt_subtype;
+       enum near_tag_sub_type tgt_subtype;
 
        DBG("");
 
index 37339fc..75754ee 100644 (file)
@@ -334,7 +334,6 @@ static int nfctype3_recv_block_0(uint8_t *resp, int length, void *data)
        t3_tag->cb = cookie->cb;
        t3_tag->tag = tag;
 
-       near_tag_set_uid(tag, cookie->IDm , LEN_ID);
        err = nfctype3_data_read(t3_tag);
 
 out:
index f59fda4..b354587 100644 (file)
@@ -203,6 +203,7 @@ int main(int argc, char *argv[])
        parse_config(config);
 
        __near_netlink_init();
+       __near_tag_init();
        __near_target_init();
        __near_adapter_init();
        __near_ndef_init();
@@ -224,6 +225,7 @@ int main(int argc, char *argv[])
        __near_manager_cleanup();
        __near_ndef_cleanup();
        __near_adapter_cleanup();
+       __near_tag_cleanup();
        __near_target_cleanup();
        __near_netlink_cleanup();
 
index 15f362c..ae497c4 100644 (file)
@@ -118,6 +118,8 @@ const char *__near_ndef_get_uri_prefix(uint8_t id);
 
 #include <near/tag.h>
 
+int __near_tag_init(void);
+void __near_tag_cleanup(void);
 void __near_tag_append_records(struct near_tag *tag, DBusMessageIter *iter);
 uint32_t __near_tag_n_records(struct near_tag *tag);
 int __near_tag_add_record(struct near_tag *tag, struct near_ndef_record *record);
index 40efec1..fad7ef8 100644 (file)
--- a/src/tag.c
+++ b/src/tag.c
 
 #include "near.h"
 
-#define TAG_UID_MAX_LEN 8
-
 #define TYPE3_IDM_LEN 8
 #define TYPE3_ATTR_BLOCK_SIZE 16
 
 struct near_tag {
+       char *path;
+
        uint32_t adapter_idx;
        uint32_t target_idx;
 
-       uint8_t uid[TAG_UID_MAX_LEN];
-       near_bool_t readonly;
+       uint32_t protocol;
+       uint32_t type;
+       enum near_tag_sub_type sub_type;
        enum near_tag_memory_layout layout;
+       near_bool_t readonly;
+
+       uint8_t nfcid[NFC_MAX_NFCID1_LEN];
+       uint8_t nfcid_len;
 
        size_t data_length;
        uint8_t *data;
@@ -53,6 +58,7 @@ struct near_tag {
        uint32_t n_records;
        GList *records;
 
+       /* Tag specific structures */
        struct {
                uint8_t IDm[TYPE3_IDM_LEN];
                uint8_t attr[TYPE3_ATTR_BLOCK_SIZE];
@@ -64,8 +70,154 @@ struct near_tag {
        } t4;
 };
 
+static DBusConnection *connection = NULL;
+
+static GHashTable *tag_hash;
+
 static GSList *driver_list = NULL;
 
+static void append_records(DBusMessageIter *iter, void *user_data)
+{
+       struct near_tag *tag = user_data;
+       GList *list;
+
+       DBG("");
+
+       for (list = tag->records; list; list = list->next) {
+               struct near_ndef_record *record = list->data;
+               char *path;
+
+               path = __near_ndef_record_get_path(record);
+               if (path == NULL)
+                       continue;
+
+               dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
+                                                       &path);
+       }
+}
+
+static const char *type_string(struct near_tag *tag)
+{
+       const char *type;
+
+       DBG("type 0x%x", tag->type);
+
+       switch (tag->type) {
+       case NFC_PROTO_JEWEL:
+               type = "Type 1";
+               break;
+
+       case NFC_PROTO_MIFARE:
+               type = "Type 2";
+               break;
+
+       case NFC_PROTO_FELICA:
+               type = "Type 3";
+               break;
+
+       case NFC_PROTO_ISO14443:
+               type = "Type 4";
+               break;
+
+       default:
+               type = NULL;
+               near_error("Unknown tag type 0x%x", tag->type);
+               break;
+       }
+
+       return type;
+}
+
+static const char *protocol_string(struct near_tag *tag)
+{
+       const char *protocol;
+
+       DBG("protocol 0x%x", tag->protocol);
+
+       switch (tag->protocol) {
+       case NFC_PROTO_FELICA_MASK:
+               protocol = "Felica";
+               break;
+
+       case NFC_PROTO_MIFARE_MASK:
+               protocol = "MIFARE";
+               break;
+
+       case NFC_PROTO_JEWEL_MASK:
+               protocol = "Jewel";
+               break;
+
+       case NFC_PROTO_ISO14443_MASK:
+               protocol = "ISO-DEP";
+               break;
+
+       default:
+               near_error("Unknown tag protocol 0x%x", tag->protocol);
+               protocol = NULL;
+       }
+
+       return protocol;
+}
+
+static DBusMessage *get_properties(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+{
+       struct near_tag *tag = data;
+       const char *protocol, *type;
+       DBusMessage *reply;
+       DBusMessageIter array, dict;
+
+       DBG("conn %p", conn);
+
+       reply = dbus_message_new_method_return(msg);
+       if (reply == NULL)
+               return NULL;
+
+       dbus_message_iter_init_append(reply, &array);
+
+       near_dbus_dict_open(&array, &dict);
+
+       type = type_string(tag);
+       if (type != NULL)
+               near_dbus_dict_append_basic(&dict, "Type",
+                                       DBUS_TYPE_STRING, &type);
+
+       protocol = protocol_string(tag);
+       if (protocol != NULL)
+               near_dbus_dict_append_basic(&dict, "Protocol",
+                                       DBUS_TYPE_STRING, &protocol);
+
+       near_dbus_dict_append_basic(&dict, "ReadOnly",
+                                       DBUS_TYPE_BOOLEAN, &tag->readonly);
+
+       near_dbus_dict_append_array(&dict, "Records",
+                               DBUS_TYPE_OBJECT_PATH, append_records, tag);
+
+       near_dbus_dict_close(&array, &dict);
+
+       return reply;
+}
+
+static DBusMessage *set_property(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+{
+       DBG("conn %p", conn);
+
+       return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+static GDBusMethodTable tag_methods[] = {
+       { "GetProperties",     "",      "a{sv}", get_properties     },
+       { "SetProperty",       "sv",    "",      set_property       },
+       { },
+};
+
+static GDBusSignalTable tag_signals[] = {
+       { "PropertyChanged",            "sv"    },
+       { }
+};
+
+
 void __near_tag_append_records(struct near_tag *tag, DBusMessageIter *iter)
 {
        GList *list;
@@ -83,12 +235,13 @@ void __near_tag_append_records(struct near_tag *tag, DBusMessageIter *iter)
        }
 }
 
-static int tag_initialize(struct near_tag *tag,
+static int tag_initialize(struct near_tag *tag, char *path,
                        uint32_t adapter_idx, uint32_t target_idx,
                        uint8_t * data, size_t data_length)
 {
        DBG("data length %zu", data_length);
 
+       tag->path = path;
        tag->adapter_idx = adapter_idx;
        tag->target_idx = target_idx;
        tag->n_records = 0;
@@ -111,17 +264,36 @@ struct near_tag *__near_tag_new(uint32_t adapter_idx, uint32_t target_idx,
                                uint8_t *data, size_t data_length)
 {
        struct near_tag *tag;
+       char *path;
+
+       path = g_strdup_printf("%s/nfc%d/tag%d", NFC_PATH,
+                                       adapter_idx, target_idx);
+
+       if (path == NULL)
+               return NULL;
+
+       if (g_hash_table_lookup(tag_hash, path) != NULL)
+               return NULL;
 
        tag = g_try_malloc0(sizeof(struct near_tag));
        if (tag == NULL)
                return NULL;
 
-       if (tag_initialize(tag, adapter_idx, target_idx,
+       if (tag_initialize(tag, path, adapter_idx, target_idx,
                                        data, data_length) < 0) {
                g_free(tag);
                return NULL;
        }
 
+       g_hash_table_insert(tag_hash, path, tag);
+
+       DBG("connection %p", connection);
+
+       g_dbus_register_interface(connection, tag->path,
+                                       NFC_TAG_INTERFACE,
+                                       tag_methods, tag_signals,
+                                                       NULL, tag, NULL);
+
        return tag;
 }
 
@@ -129,6 +301,8 @@ void __near_tag_free(struct near_tag *tag)
 {
        GList *list;
 
+       DBG("");
+
        for (list = tag->records; list; list = list->next) {
                struct near_ndef_record *record = list->data;
 
@@ -136,6 +310,7 @@ void __near_tag_free(struct near_tag *tag)
        }
 
        g_list_free(tag->records);
+       g_free(tag->path);
        g_free(tag->data);
        g_free(tag);
 }
@@ -156,17 +331,6 @@ int __near_tag_add_record(struct near_tag *tag,
        return 0;
 }
 
-int near_tag_set_uid(struct near_tag *tag, uint8_t *uid, size_t uid_length)
-{
-       if (uid_length > TAG_UID_MAX_LEN)
-               return -EINVAL;
-
-       memset(tag->uid, 0, TAG_UID_MAX_LEN);
-       memcpy(tag->uid, uid, uid_length);
-
-       return 0;
-}
-
 int near_tag_set_ro(struct near_tag *tag, near_bool_t readonly)
 {
        tag->readonly = readonly;
@@ -409,3 +573,32 @@ int __near_tag_check_presence(struct near_target *target, near_tag_io_cb cb)
 
        return -EOPNOTSUPP;
 }
+
+static void free_tag(gpointer data)
+{
+       struct near_tag *tag = data;
+
+       DBG("");
+
+       __near_tag_free(tag);
+}
+
+int __near_tag_init(void)
+{
+       DBG("");
+
+       connection = near_dbus_get_connection();
+
+       tag_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
+                                               g_free, free_tag);
+
+       return 0;
+}
+
+void __near_tag_cleanup(void)
+{
+       DBG("");
+
+       g_hash_table_destroy(tag_hash);
+       tag_hash = NULL;
+}
index 41a7f4c..c1a7443 100644 (file)
@@ -41,7 +41,7 @@ struct near_target {
        uint32_t adapter_idx;
        uint32_t protocols;
        enum near_target_type type;
-       enum near_target_sub_type sub_type;
+       enum near_tag_sub_type sub_type;
        uint8_t nfcid[NFC_MAX_NFCID1_LEN];
        uint8_t nfcid_len;
 
@@ -296,7 +296,7 @@ static GDBusSignalTable target_signals[] = {
 #define NFC_TAG_A_SENS_RES_SSD(sens_res) ((sens_res) & 0x001f)
 #define NFC_TAG_A_SENS_RES_PLATCONF(sens_res) (((sens_res) & 0x0f00) >> 8)
 
-static enum near_target_sub_type get_tag_type2_sub_type(uint8_t sel_res)
+static enum near_tag_sub_type get_tag_type2_sub_type(uint8_t sel_res)
 {
        switch(sel_res) {
        case 0x00 :
@@ -425,7 +425,7 @@ void __near_target_remove(struct near_target *target)
        g_hash_table_remove(target_hash, target->path);
 }
 
-enum near_target_sub_type near_target_get_subtype(uint32_t adapter_idx,
+enum near_tag_sub_type near_target_get_subtype(uint32_t adapter_idx,
                                uint32_t target_idx)
 
 {
diff --git a/test/dump-tag b/test/dump-tag
new file mode 100755 (executable)
index 0000000..8ce8d6b
--- /dev/null
@@ -0,0 +1,45 @@
+#!/usr/bin/python
+
+import sys
+import dbus
+
+bus = dbus.SystemBus()
+
+def extract_list(list):
+       val = "["
+       for i in list:
+               val += " " + str(i)
+       val += " ]"
+       
+       return val
+
+def extract_record(key, list):
+       for i in list:
+               record = dbus.Interface(bus.get_object("org.neard", i),
+                                               "org.neard.Record")
+
+               properties = record.GetProperties()
+               print "        Record = [ %s ]" % (str(i))
+
+               for key in properties.keys():
+                       val = str(properties[key])
+                       print "              %s = %s" % (key, val)
+
+tag = dbus.Interface(bus.get_object("org.neard", sys.argv[1]),
+                                               "org.neard.Tag")
+
+properties = tag.GetProperties()
+
+print "[ %s ]" % (sys.argv[1])
+
+for key in properties.keys():
+    if key in ["Type"]:
+        val = str(properties[key])
+       print "        %s = %s" % (key, val)
+    elif key in ["Protocol"]:
+       val = str(properties[key])
+       print "        %s = %s" % (key, val)
+
+    if key in ["Records"]:
+        extract_record(key, properties[key])
+