Upgrade bluez5_37 :Merge the code from private
[platform/upstream/bluez.git] / client / main.c
index 4e7a54a..4faa9c6 100644 (file)
@@ -162,6 +162,7 @@ static void print_iter(const char *label, const char *name,
        unsigned char byte;
        const char *valstr;
        DBusMessageIter subiter;
+       char *entry;
 
        if (iter == NULL) {
                rl_printf("%s%s is nil\n", label, name);
@@ -212,9 +213,14 @@ static void print_iter(const char *label, const char *name,
                break;
        case DBUS_TYPE_DICT_ENTRY:
                dbus_message_iter_recurse(iter, &subiter);
-               dbus_message_iter_get_basic(&subiter, &valstr);
+               entry = g_strconcat(name, " Key", NULL);
+               print_iter(label, entry, &subiter);
+               g_free(entry);
+
+               entry = g_strconcat(name, " Value", NULL);
                dbus_message_iter_next(&subiter);
-               print_iter(label, valstr, &subiter);
+               print_iter(label, entry, &subiter);
+               g_free(entry);
                break;
        default:
                rl_printf("%s%s has unsupported type\n", label, name);
@@ -381,6 +387,8 @@ static void set_default_device(GDBusProxy *proxy, const char *attribute)
 
 done:
        rl_set_prompt(desc ? desc : PROMPT_ON);
+       printf("\r");
+       rl_on_new_line();
        rl_redisplay();
        g_free(desc);
 }
@@ -430,12 +438,10 @@ static void proxy_removed(GDBusProxy *proxy, void *user_data)
                                agent_unregister(dbus_conn, NULL);
                }
        } else if (!strcmp(interface, "org.bluez.GattService1")) {
-               if (service_is_child(proxy)) {
-                       gatt_remove_service(proxy);
+               gatt_remove_service(proxy);
 
-                       if (default_attr == proxy)
-                               set_default_attribute(NULL);
-               }
+               if (default_attr == proxy)
+                       set_default_attribute(NULL);
        } else if (!strcmp(interface, "org.bluez.GattCharacteristic1")) {
                gatt_remove_characteristic(proxy);
 
@@ -899,6 +905,222 @@ static void cmd_scan(const char *arg)
        }
 }
 
