Add GATT data batching 61/229261/1 accepted/tizen/unified/20200402.155610 submit/tizen/20200401.080249
authorDeokhyun Kim <dukan.kim@samsung.com>
Tue, 25 Feb 2020 02:26:54 +0000 (11:26 +0900)
committerWootak Jung <wootak.jung@samsung.com>
Tue, 31 Mar 2020 00:39:21 +0000 (09:39 +0900)
Change-Id: I68a2b1047e43bc074df64edc018ab885a1a7ac1e

lib/mgmt.h
src/adapter.c

index 98fe5b2..e414bb6 100644 (file)
@@ -1148,6 +1148,34 @@ struct mgmt_cp_set_streaming_mode {
        bdaddr_t bdaddr;
 } __packed;
 
+#define MGMT_OP_GET_LE_BATCHING_BUFFER (TIZEN_OP_CODE_BASE + 0x1f)
+
+struct mgmt_rp_get_le_batching_buffer {
+       uint8_t status;
+       uint32_t buffer;
+} __packed;
+
+#define MGMT_OP_SET_LE_BATCHING_PARAM  (TIZEN_OP_CODE_BASE + 0x20)
+struct mgmt_cp_set_le_batching_param {
+       bdaddr_t        bdaddr;
+       uint16_t        pkt_th;
+       uint16_t        timeout;
+} __packed;
+
+struct mgmt_rp_set_le_batching_param {
+       uint8_t status;
+} __packed;
+
+#define MGMT_OP_SET_LE_BATCHING_ENABLE (TIZEN_OP_CODE_BASE + 0x21)
+struct mgmt_cp_set_le_batching_enable {
+       bdaddr_t        bdaddr;
+       uint8_t enable;
+} __packed;
+
+struct mgmt_rp_set_le_batching_enable {
+       uint8_t status;
+} __packed;
+
 /* BEGIN TIZEN_Bluetooth :: name update changes */
 #define MGMT_EV_DEVICE_NAME_UPDATE             (TIZEN_EV_BASE + 0x01)
 struct mgmt_ev_device_name_update {
index 294121b..d77f37f 100644 (file)
@@ -222,6 +222,17 @@ struct le_data_length_read_request {
        struct btd_adapter *adapter;
        DBusMessage *msg;
 };
+
+struct le_batching_request {
+       struct btd_adapter *adapter;
+       DBusMessage *msg;
+};
+
+struct le_batching_set_param_request {
+       struct btd_adapter *adapter;
+       DBusMessage *msg;
+       bdaddr_t bdaddr;
+};
 #endif
 
 struct btd_adapter {
@@ -353,6 +364,7 @@ struct btd_adapter {
 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
        bool le_2m_phy_supported;
        bool le_coded_phy_supported;
+       guint le_batching_available_pkts;
 #endif
 };
 
@@ -5850,6 +5862,261 @@ static DBusMessage *le_read_host_suggested_default_data_length(
        return NULL;
 }
 
+static void get_le_batching_available_pkts_complete(
+                       uint8_t status, uint16_t length,
+                       const void *param, void *user_data)
+{
+       const struct mgmt_rp_get_le_batching_buffer *rp = param;
+       struct le_batching_request *request =
+               (struct le_batching_request*)user_data;
+       DBusMessage *reply;
+
+       if (status != MGMT_STATUS_SUCCESS) {
+               error("mgmt fail: %s (0x%02x)", mgmt_errstr(status), status);
+               reply = btd_error_failed(request->msg, mgmt_errstr(status));
+               goto done;
+       }
+
+       if (length < sizeof(*rp)) {
+               reply = btd_error_failed(request->msg,
+                       "Wrong size of get le batching buffer");
+               goto done;
+       }
+
+       DBG("LE Batching buffer: [%u]", rp->buffer);
+       request->adapter->le_batching_available_pkts = rp->buffer;
+       reply = g_dbus_create_reply(request->msg,
+                               DBUS_TYPE_UINT32, &rp->buffer,
+                               DBUS_TYPE_INVALID);
+       if (!reply)
+               reply = btd_error_failed(request->msg,
+                                       "Failed to create reply.");
+
+done:
+       if (!g_dbus_send_message(dbus_conn, reply))
+               error("D-Bus send failed");
+
+       dbus_message_unref(request->msg);
+       g_free(request);
+}
+
+static DBusMessage *adapter_get_le_batching_available_pkts(DBusConnection *conn,
+                                               DBusMessage *msg, void *data)
+{
+       struct btd_adapter *adapter = data;
+       struct le_batching_request *request;
+       DBusMessage *reply;
+       dbus_uint32_t val;
+
+       if (!(adapter->current_settings & MGMT_SETTING_POWERED))
+               return btd_error_not_ready(msg);
+
+       if (adapter->le_batching_available_pkts < 0)
+               return btd_error_not_supported(msg);
+
+       if (adapter->le_batching_available_pkts > 0) {
+               reply = dbus_message_new_method_return(msg);
+               if (!reply)
+                       return NULL;
+
+               val = adapter->le_batching_available_pkts;
+               dbus_message_append_args(reply, DBUS_TYPE_UINT32, &val,
+                                                               DBUS_TYPE_INVALID);
+               DBG("LE Batching buffer: [%u]", val);
+               return reply;
+       }
+
+       request = g_new(struct le_batching_request, 1);
+
+       request->msg = dbus_message_ref(msg);
+       request->adapter = adapter;
+
+       if (mgmt_send(adapter->mgmt, MGMT_OP_GET_LE_BATCHING_BUFFER,
+                               adapter->dev_id, 0, NULL,
+                               get_le_batching_available_pkts_complete, request, NULL) == 0) {
+               dbus_message_unref(request->msg);
+               g_free(request);
+               return btd_error_failed(msg, "Unable to get le batching buffer");
+       }
+
+       return NULL;
+}
+
+static void set_le_batching_enable_complete(
+                       uint8_t status, uint16_t length,
+                       const void *param, void *user_data)
+{
+       const struct mgmt_rp_set_le_batching_enable *rp = param;
+       struct le_batching_request *request =
+               (struct le_batching_request*)user_data;
+       DBusMessage *reply;
+
+       DBG("");
+       if (status != MGMT_STATUS_SUCCESS) {
+               error("mgmt fail: %s (0x%02x)", mgmt_errstr(status), status);
+               reply = btd_error_failed(request->msg, mgmt_errstr(status));
+               goto done;
+       }
+
+       if (length < sizeof(*rp)) {
+               reply = btd_error_failed(request->msg,
+                       "Wrong size of get le batching buffer");
+               goto done;
+       }
+
+       reply = g_dbus_create_reply(request->msg,
+                               DBUS_TYPE_INVALID);
+       if (!reply)
+               reply = btd_error_failed(request->msg,
+                                       "Failed to create reply.");
+
+done:
+       if (!g_dbus_send_message(dbus_conn, reply))
+               error("D-Bus send failed");
+
+       dbus_message_unref(request->msg);
+       g_free(request);
+}
+
+static void set_le_batching_param_complete(
+                       uint8_t status, uint16_t length,
+                       const void *param, void *user_data)
+{
+       const struct mgmt_rp_get_le_batching_buffer *rp = param;
+       struct mgmt_cp_set_le_batching_enable cp;
+       struct le_batching_set_param_request *request =
+               (struct le_batching_set_param_request*)user_data;
+       DBusMessage *reply;
+
+       if (status != MGMT_STATUS_SUCCESS) {
+               error("mgmt fail: %s (0x%02x)", mgmt_errstr(status), status);
+               reply = btd_error_failed(request->msg, mgmt_errstr(status));
+               goto done;
+       }
+
+       if (length < sizeof(*rp)) {
+               reply = btd_error_failed(request->msg,
+                       "Wrong size of get le batching buffer");
+               goto done;
+       }
+
+       memset(&cp, 0, sizeof(struct mgmt_cp_set_le_batching_enable));
+       cp.bdaddr = request->bdaddr;
+       cp.enable = 1;
+       if (mgmt_send(request->adapter->mgmt, MGMT_OP_SET_LE_BATCHING_ENABLE,
+                       request->adapter->dev_id, sizeof(cp), &cp,
+                       set_le_batching_enable_complete, request, NULL) == 0) {
+               reply = btd_error_failed(request->msg, "Unable to set le batching enable");
+               goto done;
+       }
+
+       return;
+done:
+       if (!g_dbus_send_message(dbus_conn, reply))
+               error("D-Bus send failed");
+
+       dbus_message_unref(request->msg);
+       g_free(request);
+}
+
+static DBusMessage *adapter_enable_le_batching(DBusConnection *conn,
+                                               DBusMessage *msg, void *data)
+{
+       struct btd_adapter *adapter = data;
+       struct mgmt_cp_set_le_batching_param cp;
+       struct le_batching_set_param_request *request;
+       bdaddr_t bt_addr = { { 0, } };
+       const gchar *address = NULL;
+       dbus_int32_t packet_threshold;
+       dbus_int32_t timeout;
+
+       if (!(adapter->current_settings & MGMT_SETTING_POWERED))
+               return btd_error_not_ready(msg);
+
+       if (!dbus_message_get_args(msg, NULL,
+                               DBUS_TYPE_STRING, &address,
+                               DBUS_TYPE_INT32, &packet_threshold,
+                               DBUS_TYPE_INT32, &timeout,
+                               DBUS_TYPE_INVALID))
+               return btd_error_invalid_args(msg);
+
+       if (packet_threshold < 0 || packet_threshold > 0x7fff ||
+               timeout < 0 || timeout > 0x7fff)
+               return btd_error_invalid_args(msg);
+
+       DBG("Set LE batching param: [%s %d %d]", address,
+                       packet_threshold, timeout);
+
+       memset(&bt_addr, 0, sizeof(bdaddr_t));
+       str2ba(address, &bt_addr);
+       memset(&cp, 0, sizeof(struct mgmt_cp_set_le_batching_param));
+
+       if (bachk(address) < 0)
+               return btd_error_invalid_args(msg);
+
+       cp.bdaddr = bt_addr;
+       cp.pkt_th = packet_threshold;
+       /* 1sec = 100 */
+       cp.timeout = timeout * 100;
+
+       request = g_new(struct le_batching_set_param_request, 1);
+       request->msg = dbus_message_ref(msg);
+       request->adapter = adapter;
+       request->bdaddr = bt_addr;
+       if (mgmt_send(adapter->mgmt, MGMT_OP_SET_LE_BATCHING_PARAM,
+                       adapter->dev_id, sizeof(cp), &cp,
+                       set_le_batching_param_complete, request, NULL) == 0) {
+               dbus_message_unref(request->msg);
+               g_free(request);
+               return btd_error_failed(msg, "Unable to set le batching param");
+       }
+
+       return NULL;
+}
+
+static DBusMessage *adapter_disable_le_batching(DBusConnection *conn,
+                                               DBusMessage *msg, void *data)
+{
+       struct btd_adapter *adapter = data;
+       struct le_batching_request *request;
+       struct mgmt_cp_set_le_batching_enable cp;
+       bdaddr_t bt_addr = { { 0, } };
+       const gchar *address = NULL;
+
+       if (!(adapter->current_settings & MGMT_SETTING_POWERED))
+               return btd_error_not_ready(msg);
+
+       if (!dbus_message_get_args(msg, NULL,
+                               DBUS_TYPE_STRING, &address,
+                               DBUS_TYPE_INVALID))
+               return btd_error_invalid_args(msg);
+
+       DBG("Disable LE Batching: [%s]", address);
+
+       memset(&bt_addr, 0, sizeof(bdaddr_t));
+       str2ba(address, &bt_addr);
+       memset(&cp, 0, sizeof(struct mgmt_cp_set_le_batching_enable));
+
+       if (bachk(address) < 0)
+               return btd_error_invalid_args(msg);
+
+       cp.bdaddr = bt_addr;
+       cp.enable = 0;
+
+       request = g_new(struct le_batching_request, 1);
+       request->msg = dbus_message_ref(msg);
+       request->adapter = adapter;
+       if (mgmt_send(adapter->mgmt, MGMT_OP_SET_LE_BATCHING_ENABLE,
+                       adapter->dev_id, sizeof(cp), &cp,
+                       set_le_batching_enable_complete, request, NULL) == 0) {
+               dbus_message_unref(request->msg);
+               g_free(request);
+               return btd_error_failed(msg, "Unable to set le batching enable");
+       }
+
+       return NULL;
+}
+
 void le_set_data_length_return_param_complete(
                        uint8_t status, uint16_t length,
                        const void *param, void *user_data)
@@ -7686,6 +7953,20 @@ static const GDBusMethodTable adapter_methods[] = {
        { GDBUS_ASYNC_METHOD("LEReadHostSuggestedDataLength", NULL,
                        GDBUS_ARGS({"def_tx_octets", "q" }, { "def_tx_time", "q" }),
                        le_read_host_suggested_default_data_length)},
+       { GDBUS_ASYNC_METHOD("GetLeBatchingAvailablePkts",
+                       NULL,
+                       GDBUS_ARGS({ "AvailablePkts", "u" }),
+                       adapter_get_le_batching_available_pkts) },
+       { GDBUS_ASYNC_METHOD("EnableLeBatching",
+                       GDBUS_ARGS({ "bt_address", "s" },
+                               { "packet_threshold", "i" },
+                               { "timeout", "i"}),
+                       NULL,
+                       adapter_enable_le_batching) },
+       { GDBUS_ASYNC_METHOD("DisableLeBatching",
+                       GDBUS_ARGS({ "bt_address", "s" }),
+                       NULL,
+                       adapter_disable_le_batching) },
 #endif
        { GDBUS_METHOD("GetDiscoveryFilters", NULL,
                        GDBUS_ARGS({ "filters", "as" }),