[Adapt: Bluez HAL] Implement SSP and Legacy Pairing event handlers 59/78759/2
authorAnupam Roy <anupam.r@samsung.com>
Wed, 6 Jul 2016 18:22:00 +0000 (14:22 -0400)
committerAnupam Roy <anupam.r@samsung.com>
Wed, 6 Jul 2016 20:14:27 +0000 (16:14 -0400)
This patch handles following events
 1/ PIN Code Request
 2/ PASSKEY Request
 3/ DISPLAY Request
 4/ Confirmation Request

Note: Currently syspopup Mode is disabled.
Therefore SSP and Legacy Pairing events will be
sent to HAL user.

Change-Id: Ib3f10fc3774b9831b52586958a4aa18dbc26ad75
Signed-off-by: Anupam Roy <anupam.r@samsung.com>
bt-oal/bluez_hal/CMakeLists.txt
bt-oal/bluez_hal/src/bt-hal-agent.c
bt-oal/bluez_hal/src/bt-hal-agent.h
bt-oal/bluez_hal/src/bt-hal-bluetooth.c
bt-oal/bluez_hal/src/bt-hal-gap-agent.c [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-gap-agent.h [moved from bt-oal/bluez_hal/src/bt-hal-gap-agent1.h with 80% similarity]
bt-oal/bluez_hal/src/bt-hal-gap-agent.xml [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-gap-agent1.c [deleted file]
packaging/bluetooth-frwk.spec

index 016ed83..442c383 100644 (file)
@@ -8,7 +8,7 @@ SET(SRCS
 ./src/bt-hal-dbus-common-utils.c
 ./src/bt-hal-event-receiver.c
 ./src/bt-hal-utils.c
-./src/bt-hal-gap-agent1.c
+./src/bt-hal-gap-agent.c
 ./src/bt-hal-agent.c
 )
 
index 535c951..80f50de 100644 (file)
 #include "bt-hal-event-receiver.h"
 
 #include <bt-hal-agent.h>
-#include <bt-hal-gap-agent1.h>
+#include <bt-hal-gap-agent.h>
 #include <bt-hal-dbus-common-utils.h>
 
+#define BT_HAL_AGENT_AUTO_PAIR_BLACKLIST_FILE (APP_SYSCONFDIR"/auto-pair-blacklist")
+#define BT_HAL_AGENT_NEW_LINE "\r\n"
+#define BUF_SIZE                256
+#define PAGE_SIZE               (1 << 12)
+#define _ALIGN_UP(addr, size)    (((addr)+((size)-1))&(~((size)-1)))
+#define _ALIGN_DOWN(addr, size) ((addr)&(~((size)-1)))
+#define PAGE_ALIGN(addr)        _ALIGN_DOWN(addr, PAGE_SIZE)
+#define BT_HAL_PIN_MAX_LENGTH 16
+#define BT_HAL_PASSKEY_MAX_LENGTH 4
+#define BT_HAL_LOWER_ADDRESS_LENGTH 9
+#define BT_HAL_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS 200
+#define BT_HAL_AGENT_SYSPOPUP_MAX_ATTEMPT 3
+
+#define G_VARIANT_UNREF(variant) \
+        g_variant_unref(variant); \
+        variant = NULL
+#define BT_HAL_MAX_EVENT_STR_LENGTH 50
+
 static void *adapter_agent = NULL;
 
+/* Forward delcaration */
+static void __bt_hal_send_pin_request_event(const gchar *address, const gchar *name,
+               uint32_t cod);
+static gboolean __bt_hal_pincode_request(GapAgentPrivate *agent, GDBusProxy *device);
+static gboolean __bt_hal_display_request(GapAgentPrivate *agent, GDBusProxy *device,
+               guint passkey);
+static gboolean __bt_hal_passkey_request(GapAgentPrivate *agent, GDBusProxy *device);
+static gboolean __bt_hal_confirm_request(GapAgentPrivate *agent, GDBusProxy *device,
+               guint passkey);
+static GVariant *__bt_hal_service_getall(GDBusProxy *device, const char *interface);
+static void __bt_hal_agent_release_memory(void);
+static inline void stack_trim(void);
+
+#ifdef TIZEN_SYSPOPUP_SUPPORTED
+static gboolean __bt_hal_device_is_hid_keyboard(unsigned int dev_class);
+static int __bt_hal_device_generate_passkey(char *passkey, int size);
+static gboolean __bt_hal_device_is_auto_response(uint32_t dev_class,
+                const gchar *address, const gchar *name);
+static gboolean __bt_hal_device_is_device_blacklisted(const char *address, const char *name);
+static gboolean __bt_hal_find_device_by_address_exactname(char *buffer,
+                const char *address);
+static gboolean __bt_hal_find_device_by_partial_name(char *buffer,
+                const char *partial_name);
+static gboolean __bt_hal_agent_system_popup_timer_cb(gpointer user_data);
+#else
+static void __bt_hal_send_ssp_request_events(const gchar *address, const gchar *name,
+               guint passkey, uint32_t cod, unsigned char variant);
+#endif
+
 void* _bt_hal_create_agent(const char *path, gboolean adapter)
 {
        GAP_AGENT_FUNC_CB func_cb;
@@ -69,10 +116,10 @@ void* _bt_hal_create_agent(const char *path, gboolean adapter)
        if (!adapter_proxy)
                return NULL;
 
-       func_cb.pincode_func = NULL;
-       func_cb.display_func = NULL;
-       func_cb.passkey_func = NULL;
-       func_cb.confirm_func = NULL;
+       func_cb.pincode_func = __bt_hal_pincode_request;
+       func_cb.display_func = __bt_hal_display_request;
+       func_cb.passkey_func = __bt_hal_passkey_request;
+       func_cb.confirm_func = __bt_hal_confirm_request;
        func_cb.authorize_func = NULL;
        func_cb.pairing_cancel_func = NULL;
        func_cb.authorization_cancel_func = NULL;
@@ -152,3 +199,794 @@ void* _bt_hal_get_adapter_agent(void)
 {
        return adapter_agent;
 }
+
+/* Legacy Pairing */
+static void __bt_hal_send_pin_request_event(const gchar *address, const gchar *name,
+               uint32_t cod)
+{
+       struct hal_ev_pin_request ev;
+       memset(&ev, 0, sizeof(ev));
+
+       DBG("Remote Device address [%s]", address);
+       DBG("Remote Device Name [%s]", name);
+       DBG("Remote Device COD [%u]", cod);
+
+       _bt_convert_addr_string_to_type(ev.bdaddr, address);
+
+       memcpy(ev.name, name, strlen(name));
+       ev.class_of_dev = cod;
+
+       handle_stack_msg event_cb = _bt_hal_get_stack_message_handler();
+       if (event_cb) {
+               DBG("Sending PIN REQUEST");
+               event_cb(HAL_EV_PIN_REQUEST, (void*)&ev, sizeof(ev));
+       }
+
+       DBG("-");
+}
+
+static gboolean __bt_hal_pincode_request(GapAgentPrivate *agent, GDBusProxy *device)
+{
+       uint32_t device_class;
+       const gchar *address;
+       const gchar *name;
+       GVariant *reply = NULL;
+       GVariant *reply_temp = NULL;
+       GVariant *tmp_value;
+       DBG("+");
+
+       reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
+
+       if (reply_temp == NULL) {
+               gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
+                               NULL);
+               goto done;
+       }
+
+       g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/
+
+       tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
+       g_variant_get(tmp_value, "u", &device_class);
+       G_VARIANT_UNREF(tmp_value);
+
+       tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
+       g_variant_get(tmp_value, "s", &address);
+       G_VARIANT_UNREF(tmp_value);
+
+       tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
+       g_variant_get(tmp_value, "s", &name);
+       G_VARIANT_UNREF(tmp_value);
+
+       if (!name)
+               name = address;
+#ifdef TIZEN_SYSPOPUP_SUPPORTED
+       if (__bt_hal_device_is_hid_keyboard(device_class)) {
+               DBG("Device is HID Keyboard");
+               char str_passkey[BT_HAL_PASSKEY_MAX_LENGTH + 1] = { 0 };
+               if (__bt_hal_device_generate_passkey(str_passkey,
+                                       BT_HAL_PASSKEY_MAX_LENGTH) != 0) {
+                       gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT,
+                                       "", NULL);
+                       goto done;
+               }
+               gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT,
+                               str_passkey, NULL);
+
+               DBG("Launch BT Syspopup");
+               _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST,
+                               name, str_passkey, NULL,
+                               _gap_agent_get_path(agent));
+       } else if (!__bt_hal_device_is_auto_response(device_class, address, name)) {
+               DBG("Device is not of AUto response class, Show PIN Entry");
+               _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_PIN_REQUEST, name, NULL,
+                               NULL, _gap_agent_get_path(agent));
+       } else {
+               DBG("Device is of Type Auto response, send event to HAL");
+               __bt_hal_send_pin_request_event(address, name, device_class);
+       }
+#else
+       DBG("PIN CODE request, device class [%u]", device_class);
+       __bt_hal_send_pin_request_event(address, name, device_class);
+#endif
+
+done:
+       g_variant_unref(reply);
+       g_variant_unref(reply_temp);
+       __bt_hal_agent_release_memory();
+       DBG("-");
+
+       return TRUE;
+}
+
+
+/* BT_SSP_VARIANT_PASSKEY_CONFIRMATION */
+/* BT_SSP_VARIANT_PASSKEY_NOTIFICATION */
+/* BT_SSP_VARIANT_PASSKEY_ENTRY */
+/* BT_SSP_VARIANT_CONSENT */
+
+#ifndef TIZEN_SYSPOPUP_SUPPORTED
+static void __bt_hal_send_ssp_request_events(const gchar *address,
+               const gchar *name,
+               guint passkey,
+               uint32_t cod,
+               unsigned char variant)
+{
+       struct hal_ev_ssp_request ev;
+       memset(&ev, 0, sizeof(ev));
+       DBG("sizeof ev [%d]", sizeof(ev));
+
+       DBG("Remote Device address [%s]", address);
+       DBG("Remote Device Name [%s]", name);
+       DBG("Remote Device passkey [%d]", passkey);
+       DBG("Remote Device pairing variant [0x%x]", variant);
+       DBG("Remote Device cod [%d]", cod);
+
+       _bt_convert_addr_string_to_type(ev.bdaddr, address);
+
+       memcpy(ev.name, name, strlen(name));
+       ev.class_of_dev = cod;
+       ev.pairing_variant = variant;
+       ev.passkey = passkey;
+
+       handle_stack_msg event_cb = _bt_hal_get_stack_message_handler();
+       if (event_cb) {
+               DBG("Sending SSP type [%d]", variant);
+               event_cb(HAL_EV_SSP_REQUEST, (void*)&ev, sizeof(ev));
+       }
+
+       DBG("-");
+}
+#endif
+
+/* SSP */
+static gboolean __bt_hal_display_request(GapAgentPrivate *agent, GDBusProxy *device,
+               guint passkey)
+{
+       const gchar *address;
+       const gchar *name;
+       char *str_passkey;
+       uint32_t device_class;
+       GVariant *reply = NULL;
+       GVariant *reply_temp = NULL;
+       GVariant *tmp_value = NULL;
+       DBG("+");
+
+       reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
+       if (reply_temp == NULL) {
+               gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
+                               NULL);
+               goto done;
+       }
+
+       g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/
+
+       tmp_value = g_variant_lookup_value (reply, "Address", G_VARIANT_TYPE_STRING);
+       g_variant_get(tmp_value, "s", &address);
+       G_VARIANT_UNREF(tmp_value);
+       if (!address) {
+               gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
+               goto done;
+       }
+
+       tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
+       g_variant_get(tmp_value, "s", &name);
+       G_VARIANT_UNREF(tmp_value);
+
+       tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
+       g_variant_get(tmp_value, "u", &device_class);
+       G_VARIANT_UNREF(tmp_value);
+
+       if (!name)
+               name = address;
+
+       str_passkey = g_strdup_printf("%d", passkey);
+
+#ifdef TIZEN_SYSPOPUP_SUPPORTED
+       DBG("Launch BT Syspopup: KEYBOARD_PASSKEY_REQUEST");
+       _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST, name,
+                       str_passkey, NULL,
+                       _gap_agent_get_path(agent));
+#else
+
+       __bt_hal_send_ssp_request_events(address, name, passkey, device_class,
+                       BT_SSP_VARIANT_PASSKEY_NOTIFICATION);
+#endif
+
+       g_free(str_passkey);
+done:
+       g_variant_unref(reply);
+       g_variant_unref(reply_temp);
+       __bt_hal_agent_release_memory();
+
+       DBG("-");
+       return TRUE;
+}
+
+/* SSP */
+static gboolean __bt_hal_passkey_request(GapAgentPrivate *agent, GDBusProxy *device)
+{
+       const gchar *address;
+       const gchar *name;
+       uint32_t device_class;
+       GVariant *reply = NULL;
+       GVariant *reply_temp = NULL;
+       GVariant *tmp_value;
+       DBG("+");
+
+       reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
+
+       if (reply_temp == NULL) {
+               gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
+                               NULL);
+               goto done;
+       }
+
+       g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/
+
+       tmp_value = g_variant_lookup_value (reply, "Address", G_VARIANT_TYPE_STRING);
+       g_variant_get(tmp_value, "s", &address);
+       G_VARIANT_UNREF(tmp_value);
+       if (!address) {
+               gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
+               goto done;
+       }
+
+       tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
+       g_variant_get(tmp_value, "s", &name);
+       G_VARIANT_UNREF(tmp_value);
+
+       tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
+       g_variant_get(tmp_value, "u", &device_class);
+       G_VARIANT_UNREF(tmp_value);
+
+       if (!name)
+               name = address;
+#ifdef TIZEN_SYSPOPUP_SUPPORTED
+       DBG("Launch BT Syspopup: PASSKEY_REQUEST");
+       _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_PASSKEY_REQUEST, name, NULL, NULL,
+                       _gap_agent_get_path(agent));
+#else
+       __bt_hal_send_ssp_request_events(address, name, 0, device_class,
+                       BT_SSP_VARIANT_PASSKEY_ENTRY);
+#endif
+
+done:
+       g_variant_unref(reply);
+       g_variant_unref(reply_temp);
+       __bt_hal_agent_release_memory();
+
+       DBG("-");
+       return TRUE;
+}
+
+/*ssp*/
+static gboolean __bt_hal_confirm_request(GapAgentPrivate *agent, GDBusProxy *device,
+               guint passkey)
+{
+       const gchar *address;
+       const gchar *name;
+       char str_passkey[7];
+       uint32_t device_class;
+       GVariant *reply_temp = NULL;
+       GVariant *reply = NULL;
+       GVariant *tmp_value;
+       DBG("+ passkey[%.6d]", passkey);
+       DBG("Agent Path [%s]", agent->path);
+
+       snprintf(str_passkey, sizeof(str_passkey), "%.6d", passkey);
+
+       reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
+
+       if (reply_temp == NULL) {
+               ERR("####Device doesn't exist####");
+               gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
+                               NULL);
+               goto done;
+       }
+       g_variant_get(reply_temp,"(@a{sv})", &reply); /* Format of reply a{sv}*/
+
+       tmp_value = g_variant_lookup_value (reply, "Address", G_VARIANT_TYPE_STRING);
+       g_variant_get(tmp_value, "s", &address);
+       G_VARIANT_UNREF(tmp_value);
+
+       tmp_value = g_variant_lookup_value (reply, "Name", G_VARIANT_TYPE_STRING);
+       g_variant_get(tmp_value, "s", &name);
+       G_VARIANT_UNREF(tmp_value);
+
+       tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
+       g_variant_get(tmp_value, "u", &device_class);
+       G_VARIANT_UNREF(tmp_value);
+
+       if (!name)
+               name = address;
+#ifdef TIZEN_WEARABLE
+       uint32_t major_class;
+
+
+       major_class = (device_class & 0x1f00) >> 8;
+
+       if (major_class == BLUETOOTH_DEVICE_MAJOR_CLASS_AUDIO) {
+               DBG("Audio device. Launch passkey pop-up");
+               _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name,
+                               str_passkey, NULL, _gap_agent_get_path(agent));
+               goto done;
+       }
+
+       if (__is_reset_required(address)) {
+               DBG("Launch system reset pop-up");
+               _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_SYSTEM_RESET_REQUEST, name,
+                               NULL, NULL, _gap_agent_get_path(agent));
+       } else {
+               DBG("Launch passkey pop-up");
+               _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_PASSKEY_AUTO_ACCEPTED, name,
+                               str_passkey, NULL, _gap_agent_get_path(agent));
+
+               gap_agent_reply_confirmation(agent, GAP_AGENT_ACCEPT, NULL);
+       }
+#else
+
+#ifdef TIZEN_SYSPOPUP_SUPPORTED
+       DBG("Launch BT Syspopup");
+       DBG("Name [%s]", name);
+       DBG("Passkey [%s]", str_passkey);
+       _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name,
+                       str_passkey, NULL,
+                       _gap_agent_get_path(agent));
+#else
+       __bt_hal_send_ssp_request_events(address, name, passkey,
+                       device_class, BT_SSP_VARIANT_PASSKEY_CONFIRMATION);
+#endif //TIZEN_SYSPOPUP_SUPPORTED
+#endif //TIZEN_WEARABLE
+
+done:
+       g_variant_unref(reply);
+       g_variant_unref(reply_temp);
+       __bt_hal_agent_release_memory();
+       DBG("-");
+       return TRUE;
+}
+
+#ifdef TIZEN_SYSPOPUP_SUPPORTED
+int _bt_hal_launch_system_popup(bt_hal_agent_event_type_t event_type,
+               const char *device_name,
+               char *passkey,
+               const char *filename,
+               const char *agent_path)
+{
+       int ret;
+       bundle *b;
+       char event_str[BT_HAL_MAX_EVENT_STR_LENGTH + 1];
+       DBG("+");
+
+       b = bundle_create();
+       if (!b) {
+               DBG("Launching system popup failed");
+               return -1;
+       }
+
+       bundle_add(b, "device-name", device_name);
+       bundle_add(b, "passkey", passkey);
+       bundle_add(b, "file", filename);
+       bundle_add(b, "agent-path", agent_path);
+
+       switch (event_type) {
+               case BT_HAL_AGENT_EVENT_PIN_REQUEST:
+                       g_strlcpy(event_str, "pin-request", sizeof(event_str));
+                       break;
+
+               case BT_HAL_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST:
+                       g_strlcpy(event_str, "passkey-confirm-request",
+                                       sizeof(event_str));
+                       break;
+
+               case BT_HAL_AGENT_EVENT_PASSKEY_AUTO_ACCEPTED:
+                       g_strlcpy(event_str, "passkey-auto-accepted",
+                                       sizeof(event_str));
+                       break;
+
+               case BT_HAL_AGENT_EVENT_PASSKEY_REQUEST:
+                       g_strlcpy(event_str, "passkey-request", sizeof(event_str));
+                       break;
+
+               case BT_HAL_AGENT_EVENT_PASSKEY_DISPLAY_REQUEST:
+                       g_strlcpy(event_str, "passkey-display-request",
+                                       sizeof(event_str));
+               case BT_HAL_AGENT_EVENT_AUTHORIZE_REQUEST:
+                       g_strlcpy(event_str, "authorize-request",
+                                       sizeof(event_str));
+                       break;
+
+               case BT_HAL_AGENT_EVENT_CONFIRM_MODE_REQUEST:
+                       g_strlcpy(event_str, "confirm-mode-request",
+                                       sizeof(event_str));
+                       break;
+
+               case BT_HAL_AGENT_EVENT_FILE_RECEIVED:
+                       g_strlcpy(event_str, "file-received", sizeof(event_str));
+                       break;
+
+               case BT_HAL_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST:
+                       g_strlcpy(event_str, "keyboard-passkey-request",
+                                       sizeof(event_str));
+                       break;
+
+               case BT_HAL_AGENT_EVENT_TERMINATE:
+                       g_strlcpy(event_str, "terminate", sizeof(event_str));
+                       break;
+
+               case BT_HAL_AGENT_EVENT_EXCHANGE_REQUEST:
+                       g_strlcpy(event_str, "exchange-request", sizeof(event_str));
+                       break;
+
+               case BT_HAL_AGENT_EVENT_PBAP_REQUEST:
+                       g_strlcpy(event_str, "phonebook-request", sizeof(event_str));
+                       break;
+
+               case BT_HAL_AGENT_EVENT_MAP_REQUEST:
+                       g_strlcpy(event_str, "message-request", sizeof(event_str));
+                       break;
+#ifdef TIZEN_WEARABLE
+               case BT_HAL_AGENT_EVENT_SYSTEM_RESET_REQUEST:
+                       __bt_register_popup_event_signal();
+                       g_strlcpy(event_str, "system-reset-request", sizeof(event_str));
+                       break;
+#endif
+
+               case BT_HAL_AGENT_EVENT_LEGACY_PAIR_FAILED_FROM_REMOTE:
+                       g_strlcpy(event_str, "remote-legacy-pair-failed", sizeof(event_str));
+                       break;
+
+               default:
+                       DBG("Invalid event type");
+                       bundle_free(b);
+                       return -1;
+
+       }
+
+       bundle_add(b, "event-type", event_str);
+
+       ret = syspopup_launch("bt-syspopup", b);
+       if (0 > ret) {
+               DBG("Popup launch failed...retry %d", ret);
+
+               g_timeout_add(BT_HAL_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS,
+                               (GSourceFunc)__bt_hal_agent_system_popup_timer_cb, b);
+       } else {
+               bundle_free(b);
+       }
+
+       DBG("_bt_agent_launch_system_popup");
+       return 0;
+}
+
+static gboolean __bt_hal_agent_system_popup_timer_cb(gpointer user_data)
+{
+       int ret;
+       static int retry_count;
+       bundle *b = (bundle *)user_data;
+       if (user_data == NULL)
+               return  FALSE;
+
+       ++retry_count;
+
+       ret = syspopup_launch("bt-syspopup", b);
+       if (ret < 0) {
+               DBG("Sorry! Can't launch popup, ret=%d, Re-try[%d] time..",
+                               ret, retry_count);
+               if (retry_count >= BT_HAL_AGENT_SYSPOPUP_MAX_ATTEMPT) {
+                       DBG("Sorry!! Max retry %d reached", retry_count);
+                       bundle_free(b);
+                       retry_count = 0;
+                       return FALSE;
+               }
+       } else {
+               DBG("Hurray!! Finally Popup launched");
+               retry_count = 0;
+               bundle_free(b);
+       }
+
+       return (ret < 0) ? TRUE : FALSE;
+}
+
+static gboolean __bt_hal_device_is_hid_keyboard(unsigned int dev_class)
+{
+       switch ((dev_class & 0x1f00) >> 8) {
+               case 0x05:
+                       switch ((dev_class & 0xc0) >> 6) {
+                               case 0x01:
+                                       /* input-keyboard" */
+                                       return TRUE;
+                       }
+                       break;
+       }
+
+       return FALSE;
+}
+
+static int __bt_hal_device_generate_passkey(char *passkey, int size)
+{
+       int i;
+       ssize_t len;
+       int random_fd;
+       unsigned int value = 0;
+
+       if (passkey == NULL)
+               return -1;
+
+       if (size <= 0)
+               return -1;
+
+       random_fd = open("/dev/urandom", O_RDONLY);
+
+       if (random_fd < 0)
+               return -1;
+
+       for (i = 0; i < size; i++) {
+               len = read(random_fd, &value, sizeof(value));
+               if (len > 0)
+                       passkey[i] = '0' + (value % 10);
+       }
+
+       close(random_fd);
+
+       DBG("passkey: %s", passkey);
+
+       return 0;
+}
+
+static gboolean __bt_hal_find_device_by_address_exactname(char *buffer,
+               const char *address)
+{
+       char *pch;
+       char *last;
+
+       pch = strtok_r(buffer, "= ,", &last);
+
+       if (pch == NULL)
+               return FALSE;
+
+       while ((pch = strtok_r(NULL, ",", &last))) {
+               if (0 == g_strcmp0(pch, address)) {
+                       DBG("Match found\n");
+                       return TRUE;
+               }
+       }
+       return FALSE;
+}
+
+static gboolean __bt_hal_find_device_by_partial_name(char *buffer,
+               const char *partial_name)
+{
+       char *pch;
+       char *last;
+
+       pch = strtok_r(buffer, "= ,", &last);
+
+       if (pch == NULL)
+               return FALSE;
+
+       while ((pch = strtok_r(NULL, ",", &last))) {
+               if (g_str_has_prefix(partial_name, pch)) {
+                       DBG("Match found\n");
+                       return TRUE;
+               }
+       }
+       return FALSE;
+}
+
+static gboolean __bt_hal_device_is_device_blacklisted(const char *address,
+               const char *name)
+{
+       char *buffer;
+       char **lines;
+       int i;
+       FILE *fp;
+       long size;
+       size_t result;
+
+       DBG("+");
+
+       fp = fopen(BT_HAL_AGENT_AUTO_PAIR_BLACKLIST_FILE, "r");
+
+       if (fp == NULL) {
+               ERR("Unable to open blacklist file");
+               return FALSE;
+       }
+
+       fseek(fp, 0, SEEK_END);
+       size = ftell(fp);
+       if (size <= 0) {
+               DBG("size is not a positive number");
+               fclose(fp);
+               return FALSE;
+       }
+
+       rewind(fp);
+
+       buffer = g_malloc0(sizeof(char) * size);
+       /* Fix : NULL_RETURNS */
+       if (buffer == NULL) {
+               ERR("Fail to allocate memory");
+               fclose(fp);
+               return FALSE;
+       }
+       result = fread((char *)buffer, 1, size, fp);
+       fclose(fp);
+       if (result != size) {
+               ERR("Read Error");
+               g_free(buffer);
+               return FALSE;
+       }
+
+       DBG("Buffer = %s", buffer);
+
+       lines = g_strsplit_set(buffer, BT_HAL_AGENT_NEW_LINE, 0);
+       g_free(buffer);
+
+       if (lines == NULL) {
+               ERR("No lines in the file");
+               return FALSE;
+       }
+
+       for (i = 0; lines[i] != NULL; i++) {
+               if (g_str_has_prefix(lines[i], "AddressBlacklist"))
+                       if (__bt_hal_find_device_by_address_exactname(
+                                               lines[i], address))
+                               goto done;
+               if (g_str_has_prefix(lines[i], "ExactNameBlacklist"))
+                       if (__bt_hal_find_device_by_address_exactname(
+                                               lines[i], name))
+                               goto done;
+               if (g_str_has_prefix(lines[i], "PartialNameBlacklist"))
+                       if (__bt_hal_find_device_by_partial_name(lines[i],
+                                               name))
+                               goto done;
+               if (g_str_has_prefix(lines[i], "KeyboardAutoPair"))
+                       if (__bt_hal_find_device_by_address_exactname(
+                                               lines[i], address))
+                               goto done;
+       }
+       g_strfreev(lines);
+       DBG("-");
+       return FALSE;
+done:
+       DBG("Found the device");
+       g_strfreev(lines);
+       return TRUE;
+}
+
+static gboolean __bt_hal_device_is_auto_response(uint32_t dev_class,
+               const gchar *address, const gchar *name)
+{
+       gboolean is_headset = FALSE;
+       gboolean is_mouse = FALSE;
+       char lap_address[BT_HAL_LOWER_ADDRESS_LENGTH];
+
+       DBG("bt_agent_is_headset_class, %d +", dev_class);
+
+       if (address == NULL)
+               return FALSE;
+
+       switch ((dev_class & 0x1f00) >> 8) {
+               case 0x04:
+                       switch ((dev_class & 0xfc) >> 2) {
+                               case 0x01:
+                               case 0x02:
+                                       /* Headset */
+                                       is_headset = TRUE;
+                                       break;
+                               case 0x06:
+                                       /* Headphone */
+                                       is_headset = TRUE;
+                                       break;
+                               case 0x0b:      /* VCR */
+                               case 0x0c:      /* Video Camera */
+                               case 0x0d:      /* Camcorder */
+                                       break;
+                               default:
+                                       /* Other audio device */
+                                       is_headset = TRUE;
+                                       break;
+                       }
+                       break;
+               case 0x05:
+                       switch (dev_class & 0xff) {
+                               case 0x80:  /* 0x80: Pointing device(Mouse) */
+                                       is_mouse = TRUE;
+                                       break;
+
+                               case 0x40: /* 0x40: input device (BT keyboard) */
+
+                                       /* Get the LAP(Lower Address part) */
+                                       g_strlcpy(lap_address, address, sizeof(lap_address));
+
+                                       /* Need to Auto pair the blacklisted Keyboard */
+                                       if (__bt_hal_device_is_device_blacklisted(lap_address, name) != TRUE) {
+                                               DBG("Device is not black listed\n");
+                                               return FALSE;
+                                       } else {
+                                               ERR("Device is black listed\n");
+                                               return TRUE;
+                                       }
+                       }
+       }
+
+       if ((!is_headset) && (!is_mouse))
+               return FALSE;
+
+       /* Get the LAP(Lower Address part) */
+       g_strlcpy(lap_address, address, sizeof(lap_address));
+
+       DBG("Device address = %s\n", address);
+       DBG("Address 3 byte = %s\n", lap_address);
+
+       if (__bt_hal_device_is_device_blacklisted(lap_address, name)) {
+               ERR("Device is black listed\n");
+               return FALSE;
+       }
+
+       return TRUE;
+}
+#endif
+
+static GVariant *__bt_hal_service_getall(GDBusProxy *device, const char *interface)
+{
+       GError *error = NULL;
+       GVariant *reply;
+       DBG("+");
+       reply = g_dbus_proxy_call_sync(device,
+                       "GetAll", g_variant_new("(s)", interface),
+                       G_DBUS_CALL_FLAGS_NONE, -1,
+                       NULL, &error);
+       if (reply == NULL) {
+               ERR("GetAll dBUS-RPC failed");
+               if (error) {
+                       ERR("D-Bus API failure: errCode[%x], message[%s]",
+                                       error->code, error->message);
+                       g_clear_error(&error);
+               }
+               return NULL;
+       }
+
+       DBG("-");
+       return reply;
+}
+
+static void __bt_hal_agent_release_memory(void)
+{
+       /* Release Malloc Memory*/
+       malloc_trim(0);
+
+       /* Release Stack Memory*/
+       stack_trim();
+}
+
+static inline void stack_trim(void)
+{
+#ifdef STACK_FLUSH
+        unsigned int sp;
+        char buf[BUF_SIZE];
+        FILE *file;
+        unsigned int stacktop;
+        int found = 0;
+
+        asm volatile ("mov %0,sp " : "=r"(sp));
+
+        sprintf(buf, "/proc/%d/maps", getpid());
+        file = fopen(buf, "r");
+        while (fgets(buf, BUF_SIZE, file) != NULL) {
+                if (strstr(buf, "[stack]")) {
+                        found = 1;
+                        break;
+                }
+        }
+        fclose(file);
+
+        if (found) {
+                sscanf(buf, "%x-", &stacktop);
+                if (madvise((void *)PAGE_ALIGN(stacktop), PAGE_ALIGN(sp) - stacktop,
+                                                                                MADV_DONTNEED) < 0)
+                        perror("stack madvise fail");
+        }
+#endif
+}
index f54dbd4..26a0124 100644 (file)
 #include <dlog.h>
 #include <stdio.h>
 
