[Adapt:BluezHAL]Add HIDHost connect/Disconnect API 05/79405/1
authorAtul Rai <a.rai@samsung.com>
Thu, 7 Jul 2016 08:23:21 +0000 (17:23 +0900)
committerAtul Rai <a.rai@samsung.com>
Mon, 11 Jul 2016 08:43:04 +0000 (17:43 +0900)
This patch added implementation for HID host connect and
disconnect APIs in BlueZ HAL. It also implements connection
state callback event handling in Bluez HAL.

Change-Id: I15f79cc89586df3e16e10086fee434bf6e631614
Signed-off-by: Atul Rai <a.rai@samsung.com>
bt-oal/bluez_hal/CMakeLists.txt
bt-oal/bluez_hal/inc/bt-hal-msg.h
bt-oal/bluez_hal/src/bt-hal-dbus-common-utils.h
bt-oal/bluez_hal/src/bt-hal-hid-dbus-handler.c [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-hid-dbus-handler.h [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-hidhost.c

index c700630..32c8502 100644 (file)
@@ -11,6 +11,7 @@ SET(SRCS
 ./src/bt-hal-gap-agent.c
 ./src/bt-hal-agent.c
 ./src/bt-hal-hidhost.c
+./src/bt-hal-hid-dbus-handler.c
 )
 
 SET(PREFIX ${CMAKE_INSTALL_PREFIX})
index e104e90..974960c 100644 (file)
@@ -170,5 +170,68 @@ struct hal_ev_acl_state_changed {
 #define BT_TRANSPORT_BR_EDR             0x01
 #define BT_TRANSPORT_LE                 0x02
 
+/* HID host events */
+#define HAL_HIDHOST_STATE_CONNECTED    0x00
+#define HAL_HIDHOST_STATE_CONNECTING   0x01
+#define HAL_HIDHOST_STATE_DISCONNECTED 0x02
+#define HAL_HIDHOST_STATE_DISCONNECTING        0x03
+#define HAL_HIDHOST_STATE_NO_HID       0x07
+#define HAL_HIDHOST_STATE_FAILED       0x08
+#define HAL_HIDHOST_STATE_UNKNOWN      0x09
+
+#define HAL_EV_HIDHOST_CONN_STATE              0x81
+struct hal_ev_hidhost_conn_state {
+               uint8_t bdaddr[6];
+                       uint8_t state;
+} __attribute__((packed));
+
+#define HAL_EV_HIDHOST_INFO    0x82
+struct hal_ev_hidhost_info {
+       uint8_t  bdaddr[6];
+       uint8_t  attr;
+       uint8_t  subclass;
+       uint8_t  app_id;
+       uint16_t vendor;
+       uint16_t product;
+       uint16_t version;
+       uint8_t  country;
+       uint16_t descr_len;
+       uint8_t  descr[884];
+} __attribute__((packed));
+
+#define HAL_EV_HIDHOST_PROTO_MODE      0x83
+struct hal_ev_hidhost_proto_mode {
+       uint8_t bdaddr[6];
+       uint8_t status;
+       uint8_t mode;
+} __attribute__((packed));
+
+#define HAL_EV_HIDHOST_IDLE_TIME       0x84
+struct hal_ev_hidhost_idle_time {
+       uint8_t bdaddr[6];
+       uint8_t status;
+       uint32_t idle_rate;
+} __attribute__((packed));
+
+#define HAL_EV_HIDHOST_GET_REPORT      0x85
+struct hal_ev_hidhost_get_report {
+       uint8_t  bdaddr[6];
+       uint8_t  status;
+       uint16_t len;
+       uint8_t  data[0];
+} __attribute__((packed));
+
+#define HAL_EV_HIDHOST_VIRTUAL_UNPLUG  0x86
+struct hal_ev_hidhost_virtual_unplug {
+       uint8_t  bdaddr[6];
+       uint8_t  status;
+} __attribute__((packed));
+
+#define HAL_EV_HIDHOST_HANDSHAKE       0x87
+struct hal_ev_hidhost_handshake {
+       uint8_t  bdaddr[6];
+       uint8_t  status;
+} __attribute__((packed));
+
 #endif //_BT_HAL_MSG_H_
 
index 9ca55a9..de22a50 100644 (file)
@@ -110,6 +110,7 @@ extern "C" {
 #define BT_HAL_NAME_OWNER_CHANGED "NameOwnerChanged"
 #define BT_HAL_PROPERTIES_CHANGED "PropertiesChanged"
 
+#define HID_UUID                "00001124-0000-1000-8000-00805f9b34fb"
 
 /**
  * This is Bluetooth error code
diff --git a/bt-oal/bluez_hal/src/bt-hal-hid-dbus-handler.c b/bt-oal/bluez_hal/src/bt-hal-hid-dbus-handler.c
new file mode 100644 (file)
index 0000000..2e33070
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Atul Kumar Rai <a.rai@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <dlog.h>
+#include <vconf.h>
+
+#include "bt-hal-hid-dbus-handler.h"
+#include "bt-hal-dbus-common-utils.h"
+#include "bt-hal-internal.h"
+
+static handle_stack_msg event_cb = NULL;
+
+/* To send stack event to hal-hidhost handler */
+void _bt_hal_register_hid_dbus_handler_cb(handle_stack_msg cb)
+{
+       event_cb = cb;
+}
+
+/* To send stack event to hal-hidhost handler */
+void _bt_hal_unregister_hid_dbus_handler_cb()
+{
+       event_cb = NULL;
+}
+
+static void __bt_hid_connect_cb(GDBusProxy *proxy, GAsyncResult *res,
+               gpointer user_data)
+{
+       GError *g_error = NULL;
+       struct hal_ev_hidhost_conn_state ev;
+       GVariant *reply = NULL;
+       char *address = user_data;
+       int result = BT_STATUS_SUCCESS;
+
+       DBG("+");
+
+       reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
+       g_object_unref(proxy);
+       if (reply == NULL) {
+               ERR("Hid Connect Dbus Call Error");
+               if (g_error) {
+                       ERR("Error: %s\n", g_error->message);
+                       g_clear_error(&g_error);
+               }
+               result = BT_STATUS_FAIL;
+       }
+       g_variant_unref(reply);
+
+       DBG("Address: %s", address);
+       /*
+        * If result is success, HID connected event will be triggered
+        * automatically from stack, so return from here.
+        */
+       if (result == BT_STATUS_SUCCESS)
+               goto done;
+
+       /* Prepare to send HID connection state event */
+       memset(&ev, 0, sizeof(ev));
+       _bt_convert_addr_string_to_type(ev.bdaddr, address);
+       ev.state = HAL_HIDHOST_STATE_DISCONNECTED;
+       if (!event_cb)
+               ERR("HID dbus handler callback not registered");
+       else
+               event_cb(HAL_EV_HIDHOST_CONN_STATE, (void *)&ev, sizeof(ev));
+
+done:
+       g_free(address);
+}
+
+bt_status_t _bt_hal_dbus_handler_hidhost_connect(bt_bdaddr_t *bd_addr)
+{
+       char *address;
+       struct hal_ev_hidhost_conn_state ev;
+       GDBusConnection *conn;
+
+       int ret;
+       char *uuid;
+
+       if(!bd_addr) {
+               ERR("bd_addr is NULL, return");
+               return BT_STATUS_PARM_INVALID;
+       }
+
+       conn = _bt_get_system_gconn();
+       if(!conn) {
+               ERR("_bt_get_system_gconn returned NULL, return");
+               return BT_STATUS_FAIL;
+       }
+
+       address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE * sizeof(char));
+       if (!address) {
+               ERR("Memory allocation failed");
+               return BT_STATUS_NOMEM;
+       }
+       _bt_convert_addr_type_to_string(address, bd_addr->address);
+       uuid = HID_UUID;
+
+       ret = _bt_connect_profile(address, uuid,
+                       __bt_hid_connect_cb, address);
+
+       if (ret != BT_HAL_ERROR_NONE) {
+               ERR("_bt_connect_profile Error");
+               return BT_STATUS_FAIL;
+       }
+
+       /* Prepare to send HID connecting event */
+       memset(&ev, 0, sizeof(ev));
+       ev.state = HAL_HIDHOST_STATE_CONNECTING;
+       memcpy(ev.bdaddr, bd_addr, sizeof(bt_bdaddr_t));
+       if (!event_cb)
+               ERR("HID dbus handler callback not registered");
+       else
+               event_cb(HAL_EV_HIDHOST_CONN_STATE, (void *)&ev, sizeof(ev));
+
+       return BT_STATUS_SUCCESS;
+}
+
+static void __bt_hid_disconnect_cb(GDBusProxy *proxy, GAsyncResult *res,
+               gpointer user_data)
+{
+       GError *g_error = NULL;
+       GVariant *reply = NULL;
+       char *address = user_data;
+       int result = BT_STATUS_SUCCESS;
+
+       DBG("+");
+
+       reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
+       g_object_unref(proxy);
+       if (reply == NULL) {
+               ERR("Hid Disconnect Dbus Call Error");
+               if (g_error) {
+                       ERR("Error: %s\n", g_error->message);
+                       g_clear_error(&g_error);
+               }
+               result = BT_STATUS_FAIL;
+       }
+       g_variant_unref(reply);
+
+       if (result != BT_STATUS_FAIL)
+               DBG("HID Disconnect successful for Device: %s", address);
+       else
+               DBG("HID Disconnect un-successful for Device: %s", address);
+       g_free(address);
+       DBG("-");
+}
+
+bt_status_t _bt_hal_dbus_handler_hidhost_disconnect(bt_bdaddr_t *bd_addr)
+{
+       char *address;
+       struct hal_ev_hidhost_conn_state ev;
+       GDBusConnection *conn;
+
+       int ret;
+       char *uuid;
+
+       if(!bd_addr) {
+               ERR("bd_addr is NULL, return");
+               return BT_STATUS_PARM_INVALID;
+       }
+
+       conn = _bt_get_system_gconn();
+       if(!conn) {
+               ERR("_bt_get_system_gconn returned NULL, return");
+               return BT_STATUS_FAIL;
+       }
+
+       address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE * sizeof(char));
+       if (!address) {
+               ERR("Memory allocation failed");
+               return BT_STATUS_NOMEM;
+       }
+       _bt_convert_addr_type_to_string(address, bd_addr->address);
+       uuid = HID_UUID;
+
+       ret = _bt_disconnect_profile(address, uuid,
+                       __bt_hid_disconnect_cb, address);
+       if (ret != BT_HAL_ERROR_NONE) {
+               ERR("_bt_connect_profile Error");
+               return BT_STATUS_FAIL;
+       }
+
+       /* Prepare to send HID connecting event */
+       memset(&ev, 0, sizeof(ev));
+       ev.state = HAL_HIDHOST_STATE_DISCONNECTING;
+       memcpy(ev.bdaddr, bd_addr, sizeof(bt_bdaddr_t));
+       if (!event_cb)
+               ERR("HID dbus handler callback not registered");
+       else
+               event_cb(HAL_EV_HIDHOST_CONN_STATE, (void *)&ev, sizeof(ev));
+
+       return BT_STATUS_SUCCESS;
+}
diff --git a/bt-oal/bluez_hal/src/bt-hal-hid-dbus-handler.h b/bt-oal/bluez_hal/src/bt-hal-hid-dbus-handler.h
new file mode 100644 (file)
index 0000000..40707fe
--- /dev/null
@@ -0,0 +1,46 @@
+/* Bluetooth-frwk
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Atul Kumar Rai <a.rai@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *              http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+#ifndef _BT_HAL_HID_DBUS_HANDLER_H_
+#define _BT_HAL_HID_DBUS_HANDLER_H_
+
+#include <glib.h>
+#include <sys/types.h>
+
+#include "bt-hal.h"
+#include "bt-hal-log.h"
+#include "bt-hal-msg.h"
+
+#include "bt-hal-event-receiver.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void _bt_hal_register_hid_dbus_handler_cb(handle_stack_msg cb);
+void _bt_hal_unregister_hid_dbus_handler_cb();
+bt_status_t _bt_hal_dbus_handler_hidhost_connect(bt_bdaddr_t *bd_addr);
+bt_status_t _bt_hal_dbus_handler_hidhost_disconnect(bt_bdaddr_t *bd_addr);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* _BT_HAL_HID_DBUS_HANDLER_H_ */
index d39681b..e249a7d 100644 (file)
@@ -30,6 +30,8 @@
 #include "bt-hal-msg.h"
 #include "bt-hal-utils.h"
 
+#include "bt-hal-hid-dbus-handler.h"
+
 static const bthh_callbacks_t *bt_hal_hid_cbacks;
 
 static bool interface_ready(void)
@@ -37,16 +39,26 @@ static bool interface_ready(void)
        return bt_hal_hid_cbacks != NULL;
 }
 
+static void __bt_hal_handle_conn_state(void *buf, uint16_t len)
+{
+       struct hal_ev_hidhost_conn_state *ev = buf;
+
+       if (bt_hal_hid_cbacks->connection_state_cb)
+               bt_hal_hid_cbacks->connection_state_cb((bt_bdaddr_t *) ev->bdaddr,
+                                                               ev->state);
+}
+
+
 static bt_status_t hidhost_connect(bt_bdaddr_t *bd_addr)
 {
        DBG("");
-       return BT_STATUS_UNSUPPORTED;
+       return _bt_hal_dbus_handler_hidhost_connect(bd_addr);
 }
 
 static bt_status_t hidhost_disconnect(bt_bdaddr_t *bd_addr)
 {
        DBG("");
-       return BT_STATUS_UNSUPPORTED;
+       return _bt_hal_dbus_handler_hidhost_disconnect(bd_addr);
 }
 
 static bt_status_t virtual_unplug(bt_bdaddr_t *bd_addr)
@@ -98,6 +110,26 @@ static bt_status_t hidhost_send_data(bt_bdaddr_t *bd_addr, char *data)
        return BT_STATUS_UNSUPPORTED;
 }
 
+static void __bt_hal_handle_hid_events(int message, void *buf, uint16_t len)
+{
+       DBG("+");
+
+       if (!interface_ready())
+               return;
+
+       switch(message) {
+               case HAL_EV_HIDHOST_CONN_STATE:
+                       DBG("Event: HAL_EV_HIDHOST_CONN_STATE");
+                       __bt_hal_handle_conn_state(buf, len);
+                       break;
+               default:
+                       DBG("Event Currently not handled!!");
+                       break;
+       }
+
+       DBG("-");
+}
+
 static bt_status_t init(bthh_callbacks_t *callbacks)
 {
        DBG("");
@@ -106,6 +138,9 @@ static bt_status_t init(bthh_callbacks_t *callbacks)
                return BT_STATUS_DONE;
 
        bt_hal_hid_cbacks = callbacks;
+       DBG("Register HID events callback function");
+       _bt_hal_register_hid_dbus_handler_cb(__bt_hal_handle_hid_events);
+
        return BT_STATUS_SUCCESS;
 }
 
@@ -116,6 +151,8 @@ static void cleanup(void)
        if (!interface_ready())
                return;
 
+       _bt_hal_unregister_hid_dbus_handler_cb();
+
        bt_hal_hid_cbacks = NULL;
 }