X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=bt-service%2Fbt-service-otp.c;h=3e497072d5706a6e4ddb4fb6f6982cc9015cad7c;hb=123df36aa056cc20a1de3d7982c5b0e55aa89578;hp=c46edfa649aaba002a24c562d321a0fa2357752e;hpb=c5d845104b6ac010cb6d432b6751da3731d51e3e;p=platform%2Fcore%2Fconnectivity%2Fbluetooth-frwk.git diff --git a/bt-service/bt-service-otp.c b/bt-service/bt-service-otp.c index c46edfa..3e49707 100644 --- a/bt-service/bt-service-otp.c +++ b/bt-service/bt-service-otp.c @@ -38,6 +38,28 @@ #define BT_OTP_BASE_DIR_PATH "/home/owner/media/otp/" +#define GATT_CHAR_INTERFACE "org.bluez.GattCharacteristic1" + +#define GATT_DEFAULT_TIMEOUT (6 * 1000) /* Dependent on supervision timeout 6 sec */ + +/* OTP Notification Request structure */ +typedef struct { + char *handle; + char *sender; + int req_id; +} bt_otp_notification_info; + +/* OTP transport specific data read Request info structure */ +typedef struct { + char *handle; + char *sender; + int req_id; +} bt_otp_read_req_info; + +static GSList *otp_read_req_info_list = NULL; + +static GSList *otp_notification_info_list = NULL; + static GDBusProxy *otp_gproxy; static GDBusProxy *_bt_core_gdbus_init_otp_proxy(void) @@ -116,7 +138,7 @@ void server_init_cb(GObject *object, GAsyncResult *res, BLUETOOTH_EVENT_OTP_SERVER_STATE_CHANGED, param); - out_param = g_variant_new_from_data((const GVariantType *)"i", + out_param = g_variant_new_from_data((const GVariantType*)"i", result, sizeof(int), TRUE, NULL, NULL); if (req_info) { @@ -125,6 +147,7 @@ void server_init_cb(GObject *object, GAsyncResult *res, _bt_delete_request_list(req_info->req_id); } + g_variant_unref(result); } @@ -194,7 +217,7 @@ void server_deinit_cb(GObject *object, GAsyncResult *res, param); if (req_info) { - out_param = g_variant_new_from_data((const GVariantType *)"i", + out_param = g_variant_new_from_data((const GVariantType*)"i", result, sizeof(int), TRUE, NULL, NULL); g_dbus_method_invocation_return_value(req_info->context, @@ -231,3 +254,349 @@ int bt_otp_server_deinit(int request_id) BT_DBG("-"); return BLUETOOTH_ERROR_NONE; } + +int __get_handle_length(char *handle) +{ + int i = 0; + while (handle && (handle[i] != '\0')) { + i++; + } + return i; +} + +static bt_otp_read_req_info *__bt_otp_get_read_info(char *handle) +{ + GSList *l; + bt_otp_read_req_info *info = NULL; + BT_INFO("Found waiting for OTP Read from charc handle[%s]", handle); + for (l = otp_read_req_info_list; l != NULL; l = g_slist_next(l)) { + info = (bt_otp_read_req_info *)l->data; + if (info == NULL) + continue; + + if (!g_strcmp0(info->handle, handle)) { + BT_INFO("Found waiting for OTP Read from remote addr[%s]", + info->handle); + return info; + } + } + return NULL; +} + +static void __bt_otp_remove_read_info(bt_otp_read_req_info *info) +{ + BT_DBG("Removing Read Req Info [%s]", info->handle); + + otp_read_req_info_list = g_slist_remove(otp_read_req_info_list, info); + if (info->handle) + g_free(info->handle); + if (info->sender) + g_free(info->sender); + g_free(info); +} + +static void __bt_otp_read_char_cb(GObject *source_object, + GAsyncResult *res, gpointer user_data) +{ + bt_gatt_char_descriptor_property_t att_value = { 0, }; + GDBusConnection *system_gconn = NULL; + GVariant *var_data, *param = NULL; + int result = BLUETOOTH_ERROR_NONE; + bt_otp_read_req_info *info = NULL; + GByteArray *gp_byte_array = NULL; + request_info_t *req_info = NULL; + GVariantIter *iter = NULL; + GVariant *value = NULL; + char *otp_data = NULL; + GVariant *out_param1; + GError *error = NULL; + guint8 g_byte; + char *handle; + + BT_DBG("+"); + system_gconn = _bt_gdbus_get_system_gconn(); + + handle = (char *)user_data; + info = __bt_otp_get_read_info(handle); + + value = g_dbus_connection_call_finish(system_gconn, res, &error); + + if (error) { + BT_ERR("Error : %s \n", error->message); + g_free(handle); + if (info) { + req_info = _bt_get_request_info(info->req_id); + __bt_otp_remove_read_info(info); + } + result = BLUETOOTH_ERROR_INTERNAL; + goto dbus_return; + } + + gp_byte_array = g_byte_array_new(); + g_variant_get(value, "(ay)", &iter); + + while (g_variant_iter_loop(iter, "y", &g_byte)) + g_byte_array_append(gp_byte_array, &g_byte, 1); + + if (gp_byte_array->len != 0) { + att_value.val_len = (unsigned int)gp_byte_array->len; + att_value.val = (unsigned char *)gp_byte_array->data; + } + + otp_data = (char *)g_memdup(att_value.val, att_value.val_len); + + var_data = g_variant_new_from_data((const GVariantType*)"ay", + otp_data, att_value.val_len, TRUE, NULL, NULL); + + if (info) { + param = g_variant_new("(isn@ay)", result, handle, att_value.val_len, var_data); + _bt_send_event_to_dest(info->sender, BT_OTP_EVENT, + BLUETOOTH_EVENT_OTP_READ_CHAR_VAL, + param); + req_info = _bt_get_request_info(info->req_id); + __bt_otp_remove_read_info(info); + } + +dbus_return: + if (req_info == NULL) { + BT_ERR("OTP data read Request not found!!"); + goto done; + } + + if (req_info->context == NULL) + goto done; + + out_param1 = g_variant_new_from_data((const GVariantType*)"ay", + handle, __get_handle_length(handle), TRUE, NULL, NULL); + g_dbus_method_invocation_return_value(req_info->context, + g_variant_new("(iv)", result, out_param1)); + + _bt_delete_request_list(req_info->req_id); + +done: + /* Data free */ + if (error) + g_clear_error(&error); + if (gp_byte_array) + g_byte_array_free(gp_byte_array, TRUE); + if (handle) + g_free(handle); + if (value) + g_variant_unref(value); + if (iter) + g_variant_iter_free(iter); + if (otp_data) + g_free(otp_data); + BT_DBG("-"); +} + +int _bt_otp_read_characteristic_value(int request_id, char *sender, char *handle) +{ + GDBusConnection *conn; + bt_otp_read_req_info *info = NULL; + GVariantBuilder *builder = NULL; + char *charc_handle = g_strdup(handle); + guint16 offset = 0; + + BT_CHECK_PARAMETER(handle, return); + BT_CHECK_PARAMETER(sender, return); + + conn = _bt_gdbus_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_DBG("Read OTP Characteristic from server handle [%s]", handle); + + /* If OTP data read already pending on same Server, then return In progress */ + if (__bt_otp_get_read_info(handle) != NULL) { + BT_ERR("Read Req is ongoing in remote server [%s]", charc_handle); + g_free(charc_handle); + return BLUETOOTH_ERROR_IN_PROGRESS; + } + + builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); + /*offset*/ + g_variant_builder_add(builder, "{sv}", "offset", + g_variant_new("q", offset)); + + g_dbus_connection_call(conn, + BT_BLUEZ_NAME, + handle, + GATT_CHAR_INTERFACE, + "ReadValue", + g_variant_new("(a{sv})", builder), + G_VARIANT_TYPE("(ay)"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + (GAsyncReadyCallback)__bt_otp_read_char_cb, + (gpointer)charc_handle); + + /* Save Info in pending list */ + info = g_malloc0(sizeof(bt_otp_read_req_info)); + info->handle = g_strdup(handle); + BT_INFO("Found waiting for OTP Read from charc handle[%s] [%s]", info->handle, handle); + info->sender = g_strdup(sender); + info->req_id = request_id; + otp_read_req_info_list = g_slist_append(otp_read_req_info_list, info); + + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; +} + +static bt_otp_notification_info *__bt_otp_get_notification_info(char *handle) +{ + GSList *l; + bt_otp_notification_info *info = NULL; + + for (l = otp_notification_info_list; l != NULL; l = g_slist_next(l)) { + info = (bt_otp_notification_info *)l->data; + if (info == NULL) + continue; + + if (!g_strcmp0(info->handle, handle)) { + BT_INFO("Found waiting for Ind from Server addr[%s]", + info->handle); + return info; + } + } + return NULL; +} + +static void __bt_otp_remove_notification_info(bt_otp_notification_info *info) +{ + BT_DBG("Removing Notification Info [%s]", info->handle); + + otp_notification_info_list = g_slist_remove(otp_notification_info_list, info); + if (info->handle) + g_free(info->handle); + if (info->sender) + g_free(info->sender); + g_free(info); +} + +static void __bt_otp_notification_enable_request_cb(GObject *source_object, + GAsyncResult *res, gpointer user_data) +{ + GError *error = NULL; + GDBusConnection *system_gconn = NULL; + GVariant *value = NULL; + GVariant *param = NULL; + GVariant *out_param1 = NULL; + int result = BLUETOOTH_ERROR_NONE; + char *handle = NULL; + bt_otp_notification_info *info = NULL; + request_info_t *req_info = NULL; + BT_DBG("+"); + + system_gconn = _bt_gdbus_get_system_gconn(); + value = g_dbus_connection_call_finish(system_gconn, res, &error); + + if (error) { + BT_ERR("Error : %s \n", error->message); + if (g_strrstr(error->message, "Already notifying")) + result = BLUETOOTH_ERROR_NONE; + else if (g_strrstr(error->message, "In Progress")) + result = BLUETOOTH_ERROR_IN_PROGRESS; + else if (g_strrstr(error->message, "Operation is not supported")) + result = BLUETOOTH_ERROR_NOT_SUPPORT; + else if (g_strrstr(error->message, "Write not permitted") || + g_strrstr(error->message, "Operation Not Authorized")) + result = BLUETOOTH_ERROR_PERMISSION_DEINED; + else if (g_strrstr(error->message, "Not paired")) + result = BLUETOOTH_ERROR_NOT_PAIRED; + else + result = BLUETOOTH_ERROR_INTERNAL; + } else { + BT_DBG("OTP CCCD enable request successful, send event to BT App"); + } + + handle = (char *)user_data; + info = __bt_otp_get_notification_info(handle); + + if (info) + req_info = _bt_get_request_info(info->req_id); + + /* CCCD Enable request failed */ + if (result != BLUETOOTH_ERROR_NONE && info != NULL) { + BT_ERR("Activation Request failed"); + /* Remove Indication Info */ + __bt_otp_remove_notification_info(info); + } else { + /* CCCD Enable Request successful */ + if (info) { + param = g_variant_new("(is)", result, handle); + _bt_send_event_to_dest(info->sender, BT_OTP_EVENT, + BLUETOOTH_EVENT_OTP_NOTIFICATION_ENABLED, + param); + } + } + + if (req_info == NULL) { + BT_ERR("OTP Control Point CCCD Enable Request is not found!!"); + goto done; + } + + if (req_info->context == NULL) + goto done; + + out_param1 = g_variant_new_from_data((const GVariantType*)"ay", + handle, __get_handle_length(handle), TRUE, NULL, NULL); + g_dbus_method_invocation_return_value(req_info->context, + g_variant_new("(iv)", result, out_param1)); + + _bt_delete_request_list(req_info->req_id); + +done: + if (value) + g_variant_unref(value); + if (error) + g_clear_error(&error); + if (handle) + g_free(handle); + + BT_DBG("-"); + return; +} + +int _bt_otp_enable_notification(int request_id, char *sender, char *handle) +{ + bt_otp_notification_info *info = NULL; + char *charc_handle = g_strdup(handle); + GDBusConnection *conn; + + BT_CHECK_PARAMETER(handle, return); + BT_CHECK_PARAMETER(sender, return); + + conn = _bt_gdbus_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_DBG("OTP Control point CCCD Handle [%s]", handle); + + if (__bt_otp_get_notification_info(handle) != NULL) { + BT_ERR("Activation is already ongoing for same remote server"); + g_free(charc_handle); + return BLUETOOTH_ERROR_IN_PROGRESS; + } + + BT_INFO("Start Notify to Bluez"); + g_dbus_connection_call(conn, + BT_BLUEZ_NAME, + handle, + GATT_CHAR_INTERFACE, + "StartNotify", + NULL, + NULL, + G_DBUS_CALL_FLAGS_NONE, + GATT_DEFAULT_TIMEOUT, NULL, + (GAsyncReadyCallback)__bt_otp_notification_enable_request_cb, + (gpointer)charc_handle); + + info = g_malloc0(sizeof(bt_otp_notification_info)); + info->handle = g_strdup(handle); + info->sender = g_strdup(sender); + info->req_id = request_id; + otp_notification_info_list = g_slist_append(otp_notification_info_list, info); + + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; +}