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 {
#ifdef TIZEN_FEATURE_BLUEZ_MODIFY
bool le_2m_phy_supported;
bool le_coded_phy_supported;
+ guint le_batching_available_pkts;
#endif
};
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)
{ 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" }),