2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
22 #include <stacktrim.h>
23 #include <syspopup_caller.h>
25 #include <bundle_internal.h>
27 #ifdef TIZEN_FEATURE_NETWORK_TETHERING_ENABLE
28 #include <tethering.h>
31 #include "bt-internal-types.h"
32 #include "bt-service-common.h"
33 #include "bt-service-agent.h"
34 #include "bt-service-gap-agent.h"
35 #include "bt-service-adapter.h"
36 #include "bt-service-event.h"
37 #include "bt-service-rfcomm-server.h"
38 #include "bt-service-device.h"
39 #include "bt-service-audio.h"
41 #ifdef TIZEN_FEATURE_BT_DPM
42 #include "bt-service-dpm.h"
45 #define BT_APP_AUTHENTICATION_TIMEOUT 35
46 #define BT_APP_AUTHORIZATION_TIMEOUT 15
48 #define HFP_AUDIO_GATEWAY_UUID "0000111f-0000-1000-8000-00805f9b34fb"
49 #define HSP_AUDIO_GATEWAY_UUID "00001112-0000-1000-8000-00805f9b34fb"
50 #define A2DP_UUID "0000110D-0000-1000-8000-00805F9B34FB"
51 #define AVRCP_TARGET_UUID "0000110c-0000-1000-8000-00805f9b34fb"
52 #define OPP_UUID "00001105-0000-1000-8000-00805f9b34fb"
53 #define FTP_UUID "00001106-0000-1000-8000-00805f9b34fb"
54 #define SPP_UUID "00001101-0000-1000-8000-00805f9b34fb"
55 #define PBAP_UUID "0000112f-0000-1000-8000-00805f9b34fb"
56 #define MAP_UUID "00001132-0000-1000-8000-00805f9b34fb"
57 #define NAP_UUID "00001116-0000-1000-8000-00805f9b34fb"
58 #define GN_UUID "00001117-0000-1000-8000-00805f9b34fb"
59 #define BNEP_UUID "0000000f-0000-1000-8000-00805f9b34fb"
60 #define HID_UUID "00001124-0000-1000-8000-00805f9b34fb"
61 #define HID_DEVICE_UUID "00001124-0000-1000-8000-00805f9b43bf"
62 #define SAP_UUID_OLD "a49eb41e-cb06-495c-9f4f-bb80a90cdf00"
63 #define SAP_UUID_NEW "a49eb41e-cb06-495c-9f4f-aa80a90cdf4a"
64 #define IOTIVITY_UUID "12341234-1C25-481F-9DFB-59193D238280"
66 #define BT_AGENT_OBJECT "/org/bluez/agent/frwk_agent"
68 #define BT_AGENT_INTERFACE "org.bluez.Agent1"
70 #define BT_AGENT_SIGNAL_RFCOMM_AUTHORIZE "RfcommAuthorize"
71 #define BT_AGENT_SIGNAL_OBEX_AUTHORIZE "ObexAuthorize"
73 #define BT_PASSKEY_MAX_LENGTH 4
75 #define BT_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS 200
76 #define BT_AGENT_SYSPOPUP_MAX_ATTEMPT 3
77 #define BT_PAN_MAX_CONNECTION 4
79 extern guint nap_connected_device_count;
81 static char *passkey_watcher = NULL;
83 #define G_VARIANT_UNREF(variant) \
84 g_variant_unref(variant); \
87 static int __bt_agent_is_auto_response(uint32_t dev_class, const gchar *address,
89 static gboolean __bt_agent_is_hid_keyboard(uint32_t dev_class);
90 static int __bt_agent_generate_passkey(char *passkey, int size);
92 static void __bt_agent_release_memory(void)
94 /* Release Malloc Memory*/
97 /* Release Stack Memory*/
100 static gboolean __bt_agent_system_popup_timer_cb(gpointer user_data)
103 static int retry_count;
104 bundle *b = (bundle *)user_data;
105 retv_if(user_data == NULL, FALSE);
109 ret = syspopup_launch("bt-syspopup", b);
111 BT_ERR("Sorry! Can't launch popup, ret=%d, Re-try[%d] time..",
113 if (retry_count >= BT_AGENT_SYSPOPUP_MAX_ATTEMPT) {
114 BT_ERR("Sorry!! Max retry %d reached", retry_count);
120 BT_DBG("Hurray!! Finally Popup launched");
125 return (ret < 0) ? TRUE : FALSE;
128 int _bt_launch_system_popup(bt_agent_event_type_t event_type,
129 const char *device_name,
130 const unsigned char *auth_info,
132 const char *filename,
133 const char *agent_path)
137 char event_str[BT_MAX_EVENT_STR_LENGTH + 1];
141 BT_ERR("Launching system popup failed");
145 bundle_add(b, "device-name", device_name);
146 bundle_add(b, "auth-info", (const char *)auth_info);
147 bundle_add(b, "passkey", passkey);
148 bundle_add(b, "file", filename);
149 bundle_add(b, "agent-path", agent_path);
151 switch (event_type) {
152 case BT_AGENT_EVENT_PIN_REQUEST:
153 g_strlcpy(event_str, "pin-request", sizeof(event_str));
156 case BT_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST:
157 g_strlcpy(event_str, "passkey-confirm-request",
161 case BT_AGENT_EVENT_PASSKEY_REQUEST:
162 g_strlcpy(event_str, "passkey-request", sizeof(event_str));
165 case BT_AGENT_EVENT_PASSKEY_DISPLAY_REQUEST:
166 g_strlcpy(event_str, "passkey-display-request",
170 case BT_AGENT_EVENT_AUTHORIZE_REQUEST:
171 g_strlcpy(event_str, "authorize-request",
175 case BT_AGENT_EVENT_CONFIRM_MODE_REQUEST:
176 g_strlcpy(event_str, "confirm-mode-request",
180 case BT_AGENT_EVENT_FILE_RECEIVED:
181 g_strlcpy(event_str, "file-received", sizeof(event_str));
184 case BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST:
185 g_strlcpy(event_str, "keyboard-passkey-request",
189 case BT_AGENT_EVENT_TERMINATE:
190 g_strlcpy(event_str, "terminate", sizeof(event_str));
193 case BT_AGENT_EVENT_EXCHANGE_REQUEST:
194 g_strlcpy(event_str, "exchange-request", sizeof(event_str));
197 case BT_AGENT_EVENT_PBAP_REQUEST:
198 g_strlcpy(event_str, "phonebook-request", sizeof(event_str));
201 case BT_AGENT_EVENT_MAP_REQUEST:
202 g_strlcpy(event_str, "message-request", sizeof(event_str));
205 case BT_AGENT_EVENT_LEGACY_PAIR_FAILED_FROM_REMOTE:
206 g_strlcpy(event_str, "remote-legacy-pair-failed", sizeof(event_str));
210 BT_ERR("Invalid event type");
216 bundle_add(b, "event-type", event_str);
218 ret = syspopup_launch("bt-syspopup", b);
220 BT_ERR("Popup launch failed...retry %d", ret);
222 g_timeout_add(BT_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS,
223 (GSourceFunc)__bt_agent_system_popup_timer_cb, b);
228 BT_INFO("_bt_agent_launch_system_popup");
232 static GVariant *__bt_service_getall(GDBusProxy *device, const char *interface)
234 GError *error = NULL;
237 reply = g_dbus_proxy_call_sync(device,
238 "GetAll", g_variant_new("(s)", interface),
239 G_DBUS_CALL_FLAGS_NONE, -1,
242 ERR("GetAll dBUS-RPC failed");
244 ERR("D-Bus API failure: errCode[%x], message[%s]",
245 error->code, error->message);
246 g_clear_error(&error);
254 static gboolean __pincode_request(GapAgentPrivate *agent, GDBusProxy *device)
256 uint32_t device_class;
257 gchar *address = NULL;
258 unsigned char auth_info[5] = {0, };
260 GVariant *reply = NULL;
261 GVariant *reply_temp = NULL;
263 char pin_code[BLUETOOTH_PIN_CODE_MAX_LENGTH + 1];
264 #ifdef TIZEN_FEATURE_BT_DPM
265 int pairing_state = DPM_STATUS_ERROR;
270 #ifdef TIZEN_FEATURE_BT_DPM
271 _bt_dpm_get_bluetooth_pairing_state(&pairing_state);
272 if (pairing_state == DPM_RESTRICTED) {
273 BT_ERR("Not allow to pair the device");
274 gap_agent_reply_confirmation(agent, GAP_AGENT_REJECT, NULL);
275 __bt_agent_release_memory();
280 reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
282 if (reply_temp == NULL) {
283 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
288 g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
290 tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
291 g_variant_get(tmp_value, "u", &device_class);
292 G_VARIANT_UNREF(tmp_value);
294 tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
295 g_variant_get(tmp_value, "s", &address);
296 G_VARIANT_UNREF(tmp_value);
298 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
302 tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
303 g_variant_get(tmp_value, "s", &name);
304 G_VARIANT_UNREF(tmp_value);
306 BT_DBG("Replacing the name with address");
307 name = g_strdup(address);
309 BT_INFO("Name = %s, Address = %s, Class = 0x%x", name, address, device_class);
310 if (name[0] == '\0') {
312 BT_DBG("Name[0]=NULL, Replacing the name with address");
313 name = g_strdup(address);
317 __bt_get_auth_info(reply, (char *)auth_info);
318 if (_bt_is_device_creating() == TRUE &&
319 _bt_is_bonding_device_address(address) == TRUE &&
320 __bt_agent_is_auto_response(device_class, address, name)) {
321 BT_DBG("0000 Auto Pair");
322 /* Use Fixed PIN "0000" for basic pairing */
323 _bt_set_autopair_status_in_bonding_info(TRUE);
324 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT, "0000",
326 } else if (__bt_agent_is_hid_keyboard(device_class)) {
327 BT_DBG("HID Keyboard");
328 char str_passkey[BT_PASSKEY_MAX_LENGTH + 1] = { 0 };
330 if (__bt_agent_generate_passkey(str_passkey,
331 BT_PASSKEY_MAX_LENGTH) != 0) {
332 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT,
337 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT,
340 _bt_launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST,
341 name, auth_info, str_passkey, NULL,
342 _gap_agent_get_path(agent));
343 } else if (_bt_get_device_pin_code(address, pin_code)
344 == BLUETOOTH_ERROR_NONE) {
345 BT_DBG("Use stored PIN code(%s)", pin_code);
346 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT, pin_code,
350 BT_DBG("Show Pin entry");
351 _bt_launch_system_popup(BT_AGENT_EVENT_PIN_REQUEST, name, auth_info,
352 NULL, NULL, _gap_agent_get_path(agent));
356 g_variant_unref(reply);
357 g_variant_unref(reply_temp);
360 __bt_agent_release_memory();
366 static gboolean __passkey_request(GapAgentPrivate *agent, GDBusProxy *device)
368 gchar *address = NULL;
370 unsigned char auth_info[5] = {0, };
371 GVariant *reply = NULL;
372 GVariant *reply_temp = NULL;
374 #ifdef TIZEN_FEATURE_BT_DPM
375 int pairing_state = DPM_STATUS_ERROR;
380 #ifdef TIZEN_FEATURE_BT_DPM
381 _bt_dpm_get_bluetooth_pairing_state(&pairing_state);
382 if (pairing_state == DPM_RESTRICTED) {
383 BT_ERR("Not allow to pair the device");
384 gap_agent_reply_confirmation(agent, GAP_AGENT_REJECT, NULL);
385 __bt_agent_release_memory();
390 reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
392 if (reply_temp == NULL) {
393 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
398 g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
400 tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
401 g_variant_get(tmp_value, "s", &address);
402 G_VARIANT_UNREF(tmp_value);
404 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
408 tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
409 g_variant_get(tmp_value, "s", &name);
410 G_VARIANT_UNREF(tmp_value);
412 name = g_strdup(address);
414 __bt_get_auth_info(reply, (char *)auth_info);
416 _bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_REQUEST, name, auth_info,
417 NULL, NULL, _gap_agent_get_path(agent));
420 g_variant_unref(reply);
421 g_variant_unref(reply_temp);
424 __bt_agent_release_memory();
430 static gboolean __display_request(GapAgentPrivate *agent, GDBusProxy *device,
433 gchar *address = NULL;
435 unsigned char auth_info[5] = {0, };
437 GVariant *reply = NULL;
438 GVariant *reply_temp = NULL;
439 GVariant *tmp_value = NULL;
443 reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
444 if (reply_temp == NULL) {
445 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
450 g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
452 tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
453 g_variant_get(tmp_value, "s", &address);
454 G_VARIANT_UNREF(tmp_value);
456 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
460 tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
461 g_variant_get(tmp_value, "s", &name);
462 G_VARIANT_UNREF(tmp_value);
464 name = g_strdup(address);
466 __bt_get_auth_info(reply, (char *)auth_info);
468 str_passkey = g_strdup_printf("%06d", passkey);
470 if (passkey_watcher) {
471 GVariant *param = NULL;
473 BT_INFO("Send passkey to %s", passkey_watcher);
475 param = g_variant_new("(ss)", address, str_passkey);
477 _bt_send_event_to_dest(passkey_watcher, BT_ADAPTER_EVENT,
478 BLUETOOTH_EVENT_PASSKEY_NOTIFICATION, param);
480 _bt_launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST, name,
481 auth_info, str_passkey, NULL,
482 _gap_agent_get_path(agent));
488 g_variant_unref(reply);
489 g_variant_unref(reply_temp);
492 __bt_agent_release_memory();
498 static gboolean __confirm_request(GapAgentPrivate *agent, GDBusProxy *device,
501 gchar *address = NULL;
503 unsigned char auth_info[5] = {0, };
505 GVariant *reply_temp = NULL;
506 GVariant *reply = NULL;
508 #ifdef TIZEN_FEATURE_BT_DPM
509 int pairing_state = DPM_STATUS_ERROR;
511 BT_DBG("+ passkey[%.6d]", passkey);
513 #ifdef TIZEN_FEATURE_BT_DPM
514 _bt_dpm_get_bluetooth_pairing_state(&pairing_state);
515 if (pairing_state == DPM_RESTRICTED) {
516 BT_ERR("Not allow to pair the device");
517 gap_agent_reply_confirmation(agent, GAP_AGENT_REJECT, NULL);
518 __bt_agent_release_memory();
523 snprintf(str_passkey, sizeof(str_passkey), "%.6d", passkey);
525 reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
527 if (reply_temp == NULL) {
528 BT_ERR("Device doesn't exist");
529 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
534 g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
536 tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
537 g_variant_get(tmp_value, "s", &address);
538 G_VARIANT_UNREF(tmp_value);
540 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
544 tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
545 g_variant_get(tmp_value, "s", &name);
546 G_VARIANT_UNREF(tmp_value);
548 name = g_strdup(address);
549 __bt_get_auth_info(reply, (char *)auth_info);
551 BT_DBG("LAUNCH SYSPOPUP");
552 _bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name,
553 auth_info, str_passkey, NULL,
554 _gap_agent_get_path(agent));
557 g_variant_unref(reply);
558 g_variant_unref(reply_temp);
561 __bt_agent_release_memory();
567 static gboolean __pairing_cancel_request(GapAgentPrivate *agent, const char *address)
569 BT_DBG("On Going Pairing is cancelled by remote\n");
571 syspopup_destroy_all();
573 __bt_agent_release_memory();
578 static gboolean __a2dp_authorize_request_check(void)
580 /* Check for existing Media device to disconnect */
581 return _bt_is_headset_type_connected(BT_AUDIO_A2DP, NULL);
584 static gboolean __authorize_request(GapAgentPrivate *agent, GDBusProxy *device,
587 gchar *address = NULL;
589 unsigned char auth_info[5] = {0, };
591 GVariant *reply = NULL;
592 GVariant *reply_temp = NULL;
594 #ifdef TIZEN_FEATURE_NETWORK_TETHERING_ENABLE
596 tethering_h tethering = NULL;
598 int result = BLUETOOTH_ERROR_NONE;
599 int request_type = BT_AGENT_EVENT_AUTHORIZE_REQUEST;
603 /* Check if already Media connection exsist */
604 if (!strcasecmp(uuid, A2DP_UUID)) {
605 gboolean ret = FALSE;
607 ret = __a2dp_authorize_request_check();
610 BT_ERR("Already one A2DP device connected \n");
611 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT,
616 /* Check completed */
618 if (!strcasecmp(uuid, HFP_AUDIO_GATEWAY_UUID) ||
619 !strcasecmp(uuid, HSP_AUDIO_GATEWAY_UUID) ||
620 !strcasecmp(uuid, HFP_HS_UUID) ||
621 !strcasecmp(uuid, HSP_HS_UUID) ||
622 !strcasecmp(uuid, A2DP_UUID) ||
623 !strcasecmp(uuid, HID_UUID) ||
624 !strcasecmp(uuid, HID_DEVICE_UUID) ||
625 !strcasecmp(uuid, SAP_UUID_OLD) ||
626 !strcasecmp(uuid, SAP_UUID_NEW) ||
627 !strcasecmp(uuid, IOTIVITY_UUID) ||
628 !strcasecmp(uuid, AVRCP_TARGET_UUID)) {
629 BT_DBG("Auto accept authorization for audio device (HFP, A2DP, AVRCP) [%s]", uuid);
630 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT,
636 if (!strcasecmp(uuid, NAP_UUID) ||
637 !strcasecmp(uuid, GN_UUID) ||
638 !strcasecmp(uuid, BNEP_UUID)) {
640 BT_DBG("Network connection request: %s", uuid);
641 #ifdef TIZEN_FEATURE_NETWORK_TETHERING_ENABLE
642 if (nap_connected_device_count >=
643 BT_PAN_MAX_CONNECTION) {
644 BT_ERR("Max connection exceeded");
648 ret = tethering_create(&tethering);
650 if (ret != TETHERING_ERROR_NONE) {
651 BT_ERR("Fail to create tethering: %d", ret);
655 enabled = tethering_is_enabled(tethering, TETHERING_TYPE_BT);
657 ret = tethering_destroy(tethering);
659 if (ret != TETHERING_ERROR_NONE)
660 BT_ERR("Fail to create tethering: %d", ret);
662 if (enabled != true) {
663 BT_ERR("BT tethering is not enabled");
668 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT,
671 #ifdef TIZEN_FEATURE_NETWORK_TETHERING_ENABLE
673 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT,
680 reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
681 if (reply_temp == NULL) {
682 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
687 g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
689 tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
690 g_variant_get(tmp_value, "s", &address);
691 G_VARIANT_UNREF(tmp_value);
693 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
697 tmp_value = g_variant_lookup_value(reply, "Alias", G_VARIANT_TYPE_STRING);
698 g_variant_get(tmp_value, "s", &name);
699 G_VARIANT_UNREF(tmp_value);
701 name = g_strdup(address);
703 tmp_value = g_variant_lookup_value(reply, "Trusted", G_VARIANT_TYPE_BOOLEAN);
704 g_variant_get(tmp_value, "b", &trust);
705 G_VARIANT_UNREF(tmp_value);
707 __bt_get_auth_info(reply, (char *)auth_info);
709 BT_INFO("Authorization request for device [%s] Service:[%s]\n", address, uuid);
711 if (strcasecmp(uuid, OPP_UUID) == 0 &&
712 _gap_agent_exist_osp_server(agent, BT_OBEX_SERVER,
714 _bt_send_event(BT_OPP_SERVER_EVENT,
715 BLUETOOTH_EVENT_OBEX_SERVER_CONNECTION_AUTHORIZE,
716 g_variant_new("(iss)", result, address, name));
720 /* TODO: MAP? see above */
722 if (_gap_agent_exist_osp_server(agent, BT_RFCOMM_SERVER,
723 (char *)uuid) == TRUE) {
724 bt_agent_osp_server_t *osp_serv;
725 osp_serv = _gap_agent_get_osp_server(agent,
726 BT_RFCOMM_SERVER, (char *)uuid);
729 _bt_send_event(BT_RFCOMM_SERVER_EVENT,
730 BLUETOOTH_EVENT_RFCOMM_AUTHORIZE,
731 g_variant_new("(issssn)", result, address, uuid,
732 name, osp_serv->path, osp_serv->fd));
738 if (!strcasecmp(uuid, OPP_UUID))
739 request_type = BT_AGENT_EVENT_EXCHANGE_REQUEST;
740 else if (!strcasecmp(uuid, PBAP_UUID))
741 request_type = BT_AGENT_EVENT_PBAP_REQUEST;
742 else if (!strcasecmp(uuid, MAP_UUID))
743 request_type = BT_AGENT_EVENT_MAP_REQUEST;
744 /* TODO: MAP is already here */
747 BT_INFO("Trusted device, so authorize\n");
748 gap_agent_reply_authorize(agent,
749 GAP_AGENT_ACCEPT, NULL);
751 _bt_launch_system_popup(request_type, name, auth_info, NULL, NULL,
752 _gap_agent_get_path(agent));
757 g_variant_unref(reply);
760 g_variant_unref(reply_temp);
764 __bt_agent_release_memory();
770 static gboolean __authorization_cancel_request(GapAgentPrivate *agent,
773 BT_DBG("On Going Authorization is cancelled by remote\n");
775 gap_agent_reply_authorize(agent, GAP_AGENT_CANCEL, NULL);
777 syspopup_destroy_all();
779 __bt_agent_release_memory();
784 void _bt_destroy_agent(void *agent)
789 _gap_agent_reset_dbus((GapAgentPrivate *)agent);
794 void* _bt_create_agent(const char *path, gboolean adapter)
796 GAP_AGENT_FUNC_CB func_cb;
797 GDBusProxy *adapter_proxy;
798 GapAgentPrivate *agent;
800 adapter_proxy = _bt_get_adapter_proxy();
804 func_cb.pincode_func = __pincode_request;
805 func_cb.display_func = __display_request;
806 func_cb.passkey_func = __passkey_request;
807 func_cb.confirm_func = __confirm_request;
808 func_cb.authorize_func = __authorize_request;
809 func_cb.pairing_cancel_func = __pairing_cancel_request;
810 func_cb.authorization_cancel_func = __authorization_cancel_request;
813 agent = g_new0(GapAgentPrivate, 1);
815 _gap_agent_setup_dbus(agent, &func_cb, path, adapter_proxy);
818 if (!_gap_agent_register(agent)) {
819 _bt_destroy_agent(agent);
827 gboolean _bt_agent_register_osp_server(const gint type,
828 const char *uuid, char *path, int fd)
830 void *agent = _bt_get_adapter_agent();
834 return _gap_agent_register_osp_server(agent, type, uuid, path, fd);
838 gboolean _bt_agent_unregister_osp_server(const gint type, const char *uuid)
840 void *agent = _bt_get_adapter_agent();
845 return _gap_agent_unregister_osp_server(agent, type, uuid);
848 gboolean _bt_agent_reply_authorize(gboolean accept)
852 void *agent = _bt_get_adapter_agent();
856 accept_val = accept ? GAP_AGENT_ACCEPT : GAP_AGENT_REJECT;
858 return gap_agent_reply_authorize(agent, accept_val, NULL);
861 gboolean _bt_agent_is_canceled(void)
863 void *agent = _bt_get_adapter_agent();
867 return _gap_agent_is_canceled(agent);
870 void _bt_agent_set_canceled(gboolean value)
872 void *agent = _bt_get_adapter_agent();
876 return _gap_agent_set_canceled(agent, value);
879 int _bt_agent_reply_cancellation(void)
881 void *agent = _bt_get_adapter_agent();
884 return BLUETOOTH_ERROR_INTERNAL;
886 if (gap_agent_reply_confirmation(agent, GAP_AGENT_CANCEL, NULL) != TRUE) {
887 BT_ERR("Fail to reply agent");
888 return BLUETOOTH_ERROR_INTERNAL;
891 return BLUETOOTH_ERROR_NONE;
894 static gboolean __bt_agent_is_hid_keyboard(uint32_t dev_class)
896 switch ((dev_class & 0x1f00) >> 8) {
898 switch ((dev_class & 0xc0) >> 6) {
900 /* input-keyboard" */
909 static gboolean __bt_agent_find_device_by_address_exactname(char *buffer,
915 pch = strtok_r(buffer, "= ,", &last);
920 while ((pch = strtok_r(NULL, ",", &last))) {
921 if (0 == g_strcmp0(pch, address)) {
922 BT_DBG("Match found\n");
929 static gboolean __bt_agent_find_device_by_partial_name(char *buffer,
930 const char *partial_name)
935 pch = strtok_r(buffer, "= ,", &last);
940 while ((pch = strtok_r(NULL, ",", &last))) {
941 if (g_str_has_prefix(partial_name, pch)) {
942 BT_DBG("Match found\n");
949 static gboolean __bt_agent_is_device_blacklist(const char *address,
961 fp = fopen(BT_AGENT_AUTO_PAIR_BLACKLIST_FILE, "r");
964 BT_ERR("Unable to open blacklist file");
968 fseek(fp, 0, SEEK_END);
971 BT_DBG("size is not a positive number");
978 buffer = g_malloc0(sizeof(char) * size);
979 result = fread((char *)buffer, 1, size, fp);
981 if (result != size) {
982 BT_ERR("Read Error");
987 BT_DBG("Buffer = %s", buffer);
989 lines = g_strsplit_set(buffer, BT_AGENT_NEW_LINE, 0);
993 BT_ERR("No lines in the file");
997 for (i = 0; lines[i] != NULL; i++) {
998 if (g_str_has_prefix(lines[i], "AddressBlacklist"))
999 if (__bt_agent_find_device_by_address_exactname(
1002 if (g_str_has_prefix(lines[i], "ExactNameBlacklist"))
1003 if (__bt_agent_find_device_by_address_exactname(
1006 if (g_str_has_prefix(lines[i], "PartialNameBlacklist"))
1007 if (__bt_agent_find_device_by_partial_name(lines[i],
1010 if (g_str_has_prefix(lines[i], "KeyboardAutoPair"))
1011 if (__bt_agent_find_device_by_address_exactname(
1019 BT_DBG("Found the device");
1024 static gboolean __bt_agent_is_auto_response(uint32_t dev_class,
1025 const gchar *address, const gchar *name)
1027 gboolean is_headset = FALSE;
1028 gboolean is_mouse = FALSE;
1029 char lap_address[BT_LOWER_ADDRESS_LENGTH];
1031 BT_DBG("bt_agent_is_headset_class, %d +", dev_class);
1033 if (address == NULL)
1036 switch ((dev_class & 0x1f00) >> 8) {
1038 switch ((dev_class & 0xfc) >> 2) {
1048 case 0x0b: /* VCR */
1049 case 0x0c: /* Video Camera */
1050 case 0x0d: /* Camcorder */
1053 /* Other audio device */
1059 switch (dev_class & 0xff) {
1060 case 0x80: /* 0x80: Pointing device(Mouse) */
1064 case 0x40: /* 0x40: input device (BT keyboard) */
1066 /* Get the LAP(Lower Address part) */
1067 g_strlcpy(lap_address, address, sizeof(lap_address));
1069 /* Need to Auto pair the blacklisted Keyboard */
1070 if (__bt_agent_is_device_blacklist(lap_address, name) != TRUE) {
1071 BT_DBG("Device is not black listed\n");
1074 BT_ERR("Device is black listed\n");
1080 if ((!is_headset) && (!is_mouse))
1083 /* Get the LAP(Lower Address part) */
1084 g_strlcpy(lap_address, address, sizeof(lap_address));
1086 BT_DBG("Device address = %s\n", address);
1087 BT_DBG("Address 3 byte = %s\n", lap_address);
1089 if (__bt_agent_is_device_blacklist(lap_address, name)) {
1090 BT_ERR("Device is black listed\n");
1097 static int __bt_agent_generate_passkey(char *passkey, int size)
1102 unsigned int value = 0;
1104 if (passkey == NULL)
1110 random_fd = open("/dev/urandom", O_RDONLY);
1115 for (i = 0; i < size; i++) {
1116 len = read(random_fd, &value, sizeof(value));
1118 passkey[i] = '0' + (value % 10);
1123 BT_DBG("passkey: %s", passkey);
1128 int _bt_set_passkey_notification(const char *sender, gboolean enable)
1130 BT_INFO("Set passkey notification(sender:%s, %s)",
1131 sender, enable ? "Enable" : "Disable");
1133 g_free(passkey_watcher);
1135 passkey_watcher = g_strdup(sender);
1137 passkey_watcher = NULL;
1139 return BLUETOOTH_ERROR_NONE;