+typedef enum {
+        BT_HAL_AGENT_EVENT_PIN_REQUEST,
+        BT_HAL_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST,
+        BT_HAL_AGENT_EVENT_PASSKEY_AUTO_ACCEPTED,
+        BT_HAL_AGENT_EVENT_PASSKEY_REQUEST,
+        BT_HAL_AGENT_EVENT_PASSKEY_DISPLAY_REQUEST,
+        BT_HAL_AGENT_EVENT_AUTHORIZE_REQUEST,
+        BT_HAL_AGENT_EVENT_CONFIRM_MODE_REQUEST,
+        BT_HAL_AGENT_EVENT_APP_CONFIRM_REQUEST,
+        BT_HAL_AGENT_EVENT_FILE_RECEIVED,
+        BT_HAL_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST,
+        BT_HAL_AGENT_EVENT_SECURITY,
+        BT_HAL_AGENT_EVENT_TERMINATE,
+        BT_HAL_AGENT_EVENT_EXCHANGE_REQUEST,
+        BT_HAL_AGENT_EVENT_PBAP_REQUEST,
+        BT_HAL_AGENT_EVENT_MAP_REQUEST,
+        BT_HAL_AGENT_EVENT_SYSTEM_RESET_REQUEST,
+        BT_HAL_AGENT_EVENT_LEGACY_PAIR_FAILED_FROM_REMOTE,
+} bt_hal_agent_event_type_t;
+
 void* _bt_hal_create_agent(const char *path, gboolean adapter);
 
 void _bt_hal_destroy_agent(void *agent);
