#include <stdio.h>
|
#include <errno.h>
|
#include <glib.h>
|
#include <unistd.h>
|
#include <stdlib.h>
|
|
#include "a2dp_source/a2dp_masterctrl.h"
|
#include "a2dp_source/gatt.h"
|
#include "utility.h"
|
#include "slog.h"
|
#include "gatt_client.h"
|
|
extern struct adapter *default_ctrl;
|
extern GDBusProxy *ble_dev;
|
extern GDBusProxy *default_attr;
|
|
typedef struct {
|
RK_BLE_CLIENT_STATE_CALLBACK state_cb;
|
RK_BLE_CLIENT_RECV_CALLBACK recv_cb;
|
RK_BLE_CLIENT_STATE state;
|
} gatt_client_control_t;
|
|
static gatt_client_control_t g_gatt_client_ctl = {
|
NULL, NULL, RK_BLE_CLIENT_STATE_IDLE,
|
};
|
|
void gatt_client_register_state_callback(RK_BLE_CLIENT_STATE_CALLBACK cb)
|
{
|
g_gatt_client_ctl.state_cb = cb;
|
}
|
|
void gatt_client_register_recv_callback(RK_BLE_CLIENT_RECV_CALLBACK cb)
|
{
|
g_gatt_client_ctl.recv_cb = cb;
|
}
|
|
void gatt_client_state_send(RK_BLE_CLIENT_STATE state)
|
{
|
char addr[18], name[256];
|
|
g_gatt_client_ctl.state = state;
|
|
if(!g_gatt_client_ctl.state_cb) {
|
pr_info("%s: ble_client_state_cb are not registered\n", __func__);
|
return;
|
}
|
|
memset(addr, 0, 18);
|
memset(name, 0, 256);
|
bt_get_device_addr_by_proxy(ble_dev, addr, 18);
|
bt_get_device_name_by_proxy(ble_dev, name, 256);
|
g_gatt_client_ctl.state_cb(addr, name, state);
|
}
|
|
void gatt_client_recv_data_send(GDBusProxy *proxy, DBusMessageIter *iter)
|
{
|
DBusMessageIter array, uuid_iter;
|
const char *uuid;
|
uint8_t *value;
|
int len;
|
|
if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) {
|
pr_info("%s: Unable to get value\n", __func__);
|
return;
|
}
|
|
dbus_message_iter_recurse(iter, &array);
|
dbus_message_iter_get_fixed_array(&array, &value, &len);
|
|
if (len < 0) {
|
pr_info("%s: Unable to parse value\n", __func__);
|
return;
|
}
|
|
if (g_dbus_proxy_get_property(proxy, "UUID", &uuid_iter) == FALSE)
|
return;
|
|
dbus_message_iter_get_basic(&uuid_iter, &uuid);
|
|
if (g_gatt_client_ctl.recv_cb)
|
g_gatt_client_ctl.recv_cb(uuid, value, len);
|
}
|
|
RK_BLE_CLIENT_STATE gatt_client_get_state()
|
{
|
return g_gatt_client_ctl.state;
|
}
|
|
void gatt_client_open()
|
{
|
ble_clean();
|
}
|
|
void gatt_client_close()
|
{
|
pr_info("%s\n", __func__);
|
ble_deregister_mtu_callback();
|
g_gatt_client_ctl.state = RK_BLE_CLIENT_STATE_IDLE;
|
g_gatt_client_ctl.recv_cb = NULL;
|
g_gatt_client_ctl.state_cb = NULL;
|
}
|
|
int gatt_client_get_service_info(char *address, RK_BLE_CLIENT_SERVICE_INFO *info)
|
{
|
GDBusProxy *proxy;
|
|
if(!address || !info) {
|
pr_err("%s: Invalid parameters\n", __func__);
|
return -1;
|
}
|
|
proxy = find_device_by_address(address);
|
if (!proxy) {
|
pr_info("%s: can't find device(%s)\n", __func__, address);
|
return -1;
|
}
|
|
memset(info, 0, sizeof(RK_BLE_CLIENT_SERVICE_INFO));
|
gatt_get_list_attributes(g_dbus_proxy_get_path(proxy), info);
|
return 0;
|
}
|
|
static int gatt_client_select_attribute(char *uuid)
|
{
|
GDBusProxy *proxy;
|
|
if (!ble_dev) {
|
pr_info("%s: No ble client connected\n", __func__);
|
return -1;
|
}
|
|
proxy = gatt_select_attribute(NULL, uuid);
|
if (proxy) {
|
set_default_attribute(proxy);
|
return 0;
|
}
|
|
return -1;
|
}
|
|
int gatt_client_read(char *uuid, int offset)
|
{
|
if(!uuid) {
|
pr_err("%s: Invalid uuid\n", __func__);
|
return -1;
|
}
|
|
if(gatt_client_select_attribute(uuid) < 0) {
|
pr_err("%s: select attribute failed\n", __func__);
|
return -1;
|
}
|
|
return gatt_read_attribute(default_attr, offset);
|
}
|
|
int gatt_client_write(char *uuid, char *data, int data_len, int offset)
|
{
|
if(!uuid || !data) {
|
pr_err("%s: Invalid uuid or data\n", __func__);
|
return -1;
|
}
|
|
if(gatt_client_select_attribute(uuid) < 0) {
|
pr_err("%s: select attribute failed\n", __func__);
|
return -1;
|
}
|
|
return gatt_write_attribute(default_attr, data, data_len, offset);
|
}
|
|
bool gatt_client_is_notifying(const char *uuid)
|
{
|
if(!uuid) {
|
pr_err("%s: Invalid uuid\n", __func__);
|
return -1;
|
}
|
|
if(gatt_client_select_attribute(uuid) < 0) {
|
pr_err("%s: select attribute failed\n", __func__);
|
return -1;
|
}
|
|
return gatt_get_notifying(default_attr);
|
}
|
|
int gatt_client_notify(const char *uuid, bool enable)
|
{
|
if(!uuid) {
|
pr_err("%s: Invalid uuid\n", __func__);
|
return -1;
|
}
|
|
if(gatt_client_select_attribute(uuid) < 0) {
|
pr_err("%s: select attribute failed\n", __func__);
|
return -1;
|
}
|
|
return gatt_notify_attribute(default_attr, enable ? true : false);
|
}
|
|
int gatt_client_get_eir_data(char *address, char *eir_data, int eir_len)
|
{
|
DBusMessageIter iter;
|
DBusMessageIter array;
|
unsigned char *data;
|
int len, data_len = 0;
|
struct GDBusProxy *proxy;
|
|
if(!address || (strlen(address) < 17)) {
|
pr_err("%s: invalid address\n", __func__);
|
return -1;
|
}
|
|
if(!eir_data || eir_len <= 0) {
|
pr_err("%s: invalid eir_data buf, len = %d\n", __func__, len);
|
return -1;
|
}
|
|
proxy = find_device_by_address(address);
|
if(proxy == NULL)
|
return -1;
|
|
if (g_dbus_proxy_get_property(proxy, "EirData", &iter) == FALSE) {
|
pr_err("%s: get broadcast data failed\n", __func__);
|
return- 1;
|
}
|
|
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
|
pr_err("%s: iter type != DBUS_TYPE_ARRAY\n", __func__);
|
return -1;
|
}
|
|
dbus_message_iter_recurse(&iter, &array);
|
|
if (!dbus_type_is_fixed(dbus_message_iter_get_arg_type(&array))) {
|
pr_err("%s: dbus type isn't fixed\n", __func__);
|
return -1;
|
}
|
|
if(dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_BYTE) {
|
pr_err("%s: iter type != DBUS_TYPE_BYTE\n", __func__);
|
return -1;
|
}
|
|
dbus_message_iter_get_fixed_array(&array, &data, &data_len);
|
if (data_len <= 0) {
|
pr_err("%s: get broadcast data failed, len = %d\n", __func__, data_len);
|
return -1;
|
}
|
|
pr_err("%s: get broadcast data, data_len = %d\n", __func__, data_len);
|
|
bt_shell_hexdump((void *)data, data_len * sizeof(*data));
|
|
len = data_len > eir_len ? eir_len : data_len;
|
memset(eir_data, 0, eir_len);
|
memcpy(eir_data, data, len);
|
return 0;
|
}
|