+static void append_variant(DBusMessageIter *iter, int type, void *val)
+{
+       DBusMessageIter value;
+       char sig[2] = { type, '\0' };
+
+       dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, sig, &value);
+
+       dbus_message_iter_append_basic(&value, type, val);
+
+       dbus_message_iter_close_container(iter, &value);
+}
+
+static void dict_append_entry(DBusMessageIter *dict, const char *key,
+                                                       int type, void *val)
+{
+       DBusMessageIter entry;
+
+       if (type == DBUS_TYPE_STRING) {
+               const char *str = *((const char **) val);
+
+               if (str == NULL)
+                       return;
+       }
+
+       dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
+                                                       NULL, &entry);
+
+       dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+
+       append_variant(&entry, type, val);
+
+       dbus_message_iter_close_container(dict, &entry);
+}
+
+#define        DISTANCE_VAL_INVALID    0x7FFF
+
+struct set_discovery_filter_args {
+       char *transport;
+       dbus_uint16_t rssi;
+       dbus_int16_t pathloss;
+       GSList *uuids;
+};
+
+static void set_discovery_filter_setup(DBusMessageIter *iter,
+                                          void *user_data)
+{
+       struct set_discovery_filter_args *args = user_data;
+       DBusMessageIter dict;
+
+       dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+                           DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+                           DBUS_TYPE_STRING_AS_STRING
+                           DBUS_TYPE_VARIANT_AS_STRING
+                           DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+       if (args->uuids != NULL) {
+               DBusMessageIter entry, value, arrayIter;
+               char *uuids = "UUIDs";
+               GSList *l;
+
+               dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
+                                                NULL, &entry);
+               /* dict key */
+               dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
+                                              &uuids);
+
+               dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
+                                                "as", &value);
+
+               dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY, "s",
+                                                &arrayIter);
+
+               for (l = args->uuids; l != NULL; l = g_slist_next(l))
+                       /* list->data contains string representation of uuid */
+                       dbus_message_iter_append_basic(&arrayIter,
+                                                      DBUS_TYPE_STRING,
+                                                      &l->data);
+
+               dbus_message_iter_close_container(&value, &arrayIter);
+
+               /* close vararg*/
+               dbus_message_iter_close_container(&entry, &value);
+
+               /* close entry */
+               dbus_message_iter_close_container(&dict, &entry);
+       }
+
+       if (args->pathloss != DISTANCE_VAL_INVALID)
+               dict_append_entry(&dict, "Pathloss", DBUS_TYPE_UINT16,
+                                 &args->pathloss);
+
+       if (args->rssi != DISTANCE_VAL_INVALID)
+               dict_append_entry(&dict, "RSSI", DBUS_TYPE_INT16, &args->rssi);
+
+       if (args->transport != NULL)
+               dict_append_entry(&dict, "Transport", DBUS_TYPE_STRING,
+                                 &args->transport);
+
+       dbus_message_iter_close_container(iter, &dict);
+}
+
+
+static void set_discovery_filter_reply(DBusMessage *message,
+                                      void *user_data)
+{
+       DBusError error;
+
+       dbus_error_init(&error);
+       if (dbus_set_error_from_message(&error, message) == TRUE) {
+               rl_printf("SetDiscoveryFilter failed: %s\n", error.name);
+               dbus_error_free(&error);
+               return;
+       }
+
+       rl_printf("SetDiscoveryFilter success\n");
+}
+
+static gint filtered_scan_rssi = DISTANCE_VAL_INVALID;
+static gint filtered_scan_pathloss = DISTANCE_VAL_INVALID;
+static GSList *filtered_scan_uuids;
+static char *filtered_scan_transport;
+
+static void cmd_set_scan_filter_commit(void)
+{
+       struct set_discovery_filter_args args;
+
+       args.uuids = NULL;
+       args.pathloss = filtered_scan_pathloss;
+       args.rssi = filtered_scan_rssi;
+       args.transport = filtered_scan_transport;
+       args.uuids = filtered_scan_uuids;
+
+       if (check_default_ctrl() == FALSE)
+               return;
+
+       if (g_dbus_proxy_method_call(default_ctrl, "SetDiscoveryFilter",
+               set_discovery_filter_setup, set_discovery_filter_reply,
+               &args, NULL) == FALSE) {
+               rl_printf("Failed to set discovery filter\n");
+               return;
+       }
+}
+
+static void cmd_set_scan_filter_uuids(const char *arg)
+{
+       char *uuid_str, *saveptr, *uuids, *uuidstmp;
+
+       g_slist_free_full(filtered_scan_uuids, g_free);
+       filtered_scan_uuids = NULL;
+
+       if (!arg || !strlen(arg))
+               return;
+
+       uuids = g_strdup(arg);
+       for (uuidstmp = uuids; ; uuidstmp = NULL) {
+               uuid_str = strtok_r(uuidstmp, " \t", &saveptr);
+               if (uuid_str == NULL)
+                       break;
+           filtered_scan_uuids = g_slist_append(filtered_scan_uuids,
+                                                       strdup(uuid_str));
+       }
+
+       g_free(uuids);
+
+       cmd_set_scan_filter_commit();
+}
+
+static void cmd_set_scan_filter_rssi(const char *arg)
+{
+       filtered_scan_pathloss = DISTANCE_VAL_INVALID;
+
+       if (!arg || !strlen(arg))
+               filtered_scan_rssi = DISTANCE_VAL_INVALID;
+       else
+               filtered_scan_rssi = atoi(arg);
+
+       cmd_set_scan_filter_commit();
+}
+
+static void cmd_set_scan_filter_pathloss(const char *arg)
+{
+       filtered_scan_rssi = DISTANCE_VAL_INVALID;
+
+       if (!arg || !strlen(arg))
+               filtered_scan_pathloss = DISTANCE_VAL_INVALID;
+       else
+               filtered_scan_pathloss = atoi(arg);
+
+       cmd_set_scan_filter_commit();
+}
+
+static void cmd_set_scan_filter_transport(const char *arg)
+{
+       g_free(filtered_scan_transport);
+
+       if (!arg || !strlen(arg))
+               filtered_scan_transport = NULL;
+       else
+               filtered_scan_transport = g_strdup(arg);
+
+       cmd_set_scan_filter_commit();
+}
+
+static void cmd_set_scan_filter_clear(const char *arg)
+{
+       /* set default values for all options */
+       filtered_scan_rssi = DISTANCE_VAL_INVALID;
+       filtered_scan_pathloss = DISTANCE_VAL_INVALID;
+       g_slist_free_full(filtered_scan_uuids, g_free);
+       filtered_scan_uuids = NULL;
+       g_free(filtered_scan_transport);
+       filtered_scan_transport = NULL;
+
+       cmd_set_scan_filter_commit();
+}
+
 static struct GDBusProxy *find_device(const char *arg)
 {
        GDBusProxy *proxy;
@@ -950,8 +1172,11 @@ static void cmd_info(const char *arg)
 #ifdef __TIZEN_PATCH__
        print_property(proxy, "Flag");
        print_property(proxy, "ManufacturerDataLen");
-       print_property(proxy, "ManufacturerData");
 #endif
+       print_property(proxy, "ManufacturerData");
+       print_property(proxy, "ServiceData");
+       print_property(proxy, "RSSI");
+       print_property(proxy, "TxPower");
 }
 
 static void pair_reply(DBusMessage *message, void *user_data)
