Fix : Wrong service is disconnected 81/125381/1
authorSeungyoun Ju <sy39.ju@samsung.com>
Tue, 11 Apr 2017 09:26:15 +0000 (18:26 +0900)
committerSeungyoun Ju <sy39.ju@samsung.com>
Mon, 17 Apr 2017 07:12:36 +0000 (16:12 +0900)
[Model] COMMON
[BinType] AP
[Customer] OPEN

[Issue#] P170328-03204
[Request] PLM
[Occurrence Version] R360XXE1CQC1

[Problem] If there are external profiles which have same UUID but
 different role and both are connected, DisconnectProfile method call
 couldn't be operated properly. Because it always selects the first
 service using the UUID.
[Cause & Measure] DisconnectProfile method call always selects the first
 service using the UUID. So new method call is added to select the
 service using the object path.
 Based on the parameter, proper service could be selected and it handles
 disconnection.
[Checking Method] Make client / server RFCOMM connections using same
 UUID at the same time -> Disconnect server connection

[Team] Basic connection
[Developer] Seungyoun Ju
[Solution company] Samsung
[Change Type] Specification change

Change-Id: I66ad3c6f5d7b9d4d6c5e3a8c1dec8f4a663b53c5

doc/device-api.txt
src/device.c
src/profile.c
src/profile.h

index 69c854e..263344c 100644 (file)
@@ -68,6 +68,27 @@ Methods              void Connect()
                                         org.bluez.Error.NotSupported
 
 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
+               void DisconnectExtProfile(object profile)
+
+                       This method disconnects a specific profile of
+                       this device. The profile needs to be added by
+                       RegisterProfile method call.
+
+                       This method could be used when multiple profiles with
+                       same UUID are registered and it needs to disconnect one
+                       of them.
+
+                       There is no connection tracking for a profile, so
+                       as long as the profile is registered this will always
+                       succeed.
+
+                       Possible errors: org.bluez.Error.Failed
+                                        org.bluez.Error.InProgress
+                                        org.bluez.Error.InvalidArguments
+                                        org.bluez.Error.NotSupported
+#endif
+
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
                void Pair(uint8 conn_type)
 #else
                void Pair()
index a208fed..c808291 100644 (file)
@@ -2493,6 +2493,55 @@ static DBusMessage *disconnect_profile(DBusConnection *conn, DBusMessage *msg,
        return btd_error_failed(msg, strerror(-err));
 }
 
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
+static DBusMessage *disconnect_ext_profile(DBusConnection *conn,
+                                          DBusMessage *msg, void *user_data)
+{
+       struct btd_device *dev = user_data;
+       struct btd_profile *profile;
+       struct btd_service *service;
+       const char *sender, *path;
+       GSList *l;
+       int err;
+
+       sender = dbus_message_get_sender(msg);
+
+       DBG("sender %s", sender);
+
+       if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+                                                       DBUS_TYPE_INVALID))
+               return btd_error_invalid_args(msg);
+
+       profile = btd_profile_find_ext(sender, path);
+       if (!profile)
+               return btd_error_invalid_args(msg);
+
+       l = find_service_with_profile(dev->services, profile);
+       if (!l)
+               return btd_error_invalid_args(msg);
+
+       service = l->data;
+
+       if (dev->disconnect)
+               return btd_error_in_progress(msg);
+
+       dev->disconnect = dbus_message_ref(msg);
+
+       err = btd_service_disconnect(service);
+       if (err == 0)
+               return NULL;
+
+       if (dev->disconnect)
+               dbus_message_unref(dev->disconnect);
+       dev->disconnect = NULL;
+
+       if (err == -ENOTSUP)
+               return btd_error_not_supported(msg);
+
+       return btd_error_failed(msg, strerror(-err));
+}
+#endif
+
 static void store_services(struct btd_device *device)
 {
        struct btd_adapter *adapter = device->adapter;
@@ -3806,6 +3855,9 @@ static const GDBusMethodTable device_methods[] = {
        { GDBUS_ASYNC_METHOD("DisconnectProfile", GDBUS_ARGS({ "UUID", "s" }),
                                                NULL, disconnect_profile) },
 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
+       { GDBUS_ASYNC_METHOD("DisconnectExtProfile",
+                                       GDBUS_ARGS({ "profile", "o" }), NULL,
+                                       disconnect_ext_profile) },
        { GDBUS_ASYNC_METHOD("Pair", GDBUS_ARGS({ "conn_type", "y" }), NULL,
                        pair_device) },
 #else
index c5bd97f..3ff1ba4 100644 (file)
@@ -1023,6 +1023,22 @@ static struct ext_profile *find_ext_profile(const char *owner,
        return NULL;
 }
 
+#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
+struct btd_profile *btd_profile_find_ext(const char *owner, const char *path)
+{
+       struct ext_profile *ext;
+
+       if (!owner || !path)
+               return NULL;
+
+       ext = find_ext_profile(owner, path);
+       if (!ext)
+               return NULL;
+
+       return &ext->p;
+}
+#endif
+
 static void ext_io_destroy(gpointer p)
 {
        struct ext_io *ext_io = p;
index d6e20f3..bbdf05d 100644 (file)
@@ -75,6 +75,7 @@ bool btd_profile_remove_custom_prop(const char *uuid, const char *name);
 
 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
 gboolean ext_profile_is_registered_as_client_role(struct btd_profile *p);
+struct btd_profile *btd_profile_find_ext(const char *owner, const char *path);
 #endif
 
 void btd_profile_init(void);