Code synchronization with latest tizen 4.0 codes
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-hid-device.c
index d6b307f..db0f6bb 100755 (executable)
 #define BT_HID_HSHK_ERR_UNKNOWN        0x0E
 #define BT_HID_HSHK_ERR_FATAL  0x0F
 
-typedef struct {
-       guint object_id;
-       gchar *path;
-       int id;
-       char *uuid;
-       GSList *device_list;
-} hid_info_t;
+#define BT_HID_SERVICE_NAME "org.bluez.hid_agent"
+#define BT_HID_AGENT_OBJECT_PATH "/org/bluez/hid_agent"
+#define BT_HID_SERVICE_INTERFACE "org.tizen.HidApp"
 
 typedef struct {
        int ctrl_fd;
@@ -81,7 +77,7 @@ struct reports {
        guint8 rep_data[20];
 } __attribute__((__packed__));
 
-static hid_info_t *hid_info = NULL;
+static GSList *device_list;
 
 /* Variable for privilege, only for write API,
   before we should reduce time to bt-service dbus calling
@@ -156,11 +152,36 @@ int _bt_hid_device_get_fd(const char *address, int *ctrl, int *intr)
        return ret;
 }
 
+static GVariant* __bt_hid_agent_dbus_send(const char *path,
+                               const char *interface,  const char *method,
+                               GError **err, GVariant *parameters)
+{
+       GVariant *reply = NULL;
+       GDBusProxy *proxy = NULL;
+       GDBusConnection *conn = NULL;
+
+       conn = _bt_gdbus_get_system_gconn();
+       retv_if(conn == NULL, NULL);
+
+       proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
+               NULL, BT_HID_SERVICE_NAME, path, interface, NULL, err);
+       if (proxy == NULL) {
+               BT_ERR("Unable to allocate new proxy");
+               return NULL;
+       }
+
+       reply = g_dbus_proxy_call_sync(proxy, method, parameters,
+                               G_DBUS_CALL_FLAGS_NONE, -1, NULL, err);
+
+       g_object_unref(proxy);
+       return reply;
+}
+
 static hid_connected_device_info_t *__find_hid_info_with_address(const char *remote_addr)
 {
        GSList *l;
 
-       for (l = hid_info->device_list; l != NULL; l = l->next) {
+       for (l = device_list; l != NULL; l = l->next) {
                hid_connected_device_info_t *info = l->data;
                if (g_strcmp0((const char *)info->address, (const char *)remote_addr) == 0)
                        return info;
@@ -245,7 +266,7 @@ static gboolean __hid_disconnect(hid_connected_device_info_t *info)
        bt_event_info_t *event_info;
 
        BT_INFO_C("Disconnected [HID Device]");
-       hid_info->device_list = g_slist_remove(hid_info->device_list, info);
+       device_list = g_slist_remove(device_list, info);
        if (info->ctrl_data_id > 0) {
                g_source_remove(info->ctrl_data_id);
                info->ctrl_data_id = 0;
@@ -290,29 +311,6 @@ static gboolean __hid_disconnect(hid_connected_device_info_t *info)
        return FALSE;
 }
 
-void __free_hid_info(hid_info_t *info)
-{
-       BT_DBG("");
-
-       _bt_unregister_gdbus(info->object_id);
-
-       while (info->device_list) {
-               hid_connected_device_info_t *dev_info = NULL;
-               dev_info = (hid_connected_device_info_t *)info->device_list->data;
-
-               if (dev_info->disconnect_idle_id > 0) {
-                       BT_INFO("Disconnect idle still not process remove source");
-                       g_source_remove(dev_info->disconnect_idle_id);
-                       dev_info->disconnect_idle_id = 0;
-               }
-               __hid_disconnect(dev_info);
-       }
-
-       g_free(info->path);
-       g_free(info->uuid);
-       g_free(info);
-}
-
 static gboolean __is_error_by_disconnect(GError *err)
 {
        return !g_strcmp0(err->message, "Connection reset by peer") ||
@@ -321,9 +319,9 @@ static gboolean __is_error_by_disconnect(GError *err)
 }
 
 static gboolean __received_cb(GIOChannel *chan, GIOCondition cond,
-                                                               gpointer user_data)
+                                                               gpointer data)
 {
-       hid_connected_device_info_t *info = user_data;
+       hid_connected_device_info_t *info = data;
        GIOStatus status = G_IO_STATUS_NORMAL;
        char buffer[BT_RFCOMM_BUFFER_LEN];
        gsize len = 0;
@@ -454,14 +452,36 @@ static gboolean __received_cb(GIOChannel *chan, GIOCondition cond,
                        break;
                }
 
+               case BT_HID_TRANS_GET_IDLE:{
+                       BT_INFO("Get_IDLE");
+                       data.type = HTYPE_TRANS_GET_IDLE;
+                       data.param = PTYPE_DATA_RTYPE_INPUT;
+                       data.buffer_size = len;
+                       data.buffer = (char *) malloc(sizeof(char) * len);
+                       if (data.buffer)
+                               memcpy(data.buffer, buffer, len);
+                       break;
+               }
+
+               case BT_HID_TRANS_SET_IDLE:{
+                       BT_INFO("Set_IDLE");
+                       data.type = HTYPE_TRANS_SET_IDLE;
+                       data.param = PTYPE_DATA_RTYPE_INPUT;
+                       data.buffer_size = len;
+                       data.buffer = (char *) malloc(sizeof(char) * len);
+                       if (data.buffer)
+                               memcpy(data.buffer, buffer, len);
+                       break;
+               }
+
                default: {
                        BT_INFO("unsupported HIDP control message");
                        BT_ERR("Send Handshake Message");
-                       guint8 type1 = BT_HID_TRANS_HANDSHAKE |
+                       guint8 type = BT_HID_TRANS_HANDSHAKE |
                                BT_HID_HSHK_ERR_UNSUPPORTED_REQUEST;
                        data.type = HTYPE_TRANS_UNKNOWN;
                        int fd = g_io_channel_unix_get_fd(chan);
-                       int bytes = write(fd,  &type1, sizeof(type1));
+                       int bytes = write(fd,  &type, sizeof(type));
                        BT_INFO("Bytes Written %d", bytes);
                        break;
                }
@@ -497,23 +517,15 @@ static gboolean __received_cb(GIOChannel *chan, GIOCondition cond,
 
 int new_hid_connection(const char *path, int fd, bluetooth_device_address_t *addr)
 {
-       hid_info_t *info = NULL;
        hid_connected_device_info_t *dev_info = NULL;
        char address[18];
-       info = hid_info;
 
-       if (info == NULL)
-               return -1;
        _bt_convert_addr_type_to_string((char *)address, addr->addr);
        BT_INFO("Address [%s]", address);
        dev_info = __find_hid_info_with_address(address);
        if (dev_info == NULL) {
                dev_info = (hid_connected_device_info_t *)
                        g_malloc0(sizeof(hid_connected_device_info_t));
-               if (dev_info == NULL) {
-                       BT_ERR("Fail to allocation memory");
-                       return -1;
-               }
 
                dev_info->intr_fd = -1;
                dev_info->ctrl_fd = -1;
@@ -526,7 +538,7 @@ int new_hid_connection(const char *path, int fd, bluetooth_device_address_t *add
                dev_info->intr_data_id = g_io_add_watch(dev_info->intr_data_io,
                                G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
                                __received_cb, dev_info);
-               hid_info->device_list = g_slist_append(hid_info->device_list, dev_info);
+               device_list = g_slist_append(device_list, dev_info);
        } else {
                dev_info->ctrl_fd = fd;
                dev_info->ctrl_data_io = g_io_channel_unix_new(dev_info->ctrl_fd);
@@ -543,35 +555,26 @@ int new_hid_connection(const char *path, int fd, bluetooth_device_address_t *add
 
        return 0;
 }
-static hid_info_t *__register_method()
-{
-       int object_id;
-       hid_info_t *info = NULL;
-       char *path = NULL;
-       path = g_strdup_printf("/org/socket/server/%d", getpid());
 
-       object_id = _bt_register_new_conn(path, new_hid_connection);
-       if (object_id < 0)
-               return NULL;
+static void __free_hid_info(void *data)
+{
+       BT_DBG("");
 
-       info = g_new(hid_info_t, 1);
-       info->object_id = (guint)object_id;
-       info->path = path;
-       info->id = 0;
-       info->device_list = NULL;
+       hid_connected_device_info_t *dev_info = (hid_connected_device_info_t *)data;
 
-       return info;
+       if (dev_info->disconnect_idle_id > 0) {
+               BT_INFO("Disconnect idle still not process remove source");
+               g_source_remove(dev_info->disconnect_idle_id);
+               dev_info->disconnect_idle_id = 0;
+       }
+       __hid_disconnect(dev_info);
 }
 
 void _bluetooth_hid_free_hid_info(void)
 {
-       if (hid_info == NULL) {
-               BT_DBG("hid_info is already NULL");
-               return;
-       }
+       g_slist_free_full(device_list, __free_hid_info);
 
-       __free_hid_info(hid_info);
-       hid_info = NULL;
+       device_list = NULL;
 }
 
 BT_EXPORT_API int bluetooth_hid_device_init(hid_cb_func_ptr callback_ptr, void *user_data)
@@ -611,8 +614,10 @@ BT_EXPORT_API int bluetooth_hid_device_deinit(void)
 
 BT_EXPORT_API int bluetooth_hid_device_activate(void)
 {
-       bt_register_profile_info_t profile_info;
-       int result = BLUETOOTH_ERROR_NONE;
+       GVariant *reply;
+       GError *err = NULL;
+
+       BT_CHECK_ENABLED(return);
 
        if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_ACTIVATE)
                 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
@@ -620,40 +625,61 @@ BT_EXPORT_API int bluetooth_hid_device_activate(void)
                return BLUETOOTH_ERROR_PERMISSION_DEINED;
        }
 
-       if (hid_info != NULL)
-               return BLUETOOTH_ERROR_IN_PROGRESS;
+       reply = __bt_hid_agent_dbus_send(BT_HID_AGENT_OBJECT_PATH,
+                       BT_HID_SERVICE_INTERFACE,
+                       "RegisterApplication", &err, NULL);
 
-       hid_info = __register_method();
-       if (hid_info == NULL)
-               return BLUETOOTH_ERROR_INTERNAL;
-
-       hid_info->uuid = g_strdup(HID_DEVICE_UUID);
-
-       profile_info.authentication = TRUE;
-       profile_info.authorization = TRUE;
-       profile_info.obj_path = hid_info->path;
-       profile_info.role = g_strdup("Hid");
-       profile_info.service = hid_info->uuid;
-       profile_info.uuid = hid_info->uuid;
+       if (!reply) {
+               int ret = BLUETOOTH_ERROR_INTERNAL;
+               BT_ERR("Error returned in method call");
+               if (err) {
+                       BT_ERR("Error = %s", err->message);
+                       if (strcmp(err->message, BT_ERROR_ALREADY_EXIST) == 0)
+                               ret = BLUETOOTH_ERROR_IN_PROGRESS;
+                       else
+                               ret = BLUETOOTH_ERROR_INTERNAL;
+                       g_clear_error(&err);
+               }
+               return ret;
+       }
 
-       BT_INFO("uuid %s", profile_info.uuid);
-       result = _bt_register_profile(&profile_info, FALSE);
+       g_variant_unref(reply);
 
-       return result;
+       return BLUETOOTH_ERROR_NONE;
 }
 
 BT_EXPORT_API int bluetooth_hid_device_deactivate(void)
 {
+       GVariant *reply;
+       GError *err = NULL;
+
+       BT_CHECK_ENABLED(return);
+
        if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_DEACTIVATE)
                 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
                BT_ERR("Don't have a privilege to use this API");
                return BLUETOOTH_ERROR_PERMISSION_DEINED;
        }
 
-       if (hid_info == NULL)
-               return BLUETOOTH_ERROR_NOT_IN_OPERATION;
+       reply = __bt_hid_agent_dbus_send(BT_HID_AGENT_OBJECT_PATH,
+                       BT_HID_SERVICE_INTERFACE,
+                       "UnregisterApplication", &err, NULL);
 
-       _bt_unregister_profile(hid_info->path);
+       if (!reply) {
+               int ret = BLUETOOTH_ERROR_INTERNAL;
+               BT_ERR("Error returned in method call");
+               if (err) {
+                       BT_ERR("Error = %s", err->message);
+                       if (strcmp(err->message, BT_ERROR_NOT_AVAILABLE) == 0)
+                               ret = BLUETOOTH_ERROR_NOT_IN_OPERATION;
+                       else
+                               ret = BLUETOOTH_ERROR_INTERNAL;
+                       g_clear_error(&err);
+               }
+               return ret;
+       }
+
+       g_variant_unref(reply);
 
        _bluetooth_hid_free_hid_info();
 
@@ -668,6 +694,8 @@ BT_EXPORT_API int bluetooth_hid_device_connect(const char *remote_addr)
        BT_DBG("+");
        BT_CHECK_PARAMETER(remote_addr, return);
 
+       BT_CHECK_ENABLED(return);
+
        info = __find_hid_info_with_address(remote_addr);
        if (info) {
                BT_ERR("Connection Already Exists");
@@ -679,7 +707,7 @@ BT_EXPORT_API int bluetooth_hid_device_connect(const char *remote_addr)
                return BLUETOOTH_ERROR_PERMISSION_DEINED;
        }
 
-       g_strlcpy(device_address, remote_addr, BT_ADDRESS_STRING_SIZE);
+       memcpy(device_address, remote_addr, BT_ADDRESS_STRING_SIZE);
        ret = _bt_connect_profile(device_address, HID_DEVICE_UUID,
                                __hid_connect_response_cb, NULL);
 
@@ -689,6 +717,8 @@ BT_EXPORT_API int bluetooth_hid_device_disconnect(const char *remote_addr)
 {
        BT_CHECK_PARAMETER(remote_addr, return);
 
+       BT_CHECK_ENABLED(return);
+
        if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DEVICE_DISCONNECT)
                 == BLUETOOTH_ERROR_PERMISSION_DEINED) {
                BT_ERR("Don't have a privilege to use this API");
@@ -855,9 +885,7 @@ BT_EXPORT_API int bluetooth_hid_device_send_custom_event(const char *remote_addr
        else
                socket_fd = info->ctrl_fd;
 
-       send_event = (char*)g_malloc0(data_len + 2);
-       if (send_event == NULL)
-               return BLUETOOTH_ERROR_OUT_OF_MEMORY;
+       send_event = g_malloc0(data_len + 2);
 
        send_event[0] = (char)btcode;
        send_event[1] = (char)report_id;
@@ -878,7 +906,7 @@ BT_EXPORT_API int bluetooth_hid_device_reply_to_report(const char *remote_addr,
 {
        int result;
        struct reports output_report = { 0 };
-       int bytes = 0;
+       int bytes = BLUETOOTH_ERROR_INTERNAL;
        hid_connected_device_info_t *info = NULL;
        info = __find_hid_info_with_address(remote_addr);
        if (info == NULL) {
@@ -959,6 +987,26 @@ BT_EXPORT_API int bluetooth_hid_device_reply_to_report(const char *remote_addr,
                BT_DBG("Bytes Written %d", bytes);
                break;
        }
+
+       case HTYPE_TRANS_GET_IDLE: {
+               BT_DBG("Replying to Get_IDLE");
+               output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_OUTPUT;
+               output_report.rep_data[0] = data[0];
+               bytes = write(info->intr_fd, &output_report, 2);
+               BT_DBG("Bytes Written %d", bytes);
+               break;
+       }
+
+       case HTYPE_TRANS_SET_IDLE: {
+               BT_DBG("Reply to Set_IDLE");
+               output_report.type = BT_HID_TRANS_DATA | BT_HID_DATA_RTYPE_INPUT;
+               memcpy(output_report.rep_data, data, data_len);
+               bytes = write(info->ctrl_fd, &output_report,
+                               sizeof(output_report));
+               BT_DBG("Bytes Written %d", bytes);
+               break;
+       }
+
        default:
                break;
                }