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>
24 #include <bundle_internal.h>
26 #include "bt-internal-types.h"
27 #include "bt-service-common.h"
28 #include "bt-service-agent.h"
29 #include "bt-service-gap-agent.h"
30 #include "bt-service-adapter.h"
31 #include "bt-service-event.h"
32 #include "bt-service-rfcomm-server.h"
33 #include "bt-service-device.h"
34 #include "bt-service-audio.h"
36 #ifdef TIZEN_FEATURE_BT_DPM
37 #include "bt-service-dpm.h"
40 #define BT_APP_AUTHENTICATION_TIMEOUT 35
41 #define BT_APP_AUTHORIZATION_TIMEOUT 15
43 #define HFP_AUDIO_GATEWAY_UUID "0000111f-0000-1000-8000-00805f9b34fb"
44 #define HSP_AUDIO_GATEWAY_UUID "00001112-0000-1000-8000-00805f9b34fb"
45 #define A2DP_UUID "0000110D-0000-1000-8000-00805F9B34FB"
46 #define AVRCP_TARGET_UUID "0000110c-0000-1000-8000-00805f9b34fb"
47 #define OPP_UUID "00001105-0000-1000-8000-00805f9b34fb"
48 #define FTP_UUID "00001106-0000-1000-8000-00805f9b34fb"
49 #define SPP_UUID "00001101-0000-1000-8000-00805f9b34fb"
50 #define PBAP_UUID "0000112f-0000-1000-8000-00805f9b34fb"
51 #define MAP_UUID "00001132-0000-1000-8000-00805f9b34fb"
52 #define NAP_UUID "00001116-0000-1000-8000-00805f9b34fb"
53 #define GN_UUID "00001117-0000-1000-8000-00805f9b34fb"
54 #define BNEP_UUID "0000000f-0000-1000-8000-00805f9b34fb"
55 #define HID_UUID "00001124-0000-1000-8000-00805f9b34fb"
56 #define HID_DEVICE_UUID "00001124-0000-1000-8000-00805f9b43bf"
57 #define SAP_UUID_OLD "a49eb41e-cb06-495c-9f4f-bb80a90cdf00"
58 #define SAP_UUID_NEW "a49eb41e-cb06-495c-9f4f-aa80a90cdf4a"
59 #define IOTIVITY_UUID "12341234-1C25-481F-9DFB-59193D238280"
61 #define BT_AGENT_OBJECT "/org/bluez/agent/frwk_agent"
63 #define BT_AGENT_INTERFACE "org.bluez.Agent1"
65 #define BT_AGENT_SIGNAL_RFCOMM_AUTHORIZE "RfcommAuthorize"
66 #define BT_AGENT_SIGNAL_OBEX_AUTHORIZE "ObexAuthorize"
68 #define BT_PASSKEY_MAX_LENGTH 4
70 #define BT_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS 200
71 #define BT_AGENT_SYSPOPUP_MAX_ATTEMPT 3
72 #define BT_PAN_MAX_CONNECTION 4
74 extern guint nap_connected_device_count;
76 static char *passkey_watcher;
78 #define G_VARIANT_UNREF(variant) \
79 g_variant_unref(variant); \
82 static int __bt_agent_is_auto_response(uint32_t dev_class, const gchar *address,
84 static gboolean __bt_agent_is_hid_keyboard(uint32_t dev_class);
85 static int __bt_agent_generate_passkey(char *passkey, int size);
87 static void __bt_agent_release_memory(void)
89 /* Release Malloc Memory*/
92 /* Release Stack Memory*/
96 static GVariant *__bt_service_getall(GDBusProxy *device, const char *interface)
101 reply = g_dbus_proxy_call_sync(device,
102 "GetAll", g_variant_new("(s)", interface),
103 G_DBUS_CALL_FLAGS_NONE, -1,
106 ERR("GetAll dBUS-RPC failed");
108 ERR("D-Bus API failure: errCode[%x], message[%s]",
109 error->code, error->message);
110 g_clear_error(&error);
118 static gboolean __pincode_request(GapAgentPrivate *agent, GDBusProxy *device)
120 uint32_t device_class;
121 gchar *address = NULL;
122 unsigned char auth_info[5] = {0, };
124 GVariant *reply = NULL;
125 GVariant *reply_temp = NULL;
127 char pin_code[BLUETOOTH_PIN_CODE_MAX_LENGTH + 1];
128 int ret = BLUETOOTH_ERROR_NONE;
129 #ifdef TIZEN_FEATURE_BT_DPM
130 int pairing_state = DPM_STATUS_ERROR;
135 #ifdef TIZEN_FEATURE_BT_DPM
136 _bt_dpm_get_bluetooth_pairing_state(&pairing_state);
137 if (pairing_state == DPM_RESTRICTED) {
138 BT_ERR("Not allow to pair the device");
139 gap_agent_reply_confirmation(agent, GAP_AGENT_REJECT, NULL);
140 __bt_agent_release_memory();
145 reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
147 if (reply_temp == NULL) {
148 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
153 g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
155 tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
156 g_variant_get(tmp_value, "u", &device_class);
157 G_VARIANT_UNREF(tmp_value);
159 tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
160 g_variant_get(tmp_value, "s", &address);
161 G_VARIANT_UNREF(tmp_value);
163 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
167 tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
168 g_variant_get(tmp_value, "s", &name);
169 G_VARIANT_UNREF(tmp_value);
171 BT_DBG("Replacing the name with address");
172 name = g_strdup(address);
174 BT_INFO("Name = %s, Address = %s, Class = 0x%x", name, address, device_class);
175 if (name[0] == '\0') {
177 BT_DBG("Name[0]=NULL, Replacing the name with address");
178 name = g_strdup(address);
182 __bt_get_auth_info(reply, (char *)auth_info);
183 if (_bt_is_device_creating() == TRUE &&
184 _bt_is_bonding_device_address(address) == TRUE &&
185 __bt_agent_is_auto_response(device_class, address, name)) {
186 BT_DBG("0000 Auto Pair");
187 /* Use Fixed PIN "0000" for basic pairing */
188 _bt_set_autopair_status_in_bonding_info(TRUE);
189 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT, "0000",
191 } else if (__bt_agent_is_hid_keyboard(device_class)) {
192 BT_DBG("HID Keyboard");
193 char str_passkey[BT_PASSKEY_MAX_LENGTH + 1] = { 0 };
195 if (__bt_agent_generate_passkey(str_passkey,
196 BT_PASSKEY_MAX_LENGTH) != 0) {
197 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT,
202 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT,
205 if (headed_plugin_info->plugin_headed_enabled) {
206 headed_plugin_info->headed_plugin->bt_launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST,
207 name, auth_info, str_passkey, NULL, _gap_agent_get_path(agent));
209 GVariant *param = NULL;
210 param = g_variant_new("(isss)", ret, address, name, str_passkey);
211 _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_KEYBOARD_PASSKEY_DISPLAY, param);
213 } else if (_bt_get_device_pin_code(address, pin_code)
214 == BLUETOOTH_ERROR_NONE) {
215 BT_DBG("Use stored PIN code(%s)", pin_code);
216 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT, pin_code,
220 if (headed_plugin_info->plugin_headed_enabled) {
221 BT_DBG("Show Pin entry");
222 headed_plugin_info->headed_plugin->bt_launch_system_popup(BT_AGENT_EVENT_PIN_REQUEST, name, auth_info,
223 NULL, NULL, _gap_agent_get_path(agent));
225 BT_INFO("Plugin Headed not Enabled");
226 GVariant *param = NULL;
227 param = g_variant_new("(iss)", ret, address, name);
228 _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_PIN_REQUEST, param);
233 g_variant_unref(reply);
234 g_variant_unref(reply_temp);
237 __bt_agent_release_memory();
243 static gboolean __passkey_request(GapAgentPrivate *agent, GDBusProxy *device)
245 gchar *address = NULL;
247 unsigned char auth_info[5] = {0, };
248 GVariant *reply = NULL;
249 GVariant *reply_temp = NULL;
251 int ret = BLUETOOTH_ERROR_NONE;
252 #ifdef TIZEN_FEATURE_BT_DPM
253 int pairing_state = DPM_STATUS_ERROR;
258 #ifdef TIZEN_FEATURE_BT_DPM
259 _bt_dpm_get_bluetooth_pairing_state(&pairing_state);
260 if (pairing_state == DPM_RESTRICTED) {
261 BT_ERR("Not allow to pair the device");
262 gap_agent_reply_confirmation(agent, GAP_AGENT_REJECT, NULL);
263 __bt_agent_release_memory();
268 reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
270 if (reply_temp == NULL) {
271 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
276 g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
278 tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
279 g_variant_get(tmp_value, "s", &address);
280 G_VARIANT_UNREF(tmp_value);
282 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
286 tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
287 g_variant_get(tmp_value, "s", &name);
288 G_VARIANT_UNREF(tmp_value);
290 name = g_strdup(address);
292 __bt_get_auth_info(reply, (char *)auth_info);
294 if (headed_plugin_info->plugin_headed_enabled) {
295 headed_plugin_info->headed_plugin->bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_REQUEST, name, auth_info,
296 NULL, NULL, _gap_agent_get_path(agent));
298 BT_INFO("Plugin Headed not Enabled");
299 GVariant *param = NULL;
300 param = g_variant_new("(iss)", ret, address, name);
301 _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_PASSKEY_REQUEST, param);
306 g_variant_unref(reply);
307 g_variant_unref(reply_temp);
310 __bt_agent_release_memory();
316 static gboolean __display_request(GapAgentPrivate *agent, GDBusProxy *device,
319 gchar *address = NULL;
321 unsigned char auth_info[5] = {0, };
323 GVariant *reply = NULL;
324 GVariant *reply_temp = NULL;
325 GVariant *tmp_value = NULL;
326 int ret = BLUETOOTH_ERROR_NONE;
330 reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
331 if (reply_temp == NULL) {
332 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
337 g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
339 tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
340 g_variant_get(tmp_value, "s", &address);
341 G_VARIANT_UNREF(tmp_value);
343 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
347 tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
348 g_variant_get(tmp_value, "s", &name);
349 G_VARIANT_UNREF(tmp_value);
351 name = g_strdup(address);
353 __bt_get_auth_info(reply, (char *)auth_info);
355 str_passkey = g_strdup_printf("%06d", passkey);
357 GVariant *param = NULL;
358 param = g_variant_new("(ss)", address, str_passkey);
360 if (passkey_watcher) {
361 BT_INFO("Send passkey to %s", passkey_watcher);
362 _bt_send_event_to_dest(passkey_watcher, BT_ADAPTER_EVENT,
363 BLUETOOTH_EVENT_PASSKEY_NOTIFICATION, param);
365 if (headed_plugin_info->plugin_headed_enabled) {
366 BT_INFO("Plugin Headed Enabled");
367 headed_plugin_info->headed_plugin->bt_launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST, name,
368 auth_info, str_passkey, NULL, _gap_agent_get_path(agent));
370 BT_INFO("Plugin Headed not Enabled");
371 GVariant *param = NULL;
372 param = g_variant_new("(isss)", ret, address, name, str_passkey);
373 _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_KEYBOARD_PASSKEY_DISPLAY, param);
380 g_variant_unref(reply);
381 g_variant_unref(reply_temp);
384 __bt_agent_release_memory();
390 static gboolean __confirm_request(GapAgentPrivate *agent, GDBusProxy *device,
393 gchar *address = NULL;
395 unsigned char auth_info[5] = {0, };
397 GVariant *reply_temp = NULL;
398 GVariant *reply = NULL;
400 int ret = BLUETOOTH_ERROR_NONE;
401 #ifdef TIZEN_FEATURE_BT_DPM
402 int pairing_state = DPM_STATUS_ERROR;
404 BT_DBG("+ passkey[%.6d]", passkey);
406 #ifdef TIZEN_FEATURE_BT_DPM
407 _bt_dpm_get_bluetooth_pairing_state(&pairing_state);
408 if (pairing_state == DPM_RESTRICTED) {
409 BT_ERR("Not allow to pair the device");
410 gap_agent_reply_confirmation(agent, GAP_AGENT_REJECT, NULL);
411 __bt_agent_release_memory();
416 snprintf(str_passkey, sizeof(str_passkey), "%.6d", passkey);
418 reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
420 if (reply_temp == NULL) {
421 BT_ERR("Device doesn't exist");
422 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
427 g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
429 tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
430 g_variant_get(tmp_value, "s", &address);
431 G_VARIANT_UNREF(tmp_value);
433 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
437 tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
438 g_variant_get(tmp_value, "s", &name);
439 G_VARIANT_UNREF(tmp_value);
441 name = g_strdup(address);
442 __bt_get_auth_info(reply, (char *)auth_info);
444 if (headed_plugin_info->plugin_headed_enabled) {
445 BT_DBG("LAUNCH SYSPOPUP");
446 headed_plugin_info->headed_plugin->bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name,
447 auth_info, str_passkey, NULL,
448 _gap_agent_get_path(agent));
450 BT_DBG("Headless Confirmation");
451 GVariant *param = NULL;
452 param = g_variant_new("(isss)", ret, address, name, str_passkey);
453 _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_PASSKEY_CONFIRM_REQUEST, param);
457 g_variant_unref(reply);
458 g_variant_unref(reply_temp);
461 __bt_agent_release_memory();
467 static gboolean __pairing_cancel_request(GapAgentPrivate *agent, const char *address)
469 BT_DBG("On Going Pairing is cancelled by remote\n");
471 if (headed_plugin_info->plugin_headed_enabled)
472 headed_plugin_info->headed_plugin->bt_destroy_popup_all();
474 __bt_agent_release_memory();
479 static gboolean __a2dp_authorize_request_check(void)
481 /* Check for existing Media device to disconnect */
482 return _bt_is_headset_type_connected(BT_AUDIO_A2DP, NULL);
485 static gboolean __bt_agent_is_hid_device_connectable(void)
487 GDBusProxy *proxy = NULL;
488 GVariant *reply = NULL;
490 gboolean connectable = FALSE;
492 proxy = _bt_gdbus_get_hid_agent_proxy();
493 retv_if(proxy == NULL, FALSE);
495 reply = g_dbus_proxy_call_sync(proxy, "IsHidConnectable", NULL,
496 G_DBUS_CALL_FLAGS_NONE, 2000, NULL, &err);
498 BT_ERR("Error returned in method call");
500 BT_ERR("Error message = %s", err->message);
505 g_variant_get(reply, "(b)", &connectable);
506 g_variant_unref(reply);
508 g_object_unref(proxy);
510 BT_INFO("HID Device is %s",
511 connectable ? "Connectable" : "Non-connectable");
516 static gboolean __authorize_request(GapAgentPrivate *agent, GDBusProxy *device,
519 gchar *address = NULL;
521 unsigned char auth_info[5] = {0, };
523 GVariant *reply = NULL;
524 GVariant *reply_temp = NULL;
526 int result = BLUETOOTH_ERROR_NONE;
527 int request_type = BT_AGENT_EVENT_AUTHORIZE_REQUEST;
531 /* Check if already Media connection exsist */
532 if (!strcasecmp(uuid, A2DP_UUID)) {
533 gboolean ret = FALSE;
535 ret = __a2dp_authorize_request_check();
538 BT_ERR("Already one A2DP device connected \n");
539 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT,
544 /* Check completed */
546 if (!strcasecmp(uuid, HID_UUID)) {
547 gboolean is_connectable = __bt_agent_is_hid_device_connectable();
548 BT_DBG("Automatically %s authorization for HID",
549 is_connectable ? "accept" : "reject");
550 if (is_connectable == TRUE)
551 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT, NULL);
553 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL);
557 if (!strcasecmp(uuid, HFP_AUDIO_GATEWAY_UUID) ||
558 !strcasecmp(uuid, HSP_AUDIO_GATEWAY_UUID) ||
559 !strcasecmp(uuid, HFP_HS_UUID) ||
560 !strcasecmp(uuid, HSP_HS_UUID) ||
561 !strcasecmp(uuid, A2DP_UUID) ||
562 !strcasecmp(uuid, HID_DEVICE_UUID) ||
563 !strcasecmp(uuid, SAP_UUID_OLD) ||
564 !strcasecmp(uuid, SAP_UUID_NEW) ||
565 !strcasecmp(uuid, IOTIVITY_UUID) ||
566 !strcasecmp(uuid, AVRCP_TARGET_UUID)) {
567 BT_DBG("Auto accept authorization for audio device (HFP, A2DP, AVRCP) [%s]", uuid);
568 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT,
574 if (!strcasecmp(uuid, NAP_UUID) ||
575 !strcasecmp(uuid, GN_UUID) ||
576 !strcasecmp(uuid, BNEP_UUID)) {
578 BT_DBG("Network connection request: %s", uuid);
579 if (TIZEN_FEATURE_NETWORK_TETHERING_ENABLE) {
580 if (nap_connected_device_count >=
581 BT_PAN_MAX_CONNECTION) {
582 BT_ERR("Max connection exceeded");
586 if (headed_plugin_info->plugin_headed_enabled) {
587 if (headed_plugin_info->headed_plugin->bt_is_tethering_enabled() == FALSE) {
588 BT_ERR("BT tethering is not enabled");
594 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT,
598 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT,
604 reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
605 if (reply_temp == NULL) {
606 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
611 g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
613 tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
614 g_variant_get(tmp_value, "s", &address);
615 G_VARIANT_UNREF(tmp_value);
617 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
621 tmp_value = g_variant_lookup_value(reply, "Alias", G_VARIANT_TYPE_STRING);
622 g_variant_get(tmp_value, "s", &name);
623 G_VARIANT_UNREF(tmp_value);
625 name = g_strdup(address);
627 tmp_value = g_variant_lookup_value(reply, "Trusted", G_VARIANT_TYPE_BOOLEAN);
628 g_variant_get(tmp_value, "b", &trust);
629 G_VARIANT_UNREF(tmp_value);
631 __bt_get_auth_info(reply, (char *)auth_info);
633 BT_INFO("Authorization request for device [%s] Service:[%s]\n", address, uuid);
635 if (strcasecmp(uuid, OPP_UUID) == 0 &&
636 _gap_agent_exist_osp_server(agent, BT_OBEX_SERVER,
638 _bt_send_event(BT_OPP_SERVER_EVENT,
639 BLUETOOTH_EVENT_OBEX_SERVER_CONNECTION_AUTHORIZE,
640 g_variant_new("(iss)", result, address, name));
644 /* TODO: MAP? see above */
646 if (_gap_agent_exist_osp_server(agent, BT_RFCOMM_SERVER,
647 (char *)uuid) == TRUE) {
648 bt_agent_osp_server_t *osp_serv;
649 osp_serv = _gap_agent_get_osp_server(agent,
650 BT_RFCOMM_SERVER, (char *)uuid);
653 _bt_send_event(BT_RFCOMM_SERVER_EVENT,
654 BLUETOOTH_EVENT_RFCOMM_AUTHORIZE,
655 g_variant_new("(issssn)", result, address, uuid,
656 name, osp_serv->path, osp_serv->fd));
662 if (!strcasecmp(uuid, OPP_UUID))
663 request_type = BT_AGENT_EVENT_EXCHANGE_REQUEST;
664 else if (!strcasecmp(uuid, PBAP_UUID))
665 request_type = BT_AGENT_EVENT_PBAP_REQUEST;
666 else if (!strcasecmp(uuid, MAP_UUID))
667 request_type = BT_AGENT_EVENT_MAP_REQUEST;
668 /* TODO: MAP is already here */
670 if (trust || !headed_plugin_info->plugin_headed_enabled) {
671 BT_INFO("Trusted or Headless device, so authorize\n");
672 gap_agent_reply_authorize(agent,
673 GAP_AGENT_ACCEPT, NULL);
678 if (headed_plugin_info->plugin_headed_enabled) {
679 headed_plugin_info->headed_plugin->bt_launch_system_popup(request_type, name, auth_info, NULL, NULL,
680 _gap_agent_get_path(agent));
685 g_variant_unref(reply);
688 g_variant_unref(reply_temp);
692 __bt_agent_release_memory();
698 static gboolean __authorization_cancel_request(GapAgentPrivate *agent,
701 BT_DBG("On Going Authorization is cancelled by remote\n");
703 gap_agent_reply_authorize(agent, GAP_AGENT_CANCEL, NULL);
705 if (headed_plugin_info->plugin_headed_enabled)
706 headed_plugin_info->headed_plugin->bt_destroy_popup_all();
708 __bt_agent_release_memory();
713 void _bt_destroy_agent(void *agent)
718 _gap_agent_reset_dbus((GapAgentPrivate *)agent);
723 void* _bt_create_agent(const char *path, gboolean adapter)
725 GAP_AGENT_FUNC_CB func_cb;
726 GDBusProxy *adapter_proxy;
727 GapAgentPrivate *agent;
729 adapter_proxy = _bt_get_adapter_proxy();
733 func_cb.pincode_func = __pincode_request;
734 func_cb.display_func = __display_request;
735 func_cb.passkey_func = __passkey_request;
736 func_cb.confirm_func = __confirm_request;
737 func_cb.authorize_func = __authorize_request;
738 func_cb.pairing_cancel_func = __pairing_cancel_request;
739 func_cb.authorization_cancel_func = __authorization_cancel_request;
742 agent = g_new0(GapAgentPrivate, 1);
744 _gap_agent_setup_dbus(agent, &func_cb, path, adapter_proxy);
747 if (!_gap_agent_register(agent)) {
748 _bt_destroy_agent(agent);
756 gboolean _bt_agent_register_osp_server(const gint type,
757 const char *uuid, char *path, int fd)
759 void *agent = _bt_get_adapter_agent();
763 return _gap_agent_register_osp_server(agent, type, uuid, path, fd);
767 gboolean _bt_agent_unregister_osp_server(const gint type, const char *uuid)
769 void *agent = _bt_get_adapter_agent();
774 return _gap_agent_unregister_osp_server(agent, type, uuid);
777 gboolean _bt_agent_reply_authorize(gboolean accept)
781 void *agent = _bt_get_adapter_agent();
785 accept_val = accept ? GAP_AGENT_ACCEPT : GAP_AGENT_REJECT;
787 return gap_agent_reply_authorize(agent, accept_val, NULL);
790 gboolean _bt_agent_is_canceled(void)
792 void *agent = _bt_get_adapter_agent();
796 return _gap_agent_is_canceled(agent);
799 void _bt_agent_set_canceled(gboolean value)
801 void *agent = _bt_get_adapter_agent();
805 return _gap_agent_set_canceled(agent, value);
808 int _bt_agent_reply_cancellation(void)
810 void *agent = _bt_get_adapter_agent();
813 return BLUETOOTH_ERROR_INTERNAL;
815 if (gap_agent_reply_confirmation(agent, GAP_AGENT_CANCEL, NULL) != TRUE) {
816 BT_ERR("Fail to reply agent");
817 return BLUETOOTH_ERROR_INTERNAL;
820 return BLUETOOTH_ERROR_NONE;
823 static gboolean __bt_agent_is_hid_keyboard(uint32_t dev_class)
825 switch ((dev_class & 0x1f00) >> 8) {
827 switch ((dev_class & 0xc0) >> 6) {
829 /* input-keyboard" */
838 static gboolean __bt_agent_find_device_by_address_exactname(char *buffer,
844 pch = strtok_r(buffer, "= ,", &last);
849 while ((pch = strtok_r(NULL, ",", &last))) {
850 if (0 == g_strcmp0(pch, address)) {
851 BT_DBG("Match found\n");
858 static gboolean __bt_agent_find_device_by_partial_name(char *buffer,
859 const char *partial_name)
864 pch = strtok_r(buffer, "= ,", &last);
869 while ((pch = strtok_r(NULL, ",", &last))) {
870 if (g_str_has_prefix(partial_name, pch)) {
871 BT_DBG("Match found\n");
878 static gboolean __bt_agent_is_device_blacklist(const char *address,
890 fp = fopen(BT_AGENT_AUTO_PAIR_BLACKLIST_FILE, "r");
893 BT_ERR("Unable to open blacklist file");
897 fseek(fp, 0, SEEK_END);
900 BT_DBG("size is not a positive number");
907 buffer = g_malloc0(sizeof(char) * size);
908 result = fread((char *)buffer, 1, size, fp);
910 if (result != size) {
911 BT_ERR("Read Error");
916 BT_DBG("Buffer = %s", buffer);
918 lines = g_strsplit_set(buffer, BT_AGENT_NEW_LINE, 0);
922 BT_ERR("No lines in the file");
926 for (i = 0; lines[i] != NULL; i++) {
927 if (g_str_has_prefix(lines[i], "AddressBlacklist"))
928 if (__bt_agent_find_device_by_address_exactname(
931 if (g_str_has_prefix(lines[i], "ExactNameBlacklist"))
932 if (__bt_agent_find_device_by_address_exactname(
935 if (g_str_has_prefix(lines[i], "PartialNameBlacklist"))
936 if (__bt_agent_find_device_by_partial_name(lines[i],
939 if (g_str_has_prefix(lines[i], "KeyboardAutoPair"))
940 if (__bt_agent_find_device_by_address_exactname(
948 BT_DBG("Found the device");
953 static gboolean __bt_agent_is_auto_response(uint32_t dev_class,
954 const gchar *address, const gchar *name)
956 gboolean is_headset = FALSE;
957 gboolean is_mouse = FALSE;
958 char lap_address[BT_LOWER_ADDRESS_LENGTH];
960 BT_DBG("bt_agent_is_headset_class, %d +", dev_class);
965 switch ((dev_class & 0x1f00) >> 8) {
967 switch ((dev_class & 0xfc) >> 2) {
978 case 0x0c: /* Video Camera */
979 case 0x0d: /* Camcorder */
982 /* Other audio device */
988 switch (dev_class & 0xff) {
989 case 0x80: /* 0x80: Pointing device(Mouse) */
993 case 0x40: /* 0x40: input device (BT keyboard) */
995 /* Get the LAP(Lower Address part) */
996 g_strlcpy(lap_address, address, sizeof(lap_address));
998 /* Need to Auto pair the blacklisted Keyboard */
999 if (__bt_agent_is_device_blacklist(lap_address, name) != TRUE) {
1000 BT_DBG("Device is not black listed\n");
1003 BT_ERR("Device is black listed\n");
1009 if ((!is_headset) && (!is_mouse))
1012 /* Get the LAP(Lower Address part) */
1013 g_strlcpy(lap_address, address, sizeof(lap_address));
1015 BT_DBG("Device address = %s\n", address);
1016 BT_DBG("Address 3 byte = %s\n", lap_address);
1018 if (__bt_agent_is_device_blacklist(lap_address, name)) {
1019 BT_ERR("Device is black listed\n");
1026 static int __bt_agent_generate_passkey(char *passkey, int size)
1031 unsigned int value = 0;
1033 if (passkey == NULL)
1039 random_fd = open("/dev/urandom", O_RDONLY);
1044 for (i = 0; i < size; i++) {
1045 len = read(random_fd, &value, sizeof(value));
1047 passkey[i] = '0' + (value % 10);
1052 BT_DBG("passkey: %s", passkey);
1057 int _bt_set_passkey_notification(const char *sender, gboolean enable)
1059 BT_INFO("Set passkey notification(sender:%s, %s)",
1060 sender, enable ? "Enable" : "Disable");
1062 g_free(passkey_watcher);
1064 passkey_watcher = g_strdup(sender);
1066 passkey_watcher = NULL;
1068 return BLUETOOTH_ERROR_NONE;