Re: [RFC PATCH BlueZ 1/1] Added GDBusMethod to notify one device of characteristic change

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Bernie,

On Tue, Aug 17, 2021 at 10:30 AM Bernie Conrad <bernie@xxxxxxxxxxxxxxxxx> wrote:
>
> Implementation of the method and modification of the dbus method table.
>
> ---
>  src/gatt-database.c | 93 +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 93 insertions(+)
>
> diff --git a/src/gatt-database.c b/src/gatt-database.c
> index 99c95f2d6..7e6b70a80 100644
> --- a/src/gatt-database.c
> +++ b/src/gatt-database.c
> @@ -3615,6 +3615,93 @@ static DBusMessage *manager_unregister_app(DBusConnection *conn,
>         return dbus_message_new_method_return(msg);
>  }
>
> +static DBusMessage *notify_characteristic_changed(DBusConnection *conn,
> +                                                                                       DBusMessage *msg, void *user_data)
> +{
> +       struct btd_gatt_database *database = user_data;
> +       uint8_t *value = NULL;
> +       int value_len = 0;
> +       DBusMessageIter args;
> +       DBusMessageIter array;
> +       const char *characteristic_path;
> +       const char *client_path;
> +       const char *application_path;
> +       struct svc_match_data match_data;
> +       const char *sender = dbus_message_get_sender(msg);
> +       struct gatt_app *app;
> +       struct external_service *service;
> +       struct external_chrc *chrc;
> +       struct notify notify;
> +       struct device_state *client_state;
> +       struct btd_device *client_device;
> +
> +       if (!dbus_message_iter_init(msg, &args))
> +               return btd_error_invalid_args(msg);
> +
> +       if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH)
> +               return btd_error_invalid_args(msg);
> +       dbus_message_iter_get_basic(&args, &application_path);
> +
> +       dbus_message_iter_next(&args);
> +       if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH)
> +               return btd_error_invalid_args(msg);
> +       dbus_message_iter_get_basic(&args, &client_path);
> +
> +       dbus_message_iter_next(&args);
> +       if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH)
> +               return btd_error_invalid_args(msg);
> +       dbus_message_iter_get_basic(&args, &characteristic_path);
> +
> +       dbus_message_iter_next(&args);
> +       if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_ARRAY)
> +               return btd_error_invalid_args(msg);
> +
> +
> +       dbus_message_iter_recurse(&args, &array);
> +       dbus_message_iter_get_fixed_array(&array, &value, &value_len);
> +
> +       match_data.path = application_path;
> +       match_data.sender = sender;
> +       app = queue_find(database->apps, match_app, &match_data);
> +       if (!app)
> +               return btd_error_does_not_exist(msg);
> +
> +
> +       service = queue_find(app->services, match_service_by_chrc,
> +                                         characteristic_path);
> +       if (!service)
> +               return btd_error_does_not_exist(msg);
> +
> +
> +       chrc = queue_find(service->chrcs, match_chrc, characteristic_path);
> +       if (!chrc)
> +               return btd_error_agent_not_available(msg);
> +
> +
> +       client_device = btd_adapter_find_device_by_path(database->adapter,
> +                                                                                                client_path);
> +       if (!client_device)
> +               return btd_error_does_not_exist(msg);
> +
> +       client_state = find_device_state(database,
> +                                                               device_get_address(client_device),
> +                                                               btd_device_get_bdaddr_type(client_device));
> +       if (!client_state)
> +               return btd_error_does_not_exist(msg);
> +
> +
> +       notify.handle = gatt_db_attribute_get_handle(chrc->attrib);
> +       notify.ccc_handle = gatt_db_attribute_get_handle(chrc->ccc);
> +       notify.database = database;
> +       notify.value = value;
> +       notify.len = value_len;
> +       notify.conf = conf_cb;
> +
> +       send_notification_to_device(client_state, &notify);
> +       DBG("Notification/Indication sent to %s.", client_path);
> +       return dbus_message_new_method_return(msg);
> +}
> +
>  static const GDBusMethodTable manager_methods[] = {
>         { GDBUS_ASYNC_METHOD("RegisterApplication",
>                                         GDBUS_ARGS({ "application", "o" },
> @@ -3623,6 +3710,12 @@ static const GDBusMethodTable manager_methods[] = {
>         { GDBUS_ASYNC_METHOD("UnregisterApplication",
>                                         GDBUS_ARGS({ "application", "o" }),
>                                         NULL, manager_unregister_app) },
> +       { GDBUS_ASYNC_METHOD("NotifyCharacteristicChanged",
> +                                       GDBUS_ARGS({"application", "o" },
> +                                       { "device", "o" },
> +                                       { "characteristic_path", "o"},
> +                                       { "value", "ay"}),
> +                                       NULL, notify_characteristic_changed) },

I don't think this will gonna fly, we should actually emit for the
server object and not directly to the device so I rather have a
different property e.g. object, array{byte} DeviceValue, that said
this is a bit of a layer violation since the GATT layer should be in
controller of things like device address, etc, in fact it doesn't know
which devices are subscribed to its CCC. In zephyr the way we handled
this was to push this to the application by having it handling the CCC
attribute, that said I think that can create non-compliant
implementation of CCC so Im not sure if we should do that either,
anyway we could block the DeviceValue notification if the device set
is not in fact subscribed.

>         { }
>  };
>
> --
> 2.17.1
>


-- 
Luiz Augusto von Dentz



[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux