Implemented enable and disable Gatt watch notification 64/181364/3 submit/tizen/20180614.065332 submit/tizen/20180617.234448
authorAmit Purwar <amit.purwar@samsung.com>
Tue, 12 Jun 2018 11:56:50 +0000 (17:26 +0530)
committeramit purwar <amit.purwar@samsung.com>
Wed, 13 Jun 2018 07:00:24 +0000 (07:00 +0000)
Implemented enable and disable the watch notification on
gatt characteristic

Change-Id: I192746b8a6ec2d8012f8590dd0b9be45334f9c8e
Signed-off-by: Amit Purwar <amit.purwar@samsung.com>
bt-oal/bluez_hal/inc/bt-hal-msg.h
bt-oal/bluez_hal/src/bt-hal-gatt-client.c
bt-oal/bluez_hal/src/bt-hal-gatt.c
bt-oal/include/oal-event.h
bt-oal/include/oal-gatt.h
bt-oal/oal-gatt.c
bt-service-adaptation/services/bt-request-handler.c
bt-service-adaptation/services/bt-service-common.c
bt-service-adaptation/services/gatt/bt-service-gatt.c
bt-service-adaptation/services/include/bt-service-gatt.h

index b48ca63..decf025 100644 (file)
@@ -708,4 +708,15 @@ struct hal_ev_gatt_client_write_result {
        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_
index ec6f955..c30f3f3 100644 (file)
@@ -148,12 +148,12 @@ static int bt_inst_id = 0;
 
 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;
@@ -175,6 +175,8 @@ static hal_gattc_server_info_t *__bt_find_gatt_conn_info_from_conn_id(int  conn_
 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 */
@@ -1373,7 +1375,7 @@ static void __hal_internal_read_char_cb(GObject *source_object,
        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;
@@ -1540,7 +1542,7 @@ static void __hal_bluetooth_internal_write_cb(GObject *source_object,
        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
@@ -1744,7 +1746,7 @@ static void __hal_internal_read_desc_cb(GObject *source_object,
        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;
@@ -1924,7 +1926,7 @@ static void __hal_bluetooth_internal_desc_write_cb(GObject *source_object,
        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;
@@ -2079,25 +2081,312 @@ bt_status_t execute_write(int conn_id, int execute)
        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 */
@@ -2313,8 +2602,8 @@ const btgatt_client_interface_t btgatt_client_interface = {
        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,
index 92c46f3..ec529ee 100644 (file)
@@ -83,6 +83,7 @@ static void __bt_handle_gatt_client_read_charac(void *buf, uint16_t len);
 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)
@@ -359,6 +360,10 @@ static void __bt_hal_gatt_events(int message, void *buf, uint16_t len)
                __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;
@@ -564,6 +569,24 @@ static void __bt_handle_gatt_client_write_desc(void *buf, uint16_t len)
                                        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;
index be8c158..97fde1c 100644 (file)
@@ -434,6 +434,14 @@ typedef struct {
        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 {
index 2913529..e448edd 100644 (file)
@@ -438,4 +438,10 @@ oal_status_t gattc_write_descriptor(int conn_id, oal_gatt_srvc_id_t *srvc_id, oa
 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_ */
index 72cace4..51f1343 100644 (file)
@@ -208,6 +208,8 @@ static void cb_gattc_read_characteristic(int conn_id, int status, btgatt_read_pa
 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 = {
@@ -220,7 +222,7 @@ 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*/
@@ -1463,6 +1465,28 @@ static void cb_gattc_get_descriptor(int conn_id, int status, btgatt_srvc_id_t *s
        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];
@@ -1814,6 +1838,57 @@ oal_status_t gattc_get_descriptor(int conn_id, oal_gatt_srvc_id_t *srvc_id,
        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)
 {
index 12d6f0f..fad5f48 100644 (file)
@@ -2574,6 +2574,34 @@ int __bt_bluez_request(int function_name,
                }
                break;
        }
+       /* Local Async */
+       case BT_GATT_WATCH_CHARACTERISTIC: {
+               bluetooth_gatt_client_char_prop_info_t param;
+               int client_id;
+               gboolean is_notify;
+
+               memset(&param, 0x00, sizeof(bluetooth_gatt_client_char_prop_info_t));
+
+               sender = (char*)g_dbus_method_invocation_get_sender(context);
+
+               __bt_service_get_parameters(in_param1, &param,
+                               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(&param , 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(&param, sizeof(bluetooth_gatt_client_char_prop_info_t)));
+               }
+               break;
+       }
        case BT_GATT_WATCH_SERVICE_CHANGED_INDICATION: {
                gboolean is_enabled;
                bluetooth_device_address_t address;
index d2e9ab0..d2e9ee8 100644 (file)
@@ -1139,7 +1139,6 @@ invocation_info_t* _bt_get_request_info_data(int service_function, char *address
 }
 
 #ifdef TIZEN_GATT_CLIENT
-/*amit*/
 invocation_info_t* _bt_get_request_info_data_from_function_name(int service_function)
 {
        GSList *l;
index 54bb798..21dc216 100644 (file)
@@ -107,6 +107,15 @@ char uuid_list[NUM_UUID][BT_UUID_STRING_MAX] = {"0000b00b-0000-0000-f065-080080f
 
 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 */
@@ -244,6 +253,8 @@ static void __bt_handle_client_characteristic_write_data(event_gattc_write_data
 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
 
@@ -1018,6 +1029,29 @@ static void __bt_gatt_handle_pending_request_info(int result,
                        }
                        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;
@@ -1391,6 +1425,24 @@ static struct gatt_out_conn_info_t* __bt_find_gatt_outgoing_conn_info(char *addr
        }
        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
 
 
@@ -2008,6 +2060,17 @@ static void __bt_gatt_event_handler(int event_type, gpointer event_data)
        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:
@@ -3701,6 +3764,57 @@ static void __bt_hanlde_le_device_disconnection(event_dev_conn_status_t *event_d
                                                 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(&notif_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(&notif_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(&notif_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,
+                       &notif_info,
+                       sizeof(bt_gatt_notif_reg_info_t));
+}
 
 
 gboolean _bt_is_remote_gatt_device_connected(bluetooth_device_address_t *address)
@@ -4241,6 +4355,62 @@ int _bt_gatt_write_descriptor_value_by_type(
        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)
 {
index 3f52c88..95a88f9 100644 (file)
@@ -133,6 +133,8 @@ int _bt_gatt_write_descriptor_value_by_type(
 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,