./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
)
#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;
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;
{
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
+}
#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);
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__
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)
{
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("+");
__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;
--- /dev/null
+/*
+ * 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;
+}
*
*/
-#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>
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__
--- /dev/null
+<?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>
+++ /dev/null
-/*
- * 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("-");
-}
%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