#define AMB_INTERFACE_NAME "org.automotive.Manager"
#define DBUS_INTERFACE_NAME "org.freedesktop.DBus.Properties"
+struct callback_item {
+ AMB_PROPERTY_CHANGED_CALLBACK callback;
+ void *user_data;
+ gboolean is_delete;
+ guint32 cid;
+};
+
struct signal_item {
+ gchar *key;
guint id;
GDBusProxy *obj;
+ GList *cb_list;
+ guint32 next_cid;
};
/******************************************************************************
gchar *sender_name,
gchar *signal_name,
GVariant *parameters,
- gpointer user_callback)
+ gpointer signal_item)
{
gchar *obj_name;
GVariant *value;
- AMB_PROPERTY_CHANGED_CALLBACK callback = (AMB_PROPERTY_CHANGED_CALLBACK)user_callback;
+ GList *l;
+ GList *ll;
+ struct signal_item *item = (struct signal_item *)signal_item;
if (g_strcmp0("PropertiesChanged", signal_name)) {
DEBUGOUT("Error: signal name: %s\n", signal_name);
}
g_variant_get(parameters, "(s@a{sv}as)", &obj_name, &value, NULL);
- if (callback)
- callback(obj_name, value);
+ for (l = item->cb_list; l != NULL; l = l->next) {
+ struct callback_item *citem = l->data;
+ if (!citem->is_delete && citem->callback) {
+ citem->callback(obj_name, value, citem->user_data);
+ }
+ }
g_free(obj_name);
g_variant_unref(value);
+ // remove all marked callback items
+ for (l = item->cb_list, ll = g_list_next(l);
+ l != NULL;
+ l = ll, ll = g_list_next(ll)) {
+ struct callback_item *citem = l->data;
+ if (citem->is_delete) {
+ DEBUGOUT("%s, id = %u is deleted\n", signal_name, citem->cid);
+ g_free(citem);
+ item->cb_list = g_list_delete_link(item->cb_list, l);
+ }
+ }
+
+ if (g_list_length(item->cb_list) == 0) {
+ DEBUGOUT("Remove item from htable\n");
+
+ GHashTable *htable = get_htable();
+ if (!htable) {
+ DEBUGOUT("Error: get_htable() returns NULL\n");
+ return ;
+ }
+
+ g_signal_handler_disconnect(item->obj, item->id);
+ if (!g_hash_table_remove(htable, item->key))
+ DEBUGOUT("Error: fail to g_hash_table_remove()\n");
+
+ g_free(item->key);
+ g_free(item);
+ }
return ;
}
EXPORT int amb_register_property_changed_handler(gchar *objname,
ZoneType zone,
- AMB_PROPERTY_CHANGED_CALLBACK callback)
+ AMB_PROPERTY_CHANGED_CALLBACK callback,
+ void *user_data,
+ guint32 *id)
{
GDBusProxy *proxy;
GDBusProxy *objproxy;
- guint id;
struct signal_item *item;
+ struct callback_item *citem;
GHashTable *htable;
+ if (callback == NULL)
+ return -EINVAL;
+
htable = get_htable();
if (!htable) {
DEBUGOUT("Error: get_htable() returns NULL\n");
return -EINVAL;
}
- item = g_new0(struct signal_item, 1);
- if (!item) {
+ if (!g_hash_table_lookup_extended(htable,
+ g_dbus_proxy_get_object_path(objproxy),
+ NULL, (gpointer*)&item)) {
+ guint sid;
+ DEBUGOUT("Not register: %s\n", g_dbus_proxy_get_object_path(objproxy));
+
+ item = g_new0(struct signal_item, 1);
+ if (!item) {
+ DEBUGOUT("Error: fail to g_new0()\n");
+ g_object_unref(objproxy);
+ return -ENOMEM;
+ }
+ sid = g_signal_connect(objproxy, "g-signal", G_CALLBACK(on_signal_handler), (gpointer)item);
+
+ item->key = g_strdup(g_dbus_proxy_get_object_path(objproxy));
+ item->id = sid;
+ item->next_cid = 0;
+ item->obj = objproxy;
+ g_hash_table_insert(htable, item->key, item);
+ }
+
+ citem = g_new0(struct callback_item, 1);
+ if (!citem) {
DEBUGOUT("Error: fail to g_new0()\n");
g_object_unref(objproxy);
return -ENOMEM;
}
- id = g_signal_connect(objproxy, "g-signal", G_CALLBACK(on_signal_handler), (gpointer)callback);
- item->id = id;
- item->obj = objproxy;
-
- g_hash_table_insert(htable,
- g_strdup(g_dbus_proxy_get_object_path(objproxy)),
- item);
-
- DEBUGOUT("instance: %s ID: %u\n", g_dbus_proxy_get_object_path(objproxy), id);
+ citem->cid = __atomic_fetch_add(&item->next_cid, 1, __ATOMIC_RELAXED);
+ citem->is_delete = FALSE;
+ citem->callback = callback;
+ citem->user_data = user_data;
+ *id = citem->cid;
+ item->cb_list = g_list_append(item->cb_list, citem);
+ DEBUGOUT("instance: %s ID: %u\n", g_dbus_proxy_get_object_path(objproxy), *id);
return 0;
}
-EXPORT int amb_unregister_property_changed_handler(gchar *objname, ZoneType zone)
+EXPORT int amb_unregister_property_changed_handler(gchar *objname, ZoneType zone, guint32 id)
{
GHashTable *htable;
GDBusProxy *proxy;
GDBusProxy *objproxy;
- gpointer key;
struct signal_item *item;
gchar *objpath;
+ GList *l;
htable = get_htable();
if (!htable) {
objpath = (gchar*)g_dbus_proxy_get_object_path(objproxy);
- if (!g_hash_table_lookup_extended(htable, objpath, &key, (gpointer*)&item)) {
+ if (!g_hash_table_lookup_extended(htable, objpath, NULL, (gpointer*)&item)) {
DEBUGOUT("Error: fail to find the object :%s\n", objpath);
g_object_unref(objproxy);
return -EINVAL;
}
- DEBUGOUT("instance: %s ID: %u\n", objpath, item->id);
-
- g_signal_handler_disconnect(item->obj, item->id);
- if (!g_hash_table_remove(htable, objpath)) {
- DEBUGOUT("Error: fail to g_hash_table_remove()\n");
+ // mark to delete
+ for (l = item->cb_list; l != NULL; l = l->next) {
+ struct callback_item *citem = l->data;
+ if (citem->cid == id) {
+ DEBUGOUT("%s: id: %u is marked to delete\n", objname, citem->cid);
+ citem->is_delete = TRUE;
+ }
}
-
- g_free(key);
- g_free(item);
-
+ DEBUGOUT("Delete monitoring: %s ID: %u\n", objpath, id);
return 0;
}
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <libamb-client.h>
#include <libamb-objects.h>
amb_release_property_all_with_zone(ret);
}
-static void signal_handler(const gchar *objname, gpointer data)
-{
- gchar *s;
- GVariant *gdata = (GVariant *)data;
-
- if (!data)
- return ;
-
- s = g_variant_print(gdata, TRUE);
- g_print("== signal_handler: %s\n", objname);
- g_print("%s\n", s);
-
- g_free(s);
-}
-
-static gboolean timer_callback(gpointer d)
-{
- int rc;
- gchar *objname = (gchar *)d;
-
- fprintf(stderr, "Enter %s(): %s\n", __func__, objname);
-
- rc = amb_unregister_property_changed_handler(objname, 0);
- if (rc != 0) {
- fprintf(stderr, "Fail to amb_unregister_property_changed_handler(): %s\n", objname);
- }
-
- return FALSE;
-}
-
-void test_signal_listen(gchar *objname, ZoneType zone)
-{
- GMainLoop *loop;
- int rc;
-
- rc = amb_register_property_changed_handler(objname, zone, (AMB_PROPERTY_CHANGED_CALLBACK)signal_handler);
- if (rc != 0) {
- fprintf(stderr, "Fail to amb_register_property_changed_handler(): %s\n", objname);
- return ;
- }
-
- g_timeout_add_seconds(10, timer_callback, objname);
-
- loop = g_main_loop_new(NULL, FALSE);
- g_main_loop_run(loop);
-
- g_main_loop_unref(loop);
-}
-
-static void VehicleOdometer_handler(const gchar *objname, gpointer data)
-{
- struct VehicleOdometerType retdata;
-
- if (!data)
- return ;
-
- amb_convert_VehicleOdometerType(data, &retdata);
-
- fprintf(stderr, " == VehicleOdometer ==\n");
- fprintf(stderr, " Zone: %d\n", retdata.Zone);
- fprintf(stderr, " Value: %d\n", retdata.Value);
- fprintf(stderr, " ValueSequence: %d\n", retdata.ValueSequence);
- fprintf(stderr, " Time: %f\n", retdata.Time);
-}
-
-static void test_VehicleOdometer_listen()
-{
- GMainLoop *loop;
- int rc;
-
- rc = amb_register_property_changed_handler("VehicleOdometer", 0,
- (AMB_PROPERTY_CHANGED_CALLBACK)VehicleOdometer_handler);
- if (rc != 0) {
- fprintf(stderr, "Fail to amb_register_property_changed_handler(): %s\n", "VehicleOdometer");
- return ;
- }
-
- g_timeout_add_seconds(10, timer_callback, "VehicleOdometer");
-
- loop = g_main_loop_new(NULL, FALSE);
- g_main_loop_run(loop);
-
- g_main_loop_unref(loop);
-}
-
static void test_samsungcan_GearboxPosition()
{
struct GearboxPositionDisplayType *p;
amb_release_data(p);
}
-static void LampHazardLight_handler(const gchar *objname, gpointer data)
+static void LampHazardLight_handler(const gchar *objname, gpointer data, void *user_data)
{
struct LampHazardLightType retdata;
fprintf(stderr, " Time: %f\n", retdata.Time);
}
-static void test_LampHazardLight_listen()
-{
- GMainLoop *loop;
- int rc;
-
- rc = amb_register_property_changed_handler("LampHazardLight", 0,
- (AMB_PROPERTY_CHANGED_CALLBACK)LampHazardLight_handler);
- if (rc != 0) {
- fprintf(stderr, "Fail to amb_register_property_changed_handler(): %s\n", "LampHazardLight");
- return ;
- }
-
- g_timeout_add_seconds(10, timer_callback, "LampHazardLight");
-
- loop = g_main_loop_new(NULL, FALSE);
- g_main_loop_run(loop);
-
- g_main_loop_unref(loop);
-}
-
static void test_WarningSafetybelts()
{
struct WarningSafetybeltsType *p;
amb_release_data(p);
}
-static void WarningSafetybelts_handler(const gchar *objname, gpointer data)
-{
- struct WarningSafetybeltsType retdata;
-
- if (!data)
- return ;
-
- amb_convert_WarningSafetybeltsType(data, &retdata);
-
- fprintf(stderr, " == WarningSafetybelts ==\n");
- fprintf(stderr, " Zone: %d\n", retdata.Zone);
- fprintf(stderr, " Value: %s\n", (retdata.Value) ? "Set" : "None");
- fprintf(stderr, " ValueSequence: %d\n", retdata.ValueSequence);
- fprintf(stderr, " Time: %f\n", retdata.Time);
-}
-
-static void test_WarningSafetybelts_listen()
-{
- GMainLoop *loop;
- int rc;
-
- rc = amb_register_property_changed_handler("WarningSafetybelts", 0,
- (AMB_PROPERTY_CHANGED_CALLBACK)WarningSafetybelts_handler);
- if (rc != 0) {
- fprintf(stderr, "Fail to amb_register_property_changed_handler(): %s\n", "WarningSafetybelts");
- return ;
- }
-
- g_timeout_add_seconds(10, timer_callback, "WarningSafetybelts");
-
- loop = g_main_loop_new(NULL, FALSE);
- g_main_loop_run(loop);
-
- g_main_loop_unref(loop);
-}
-
static void test_samsungcan_VehicleOdometer()
{
struct VehicleOdometerType *p;
}
fprintf(stderr, " == TPMS_FL ==\n");
fprintf(stderr, " Zone: %d\n", p->Zone);
- // fprintf(stderr, " Value: %u\n", (unsigned int)p->Value);
fprintf(stderr, " Value: %u\n", p->Value);
fprintf(stderr, " ValueSequence: %d\n", p->ValueSequence);
fprintf(stderr, " Time: %f\n", p->Time);
amb_release_data(p);
}
-static void TPMS_FL_handler(const gchar *objname, gpointer data)
-{
- struct TPMS_FLType retdata;
-
- if (!data)
- return ;
-
- amb_convert_TPMS_FLType(data, &retdata);
-
- fprintf(stderr, " == TPMS_FL ==\n");
- fprintf(stderr, " Zone: %d\n", retdata.Zone);
- fprintf(stderr, " Value: %u\n", retdata.Value);
- fprintf(stderr, " ValueSequence: %d\n", retdata.ValueSequence);
- fprintf(stderr, " Time: %f\n", retdata.Time);
-}
-
-static void test_TPMS_FL_listen()
-{
- GMainLoop *loop;
- int rc;
-
- rc = amb_register_property_changed_handler("TPMS_FL", 0,
- (AMB_PROPERTY_CHANGED_CALLBACK)TPMS_FL_handler);
- if (rc != 0) {
- fprintf(stderr, "Fail to amb_register_property_changed_handler(): %s\n", "WarningSafetybelts");
- return ;
- }
-
- g_timeout_add_seconds(10, timer_callback, "TPMS_FL");
-
- loop = g_main_loop_new(NULL, FALSE);
- g_main_loop_run(loop);
-
- g_main_loop_unref(loop);
-}
-
static void test_FuelGage()
{
struct FuelGageType *p;
amb_release_data(p);
}
+/*****************************************************************************/
+
+struct user_data_test {
+ int value;
+ char *name;
+};
+
+struct user_data_test *udata;
+struct user_data_test *udata2;
+
+static int convert_VehicleOdometerType(GVariant *data, struct VehicleOdometerType *retdata)
+{
+ GVariantIter *iter;
+ gchar *key;
+ GVariant *value;
+ GVariant *gdata;
+
+ gdata = (GVariant *)data;
+
+
+ g_variant_get(gdata, "a{sv}", &iter);
+ while(g_variant_iter_loop(iter, "{sv}", &key, &value)) {
+ if (!g_strcmp0(key, "Zone")) {
+ g_variant_get(value, "i", &retdata->Zone);
+ fprintf(stderr, "%s: %d\n", key, retdata->Zone);
+ } else if (!g_strcmp0(key, "ValueSequence") || !g_strcmp0(key, "ValueSequence")) {
+ g_variant_get(value, "i", &retdata->ValueSequence);
+ fprintf(stderr, "%s: %d\n", key, retdata->ValueSequence);
+ } else if (!g_strcmp0(key, "Time")) {
+ g_variant_get(value, "d", &retdata->Time);
+ fprintf(stderr, "%s: %f\n", key, retdata->Time);
+ } else if (!g_strcmp0(key, "Value") || !g_strcmp0(key, "Vaule")) {
+ g_variant_get(value, "u", &retdata->Value);
+ fprintf(stderr, "%s: %d\n", key, retdata->Value);
+ }
+ }
+ g_variant_iter_free(iter);
+ return 0;
+}
+
+static void VehicleOdometer_handler(const gchar *objname, gpointer data, void *user_data)
+{
+ struct VehicleOdometerType retdata;
+ struct user_data_test *udata = (struct user_data_test *)user_data;
+
+ fprintf(stderr, "== User Data ==\n");
+ fprintf(stderr, " value: %d\n", udata->value);
+ fprintf(stderr, " name: %s\n", udata->name);
+
+
+ if (!data)
+ return ;
+
+ convert_VehicleOdometerType(data, &retdata);
+}
+
+static gboolean timer_callback(gpointer d)
+{
+ free(udata->name);
+ g_free(udata);
+ exit(0);
+
+ return FALSE;
+}
+
+static void test_VehicleOdometer_listen()
+{
+ GMainLoop *loop;
+ guint32 id1;
+ guint32 id2;
+ int rc;
+
+ udata = g_new0(struct user_data_test, 1);
+ udata->value = 20;
+ udata->name = strdup("Test Name");
+
+ rc = amb_register_property_changed_handler("VehicleOdometer",
+ 0,
+ (AMB_PROPERTY_CHANGED_CALLBACK)VehicleOdometer_handler,
+ (void *)udata, &id1);
+ if (rc != 0) {
+ fprintf(stderr, "Fail to amb_register_property_changed_handler(): %s\n", "VehicleOdometer");
+ return ;
+ }
+
+ udata2 = g_new0(struct user_data_test, 1);
+ udata2->value = 100;
+ udata2->name = strdup("Test Name2");
+ rc = amb_register_property_changed_handler("VehicleOdometer",
+ 0,
+ (AMB_PROPERTY_CHANGED_CALLBACK)VehicleOdometer_handler,
+ (void *)udata2, &id2);
+ if (rc != 0) {
+ fprintf(stderr, "Fail to amb_register_property_changed_handler(): %s\n", "VehicleOdometer");
+ return ;
+ }
+ fprintf(stderr, "id1: %u, id2: %u\n", id1, id2);
+
+#if 0
+ rc = amb_unregister_property_changed_handler("VehicleOdometer", 0, id1);
+ if (rc != 0) {
+ fprintf(stderr, "Fail to amb_unregister_property_changed_handler(): %u\n", id1);
+ return ;
+ }
+#endif
+
+ // g_timeout_add_seconds(10, timer_callback, "VehicleOdometer");
+ loop = g_main_loop_new(NULL, FALSE);
+ g_main_loop_run(loop);
+
+ g_main_loop_unref(loop);
+}
+
+
int main()
{
- test_get_object_list();
+ test_VehicleOdometer_listen();
- // cansend vcan0 207#03.00.00.00.00.00.00.00
test_FR_KeyEvent01();
test_FR_KeyEvent02();
+ test_get_object_list();
+
// cansend vcan0 104#3C.00.00.00.00.00.00.00
test_FuelGage();
// cansend vcan0 104#3C.00.00.00.00.00.00.00
test_TPMS_FL();
- test_TPMS_FL_listen();
// cansend vcan0 206#00.00.00.00.01.00.00.00
test_LampHazardLight();
- test_LampHazardLight_listen();
// cansend vcan0 206#01.00.00.00.00.00.00.00
test_WarningSafetybelts();
test_samsungcan_VehicleSpeed();
test_samsungcan_GearboxPosition();
- test_VehicleOdometer_listen();
-
#ifdef EXAMPLE_PLUGIN
test_get_property_all("ClimateControl");
test_get_property_all("VehicleSpeed");
test_set_property("ClimateControl", "AirConditioning", 5, g_variant_new("b", TRUE));
- test_signal_listen("VehicleSpeed", 0);
-
test_samsungcan_GearboxPosition();
#endif