From: Amit Purwar Date: Fri, 31 Aug 2018 11:30:37 +0000 (+0530) Subject: Added feature : notification of GATT char Changed Value X-Git-Tag: accepted/tizen/unified/20180910.172010~8 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fconnectivity%2Fbluetooth-frwk.git;a=commitdiff_plain;h=4da5859a5659765615d14ac0f845c9c6b3dbaab0 Added feature : notification of GATT char Changed Value Change-Id: I387bb74f169da38481ee4a03a65817f0ec0e89f9 Signed-off-by: Amit Purwar --- diff --git a/bt-api/bt-event-handler.c b/bt-api/bt-event-handler.c index ef23dad..d79bebc 100644 --- a/bt-api/bt-event-handler.c +++ b/bt-api/bt-event-handler.c @@ -3508,10 +3508,17 @@ static void __bt_gatt_client_event_filter(GDBusConnection *connection, BT_INFO("GATT Client Char value changed in remote Server [%s]", address); BT_INFO("GATT Client Char Val len: [%d]", char_prop.val_len); - /* Copy Data */ - memcpy(&char_prop.value, g_variant_get_data(data_var), char_prop.val_len); + if (char_prop.val_len > 0) { + /* Copy Data */ + memcpy(&char_prop.value, g_variant_get_data(data_var), char_prop.val_len); + } + memcpy(&char_prop.prop.uuid, g_variant_get_data(char_uuid_var), 16); + /* Copy SVC data */ + memcpy(&char_prop.svc_prop.uuid, g_variant_get_data(svc_uuid_var), 16); + char_prop.svc_prop.instance_id = svc_inst; + /* DEBUG */ for (i = 0; i < char_prop.val_len; i++) BT_INFO("Data[%d] = [0x%x]", i, char_prop.value[i]); diff --git a/bt-oal/bluez_hal/inc/bt-hal-msg.h b/bt-oal/bluez_hal/inc/bt-hal-msg.h index a8a3a9c..c8c3478 100644 --- a/bt-oal/bluez_hal/inc/bt-hal-msg.h +++ b/bt-oal/bluez_hal/inc/bt-hal-msg.h @@ -738,7 +738,7 @@ struct hal_ev_gatt_server_acquire_write_res { uint8_t bdaddr[6]; } __attribute__((packed)); -#define HAL_EV_GATT_SERVER_ACQUIRE_NOTIFY_RES 0XC10 +#define HAL_EV_GATT_SERVER_ACQUIRE_NOTIFY_RES 0XCA struct hal_ev_gatt_server_acquire_notify { int32_t mtu; int32_t trans_id; @@ -747,6 +747,17 @@ struct hal_ev_gatt_server_acquire_notify { char *path; } __attribute__((packed)); - +#define HAL_EV_GATT_CLIENT_NOTIFY_CHANGED_VALUE 0XCB +struct hal_ev_gatt_client_notify_changed_value { + int32_t conn_id; + uint8_t value[600]; + int32_t len; + uint8_t bdaddr[6]; + int32_t is_primary; + int32_t inst_id; + uint8_t svc_uuid[16]; + uint8_t char_uuid[16]; + uint8_t is_notify; +} __attribute__((packed)); #endif //_BT_HAL_MSG_H_ diff --git a/bt-oal/bluez_hal/src/bt-hal-event-receiver.c b/bt-oal/bluez_hal/src/bt-hal-event-receiver.c index 8161fdc..a634552 100644 --- a/bt-oal/bluez_hal/src/bt-hal-event-receiver.c +++ b/bt-oal/bluez_hal/src/bt-hal-event-receiver.c @@ -435,7 +435,7 @@ static void __bt_hal_adapter_property_changed_event(GVariant *msg) GVariantIter *iter = NULL; g_variant_get(value, "as", &iter); bt_local_le_features_t le_features; - gboolean le_features_present = FALSE; + gboolean le_features_present = FALSE; if (iter == NULL) continue; @@ -906,6 +906,36 @@ static gboolean __bt_hal_parse_interface(GVariant *msg) return FALSE; } +void __bt_hal_handle_gatt_char_event(GVariant *parameters, const char *signal_name) +{ + DBG("+"); + + if (signal_name == NULL) + return; + + if (strcasecmp(signal_name, "GattValueChanged") == 0) { + DBG("GattValueChanged event received"); + + int result = 0; + const char *char_handle = NULL; + GVariant *char_value_var = NULL; + int len = 0; + char *char_value = NULL; + + g_variant_get(parameters, "(i&s@ay)", &result, &char_handle, &char_value_var); + DBG("char handle: %s", char_handle); + + len = g_variant_get_size(char_value_var); + if (len > 0) + char_value = (char *)g_variant_get_data(char_value_var); + + _bt_hal_handle_gattc_value_changed_event(result, char_handle, char_value, len); + + g_variant_unref(char_value_var); + } +} + + static gboolean __bt_hal_event_manager(gpointer data) { bt_hal_event_type_t bt_event = 0x00; @@ -1011,6 +1041,9 @@ static gboolean __bt_hal_event_manager(gpointer data) } else if (g_strcmp0(param->interface_name, BT_HAL_MEDIATRANSPORT_INTERFACE) == 0) { DBG("Manager Event: Interface Name: BT_HAL_MEDIATRANSPORT_INTERFACE"); __bt_hal_handle_avrcp_transport_events(param->parameters, param->signal_name, param->object_path); + } else if (g_strcmp0(param->interface_name, BT_HAL_GATT_CHAR_INTERFACE) == 0) { + DBG("Manager Event: Interface Name: BT_HAL_GATT_CHAR_INTERFACE"); + __bt_hal_handle_gatt_char_event(param->parameters, param->signal_name); } @@ -1259,6 +1292,34 @@ static int __bt_hal_register_input_subscribe_signal(GDBusConnection *conn, int s return 0; } +static int __bt_hal_register_gatt_subscribe_signal(GDBusConnection *conn, + int subscribe) +{ + static int subs_gatt_id = -1; + + DBG("+"); + + if (subscribe) { + if (subs_gatt_id == -1) { + subs_gatt_id = g_dbus_connection_signal_subscribe(conn, + NULL, BT_HAL_GATT_CHAR_INTERFACE, + NULL, NULL, NULL, 0, + __bt_hal_manager_event_filter, + NULL, NULL); + } + } else { + if (subs_gatt_id == -1) { + g_dbus_connection_signal_unsubscribe(conn, + subs_gatt_id); + subs_gatt_id = -1; + } + } + + return BT_HAL_ERROR_NONE; +} + + + static int __bt_hal_register_service_event(GDBusConnection *g_conn, int event_type) { DBG("+"); @@ -1280,6 +1341,9 @@ static int __bt_hal_register_service_event(GDBusConnection *g_conn, int event_ty case BT_HAL_HEADSET_EVENT: __bt_hal_register_audio_subscribe_signal(g_conn, TRUE); break; + case BT_HAL_GATT_EVENT: + __bt_hal_register_gatt_subscribe_signal(g_conn, TRUE); + break; default: INFO_C("Register Event: event_type [%d]", event_type); return BT_HAL_ERROR_NOT_SUPPORT; @@ -1355,6 +1419,9 @@ static int __bt_hal_initialize_manager_receiver(void) if (__bt_hal_register_service_event(manager_conn, BT_HAL_HEADSET_EVENT) != BT_HAL_ERROR_NONE) goto fail; + if (__bt_hal_register_service_event(manager_conn, + BT_HAL_GATT_EVENT) != BT_HAL_ERROR_NONE) + goto fail; return BT_HAL_ERROR_NONE; fail: if (manager_conn) { diff --git a/bt-oal/bluez_hal/src/bt-hal-gatt-client.c b/bt-oal/bluez_hal/src/bt-hal-gatt-client.c index 0bfd12d..61c4af9 100644 --- a/bt-oal/bluez_hal/src/bt-hal-gatt-client.c +++ b/bt-oal/bluez_hal/src/bt-hal-gatt-client.c @@ -117,6 +117,7 @@ typedef struct { typedef struct { gchar *svc_path; bt_uuid_t svc_uuid; + int is_primary; GSList *gatt_list_chars; } hal_gattc_service_t; @@ -565,6 +566,28 @@ static hal_gattc_char_t* _gattc_find_char_from_uuid(hal_gattc_service_t *gattc_s return NULL; } +static hal_gattc_char_t* _gattc_find_char_from_uuid_for_notify(hal_gattc_service_t *gattc_svc, bt_uuid_t *char_uuid) +{ + DBG("+"); + + GSList *l; + hal_gattc_char_t *info = NULL; + + for (l = gattc_svc->gatt_list_chars; l != NULL; l = g_slist_next(l)) { + info = (hal_gattc_char_t*)l->data; + if (info == NULL) + continue; + + if (!memcmp(&info->chr_uuid, char_uuid, sizeof(bt_uuid_t)) && + ((info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) || + (info->permission & HAL_GATT_CHARACTERISTIC_PROPERTY_INDICATE))) { + INFO("Found GATT char uuid"); + return info; + } + } + return NULL; +} + static hal_gattc_desc_t* _gattc_find_desc_from_uuid(hal_gattc_char_t *gattc_char, bt_uuid_t *desc_uuid) { DBG("+"); @@ -587,7 +610,7 @@ static hal_gattc_desc_t* _gattc_find_desc_from_uuid(hal_gattc_char_t *gattc_char static hal_gattc_service_t* _hal_gatt_client_add_service(hal_gattc_server_info_t *conn_info, - const char *uuid_str, char *object_path) + const char *uuid_str, char *object_path, int is_primary) { DBG("+"); hal_gattc_service_t *gattc_service = NULL; @@ -595,6 +618,7 @@ static hal_gattc_service_t* _hal_gatt_client_add_service(hal_gattc_server_info_t gattc_service = g_malloc0(sizeof(hal_gattc_service_t)); gattc_service->svc_path = g_strdup(object_path); _bt_hal_convert_uuid_string_to_type(gattc_service->svc_uuid.uu, uuid_str); + gattc_service->is_primary = is_primary; DBG("service count[%d]", g_slist_length(conn_info->gatt_list_services)); @@ -629,7 +653,7 @@ static void _gattc_create_new_service(hal_gattc_server_info_t *conn_info, gboole DBG("+"); /* add the service */ - gatt_svc = _hal_gatt_client_add_service(conn_info, uuid_str, object_path); + gatt_svc = _hal_gatt_client_add_service(conn_info, uuid_str, object_path, is_primary); if (gatt_svc == NULL) { ERR("Failed to add service"); return; @@ -2406,8 +2430,7 @@ static bt_status_t _hal_register_for_notification(int client_if, /* find characteristic */ - gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, - HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY); + gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid); if (NULL == gattc_char) { DBG("Failed to get the gatt char"); return BT_STATUS_FAIL; @@ -2572,8 +2595,7 @@ static bt_status_t _hal_deregister_for_notification(int client_if, /* find characteristic */ - gattc_char = _gattc_find_char_from_uuid(gattc_service, &char_id->uuid, - HAL_GATT_CHARACTERISTIC_PROPERTY_NOTIFY); + gattc_char = _gattc_find_char_from_uuid_for_notify(gattc_service, &char_id->uuid); if (NULL == gattc_char) { DBG("Failed to get the gatt char"); return BT_STATUS_FAIL; @@ -3339,3 +3361,86 @@ static void _bt_hal_send_search_service_complete_event(int conn_id, int status) event_cb(HAL_EV_GATT_CLIENT_SEARCH_COMPLETE, (void *)&ev, sizeof(ev)); } + +static void _bt_hal_send_value_changed_event(hal_gattc_server_info_t *conn_info, + hal_gattc_service_t *svc_info, hal_gattc_char_t *char_info, + char *char_value, int len) +{ + struct hal_ev_gatt_client_notify_changed_value ev; + hal_gattc_client_info_t *gattc_client = NULL; + + if (!event_cb) { + ERR("gatt client callback not registered"); + return; + } + + gattc_client = __bt_find_gatt_client_info(&conn_info->bd_addr); + if (NULL == gattc_client) { + ERR("failed to get the gatt client info"); + return ; + } + + //send event + DBG("sending gatt client connected status event"); + memset(&ev, 0, sizeof(ev)); + + ev.conn_id = gattc_client->conn_id; + ev.inst_id = conn_info->inst_id; + ev.is_primary = svc_info->is_primary; + memcpy(ev.svc_uuid, svc_info->svc_uuid.uu, sizeof(ev.svc_uuid)); + memcpy(ev.char_uuid, char_info->chr_uuid.uu, sizeof(ev.char_uuid)); + + memcpy(ev.bdaddr, conn_info->bd_addr.address, BT_HAL_ADDRESS_LENGTH_MAX); + + if (len > 0 && (char_value != NULL)) { + memcpy(ev.value, char_value, len); + ev.len = len; + } + + event_cb(HAL_EV_GATT_CLIENT_NOTIFY_CHANGED_VALUE, (void *)&ev, sizeof(ev)); +} + +void _bt_hal_handle_gattc_value_changed_event(int result, const char *char_handle, + char *char_value, int len) +{ + char device_address[BT_HAL_ADDRESS_STRING_SIZE] = { 0 }; + hal_gattc_server_info_t *conn_info = NULL; + bt_bdaddr_t bd_addr; + GSList *l; + GSList *k; + hal_gattc_service_t *svc_info = NULL; + hal_gattc_char_t *char_info = NULL; + + DBG("+"); + + _bt_hal_convert_device_path_to_address(char_handle, device_address); + device_address[BT_HAL_ADDRESS_STRING_SIZE - 1] = '\0'; + DBG("device address:[%s]", device_address); + DBG("char handle:[%s]", char_handle); + + _bt_hal_convert_addr_string_to_type(bd_addr.address, device_address); + conn_info = __bt_find_gatt_conn_info(&bd_addr); + + //find service for notified char path + for (l = conn_info->gatt_list_services; l != NULL; l = g_slist_next(l)) { + svc_info = (hal_gattc_service_t*)l->data; + if (svc_info == NULL) + continue; + + /* find characteristic object path */ + for (k = svc_info->gatt_list_chars; k != NULL; k = g_slist_next(k)) { + char_info = (hal_gattc_char_t *)k->data; + if (char_info == NULL) + continue; + + if (g_strcmp0(char_info->chr_path, char_handle) == 0) { + DBG("Found char handle[%s]", char_info->chr_path); + + //send event + _bt_hal_send_value_changed_event(conn_info, svc_info, + char_info, char_value, len); + return; + } + } + } +} diff --git a/bt-oal/bluez_hal/src/bt-hal-gatt-client.h b/bt-oal/bluez_hal/src/bt-hal-gatt-client.h index 82e85f0..a4e58b8 100644 --- a/bt-oal/bluez_hal/src/bt-hal-gatt-client.h +++ b/bt-oal/bluez_hal/src/bt-hal-gatt-client.h @@ -39,6 +39,8 @@ void _bt_hal_register_gatt_client_handler_cb(handle_stack_msg cb); void _bt_hal_unregister_gatt_client_handler_cb(void); void _bt_hal_handle_gattc_connected_event(char* address, gboolean connected); +void _bt_hal_handle_gattc_value_changed_event(int result, const char *char_handle, + char *char_value, int len); #ifdef TIZEN_BT_HAL int _bt_hal_gatt_client_get_le_scan_type(void); diff --git a/bt-oal/bluez_hal/src/bt-hal-gatt.c b/bt-oal/bluez_hal/src/bt-hal-gatt.c index 33378b8..dbeed8c 100644 --- a/bt-oal/bluez_hal/src/bt-hal-gatt.c +++ b/bt-oal/bluez_hal/src/bt-hal-gatt.c @@ -84,6 +84,7 @@ 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 void __bt_handle_gatt_client_changed_value(void *buf, uint16_t len); /*****************************************************************************************************/ static bool interface_ready(void) @@ -399,6 +400,10 @@ static void __bt_hal_gatt_events(int message, void *buf, uint16_t len) __bt_handle_gatt_client_watch_notification(buf, len); break; } + case HAL_EV_GATT_CLIENT_NOTIFY_CHANGED_VALUE: { + __bt_handle_gatt_client_changed_value(buf, len); + break; + } case HAL_EV_GATT_SERVER_ACQUIRE_WRITE_RES:{ __bt_hal_handle_gatt_server_acquire_write_requested(buf, len); break; @@ -631,6 +636,29 @@ static void __bt_handle_gatt_client_watch_notification(void *buf, uint16_t len) ev->registered, ev->status, &gatt_srvc_id, &gatt_char_id); } +static void __bt_handle_gatt_client_changed_value(void *buf, uint16_t len) +{ + struct hal_ev_gatt_client_notify_changed_value *ev = buf; + btgatt_notify_params_t changd_value_parm; + + changd_value_parm.srvc_id.is_primary = ev->is_primary; + changd_value_parm.srvc_id.id.inst_id = ev->inst_id; + memcpy(changd_value_parm.srvc_id.id.uuid.uu, ev->svc_uuid, 16); + + changd_value_parm.char_id.inst_id = ev->inst_id; + memcpy(changd_value_parm.char_id.uuid.uu, ev->char_uuid, 16); + changd_value_parm.is_notify = ev->is_notify; + + memcpy(changd_value_parm.bda.address, ev->bdaddr, 6); + + changd_value_parm.len = ev->len; + if (ev->len > 0) + memcpy(changd_value_parm.value, ev->value, ev->len); + + if (bt_gatt_callbacks->client->notify_cb) + bt_gatt_callbacks->client->notify_cb(ev->conn_id, &changd_value_parm); +} + static bt_hal_le_adv_info_t *__bt_hal_get_adv_ind_info(char *addr) { GSList *l; diff --git a/bt-oal/bluez_hal/src/bt-hal-internal.h b/bt-oal/bluez_hal/src/bt-hal-internal.h index 3629b35..80c6fc9 100644 --- a/bt-oal/bluez_hal/src/bt-hal-internal.h +++ b/bt-oal/bluez_hal/src/bt-hal-internal.h @@ -50,6 +50,7 @@ typedef enum { BT_HAL_AVRCP_CONTROL_EVENT, BT_HAL_A2DP_SOURCE_EVENT, BT_HAL_HID_DEVICE_EVENT, + BT_HAL_GATT_EVENT, /* Will be added */ } bt_hal_event_type_t; diff --git a/bt-oal/include/oal-event.h b/bt-oal/include/oal-event.h index a484750..1639420 100644 --- a/bt-oal/include/oal-event.h +++ b/bt-oal/include/oal-event.h @@ -464,6 +464,15 @@ typedef struct { #define BLE_READ_NOTIFY_DATA_LENGTH 600 typedef struct { + int is_notify; + uint16_t data_len; + uint8_t data[BLE_READ_NOTIFY_DATA_LENGTH]; + bt_address_t address; + oal_gatt_id_t char_id; + oal_gatt_srvc_id_t srvc_id; +} event_gattc_notify_data; + +typedef struct { uint16_t value_type; uint16_t data_len; uint8_t data[BLE_READ_NOTIFY_DATA_LENGTH]; diff --git a/bt-oal/oal-gatt.c b/bt-oal/oal-gatt.c index f80599f..3731335 100644 --- a/bt-oal/oal-gatt.c +++ b/bt-oal/oal-gatt.c @@ -212,6 +212,7 @@ static void cb_gattc_write_characteristic(int conn_id, int status, btgatt_write_ 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); +static void cb_gattc_notify(int conn_id, btgatt_notify_params_t *p_data); /*TODO GATT CLient callbacks will be implemented in subsequent patches */ static const btgatt_client_callbacks_t btgatt_client_callbacks = { @@ -225,7 +226,7 @@ static const btgatt_client_callbacks_t btgatt_client_callbacks = { cb_gattc_get_descriptor, /*cb_gattc_get_descriptor*/ NULL, /*cb_gattc_get_included_service*/ cb_gattc_register_for_notification, /*cb_gattc_register_for_notification*/ - NULL, /*cb_gattc_notify*/ + cb_gattc_notify, /*cb_gattc_notify*/ cb_gattc_read_characteristic, /*cb_gattc_read_characteristic*/ cb_gattc_write_characteristic, /*cb_gattc_write_characteristic*/ cb_gattc_read_descriptor, /*cb_gattc_read_descriptor*/ @@ -1535,6 +1536,47 @@ static void cb_gattc_register_for_notification(int client_if, int registered, in send_event(event_type, event, sizeof(*event)); } +static void cb_gattc_notify(int conn_id, btgatt_notify_params_t *p_data) +{ + bdstr_t bdstr; + char uuid_str1[2*BT_UUID_STRING_MAX]; + char uuid_str2[2*BT_UUID_STRING_MAX]; + + BT_INFO("BTGATT Client Notify Callback, conn_id:%d", conn_id); + BT_INFO("Server Address:[%s], is_notify:[%d], len:[%d]", + bdt_bd2str((bt_address_t *)&(p_data->bda), &bdstr), p_data->is_notify, p_data->len); + + uuid_to_stringname((oal_uuid_t *)&(p_data->srvc_id.id.uuid), uuid_str1); + uuid_to_stringname((oal_uuid_t *)&(p_data->char_id.uuid), uuid_str2); + + BT_INFO("Service=> UUID: [%s], Inst_id: [%u], Type: [%s]", + uuid_str1, p_data->srvc_id.id.inst_id, p_data->srvc_id.is_primary ? "Primary" : "Secondary"); + BT_INFO("Charac=> UUID: [%s], Inst_id: [%u]", uuid_str2, p_data->char_id.inst_id); + + if (p_data->len > 0) { + char *data = NULL; + data = g_malloc(3*p_data->len+1); + if (!data) { + BT_ERR("memory allocation failed"); + return; + } + + convert_hex_2_str((unsigned char *)p_data->value, p_data->len, data); + BT_INFO("Notified Data: [%s]", data); + + event_gattc_notify_data *event = g_new0(event_gattc_notify_data, 1); + memcpy(event->address.addr, p_data->bda.address, BT_ADDRESS_BYTES_NUM); + event->is_notify = p_data->is_notify; + event->data_len = p_data->len; + memcpy(event->data, p_data->value, event->data_len); + memcpy(&(event->char_id), &(p_data->char_id), sizeof(oal_gatt_id_t)); + memcpy(&(event->srvc_id), &(p_data->srvc_id), sizeof(oal_gatt_srvc_id_t)); + + send_event_bda_trace(OAL_EVENT_GATTC_NOTIFY_DATA, event, sizeof(*event), (bt_address_t *)&p_data->bda); + g_free(data); + } +} + static void cb_gattc_read_characteristic(int conn_id, int status, btgatt_read_params_t *p_data) { diff --git a/bt-service-adaptation/services/gatt/bt-service-gatt.c b/bt-service-adaptation/services/gatt/bt-service-gatt.c index 4448648..8e5db8e 100644 --- a/bt-service-adaptation/services/gatt/bt-service-gatt.c +++ b/bt-service-adaptation/services/gatt/bt-service-gatt.c @@ -255,6 +255,7 @@ 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); +static void __bt_handle_client_notification_data(event_gattc_notify_data *event_data); #endif @@ -2118,6 +2119,11 @@ static void __bt_gatt_event_handler(int event_type, gpointer event_data) __bt_handle_client_notification_registered((event_gattc_regdereg_notify_t *) event_data, FALSE); break; } + case OAL_EVENT_GATTC_NOTIFY_DATA: { + BT_INFO("OAL Event: GATT Client Notification Data"); + __bt_handle_client_notification_data((event_gattc_notify_data *) event_data); + + } #endif default: break; @@ -3906,6 +3912,91 @@ static void __bt_handle_client_notification_registered( sizeof(bt_gatt_notif_reg_info_t)); } +static void __bt_handle_client_notification_data(event_gattc_notify_data *event_data) +{ + /* No status in this event from OAL */ + int result = BLUETOOTH_ERROR_NONE; + + /* Read Information data structures */ + GVariant *param = NULL; + GVariant *data = NULL; + GVariant *data_svc_uuid = NULL; + GVariant *data_char_uuid = NULL; + char *read_val = NULL; + char *svc_uuid = NULL; + char *char_uuid = NULL; + char *addr = NULL; + int i; + int uuid_len = 16; + BT_INFO("+"); + + BT_INFO("Notifcation of charc data changed"); + + if (event_data->data_len > 0) { + /* DEBUG */ + for (i = 0; i < event_data->data_len; i++) + BT_INFO("Data[%d] = [0x%x]", i, event_data->data[i]); + + /* Fill address */ + addr = g_malloc0(BT_ADDRESS_STRING_SIZE); + _bt_convert_addr_type_to_string(addr, + (unsigned char *)&(event_data->address.addr)); + + /* Read data */ + read_val = g_memdup(&event_data->data[0], event_data->data_len); + + data = g_variant_new_from_data( + G_VARIANT_TYPE_BYTESTRING, + read_val, + event_data->data_len, + TRUE, NULL, NULL); + /* SVC uuid */ + svc_uuid = g_memdup(&event_data->srvc_id.id.uuid.uuid[0], uuid_len); + + data_svc_uuid = g_variant_new_from_data( + G_VARIANT_TYPE_BYTESTRING, + svc_uuid, + uuid_len, + TRUE, NULL, NULL); + + /* Char uuid */ + char_uuid = g_memdup(&event_data->char_id.uuid.uuid[0], uuid_len); + + data_char_uuid = g_variant_new_from_data( + G_VARIANT_TYPE_BYTESTRING, + char_uuid, + uuid_len, + TRUE, NULL, NULL); + + /* Build Param */ + param = g_variant_new("(isn@ayin@ayin@ay)", result, + addr, + 16, + data_svc_uuid, + event_data->srvc_id.id.inst_id, + 16, + data_char_uuid, + event_data->char_id.inst_id, + event_data->data_len, + data); + + /* Send Event */ + _bt_send_event(BT_GATT_CLIENT_EVENT, + BLUETOOTH_EVENT_GATT_CHAR_VAL_CHANGED, + param); + } else { + BT_ERR("No Data!!"); + } + /* Free data */ + if (read_val) + g_free(read_val); + if (svc_uuid) + g_free(svc_uuid); + if (char_uuid) + g_free(char_uuid); + if (addr) + g_free(addr); +} gboolean _bt_is_remote_gatt_device_connected(bluetooth_device_address_t *address) {