@@ -44,4 +64,7 @@ void _bt_hal_initialize_adapter_agent(void);
 
 void _bt_hal_destroy_adapter_agent(void);
 
+int _bt_hal_launch_system_popup(bt_hal_agent_event_type_t event_type, const char *device_name,
+                       char *passkey, const char *filename,
+                       const char *agent_path);
 #endif //__BT_HAL_AGENT__
index aeacae2..e4edf4b 100644 (file)
@@ -55,6 +55,8 @@ static void __bt_hal_handle_adapter_discovery_state_changed(void *buf, uint16_t
 static void __bt_hal_handle_device_found_event(void *buf, uint16_t len);
 static void __bt_hal_handle_bond_state_changed_event(void *buf, uint16_t len);
 static void __bt_hal_handle_device_acl_state_changed_event(void *buf, uint16_t len);
+static void __bt_hal_handle_ssp_request_event(void *buf, uint16_t len);
+static void __bt_hal_handle_pin_request_event(void *buf, uint16_t len);
 
 static bool interface_ready(void)
 {
@@ -586,6 +588,69 @@ static void __bt_hal_handle_device_acl_state_changed_event(void *buf, uint16_t l
         DBG("-");
 }
 
+static void __bt_hal_handle_ssp_request_event(void *buf, uint16_t len)
+{
+       struct hal_ev_ssp_request *ev = (struct hal_ev_ssp_request *)buf;
+       bt_bdaddr_t bd_addr;
+       bt_bdname_t bd_name;
+       DBG("+");
+
+       memcpy(bd_addr.address, ev->bdaddr, 6);
+       memcpy(bd_name.name, ev->name, 248);
+
+       /* BD address*/
+       DBG("[0x%x]", bd_addr.address[0]);
+       DBG("[0x%x]", bd_addr.address[1]);
+       DBG("[0x%x]", bd_addr.address[2]);
+       DBG("[0x%x]", bd_addr.address[3]);
+       DBG("[0x%x]", bd_addr.address[4]);
+       DBG("[0x%x]", bd_addr.address[5]);
+
+       DBG("COD [%d]", ev->class_of_dev);
+       DBG("pairing variant [%d]", ev->pairing_variant);
+       DBG("passkey [%d]", ev->passkey);
+
+       if (!bt_hal_cbacks->ssp_request_cb) {
+               ERR("HAL User ssp_request_cb is not set!!");
+               return;
+       }
+
+       bt_hal_cbacks->ssp_request_cb(&bd_addr, &bd_name,
+                       ev->class_of_dev,
+                       ev->pairing_variant, ev->passkey);
+       DBG("-");
+}
+
+static void __bt_hal_handle_pin_request_event(void *buf, uint16_t len)
+{
+       struct hal_ev_pin_request *ev = (struct hal_ev_pin_request *)buf;
+       bt_bdaddr_t bd_addr;
+       bt_bdname_t bd_name;
+       DBG("+");
+
+       memcpy(bd_addr.address, ev->bdaddr, 6);
+       memcpy(bd_name.name, ev->name, 248);
+
+       /* BD address*/
+       DBG("[0x%x]", bd_addr.address[0]);
+       DBG("[0x%x]", bd_addr.address[1]);
+       DBG("[0x%x]", bd_addr.address[2]);
+       DBG("[0x%x]", bd_addr.address[3]);
+       DBG("[0x%x]", bd_addr.address[4]);
+       DBG("[0x%x]", bd_addr.address[5]);
+
+       DBG("COD [%u]", ev->class_of_dev);
+
+       if (!bt_hal_cbacks->pin_request_cb) {
+               ERR("HAL User pin_request_cb is not set!!");
+               return;
+       }
+
+       bt_hal_cbacks->pin_request_cb(&bd_addr, &bd_name,
+                       ev->class_of_dev);
+       DBG("-");
+}
+
 static void __bt_hal_handle_stack_messages(int message, void *buf, uint16_t len)
 {
        DBG("+");
@@ -611,13 +676,21 @@ static void __bt_hal_handle_stack_messages(int message, void *buf, uint16_t len)
                        __bt_hal_handle_remote_device_properties_event(buf, len);
                        break;
                case HAL_EV_BOND_STATE_CHANGED:
-                        DBG("Event: HAL_EV_BOND_STATE_CHANGED:");
-                        __bt_hal_handle_bond_state_changed_event(buf, len);
-                        break;
+                       DBG("Event: HAL_EV_BOND_STATE_CHANGED:");
+                       __bt_hal_handle_bond_state_changed_event(buf, len);
+                       break;
                case HAL_EV_ACL_STATE_CHANGED:
-                        DBG("Event: HAL_ACL_STATE_CONNECTED or Disconnected");
-                        __bt_hal_handle_device_acl_state_changed_event(buf, len);
-                        break;
+                       DBG("Event: HAL_ACL_STATE_CONNECTED or Disconnected");
+                       __bt_hal_handle_device_acl_state_changed_event(buf, len);
+                       break;
+               case HAL_EV_SSP_REQUEST:
+                       DBG("Event: HAL_EV_SSP_REQUEST");
+                       __bt_hal_handle_ssp_request_event(buf, len);
+                       break;
+               case HAL_EV_PIN_REQUEST:
+                       DBG("Event: HAL_EV_PIN_REQUEST");
+                       __bt_hal_handle_pin_request_event(buf, len);
+                       break;
                default:
                        DBG("Event Currently not handled!!");
                        break;
diff --git a/bt-oal/bluez_hal/src/bt-hal-gap-agent.c b/bt-oal/bluez_hal/src/bt-hal-gap-agent.c
new file mode 100644 (file)
index 0000000..5cc8676
--- /dev/null
@@ -0,0 +1,896 @@
+/*
+ * BLUETOOTH HAL
+ *
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Anupam Roy <anupam.r@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 <string.h>
+#include <vconf.h>
+#include <vconf-keys.h>
+
+#include  <bt-hal-gap-agent.h>
+#include  <bt-hal-agent.h>
+#include  <bt-hal-internal.h>
+
+#include "bt-hal.h"
+#include "bt-hal-log.h"
+#include "bt-hal-msg.h"
+#include "bt-hal-utils.h"
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <dlog.h>
+
+#include "bt-hal-adapter-dbus-handler.h"
+#include "bt-hal-dbus-common-utils.h"
+
+static GDBusConnection *connection = NULL;
+
+typedef enum {
+       GAP_AGENT_ERROR_REJECT,
+       GAP_AGENT_ERROR_CANCEL,
+       GAP_AGENT_ERROR_TIMEOUT,
+} GapAgentError;
+
+#define GAP_AGENT_ERROR (gap_agent_error_quark())
+
+static GQuark gap_agent_error_quark(void)
+{
+        static GQuark quark = 0;
+        if (!quark)
+                quark = g_quark_from_static_string("agent");
+
+        return quark;
+}
+
+
+/* Forward declaration */
+static gboolean __gap_agent_unregister(GapAgentPrivate *agent);
+static GDBusNodeInfo *__bt_service_create_method_node_info
+(const gchar *introspection_data);
+static void __bt_gap_agent_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);
+void _gap_agent_set_canceled(GapAgentPrivate *agent, gboolean value);
+
+
+
+static gint gap_agent_id = -1;
+
+gboolean _gap_agent_register(GapAgentPrivate *agent)
+{
+       GapAgentPrivate *priv = agent;
+       GDBusProxy *agent_manager;
+       GError *error = NULL;
+       GVariant *reply;
+
+       if (!priv)
+               return FALSE;
+       if (!connection)
+               return FALSE;
+
+       if (priv->agent_manager == NULL) {
+               agent_manager = g_dbus_proxy_new_sync(connection,
+                               G_DBUS_PROXY_FLAGS_NONE, NULL,
+                               BT_HAL_BLUEZ_NAME, BT_HAL_BLUEZ_PATH,
+                               BT_HAL_AGENT_MANAGER_INTERFACE, NULL, &error);
+               if (!agent_manager) {
+                       if (error) {
+                               ERR("Unable to create proxy: %s", error->message);
+                               g_clear_error(&error);
+                       }
+                       return FALSE;
+               }
+       } else {
+               agent_manager = priv->agent_manager;
+       }
+
+       reply = g_dbus_proxy_call_sync(agent_manager, "RegisterAgent",
+#ifdef TIZEN_BT_IO_CAPA_NO_INPUT_OUTPUT
+                       g_variant_new("(os)", priv->path, "NoInputNoOutput"),
+#else
+                       g_variant_new("(os)", priv->path, "DisplayYesNo"),
+#endif
+                       G_DBUS_CALL_FLAGS_NONE, -1,
+                       NULL, &error);
+       if (reply == NULL) {
+               ERR("Agent registration failed");
+               if (error) {
+                       ERR("Agent registration failed: errCode[%x], message[%s]",
+                                       error->code, error->message);
+                       g_clear_error(&error);
+               }
+               g_object_unref(agent_manager);
+               priv->agent_manager = NULL;
+               return FALSE;
+       }
+       g_variant_unref(reply);
+       reply = NULL;
+
+       /* Set the defalut agent */
+       DBG("agent_manager[%p] priv->path[%s]", agent_manager, priv->path);
+       reply = g_dbus_proxy_call_sync(agent_manager, "RequestDefaultAgent",
+                       g_variant_new("(o)", priv->path),
+                       G_DBUS_CALL_FLAGS_NONE, -1,
+                       NULL, &error);
+       if (reply == NULL) {
+               ERR("Request Default Agent failed");
+               if (error) {
+                       ERR("Request Default Agent failed: errCode[%x], message[%s]",
+                                       error->code, error->message);
+                       g_clear_error(&error);
+               }
+               g_object_unref(agent_manager);
+               priv->agent_manager = NULL;
+               return FALSE;
+       }
+       g_variant_unref(reply);
+
+       priv->agent_manager = agent_manager;
+
+       return TRUE;
+}
+
+static const gchar gap_agent_bluez_introspection_xml[] =
+"<node name='/'>"
+"  <interface name='org.bluez.Agent1'>"
+"    <method name='RequestPinCode'>"
+"      <arg type='o' name='device' direction='in'/>"
+"      <arg type='s' name='pincode' direction='out'/>"
+"    </method>"
+"    <method name='RequestPasskey'>"
+"      <arg type='o' name='device' direction='in'/>"
+"      <arg type='u' name='passkey' direction='out'/>"
+"    </method>"
+"    <method name='DisplayPasskey'>"
+"      <arg type='o' name='device' direction='in'/>"
+"      <arg type='u' name='passkey' direction='in'/>"
+"      <arg type='q' name='entered' direction='in'/>"
+"    </method>"
+"    <method name='RequestConfirmation'>"
+"      <arg type='o' name='device' direction='in'/>"
+"      <arg type='u' name='passkey' direction='in'/>"
+"    </method>"
+"    <method name='RequestAuthorization'>"
+"      <arg type='o' name='device' direction='in'/>"
+"    </method>"
+"    <method name='AuthorizeService'>"
+"      <arg type='o' name='device' direction='in'/>"
+"      <arg type='s' name='uuid' direction='in'/>"
+"    </method>"
+"    <method name='Cancel'>"
+"    </method>"
+"    <method name='Release'>"
+"    </method>"
+"    <method name='ReplyPinCode'>"
+"      <arg type='u' name='accept' direction='in'/>"
+"      <arg type='s' name='pincode' direction='in'/>"
+"    </method>"
+"    <method name='ReplyPasskey'>"
+"      <arg type='u' name='accept' direction='in'/>"
+"      <arg type='s' name='passkey' direction='in'/>"
+"    </method>"
+"    <method name='ReplyConfirmation'>"
+"      <arg type='u' name='accept' direction='in'/>"
+"    </method>"
+"    <method name='ReplyAuthorize'>"
+"      <arg type='u' name='accept' direction='in'/>"
+"    </method>"
+"    <method name='ConfirmModeChange'>"
+"      <arg type='s' name='mode' direction='in'/>"
+"    </method>"
+"    <method name='GetDiscoverableTimeout'>"
+"      <arg type='u' name='timeout' direction='out'/>"
+"    </method>"
+"  </interface>"
+"</node>";
+
+
+static const GDBusInterfaceVTable method_table = {
+       __bt_gap_agent_method,
+       NULL,
+       NULL,
+};
+
+void _gap_agent_setup_dbus(GapAgentPrivate *agent, GAP_AGENT_FUNC_CB *func_cb,
+               const char *path,
+               GDBusProxy *adapter)
+{
+       GapAgentPrivate *priv = agent;
+       GDBusProxy *proxy;
+       GDBusNodeInfo *node_info;
+       GError *error = NULL;
+       DBG("+");
+
+       priv->path = g_strdup(path);
+
+       node_info = __bt_service_create_method_node_info(
+                       gap_agent_bluez_introspection_xml);
+       if (node_info == NULL)
+               return;
+
+       DBG("path is [%s]", path);
+
+       connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+       if (!connection) {
+               if (error) {
+                       ERR("Unable to connect to gdbus: %s", error->message);
+                       g_clear_error(&error);
+               }
+               return;
+       }
+
+       if (gap_agent_id == -1) {
+               gap_agent_id = g_dbus_connection_register_object(connection, path,
+                               node_info->interfaces[0],
+                               &method_table, priv,
+                               NULL, &error);
+       }
+
+       g_dbus_node_info_unref(node_info);
+
+       if (gap_agent_id == 0) {
+               ERR("Failed to register for Path: %s", path);
+               if (error) {
+                       ERR("Failed to register: %s", error->message);
+                       g_clear_error(&error);
+               }
+               return;
+       }
+
+       memcpy(&priv->cb, func_cb, sizeof(GAP_AGENT_FUNC_CB));
+
+       priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
+       memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
+       memset(priv->authorize_addr, 0x00, sizeof(priv->authorize_addr));
+       priv->reply_context = NULL;
+
+       DBG("path: %s", path);
+
+       proxy =  g_dbus_proxy_new_sync(connection,
+                       G_DBUS_PROXY_FLAGS_NONE, NULL,
+                       BT_HAL_BLUEZ_NAME, path,
+                       BT_HAL_AGENT_INTERFACE, NULL, &error);
+
+       if (!proxy) {
+               ERR("Unable to create proxy");
+               if (error) {
+                       ERR("Error: %s", error->message);
+                       g_clear_error(&error);
+               }
+               priv->busname = NULL;
+       } else {
+               priv->busname = g_strdup(g_dbus_proxy_get_name(proxy));
+               g_object_unref(proxy);
+               DBG("Busname: %s", priv->busname);
+       }
+       DBG("-");
+}
+
+void _gap_agent_reset_dbus(GapAgentPrivate *agent)
+{
+       GapAgentPrivate *priv = agent;
+
+       /* Fix : NULL_RETURNS */
+       if (priv == NULL)
+               return ;
+
+       __gap_agent_unregister(agent);
+
+       if (gap_agent_id > 0) {
+
+               if (connection)
+                       g_dbus_connection_unregister_object(connection,
+                                       gap_agent_id);
+               gap_agent_id = -1;
+       }
+       /*TODO*/
+#if 0
+       if (priv->osp_servers) {
+               __gap_agent_remove_osp_servers(priv->osp_servers);
+               g_slist_free(priv->osp_servers);
+               priv->osp_servers = NULL;
+       }
+#endif
+       g_object_ref(priv->adapter);
+       priv->adapter = NULL;
+
+       g_free(priv->path);
+       priv->path = NULL;
+
+       g_free(priv->busname);
+       priv->busname = NULL;
+}
+
+gchar* _gap_agent_get_path(GapAgentPrivate *agent)
+{
+       GapAgentPrivate *priv = agent;
+
+       /* Fix : NULL_RETURNS */
+       if (priv == NULL)
+               return NULL;
+
+       return priv->path;
+}
+
+gboolean _gap_agent_is_canceled(GapAgentPrivate *agent)
+{
+       GapAgentPrivate *priv = agent;
+
+       /* Fix : NULL_RETURNS */
+       if (priv == NULL)
+               return  FALSE;
+
+       return priv->canceled;
+}
+
+void _gap_agent_set_canceled(GapAgentPrivate *agent, gboolean value)
+{
+       GapAgentPrivate *priv = agent;
+
+       /* Fix : NULL_RETURNS */
+       if (priv == NULL)
+               return;
+
+       priv->canceled = value;
+}
+
+static gboolean __gap_agent_unregister(GapAgentPrivate *agent)
+{
+       GapAgentPrivate *priv = agent;
+       GDBusProxy *agent_manager;
+       GError *error = NULL;
+       GVariant *reply;
+
+       if (priv == NULL || priv->path == NULL|| connection == NULL )
+               return  FALSE;
+
+       if (priv->agent_manager == NULL) {
+               agent_manager = g_dbus_proxy_new_sync(connection,
+                               G_DBUS_PROXY_FLAGS_NONE, NULL,
+                               BT_HAL_BLUEZ_NAME, BT_HAL_BLUEZ_PATH,
+                               BT_HAL_AGENT_MANAGER_INTERFACE, NULL, &error);
+               if (!agent_manager) {
+                       if (error) {
+                               ERR("Unable to create proxy: %s", error->message);
+                               g_clear_error(&error);
+                       }
+                       return FALSE;
+               }
+       } else {
+               agent_manager = priv->agent_manager;
+       }
+
+       reply = g_dbus_proxy_call_sync(agent_manager, "UnregisterAgent",
+                       g_variant_new("o", priv->path),
+                       G_DBUS_CALL_FLAGS_NONE, -1,
+                       NULL, &error);
+       g_object_unref(agent_manager);
+       priv->agent_manager = NULL;
+
+       if (reply == NULL) {
+               ERR("Agent unregistration failed");
+               if (error) {
+                       ERR("Agent unregistration failed: errCode[%x], message[%s]",
+                                       error->code, error->message);
+                       g_clear_error(&error);
+               }
+               return FALSE;
+       }
+       g_variant_unref(reply);
+
+       return TRUE;
+}
+
+       static GDBusNodeInfo *__bt_service_create_method_node_info
+(const gchar *introspection_data)
+{
+       GError *err = NULL;
+       GDBusNodeInfo *node_info = NULL;
+
+       if (introspection_data == NULL)
+               return NULL;
+
+       node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
+
+       if (err) {
+               ERR("Unable to create node: %s", err->message);
+               g_clear_error(&err);
+       }
+       return node_info;
+}
+
+static void __bt_gap_agent_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)
+{
+       DBG("+");
+       FN_START;
+
+       DBG("Method[%s] Object Path[%s] Interface Name[%s]",
+                       method_name, object_path, interface_name);
+
+       GError *err = NULL;
+       if (g_strcmp0(method_name, "RequestPinCode") == 0) {
+               GapAgentPrivate *agent = user_data;
+               char *sender = (char *)g_dbus_method_invocation_get_sender(invocation);
+               GDBusProxy *device;
+               char *addr;
+               char *path;
+               GDBusConnection *conn;
+
+               if (sender == NULL)
+                       return;
+
+               g_variant_get(parameters, "(&o)", &path);
+               DBG("Request pin code, Device Path :%s", path);
+
+               /* Need to check
+                  if (g_strcmp0(sender, agent->busname) != 0)
+                  return;
+                */
+
+               if (!agent->cb.passkey_func)
+                       return;
+               conn = _bt_get_system_gconn();
+               if (conn == NULL)
+                       return;
+               device = g_dbus_proxy_new_sync(conn,
+                               G_DBUS_PROXY_FLAGS_NONE, NULL,
+                               BT_HAL_BLUEZ_NAME, path,
+                               BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
+               if (!device) {
+                       ERR("Fail to make device proxy");
+                       g_dbus_method_invocation_return_error(invocation,
+                                       GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
+                                       "No proxy for device");
+                       if (err) {
+                               ERR("Unable to create proxy: %s", err->message);
+                               g_clear_error(&err);
+                       }
+                       return;
+               }
+
+               agent->exec_type = GAP_AGENT_EXEC_PAIRING;
+               agent->reply_context = invocation;
+
+               addr = strstr(path, "dev_");
+               if (addr != NULL) {
+                       char *pos = NULL;
+                       addr += 4;
+                       g_strlcpy(agent->pairing_addr, addr, sizeof(agent->pairing_addr));
+
+                       while ((pos = strchr(agent->pairing_addr, '_')) != NULL) {
+                               *pos = ':';
+                       }
+               }
+               agent->cb.pincode_func(agent, device);
+               g_object_unref(device);
+               return;
+       } else if (g_strcmp0(method_name, "RequestPasskey") == 0) {
+               GapAgentPrivate *priv = user_data;
+               char *sender = (char *)g_dbus_method_invocation_get_sender(invocation);
+               GDBusProxy *device;
+               char *addr;
+               char *path;
+               GDBusConnection *conn;
+
+               if (sender == NULL)
+                       return;
+
+               g_variant_get(parameters, "(&o)", &path);
+               DBG("Request passkey : sender %s priv->busname %s Device Path :%s",
+                               sender, priv->busname, path);
+               /* Need to check
+                  if (g_strcmp0(sender, agent->busname) != 0)
+                  return;
+                */
+               if (!priv->cb.passkey_func)
+                       return;
+               conn = _bt_get_system_gconn();
+               if (conn == NULL)
+                       return;
+
+               device = g_dbus_proxy_new_sync(conn,
+                               G_DBUS_PROXY_FLAGS_NONE, NULL,
+                               BT_HAL_BLUEZ_NAME, path,
+                               BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
+
+               if (!device) {
+                       ERR("Fail to make device proxy");
+
+                       g_dbus_method_invocation_return_error(invocation,
+                                       GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
+                                       "No proxy for device");
+                       if (err) {
+                               ERR("Unable to create proxy: %s", err->message);
+                               g_clear_error(&err);
+                       }
+                       return;
+               }
+               priv->exec_type = GAP_AGENT_EXEC_PAIRING;
+               priv->reply_context = invocation;
+
+               addr = strstr(path, "dev_");
+               if (addr != NULL) {
+                       char *pos = NULL;
+                       addr += 4;
+                       g_strlcpy(priv->pairing_addr, addr, sizeof(priv->pairing_addr));
+
+                       while ((pos = strchr(priv->pairing_addr, '_')) != NULL) {
+                               *pos = ':';
+                       }
+               }
+               priv->cb.passkey_func(priv, device);
+               g_object_unref(device);
+               return;
+       } else if (g_strcmp0(method_name, "DisplayPasskey") == 0) {
+               GapAgentPrivate *priv = user_data;
+               char *sender = (char *)g_dbus_method_invocation_get_sender(invocation);
+               GDBusProxy *device;
+               guint passkey;
+               guint16 entered;
+               char *path;
+               GDBusConnection *conn;
+
+               if (sender == NULL)
+                       return;
+               g_variant_get(parameters, "(&ouq)", &path, &passkey, &entered);
+               DBG("Request passkey display :sender %s priv->busname %s"
+                               " Device Path :%s, Passkey: %d, Entered: %d",
+                               sender, priv->busname, path, passkey, entered);
+               /* Do not show popup for Key event while typing*/
+               if (entered)
+                       return;
+               /* Need to check
+                  if (g_strcmp0(sender, agent->busname) != 0)
+                  return;
+                */
+               if (!priv->cb.display_func)
+                       return;
+
+               conn = _bt_get_system_gconn();
+               if (conn == NULL)
+                       return;
+               device = g_dbus_proxy_new_sync(conn,
+                               G_DBUS_PROXY_FLAGS_NONE, NULL,
+                               BT_HAL_BLUEZ_NAME, path,
+                               BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
+               if (!device) {
+                       ERR("Fail to make device proxy");
+
+                       g_dbus_method_invocation_return_error(invocation,
+                                       GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
+                                       "No proxy for device");
+                       if (err) {
+                               ERR("Unable to create proxy: %s", err->message);
+                               g_clear_error(&err);
+                       }
+                       return;
+               }
+               g_dbus_method_invocation_return_value(invocation, NULL);
+               priv->cb.display_func(priv, device, passkey);
+               g_object_unref(device);
+               return;
+       } else if (g_strcmp0(method_name, "RequestConfirmation") == 0) {
+               GapAgentPrivate *priv = user_data;
+               char *sender = (char *)g_dbus_method_invocation_get_sender(invocation);
+               GDBusProxy *device;
+               guint passkey;
+               char *path;
+               char *addr;
+               GDBusConnection *conn;
+
+               if (sender == NULL)
+                       return;
+
+               g_variant_get(parameters, "(&ou)", &path, &passkey);
+               DBG("Request passkey confirmation, Device Path :%s, Passkey: %d",
+                               path, passkey);
+
+               DBG("Sender: [%s] priv->busname: [%s]", sender, priv->busname);
+               /* Need to check
+                  if (g_strcmp0(sender, agent->busname) != 0)
+                  return;
+                */
+               DBG("priv->cb.confirm_func [%p]", priv->cb.confirm_func);
+               if (!priv->cb.confirm_func)
+                       return;
+               conn = _bt_get_system_gconn();
+               if (conn == NULL)
+                       return;
+               device = g_dbus_proxy_new_sync(conn,
+                               G_DBUS_PROXY_FLAGS_NONE, NULL,
+                               BT_HAL_BLUEZ_NAME, path,
+                               BT_HAL_PROPERTIES_INTERFACE, NULL, &err);
+               if (!device) {
+                       ERR("Fail to make device proxy");
+                       g_dbus_method_invocation_return_error(invocation,
+                                       GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
+                                       "No proxy for device");
+                       if (err) {
+                               ERR("Unable to create proxy: %s", err->message);
+                               g_clear_error(&err);
+                       }
+                       return;
+               }
+               priv->exec_type = GAP_AGENT_EXEC_PAIRING;
+               priv->reply_context = invocation;
+               addr = strstr(path, "dev_");
+               if (addr != NULL) {
+                       char *pos = NULL;
+                       addr += 4;
+                       g_strlcpy(priv->pairing_addr, addr, sizeof(priv->pairing_addr));
+
+                       while ((pos = strchr(priv->pairing_addr, '_')) != NULL) {
+                               *pos = ':';
+                       }
+               }
+
+               DBG("Pairing address [%s]", priv->pairing_addr);
+               priv->cb.confirm_func(priv, device, passkey);
+               g_object_unref(device);
+               return;
+       } else if (g_strcmp0(method_name, "AuthorizeService") == 0) {
+               /* TODO */
+       } else if (g_strcmp0(method_name, "RequestAuthorization") == 0) {
+               g_dbus_method_invocation_return_value(invocation, NULL);
+       } else if (g_strcmp0(method_name, "ConfirmModeChange") == 0) {
+               g_dbus_method_invocation_return_value(invocation, NULL);
+       } else if (g_strcmp0(method_name, "Cancel") == 0) {
+               GapAgentPrivate *priv = user_data;
+               char *sender = (char *)g_dbus_method_invocation_get_sender(invocation);
+
+               if (sender == NULL)
+                       return;
+               DBG("Cancelled : agent %p sender %s", sender);
+               /* Need to check
+                  if (g_strcmp0(sender, agent->busname) != 0)
+                  return;
+                */
+               if (priv->cb.authorization_cancel_func &&
+                               priv->exec_type == GAP_AGENT_EXEC_AUTHORZATION) {
+                       priv->cb.authorization_cancel_func(priv,
+                                       priv->authorize_addr);
+                       memset(priv->authorize_addr, 0x00,
+                                       sizeof(priv->authorize_addr));
+               } else if (priv->cb.pairing_cancel_func &&
+                               priv->exec_type == GAP_AGENT_EXEC_PAIRING) {
+                       priv->cb.pairing_cancel_func(priv,
+                                       priv->pairing_addr);
+                       memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
+               }
+               if (priv->exec_type != GAP_AGENT_EXEC_CONFIRM_MODE &&
+                               priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
+                               priv->reply_context != NULL) {
+
+                       g_dbus_method_invocation_return_error(priv->reply_context,
+                                       GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
+                                       "Rejected by remote cancel");
+               }
+
+               /* Canceled flag is set when user cancels pairing request
+                * Since here bluez has cancelled pairing request, we set the flag to false
+                */
+               priv->canceled = FALSE;
+               priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
+               priv->reply_context = NULL;
+               return;
+       } else if (g_strcmp0(method_name, "Release") == 0) {
+               GapAgentPrivate *priv = user_data;
+               char *sender = (char *)g_dbus_method_invocation_get_sender(invocation);
+
+               if (sender == NULL)
+                       return;
+
+               DBG("Released : sender %s\n", sender);
+
+               /* Need to check
+               if (g_strcmp0(sender, agent->busname) != 0)
+                       return;
+                */
+
+               g_dbus_method_invocation_return_value(invocation, NULL);
+
+               if (priv) {
+                       priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
+                       priv->reply_context = NULL;
+
+                       memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
+                       memset(priv->authorize_addr, 0x00, sizeof(priv->authorize_addr));
+               }
+               return;
+       } else if (g_strcmp0(method_name, "GetDiscoverableTimeout") == 0) {
+               /* TODO */
+       } else if (g_strcmp0(method_name, "ReplyPinCode") == 0) {
+               GapAgentPrivate *priv = user_data;
+               const char *pin_code;
+               const guint accept;
+
+               g_variant_get(parameters, "(u&s)", &accept, &pin_code);
+               DBG("Accept: %d PinCode: %s", accept, pin_code);
+               gap_agent_reply_pin_code(priv, accept, pin_code, invocation);
+       } else if (g_strcmp0(method_name, "ReplyPasskey") == 0) {
+               GapAgentPrivate *priv = user_data;
+               const char *passkey;
+               const guint accept;
+
+               g_variant_get(parameters, "(u&s)", &accept, &passkey);
+               DBG("Accept: %d PinCode: %s", accept, passkey);
+               gap_agent_reply_passkey(priv, accept, passkey, invocation);
+       } else if (g_strcmp0(method_name, "ReplyConfirmation") == 0) {
+               GapAgentPrivate *priv = user_data;
+               const guint accept;
+
+               g_variant_get(parameters, "(u)", &accept);
+               DBG("Accept: %d", accept);
+               gap_agent_reply_confirmation(priv, accept, invocation);
+       } else if (g_strcmp0(method_name, "ReplyAuthorize") == 0) {
+               /* TODO */
+       }
+       DBG("-");
+}
+
+gboolean gap_agent_reply_confirmation(GapAgentPrivate *agent, const guint accept,
+                GDBusMethodInvocation *context)
+{
+
+       DBG("+");
+
+       GapAgentPrivate *priv = agent;
+
+       /* Fix : NULL_RETURNS */
+       if (priv == NULL)
+               return FALSE;
+
+       if (priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
+                       priv->reply_context != NULL) {
+               if (accept == GAP_AGENT_ACCEPT) {
+                       g_dbus_method_invocation_return_value(priv->reply_context, NULL);
+                       priv->canceled = FALSE;
+               } else {
+                       switch (accept) {
+                               case GAP_AGENT_CANCEL:
+                                       g_dbus_method_invocation_return_error(priv->reply_context,
+                                                       GAP_AGENT_ERROR, GAP_AGENT_ERROR_CANCEL,
+                                                       "CanceledbyUser");
+                                       priv->canceled = TRUE;
+                                       break;
+                               case GAP_AGENT_TIMEOUT:
+                               case GAP_AGENT_REJECT:
+                               default:
+                                       g_dbus_method_invocation_return_error(priv->reply_context,
+                                                       GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
+                                                       "Confirmation request rejected");
+                                       priv->canceled = FALSE;
+                                       break;
+                       }
+               }
+       }
+
+       priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
+       priv->reply_context = NULL;
+       memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
+
+       DBG("-");
+       return TRUE;
+}
+
+gboolean gap_agent_reply_pin_code(GapAgentPrivate *agent, const guint accept,
+                                                const char *pin_code,
+                                                GDBusMethodInvocation *context)
+{
+       DBG("+");
+       GapAgentPrivate *priv = agent;
+
+       /* Fix : NULL_RETURNS */
+       if (priv == NULL)
+               return FALSE;
+
+       if (priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
+                       priv->reply_context != NULL) {
+               if (accept == GAP_AGENT_ACCEPT) {
+                       g_dbus_method_invocation_return_value(priv->reply_context,
+                                       g_variant_new("(s)", pin_code));
+                       priv->canceled = FALSE;
+               } else {
+                       switch (accept) {
+                               case GAP_AGENT_CANCEL:
+                                       g_dbus_method_invocation_return_error(priv->reply_context,
+                                                       GAP_AGENT_ERROR, GAP_AGENT_ERROR_CANCEL,
+                                                       "CanceledbyUser");
+                                       priv->canceled = TRUE;
+                                       break;
+                               case GAP_AGENT_TIMEOUT:
+                               case GAP_AGENT_REJECT:
+                               default:
+                                       g_dbus_method_invocation_return_error(priv->reply_context,
+                                                       GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
+                                                       "Pairing request rejected");
+                                       priv->canceled = FALSE;
+                                       break;
+                       }
+               }
+       }
+       priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
+       priv->reply_context = NULL;
+       memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
+
+       DBG("-");
+       return TRUE;
+}
+
+gboolean gap_agent_reply_passkey(GapAgentPrivate *agent, const guint accept,
+                                                const char *passkey,
+                                                GDBusMethodInvocation *context)
+{
+       DBG("+");
+       GapAgentPrivate *priv = agent;
+
+       /* Fix : NULL_RETURNS */
+       if (priv == NULL)
+               return FALSE;
+
+       if (priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
+                       priv->reply_context != NULL) {
+               if (accept == GAP_AGENT_ACCEPT) {
+                       guint pass_key = atoi(passkey);
+                       g_dbus_method_invocation_return_value(priv->reply_context,
+                                       g_variant_new("(u)", pass_key));
+                       priv->canceled = FALSE;
+               } else {
+                       switch (accept) {
+                               case GAP_AGENT_CANCEL:
+                                       g_dbus_method_invocation_return_error(priv->reply_context,
+                                                       GAP_AGENT_ERROR, GAP_AGENT_ERROR_CANCEL,
+                                                       "CanceledbyUser");
+                                       priv->canceled = TRUE;
+                                       break;
+                               case GAP_AGENT_TIMEOUT:
+                               case GAP_AGENT_REJECT:
+                               default:
+                                       g_dbus_method_invocation_return_error(priv->reply_context,
+                                                       GAP_AGENT_ERROR, GAP_AGENT_ERROR_REJECT,
+                                                       "Passkey request rejected");
+                                       priv->canceled = FALSE;
+                                       break;
+                       }
+               }
+       }
+
+       priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
+       priv->reply_context = NULL;
+       memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
+
+       DBG("-");
+       return TRUE;
+}
similarity index 80%
rename from bt-oal/bluez_hal/src/bt-hal-gap-agent1.h
rename to bt-oal/bluez_hal/src/bt-hal-gap-agent.h
index 0ee2145..430c2df 100644 (file)
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef __BT_HAL_GAP_AGENT_1_H__
-#define _BT_HAL_GAP_AGENT_1_H__
+#ifndef __BT_HAL_GAP_AGENT_H__
+#define _BT_HAL_GAP_AGENT_H__
 
 #include <stdint.h>
 #include <glib.h>
@@ -99,4 +99,13 @@ gboolean _gap_agent_is_canceled(GapAgentPrivate *agent);
 
 void _gap_agent_set_canceled(GapAgentPrivate *agent, gboolean value);
 
-#endif //_BT_HAL_GAP_AGENT_1_H__
+gboolean gap_agent_reply_pin_code(GapAgentPrivate *agent, const guint accept,
+                                                const char *pin_code,
+                                                GDBusMethodInvocation *context);
+gboolean gap_agent_reply_passkey(GapAgentPrivate *agent, const guint accept,
+                                                const char *passkey,
+                                                GDBusMethodInvocation *context);
+gboolean gap_agent_reply_confirmation(GapAgentPrivate *agent, const guint accept,
+                GDBusMethodInvocation *context);
+
+#endif //_BT_HAL_GAP_AGENT_H__
diff --git a/bt-oal/bluez_hal/src/bt-hal-gap-agent.xml b/bt-oal/bluez_hal/src/bt-hal-gap-agent.xml
new file mode 100644 (file)
index 0000000..477b018
--- /dev/null
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node name="/">
+  <interface name="org.bluez.Agent1">
+    <method name="RequestPinCode">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="o" name="device"/>
+      <arg type="s" name="pincode" direction="out"/>
+    </method>
+
+    <method name="RequestPasskey">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="o" name="device"/>
+      <arg type="u" name="passkey" direction="out"/>
+    </method>
+
+    <method name="DisplayPasskey">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="o" name="device"/>
+      <arg type="u" name="passkey"/>
+      <arg type="q" name="entered"/>
+    </method>
+
+    <method name="RequestConfirmation">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="o" name="device"/>
+      <arg type="u" name="passkey"/>
+    </method>
+
+    <method name="RequestAuthorization">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="o" name="device"/>
+    </method>
+
+   <method name="AuthorizeService">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="o" name="device"/>
+      <arg type="s" name="uuid"/>
+    </method>
+
+   <method name="Cancel">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+    </method>
+
+    <method name="Release">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+    </method>
+
+    <method name="ReplyPinCode">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="u" name="accept"/>
+      <arg type="s" name="pincode"/>
+    </method>
+
+    <method name="ReplyPasskey">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="u" name="accept"/>
+      <arg type="s" name="passkey"/>
+    </method>
+
+    <method name="ReplyConfirmation">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="u" name="accept"/>
+    </method>
+
+    <method name="ReplyAuthorize">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="u" name="accept"/>
+    </method>
+
+    <method name="ConfirmModeChange">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="s" name="mode"/>
+    </method>
+
+    <method name="GetDiscoverableTimeout">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="u" name="timeout" direction="out"/>
+    </method>
+  </interface>
+</node>
diff --git a/bt-oal/bluez_hal/src/bt-hal-gap-agent1.c b/bt-oal/bluez_hal/src/bt-hal-gap-agent1.c
deleted file mode 100644 (file)
index 9c10eec..0000000
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * BLUETOOTH HAL
- *
- * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: Anupam Roy <anupam.r@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 <string.h>
-#include <vconf.h>
-#include <vconf-keys.h>
-
-#include  <bt-hal-gap-agent1.h>
-#include  <bt-hal-agent.h>
-#include  <bt-hal-internal.h>
-
-#include "bt-hal.h"
-#include "bt-hal-log.h"
-#include "bt-hal-msg.h"
-#include "bt-hal-utils.h"
-
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus.h>
-#include <glib.h>
-#include <gio/gio.h>
-#include <dlog.h>
-
-#include "bt-hal-adapter-dbus-handler.h"
-#include "bt-hal-dbus-common-utils.h"
-
-static GDBusConnection *connection = NULL;
-
-typedef enum {
-       GAP_AGENT_ERROR_REJECT,
-       GAP_AGENT_ERROR_CANCEL,
-       GAP_AGENT_ERROR_TIMEOUT,
-} GapAgentError;
-
-
-/* Forward declaration */
-static gboolean __gap_agent_unregister(GapAgentPrivate *agent);
-static GDBusNodeInfo *__bt_service_create_method_node_info
-(const gchar *introspection_data);
-static void __bt_gap_agent_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);
-void _gap_agent_set_canceled(GapAgentPrivate *agent, gboolean value);
-
-
-
-static gint gap_agent_id = -1;
-
-gboolean _gap_agent_register(GapAgentPrivate *agent)
-{
-       GapAgentPrivate *priv = agent;
-       GDBusProxy *agent_manager;
-       GError *error = NULL;
-       GVariant *reply;
-
-       if (!priv)
-               return FALSE;
-       if (!connection)
-               return FALSE;
-
-       if (priv->agent_manager == NULL) {
-               agent_manager = g_dbus_proxy_new_sync(connection,
-                               G_DBUS_PROXY_FLAGS_NONE, NULL,
-                               BT_HAL_BLUEZ_NAME, BT_HAL_BLUEZ_PATH,
-                               BT_HAL_AGENT_MANAGER_INTERFACE, NULL, &error);
-               if (!agent_manager) {
-                       if (error) {
-                               ERR("Unable to create proxy: %s", error->message);
-                               g_clear_error(&error);
-                       }
-                       return FALSE;
-               }
-       } else {
-               agent_manager = priv->agent_manager;
-       }
-
-       reply = g_dbus_proxy_call_sync(agent_manager, "RegisterAgent",
-#ifdef TIZEN_BT_IO_CAPA_NO_INPUT_OUTPUT
-                       g_variant_new("(os)", priv->path, "NoInputNoOutput"),
-#else
-                       g_variant_new("(os)", priv->path, "DisplayYesNo"),
-#endif
-                       G_DBUS_CALL_FLAGS_NONE, -1,
-                       NULL, &error);
-       if (reply == NULL) {
-               ERR("Agent registration failed");
-               if (error) {
-                       ERR("Agent registration failed: errCode[%x], message[%s]",
-                                       error->code, error->message);
-                       g_clear_error(&error);
-               }
-               g_object_unref(agent_manager);
-               priv->agent_manager = NULL;
-               return FALSE;
-       }
-       g_variant_unref(reply);
-       reply = NULL;
-
-       /* Set the defalut agent */
-       DBG("agent_manager[%p] priv->path[%s]", agent_manager, priv->path);
-       reply = g_dbus_proxy_call_sync(agent_manager, "RequestDefaultAgent",
-                       g_variant_new("(o)", priv->path),
-                       G_DBUS_CALL_FLAGS_NONE, -1,
-                       NULL, &error);
-       if (reply == NULL) {
-               ERR("Request Default Agent failed");
-               if (error) {
-                       ERR("Request Default Agent failed: errCode[%x], message[%s]",
-                                       error->code, error->message);
-                       g_clear_error(&error);
-               }
-               g_object_unref(agent_manager);
-               priv->agent_manager = NULL;
-               return FALSE;
-       }
-       g_variant_unref(reply);
-
-       priv->agent_manager = agent_manager;
-
-       return TRUE;
-}
-
-
-static const gchar gap_agent_bluez_introspection_xml[] =
-"<node name='/'>"
-"  <interface name='org.bluez.Agent1'>"
-"    <method name='RequestPinCode'>"
-"      <arg type='o' name='device' direction='in'/>"
-"      <arg type='s' name='pincode' direction='out'/>"
-"    </method>"
-"    <method name='RequestPasskey'>"
-"      <arg type='o' name='device' direction='in'/>"
-"      <arg type='u' name='passkey' direction='out'/>"
-"    </method>"
-"    <method name='DisplayPasskey'>"
-"      <arg type='o' name='device' direction='in'/>"
-"      <arg type='u' name='passkey' direction='in'/>"
-"      <arg type='q' name='entered' direction='in'/>"
-"    </method>"
-"    <method name='RequestConfirmation'>"
-"      <arg type='o' name='device' direction='in'/>"
-"      <arg type='u' name='passkey' direction='in'/>"
-"    </method>"
-"    <method name='RequestAuthorization'>"
-"      <arg type='o' name='device' direction='in'/>"
-"    </method>"
-"    <method name='AuthorizeService'>"
-"      <arg type='o' name='device' direction='in'/>"
-"      <arg type='s' name='uuid' direction='in'/>"
-"    </method>"
-"    <method name='Cancel'>"
-"    </method>"
-"    <method name='Release'>"
-"    </method>"
-"    <method name='ReplyPinCode'>"
-"      <arg type='u' name='accept' direction='in'/>"
-"      <arg type='s' name='pincode' direction='in'/>"
-"    </method>"
-"    <method name='ReplyPasskey'>"
-"      <arg type='u' name='accept' direction='in'/>"
-"      <arg type='s' name='passkey' direction='in'/>"
-"    </method>"
-"    <method name='ReplyConfirmation'>"
-"      <arg type='u' name='accept' direction='in'/>"
-"    </method>"
-"    <method name='ReplyAuthorize'>"
-"      <arg type='u' name='accept' direction='in'/>"
-"    </method>"
-"    <method name='ConfirmModeChange'>"
-"      <arg type='s' name='mode' direction='in'/>"
-"    </method>"
-"    <method name='GetDiscoverableTimeout'>"
-"      <arg type='u' name='timeout' direction='out'/>"
-"    </method>"
-"  </interface>"
-"</node>";
-
-
-static const GDBusInterfaceVTable method_table = {
-       __bt_gap_agent_method,
-       NULL,
-       NULL,
-};
-
-void _gap_agent_setup_dbus(GapAgentPrivate *agent, GAP_AGENT_FUNC_CB *func_cb,
-               const char *path,
-               GDBusProxy *adapter)
-{
-       GapAgentPrivate *priv = agent;
-       GDBusProxy *proxy;
-       GDBusNodeInfo *node_info;
-       GError *error = NULL;
-       DBG("+");
-
-       priv->path = g_strdup(path);
-
-       node_info = __bt_service_create_method_node_info(
-                       gap_agent_bluez_introspection_xml);
-       if (node_info == NULL)
-               return;
-
-       DBG("path is [%s]", path);
-
-       connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
-       if (!connection) {
-               if (error) {
-                       ERR("Unable to connect to gdbus: %s", error->message);
-                       g_clear_error(&error);
-               }
-               return;
-       }
-
-       if (gap_agent_id == -1) {
-               gap_agent_id = g_dbus_connection_register_object(connection, path,
-                               node_info->interfaces[0],
-                               &method_table, priv,
-                               NULL, &error);
-       }
-
-       g_dbus_node_info_unref(node_info);
-
-       if (gap_agent_id == 0) {
-               ERR("Failed to register for Path: %s", path);
-               if (error) {
-                       ERR("Failed to register: %s", error->message);
-                       g_clear_error(&error);
-               }
-               return;
-       }
-
-       memcpy(&priv->cb, func_cb, sizeof(GAP_AGENT_FUNC_CB));
-
-       priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION;
-       memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr));
-       memset(priv->authorize_addr, 0x00, sizeof(priv->authorize_addr));
-       priv->reply_context = NULL;
-
-       DBG("path: %s", path);
-
-       proxy =  g_dbus_proxy_new_sync(connection,
-                       G_DBUS_PROXY_FLAGS_NONE, NULL,
-                       BT_HAL_BLUEZ_NAME, path,
-                       BT_HAL_AGENT_INTERFACE, NULL, &error);
-
-       if (!proxy) {
-               ERR("Unable to create proxy");
-               if (error) {
-                       ERR("Error: %s", error->message);
-                       g_clear_error(&error);
-               }
-               priv->busname = NULL;
-       } else {
-               priv->busname = g_strdup(g_dbus_proxy_get_name(proxy));
-               g_object_unref(proxy);
-               DBG("Busname: %s", priv->busname);
-       }
-       DBG("-");
-}
-
-
-void _gap_agent_reset_dbus(GapAgentPrivate *agent)
-{
-       GapAgentPrivate *priv = agent;
-
-       /* Fix : NULL_RETURNS */
-       if (priv == NULL)
-               return ;
-
-       __gap_agent_unregister(agent);
-
-       if (gap_agent_id > 0) {
-
-               if (connection)
-                       g_dbus_connection_unregister_object(connection,
-                                       gap_agent_id);
-               gap_agent_id = -1;
-       }
-       /*TODO*/
-#if 0
-       if (priv->osp_servers) {
-               __gap_agent_remove_osp_servers(priv->osp_servers);
-               g_slist_free(priv->osp_servers);
-               priv->osp_servers = NULL;
-       }
-#endif
-       g_object_ref(priv->adapter);
-       priv->adapter = NULL;
-
-       g_free(priv->path);
-       priv->path = NULL;
-
-       g_free(priv->busname);
-       priv->busname = NULL;
-}
-
-gchar* _gap_agent_get_path(GapAgentPrivate *agent)
-{
-       GapAgentPrivate *priv = agent;
-
-       /* Fix : NULL_RETURNS */
-       if (priv == NULL)
-               return NULL;
-
-       return priv->path;
-}
-
-gboolean _gap_agent_is_canceled(GapAgentPrivate *agent)
-{
-       GapAgentPrivate *priv = agent;
-
-       /* Fix : NULL_RETURNS */
-       if (priv == NULL)
-               return  FALSE;
-
-       return priv->canceled;
-}
-
-void _gap_agent_set_canceled(GapAgentPrivate *agent, gboolean value)
-{
-       GapAgentPrivate *priv = agent;
-
-       /* Fix : NULL_RETURNS */
-       if (priv == NULL)
-               return;
-
-       priv->canceled = value;
-}
-
-static gboolean __gap_agent_unregister(GapAgentPrivate *agent)
-{
-       GapAgentPrivate *priv = agent;
-       GDBusProxy *agent_manager;
-       GError *error = NULL;
-       GVariant *reply;
-
-       if (priv == NULL || priv->path == NULL|| connection == NULL )
-               return  FALSE;
-
-       if (priv->agent_manager == NULL) {
-               agent_manager = g_dbus_proxy_new_sync(connection,
-                               G_DBUS_PROXY_FLAGS_NONE, NULL,
-                               BT_HAL_BLUEZ_NAME, BT_HAL_BLUEZ_PATH,
-                               BT_HAL_AGENT_MANAGER_INTERFACE, NULL, &error);
-               if (!agent_manager) {
-                       if (error) {
-                               ERR("Unable to create proxy: %s", error->message);
-                               g_clear_error(&error);
-                       }
-                       return FALSE;
-               }
-       } else {
-               agent_manager = priv->agent_manager;
-       }
-
-       reply = g_dbus_proxy_call_sync(agent_manager, "UnregisterAgent",
-                       g_variant_new("o", priv->path),
-                       G_DBUS_CALL_FLAGS_NONE, -1,
-                       NULL, &error);
-       g_object_unref(agent_manager);
-       priv->agent_manager = NULL;
-
-       if (reply == NULL) {
-               ERR("Agent unregistration failed");
-               if (error) {
-                       ERR("Agent unregistration failed: errCode[%x], message[%s]",
-                                       error->code, error->message);
-                       g_clear_error(&error);
-               }
-               return FALSE;
-       }
-       g_variant_unref(reply);
-
-       return TRUE;
-}
-
-       static GDBusNodeInfo *__bt_service_create_method_node_info
-(const gchar *introspection_data)
-{
-       GError *err = NULL;
-       GDBusNodeInfo *node_info = NULL;
-
-       if (introspection_data == NULL)
-               return NULL;
-
-       node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
-
-       if (err) {
-               ERR("Unable to create node: %s", err->message);
-               g_clear_error(&err);
-       }
-       return node_info;
-}
-
-static void __bt_gap_agent_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)
-{
-       DBG("+");
-       FN_START;
-
-       DBG("Method[%s] Object Path[%s] Interface Name[%s]",
-                       method_name, object_path, interface_name);
-       /* TODO Fill handlers */
-       if (g_strcmp0(method_name, "RequestPinCode") == 0) {
-       } else if (g_strcmp0(method_name, "RequestPasskey") == 0) {
-       } else if (g_strcmp0(method_name, "DisplayPasskey") == 0) {
-       } else if (g_strcmp0(method_name, "RequestConfirmation") == 0) {
-       } else if (g_strcmp0(method_name, "AuthorizeService") == 0) {
-       } else if (g_strcmp0(method_name, "RequestAuthorization") == 0) {
-       } else if (g_strcmp0(method_name, "ConfirmModeChange") == 0) {
-       } else if (g_strcmp0(method_name, "Cancel") == 0) {
-       } else if (g_strcmp0(method_name, "Release") == 0) {
-       } else if (g_strcmp0(method_name, "GetDiscoverableTimeout") == 0) {
-       } else if (g_strcmp0(method_name, "ReplyPinCode") == 0) {
-       } else if (g_strcmp0(method_name, "ReplyPasskey") == 0) {
-       } else if (g_strcmp0(method_name, "ReplyConfirmation") == 0) {
-       } else if (g_strcmp0(method_name, "ReplyAuthorize") == 0) {
-       }
-       DBG("-");
-}
index a9428b6..adfe68b 100644 (file)
@@ -179,6 +179,7 @@ export BT_INCLUDE_OAL=ENABLED
 %if %{bt_bluez_hal} == ENABLED
 export BT_INCLUDE_OAL_BLUEZ=ENABLED
 export CFLAGS="$CFLAGS -DTIZEN_BT_INCLUDE_OAL_BLUEZ"
+#export CFLAGS="$CFLAGS -DTIZEN_SYSPOPUP_SUPPORTED"
 %else
 export BT_INCLUDE_OAL_BLUEZ=DISABLED
 %endif