uint8_t char_uuid[16];
uint8_t desc_uuid[16];
} __attribute__((packed));
+
+#define HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION 0XC7
+struct hal_ev_gatt_client_watch_notification {
+ int32_t client_if;
+ int32_t registered;
+ int32_t status;
+ int32_t is_primary;
+ int32_t inst_id;
+ uint8_t svc_uuid[16];
+ uint8_t char_uuid[16];
+} __attribute__((packed));
#endif //_BT_HAL_MSG_H_
typedef struct {
int conn_id;
+ int result;
btgatt_srvc_id_t srvc_id;
btgatt_gatt_id_t char_id;
btgatt_gatt_id_t desc_id;
} hal_gatt_resp_data_t;
-
typedef struct {
int client_if;
bt_uuid_t app_uuid;
static void _bt_hal_send_search_service_result_event(int conn_id, int is_primary,
const char* uuid_str, int inst_id);
static void _bt_hal_send_search_service_complete_event(int conn_id, int status);
+static hal_gattc_server_info_t *__bt_find_gatt_conn_info(bt_bdaddr_t *serv_addr);
+static hal_gattc_client_info_t *__bt_find_gatt_client_info(bt_bdaddr_t *serv_addr);
/* To send stack event to hal-av handler */
value = g_dbus_connection_call_finish(system_gconn, res, &error);
if (error) {
- ERR("Read Characteristic dbus failed Error:", error->message);
+ ERR("Read Characteristic dbus failed Error:[%s]", error->message);
//send failed event
result = BT_STATUS_FAIL;
value = g_dbus_connection_call_finish(system_gconn, res, &error);
if (error) {
- ERR("write Characteristic dbus failed Error:", error->message);
+ ERR("write Characteristic dbus failed Error:[%s]", error->message);
result = BT_STATUS_FAIL;
//send failed event
value = g_dbus_connection_call_finish(system_gconn, res, &error);
if (error) {
- ERR("Read descriptor dbus failed Error:", error->message);
+ ERR("Read descriptor dbus failed Error:[%s]", error->message);
//send failed event
result = BT_STATUS_FAIL;
value = g_dbus_connection_call_finish(system_gconn, res, &error);
if (error) {
- ERR("write descriptor dbus failed Error:", error->message);
+ ERR("write descriptor dbus failed Error: [%s]", error->message);
//send failed event
result = BT_STATUS_FAIL;
return BT_STATUS_UNSUPPORTED;
}
+static gboolean _hal_watch_register_notifi_cb(gpointer user_data)
+{
+ struct hal_ev_gatt_client_watch_notification ev;
+ hal_gatt_resp_data_t *resp_data = user_data;
+
+ DBG("sending the watch register notification event");
+ /* send the event */
+ memset(&ev, 0, sizeof(ev));
+ ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
+ ev.registered = 1;
+ ev.status = resp_data->result;
+
+ ev.is_primary = resp_data->srvc_id.is_primary;
+ ev.inst_id = resp_data->srvc_id.id.inst_id;
+
+ memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
+ memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
+
+ if (!event_cb)
+ ERR("GATT Callback not registered");
+ else
+ event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
+
+ g_free(user_data);
+
+ return FALSE;
+}
+
+static bt_status_t _hal_register_for_notification(int client_if,
+ bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
+ btgatt_gatt_id_t *char_id)
+{
+ int result = BT_STATUS_SUCCESS;
+ GError *error = NULL;
+ GDBusConnection *g_conn;
+ hal_gattc_client_info_t *gattc_client = NULL;
+ hal_gattc_server_info_t * conn_info = NULL;
+ hal_gattc_service_t *gattc_service = NULL;
+ hal_gattc_char_t *gattc_char = NULL;
+ char* char_handle = NULL;
+ char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
+ char char_uuid_str[BT_HAL_UUID_STRING_LEN];
+ hal_gatt_resp_data_t *resp_data;
+
+ DBG("+");
+
+ gattc_client = __bt_find_gatt_client_info(bd_addr);
+ if (gattc_client == NULL) {
+ ERR("failed to get the gatt client info");
+ return BT_STATUS_FAIL;
+ }
+
+ if (gattc_client->client_if != client_if) {
+ ERR("could not find the gatt client for client id[%d]", client_if);
+ return BT_STATUS_FAIL;
+ }
+
+ /* get the connection info */
+ conn_info = __bt_find_gatt_conn_info(bd_addr);
+ if (NULL == conn_info) {
+ ERR("Failed to get the conn_info");
+ return BT_STATUS_FAIL;
+ }
+
+ if (conn_info->inst_id != gattc_client->inst_id) {
+ ERR("could not fild the conn_info");
+ return BT_STATUS_FAIL;
+ }
+
+ /* find service */
+ gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
+ if (NULL == gattc_service) {
+ DBG("Failed to get the gatt service");
+ return BT_STATUS_FAIL;
+ }
+
+ DBG("service path [%s]", gattc_service->svc_path);
+ _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
+ DBG("service uuid [%s]", svc_uuid_str);
+
+
+ /* find characteristic */
+ gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid);
+ if (NULL == gattc_char) {
+ DBG("Failed to get the gatt char");
+ return BT_STATUS_FAIL;
+ }
+
+ DBG("char path [%s]", gattc_char->chr_path);
+ _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
+ DBG("char uuid [%s]", char_uuid_str);
+
+ char_handle = gattc_char->chr_path;
+
+ g_conn = _bt_hal_get_system_gconn();
+ if (g_conn == NULL) {
+ ERR("conn NULL");
+ return BT_STATUS_FAIL;
+ }
+
+ resp_data = malloc(sizeof(hal_gatt_resp_data_t));
+ if (NULL == resp_data) {
+ ERR("failed to get the memory");
+ return BT_STATUS_FAIL;
+ }
+
+ DBG("#StartNotify");
+ g_dbus_connection_call_sync(g_conn,
+ BT_HAL_BLUEZ_NAME,
+ char_handle,
+ BT_HAL_GATT_CHAR_INTERFACE,
+ "StartNotify",
+ NULL,
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
+
+ if (error) {
+ g_dbus_error_strip_remote_error(error);
+ ERR("### Watch Failed: %s", error->message);
+ if (g_strrstr(error->message, "Already notifying"))
+ result = BT_STATUS_SUCCESS;
+ else if (g_strrstr(error->message, "In Progress"))
+ result = BT_STATUS_BUSY;
+ else if (g_strrstr(error->message, "Operation is not supported"))
+ result = BT_STATUS_UNSUPPORTED;
+ /*failed because of either Insufficient Authorization or Write Not Permitted */
+ else if (g_strrstr(error->message, "Write not permitted") ||
+ g_strrstr(error->message, "Operation Not Authorized"))
+ result = BT_STATUS_AUTH_FAILURE;
+ /* failed because of either Insufficient Authentication,
+ Insufficient Encryption Key Size, or Insufficient Encryption. */
+ else if (g_strrstr(error->message, "Not paired"))
+ result = BT_STATUS_NOT_READY;
+ else
+ result = BT_STATUS_FAIL;
+
+ g_clear_error(&error);
+ }
+
+ resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
+ resp_data->result = result;
+ memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+ memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
+
+ g_idle_add(_hal_watch_register_notifi_cb, (gpointer)resp_data);
+
+ DBG("-");
+
+ return BT_STATUS_SUCCESS;
+}
+
/**
* Register to receive notifications or indications for a given
* characteristic
*/
-bt_status_t register_for_notification(int client_if,
+bt_status_t btif_register_for_notification(int client_if,
const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
btgatt_gatt_id_t *char_id)
{
CHECK_BTGATT_INIT();
- return BT_STATUS_UNSUPPORTED;
+
+ return _hal_register_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
}
+static gboolean _hal_watch_deregister_notifi_cb(gpointer user_data)
+{
+ struct hal_ev_gatt_client_watch_notification ev;
+ hal_gatt_resp_data_t *resp_data = user_data;
+
+ DBG("sending the watch deregister notification event");
+ /* send the event */
+ memset(&ev, 0, sizeof(ev));
+ ev.client_if = resp_data->conn_id; /* conn_id is saved with client_if */
+ ev.registered = 0;
+ ev.status = resp_data->result;
+
+ ev.is_primary = resp_data->srvc_id.is_primary;
+ ev.inst_id = resp_data->srvc_id.id.inst_id;
+
+ memcpy(ev.svc_uuid, resp_data->srvc_id.id.uuid.uu, sizeof(ev.svc_uuid));
+ memcpy(ev.char_uuid, resp_data->char_id.uuid.uu, sizeof(ev.char_uuid));
+
+ if (!event_cb)
+ ERR("GATT Callback not registered");
+ else
+ event_cb(HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION, (void *)&ev, sizeof(ev));
+
+ g_free(user_data);
+
+ return FALSE;
+}
+
+static bt_status_t _hal_deregister_for_notification(int client_if,
+ bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
+ btgatt_gatt_id_t *char_id)
+{
+ int result = BT_STATUS_SUCCESS;
+ GError *error = NULL;
+ GDBusConnection *g_conn;
+ hal_gattc_client_info_t *gattc_client = NULL;
+ hal_gattc_server_info_t * conn_info = NULL;
+ hal_gattc_service_t *gattc_service = NULL;
+ hal_gattc_char_t *gattc_char = NULL;
+ char* char_handle = NULL;
+ char svc_uuid_str[BT_HAL_UUID_STRING_LEN];
+ char char_uuid_str[BT_HAL_UUID_STRING_LEN];
+ hal_gatt_resp_data_t *resp_data;
+
+ DBG("+");
+
+ gattc_client = __bt_find_gatt_client_info(bd_addr);
+ if (gattc_client == NULL) {
+ ERR("failed to get the gatt client info");
+ return BT_STATUS_FAIL;
+ }
+
+ if (gattc_client->client_if != client_if) {
+ ERR("could not find the gatt client for client id[%d]", client_if);
+ return BT_STATUS_FAIL;
+ }
+
+ /* get the connection info */
+ conn_info = __bt_find_gatt_conn_info(bd_addr);
+ if (NULL == conn_info) {
+ ERR("Failed to get the conn_info");
+ return BT_STATUS_FAIL;
+ }
+
+ if (conn_info->inst_id != gattc_client->inst_id) {
+ ERR("could not fild the conn_info");
+ return BT_STATUS_FAIL;
+ }
+
+ /* find service */
+ gattc_service = _gattc_find_service_from_uuid(conn_info, &srvc_id->id.uuid);
+ if (NULL == gattc_service) {
+ DBG("Failed to get the gatt service");
+ return BT_STATUS_FAIL;
+ }
+
+ DBG("service path [%s]", gattc_service->svc_path);
+ _bt_hal_convert_uuid_type_to_string(svc_uuid_str, gattc_service->svc_uuid.uu);
+ DBG("service uuid [%s]", svc_uuid_str);
+
+
+ /* find characteristic */
+ gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid);
+ if (NULL == gattc_char) {
+ DBG("Failed to get the gatt char");
+ return BT_STATUS_FAIL;
+ }
+
+ DBG("char path [%s]", gattc_char->chr_path);
+ _bt_hal_convert_uuid_type_to_string(char_uuid_str, gattc_char->chr_uuid.uu);
+ DBG("char uuid [%s]", char_uuid_str);
+
+ char_handle = gattc_char->chr_path;
+
+ g_conn = _bt_hal_get_system_gconn();
+ if (g_conn == NULL) {
+ ERR("conn NULL");
+ return BT_STATUS_FAIL;
+ }
+
+ resp_data = malloc(sizeof(hal_gatt_resp_data_t));
+ if (NULL == resp_data) {
+ ERR("failed to get the memory");
+ return BT_STATUS_FAIL;
+ }
+
+ DBG("#StartNotify");
+ g_dbus_connection_call_sync(g_conn,
+ BT_HAL_BLUEZ_NAME,
+ char_handle,
+ BT_HAL_GATT_CHAR_INTERFACE,
+ "StopNotify",
+ NULL,
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ BT_HAL_MAX_DBUS_TIMEOUT, NULL, &error);
+
+ if (error) {
+ ERR("### Watch Failed: %s", error->message);
+ g_clear_error(&error);
+ result = BT_STATUS_FAIL;
+ }
+
+ resp_data->conn_id = gattc_client->client_if; /* saving client_if instead of conn_id */
+ resp_data->result = result;
+ memcpy(&resp_data->srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+ memcpy(&resp_data->char_id, char_id, sizeof(btgatt_gatt_id_t));
+
+ g_idle_add(_hal_watch_deregister_notifi_cb, (gpointer)resp_data);
+
+ DBG("-");
+
+ return BT_STATUS_SUCCESS;
+}
/** Deregister a previous request for notifications/indications */
-bt_status_t deregister_for_notification(int client_if,
+bt_status_t btif_deregister_for_notification(int client_if,
const bt_bdaddr_t *bd_addr, btgatt_srvc_id_t *srvc_id,
btgatt_gatt_id_t *char_id)
{
CHECK_BTGATT_INIT();
- return BT_STATUS_UNSUPPORTED;
+ return _hal_deregister_for_notification(client_if, (bt_bdaddr_t *)bd_addr, srvc_id, char_id);
}
/** Request RSSI for a given remote device */
btif_read_descriptor,
btif_write_descriptor,
execute_write,
- register_for_notification,
- deregister_for_notification,
+ btif_register_for_notification,
+ btif_deregister_for_notification,
read_remote_rssi,
ota_fw_update,
get_device_type,
static void __bt_handle_gatt_client_read_desc(void *buf, uint16_t len);
static void __bt_handle_gatt_client_write_char(void *buf, uint16_t len);
static void __bt_handle_gatt_client_write_desc(void *buf, uint16_t len);
+static void __bt_handle_gatt_client_watch_notification(void *buf, uint16_t len);
/*****************************************************************************************************/
static bool interface_ready(void)
__bt_handle_gatt_client_write_desc(buf, len);
break;
}
+ case HAL_EV_GATT_CLIENT_WATCH_NOTIFICATION: {
+ __bt_handle_gatt_client_watch_notification(buf, len);
+ break;
+ }
default:
DBG("Event Currently not handled!!");
break;
ev->status, &desc_write_parm);
}
+static void __bt_handle_gatt_client_watch_notification(void *buf, uint16_t len)
+{
+ struct hal_ev_gatt_client_watch_notification *ev = buf;
+ btgatt_srvc_id_t gatt_srvc_id;
+ btgatt_gatt_id_t gatt_char_id;
+
+ gatt_srvc_id.is_primary = ev->is_primary;
+ gatt_srvc_id.id.inst_id = ev->inst_id;
+ memcpy(gatt_srvc_id.id.uuid.uu, ev->svc_uuid, 16);
+
+ memcpy(gatt_char_id.uuid.uu, ev->char_uuid, 16);
+ gatt_char_id.inst_id = ev->inst_id;
+
+ if (bt_gatt_callbacks->client->register_for_notification_cb)
+ bt_gatt_callbacks->client->register_for_notification_cb(ev->client_if,
+ ev->registered, ev->status, &gatt_srvc_id, &gatt_char_id);
+}
+
static bt_hal_le_adv_info_t *__bt_hal_get_adv_ind_info(char *addr)
{
GSList *l;
oal_gatt_srvc_id_t srvc_id;
} event_gattc_descriptor_result_t;
+typedef struct {
+ oal_status_t status;
+ int client_if;
+ oal_gatt_id_t char_id;
+ oal_gatt_srvc_id_t srvc_id;
+} event_gattc_regdereg_notify_t;
+
+
#define BLE_READ_NOTIFY_DATA_LENGTH 600
typedef struct {
oal_status_t gattc_disconnect(int client_id, bt_address_t *device_address, int conn_id);
oal_status_t gattc_conn_param_update(bt_address_t * address, int min, int max, int latency, int timeout);
+
+oal_status_t gattc_register_for_notification(int client_id, bt_address_t * address,
+ oal_gatt_srvc_id_t *srvc_id, oal_gatt_id_t *char_id);
+
+oal_status_t gattc_deregister_for_notification(int client_id, bt_address_t * address,
+ oal_gatt_srvc_id_t *srvc_id, oal_gatt_id_t *char_id);
#endif /* OAL_GATT_H_ */
static void cb_gattc_read_descriptor(int conn_id, int status, btgatt_read_params_t *p_data);
static void cb_gattc_write_characteristic(int conn_id, int status, btgatt_write_params_t *p_data);
static void cb_gattc_write_descriptor(int conn_id, int status, btgatt_write_params_t *p_data);
+static void cb_gattc_register_for_notification(int conn_id, int registered, int status,
+ btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id);
/*TODO GATT CLient callbacks will be implemented in subsequent patches */
static const btgatt_client_callbacks_t btgatt_client_callbacks = {
cb_gattc_get_characteristics, /*cb_gattc_get_characteristics*/
cb_gattc_get_descriptor, /*cb_gattc_get_descriptor*/
NULL, /*cb_gattc_get_included_service*/
- NULL, /*cb_gattc_register_for_notification*/
+ cb_gattc_register_for_notification, /*cb_gattc_register_for_notification*/
NULL, /*cb_gattc_notify*/
cb_gattc_read_characteristic, /*cb_gattc_read_characteristic*/
cb_gattc_write_characteristic, /*cb_gattc_write_characteristic*/
send_event(OAL_EVENT_GATTC_DESC_SERACH_RESULT, event, sizeof(*event));
}
+static void cb_gattc_register_for_notification(int client_if, int registered, int status, btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id)
+{
+ char uuid_str1[2*BT_UUID_STRING_MAX];
+ char uuid_str2[2*BT_UUID_STRING_MAX];
+ BT_INFO("BTGATT Client Register For Notification Callback, client_if:%d, status:%d, registered: %s",
+ client_if, status, registered == 1 ? "REGISTERED" : "DEREGISTERED");
+ uuid_to_stringname((oal_uuid_t *)&(srvc_id->id.uuid), uuid_str1);
+ uuid_to_stringname((oal_uuid_t *)&(char_id->uuid), uuid_str2);
+ BT_INFO("Service=> UUID: [%s], Inst_id: [%u], Type: [%s]", uuid_str1, srvc_id->id.inst_id, srvc_id->is_primary ? "Primary" : "Secondary");
+ BT_INFO("Charac=> UUID: [%s], Inst_id: [%u]", uuid_str2, char_id->inst_id);
+
+ event_gattc_regdereg_notify_t *event = g_new0(event_gattc_regdereg_notify_t, 1);
+ oal_event_t event_type = (registered == 1 ? OAL_EVENT_GATTC_NOTIFICATION_REGISTERED : OAL_EVENT_GATTC_NOTIFICATION_DEREGISTERED);
+ event->client_if = client_if;
+ event->status = convert_to_oal_status(status);
+ memcpy(&(event->srvc_id), srvc_id, sizeof(oal_gatt_srvc_id_t));
+ memcpy(&(event->char_id), char_id, sizeof(oal_gatt_id_t));
+
+ send_event(event_type, event, sizeof(*event));
+}
+
+
static void cb_gattc_read_characteristic(int conn_id, int status, btgatt_read_params_t *p_data)
{
char uuid_str1[2*BT_UUID_STRING_MAX];
return OAL_STATUS_SUCCESS;
}
+oal_status_t gattc_register_for_notification(int client_id, bt_address_t * address,
+ oal_gatt_srvc_id_t *srvc_id, oal_gatt_id_t *char_id) {
+ int ret = OAL_STATUS_SUCCESS;
+ char uuid_str1[2*BT_UUID_STRING_MAX];
+ char uuid_str2[2*BT_UUID_STRING_MAX];
+ bdstr_t bdstr;
+
+ OAL_CHECK_PARAMETER(address, return);
+ OAL_CHECK_PARAMETER(srvc_id, return);
+ OAL_CHECK_PARAMETER(char_id, return);
+ uuid_to_stringname(&(srvc_id->id.uuid), uuid_str1);
+ uuid_to_stringname(&(char_id->uuid), uuid_str2);
+ API_TRACE("Client Register Notification: [%s], Service_uuid: [%s], Char_uuid: [%s]", bdt_bd2str(address, &bdstr), uuid_str1, uuid_str2);
+ CHECK_OAL_GATT_ENABLED();
+ CHECK_CLIENT_REGISTRATION(client_id);
+
+ ret = gatt_api->client->register_for_notification(client_id, (bt_bdaddr_t *)address, (btgatt_srvc_id_t *)srvc_id, (btgatt_gatt_id_t *)char_id);
+ if (ret != BT_STATUS_SUCCESS) {
+ BT_ERR("GATT client register notification failed: %s", status2string(ret));
+ return convert_to_oal_status(ret);
+ }
+
+ return OAL_STATUS_SUCCESS;
+}
+
+oal_status_t gattc_deregister_for_notification(int client_id, bt_address_t * address,
+ oal_gatt_srvc_id_t *srvc_id, oal_gatt_id_t *char_id) {
+ int ret = OAL_STATUS_SUCCESS;
+ char uuid_str1[2*BT_UUID_STRING_MAX];
+ char uuid_str2[2*BT_UUID_STRING_MAX];
+ bdstr_t bdstr;
+
+ OAL_CHECK_PARAMETER(address, return);
+ OAL_CHECK_PARAMETER(srvc_id, return);
+ OAL_CHECK_PARAMETER(char_id, return);
+ uuid_to_stringname(&(srvc_id->id.uuid), uuid_str1);
+ uuid_to_stringname(&(char_id->uuid), uuid_str2);
+ API_TRACE("Client Deregister Notification: [%s], Service_uuid: [%s], Char_uuid: [%s]", bdt_bd2str(address, &bdstr), uuid_str1, uuid_str2);
+ CHECK_OAL_GATT_ENABLED();
+ CHECK_CLIENT_REGISTRATION(client_id);
+
+ ret = gatt_api->client->deregister_for_notification(client_id, (bt_bdaddr_t *)address, (btgatt_srvc_id_t *)srvc_id, (btgatt_gatt_id_t *)char_id);
+ if (ret != BT_STATUS_SUCCESS) {
+ BT_ERR("GATT client deregister notification failed: %s", status2string(ret));
+ return convert_to_oal_status(ret);
+ }
+
+ return OAL_STATUS_SUCCESS;
+}
+
+
oal_status_t gattc_read_characteristic(int conn_id, oal_gatt_srvc_id_t *srvc_id,
oal_gatt_id_t *char_id, oal_gatt_auth_req_t auth_req)
{
}
break;
}
+ /* Local Async */
+ case BT_GATT_WATCH_CHARACTERISTIC: {
+ bluetooth_gatt_client_char_prop_info_t param;
+ int client_id;
+ gboolean is_notify;
+
+ memset(¶m, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
+
+ sender = (char*)g_dbus_method_invocation_get_sender(context);
+
+ __bt_service_get_parameters(in_param1, ¶m,
+ sizeof(bluetooth_gatt_client_char_prop_info_t));
+ __bt_service_get_parameters(in_param2, &client_id,
+ sizeof(int));
+ __bt_service_get_parameters(in_param3, &is_notify,
+ sizeof(gboolean));
+
+ result = _bt_gatt_watch_characteristic(¶m , client_id, is_notify);
+ if (BLUETOOTH_ERROR_NONE == result) {
+ BT_INFO("GATT Client: Save Invocation data for characteristic props app[%s]", sender);
+
+ /* Save the informations to invocation */
+ _bt_save_invocation_context(context, result, sender,
+ function_name,
+ (gpointer)g_memdup(¶m, sizeof(bluetooth_gatt_client_char_prop_info_t)));
+ }
+ break;
+ }
case BT_GATT_WATCH_SERVICE_CHANGED_INDICATION: {
gboolean is_enabled;
bluetooth_device_address_t address;
}
#ifdef TIZEN_GATT_CLIENT
-/*amit*/
invocation_info_t* _bt_get_request_info_data_from_function_name(int service_function)
{
GSList *l;
static int gatt_default_client = -1;
+typedef struct {
+ gboolean is_registered;
+ bluetooth_device_address_t addr;
+ unsigned char svc_uuid[BLUETOOTH_UUID_HEX_MAX_LEN];
+ int svc_inst;
+ unsigned char char_uuid[BLUETOOTH_UUID_HEX_MAX_LEN];
+ int char_inst;
+} bt_gatt_notif_reg_info_t;
+
struct gatt_out_conn_info_t {
int client_id; /* This value unique identifies a GATT Client instance */
char *addr; /* Remote GATT Server address */
static void __bt_handle_client_descriptor_write_data(event_gattc_write_data *event_data);
static int __bt_do_unregister_gatt_instance(int instance_id);
static void __bt_hanlde_le_device_disconnection(event_dev_conn_status_t *event_data);
+static void __bt_handle_client_notification_registered(event_gattc_regdereg_notify_t *event_data,
+ gboolean is_registered);
#endif
}
break;
}
+ case BT_GATT_WATCH_CHARACTERISTIC: {
+ bt_gatt_notif_reg_info_t *param = (bt_gatt_notif_reg_info_t*)data;
+ bluetooth_gatt_client_char_prop_info_t *prop = (bluetooth_gatt_client_char_prop_info_t*)req_info->user_data;
+ BT_INFO("Request Sender [%s]", req_info->sender);
+ /* Match both address, service properties &char properties to determine same request */
+ if (!memcmp(param->addr.addr,
+ prop->device_address.addr,
+ sizeof(bluetooth_device_address_t)) &&
+ !memcmp(param->svc_uuid, prop->svc.uuid, BLUETOOTH_UUID_HEX_MAX_LEN) &&
+ param->svc_inst == prop->svc.instance_id &&
+ !memcmp(param->char_uuid, prop->characteristic.uuid, BLUETOOTH_UUID_HEX_MAX_LEN) &&
+ param->char_inst == prop->characteristic.instance_id) {
+ BT_INFO("Characteristic Watch Successful: Is registered [%d]",
+ param->is_registered);
+ out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
+ g_array_append_vals(out_param, param, sizeof(bt_gatt_notif_reg_info_t));
+ _bt_service_method_return(req_info->context, out_param, result);
+ g_free(req_info->user_data);
+ _bt_free_info_from_invocation_list(req_info);
+ g_array_free(out_param, TRUE);
+ }
+ break;
+ }
case BT_GATT_READ_CHARACTERISTIC:
case BT_GATT_WRITE_CHARACTERISTIC_VALUE_BY_TYPE: {
bluetooth_gatt_client_char_prop_info_t *param = (bluetooth_gatt_client_char_prop_info_t*)data;
}
return NULL;
}
+
+static struct gatt_server_info_t *__bt_find_remote_gatt_server_info_from_client_if(int client_if)
+{
+ GSList *l;
+ struct gatt_server_info_t *info = NULL;
+
+ for (l = gatt_server_info_list; l != NULL; l = g_slist_next(l)) {
+ info = (struct gatt_server_info_t*)l->data;
+ if (info == NULL)
+ continue;
+
+ if (info->client_id == client_if) {
+ BT_INFO("Remote GATT server found addr[%s]", info->addr);
+ return info;
+ }
+ }
+ return NULL;
+}
#endif
case OAL_EVENT_DEVICE_LE_DISCONNECTED: {
BT_INFO("OAL Event: LE device disconnected");
__bt_hanlde_le_device_disconnection((event_dev_conn_status_t *)event_data);
+ break;
+ }
+ case OAL_EVENT_GATTC_NOTIFICATION_REGISTERED: {
+ BT_INFO("OAL Event: GATT Client Notification Registered");
+ __bt_handle_client_notification_registered((event_gattc_regdereg_notify_t *) event_data, TRUE);
+ break;
+ }
+ case OAL_EVENT_GATTC_NOTIFICATION_DEREGISTERED: {
+ BT_INFO("OAL Event: GATT Client Notification Registered");
+ __bt_handle_client_notification_registered((event_gattc_regdereg_notify_t *) event_data, FALSE);
+ break;
}
#endif
default:
BT_ADDRESS_STRING_SIZE);
}
+static void __bt_handle_client_notification_registered(
+ event_gattc_regdereg_notify_t *event_data,
+ gboolean is_registered)
+{
+ int result = BLUETOOTH_ERROR_NONE;
+ struct gatt_server_info_t *conn_info = NULL;
+ bt_gatt_notif_reg_info_t notif_info;
+ BT_INFO("+");
+
+ memset(¬if_info, 0x00, sizeof(bt_gatt_notif_reg_info_t));
+
+ BT_INFO("Client Interface [%d] status [%d]",
+ event_data->client_if,
+ event_data->status);
+
+ /* Extract Address from conn_id of event data */
+ conn_info = __bt_find_remote_gatt_server_info_from_client_if(
+ event_data->client_if);
+
+ if (!conn_info) {
+ BT_INFO("Connection Info is not present, return");
+ return;
+ }
+ BT_INFO("Notification Registered for addr [%s]",
+ conn_info->addr);
+
+
+ /* Fill svc informations in buffer */
+ memcpy(¬if_info.svc_uuid,
+ event_data->srvc_id.id.uuid.uuid, BLUETOOTH_UUID_HEX_MAX_LEN);
+ notif_info.svc_inst = event_data->srvc_id.id.inst_id;
+
+ /* Fill char in buffer */
+ memcpy(¬if_info.char_uuid,
+ event_data->char_id.uuid.uuid, BLUETOOTH_UUID_HEX_MAX_LEN);
+ notif_info.char_inst = event_data->char_id.inst_id;
+
+ /* Fill remote device address */
+ _bt_convert_addr_string_to_type(notif_info.addr.addr, conn_info->addr);
+
+ notif_info.is_registered = is_registered;
+
+ if (event_data->status != OAL_STATUS_SUCCESS)
+ result = BLUETOOTH_ERROR_INTERNAL;
+
+ /* Send DBUS Return for BT_GATT_WATCH_CHARACTERISTIC */
+ __bt_gatt_handle_pending_request_info(result,
+ BT_GATT_WATCH_CHARACTERISTIC,
+ ¬if_info,
+ sizeof(bt_gatt_notif_reg_info_t));
+}
gboolean _bt_is_remote_gatt_device_connected(bluetooth_device_address_t *address)
return BLUETOOTH_ERROR_NONE;
}
+int _bt_gatt_watch_characteristic(
+ bluetooth_gatt_client_char_prop_info_t *chr,
+ int client_id,
+ gboolean is_notify)
+{
+ struct gatt_server_info_t *conn_info = NULL;
+ oal_gatt_srvc_id_t srvc_id;
+ oal_gatt_id_t char_id;
+ int ret = OAL_STATUS_SUCCESS;
+ char *addr;
+
+ BT_CHECK_PARAMETER(chr, return);
+
+ BT_INFO("Client ID [%d] Is Notify [%d]", client_id, is_notify);
+
+ addr = g_malloc0(sizeof(char) * BT_ADDRESS_STRING_SIZE);
+ _bt_convert_addr_type_to_string(addr, chr->device_address.addr);
+
+ /* Check if remote GATT Server is connected or not */
+ conn_info = __bt_find_remote_gatt_server_info(addr);
+ if (conn_info) {
+ BT_INFO("GATT Server [%s] is connected, conn Id [%d]",
+ conn_info->addr, conn_info->connection_id);
+ } else {
+ BT_ERR("GATT Server is not yet connected..");
+ g_free(addr);
+ return BLUETOOTH_ERROR_NOT_CONNECTED;
+ }
+ srvc_id.is_prmry = TRUE;
+ srvc_id.id.inst_id = chr->svc.instance_id;
+ memcpy(srvc_id.id.uuid.uuid, chr->svc.uuid, BLUETOOTH_UUID_HEX_MAX_LEN);
+
+ char_id.inst_id = chr->characteristic.instance_id;
+ memcpy(char_id.uuid.uuid, chr->characteristic.uuid, BLUETOOTH_UUID_HEX_MAX_LEN);
+
+ /* Register or unregister Notification characteristic */
+ if (is_notify)
+ ret = gattc_register_for_notification(conn_info->client_id,
+ (bt_address_t*)&(chr->device_address),
+ &srvc_id, &char_id);
+ else
+ ret = gattc_deregister_for_notification(conn_info->client_id,
+ (bt_address_t*)&(chr->device_address),
+ &srvc_id, &char_id);
+
+ BT_INFO("Result[%d]", ret);
+ if (ret != OAL_STATUS_SUCCESS) {
+ BT_ERR("ret: %d", ret);
+ g_free(addr);
+ return BLUETOOTH_ERROR_INTERNAL;
+ }
+ g_free(addr);
+ return BLUETOOTH_ERROR_NONE;
+}
+
+
int _bt_disconnect_le_device(bluetooth_device_address_t *address,
int client_id)
{
int _bt_disconnect_le_device(bluetooth_device_address_t *address,
int client_id);
+int _bt_gatt_watch_characteristic(bluetooth_gatt_client_char_prop_info_t *chr,
+ int client_id, gboolean is_notify);
int _bt_gatt_watch_service_changed_indication(const char *sender,
bluetooth_device_address_t *address,