[OTP] Add support for OACP Read
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-otp.c
index 85cf974..7d7a7f0 100644 (file)
@@ -14,6 +14,7 @@
  * limitations under the License.
  *
  */
+#include <gio/gunixfdlist.h>
 
 #include "bluetooth-api.h"
 #include "bt-internal-types.h"
 #include "bt-request-sender.h"
 #include "bt-event-handler.h"
 
+static int _bluetooth_handle_get_len(const char *str)
+{
+       int i;
+       for (i = 0; str && str[i] != '\0'; i++);
+       return i;
+}
+
 BT_EXPORT_API int bluetooth_otp_server_init(const char *directory)
 {
        int result = BLUETOOTH_ERROR_INTERNAL;
@@ -78,4 +86,328 @@ BT_EXPORT_API int bluetooth_otp_server_deinit()
 
        BT_DBG("-");
        return result;
-}
\ No newline at end of file
+}
+
+BT_EXPORT_API int bluetooth_otp_read_characteristic_value(const char *handle)
+{
+       char *path;
+       int path_len = 0;
+       bt_user_info_t *user_info;
+       int result = BLUETOOTH_ERROR_INTERNAL;
+       BT_DBG("+");
+
+       BT_CHECK_PARAMETER(handle, return);
+       BT_CHECK_ENABLED_LE(return);
+
+       user_info = _bt_get_user_data(BT_COMMON);
+       retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
+
+       BT_INIT_PARAMS();
+       BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       path = g_strdup(handle);
+       path_len = _bluetooth_handle_get_len(path);
+       g_array_append_vals(in_param1, path, path_len);
+       g_free(path);
+
+       result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_OTP_READ_VALUE,
+                       in_param1, in_param2, in_param3, in_param4,
+                       user_info->cb, user_info->user_data);
+
+       BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       BT_DBG("-");
+       return result;
+}
+
+BT_EXPORT_API int bluetooth_otp_enable_notification(const char *handle)
+{
+       char *path;
+       int path_len = 0;
+       bt_user_info_t *user_info;
+       int result = BLUETOOTH_ERROR_INTERNAL;
+       BT_DBG("+");
+
+       BT_CHECK_PARAMETER(handle, return);
+       BT_CHECK_ENABLED_LE(return);
+
+       user_info = _bt_get_user_data(BT_COMMON);
+       retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
+
+       BT_INIT_PARAMS();
+       BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       path = g_strdup(handle);
+       path_len = _bluetooth_handle_get_len(path);
+       g_array_append_vals(in_param1, path, path_len);
+       g_free(path);
+
+       result = _bt_send_request_async(
+                                       BT_BLUEZ_SERVICE,
+                                       BT_OTP_ENABLE_NOTIFICATION,
+                                       in_param1, in_param2,
+                                       in_param3, in_param4,
+                                       user_info->cb, user_info->user_data);
+
+       BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       BT_DBG("-");
+       return result;
+}
+
+BT_EXPORT_API int bluetooth_otp_write_characteristics_value(const char *handle,
+                                               unsigned char *buf, int length)
+{
+       char *path;
+       int path_len = 0;
+       bt_user_info_t *user_info;
+       int result = BLUETOOTH_ERROR_INTERNAL;
+       bluetooth_otp_charc_data_t data;
+       BT_DBG("+");
+
+       BT_CHECK_PARAMETER(handle, return);
+       BT_CHECK_PARAMETER(buf, return);
+       BT_CHECK_ENABLED_LE(return);
+
+       user_info = _bt_get_user_data(BT_COMMON);
+       retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
+
+       BT_INIT_PARAMS();
+       BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       memset(&data, 0x00, sizeof(bluetooth_otp_charc_data_t));
+
+       data.length = length;
+       if (length > 0)
+               memcpy(data.data, buf, length);
+
+       path = g_strdup(handle);
+       path_len = _bluetooth_handle_get_len(path);
+
+       /*Fill parameters*/
+       g_array_append_vals(in_param1, path, path_len);
+
+       g_array_append_vals(in_param2, &data,
+                       sizeof(bluetooth_otp_charc_data_t));
+
+       int i;
+       for (i = 0; i < length; i++)
+               BT_INFO("Value[%d] = %u", i, buf[i]);
+       result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_OTP_WRITE_VALUE,
+                       in_param1, in_param2, in_param3, in_param4,
+                       user_info->cb, user_info->user_data);
+
+       BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       g_free(path);
+       BT_DBG("-");
+       return result;
+}
+
+#define BT_OTP_CLIENT_SERVICE_NAME     "org.otp.client"
+#define BT_OTP_CLIENT_OBJECT_PATH      "/org/otp/client"
+
+static const gchar otc_connection_xml[] =
+"<node name='/'>"
+" <interface name='org.otp.otc_channel'>"
+"     <method name='NewConnection'>"
+"          <arg type='o' name='object' direction='in'/>"
+"          <arg type='h' name='fd' direction='in'/>"
+"     </method>"
+"  </interface>"
+"</node>";
+
+GDBusNodeInfo *otp_node_info = NULL;
+static GDBusConnection *g_conn;
+static guint g_owner_id = 0;
+
+static void __new_connection_method(GDBusConnection *connection,
+                                           const gchar *sender,
+                                           const gchar *object_path,
+                                           const gchar *interface_name,
+                                           const gchar *method_name,
+                                           GVariant *parameters,
+                                           GDBusMethodInvocation *invocation,
+                                           gpointer user_data)
+{
+       BT_DBG("method %s", method_name);
+       if (g_strcmp0(method_name, "NewConnection") == 0) {
+               int index;
+               GDBusMessage *msg;
+               GUnixFDList *fd_list;
+               char *dev_path;
+               char address[BT_ADDRESS_STRING_SIZE] = { 0 };
+               int fd;
+               bluetooth_otc_info_t *otc_info = NULL;
+               bt_event_info_t *event_info;
+               int result = BLUETOOTH_ERROR_NONE;
+
+               g_variant_get(parameters, "(oh)", &dev_path, &index);
+
+               msg = g_dbus_method_invocation_get_message(invocation);
+               fd_list = g_dbus_message_get_unix_fd_list(msg);
+               if (fd_list == NULL) {
+                       BT_ERR("fd_list is NULL");
+                       return;
+               }
+
+               fd = g_unix_fd_list_get(fd_list, index, NULL);
+               if (fd == -1) {
+                       BT_ERR("Invalid fd return");
+                       return;
+               }
+
+               _bt_convert_device_path_to_address(dev_path, address);
+
+               BT_INFO("OTC Connected fd: %d, address %s", fd, address);
+
+               otc_info = g_malloc0(sizeof(bluetooth_otc_info_t));
+               otc_info->fd = fd;
+               otc_info->connected = TRUE;
+               otc_info->address = g_strdup(address);
+
+               event_info = _bt_event_get_cb_data(BT_OTP_EVENT);
+
+               if (event_info) {
+                       _bt_common_event_cb(BLUETOOTH_EVENT_OTC_STATE_CHANGED,
+                                       result, otc_info, event_info->cb,
+                                       event_info->user_data);
+               }
+
+               g_dbus_method_invocation_return_value(invocation, NULL);
+       }
+}
+
+static const GDBusInterfaceVTable method_table = {
+       __new_connection_method,
+       NULL,
+       NULL,
+};
+
+static void _bt_otp_on_bus_acquired(GDBusConnection *connection,
+                               const gchar *name, gpointer user_data)
+{
+       guint object_id;
+       GError *error = NULL;
+
+       BT_DBG("+");
+
+       g_conn = connection;
+
+       object_id = g_dbus_connection_register_object(connection,
+                                               BT_OTP_CLIENT_OBJECT_PATH,
+                                               otp_node_info->interfaces[0],
+                                               &method_table,
+                                               NULL, NULL, &error);
+       if (object_id == 0) {
+               BT_ERR("Failed to register method table: %s", error->message);
+               g_error_free(error);
+               g_dbus_node_info_unref(otp_node_info);
+       }
+
+       BT_DBG("-");
+}
+
+static void _bt_otp_on_name_acquired(GDBusConnection *connection,
+                                       const gchar     *name,
+                                       gpointer user_data)
+{
+       BT_DBG("");
+}
+
+static void _bt_otp_on_name_lost(GDBusConnection *connection,
+                               const gchar     *name,
+                               gpointer user_data)
+{
+       BT_DBG("+");
+
+       if (g_conn) {
+               g_object_unref(g_conn);
+               g_conn = NULL;
+       }
+
+       g_dbus_node_info_unref(otp_node_info);
+       BT_DBG("-");
+}
+
+int _bt_otp_register_interface(void)
+{
+       BT_DBG("+");
+       GError *error = NULL;
+       guint owner_id;
+
+       otp_node_info = g_dbus_node_info_new_for_xml(otc_connection_xml,
+                                                               &error);
+       if (!otp_node_info) {
+               BT_ERR("Failed to install: %s", error->message);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
+                               BT_OTP_CLIENT_SERVICE_NAME,
+                               G_BUS_NAME_OWNER_FLAGS_NONE,
+                               _bt_otp_on_bus_acquired,
+                               _bt_otp_on_name_acquired,
+                               _bt_otp_on_name_lost,
+                               NULL, NULL);
+       g_owner_id = owner_id;
+       BT_DBG("owner_id is [%d]\n", owner_id);
+
+       BT_DBG("-");
+       return BLUETOOTH_ERROR_NONE;
+}
+
+void _bt_otp_unregister_interface(void)
+{
+       BT_DBG("+");
+
+       g_bus_unown_name(g_owner_id);
+
+       BT_DBG("-");
+}
+
+BT_EXPORT_API int bluetooth_otp_connect_otc(const bluetooth_device_address_t *device_address)
+{
+       int ret = BLUETOOTH_ERROR_INTERNAL;
+
+       BT_CHECK_PARAMETER(device_address, return);
+       BT_CHECK_ENABLED_LE(return);
+
+       BT_INIT_PARAMS();
+       BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       g_array_append_vals(in_param1, device_address,
+                               sizeof(bluetooth_device_address_t));
+
+       _bt_otp_register_interface();
+
+       ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_LE_OTC_CONNECT,
+               in_param1, in_param2, in_param3, in_param4, &out_param);
+
+       BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       return ret;
+}
+
+BT_EXPORT_API int bluetooth_otp_disconnect_otc(const bluetooth_device_address_t *device_address)
+{
+       int ret = BLUETOOTH_ERROR_INTERNAL;
+
+       BT_CHECK_PARAMETER(device_address, return);
+       BT_CHECK_ENABLED_LE(return);
+
+       BT_INIT_PARAMS();
+       BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+       /* TODO: Send fd as in_param2 */
+       g_array_append_vals(in_param1, device_address,
+                               sizeof(bluetooth_device_address_t));
+
+       ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_LE_OTC_DISCONNECT,
+               in_param1, in_param2, in_param3, in_param4, &out_param);
+
+       _bt_otp_unregister_interface();
+
+       BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       return ret;
+}