@@ -1203,7 +1428,12 @@ static void cmd_disconn(const char *arg)
                rl_printf("Failed to disconnect\n");
                return;
        }
+       if (strlen(arg) == 0) {
+               DBusMessageIter iter;
 
+               if (g_dbus_proxy_get_property(proxy, "Address", &iter) == TRUE)
+                       dbus_message_iter_get_basic(&iter, &arg);
+       }
        rl_printf("Attempting to disconnect from %s\n", arg);
 }
 
@@ -1476,6 +1706,17 @@ static const struct {
                                                        capability_generator},
        { "default-agent",NULL,       cmd_default_agent,
                                "Set agent as the default one" },
+       { "set-scan-filter-uuids", "[uuid1 uuid2 ...]",
+                       cmd_set_scan_filter_uuids, "Set scan filter uuids" },
+       { "set-scan-filter-rssi", "[rssi]", cmd_set_scan_filter_rssi,
+                               "Set scan filter rssi, and clears pathloss" },
+       { "set-scan-filter-pathloss", "[pathloss]",
+                                               cmd_set_scan_filter_pathloss,
+                               "Set scan filter pathloss, and clears rssi" },
+       { "set-scan-filter-transport", "[transport]",
+               cmd_set_scan_filter_transport, "Set scan filter transport" },
+       { "set-scan-filter-clear", "", cmd_set_scan_filter_clear,
+                                               "Clears discovery filter." },
        { "scan",         "<on/off>", cmd_scan, "Scan for devices" },
        { "info",         "[dev]",    cmd_info, "Device information",
                                                        dev_generator },
@@ -1666,7 +1907,7 @@ static guint setup_standard_input(void)
 static gboolean signal_handler(GIOChannel *channel, GIOCondition condition,
                                                        gpointer user_data)
 {
-       static unsigned int __terminated = 0;
+       static bool terminated = false;
        struct signalfd_siginfo si;
        ssize_t result;
        int fd;
@@ -1699,13 +1940,13 @@ static gboolean signal_handler(GIOChannel *channel, GIOCondition condition,
                 * exit and fall through.
                 */
        case SIGTERM:
-               if (__terminated == 0) {
+               if (!terminated) {
                        rl_replace_line("", 0);
                        rl_crlf();
                        g_main_loop_quit(main_loop);
                }
 
-               __terminated = 1;
+               terminated = true;
                break;
        }