From f8cd843634b70ab96c83bd552606c197fcf5decc Mon Sep 17 00:00:00 2001 From: "h.sandeep" Date: Wed, 18 Feb 2015 10:54:16 +0530 Subject: [PATCH] Code Sync [Tizen3.0]: Merged the tizen_2.4 Spin code to tizen.org Spin code from project: framework/connectivity/bluetooth-frwk branch: tizen_2.4 change-id: Ibbe6db4cccd67a127bbb5b2f6596220d07a18072 1. Merged the tizen_2.4 Spin code to tizen branch 2. Fixed the build errors 3. Package dependencies are commented under ENABLE_TIZEN_2_4 macro Change-Id: I44ff6a65151b11a82c0f48e5efe0b63cd96e9bad Signed-off-by: h.sandeep --- AUTHORS | 2 +- CMakeLists.txt | 11 +- LICENSE | 204 ++ bluetooth-frwk-core.manifest | 24 + bluetooth-frwk-test.manifest | 13 + bluetooth-frwk.manifest | 47 + bluetooth_log_dump.sh | 19 + bt-api/CMakeLists.txt | 36 +- bt-api/TFX79AA.tmp | 0 bt-api/TFXF5A4.tmp | 1201 ++++++++ bt-api/bluetooth-api.pc.in | 2 +- bt-api/bt-adapter-le.c | 486 ++++ bt-api/bt-adapter.c | 208 +- bt-api/bt-audio.c | 770 +++++- bt-api/bt-avrcp.c | 247 +- bt-api/bt-common.c | 1176 +++++++- bt-api/bt-device.c | 193 +- bt-api/bt-event-handler.c | 2168 +++++++++------ bt-api/bt-gatt-client.c | 1466 ++++++++++ bt-api/bt-gatt-service.c | 1619 +++++++++++ bt-api/bt-gatt.xml | 0 bt-api/bt-hdp.c | 205 +- bt-api/bt-hid.c | 34 +- bt-api/bt-mdm.c | 354 +++ bt-api/bt-network.c | 67 +- bt-api/bt-obex-server.c | 14 +- bt-api/bt-oob.c | 10 +- bt-api/bt-opp-client.c | 32 +- bt-api/bt-pbap.c | 244 ++ bt-api/bt-request-sender.c | 405 ++- bt-api/bt-request-service.xml | 0 bt-api/bt-rfcomm-client.c | 748 ++++- bt-api/bt-rfcomm-server.c | 490 +++- bt-api/bt-scmst.c | 51 + bt-api/bt-service-api.pc.in | 2 +- bt-api/bt-telephony.c | 1596 +++++++---- bt-api/bt-telephony.xml | 24 +- bt-api/include/bt-common.h | 152 +- bt-api/include/bt-event-handler.h | 22 +- bt-api/include/bt-mdm.h | 70 + bt-api/include/bt-request-sender.h | 26 +- bt-api/marshal.list | 0 bt-core/CMakeLists.txt | 17 +- bt-core/bluetooth-frwk-core | 9 + bt-core/bt-core-adapter.c | 796 ++++++ bt-core/bt-core-adapter.xml | 27 + bt-core/bt-core-dbus-handler.c | 463 ++++ bt-core/bt-core-main.c | 201 ++ bt-core/bt-core-noti-handler.c | 326 +++ bt-core/bt-request-service.xml | 21 + bt-core/include/bt-core-adapter.h | 82 + bt-core/include/bt-core-common.h | 101 + bt-core/include/bt-core-dbus-handler.h | 80 + bt-core/include/bt-core-main.h | 41 + bt-core/include/bt-core-noti-handler.h | 45 + bt-core/org.projectx.bt_core.service | 0 bt-service/CMakeLists.txt | 77 +- bt-service/auto-pair-blacklist | 3 +- bt-service/bluetooth-frwk-service | 9 + bt-service/bt-request-handler.c | 985 ++++++- bt-service/bt-request-service.xml | 0 bt-service/bt-service-adapter-le.c | 766 +++++ bt-service/bt-service-adapter.c | 1616 ++++++++--- bt-service/bt-service-agent.c | 522 +++- bt-service/bt-service-audio.c | 778 ++++-- bt-service/bt-service-avrcp.c | 1458 ++++++---- bt-service/bt-service-common.c | 359 ++- bt-service/bt-service-device.c | 1150 +++++--- bt-service/bt-service-event-receiver.c | 2925 +++++++++++++------- bt-service/bt-service-event-sender.c | 293 +- bt-service/bt-service-gap-agent.c | 162 +- bt-service/bt-service-gap-agent.xml | 9 +- bt-service/bt-service-gap-agent1.xml | 81 + bt-service/bt-service-headset-connection.c | 267 ++ bt-service/bt-service-hid.c | 84 +- bt-service/bt-service-main.c | 165 +- bt-service/bt-service-mdm.c | 650 +++++ bt-service/bt-service-media-agent.xml | 6 + bt-service/bt-service-network.c | 173 +- bt-service/bt-service-obex-agent.c | 38 +- bt-service/bt-service-obex-agent.xml | 16 +- bt-service/bt-service-obex-server.c | 186 +- bt-service/bt-service-oob.c | 12 +- bt-service/bt-service-opp-client.c | 501 +++- bt-service/bt-service-pbap.c | 1321 +++++++++ bt-service/bt-service-rfcomm-client.c | 50 +- bt-service/bt-service-rfcomm-server.c | 92 +- bt-service/bt-service-util.c | 11 +- bt-service/include/bt-request-handler.h | 11 +- bt-service/include/bt-service-adapter-le.h | 74 + bt-service/include/bt-service-adapter.h | 88 +- bt-service/include/bt-service-agent.h | 29 +- bt-service/include/bt-service-audio.h | 52 +- bt-service/include/bt-service-avrcp.h | 25 +- bt-service/include/bt-service-common.h | 178 +- bt-service/include/bt-service-device.h | 32 +- bt-service/include/bt-service-event.h | 19 +- bt-service/include/bt-service-gap-agent.h | 22 +- bt-service/include/bt-service-headset-connection.h | 39 + bt-service/include/bt-service-hid.h | 11 +- bt-service/include/bt-service-main.h | 13 +- bt-service/include/bt-service-mdm.h | 69 + bt-service/include/bt-service-network.h | 18 +- bt-service/include/bt-service-obex-agent.h | 15 +- bt-service/include/bt-service-obex-server.h | 19 +- bt-service/include/bt-service-oob.h | 11 +- bt-service/include/bt-service-opp-client.h | 34 +- bt-service/include/bt-service-pbap.h | 63 + bt-service/include/bt-service-rfcomm-client.h | 10 +- bt-service/include/bt-service-rfcomm-server.h | 14 +- bt-service/include/bt-service-util.h | 11 +- bt-service/include/stacktrim.h | 10 +- bt-service/marshal.list | 0 bt-service/mobile/stack_info | 10 + bt-service/org.projectx.bt.service | 5 + bt-service/wearable/stack_info | 7 + include/bluetooth-api.h | 1694 +++++++++++- include/bluetooth-audio-api.h | 63 +- include/bluetooth-hid-api.h | 10 +- include/bluetooth-media-control.h | 205 +- include/bluetooth-scmst-api.h | 30 + include/bluetooth-telephony-api.h | 33 +- include/bt-internal-types.h | 162 +- packaging/bluetooth-frwk-mobile.service | 13 + packaging/bluetooth-frwk-wearable.service | 13 + packaging/bluetooth-frwk.manifest | 0 packaging/bluetooth-frwk.spec | 175 +- test/CMakeLists.txt | 2 + test/bluetooth-frwk-test.c | 255 +- test/gatt-test/CMakeLists.txt | 0 test/gatt-test/TFXF4E2.tmp | 0 test/gatt-test/bluetooth-gatt-test.c | 4 +- test/handsfree/CMakeLists.txt | 32 + test/handsfree/bluetooth-hf-test.c | 540 ++++ test/le-adv/CMakeLists.txt | 33 + test/le-adv/bluetooth-advertising-test.c | 393 +++ test/media-control/CMakeLists.txt | 0 test/media-control/bluetooth-media-control-test.c | 11 +- test/telephony/CMakeLists.txt | 0 test/telephony/bluetooth-telephony-test.c | 50 +- 140 files changed, 30701 insertions(+), 5318 deletions(-) mode change 100644 => 100755 AUTHORS mode change 100644 => 100755 CMakeLists.txt create mode 100755 LICENSE create mode 100755 bluetooth-frwk-core.manifest create mode 100755 bluetooth-frwk-test.manifest create mode 100755 bluetooth-frwk.manifest create mode 100755 bluetooth_log_dump.sh mode change 100644 => 100755 bt-api/CMakeLists.txt create mode 100755 bt-api/TFX79AA.tmp create mode 100755 bt-api/TFXF5A4.tmp mode change 100644 => 100755 bt-api/bluetooth-api.pc.in create mode 100755 bt-api/bt-adapter-le.c mode change 100644 => 100755 bt-api/bt-adapter.c mode change 100644 => 100755 bt-api/bt-audio.c mode change 100644 => 100755 bt-api/bt-avrcp.c mode change 100644 => 100755 bt-api/bt-common.c mode change 100644 => 100755 bt-api/bt-device.c mode change 100644 => 100755 bt-api/bt-event-handler.c create mode 100755 bt-api/bt-gatt-client.c create mode 100755 bt-api/bt-gatt-service.c mode change 100644 => 100755 bt-api/bt-gatt.xml mode change 100644 => 100755 bt-api/bt-hdp.c mode change 100644 => 100755 bt-api/bt-hid.c create mode 100755 bt-api/bt-mdm.c mode change 100644 => 100755 bt-api/bt-network.c mode change 100644 => 100755 bt-api/bt-obex-server.c mode change 100644 => 100755 bt-api/bt-oob.c mode change 100644 => 100755 bt-api/bt-opp-client.c create mode 100755 bt-api/bt-pbap.c mode change 100644 => 100755 bt-api/bt-request-sender.c mode change 100644 => 100755 bt-api/bt-request-service.xml mode change 100644 => 100755 bt-api/bt-rfcomm-client.c mode change 100644 => 100755 bt-api/bt-rfcomm-server.c create mode 100755 bt-api/bt-scmst.c mode change 100644 => 100755 bt-api/bt-service-api.pc.in mode change 100644 => 100755 bt-api/bt-telephony.c mode change 100644 => 100755 bt-api/bt-telephony.xml mode change 100644 => 100755 bt-api/include/bt-common.h mode change 100644 => 100755 bt-api/include/bt-event-handler.h create mode 100755 bt-api/include/bt-mdm.h mode change 100644 => 100755 bt-api/include/bt-request-sender.h mode change 100644 => 100755 bt-api/marshal.list mode change 100644 => 100755 bt-core/CMakeLists.txt create mode 100755 bt-core/bluetooth-frwk-core create mode 100755 bt-core/bt-core-adapter.c create mode 100755 bt-core/bt-core-adapter.xml create mode 100755 bt-core/bt-core-dbus-handler.c create mode 100755 bt-core/bt-core-main.c create mode 100755 bt-core/bt-core-noti-handler.c create mode 100755 bt-core/bt-request-service.xml create mode 100755 bt-core/include/bt-core-adapter.h create mode 100755 bt-core/include/bt-core-common.h create mode 100755 bt-core/include/bt-core-dbus-handler.h create mode 100755 bt-core/include/bt-core-main.h create mode 100755 bt-core/include/bt-core-noti-handler.h mode change 100644 => 100755 bt-core/org.projectx.bt_core.service mode change 100644 => 100755 bt-service/CMakeLists.txt mode change 100644 => 100755 bt-service/auto-pair-blacklist create mode 100755 bt-service/bluetooth-frwk-service mode change 100644 => 100755 bt-service/bt-request-handler.c mode change 100644 => 100755 bt-service/bt-request-service.xml create mode 100755 bt-service/bt-service-adapter-le.c mode change 100644 => 100755 bt-service/bt-service-adapter.c mode change 100644 => 100755 bt-service/bt-service-agent.c mode change 100644 => 100755 bt-service/bt-service-audio.c mode change 100644 => 100755 bt-service/bt-service-avrcp.c mode change 100644 => 100755 bt-service/bt-service-common.c mode change 100644 => 100755 bt-service/bt-service-device.c mode change 100644 => 100755 bt-service/bt-service-event-receiver.c mode change 100644 => 100755 bt-service/bt-service-event-sender.c mode change 100644 => 100755 bt-service/bt-service-gap-agent.c mode change 100644 => 100755 bt-service/bt-service-gap-agent.xml create mode 100755 bt-service/bt-service-gap-agent1.xml create mode 100755 bt-service/bt-service-headset-connection.c mode change 100644 => 100755 bt-service/bt-service-hid.c mode change 100644 => 100755 bt-service/bt-service-main.c create mode 100755 bt-service/bt-service-mdm.c mode change 100644 => 100755 bt-service/bt-service-media-agent.xml mode change 100644 => 100755 bt-service/bt-service-network.c mode change 100644 => 100755 bt-service/bt-service-obex-agent.c mode change 100644 => 100755 bt-service/bt-service-obex-agent.xml mode change 100644 => 100755 bt-service/bt-service-obex-server.c mode change 100644 => 100755 bt-service/bt-service-oob.c mode change 100644 => 100755 bt-service/bt-service-opp-client.c create mode 100755 bt-service/bt-service-pbap.c mode change 100644 => 100755 bt-service/bt-service-rfcomm-client.c mode change 100644 => 100755 bt-service/bt-service-rfcomm-server.c mode change 100644 => 100755 bt-service/bt-service-util.c mode change 100644 => 100755 bt-service/include/bt-request-handler.h create mode 100755 bt-service/include/bt-service-adapter-le.h mode change 100644 => 100755 bt-service/include/bt-service-adapter.h mode change 100644 => 100755 bt-service/include/bt-service-agent.h mode change 100644 => 100755 bt-service/include/bt-service-audio.h mode change 100644 => 100755 bt-service/include/bt-service-avrcp.h mode change 100644 => 100755 bt-service/include/bt-service-common.h mode change 100644 => 100755 bt-service/include/bt-service-device.h mode change 100644 => 100755 bt-service/include/bt-service-event.h mode change 100644 => 100755 bt-service/include/bt-service-gap-agent.h create mode 100755 bt-service/include/bt-service-headset-connection.h mode change 100644 => 100755 bt-service/include/bt-service-hid.h mode change 100644 => 100755 bt-service/include/bt-service-main.h create mode 100755 bt-service/include/bt-service-mdm.h mode change 100644 => 100755 bt-service/include/bt-service-network.h mode change 100644 => 100755 bt-service/include/bt-service-obex-agent.h mode change 100644 => 100755 bt-service/include/bt-service-obex-server.h mode change 100644 => 100755 bt-service/include/bt-service-oob.h mode change 100644 => 100755 bt-service/include/bt-service-opp-client.h create mode 100755 bt-service/include/bt-service-pbap.h mode change 100644 => 100755 bt-service/include/bt-service-rfcomm-client.h mode change 100644 => 100755 bt-service/include/bt-service-rfcomm-server.h mode change 100644 => 100755 bt-service/include/bt-service-util.h mode change 100644 => 100755 bt-service/include/stacktrim.h mode change 100644 => 100755 bt-service/marshal.list create mode 100755 bt-service/mobile/stack_info create mode 100755 bt-service/org.projectx.bt.service create mode 100755 bt-service/wearable/stack_info mode change 100644 => 100755 include/bluetooth-api.h mode change 100644 => 100755 include/bluetooth-audio-api.h mode change 100644 => 100755 include/bluetooth-hid-api.h mode change 100644 => 100755 include/bluetooth-media-control.h create mode 100755 include/bluetooth-scmst-api.h mode change 100644 => 100755 include/bluetooth-telephony-api.h mode change 100644 => 100755 include/bt-internal-types.h create mode 100755 packaging/bluetooth-frwk-mobile.service create mode 100755 packaging/bluetooth-frwk-wearable.service mode change 100644 => 100755 packaging/bluetooth-frwk.manifest mode change 100644 => 100755 packaging/bluetooth-frwk.spec mode change 100644 => 100755 test/CMakeLists.txt mode change 100644 => 100755 test/bluetooth-frwk-test.c mode change 100644 => 100755 test/gatt-test/CMakeLists.txt create mode 100755 test/gatt-test/TFXF4E2.tmp mode change 100644 => 100755 test/gatt-test/bluetooth-gatt-test.c create mode 100755 test/handsfree/CMakeLists.txt create mode 100755 test/handsfree/bluetooth-hf-test.c create mode 100755 test/le-adv/CMakeLists.txt create mode 100755 test/le-adv/bluetooth-advertising-test.c mode change 100644 => 100755 test/media-control/CMakeLists.txt mode change 100644 => 100755 test/media-control/bluetooth-media-control-test.c mode change 100644 => 100755 test/telephony/CMakeLists.txt mode change 100644 => 100755 test/telephony/bluetooth-telephony-test.c diff --git a/AUTHORS b/AUTHORS old mode 100644 new mode 100755 index 46d1687..b00a70d --- a/AUTHORS +++ b/AUTHORS @@ -1,2 +1,2 @@ -Jinmin Jung +Taesoo Jun DoHyun Pyun diff --git a/CMakeLists.txt b/CMakeLists.txt old mode 100644 new mode 100755 index 9a47572..9bca208 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,13 +1,4 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -OPTION(LIBNOTIFY_SUPPORT "Enable libnotify for popup" Off) -IF(LIBNOTIFY_SUPPORT) - ADD_DEFINITIONS("-DLIBNOTIFY_SUPPORT") -ENDIF(LIBNOTIFY_SUPPORT) - -OPTION(LIBNOTIFICATION_SUPPORT "Use Tizen notification system" Off) -IF(LIBNOTIFICATION_SUPPORT) - ADD_DEFINITIONS("-DLIBNOTIFICATION_SUPPORT") -ENDIF(LIBNOTIFICATION_SUPPORT) ADD_SUBDIRECTORY(bt-api) @@ -15,4 +6,4 @@ ADD_SUBDIRECTORY(bt-service) ADD_SUBDIRECTORY(bt-core) -#ADD_SUBDIRECTORY(test) +ADD_SUBDIRECTORY(test) diff --git a/LICENSE b/LICENSE new file mode 100755 index 0000000..a06208b --- /dev/null +++ b/LICENSE @@ -0,0 +1,204 @@ +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + diff --git a/bluetooth-frwk-core.manifest b/bluetooth-frwk-core.manifest new file mode 100755 index 0000000..e3bf17e --- /dev/null +++ b/bluetooth-frwk-core.manifest @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bluetooth-frwk-test.manifest b/bluetooth-frwk-test.manifest new file mode 100755 index 0000000..5f737de --- /dev/null +++ b/bluetooth-frwk-test.manifest @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/bluetooth-frwk.manifest b/bluetooth-frwk.manifest new file mode 100755 index 0000000..c82d314 --- /dev/null +++ b/bluetooth-frwk.manifest @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bluetooth_log_dump.sh b/bluetooth_log_dump.sh new file mode 100755 index 0000000..073e407 --- /dev/null +++ b/bluetooth_log_dump.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +#-------------------------------------- +# bluetooth +#-------------------------------------- + +BLUETOOTH_DEBUG=${1}/bluetooth +PREV_PWD=${PWD} +BT_DATA_DIR=/var/lib/bluetooth + +mkdir -p ${BLUETOOTH_DEBUG} + +if [ -e ${BT_DATA_DIR} ] +then + cd ${BT_DATA_DIR} + /bin/tar -cvzf ${BLUETOOTH_DEBUG}/bt_log.tar.gz * +fi + +cd ${PREV_PWD} diff --git a/bt-api/CMakeLists.txt b/bt-api/CMakeLists.txt old mode 100644 new mode 100755 index 5dcb855..92c9a9f --- a/bt-api/CMakeLists.txt +++ b/bt-api/CMakeLists.txt @@ -4,6 +4,7 @@ PROJECT(bt-service-api C) SET(SRCS bt-common.c bt-adapter.c +bt-adapter-le.c bt-device.c bt-hid.c bt-network.c @@ -11,7 +12,6 @@ bt-audio.c bt-oob.c bt-hdp.c bt-avrcp.c -bt-gatt.c bt-telephony.c bt-opp-client.c bt-obex-server.c @@ -19,14 +19,18 @@ bt-rfcomm-client.c bt-rfcomm-server.c bt-request-sender.c bt-event-handler.c -) +bt-scmst.c +bt-gatt-service.c +bt-pbap.c +bt-gatt-client.c) SET(HEADERS bluetooth-api.h bluetooth-hid-api.h bluetooth-audio-api.h bluetooth-telephony-api.h -bluetooth-media-control.h) +bluetooth-media-control.h +bluetooth-scmst-api.h) SET(PREFIX ${CMAKE_INSTALL_PREFIX}) SET(EXEC_PREFIX "\${prefix}") @@ -41,13 +45,21 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include) INCLUDE(FindPkgConfig) -IF(LIBNOTIFY_SUPPORT OR LIBNOTIFICATION_SUPPORT) -pkg_check_modules(packages REQUIRED dlog dbus-glib-1 gobject-2.0 gmodule-2.0 vconf -libxml-2.0) -ELSE(LIBNOTIFY_SUPPORT OR LIBNOTIFICATION_SUPPORT) -pkg_check_modules(packages REQUIRED dlog dbus-glib-1 gobject-2.0 gmodule-2.0 vconf - libxml-2.0 syspopup-caller) -ENDIF(LIBNOTIFY_SUPPORT OR LIBNOTIFICATION_SUPPORT) +SET(PKG_MODULES + dlog + dbus-glib-1 + gobject-2.0 + gmodule-2.0 + vconf + libxml-2.0 + security-server + glib-2.0 + gio-2.0 + gio-unix-2.0 +) + +INCLUDE(FindPkgConfig) +pkg_check_modules(packages REQUIRED ${PKG_MODULES}) FOREACH(flag ${packages_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") @@ -79,8 +91,8 @@ SET_TARGET_PROPERTIES(bluetooth-api PROPERTIES SOVERSION ${VERSION_MAJOR}) SET_TARGET_PROPERTIES(bluetooth-api PROPERTIES VERSION ${VERSION}) TARGET_LINK_LIBRARIES(bluetooth-api ${packages_LDFLAGS}) CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/bluetooth-api.pc.in ${CMAKE_CURRENT_BINARY_DIR}/bluetooth-api.pc @ONLY) -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/bluetooth-api.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) -INSTALL(TARGETS bluetooth-api DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/bluetooth-api.pc DESTINATION lib/pkgconfig) +INSTALL(TARGETS bluetooth-api DESTINATION lib COMPONENT RuntimeLibraries) FOREACH(hfile ${HEADERS}) INSTALL(FILES ${CMAKE_SOURCE_DIR}/include/${hfile} DESTINATION include/bt-service) diff --git a/bt-api/TFX79AA.tmp b/bt-api/TFX79AA.tmp new file mode 100755 index 0000000..e69de29 diff --git a/bt-api/TFXF5A4.tmp b/bt-api/TFXF5A4.tmp new file mode 100755 index 0000000..738f6b0 --- /dev/null +++ b/bt-api/TFXF5A4.tmp @@ -0,0 +1,1201 @@ +/* + * Bluetooth-frwk low energy + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * 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 +#include +#include +#include + +#include "bluetooth-api.h" +#include "bt-common.h" +#include "bt-internal-types.h" + + +#define BLUEZ_CHAR_INTERFACE "org.bluez.Characteristic" + +#define GATT_OBJECT_PATH "/org/bluez/gatt_attrib" + +typedef struct { + GObject parent; +} BluetoothGattService; + +typedef struct { + GObjectClass parent; +} BluetoothGattServiceClass; + +typedef struct { + char *char_uuid; + char **handle; +} char_pty_req_t; + +GType bluetooth_gatt_service_get_type(void); + +#define BLUETOOTH_GATT_TYPE_SERVICE (bluetooth_gatt_service_get_type()) + +#define BLUETOOTH_GATT_SERVICE(object) \ + (G_TYPE_CHECK_INSTANCE_CAST((object), \ + BLUETOOTH_GATT_TYPE_SERVICE, BluetoothGattService)) + +#define BLUETOOTH_GATT_SERVICE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), \ + BLUETOOTH_GATT_TYPE_SERVICE, BluetoothGattServiceClass)) + +#define BLUETOOTH_GATT_IS_SERVICE(object) \ + (G_TYPE_CHECK_INSTANCE_TYPE((object), BLUETOOTH_GATT_TYPE_SERVICE)) + +#define BLUETOOTH_GATT_IS_SERVICE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), BLUETOOTH_GATT_TYPE_SERVICE)) + +#define BLUETOOTH_GATT_SERVICE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), \ + BLUETOOTH_GATT_TYPE_SERVICE, BluetoothGattServiceClass)) + +G_DEFINE_TYPE(BluetoothGattService, bluetooth_gatt_service, G_TYPE_OBJECT) + +static gboolean bluetooth_gatt_value_changed(BluetoothGattService *agent, + gchar *obj_path, + GArray *byte_array, + DBusGMethodInvocation *context); + +#include "bt-gatt-glue.h" + +static void bluetooth_gatt_service_init(BluetoothGattService *obj) +{ + g_assert(obj != NULL); +} + +static void bluetooth_gatt_service_finalize(GObject *obj) +{ + G_OBJECT_CLASS(bluetooth_gatt_service_parent_class)->finalize(obj); +} + +static void bluetooth_gatt_service_class_init(BluetoothGattServiceClass *klass) +{ + GObjectClass *object_class = (GObjectClass *)klass; + + g_assert(klass != NULL); + + object_class->finalize = bluetooth_gatt_service_finalize; + + dbus_g_object_type_install_info(BLUETOOTH_GATT_TYPE_SERVICE, + &dbus_glib_bluetooth_gatt_object_info); +} + +static gboolean bluetooth_gatt_value_changed(BluetoothGattService *agent, + gchar *obj_path, + GArray *byte_array, + DBusGMethodInvocation *context) +{ + bt_gatt_char_value_t char_val; + bt_user_info_t *user_info; + BT_DBG("+"); + + char_val.char_handle = obj_path; + char_val.char_value = &g_array_index(byte_array, guint8, 0); + char_val.val_len = byte_array->len; + BT_DBG("Byte array length = %d", char_val.val_len); + + user_info = _bt_get_user_data(BT_COMMON); + + if (user_info->cb) { + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_CHAR_VAL_CHANGED, + BLUETOOTH_ERROR_NONE, &char_val, + user_info->cb, user_info->user_data); + } + + BT_DBG("-"); + + return TRUE; +} + +static void __add_value_changed_method(DBusGConnection *conn) +{ + static gboolean method_added = FALSE; + BluetoothGattService *bluetooth_gatt_obj = NULL; + + if (method_added) { + BT_ERR("Method already added. \n"); + return; + } + + method_added = TRUE; + + bluetooth_gatt_obj = g_object_new(BLUETOOTH_GATT_TYPE_SERVICE, NULL); + + dbus_g_connection_register_g_object(conn, GATT_OBJECT_PATH, + G_OBJECT(bluetooth_gatt_obj)); + +} + +static char **__get_string_array_from_gptr_array(GPtrArray *gp) +{ + gchar *gp_path = NULL; + char **path = NULL; + int i; + + if (gp->len == 0) + return NULL; + + path = g_malloc0((gp->len + 1) * sizeof(char *)); + + for (i = 0; i < gp->len; i++) { + gp_path = g_ptr_array_index(gp, i); + path[i] = g_strdup(gp_path); + BT_DBG("path[%d] : [%s]", i, path[i]); + } + + return path; +} + +static void __bluetooth_internal_get_char_cb(DBusGProxy *proxy, + DBusGProxyCall *call, + gpointer user_data) +{ + GError *error = NULL; + GPtrArray *gp_array = NULL; + bt_gatt_discovered_char_t svc_char = { 0, }; + bt_user_info_t *user_info; + + svc_char.service_handle = user_data; + + user_info = _bt_get_user_data(BT_COMMON); + + if (!dbus_g_proxy_end_call(proxy, call, &error, + dbus_g_type_get_collection("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), + &gp_array, G_TYPE_INVALID)) { + BT_ERR("Error : %s \n", error->message); + g_error_free(error); + + if (user_info->cb) { + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED, + BLUETOOTH_ERROR_NONE, &svc_char, + user_info->cb, user_info->user_data); + } + g_free(svc_char.service_handle); + g_object_unref(proxy); + return; + } + + if (NULL != gp_array) { + svc_char.handle_info.count = gp_array->len; + svc_char.handle_info.handle = __get_string_array_from_gptr_array(gp_array); + } + + if (user_info) { + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED, + BLUETOOTH_ERROR_NONE, &svc_char, + user_info->cb, user_info->user_data); + } + + g_ptr_array_free(gp_array, TRUE); + g_free(svc_char.service_handle); + g_free(svc_char.handle_info.handle); + g_object_unref(proxy); +} + +static void __bluetooth_internal_read_cb(GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + bt_user_info_t *user_info; + bt_gatt_char_value_t rsp = { 0, }; + GDBusConnection *system_gconn = NULL; + GVariant *return_data; + GByteArray *gp_byte_array = NULL; + GVariantIter *iter; + guint8 g_byte; + + user_info = _bt_get_user_data(BT_COMMON); + + system_gconn = _bt_init_system_gdbus_conn(); + return_data = g_dbus_connection_call_finish(system_gconn, res, &error); + + if (error) { + BT_ERR("Error : %s \n", error->message); + if(return_data) + g_variant_unref(return_data); + g_clear_error(&error); + return; + } + + gp_byte_array = g_byte_array_new(); + g_variant_get(return_data, "(ay)", &iter); + + while (g_variant_iter_loop(iter, "y", &g_byte)) { + g_byte_array_append(gp_byte_array, &g_byte, 1); + } + + if (NULL != gp_byte_array) { + rsp.val_len = gp_byte_array->len; + rsp.char_value = gp_byte_array->data; + } + + if (user_info) { + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR, + BLUETOOTH_ERROR_NONE, &rsp, + user_info->cb, user_info->user_data); + } + + g_byte_array_free(gp_byte_array, TRUE); + g_variant_unref(return_data); + g_variant_iter_free(iter); + return; +} + +static void __bluetooth_internal_write_cb(GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + bt_user_info_t *user_info; + GDBusConnection *system_gconn = NULL; + GVariant *return_data; + int result = BLUETOOTH_ERROR_NONE; + + BT_DBG("__bluetooth_internal_write_cb"); + user_info = _bt_get_user_data(BT_COMMON); + + system_gconn = _bt_init_system_gdbus_conn(); + return_data = g_dbus_connection_call_finish(system_gconn, res, &error); + + if (error) { + BT_ERR("Error : %s \n", error->message); + g_clear_error(&error); + result = BLUETOOTH_ERROR_INTERNAL; + } + if (user_info) { + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR, + result, NULL, + user_info->cb, user_info->user_data); + } + BT_DBG("BP 0>>>>>>"); + + if(return_data) + g_variant_unref(return_data); + + return; +} + +static void __bluetooth_internal_get_char_desc_cb(GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + GByteArray *gp_byte_array = NULL; + bt_gatt_char_property_t svc_char_desc = { 0, }; + bt_user_info_t *user_info; + GDBusConnection *system_gconn = NULL; + GVariant *return_data; + GVariantIter *iter; + guint8 g_byte; + + svc_char_desc.handle = user_data; + svc_char_desc.val_len = 0x00; + svc_char_desc.description = NULL; + + user_info = _bt_get_user_data(BT_COMMON); + system_gconn = _bt_init_system_gdbus_conn(); + return_data = g_dbus_connection_call_finish(system_gconn, res, &error); + BT_DBG("result data received.."); + if (error) { + BT_ERR("Error : %s \n", error->message); + g_clear_error(&error); + g_free(svc_char_desc.handle); + return; + } + gp_byte_array = g_byte_array_new(); + g_variant_get(return_data, "(ay)", &iter); + + /*Format*/ + if (g_variant_iter_loop(iter, "y", &g_byte)) + svc_char_desc.format.format = g_byte; + + /*Handle and UUIDs*/ + while (g_variant_iter_loop(iter, "y", &g_byte)) { + g_byte_array_append(gp_byte_array, &g_byte, 1); + } + + if (NULL != gp_byte_array) { + svc_char_desc.val_len = gp_byte_array->len; + svc_char_desc.description = (char *)gp_byte_array->data; + } + + if (user_info) { + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED, + BLUETOOTH_ERROR_NONE, &svc_char_desc, + user_info->cb, user_info->user_data); + } + + g_byte_array_free(gp_byte_array, TRUE); + g_free(svc_char_desc.handle); + g_variant_unref(return_data); + g_variant_iter_free(iter); +} + +static void __free_char_req(char_pty_req_t *char_req) +{ + g_free(char_req->char_uuid); + g_strfreev(char_req->handle); + g_free(char_req); +} + +static gboolean __filter_chars_with_uuid(gpointer data) +{ + int i = 0; + bt_gatt_char_property_t *char_pty; + char_pty_req_t *char_req = data; + bt_user_info_t *user_info; + int ret; + + user_info = _bt_get_user_data(BT_COMMON); + if (user_info->cb == NULL) { + __free_char_req(char_req); + return FALSE; + } + + char_pty = g_new0(bt_gatt_char_property_t, 1); + + while (char_req->handle[i] != NULL) { + BT_DBG("char_pty[%d] = %s", i, char_req->handle[i]); + ret = bluetooth_gatt_get_characteristics_property(char_req->handle[i], + char_pty); + if (ret != BLUETOOTH_ERROR_NONE) { + BT_ERR("get char property failed"); + goto done; + } + + if (char_pty->uuid && g_strstr_len(char_pty->uuid, -1, + char_req->char_uuid) != NULL) { + BT_DBG("Requested Char recieved"); + ret = BLUETOOTH_ERROR_NONE; + break; + } + + bluetooth_gatt_free_char_property(char_pty); + + i++; + } + +done: + if (char_req->handle[i] == NULL) + ret = BLUETOOTH_ERROR_NOT_FOUND; + + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID, ret, + char_pty, user_info->cb, user_info->user_data); + + g_free(char_pty); + __free_char_req(char_req); + + return FALSE; +} + +static void __disc_char_from_uuid_cb(DBusGProxy *proxy, + DBusGProxyCall *call, + gpointer user_data) +{ + GError *error = NULL; + GPtrArray *gp_array = NULL; + bt_user_info_t *user_info; + char_pty_req_t *char_req = user_data; + + user_info = _bt_get_user_data(BT_COMMON); + if (!user_info->cb) { + __free_char_req(char_req); + return; + } + + if (!dbus_g_proxy_end_call(proxy, call, &error, + dbus_g_type_get_collection("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), + &gp_array, G_TYPE_INVALID)) { + BT_ERR("Error : %s \n", error->message); + g_error_free(error); + + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID, + BLUETOOTH_ERROR_INTERNAL, NULL, + user_info->cb, user_info->user_data); + + __free_char_req(char_req); + g_object_unref(proxy); + return; + } + + if (gp_array == NULL) { + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID, + BLUETOOTH_ERROR_NOT_FOUND, NULL, + user_info->cb, user_info->user_data); + + __free_char_req(char_req); + g_object_unref(proxy); + + return; + } + + char_req->handle = __get_string_array_from_gptr_array(gp_array); + + __filter_chars_with_uuid(char_req); + + g_ptr_array_free(gp_array, TRUE); + g_object_unref(proxy); +} + + +static int __discover_char_from_uuid(const char *service_handle, + const char *char_uuid){ + DBusGProxy *service_proxy = NULL; + DBusGConnection *conn; + char_pty_req_t *char_req; + + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + service_proxy = dbus_g_proxy_new_for_name(conn, + BT_BLUEZ_NAME, service_handle, + BLUEZ_CHAR_INTERFACE); + retv_if(service_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + char_req = g_new0(char_pty_req_t, 1); + + char_req->char_uuid = g_strdup(char_uuid); + BT_DBG("Char uuid %s ", char_uuid); + + if (!dbus_g_proxy_begin_call(service_proxy, "DiscoverCharacteristics", + (DBusGProxyCallNotify)__disc_char_from_uuid_cb, + char_req, NULL, G_TYPE_INVALID)) { + __free_char_req(char_req); + g_object_unref(service_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_free_primary_services(bt_gatt_handle_info_t *prim_svc) +{ + BT_DBG("+"); + + BT_CHECK_PARAMETER(prim_svc, return); + + g_strfreev(prim_svc->handle); + + memset(prim_svc, 0, sizeof(bt_gatt_handle_info_t)); + + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_free_service_property(bt_gatt_service_property_t *svc_pty) +{ + BT_DBG("+"); + + BT_CHECK_PARAMETER(svc_pty, return); + + g_free(svc_pty->uuid); + g_free(svc_pty->handle); + g_strfreev(svc_pty->handle_info.handle); + + memset(svc_pty, 0, sizeof(bt_gatt_service_property_t)); + + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_free_char_property(bt_gatt_char_property_t *char_pty) +{ + BT_DBG("+"); + + BT_CHECK_PARAMETER(char_pty, return); + + g_free(char_pty->uuid); + g_free(char_pty->name); + g_free(char_pty->description); + g_free(char_pty->val); + g_free(char_pty->handle); + + memset(char_pty, 0, sizeof(bt_gatt_char_property_t)); + + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_get_primary_services(const bluetooth_device_address_t *address, + bt_gatt_handle_info_t *prim_svc) +{ + char device_address[BT_ADDRESS_STRING_SIZE] = { 0 }; + gchar *device_path = NULL; + GError *error = NULL; + + GVariant *result; + GVariantIter *iter; + GDBusConnection *conn; + GVariant *value = NULL; + gchar *g_str; + + GPtrArray *gp_array = NULL; + int ret = BLUETOOTH_ERROR_INTERNAL; + + BT_DBG("+"); + + BT_CHECK_PARAMETER(address, return); + BT_CHECK_PARAMETER(prim_svc, return); + + BT_CHECK_ENABLED(return); + + /* About org.tizen.device1 interface, dbus SMACK is not working. So use bt-service's + privilege checking logic */ + if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_GATT_GET_PRIMARY_SERVICES) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } + + _bt_convert_addr_type_to_string(device_address, + (unsigned char *)address->addr); + + BT_INFO("bluetooth address [%s]\n", device_address); + + device_path = _bt_get_device_object_path(device_address); + + retv_if(device_path == NULL, BLUETOOTH_ERROR_INTERNAL); + + conn = _bt_init_system_gdbus_conn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + result = g_dbus_connection_call_sync(conn, + BT_BLUEZ_NAME, + device_path, + BT_DEVICE_INTERFACE, + "GetPrimServices", + NULL, + G_VARIANT_TYPE ("(ao)"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + if (error) { + BT_ERR("GetPrimServices Call Error %s[%s]", error->message, + device_address); + g_clear_error(&error); + return BLUETOOTH_ERROR_INTERNAL; + } + g_free(device_path); + + gp_array = g_ptr_array_new(); + g_variant_get(result, "(ao)", &iter); + while ((value = g_variant_iter_next_value(iter))) { + g_variant_get(value, "o", &g_str); + g_ptr_array_add(gp_array, (gpointer)g_str); + } + + if (gp_array == NULL) { + BT_ERR("gp_array == NULL"); + goto done; + } + + prim_svc->count = gp_array->len; + prim_svc->handle = __get_string_array_from_gptr_array(gp_array); + + g_ptr_array_free(gp_array, TRUE); + g_variant_iter_free(iter); + g_variant_unref(result); + + ret = BLUETOOTH_ERROR_NONE; +done: + BT_DBG("-"); + return ret; +} + +BT_EXPORT_API int bluetooth_gatt_discover_service_characteristics(const char *service_handle) +{ + DBusGProxy *service_proxy = NULL; + char *handle; + DBusGConnection *conn; + + BT_CHECK_PARAMETER(service_handle, return); + + BT_CHECK_ENABLED(return); + + /* Because this API is async call, so can't use dbus SMACK */ + if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_GATT_DISCOVER_CHARACTERISTICS) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } + + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + service_proxy = dbus_g_proxy_new_for_name(conn, + BT_BLUEZ_NAME, service_handle, + BLUEZ_CHAR_INTERFACE); + + retv_if(service_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + handle = g_strdup(service_handle); + BT_DBG("Requested characteristic handle:%s \n ", handle); + + if (!dbus_g_proxy_begin_call(service_proxy, "DiscoverCharacteristics", + (DBusGProxyCallNotify)__bluetooth_internal_get_char_cb, + handle, NULL, G_TYPE_INVALID)) { + g_free(handle); + g_object_unref(service_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_get_service_property(const char *service_handle, + bt_gatt_service_property_t *service) +{ + DBusGProxy *service_proxy = NULL; + GHashTable *hash = NULL; + GError *error = NULL; + GValue *value = NULL; + GPtrArray *gp_array = NULL ; + DBusGConnection *conn; + int ret = BLUETOOTH_ERROR_NONE; + + BT_CHECK_PARAMETER(service_handle, return); + BT_CHECK_PARAMETER(service, return); + + BT_CHECK_ENABLED(return); + + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + service_proxy = dbus_g_proxy_new_for_name(conn, + BT_BLUEZ_NAME, service_handle, + BLUEZ_CHAR_INTERFACE); + + retv_if(service_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call(service_proxy, "GetProperties", &error, G_TYPE_INVALID, + dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), + &hash, G_TYPE_INVALID); + + g_object_unref(service_proxy); + + if (error != NULL) { + BT_ERR("GetProperties Call Error %s\n", error->message); + + if (g_strrstr(error->message, BT_ACCESS_DENIED_MSG)) + ret = BLUETOOTH_ERROR_ACCESS_DENIED; + else + ret = BLUETOOTH_ERROR_INTERNAL; + + g_error_free(error); + return ret; + } + + retv_if(hash == NULL, BLUETOOTH_ERROR_INTERNAL); + + memset(service, 0, sizeof(bt_gatt_service_property_t)); + + value = g_hash_table_lookup(hash, "UUID"); + service->uuid = value ? g_value_dup_string(value) : NULL; + if (service->uuid) { + BT_DBG("svc_pty.uuid = [%s] \n", service->uuid); + } + + value = g_hash_table_lookup(hash, "Characteristics"); + gp_array = value ? g_value_get_boxed(value) : NULL; + if (gp_array) { + service->handle_info.count = gp_array->len; + service->handle_info.handle = __get_string_array_from_gptr_array(gp_array); + } + + service->handle = g_strdup(service_handle); + g_hash_table_destroy(hash); + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *service_handle) +{ + DBusGProxy *watch_proxy = NULL; + GError *error = NULL; + DBusGConnection *conn; + int ret = BLUETOOTH_ERROR_NONE; + + BT_CHECK_PARAMETER(service_handle, return); + + BT_CHECK_ENABLED(return); + + BT_DBG("Entered service handle:%s \n ", service_handle); + + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + watch_proxy = dbus_g_proxy_new_for_name(conn, + BT_BLUEZ_NAME, service_handle, + BLUEZ_CHAR_INTERFACE); + + retv_if(watch_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + __add_value_changed_method(conn); + + dbus_g_proxy_call(watch_proxy, "RegisterCharacteristicsWatcher", &error, + DBUS_TYPE_G_OBJECT_PATH, GATT_OBJECT_PATH, + G_TYPE_INVALID, G_TYPE_INVALID); + if (error) { + BT_ERR("Method call Fail: %s", error->message); + + if (g_strrstr(error->message, BT_ACCESS_DENIED_MSG)) + ret = BLUETOOTH_ERROR_ACCESS_DENIED; + else + ret = BLUETOOTH_ERROR_INTERNAL; + + g_error_free(error); + g_object_unref(watch_proxy); + return ret; + } + + g_object_unref(watch_proxy); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *service_handle) +{ + DBusGProxy *watch_proxy = NULL; + GError *error = NULL; + DBusGConnection *conn; + int ret = BLUETOOTH_ERROR_NONE; + + BT_CHECK_PARAMETER(service_handle, return); + + BT_CHECK_ENABLED(return); + + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + watch_proxy = dbus_g_proxy_new_for_name(conn, + BT_BLUEZ_NAME, service_handle, + BLUEZ_CHAR_INTERFACE); + + retv_if(watch_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call(watch_proxy, "UnregisterCharacteristicsWatcher", &error, + DBUS_TYPE_G_OBJECT_PATH, GATT_OBJECT_PATH, + G_TYPE_INVALID, G_TYPE_INVALID); + if (error) { + BT_ERR("Method call Fail: %s", error->message); + + if (g_strrstr(error->message, BT_ACCESS_DENIED_MSG)) + ret = BLUETOOTH_ERROR_ACCESS_DENIED; + else + ret = BLUETOOTH_ERROR_INTERNAL; + + g_error_free(error); + g_object_unref(watch_proxy); + return ret; + } + + g_object_unref(watch_proxy); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_get_characteristics_property(const char *char_handle, + bt_gatt_char_property_t *characteristic) +{ + DBusGProxy *characteristic_proxy = NULL; + GHashTable *hash = NULL; + GError *error = NULL; + GValue *value = NULL; + GByteArray *gb_array = NULL; + DBusGConnection *conn; + int ret = BLUETOOTH_ERROR_NONE; + + BT_CHECK_PARAMETER(char_handle, return); + BT_CHECK_PARAMETER(characteristic, return); + + BT_CHECK_ENABLED(return); + + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + characteristic_proxy = dbus_g_proxy_new_for_name(conn, + BT_BLUEZ_NAME, char_handle, + BLUEZ_CHAR_INTERFACE); + + retv_if(characteristic_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call(characteristic_proxy, "GetProperties", &error, G_TYPE_INVALID, + dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), + &hash, G_TYPE_INVALID); + if (error != NULL) { + BT_ERR("GetProperties Call Error %s\n", error->message); + + if (g_strrstr(error->message, BT_ACCESS_DENIED_MSG)) + ret = BLUETOOTH_ERROR_ACCESS_DENIED; + else + ret = BLUETOOTH_ERROR_INTERNAL; + + g_error_free(error); + g_object_unref(characteristic_proxy); + return ret; + } + g_object_unref(characteristic_proxy); + + retv_if(hash == NULL, BLUETOOTH_ERROR_INTERNAL); + + memset(characteristic, 0, sizeof(bt_gatt_char_property_t)); + + value = g_hash_table_lookup(hash, "UUID"); + characteristic->uuid = value ? g_value_dup_string(value) : NULL; + if (characteristic->uuid) { + BT_DBG("characteristic->uuid = [%s] \n", characteristic->uuid); + } + + value = g_hash_table_lookup(hash, "Name"); + characteristic->name = value ? g_value_dup_string(value) : NULL; + if (characteristic->name) { + DBG_SECURE("characteristic->name = [%s] \n", characteristic->name); + } + + value = g_hash_table_lookup(hash, "Description"); + characteristic->description = value ? g_value_dup_string(value) : NULL; + if (characteristic->description) { + BT_DBG("characteristic->description = [%s] \n", characteristic->description); + } + + value = g_hash_table_lookup(hash, "Value"); + + gb_array = value ? g_value_get_boxed(value) : NULL; + if (gb_array) { + if (gb_array->len) { + BT_DBG("gb_array->len = %d \n", gb_array->len); + characteristic->val_len = gb_array->len; + + characteristic->val = g_malloc0(gb_array->len * sizeof(unsigned char)); + memcpy(characteristic->val, gb_array->data, gb_array->len); + } else { + characteristic->val = NULL; + characteristic->val_len = 0; + } + } else { + characteristic->val = NULL; + characteristic->val_len = 0; + } + characteristic->handle = g_strdup(char_handle); + g_hash_table_destroy(hash); + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_set_characteristics_value(const char *char_handle, + const guint8 *value, int length) +{ + GVariant *val; + char *handle; + GVariantBuilder *builder; + GError *error = NULL; + DBusGConnection *conn; + int i = 0; + int ret = BLUETOOTH_ERROR_NONE; + + BT_CHECK_PARAMETER(char_handle, return); + BT_CHECK_PARAMETER(value, return); + retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM); + + BT_CHECK_ENABLED(return); + + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_DBG("Requested characteristic handle:%s \n ", char_handle); + + builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY); + + for (i = 0; i < length; i++) { + g_variant_builder_add(builder, "y", value[i]); + BT_DBG("value idx:%d, %d", i, value[i]); + } + + val = g_variant_new("ay", builder); + + handle = g_strdup(char_handle); + BT_DBG("BP 0"); + + g_dbus_connection_call_sync(conn, + BT_BLUEZ_NAME, + char_handle, + BLUEZ_CHAR_INTERFACE, + "SetProperty", + g_variant_new("(sv)", + "Value", val), + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (error) { + BT_ERR("Set value Fail: %s", error->message); + + if (g_strrstr(error->message, BT_ACCESS_DENIED_MSG)) + ret = BLUETOOTH_ERROR_ACCESS_DENIED; + else + ret = BLUETOOTH_ERROR_INTERNAL; + + g_error_free(error); + g_variant_builder_unref(builder); + return ret; + } + BT_DBG("BP 1"); + + g_variant_builder_unref(builder); + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_request( + const char *char_handle, const guint8 *value, int length) +{ + GVariant *val; + GError *error = NULL; + GDBusConnection *conn; + char *handle; + GVariantBuilder *builder; + int i; + + BT_CHECK_PARAMETER(char_handle, return); + BT_CHECK_PARAMETER(value, return); + retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM); + + BT_CHECK_ENABLED(return); + + /* Because this API is async call, so can't use dbus SMACK */ + if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_GATT_SET_PROPERTY_REQUEST) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } + + conn = _bt_init_system_gdbus_conn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY); + + for (i = 0; i < length; i++) { + g_variant_builder_add(builder, "y", value[i]); + } + + val = g_variant_new("ay", builder); + + handle = g_strdup(char_handle); + + g_dbus_connection_call(conn, + BT_BLUEZ_NAME, + char_handle, + BLUEZ_CHAR_INTERFACE, + "SetPropertyRequest", + g_variant_new("(sv)", + "Value", val), + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + (GAsyncReadyCallback) + __bluetooth_internal_write_cb, + handle); + + if (error) { + BT_ERR("Set value Fail: %s", error->message); + g_clear_error(&error); + g_variant_builder_unref(builder); + return BLUETOOTH_ERROR_INTERNAL; + } + g_variant_builder_unref(builder); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_get_service_from_uuid(bluetooth_device_address_t *address, + const char *service_uuid, + bt_gatt_service_property_t *service) +{ + int i; + int ret; + bt_gatt_handle_info_t prim_svc; + + BT_CHECK_PARAMETER(address, return); + BT_CHECK_PARAMETER(service_uuid, return); + BT_CHECK_PARAMETER(service, return); + + BT_CHECK_ENABLED(return); + + ret = bluetooth_gatt_get_primary_services(address, &prim_svc); + if (ret != BLUETOOTH_ERROR_NONE) { + BT_ERR("Get primary service failed "); + return ret; + } + + for (i = 0; i < prim_svc.count; i++) { + + BT_DBG("prim_svc [%d] = %s", i, prim_svc.handle[i]); + + ret = bluetooth_gatt_get_service_property(prim_svc.handle[i], + service); + if (ret != BLUETOOTH_ERROR_NONE) { + BT_ERR("Get service property failed "); + bluetooth_gatt_free_primary_services(&prim_svc); + return ret; + } + + BT_DBG("Service uuid %s", service->uuid); + + if (g_strstr_len(service->uuid, -1, service_uuid)) { + BT_INFO("Found requested service"); + ret = BLUETOOTH_ERROR_NONE; + break; + } + + bluetooth_gatt_free_service_property(service); + } + + if (i == prim_svc.count) + ret = BLUETOOTH_ERROR_NOT_FOUND; + + bluetooth_gatt_free_primary_services(&prim_svc); + + return ret; +} + +BT_EXPORT_API int bluetooth_gatt_get_char_from_uuid(const char *service_handle, + const char *char_uuid) +{ + char **char_handles; + char_pty_req_t *char_pty; + int i; + bt_gatt_service_property_t svc_pty; + int ret; + + BT_CHECK_PARAMETER(service_handle, return); + BT_CHECK_PARAMETER(char_uuid, return); + + BT_CHECK_ENABLED(return); + + ret = bluetooth_gatt_get_service_property(service_handle, &svc_pty); + if (ret != BLUETOOTH_ERROR_NONE) { + BT_ERR("Get primary service failed "); + return ret; + } + + if (bluetooth_gatt_get_service_property(service_handle, &svc_pty) != + BLUETOOTH_ERROR_NONE) { + BT_ERR("Invalid service"); + return BLUETOOTH_ERROR_NOT_FOUND; + } + + char_handles = svc_pty.handle_info.handle; + + if (char_handles == NULL) + return __discover_char_from_uuid(svc_pty.handle, char_uuid); + + char_pty = g_new0(char_pty_req_t, 1); + + char_pty->handle = g_malloc0((svc_pty.handle_info.count + 1) * + sizeof(char *)); + for (i = 0; i < svc_pty.handle_info.count; i++) { + char_pty->handle[i] = char_handles[i]; + BT_DBG("char_path[%d] : [%s]", i, char_pty->handle[i]); + } + char_pty->char_uuid = g_strdup(char_uuid); + + g_idle_add(__filter_chars_with_uuid, char_pty); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *characteristic) +{ + GDBusConnection *conn; + char *handle; + + BT_CHECK_PARAMETER(characteristic, return); + BT_CHECK_ENABLED(return); + + /* Because this API is async call, so can't use dbus SMACK */ + if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_GATT_READ_CHARACTERISTIC) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } + + conn = _bt_init_system_gdbus_conn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + handle = g_strdup(characteristic); + g_dbus_connection_call(conn, + BT_BLUEZ_NAME, + characteristic, + BLUEZ_CHAR_INTERFACE, + "ReadCharacteristic", + NULL, + G_VARIANT_TYPE("(ay)"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + (GAsyncReadyCallback) + __bluetooth_internal_read_cb, + handle); + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_discover_characteristic_descriptor + (const char *characteristic_handle) +{ + char *handle; + GDBusConnection *conn; + + BT_CHECK_PARAMETER(characteristic_handle, return); + + BT_CHECK_ENABLED(return); + + /* Because this API is async call, so can't use dbus SMACK */ + if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_GATT_DISCOVER_CHARACTERISTICS_DESCRIPTOR) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } + + conn = _bt_init_system_gdbus_conn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + handle = g_strdup(characteristic_handle); + g_dbus_connection_call(conn, + BT_BLUEZ_NAME, + characteristic_handle, + BLUEZ_CHAR_INTERFACE, + "DiscoverCharacteristicsDescriptor", + NULL, + G_VARIANT_TYPE("(ay)"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + (GAsyncReadyCallback) + __bluetooth_internal_get_char_desc_cb, + handle); + + return BLUETOOTH_ERROR_NONE; +} + diff --git a/bt-api/bluetooth-api.pc.in b/bt-api/bluetooth-api.pc.in old mode 100644 new mode 100755 index e577fa3..c7210a4 --- a/bt-api/bluetooth-api.pc.in +++ b/bt-api/bluetooth-api.pc.in @@ -1,6 +1,6 @@ prefix=@PREFIX@ exec_prefix=@EXEC_PREFIX@ -libdir=@LIB_INSTALL_DIR@ +libdir=@LIBDIR@ includedir=@INCLUDEDIR@ Name: bluetooth-api diff --git a/bt-api/bt-adapter-le.c b/bt-api/bt-adapter-le.c new file mode 100755 index 0000000..a00c1ad --- /dev/null +++ b/bt-api/bt-adapter-le.c @@ -0,0 +1,486 @@ +/* + * Bluetooth-frwk + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * 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 +#include + +#include "bluetooth-api.h" +#include "bt-internal-types.h" + +#include "bt-common.h" +#include "bt-request-sender.h" +#include "bt-event-handler.h" + +BT_EXPORT_API int bluetooth_check_adapter_le(void) +{ + int ret; + int value = 1; + + ret = _bt_get_adapter_path(_bt_gdbus_get_system_gconn(), NULL); + + if (ret != BLUETOOTH_ERROR_NONE) { + return BLUETOOTH_ADAPTER_LE_DISABLED; + } + +#ifdef ENABLE_TIZEN_2_4 + ret = vconf_get_int(VCONFKEY_BT_LE_STATUS, &value); + if (ret != 0) { + BT_ERR("fail to get vconf key!"); + return ret; + } + + BT_DBG("value : %d", value); + return value == VCONFKEY_BT_LE_STATUS_ON ? BLUETOOTH_ADAPTER_LE_ENABLED : + BLUETOOTH_ADAPTER_LE_DISABLED; +#else + return value = BLUETOOTH_ADAPTER_LE_DISABLED; +#endif +} + +BT_EXPORT_API int bluetooth_enable_adapter_le(void) +{ + int result; + + retv_if(bluetooth_check_adapter_le() == BLUETOOTH_ADAPTER_LE_ENABLED, + BLUETOOTH_ERROR_DEVICE_ALREADY_ENABLED); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_ENABLE_ADAPTER_LE, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + return result; +} + +BT_EXPORT_API int bluetooth_disable_adapter_le(void) +{ + int result; + retv_if(bluetooth_check_adapter_le() == BLUETOOTH_ADAPTER_LE_DISABLED, + BLUETOOTH_ERROR_DEVICE_NOT_ENABLED); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_DISABLE_ADAPTER_LE, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_start_le_discovery(void) +{ + int result; + + BT_CHECK_ENABLED_ANY(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_START_LE_DISCOVERY, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_stop_le_discovery(void) +{ + int result; + + BT_CHECK_ENABLED_ANY(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_STOP_LE_DISCOVERY, + in_param1, in_param2, in_param3, in_param4, &out_param); + + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_is_le_discovering(void) +{ + int result; + int is_discovering = FALSE; + + BT_CHECK_ENABLED_ANY(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_IS_LE_DISCOVERYING, + in_param1, in_param2, in_param3, in_param4, &out_param); + + if (result == BLUETOOTH_ERROR_NONE) { + is_discovering = g_array_index(out_param, + int, 0); + } else { + BT_ERR("Fail to send request"); + } + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return is_discovering; +} + +#ifdef TIZEN_WEARABLE +gboolean __bluetooth_is_privileged_process(void) +{ + FILE *fp= NULL; + char path[30] = {0, }; + char buf[256] = {0, }; + + snprintf(path, sizeof(path), "/proc/%d/cmdline", getpid()); + fp = fopen(path, "r"); + if (fp == NULL) + return FALSE; + + if (fgets(buf, 256, fp) != NULL) { + if (strstr(buf, "weconnd") != NULL) { + fclose(fp); + return TRUE; + } + } + + fclose(fp); + return FALSE; +} +#endif + +BT_EXPORT_API int bluetooth_set_advertising(gboolean enable) +{ + int result; + gboolean use_reserved_slot = FALSE; + + BT_CHECK_ENABLED_ANY(return); + +#ifdef TIZEN_WEARABLE + use_reserved_slot = __bluetooth_is_privileged_process(); +#endif + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, &enable, sizeof(gboolean)); + g_array_append_vals(in_param2, &use_reserved_slot, sizeof(gboolean)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_SET_ADVERTISING, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_set_custom_advertising(gboolean enable, + bluetooth_advertising_params_t *params) +{ + int result; + gboolean use_reserved_slot = FALSE; + + BT_CHECK_ENABLED_ANY(return); + +#ifdef TIZEN_WEARABLE + use_reserved_slot = __bluetooth_is_privileged_process(); +#endif + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, &enable, sizeof(gboolean)); + g_array_append_vals(in_param2, params, sizeof(bluetooth_advertising_params_t)); + g_array_append_vals(in_param3, &use_reserved_slot, sizeof(gboolean)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_SET_CUSTOM_ADVERTISING, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_get_advertising_data(bluetooth_advertising_data_t *adv_data, int *length) +{ + int result; + guint8 *data; + + BT_CHECK_PARAMETER(adv_data, return); + BT_CHECK_PARAMETER(length, return); + BT_CHECK_ENABLED_ANY(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GET_ADVERTISING_DATA, + in_param1, in_param2, in_param3, in_param4, &out_param); + + if (result == BLUETOOTH_ERROR_NONE) { + data = &g_array_index(out_param, guint8, 0); + *length = out_param->len; + + memset(adv_data, 0x00, sizeof(bluetooth_advertising_data_t)); + memcpy(adv_data->data, data, *length); + } + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_set_advertising_data(const bluetooth_advertising_data_t *value, int length) +{ + int result; + gboolean use_reserved_slot = FALSE; + + BT_CHECK_PARAMETER(value, return); + BT_CHECK_ENABLED_ANY(return); + + if (length > BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX - 3) + return BLUETOOTH_ERROR_INVALID_PARAM; + +#ifdef TIZEN_WEARABLE + use_reserved_slot = __bluetooth_is_privileged_process(); +#endif + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, value, sizeof(bluetooth_advertising_data_t)); + g_array_append_vals(in_param2, &length, sizeof(int)); + g_array_append_vals(in_param3, &use_reserved_slot, sizeof(gboolean)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_SET_ADVERTISING_DATA, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_get_scan_response_data(bluetooth_scan_resp_data_t *value, int *length) +{ + int result; + guint8 *data; + + BT_CHECK_PARAMETER(value, return); + BT_CHECK_PARAMETER(length, return); + BT_CHECK_ENABLED_ANY(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GET_SCAN_RESPONSE_DATA, + in_param1, in_param2, in_param3, in_param4, &out_param); + + if (result == BLUETOOTH_ERROR_NONE) { + data = &g_array_index(out_param, guint8, 0); + *length = out_param->len; + + memset(value, 0x00, sizeof(bluetooth_scan_resp_data_t)); + memcpy(value->data, data, *length); + } + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_set_scan_response_data( + const bluetooth_scan_resp_data_t *value, int length) +{ + int result; + gboolean use_reserved_slot = FALSE; + + BT_CHECK_PARAMETER(value, return); + BT_CHECK_ENABLED_ANY(return); + + if (length > BLUETOOTH_SCAN_RESP_DATA_LENGTH_MAX) + return BLUETOOTH_ERROR_INVALID_PARAM; + +#ifdef TIZEN_WEARABLE + use_reserved_slot = __bluetooth_is_privileged_process(); +#endif + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, value, length); + g_array_append_vals(in_param2, &length, sizeof(int)); + g_array_append_vals(in_param3, &use_reserved_slot, sizeof(gboolean)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_SET_SCAN_RESPONSE_DATA, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_set_scan_parameters(bluetooth_le_scan_params_t *params) +{ + int result; + + BT_CHECK_ENABLED_ANY(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, params, sizeof(bluetooth_le_scan_params_t)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_SET_SCAN_PARAMETERS, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_is_advertising(gboolean *is_advertising) +{ + int result; + + BT_CHECK_ENABLED_ANY(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_IS_ADVERTISING, + in_param1, in_param2, in_param3, in_param4, &out_param); + + if (result == BLUETOOTH_ERROR_NONE) { + *is_advertising = g_array_index(out_param, int, 0); + } else { + BT_ERR("Fail to send request"); + } + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_add_white_list(bluetooth_device_address_t *address, bluetooth_device_address_type_t address_type) +{ + int result; + + BT_CHECK_PARAMETER(address, return); + BT_CHECK_ENABLED_ANY(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t)); + g_array_append_vals(in_param2, &address_type, sizeof(int)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_ADD_WHITE_LIST, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_remove_white_list(bluetooth_device_address_t *address, bluetooth_device_address_type_t address_type) +{ + int result; + + BT_CHECK_PARAMETER(address, return); + BT_CHECK_ENABLED_ANY(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t)); + g_array_append_vals(in_param2, &address_type, sizeof(int)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_REMOVE_WHITE_LIST, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_clear_white_list(void) +{ + int result; + + BT_CHECK_ENABLED_ANY(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_CLEAR_WHITE_LIST, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_enable_le_privacy(gboolean enable_privacy) +{ + int result; + + BT_CHECK_ENABLED_ANY(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, &enable_privacy, sizeof(gboolean)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_SET_LE_PRIVACY, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_le_register_callback(bluetooth_cb_func_ptr callback_ptr, void *user_data) +{ + int ret; + + ret = _bt_register_event(BT_LE_ADAPTER_EVENT, (void *)callback_ptr, user_data); + if (ret != BLUETOOTH_ERROR_NONE && + ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) { + BT_ERR("Fail to register BT_LE_ADAPTER_EVENT event : %d", ret); + return ret; + } + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_le_unregister_callback(void) +{ + _bt_unregister_event(BT_LE_ADAPTER_EVENT); + + return BLUETOOTH_ERROR_NONE; +} \ No newline at end of file diff --git a/bt-api/bt-adapter.c b/bt-api/bt-adapter.c old mode 100644 new mode 100755 index 2def8c2..0a8b7df --- a/bt-api/bt-adapter.c +++ b/bt-api/bt-adapter.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -18,9 +22,6 @@ */ #include -#if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT) -#include -#endif #include "bluetooth-api.h" #include "bt-internal-types.h" @@ -39,7 +40,11 @@ static int __bt_fill_device_list(GArray *out_param2, GPtrArray **dev_list) BT_CHECK_PARAMETER(dev_list, return); size = out_param2->len; - retv_if(size == 0, BLUETOOTH_ERROR_NONE); + + if (size == 0) { + BT_ERR("No bonded device"); + return BLUETOOTH_ERROR_NONE; + } size = (out_param2->len) / sizeof(bluetooth_device_info_t); @@ -61,34 +66,36 @@ static int __bt_fill_device_list(GArray *out_param2, GPtrArray **dev_list) BT_EXPORT_API int bluetooth_check_adapter(void) { - int result; - bluetooth_adapter_state_t state; - - BT_INIT_PARAMS(); - BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + int ret; + int value; - result = _bt_send_request(BT_BLUEZ_SERVICE, BT_CHECK_ADAPTER, - in_param1, in_param2, in_param3, in_param4, &out_param); + ret = _bt_get_adapter_path(_bt_gdbus_get_system_gconn(), NULL); - if (result == BLUETOOTH_ERROR_NONE) { - state = g_array_index(out_param, bluetooth_adapter_state_t, 0); + if (ret != BLUETOOTH_ERROR_NONE) { + return BLUETOOTH_ADAPTER_DISABLED; } - BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + /* check VCONFKEY_BT_STATUS */ + if (vconf_get_int(VCONFKEY_BT_STATUS, &value) != 0) { + BT_ERR("fail to get vconf key!"); + return BLUETOOTH_ADAPTER_DISABLED; + } - return state ? BLUETOOTH_ADAPTER_ENABLED : BLUETOOTH_ADAPTER_DISABLED; + return value == VCONFKEY_BT_STATUS_OFF ? BLUETOOTH_ADAPTER_DISABLED : + BLUETOOTH_ADAPTER_ENABLED; } BT_EXPORT_API int bluetooth_enable_adapter(void) { int result; - BT_INIT_PARAMS(); - BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); - + BT_INFO(""); retv_if(bluetooth_check_adapter() == BLUETOOTH_ADAPTER_ENABLED, BLUETOOTH_ERROR_DEVICE_ALREADY_ENABLED); + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_ENABLE_ADAPTER, in_param1, in_param2, in_param3, in_param4, &out_param); @@ -101,6 +108,7 @@ BT_EXPORT_API int bluetooth_disable_adapter(void) { int result; + BT_INFO(""); BT_CHECK_ENABLED(return); BT_INIT_PARAMS(); @@ -114,10 +122,29 @@ BT_EXPORT_API int bluetooth_disable_adapter(void) return result; } +BT_EXPORT_API int bluetooth_recover_adapter(void) +{ + int result; + + BT_INFO(""); + BT_CHECK_ENABLED(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RECOVER_ADAPTER, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + BT_EXPORT_API int bluetooth_reset_adapter(void) { int result; + BT_INFO(""); BT_INIT_PARAMS(); BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); @@ -134,6 +161,7 @@ BT_EXPORT_API int bluetooth_get_local_address(bluetooth_device_address_t *local_ int result; BT_CHECK_PARAMETER(local_address, return); + BT_CHECK_ENABLED_ANY(return); BT_INIT_PARAMS(); BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); @@ -151,11 +179,34 @@ BT_EXPORT_API int bluetooth_get_local_address(bluetooth_device_address_t *local_ return result; } +BT_EXPORT_API int bluetooth_get_local_version(bluetooth_version_t *local_version) +{ + int result; + + BT_CHECK_PARAMETER(local_version, return); + BT_CHECK_ENABLED_ANY(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GET_LOCAL_VERSION, + in_param1, in_param2, in_param3, in_param4, &out_param); + + if (result == BLUETOOTH_ERROR_NONE) { + *local_version = g_array_index(out_param, bluetooth_version_t, 0); + } + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + BT_EXPORT_API int bluetooth_get_local_name(bluetooth_device_name_t *local_name) { int result; BT_CHECK_PARAMETER(local_name, return); + BT_CHECK_ENABLED_ANY(return); BT_INIT_PARAMS(); BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); @@ -178,7 +229,7 @@ BT_EXPORT_API int bluetooth_set_local_name(const bluetooth_device_name_t *local_ int result; BT_CHECK_PARAMETER(local_name, return); - BT_CHECK_ENABLED(return); + BT_CHECK_ENABLED_ANY(return); BT_INIT_PARAMS(); BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); @@ -228,6 +279,25 @@ BT_EXPORT_API int bluetooth_get_discoverable_mode(bluetooth_discoverable_mode_t BT_CHECK_PARAMETER(discoverable_mode_ptr, return); +#ifndef TIZEN_WEARABLE + int timeout = 0; + /* Requirement in OSP */ + if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED) { + if (vconf_get_int(BT_FILE_VISIBLE_TIME, &timeout) != 0) { + BT_ERR("Fail to get the timeout value"); + return BLUETOOTH_ERROR_INTERNAL; + } + + if (timeout == -1) { + *discoverable_mode_ptr = BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE; + } else { + *discoverable_mode_ptr = BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE; + } + + return BLUETOOTH_ERROR_NONE; + } +#endif + BT_INIT_PARAMS(); BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); @@ -235,8 +305,7 @@ BT_EXPORT_API int bluetooth_get_discoverable_mode(bluetooth_discoverable_mode_t in_param1, in_param2, in_param3, in_param4, &out_param); if (result == BLUETOOTH_ERROR_NONE) { - *discoverable_mode_ptr = g_array_index(out_param, - int, 0); + *discoverable_mode_ptr = g_array_index(out_param, int, 0); } BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); @@ -306,6 +375,30 @@ BT_EXPORT_API int bluetooth_start_discovery(unsigned short max_response, return result; } +BT_EXPORT_API int bluetooth_start_custom_discovery(bt_discovery_role_type_t role, + unsigned short max_response, + unsigned short discovery_duration, + unsigned int classOfDeviceMask) +{ + int result; + + if (role == DISCOVERY_ROLE_LE) + BT_CHECK_ENABLED_LE(return); + else + BT_CHECK_ENABLED(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, &role, sizeof(bt_discovery_role_type_t)); + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_START_CUSTOM_DISCOVERY, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + BT_EXPORT_API int bluetooth_cancel_discovery(void) { int result; @@ -349,6 +442,48 @@ BT_EXPORT_API int bluetooth_is_discovering(void) return is_discovering; } +BT_EXPORT_API int bluetooth_is_connectable(gboolean *is_connectable) +{ + int result; + + BT_CHECK_ENABLED_ANY(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_IS_CONNECTABLE, + in_param1, in_param2, in_param3, in_param4, &out_param); + + if (result == BLUETOOTH_ERROR_NONE) { + *is_connectable = g_array_index(out_param, int, 0); + } else { + BT_ERR("Fail to send request"); + } + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_set_connectable(gboolean is_connectable) +{ + int result; + + BT_CHECK_ENABLED_ANY(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, &is_connectable, sizeof(gboolean)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_SET_CONNECTABLE, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + BT_EXPORT_API int bluetooth_get_bonded_device_list(GPtrArray **dev_list) { int result; @@ -362,12 +497,33 @@ BT_EXPORT_API int bluetooth_get_bonded_device_list(GPtrArray **dev_list) result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GET_BONDED_DEVICES, in_param1, in_param2, in_param3, in_param4, &out_param); - if (result == BLUETOOTH_ERROR_NONE) { + if (result == BLUETOOTH_ERROR_NONE) result = __bt_fill_device_list(out_param, dev_list); - } BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); return result; } +BT_EXPORT_API int bluetooth_set_manufacturer_data(const bluetooth_manufacturer_data_t *value) +{ + int result; + + BT_CHECK_PARAMETER(value, return); + BT_CHECK_ENABLED_ANY(return); + + if (value->data_len > BLUETOOTH_MANUFACTURER_DATA_LENGTH_MAX) + return BLUETOOTH_ERROR_INVALID_PARAM; + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, value, sizeof(bluetooth_manufacturer_data_t)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_SET_MANUFACTURER_DATA, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} diff --git a/bt-api/bt-audio.c b/bt-api/bt-audio.c old mode 100644 new mode 100755 index e1b2130..343f114 --- a/bt-api/bt-audio.c +++ b/bt-api/bt-audio.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -17,6 +21,8 @@ * */ +#include + #include "bluetooth-api.h" #include "bluetooth-audio-api.h" #include "bt-internal-types.h" @@ -29,6 +35,10 @@ BT_EXPORT_API int bluetooth_audio_init(bt_audio_func_ptr cb, void *user_data) { int ret; + if (cb == NULL) { + BT_ERR("callback is NULL"); + return BLUETOOTH_ERROR_INVALID_PARAM; + } ret = _bt_init_event_handler(); if (ret != BLUETOOTH_ERROR_NONE && @@ -40,7 +50,12 @@ BT_EXPORT_API int bluetooth_audio_init(bt_audio_func_ptr cb, void *user_data) _bt_set_user_data(BT_AUDIO, (void *)cb, user_data); /* Register All events */ - _bt_register_event(BT_HEADSET_EVENT , (void *)cb, user_data); + ret = _bt_register_event(BT_HEADSET_EVENT, (void *)cb, user_data); + if (ret != BLUETOOTH_ERROR_NONE && + ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) { + _bt_deinit_event_handler(); + return ret; + } return BLUETOOTH_ERROR_NONE; } @@ -56,21 +71,28 @@ BT_EXPORT_API int bluetooth_audio_deinit(void) BT_EXPORT_API int bluetooth_audio_connect(bluetooth_device_address_t *remote_address) { + int service_function = BT_AUDIO_CONNECT; int result; bt_user_info_t *user_info; BT_CHECK_PARAMETER(remote_address, return); BT_CHECK_ENABLED(return); - BT_INIT_PARAMS(); - BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_AUDIO_CONNECT) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } user_info = _bt_get_user_data(BT_AUDIO); - retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t)); - result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_AUDIO_CONNECT, + result = _bt_send_request_async(BT_BLUEZ_SERVICE, service_function, in_param1, in_param2, in_param3, in_param4, user_info->cb, user_info->user_data); @@ -87,11 +109,17 @@ BT_EXPORT_API int bluetooth_audio_disconnect(bluetooth_device_address_t *remote_ BT_CHECK_PARAMETER(remote_address, return); BT_CHECK_ENABLED(return); - BT_INIT_PARAMS(); - BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_AUDIO_DISCONNECT) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } user_info = _bt_get_user_data(BT_AUDIO); - retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t)); @@ -112,11 +140,17 @@ BT_EXPORT_API int bluetooth_ag_connect(bluetooth_device_address_t *remote_addres BT_CHECK_PARAMETER(remote_address, return); BT_CHECK_ENABLED(return); - BT_INIT_PARAMS(); - BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_AG_CONNECT) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } user_info = _bt_get_user_data(BT_AUDIO); - retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t)); @@ -137,11 +171,17 @@ BT_EXPORT_API int bluetooth_ag_disconnect(bluetooth_device_address_t *remote_add BT_CHECK_PARAMETER(remote_address, return); BT_CHECK_ENABLED(return); - BT_INIT_PARAMS(); - BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_AG_DISCONNECT) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } user_info = _bt_get_user_data(BT_AUDIO); - retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t)); @@ -162,11 +202,17 @@ BT_EXPORT_API int bluetooth_av_connect(bluetooth_device_address_t *remote_addres BT_CHECK_PARAMETER(remote_address, return); BT_CHECK_ENABLED(return); - BT_INIT_PARAMS(); - BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_AV_CONNECT) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } user_info = _bt_get_user_data(BT_AUDIO); - retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t)); @@ -187,11 +233,17 @@ BT_EXPORT_API int bluetooth_av_disconnect(bluetooth_device_address_t *remote_add BT_CHECK_PARAMETER(remote_address, return); BT_CHECK_ENABLED(return); - BT_INIT_PARAMS(); - BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_AV_DISCONNECT) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } user_info = _bt_get_user_data(BT_AUDIO); - retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t)); @@ -246,3 +298,675 @@ BT_EXPORT_API int bluetooth_ag_set_speaker_gain(unsigned int speaker_gain) return result; } +#define BT_HF_SERVICE_NAME "org.bluez.hf_agent" +#define BT_HF_OBJECT_PATH "/org/bluez/handsfree_agent" +#define BT_HF_INTERFACE "org.tizen.HfApp" + + +static DBusMessage* __bt_hf_agent_dbus_send(const char *path, + const char *interface, const char *method, DBusError *err, int type, ...) +{ + DBusMessage *msg; + DBusMessage *reply; + va_list args; + + msg = dbus_message_new_method_call(BT_HF_SERVICE_NAME, + path, interface, method); + if (!msg) { + BT_ERR("Unable to allocate new D-Bus %s message \n", method); + return NULL; + } + + va_start(args, type); + + if (!dbus_message_append_args_valist(msg, type, args)) { + dbus_message_unref(msg); + va_end(args); + return NULL; + } + + va_end(args); + + dbus_error_init(err); + + BT_DBG("DBus HF API call, method = %s", method); + + reply = dbus_connection_send_with_reply_and_block(_bt_get_system_conn(), + msg, 4000, err); + dbus_message_unref(msg); + + return reply; +} + +static int __bt_hf_agent_read_call_list(DBusMessage *reply, + bt_hf_call_list_s **call_list) { + + DBusMessageIter iter; + DBusMessageIter iter_struct; + int32_t call_count; + + BT_DBG("+"); + + dbus_message_iter_init(reply, &iter); + dbus_message_iter_get_basic(&iter, &call_count); + if(call_count <= 0) { + *call_list = NULL; + return BLUETOOTH_ERROR_NOT_FOUND; + } + BT_DBG("Call count = %d", call_count); + + *call_list = g_malloc0(sizeof(bt_hf_call_list_s)); + (*call_list)->count = call_count; + dbus_message_iter_next(&iter); + dbus_message_iter_recurse(&iter, &iter_struct); + while(dbus_message_iter_get_arg_type(&iter_struct) == + DBUS_TYPE_STRUCT) { + + gchar *number = NULL; + bt_hf_call_status_info_t *call_info; + DBusMessageIter entry_iter; + + call_info = g_malloc0(sizeof(bt_hf_call_status_info_t)); + + dbus_message_iter_recurse(&iter_struct,&entry_iter); + + dbus_message_iter_get_basic(&entry_iter, &number); + call_info->number = g_strdup(number); + dbus_message_iter_next(&entry_iter); + dbus_message_iter_get_basic(&entry_iter, &call_info->direction); + dbus_message_iter_next(&entry_iter); + dbus_message_iter_get_basic(&entry_iter, &call_info->status); + dbus_message_iter_next(&entry_iter); + dbus_message_iter_get_basic(&entry_iter, &call_info->mpart); + dbus_message_iter_next(&entry_iter); + dbus_message_iter_get_basic(&entry_iter, &call_info->idx); + + (*call_list)->list = g_list_append((*call_list)->list, + (gpointer)call_info); + dbus_message_iter_next(&iter_struct); + } + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_hf_init(bt_hf_func_ptr cb, void *user_data) +{ + int ret; + + if (cb == NULL) { + BT_ERR("callback is NULL"); + return BLUETOOTH_ERROR_INVALID_PARAM; + } + + ret = dbus_threads_init_default(); + + if (ret) + BT_ERR("dbus_thread_init_default Success"); + else + BT_ERR("dbus_thread_init_default Fail"); + + ret = _bt_init_event_handler(); + + if (ret != BLUETOOTH_ERROR_NONE && + ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) { + BT_ERR("Fail to init the event handler"); + return ret; + } + + _bt_set_user_data(BT_HF, (void *)cb, user_data); + + /* Register All events */ + ret = _bt_register_event(BT_HF_AGENT_EVENT, (void *)cb, user_data); + if (ret != BLUETOOTH_ERROR_NONE && + ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) { + _bt_deinit_event_handler(); + return ret; + } + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_hf_deinit(void) +{ + int ret; + + ret = _bt_unregister_event(BT_HF_AGENT_EVENT); + if (ret != BLUETOOTH_ERROR_NONE ) + BT_ERR("_bt_unregister_event failed"); + + _bt_set_user_data(BT_HF, NULL, NULL); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_hf_connect(bluetooth_device_address_t *remote_address) +{ + int result; + bt_user_info_t *user_info; + + BT_CHECK_ENABLED(return); + BT_CHECK_PARAMETER(remote_address, return); + + if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HF_CONNECT) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } + + user_info = _bt_get_user_data(BT_HF); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t)); + + result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_HF_CONNECT, + in_param1, in_param2, in_param3, in_param4, + user_info->cb, user_info->user_data); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_hf_disconnect(bluetooth_device_address_t *remote_address) +{ + int result; + bt_user_info_t *user_info; + + BT_CHECK_PARAMETER(remote_address, return); + BT_CHECK_ENABLED(return); + + if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HF_DISCONNECT) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } + + user_info = _bt_get_user_data(BT_HF); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t)); + + result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_HF_DISCONNECT, + in_param1, in_param2, in_param3, in_param4, + user_info->cb, user_info->user_data); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_hf_answer_call() +{ + DBusMessage *reply; + DBusError err; + int ret = BLUETOOTH_ERROR_INTERNAL; + + BT_CHECK_ENABLED(return); + + reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE, + "AnswerCall", &err, DBUS_TYPE_INVALID); + if (!reply) { + BT_ERR("Error returned in method call\n"); + if (dbus_error_is_set(&err)) { + BT_ERR("Error = %s", err.message); + if (strcmp(err.message, "Operation not supported") == 0) + ret = BLUETOOTH_ERROR_NOT_IN_OPERATION; + else if (strcmp(err.message, "Operation not allowed") == 0) + ret = BLUETOOTH_ERROR_PERMISSION_DEINED; + else + ret = BLUETOOTH_ERROR_INTERNAL; + dbus_error_free(&err); + } + return ret; + } + + dbus_message_unref(reply); + + return BLUETOOTH_ERROR_NONE; + +} + +BT_EXPORT_API int bluetooth_hf_terminate_call() +{ + DBusMessage *reply; + DBusError err; + + BT_CHECK_ENABLED(return); + + reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE, + "TerminateCall", &err, DBUS_TYPE_INVALID); + if (!reply) { + BT_ERR("Error returned in method call\n"); + if (dbus_error_is_set(&err)) { + BT_ERR("Error = %s", err.message); + dbus_error_free(&err); + } + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_unref(reply); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_hf_initiate_call(char *number) +{ + DBusMessage *reply; + DBusError err; + int ret = BLUETOOTH_ERROR_INTERNAL; + + BT_CHECK_ENABLED(return); + + if (!number) + number = ""; + + reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE, + "InitiateCall", &err, DBUS_TYPE_STRING, &number, DBUS_TYPE_INVALID); + if (!reply) { + BT_ERR("Error returned in method call"); + if (dbus_error_is_set(&err)) { + BT_ERR("Error = %s", err.message); + if (strcmp(err.message, "NotConnected") == 0) + ret = BLUETOOTH_ERROR_NOT_CONNECTED; + else if (strcmp(err.message, "Operation not allowed") == 0) + ret = BLUETOOTH_ERROR_IN_PROGRESS; + else + ret = BLUETOOTH_ERROR_INTERNAL; + dbus_error_free(&err); + } + return ret; + } + + dbus_message_unref(reply); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_hf_voice_recognition(unsigned int status) +{ + DBusMessage *reply; + DBusError err; + + BT_CHECK_ENABLED(return); + + reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE, + "VoiceRecognition", &err, DBUS_TYPE_INT32, &status, DBUS_TYPE_INVALID); + if (!reply) { + BT_ERR("Error returned in method call\n"); + if (dbus_error_is_set(&err)) { + BT_ERR("Error = %s", err.message); + dbus_error_free(&err); + } + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_unref(reply); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_hf_audio_disconnect(void) +{ + DBusMessage *reply; + DBusError err; + + BT_CHECK_ENABLED(return); + + reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE, + "ScoDisconnect", &err, DBUS_TYPE_INVALID); + if (!reply) { + BT_ERR("Error returned in method call\n"); + if (dbus_error_is_set(&err)) { + BT_ERR("Error = %s", err.message); + dbus_error_free(&err); + } + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_unref(reply); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_hf_set_speaker_gain(unsigned int speaker_gain) +{ + DBusMessage *reply; + DBusError err; + + BT_CHECK_ENABLED(return); + + reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE, + "SpeakerGain", &err, DBUS_TYPE_UINT32, &speaker_gain, DBUS_TYPE_INVALID); + if (!reply) { + BT_ERR("Error returned in method call\n"); + if (dbus_error_is_set(&err)) { + BT_ERR("Error = %s", err.message); + dbus_error_free(&err); + } + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_unref(reply); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_hf_send_dtmf(char *dtmf) +{ + DBusMessage *reply; + DBusError err; + + BT_CHECK_ENABLED(return); + + reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE, + "SendDtmf", &err, DBUS_TYPE_STRING, &dtmf, DBUS_TYPE_INVALID); + if (!reply) { + BT_ERR("Error returned in method call\n"); + if (dbus_error_is_set(&err)) { + BT_ERR("Error = %s", err.message); + dbus_error_free(&err); + } + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_unref(reply); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_hf_send_xsat_cmd(int app_id, char *xsat_cmd) +{ + DBusMessage *reply; + DBusError err; + char buffer[200] = {0,}; + char *ptr = buffer; + + BT_CHECK_ENABLED(return); + + strcpy(buffer, "AT+XSAT="); + snprintf(buffer + strlen(buffer), sizeof(buffer), "%d,", app_id); + strncat(buffer, xsat_cmd, (sizeof(buffer) - 1) - strlen(buffer)); + BT_DBG("Xsat cmd received = %s", buffer); + reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE, + "SendAtCmd", &err, DBUS_TYPE_STRING, + &ptr, DBUS_TYPE_INVALID); + if (!reply) { + BT_ERR("Error returned in method call\n"); + if (dbus_error_is_set(&err)) { + BT_ERR("Error = %s", err.message); + dbus_error_free(&err); + } + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_unref(reply); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_hf_release_and_accept(void) +{ + DBusMessage *reply; + DBusError err; + + BT_CHECK_ENABLED(return); + + reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE, + "ReleaseAndAccept", &err, DBUS_TYPE_INVALID); + if (!reply) { + BT_ERR("Error returned in method call\n"); + if (dbus_error_is_set(&err)) { + BT_ERR("Error = %s", err.message); + dbus_error_free(&err); + } + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_unref(reply); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_hf_swap_call(void) +{ + DBusMessage *reply; + DBusError err; + + BT_CHECK_ENABLED(return); + + reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE, + "CallSwap", &err, DBUS_TYPE_INVALID); + if (!reply) { + BT_ERR("Error returned in method call\n"); + if (dbus_error_is_set(&err)) { + BT_ERR("Error = %s", err.message); + dbus_error_free(&err); + } + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_unref(reply); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_hf_release_all_call(void) +{ + DBusMessage *reply; + DBusError err; + + BT_CHECK_ENABLED(return); + + reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE, + "ReleaseAllCall", &err, DBUS_TYPE_INVALID); + if (!reply) { + BT_ERR("Error returned in method call\n"); + if (dbus_error_is_set(&err)) { + BT_ERR("Error = %s", err.message); + dbus_error_free(&err); + } + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_unref(reply); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_hf_join_call(void) +{ + DBusMessage *reply; + DBusError err; + + BT_CHECK_ENABLED(return); + + reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE, + "JoinCall", &err, DBUS_TYPE_INVALID); + if (!reply) { + BT_ERR("Error returned in method call\n"); + if (dbus_error_is_set(&err)) { + BT_ERR("Error = %s", err.message); + dbus_error_free(&err); + } + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_unref(reply); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_hf_get_call_list(void *call_list, + bt_hf_call_status_info_t **call_status) +{ + int i; + GList *list = call_list; + int call_count; + bt_hf_call_status_info_t * call_info; + + BT_CHECK_ENABLED(return); + retv_if(list == NULL, BLUETOOTH_ERROR_INVALID_PARAM); + retv_if(call_status == NULL, BLUETOOTH_ERROR_INVALID_PARAM); + + call_count = g_list_length(list); + + BT_DBG(" call_count = [%d]", call_count); + + for (i = 0; i < call_count; i++) { + call_info = g_list_nth_data(list, i); + BT_DBG(" direction = [%d]", call_info->direction); + BT_DBG(" status = [%d]", call_info->status); + BT_DBG(" mpart = [%d]", call_info->mpart); + BT_DBG(" number = [%s]", call_info->number); + BT_DBG(" idx = [%d]", call_info->idx); + call_status[i] = call_info; + } + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_hf_free_call_list(bt_hf_call_list_s *call_list) +{ + bt_hf_call_list_s *handle; + bt_hf_call_status_info_t *call_status; + + retv_if(call_list == NULL, BLUETOOTH_ERROR_INVALID_PARAM); + + handle = (bt_hf_call_list_s *)call_list; + do { + call_status = (bt_hf_call_status_info_t *)g_list_nth_data( + handle->list, 0); + if (call_status == NULL) + break; + handle->list = g_list_remove(handle->list, call_status); + g_free(call_status->number); + g_free(call_status); + } while (1); + g_free(handle); + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_hf_request_call_list( + bt_hf_call_list_s **call_list) +{ + DBusMessage *reply; + DBusError err; + + BT_CHECK_ENABLED(return); + + reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE, + "RequestCallList", &err, DBUS_TYPE_INVALID); + if (!reply) { + BT_ERR("dbus Error or call list is null\n"); + if (dbus_error_is_set(&err)) { + BT_ERR("Error = %s", err.message); + dbus_error_free(&err); + } + *call_list = NULL; + return BLUETOOTH_ERROR_INTERNAL; + } + __bt_hf_agent_read_call_list(reply, call_list); + + dbus_message_unref(reply); + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_hf_get_codec(unsigned int *codec_id) +{ + DBusMessage *reply; + DBusError err; + DBusMessageIter iter; + int32_t current_codec; + + BT_CHECK_ENABLED(return); + + reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE, + "GetCurrentCodec", &err, DBUS_TYPE_INVALID); + if (!reply) { + BT_ERR("Error returned in method call\n"); + if (dbus_error_is_set(&err)) { + BT_ERR("Error = %s", err.message); + dbus_error_free(&err); + } + return BLUETOOTH_ERROR_INTERNAL; + } + dbus_message_iter_init(reply, &iter); + dbus_message_iter_get_basic(&iter, ¤t_codec); + *codec_id = current_codec; + BT_DBG(" Codec ID is : %d", *codec_id); + + dbus_message_unref(reply); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_hf_get_audio_connected(unsigned int *audio_connected) +{ + DBusMessage *reply; + DBusError err; + DBusMessageIter iter; + int32_t sco_audio_connected_from_bt_agent; + + BT_CHECK_ENABLED(return); + + reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE, + "GetAudioConnected", &err, DBUS_TYPE_INVALID); + if (!reply) { + BT_ERR("Error returned in method call\n"); + if (dbus_error_is_set(&err)) { + BT_ERR("Error = %s", err.message); + dbus_error_free(&err); + } + return BLUETOOTH_ERROR_INTERNAL; + } + dbus_message_iter_init(reply, &iter); + dbus_message_iter_get_basic(&iter, &sco_audio_connected_from_bt_agent); + *audio_connected = sco_audio_connected_from_bt_agent; + + if (*audio_connected == BLUETOOTH_HF_AUDIO_CONNECTED) { + BT_DBG("SCO Audio is Connected"); + } else { + BT_DBG("SCO Audio is Disconnected"); + } + + dbus_message_unref(reply); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_hf_is_hf_connected(gboolean *hf_connected) +{ + DBusMessage *reply; + DBusError err; + DBusMessageIter iter; + gboolean hf_connected_from_bt_agent; + + BT_CHECK_ENABLED(return); + + reply = __bt_hf_agent_dbus_send(BT_HF_OBJECT_PATH, BT_HF_INTERFACE, + "IsHfConnected", &err, DBUS_TYPE_INVALID); + if (!reply) { + BT_ERR("Error returned in method call\n"); + if (dbus_error_is_set(&err)) { + BT_ERR("Error = %s", err.message); + dbus_error_free(&err); + } + return BLUETOOTH_ERROR_INTERNAL; + } + dbus_message_iter_init(reply, &iter); + dbus_message_iter_get_basic(&iter, &hf_connected_from_bt_agent); + *hf_connected = hf_connected_from_bt_agent; + + BT_DBG("%s", *hf_connected ? "Connected":"Disconnected"); + + dbus_message_unref(reply); + + return BLUETOOTH_ERROR_NONE; +} + diff --git a/bt-api/bt-avrcp.c b/bt-api/bt-avrcp.c old mode 100644 new mode 100755 index 1d705aa..bac1c89 --- a/bt-api/bt-avrcp.c +++ b/bt-api/bt-avrcp.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -119,16 +123,29 @@ BT_EXPORT_API int bluetooth_media_player_change_track( memset(&meta_data, 0x00, sizeof(media_metadata_t)); - if (_bt_copy_utf8_string(meta_data.title, metadata->title, BT_NAME_MAX)) - BT_DBG("Error in copying Title\n"); - if (_bt_copy_utf8_string(meta_data.artist, metadata->artists[0], BT_NAME_MAX)) - BT_DBG("Error in copying Artist\n"); - if (_bt_copy_utf8_string(meta_data.album, metadata->album, BT_NAME_MAX)) - BT_DBG("Error in copying Album\n"); - if (_bt_copy_utf8_string(meta_data.genre, metadata->genres[0], BT_NAME_MAX)) - BT_DBG("Error in copying Genre\n"); + if (_bt_copy_utf8_string(meta_data.title, metadata->title, BT_META_DATA_MAX_LEN)) + BT_ERR("Error in copying Title\n"); + if (_bt_copy_utf8_string(meta_data.artist, metadata->artist, BT_META_DATA_MAX_LEN)) + BT_ERR("Error in copying Artist\n"); + if (_bt_copy_utf8_string(meta_data.album, metadata->album, BT_META_DATA_MAX_LEN)) + BT_ERR("Error in copying Album\n"); + if (_bt_copy_utf8_string(meta_data.genre, metadata->genre, BT_META_DATA_MAX_LEN)) + BT_ERR("Error in copying Genre\n"); + + if (_bt_utf8_validate(meta_data.title) == FALSE) + meta_data.title[0] = '\0'; + + if (_bt_utf8_validate(meta_data.artist) == FALSE) + meta_data.artist[0] = '\0'; + + if (_bt_utf8_validate(meta_data.album) == FALSE) + meta_data.album[0] = '\0'; + + if (_bt_utf8_validate(meta_data.genre) == FALSE) + meta_data.genre[0] = '\0'; - meta_data.number = metadata->tracknumber; + meta_data.total_tracks = metadata->total_tracks; + meta_data.number = metadata->number; meta_data.duration = metadata->duration; g_array_append_vals(in_param1, &meta_data, sizeof(media_metadata_t)); @@ -140,3 +157,209 @@ BT_EXPORT_API int bluetooth_media_player_change_track( return result; } + +BT_EXPORT_API int bluetooth_media_control_init(media_cb_func_ptr callback_ptr, + void *user_data) +{ + int ret; + + /* Register AVRCP events */ + ret = _bt_register_event(BT_AVRCP_CONTROL_EVENT, + (void *)callback_ptr, user_data); + + if (ret != BLUETOOTH_ERROR_NONE && + ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) { + BT_ERR("Fail to init the event handler"); + return ret; + } + + _bt_set_user_data(BT_AVRCP, (void *)callback_ptr, user_data); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_media_control_deinit(void) +{ + int ret; + + ret = _bt_unregister_event(BT_AVRCP_CONTROL_EVENT); + + if (ret != BLUETOOTH_ERROR_NONE) { + BT_ERR("Fail to deinit the event handler"); + return ret; + } + + _bt_set_user_data(BT_AVRCP, NULL, NULL); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_media_control_connect( + bluetooth_device_address_t *remote_address) +{ + int result; + bt_user_info_t *user_info; + + BT_CHECK_PARAMETER(remote_address, return); + BT_CHECK_ENABLED(return); + + if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_AVRCP_CONTROL_CONNECT) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } + + user_info = _bt_get_user_data(BT_AVRCP); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, remote_address, + sizeof(bluetooth_device_address_t)); + + result = _bt_send_request_async(BT_BLUEZ_SERVICE, + BT_AVRCP_CONTROL_CONNECT, in_param1, + in_param2, in_param3, in_param4, + user_info->cb, user_info->user_data); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_media_control_disconnect( + bluetooth_device_address_t *remote_address) +{ + int result; + bt_user_info_t *user_info; + + BT_CHECK_PARAMETER(remote_address, return); + BT_CHECK_ENABLED(return); + + if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_AVRCP_CONTROL_DISCONNECT) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } + + user_info = _bt_get_user_data(BT_AVRCP); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, remote_address, + sizeof(bluetooth_device_address_t)); + + result = _bt_send_request_async(BT_BLUEZ_SERVICE, + BT_AVRCP_CONTROL_DISCONNECT, in_param1, + in_param2, in_param3, in_param4, + user_info->cb, user_info->user_data); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_media_control_command( + media_player_control_cmd type) +{ + int result; + + BT_CHECK_ENABLED(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, &type, sizeof(int)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_AVRCP_HANDLE_CONTROL, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_media_control_set_property( + media_player_property_type type, + unsigned int value) +{ + int result; + + BT_CHECK_ENABLED(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, &type, sizeof(int)); + g_array_append_vals(in_param2, &value, sizeof(unsigned int)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, + BT_AVRCP_CONTROL_SET_PROPERTY, + in_param1, in_param2, in_param3, + in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_media_control_get_property( + media_player_property_type type, + unsigned int *value) +{ + int result; + + BT_CHECK_PARAMETER(value, return); + BT_CHECK_ENABLED(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + g_array_append_vals(in_param1, &type, sizeof(int)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, + BT_AVRCP_CONTROL_GET_PROPERTY, + in_param1, in_param2, in_param3, + in_param4, &out_param); + + if (result == BLUETOOTH_ERROR_NONE) + *value = g_array_index(out_param, int, 0); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_media_control_get_track_info( + media_metadata_attributes_t *metadata) +{ + int result; + media_metadata_t meta_data; + + BT_CHECK_PARAMETER(metadata, return); + BT_CHECK_ENABLED(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_AVRCP_GET_TRACK_INFO, + in_param1, in_param2, in_param3, in_param4, &out_param); + + memset(&meta_data, 0x00, sizeof(media_metadata_t)); + + meta_data = g_array_index(out_param, media_metadata_t, 0); + + metadata->title = g_strdup(meta_data.title); + metadata->artist = g_strdup(meta_data.artist); + metadata->album = g_strdup(meta_data.album); + metadata->genre = g_strdup(meta_data.genre); + metadata->total_tracks = meta_data.total_tracks; + metadata->number = meta_data.number; + metadata->duration = (int64_t) meta_data.duration; + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} diff --git a/bt-api/bt-common.c b/bt-api/bt-common.c old mode 100644 new mode 100755 index 74f8a24..ec27d46 --- a/bt-api/bt-common.c +++ b/bt-api/bt-common.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -22,6 +26,12 @@ #include #include #include +#include +#include + + +#include + #include "bluetooth-api.h" #include "bluetooth-audio-api.h" @@ -35,6 +45,61 @@ static bt_user_info_t user_info[BT_MAX_USER_INFO]; static DBusGConnection *system_conn = NULL; +static GDBusConnection *system_gdbus_conn = NULL; + +static char *cookie; +static size_t cookie_size; + +static guint bus_id; + +static GDBusConnection *system_gconn = NULL; + +GDBusConnection *_bt_gdbus_init_system_gconn(void) +{ + GError *error = NULL; + + if (!g_thread_supported()) { + g_thread_init(NULL); + } + + dbus_g_thread_init(); + + g_type_init(); + + if (system_gconn != NULL) + return system_gconn; + + system_gconn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + + if (!system_gconn) { + BT_ERR("Unable to connect to dbus: %s", error->message); + g_clear_error(&error); + } + + return system_gconn; +} + +GDBusConnection *_bt_gdbus_get_system_gconn(void) +{ + GDBusConnection *local_system_gconn = NULL; + GError *error = NULL; + + if (system_gconn == NULL) { + system_gconn = _bt_gdbus_init_system_gconn(); + } else if (g_dbus_connection_is_closed(system_gconn)){ + + local_system_gconn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + + if (!local_system_gconn) { + BT_ERR("Unable to connect to dbus: %s", error->message); + g_clear_error(&error); + } + + system_gconn = local_system_gconn; + } + + return system_gconn; +} void _bt_print_device_address_t(const bluetooth_device_address_t *addr) { @@ -92,6 +157,20 @@ void _bt_headset_event_cb(int event, int result, void *param, user_data); } +void _bt_hf_event_cb(int event, int result, void *param, + void *callback, void *user_data) +{ + bt_hf_event_param_t bt_event = { 0, }; + bt_event.event = event; + bt_event.result = result; + bt_event.param_data = param; + + if (callback) + ((bt_hf_func_ptr)callback)(bt_event.event, &bt_event, + user_data); +} + + void _bt_avrcp_event_cb(int event, int result, void *param, void *callback, void *user_data) { @@ -131,7 +210,7 @@ void _bt_convert_addr_string_to_type(unsigned char *addr, for (i = 0; i < BT_ADDRESS_LENGTH_MAX; i++) { addr[i] = strtol(address, &ptr, 16); - if (ptr != NULL) { + if (ptr[0] != '\0') { if (ptr[0] != ':') return; @@ -155,7 +234,7 @@ void _bt_convert_addr_type_to_string(char *address, int _bt_copy_utf8_string(char *dest, const char *src, unsigned int length) { int i; - char *p = src; + const char *p = src; char *next; int count; @@ -177,53 +256,789 @@ int _bt_copy_utf8_string(char *dest, const char *src, unsigned int length) return BLUETOOTH_ERROR_NONE; } -static char *__bt_extract_adapter_path(DBusMessageIter *msg_iter) +gboolean _bt_utf8_validate(char *name) { - char *object_path = NULL; - DBusMessageIter value_iter; + BT_DBG("+"); + gunichar2 *u16; + glong items_written = 0; - /* Parse the signature: oa{sa{sv}}} */ - retv_if(dbus_message_iter_get_arg_type(msg_iter) != - DBUS_TYPE_OBJECT_PATH, NULL); + if (FALSE == g_utf8_validate(name, -1, NULL)) + return FALSE; - dbus_message_iter_get_basic(msg_iter, &object_path); - retv_if(object_path == NULL, NULL); + u16 = g_utf8_to_utf16(name, -1, NULL, &items_written, NULL); + if (u16 == NULL) + return FALSE; - /* object array (oa) */ - retv_if(dbus_message_iter_next(msg_iter) == FALSE, NULL); - retv_if(dbus_message_iter_get_arg_type(msg_iter) != - DBUS_TYPE_ARRAY, NULL); + g_free(u16); - dbus_message_iter_recurse(msg_iter, &value_iter); + if (items_written != g_utf8_strlen(name, -1)) + return FALSE; - /* string array (sa) */ - while (dbus_message_iter_get_arg_type(&value_iter) == - DBUS_TYPE_DICT_ENTRY) { - char *interface_name = NULL; - DBusMessageIter interface_iter; + BT_DBG("-"); + return TRUE; +} - dbus_message_iter_recurse(&value_iter, &interface_iter); - retv_if(dbus_message_iter_get_arg_type(&interface_iter) != - DBUS_TYPE_STRING, NULL); +static GDBusProxy *profile_gproxy; +static GDBusConnection *gconn; +static int latest_id = -1; +#define BT_RFCOMM_ID_MAX 245 +static gboolean id_used[BT_RFCOMM_ID_MAX]; +GDBusNodeInfo *new_conn_node; + +static const gchar rfcomm_agent_xml[] = +"" +" " +" " +" " +" " +" " +" " +" " +""; + +/* Remote socket address */ +struct sockaddr_remote { + sa_family_t family; + bluetooth_device_address_t remote_bdaddr; + unsigned char channel; +}; + +static void __get_remote_address(int fd, bluetooth_device_address_t *bdaddr) +{ + struct sockaddr_remote address; + socklen_t address_len; - dbus_message_iter_get_basic(&interface_iter, &interface_name); + address_len = sizeof(address); + if (getpeername(fd, (struct sockaddr *) &address, &address_len) != 0) { + BT_DBG("getpeername failed"); + return; + } - if (g_strcmp0(interface_name, "org.bluez.Adapter1") == 0) { - /* Tizen don't allow the multi-adapter */ - BT_DBG("Found an adapter: %s", object_path); - return g_strdup(object_path); + memcpy(bdaddr->addr, address.remote_bdaddr.addr, + BLUETOOTH_ADDRESS_LENGTH); +} + +static void __new_connection_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) +{ + BT_DBG("method %s", method_name); + if (g_strcmp0(method_name, "NewConnection") == 0) { + int index; + GDBusMessage *msg; + GUnixFDList *fd_list; + GVariantBuilder *properties; + char *obj_path; + char addr[20]; + bluetooth_device_address_t remote_addr, remote_addr1; + bt_new_connection_cb cb = user_data; + int fd; + + g_variant_get(parameters, "(oha{sv})", &obj_path, &index, + &properties); + + msg = g_dbus_method_invocation_get_message(invocation); + fd_list = g_dbus_message_get_unix_fd_list(msg); + if (fd_list == NULL) { + GQuark quark = g_quark_from_string("rfcomm-app"); + GError *err = g_error_new(quark, 0, "No fd in message"); + g_dbus_method_invocation_return_gerror(invocation, err); + g_error_free(err); + return; } - dbus_message_iter_next(&value_iter); + + fd = g_unix_fd_list_get(fd_list, index, NULL); + if (fd == -1) { + BT_ERR("Invalid fd return"); + GQuark quark = g_quark_from_string("rfcomm-app"); + GError *err = g_error_new(quark, 0, "Invalid FD return"); + g_dbus_method_invocation_return_gerror(invocation, err); + g_error_free(err); + return; + } + + __get_remote_address(fd, &remote_addr); + _bt_swap_addr(remote_addr1.addr, remote_addr.addr); + _bt_convert_addr_type_to_string(addr, remote_addr1.addr); + BT_INFO("fd: %d, address %s", fd, addr); + + g_dbus_method_invocation_return_value(invocation, NULL); + + if (cb) + cb(object_path, fd, &remote_addr1); + } +} + + +static const GDBusInterfaceVTable method_table = { + __new_connection_method, + NULL, + NULL, +}; + +void _bt_swap_addr(unsigned char *dst, const unsigned char *src) +{ + int i; + + for (i = 0; i < 6; i++) + dst[i] = src[5-i]; +} + +int __rfcomm_assign_id(void) +{ + int index; + + BT_DBG("latest_id: %d", latest_id); + + index = latest_id + 1; + + if (index >= BT_RFCOMM_ID_MAX) + index = 0; + + BT_DBG("index: %d", index); + + while (id_used[index] == TRUE) { + if (index == latest_id) { + /* No available ID */ + BT_ERR("All request ID is used"); + return -1; + } + + index++; + + if (index >= BT_RFCOMM_ID_MAX) + index = 0; + } + + latest_id = index; + id_used[index] = TRUE; + + BT_DBG("Assigned Id: %d", latest_id); + + return latest_id; +} + +void __rfcomm_delete_id(int id) +{ + ret_if(id >= BT_RFCOMM_ID_MAX); + ret_if(id < 0); + + id_used[id] = FALSE; + + /* Next server will use this ID */ + latest_id = id - 1; +} + +static GDBusConnection *__get_gdbus_connection() +{ + GError *err = NULL; + + if (gconn == NULL) + gconn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err); + + if (!gconn) { + if (err) { + BT_ERR("Unable to connect to dbus: %s", err->message); + g_clear_error(&err); + } + return NULL; + } + + return gconn; +} + +static GDBusProxy *__bt_gdbus_get_profile_proxy(void) +{ + GDBusConnection *gconn; + GError *err = NULL; + + if (profile_gproxy) + return profile_gproxy; + + gconn = __get_gdbus_connection(); + if (gconn == NULL) + return NULL; + + profile_gproxy = g_dbus_proxy_new_sync(gconn, G_DBUS_PROXY_FLAGS_NONE, + NULL, BT_BLUEZ_NAME, + "/org/bluez", + "org.bluez.ProfileManager1", + NULL, &err); + if (err) { + BT_ERR("Unable to create proxy: %s", err->message); + g_clear_error(&err); + } + + return profile_gproxy; +} + +void _bt_unregister_gdbus(int object_id) +{ + GDBusConnection *gconn; + + gconn = __get_gdbus_connection(); + if (gconn == NULL) + return; + + g_dbus_connection_unregister_object(gconn, object_id); +} + +int _bt_register_new_conn(const char *path, bt_new_connection_cb cb) +{ + GDBusConnection *gconn; + int id; + GError *error = NULL; + + gconn = __get_gdbus_connection(); + if (gconn == NULL) + return -1; + + if (new_conn_node == NULL) + new_conn_node = _bt_get_gdbus_node(rfcomm_agent_xml); + + if (new_conn_node == NULL) + return -1; + + id = g_dbus_connection_register_object(gconn, path, + new_conn_node->interfaces[0], + &method_table, + cb, NULL, &error); + if (id == 0) { + BT_ERR("Failed to register: %s", error->message); + g_error_free(error); + return -1; + } + + BT_DBG("NEW CONNECTION ID %d", id); + + return id; +} + + +int _bt_register_profile(bt_register_profile_info_t *info, gboolean use_default_rfcomm) +{ + GVariantBuilder *option_builder; + GVariant *ret; + GDBusProxy *proxy; + GError *err = NULL; + int result = BLUETOOTH_ERROR_NONE; + + proxy = __bt_gdbus_get_profile_proxy(); + if (proxy == NULL) { + BT_ERR("Getting profile proxy failed"); + return BLUETOOTH_ERROR_INTERNAL; + } + + option_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); + if (info->authentication) + g_variant_builder_add(option_builder, "{sv}", + "RequireAuthentication", + g_variant_new_boolean(TRUE)); + if (info->authorization) + g_variant_builder_add(option_builder, "{sv}", + "RequireAuthorization", + g_variant_new_boolean(TRUE)); + if (info->role) + g_variant_builder_add(option_builder, "{sv}", + "Role", + g_variant_new_string(info->role)); + + /* Setting RFCOMM channel to default value 0; would allow bluez to assign + * RFCOMM channels based on the availability when two services want + * to use the RFCOMM along with SPP. Hence bluez makes sure that no + * two services use the same SPP RFCOMM channel. */ + if (use_default_rfcomm) + g_variant_builder_add(option_builder, "{sv}", + "Channel", + g_variant_new_uint16(RFCOMM_DEFAULT_PROFILE_CHANNEL)); + if (info->service) + g_variant_builder_add(option_builder, "{sv}", + "Service", + g_variant_new_string(info->service)); + + + ret = g_dbus_proxy_call_sync(proxy, "RegisterProfile", + g_variant_new("(osa{sv})", info->obj_path, + info->uuid, + option_builder), + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, &err); + if (err) { + BT_ERR("RegisterProfile failed: %s", err->message); + + if (g_strrstr(err->message, BT_ACCESS_DENIED_MSG)) + result = BLUETOOTH_ERROR_ACCESS_DENIED; + else + result = BLUETOOTH_ERROR_INTERNAL; + + g_clear_error(&err); + } + + g_variant_builder_unref(option_builder); + + if (ret) + g_variant_unref(ret); + + return result; +} + +int _bt_register_profile_platform(bt_register_profile_info_t *info, gboolean use_default_rfcomm) +{ + GVariantBuilder *option_builder; + GVariant *ret; + GDBusProxy *proxy; + GError *err = NULL; + int result = BLUETOOTH_ERROR_NONE; + + proxy = __bt_gdbus_get_profile_proxy(); + if (proxy == NULL) { + BT_ERR("Getting profile proxy failed"); + return BLUETOOTH_ERROR_INTERNAL; + } + + option_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); + if (info->authentication) + g_variant_builder_add(option_builder, "{sv}", + "RequireAuthentication", + g_variant_new_boolean(TRUE)); + if (info->authorization) + g_variant_builder_add(option_builder, "{sv}", + "RequireAuthorization", + g_variant_new_boolean(TRUE)); + if (info->role) + g_variant_builder_add(option_builder, "{sv}", + "Role", + g_variant_new_string(info->role)); + + /* Setting RFCOMM channel to default value 0; would allow bluez to assign + * RFCOMM channels based on the availability when two services want + * to use the RFCOMM along with SPP. Hence bluez makes sure that no + * two services use the same SPP RFCOMM channel. */ + if (use_default_rfcomm) + g_variant_builder_add(option_builder, "{sv}", + "Channel", + g_variant_new_uint16(RFCOMM_DEFAULT_PROFILE_CHANNEL)); + if (info->service) + g_variant_builder_add(option_builder, "{sv}", + "Service", + g_variant_new_string(info->service)); + + + ret = g_dbus_proxy_call_sync(proxy, "RegisterProfile1", + g_variant_new("(osa{sv})", info->obj_path, + info->uuid, + option_builder), + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, &err); + if (err) { + BT_ERR("RegisterProfile failed: %s", err->message); + + if (g_strrstr(err->message, BT_ACCESS_DENIED_MSG)) + result = BLUETOOTH_ERROR_ACCESS_DENIED; + else + result = BLUETOOTH_ERROR_INTERNAL; + + g_clear_error(&err); + } + + g_variant_builder_unref(option_builder); + + if (ret) + g_variant_unref(ret); + + return result; +} + + +void _bt_unregister_profile(char *path) +{ + GVariant *ret; + GDBusProxy *proxy; + GError *err = NULL; + + proxy = __bt_gdbus_get_profile_proxy(); + if (proxy == NULL) { + BT_ERR("Getting profile proxy failed"); + return; + } + + ret = g_dbus_proxy_call_sync(proxy, "UnregisterProfile", + g_variant_new("(o)", path), + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, &err); + if (err) { + BT_ERR("UnregisterProfile failed : %s", err->message); + g_clear_error(&err); + } + + if (ret) + g_variant_unref(ret); + + return; +} + +GDBusNodeInfo * _bt_get_gdbus_node(const gchar *xml_data) +{ + if (bus_id == 0) { + char *name = g_strdup_printf("org.bt.frwk%d", getpid()); + + bus_id = g_bus_own_name(G_BUS_TYPE_SYSTEM, + name, + G_BUS_NAME_OWNER_FLAGS_NONE, + NULL, + NULL, + NULL, + NULL, + NULL); + BT_DBG("Got bus id %d", bus_id); + g_free(name); + } + + return g_dbus_node_info_new_for_xml(xml_data, NULL); +} + +int _bt_connect_profile(char *address, char *uuid, void *cb, + gpointer func_data) +{ + char *object_path; + DBusGProxy *proxy; + DBusGConnection *conn; + DBusGProxy *adapter_proxy; + GError *error = NULL; + + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + object_path = _bt_get_device_object_path(address); + if (object_path == NULL) { + BT_ERR("No searched device"); + + adapter_proxy = _bt_get_adapter_proxy(conn); + retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call(adapter_proxy, "CreateDevice", &error, + G_TYPE_STRING, address, + G_TYPE_INVALID, G_TYPE_INVALID); + + if (error != NULL) { + BT_ERR("CreateDevice Fail: %s", error->message); + g_error_free(error); + } + + object_path = _bt_get_device_object_path(address); + } + retv_if(object_path == NULL, BLUETOOTH_ERROR_INTERNAL); + + + proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + object_path, BT_DEVICE_INTERFACE); + g_free(object_path); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + if (!dbus_g_proxy_begin_call(proxy, "ConnectProfile", + (DBusGProxyCallNotify)cb, + func_data, NULL, + G_TYPE_STRING, uuid, + G_TYPE_INVALID)) { + BT_ERR("Connect Dbus Call Error"); + g_object_unref(proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + return BLUETOOTH_ERROR_NONE; +} + +int _bt_discover_services(char *address, char *uuid, void *cb, + gpointer func_data) +{ + char *object_path; + DBusGProxy *proxy; + DBusGConnection *conn; + DBusGProxy *adapter_proxy; + GError *error = NULL; + + int timeout = 10000; + BT_DBG("+"); + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + object_path = _bt_get_device_object_path(address); + if (object_path == NULL) { + BT_ERR("No searched device"); + + adapter_proxy = _bt_get_adapter_proxy(conn); + retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call(adapter_proxy, "CreateDevice", &error, + G_TYPE_STRING, address, + G_TYPE_INVALID, G_TYPE_INVALID); + + if (error != NULL) { + BT_ERR("CreateDevice Fail: %s", error->message); + g_error_free(error); + } + + object_path = _bt_get_device_object_path(address); + } + retv_if(object_path == NULL, BLUETOOTH_ERROR_INTERNAL); + + proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + object_path, BT_DEVICE_INTERFACE); + g_free(object_path); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + if (!dbus_g_proxy_begin_call_with_timeout(proxy, "DiscoverServices", + (DBusGProxyCallNotify)cb, + func_data, NULL, timeout, + G_TYPE_STRING, uuid, + G_TYPE_INVALID)) { + BT_ERR("Error: While calling DiscoverServices"); + g_object_unref(proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; +} + +int _bt_cancel_discovers(char *address) +{ + char *object_path; + DBusGProxy *proxy; + DBusGConnection *conn; + BT_DBG("+"); + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + object_path = _bt_get_device_object_path(address); + retv_if(object_path == NULL, BLUETOOTH_ERROR_INTERNAL); + + proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + object_path, BT_DEVICE_INTERFACE); + g_free(object_path); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + if (!dbus_g_proxy_call(proxy, + "CancelDiscovery", + NULL, + G_TYPE_INVALID, G_TYPE_INVALID)) { + BT_ERR("Error: while CancelDiscovery"); + g_object_unref(proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + g_object_unref(proxy); + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; +} + +int _bt_discover_service_uuids(char *address, char *remote_uuid) +{ + char *object_path; + DBusGProxy *proxy; + DBusGConnection *conn; + GHashTable *hash = NULL; + GValue *value; + char **uuid_value; + int i =0; + int result = BLUETOOTH_ERROR_INTERNAL; + retv_if(remote_uuid == NULL, BLUETOOTH_ERROR_INTERNAL); + + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + object_path = _bt_get_device_object_path(address); + retv_if(object_path == NULL, BLUETOOTH_ERROR_INTERNAL); + + proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + object_path, BT_PROPERTIES_INTERFACE); + g_free(object_path); + + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + if (!dbus_g_proxy_call(proxy, "GetAll", NULL, + G_TYPE_STRING, BT_DEVICE_INTERFACE, + G_TYPE_INVALID, + dbus_g_type_get_map("GHashTable", G_TYPE_STRING, + G_TYPE_VALUE), &hash, G_TYPE_INVALID)) { + BT_ERR("Dbus error while GetAll"); + g_object_unref(proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + g_object_unref(proxy); + BT_DBG("Remote uuids %s", remote_uuid); + value = g_hash_table_lookup(hash, "UUIDs"); + if (value == NULL) { + BT_ERR("No uuids found"); + goto done; + } + + uuid_value = g_value_get_boxed(value); + if(uuid_value == NULL) { + BT_ERR("Error: while obtaining uuids"); + goto done; + } + + for (i = 0; uuid_value[i] != NULL; i++) { + BT_DBG("Remote uuids %s", uuid_value[i]); + if (strcasecmp(uuid_value[i], remote_uuid) == 0) { + result = BLUETOOTH_ERROR_NONE; + goto done; + } + } + BT_INFO("Specified uuid not found on remote device"); +done: + if (hash) + g_hash_table_destroy(hash); + + return result; +} + +int _bt_disconnect_profile(char *address, char *uuid, void *cb, + gpointer func_data) +{ + char *object_path; + DBusGProxy *proxy; + DBusGConnection *conn; + + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + object_path = _bt_get_device_object_path(address); + retv_if(object_path == NULL, BLUETOOTH_ERROR_INTERNAL); + + + proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + object_path, BT_DEVICE_INTERFACE); + g_free(object_path); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + if (!dbus_g_proxy_begin_call(proxy, "DisconnectProfile", + (DBusGProxyCallNotify)cb, + func_data, NULL, + G_TYPE_STRING, uuid, + G_TYPE_INVALID)) { + BT_ERR("Connect Dbus Call Error"); + g_object_unref(proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + return BLUETOOTH_ERROR_NONE; +} + +int _bt_get_adapter_path(GDBusConnection *conn, char *path) +{ + GError *err = NULL; + GDBusProxy *manager_proxy = NULL; + GVariant *result = NULL; + char *adapter_path = NULL; + + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + manager_proxy = g_dbus_proxy_new_sync(conn, + G_DBUS_PROXY_FLAGS_NONE, NULL, + BT_BLUEZ_NAME, + BT_MANAGER_PATH, + BT_MANAGER_INTERFACE, + NULL, &err); + + if (!manager_proxy) { + BT_ERR("Unable to create proxy: %s", err->message); + goto fail; + } + + result = g_dbus_proxy_call_sync(manager_proxy, "DefaultAdapter", NULL, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err); + if (!result) { + if (err != NULL) + BT_ERR("Fail to get DefaultAdapter (Error: %s)", err->message); + else + BT_ERR("Fail to get DefaultAdapter"); + + goto fail; + } + + if (g_strcmp0(g_variant_get_type_string(result), "(o)")) { + BT_ERR("Incorrect result\n"); + goto fail; + } + + g_variant_get(result, "(&o)", &adapter_path); + + if (adapter_path == NULL || + strlen(adapter_path) >= BT_ADAPTER_OBJECT_PATH_MAX) { + BT_ERR("Adapter path is inproper\n"); + goto fail; + } + + if (path) + g_strlcpy(path, adapter_path, BT_ADAPTER_OBJECT_PATH_MAX); + + g_variant_unref(result); + g_object_unref(manager_proxy); + + return BLUETOOTH_ERROR_NONE; + +fail: + g_clear_error(&err); + + if (result) + g_variant_unref(result); + + if (manager_proxy) + g_object_unref(manager_proxy); + + return BLUETOOTH_ERROR_INTERNAL; + +} + +void _bt_convert_device_path_to_address(const char *device_path, + char *device_address) +{ + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + char *dev_addr; + + ret_if(device_path == NULL); + ret_if(device_address == NULL); + + dev_addr = strstr(device_path, "dev_"); + if (dev_addr != NULL) { + char *pos = NULL; + dev_addr += 4; + g_strlcpy(address, dev_addr, sizeof(address)); + + while ((pos = strchr(address, '_')) != NULL) { + *pos = ':'; + } + + g_strlcpy(device_address, address, BT_ADDRESS_STRING_SIZE); + } +} + +static char *__bt_extract_device_path(DBusMessageIter *msg_iter, char *address) +{ + char *object_path = NULL; + char device_address[BT_ADDRESS_STRING_SIZE] = { 0 }; + + /* Parse the signature: oa{sa{sv}}} */ + retv_if(dbus_message_iter_get_arg_type(msg_iter) != + DBUS_TYPE_OBJECT_PATH, NULL); + + dbus_message_iter_get_basic(msg_iter, &object_path); + retv_if(object_path == NULL, NULL); + + _bt_convert_device_path_to_address(object_path, device_address); + + if (g_strcmp0(address, device_address) == 0) { + return g_strdup(object_path); } return NULL; } -/* TO DO */ -/* Change DBusGConnection to DBusConnection*/ -int _bt_get_adapter_path(DBusGConnection *g_conn, char *path) +char *_bt_get_device_object_path(char *address) { DBusMessage *msg; DBusMessage *reply; @@ -231,21 +1046,16 @@ int _bt_get_adapter_path(DBusGConnection *g_conn, char *path) DBusMessageIter value_iter; DBusError err; DBusConnection *conn; - char *adapter_path = NULL; - - retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL); + char *object_path = NULL; - conn = dbus_g_connection_get_connection(g_conn); - retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + conn = _bt_get_system_conn(); + retv_if(conn == NULL, NULL); msg = dbus_message_new_method_call(BT_BLUEZ_NAME, BT_MANAGER_PATH, BT_MANAGER_INTERFACE, "GetManagedObjects"); - if (msg == NULL) { - BT_ERR("Can't allocate D-Bus message"); - goto fail; - } + retv_if(msg == NULL, NULL); /* Synchronous call */ dbus_error_init(&err); @@ -261,12 +1071,13 @@ int _bt_get_adapter_path(DBusGConnection *g_conn, char *path) BT_ERR("%s", err.message); dbus_error_free(&err); } - goto fail; + return NULL; } if (dbus_message_iter_init(reply, &reply_iter) == FALSE) { BT_ERR("Fail to iterate the reply"); - goto fail; + dbus_message_unref(reply); + return NULL; } dbus_message_iter_recurse(&reply_iter, &value_iter); @@ -278,44 +1089,60 @@ int _bt_get_adapter_path(DBusGConnection *g_conn, char *path) dbus_message_iter_recurse(&value_iter, &msg_iter); - adapter_path = __bt_extract_adapter_path(&msg_iter); - if (adapter_path != NULL) { - BT_DBG("Found the adapter path"); + object_path = __bt_extract_device_path(&msg_iter, address); + if (object_path != NULL) { + BT_DBG("Found the device path %s", object_path); break; } dbus_message_iter_next(&value_iter); } - if (adapter_path == NULL || - strlen(adapter_path) >= BT_ADAPTER_OBJECT_PATH_MAX) { - BT_ERR("Adapter path is inproper\n"); - goto fail; - } + dbus_message_unref(reply); - BT_DBG("adapter path: %s", adapter_path); - - if (path) - g_strlcpy(path, adapter_path, BT_ADAPTER_OBJECT_PATH_MAX); - - g_free(adapter_path); - - return BLUETOOTH_ERROR_NONE; - -fail: - g_free(adapter_path); - - return BLUETOOTH_ERROR_INTERNAL; + return object_path; } + DBusGProxy *_bt_get_adapter_proxy(DBusGConnection *conn) { + GError *err = NULL; + DBusGProxy *manager_proxy = NULL; DBusGProxy *adapter_proxy = NULL; + char *adapter_path = NULL; retv_if(conn == NULL, NULL); - adapter_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, - BT_BLUEZ_HCI_PATH, BT_PROPERTIES_INTERFACE); + manager_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + BT_MANAGER_PATH, BT_MANAGER_INTERFACE); + + retv_if(manager_proxy == NULL, NULL); + + if (!dbus_g_proxy_call(manager_proxy, "DefaultAdapter", &err, + G_TYPE_INVALID, DBUS_TYPE_G_OBJECT_PATH, + &adapter_path, + G_TYPE_INVALID)) { + if (err != NULL) { + BT_ERR("Getting DefaultAdapter failed: [%s]\n", err->message); + g_error_free(err); + } + g_object_unref(manager_proxy); + return NULL; + } + + if (adapter_path == NULL || strlen(adapter_path) >= BT_ADAPTER_OBJECT_PATH_MAX) { + BT_ERR("Adapter path is inproper\n"); + g_free(adapter_path); + g_object_unref(manager_proxy); + return NULL; + } + + adapter_proxy = dbus_g_proxy_new_for_name(conn, + BT_BLUEZ_NAME, + adapter_path, + BT_ADAPTER_INTERFACE); + g_free(adapter_path); + g_object_unref(manager_proxy); return adapter_proxy; } @@ -357,6 +1184,23 @@ DBusGConnection *_bt_get_system_gconn(void) return (system_conn) ? system_conn : __bt_init_system_gconn(); } +GDBusConnection *_bt_init_system_gdbus_conn(void) +{ + g_type_init(); + GError *error = NULL; + if (system_gdbus_conn == NULL) { + system_gdbus_conn = + g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (error) { + BT_ERR("GDBus connection Error : %s \n", + error->message); + g_clear_error(&error); + return NULL; + } + } + return system_gdbus_conn; +} + DBusConnection *_bt_get_system_conn(void) { DBusGConnection *g_conn; @@ -372,6 +1216,142 @@ DBusConnection *_bt_get_system_conn(void) return dbus_g_connection_get_connection(g_conn); } +void _bt_generate_cookie(void) +{ + int retval; + + ret_if(cookie != NULL); + + cookie_size = security_server_get_cookie_size(); + + cookie = g_malloc0((cookie_size*sizeof(char))+1); + + retval = security_server_request_cookie(cookie, cookie_size); + if(retval < 0) { + BT_ERR("Fail to get cookie: %d", retval); + } +} + +void _bt_destroy_cookie(void) +{ + g_free(cookie); + cookie = NULL; + cookie_size = 0; +} + +char *_bt_get_cookie(void) +{ + return cookie; +} + +int _bt_get_cookie_size(void) +{ + return cookie_size; +} + +int _bt_register_osp_server_in_agent(int type, char *uuid, char *path, int fd) +{ + int ret; + char uuid_str[BLUETOOTH_UUID_STRING_MAX] = { 0, }; + char path_str[BLUETOOTH_PATH_STRING] = { 0, }; + + BT_DBG("+"); + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, &type, sizeof(int)); + g_strlcpy(uuid_str, uuid, sizeof(uuid_str)); + g_array_append_vals(in_param2, &uuid_str, BLUETOOTH_UUID_STRING_MAX); + g_strlcpy(path_str, path, sizeof(path_str)); + g_array_append_vals(in_param3, &path_str, BLUETOOTH_PATH_STRING); + g_array_append_vals(in_param4, &fd, sizeof(int)); + + ret = _bt_send_request(BT_AGENT_SERVICE, BT_SET_AUTHORIZATION, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + BT_DBG("-"); + return ret; +} + +int _bt_unregister_osp_server_in_agent(int type, char *uuid) +{ + int ret; + char uuid_str[BLUETOOTH_UUID_STRING_MAX] = { 0, }; + char path_str[BLUETOOTH_PATH_STRING] = { 0, }; + + BT_DBG("+"); + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, &type, sizeof(int)); + g_strlcpy(uuid_str, uuid, sizeof(uuid_str)); + g_array_append_vals(in_param2, &uuid_str, BLUETOOTH_UUID_STRING_MAX); + + ret = _bt_send_request(BT_AGENT_SERVICE, BT_UNSET_AUTHORIZATION, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + BT_DBG("-"); + return ret; +} + +int _bt_check_privilege(int service_type, int service_function) +{ + int result; + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + result = _bt_send_request(service_type, service_function, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +GVariant *_bt_get_managed_objects(void) +{ + GDBusConnection *g_conn; + GDBusProxy *manager_proxy = NULL; + GVariant *result = NULL; + GError *error = NULL; + + BT_DBG("+"); + + g_conn = _bt_gdbus_get_system_gconn(); + retv_if(g_conn == NULL, NULL); + + manager_proxy = g_dbus_proxy_new_sync(g_conn, + G_DBUS_PROXY_FLAGS_NONE, NULL, + BT_BLUEZ_NAME, + BT_MANAGER_PATH, + BT_MANAGER_INTERFACE, + NULL, &error); + + if (error) { + BT_ERR("Unable to create proxy: %s", error->message); + g_clear_error(&error); + return NULL; + } + + result = g_dbus_proxy_call_sync (manager_proxy, + "GetManagedObjects", NULL, + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, &error); + + if (error) { + BT_ERR("Fail to get ManagedObjects (Error: %s)", error->message); + g_clear_error(&error); + } + + g_object_unref(manager_proxy); + + BT_DBG("-"); + return result; +} + BT_EXPORT_API int bluetooth_is_supported(void) { int is_supported = 0; @@ -381,12 +1361,12 @@ BT_EXPORT_API int bluetooth_is_supported(void) fd = open(RFKILL_NODE, O_RDONLY); if (fd < 0) { - BT_DBG("Fail to open RFKILL node"); + BT_ERR("Fail to open RFKILL node"); return BLUETOOTH_ERROR_INTERNAL; } if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { - BT_DBG("Fail to set RFKILL node to non-blocking"); + BT_ERR("Fail to set RFKILL node to non-blocking"); close(fd); return BLUETOOTH_ERROR_INTERNAL; } @@ -394,12 +1374,12 @@ BT_EXPORT_API int bluetooth_is_supported(void) while (1) { len = read(fd, &event, sizeof(event)); if (len < 0) { - BT_DBG("Fail to read events"); + BT_ERR("Fail to read events"); break; } if (len != RFKILL_EVENT_SIZE) { - BT_DBG("The size is wrong\n"); + BT_ERR("The size is wrong\n"); continue; } @@ -420,35 +1400,58 @@ BT_EXPORT_API int bluetooth_register_callback(bluetooth_cb_func_ptr callback_ptr { int ret; + _bt_gdbus_init_system_gconn(); __bt_init_system_gconn(); ret = _bt_init_event_handler(); - if (ret != BLUETOOTH_ERROR_NONE && ret != BLUETOOTH_ERROR_ALREADY_INITIALIZED) { BT_ERR("Fail to init the event handler"); return ret; } + _bt_generate_cookie(); + _bt_set_user_data(BT_COMMON, (void *)callback_ptr, user_data); /* Register All events */ - _bt_register_event(BT_ADAPTER_EVENT, (void *)callback_ptr, user_data); - _bt_register_event(BT_DEVICE_EVENT, (void *)callback_ptr, user_data); - _bt_register_event(BT_NETWORK_EVENT, (void *)callback_ptr, user_data); - _bt_register_event(BT_RFCOMM_CLIENT_EVENT, (void *)callback_ptr, user_data); - _bt_register_event(BT_RFCOMM_SERVER_EVENT, (void *)callback_ptr, user_data); + ret = _bt_register_event(BT_ADAPTER_EVENT, (void *)callback_ptr, user_data); + if (ret != BLUETOOTH_ERROR_NONE) + goto fail; + ret = _bt_register_event(BT_DEVICE_EVENT, (void *)callback_ptr, user_data); + if (ret != BLUETOOTH_ERROR_NONE) + goto fail; + ret = _bt_register_event(BT_NETWORK_EVENT, (void *)callback_ptr, user_data); + if (ret != BLUETOOTH_ERROR_NONE) + goto fail; + ret = _bt_register_event(BT_RFCOMM_CLIENT_EVENT, (void *)callback_ptr, user_data); + if (ret != BLUETOOTH_ERROR_NONE) + goto fail; + ret = _bt_register_event(BT_RFCOMM_SERVER_EVENT, (void *)callback_ptr, user_data); + if (ret != BLUETOOTH_ERROR_NONE) + goto fail; + + _bt_register_name_owner_changed(); return BLUETOOTH_ERROR_NONE; +fail: + BT_ERR("Fail to do _bt_register_event()"); + bluetooth_unregister_callback(); + return ret; } BT_EXPORT_API int bluetooth_unregister_callback(void) { - _bt_unregister_event(BT_ADAPTER_EVENT); - _bt_unregister_event(BT_DEVICE_EVENT); - _bt_unregister_event(BT_NETWORK_EVENT); - _bt_unregister_event(BT_RFCOMM_CLIENT_EVENT); - _bt_unregister_event(BT_RFCOMM_SERVER_EVENT); + int ret; + + _bt_destroy_cookie(); + + ret = _bt_deinit_event_handler(); + if (ret != BLUETOOTH_ERROR_NONE) { + BT_ERR("Fail to deinit the event handler"); + } + + _bt_unregister_name_owner_changed(); _bt_set_user_data(BT_COMMON, NULL, NULL); @@ -456,7 +1459,10 @@ BT_EXPORT_API int bluetooth_unregister_callback(void) dbus_g_connection_unref(system_conn); system_conn = NULL; } - + if (system_gconn) { + g_object_unref(system_gconn); + system_gconn = NULL; + } return BLUETOOTH_ERROR_NONE; } diff --git a/bt-api/bt-device.c b/bt-api/bt-device.c old mode 100644 new mode 100755 index b746e5f..dadaed2 --- a/bt-api/bt-device.c +++ b/bt-api/bt-device.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -32,6 +36,45 @@ BT_EXPORT_API int bluetooth_bond_device(const bluetooth_device_address_t *device BT_CHECK_PARAMETER(device_address, return); BT_CHECK_ENABLED(return); + if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_BOND_DEVICE) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } + + user_info = _bt_get_user_data(BT_COMMON); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, device_address, sizeof(bluetooth_device_address_t)); + + result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_BOND_DEVICE, + in_param1, in_param2, in_param3, in_param4, + user_info->cb, user_info->user_data); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_bond_device_by_type( + const bluetooth_device_address_t *device_address, + bluetooth_conn_type_t conn_type) +{ + int result; + bt_user_info_t *user_info; + + BT_CHECK_PARAMETER(device_address, return); + BT_CHECK_ENABLED(return); + + if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_BOND_DEVICE_BY_TYPE) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } + BT_INIT_PARAMS(); BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); @@ -39,8 +82,9 @@ BT_EXPORT_API int bluetooth_bond_device(const bluetooth_device_address_t *device retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); g_array_append_vals(in_param1, device_address, sizeof(bluetooth_device_address_t)); + g_array_append_vals(in_param2, &conn_type, sizeof(unsigned short)); - result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_BOND_DEVICE, + result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_BOND_DEVICE_BY_TYPE, in_param1, in_param2, in_param3, in_param4, user_info->cb, user_info->user_data); @@ -74,11 +118,17 @@ BT_EXPORT_API int bluetooth_unbond_device(const bluetooth_device_address_t *devi BT_CHECK_PARAMETER(device_address, return); BT_CHECK_ENABLED(return); - BT_INIT_PARAMS(); - BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_UNBOND_DEVICE) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } user_info = _bt_get_user_data(BT_COMMON); - retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); g_array_append_vals(in_param1, device_address, sizeof(bluetooth_device_address_t)); @@ -113,7 +163,7 @@ BT_EXPORT_API int bluetooth_get_bonded_device(const bluetooth_device_address_t * *dev_info = g_array_index(out_param, bluetooth_device_info_t, 0); } else { - BT_DBG("out_param length is 0!!"); + BT_ERR("out_param length is 0!!"); } } @@ -135,11 +185,17 @@ BT_EXPORT_API int bluetooth_search_service(const bluetooth_device_address_t *dev BT_CHECK_PARAMETER(device_address, return); BT_CHECK_ENABLED(return); - BT_INIT_PARAMS(); - BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_SEARCH_SERVICE) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } user_info = _bt_get_user_data(BT_COMMON); - retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); g_array_append_vals(in_param1, device_address, sizeof(bluetooth_device_address_t)); @@ -226,6 +282,16 @@ BT_EXPORT_API int bluetooth_is_device_connected(const bluetooth_device_address_t BT_CHECK_PARAMETER(is_connected, return); BT_CHECK_ENABLED(return); +#ifdef RFCOMM_DIRECT + if (type & BLUETOOTH_RFCOMM_SERVICE) { + result = bluetooth_rfcomm_client_is_connected(device_address, is_connected); + if (*is_connected == FALSE) + result = bluetooth_rfcomm_server_is_connected(device_address, is_connected); + + return result; + } +#endif + BT_INIT_PARAMS(); BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); @@ -244,3 +310,108 @@ BT_EXPORT_API int bluetooth_is_device_connected(const bluetooth_device_address_t return result; } +BT_EXPORT_API int bluetooth_connect_le(const bluetooth_device_address_t *device_address, gboolean auto_connect) +{ + int result; + + BT_CHECK_PARAMETER(device_address, return); + BT_CHECK_ENABLED_ANY(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, device_address, sizeof(bluetooth_device_address_t)); + g_array_append_vals(in_param2, &auto_connect, sizeof(gboolean)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_CONNECT_LE, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_disconnect_le(const bluetooth_device_address_t *device_address) +{ + int result; + + BT_CHECK_PARAMETER(device_address, return); + BT_CHECK_ENABLED_ANY(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, device_address, sizeof(bluetooth_device_address_t)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_DISCONNECT_LE, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_enable_rssi(const bluetooth_device_address_t *remote_address, + int link_type, bt_rssi_threshold_t *rssi_threshold) +{ + int result; + + BT_CHECK_ENABLED(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t)); + g_array_append_vals(in_param2, &link_type, sizeof(int)); + g_array_append_vals(in_param3, rssi_threshold, sizeof(bt_rssi_threshold_t)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_ENABLE_RSSI, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_get_rssi_strength(const bluetooth_device_address_t *remote_address, int link_type) +{ + int result; + + BT_CHECK_ENABLED(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t)); + g_array_append_vals(in_param2, &link_type, sizeof(int)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_GET_RSSI, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_le_conn_update(const bluetooth_device_address_t *address, + const bluetooth_le_conn_update_t *parameters) +{ + int result; + + BT_CHECK_ENABLED(return); + BT_CHECK_PARAMETER(address, return); + BT_CHECK_PARAMETER(parameters, return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, address, + sizeof(bluetooth_device_address_t)); + g_array_append_vals(in_param2, parameters, + sizeof(bluetooth_le_conn_update_t)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_LE_CONN_UPDATE, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} diff --git a/bt-api/bt-event-handler.c b/bt-api/bt-event-handler.c old mode 100644 new mode 100755 index acce5bd..862386c --- a/bt-api/bt-event-handler.c +++ b/bt-api/bt-event-handler.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -28,11 +32,14 @@ #include "bluetooth-api.h" #include "bluetooth-audio-api.h" #include "bt-internal-types.h" +#include "bluetooth-media-control.h" #include "bt-common.h" #include "bt-event-handler.h" #include "bt-request-sender.h" +#define BT_RELIABLE_DISABLE_TIME 300 /* 300 ms */ + typedef struct { int server_fd; } bt_server_info_t; @@ -42,10 +49,12 @@ typedef struct { } bt_sending_info_t; static int obex_server_id; +static guint disable_timer_id; static gboolean is_initialized; static GSList *sending_list = NULL; static GSList *server_list = NULL; static GSList *event_list = NULL; +static int owner_sig_id = -1; void _bt_add_push_request_id(int request_id) { @@ -67,7 +76,8 @@ static gboolean __bt_is_request_id_exist(int request_id) if (info == NULL) continue; - retv_if(info->request_id == request_id, TRUE); + if (info->request_id == request_id) + return TRUE; } return FALSE; @@ -83,6 +93,8 @@ static void __bt_remove_push_request_id(int request_id) if (info == NULL) continue; + BT_DBG("info->request_id = %d\n", info->request_id); + BT_DBG("request_id = %d\n", request_id); if (info->request_id == request_id) { sending_list = g_slist_remove(sending_list, (void *)info); g_free(info); @@ -162,48 +174,120 @@ static void __bt_get_uuid_info(bluetooth_device_info_t *dev_info, g_strfreev(parts); } } +static int __bt_call_list_create(bt_hf_call_list_s **list) +{ + bt_hf_call_list_s *handle; + + if (*list != NULL) { + BT_DBG("Already Initialized"); + return BLUETOOTH_ERROR_NONE; + } + handle = g_malloc0(sizeof(bt_hf_call_list_s)); + *list = handle; + return BLUETOOTH_ERROR_NONE; +} -static bluetooth_device_info_t *__bt_get_device_info_in_message(DBusMessage *msg, int *ret) +static int __bt_call_list_reset(bt_hf_call_list_s *list) +{ + bt_hf_call_list_s *handle; + bt_hf_call_status_info_t *call_status; + + if (list == NULL) { + BT_ERR("invalid parameter"); + return BLUETOOTH_ERROR_INVALID_PARAM; + } + handle = (bt_hf_call_list_s *)list; + do { + call_status = (bt_hf_call_status_info_t *)g_list_nth_data(handle->list, 0); + if (call_status == NULL) + break; + handle->list = g_list_remove(handle->list, call_status); + g_free(call_status->number); + g_free(call_status); + } while (1); + return BLUETOOTH_ERROR_NONE; +} + +static int __bt_call_list_destroy(bt_hf_call_list_s *list) +{ + int result; + bt_hf_call_list_s *handle; + + if (list == NULL) { + BT_ERR("invalid parameter"); + return BLUETOOTH_ERROR_INVALID_PARAM; + } + handle = (bt_hf_call_list_s *)list; + result = __bt_call_list_reset(list); + g_free(handle); + return result; +} +static int __bt_call_list_add(bt_hf_call_list_s *list, char * number, + int dir, int status, int mpart, int idx) +{ + bt_hf_call_list_s *handle; + bt_hf_call_status_info_t *call_status; + + if (list == NULL) { + BT_ERR("invalid parameter"); + return BLUETOOTH_ERROR_INVALID_PARAM; + } + handle = (bt_hf_call_list_s *)list; + call_status = g_malloc0(sizeof(bt_hf_call_status_info_t)); + call_status->number = g_strdup(number); + call_status->direction= dir; + call_status->status = status; + call_status->mpart = mpart; + call_status->idx = idx; + handle->list = g_list_append(handle->list, (gpointer)call_status); + return BLUETOOTH_ERROR_NONE; +} + +static bluetooth_device_info_t *__bt_get_device_info_in_message(GVariant *parameters, int *ret) { bluetooth_device_info_t *dev_info; - char *address = NULL; - char *name = NULL; - char **uuids = NULL; - unsigned int class = 0; - int rssi = 0; + const char *address = NULL; + const char *name = NULL; + gchar **uuids = NULL; + unsigned int dev_class = 0; + short rssi = 0; gboolean paired = FALSE; gboolean connected = FALSE; gboolean trust = FALSE; - int uuid_count = 0; + gsize uuid_count; int result = BLUETOOTH_ERROR_NONE; - - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_UINT32, &class, - DBUS_TYPE_INT16, &rssi, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_BOOLEAN, &paired, - DBUS_TYPE_BOOLEAN, &connected, - DBUS_TYPE_BOOLEAN, &trust, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, - &uuids, &uuid_count, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); + GVariant *string_var; + int i = 0, len = 0; + int manufacturer_data_len = 0; + GVariant *manufacturer_var = NULL; + const char *manufacturer_data = NULL; + + g_variant_get(parameters, "(i&sun&sbbb@asn@ay)", &result, &address, + &dev_class, &rssi, &name, &paired, + &connected, &trust, &string_var, &manufacturer_data_len, &manufacturer_var); + + if (string_var == NULL) { + BT_ERR("invalid parameters in signal"); return NULL; } + uuids = (gchar **)g_variant_get_strv(string_var, &uuid_count); + + len = g_variant_get_size(manufacturer_var); + if (len > 0) + manufacturer_data = (char *)g_variant_get_data(manufacturer_var); + dev_info = g_malloc0(sizeof(bluetooth_device_info_t)); dev_info->rssi = rssi; dev_info->paired = paired; dev_info->connected = connected; - dev_info->paired = paired; dev_info->trust = trust; - g_strlcpy(dev_info->device_name.name, name, BLUETOOTH_DEVICE_NAME_LENGTH_MAX + 1); + g_strlcpy(dev_info->device_name.name, name, + BLUETOOTH_DEVICE_NAME_LENGTH_MAX + 1); - _bt_divide_device_class(&dev_info->device_class, class); + _bt_divide_device_class(&dev_info->device_class, dev_class); _bt_convert_addr_string_to_type(dev_info->device_address.addr, address); @@ -211,164 +295,289 @@ static bluetooth_device_info_t *__bt_get_device_info_in_message(DBusMessage *msg if (uuid_count > 0) __bt_get_uuid_info(dev_info, uuids, uuid_count); - *ret = result; + if (manufacturer_data_len > BLUETOOTH_MANUFACTURER_DATA_LENGTH_MAX) { + BT_ERR("manufacturer_data_len is too long(len = %d)", manufacturer_data_len); + manufacturer_data_len = BLUETOOTH_MANUFACTURER_DATA_LENGTH_MAX; + } + dev_info->manufacturer_data.data_len = manufacturer_data_len; + if (manufacturer_data) + for (i = 0; i < manufacturer_data_len; i++) + dev_info->manufacturer_data.data[i] = manufacturer_data[i]; + *ret = result; + g_free(uuids); + g_variant_unref(string_var); + g_variant_unref(manufacturer_var); return dev_info; } -static DBusHandlerResult __bt_adapter_event_filter(DBusConnection *conn, - DBusMessage *msg, void *data) +static bluetooth_le_device_info_t *__bt_get_le_device_info_in_message(GVariant *parameters, int *ret) { - bt_event_info_t *event_info; + bluetooth_le_device_info_t *le_dev_info; + const char *address = NULL; + int i; + short addr_type = 0; + short rssi = 0; + int len = 0; + int adv_data_len = 0; + GVariant *adv_var = NULL; + const char *adv_data = NULL; + int scan_data_len = 0; + GVariant *scan_var = NULL; + const char *scan_data = NULL; int result = BLUETOOTH_ERROR_NONE; - const char *member = dbus_message_get_member(msg); - event_info = (bt_event_info_t *)data; - retv_if(event_info == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + g_variant_get(parameters, "(i&snnn@ayn@ay)", &result, &address, + &addr_type, &rssi, &adv_data_len, &adv_var, &scan_data_len, &scan_var); - if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + len = g_variant_get_size(adv_var); + if (len > 0) + adv_data = (char *)g_variant_get_data(adv_var); - if (!dbus_message_has_interface(msg, BT_EVENT_SERVICE)) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + len = g_variant_get_size(scan_var); + if (len > 0) + scan_data = (char *)g_variant_get_data(scan_var); - if (!dbus_message_has_path(msg, BT_ADAPTER_PATH)) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + le_dev_info = g_malloc0(sizeof(bluetooth_le_device_info_t)); + _bt_convert_addr_string_to_type(le_dev_info->device_address.addr, address); + le_dev_info->addr_type = addr_type; + le_dev_info->rssi = rssi; + le_dev_info->adv_ind_data.data_len = adv_data_len; - retv_if(member == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + for (i = 0; i < adv_data_len; i++) + if (adv_data) + le_dev_info->adv_ind_data.data.data[i] = adv_data[i]; - if (strcasecmp(member, BT_ENABLED) == 0) { - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + le_dev_info->scan_resp_data.data_len = scan_data_len; + + for (i = 0; i < scan_data_len; i++) + if (scan_data) + le_dev_info->scan_resp_data.data.data[i] = scan_data[i]; + + *ret = result; + g_variant_unref(adv_var); + g_variant_unref(scan_var); + return le_dev_info; +} + +gboolean __bt_reliable_disable_cb(gpointer user_data) +{ + BT_DBG("+"); + bt_event_info_t *event_info = user_data; + + if (is_initialized != FALSE) { + _bt_common_event_cb(BLUETOOTH_EVENT_DISABLED, + BLUETOOTH_ERROR_NONE, NULL, + event_info->cb, event_info->user_data); + _bt_common_event_cb(BLUETOOTH_EVENT_LE_DISABLED, + BLUETOOTH_ERROR_NONE, NULL, + event_info->cb, event_info->user_data); + } + + obex_server_id = BT_NO_SERVER; + __bt_remove_all_server(); + __bt_remove_all_push_request_id(); +#ifdef RFCOMM_DIRECT + _bt_rfcomm_server_free_all(); +#endif + BT_DBG("-"); + return FALSE; +} + +void __bt_adapter_event_filter(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + bt_event_info_t *event_info; + int result = BLUETOOTH_ERROR_NONE; + + event_info = (bt_event_info_t *)user_data; + ret_if(event_info == NULL); + + if (strcasecmp(object_path, BT_ADAPTER_PATH) != 0) + return; + if (strcasecmp(interface_name, BT_EVENT_SERVICE) != 0) + return; + + if (strcasecmp(signal_name, BT_ENABLED) == 0) { + BT_INFO("BT_ENABLED"); + g_variant_get(parameters, "(i)", &result); if (result == BLUETOOTH_ERROR_NONE) { if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0) - BT_ERR("Set vconf failed\n"); + BT_ERR("Set vconf failed"); + + if (vconf_set_int(BT_OFF_DUE_TO_POWER_SAVING_MODE, 0) != 0) + BT_ERR("Set vconf failed"); + + if (vconf_set_int(BT_OFF_DUE_TO_TIMEOUT, 0) != 0) + BT_ERR("Set vconf failed"); } _bt_common_event_cb(BLUETOOTH_EVENT_ENABLED, result, NULL, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_DISABLED) == 0) { + } else if (strcasecmp(signal_name, BT_DISABLED) == 0) { + BT_INFO("BT_DISABLED"); + int flight_mode_value = 0; + int ps_mode_value = 0; + + if (vconf_get_int(BT_OFF_DUE_TO_FLIGHT_MODE, + &flight_mode_value) != 0) + BT_ERR("Fail to get the flight_mode_deactivated value"); + + if (vconf_get_int(BT_OFF_DUE_TO_POWER_SAVING_MODE, + &ps_mode_value) != 0) + BT_ERR("Fail to get the ps_mode_deactivated value"); + + if (flight_mode_value == 1 || ps_mode_value > 0) { + BT_INFO("Flight mode deactivation"); + if (disable_timer_id > 0) + g_source_remove(disable_timer_id); + + disable_timer_id = g_timeout_add(BT_RELIABLE_DISABLE_TIME, + (GSourceFunc)__bt_reliable_disable_cb, + event_info); + } _bt_common_event_cb(BLUETOOTH_EVENT_DISABLED, - BLUETOOTH_ERROR_NONE, NULL, + result, NULL, event_info->cb, event_info->user_data); - - obex_server_id = BT_NO_SERVER; - __bt_remove_all_server(); - __bt_remove_all_push_request_id(); - } else if (strcasecmp(member, BT_DISCOVERABLE_MODE_CHANGED) == 0) { + } else if (strcasecmp(signal_name, BT_DISCOVERABLE_MODE_CHANGED) == 0) { int mode = 0; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_INT16, &mode, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - + g_variant_get(parameters, "(in)", &result, &mode); _bt_common_event_cb(BLUETOOTH_EVENT_DISCOVERABLE_MODE_CHANGED, result, &mode, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_DISCOVERABLE_TIMEOUT_CHANGED) == 0) { + } else if (strcasecmp(signal_name, BT_DISCOVERABLE_TIMEOUT_CHANGED) == 0) { int timeout = 0; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_INT16, &timeout, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - + g_variant_get(parameters, "(in)", &result, &timeout); _bt_common_event_cb(BLUETOOTH_EVENT_DISCOVERABLE_TIMEOUT_CHANGED, result, &timeout, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_ADAPTER_NAME_CHANGED) == 0) { - char *adapter_name = NULL; + } else if (strcasecmp(signal_name, BT_CONNECTABLE_CHANGED) == 0) { + gboolean connectable = FALSE; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &adapter_name, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(b)", &connectable); + BT_DBG("Connectable is changed : %d", connectable); + _bt_common_event_cb(BLUETOOTH_EVENT_CONNECTABLE_CHANGED, + result, &connectable, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_ADAPTER_NAME_CHANGED) == 0) { + char *adapter_name = NULL; + + g_variant_get(parameters, "(i&s)", &result, &adapter_name); _bt_common_event_cb(BLUETOOTH_EVENT_LOCAL_NAME_CHANGED, result, adapter_name, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_DISCOVERY_STARTED) == 0) { + } else if (strcasecmp(signal_name, BT_DISCOVERY_STARTED) == 0) { _bt_common_event_cb(BLUETOOTH_EVENT_DISCOVERY_STARTED, BLUETOOTH_ERROR_NONE, NULL, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_DISCOVERY_FINISHED) == 0) { - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - + } else if (strcasecmp(signal_name, BT_DISCOVERY_FINISHED) == 0) { + g_variant_get(parameters, "(i)", &result); _bt_common_event_cb(BLUETOOTH_EVENT_DISCOVERY_FINISHED, result, NULL, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_DEVICE_FOUND) == 0) { - int event; - bluetooth_device_info_t *device_info; + } else if (strcasecmp(signal_name, BT_ADVERTISING_STARTED) == 0) { + bluetooth_advertising_params_t adv_params = {0, }; - device_info = __bt_get_device_info_in_message(msg, &result); - retv_if(device_info == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + g_variant_get(parameters, "(idd)", &result, + &adv_params.interval_min, + &adv_params.interval_max); - if (strlen(device_info->device_name.name) > 0) { - event = BLUETOOTH_EVENT_REMOTE_DEVICE_NAME_UPDATED; - } else { - event = BLUETOOTH_EVENT_REMOTE_DEVICE_FOUND; - } + _bt_common_event_cb(BLUETOOTH_EVENT_ADVERTISING_STARTED, + result, &adv_params, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_ADVERTISING_STOPPED) == 0) { + g_variant_get(parameters, "(i)", &result); + _bt_common_event_cb(BLUETOOTH_EVENT_ADVERTISING_STOPPED, + result, NULL, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_ADVERTISING_MANUFACTURER_DATA_CHANGED) == 0) { + GVariant *var = NULL; + char *data; + int len; - _bt_common_event_cb(event, - result, device_info, + g_variant_get(parameters, "(@ay)", &var); + len = g_variant_get_size(var); + data = (char *)g_variant_get_data(var); + + _bt_common_event_cb(BLUETOOTH_EVENT_ADVERTISING_MANUFACTURER_DATA_CHANGED, + len, data, event_info->cb, event_info->user_data); - g_free(device_info); - } else if (strcasecmp(member, BT_DEVICE_DISAPPEARED) == 0) { + g_variant_unref(var); + } else if (strcasecmp(signal_name, BT_SCAN_RESPONSE_MANUFACTURER_DATA_CHANGED) == 0) { + GVariant *var = NULL; + char *data; + int len; + + g_variant_get(parameters, "(@ay)", &var); + len = g_variant_get_size(var); + data = (char *)g_variant_get_data(var); + + _bt_common_event_cb(BLUETOOTH_EVENT_SCAN_RESPONSE_MANUFACTURER_DATA_CHANGED, + len, data, + event_info->cb, event_info->user_data); + + g_variant_unref(var); + } else if (strcasecmp(signal_name, BT_MANUFACTURER_DATA_CHANGED) == 0) { + GVariant *var = NULL; + char *data; + int len; + + g_variant_get(parameters, "(@ay)", &var); + len = g_variant_get_size(var); + data = (char *)g_variant_get_data(var); + + _bt_common_event_cb(BLUETOOTH_EVENT_MANUFACTURER_DATA_CHANGED, + len, data, + event_info->cb, event_info->user_data); + + g_variant_unref(var); + } else if (strcasecmp(signal_name, BT_DEVICE_FOUND) == 0) { + int event; bluetooth_device_info_t *device_info; - device_info = __bt_get_device_info_in_message(msg, &result); - retv_if(device_info == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + device_info = __bt_get_device_info_in_message(parameters, + &result); + ret_if(device_info == NULL); + if (strlen(device_info->device_name.name) > 0) + event = BLUETOOTH_EVENT_REMOTE_DEVICE_NAME_UPDATED; + else + event = BLUETOOTH_EVENT_REMOTE_DEVICE_FOUND; - _bt_common_event_cb(BLUETOOTH_EVENT_REMOTE_DEVICE_DISAPPEARED, + _bt_common_event_cb(event, result, device_info, event_info->cb, event_info->user_data); + g_free(device_info); - } else if (strcasecmp(member, BT_BOND_CREATED) == 0) { + } else if (strcasecmp(signal_name, BT_BOND_CREATED) == 0) { bluetooth_device_info_t *device_info; - device_info = __bt_get_device_info_in_message(msg, &result); + device_info = __bt_get_device_info_in_message(parameters, + &result); + ret_if(device_info == NULL); _bt_common_event_cb(BLUETOOTH_EVENT_BONDING_FINISHED, result, device_info, event_info->cb, event_info->user_data); g_free(device_info); - } else if (strcasecmp(member, BT_BOND_DESTROYED) == 0) { - char *address = NULL; + } else if (strcasecmp(signal_name, BT_BOND_DESTROYED) == 0) { + const char *address = NULL; bluetooth_device_address_t dev_address = { {0} }; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&s)", &result, &address); _bt_convert_addr_string_to_type(dev_address.addr, address); @@ -376,11 +585,13 @@ static DBusHandlerResult __bt_adapter_event_filter(DBusConnection *conn, _bt_common_event_cb(BLUETOOTH_EVENT_BONDED_DEVICE_REMOVED, result, &dev_address, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_SERVICE_SEARCHED) == 0) { + } else if (strcasecmp(signal_name, BT_SERVICE_SEARCHED) == 0) { bluetooth_device_info_t *device_info; bt_sdp_info_t sdp_info; - device_info = __bt_get_device_info_in_message(msg, &result); + device_info = __bt_get_device_info_in_message(parameters, + &result); + ret_if(device_info == NULL); memset(&sdp_info, 0x00, sizeof(bt_sdp_info_t)); @@ -404,105 +615,262 @@ static DBusHandlerResult __bt_adapter_event_filter(DBusConnection *conn, g_free(device_info); } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } -static DBusHandlerResult __bt_device_event_filter(DBusConnection *conn, - DBusMessage *msg, void *data) +void __bt_adapter_le_event_filter(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) { bt_event_info_t *event_info; int result = BLUETOOTH_ERROR_NONE; - const char *member = dbus_message_get_member(msg); - event_info = (bt_event_info_t *)data; - retv_if(event_info == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + event_info = (bt_event_info_t *)user_data; + ret_if(event_info == NULL); - if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + if (strcasecmp(object_path, BT_LE_ADAPTER_PATH) != 0) + return; + if (strcasecmp(interface_name, BT_EVENT_SERVICE) != 0) + return; - if (!dbus_message_has_interface(msg, BT_EVENT_SERVICE)) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + if (strcasecmp(signal_name, BT_LE_ENABLED) == 0) { + BT_INFO("BT_LE_ENABLED"); + g_variant_get(parameters, "(i)", &result); + _bt_common_event_cb(BLUETOOTH_EVENT_LE_ENABLED, + result, NULL, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_LE_DISABLED) == 0) { + BT_INFO("BT_LE_DISABLED"); + _bt_common_event_cb(BLUETOOTH_EVENT_LE_DISABLED, + result, NULL, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_LE_DISCOVERY_STARTED) == 0) { + _bt_common_event_cb(BLUETOOTH_EVENT_LE_DISCOVERY_STARTED, + BLUETOOTH_ERROR_NONE, NULL, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_LE_DISCOVERY_FINISHED) == 0) { + g_variant_get(parameters, "(i)", &result); + _bt_common_event_cb(BLUETOOTH_EVENT_LE_DISCOVERY_FINISHED, + result, NULL, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_LE_DEVICE_FOUND) == 0) { + bluetooth_le_device_info_t *le_device_info; - if (!dbus_message_has_path(msg, BT_DEVICE_PATH)) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + le_device_info = __bt_get_le_device_info_in_message(parameters, + &result); + ret_if(le_device_info == NULL); + _bt_common_event_cb(BLUETOOTH_EVENT_REMOTE_LE_DEVICE_FOUND, + result, le_device_info, + event_info->cb, event_info->user_data); - retv_if(member == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + g_free(le_device_info); + } +} - if (strcasecmp(member, BT_DEVICE_CONNECTED) == 0) { - char *address = NULL; +void __bt_device_event_filter(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + bt_event_info_t *event_info; + int result = BLUETOOTH_ERROR_NONE; + + event_info = (bt_event_info_t *)user_data; + ret_if(event_info == NULL); + + if (strcasecmp(object_path, BT_DEVICE_PATH) != 0) + return; + if (strcasecmp(interface_name, BT_EVENT_SERVICE) != 0) + return; + + ret_if(signal_name == NULL); + + if (strcasecmp(signal_name, BT_GATT_CONNECTED) == 0) { + const char *address = NULL; bluetooth_device_address_t dev_address = { {0} }; + BT_DBG("BT_GATT_CONNECTED"); + g_variant_get(parameters, "(i&s)", &result, &address); - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID)) { - BT_DBG("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + _bt_convert_addr_string_to_type(dev_address.addr, address); + BT_DBG("Sending Event to Framework"); + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_CONNECTED, + result, &dev_address, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_GATT_DISCONNECTED) == 0) { + const char *address = NULL; + bluetooth_device_address_t dev_address = { {0} }; + BT_DBG("BT_GATT_DISCONNECTED"); + g_variant_get(parameters, "(i&s)", &result, &address); + + _bt_convert_addr_string_to_type(dev_address.addr, address); + BT_DBG("Sending Event to Framework"); + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_DISCONNECTED, + result, &dev_address, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_DEVICE_CONNECTED) == 0) { + const char *address = NULL; + unsigned char addr_type; + bt_connection_info_t conn_info; + bluetooth_device_address_t dev_address = { {0} }; + BT_DBG("BT_DEVICE_CONNECTED"); + g_variant_get(parameters, "(i&sy)", &result, &address, &addr_type); _bt_convert_addr_string_to_type(dev_address.addr, address); + memset(&conn_info, 0x00, sizeof(bt_connection_info_t)); + + memcpy(conn_info.device_addr.addr, + dev_address.addr, + BLUETOOTH_ADDRESS_LENGTH); + + conn_info.addr_type = addr_type; + conn_info.disc_reason = 0; + BT_DBG("Sending Event to Framework"); _bt_common_event_cb(BLUETOOTH_EVENT_DEVICE_CONNECTED, + result, &conn_info, + event_info->cb, event_info->user_data); + + } else if (strcasecmp(signal_name, BT_DEVICE_DISCONNECTED) == 0) { + const char *address = NULL; + unsigned char addr_type; + bt_connection_info_t conn_info; + bluetooth_device_address_t dev_address = { {0} }; + BT_DBG("BT_DEVICE_DISCONNECTED"); + g_variant_get(parameters, "(i&sy)", &result, &address, &addr_type); + + _bt_convert_addr_string_to_type(dev_address.addr, + address); + + memset(&conn_info, 0x00, sizeof(bt_connection_info_t)); + + memcpy(conn_info.device_addr.addr, + dev_address.addr, + BLUETOOTH_ADDRESS_LENGTH); + + conn_info.addr_type = addr_type; + conn_info.disc_reason = result; + BT_DBG("Sending Event to Framework"); + _bt_common_event_cb(BLUETOOTH_EVENT_DEVICE_DISCONNECTED, + result, &conn_info, + event_info->cb, event_info->user_data); + + } else if (strcasecmp(signal_name, BT_RSSI_MONITORING_ENABLED) == 0) { + bt_rssi_enabled_t enabled = { 0, }; + char *address; + int link_type; + gboolean rssi_enabled = FALSE; + + g_variant_get(parameters, "(isib)", &result, &address, + &link_type, &rssi_enabled); + + BT_DBG("RSSI Enabled[Address:%s LinkType:%d RSSI_dbm:%d]", + address, link_type, rssi_enabled); + enabled.address = address; + enabled.link_type = link_type; + enabled.rssi_enabled = rssi_enabled; + + _bt_common_event_cb(BLUETOOTH_EVENT_RSSI_ENABLED, + result, &enabled, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_RSSI_ALERT) == 0) { + int alert_type; + int rssi_dbm; + char *address; + int link_type; + bt_rssi_alert_t alert = { 0, }; + + g_variant_get(parameters, "(isiii)", &result, &address, + &link_type, &alert_type, &rssi_dbm); + + alert.alert_type = alert_type; + alert.rssi_dbm = rssi_dbm; + alert.address = address; + alert.link_type = link_type; + BT_DBG("Address [%s] LinkType[%d] AlertType[%d] RSSI dBm[%d]", + address, link_type, alert_type, rssi_dbm); + _bt_common_event_cb(BLUETOOTH_EVENT_RSSI_ALERT, + result, &alert, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_RAW_RSSI_EVENT) == 0) { + int rssi_dbm; + int link_type; + char *address; + bt_raw_rssi_t raw_rssi = { 0, }; + + g_variant_get(parameters, "(isii)", &result, + &address, &link_type, &rssi_dbm); + + BT_DBG("Address [%s] Link Type[%d] dBm[%d]", + address, link_type, rssi_dbm); + + raw_rssi.rssi_dbm = rssi_dbm; + raw_rssi.address = address; + raw_rssi.link_type = link_type; + + _bt_common_event_cb(BLUETOOTH_EVENT_RAW_RSSI, + result, &raw_rssi, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_DEVICE_AUTHORIZED) == 0) { + const char *address = NULL; + bluetooth_device_address_t dev_address = { {0} }; + + g_variant_get(parameters, "(i&s)", &result, &address); + + _bt_convert_addr_string_to_type(dev_address.addr, + address); + + _bt_common_event_cb(BLUETOOTH_EVENT_DEVICE_AUTHORIZED, result, &dev_address, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_DEVICE_DISCONNECTED) == 0) { - char *address = NULL; + } else if (strcasecmp(signal_name, BT_DEVICE_UNAUTHORIZED) == 0) { + const char *address = NULL; bluetooth_device_address_t dev_address = { {0} }; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID)) { - BT_DBG("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&s)", &result, &address); _bt_convert_addr_string_to_type(dev_address.addr, address); - _bt_common_event_cb(BLUETOOTH_EVENT_DEVICE_DISCONNECTED, + _bt_common_event_cb(BLUETOOTH_EVENT_DEVICE_UNAUTHORIZED, result, &dev_address, event_info->cb, event_info->user_data); } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } -static DBusHandlerResult __bt_hid_event_filter(DBusConnection *conn, - DBusMessage *msg, void *data) +void __bt_hid_event_filter(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) { bt_event_info_t *event_info; int result = BLUETOOTH_ERROR_NONE; - const char *member = dbus_message_get_member(msg); - - event_info = (bt_event_info_t *)data; - retv_if(event_info == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + event_info = (bt_event_info_t *)user_data; + ret_if(event_info == NULL); - if (!dbus_message_has_interface(msg, BT_EVENT_SERVICE)) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + if (strcasecmp(object_path, BT_HID_PATH) != 0) + return; + if (strcasecmp(interface_name, BT_EVENT_SERVICE) != 0) + return; - if (!dbus_message_has_path(msg, BT_HID_PATH)) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + ret_if(signal_name == NULL); - retv_if(member == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - - if (strcasecmp(member, BT_INPUT_CONNECTED) == 0) { - char *address = NULL; + if (strcasecmp(signal_name, BT_INPUT_CONNECTED) == 0) { + const char *address = NULL; bluetooth_device_address_t dev_address = { {0} }; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID)) { - BT_DBG("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&s)", &result, &address); _bt_convert_addr_string_to_type(dev_address.addr, address); @@ -510,17 +878,11 @@ static DBusHandlerResult __bt_hid_event_filter(DBusConnection *conn, _bt_input_event_cb(BLUETOOTH_HID_CONNECTED, result, &dev_address, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_INPUT_DISCONNECTED) == 0) { - char *address = NULL; + } else if (strcasecmp(signal_name, BT_INPUT_DISCONNECTED) == 0) { + const char *address = NULL; bluetooth_device_address_t dev_address = { {0} }; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID)) { - BT_DBG("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&s)", &result, &address); BT_DBG("address: %s", address); @@ -531,196 +893,112 @@ static DBusHandlerResult __bt_hid_event_filter(DBusConnection *conn, result, &dev_address, event_info->cb, event_info->user_data); } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } -static DBusHandlerResult __bt_headset_event_filter(DBusConnection *conn, - DBusMessage *msg, void *data) +void __bt_headset_event_filter(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) { bt_event_info_t *event_info; int result = BLUETOOTH_ERROR_NONE; - const char *member = dbus_message_get_member(msg); - - event_info = (bt_event_info_t *)data; - retv_if(event_info == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + event_info = (bt_event_info_t *)user_data; + ret_if(event_info == NULL); - if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + if (strcasecmp(object_path, BT_HEADSET_PATH) != 0) + return; + if (strcasecmp(interface_name, BT_EVENT_SERVICE) != 0) + return; - if (!dbus_message_has_interface(msg, BT_EVENT_SERVICE)) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + ret_if(signal_name == NULL); - if (!dbus_message_has_path(msg, BT_HEADSET_PATH)) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - retv_if(member == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - - if (strcasecmp(member, BT_HEADSET_CONNECTED) == 0) { + if (strcasecmp(signal_name, BT_HEADSET_CONNECTED) == 0) { char *address = NULL; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&s)", &result, &address); _bt_headset_event_cb(BLUETOOTH_EVENT_AG_CONNECTED, result, address, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_HEADSET_DISCONNECTED) == 0) { + } else if (strcasecmp(signal_name, BT_HEADSET_DISCONNECTED) == 0) { char *address = NULL; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&s)", &result, &address); _bt_headset_event_cb(BLUETOOTH_EVENT_AG_DISCONNECTED, result, address, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_STEREO_HEADSET_CONNECTED) == 0) { + } else if (strcasecmp(signal_name, BT_STEREO_HEADSET_CONNECTED) == 0) { char *address = NULL; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&s)", &result, &address); _bt_headset_event_cb(BLUETOOTH_EVENT_AV_CONNECTED, result, address, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_STEREO_HEADSET_DISCONNECTED) == 0) { + } else if (strcasecmp(signal_name, BT_STEREO_HEADSET_DISCONNECTED) == 0) { char *address = NULL; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&s)", &result, &address); _bt_headset_event_cb(BLUETOOTH_EVENT_AV_DISCONNECTED, result, address, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_SCO_CONNECTED) == 0) { - char *address = NULL; - bluetooth_device_address_t dev_address = { {0} }; - - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - - _bt_convert_addr_string_to_type(dev_address.addr, - address); - - _bt_headset_event_cb(BLUETOOTH_EVENT_AG_AUDIO_CONNECTED, - result, &dev_address, - event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_SCO_DISCONNECTED) == 0) { - char *address = NULL; - bluetooth_device_address_t dev_address = { {0} }; - - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - - _bt_convert_addr_string_to_type(dev_address.addr, - address); - - _bt_headset_event_cb(BLUETOOTH_EVENT_AG_AUDIO_DISCONNECTED, - result, &dev_address, - event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_SPEAKER_GAIN) == 0) { + } else if (strcasecmp(signal_name, BT_SPEAKER_GAIN) == 0) { unsigned int gain; guint16 spkr_gain; char *address = NULL; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_UINT16, &spkr_gain, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&sq)", &result, &address, + &spkr_gain); gain = (unsigned int)spkr_gain; _bt_headset_event_cb(BLUETOOTH_EVENT_AG_SPEAKER_GAIN, result, &gain, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_MICROPHONE_GAIN) == 0) { + } else if (strcasecmp(signal_name, BT_MICROPHONE_GAIN) == 0) { unsigned int gain; guint16 mic_gain; char *address = NULL; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_UINT16, &mic_gain, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&sq)", &result, + &address, &mic_gain); gain = (unsigned int)mic_gain; _bt_headset_event_cb(BLUETOOTH_EVENT_AG_MIC_GAIN, result, &gain, event_info->cb, event_info->user_data); } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } -static DBusHandlerResult __bt_network_event_filter(DBusConnection *conn, - DBusMessage *msg, void *data) +void __bt_network_event_filter(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) { bt_event_info_t *event_info; int result = BLUETOOTH_ERROR_NONE; - const char *member = dbus_message_get_member(msg); + event_info = (bt_event_info_t *)user_data; + ret_if(event_info == NULL); - event_info = (bt_event_info_t *)data; - retv_if(event_info == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + if (strcasecmp(object_path, BT_NETWORK_PATH) != 0) + return; + if (strcasecmp(interface_name, BT_EVENT_SERVICE) != 0) + return; - if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + ret_if(signal_name == NULL); - if (!dbus_message_has_interface(msg, BT_EVENT_SERVICE)) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - if (!dbus_message_has_path(msg, BT_NETWORK_PATH)) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - retv_if(member == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - - if (strcasecmp(member, BT_NETWORK_CONNECTED) == 0) { - char *address = NULL; + if (strcasecmp(signal_name, BT_NETWORK_CONNECTED) == 0) { + const char *address = NULL; bluetooth_device_address_t dev_address = { {0} }; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&s)", &result, &address); _bt_convert_addr_string_to_type(dev_address.addr, address); @@ -728,17 +1006,11 @@ static DBusHandlerResult __bt_network_event_filter(DBusConnection *conn, _bt_common_event_cb(BLUETOOTH_EVENT_NETWORK_CONNECTED, result, &dev_address, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_NETWORK_DISCONNECTED) == 0) { - char *address = NULL; + } else if (strcasecmp(signal_name, BT_NETWORK_DISCONNECTED) == 0) { + const char *address = NULL; bluetooth_device_address_t dev_address = { {0} }; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&s)", &result, &address); _bt_convert_addr_string_to_type(dev_address.addr, address); @@ -746,19 +1018,13 @@ static DBusHandlerResult __bt_network_event_filter(DBusConnection *conn, _bt_common_event_cb(BLUETOOTH_EVENT_NETWORK_DISCONNECTED, result, &dev_address, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_NETWORK_SERVER_CONNECTED) == 0) { - char *device = NULL; - char *address = NULL; + } else if (strcasecmp(signal_name, BT_NETWORK_SERVER_CONNECTED) == 0) { + const char *device = NULL; + const char *address = NULL; bluetooth_network_device_info_t network_info; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &device, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&s&s)", &result, + &device, &address); memset(&network_info, 0x00, sizeof(bluetooth_network_device_info_t)); @@ -766,26 +1032,20 @@ static DBusHandlerResult __bt_network_event_filter(DBusConnection *conn, address); _bt_print_device_address_t(&network_info.device_address); - g_strlcpy(network_info.interface_name, device, BLUETOOTH_INTERFACE_NAME_LENGTH); + g_strlcpy(network_info.interface_name, device, + sizeof(network_info.interface_name)); - BT_DBG("name: %s", network_info.interface_name); + DBG_SECURE("Interface: %s", network_info.interface_name); _bt_common_event_cb(BLUETOOTH_EVENT_NETWORK_SERVER_CONNECTED, result, &network_info, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_NETWORK_SERVER_DISCONNECTED) == 0) { - char *device = NULL; - char *address = NULL; + } else if (strcasecmp(signal_name, BT_NETWORK_SERVER_DISCONNECTED) == 0) { + const char *device = NULL; + const char *address = NULL; bluetooth_network_device_info_t network_info; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &device, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&s&s)", &result, &device, &address); memset(&network_info, 0x00, sizeof(bluetooth_network_device_info_t)); @@ -798,147 +1058,215 @@ static DBusHandlerResult __bt_network_event_filter(DBusConnection *conn, result, &network_info, event_info->cb, event_info->user_data); } - - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } -static DBusHandlerResult __bt_avrcp_event_filter(DBusConnection *conn, - DBusMessage *msg, void *data) +void __bt_avrcp_event_filter(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) { bt_event_info_t *event_info; int result = BLUETOOTH_ERROR_NONE; - const char *member = dbus_message_get_member(msg); - - event_info = (bt_event_info_t *)data; - retv_if(event_info == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - - if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + event_info = (bt_event_info_t *)user_data; + ret_if(event_info == NULL); - if (!dbus_message_has_interface(msg, BT_EVENT_SERVICE)) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + if (strcasecmp(object_path, BT_AVRCP_PATH) != 0) + return; + if (strcasecmp(interface_name, BT_EVENT_SERVICE) != 0) + return; - if (!dbus_message_has_path(msg, BT_AVRCP_PATH)) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + ret_if(signal_name == NULL); - retv_if(member == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - - if (strcasecmp(member, BT_STEREO_HEADSET_CONNECTED) == 0) { + if (strcasecmp(signal_name, BT_AVRCP_CONNECTED) == 0) { char *address = NULL; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&s)", &result, &address); _bt_avrcp_event_cb(BLUETOOTH_EVENT_AVRCP_CONNECTED, result, address, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_STEREO_HEADSET_DISCONNECTED) == 0) { + } else if (strcasecmp(signal_name, BT_AVRCP_DISCONNECTED) == 0) { char *address = NULL; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&s)", &result, &address); _bt_avrcp_event_cb(BLUETOOTH_EVENT_AVRCP_DISCONNECTED, result, address, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_MEDIA_SHUFFLE_STATUS) == 0) { + } else if (strcasecmp(signal_name, BT_MEDIA_SHUFFLE_STATUS) == 0) { unsigned int status; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_UINT32, &status, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + + g_variant_get(parameters, "(u)", &status); _bt_avrcp_event_cb(BLUETOOTH_EVENT_AVRCP_SETTING_SHUFFLE_STATUS, result, &status, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_MEDIA_EQUALIZER_STATUS) == 0) { + } else if (strcasecmp(signal_name, BT_MEDIA_EQUALIZER_STATUS) == 0) { unsigned int status; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_UINT32, &status, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + + g_variant_get(parameters, "(u)", &status); _bt_avrcp_event_cb(BLUETOOTH_EVENT_AVRCP_SETTING_EQUALIZER_STATUS, result, &status, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_MEDIA_REPEAT_STATUS) == 0) { + } else if (strcasecmp(signal_name, BT_MEDIA_REPEAT_STATUS) == 0) { unsigned int status; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_UINT32, &status, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + + g_variant_get(parameters, "(u)", &status); _bt_avrcp_event_cb(BLUETOOTH_EVENT_AVRCP_SETTING_REPEAT_STATUS, result, &status, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_MEDIA_SCAN_STATUS) == 0) { + } else if (strcasecmp(signal_name, BT_MEDIA_SCAN_STATUS) == 0) { unsigned int status; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_UINT32, &status, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + + g_variant_get(parameters, "(u)", &status); _bt_avrcp_event_cb(BLUETOOTH_EVENT_AVRCP_SETTING_SCAN_STATUS, result, &status, event_info->cb, event_info->user_data); } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } -static DBusHandlerResult __bt_opp_client_event_filter(DBusConnection *conn, - DBusMessage *msg, void *data) +void __bt_avrcp_control_event_filter(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) { bt_event_info_t *event_info; int result = BLUETOOTH_ERROR_NONE; - const char *member = dbus_message_get_member(msg); - - event_info = (bt_event_info_t *)data; - retv_if(event_info == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + event_info = (bt_event_info_t *)user_data; + ret_if(event_info == NULL); - if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + if (strcasecmp(object_path, BT_AVRCP_CONTROL_PATH) != 0) + return; + if (strcasecmp(interface_name, BT_EVENT_SERVICE) != 0) + return; - if (!dbus_message_has_interface(msg, BT_EVENT_SERVICE)) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + ret_if(signal_name == NULL); - if (!dbus_message_has_path(msg, BT_OPP_CLIENT_PATH)) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + if (strcasecmp(signal_name, BT_AVRCP_CONNECTED) == 0) { + char *address = NULL; - retv_if(member == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + g_variant_get(parameters, "(i&s)", &result, &address); - if (strcasecmp(member, BT_OPP_CONNECTED) == 0) { + _bt_avrcp_event_cb(BLUETOOTH_EVENT_AVRCP_CONTROL_CONNECTED, + result, address, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_AVRCP_DISCONNECTED) == 0) { char *address = NULL; + + g_variant_get(parameters, "(i&s)", &result, &address); + + _bt_avrcp_event_cb(BLUETOOTH_EVENT_AVRCP_CONTROL_DISCONNECTED, + result, address, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_MEDIA_SHUFFLE_STATUS) == 0) { + unsigned int status; + + g_variant_get(parameters, "(u)", &status); + _bt_avrcp_event_cb(BLUETOOTH_EVENT_AVRCP_CONTROL_SHUFFLE_STATUS, + result, &status, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_MEDIA_EQUALIZER_STATUS) == 0) { + unsigned int status; + + g_variant_get(parameters, "(u)", &status); + _bt_avrcp_event_cb(BLUETOOTH_EVENT_AVRCP_CONTROL_EQUALIZER_STATUS, + result, &status, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_MEDIA_REPEAT_STATUS) == 0) { + unsigned int status; + + g_variant_get(parameters, "(u)", &status); + _bt_avrcp_event_cb(BLUETOOTH_EVENT_AVRCP_CONTROL_REPEAT_STATUS, + result, &status, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_MEDIA_SCAN_STATUS) == 0) { + unsigned int status; + + g_variant_get(parameters, "(u)", &status); + _bt_avrcp_event_cb(BLUETOOTH_EVENT_AVRCP_CONTROL_SCAN_STATUS, + result, &status, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_MEDIA_PLAY_STATUS) == 0) { + unsigned int status; + + g_variant_get(parameters, "(u)", &status); + _bt_avrcp_event_cb(BLUETOOTH_EVENT_AVRCP_PLAY_STATUS_CHANGED, + result, &status, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_MEDIA_POSITION_STATUS) == 0) { + unsigned int status; + + g_variant_get(parameters, "(u)", &status); + _bt_avrcp_event_cb(BLUETOOTH_EVENT_AVRCP_SONG_POSITION_STATUS, + result, &status, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_MEDIA_TRACK_CHANGE) == 0) { + GVariant *var = NULL; + media_metadata_attributes_t metadata; + const char *title; + const char *artist; + const char *album; + const char *genre; + unsigned int total_tracks; + unsigned int number; + unsigned int duration; + + g_variant_get(parameters, "(&s&s&s&suuu)", &title, + &artist, &album, &genre, + &total_tracks, &number, + &duration); + memset(&metadata, 0x00, sizeof(media_metadata_attributes_t)); + + metadata.title = title; + metadata.artist = artist; + metadata.album = album; + metadata.genre = genre; + metadata.total_tracks = total_tracks; + metadata.number = number; + metadata.duration = (int64_t)duration; + + _bt_avrcp_event_cb(BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED, + result, &metadata, + event_info->cb, event_info->user_data); + } +} + +void __bt_opp_client_event_filter(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + bt_event_info_t *event_info; + int result = BLUETOOTH_ERROR_NONE; + event_info = (bt_event_info_t *)user_data; + ret_if(event_info == NULL); + + if (strcasecmp(object_path, BT_OPP_CLIENT_PATH) != 0) + return; + if (strcasecmp(interface_name, BT_EVENT_SERVICE) != 0) + return; + + ret_if(signal_name == NULL); + + if (strcasecmp(signal_name, BT_OPP_CONNECTED) == 0) { + const char *address = NULL; int request_id = 0; bluetooth_device_address_t dev_address = { {0} }; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INT32, &request_id, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&si)", &result, + &address, &request_id); if (__bt_is_request_id_exist(request_id) == FALSE) { BT_ERR("Different request id!"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + return; } _bt_convert_addr_string_to_type(dev_address.addr, @@ -951,23 +1279,17 @@ static DBusHandlerResult __bt_opp_client_event_filter(DBusConnection *conn, if (result != BLUETOOTH_ERROR_NONE) { __bt_remove_push_request_id(request_id); } - } else if (strcasecmp(member, BT_OPP_DISCONNECTED) == 0) { - char *address = NULL; + } else if (strcasecmp(signal_name, BT_OPP_DISCONNECTED) == 0) { + const char *address = NULL; int request_id = 0; bluetooth_device_address_t dev_address = { {0} }; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INT32, &request_id, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&si)", &result, &address, + &request_id); if (__bt_is_request_id_exist(request_id) == FALSE) { BT_ERR("Different request id!"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + return; } _bt_convert_addr_string_to_type(dev_address.addr, @@ -978,25 +1300,18 @@ static DBusHandlerResult __bt_opp_client_event_filter(DBusConnection *conn, event_info->cb, event_info->user_data); __bt_remove_push_request_id(request_id); - } else if (strcasecmp(member, BT_TRANSFER_STARTED) == 0) { - char *file_name = NULL; + } else if (strcasecmp(signal_name, BT_TRANSFER_STARTED) == 0) { + const char *file_name = NULL; int request_id = 0; guint64 size = 0; bt_opc_transfer_info_t transfer_info; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &file_name, - DBUS_TYPE_UINT64, &size, - DBUS_TYPE_INT32, &request_id, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&sti)", &result, &file_name, + &size, &request_id); if (__bt_is_request_id_exist(request_id) == FALSE) { BT_ERR("Different request id!"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + return; } memset(&transfer_info, 0x00, sizeof(bt_opc_transfer_info_t)); @@ -1009,27 +1324,19 @@ static DBusHandlerResult __bt_opp_client_event_filter(DBusConnection *conn, event_info->cb, event_info->user_data); g_free(transfer_info.filename); - } else if (strcasecmp(member, BT_TRANSFER_PROGRESS) == 0) { - char *file_name = NULL; + } else if (strcasecmp(signal_name, BT_TRANSFER_PROGRESS) == 0) { + const char *file_name = NULL; int request_id = 0; guint64 size = 0; int progress = 0; bt_opc_transfer_info_t transfer_info; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &file_name, - DBUS_TYPE_UINT64, &size, - DBUS_TYPE_INT32, &progress, - DBUS_TYPE_INT32, &request_id, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&stii)", &result, + &file_name, &size, &progress, &request_id); if (__bt_is_request_id_exist(request_id) == FALSE) { BT_ERR("Different request id!"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + return; } memset(&transfer_info, 0x00, sizeof(bt_opc_transfer_info_t)); @@ -1043,25 +1350,18 @@ static DBusHandlerResult __bt_opp_client_event_filter(DBusConnection *conn, event_info->cb, event_info->user_data); g_free(transfer_info.filename); - } else if (strcasecmp(member, BT_TRANSFER_COMPLETED) == 0) { - char *file_name = NULL; + } else if (strcasecmp(signal_name, BT_TRANSFER_COMPLETED) == 0) { + const char *file_name = NULL; int request_id = 0; guint64 size = 0; bt_opc_transfer_info_t transfer_info; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &file_name, - DBUS_TYPE_UINT64, &size, - DBUS_TYPE_INT32, &request_id, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&sti)", &result, + &file_name, &size, &request_id); if (__bt_is_request_id_exist(request_id) == FALSE) { BT_ERR("Different request id!"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + return; } memset(&transfer_info, 0x00, sizeof(bt_opc_transfer_info_t)); @@ -1075,49 +1375,38 @@ static DBusHandlerResult __bt_opp_client_event_filter(DBusConnection *conn, g_free(transfer_info.filename); } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } -static DBusHandlerResult __bt_opp_server_event_filter(DBusConnection *conn, - DBusMessage *msg, void *data) +void __bt_opp_server_event_filter(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) { bt_event_info_t *event_info; int result = BLUETOOTH_ERROR_NONE; - const char *member = dbus_message_get_member(msg); - - event_info = (bt_event_info_t *)data; - retv_if(event_info == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + event_info = (bt_event_info_t *)user_data; + ret_if(event_info == NULL); - if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + if (strcasecmp(object_path, BT_OPP_SERVER_PATH) != 0) + return; + if (strcasecmp(interface_name, BT_EVENT_SERVICE) != 0) + return; - if (!dbus_message_has_interface(msg, BT_EVENT_SERVICE)) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + ret_if(signal_name == NULL); - if (!dbus_message_has_path(msg, BT_OPP_SERVER_PATH)) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - retv_if(member == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - - if (strcasecmp(member, BT_TRANSFER_AUTHORIZED) == 0) { + if (strcasecmp(signal_name, BT_TRANSFER_AUTHORIZED) == 0) { /* Native only event */ - char *file_name = NULL; + const char *file_name = NULL; guint64 size = 0; bt_obex_server_authorize_into_t auth_info; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &file_name, - DBUS_TYPE_UINT64, &size, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&st)", &result, &file_name, &size); /* OSP server: Don't get this event */ - retv_if(obex_server_id == BT_CUSTOM_SERVER, - DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + ret_if(obex_server_id == BT_CUSTOM_SERVER); memset(&auth_info, 0x00, sizeof(bt_obex_server_authorize_into_t)); @@ -1129,24 +1418,16 @@ static DBusHandlerResult __bt_opp_server_event_filter(DBusConnection *conn, event_info->cb, event_info->user_data); g_free(auth_info.filename); - } else if (strcasecmp(member, BT_CONNECTION_AUTHORIZED) == 0) { + } else if (strcasecmp(signal_name, BT_CONNECTION_AUTHORIZED) == 0) { /* OSP only event */ - char *address = NULL; - char *name = NULL; + const char *address = NULL; + const char *name = NULL; bluetooth_device_address_t dev_address = { {0} }; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&s&s)", &result, &address, &name); /* Native server: Don't get this event */ - retv_if(obex_server_id == BT_NATIVE_SERVER, - DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + ret_if(obex_server_id == BT_NATIVE_SERVER); _bt_convert_addr_string_to_type(dev_address.addr, address); @@ -1154,30 +1435,34 @@ static DBusHandlerResult __bt_opp_server_event_filter(DBusConnection *conn, _bt_common_event_cb(BLUETOOTH_EVENT_OBEX_SERVER_CONNECTION_AUTHORIZE, result, &dev_address, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_TRANSFER_STARTED) == 0) { - char *file_name = NULL; - char *type = NULL; + } else if (strcasecmp(signal_name, BT_TRANSFER_CONNECTED) == 0) { + + g_variant_get(parameters, "(i)", &result); + + _bt_common_event_cb(BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_CONNECTED, + result, NULL, event_info->cb, + event_info->user_data); + } else if (strcasecmp(signal_name, BT_TRANSFER_DISCONNECTED) == 0) { + + g_variant_get(parameters, "(i)", &result); + + _bt_common_event_cb(BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_DISCONNECTED, + result, NULL, event_info->cb, + event_info->user_data); + } else if (strcasecmp(signal_name, BT_TRANSFER_STARTED) == 0) { + const char *file_name = NULL; + const char *type = NULL; int transfer_id = 0; int server_type = 0; /* bt_server_type_t */ guint64 size = 0; bt_obex_server_transfer_info_t transfer_info; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &file_name, - DBUS_TYPE_STRING, &type, - DBUS_TYPE_UINT64, &size, - DBUS_TYPE_INT32, &transfer_id, - DBUS_TYPE_INT32, &server_type, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&s&stii)", &result, &file_name, + &type, &size, &transfer_id, &server_type); /* Other server's event */ - retv_if(obex_server_id != server_type && - server_type != BT_FTP_SERVER, - DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + ret_if(obex_server_id != server_type && + server_type != BT_FTP_SERVER); memset(&transfer_info, 0x00, sizeof(bt_obex_server_transfer_info_t)); @@ -1185,6 +1470,8 @@ static DBusHandlerResult __bt_opp_server_event_filter(DBusConnection *conn, transfer_info.type = g_strdup(type); transfer_info.file_size = size; transfer_info.transfer_id = transfer_id; + transfer_info.server_type = (server_type == BT_FTP_SERVER) ? + FTP_SERVER : OPP_SERVER; _bt_common_event_cb(BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_STARTED, result, &transfer_info, @@ -1192,32 +1479,22 @@ static DBusHandlerResult __bt_opp_server_event_filter(DBusConnection *conn, g_free(transfer_info.filename); g_free(transfer_info.type); - } else if (strcasecmp(member, BT_TRANSFER_PROGRESS) == 0) { - char *file_name = NULL; - char *type = NULL; + } else if (strcasecmp(signal_name, BT_TRANSFER_PROGRESS) == 0) { + const char *file_name = NULL; + const char *type = NULL; int transfer_id = 0; int progress = 0; int server_type = 0; /* bt_server_type_t */ guint64 size = 0; bt_obex_server_transfer_info_t transfer_info; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &file_name, - DBUS_TYPE_STRING, &type, - DBUS_TYPE_UINT64, &size, - DBUS_TYPE_INT32, &transfer_id, - DBUS_TYPE_INT32, &progress, - DBUS_TYPE_INT32, &server_type, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&s&stiii)", &result, &file_name, + &type, &size, &transfer_id, + &progress, &server_type); /* Other server's event */ - retv_if(obex_server_id != server_type && - server_type != BT_FTP_SERVER, - DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + ret_if(obex_server_id != server_type && + server_type != BT_FTP_SERVER); memset(&transfer_info, 0x00, sizeof(bt_obex_server_transfer_info_t)); @@ -1226,6 +1503,8 @@ static DBusHandlerResult __bt_opp_server_event_filter(DBusConnection *conn, transfer_info.file_size = size; transfer_info.transfer_id = transfer_id; transfer_info.percentage = progress; + transfer_info.server_type = (server_type == BT_FTP_SERVER) ? + FTP_SERVER : OPP_SERVER; _bt_common_event_cb(BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_PROGRESS, result, &transfer_info, @@ -1233,40 +1512,34 @@ static DBusHandlerResult __bt_opp_server_event_filter(DBusConnection *conn, g_free(transfer_info.filename); g_free(transfer_info.type); - } else if (strcasecmp(member, BT_TRANSFER_COMPLETED) == 0) { - char *file_name = NULL; - char *device_name = NULL; - char *type = NULL; + } else if (strcasecmp(signal_name, BT_TRANSFER_COMPLETED) == 0) { + const char *file_name = NULL; + const char *device_name = NULL; + const char *type = NULL; + const char *file_path; int transfer_id = 0; int server_type = 0; /* bt_server_type_t */ guint64 size = 0; bt_obex_server_transfer_info_t transfer_info; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &file_name, - DBUS_TYPE_STRING, &type, - DBUS_TYPE_STRING, &device_name, - DBUS_TYPE_UINT64, &size, - DBUS_TYPE_INT32, &transfer_id, - DBUS_TYPE_INT32, &server_type, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&s&s&s&stii)", &result, &file_name, + &type, &device_name, &file_path, &size, + &transfer_id, &server_type); /* Other server's event */ - retv_if(obex_server_id != server_type && - server_type != BT_FTP_SERVER, - DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + ret_if(obex_server_id != server_type && + server_type != BT_FTP_SERVER); memset(&transfer_info, 0x00, sizeof(bt_obex_server_transfer_info_t)); transfer_info.filename = g_strdup(file_name); transfer_info.type = g_strdup(type); transfer_info.device_name = g_strdup(device_name); + transfer_info.file_path = g_strdup(file_path); transfer_info.file_size = size; transfer_info.transfer_id = transfer_id; + transfer_info.server_type = (server_type == BT_FTP_SERVER) ? + FTP_SERVER : OPP_SERVER; _bt_common_event_cb(BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_COMPLETED, result, &transfer_info, @@ -1275,47 +1548,192 @@ static DBusHandlerResult __bt_opp_server_event_filter(DBusConnection *conn, g_free(transfer_info.filename); g_free(transfer_info.type); g_free(transfer_info.device_name); + g_free(transfer_info.file_path); } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } -static DBusHandlerResult __bt_rfcomm_client_event_filter(DBusConnection *conn, - DBusMessage *msg, void *data) +void __bt_pbap_client_event_filter(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) { bt_event_info_t *event_info; int result = BLUETOOTH_ERROR_NONE; - const char *member = dbus_message_get_member(msg); + event_info = (bt_event_info_t *)user_data; + ret_if(event_info == NULL); - event_info = (bt_event_info_t *)data; - retv_if(event_info == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + if (strcasecmp(object_path, BT_PBAP_CLIENT_PATH) != 0) + return; + if (strcasecmp(interface_name, BT_EVENT_SERVICE) != 0) + return; - if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + ret_if(signal_name == NULL); - if (!dbus_message_has_interface(msg, BT_EVENT_SERVICE)) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + if (strcasecmp(signal_name, BT_PBAP_CONNECTED) == 0) { + bt_pbap_connected_t connected = { { { 0 }, }, }; + char *address = NULL; + int enabled = -1; + + g_variant_get(parameters, "(i&si)", &result, &address, &enabled); - if (!dbus_message_has_path(msg, BT_RFCOMM_CLIENT_PATH)) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + BT_DBG("address: %s", address); + BT_DBG("enabled: %d", enabled); - retv_if(member == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + _bt_convert_addr_string_to_type(connected.btaddr.addr, + address); + connected.connected = enabled; - if (strcasecmp(member, BT_RFCOMM_CONNECTED) == 0) { + _bt_common_event_cb(BLUETOOTH_PBAP_CONNECTED, + result, &connected, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_PBAP_PHONEBOOK_SIZE) == 0) { + bt_pbap_phonebook_size_t pb_size = { { { 0 }, }, }; char *address = NULL; - char *uuid = NULL; + int size = 0; + + g_variant_get(parameters, "(i&si)", &result, &address, &size); + + BT_DBG("address: %s", address); + BT_DBG("size: %d", size); + + _bt_convert_addr_string_to_type(pb_size.btaddr.addr, + address); + pb_size.size = size; + + _bt_common_event_cb(BLUETOOTH_PBAP_PHONEBOOK_SIZE, + result, &pb_size, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_PBAP_PHONEBOOK_PULL) == 0) { + bt_pbap_phonebook_pull_t pb_pull = { { { 0 } }, }; + char *address = NULL; + char *vcf_file = NULL; + int success = -1; + + g_variant_get(parameters, "(i&s&si)", &result, &address, &vcf_file, &success); + + BT_DBG("address: %s", address); + BT_DBG("vcf_file: %s", vcf_file); + BT_DBG("success: %d", success); + + _bt_convert_addr_string_to_type(pb_pull.btaddr.addr, + address); + pb_pull.vcf_file = vcf_file; + pb_pull.success = success; + _bt_common_event_cb(BLUETOOTH_PBAP_PHONEBOOK_PULL, + result, &pb_pull, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_PBAP_VCARD_LIST) == 0) { + bt_pbap_vcard_list_t vc_list = { { { 0 } }, }; + char *address = NULL; + unsigned int count = 0; + gchar **list = NULL; + GVariant *string_var; + int success = -1; + int i = 0; + + g_variant_get(parameters, "(i&s@as)", &result, &address, &string_var); + + list = (gchar **)g_variant_get_strv(string_var, &count); + + success = !result; + BT_DBG("address: %s", address); + for(i = 0; i < count; i++) + BT_DBG("%s", list[i]); + BT_DBG("success: %d", success); + + _bt_convert_addr_string_to_type(vc_list.btaddr.addr, + address); + vc_list.vcards = list; + vc_list.length = count; + vc_list.success = success; + _bt_common_event_cb(BLUETOOTH_PBAP_VCARD_LIST, + result, &vc_list, + event_info->cb, event_info->user_data); + + g_variant_unref(string_var); + //free lists + } else if (strcasecmp(signal_name, BT_PBAP_VCARD_PULL) == 0) { + bt_pbap_vcard_pull_t vc_pull = { { { 0 } }, }; + char *address = NULL; + char *vcf_file = NULL; + int success = -1; + + g_variant_get(parameters, "(i&s&si)", &result, &address, &vcf_file, &success); + + BT_DBG("address: %s", address); + BT_DBG("vcf_file: %s", vcf_file); + BT_DBG("success: %d", success); + + _bt_convert_addr_string_to_type(vc_pull.btaddr.addr, + address); + vc_pull.vcf_file = vcf_file; + vc_pull.success = success; + _bt_common_event_cb(BLUETOOTH_PBAP_VCARD_PULL, + result, &vc_pull, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_PBAP_SEARCH_PHONEBOOK) == 0) { + bt_pbap_phonebook_search_list_t vc_list = { { { 0 } }, }; + char *address = NULL; + unsigned int count = 0; + gchar **list = NULL; + GVariant *string_var; + int success = -1; + int i = 0; + + g_variant_get(parameters, "(i&s@as)", &result, &address, &string_var); + + list = (gchar **)g_variant_get_strv(string_var, &count); + success = !result; + BT_DBG("address: %s", address); + for(i = 0; i < count; i++) + BT_DBG("%s", list[i]); + BT_DBG("success: %d", success); + + _bt_convert_addr_string_to_type(vc_list.btaddr.addr, + address); + vc_list.vcards = list; + vc_list.length = count; + vc_list.success = success; + _bt_common_event_cb(BLUETOOTH_PBAP_PHONEBOOK_SEARCH, + result, &vc_list, + event_info->cb, event_info->user_data); + + g_variant_unref(string_var); + //free lists + } +} + +void __bt_rfcomm_client_event_filter(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + bt_event_info_t *event_info; + int result = BLUETOOTH_ERROR_NONE; + event_info = (bt_event_info_t *)user_data; + ret_if(event_info == NULL); + + if (strcasecmp(object_path, BT_RFCOMM_CLIENT_PATH) != 0) + return; + if (strcasecmp(interface_name, BT_EVENT_SERVICE) != 0) + return; + + ret_if(signal_name == NULL); + + if (strcasecmp(signal_name, BT_RFCOMM_CONNECTED) == 0) { + const char *address = NULL; + const char *uuid = NULL; int socket_fd = 0; bluetooth_rfcomm_connection_t conn_info; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_STRING, &uuid, - DBUS_TYPE_INT16, &socket_fd, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&s&sn)", &result, &address, + &uuid, &socket_fd); memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t)); conn_info.device_role = RFCOMM_ROLE_CLIENT; @@ -1327,21 +1745,14 @@ static DBusHandlerResult __bt_rfcomm_client_event_filter(DBusConnection *conn, _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_CONNECTED, result, &conn_info, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_RFCOMM_DISCONNECTED) == 0) { - char *address = NULL; - char *uuid = NULL; + } else if (strcasecmp(signal_name, BT_RFCOMM_DISCONNECTED) == 0) { + const char *address = NULL; + const char *uuid = NULL; int socket_fd = 0; bluetooth_rfcomm_disconnection_t disconn_info; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_STRING, &uuid, - DBUS_TYPE_INT16, &socket_fd, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&s&sn)", &result, &address, + &uuid, &socket_fd); memset(&disconn_info, 0x00, sizeof(bluetooth_rfcomm_disconnection_t)); disconn_info.device_role = RFCOMM_ROLE_CLIENT; @@ -1353,72 +1764,58 @@ static DBusHandlerResult __bt_rfcomm_client_event_filter(DBusConnection *conn, _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_DISCONNECTED, result, &disconn_info, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_RFCOMM_DATA_RECEIVED) == 0) { - char *buffer = NULL; + } else if (strcasecmp(signal_name, BT_RFCOMM_DATA_RECEIVED) == 0) { + char *buffer; int buffer_len = 0; int socket_fd = 0; bluetooth_rfcomm_received_data_t data_r; + GVariant *byte_var; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_INT16, &socket_fd, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, - &buffer, &buffer_len, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(in@ay)", &result, &socket_fd, + &byte_var); + + buffer_len = g_variant_get_size( byte_var); + buffer = (char *) g_variant_get_data(byte_var); data_r.socket_fd = socket_fd; data_r.buffer_size = buffer_len; - data_r.buffer = g_memdup(buffer, buffer_len); + data_r.buffer = buffer; _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_DATA_RECEIVED, result, &data_r, event_info->cb, event_info->user_data); - - g_free(data_r.buffer); + g_variant_unref(byte_var); } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } -static DBusHandlerResult __bt_rfcomm_server_event_filter(DBusConnection *conn, - DBusMessage *msg, void *data) +void __bt_rfcomm_server_event_filter(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) { bt_event_info_t *event_info; int result = BLUETOOTH_ERROR_NONE; - const char *member = dbus_message_get_member(msg); + event_info = (bt_event_info_t *)user_data; + ret_if(event_info == NULL); - event_info = (bt_event_info_t *)data; - retv_if(event_info == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + if (strcasecmp(object_path, BT_RFCOMM_SERVER_PATH) != 0) + return; + if (strcasecmp(interface_name, BT_EVENT_SERVICE) != 0) + return; - if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + ret_if(signal_name == NULL); - if (!dbus_message_has_interface(msg, BT_EVENT_SERVICE)) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - if (!dbus_message_has_path(msg, BT_RFCOMM_SERVER_PATH)) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - retv_if(member == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - - if (strcasecmp(member, BT_RFCOMM_CONNECTED) == 0) { - char *address = NULL; - char *uuid = NULL; + if (strcasecmp(signal_name, BT_RFCOMM_CONNECTED) == 0) { + const char *address = NULL; + const char *uuid = NULL; int socket_fd = 0; bluetooth_rfcomm_connection_t conn_info; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_STRING, &uuid, - DBUS_TYPE_INT16, &socket_fd, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&s&sn)", &result, &address, + &uuid, &socket_fd); memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t)); conn_info.device_role = RFCOMM_ROLE_SERVER; @@ -1430,21 +1827,14 @@ static DBusHandlerResult __bt_rfcomm_server_event_filter(DBusConnection *conn, _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_CONNECTED, result, &conn_info, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_RFCOMM_DISCONNECTED) == 0) { - char *address = NULL; - char *uuid = NULL; + } else if (strcasecmp(signal_name, BT_RFCOMM_DISCONNECTED) == 0) { + const char *address = NULL; + const char *uuid = NULL; int socket_fd = 0; bluetooth_rfcomm_disconnection_t disconn_info; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_STRING, &uuid, - DBUS_TYPE_INT16, &socket_fd, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&s&sn)", &result, &address, + &uuid, &socket_fd); memset(&disconn_info, 0x00, sizeof(bluetooth_rfcomm_disconnection_t)); disconn_info.device_role = RFCOMM_ROLE_SERVER; @@ -1456,28 +1846,20 @@ static DBusHandlerResult __bt_rfcomm_server_event_filter(DBusConnection *conn, _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_DISCONNECTED, result, &disconn_info, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_CONNECTION_AUTHORIZED) == 0) { + } else if (strcasecmp(signal_name, BT_CONNECTION_AUTHORIZED) == 0) { /* OSP only event */ bluetooth_rfcomm_connection_request_t req_ind; char *address = NULL; char *uuid = NULL; char *name = NULL; + char *path = NULL; int socket_fd = 0; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_STRING, &uuid, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INT16, &socket_fd, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(i&s&s&s&sn)", &result, &address, + &uuid, &name, &path, &socket_fd); - /* Don't send the authorized event to other server */ - retv_if(__bt_is_server_exist(socket_fd) == FALSE, - DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + if (_check_uuid_path(path, uuid) == FALSE) + return; memset(&req_ind, 0x00, sizeof(bluetooth_rfcomm_connection_request_t)); _bt_convert_addr_string_to_type(req_ind.device_addr.addr, @@ -1488,50 +1870,195 @@ static DBusHandlerResult __bt_rfcomm_server_event_filter(DBusConnection *conn, _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_AUTHORIZE, result, &req_ind, event_info->cb, event_info->user_data); - } else if (strcasecmp(member, BT_RFCOMM_SERVER_REMOVED) == 0) { + } else if (strcasecmp(signal_name, BT_RFCOMM_SERVER_REMOVED) == 0) { /* OSP only event */ int socket_fd = 0; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_INT16, &socket_fd, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(in)", &result, &socket_fd); - retv_if(__bt_is_server_exist(socket_fd) == FALSE, - DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + ret_if(__bt_is_server_exist(socket_fd) == FALSE); _bt_remove_server(socket_fd); - } else if (strcasecmp(member, BT_RFCOMM_DATA_RECEIVED) == 0) { + } else if (strcasecmp(signal_name, BT_RFCOMM_DATA_RECEIVED) == 0) { char *buffer = NULL; int buffer_len = 0; int socket_fd = 0; bluetooth_rfcomm_received_data_t data_r; + GVariant *byte_var; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_INT16, &socket_fd, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, - &buffer, &buffer_len, - DBUS_TYPE_INVALID)) { - BT_ERR("Unexpected parameters in signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + g_variant_get(parameters, "(in@ay)", &result, + &socket_fd, &byte_var); + + buffer_len = g_variant_get_size( byte_var); + buffer = (char *) g_variant_get_data(byte_var); data_r.socket_fd = socket_fd; data_r.buffer_size = buffer_len; - data_r.buffer = g_memdup(buffer, buffer_len); + data_r.buffer = buffer; _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_DATA_RECEIVED, result, &data_r, event_info->cb, event_info->user_data); - - g_free(data_r.buffer); + g_variant_unref(byte_var); } +} + +void __bt_hf_agent_event_filter(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + BT_DBG("+\n"); + + bt_event_info_t *event_info; + int result = BLUETOOTH_ERROR_NONE; + event_info = (bt_event_info_t *)user_data; + ret_if(event_info == NULL); + + BT_DBG("+\n"); + if (strcasecmp(object_path, BT_HF_AGENT_PATH) != 0) + return; + if (strcasecmp(interface_name, BT_HF_SERVICE_INTERFACE) != 0) + return; - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + ret_if(signal_name == NULL); + + BT_DBG("%s",signal_name); + if (strcasecmp(signal_name, "Connected") == 0) { + char *address = NULL; + + g_variant_get(parameters, "(s)", &address); + _bt_hf_event_cb(BLUETOOTH_EVENT_HF_CONNECTED, + result, address, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, "Disconnected") == 0) { + char *address = NULL; + + g_variant_get(parameters, "(s)", &address); + _bt_hf_event_cb(BLUETOOTH_EVENT_HF_DISCONNECTED, + result, address, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, "AudioConnected") == 0) { + _bt_hf_event_cb(BLUETOOTH_EVENT_HF_AUDIO_CONNECTED, + result, NULL, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, "AudioDisconnected") == 0) { + _bt_hf_event_cb(BLUETOOTH_EVENT_HF_AUDIO_DISCONNECTED, + result, NULL, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, "Ring") == 0) { + char *phoneno = NULL; + + g_variant_get(parameters, "(&s)", &phoneno); + + _bt_hf_event_cb(BLUETOOTH_EVENT_HF_RING_INDICATOR, + result, phoneno, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, "CallWaiting") == 0) { + char *phoneno = NULL; + + g_variant_get(parameters, "(&s)", &phoneno); + + _bt_hf_event_cb(BLUETOOTH_EVENT_HF_CALL_WAITING, + result, phoneno, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, "CallTerminated") == 0) { + _bt_hf_event_cb(BLUETOOTH_EVENT_HF_CALL_TERMINATED, + result, NULL, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, "CallStarted") == 0) { + _bt_hf_event_cb(BLUETOOTH_EVENT_HF_CALL_STARTED, + result, NULL, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, "CallEnded") == 0) { + _bt_hf_event_cb(BLUETOOTH_EVENT_HF_CALL_ENDED, + result, NULL, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, "NoCallsHeld") == 0) { + _bt_hf_event_cb(BLUETOOTH_EVENT_HF_CALL_UNHOLD, + result, NULL, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, "CallsSwapped") == 0) { + _bt_hf_event_cb(BLUETOOTH_EVENT_HF_CALL_SWAPPED, + result, NULL, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, "CallOnHold") == 0) { + _bt_hf_event_cb(BLUETOOTH_EVENT_HF_CALL_ON_HOLD, + result, NULL, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, "CallStatusUpdate") == 0) { + int call_count; + GVariant *var_data = NULL; + char *number = NULL; + int idx, dir, status, mpart; + bt_hf_call_list_s *handle = NULL; + + g_variant_get(parameters, "(i@a(siiii))", &call_count, + &var_data); + BT_DBG("call count : %d",call_count); + + if (var_data){ + GVariantIter *iter = NULL; + __bt_call_list_create(&handle); + + g_variant_get(var_data, "a(siiii)", &iter); + while (g_variant_iter_loop(iter, "(siiii)", &number, + &dir, &status, &mpart, &idx)) { + BT_DBG("call number:%s, dir:%d, status : %d", + number, dir, status); + BT_DBG("call mpart : %d, idx : %d",mpart, idx); + __bt_call_list_add(handle, number, dir, + status, mpart, idx); + } + g_variant_iter_free(iter); + g_variant_unref(var_data); + } + + if (handle && (call_count == g_list_length(handle->list))) { + handle->count = call_count; + _bt_hf_event_cb(BLUETOOTH_EVENT_HF_CALL_STATUS, + result, handle, + event_info->cb, event_info->user_data); + } else { + BT_ERR(" Mismatch in call count : %d",call_count); + } + + __bt_call_list_destroy(handle); + } else if (strcasecmp(signal_name, "VoiceRecognition") == 0) { + int status; + g_variant_get(parameters, "(i)", &status); + BT_DBG("status = [%d]\n", status); + if (status) + _bt_hf_event_cb(BLUETOOTH_EVENT_HF_VOICE_RECOGNITION_ENABLED, + result, NULL, + event_info->cb, event_info->user_data); + else + _bt_hf_event_cb(BLUETOOTH_EVENT_HF_VOICE_RECOGNITION_DISABLED, + result, NULL, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, "VolumeSpeaker") == 0) { + int value; + g_variant_get(parameters, "(i)", &value); + BT_DBG("Value = [%d]\n", value); + _bt_hf_event_cb(BLUETOOTH_EVENT_HF_VOLUME_SPEAKER, + result, &value, + event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, "SamsungXSAT") == 0) { + int value = 0; + char *msg = NULL; + bluetooth_vendor_dep_at_cmd_t cmd; + g_variant_get(parameters, "(i&s)", &value, &msg); + BT_DBG("Value = [%d], message = %s\n", value, msg); + cmd.app_id = value; + cmd.message = msg; + _bt_hf_event_cb(BLUETOOTH_EVENT_HF_VENDOR_DEP_CMD, + result, &cmd, + event_info->cb, event_info->user_data); + } + BT_DBG("-\n"); } static void __bt_remove_all_events(void) @@ -1560,13 +2087,14 @@ static gboolean __bt_event_is_registered(int event_type) if (info == NULL) continue; - retv_if(info->event_type == event_type, TRUE); + if (info->event_type == event_type) + return TRUE; } return FALSE; } -bt_event_info_t* __bt_event_get_cb_data(int event_type) +bt_event_info_t *_bt_event_get_cb_data(int event_type) { GSList *l; bt_event_info_t *info; @@ -1644,6 +2172,11 @@ int _bt_deinit_event_handler(void) __bt_remove_all_events(); + if (disable_timer_id > 0) { + g_source_remove(disable_timer_id); + disable_timer_id = 0; + } + is_initialized = FALSE; return BLUETOOTH_ERROR_NONE; @@ -1655,19 +2188,18 @@ static void __bt_event_data_free(void *data) ret_if(cb_data == NULL); - if (cb_data->conn) - dbus_connection_unref(cb_data->conn); - + g_object_unref(cb_data->conn); g_free(cb_data); } int _bt_register_event(int event_type, void *event_cb, void *user_data) { - DBusError dbus_error; - char *match; - DBusConnection *connection_type; - DBusHandleMessageFunction event_func; + GError *error = NULL; + GDBusConnection *connection_type; + GDBusSignalCallback event_func; bt_event_info_t *cb_data; + const char *path; + const char *interface = BT_EVENT_SERVICE; if (is_initialized == FALSE) _bt_init_event_handler(); @@ -1679,139 +2211,101 @@ int _bt_register_event(int event_type, void *event_cb, void *user_data) switch (event_type) { case BT_ADAPTER_EVENT: - connection_type = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); - retv_if(connection_type == NULL, BLUETOOTH_ERROR_INTERNAL); - event_func = __bt_adapter_event_filter; - match = g_strdup_printf(EVENT_MATCH_RULE, BT_EVENT_SERVICE, - BT_ADAPTER_PATH); + path = BT_ADAPTER_PATH; + break; + case BT_LE_ADAPTER_EVENT: + event_func = __bt_adapter_le_event_filter; + path = BT_LE_ADAPTER_PATH; break; case BT_DEVICE_EVENT: - connection_type = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); - retv_if(connection_type == NULL, BLUETOOTH_ERROR_INTERNAL); - event_func = __bt_device_event_filter; - match = g_strdup_printf(EVENT_MATCH_RULE, BT_EVENT_SERVICE, - BT_DEVICE_PATH); + path = BT_DEVICE_PATH; break; case BT_HID_EVENT: - connection_type = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); - retv_if(connection_type == NULL, BLUETOOTH_ERROR_INTERNAL); - event_func = __bt_hid_event_filter; - match = g_strdup_printf(EVENT_MATCH_RULE, BT_EVENT_SERVICE, - BT_HID_PATH); + path = BT_HID_PATH; break; case BT_HEADSET_EVENT: - connection_type = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); - retv_if(connection_type == NULL, BLUETOOTH_ERROR_INTERNAL); - event_func = __bt_headset_event_filter; - match = g_strdup_printf(EVENT_MATCH_RULE, BT_EVENT_SERVICE, - BT_HEADSET_PATH); + path = BT_HEADSET_PATH; break; case BT_NETWORK_EVENT: - connection_type = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); - retv_if(connection_type == NULL, BLUETOOTH_ERROR_INTERNAL); - event_func = __bt_network_event_filter; - match = g_strdup_printf(EVENT_MATCH_RULE, BT_EVENT_SERVICE, - BT_NETWORK_PATH); + path = BT_NETWORK_PATH; break; case BT_AVRCP_EVENT: - connection_type = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); - retv_if(connection_type == NULL, BLUETOOTH_ERROR_INTERNAL); - event_func = __bt_avrcp_event_filter; - match = g_strdup_printf(EVENT_MATCH_RULE, BT_EVENT_SERVICE, - BT_AVRCP_PATH); + path = BT_AVRCP_PATH; + break; + case BT_AVRCP_CONTROL_EVENT: + event_func = __bt_avrcp_control_event_filter; + path = BT_AVRCP_CONTROL_PATH; break; case BT_OPP_CLIENT_EVENT: - connection_type = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); - retv_if(connection_type == NULL, BLUETOOTH_ERROR_INTERNAL); - event_func = __bt_opp_client_event_filter; - match = g_strdup_printf(EVENT_MATCH_RULE, BT_EVENT_SERVICE, - BT_OPP_CLIENT_PATH); + path = BT_OPP_CLIENT_PATH; break; case BT_OPP_SERVER_EVENT: - connection_type = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); - retv_if(connection_type == NULL, BLUETOOTH_ERROR_INTERNAL); - event_func = __bt_opp_server_event_filter; - match = g_strdup_printf(EVENT_MATCH_RULE, BT_EVENT_SERVICE, - BT_OPP_SERVER_PATH); + path = BT_OPP_SERVER_PATH; + break; + case BT_PBAP_CLIENT_EVENT: + event_func = __bt_pbap_client_event_filter; + path = BT_PBAP_CLIENT_PATH; break; case BT_RFCOMM_CLIENT_EVENT: - connection_type = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); - retv_if(connection_type == NULL, BLUETOOTH_ERROR_INTERNAL); - event_func = __bt_rfcomm_client_event_filter; - match = g_strdup_printf(EVENT_MATCH_RULE, BT_EVENT_SERVICE, - BT_RFCOMM_CLIENT_PATH); + path = BT_RFCOMM_CLIENT_PATH; break; case BT_RFCOMM_SERVER_EVENT: - connection_type = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); - retv_if(connection_type == NULL, BLUETOOTH_ERROR_INTERNAL); - event_func = __bt_rfcomm_server_event_filter; - match = g_strdup_printf(EVENT_MATCH_RULE, BT_EVENT_SERVICE, - BT_RFCOMM_SERVER_PATH); + path = BT_RFCOMM_SERVER_PATH; + break; + case BT_HF_AGENT_EVENT: + BT_DBG("BT_HF_AGENT_EVENT\n"); + event_func = __bt_hf_agent_event_filter; + path = BT_HF_AGENT_PATH; + interface = BT_HF_SERVICE_INTERFACE; break; default: BT_ERR("Unknown event"); return BLUETOOTH_ERROR_INTERNAL; } + connection_type = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (connection_type == NULL) { + if (error) { + BT_ERR("Unable to get the bus: %s", error->message); + g_clear_error(&error); + } + return BLUETOOTH_ERROR_INTERNAL; + } + cb_data = g_new0(bt_event_info_t, 1); cb_data->event_type = event_type; cb_data->conn = connection_type; - cb_data->func = event_func; - cb_data->match_rule = match; cb_data->cb = event_cb; cb_data->user_data = user_data; - if (!dbus_connection_add_filter(connection_type, event_func, - (void *)cb_data, __bt_event_data_free)) { - BT_ERR("Fail to add filter"); - goto fail; - } - - dbus_error_init(&dbus_error); - - if (match) - dbus_bus_add_match(connection_type, match, &dbus_error); - - if (dbus_error_is_set(&dbus_error)) { - BT_ERR("Fail to add match: %s\n", dbus_error.message); - dbus_error_free(&dbus_error); - goto fail; - } + cb_data->id = g_dbus_connection_signal_subscribe(connection_type, + NULL, interface, NULL, path, NULL, 0, + event_func, cb_data, NULL); event_list = g_slist_append(event_list, cb_data); return BLUETOOTH_ERROR_NONE; -fail: - if (connection_type) - dbus_connection_unref(connection_type); - - g_free(cb_data); - g_free(match); - return BLUETOOTH_ERROR_INTERNAL; } int _bt_unregister_event(int event_type) { - DBusConnection *connection_type; - DBusHandleMessageFunction event_func; + GDBusConnection *connection_type; bt_event_info_t *cb_data; - char *match; - DBusError dbus_error; if (is_initialized == FALSE) { BT_ERR("Event is not registered"); - return BLUETOOTH_ERROR_INTERNAL; + return BLUETOOTH_ERROR_NOT_INITIALIZED; } if (__bt_event_is_registered(event_type) == FALSE) { @@ -1819,7 +2313,7 @@ int _bt_unregister_event(int event_type) return BLUETOOTH_ERROR_INTERNAL; } - cb_data = __bt_event_get_cb_data(event_type); + cb_data = _bt_event_get_cb_data(event_type); if (cb_data == NULL) { BT_ERR("No matched event data"); @@ -1827,26 +2321,72 @@ int _bt_unregister_event(int event_type) } connection_type = cb_data->conn; - event_func = cb_data->func; - match = cb_data->match_rule; event_list = g_slist_remove(event_list, (void *)cb_data); retv_if(connection_type == NULL, BLUETOOTH_ERROR_INTERNAL); - retv_if(event_func == NULL, BLUETOOTH_ERROR_INTERNAL); - dbus_error_init(&dbus_error); + g_dbus_connection_signal_unsubscribe(connection_type, cb_data->id); + + __bt_event_data_free((void *)cb_data); + + return BLUETOOTH_ERROR_NONE; +} + +static void __bt_name_owner_changed(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + const char *name = NULL; + const char *old_owner = NULL; + const char *new_owner = NULL; + bt_event_info_t *event_info; + + g_variant_get(parameters, "(&s&s&s)", &name, &old_owner, &new_owner); + + if (g_strcmp0(name, BT_DBUS_NAME) == 0 && + (new_owner != NULL && *new_owner == '\0')) { + BT_DBG("bt-service is terminated"); + event_info = _bt_event_get_cb_data(BT_ADAPTER_EVENT); + if (event_info == NULL) + return; + + if (disable_timer_id > 0) + g_source_remove(disable_timer_id); + + disable_timer_id = g_timeout_add(BT_RELIABLE_DISABLE_TIME, + (GSourceFunc)__bt_reliable_disable_cb, + event_info); + } +} - dbus_bus_remove_match (connection_type, match, &dbus_error); +void _bt_register_name_owner_changed(void) +{ + GDBusConnection *connection_type; - if (dbus_error_is_set(&dbus_error)) { - BT_ERR("Fail to remove match: %s\n", dbus_error.message); - dbus_error_free(&dbus_error); + connection_type = _bt_gdbus_get_system_gconn(); + if (connection_type == NULL) { + BT_ERR("Unable to get the bus"); + return; } + owner_sig_id = g_dbus_connection_signal_subscribe(connection_type, + NULL, DBUS_INTERFACE_DBUS, + BT_NAME_OWNER_CHANGED, NULL, NULL, 0, + __bt_name_owner_changed, NULL, NULL); +} - dbus_connection_remove_filter(connection_type, event_func, - (void *)cb_data); +void _bt_unregister_name_owner_changed(void) +{ + GDBusConnection *connection_type; - g_free(match); - return BLUETOOTH_ERROR_NONE; + connection_type = _bt_gdbus_get_system_gconn(); + if (connection_type != NULL && owner_sig_id != -1) { + g_dbus_connection_signal_unsubscribe(connection_type, + owner_sig_id); + owner_sig_id = -1; + } } diff --git a/bt-api/bt-gatt-client.c b/bt-api/bt-gatt-client.c new file mode 100755 index 0000000..486513d --- /dev/null +++ b/bt-api/bt-gatt-client.c @@ -0,0 +1,1466 @@ +/* + * Bluetooth-frwk low energy (GATT Client) + * + * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Chanyeol Park + * + * 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 +#include +#include +#include +#include +#include + +#include "bt-common.h" + +#define GATT_SERV_INTERFACE "org.bluez.GattService1" +#define GATT_CHAR_INTERFACE "org.bluez.GattCharacteristic1" +#define GATT_DESC_INTERFACE "org.bluez.GattDescriptor1" + +#define GATT_USER_DESC_UUID "00002901-0000-1000-8000-00805f9b34fb" +#define GATT_CHAR_CLIENT_CONF "00002902-0000-1000-8000-00805f9b34fb" +#define GATT_CHAR_SERVER_CONF "00002903-0000-1000-8000-00805f9b34fb" +#define GATT_CHAR_FORMAT "00002904-0000-1000-8000-00805f9b34fb" + +typedef enum { + TYPE_NONE, + USER_DESC, + CLIENT_CONF, + SERVER_CONF, + CHAR_FORMAT +}char_descriptor_type_t; + +BT_EXPORT_API int bluetooth_gatt_free_service_property(bt_gatt_service_property_t *svc_pty) +{ + BT_DBG("+"); + + BT_CHECK_PARAMETER(svc_pty, return); + + g_free(svc_pty->uuid); + g_free(svc_pty->handle); + g_strfreev(svc_pty->include_handles.handle); + g_strfreev(svc_pty->char_handle.handle); + + memset(svc_pty, 0, sizeof(bt_gatt_service_property_t)); + + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_free_char_property(bt_gatt_char_property_t *char_pty) +{ + BT_DBG("+"); + + BT_CHECK_PARAMETER(char_pty, return); + + g_free(char_pty->uuid); + g_free(char_pty->name); + g_free(char_pty->description); + g_free(char_pty->val); + g_free(char_pty->handle); + g_strfreev(char_pty->char_desc_handle.handle); + + memset(char_pty, 0, sizeof(bt_gatt_char_property_t)); + + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_free_desc_property(bt_gatt_char_descriptor_property_t *desc_pty) +{ + BT_DBG("+"); + + BT_CHECK_PARAMETER(desc_pty, return); + + g_free(desc_pty->uuid); + g_free(desc_pty->val); + g_free(desc_pty->handle); + + memset(desc_pty, 0, sizeof(bt_gatt_char_descriptor_property_t)); + + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; +} + +static char **__get_string_array_from_gptr_array(GPtrArray *gp) +{ + gchar *gp_path = NULL; + char **path = NULL; + int i; + + if (gp->len == 0) + return NULL; + + path = g_malloc0((gp->len + 1) * sizeof(char *)); + + for (i = 0; i < gp->len; i++) { + gp_path = g_ptr_array_index(gp, i); + path[i] = g_strdup(gp_path); + BT_DBG("path[%d] : [%s]", i, path[i]); + } + + return path; +} + +BT_EXPORT_API int bluetooth_gatt_get_service_property(const char *service_handle, + bt_gatt_service_property_t *service) +{ + GDBusProxy *properties_proxy = NULL; + GError *error = NULL; + GVariant *result = NULL; + GDBusConnection *g_conn; + int len; + char *char_handle = NULL; + GPtrArray *gp_array = NULL ; + GVariantIter *property_iter, *char_iter; + const gchar *key; + GVariant *value; + + BT_CHECK_PARAMETER(service_handle, return); + BT_CHECK_PARAMETER(service, return); + BT_CHECK_ENABLED(return); + + g_conn = _bt_gdbus_get_system_gconn(); + retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + properties_proxy = g_dbus_proxy_new_sync(g_conn, + G_DBUS_PROXY_FLAGS_NONE, NULL, + BT_BLUEZ_NAME, + service_handle, + BT_PROPERTIES_INTERFACE, + NULL, &error); + + retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + result = g_dbus_proxy_call_sync(properties_proxy, + "GetAll", + g_variant_new("(s)", GATT_SERV_INTERFACE), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("Fail to get properties (Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("Fail to get properties"); + g_object_unref(properties_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + + g_variant_get(result, "(a{sv})", &property_iter); + + memset(service, 0, sizeof(bt_gatt_service_property_t)); + + while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) { + if (!g_strcmp0(key,"UUID")) { + service->uuid = g_variant_dup_string(value,&len); + + } else if(!g_strcmp0(key, "Primary")) { + service->primary = g_variant_get_boolean(value); + + } else if (!g_strcmp0(key, "Includes")) { + g_variant_get(value, "ao", &char_iter); + gp_array = g_ptr_array_new(); + while (g_variant_iter_loop(char_iter, "&o", &char_handle)) { + g_ptr_array_add(gp_array, (gpointer)char_handle); + } + if (gp_array->len != 0) { + service->include_handles.count = gp_array->len; + service->include_handles.handle = + __get_string_array_from_gptr_array(gp_array); + } + g_ptr_array_free(gp_array, TRUE); + } else if (!g_strcmp0(key, "Characteristics")) { + g_variant_get(value, "ao", &char_iter); + gp_array = g_ptr_array_new(); + while (g_variant_iter_loop(char_iter, "&o", &char_handle)) { + g_ptr_array_add(gp_array, (gpointer)char_handle); + } + if (gp_array->len != 0) { + service->char_handle.count = gp_array->len; + service->char_handle.handle = + __get_string_array_from_gptr_array(gp_array); + } + g_ptr_array_free(gp_array, TRUE); + } + } + + service->handle = g_strdup(service_handle); + + g_variant_iter_free(property_iter); + g_variant_unref(result); + g_object_unref(properties_proxy); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_get_primary_services( + const bluetooth_device_address_t *address, + bt_gatt_handle_info_t *prim_svc) +{ + GVariant *result = NULL; + GVariantIter *iter; + GVariantIter *svc_iter; + GVariantIter *interface_iter; + char *object_path = NULL; + char *interface_str = NULL; + const gchar *key = NULL; + GVariant *value = NULL; + GPtrArray *gp_array = NULL; + char device_address[BT_ADDRESS_STRING_SIZE] = { 0 }; + char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 }; + int ret = BLUETOOTH_ERROR_INTERNAL; + + BT_INFO("+"); + BT_CHECK_PARAMETER(address, return); + BT_CHECK_PARAMETER(prim_svc, return); + BT_CHECK_ENABLED(return); + + result = _bt_get_managed_objects(); + if (result == NULL) + return ret; + + _bt_convert_addr_type_to_string(device_address, + (unsigned char *)address->addr); + + gp_array = g_ptr_array_new(); + g_variant_get(result, "(a{oa{sa{sv}}})", &iter); + + while (g_variant_iter_loop(iter, "{&oa{sa{sv}}}", &object_path, + &interface_iter)) { + if (object_path == NULL) + continue; + + _bt_convert_device_path_to_address(object_path, temp_address); + + if (g_strcmp0(temp_address, device_address) != 0) + continue; + + while (g_variant_iter_loop(interface_iter, "{sa{sv}}", + &interface_str, &svc_iter)) { + if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0) + continue; + + BT_DBG("Object Path: %s", object_path); + while (g_variant_iter_loop(svc_iter, "{sv}", &key, &value)) { + if (g_strcmp0(key, "Primary") == 0) { + if (g_variant_get_boolean(value)) + g_ptr_array_add(gp_array, (gpointer)object_path); + } + } + } + } + + if (gp_array->len == 0) { + BT_ERR("gp_array is NULL"); + ret = BLUETOOTH_ERROR_NOT_FOUND; + } else { + ret = BLUETOOTH_ERROR_NONE; + prim_svc->count = gp_array->len; + prim_svc->handle = __get_string_array_from_gptr_array(gp_array); + } + + g_ptr_array_free(gp_array, TRUE); + g_variant_iter_free(iter); + g_variant_unref(result); + BT_DBG("-"); + return ret; +} + +BT_EXPORT_API int bluetooth_gatt_get_service_from_uuid(bluetooth_device_address_t *address, + const char *service_uuid, + bt_gatt_service_property_t *service) +{ + GVariant *result = NULL; + GVariantIter *iter; + GVariantIter *svc_iter; + GVariantIter *interface_iter; + GError *error = NULL; + char *object_path = NULL; + char *interface_str = NULL; + char device_address[BT_ADDRESS_STRING_SIZE] = { 0 }; + char temp_address[BT_ADDRESS_STRING_SIZE] = { 0 }; + int ret = BLUETOOTH_ERROR_INTERNAL; + + BT_CHECK_PARAMETER(address, return); + BT_CHECK_PARAMETER(service_uuid, return); + BT_CHECK_PARAMETER(service, return); + BT_CHECK_ENABLED(return); + + result = _bt_get_managed_objects(); + if (result == NULL) + return ret; + + _bt_convert_addr_type_to_string(device_address, + (unsigned char *)address->addr); + + g_variant_get(result, "(a{oa{sa{sv}}})", &iter); + + while (g_variant_iter_loop(iter, "{oa{sa{sv}}}", &object_path, + &interface_iter)) { + if (object_path == NULL) + continue; + + _bt_convert_device_path_to_address(object_path, + temp_address); + + if (g_strcmp0(temp_address, device_address) != 0) + continue; + + while (g_variant_iter_loop(interface_iter, "{sa{sv}}", + &interface_str, &svc_iter)) { + if (g_strcmp0(interface_str, GATT_SERV_INTERFACE) != 0) + continue; + + BT_DBG("Object Path: %s", object_path); + ret = bluetooth_gatt_get_service_property(object_path, + service); + + if (ret != BLUETOOTH_ERROR_NONE) { + BT_ERR("Get service property failed(0x%08x)", ret); + } else { + if (service->primary == TRUE && + g_strstr_len(service->uuid, -1, + service_uuid)) { + ret = BLUETOOTH_ERROR_NONE; + goto done; + } + } + bluetooth_gatt_free_service_property(service); + } + } + +done: + g_variant_iter_free(iter); + g_variant_unref(result); + + return ret; +} + +static void __bluetooth_internal_get_char_cb(GDBusProxy *proxy, + GAsyncResult *res, gpointer user_data) +{ + GVariant *value; + GVariant *char_value; + GVariantIter *char_iter; + GPtrArray *gp_array = NULL; + bt_gatt_discovered_char_t svc_char = { 0, }; + int i; + char *char_handle; + GError *error = NULL; + bt_user_info_t *user_info; + + BT_DBG("+"); + + user_info = _bt_get_user_data(BT_COMMON); + svc_char.service_handle = user_data; + + value = g_dbus_proxy_call_finish(proxy, res, &error); + + if (value == NULL) { + if (error != NULL) { + BT_ERR("Get service characteristics failed\n errCode[%x]," + "message[%s]\n", error->code, error->message); + g_clear_error(&error); + } else { + BT_ERR("Get service characteristics failed\n"); + } + if (user_info) { + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED, + BLUETOOTH_ERROR_INTERNAL, NULL, + user_info->cb, user_info->user_data); + } + g_free(svc_char.service_handle); + g_object_unref(proxy); + return; + } + + g_variant_get(value, "(v)", &char_value); + g_variant_get(char_value, "ao", &char_iter); + + int len = g_variant_get_size(char_iter); + if (len > 0) { + gp_array = g_ptr_array_new(); + for (i = 0; i < len; i++) { + g_variant_iter_loop(char_iter, "&o", &char_handle); + g_ptr_array_add(gp_array, (gpointer)char_handle); + } + if (gp_array->len != 0) { + svc_char.handle_info.count = gp_array->len; + svc_char.handle_info.handle = + __get_string_array_from_gptr_array(gp_array); + } + g_ptr_array_free(gp_array, TRUE); + } + + if (user_info) { + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED, + BLUETOOTH_ERROR_NONE, &svc_char, + user_info->cb, user_info->user_data); + } + + g_strfreev(svc_char.handle_info.handle); + g_free(svc_char.service_handle); + g_variant_iter_free(char_iter); + g_object_unref(proxy); +} + +BT_EXPORT_API int bluetooth_gatt_discover_service_characteristics( + const char *service_handle) +{ + GDBusProxy *properties_proxy = NULL; + GDBusConnection *g_conn; + GError *error = NULL; + char *handle; + + BT_DBG("+"); + + BT_CHECK_PARAMETER(service_handle, return); + BT_CHECK_ENABLED(return); + + g_conn = _bt_gdbus_get_system_gconn(); + retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + properties_proxy = g_dbus_proxy_new_sync(g_conn, + G_DBUS_PROXY_FLAGS_NONE, NULL, + BT_BLUEZ_NAME, + service_handle, + BT_PROPERTIES_INTERFACE, + NULL, &error); + + retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + handle = g_strdup(service_handle); + g_dbus_proxy_call(properties_proxy, + "Get", + g_variant_new("(ss)", + GATT_SERV_INTERFACE, "Characteristics"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + (GAsyncReadyCallback)__bluetooth_internal_get_char_cb, + (gpointer)handle); + + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; +} + + +static int __get_permission_flag(char *permission) +{ + int ret = 0; + + retv_if(permission == NULL, ret); + + BT_DBG("permission = %s",permission); + + if (!g_strcmp0(permission,"broadcast")) { + ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST; + } else if (!g_strcmp0(permission,"read")) { + ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ; + } else if (!g_strcmp0(permission,"write-without-response")) { + ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE; + } else if (!g_strcmp0(permission,"write")) { + ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE; + } else if (!g_strcmp0(permission,"notify")) { + ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY; + } else if (!g_strcmp0(permission,"indicate")) { + ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE; + } else if (!g_strcmp0(permission,"authenticated-signed-writes")) { + ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE; + } else if (!g_strcmp0(permission,"reliable-write")) { + ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS; + } else if (!g_strcmp0(permission,"writable-auxiliaries")) { + ret = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS; + } + + return ret; +} + +BT_EXPORT_API int bluetooth_gatt_get_characteristics_property( + const char *char_handle, bt_gatt_char_property_t *characteristic) +{ + GDBusProxy *properties_proxy = NULL; + GError *error = NULL; + GVariant *value = NULL; + GVariant *result = NULL; + GByteArray *gb_array = NULL; + GPtrArray *gp_array = NULL ; + GDBusConnection *g_conn; + guint8 char_value; + const gchar *key; + gchar* permission; + char *char_desc_handle = NULL; + int len; + GVariantIter *property_iter; + GVariantIter *char_value_iter; + GVariantIter *char_perm_iter; + GVariantIter *char_desc_iter; + + BT_DBG("+"); + BT_CHECK_PARAMETER(char_handle, return); + BT_CHECK_PARAMETER(characteristic, return); + + BT_CHECK_ENABLED(return); + + g_conn = _bt_gdbus_get_system_gconn(); + retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + properties_proxy = g_dbus_proxy_new_sync(g_conn, + G_DBUS_PROXY_FLAGS_NONE, NULL, + BT_BLUEZ_NAME, + char_handle, + BT_PROPERTIES_INTERFACE, + NULL, &error); + + retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + result = g_dbus_proxy_call_sync(properties_proxy, + "GetAll", + g_variant_new("(s)", GATT_CHAR_INTERFACE), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("Fail to get properties (Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("Fail to get properties"); + g_object_unref(properties_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + + g_variant_get(result, "(a{sv})", &property_iter); + + memset(characteristic, 0, sizeof(bt_gatt_char_property_t)); + characteristic->handle = g_strdup(char_handle); + + while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) { + BT_DBG("property"); + if (!g_strcmp0(key,"UUID")) { + characteristic->uuid = g_variant_dup_string(value,&len); + BT_DBG("UUID of the char = %s",characteristic->uuid); + } else if(!g_strcmp0(key, "Value")) { + gb_array = g_byte_array_new(); + g_variant_get(value, "ay", &char_value_iter); + while(g_variant_iter_loop(char_value_iter, "y", &char_value)) { + BT_DBG("value of char = %d",char_value); + g_byte_array_append(gb_array, &char_value, 1); + } + if (gb_array->len != 0) { + characteristic->val = g_malloc0(gb_array->len * + sizeof(unsigned char)); + memcpy(characteristic->val, gb_array->data, gb_array->len); + } + characteristic->val_len = gb_array->len; + g_byte_array_free(gb_array, TRUE); + } else if(!g_strcmp0(key, "Flags")) { + g_variant_get(value, "as", &char_perm_iter); + characteristic->permission = 0x00; + while (g_variant_iter_loop(char_perm_iter, "s", &permission)) { + BT_DBG("permission = %s",permission); + characteristic->permission |= __get_permission_flag(permission); + BT_DBG("permission check = %d",characteristic->permission); + } + g_variant_iter_free(char_perm_iter); + } else if (!g_strcmp0(key, "Descriptors")) { + g_variant_get(value, "ao", &char_desc_iter); + gp_array = g_ptr_array_new(); + while (g_variant_iter_loop(char_desc_iter, "&o", &char_desc_handle)) { + g_ptr_array_add(gp_array, (gpointer)char_desc_handle); + } + if (gp_array->len != 0) { + characteristic->char_desc_handle.count = gp_array->len; + characteristic->char_desc_handle.handle = + __get_string_array_from_gptr_array(gp_array); + } + g_ptr_array_free(gp_array, TRUE); + } + } + + g_variant_iter_free(property_iter); + g_variant_unref(result); + g_object_unref(properties_proxy); + + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; +} + +void bluetooth_gatt_get_char_from_uuid_cb(GDBusProxy *proxy, + GAsyncResult *res, gpointer user_data) +{ + GVariant *value; + GVariantIter *char_iter; + int i, len; + char *char_handle; + GError *error = NULL; + bt_user_info_t *user_info; + int ret = BLUETOOTH_ERROR_INTERNAL; + bt_gatt_char_property_t characteristic; + + user_info = _bt_get_user_data(BT_COMMON); + + value = g_dbus_proxy_call_finish(proxy, res, &error); + + if (value == NULL) { + if (error != NULL) { + BT_ERR("Get service characteristics failed\n errCode[%x]," + "message[%s]\n", error->code, error->message); + g_clear_error(&error); + } else { + BT_ERR("Get service characteristics failed\n"); + } + if (user_info) { + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID, + BLUETOOTH_ERROR_INTERNAL, NULL, + user_info->cb, user_info->user_data); + } + g_object_unref(proxy); + g_free(user_data); + return; + } + + g_variant_get(value, "(ao)", &char_iter); + + len = g_variant_get_size(char_iter); + + for (i = 0; i < len; i++) { + g_variant_iter_loop(char_iter, "o", &char_handle); + if (!char_handle) + continue; + ret = bluetooth_gatt_get_characteristics_property(char_handle, + &characteristic); + + if (ret != BLUETOOTH_ERROR_NONE) { + BT_ERR("Get characteristic property failed(0x%08x)", ret); + } else { + if (g_strstr_len(characteristic.uuid, -1, user_data)) { + ret = BLUETOOTH_ERROR_NONE; + break; + } + } + bluetooth_gatt_free_char_property(&characteristic); + } + + if (user_info) { + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID, ret, + &characteristic, user_info->cb, user_info->user_data); + } + + bluetooth_gatt_free_char_property(&characteristic); + g_variant_iter_free(char_iter); + g_free(user_data); +} + +BT_EXPORT_API int bluetooth_gatt_get_char_from_uuid(const char *service_handle, + const char *char_uuid) +{ + GDBusProxy *properties_proxy = NULL; + GDBusConnection *g_conn; + GError *error = NULL; + char *uuid; + + BT_CHECK_PARAMETER(service_handle, return); + BT_CHECK_PARAMETER(char_uuid, return); + BT_CHECK_ENABLED(return); + + g_conn = _bt_gdbus_get_system_gconn(); + retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + properties_proxy = g_dbus_proxy_new_sync(g_conn, + G_DBUS_PROXY_FLAGS_NONE, NULL, + BT_BLUEZ_NAME, + service_handle, + BT_PROPERTIES_INTERFACE, + NULL, &error); + + retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + uuid = g_strdup(char_uuid); + g_dbus_proxy_call(properties_proxy, + "Get", + g_variant_new("(ss)", + GATT_SERV_INTERFACE, "Characteristics"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + (GAsyncReadyCallback)bluetooth_gatt_get_char_from_uuid_cb, + (gpointer)uuid); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_get_char_descriptor_property( + const char *descriptor_handle, bt_gatt_char_descriptor_property_t *descriptor) +{ + GDBusProxy *properties_proxy = NULL; + GError *error = NULL; + GDBusConnection *g_conn; + GVariant *result = NULL; + GVariantIter *property_iter; + const gchar *key; + guint8 char_value; + int len; + GVariant *value = NULL; + GByteArray *gb_array = NULL; + GVariantIter *desc_value_iter; + + BT_DBG("+"); + BT_CHECK_PARAMETER(descriptor_handle, return); + BT_CHECK_PARAMETER(descriptor, return); + + BT_CHECK_ENABLED(return); + + g_conn = _bt_gdbus_get_system_gconn(); + retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + properties_proxy = g_dbus_proxy_new_sync(g_conn, + G_DBUS_PROXY_FLAGS_NONE, NULL, + BT_BLUEZ_NAME, + descriptor_handle, + BT_PROPERTIES_INTERFACE, + NULL, &error); + + retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + result = g_dbus_proxy_call_sync(properties_proxy, + "GetAll", + g_variant_new("(s)", GATT_DESC_INTERFACE), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("Fail to get properties (Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("Fail to get properties"); + g_object_unref(properties_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + + g_variant_get(result, "(a{sv})", &property_iter); + + memset(descriptor, 0, sizeof(bt_gatt_char_descriptor_property_t)); + descriptor->handle = g_strdup(descriptor_handle); + + while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) { + BT_DBG("property"); + if (!g_strcmp0(key,"UUID")) { + descriptor->uuid = g_variant_dup_string(value,&len); + BT_DBG("UUID of the char_desc = %s",descriptor->uuid); + } else if(!g_strcmp0(key, "Value")) { + gb_array = g_byte_array_new(); + g_variant_get(value, "ay", &desc_value_iter); + while(g_variant_iter_loop(desc_value_iter, "y", &char_value)) { + BT_DBG("value of descriptor = %d",char_value); + g_byte_array_append(gb_array, &char_value, 1); + } + if (gb_array->len != 0) { + descriptor->val = g_malloc0(gb_array->len * + sizeof(unsigned char)); + memcpy(descriptor->val, gb_array->data, gb_array->len); + } + descriptor->val_len = gb_array->len; + g_byte_array_free(gb_array, TRUE); + } + } + + g_variant_iter_free(property_iter); + g_variant_unref(result); + g_object_unref(properties_proxy); + + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; +} + +static void __bluetooth_internal_read_cb(GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + bt_user_info_t *user_info; + bt_gatt_char_value_t char_value = { 0, }; + GDBusConnection *system_gconn = NULL; + GVariant *value; + GByteArray *gp_byte_array = NULL; + GVariantIter *iter; + guint8 g_byte; + + BT_DBG("+"); + user_info = _bt_get_user_data(BT_COMMON); + + system_gconn = _bt_gdbus_get_system_gconn(); + value = g_dbus_connection_call_finish(system_gconn, res, &error); + + if (error) { + BT_ERR("Error : %s \n", error->message); + g_clear_error(&error); + if (user_info) { + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR, + BLUETOOTH_ERROR_INTERNAL, NULL, + user_info->cb, user_info->user_data); + } + g_free(user_data); + return; + } + + char_value.char_handle = user_data; + gp_byte_array = g_byte_array_new(); + g_variant_get(value, "(ay)", &iter); + + while (g_variant_iter_loop(iter, "y", &g_byte)) { + g_byte_array_append(gp_byte_array, &g_byte, 1); + } + + if (gp_byte_array->len != 0) { + char_value.val_len = gp_byte_array->len; + char_value.char_value = gp_byte_array->data; + } + + if (user_info) { + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_CHAR, + BLUETOOTH_ERROR_NONE, &char_value, + user_info->cb, user_info->user_data); + } + + g_free(char_value.char_handle); + g_byte_array_free(gp_byte_array, TRUE); + g_variant_unref(value); + g_variant_iter_free(iter); + + BT_DBG("-"); +} + +BT_EXPORT_API int bluetooth_gatt_read_characteristic_value(const char *characteristic) +{ + GDBusConnection *conn; + char *handle; + + BT_CHECK_PARAMETER(characteristic, return); + BT_CHECK_ENABLED(return); + + conn = _bt_gdbus_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + handle = g_strdup(characteristic); + + g_dbus_connection_call(conn, + BT_BLUEZ_NAME, + characteristic, + GATT_CHAR_INTERFACE, + "ReadValue", + NULL, + G_VARIANT_TYPE("(ay)"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + (GAsyncReadyCallback)__bluetooth_internal_read_cb, + (gpointer)handle); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_set_characteristics_value( + const char *char_handle, const guint8 *value, int length) +{ + GVariant *val; + GVariantBuilder *builder; + GError *error = NULL; + GDBusConnection *conn; + int i = 0; + + BT_DBG("+"); + BT_CHECK_PARAMETER(char_handle, return); + BT_CHECK_PARAMETER(value, return); + retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM); + BT_CHECK_ENABLED(return); + + conn = _bt_gdbus_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + builder = g_variant_builder_new(G_VARIANT_TYPE("ay")); + + for (i = 0; i < length; i++) { + g_variant_builder_add(builder, "y", value[i]); + } + + val = g_variant_new("(ay)", builder); + + g_dbus_connection_call_sync(conn, + BT_BLUEZ_NAME, + char_handle, + GATT_CHAR_INTERFACE, + "WriteValue", + val, + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, &error); + + if (error) { + BT_ERR("Set value Failed: %s", error->message); + g_clear_error(&error); + g_variant_builder_unref(builder); + return BLUETOOTH_ERROR_INTERNAL; + } + + g_variant_builder_unref(builder); + + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; +} + +static void __bluetooth_internal_write_cb(GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + BT_DBG("+"); + GError *error = NULL; + bt_user_info_t *user_info; + GDBusConnection *system_gconn = NULL; + GVariant *value; + int result = BLUETOOTH_ERROR_NONE; + + user_info = _bt_get_user_data(BT_COMMON); + + system_gconn = _bt_gdbus_get_system_gconn(); + value = g_dbus_connection_call_finish(system_gconn, res, &error); + + if (error) { + BT_ERR("Error : %s \n", error->message); + g_clear_error(&error); + result = BLUETOOTH_ERROR_INTERNAL; + } + if (user_info) { + BT_DBG("result = %d", result); + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_CHAR, + result, NULL, + user_info->cb, user_info->user_data); + } + + if (value) + g_variant_unref(value); + BT_DBG("-"); + return; +} + +BT_EXPORT_API int bluetooth_gatt_set_characteristics_value_request( + const char *char_handle, const guint8 *value, int length) +{ + GVariant *val; + GDBusConnection *conn; + GVariantBuilder *builder; + int i; + + BT_DBG("+"); + BT_CHECK_PARAMETER(char_handle, return); + BT_CHECK_PARAMETER(value, return); + retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM); + BT_CHECK_ENABLED(return); + + conn = _bt_gdbus_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + builder = g_variant_builder_new(G_VARIANT_TYPE("ay")); + + for (i = 0; i < length; i++) { + g_variant_builder_add(builder, "y", value[i]); + BT_DBG("value [] = %d", value[i]); + } + + val = g_variant_new("(ay)", builder); + + g_dbus_connection_call(conn, + BT_BLUEZ_NAME, + char_handle, + GATT_CHAR_INTERFACE, + "WriteValue", + val, + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, + (GAsyncReadyCallback)__bluetooth_internal_write_cb, + NULL); + + g_variant_builder_unref(builder); + + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; +} + +static int __bluetooth_gatt_descriptor_iter(const char *char_handle, + bt_gatt_char_property_t *characteristic) +{ + BT_DBG("+"); + GDBusProxy *properties_proxy = NULL; + GError *error = NULL; + GVariant *value = NULL; + GVariant *result = NULL; + GDBusConnection *g_conn; + int i, ret = BLUETOOTH_ERROR_NONE; + char *uuid = NULL; + int len = 0; + GVariantIter *desc_value_iter, *property_iter; + const gchar *key; + char_descriptor_type_t desc_type = TYPE_NONE; + + g_conn = _bt_gdbus_get_system_gconn(); + retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + properties_proxy = g_dbus_proxy_new_sync(g_conn, + G_DBUS_PROXY_FLAGS_NONE, NULL, + BT_BLUEZ_NAME, + char_handle, + BT_PROPERTIES_INTERFACE, + NULL, &error); + + retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + result = g_dbus_proxy_call_sync(properties_proxy, + "GetAll", + g_variant_new("(s)", GATT_DESC_INTERFACE), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!result) { + if (error != NULL) { + BT_ERR("Fail to get properties (Error: %s)", error->message); + g_clear_error(&error); + } else + BT_ERR("Fail to get properties"); + g_object_unref(properties_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + g_variant_get(result, "(a{sv})", &property_iter); + while (g_variant_iter_loop(property_iter, "{sv}", &key, &value)) { + if (!g_strcmp0(key,"UUID")) { + uuid = g_variant_get_string(value, &len); + if (g_strcmp0(uuid, GATT_USER_DESC_UUID) == 0) { + BT_DBG("GATT_USER_DESC_UUID"); + desc_type = USER_DESC; + } else if (g_strcmp0(uuid, GATT_CHAR_FORMAT) == 0) { + BT_DBG("GATT_CHAR_FORMAT"); + desc_type = CHAR_FORMAT; + } else if (g_strcmp0(uuid, GATT_CHAR_CLIENT_CONF) == 0) { + BT_DBG("GATT_CHAR_CLIENT_CONF"); + desc_type = CLIENT_CONF; + } else if (g_strcmp0(uuid, GATT_CHAR_SERVER_CONF) == 0) { + BT_DBG("GATT_CHAR_SERVER_CONF"); + desc_type = SERVER_CONF; + } else { + BT_DBG("descriptor uuid = %s", uuid); + } + } else if (!g_strcmp0(key, "Value")) { + switch(desc_type) { + case CHAR_FORMAT : + BT_DBG("Format descriptor"); + g_variant_get(value, "(yyqyq)", + &(characteristic->format.format), + &(characteristic->format.exponent), + &(characteristic->format.unit), + &(characteristic->format.name_space), + &(characteristic->format.description)); + break; + case USER_DESC: + BT_DBG("User descriptor"); + g_variant_get(value, "ay", &desc_value_iter); + len = g_variant_get_size(desc_value_iter); + + if (len > 0) { + characteristic->description = (guint8 *)g_malloc0(len + 1); + if (!characteristic->description) { + ret = BLUETOOTH_ERROR_OUT_OF_MEMORY; + goto done; + } + } + for (i = 0; i < len; i++) { + g_variant_iter_loop(desc_value_iter, "y", + &characteristic->description[i]); + BT_DBG("description = %s", characteristic->description); + } + break; + case CLIENT_CONF : + BT_DBG(" CLIENT_CONF"); + break; + case SERVER_CONF : + BT_DBG(" SERVER_CONF"); + break; + } + } + } + +done: + g_variant_iter_free(property_iter); + g_variant_unref(result); + g_object_unref(properties_proxy); + + BT_DBG("-"); + return ret; +} + + +static void bluetooth_gatt_get_char_desc_cb(GDBusProxy *proxy, + GAsyncResult *res, gpointer user_data) +{ + BT_DBG("+"); + GVariant *value; + GVariant *char_value; + GVariantIter *char_iter; + int i; + char *char_handle; + GError *error = NULL; + bt_user_info_t *user_info; + bt_gatt_char_property_t characteristic = {0, }; + int ret = BLUETOOTH_ERROR_INTERNAL; + + user_info = _bt_get_user_data(BT_COMMON); + + value = g_dbus_proxy_call_finish(proxy, res, &error); + + if (value == NULL) { + if (error != NULL) { + BT_ERR("Get characteristic descriptor failed\n errCode[%x]," + "message[%s]\n", error->code, error->message); + g_clear_error(&error); + } else { + BT_ERR("Get characteristic descriptor failed\n"); + } + if (user_info) { + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED, + BLUETOOTH_ERROR_INTERNAL, NULL, + user_info->cb, user_info->user_data); + } + g_free(user_data); + g_object_unref(proxy); + return; + } + + g_variant_get(value, "(v)", &char_value); + g_variant_get(char_value, "ao", &char_iter); + + int len = g_variant_get_size(char_iter); + if (len > 0) { + for (i = 0; i < len; i++) { + g_variant_iter_loop(char_iter, "o", &char_handle); + BT_DBG("object path of descriptor = %s",char_handle); + if(char_handle) { + ret = __bluetooth_gatt_descriptor_iter(char_handle, + &characteristic); + BT_DBG("Descriptor read status [%d]",ret); + } + } + } + + characteristic.handle = user_data; + if (user_info) { + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_SVC_CHAR_DESC_DISCOVERED, + ret, &characteristic, user_info->cb, user_info->user_data); + } + bluetooth_gatt_free_char_property(&characteristic); + + g_variant_iter_free(char_iter); + BT_DBG("-"); +} + +BT_EXPORT_API int bluetooth_gatt_discover_characteristic_descriptor( + const char *characteristic_handle) +{ + GDBusProxy *properties_proxy = NULL; + GDBusConnection *g_conn; + char *handle; + GError *error = NULL; + + BT_CHECK_PARAMETER(characteristic_handle, return); + BT_CHECK_ENABLED(return); + + g_conn = _bt_gdbus_get_system_gconn(); + retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + properties_proxy = g_dbus_proxy_new_sync(g_conn, + G_DBUS_PROXY_FLAGS_NONE, NULL, + BT_BLUEZ_NAME, + characteristic_handle, + BT_PROPERTIES_INTERFACE, + NULL, &error); + + retv_if(properties_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + handle = g_strdup(characteristic_handle); + g_dbus_proxy_call(properties_proxy, + "Get", + g_variant_new("(ss)", + GATT_CHAR_INTERFACE, "Descriptors"), + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, + (GAsyncReadyCallback)bluetooth_gatt_get_char_desc_cb, + (gpointer)handle); + + return BLUETOOTH_ERROR_NONE; +} + +static void __bluetooth_internal_read_desc_cb(GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + bt_user_info_t *user_info; + bt_gatt_char_property_t char_value = { 0, }; + GDBusConnection *system_gconn = NULL; + GVariant *value; + GByteArray *gp_byte_array = NULL; + GVariantIter *iter; + guint8 g_byte; + + BT_DBG("+"); + user_info = _bt_get_user_data(BT_COMMON); + system_gconn = _bt_gdbus_get_system_gconn(); + + char_value.handle = user_data; + value = g_dbus_connection_call_finish(system_gconn, res, &error); + + if (error) { + BT_ERR("Error : %s \n", error->message); + g_clear_error(&error); + if (user_info) { + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC, + BLUETOOTH_ERROR_INTERNAL, NULL, + user_info->cb, user_info->user_data); + } + g_free(char_value.handle); + return; + } + + gp_byte_array = g_byte_array_new(); + g_variant_get(value, "(ay)", &iter); + + while(g_variant_iter_loop(iter, "y", &g_byte)) { + g_byte_array_append(gp_byte_array, &g_byte, 1); + } + + if (gp_byte_array->len != 0) { + char_value.val_len = gp_byte_array->len; + char_value.description= gp_byte_array->data; + } + + if (user_info) { + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_READ_DESC, + BLUETOOTH_ERROR_NONE, &char_value, + user_info->cb, user_info->user_data); + } + + g_byte_array_free(gp_byte_array, TRUE); + g_free(char_value.handle); + g_variant_unref(value); + g_variant_iter_free(iter); + + BT_DBG("-"); +} + +BT_EXPORT_API int bluetooth_gatt_read_descriptor_value(const char *char_descriptor) +{ + GDBusConnection *conn; + char *handle; + + BT_DBG("+"); + BT_CHECK_PARAMETER(char_descriptor, return); + BT_CHECK_ENABLED(return); + + conn = _bt_gdbus_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + handle = g_strdup(char_descriptor); + + g_dbus_connection_call(conn, + BT_BLUEZ_NAME, + char_descriptor, + GATT_DESC_INTERFACE, + "ReadValue", + NULL, + G_VARIANT_TYPE("(ay)"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + (GAsyncReadyCallback)__bluetooth_internal_read_desc_cb, + (gpointer)handle); + + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; +} + +static void __bluetooth_internal_write_desc_cb(GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + bt_user_info_t *user_info; + GDBusConnection *system_gconn = NULL; + GVariant *value; + int result = BLUETOOTH_ERROR_NONE; + + BT_DBG("+"); + user_info = _bt_get_user_data(BT_COMMON); + + system_gconn = _bt_gdbus_get_system_gconn(); + value = g_dbus_connection_call_finish(system_gconn, res, &error); + + if (error) { + BT_ERR("Error : %s \n", error->message); + g_clear_error(&error); + result = BLUETOOTH_ERROR_INTERNAL; + } + if (user_info) { + _bt_common_event_cb(BLUETOOTH_EVENT_GATT_WRITE_DESC, + result, NULL, + user_info->cb, user_info->user_data); + } + + if(value) + g_variant_unref(value); + + BT_DBG("-"); +} + +BT_EXPORT_API int bluetooth_gatt_write_descriptor_value( + const char *desc_handle, const guint8 *value, int length) +{ + GVariant *val; + GDBusConnection *conn; + GVariantBuilder *builder; + int i; + + BT_DBG("+"); + BT_CHECK_PARAMETER(desc_handle, return); + BT_CHECK_PARAMETER(value, return); + retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM); + BT_CHECK_ENABLED(return); + + conn = _bt_gdbus_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + builder = g_variant_builder_new(G_VARIANT_TYPE("ay")); + + for (i = 0; i < length; i++) { + g_variant_builder_add(builder, "y", value[i]); + } + + val = g_variant_new("(ay)", builder); + + g_dbus_connection_call(conn, + BT_BLUEZ_NAME, + desc_handle, + GATT_DESC_INTERFACE, + "WriteValue", + val, + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, + (GAsyncReadyCallback)__bluetooth_internal_write_desc_cb, + NULL); + + g_variant_builder_unref(builder); + + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_watch_characteristics(const char *char_handle) +{ + + GDBusConnection *conn; + GError *error = NULL; + int ret = BLUETOOTH_ERROR_NONE; + BT_DBG("+"); +/* Implementation in Bluez is not complete */ +#if 0 + BT_CHECK_PARAMETER(char_handle, return); + + BT_CHECK_ENABLED(return); + + BT_DBG("Entered characteristic handle:%s \n ", char_handle); + + conn = _bt_gdbus_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + g_dbus_connection_call_sync(conn, + BT_BLUEZ_NAME, + char_handle, + GATT_CHAR_INTERFACE, + "StartNotify", + NULL, + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, &error); + + if (error) { + BT_ERR("Watch Failed: %s", error->message); + g_clear_error(&error); + ret = BLUETOOTH_ERROR_INTERNAL; + } +#endif + BT_DBG("-"); + return ret; +} + +BT_EXPORT_API int bluetooth_gatt_unwatch_characteristics(const char *service_handle) +{ + + GDBusConnection *conn; + GError *error = NULL; + int ret = BLUETOOTH_ERROR_NONE; + BT_DBG("+"); +/* Implementation in Bluez is not complete */ +#if 0 + BT_CHECK_PARAMETER(char_handle, return); + + BT_CHECK_ENABLED(return); + + BT_DBG("Entered characteristic handle:%s \n ", char_handle); + + conn = _bt_gdbus_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + g_dbus_connection_call_sync(conn, + BT_BLUEZ_NAME, + char_handle, + GATT_CHAR_INTERFACE, + "StopNotify", + NULL, + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, &error); + + if (error) { + BT_ERR("Watch Failed: %s", error->message); + g_clear_error(&error); + ret = BLUETOOTH_ERROR_INTERNAL; + } +#endif + BT_DBG("-"); + return ret; +} diff --git a/bt-api/bt-gatt-service.c b/bt-api/bt-gatt-service.c new file mode 100755 index 0000000..a9b670f --- /dev/null +++ b/bt-api/bt-gatt-service.c @@ -0,0 +1,1619 @@ +/* + * Bluetooth-frwk low energy + * + * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Chanyeol Park + * + * 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 +#include +#include +#include +#include +#include + +#include "bt-common.h" + +#define NUMBER_OF_FLAGS 10 + +GDBusConnection *g_conn; +guint owner_id; +guint manager_id; +static gboolean new_service = FALSE; +static gboolean new_char = FALSE; +static int serv_id = 1; + +/* Introspection data for the service we are exporting */ +static const gchar service_introspection_xml[] = +"" +" " +" " +" " +" " +" " +" " +""; + +/* Introspection data for the characteristics we are exporting */ +static const gchar characteristics_introspection_xml[] = +"" +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +""; + +/* Introspection data for the descriptor we are exporting */ +static const gchar descriptor_introspection_xml[] = +"" +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +""; + +static const gchar manager_introspection_xml[] = +"" +" " +" " +" " +" " +" " +""; + +static const gchar properties_introspection_xml[] = +"" +" " +" " +" " +" " +" " +" " +" " +""; + +struct gatt_service_info { + gchar *serv_path; + guint serv_id; + gchar *service_uuid; + guint manager_id; + guint prop_id; + GSList *char_data; + gboolean is_svc_registered; +}; + +struct gatt_char_info { + gchar *char_path; + guint char_id; + gchar *char_uuid; + gchar *char_value; + gchar *char_flags[NUMBER_OF_FLAGS]; + int value_length; + int flags_length; + GSList *desc_data; +}; + +struct gatt_desc_info { + gchar *desc_path; + guint desc_id; + gchar *desc_uuid; + gchar *desc_value; + int value_length; +}; + +static GSList *gatt_services = NULL; + +#define BT_GATT_SERVICE_NAME "org.frwk.gatt_service" +#define BT_GATT_SERVICE_PATH "/org/frwk/gatt_service" + +#define GATT_SERV_OBJECT_PATH "/service" + +#define GATT_MNGR_INTERFACE "org.bluez.GattManager1" +#define GATT_SERV_INTERFACE "org.bluez.GattService1" +#define GATT_CHAR_INTERFACE "org.bluez.GattCharacteristic1" +#define GATT_DESC_INTERFACE "org.bluez.GattDescriptor1" + +static GDBusProxy *manager_gproxy = NULL; + +static void __bt_gatt_manager_method_call(GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + if (g_strcmp0(method_name, "GetManagedObjects") == 0) { + + BT_DBG("Getting values for service, chars and descriptors"); + GVariantBuilder *builder; + /*Main Builder */ + builder = g_variant_builder_new( + G_VARIANT_TYPE("a{oa{sa{sv}}}")); + + /* Prepare inner builder for GattService1 interface */ + + GVariantBuilder *svc_builder = NULL; + GVariantBuilder *inner_builder = NULL; + + GSList *l1 = g_slist_last(gatt_services); + struct gatt_service_info *serv_info = l1->data; + if (serv_info == NULL) { + BT_ERR("service info value is NULL"); + g_dbus_method_invocation_return_value(invocation, NULL); + return; + } + + /* Prepare inner builder for GattService1 interface */ + BT_DBG("Creating builder for service"); + svc_builder = g_variant_builder_new( + G_VARIANT_TYPE("a{sa{sv}}")); + inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); + + g_variant_builder_add(inner_builder, "{sv}", "UUID", + g_variant_new_string(serv_info->service_uuid)); + + g_variant_builder_add(svc_builder, "{sa{sv}}", + GATT_SERV_INTERFACE, + inner_builder); + + g_variant_builder_add(builder, "{oa{sa{sv}}}", + serv_info->serv_path, + svc_builder); + + /* Prepare inner builder for GattCharacteristic1 interface */ + + GSList *l2 = serv_info->char_data; + BT_DBG("Creating builder for characteristics \n"); + + if (l2 == NULL) + BT_DBG("characteristic data is NULL"); + + for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) { + + GVariantBuilder *char_builder = NULL; + GVariantBuilder *inner_builder = NULL; + GVariantBuilder *builder1 = NULL; + GVariantBuilder *builder2 = NULL; + GVariant *char_val = NULL; + GVariant *flags_val = NULL; + int i = 0; + + char_builder = g_variant_builder_new( + G_VARIANT_TYPE( + "a{sa{sv}}")); + inner_builder = g_variant_builder_new( + G_VARIANT_TYPE( + "a{sv}")); + + struct gatt_char_info *char_info = l2->data; + if (char_info == NULL) { + BT_ERR("char_info is NULL"); + continue; + } + + /*Uuid*/ + g_variant_builder_add(inner_builder, "{sv}", "UUID", + g_variant_new_string(char_info->char_uuid)); + /*Service*/ + g_variant_builder_add(inner_builder, "{sv}", "Service", + g_variant_new("o", serv_info->serv_path)); + /*Value*/ + builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY); + + if(char_info->char_value != NULL) { + for (i = 0; i < char_info->value_length; i++) { + g_variant_builder_add(builder1, "y", + char_info->char_value[i]); + } + char_val = g_variant_new("ay", builder1); + g_variant_builder_add(inner_builder, "{sv}", + "Value", char_val); + } + /*Flags*/ + builder2 = g_variant_builder_new(G_VARIANT_TYPE("as")); + + for (i = 0; i < char_info->flags_length; i++) { + g_variant_builder_add(builder2, "s", + char_info->char_flags[i]); + } + + flags_val = g_variant_new("as", builder2); + g_variant_builder_add(inner_builder, "{sv}", "Flags", + flags_val); + + g_variant_builder_add(char_builder, "{sa{sv}}", + GATT_CHAR_INTERFACE , inner_builder); + g_variant_builder_add(builder, "{oa{sa{sv}}}", + char_info->char_path, char_builder); + + /*Prepare inner builder for GattDescriptor1 interface*/ + + GSList *l3 = char_info->desc_data; + + if (l3 == NULL) + BT_DBG("descriptor data is NULL"); + + for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) { + + BT_DBG("Creating builder for descriptor \n"); + + GVariantBuilder *desc_builder = NULL; + GVariantBuilder *inner_builder = NULL; + GVariantBuilder *builder1 = NULL; + GVariant *desc_val = NULL; + + desc_builder = g_variant_builder_new( + G_VARIANT_TYPE( + "a{sa{sv}}")); + inner_builder = g_variant_builder_new( + G_VARIANT_TYPE( + "a{sv}")); + + struct gatt_desc_info *desc_info = l3->data; + if (desc_info == NULL) { + BT_ERR("desc_info is NULL"); + continue; + } + + /*Uuid*/ + g_variant_builder_add(inner_builder, + "{sv}", "UUID", + g_variant_new_string( + desc_info->desc_uuid)); + + /*Characteristic*/ + g_variant_builder_add(inner_builder, "{sv}", + "Characteristic", + g_variant_new("o", + char_info->char_path)); + + /*Value*/ + builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY); + + if(desc_info->desc_value != NULL) { + for (i = 0; i < desc_info->value_length; i++) { + g_variant_builder_add(builder1, "y", + desc_info->desc_value[i]); + } + desc_val = g_variant_new("ay", builder1); + g_variant_builder_add(inner_builder, "{sv}", + "Value", desc_val); + } + + g_variant_builder_add(desc_builder, "{sa{sv}}", + GATT_DESC_INTERFACE, + inner_builder); + + g_variant_builder_add(builder, "{oa{sa{sv}}}", + desc_info->desc_path, + desc_builder); + + /*unref descriptor builder pointers*/ + g_variant_builder_unref(builder1); + g_variant_builder_unref(inner_builder); + g_variant_builder_unref(desc_builder); + } + + /*unref char builder pointers*/ + g_variant_builder_unref(builder1); + g_variant_builder_unref(builder2); + g_variant_builder_unref(inner_builder); + g_variant_builder_unref(char_builder); + } + + /*unref service builder pointers*/ + g_variant_builder_unref(inner_builder); + g_variant_builder_unref(svc_builder); + + /* Return builder as method reply */ + BT_DBG("Sending gatt service builder values to Bluez"); + g_dbus_method_invocation_return_value(invocation, + g_variant_new( + "(a{oa{sa{sv}}})", + builder)); + } +} + +static void __bt_gatt_prop_method_call(GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + g_dbus_method_invocation_return_value(invocation, NULL); +} + +gboolean __bt_gatt_emit_interface_removed(gchar *object_path, gchar *interface) +{ + gboolean ret; + GError *error = NULL; + GVariantBuilder *array_builder; + + array_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY); + g_variant_builder_init(array_builder, G_VARIANT_TYPE ("as")); + g_variant_builder_add(array_builder, "s", interface); + + ret = g_dbus_connection_emit_signal(g_conn, NULL, "/", + "org.freedesktop.Dbus.Objectmanager", + "InterfacesRemoved", + g_variant_new ("(oas)", + object_path, array_builder), + &error); + + if (!ret) { + if (error != NULL) { + /* dbus gives error cause */ + BT_ERR("d-bus api failure: errcode[%x], message[%s]", + error->code, error->message); + g_clear_error(&error); + } + } + g_variant_builder_unref(array_builder); + + return ret; +} + +static gboolean __bt_gatt_desc_set_property(GDBusConnection *connection, + const gchar *sender, const gchar *object_path, + const gchar *interface_name, + const gchar *property_name, + GVariant *value, + GError **err, gpointer user_data) +{ + BT_DBG("+"); + + return TRUE; +} + +static gboolean __bt_gatt_char_set_property(GDBusConnection *connection, + const gchar *sender, const gchar *object_path, + const gchar *interface_name, + const gchar *property_name, + GVariant *value, + GError **err, gpointer user_data) +{ + BT_DBG("+"); + + if (g_strcmp0(property_name, "Value") == 0) { + GVariantIter *var = NULL; + bt_gatt_char_value_t char_val = {0, }; + bt_user_info_t *user_info = NULL; + int len = 0, i; + + g_variant_get(value, "ay", &var); + len = g_variant_get_size(var); + + char_val.char_handle = object_path; + if (len > 0) { + char_val.char_value = (guint8 *)malloc(len); + if (!char_val.char_value) + return FALSE; + } + for (i = 0; i < len; i++) + g_variant_iter_loop(var, "y", &char_val.char_value[i]); + char_val.val_len = len; + user_info = _bt_get_user_data(BT_COMMON); + if (user_info != NULL) + _bt_common_event_cb( + BLUETOOTH_EVENT_GATT_SERVER_CHARACTERISTIC_VALUE_CHANGED, + BLUETOOTH_ERROR_NONE, &char_val, + user_info->cb, user_info->user_data); + + bluetooth_gatt_update_characteristic(object_path, char_val.char_value, + char_val.val_len); + + free(char_val.char_value); + } + + return TRUE; +} + +static GVariant *__bt_gatt_desc_get_property(GDBusConnection *connection, + const gchar *sender, const gchar *object_path, + const gchar *interface_name, + const gchar *property_name, + GError **error, gpointer user_data) +{ + BT_DBG("+"); + + return NULL; +} + +static GVariant *__bt_gatt_char_get_property(GDBusConnection *connection, + const gchar *sender, const gchar *object_path, + const gchar *interface_name, + const gchar *property_name, + GError **error, gpointer user_data) +{ + BT_DBG("+"); + + return NULL; +} + +static GVariant *__bt_gatt_serv_get_property(GDBusConnection *connection, + const gchar *sender, const gchar *object_path, + const gchar *interface_name, + const gchar *property_name, + GError **error, gpointer user_data) +{ + BT_DBG("+"); + + return NULL; +} + +static const GDBusInterfaceVTable desc_interface_vtable = { + NULL, + __bt_gatt_desc_get_property, + __bt_gatt_desc_set_property +}; + +static const GDBusInterfaceVTable char_interface_vtable = { + NULL, + __bt_gatt_char_get_property, + __bt_gatt_char_set_property, +}; + +static const GDBusInterfaceVTable serv_interface_vtable = { + NULL, + __bt_gatt_serv_get_property, + NULL, +}; + +static const GDBusInterfaceVTable manager_interface_vtable = { + __bt_gatt_manager_method_call, + NULL, + NULL +}; + +static const GDBusInterfaceVTable properties_interface_vtable = { + __bt_gatt_prop_method_call, + NULL, + NULL +}; + +static GDBusNodeInfo *__bt_gatt_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) { + BT_ERR("Unable to create node: %s", err->message); + g_clear_error(&err); + } + return node_info; +} + +static struct gatt_service_info *__bt_gatt_find_gatt_service_info( + const char *service_path) +{ + GSList *l; + + for (l = gatt_services; l != NULL; l = l->next) { + struct gatt_service_info *info = l->data; + + if (g_strcmp0(info->serv_path, service_path) == 0) + return info; + } + BT_ERR("Gatt service not found"); + return NULL; +} + +static struct gatt_char_info *__bt_gatt_find_gatt_char_info( + const char *service_path, const char *char_path) +{ + GSList *l1, *l2; + + for (l1 = gatt_services; l1 != NULL; l1 = l1->next) { + struct gatt_service_info *serv_info = l1->data; + + if (g_strcmp0(serv_info->serv_path, service_path) == 0) { + + for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) { + struct gatt_char_info *char_info = l2->data; + + if (g_strcmp0(char_info->char_path, char_path) + == 0) + return char_info; + } + BT_ERR("Gatt characteristic not found"); + return NULL; + } + } + BT_ERR("Gatt service not found"); + return NULL; +} + +static struct gatt_desc_info *__bt_gatt_find_gatt_desc_info( + const char *serv_path, const char *char_path, + const char *desc_path) +{ + GSList *l1, *l2, *l3; + + for (l1 = gatt_services; l1 != NULL; l1 = l1->next) { + struct gatt_service_info *serv_info = l1->data; + + if (g_strcmp0(serv_info->serv_path, serv_path) == 0) { + for (l2 = serv_info->char_data; l2 != NULL; l2 = l2->next) { + struct gatt_char_info *char_info = l2->data; + + if (g_strcmp0(char_info->char_path, char_path) + == 0) { + for (l3 = char_info->desc_data; l3 != NULL; l3 = l3->next) { + struct gatt_desc_info *desc_info = l3->data; + if (g_strcmp0(desc_info->desc_path, + desc_path) == 0) { + return desc_info; + } + } + } + } + } + } + BT_ERR("Gatt descriptor not found"); + return NULL; +} + + +static GDBusProxy *__bt_gatt_gdbus_init_manager_proxy(const gchar *service, + const gchar *path, const gchar *interface) +{ + GDBusProxy *proxy; + GError *err = NULL; + + if (g_conn == NULL) + g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, + NULL, &err); + + if (!g_conn) { + if (err) { + BT_ERR("Unable to connect to gdbus: %s", err->message); + g_clear_error(&err); + } + return NULL; + } + + proxy = g_dbus_proxy_new_sync(g_conn, + G_DBUS_PROXY_FLAGS_NONE, NULL, + service, path, + interface, NULL, &err); + + if (!proxy) { + if (err) { + BT_ERR("Unable to create proxy: %s", err->message); + g_clear_error(&err); + } + return NULL; + } + manager_gproxy = proxy; + + return proxy; +} + +static GDBusProxy *__bt_gatt_gdbus_get_manager_proxy(const gchar *service, + const gchar *path, const gchar *interface) +{ + return (manager_gproxy) ? manager_gproxy : + __bt_gatt_gdbus_init_manager_proxy(service, + path, interface); +} + +static gboolean __bt_gatt_export_properties_method(const char *svc_path) +{ + guint prop_id; + GDBusNodeInfo *prop_info; + GError *error = NULL; + struct gatt_service_info *svc_info; + + BT_DBG("svc_path %s", svc_path); + svc_info = __bt_gatt_find_gatt_service_info(svc_path); + + if (!svc_info) { + BT_ERR("Unable to find service info"); + return FALSE; + } + + /* Register ObjectManager interface */ + prop_info = __bt_gatt_create_method_node_info( + properties_introspection_xml); + + if (prop_info == NULL) { + BT_ERR("failed to get node info"); + return FALSE; + } + + prop_id = g_dbus_connection_register_object(g_conn, svc_path, + prop_info->interfaces[0], + &properties_interface_vtable, + NULL, NULL, &error); + + if (prop_id == 0) { + BT_ERR("failed to register: %s", error->message); + g_error_free(error); + return FALSE; + } + svc_info->prop_id = prop_id; + + return TRUE; +} + +int bluetooth_gatt_convert_prop2string( + bt_gatt_characteristic_property_t properties, + char *char_properties[]) +{ + int flag_count = 0; + + if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST) { + char_properties[flag_count] = g_strdup("broadcast"); + flag_count++; + } + if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ) { + char_properties[flag_count] = g_strdup("read"); + flag_count++; + } + if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE) { + char_properties[flag_count] = g_strdup("write-without-response"); + flag_count++; + } + if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE) { + char_properties[flag_count] = g_strdup("write"); + flag_count++; + } + if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY) { + char_properties[flag_count] = g_strdup("notify"); + flag_count++; + } + if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE) { + char_properties[flag_count] = g_strdup("indicate"); + flag_count++; + } + if (properties & BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE) { + char_properties[flag_count] = g_strdup("authenticated-signed-writes"); + flag_count++; + } + + if (flag_count == 0) { + char_properties[flag_count] = g_strdup("read"); + flag_count++; + } + + return flag_count; +} + +static void __bt_gatt_set_service_state(const char *service_path, + gboolean state) +{ + struct gatt_service_info *svc_info = NULL; + svc_info = __bt_gatt_find_gatt_service_info(service_path); + + if (svc_info != NULL) { + BT_DBG("Updating the gatt service register state %d", state); + svc_info->is_svc_registered = state; + return; + } + + BT_DBG("gatt service not found"); +} + +static gboolean __bt_gatt_get_service_state(const char *service_path) +{ + struct gatt_service_info *svc_info = NULL; + + svc_info = __bt_gatt_find_gatt_service_info(service_path); + + if (svc_info != NULL) { + BT_DBG("Return the state of the gatt service %d", + svc_info->is_svc_registered); + return svc_info->is_svc_registered; + } + + BT_DBG("gatt service info is NULL"); + return FALSE; +} + +void get_service_cb(GObject *object, GAsyncResult *res, gpointer user_data) +{ + GError *error = NULL; + GVariant *result; + GVariantIter *iter = NULL; + const gchar *key = NULL; + GVariant *value = NULL; + gchar *service = NULL; + gchar *characteristic = NULL; + gchar *descriptor = NULL; + int n_char = 1; + + BT_DBG(" "); + result = g_dbus_proxy_call_finish(manager_gproxy, res, &error); + + if (result == NULL) { + /* dBUS-RPC is failed */ + BT_ERR("Dbus-RPC is failed\n"); + + if (error != NULL) { + /* dBUS gives error cause */ + BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n", + error->code, error->message); + g_clear_error(&error); + } + } else { + char *char_cmp = NULL; + g_variant_get (result, "(a{sv})", &iter); + char_cmp = g_strdup_printf("Characteristic%d", n_char); + + while (g_variant_iter_loop(iter, "{sv}", &key, &value)) { + if (g_strcmp0(key, "Service") == 0) { + service = g_variant_get_string(value, NULL); + BT_DBG("Service %s", service); + } else if (g_strcmp0(key, char_cmp) == 0) { + characteristic = g_variant_get_string(value, NULL); + g_free(char_cmp); + char_cmp = g_strdup_printf("Characteristic%d", ++n_char); + BT_DBG("%s", characteristic); + } else if (g_strcmp0(key, "Descriptor") == 0) { + descriptor = g_variant_get_string(value, NULL); + BT_DBG("Descriptor %s", descriptor); + } + } + /* TODO: Store the service informationa and + * Send respponse to CAPI layer. */ + + g_variant_unref(result); + if (char_cmp); + g_free(char_cmp); + } +} +void register_service_cb(GObject *object, GAsyncResult *res, gpointer user_data) +{ + BT_DBG("register_service_cb\n"); + + GError *error = NULL; + GVariant *result; + + result = g_dbus_proxy_call_finish(manager_gproxy, res, &error); + + if (result == NULL) { + /* dBUS-RPC is failed */ + BT_ERR("Dbus-RPC is failed\n"); + + if (error != NULL) { + /* dBUS gives error cause */ + BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n", + error->code, error->message); + g_clear_error(&error); + } + } +} + +void unregister_service_cb(GObject *object, GAsyncResult *res, + gpointer user_data) +{ + BT_DBG("unregister_service_cb\n"); + + GError *error = NULL; + GVariant *result; + + result = g_dbus_proxy_call_finish(manager_gproxy, res, &error); + + if (result == NULL) { + /* dBUS-RPC is failed */ + BT_ERR("Dbus-RPC is failed\n"); + + if (error != NULL) { + /* dBUS gives error cause */ + BT_ERR("D-Bus API failure: errCode[%x], message[%s]\n", + error->code, error->message); + g_clear_error(&error); + } + } +} + +static int __bt_gatt_unregister_service(const char *service_path) +{ + if (!__bt_gatt_get_service_state(service_path)) { + BT_DBG("service not registered \n"); + return BLUETOOTH_ERROR_NOT_FOUND; + } + + GDBusProxy *proxy = NULL; + + proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez", + "/org/bluez", GATT_MNGR_INTERFACE); + + if (proxy == NULL) + return BLUETOOTH_ERROR_INTERNAL; + + /* Async Call to Unregister Service */ + g_dbus_proxy_call(proxy, + "UnregisterService", + g_variant_new("(o)", + service_path), + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, + (GAsyncReadyCallback) unregister_service_cb, + NULL); + + __bt_gatt_set_service_state(service_path, FALSE); + + return BLUETOOTH_ERROR_NONE; +} + +static GDBusConnection *__bt_gatt_get_gdbus_connection(void) +{ + GDBusConnection *local_system_gconn = NULL; + GError *err = NULL; + + if (g_conn == NULL) { + g_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err); + if (!g_conn) { + if (err) { + BT_ERR("Unable to connect to dbus: %s", err->message); + g_clear_error(&err); + } + g_conn = NULL; + } + } else if (g_dbus_connection_is_closed(g_conn)) { + local_system_gconn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err); + + if (!local_system_gconn) { + BT_ERR("Unable to connect to dbus: %s", err->message); + g_clear_error(&err); + } + + g_conn = local_system_gconn; + } + + return g_conn; +} + +BT_EXPORT_API int bluetooth_gatt_init(void) +{ + guint object_id; + GDBusConnection *conn; + GDBusNodeInfo *obj_info; + GError *error = NULL; + + owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM, + BT_GATT_SERVICE_NAME, + G_BUS_NAME_OWNER_FLAGS_NONE, + NULL, NULL, NULL, NULL, NULL); + + BT_DBG("owner_id is [%d]", owner_id); + + serv_id = 1; + + conn = __bt_gatt_get_gdbus_connection(); + if (!conn) { + BT_ERR("Unable to get connection"); + return BLUETOOTH_ERROR_INTERNAL; + } + + /* Register ObjectManager interface */ + obj_info = __bt_gatt_create_method_node_info( + manager_introspection_xml); + + if (obj_info == NULL) { + BT_ERR("failed to get node info"); + return BLUETOOTH_ERROR_INTERNAL; + } + + manager_id = g_dbus_connection_register_object(g_conn, "/", + obj_info->interfaces[0], + &manager_interface_vtable, + NULL, NULL, &error); + + if (manager_id == 0) { + BT_ERR("failed to register: %s", error->message); + g_error_free(error); + return BLUETOOTH_ERROR_INTERNAL; + } + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_deinit() +{ + /* Unown gdbus bus */ + if (owner_id) { + + /* remove/unregister all services */ + BT_DBG("removing all registered gatt service\n"); + bluetooth_gatt_delete_services(); + + g_bus_unown_name(owner_id); + + /* unregister the exported interface for object manager */ + g_dbus_connection_unregister_object(g_conn, + manager_id); + + BT_DBG("Gatt service deinitialized \n"); + + g_slist_free(gatt_services); + gatt_services = NULL; + + return BLUETOOTH_ERROR_NONE; + } + + return BLUETOOTH_ERROR_NOT_FOUND; +} + +BT_EXPORT_API int bluetooth_gatt_add_service(const char *svc_uuid, + char **svc_path) +{ + GError *error = NULL; + guint object_id; + GDBusNodeInfo *node_info; + gchar *path = NULL; + GVariantBuilder *builder = NULL; + GVariantBuilder *inner_builder = NULL; + struct gatt_service_info *serv_info = NULL; + + node_info = __bt_gatt_create_method_node_info( + service_introspection_xml); + + if (node_info == NULL) + return BLUETOOTH_ERROR_INTERNAL; + + path = g_strdup_printf(GATT_SERV_OBJECT_PATH"%d", serv_id++); + BT_DBG("gatt service path is [%s]", path); + + object_id = g_dbus_connection_register_object(g_conn, path, + node_info->interfaces[0], + &serv_interface_vtable, + NULL, NULL, &error); + + if (object_id == 0) { + BT_ERR("failed to register: %s", error->message); + g_error_free(error); + g_free(path); + + return BLUETOOTH_ERROR_INTERNAL; + } + + /* Add object_id/gatt service information; it's required at the time of + * service unregister and Getmanagedobjects + */ + serv_info = g_new0(struct gatt_service_info, 1); + + serv_info->serv_path = g_strdup(path); + serv_info->serv_id = object_id; + serv_info->service_uuid = g_strdup(svc_uuid); + serv_info->is_svc_registered = FALSE; + + gatt_services = g_slist_append(gatt_services, serv_info); + + /* emit interfacesadded signal here for service path */ + builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}")); + inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); + + g_variant_builder_add(inner_builder, "{sv}", + "UUID", g_variant_new_string(svc_uuid)); + + g_variant_builder_add(builder, "{sa{sv}}", + GATT_SERV_INTERFACE, inner_builder); + + g_dbus_connection_emit_signal(g_conn, NULL, "/", + "org.freedesktop.Dbus.ObjectManager", + "InterfacesAdded", + g_variant_new("(oa{sa{sv}})", + path, builder), + &error); + + new_service = TRUE; + + *svc_path = g_strdup(path); + + g_free(path); + g_variant_builder_unref(inner_builder); + g_variant_builder_unref(builder); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_add_new_characteristic( + const char *svc_path, const char *char_uuid, + bt_gatt_characteristic_property_t properties, + char **char_path) +{ + static int char_id; + GError *error = NULL; + guint object_id; + GDBusNodeInfo *node_info; + gchar *path = NULL; + GVariantBuilder *builder = NULL; + GVariantBuilder *inner_builder = NULL; + struct gatt_service_info *serv_info = NULL; + struct gatt_char_info *char_info = NULL; + GVariantBuilder *builder2 = NULL; + GVariant *flags_val = NULL; + int i = 0; + char *char_flags[NUMBER_OF_FLAGS]; + int flag_count = 0; + + if (new_service) { + char_id = 1; + new_service = FALSE; + } + + BT_DBG("gatt svc_path path is [%s]", svc_path); + serv_info = __bt_gatt_find_gatt_service_info(svc_path); + if (serv_info == NULL) + return BLUETOOTH_ERROR_INVALID_PARAM; + + node_info = __bt_gatt_create_method_node_info( + characteristics_introspection_xml); + + if (node_info == NULL) + return BLUETOOTH_ERROR_INTERNAL; + + path = g_strdup_printf("%s/characteristic%d", svc_path, char_id++); + BT_DBG("gatt characteristic path is [%s]", path); + + object_id = g_dbus_connection_register_object(g_conn, path, + node_info->interfaces[0], + &char_interface_vtable, + NULL, NULL, &error); + + if (object_id == 0) { + BT_ERR("failed to register: %s", error->message); + g_error_free(error); + g_free(path); + + return BLUETOOTH_ERROR_INTERNAL; + } + + flag_count = bluetooth_gatt_convert_prop2string(properties, char_flags); + + char_info = g_new0(struct gatt_char_info, 1); + + char_info->char_path = g_strdup(path); + char_info->char_id = object_id; + char_info->char_uuid = g_strdup(char_uuid); + + for (i = 0; i < flag_count; i++) { + char_info->char_flags[i] = char_flags[i]; + } + + char_info->flags_length = flag_count; + + serv_info->char_data = g_slist_append(serv_info->char_data, char_info); + + builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}")); + inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); + + g_variant_builder_add(inner_builder, "{sv}", "UUID", + g_variant_new("s", char_uuid)); + g_variant_builder_add(inner_builder, "{sv}", "Service", + g_variant_new("o", svc_path)); + + builder2 = g_variant_builder_new(G_VARIANT_TYPE("as")); + + for (i = 0; i < flag_count; i++) { + g_variant_builder_add(builder2, "s", char_flags[i]); + } + + flags_val = g_variant_new("as", builder2); + g_variant_builder_add(inner_builder, "{sv}", "Flags", + flags_val); + + g_variant_builder_add(builder, "{sa{sv}}", + GATT_CHAR_INTERFACE, + inner_builder); + + g_dbus_connection_emit_signal(g_conn, NULL, "/", + "org.freedesktop.Dbus.ObjectManager", + "InterfacesAdded", + g_variant_new("(oa{sa{sv}})", + path, builder), + &error); + + *char_path = g_strdup(path); + + new_char = TRUE; + + g_free(path); + + g_variant_builder_unref(inner_builder); + g_variant_builder_unref(builder); + g_variant_builder_unref(builder2); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_set_characteristic_value( + const char *characteristic, const char *char_value, + int value_length) +{ + gchar **line_argv = NULL; + char *serv_path = NULL; + struct gatt_char_info *char_info = NULL; + GVariantBuilder *builder1 = NULL; + GVariantBuilder *builder = NULL; + GVariantBuilder *inner_builder = NULL; + GVariant *char_val = NULL; + GError *error = NULL; + int i = 0; + + line_argv = g_strsplit_set(characteristic, "/", 0); + serv_path = g_strdup_printf("/%s", line_argv[1]); + + char_info = __bt_gatt_find_gatt_char_info(serv_path, characteristic); + + if (char_info == NULL) { + g_strfreev(line_argv); + return BLUETOOTH_ERROR_INVALID_PARAM; + } + + char_info->value_length = value_length; + + char_info->char_value = (char *)malloc(value_length); + for (i = 0; i < value_length; i++) + char_info->char_value[i] = char_value[i]; + + builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}")); + inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); + + builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY); + + for (i = 0; i < value_length; i++) { + g_variant_builder_add(builder1, "y", char_value[i]); + } + + char_val = g_variant_new("ay", builder1); + g_variant_builder_add(inner_builder, "{sv}", "Value", char_val); + + g_variant_builder_add(builder, "{sa{sv}}", + GATT_CHAR_INTERFACE, + inner_builder); + + g_dbus_connection_emit_signal(g_conn, NULL, "/", + "org.freedesktop.Dbus.ObjectManager", + "InterfacesAdded", + g_variant_new("(oa{sa{sv}})", + char_info->char_path, builder), + &error); + + g_strfreev(line_argv); + g_variant_builder_unref(inner_builder); + g_variant_builder_unref(builder); + g_variant_builder_unref(builder1); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_add_descriptor( + const char *char_path, const char *desc_uuid, + char **desc_path) +{ + static int desc_id = 1; + GError *error = NULL; + guint object_id; + GDBusNodeInfo *node_info; + gchar *path = NULL; + GVariantBuilder *builder = NULL; + GVariantBuilder *inner_builder = NULL; + struct gatt_char_info *char_info = NULL; + struct gatt_desc_info *desc_info = NULL; + gchar **line_argv = NULL; + char *serv_path; + + if (new_char) { + desc_id = 1; + new_char = FALSE; + } + + line_argv = g_strsplit_set(char_path, "/", 0); + serv_path = g_strdup_printf("/%s", line_argv[1]); + + char_info = __bt_gatt_find_gatt_char_info(serv_path, char_path); + + g_free(serv_path); + + if (char_info == NULL) { + g_strfreev(line_argv); + return BLUETOOTH_ERROR_INVALID_PARAM; + } + + node_info = __bt_gatt_create_method_node_info( + descriptor_introspection_xml); + + if (node_info == NULL) { + g_strfreev(line_argv); + return BLUETOOTH_ERROR_INTERNAL; + } + + path = g_strdup_printf("%s/descriptor%d", char_path, desc_id++); + BT_DBG("gatt descriptor path is [%s]", path); + + object_id = g_dbus_connection_register_object(g_conn, path, + node_info->interfaces[0], + &desc_interface_vtable, + NULL, NULL, &error); + + if (object_id == 0) { + BT_ERR("failed to register: %s", error->message); + g_error_free(error); + g_free(path); + g_strfreev(line_argv); + + return BLUETOOTH_ERROR_INTERNAL; + } + + desc_info = g_new0(struct gatt_desc_info, 1); + + desc_info->desc_path = g_strdup(path); + desc_info->desc_id = object_id; + desc_info->desc_uuid = g_strdup(desc_uuid); + + char_info->desc_data = g_slist_append(char_info->desc_data, desc_info); + + builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}")); + inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); + + g_variant_builder_add(inner_builder, "{sv}", "UUID", + g_variant_new("s", desc_uuid)); + g_variant_builder_add(inner_builder, "{sv}", "Characteristic", + g_variant_new("o", char_path)); + + g_variant_builder_add(builder, "{sa{sv}}", + GATT_DESC_INTERFACE, + inner_builder); + + g_dbus_connection_emit_signal(g_conn, NULL, "/", + "org.freedesktop.Dbus.ObjectManager", + "InterfacesAdded", + g_variant_new("(oa{sa{sv}})", + path, builder), + &error); + + *desc_path = g_strdup(path); + + g_free(path); + g_strfreev(line_argv); + g_variant_builder_unref(inner_builder); + g_variant_builder_unref(builder); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_set_descriptor_value( + const char *desc_path, const char *desc_value, + int value_length) +{ + GError *error = NULL; + GVariantBuilder *builder = NULL; + GVariantBuilder *inner_builder = NULL; + GVariantBuilder *builder1 = NULL; + struct gatt_desc_info *desc_info = NULL; + gchar **line_argv = NULL; + char *char_path; + GVariant *desc_val = NULL; + char *serv_path = NULL; + int i ; + + line_argv = g_strsplit_set(desc_path, "/", 0); + serv_path = g_strdup_printf("/%s", line_argv[1]); + char_path = g_strdup_printf("%s/%s", serv_path, line_argv[2]); + + desc_info = __bt_gatt_find_gatt_desc_info(serv_path, char_path, desc_path); + + if (desc_info == NULL) { + g_strfreev(line_argv); + return BLUETOOTH_ERROR_INVALID_PARAM; + } + + desc_info->desc_value = (char *)malloc(value_length); + + for (i = 0; i < value_length; i++) + desc_info->desc_value[i] = desc_value[i]; + + desc_info->value_length = value_length; + + builder = g_variant_builder_new(G_VARIANT_TYPE("a{sa{sv}}")); + inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); + + builder1 = g_variant_builder_new(G_VARIANT_TYPE_ARRAY); + + for (i = 0; i < value_length; i++) { + g_variant_builder_add(builder1, "y", desc_value[i]); + } + desc_val = g_variant_new("ay", builder1); + g_variant_builder_add(inner_builder, "{sv}", "Value", desc_val); + + g_variant_builder_add(builder, "{sa{sv}}", + GATT_DESC_INTERFACE, + inner_builder); + + g_dbus_connection_emit_signal(g_conn, NULL, "/", + "org.freedesktop.Dbus.ObjectManager", + "InterfacesAdded", + g_variant_new("(oa{sa{sv}})", + desc_info->desc_path, builder), + &error); + + g_strfreev(line_argv); + g_variant_builder_unref(inner_builder); + g_variant_builder_unref(builder); + g_variant_builder_unref(builder1); + + return BLUETOOTH_ERROR_NONE; +} + +int bluetooth_gatt_get_service(const char *svc_uuid) +{ + GDBusProxy *proxy = NULL; + gchar *uuid = NULL; + + proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez", + "/org/bluez", GATT_MNGR_INTERFACE); + if (proxy == NULL) + return BLUETOOTH_ERROR_INTERNAL; + + uuid = g_strdup(svc_uuid); + + g_dbus_proxy_call(proxy, + "GetService", + g_variant_new("(s)", + uuid), + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, + (GAsyncReadyCallback) get_service_cb, + NULL); + + g_free(uuid); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_register_service( + const char *svc_path) +{ + GDBusProxy *proxy = NULL; + gchar *path = NULL; + + if (__bt_gatt_get_service_state(svc_path)) { + BT_DBG("service already registered \n"); + return BLUETOOTH_ERROR_NONE; + } + + if (!__bt_gatt_export_properties_method(svc_path)) { + BT_ERR("Failed to export Object manager method"); + return BLUETOOTH_ERROR_INTERNAL; + } + + proxy = __bt_gatt_gdbus_get_manager_proxy("org.bluez", + "/org/bluez", GATT_MNGR_INTERFACE); + if (proxy == NULL) + return BLUETOOTH_ERROR_INTERNAL; + + path = g_strdup(svc_path); + + g_dbus_proxy_call(proxy, + "RegisterService", + g_variant_new("(oa{sv})", + path, NULL), + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, + (GAsyncReadyCallback) register_service_cb, + NULL); + + __bt_gatt_set_service_state(svc_path, TRUE); + + g_free(path); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_delete_services(void) +{ + GSList *l; + int error = BLUETOOTH_ERROR_NONE; + l = gatt_services; + + if (l != NULL) { + for (l = gatt_services; l != NULL; l = l->next) { + struct gatt_service_info *info = l->data; + BT_DBG("svc_path is %s", info->serv_path); + if (bluetooth_gatt_unregister_service(info->serv_path) + != BLUETOOTH_ERROR_NONE) { + error = BLUETOOTH_ERROR_INTERNAL; + BT_DBG(" Error in removing service %s \n", + info->serv_path); + } + } + BT_DBG(" All services removed successfully.\n "); + } + else { + BT_DBG(" There are no registered services.\n "); + } + + g_slist_free(gatt_services); + gatt_services = NULL; + serv_id = 1; + + if (error != BLUETOOTH_ERROR_NONE) + return error; + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_gatt_update_characteristic( + const char *char_path, const char* char_value, + int value_length) +{ + GVariantBuilder *outer_builder; + GVariantBuilder *inner_builder; + GVariantBuilder *invalidated_builder; + GVariant *update_value = NULL; + GError *error = NULL; + gboolean ret = FALSE; + int err = BLUETOOTH_ERROR_NONE; + int i = 0; + gchar **line_argv = NULL; + gchar *serv_path = NULL; + + line_argv = g_strsplit_set(char_path, "/", 0); + serv_path = g_strdup_printf("/%s", line_argv[1]); + + if (!__bt_gatt_get_service_state(serv_path)) { + BT_DBG("service not registered for this characteristic \n"); + g_strfreev(line_argv); + g_free(serv_path); + return BLUETOOTH_ERROR_INTERNAL; + } + g_free(serv_path); + + outer_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); + invalidated_builder = g_variant_builder_new(G_VARIANT_TYPE("as")); + + inner_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY); + for (i = 0; i < value_length; i++) { + g_variant_builder_add(inner_builder, "y", char_value[i]); + } + + update_value = g_variant_new("ay", inner_builder); + + outer_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY); + g_variant_builder_add(outer_builder, "{sv}", "Value", + update_value); + + BT_DBG("Updating characteristic value \n"); + ret = g_dbus_connection_emit_signal(g_conn, NULL, + char_path, + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + g_variant_new("(sa{sv}as)", + "org.bluez.GattCharacteristic1", + outer_builder, invalidated_builder), + &error); + + if (!ret) { + if (error != NULL) { + BT_ERR("D-Bus API failure: errCode[%x], \ + message[%s]", + error->code, error->message); + g_clear_error(&error); + } + err = BLUETOOTH_ERROR_INTERNAL; + } + + g_strfreev(line_argv); + g_variant_builder_unref(inner_builder); + g_variant_builder_unref(outer_builder); + g_variant_builder_unref(invalidated_builder); + + return err; +} + +BT_EXPORT_API int bluetooth_gatt_unregister_service(const char *svc_path) +{ + GSList *l, *l1; + struct gatt_service_info *svc_info; + gboolean ret; + int err = BLUETOOTH_ERROR_NONE; + GSList *tmp; + + BT_DBG("svc_path %s", svc_path); + svc_info = __bt_gatt_find_gatt_service_info(svc_path); + + if (!svc_info) { + BT_ERR("Unable to find service info"); + return BLUETOOTH_ERROR_NOT_FOUND; + } + + err = __bt_gatt_unregister_service(svc_path); + if (err != BLUETOOTH_ERROR_NONE) { + BT_DBG("Could not unregister application"); + return err; + } + + for (l = svc_info->char_data; l != NULL; l = l->next) { + struct gatt_char_info *char_info = l->data; + + for (l1 = char_info->desc_data; l1 != NULL; l1 = l1->next) { + struct gatt_desc_info *desc_info = l1->data; + + ret = g_dbus_connection_unregister_object(g_conn, + desc_info->desc_id); + if (ret) { + __bt_gatt_emit_interface_removed( + desc_info->desc_path, + GATT_DESC_INTERFACE); + } else { + err = BLUETOOTH_ERROR_INTERNAL; + } + } + ret = g_dbus_connection_unregister_object(g_conn, + char_info->char_id); + if (ret) { + __bt_gatt_emit_interface_removed(char_info->char_path, + GATT_CHAR_INTERFACE); + } else { + err = BLUETOOTH_ERROR_INTERNAL; + } + } + ret = g_dbus_connection_unregister_object(g_conn, svc_info->serv_id); + if (ret) { + __bt_gatt_emit_interface_removed(svc_info->serv_path, + GATT_SERV_INTERFACE); + } else { + err = BLUETOOTH_ERROR_INTERNAL; + } + + ret = g_dbus_connection_unregister_object(g_conn, svc_info->prop_id); + if (ret) { + BT_DBG("Unregistered the service on properties interface"); + } + + for (tmp = gatt_services; tmp != NULL; tmp = tmp->next) { + struct gatt_service_info *info = tmp->data; + + if (g_strcmp0(info->serv_path, svc_path) == 0) { + g_slist_delete_link(gatt_services, tmp->data); + } + } + + new_service = FALSE; + + if (gatt_services->next == NULL) + serv_id--; + + return err; +} diff --git a/bt-api/bt-gatt.xml b/bt-api/bt-gatt.xml old mode 100644 new mode 100755 diff --git a/bt-api/bt-hdp.c b/bt-api/bt-hdp.c old mode 100644 new mode 100755 index 36aa058..98dffc6 --- a/bt-api/bt-hdp.c +++ b/bt-api/bt-hdp.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -20,6 +24,7 @@ #include #include #include +#include #include #include "bluetooth-api.h" @@ -27,13 +32,14 @@ #include "bt-internal-types.h" #define HDP_BUFFER_SIZE 1024 -#define BLUEZ_HDP_MANAGER_INTERFACE "org.bluez.HealthManager" -#define BLUEZ_HDP_DEVICE_INTERFACE "org.bluez.HealthDevice" -#define BLUEZ_HDP_CHANNEL_INTERFACE "org.bluez.HealthChannel" +#define BLUEZ_HDP_MANAGER_INTERFACE "org.bluez.HealthManager1" +#define BLUEZ_HDP_DEVICE_INTERFACE "org.bluez.HealthDevice1" +#define BLUEZ_HDP_CHANNEL_INTERFACE "org.bluez.HealthChannel1" typedef struct { char *obj_channel_path; int fd; + guint watch_id; } hdp_obj_info_t; typedef struct { @@ -41,6 +47,14 @@ typedef struct { GSList *obj_info; } hdp_app_list_t; +/* Variable for privilege, only for write API, + before we should reduce time to bt-service dbus calling + -1 : Don't have a permission to access API + 0 : Initial value, not yet check + 1 : Have a permission to access API +*/ +static int privilege_token; + /********************************************************************** * Static Functions declaration * @@ -64,7 +78,7 @@ static int __bt_hdp_internal_add_filter(void); static int __bt_hdp_internal_acquire_fd(const char *path); -static void __bt_hdp_internal_watch_fd(int file_desc, const char *path); +static guint __bt_hdp_internal_watch_fd(int file_desc, const char *path); static gboolean __bt_hdp_internal_data_received(GIOChannel *gio, GIOCondition cond, @@ -102,7 +116,7 @@ BT_EXPORT_API int bluetooth_hdp_activate(unsigned short data_type, /*For source role is mandatory */ if (role == HDP_ROLE_SOURCE && channel_type == HDP_QOS_ANY) { - BT_DBG("For source, type is mandatory - Reliable/Streaming"); + BT_ERR("For source, type is mandatory - Reliable/Streaming"); return BLUETOOTH_ERROR_INVALID_PARAM; } @@ -115,6 +129,7 @@ BT_EXPORT_API int bluetooth_hdp_activate(unsigned short data_type, static void __bt_hdp_obj_info_free(hdp_obj_info_t *info) { if (info) { + g_source_remove(info->watch_id); close(info->fd); g_free(info->obj_channel_path); g_free(info); @@ -196,9 +211,9 @@ static int __bt_hdp_internal_create_application(unsigned int data_type, if (role == HDP_ROLE_SOURCE) { key_type = "ChannelType"; if (channel_type == HDP_QOS_RELIABLE) - svalue = "Reliable"; + svalue = "reliable"; else if (channel_type == HDP_QOS_STREAMING) - svalue = "Streaming"; + svalue = "streaming"; dbus_message_iter_open_container(&array_iter, DBUS_TYPE_DICT_ENTRY, NULL, &entry); @@ -227,9 +242,15 @@ static int __bt_hdp_internal_create_application(unsigned int data_type, if (dbus_error_is_set(&err)) { BT_ERR("%s", err.message); + + if (g_strrstr(err.message, BT_ACCESS_DENIED_MSG)) + ret = BLUETOOTH_ERROR_ACCESS_DENIED; + else + ret = BLUETOOTH_ERROR_INTERNAL; + dbus_error_free(&err); } - return BLUETOOTH_ERROR_INTERNAL; + return ret; } if (!dbus_message_get_args(reply, &err, DBUS_TYPE_OBJECT_PATH, @@ -336,10 +357,9 @@ static void __bt_hdp_internal_handle_connect(DBusMessage *msg) const char *path = dbus_message_get_path(msg); const char *obj_channel_path; bt_user_info_t *user_info; - bt_hdp_connected_t conn_ind; int ret; - BT_DBG("+********Signal - ChannelConnected******\n\n"); + BT_INFO("+********Signal - ChannelConnected******\n\n"); BT_DBG("Path = %s", path); if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, @@ -348,14 +368,21 @@ static void __bt_hdp_internal_handle_connect(DBusMessage *msg) return; } - BT_DBG("Channel connected, Path = %s", obj_channel_path); + BT_INFO("Channel connected, Path = %s", obj_channel_path); + + user_info = _bt_get_user_data(BT_COMMON); + if (user_info == NULL || user_info->cb == NULL) + return; ret = __bt_hdp_internal_acquire_fd(obj_channel_path); if (ret != BLUETOOTH_ERROR_NONE) { - user_info = _bt_get_user_data(BT_COMMON); - if (user_info) { + _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED, + BLUETOOTH_ERROR_CONNECTION_ERROR, NULL, + user_info->cb, user_info->user_data); + } else { + if (user_info->cb) { _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED, - BLUETOOTH_ERROR_CONNECTION_ERROR, &conn_ind, + BLUETOOTH_ERROR_NONE, NULL, user_info->cb, user_info->user_data); } } @@ -373,7 +400,7 @@ static void __bt_hdp_internal_handle_disconnect(DBusMessage *msg) hdp_obj_info_t *info; bt_user_info_t *user_info; - BT_DBG("+********Signal - ChannelDeleted ******\n\n"); + BT_INFO("+********Signal - ChannelDeleted ******\n\n"); BT_DBG("Path = %s", path); if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, @@ -382,7 +409,7 @@ static void __bt_hdp_internal_handle_disconnect(DBusMessage *msg) return; } - BT_DBG("Channel Deleted, Path = %s", obj_channel_path); + BT_INFO("Channel Deleted, Path = %s", obj_channel_path); info = __bt_hdp_internal_gslist_obj_find_using_path(obj_channel_path); if (!info) { @@ -400,7 +427,7 @@ static void __bt_hdp_internal_handle_disconnect(DBusMessage *msg) user_info = _bt_get_user_data(BT_COMMON); - if (user_info) { + if (user_info->cb) { _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED, BLUETOOTH_ERROR_NONE, &dis_ind, user_info->cb, user_info->user_data); @@ -426,7 +453,7 @@ static void __bt_hdp_internal_handle_property_changed(DBusMessage *msg) dbus_message_iter_init(msg, &item_iter); if (dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_STRING) { - BT_DBG("This is bad format dbus"); + BT_ERR("This is bad format dbus"); return; } @@ -437,7 +464,7 @@ static void __bt_hdp_internal_handle_property_changed(DBusMessage *msg) BT_DBG("Property (%s)\n", property); if (0 == g_strcmp0(property, "MainChannel")) { - BT_DBG("Property MainChannel received"); + BT_INFO("Property MainChannel received"); dbus_message_iter_next(&item_iter); @@ -470,6 +497,7 @@ static int __bt_hdp_internal_acquire_fd(const char *path) DBusError err; int fd; bt_user_info_t *user_info; + char *dev_path; BT_DBG("+"); @@ -516,7 +544,11 @@ static int __bt_hdp_internal_acquire_fd(const char *path) BT_DBG("File Descriptor = %d, Dev_path = %s \n", fd, path); msg = dbus_message_new_method_call(BT_BLUEZ_NAME, path, - BLUEZ_HDP_CHANNEL_INTERFACE, "GetProperties"); + BT_PROPERTIES_INTERFACE, "GetAll"); + dev_path = g_strdup(BLUEZ_HDP_CHANNEL_INTERFACE); + dbus_message_append_args(msg, DBUS_TYPE_STRING, &dev_path, + DBUS_TYPE_INVALID); + g_free(dev_path); retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL); @@ -597,17 +629,16 @@ static int __bt_hdp_internal_acquire_fd(const char *path) /*Only process register with app handle receive the Connected event */ if (NULL == list) { - BT_DBG("**** Could not locate the list for %s*****\n", app_handle); + BT_ERR("**** Could not locate the list for %s*****\n", app_handle); goto error; } hdp_obj_info_t *info = g_new0(hdp_obj_info_t, 1); info->fd = fd; info->obj_channel_path = g_strdup(path); + info->watch_id = __bt_hdp_internal_watch_fd(fd, info->obj_channel_path); list->obj_info = g_slist_append(list->obj_info, info); - __bt_hdp_internal_watch_fd(fd, info->obj_channel_path); - _bt_device_path_to_address(path, address); _bt_convert_addr_string_to_type(device_addr.addr, address); @@ -622,7 +653,7 @@ static int __bt_hdp_internal_acquire_fd(const char *path) user_info = _bt_get_user_data(BT_COMMON); - if (user_info) { + if (user_info->cb) { _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED, BLUETOOTH_ERROR_NONE, &conn_ind, user_info->cb, user_info->user_data); @@ -639,9 +670,10 @@ static int __bt_hdp_internal_acquire_fd(const char *path) return BLUETOOTH_ERROR_INTERNAL; } -static void __bt_hdp_internal_watch_fd(int file_desc, const char *path) +static guint __bt_hdp_internal_watch_fd(int file_desc, const char *path) { GIOChannel *gio; + guint id; BT_DBG("+"); @@ -649,9 +681,10 @@ static void __bt_hdp_internal_watch_fd(int file_desc, const char *path) g_io_channel_set_close_on_unref(gio, TRUE); - g_io_add_watch(gio, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, + id = g_io_add_watch(gio, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, __bt_hdp_internal_data_received, (void *)path); BT_DBG("-"); + return id; } @@ -663,7 +696,7 @@ static void __bt_hdp_internal_handle_disconnect_cb(int sk, const char *path) hdp_obj_info_t *info; bt_user_info_t *user_info; - BT_DBG("******** Socket Error ******\n"); + BT_INFO("******** Socket Error ******\n"); info = __bt_hdp_internal_gslist_obj_find_using_path(path); ret_if(info == NULL); @@ -678,7 +711,7 @@ static void __bt_hdp_internal_handle_disconnect_cb(int sk, const char *path) user_info = _bt_get_user_data(BT_COMMON); - if (user_info) { + if (user_info->cb) { _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED, BLUETOOTH_ERROR_NONE, &dis_ind, user_info->cb, user_info->user_data); @@ -714,7 +747,7 @@ static gboolean __bt_hdp_internal_data_received(GIOChannel *gio, if (act_read > 0) { BT_DBG("Received data of %d\n", act_read); } else { - BT_DBG("Read failed.....\n"); + BT_ERR("Read failed.....\n"); return FALSE; } @@ -724,7 +757,7 @@ static gboolean __bt_hdp_internal_data_received(GIOChannel *gio, user_info = _bt_get_user_data(BT_COMMON); - if (user_info) { + if (user_info->cb) { _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DATA_RECEIVED, BLUETOOTH_ERROR_NONE, &data_ind, user_info->cb, user_info->user_data); @@ -829,7 +862,7 @@ static gboolean __bt_hdp_internal_destroy_application_cb(gpointer data) list = __bt_hdp_internal_gslist_find_app_handler((void *)app_handle); if (NULL == list) { - BT_DBG("**** list not found for %s ******\n", app_handle); + BT_ERR("**** list not found for %s ******\n", app_handle); return FALSE; } @@ -853,6 +886,7 @@ static int __bt_hdp_internal_destroy_application(const char *app_handle) DBusMessage *reply; DBusError err; DBusConnection *conn; + int result = BLUETOOTH_ERROR_NONE; conn = _bt_get_system_conn(); retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); @@ -875,10 +909,16 @@ static int __bt_hdp_internal_destroy_application(const char *app_handle) if (dbus_error_is_set(&err)) { BT_ERR("%s", err.message); + + if (g_strrstr(err.message, BT_ACCESS_DENIED_MSG)) + result = BLUETOOTH_ERROR_ACCESS_DENIED; + else + result = BLUETOOTH_ERROR_INTERNAL; + dbus_error_free(&err); } - return BLUETOOTH_ERROR_INTERNAL; + return result ; } dbus_message_unref(reply); @@ -911,23 +951,48 @@ BT_EXPORT_API int bluetooth_hdp_send_data(unsigned int channel_id, { int wbytes = 0; int written = 0; + int result; BT_DBG("+"); BT_CHECK_ENABLED(return); if ((channel_id == 0) || (NULL == buffer) || (size == 0)) { - BT_DBG("Invalid arguments..\n"); + BT_ERR("Invalid arguments..\n"); return BLUETOOTH_ERROR_INVALID_PARAM; - } else { - while (wbytes < size) { - written = write(channel_id, buffer + wbytes, size - wbytes); - if (written <= 0) { - BT_DBG("write failed..\n"); - return BLUETOOTH_ERROR_NOT_IN_OPERATION; - } - wbytes += written; + } + + switch (privilege_token) { + case 0: + result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_HDP_SEND_DATA); + + if (result == BLUETOOTH_ERROR_NONE) { + privilege_token = 1; /* Have a permission */ + } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + privilege_token = -1; /* Don't have a permission */ + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } else { + /* Just break - It is not related with permission error */ } + break; + case 1: + /* Already have a privilege */ + break; + case -1: + return BLUETOOTH_ERROR_PERMISSION_DEINED; + default: + /* Invalid privilge token value */ + return BLUETOOTH_ERROR_INTERNAL; + } + + while (wbytes < size) { + written = write(channel_id, buffer + wbytes, size - wbytes); + if (written <= 0) { + BT_ERR("write failed..\n"); + return BLUETOOTH_ERROR_NOT_IN_OPERATION; + } + wbytes += written; } return BLUETOOTH_ERROR_NONE; @@ -953,13 +1018,20 @@ static void __bt_hdp_connect_request_cb(DBusGProxy *hdp_proxy, DBusGProxyCall *c user_info = _bt_get_user_data(BT_COMMON); - if (user_info) { + if (user_info->cb) { _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED, BLUETOOTH_ERROR_CONNECTION_ERROR, conn_ind, user_info->cb, user_info->user_data); } } else { BT_DBG("Obj Path returned = %s\n", obj_connect_path); + user_info = _bt_get_user_data(BT_COMMON); + + if (user_info->cb) { + _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED, + BLUETOOTH_ERROR_NONE, conn_ind, + user_info->cb, user_info->user_data); + } g_free(obj_connect_path); } g_free((void *)conn_ind->app_handle); @@ -986,6 +1058,12 @@ BT_EXPORT_API int bluetooth_hdp_connect(const char *app_handle, BT_CHECK_PARAMETER(app_handle, return); BT_CHECK_PARAMETER(device_address, return); + if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_HDP_CONNECT) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } + if (channel_type == HDP_QOS_RELIABLE) { role = "Reliable"; } else if (channel_type == HDP_QOS_STREAMING) { @@ -1000,13 +1078,14 @@ BT_EXPORT_API int bluetooth_hdp_connect(const char *app_handle, conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &err); if (err != NULL) { - BT_DBG("ERROR: Can't get on system bus [%s]", err->message); + BT_ERR("ERROR: Can't get on system bus [%s]", err->message); g_error_free(err); return BLUETOOTH_ERROR_INTERNAL; } /* If the adapter path is wrong, we can think the BT is not enabled. */ - if (_bt_get_adapter_path(conn, default_adapter_path) < 0) { + if (_bt_get_adapter_path(_bt_gdbus_get_system_gconn(), + default_adapter_path) < 0) { BT_ERR("Could not get adapter path\n"); dbus_g_connection_unref(conn); return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; @@ -1033,7 +1112,7 @@ BT_EXPORT_API int bluetooth_hdp_connect(const char *app_handle, dbus_g_connection_unref(conn); if (hdp_proxy == NULL) { - BT_DBG("Failed to get the HDP server proxy\n"); + BT_ERR("Failed to get the HDP server proxy\n"); g_free(dev_path); return BLUETOOTH_ERROR_NOT_PAIRED; } @@ -1075,19 +1154,28 @@ static void __bt_hdp_disconnect_request_cb(DBusGProxy *hdp_proxy, DBusGProxyCall g_object_unref(hdp_proxy); + user_info = _bt_get_user_data(BT_COMMON); + if (user_info == NULL || user_info->cb == NULL) { + g_free(disconn_ind); + if (g_error) + g_error_free(g_error); + return; + } + if (g_error != NULL) { BT_ERR("HDP disconnection Dbus Call Error: %s\n", g_error->message); g_error_free(g_error); - user_info = _bt_get_user_data(BT_COMMON); - - if (user_info) { + _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED, + BLUETOOTH_ERROR_CONNECTION_ERROR, disconn_ind, + user_info->cb, user_info->user_data); + } else { + if (user_info->cb) { _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED, - BLUETOOTH_ERROR_CONNECTION_ERROR, disconn_ind, + BLUETOOTH_ERROR_NONE, disconn_ind, user_info->cb, user_info->user_data); } - } else { - BT_DBG("HDP disconnection Dbus Call is done\n"); + BT_INFO("HDP disconnection Dbus Call is done\n"); } g_free(disconn_ind); @@ -1109,6 +1197,12 @@ BT_EXPORT_API int bluetooth_hdp_disconnect(unsigned int channel_id, BT_CHECK_ENABLED(return); BT_CHECK_PARAMETER(device_address, return); + if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_HDP_DISCONNECT) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } + hdp_obj_info_t *info = __bt_hdp_internal_gslist_obj_find_using_fd(channel_id); if (NULL == info) { BT_ERR("*** Could not locate the list for %d*****\n", channel_id); @@ -1124,7 +1218,8 @@ BT_EXPORT_API int bluetooth_hdp_disconnect(unsigned int channel_id, } /* If the adapter path is wrong, we can think the BT is not enabled. */ - if (_bt_get_adapter_path(conn, default_adapter_path) < 0) { + if (_bt_get_adapter_path(_bt_gdbus_get_system_gconn(), + default_adapter_path) < 0) { BT_ERR("Could not get adapter path\n"); dbus_g_connection_unref(conn); return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; diff --git a/bt-api/bt-hid.c b/bt-api/bt-hid.c old mode 100644 new mode 100755 index 20fe85c..b03143b --- a/bt-api/bt-hid.c +++ b/bt-api/bt-hid.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -67,11 +71,17 @@ BT_EXPORT_API int bluetooth_hid_connect(hid_device_address_t *device_address) BT_CHECK_PARAMETER(device_address, return); BT_CHECK_ENABLED(return); - BT_INIT_PARAMS(); - BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_CONNECT) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } user_info = _bt_get_user_data(BT_HID); - retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); g_array_append_vals(in_param1, device_address, sizeof(bluetooth_device_address_t)); @@ -92,11 +102,17 @@ BT_EXPORT_API int bluetooth_hid_disconnect(hid_device_address_t *device_address) BT_CHECK_PARAMETER(device_address, return); BT_CHECK_ENABLED(return); - BT_INIT_PARAMS(); - BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_HID_DISCONNECT) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } user_info = _bt_get_user_data(BT_HID); - retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); g_array_append_vals(in_param1, device_address, sizeof(bluetooth_device_address_t)); diff --git a/bt-api/bt-mdm.c b/bt-api/bt-mdm.c new file mode 100755 index 0000000..6c5584b --- /dev/null +++ b/bt-api/bt-mdm.c @@ -0,0 +1,354 @@ +/* + * Bluetooth-frwk + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * 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. + * + */ + +#ifdef TIZEN_MDM_ENABLE +#include +#include "bt-internal-types.h" +#include "bt-common.h" +#include "bt-mdm.h" + +int _bt_launch_mdm_popup(char *mode) +{ + int ret = 0; + bundle *b; + + b = bundle_create(); + retv_if(b == NULL, BLUETOOTH_ERROR_INTERNAL); + + bundle_add(b, "mode", mode); + + ret = syspopup_launch(BT_MDM_SYSPOPUP, b); + + if (ret < 0) + BT_ERR("Popup launch failed: %d\n", ret); + + bundle_free(b); + + return ret; +} + +bt_mdm_status_e _bt_check_mdm_handsfree_only(void) +{ + mdm_bt_allow_t mode; + + if (mdm_get_service() != MDM_RESULT_SUCCESS) return BT_MDM_NO_SERVICE; + + mode = mdm_get_allow_bluetooth_mode(); + mdm_release_service(); + + return (mode == MDM_BT_HANDSFREE_ONLY ? BT_MDM_RESTRICTED : BT_MDM_ALLOWED); +} + +#ifdef MDM_PHASE_2 +bt_mdm_status_e _bt_check_mdm_pairing_restriction(void) +{ + bt_mdm_status_e mdm_status = BT_MDM_ALLOWED; + + if (mdm_get_service() != MDM_RESULT_SUCCESS) + return BT_MDM_NO_SERVICE; + + if (mdm_get_bluetooth_pairing_state() == MDM_RESTRICTED) { + /* Not allow to visible on */ + BT_ERR("Pairing Restricted"); + mdm_status = BT_MDM_RESTRICTED; + } + mdm_release_service(); + + return mdm_status; +} + +bt_mdm_status_e _bt_check_mdm_transfer_restriction(void) +{ + bt_mdm_status_e mdm_status = BT_MDM_ALLOWED; + + mdm_status = _bt_check_mdm_blacklist_uuid(BT_OPP_UUID); + + if (mdm_status == BT_MDM_NO_SERVICE || mdm_status == BT_MDM_RESTRICTED) { + return mdm_status; + } + + if (mdm_get_service() != MDM_RESULT_SUCCESS) return BT_MDM_NO_SERVICE; + + if (mdm_get_bluetooth_data_transfer_state() == MDM_RESTRICTED || + mdm_get_allow_bluetooth_mode() == MDM_BT_HANDSFREE_ONLY) { + /* Not allow to visible on */ + BT_ERR("Restricted to set visible mode"); + mdm_status = BT_MDM_RESTRICTED; + } + mdm_release_service(); + + return mdm_status; +} + +bt_mdm_status_e _bt_check_mdm_hsp_restriction(void) +{ + bt_mdm_status_e mdm_status = BT_MDM_ALLOWED; + + mdm_status = _bt_check_mdm_blacklist_uuid(BT_HFP_AUDIO_GATEWAY_UUID); + + if (mdm_status == BT_MDM_NO_SERVICE || mdm_status == BT_MDM_RESTRICTED) { + return mdm_status; + } + + if (mdm_get_service() != MDM_RESULT_SUCCESS) return BT_MDM_NO_SERVICE; + + if (mdm_get_bluetooth_profile_state(BLUETOOTH_HSP_PROFILE) == MDM_RESTRICTED || + mdm_get_bluetooth_profile_state(BLUETOOTH_HFP_PROFILE) == MDM_RESTRICTED) { + /* Not allow to visible on */ + BT_ERR("Restrict hsp / hfp profile"); + mdm_status = BT_MDM_RESTRICTED; + } + mdm_release_service(); + + return mdm_status; +} + +bt_mdm_status_e _bt_check_mdm_a2dp_restriction(void) +{ + bt_mdm_status_e mdm_status = BT_MDM_ALLOWED; + + mdm_status = _bt_check_mdm_blacklist_uuid(BT_A2DP_UUID); + + if (mdm_status == BT_MDM_NO_SERVICE || mdm_status == BT_MDM_RESTRICTED) { + return mdm_status; + } + + if (mdm_get_service() != MDM_RESULT_SUCCESS) return BT_MDM_NO_SERVICE; + + if (mdm_get_bluetooth_profile_state(BLUETOOTH_A2DP_PROFILE) == MDM_RESTRICTED) { + /* Not allow to visible on */ + BT_ERR("Restrict a2dp profile"); + mdm_status = BT_MDM_RESTRICTED; + } + mdm_release_service(); + + return mdm_status; +} + +bt_mdm_status_e _bt_check_mdm_avrcp_restriction(void) +{ + bt_mdm_status_e mdm_status = BT_MDM_ALLOWED; + + + mdm_status = _bt_check_mdm_blacklist_uuid(BT_AVRCP_TARGET_UUID); + + if (mdm_status == BT_MDM_NO_SERVICE || mdm_status == BT_MDM_RESTRICTED) { + return mdm_status; + } + + if (mdm_get_service() != MDM_RESULT_SUCCESS) return BT_MDM_NO_SERVICE; + + if (mdm_get_bluetooth_profile_state(BLUETOOTH_AVRCP_PROFILE) == MDM_RESTRICTED) { + /* Not allow to visible on */ + BT_ERR("Restrict avrcp profile"); + mdm_status = BT_MDM_RESTRICTED; + } + mdm_release_service(); + + return mdm_status; +} + +bt_mdm_status_e _bt_check_mdm_spp_restriction(void) +{ + bt_mdm_status_e mdm_status = BT_MDM_ALLOWED; + + mdm_status = _bt_check_mdm_blacklist_uuid(BT_SPP_UUID); + + if (mdm_status == BT_MDM_NO_SERVICE || mdm_status == BT_MDM_RESTRICTED) { + return mdm_status; + } + + if (mdm_get_service() != MDM_RESULT_SUCCESS) return BT_MDM_NO_SERVICE; + + if (mdm_get_bluetooth_profile_state(BLUETOOTH_SPP_PROFILE) == MDM_RESTRICTED) { + /* Not allow to visible on */ + BT_ERR("Restrict spp profile"); + mdm_status = BT_MDM_RESTRICTED; + } + mdm_release_service(); + + return mdm_status; +} + +bt_mdm_status_e _bt_check_mdm_whitelist_devices(const bluetooth_device_address_t *address) +{ + mdm_data_t *lp_data = NULL; + GList *whitelist = NULL; + char *device_name; + bluetooth_device_info_t dev_info; + bt_mdm_status_e mdm_status = BT_MDM_ALLOWED; + + if (mdm_get_service() != MDM_RESULT_SUCCESS) return BT_MDM_NO_SERVICE; + + memset(&dev_info, 0x00, sizeof(bluetooth_device_info_t)); + + if (bluetooth_get_bonded_device(address, + &dev_info) != BLUETOOTH_ERROR_NONE) { + BT_ERR("Not paired device"); + return mdm_status; + } + + lp_data = mdm_get_bluetooth_devices_from_whitelist(); + if (lp_data == NULL) { + BT_ERR("No whitelist"); + mdm_release_service(); + return mdm_status; + } + + for (whitelist = (GList *)lp_data->data; whitelist; whitelist = whitelist->next) { + device_name = whitelist->data; + + DBG_SECURE("whitelist device name: %s", device_name); + + if (g_strcmp0(dev_info.device_name.name, + device_name) == 0) { + mdm_status = BT_MDM_RESTRICTED; + break; + } + } + + mdm_free_data(lp_data); + mdm_release_service(); + + return mdm_status; +} + +bt_mdm_status_e _bt_check_mdm_whitelist_uuid(char *uuid) +{ + mdm_data_t *lp_data; + GList *blacklist; + char *blacklist_uuid; + bt_mdm_status_e mdm_status = BT_MDM_ALLOWED; + + if (mdm_get_service() != MDM_RESULT_SUCCESS) + return BT_MDM_NO_SERVICE; + + if (uuid == NULL) + return mdm_status; + + lp_data = mdm_get_bluetooth_uuids_from_blacklist(); + if (lp_data == NULL) { + BT_ERR("No blacklist"); + mdm_release_service(); + return mdm_status; + } + + for (blacklist = (GList *)lp_data->data; blacklist; blacklist = blacklist->next) { + blacklist_uuid = blacklist->data; + + BT_DBG("blacklist_uuid: %s", blacklist_uuid); + + if (g_strcmp0(blacklist_uuid, uuid) == 0) { + mdm_status = BT_MDM_RESTRICTED; + break; + } + } + + mdm_free_data(lp_data); + mdm_release_service(); + + return mdm_status; +} + +bt_mdm_status_e _bt_check_mdm_blacklist_devices(const bluetooth_device_address_t *address) +{ + mdm_data_t *lp_data; + GList *blacklist; + char *device_name; + bluetooth_device_info_t dev_info; + bt_mdm_status_e mdm_status = BT_MDM_ALLOWED; + + if (mdm_get_service() != MDM_RESULT_SUCCESS) return BT_MDM_NO_SERVICE; + + memset(&dev_info, 0x00, sizeof(bluetooth_device_info_t)); + + if (bluetooth_get_bonded_device(address, + &dev_info) != BLUETOOTH_ERROR_NONE) { + BT_ERR("Not paired device"); + return mdm_status; + } + + lp_data = mdm_get_bluetooth_devices_from_blacklist(); + if (lp_data == NULL) { + BT_ERR("No blacklist"); + mdm_release_service(); + return mdm_status; + } + + for (blacklist = (GList *)lp_data->data; blacklist; blacklist = blacklist->next) { + device_name = blacklist->data; + + DBG_SECURE("blacklist name: %s", device_name); + + if (g_strcmp0(dev_info.device_name.name, + device_name) == 0) { + mdm_status = BT_MDM_RESTRICTED; + break; + } + } + + mdm_free_data(lp_data); + mdm_release_service(); + + return mdm_status; +} + +bt_mdm_status_e _bt_check_mdm_blacklist_uuid(char *uuid) +{ + mdm_data_t *lp_data; + GList *blacklist; + char *blacklist_uuid; + bt_mdm_status_e mdm_status = BT_MDM_ALLOWED; + + if (mdm_get_service() != MDM_RESULT_SUCCESS) + return BT_MDM_NO_SERVICE; + + if (uuid == NULL) + return mdm_status; + + lp_data = mdm_get_bluetooth_uuids_from_blacklist(); + if (lp_data == NULL) { + BT_ERR("No blacklist"); + mdm_release_service(); + return mdm_status; + } + + for (blacklist = (GList *)lp_data->data; blacklist; blacklist = blacklist->next) { + blacklist_uuid = blacklist->data; + + BT_DBG("blacklist_uuid: %s", blacklist_uuid); + + if (g_strcmp0(blacklist_uuid, uuid) == 0) { + mdm_status = BT_MDM_RESTRICTED; + break; + } + } + + mdm_free_data(lp_data); + mdm_release_service(); + + return mdm_status; +} +#endif +#endif + diff --git a/bt-api/bt-network.c b/bt-api/bt-network.c old mode 100644 new mode 100755 index c7c5b5a..987b45d --- a/bt-api/bt-network.c +++ b/bt-api/bt-network.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -68,11 +72,17 @@ BT_EXPORT_API int bluetooth_network_connect(const bluetooth_device_address_t *de BT_CHECK_PARAMETER(device_address, return); BT_CHECK_ENABLED(return); - BT_INIT_PARAMS(); - BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_NETWORK_CONNECT) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } user_info = _bt_get_user_data(BT_COMMON); - retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); g_array_append_vals(in_param1, device_address, sizeof(bluetooth_device_address_t)); @@ -95,11 +105,17 @@ BT_EXPORT_API int bluetooth_network_disconnect(const bluetooth_device_address_t BT_CHECK_PARAMETER(device_address, return); BT_CHECK_ENABLED(return); - BT_INIT_PARAMS(); - BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_NETWORK_DISCONNECT) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } user_info = _bt_get_user_data(BT_COMMON); - retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); g_array_append_vals(in_param1, device_address, sizeof(bluetooth_device_address_t)); @@ -113,3 +129,36 @@ BT_EXPORT_API int bluetooth_network_disconnect(const bluetooth_device_address_t return result; } +BT_EXPORT_API int bluetooth_network_server_disconnect(const bluetooth_device_address_t *device_address) +{ + int result; + bt_user_info_t *user_info; + + BT_CHECK_PARAMETER(device_address, return); + BT_CHECK_ENABLED(return); + + if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_NETWORK_SERVER_DISCONNECT) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } + + user_info = _bt_get_user_data(BT_COMMON); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, device_address, + sizeof(bluetooth_device_address_t)); + + result = _bt_send_request_async(BT_BLUEZ_SERVICE, + BT_NETWORK_SERVER_DISCONNECT, + in_param1, in_param2, in_param3, in_param4, + user_info->cb, user_info->user_data); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + diff --git a/bt-api/bt-obex-server.c b/bt-api/bt-obex-server.c old mode 100644 new mode 100755 index 09088f9..b4b6513 --- a/bt-api/bt-obex-server.c +++ b/bt-api/bt-obex-server.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -40,7 +44,7 @@ BT_EXPORT_API int bluetooth_obex_server_init(const char *dst_path) return BLUETOOTH_ERROR_AGENT_ALREADY_EXIST; user_info = _bt_get_user_data(BT_COMMON); - retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); BT_INIT_PARAMS(); BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); @@ -112,7 +116,7 @@ BT_EXPORT_API int bluetooth_obex_server_init_without_agent(const char *dst_path) return BLUETOOTH_ERROR_AGENT_ALREADY_EXIST; user_info = _bt_get_user_data(BT_COMMON); - retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); BT_INIT_PARAMS(); BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); diff --git a/bt-api/bt-oob.c b/bt-api/bt-oob.c old mode 100644 new mode 100755 index d2145c4..9f618c7 --- a/bt-api/bt-oob.c +++ b/bt-api/bt-oob.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, diff --git a/bt-api/bt-opp-client.c b/bt-api/bt-opp-client.c old mode 100644 new mode 100755 index e6e980a..6b91b22 --- a/bt-api/bt-opp-client.c +++ b/bt-api/bt-opp-client.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -26,7 +30,6 @@ #include "bt-request-sender.h" #include "bt-event-handler.h" - static void __bt_get_file_size(char **files, unsigned long *file_size, int *count) { int file_count = 0; @@ -46,7 +49,7 @@ BT_EXPORT_API int bluetooth_opc_init(void) bt_user_info_t *user_info; user_info = _bt_get_user_data(BT_COMMON); - retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); return _bt_register_event(BT_OPP_CLIENT_EVENT, user_info->cb, user_info->user_data); } @@ -70,18 +73,30 @@ BT_EXPORT_API int bluetooth_opc_push_files(bluetooth_device_address_t *remote_ad BT_CHECK_PARAMETER(file_name_array, return); BT_CHECK_ENABLED(return); + if (_bt_check_privilege(BT_CHECK_PRIVILEGE, BT_OPP_PUSH_FILES) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } + __bt_get_file_size(file_name_array, &size, &file_count); retv_if(file_count == 0, BLUETOOTH_ERROR_INVALID_PARAM); + user_info = _bt_get_user_data(BT_COMMON); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + BT_INIT_PARAMS(); BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); - user_info = _bt_get_user_data(BT_COMMON); - retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); - g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t)); for (i = 0; i < file_count; i++) { + if (strlen(file_name_array[i]) >= sizeof(filename)) { + BT_ERR("[%s] has too long path.", file_name_array[i]); + BT_FREE_PARAMS(in_param1, in_param2, in_param3, + in_param4, out_param); + return BLUETOOTH_ERROR_INVALID_PARAM; + } g_strlcpy(filename, file_name_array[i], sizeof(filename)); g_array_append_vals(in_param2, filename, BT_FILE_PATH_MAX); } @@ -129,6 +144,7 @@ BT_EXPORT_API gboolean bluetooth_opc_session_is_exist(void) if (result == BLUETOOTH_ERROR_NONE) { exist = g_array_index(out_param, gboolean, 0); + BT_DBG("Exist %d", exist); } else { BT_ERR("Fail to send request"); } diff --git a/bt-api/bt-pbap.c b/bt-api/bt-pbap.c new file mode 100755 index 0000000..031440c --- /dev/null +++ b/bt-api/bt-pbap.c @@ -0,0 +1,244 @@ +/* + * Bluetooth-frwk + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * 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 +#include + +#include "bluetooth-api.h" +#include "bt-internal-types.h" + +#include "bt-common.h" +#include "bt-request-sender.h" +#include "bt-event-handler.h" + +static char is_pbap_initialized = FALSE; + +#define BT_CHECK_PBAP_INITIALIZED(func) \ + if (is_pbap_initialized == FALSE) \ + { \ + BT_ERR("BT PBAP Client is not initiatized"); \ + func BLUETOOTH_ERROR_NOT_INITIALIZED; \ + } \ + + +BT_EXPORT_API int bluetooth_pbap_init(void) +{ + bt_user_info_t *user_info; + int ret; + + BT_CHECK_ENABLED(return); + if (is_pbap_initialized) + return BLUETOOTH_ERROR_ALREADY_INITIALIZED; + + user_info = _bt_get_user_data(BT_COMMON); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); + + ret = _bt_register_event(BT_PBAP_CLIENT_EVENT, user_info->cb, + user_info->user_data); + if (ret == 0) + is_pbap_initialized = TRUE; + + return ret; +} + +BT_EXPORT_API int bluetooth_pbap_deinit(void) +{ + int ret; + BT_CHECK_ENABLED(return); + BT_CHECK_PBAP_INITIALIZED(return); + + ret = _bt_unregister_event(BT_PBAP_CLIENT_EVENT); + + if (ret == 0) + is_pbap_initialized = FALSE; + + return ret; +} + +BT_EXPORT_API int bluetooth_pbap_connect(const bluetooth_device_address_t *address) +{ + BT_DBG("+"); + int result; + + BT_CHECK_ENABLED(return); + BT_CHECK_PBAP_INITIALIZED(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, address, + sizeof(bluetooth_device_address_t)); + result = _bt_send_request(BT_OBEX_SERVICE, BT_PBAP_CONNECT, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + BT_DBG("-"); + return result; +} + +BT_EXPORT_API int bluetooth_pbap_disconnect(const bluetooth_device_address_t *address) +{ + BT_DBG("+"); + int result; + + BT_CHECK_ENABLED(return); + BT_CHECK_PBAP_INITIALIZED(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, address, + sizeof(bluetooth_device_address_t)); + result = _bt_send_request(BT_OBEX_SERVICE, BT_PBAP_DISCONNECT, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + BT_DBG("-"); + return result; +} + +BT_EXPORT_API int bluetooth_pbap_get_phonebook_size(const bluetooth_device_address_t *address, + bt_pbap_folder_t *folder) +{ + BT_DBG("+"); + int result; + + BT_CHECK_ENABLED(return); + BT_CHECK_PBAP_INITIALIZED(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t)); + + g_array_append_vals(in_param2, folder, sizeof(bt_pbap_folder_t)); + + result = _bt_send_request(BT_OBEX_SERVICE, BT_PBAP_GET_PHONEBOOK_SIZE, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + BT_DBG("-"); + return result; +} + +BT_EXPORT_API int bluetooth_pbap_get_phonebook(const bluetooth_device_address_t *address, + bt_pbap_folder_t *folder, bt_pbap_pull_parameters_t *app_param) +{ + BT_DBG("+"); + int result; + + BT_CHECK_ENABLED(return); + BT_CHECK_PBAP_INITIALIZED(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, address, + sizeof(bluetooth_device_address_t)); + g_array_append_vals(in_param2, folder, sizeof(bt_pbap_folder_t)); + g_array_append_vals(in_param3, app_param, sizeof(bt_pbap_pull_parameters_t)); + result = _bt_send_request(BT_OBEX_SERVICE, BT_PBAP_GET_PHONEBOOK, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + BT_DBG("-"); + return result; +} + +BT_EXPORT_API int bluetooth_pbap_get_list(const bluetooth_device_address_t *address, + bt_pbap_folder_t *folder, bt_pbap_list_parameters_t *app_param) +{ + BT_DBG("+"); + int result; + + BT_CHECK_ENABLED(return); + BT_CHECK_PBAP_INITIALIZED(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, address, + sizeof(bluetooth_device_address_t)); + g_array_append_vals(in_param2, folder, sizeof(bt_pbap_folder_t)); + g_array_append_vals(in_param3, app_param, sizeof(bt_pbap_list_parameters_t)); + + result = _bt_send_request(BT_OBEX_SERVICE, BT_PBAP_GET_LIST, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + BT_DBG("-"); + return result; +} + +BT_EXPORT_API int bluetooth_pbap_pull_vcard(const bluetooth_device_address_t *address, + bt_pbap_folder_t *folder, bt_pbap_pull_vcard_parameters_t *app_param) +{ + BT_DBG("+"); + int result; + + BT_CHECK_ENABLED(return); + BT_CHECK_PBAP_INITIALIZED(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t)); + g_array_append_vals(in_param2, folder, sizeof(bt_pbap_folder_t)); + g_array_append_vals(in_param3, app_param, sizeof(bt_pbap_pull_vcard_parameters_t)); + + result = _bt_send_request(BT_OBEX_SERVICE, BT_PBAP_PULL_VCARD, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + BT_DBG("-"); + return result; +} + +BT_EXPORT_API int bluetooth_pbap_phonebook_search(const bluetooth_device_address_t *address, + bt_pbap_folder_t *folder, bt_pbap_search_parameters_t *app_param) +{ + BT_DBG("+"); + int result; + BT_CHECK_ENABLED(return); + BT_CHECK_PBAP_INITIALIZED(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, address, sizeof(bluetooth_device_address_t)); + g_array_append_vals(in_param2, folder, sizeof(bt_pbap_folder_t)); + g_array_append_vals(in_param3, app_param, sizeof(bt_pbap_search_parameters_t)); + + result = _bt_send_request(BT_OBEX_SERVICE, BT_PBAP_PHONEBOOK_SEARCH, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + BT_DBG("-"); + return result; +} diff --git a/bt-api/bt-request-sender.c b/bt-api/bt-request-sender.c old mode 100644 new mode 100755 index 2438cb3..1352b05 --- a/bt-api/bt-request-sender.c +++ b/bt-api/bt-request-sender.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -30,6 +34,7 @@ #include "bt-common.h" #include "bt-request-sender.h" #include "bt-event-handler.h" +#include "bluetooth-media-control.h" /* auto generated header by bt-request-service.xml*/ #include "bt-request-service.h" @@ -40,79 +45,76 @@ DBusGConnection *service_conn; DBusGConnection *system_conn; DBusGProxy *service_proxy; -static void __bt_remove_all_sending_requests(void) -{ - GSList *l; - bt_req_info_t *info; - - for (l = sending_requests; l != NULL; l = g_slist_next(l)) { - info = l->data; - - if (info && info->proxy && info->proxy_call) - dbus_g_proxy_cancel_call(info->proxy, info->proxy_call); - } - - g_slist_free(sending_requests); - sending_requests = NULL; -} +static GDBusConnection *service_gconn; +static GDBusProxy *service_gproxy; -DBusGProxy *_bt_init_service_proxy(void) +static GDBusProxy *__bt_gdbus_init_service_proxy(void) { - DBusGProxy *proxy; + GDBusProxy *proxy; + GError *err = NULL; g_type_init(); - if (service_conn == NULL) { - service_conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL); - retv_if(service_conn == NULL, NULL); + if (service_gconn == NULL) + service_gconn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err); + + if (!service_gconn) { + if (err) { + BT_ERR("Unable to connect to dbus: %s", err->message); + g_clear_error(&err); + } + return NULL; } - proxy = dbus_g_proxy_new_for_name(service_conn, BT_DBUS_NAME, BT_SERVICE_PATH, - BT_DBUS_NAME); + proxy = g_dbus_proxy_new_sync(service_gconn, + G_DBUS_PROXY_FLAGS_NONE, NULL, + BT_DBUS_NAME, + BT_SERVICE_PATH, + BT_DBUS_NAME, + NULL, &err); + if (!proxy) { + if (err) { + BT_ERR("Unable to create proxy: %s", err->message); + g_clear_error(&err); + } - if (proxy == NULL) { - dbus_g_connection_unref(service_conn); - service_conn = NULL; + g_object_unref(service_gconn); + service_gconn = NULL; return NULL; } - service_proxy = proxy; + service_gproxy = proxy; return proxy; } -void _bt_deinit_proxys(void) +static GDBusProxy *__bt_gdbus_get_service_proxy(void) { - __bt_remove_all_sending_requests(); + return (service_gproxy) ? service_gproxy : __bt_gdbus_init_service_proxy(); +} - if (service_proxy) { +void _bt_gdbus_deinit_proxys(void) +{ + if (service_gproxy) { g_object_unref(service_proxy); service_proxy = NULL; } - if (service_conn) { - dbus_g_connection_unref(service_conn); - service_conn = NULL; - } - - if (system_conn) { - dbus_g_connection_unref(system_conn); - system_conn = NULL; + if (service_gconn) { + g_object_unref(service_gconn); + service_gconn = NULL; } } -static DBusGProxy *__bt_get_service_proxy(void) -{ - return (service_proxy) ? service_proxy : _bt_init_service_proxy(); -} - static void __bt_get_event_info(int service_function, GArray *output, int *event, int *event_type, void **param_data) { ret_if(event == NULL); + BT_DBG("service_function : %x", service_function); switch (service_function) { case BT_BOND_DEVICE: + case BT_BOND_DEVICE_BY_TYPE: *event_type = BT_ADAPTER_EVENT; *event = BLUETOOTH_EVENT_BONDING_FINISHED; ret_if(output == NULL); @@ -173,6 +175,18 @@ static void __bt_get_event_info(int service_function, GArray *output, ret_if(output == NULL); *param_data = &g_array_index(output, char, 0); break; + case BT_HF_CONNECT: + *event_type = BT_HF_AGENT_EVENT; + *event = BLUETOOTH_EVENT_HF_CONNECTED; + ret_if(output == NULL); + *param_data = &g_array_index(output, char, 0); + break; + case BT_HF_DISCONNECT: + *event_type = BT_HF_AGENT_EVENT; + *event = BLUETOOTH_EVENT_HF_DISCONNECTED; + ret_if(output == NULL); + *param_data = &g_array_index(output, char, 0); + break; case BT_NETWORK_CONNECT: *event_type = BT_ADAPTER_EVENT; *event = BLUETOOTH_EVENT_NETWORK_CONNECTED; @@ -193,7 +207,18 @@ static void __bt_get_event_info(int service_function, GArray *output, ret_if(output == NULL); *param_data = &g_array_index(output, bluetooth_rfcomm_connection_t, 0); - + break; + case BT_AVRCP_CONTROL_CONNECT: + *event_type = BT_AVRCP_CONTROL_EVENT; + *event = BLUETOOTH_EVENT_AVRCP_CONTROL_CONNECTED; + ret_if(output == NULL); + *param_data = &g_array_index(output, char, 0); + break; + case BT_AVRCP_CONTROL_DISCONNECT: + *event_type = BT_AVRCP_CONTROL_EVENT; + *event = BLUETOOTH_EVENT_AVRCP_CONTROL_DISCONNECTED; + ret_if(output == NULL); + *param_data = &g_array_index(output, char, 0); break; default: BT_ERR("Unknown function"); @@ -206,22 +231,47 @@ out param1: API result out param2: return paramter out param3: */ -void __send_request_cb(DBusGProxy *proxy, GArray *out_param1, - GArray *out_param2, GError *error, - gpointer userdata) +static void __bt_fill_garray_from_variant(GVariant *var, GArray *param) +{ + char *data; + int size; + + size = g_variant_get_size(var); + if (size > 0) { + data = (char *)g_variant_get_data(var); + if (data) + param = g_array_append_vals(param, data, size); + + } +} + +static void __send_request_cb(GDBusProxy *proxy, + GAsyncResult *res, + gpointer user_data) { bluetooth_event_param_t bt_event; - bt_req_info_t *cb_data = userdata; + bt_req_info_t *cb_data = user_data; int result = BLUETOOTH_ERROR_NONE; int event_type = BT_ADAPTER_EVENT; int request_id; + GError *error = NULL; + GVariant *value; + GVariant *param1; + GVariant *param2; + GArray *out_param1 = NULL; + GArray *out_param2 = NULL; + BT_DBG("+"); memset(&bt_event, 0x00, sizeof(bluetooth_event_param_t)); - if (error != NULL) { - /* dBUS gives error cause */ - BT_ERR("D-Bus API failure: message[%s]", error->message); - g_error_free(error); + value = g_dbus_proxy_call_finish(proxy, res, &error); + if (value == NULL) { + if (error) { + /* dBUS gives error cause */ + BT_ERR("D-Bus API failure: message[%s]", + error->message); + g_clear_error(&error); + } result = BLUETOOTH_ERROR_TIMEOUT; ret_if(cb_data == NULL); @@ -230,9 +280,24 @@ void __send_request_cb(DBusGProxy *proxy, GArray *out_param1, &bt_event.event, &event_type, &bt_event.param_data); } else { - ret_if(out_param2 == NULL); + g_variant_get(value, "(@ay@ay)", ¶m1, ¶m2); + g_variant_unref(value); - result = g_array_index(out_param2, int, 0); + if (param1) { + out_param1 = g_array_new(TRUE, TRUE, sizeof(gchar)); + __bt_fill_garray_from_variant(param1, out_param1); + g_variant_unref(param1); + } + + if (param2) { + out_param2 = g_array_new(TRUE, TRUE, sizeof(gchar)); + __bt_fill_garray_from_variant(param2, out_param2); + result = g_array_index(out_param2, int, 0); + g_variant_unref(param2); + g_array_free(out_param2, TRUE); + } else { + result = BLUETOOTH_ERROR_INTERNAL; + } ret_if(cb_data == NULL); @@ -240,26 +305,16 @@ void __send_request_cb(DBusGProxy *proxy, GArray *out_param1, &bt_event.event, &event_type, &bt_event.param_data); - if (result == BLUETOOTH_ERROR_NONE) { + if (result == BLUETOOTH_ERROR_NONE && out_param1) { if (cb_data->service_function == BT_OPP_PUSH_FILES) { request_id = g_array_index(out_param1, int, 0); + BT_DBG("request_id : %d", request_id); _bt_add_push_request_id(request_id); } - if (out_param1) - g_array_free(out_param1, FALSE); - - if (out_param2) - g_array_free(out_param2, FALSE); - goto done; } - if (out_param1) - g_array_free(out_param1, FALSE); - - if (out_param2) - g_array_free(out_param2, FALSE); } if (cb_data->cb == NULL) @@ -267,6 +322,7 @@ void __send_request_cb(DBusGProxy *proxy, GArray *out_param1, /* Only if fail case, call the callback function*/ bt_event.result = result; + BT_INFO("event_type[%d], result=[%d]", event_type, result); if (event_type == BT_ADAPTER_EVENT || event_type == BT_RFCOMM_CLIENT_EVENT) { ((bluetooth_cb_func_ptr)cb_data->cb)(bt_event.event, @@ -280,87 +336,158 @@ void __send_request_cb(DBusGProxy *proxy, GArray *out_param1, ((bt_audio_func_ptr)cb_data->cb)(bt_event.event, (bt_audio_event_param_t *)&bt_event, cb_data->user_data); + } else if (event_type == BT_HF_AGENT_EVENT) { + ((bt_audio_func_ptr)cb_data->cb)(bt_event.event, + (bt_audio_event_param_t *)&bt_event, + cb_data->user_data); + } else if (event_type == BT_AVRCP_CONTROL_EVENT) { + ((media_cb_func_ptr)cb_data->cb)(bt_event.event, + (media_event_param_t *)&bt_event, + cb_data->user_data); + } else { + BT_INFO("Not handled event type : %d", event_type); } done: + if (out_param1) + g_array_free(out_param1, TRUE); + sending_requests = g_slist_remove(sending_requests, (void *)cb_data); g_free(cb_data); + BT_DBG("-"); } -int _bt_send_request(int service_type, int service_function, +int _bt_sync_send_request(int service_type, int service_function, GArray *in_param1, GArray *in_param2, GArray *in_param3, GArray *in_param4, GArray **out_param1) { int result = BLUETOOTH_ERROR_NONE; - gboolean ret; + char *cookie; GError *error = NULL; GArray *in_param5 = NULL; GArray *out_param2 = NULL; - DBusGProxy *proxy; + + GDBusProxy *proxy; + GVariant *ret; + GVariant *param1; + GVariant *param2; + GVariant *param3; + GVariant *param4; + GVariant *param5; switch (service_type) { case BT_BLUEZ_SERVICE: case BT_OBEX_SERVICE: - proxy = __bt_get_service_proxy(); - retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + case BT_AGENT_SERVICE: + case BT_CHECK_PRIVILEGE: + proxy = __bt_gdbus_get_service_proxy(); + if (!proxy) + return BLUETOOTH_ERROR_INTERNAL; + + in_param5 = g_array_new(TRUE, TRUE, sizeof(gchar)); - in_param5 = g_array_new(FALSE, FALSE, sizeof(gchar)); + cookie = _bt_get_cookie(); - ret = org_projectx_bt_service_request(proxy, - service_type, service_function, - BT_SYNC_REQ, in_param1, in_param2, - in_param3, in_param4, in_param5, - out_param1, &out_param2, &error); + if (cookie) { + g_array_append_vals(in_param5, cookie, + _bt_get_cookie_size()); + } + + param1 = g_variant_new_from_data((const GVariantType *)"ay", + in_param1->data, in_param1->len, + TRUE, NULL, NULL); + param2 = g_variant_new_from_data((const GVariantType *)"ay", + in_param2->data, in_param2->len, + TRUE, NULL, NULL); + param3 = g_variant_new_from_data((const GVariantType *)"ay", + in_param3->data, in_param3->len, + TRUE, NULL, NULL); + param4 = g_variant_new_from_data((const GVariantType *)"ay", + in_param4->data, in_param4->len, + TRUE, NULL, NULL); + param5 = g_variant_new_from_data((const GVariantType *)"ay", + in_param5->data, in_param5->len, + TRUE, NULL, NULL); + + ret = g_dbus_proxy_call_sync(proxy, "service_request", + g_variant_new("(iii@ay@ay@ay@ay@ay)", + service_type, service_function, + BT_SYNC_REQ, param1, + param2, param3, + param4, param5), + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, &error); g_array_free(in_param5, TRUE); - break; - default: - BT_ERR("Unknown service type"); - return BLUETOOTH_ERROR_INTERNAL; - } - if (out_param2) { - result = g_array_index(out_param2, int, 0); - g_array_free(out_param2, TRUE); - } else { - result = BLUETOOTH_ERROR_INTERNAL; - } + if (ret == NULL) { + /* dBUS-RPC is failed */ + BT_ERR("dBUS-RPC is failed"); - if (ret != TRUE) { - /* dBUS-RPC is failed */ - BT_ERR("dBUS-RPC is failed"); + if (error != NULL) { + /* dBUS gives error cause */ + BT_ERR("D-Bus API failure: errCode[%x], message[%s]", + error->code, error->message); - if (error != NULL) { - /* dBUS gives error cause */ - BT_ERR("D-Bus API failure: errCode[%x], message[%s]", - error->code, error->message); + g_clear_error(&error); + } else { + /* dBUS does not give error cause dBUS-RPC is failed */ + BT_ERR("error returned was NULL"); + } - g_error_free(error); + return BLUETOOTH_ERROR_INTERNAL; } - else { - /* dBUS does not give error cause dBUS-RPC is failed */ - BT_ERR("error returned was NULL"); + + param1 = NULL; + param2 = NULL; + + g_variant_get(ret, "(@ay@ay)", ¶m1, ¶m2); + + if (param1) { + *out_param1 = g_array_new(TRUE, TRUE, sizeof(gchar)); + __bt_fill_garray_from_variant(param1, *out_param1); + g_variant_unref(param1); } - return result; - } + if (param2) { + out_param2 = g_array_new(TRUE, TRUE, sizeof(gchar)); + __bt_fill_garray_from_variant(param2, out_param2); + result = g_array_index(out_param2, int, 0); + g_variant_unref(param2); + g_array_free(out_param2, TRUE); + } else { + result = BLUETOOTH_ERROR_INTERNAL; + } - BT_DBG("dBUS RPC is successfully done. type=%d, function=0x%x", - service_type, service_function); + g_variant_unref(ret); + break; + default: + BT_ERR("Unknown service type"); + return BLUETOOTH_ERROR_INTERNAL; + } return result; } -int _bt_send_request_async(int service_type, int service_function, +int _bt_async_send_request(int service_type, int service_function, GArray *in_param1, GArray *in_param2, GArray *in_param3, GArray *in_param4, void *callback, void *user_data) { GArray* in_param5 = NULL; bt_req_info_t *cb_data; - DBusGProxy *proxy; - DBusGProxyCall *proxy_call; + char *cookie; + + GDBusProxy *proxy; + int timeout; + GVariant *param1; + GVariant *param2; + GVariant *param3; + GVariant *param4; + GVariant *param5; + + BT_DBG("service_function : %x", service_function); cb_data = g_new0(bt_req_info_t, 1); @@ -371,36 +498,60 @@ int _bt_send_request_async(int service_type, int service_function, switch (service_type) { case BT_BLUEZ_SERVICE: case BT_OBEX_SERVICE: - proxy = __bt_get_service_proxy(); - retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - - dbus_g_proxy_set_default_timeout(proxy, BT_DBUS_TIMEOUT_MAX); + proxy = __bt_gdbus_get_service_proxy(); + if (!proxy) { + g_free(cb_data); + return BLUETOOTH_ERROR_INTERNAL; + } - in_param5 = g_array_new(FALSE, FALSE, sizeof(gchar)); + /* Do not timeout the request in certain cases. Sometime the + * request may take undeterministic time to reponse. + * (for ex: pairing retry) */ + if (service_function == BT_BOND_DEVICE || + service_function == BT_BOND_DEVICE_BY_TYPE) + timeout = INT_MAX; + else + timeout = BT_DBUS_TIMEOUT_MAX; - proxy_call = org_projectx_bt_service_request_async(proxy, service_type, - service_function, BT_ASYNC_REQ, in_param1, in_param2, - in_param3, in_param4, in_param5, - (org_projectx_bt_service_request_reply)__send_request_cb, - (gpointer)cb_data); + in_param5 = g_array_new(TRUE, TRUE, sizeof(gchar)); - if (proxy_call == NULL) { + cookie = _bt_get_cookie(); - BT_ERR("dBUS-RPC is failed"); - g_array_free(in_param5, TRUE); - g_free(cb_data); - return BLUETOOTH_ERROR_INTERNAL; + if (cookie) { + g_array_append_vals(in_param5, cookie, + _bt_get_cookie_size()); } - + param1 = g_variant_new_from_data((const GVariantType *)"ay", + in_param1->data, in_param1->len, + TRUE, NULL, NULL); + param2 = g_variant_new_from_data((const GVariantType *)"ay", + in_param2->data, in_param2->len, + TRUE, NULL, NULL); + param3 = g_variant_new_from_data((const GVariantType *)"ay", + in_param3->data, in_param3->len, + TRUE, NULL, NULL); + param4 = g_variant_new_from_data((const GVariantType *)"ay", + in_param4->data, in_param4->len, + TRUE, NULL, NULL); + param5 = g_variant_new_from_data((const GVariantType *)"ay", + in_param5->data, in_param5->len, + TRUE, NULL, NULL); + + g_dbus_proxy_call(proxy, "service_request", + g_variant_new("(iii@ay@ay@ay@ay@ay)", + service_type, service_function, + BT_ASYNC_REQ, param1, param2, + param3, param4, param5), + G_DBUS_CALL_FLAGS_NONE, + timeout, NULL, + (GAsyncReadyCallback)__send_request_cb, + (gpointer)cb_data); sending_requests = g_slist_append(sending_requests, cb_data); g_array_free(in_param5, TRUE); break; } - BT_DBG("dBUS RPC is successfully done. type=%d, function=0x%x", - service_type, service_function); - return BLUETOOTH_ERROR_NONE; } diff --git a/bt-api/bt-request-service.xml b/bt-api/bt-request-service.xml old mode 100644 new mode 100755 diff --git a/bt-api/bt-rfcomm-client.c b/bt-api/bt-rfcomm-client.c old mode 100644 new mode 100755 index e91ff6d..684ad27 --- a/bt-api/bt-rfcomm-client.c +++ b/bt-api/bt-rfcomm-client.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -18,6 +22,10 @@ */ #include +#ifdef RFCOMM_DIRECT +#include +#include +#endif #include "bluetooth-api.h" #include "bt-internal-types.h" @@ -26,28 +34,626 @@ #include "bt-request-sender.h" #include "bt-event-handler.h" -BT_EXPORT_API int bluetooth_rfcomm_connect(const bluetooth_device_address_t *remote_bt_address, - const char *remote_uuid) +#ifdef RFCOMM_DIRECT + +#define BT_TIMEOUT_MESSAGE "Did not receive a reply. Possible causes include: " \ + "the remote application did not send a reply, " \ + "the message bus security policy blocked the reply, " \ + "the reply timeout expired, or the network connection " \ + "was broken." + +static GSList *rfcomm_clients; + +/* Variable for privilege, only for write API, + before we should reduce time to bt-service dbus calling + -1 : Don't have a permission to access API + 0 : Initial value, not yet check + 1 : Have a permission to access API +*/ +static int privilege_token; + +typedef struct { + char bt_addr[BT_ADDRESS_STRING_SIZE]; + int fd; + int watch_id; + gboolean disconnected; +} rfcomm_conn_info_t; + +typedef struct { + char uuid[BLUETOOTH_UUID_STRING_MAX]; + char *device_path; + char *obj_path; + int object_id; + int id; + GSList *rfcomm_conns; + unsigned int idle_id; +} rfcomm_cb_data_t; + +static void __client_connected_cb(rfcomm_cb_data_t *cb_data, + char *dev_address, int result); + +static void __bt_free_cb_data(rfcomm_cb_data_t *cb_data) +{ + BT_DBG("+"); + + if (cb_data->id >= 0) + __rfcomm_delete_id(cb_data->id); + + if (cb_data->object_id > 0) + _bt_unregister_gdbus(cb_data->object_id); + + if (cb_data->obj_path) { + BT_INFO("Unregister profile"); + _bt_unregister_profile(cb_data->obj_path); + } + + if (cb_data->idle_id != 0) { + BT_INFO("Removing idle source"); + g_source_remove(cb_data->idle_id); + } + + g_free(cb_data->obj_path); + + g_free(cb_data->device_path); + g_free(cb_data); + BT_DBG("-"); +} + +static void rfcomm_cb_data_remove(rfcomm_cb_data_t *info) +{ + if (info) { + BT_INFO("No more device connected remove info"); + rfcomm_clients = g_slist_remove(rfcomm_clients, info); + __bt_free_cb_data(info); + } +} + +gint compare(gpointer *a, gpointer *b) +{ + rfcomm_conn_info_t *node = (rfcomm_conn_info_t *)a; + char *address = (char *)b; + return g_strcmp0(node->bt_addr, address); +} + +gint compare_fd(gpointer *a, gpointer *b) +{ + rfcomm_conn_info_t *node = (rfcomm_conn_info_t *)a; + int fd = (int )*b; + if (node->fd == fd) + return 0; + return 1; +} +static void __bt_free_conn(rfcomm_conn_info_t *conn) +{ + BT_DBG("+"); + + if (conn == NULL) + return; + + if (conn->fd > 0) + close(conn->fd); + if (conn->watch_id > 0) { + g_source_remove(conn->watch_id); + conn->watch_id = 0; + } + g_free(conn); + + BT_DBG("-"); +} + +static void __rfcomm_remove_conn_info_t(rfcomm_cb_data_t *info, char *address) +{ + GSList *l = NULL; + rfcomm_conn_info_t *conn_info = NULL; + l = g_slist_find_custom(info->rfcomm_conns, address, (GCompareFunc)compare); + if (l) + conn_info = l->data; + if (conn_info) { + info->rfcomm_conns = g_slist_remove(info->rfcomm_conns, conn_info); + __bt_free_conn(conn_info); + } +} + +static rfcomm_conn_info_t *__get_conn_info_from_fd(rfcomm_cb_data_t *info, + int fd) +{ + GSList *l; + rfcomm_conn_info_t *device_node = NULL; + for(l = info->rfcomm_conns; l != NULL; l = l->next) { + device_node = l->data; + if ( device_node && device_node->fd == fd) + return device_node; + } + return NULL; +} + +static rfcomm_conn_info_t * __get_conn_info_for_disconnection( + rfcomm_cb_data_t *info) +{ + GSList *l; + rfcomm_conn_info_t *device_node = NULL; + for(l = info->rfcomm_conns; l != NULL; l = l->next) { + device_node = l->data; + if (device_node && device_node->disconnected == TRUE) + return device_node; + } + return NULL; +} + +static rfcomm_conn_info_t *__get_conn_info_from_address(rfcomm_cb_data_t *info, + char *dev_address) +{ + GSList *l = NULL; + rfcomm_conn_info_t *conn_info = NULL; + l = g_slist_find_custom(info->rfcomm_conns, dev_address, + (GCompareFunc)compare); + if (l) + conn_info = l->data; + return conn_info; +} + +static void __rfcomm_client_connected_cb(rfcomm_cb_data_t *info, + char *dev_address, int result) +{ + __client_connected_cb(info, dev_address, result); + __rfcomm_remove_conn_info_t(info, dev_address); + + if (info->rfcomm_conns == NULL) + rfcomm_cb_data_remove(info); +} + +static rfcomm_cb_data_t *__find_rfcomm_info_with_fd(int fd) +{ + GSList *l; + GSList *device_fd; + for (l = rfcomm_clients; l != NULL; l = l->next) { + rfcomm_cb_data_t *info = l->data; + device_fd = g_slist_find_custom(info->rfcomm_conns, &fd, + (GCompareFunc)compare_fd); + if (device_fd) + return info; + } + + return NULL; +} + +static rfcomm_cb_data_t *__find_rfcomm_info_from_path(const char *path) +{ + GSList *l; + + for (l = rfcomm_clients; l != NULL; l = l->next) { + rfcomm_cb_data_t *info = l->data; + + if (info != NULL) + if (g_strcmp0(info->obj_path, path) == 0) + return info; + } + + return NULL; +} + +static rfcomm_cb_data_t *__find_rfcomm_info_from_uuid(const char *uuid) +{ + GSList *l; + + for (l = rfcomm_clients; l != NULL; l = l->next) { + rfcomm_cb_data_t *info = l->data; + + if (g_strcmp0(info->uuid, uuid) == 0) + return info; + } + + return NULL; +} + +static void _bt_rfcomm_disconnect_conn_info(rfcomm_conn_info_t *conn_info, + rfcomm_cb_data_t *info) +{ + bluetooth_rfcomm_disconnection_t disconn_info; + bt_event_info_t *event_info = NULL; + if (conn_info->disconnected == FALSE) + return; + event_info = _bt_event_get_cb_data(BT_RFCOMM_CLIENT_EVENT); + if (event_info == NULL) { + if (info->rfcomm_conns == NULL) + rfcomm_cb_data_remove(info); + return; + } + memset(&disconn_info, 0x00, sizeof(bluetooth_rfcomm_disconnection_t)); + disconn_info.device_role = RFCOMM_ROLE_CLIENT; + g_strlcpy(disconn_info.uuid, info->uuid, BLUETOOTH_UUID_STRING_MAX); + BT_DBG("Disconnected FD [%d]", conn_info->fd); + _bt_convert_addr_string_to_type(disconn_info.device_addr.addr, + conn_info->bt_addr); + + disconn_info.socket_fd = conn_info->fd; + + BT_DBG("Disconnection Result[%d] BT_ADDRESS[%s] UUID[%s] FD[%d]", + BLUETOOTH_ERROR_NONE, conn_info->bt_addr, + info->uuid, conn_info->fd); + _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_DISCONNECTED, + BLUETOOTH_ERROR_NONE, &disconn_info, + event_info->cb, event_info->user_data); + + if(conn_info) { + BT_DBG("List is present deleting it"); + __rfcomm_remove_conn_info_t(info, conn_info->bt_addr); + } + if (info->rfcomm_conns == NULL) + rfcomm_cb_data_remove(info); + + BT_DBG("-"); +} + +static gboolean __rfcomm_client_disconnect(gpointer user_data) +{ + rfcomm_cb_data_t *info = (rfcomm_cb_data_t *) user_data; + BT_INFO_C("Disconnected [RFCOMM Client]"); + retv_if(info == NULL, FALSE); + + if (g_slist_find(rfcomm_clients, info) == NULL) { + BT_INFO("rfcomm resource is already freed"); + return FALSE; + } + info->idle_id = 0; + g_slist_foreach(info->rfcomm_conns, + (GFunc) _bt_rfcomm_disconnect_conn_info, info); + BT_DBG("-"); + return FALSE; +} + +static gboolean __is_error_by_disconnect(GError *err) +{ + return !g_strcmp0(err->message, "Connection reset by peer") || + !g_strcmp0(err->message, "Connection timed out") || + !g_strcmp0(err->message, "Software caused connection abort"); +} + +static gboolean __client_data_received_cb(GIOChannel *chan, GIOCondition cond, + gpointer data) +{ + char *buffer = NULL; + gsize len = 0; + int result = BLUETOOTH_ERROR_NONE; + rfcomm_cb_data_t *info = data; + rfcomm_conn_info_t *conn_info = NULL; + bt_event_info_t *event_info; + bluetooth_rfcomm_received_data_t data_r; + GIOStatus status = G_IO_STATUS_NORMAL; + GError *err = NULL; + int fd; + BT_DBG(""); + + retv_if(info == NULL, FALSE); + fd = g_io_channel_unix_get_fd(chan); + if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) { + BT_ERR_C("RFComm Client disconnected: %d", fd); + conn_info = __get_conn_info_from_fd(info, fd); + if (conn_info == NULL) { + BT_ERR("No Connection info found with FD [%d]", fd); + return FALSE; + } + conn_info->disconnected = TRUE; + __rfcomm_client_disconnect(info); + return FALSE; + } + + buffer = g_malloc0(BT_RFCOMM_BUFFER_LEN + 1); + + status = g_io_channel_read_chars(chan, buffer, BT_RFCOMM_BUFFER_LEN, + &len, &err); + if (status != G_IO_STATUS_NORMAL) { + BT_ERR("IO Channel read is failed with %d", status); + + g_free(buffer); + if (err) { + BT_ERR("IO Channel read error [%s]", err->message); + if (status == G_IO_STATUS_ERROR && + __is_error_by_disconnect(err)) { + BT_ERR("cond : %d", cond); + g_error_free(err); + conn_info = __get_conn_info_from_fd(info, fd); + if (conn_info == NULL) { + BT_ERR("No Connection info found with FD [%d]", fd); + return FALSE; + } + conn_info->disconnected = TRUE; + __rfcomm_client_disconnect(info); + return FALSE; + } + g_error_free(err); + } + return TRUE; + } + + event_info = _bt_event_get_cb_data(BT_RFCOMM_CLIENT_EVENT); + if (event_info == NULL) { + g_free(buffer); + return TRUE; + } + + data_r.socket_fd = fd; + data_r.buffer_size = len; + data_r.buffer = buffer; + + _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_DATA_RECEIVED, + result, &data_r, + event_info->cb, event_info->user_data); + + g_free(buffer); + return TRUE; +} + +static void __client_connected_cb(rfcomm_cb_data_t *cb_data, char *dev_address, + int result) +{ + bluetooth_rfcomm_connection_t conn_info; + bt_event_info_t *event_info; + rfcomm_conn_info_t *conn_list_info = NULL; + BT_INFO_C("Connected [RFCOMM Client]"); + + event_info = _bt_event_get_cb_data(BT_RFCOMM_CLIENT_EVENT); + if (event_info == NULL) + return; + + memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t)); + conn_info.device_role = RFCOMM_ROLE_CLIENT; + g_strlcpy(conn_info.uuid, cb_data->uuid, BLUETOOTH_UUID_STRING_MAX); + _bt_convert_addr_string_to_type(conn_info.device_addr.addr, + dev_address); + conn_list_info = __get_conn_info_from_address(cb_data, dev_address); + if (conn_list_info == NULL) { + BT_ERR("Device addres %s not found in connection list", dev_address); + return; + } + conn_info.socket_fd = conn_list_info->fd; + conn_info.server_id = -1; + + BT_DBG("Connection Result[%d] BT_ADDRESS[%s] UUID[%s] FD[%d]", + result, conn_list_info->bt_addr, cb_data->uuid, conn_list_info->fd); + _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_CONNECTED, + result, &conn_info, + event_info->cb, event_info->user_data); + BT_DBG("-"); +} + +#endif + +int new_connection(const char *path, int fd, bluetooth_device_address_t *addr) +{ + rfcomm_cb_data_t *info; + GIOChannel *data_io; + rfcomm_conn_info_t *conn_info = NULL; + BT_DBG("%s %d", path, fd); + char address[BT_ADDRESS_STRING_SIZE]; + _bt_convert_addr_type_to_string(address, + (unsigned char *)addr); + info = __find_rfcomm_info_from_path(path); + if (info == NULL) + return -1; + conn_info = __get_conn_info_from_address(info, address); + + if (conn_info == NULL) { + BT_ERR("Device Address %s not found in connection list", address); + return -1; + } + conn_info->fd = fd; + BT_DBG("connection info fd %d", conn_info->fd); + data_io = g_io_channel_unix_new(fd); + g_io_channel_set_encoding(data_io, NULL, NULL); + g_io_channel_set_flags(data_io, G_IO_FLAG_NONBLOCK, NULL); + conn_info->watch_id = g_io_add_watch(data_io, + G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, + __client_data_received_cb, info); + + g_io_channel_unref(data_io); + + __client_connected_cb(info, address,BLUETOOTH_ERROR_NONE); + + return 0; +} + +static void __bt_connect_response_cb(DBusGProxy *proxy, DBusGProxyCall *call, + gpointer user_data) + { + GError *error = NULL; + rfcomm_cb_data_t *cb_data; + char dev_address[BT_ADDRESS_STRING_SIZE]; + const char *path; + BT_DBG("+"); + + ret_if(user_data == NULL); + + cb_data = user_data; + + if (!dbus_g_proxy_end_call(proxy, call, &error, G_TYPE_INVALID)) { + int result; + + BT_ERR("Error : %s \n", error->message); + + if (g_strcmp0(error->message, "In Progress") == 0) + result = BLUETOOTH_ERROR_DEVICE_BUSY; + else + result = BLUETOOTH_ERROR_INTERNAL; + path = dbus_g_proxy_get_path(proxy); + _bt_convert_device_path_to_address(path, dev_address); + __rfcomm_client_connected_cb(cb_data, dev_address, result); + + g_error_free(error); + g_object_unref(proxy); + } + BT_DBG("-"); +} + +static void __bt_discover_service_response_cb(DBusGProxy *proxy, + DBusGProxyCall *call, gpointer user_data) +{ + rfcomm_cb_data_t *cb_data; + int ret = 0; + GError *err = NULL; + GHashTable *hash = NULL; + bt_register_profile_info_t info = {0}; + int result = BLUETOOTH_ERROR_NONE; + char dev_address[BT_ADDRESS_STRING_SIZE]; + const char *path; + + BT_DBG("+"); + + ret_if(user_data == NULL); + + cb_data = user_data; + + path = dbus_g_proxy_get_path(proxy); + _bt_convert_device_path_to_address(path, dev_address); + BT_DBG("Device Adress [%s]", dev_address); + dbus_g_proxy_end_call(proxy, call, &err, + dbus_g_type_get_map("GHashTable", + G_TYPE_UINT, G_TYPE_STRING), &hash, + G_TYPE_INVALID); + g_object_unref(proxy); + if (err != NULL) { + BT_ERR("Error occured in Proxy call [%s]\n", err->message); + if (!strcmp("Operation canceled", err->message)) { + result = BLUETOOTH_ERROR_CANCEL_BY_USER; + } else if (!strcmp("In Progress", err->message)) { + result = BLUETOOTH_ERROR_IN_PROGRESS; + } else if (!strcmp("Host is down", err->message)) { + result = BLUETOOTH_ERROR_HOST_DOWN; + } else if (!strcmp(BT_TIMEOUT_MESSAGE, err->message)) { + result = BLUETOOTH_ERROR_SERVICE_SEARCH_ERROR; + ret = _bt_cancel_discovers(dev_address); + if (ret != BLUETOOTH_ERROR_NONE) + BT_ERR("Error: While CancelDiscovery"); + } else { + result = BLUETOOTH_ERROR_CONNECTION_ERROR; + } + __rfcomm_client_connected_cb(cb_data, dev_address, result); + goto done; + } else { + BT_INFO("Services are Updated checking required uuid is there"); + /* Check here for uuid present */ + ret = _bt_discover_service_uuids(dev_address, (char *)cb_data->uuid); + if (ret == BLUETOOTH_ERROR_NONE) { + info.uuid = (char *)cb_data->uuid; + info.obj_path = cb_data->obj_path; + info.role = "client"; + + ret = _bt_register_profile(&info, FALSE); + if (ret < 0) + BT_DBG("Error: register profile"); + ret = _bt_connect_profile(dev_address, cb_data->uuid, + __bt_connect_response_cb, cb_data); + + if (ret != BLUETOOTH_ERROR_NONE) { + BT_ERR("ConnectProfile failed"); + result = BLUETOOTH_ERROR_CONNECTION_ERROR; + __rfcomm_client_connected_cb(cb_data, dev_address, result); + goto done; + } + } else { + BT_ERR("remote uuid not found"); + result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND; + __rfcomm_client_connected_cb(cb_data, dev_address, result); + } + } +done: + if (err) + g_error_free(err); + if (hash) + g_hash_table_destroy(hash); +} + +BT_EXPORT_API int bluetooth_rfcomm_connect( + const bluetooth_device_address_t *remote_bt_address, + const char *remote_uuid) +{ + +#ifdef RFCOMM_DIRECT + rfcomm_cb_data_t *cb_data = NULL; + rfcomm_conn_info_t *conn = NULL; +#else int result; int connect_type; bt_user_info_t *user_info; char uuid[BLUETOOTH_UUID_STRING_MAX]; - +#endif BT_CHECK_PARAMETER(remote_bt_address, return); BT_CHECK_PARAMETER(remote_uuid, return); BT_CHECK_ENABLED(return); - BT_INIT_PARAMS(); - BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); +#ifdef RFCOMM_DIRECT + BT_INFO_C("<<<<<<<<< RFCOMM Connect request from app >>>>>>>>>>>"); + int ret; + int id, object_id; + char *path; + + if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_RFCOMM_CLIENT_CONNECT) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } + id = __rfcomm_assign_id(); + if (id < 0) + return BLUETOOTH_ERROR_INTERNAL; + + cb_data = __find_rfcomm_info_from_uuid(remote_uuid); + if (!cb_data) { + path = g_strdup_printf("/org/socket/client/%d/%d", getpid(), id); + + object_id = _bt_register_new_conn(path, new_connection); + if (object_id < 0) { + __rfcomm_delete_id(id); + return BLUETOOTH_ERROR_INTERNAL; + } + + cb_data = g_new0(rfcomm_cb_data_t, 1); + g_strlcpy(cb_data->uuid, remote_uuid, BLUETOOTH_UUID_STRING_MAX); + cb_data->obj_path = path; + cb_data->object_id = object_id; + cb_data->id = id; + } + conn = g_new0(rfcomm_conn_info_t, 1); + conn->fd = -1; + _bt_convert_addr_type_to_string(conn->bt_addr, + (unsigned char *)remote_bt_address->addr); + + BT_DBG("Connecting to %s uuid %s", conn->bt_addr, remote_uuid); + cb_data->rfcomm_conns = g_slist_append(cb_data->rfcomm_conns, conn); + ret = _bt_discover_services(conn->bt_addr, (char *)remote_uuid, + __bt_discover_service_response_cb, cb_data); + if (ret != BLUETOOTH_ERROR_NONE) { + BT_ERR("Error returned while service discovery"); + __rfcomm_remove_conn_info_t(cb_data, conn->bt_addr); + if (cb_data->rfcomm_conns == NULL) + rfcomm_cb_data_remove(cb_data); + return BLUETOOTH_ERROR_INTERNAL; + } + if (g_slist_find(rfcomm_clients, cb_data) == NULL) { + BT_INFO("Adding callback information to rfcomm_clients"); + rfcomm_clients = g_slist_append(rfcomm_clients, cb_data); + } else + BT_INFO("Callback information is already added"); + + return BLUETOOTH_ERROR_NONE; +#else user_info = _bt_get_user_data(BT_COMMON); - retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL); /* connect_type: BT_RFCOMM_UUID / BT_RFCOMM_CHANNEL*/ /* In now, we only support to connecty using UUID */ connect_type = BT_RFCOMM_UUID; + if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_RFCOMM_CLIENT_CONNECT) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + g_array_append_vals(in_param1, remote_bt_address, sizeof(bluetooth_device_address_t)); @@ -67,6 +673,41 @@ BT_EXPORT_API int bluetooth_rfcomm_connect(const bluetooth_device_address_t *rem BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); return result; +#endif +} + +BT_EXPORT_API int bluetooth_rfcomm_client_is_connected(bluetooth_device_address_t *device_address, gboolean *connected) +{ + GSList *l; + GSList *conn_list = NULL; + rfcomm_cb_data_t *client_info; + rfcomm_conn_info_t *conn_info; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + + BT_CHECK_PARAMETER(device_address, return); + BT_CHECK_PARAMETER(connected, return); + + _bt_convert_addr_type_to_string(address, device_address->addr); + *connected = FALSE; + + for (l = rfcomm_clients; l != NULL; l = l->next) { + client_info = l->data; + if (client_info == NULL) + continue; + for(conn_list = client_info->rfcomm_conns; + conn_list != NULL; conn_list = conn_list->next) { + conn_info = conn_list->data; + if(conn_info == NULL) + continue; + + if (g_strcmp0(address, conn_info->bt_addr) == 0) { + *connected = TRUE; + return BLUETOOTH_ERROR_NONE; + } + } + } + + return BLUETOOTH_ERROR_NONE; } BT_EXPORT_API gboolean bluetooth_rfcomm_is_client_connected(void) @@ -79,8 +720,10 @@ BT_EXPORT_API gboolean bluetooth_rfcomm_is_client_connected(void) BT_INIT_PARAMS(); BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); - result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_CLIENT_IS_CONNECTED, - in_param1, in_param2, in_param3, in_param4, &out_param); + result = _bt_send_request(BT_BLUEZ_SERVICE, + BT_RFCOMM_CLIENT_IS_CONNECTED, + in_param1, in_param2, in_param3, + in_param4, &out_param); BT_DBG("result: %x", result); @@ -98,6 +741,47 @@ BT_EXPORT_API gboolean bluetooth_rfcomm_is_client_connected(void) BT_EXPORT_API int bluetooth_rfcomm_disconnect(int socket_fd) { +#ifdef RFCOMM_DIRECT + rfcomm_cb_data_t *info; + rfcomm_conn_info_t *conn_info; + BT_INFO_C("<<<<<<<<< RFCOMM Disconnect request from app >>>>>>>>"); + BT_CHECK_ENABLED(return); + + if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_RFCOMM_SOCKET_DISCONNECT) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } + + if (socket_fd < 0) { + BT_ERR("Invalid FD"); + return BLUETOOTH_ERROR_INVALID_PARAM; + } + BT_DBG("FDD %d", socket_fd); + + info = __find_rfcomm_info_with_fd(socket_fd); + if (info == NULL) { + BT_DBG("Could not find in client, so check in server"); + return bluetooth_rfcomm_server_disconnect(socket_fd); + } + conn_info = __get_conn_info_from_fd(info, socket_fd); + if (conn_info == NULL) { + BT_ERR("FATAL Error"); + return BLUETOOTH_ERROR_INTERNAL; + } + if (conn_info->watch_id <= 0) { + BT_ERR("Invalid state"); + return BLUETOOTH_ERROR_NOT_CONNECTED; + } + conn_info->disconnected = TRUE; + close(socket_fd); + BT_INFO("conn_info %s", conn_info->bt_addr); + _bt_disconnect_profile(conn_info->bt_addr, info->uuid, NULL,NULL); + if (info->idle_id == 0) + info->idle_id = g_idle_add(__rfcomm_client_disconnect, info); + + return BLUETOOTH_ERROR_NONE; +#else int result; int service_function; @@ -123,23 +807,60 @@ BT_EXPORT_API int bluetooth_rfcomm_disconnect(int socket_fd) BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); return result; +#endif } BT_EXPORT_API int bluetooth_rfcomm_write(int fd, const char *buf, int length) { - int result; +#ifdef RFCOMM_DIRECT + int written; +#else char *buffer; +#endif + int result; BT_CHECK_PARAMETER(buf, return); +#ifndef RFCOMM_DIRECT BT_CHECK_ENABLED(return); +#endif retv_if(length <= 0, BLUETOOTH_ERROR_INVALID_PARAM); +#ifdef RFCOMM_DIRECT + switch (privilege_token) { + case 0: + result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_RFCOMM_SOCKET_WRITE); + + if (result == BLUETOOTH_ERROR_NONE) { + privilege_token = 1; /* Have a permission */ + } else if (result == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + privilege_token = -1; /* Don't have a permission */ + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } else { + /* Just break - It is not related with permission error */ + } + break; + case 1: + /* Already have a privilege */ + break; + case -1: + return BLUETOOTH_ERROR_PERMISSION_DEINED; + default: + /* Invalid privilge token value */ + return BLUETOOTH_ERROR_INTERNAL; + } + + written = write(fd, buf, length); + /*BT_DBG("Length %d, written = %d, balance(%d)", + length, written, length - written); */ + return written; +#else BT_INIT_PARAMS(); BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); buffer = g_malloc0(length + 1); - g_strlcpy(buffer, buf, length + 1); + memcpy(buffer, buf, length); g_array_append_vals(in_param1, &fd, sizeof(int)); g_array_append_vals(in_param2, &length, sizeof(int)); @@ -155,5 +876,6 @@ BT_EXPORT_API int bluetooth_rfcomm_write(int fd, const char *buf, int length) g_free(buffer); return result; +#endif } diff --git a/bt-api/bt-rfcomm-server.c b/bt-api/bt-rfcomm-server.c old mode 100644 new mode 100755 index 5396f70..600f93a --- a/bt-api/bt-rfcomm-server.c +++ b/bt-api/bt-rfcomm-server.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -18,6 +22,11 @@ */ #include +#ifdef RFCOMM_DIRECT +#include +#include +#include +#endif #include "bluetooth-api.h" #include "bt-internal-types.h" @@ -26,15 +35,338 @@ #include "bt-request-sender.h" #include "bt-event-handler.h" +#ifdef RFCOMM_DIRECT + +static GSList *rfcomm_nodes; + +typedef struct { + guint object_id; + gchar *path; + int id; + char *uuid; + int fd; + GIOChannel *data_io; + guint data_id; + bluetooth_device_address_t addr; + guint disconnect_idle_id; +} rfcomm_info_t; + +static rfcomm_info_t *__find_rfcomm_info_with_id(int id) +{ + GSList *l; + + for (l = rfcomm_nodes; l != NULL; l = l->next) { + rfcomm_info_t *info = l->data; + + if (info->id == id) + return info; + } + + return NULL; +} + +static rfcomm_info_t *__find_rfcomm_info_with_fd(int fd) +{ + GSList *l; + + for (l = rfcomm_nodes; l != NULL; l = l->next) { + rfcomm_info_t *info = l->data; + + if (info->fd == fd) + return info; + } + + return NULL; +} + +static rfcomm_info_t *__find_rfcomm_info_with_path(const gchar *path) +{ + GSList *l; + + for (l = rfcomm_nodes; l != NULL; l = l->next) { + rfcomm_info_t *info = l->data; + + if (g_strcmp0(info->path, path) == 0) + return info; + } + + return NULL; +} + +gboolean _check_uuid_path(char *path, char *uuid) +{ + rfcomm_info_t *info = NULL; + info = __find_rfcomm_info_with_path(path); + if (!info) + return FALSE; + + if (strcmp(info->uuid, uuid) == 0) + return TRUE; + + return FALSE; +} + +static void __connected_cb(rfcomm_info_t *info, bt_event_info_t *event_info) +{ + bluetooth_rfcomm_connection_t conn_info; + + memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t)); + conn_info.device_role = RFCOMM_ROLE_SERVER; + g_strlcpy(conn_info.uuid, info->uuid, BLUETOOTH_UUID_STRING_MAX); + conn_info.socket_fd = info->fd; + conn_info.device_addr = info->addr; + conn_info.server_id = info->id; + + BT_INFO_C("Connected [RFCOMM Server]"); + _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_CONNECTED, + BLUETOOTH_ERROR_NONE, &conn_info, + event_info->cb, event_info->user_data); +} + +static gboolean __rfcomm_server_disconnect(rfcomm_info_t *info) +{ + bluetooth_rfcomm_disconnection_t disconn_info; + int fd = info->fd; + bt_event_info_t *event_info; + + BT_INFO_C("Disconnected [RFCOMM Server]"); + + if (info->data_id > 0) { + g_source_remove(info->data_id); + info->data_id = 0; + } + + if (info->fd >= 0) { + close(info->fd); + info->fd = -1; + } + + if (info->data_io) { + g_io_channel_shutdown(info->data_io, TRUE, NULL); + g_io_channel_unref(info->data_io); + info->data_io = NULL; + } + info->disconnect_idle_id = 0; + event_info = _bt_event_get_cb_data(BT_RFCOMM_SERVER_EVENT); + if (event_info == NULL) + return FALSE; + + memset(&disconn_info, 0x00, sizeof(bluetooth_rfcomm_disconnection_t)); + disconn_info.device_role = RFCOMM_ROLE_SERVER; + g_strlcpy(disconn_info.uuid, info->uuid, BLUETOOTH_UUID_STRING_MAX); + disconn_info.socket_fd = fd; + disconn_info.device_addr = info->addr; + + _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_DISCONNECTED, + BLUETOOTH_ERROR_NONE, &disconn_info, + event_info->cb, event_info->user_data); + + BT_DBG("-"); + return FALSE; +} + +static gboolean __data_received_cb(GIOChannel *chan, GIOCondition cond, + gpointer data) +{ + char *buffer = NULL; + gsize len = 0; + int result = BLUETOOTH_ERROR_NONE; + rfcomm_info_t *info = data; + bt_event_info_t *event_info; + bluetooth_rfcomm_received_data_t data_r; + GIOStatus status = G_IO_STATUS_NORMAL; + GError *err = NULL; + + retv_if(info == NULL, FALSE); + + event_info = _bt_event_get_cb_data(BT_RFCOMM_SERVER_EVENT); + + if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) { + BT_ERR_C("RFComm Server disconnected: %d", info->fd); + + if (info->disconnect_idle_id > 0) { + BT_INFO("Disconnect idle still not process remove source"); + g_source_remove(info->disconnect_idle_id); + info->disconnect_idle_id = 0; + } + + __rfcomm_server_disconnect(info); + return FALSE; + } + + buffer = g_malloc0(BT_RFCOMM_BUFFER_LEN + 1); + + status = g_io_channel_read_chars(chan, buffer, BT_RFCOMM_BUFFER_LEN, + &len, &err); + if (status != G_IO_STATUS_NORMAL) { + BT_ERR("IO Channel read is failed with %d", status); + + g_free(buffer); + if (err) { + BT_ERR("IO Channel read error [%s]", err->message); + if (status == G_IO_STATUS_ERROR && + !g_strcmp0(err->message, "Connection reset by peer")) { + BT_ERR("cond : %d", cond); + g_error_free(err); + if (info->disconnect_idle_id > 0) { + BT_INFO("Disconnect idle still not process remove source"); + g_source_remove(info->disconnect_idle_id); + info->disconnect_idle_id = 0; + } + __rfcomm_server_disconnect(info); + return FALSE; + } + g_error_free(err); + } + return TRUE; + } + + if (len == 0) + BT_ERR("Length is zero"); + + if (event_info == NULL) { + g_free(buffer); + return TRUE; + } + + data_r.socket_fd = info->fd; + data_r.buffer_size = len; + data_r.buffer = buffer; + + _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_DATA_RECEIVED, + result, &data_r, + event_info->cb, event_info->user_data); + + g_free(buffer); + + return TRUE; +} + +int new_server_connection(const char *path, int fd, bluetooth_device_address_t *addr) +{ + rfcomm_info_t *info; + bt_event_info_t *event_info; + + BT_DBG("%s %d", path, fd); + + info = __find_rfcomm_info_with_path(path); + if (info == NULL) + return -1; + + info->fd = fd; + memcpy(&info->addr, addr, sizeof(bluetooth_device_address_t)); + + info->data_io = g_io_channel_unix_new(info->fd); + + g_io_channel_set_encoding(info->data_io, NULL, NULL); + g_io_channel_set_flags(info->data_io, G_IO_FLAG_NONBLOCK, NULL); + + info->data_id = g_io_add_watch(info->data_io, + G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, + __data_received_cb, info); + + event_info = _bt_event_get_cb_data(BT_RFCOMM_SERVER_EVENT); + if (event_info) { + __connected_cb(info, event_info); + } + + return 0; +} + +static rfcomm_info_t *__register_method() +{ + gchar *path; + rfcomm_info_t *info; + int object_id; + int id; + + id = __rfcomm_assign_id(); + if (id < 0) + return NULL; + + path = g_strdup_printf("/org/socket/server/%d/%d", getpid(), id); + + object_id = _bt_register_new_conn(path, new_server_connection); + if (object_id < 0) { + __rfcomm_delete_id(id); + return NULL; + } + info = g_new(rfcomm_info_t, 1); + info->object_id = (guint)object_id; + info->path = path; + info->id = id; + info->fd = -1; + + rfcomm_nodes = g_slist_append(rfcomm_nodes, info); + + return info; +} + +void free_rfcomm_info(rfcomm_info_t *info) +{ + bt_event_info_t *event_info; + + BT_DBG(""); + if (info->disconnect_idle_id > 0) { + BT_INFO("Disconnect idle still not process remove source"); + g_source_remove(info->disconnect_idle_id); + info->disconnect_idle_id = 0; + } + + __rfcomm_delete_id(info->id); + _bt_unregister_gdbus(info->object_id); + + if (info->fd >= 0) { + event_info = _bt_event_get_cb_data(BT_RFCOMM_SERVER_EVENT); + if (event_info) + BT_DBG("event type %d", event_info->event_type); + __rfcomm_server_disconnect(info); + } + + g_free(info->path); + g_free(info->uuid); + g_free(info); +} + +void _bt_rfcomm_server_free_all() +{ + BT_DBG("Free all the servers"); + + g_slist_free_full(rfcomm_nodes, (GDestroyNotify)free_rfcomm_info); + rfcomm_nodes = NULL; +} +#endif BT_EXPORT_API int bluetooth_rfcomm_create_socket(const char *uuid) { +#ifdef RFCOMM_DIRECT + rfcomm_info_t *info; +#else int result; int socket_fd = -1; char uuid_str[BLUETOOTH_UUID_STRING_MAX]; +#endif BT_CHECK_ENABLED(return); BT_CHECK_PARAMETER(uuid, return); + BT_INFO("UUID Provided %s", uuid); + + if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_RFCOMM_CREATE_SOCKET) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } + +#ifdef RFCOMM_DIRECT + BT_INFO("<<<<<<<<< RFCOMM Create socket from app >>>>>>>>>"); + info = __register_method(); + if (info == NULL) + return -1; + + info->uuid = g_strdup(uuid); + info->disconnect_idle_id = 0; + return info->id; +#else BT_INIT_PARAMS(); BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); @@ -56,14 +388,40 @@ BT_EXPORT_API int bluetooth_rfcomm_create_socket(const char *uuid) BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); return socket_fd; +#endif } BT_EXPORT_API int bluetooth_rfcomm_remove_socket(int socket_fd) { +#ifdef RFCOMM_DIRECT + rfcomm_info_t *info; +#else int result; +#endif BT_CHECK_ENABLED(return); + if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_RFCOMM_REMOVE_SOCKET) + == BLUETOOTH_ERROR_PERMISSION_DEINED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_ERROR_PERMISSION_DEINED; + } + +#ifdef RFCOMM_DIRECT + BT_INFO("<<<<<<<<< RFCOMM Remove socket request from app, fd=[%d] >>>>>>>>>>>", socket_fd); + + info = __find_rfcomm_info_with_id(socket_fd); + if (info == NULL) + return BLUETOOTH_ERROR_INVALID_PARAM; + + _bt_unregister_osp_server_in_agent(BT_RFCOMM_SERVER,info->uuid); + _bt_unregister_profile(info->path); + + rfcomm_nodes = g_slist_remove(rfcomm_nodes, info); + free_rfcomm_info(info); + + return BLUETOOTH_ERROR_NONE; +#else BT_INIT_PARAMS(); BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); @@ -81,10 +439,38 @@ BT_EXPORT_API int bluetooth_rfcomm_remove_socket(int socket_fd) BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); return result; +#endif } BT_EXPORT_API int bluetooth_rfcomm_server_disconnect(int socket_fd) { +#ifdef RFCOMM_DIRECT + rfcomm_info_t *info; + + char address[20]; + + BT_INFO(">>>>>>>>RFCOMM server disconnect request from APP>>>>>>>>>"); + + info = __find_rfcomm_info_with_fd(socket_fd); + if (info == NULL) + return BLUETOOTH_ERROR_INVALID_PARAM; + + if (info->data_io == NULL) + return BLUETOOTH_ERROR_NOT_CONNECTED; + + g_io_channel_shutdown(info->data_io, TRUE, NULL); + g_io_channel_unref(info->data_io); + info->data_io = NULL; + + _bt_convert_addr_type_to_string(address, info->addr.addr); + BT_DBG("Address %s", address); + _bt_disconnect_profile(address, info->uuid, NULL,NULL); + + info->disconnect_idle_id = g_idle_add(__rfcomm_server_disconnect, info); + BT_DBG("-"); + + return BLUETOOTH_ERROR_NONE; +#else int result; BT_CHECK_ENABLED(return); @@ -102,6 +488,7 @@ BT_EXPORT_API int bluetooth_rfcomm_server_disconnect(int socket_fd) BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); return result; +#endif } BT_EXPORT_API gboolean bluetooth_rfcomm_is_server_uuid_available(const char *uuid) @@ -136,13 +523,68 @@ BT_EXPORT_API gboolean bluetooth_rfcomm_is_server_uuid_available(const char *uui return available; } +BT_EXPORT_API int bluetooth_rfcomm_server_is_connected(bluetooth_device_address_t *device_address, gboolean *connected) +{ + GSList *l; + rfcomm_info_t *info; + char connected_addr[BT_ADDRESS_STRING_SIZE] = { 0 }; + char input_addr[BT_ADDRESS_STRING_SIZE] = { 0 }; + + BT_CHECK_PARAMETER(device_address, return); + BT_CHECK_PARAMETER(connected, return); + + _bt_convert_addr_type_to_string(input_addr, device_address->addr); + + *connected = FALSE; + + for (l = rfcomm_nodes; l != NULL; l = l->next) { + info = l->data; + + if (info == NULL) + continue; + _bt_convert_addr_type_to_string(connected_addr, info->addr.addr); + + if (g_strcmp0(connected_addr, input_addr) == 0) { + *connected = TRUE; + return BLUETOOTH_ERROR_NONE; + } + } + + return BLUETOOTH_ERROR_NONE; +} + BT_EXPORT_API int bluetooth_rfcomm_listen_and_accept(int socket_fd, int max_pending_connection) { +#ifdef RFCOMM_DIRECT + rfcomm_info_t *info; +#else int result; gboolean native_service = TRUE; +#endif BT_CHECK_ENABLED(return); +#ifdef RFCOMM_DIRECT + BT_INFO("<<<<<<<<< RFCOMM Listen & accept from app >>>>>>>>>>>"); + + info = __find_rfcomm_info_with_id(socket_fd); + if (info == NULL) + return BLUETOOTH_ERROR_INVALID_PARAM; + + bt_register_profile_info_t profile_info; + int result; + + profile_info.authentication = TRUE; + profile_info.authorization = TRUE; + profile_info.obj_path = info->path; + profile_info.role = NULL; + profile_info.service = info->uuid; + profile_info.uuid = info->uuid; + BT_INFO("uuid %s", profile_info.uuid); + result = _bt_register_profile(&profile_info, TRUE); + + return result; +#else BT_INIT_PARAMS(); BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); @@ -158,15 +600,46 @@ BT_EXPORT_API int bluetooth_rfcomm_listen_and_accept(int socket_fd, int max_pend BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); return result; +#endif } BT_EXPORT_API int bluetooth_rfcomm_listen(int socket_fd, int max_pending_connection) { +#ifdef RFCOMM_DIRECT + rfcomm_info_t *info; +#else int result; gboolean native_service = FALSE; +#endif BT_CHECK_ENABLED(return); +#ifdef RFCOMM_DIRECT + BT_INFO("<<<<<<<<< RFCOMM Listen >>>>>>>>>>>"); + + info = __find_rfcomm_info_with_id(socket_fd); + if (info == NULL) + return BLUETOOTH_ERROR_INVALID_PARAM; + + bt_register_profile_info_t profile_info; + int result; + + profile_info.authentication = TRUE; + profile_info.authorization = TRUE; + profile_info.obj_path = info->path; + profile_info.role = NULL; + profile_info.service = info->uuid; + profile_info.uuid = info->uuid; + BT_INFO("UUID %s", info->uuid); + BT_INFO("PATH %s", info->path); + result = _bt_register_profile_platform(&profile_info, TRUE); + if (result != BLUETOOTH_ERROR_NONE) + return result; + + return _bt_register_osp_server_in_agent(BT_RFCOMM_SERVER, info->uuid, + info->path, socket_fd); + +#else BT_INIT_PARAMS(); BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); @@ -186,9 +659,10 @@ BT_EXPORT_API int bluetooth_rfcomm_listen(int socket_fd, int max_pending_connect BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); return result; +#endif } -BT_EXPORT_API int bluetooth_rfcomm_accept_connection(int server_fd, int *client_fd) +BT_EXPORT_API int bluetooth_rfcomm_accept_connection(int server_fd) { int result; @@ -204,14 +678,8 @@ BT_EXPORT_API int bluetooth_rfcomm_accept_connection(int server_fd, int *client_ BT_DBG("result: %x", result); - if (result == BLUETOOTH_ERROR_NONE) { - *client_fd = g_array_index(out_param, int, 0); - } - BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); - BT_DBG("client_fd: %d", *client_fd); - return result; } @@ -221,6 +689,8 @@ BT_EXPORT_API int bluetooth_rfcomm_reject_connection(int server_fd) BT_CHECK_ENABLED(return); + BT_INFO("+"); + BT_INIT_PARAMS(); BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); diff --git a/bt-api/bt-scmst.c b/bt-api/bt-scmst.c new file mode 100755 index 0000000..61d2285 --- /dev/null +++ b/bt-api/bt-scmst.c @@ -0,0 +1,51 @@ +/* + * Bluetooth-frwk + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * 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 +#include +#include +#include + +#include "bt-common.h" +#include "bt-internal-types.h" +#include "bt-request-sender.h" +#include "bluetooth-scmst-api.h" + +BT_EXPORT_API int bluetooth_a2dp_set_content_protection(gboolean status) +{ + int result; + + BT_CHECK_ENABLED(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, &status, sizeof(gboolean)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_SET_CONTENT_PROTECT, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} diff --git a/bt-api/bt-service-api.pc.in b/bt-api/bt-service-api.pc.in old mode 100644 new mode 100755 index 0012031..d0d81d4 --- a/bt-api/bt-service-api.pc.in +++ b/bt-api/bt-service-api.pc.in @@ -1,6 +1,6 @@ prefix=@PREFIX@ exec_prefix=@EXEC_PREFIX@ -libdir=@LIB_INSTALL_DIR@ +libdir=@LIBDIR@ includedir=@INCLUDEDIR@ Name: bt-service diff --git a/bt-api/bt-telephony.c b/bt-api/bt-telephony.c old mode 100644 new mode 100755 index 61c9450..5078ad6 --- a/bt-api/bt-telephony.c +++ b/bt-api/bt-telephony.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-telephony * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * GirishAshok Joshi + * Chanyeol Park * * 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 + * 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, @@ -30,6 +34,11 @@ #include "bluetooth-telephony-api.h" #include "marshal.h" +#define BT_SCO_TIMEOUT 3000 + +#define BT_CVSD_CODEC_ID 1 +#define BT_MSBC_CODEC_ID 2 + typedef struct { DBusGConnection *conn; DBusGProxy *proxy; @@ -47,19 +56,35 @@ typedef struct { void *user_data; } bt_telephony_info_t; + +char *src_addr = NULL; + + + #define BLUETOOTH_TELEPHONY_ERROR (__bluetooth_telephony_error_quark()) + #define BLUEZ_SERVICE_NAME "org.bluez" +#define BLUEZ_HEADSET_INTERFACE "org.bluez.Headset" + #define BLUEZ_MANAGER_INTERFACE "org.freedesktop.DBus.ObjectManager" #define BLUEZ_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties" #define BLUEZ_ADAPTER_INTERFACE "org.bluez.Adapter1" #define BLUEZ_DEVICE_INTERFACE "org.bluez.Device1" +#define HFP_AGENT_SERVICE "org.bluez.ag_agent" + -#define HFP_AGENT_SERVICE "org.bluez.hfp_agent" -#define HFP_AGENT_PATH "/org/bluez/hfp_ag" +#define HFP_AGENT_PATH "/org/bluez/hfp_agent" #define HFP_AGENT_INTERFACE "Org.Hfp.App.Interface" #define CSD_CALL_APP_PATH "/org/tizen/csd/%d" #define HFP_NREC_STATUS_CHANGE "NrecStatusChanged" +#define HFP_ANSWER_CALL "Answer" +#define HFP_REJECT_CALL "Reject" +#define HFP_RELEASE_CALL "Release" +#define HFP_THREEWAY_CALL "Threeway" + +#define DEFAULT_ADAPTER_OBJECT_PATH "/org/bluez/hci0" + #define BT_TELEPHONY_CHECK_ENABLED() \ do { \ @@ -120,39 +145,21 @@ GType bluetooth_telephony_method_get_type(void); G_DEFINE_TYPE(BluetoothTelephonyMethod, bluetooth_telephony_method, G_TYPE_OBJECT) + static DBusHandlerResult __bt_telephony_adapter_filter(DBusConnection *conn, - DBusMessage *msg, void *data); + DBusMessage *msg, void *data); static int __bt_telephony_get_object_path(DBusMessage *msg, char **path); -static char *__bt_extract_device_path(DBusMessageIter *msg_iter, char *address); - -static char *_bt_get_device_object_path(char *address); - -static void _bt_convert_device_path_to_address(const char *device_path, - char *device_address); - -static char *__bt_get_default_adapter_path(DBusMessageIter *msg_iter); - -static gboolean bluetooth_telephony_method_answer(BluetoothTelephonyMethod *object, - guint callid, - DBusGMethodInvocation *context); - -static gboolean bluetooth_telephony_method_release( - BluetoothTelephonyMethod *object, guint callid, - DBusGMethodInvocation *context); - -static gboolean bluetooth_telephony_method_reject(BluetoothTelephonyMethod *object, - guint callid, DBusGMethodInvocation *context); - -static gboolean bluetooth_telephony_method_threeway( - BluetoothTelephonyMethod *object, guint value, - DBusGMethodInvocation *context); +static int __bt_telephony_get_src_addr(DBusMessage *msg); static gboolean bluetooth_telephony_method_send_dtmf( BluetoothTelephonyMethod *object, gchar *dtmf, DBusGMethodInvocation *context); +static gboolean bluetooth_telephony_method_vendor_cmd( + BluetoothTelephonyMethod *object, + gchar *at_cmd, DBusGMethodInvocation *context); #include "bt-telephony-glue.h" static GObject *object; @@ -168,7 +175,7 @@ static DBusMessage* __bluetooth_telephony_dbus_method_send(const char *path, const char *interface, const char *method, DBusError *err, int type, ...); static int __bluetooth_telephony_send_call_status( bt_telephony_call_status_t call_status, - unsigned int call_id); + unsigned int call_id, const char *ph_number); static GError *__bluetooth_telephony_error(bluetooth_telephony_error_t error, const char *err_msg); @@ -180,8 +187,7 @@ static int __bluetooth_telephony_proxy_init(void); static void __bluetooth_telephony_proxy_deinit(void); static int __bluetooth_telephony_register(void); static int __bluetooth_telephony_unregister(void); -static int __bluetooth_get_default_adapter_path(DBusGConnection *GConn, - char *path); + static gboolean __bluetooth_telephony_is_headset(uint32_t device_class); static int __bluetooth_telephony_get_connected_device(void); static DBusGProxy *__bluetooth_telephony_get_connected_device_proxy(void); @@ -190,11 +196,11 @@ static DBusGProxy *__bluetooth_telephony_get_connected_device_proxy(void); static int __bt_telephony_get_error(const char *error_message) { if (error_message == NULL) { - BT_DBG("Error message NULL\n"); + BT_ERR("Error message NULL"); return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; } - BT_DBG("Error message = %s \n", error_message); + BT_ERR("Error message = %s", error_message); if (g_strcmp0(error_message, "NotAvailable") == 0) return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE; else if (g_strcmp0(error_message, "NotConnected") == 0) @@ -213,10 +219,54 @@ static int __bt_telephony_get_error(const char *error_message) return BLUETOOTH_TELEPHONY_ERROR_I_O_ERROR; else if (g_strcmp0(error_message, "Operation currently not available") == 0) return BLUETOOTH_TELEPHONY_ERROR_OPERATION_NOT_AVAILABLE; + else if (g_strrstr(error_message, BT_ACCESS_DENIED_MSG)) + return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED; else return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; } +static int __bt_telephony_check_privilege(void) +{ + DBusMessage *msg; + DBusMessage *reply; + DBusError err; + DBusConnection *conn; + int ret; + + conn = _bt_get_system_conn(); + retv_if(conn == NULL, BLUETOOTH_TELEPHONY_ERROR_INTERNAL); + + msg = dbus_message_new_method_call(HFP_AGENT_SERVICE, + HFP_AGENT_PATH, HFP_AGENT_INTERFACE, + "CheckPrivilege"); + if (!msg) { + BT_ERR("Unable to allocate new D-Bus message \n"); + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + } + + dbus_error_init(&err); + + reply = dbus_connection_send_with_reply_and_block(conn, + msg, -1, &err); + + dbus_message_unref(msg); + + if (!reply) { + BT_ERR("Error returned in method call"); + if (dbus_error_is_set(&err)) { + ret = __bt_telephony_get_error(err.message); + BT_ERR("Error here %d\n", ret); + dbus_error_free(&err); + return ret; + } + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + } + + dbus_message_unref(reply); + + return BLUETOOTH_TELEPHONY_ERROR_NONE; +} + static void __bt_telephony_event_cb(int event, int result, void *param_data) { telephony_event_param_t bt_event = { 0, }; @@ -245,8 +295,13 @@ static DBusMessage* __bluetooth_telephony_dbus_method_send(const char *path, DBusMessage *msg; DBusMessage *reply; va_list args; +#ifdef TIZEN_WEARABLE + int timeout = 4000; +#else + int timeout = -1; +#endif - BT_DBG("+"); + FN_START; msg = dbus_message_new_method_call(HFP_AGENT_SERVICE, path, interface, method); @@ -269,31 +324,39 @@ static DBusMessage* __bluetooth_telephony_dbus_method_send(const char *path, reply = dbus_connection_send_with_reply_and_block( dbus_g_connection_get_connection(telephony_dbus_info.conn), - msg, -1, err); - + msg, timeout, err); dbus_message_unref(msg); - BT_DBG("-"); + FN_END; return reply; } static int __bluetooth_telephony_send_call_status( bt_telephony_call_status_t call_status, - unsigned int call_id) + unsigned int call_id, const char *ph_number) { DBusMessage *reply; DBusError err; char *path = g_strdup(telephony_info.call_path); + char *phone_number; int ret; - BT_DBG("+"); + FN_START; + + if (NULL == ph_number) + phone_number = g_strdup(""); + else + phone_number = g_strdup(ph_number); reply = __bluetooth_telephony_dbus_method_send( HFP_AGENT_PATH, HFP_AGENT_INTERFACE, "ChangeCallStatus", &err, DBUS_TYPE_STRING, &path, + DBUS_TYPE_STRING, &phone_number, DBUS_TYPE_INT32, &call_status, DBUS_TYPE_INT32, &call_id, DBUS_TYPE_INVALID); + g_free(path); + g_free(phone_number); if (!reply) { BT_ERR("Error returned in method call\n"); @@ -318,27 +381,27 @@ static GError *__bluetooth_telephony_error(bluetooth_telephony_error_t error, static void bluetooth_telephony_method_init(BluetoothTelephonyMethod *object) { - BT_DBG("+"); + FN_START; BT_DBG("agent %p\n", object); - BT_DBG("-"); + FN_END; } static void __bluetooth_telephony_method_finalize( BluetoothTelephonyMethod *object) { - BT_DBG("+"); + FN_START; G_OBJECT_CLASS(bluetooth_telephony_method_parent_class)->finalize(( GObject *)object); - BT_DBG("-"); + FN_END; } static BluetoothTelephonyMethod *__bluetooth_telephony_method_new(void) { BluetoothTelephonyMethod *obj; - BT_DBG("+"); + FN_START; obj = g_object_new(BLUETOOTH_TELEPHONY_METHOD, NULL); - BT_DBG("-"); + FN_END; return obj; } @@ -347,7 +410,7 @@ static void bluetooth_telephony_method_class_init( BluetoothTelephonyMethodClass *klass) { GObjectClass *object_class = NULL; - BT_DBG("+"); + FN_START; object_class = G_OBJECT_CLASS(klass); object_class->finalize = (void *)__bluetooth_telephony_method_finalize; @@ -355,82 +418,92 @@ static void bluetooth_telephony_method_class_init( /*Registration of the Framework methods */ dbus_g_object_type_install_info(BLUETOOTH_TELEPHONY_METHOD, &dbus_glib_bluetooth_telephony_method_object_info); - BT_DBG("-"); + FN_END; return; } -static gboolean bluetooth_telephony_method_answer( - BluetoothTelephonyMethod *object, - guint callid, DBusGMethodInvocation *context) +static void __bluetooth_telephony_answer_call(DBusMessage *msg) { telephony_event_callid_t call_data = { 0, }; + unsigned int callid; - BT_DBG("+"); - BT_DBG("call_id = [%d]", callid); + FN_START; + if (!dbus_message_get_args(msg, NULL, + DBUS_TYPE_UINT32, &callid, + DBUS_TYPE_INVALID)) { + BT_ERR("Error Getting parameters"); + return; + } + BT_DBG("call_id = [%d]", callid); call_data.callid = callid; __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_ANSWER_CALL, BLUETOOTH_TELEPHONY_ERROR_NONE, (void *)&call_data); - - dbus_g_method_return(context); - BT_DBG("-"); - return TRUE; + FN_END; } -static gboolean bluetooth_telephony_method_release( - BluetoothTelephonyMethod *object, - guint callid, DBusGMethodInvocation *context) +static void __bluetooth_telephony_release_call(DBusMessage *msg) { telephony_event_callid_t call_data = { 0, }; + unsigned int callid; - BT_DBG("+"); - BT_DBG("call_id = [%d]\n", callid); + FN_START; + if (!dbus_message_get_args(msg, NULL, + DBUS_TYPE_UINT32, &callid, + DBUS_TYPE_INVALID)) { + BT_ERR("Error Getting parameters"); + return; + } + BT_DBG("call_id = [%d]", callid); call_data.callid = callid; __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_RELEASE_CALL, BLUETOOTH_TELEPHONY_ERROR_NONE, (void *)&call_data); - - dbus_g_method_return(context); - BT_DBG("-"); - return TRUE; - + FN_END; } -static gboolean bluetooth_telephony_method_reject( - BluetoothTelephonyMethod *object, - guint callid, DBusGMethodInvocation *context) +static void __bluetooth_telephony_reject_call(DBusMessage *msg) { telephony_event_callid_t call_data = { 0, }; + unsigned int callid; - BT_DBG("+"); - BT_DBG("call_id = [%d]", callid); + FN_START; + if (!dbus_message_get_args(msg, NULL, + DBUS_TYPE_UINT32, &callid, + DBUS_TYPE_INVALID)) { + BT_ERR("Error Getting parameters"); + return; + } + BT_DBG("call_id = [%d]", callid); call_data.callid = callid; __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_REJECT_CALL, BLUETOOTH_TELEPHONY_ERROR_NONE, (void *)&call_data); - - dbus_g_method_return(context); - BT_DBG("-"); - return TRUE; + FN_END; } -static gboolean bluetooth_telephony_method_threeway( - BluetoothTelephonyMethod *object, - guint value, DBusGMethodInvocation *context) +static void __bluetooth_telephony_threeway_call(DBusMessage *msg) { int event = 0; - GError *err; + unsigned int chld_value; + + FN_START; + if (!dbus_message_get_args(msg, NULL, + DBUS_TYPE_UINT32, &chld_value, + DBUS_TYPE_INVALID)) { + BT_ERR("Error Getting parameters"); + return; + } - BT_DBG("+"); - BT_DBG("chld value = [%d]", value); + BT_DBG("chld value = [%d]", chld_value); - switch (value) { + switch (chld_value) { case 0: event = BLUETOOTH_EVENT_TELEPHONY_CHLD_0_RELEASE_ALL_HELD_CALL; break; @@ -445,21 +518,12 @@ static gboolean bluetooth_telephony_method_threeway( break; default: BT_ERR("Invalid CHLD command"); - err = __bluetooth_telephony_error( - BLUETOOTH_TELEPHONY_ERROR_INVALID_CHLD_INDEX, - "Invalid chld command"); - dbus_g_method_return_error(context, err); - g_error_free(err); - return FALSE; + return; } - BT_DBG("event = [%d]", event); - __bt_telephony_event_cb(event, BLUETOOTH_TELEPHONY_ERROR_NONE, NULL); - dbus_g_method_return(context); - BT_DBG("-"); - return TRUE; + FN_END; } static gboolean bluetooth_telephony_method_send_dtmf( @@ -469,10 +533,10 @@ static gboolean bluetooth_telephony_method_send_dtmf( telephony_event_dtmf_t call_data = { 0, }; GError *err; - BT_DBG("+"); + FN_START; if (dtmf == NULL) { - BT_DBG("Number dial failed\n"); + BT_ERR("Number dial failed"); err = __bluetooth_telephony_error( BLUETOOTH_TELEPHONY_ERROR_INVALID_DTMF, "Invalid dtmf"); @@ -481,7 +545,7 @@ static gboolean bluetooth_telephony_method_send_dtmf( return FALSE; } - BT_DBG("Dtmf = %s \n", dtmf); + DBG_SECURE("Dtmf = %s", dtmf); call_data.dtmf = g_strdup(dtmf); @@ -490,7 +554,35 @@ static gboolean bluetooth_telephony_method_send_dtmf( dbus_g_method_return(context); g_free(call_data.dtmf); - BT_DBG("-"); + FN_END; + return TRUE; +} + +static gboolean bluetooth_telephony_method_vendor_cmd( + BluetoothTelephonyMethod *object, + gchar *at_cmd, DBusGMethodInvocation *context) +{ + GError *err; + + FN_START; + + if (at_cmd == NULL) { + BT_ERR("Vendor command is NULL\n"); + err = __bluetooth_telephony_error( + BLUETOOTH_TELEPHONY_ERROR_APPLICATION, + "Invalid at vendor cmd"); + dbus_g_method_return_error(context, err); + g_error_free(err); + return FALSE; + } + + DBG_SECURE("Vendor AT cmd = %s", at_cmd); + + __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_VENDOR_AT_CMD, + BLUETOOTH_TELEPHONY_ERROR_NONE, at_cmd); + + dbus_g_method_return(context); + FN_END; return TRUE; } @@ -501,10 +593,10 @@ static void __bluetooth_handle_nrec_status_change(DBusMessage *msg) if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_BOOLEAN, &status, DBUS_TYPE_INVALID)) { - BT_DBG("Error Getting parameters\n"); + BT_ERR("Error Getting parameters"); return; } - BT_DBG("NREC status = %d\n", status); + BT_INFO("NREC status = %d", status); __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_NREC_CHANGED, BLUETOOTH_TELEPHONY_ERROR_NONE, (void *)&status); @@ -528,6 +620,33 @@ static DBusHandlerResult __bluetooth_telephony_event_filter( return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } + if (dbus_message_is_signal(msg, HFP_AGENT_SERVICE, + HFP_ANSWER_CALL)) { + __bluetooth_telephony_answer_call(msg); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if (dbus_message_is_signal(msg, HFP_AGENT_SERVICE, + HFP_REJECT_CALL)) { + __bluetooth_telephony_reject_call(msg); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if (dbus_message_is_signal(msg, HFP_AGENT_SERVICE, + HFP_RELEASE_CALL)) { + __bluetooth_telephony_release_call(msg); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if (dbus_message_is_signal(msg, HFP_AGENT_SERVICE, + HFP_THREEWAY_CALL)) { + __bluetooth_telephony_threeway_call(msg); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if (!dbus_message_has_interface(msg, BLUEZ_HEADSET_INTERFACE)) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; @@ -541,7 +660,7 @@ static DBusHandlerResult __bluetooth_telephony_event_filter( if (property == NULL) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - BT_DBG("Property (%s)\n", property); + BT_DBG("Property (%s)", property); if (g_strcmp0(property, "State") == 0) { char *state = NULL; @@ -549,10 +668,10 @@ static DBusHandlerResult __bluetooth_telephony_event_filter( dbus_message_iter_recurse(&item_iter, &value_iter); dbus_message_iter_get_basic(&value_iter, &state); if (NULL == state) { - BT_ERR("State is null\n"); + BT_ERR("State is null"); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } - BT_DBG("State %s\n", state); + BT_DBG("State : %s", state); if (g_strcmp0(state, "connected") == 0) { telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED; @@ -561,12 +680,6 @@ static DBusHandlerResult __bluetooth_telephony_event_filter( } else if (g_strcmp0(state, "disconnected") == 0) { /* Headset state: playing -> disconnected */ if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING) { - if (!vconf_set_bool(VCONFKEY_BT_HEADSET_SCO, FALSE)) { - BT_DBG("SVCONFKEY_BT_HEADSET_SCO - Set to FALSE\n"); - } else { - BT_DBG("vconf_set_bool - Failed\n"); - } - __bt_telephony_event_cb( BLUETOOTH_EVENT_TELEPHONY_AUDIO_DISCONNECTED, BLUETOOTH_TELEPHONY_ERROR_NONE, NULL); @@ -583,7 +696,7 @@ static DBusHandlerResult __bluetooth_telephony_event_filter( dbus_message_iter_next(&item_iter); dbus_message_iter_recurse(&item_iter, &value_iter); dbus_message_iter_get_basic(&value_iter, &connected); - BT_DBG("Connected %d\n", connected); + BT_DBG("Connected : %d", connected); if (connected) { /*Get device address*/ @@ -610,7 +723,7 @@ static DBusHandlerResult __bluetooth_telephony_event_filter( telephony_dbus_info.proxy = __bluetooth_telephony_get_connected_device_proxy(); - BT_DBG("Headset Connected"); + BT_INFO("Headset Connected"); __bt_telephony_event_cb( BLUETOOTH_EVENT_TELEPHONY_HFP_CONNECTED, @@ -627,7 +740,7 @@ static DBusHandlerResult __bluetooth_telephony_event_filter( telephony_dbus_info.proxy = NULL; } - BT_DBG("Headset Disconnected"); + BT_INFO("Headset Disconnected"); __bt_telephony_event_cb( BLUETOOTH_EVENT_TELEPHONY_HFP_DISCONNECTED, @@ -644,7 +757,7 @@ static DBusHandlerResult __bluetooth_telephony_event_filter( dbus_message_iter_get_basic(&value_iter, &gain); spkr_gain = (unsigned int)gain; - BT_DBG("spk_gain[%d]\n", spkr_gain); + BT_DBG("spk_gain[%d]", spkr_gain); __bt_telephony_event_cb( BLUETOOTH_EVENT_TELEPHONY_SET_SPEAKER_GAIN, @@ -662,7 +775,7 @@ static DBusHandlerResult __bluetooth_telephony_event_filter( dbus_message_iter_get_basic(&value_iter, &gain); mic_gain = (unsigned int)gain; - BT_DBG("mic_gain[%d]\n", mic_gain); + BT_DBG("mic_gain[%d]", mic_gain); __bt_telephony_event_cb( BLUETOOTH_EVENT_TELEPHONY_SET_MIC_GAIN, @@ -679,23 +792,11 @@ static DBusHandlerResult __bluetooth_telephony_event_filter( dbus_message_iter_get_basic(&value_iter, &audio_sink_playing); if (audio_sink_playing) { - if (!vconf_set_bool(VCONFKEY_BT_HEADSET_SCO, TRUE)) { - BT_DBG("SVCONFKEY_BT_HEADSET_SCO -" - "Set to TRUE\n"); - } else { - BT_DBG("vconf_set_bool - Failed\n"); - } telephony_info.headset_state = BLUETOOTH_STATE_PLAYING; __bt_telephony_event_cb( BLUETOOTH_EVENT_TELEPHONY_AUDIO_CONNECTED, BLUETOOTH_TELEPHONY_ERROR_NONE, NULL); } else { - if (!vconf_set_bool(VCONFKEY_BT_HEADSET_SCO, FALSE)) { - BT_DBG("SVCONFKEY_BT_HEADSET_SCO -" - "Set to FALSE\n"); - } else { - BT_DBG("vconf_set_bool - Failed\n"); - } telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED; __bt_telephony_event_cb( @@ -708,9 +809,10 @@ static DBusHandlerResult __bluetooth_telephony_event_filter( return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } + static int __bluetooth_telephony_proxy_init(void) { - BT_DBG("+"); + FN_START; object = (GObject *)__bluetooth_telephony_method_new(); @@ -722,13 +824,13 @@ static int __bluetooth_telephony_proxy_init(void) dbus_g_connection_register_g_object(telephony_dbus_info.conn, telephony_info.call_path, G_OBJECT(object)); - BT_DBG("-"); + FN_END; return BLUETOOTH_TELEPHONY_ERROR_NONE; } static void __bluetooth_telephony_proxy_deinit(void) { - BT_DBG("+"); + FN_START; dbus_g_connection_unregister_g_object(telephony_dbus_info.conn, G_OBJECT(object)); @@ -736,7 +838,7 @@ static void __bluetooth_telephony_proxy_deinit(void) g_object_unref(object); object = NULL; - BT_DBG("-"); + FN_END; return; } @@ -747,16 +849,17 @@ static int __bluetooth_telephony_register(void) char *path = g_strdup(telephony_info.call_path); int ret; - BT_DBG("+"); + FN_START; reply = __bluetooth_telephony_dbus_method_send( HFP_AGENT_PATH, HFP_AGENT_INTERFACE, "RegisterApplication", &err, DBUS_TYPE_STRING, &path, + DBUS_TYPE_STRING, &src_addr, DBUS_TYPE_INVALID); g_free(path); if (!reply) { - BT_ERR("Error returned in method call\n"); + BT_ERR("Error returned in method call"); if (dbus_error_is_set(&err)) { ret = __bt_telephony_get_error(err.message); BT_ERR("Error here %d\n", ret); @@ -767,7 +870,8 @@ static int __bluetooth_telephony_register(void) } dbus_message_unref(reply); - BT_DBG("-"); + BT_DBG("__bluetooth_telephony_register completed"); + FN_END; return BLUETOOTH_TELEPHONY_ERROR_NONE; } @@ -778,7 +882,7 @@ static int __bluetooth_telephony_unregister(void) char *path = g_strdup(telephony_info.call_path); int ret; - BT_DBG("+"); + FN_START; reply = __bluetooth_telephony_dbus_method_send( HFP_AGENT_PATH, HFP_AGENT_INTERFACE, @@ -787,7 +891,7 @@ static int __bluetooth_telephony_unregister(void) g_free(path); if (!reply) { - BT_ERR("Error returned in method call\n"); + BT_ERR("Error returned in method call"); if (dbus_error_is_set(&err)) { ret = __bt_telephony_get_error(err.message); dbus_error_free(&err); @@ -797,91 +901,67 @@ static int __bluetooth_telephony_unregister(void) } dbus_message_unref(reply); - BT_DBG("+"); + BT_DBG("__bluetooth_telephony_unregister completed"); + FN_END; return BLUETOOTH_TELEPHONY_ERROR_NONE; } -static int __bluetooth_get_default_adapter_path(DBusGConnection *GConn, - char *path) +#ifndef TIZEN_WEARABLE +static void __bluetooth_telephony_init_headset_state(void) { - DBusMessage *msg; DBusMessage *reply; - DBusMessageIter reply_iter; - DBusMessageIter value_iter; DBusError err; - DBusConnection *conn; - char *adapter_path = NULL; - - BT_DBG("+"); - conn = dbus_g_connection_get_connection(telephony_dbus_info.conn); - - retv_if(conn == NULL, NULL); + gboolean status = FALSE; - msg = dbus_message_new_method_call(BT_BLUEZ_NAME, BT_MANAGER_PATH, - BT_MANAGER_INTERFACE, - "GetManagedObjects"); + FN_START; - retv_if(msg == NULL, NULL); - /* Synchronous call */ - dbus_error_init(&err); - reply = dbus_connection_send_with_reply_and_block( - conn, msg, -1, &err); - dbus_message_unref(msg); + if (telephony_dbus_info.conn == NULL) { + BT_ERR("Bluetooth telephony not initilized"); + return; + } + reply = __bluetooth_telephony_dbus_method_send( + HFP_AGENT_PATH, HFP_AGENT_INTERFACE, + "IsConnected", &err, DBUS_TYPE_INVALID); if (!reply) { - BT_ERR("Can't get managed objects"); - + BT_ERR("Error returned in method call\n"); if (dbus_error_is_set(&err)) { - BT_ERR("%s", err.message); + __bt_telephony_get_error(err.message); dbus_error_free(&err); } - return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; - } - - if (dbus_message_iter_init(reply, &reply_iter) == FALSE) { - BT_ERR("Fail to iterate the reply"); - return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + return; } - dbus_message_iter_recurse(&reply_iter, &value_iter); - - /* signature of GetManagedObjects: a{oa{sa{sv}}} */ - while (dbus_message_iter_get_arg_type(&value_iter) == - DBUS_TYPE_DICT_ENTRY) { - DBusMessageIter msg_iter; - - dbus_message_iter_recurse(&value_iter, &msg_iter); - - adapter_path = __bt_get_default_adapter_path(&msg_iter); - if (adapter_path != NULL) { - BT_DBG("Found the adapter path"); - break; + if (!dbus_message_get_args(reply, &err, + DBUS_TYPE_BOOLEAN, &status, + DBUS_TYPE_INVALID)) { + BT_ERR("Error to get features"); + if (dbus_error_is_set(&err)) { + BT_ERR("error message: %s", err.message); + dbus_error_free(&err); } - dbus_message_iter_next(&value_iter); + dbus_message_unref(reply); + return; } - if (adapter_path == NULL) { - return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; - } + BT_INFO("Headset Connected Status = [%d]", status); + if (status) + telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED; + else + return; - if (strlen(adapter_path) >= BT_ADAPTER_PATH_LEN) { - BT_ERR("Path too long.\n"); - g_free(adapter_path); - return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; - } + if (bluetooth_telephony_is_sco_connected()) + telephony_info.headset_state = BLUETOOTH_STATE_PLAYING; - BT_DBG("object path = %s", adapter_path); - g_strlcpy(path, adapter_path, BT_ADAPTER_PATH_LEN); - g_free(adapter_path); - BT_DBG("-"); - return BLUETOOTH_TELEPHONY_ERROR_NONE; + FN_END; } +#endif static gboolean __bluetooth_telephony_is_headset(uint32_t device_class) { gboolean flag = FALSE; - BT_DBG("+"); + FN_START; switch ((device_class & 0x1f00) >> 8) { case 0x04: @@ -902,11 +982,58 @@ static gboolean __bluetooth_telephony_is_headset(uint32_t device_class) break; } break; + + /* Tizen Wearable device */ + case 0x07: + switch ((device_class & 0xfc) >> 2) { + case 0x01: /* Wrist Watch */ + flag = TRUE; + break; + default: + break; + } + break; } - BT_DBG("-"); + BT_DBG("[%d]", flag); + FN_END; return flag; } +static gboolean __bluetooth_telephony_is_headset_by_uuid(GValue *value) +{ + int i; + char **uuids; + char **parts; + unsigned int service = 0; + + FN_START; + + retv_if(value == NULL, FALSE); + + uuids = g_value_get_boxed(value); + retv_if(uuids == NULL, FALSE); + + for (i = 0; uuids[i] != NULL; i++) { + parts = g_strsplit(uuids[i], "-", -1); + + if (parts == NULL || parts[0] == NULL) { + g_strfreev(parts); + continue; + } + + service = g_ascii_strtoull(parts[0], NULL, 16); + g_strfreev(parts); + + if (service == BLUETOOTH_HS_PROFILE_UUID || + service == BLUETOOTH_HF_PROFILE_UUID) + return TRUE; + } + + FN_END; + return FALSE; +} + + static int __bluetooth_telephony_get_connected_device(void) { DBusMessage *msg; @@ -921,20 +1048,21 @@ static int __bluetooth_telephony_get_connected_device(void) uint32_t device_class; gboolean playing = FALSE; gboolean connected = FALSE; - GHashTable *list_hash; + GHashTable *list_hash = NULL; GValue *value = {0}; char *object_path = NULL; DBusGProxy *proxy = NULL; const gchar *address; + FN_START; conn = _bt_get_system_conn(); - retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + retv_if(conn == NULL, BLUETOOTH_TELEPHONY_ERROR_INTERNAL); msg = dbus_message_new_method_call(BLUEZ_SERVICE_NAME, "/", BLUEZ_MANAGER_INTERFACE, "GetManagedObjects"); - retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL); + retv_if(msg == NULL, BLUETOOTH_TELEPHONY_ERROR_INTERNAL); /* Synchronous call */ dbus_error_init(&err); @@ -950,12 +1078,13 @@ static int __bluetooth_telephony_get_connected_device(void) BT_ERR("%s", err.message); dbus_error_free(&err); } - return BLUETOOTH_ERROR_INTERNAL; + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; } if (dbus_message_iter_init(reply, &reply_iter) == FALSE) { BT_ERR("Fail to iterate the reply"); - return BLUETOOTH_ERROR_INTERNAL; + dbus_message_unref(reply); + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; } dbus_message_iter_recurse(&reply_iter, &value_iter); @@ -969,37 +1098,63 @@ static int __bluetooth_telephony_get_connected_device(void) /* Parse the signature: oa{sa{sv}}} */ retv_if(dbus_message_iter_get_arg_type(&msg_iter) != - DBUS_TYPE_OBJECT_PATH, NULL); + DBUS_TYPE_OBJECT_PATH, + BLUETOOTH_TELEPHONY_ERROR_INTERNAL); dbus_message_iter_get_basic(&msg_iter, &object_path); - if (object_path) { - proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn, - BLUEZ_SERVICE_NAME, object_path, - BLUEZ_PROPERTIES_INTERFACE); - + proxy = dbus_g_proxy_new_for_name( + telephony_dbus_info.conn, + BLUEZ_SERVICE_NAME, + object_path, + BLUEZ_PROPERTIES_INTERFACE); if (proxy == NULL) goto done; - dbus_g_proxy_call(proxy, "GetAll", &err, - G_TYPE_STRING, BLUEZ_DEVICE_INTERFACE, + dbus_g_proxy_call(proxy, "GetAll", &error, + G_TYPE_STRING, + BLUEZ_DEVICE_INTERFACE, G_TYPE_INVALID, - dbus_g_type_get_map("GHashTable", G_TYPE_STRING, - G_TYPE_VALUE), &list_hash, G_TYPE_INVALID); + dbus_g_type_get_map("GHashTable", + G_TYPE_STRING, + G_TYPE_VALUE), + &list_hash, + G_TYPE_INVALID); + if (list_hash == NULL) + goto done; - if (list_hash != NULL) { - value = g_hash_table_lookup(list_hash, "Class"); - device_class = value ? g_value_get_uint(value) : 0; + if (error) { + BT_ERR("error in GetBasicProperties [%s]\n", error->message); + g_error_free(error); + goto done; } - if (!__bluetooth_telephony_is_headset(device_class)) { - g_object_unref(proxy); - proxy = NULL; - g_hash_table_destroy(list_hash); - dbus_message_iter_next(&value_iter); - continue; + value = g_hash_table_lookup(list_hash, "Class"); + device_class = value ? g_value_get_uint(value) : 0; + + if (device_class == 0) { + BT_DBG("COD is NULL (maybe paired by nfc)... Checking UUIDs"); + value = g_hash_table_lookup(list_hash, "UUIDs"); + if (!__bluetooth_telephony_is_headset_by_uuid(value)) { + BT_DBG("UUID checking completed. None HF device"); + g_object_unref(proxy); + proxy = NULL; + g_hash_table_destroy(list_hash); + dbus_message_iter_next(&value_iter); + continue; + } + BT_DBG("UUID checking completed. HF device"); + } else { + if (!__bluetooth_telephony_is_headset(device_class)) { + g_object_unref(proxy); + proxy = NULL; + g_hash_table_destroy(list_hash); + dbus_message_iter_next(&value_iter); + continue; + } } + /* this is headset; Check for Connection */ headset_agent_proxy = dbus_g_proxy_new_for_name( telephony_dbus_info.conn, @@ -1013,21 +1168,26 @@ static int __bluetooth_telephony_get_connected_device(void) dbus_g_proxy_call(headset_agent_proxy, "IsConnected", &error, G_TYPE_INVALID, - &connected, G_TYPE_INVALID); + G_TYPE_BOOLEAN, &connected, + G_TYPE_INVALID); if (error == NULL) { if (connected) { value = g_hash_table_lookup(list_hash, "Address"); address = value ? g_value_get_string( - value) : NULL; - - g_strlcpy(telephony_info.address, address, - sizeof(telephony_info.address)); - dbus_g_proxy_call(headset_agent_proxy, "IsPlaying", - &error, G_TYPE_INVALID, - &playing, G_TYPE_INVALID); - + value) : NULL; + + g_strlcpy(telephony_info.address, + address, + sizeof(telephony_info.address)); + dbus_g_proxy_call(headset_agent_proxy, + "IsPlaying", + &error, + G_TYPE_INVALID, + G_TYPE_BOOLEAN, + &playing, + G_TYPE_INVALID); if (playing) telephony_info.headset_state = BLUETOOTH_STATE_PLAYING; @@ -1053,39 +1213,34 @@ static int __bluetooth_telephony_get_connected_device(void) done: if (proxy) g_object_unref(proxy); - BT_DBG("-"); - return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + + dbus_message_unref(reply); + + FN_END; + return BLUETOOTH_TELEPHONY_ERROR_NONE; } static DBusGProxy *__bluetooth_telephony_get_connected_device_proxy(void) { DBusGProxy *proxy = NULL; - char *object_path = NULL; - BT_DBG("+"); + FN_START; if (strlen(telephony_info.address) == 0) __bluetooth_telephony_get_connected_device(); - if (strlen(telephony_info.address) == 0) { + if (strlen(telephony_info.address) == 0) return NULL; - } - - if (telephony_info.obj_path) { - g_free(telephony_info.obj_path); - telephony_info.obj_path = NULL; - } - - object_path = _bt_get_device_object_path(telephony_info.address); - g_strlcpy(telephony_info.obj_path, object_path, BT_ADAPTER_PATH_LEN); proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn, - HFP_AGENT_SERVICE, telephony_info.obj_path, + HFP_AGENT_SERVICE, HFP_AGENT_PATH, HFP_AGENT_INTERFACE); + FN_END; return proxy; } + BT_EXPORT_API int bluetooth_telephony_init(bt_telephony_func_ptr cb, void *user_data) { @@ -1093,10 +1248,13 @@ BT_EXPORT_API int bluetooth_telephony_init(bt_telephony_func_ptr cb, DBusConnection *conn; int ret = BLUETOOTH_TELEPHONY_ERROR_NONE; GError *error = NULL; - char object_path[BT_ADAPTER_PATH_LEN] = {0}; - BT_DBG("+"); + DBusConnection *dbus_conn; + bluetooth_device_address_t loc_address = { {0} }; + char src_address[BT_ADDRESS_STRING_SIZE] = { 0 }; + + FN_START; g_type_init(); if (is_initialized == TRUE) { @@ -1162,19 +1320,18 @@ BT_EXPORT_API int bluetooth_telephony_init(bt_telephony_func_ptr cb, dbus_conn = dbus_g_connection_get_connection(telephony_dbus_info.conn); /*Add Signal callback for BT enabled*/ - if (!dbus_connection_add_filter(dbus_conn, __bt_telephony_adapter_filter, - NULL, NULL)) { + if (!dbus_connection_add_filter(dbus_conn, + __bt_telephony_adapter_filter, + NULL, NULL)) { BT_ERR("Fail to add filter"); return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; } dbus_error_init(&dbus_error); - dbus_bus_add_match(dbus_conn, "type='signal',interface='org.freedesktop.DBus.ObjectManager'" ",member='InterfacesAdded'", &dbus_error); - if (dbus_error_is_set(&dbus_error)) { BT_ERR("Fail to add match: %s\n", dbus_error.message); dbus_error_free(&dbus_error); @@ -1190,38 +1347,92 @@ BT_EXPORT_API int bluetooth_telephony_init(bt_telephony_func_ptr cb, conn = dbus_g_connection_get_connection(telephony_dbus_info.conn); dbus_connection_add_filter(conn, __bluetooth_telephony_event_filter, NULL, NULL); - dbus_bus_add_match(conn, - "type='signal',interface='"HFP_AGENT_SERVICE + "type='signal',interface='"BLUEZ_HEADSET_INTERFACE "',member='PropertyChanged'", &dbus_error); + if (dbus_error_is_set(&dbus_error)) { + BT_ERR("Fail to add dbus filter signal\n"); + dbus_error_free(&dbus_error); + goto fail; + } + + dbus_error_init(&dbus_error); dbus_bus_add_match(conn, "type='signal',interface='"HFP_AGENT_SERVICE "',member='"HFP_NREC_STATUS_CHANGE"'" , &dbus_error); + if (dbus_error_is_set(&dbus_error)) { + BT_ERR("Fail to add dbus filter signal\n"); + dbus_error_free(&dbus_error); + goto fail; + } + + dbus_error_init(&dbus_error); + dbus_bus_add_match(conn, + "type='signal',interface='"HFP_AGENT_SERVICE + "',member='"HFP_ANSWER_CALL"'" , &dbus_error); + if (dbus_error_is_set(&dbus_error)) { + BT_ERR("Fail to add dbus filter signal\n"); + dbus_error_free(&dbus_error); + goto fail; + } + dbus_error_init(&dbus_error); + dbus_bus_add_match(conn, + "type='signal',interface='"HFP_AGENT_SERVICE + "',member='"HFP_REJECT_CALL"'" , &dbus_error); if (dbus_error_is_set(&dbus_error)) { BT_ERR("Fail to add dbus filter signal\n"); dbus_error_free(&dbus_error); goto fail; } - /*Check for BT status*/ - ret = __bluetooth_get_default_adapter_path(telephony_dbus_info.conn, - object_path); - if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) + dbus_error_init(&dbus_error); + dbus_bus_add_match(conn, + "type='signal',interface='"HFP_AGENT_SERVICE + "',member='"HFP_RELEASE_CALL"'" , &dbus_error); + if (dbus_error_is_set(&dbus_error)) { + BT_ERR("Fail to add dbus filter signal\n"); + dbus_error_free(&dbus_error); + goto fail; + } + + dbus_error_init(&dbus_error); + dbus_bus_add_match(conn, + "type='signal',interface='"HFP_AGENT_SERVICE + "',member='"HFP_THREEWAY_CALL"'" , &dbus_error); + if (dbus_error_is_set(&dbus_error)) { + BT_ERR("Fail to add dbus filter signal\n"); + dbus_error_free(&dbus_error); + goto fail; + } + + if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED) return BLUETOOTH_TELEPHONY_ERROR_NONE; /*Bluetooth is active, therefore set the flag */ is_active = TRUE; - + if (!src_addr) { + ret = bluetooth_get_local_address(&loc_address); + if (ret != BLUETOOTH_ERROR_NONE) { + BT_ERR("Fail to get local address\n"); + ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + goto fail; + } + _bt_convert_addr_type_to_string(src_address, loc_address.addr); + src_addr = g_strdup(src_address); + } ret = __bluetooth_telephony_register(); if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) { BT_ERR("__bluetooth_telephony_register failed\n"); goto fail; } - BT_DBG("-"); - return ret; +#ifndef TIZEN_WEARABLE + __bluetooth_telephony_init_headset_state(); +#endif + FN_END; + return ret; fail: bluetooth_telephony_deinit(); return ret; @@ -1232,18 +1443,25 @@ BT_EXPORT_API int bluetooth_telephony_deinit(void) DBusConnection *conn; DBusError error; - BT_DBG("+"); - + FN_START; BT_TELEPHONY_CHECK_INITIALIZED(); is_initialized = FALSE; + conn = dbus_g_connection_get_connection(telephony_dbus_info.conn); dbus_error_init(&error); - dbus_bus_remove_match(conn, - "type='signal',interface='"HFP_AGENT_SERVICE + "type='signal',interface='"BLUEZ_HEADSET_INTERFACE "',member='PropertyChanged'", &error); + if (dbus_error_is_set(&error)) { + BT_ERR("Fail to remove dbus filter signal\n"); + dbus_error_free(&error); + /* Need to re initilize before use */ + dbus_error_init(&error); + } + + dbus_error_init(&error); dbus_bus_remove_match(conn, "type='signal',interface='"HFP_AGENT_SERVICE "',member='"HFP_NREC_STATUS_CHANGE"'", &error); @@ -1252,10 +1470,48 @@ BT_EXPORT_API int bluetooth_telephony_deinit(void) dbus_error_free(&error); } - dbus_connection_remove_filter(conn, __bluetooth_telephony_event_filter, - NULL); + dbus_error_init(&error); + dbus_bus_remove_match(conn, + "type='signal',interface='"HFP_AGENT_SERVICE + "',member='"HFP_ANSWER_CALL"'", &error); + if (dbus_error_is_set(&error)) { + BT_ERR("Fail to remove dbus filter signal\n"); + dbus_error_free(&error); + } + + dbus_error_init(&error); + dbus_bus_remove_match(conn, + "type='signal',interface='"HFP_AGENT_SERVICE + "',member='"HFP_REJECT_CALL"'", &error); + if (dbus_error_is_set(&error)) { + BT_ERR("Fail to remove dbus filter signal\n"); + dbus_error_free(&error); + } - if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_ENABLED) + dbus_error_init(&error); + dbus_bus_remove_match(conn, + "type='signal',interface='"HFP_AGENT_SERVICE + "',member='"HFP_RELEASE_CALL"'", &error); + if (dbus_error_is_set(&error)) { + BT_ERR("Fail to remove dbus filter signal\n"); + dbus_error_free(&error); + } + + dbus_error_init(&error); + dbus_bus_remove_match(conn, + "type='signal',interface='"HFP_AGENT_SERVICE + "',member='"HFP_THREEWAY_CALL"'", &error); + if (dbus_error_is_set(&error)) { + BT_ERR("Fail to remove dbus filter signal\n"); + dbus_error_free(&error); + } + + dbus_connection_remove_filter(conn, + __bluetooth_telephony_event_filter, + NULL); + + if (bluetooth_check_adapter() != BLUETOOTH_ADAPTER_DISABLED || + bluetooth_check_adapter_le() != BLUETOOTH_ADAPTER_LE_DISABLED) __bluetooth_telephony_unregister(); __bluetooth_telephony_proxy_deinit(); @@ -1265,7 +1521,8 @@ BT_EXPORT_API int bluetooth_telephony_deinit(void) telephony_info.call_count = 0; telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED; - /*Remove BT enabled signal*/ + /* Remove BT enabled signal */ + dbus_error_init(&error); dbus_bus_remove_match(conn, "type='signal',interface='org.freedesktop.DBus.ObjectManager'" ",member='InterfacesAdded'", @@ -1276,55 +1533,86 @@ BT_EXPORT_API int bluetooth_telephony_deinit(void) } dbus_connection_remove_filter(dbus_g_connection_get_connection( - telephony_dbus_info.conn), __bt_telephony_adapter_filter, - NULL); + telephony_dbus_info.conn), + __bt_telephony_adapter_filter, + NULL); + g_free(src_addr); + src_addr = NULL; - g_object_unref(telephony_dbus_info.manager_proxy); - telephony_dbus_info.manager_proxy = NULL; + if (telephony_dbus_info.manager_proxy != NULL) { + g_object_unref(telephony_dbus_info.manager_proxy); + telephony_dbus_info.manager_proxy = NULL; + } - dbus_g_connection_unref(telephony_dbus_info.conn); - telephony_dbus_info.conn = NULL; + if (telephony_dbus_info.conn != NULL) { + dbus_g_connection_unref(telephony_dbus_info.conn); + telephony_dbus_info.conn = NULL; + } - g_object_unref(telephony_dbus_info.dbus_proxy); - telephony_dbus_info.dbus_proxy = NULL; + if (telephony_dbus_info.dbus_proxy != NULL) { + g_object_unref(telephony_dbus_info.dbus_proxy); + telephony_dbus_info.dbus_proxy = NULL; + } - BT_DBG("-"); + FN_END; return BLUETOOTH_TELEPHONY_ERROR_NONE; } BT_EXPORT_API gboolean bluetooth_telephony_is_sco_connected(void) { - BT_DBG("+"); + DBusMessage *reply; + DBusError err; - if (telephony_dbus_info.conn == NULL) { - BT_ERR("Bluetooth telephony not initilized"); + gboolean status = FALSE; + + FN_START; + + retv_if(is_initialized == FALSE, FALSE); + retv_if(bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED, FALSE); + + reply = __bluetooth_telephony_dbus_method_send( + HFP_AGENT_PATH, HFP_AGENT_INTERFACE, + "IsPlaying", &err, DBUS_TYPE_INVALID); + + if (!reply) { + BT_ERR("Error returned in method call\n"); + if (dbus_error_is_set(&err)) { + __bt_telephony_get_error(err.message); + dbus_error_free(&err); + } return FALSE; } - /* To get the headset state */ - if (telephony_dbus_info.proxy == NULL) - telephony_dbus_info.proxy = - __bluetooth_telephony_get_connected_device_proxy(); - - if (telephony_dbus_info.proxy == NULL) + if (!dbus_message_get_args(reply, &err, + DBUS_TYPE_BOOLEAN, &status, + DBUS_TYPE_INVALID)) { + BT_ERR("Error to get features"); + if (dbus_error_is_set(&err)) { + BT_ERR("error message: %s", err.message); + dbus_error_free(&err); + } + dbus_message_unref(reply); return FALSE; + } - if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING) - return TRUE; +#ifdef TIZEN_WEARABLE + if (status == TRUE && telephony_info.headset_state != BLUETOOTH_STATE_PLAYING) + telephony_info.headset_state = BLUETOOTH_STATE_PLAYING; +#endif - BT_DBG("-"); - return FALSE; + BT_INFO("SCO Connected Status = [%d]", status); + return status; } BT_EXPORT_API int bluetooth_telephony_is_nrec_enabled(gboolean *status) { - DBusMessage* reply; + DBusMessage *reply; DBusError err; DBusMessageIter reply_iter; DBusMessageIter reply_iter_entry; const char *property; - BT_DBG("+"); + FN_START; BT_TELEPHONY_CHECK_INITIALIZED(); BT_TELEPHONY_CHECK_ENABLED(); @@ -1332,6 +1620,9 @@ BT_EXPORT_API int bluetooth_telephony_is_nrec_enabled(gboolean *status) if (status == NULL) return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM; + if (telephony_info.headset_state == BLUETOOTH_STATE_DISCONNETED) + return BLUETOOTH_TELEPHONY_ERROR_AUDIO_NOT_CONNECTED; + reply = __bluetooth_telephony_dbus_method_send( HFP_AGENT_PATH, HFP_AGENT_INTERFACE, "GetProperties", &err, DBUS_TYPE_INVALID); @@ -1339,7 +1630,7 @@ BT_EXPORT_API int bluetooth_telephony_is_nrec_enabled(gboolean *status) if (!reply) { BT_ERR("Error returned in method call\n"); if (dbus_error_is_set(&err)) { - BT_DBG("Error message = %s \n", err.message); + BT_DBG("Error message = %s", err.message); dbus_error_free(&err); } return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; @@ -1348,7 +1639,8 @@ BT_EXPORT_API int bluetooth_telephony_is_nrec_enabled(gboolean *status) dbus_message_iter_init(reply, &reply_iter); if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) { - BT_ERR("Can't get reply arguments - DBUS_TYPE_ARRAY\n"); + BT_ERR("Can't get reply arguments - DBUS_TYPE_ARRAY"); + dbus_message_unref(reply); return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; } @@ -1361,7 +1653,7 @@ BT_EXPORT_API int bluetooth_telephony_is_nrec_enabled(gboolean *status) DBusMessageIter dict_entry, dict_entry_val; dbus_message_iter_recurse(&reply_iter_entry, &dict_entry); dbus_message_iter_get_basic(&dict_entry, &property); - BT_DBG("String received = %s\n", property); + BT_DBG("String received = %s", property); if (g_strcmp0("nrec", property) == 0) { dbus_message_iter_next(&dict_entry); @@ -1376,20 +1668,91 @@ BT_EXPORT_API int bluetooth_telephony_is_nrec_enabled(gboolean *status) dbus_message_iter_next(&reply_iter_entry); } dbus_message_unref(reply); - BT_DBG("-"); + FN_END; return BLUETOOTH_TELEPHONY_ERROR_NONE; } -BT_EXPORT_API int bluetooth_telephony_start_voice_recognition(void) +BT_EXPORT_API int bluetooth_telephony_is_wbs_mode(gboolean *status) +{ + DBusMessage *reply; + DBusError err; + DBusMessageIter reply_iter; + DBusMessageIter reply_iter_entry; + unsigned int codec; + const char *property; + + FN_START; + + BT_TELEPHONY_CHECK_INITIALIZED(); + BT_TELEPHONY_CHECK_ENABLED(); + + if (status == NULL) + return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM; + + *status = FALSE; + + reply = __bluetooth_telephony_dbus_method_send( + HFP_AGENT_PATH, HFP_AGENT_INTERFACE, + "GetProperties", &err, DBUS_TYPE_INVALID); + + if (!reply) { + BT_ERR("Error returned in method call"); + if (dbus_error_is_set(&err)) { + BT_ERR("Error message = %s", err.message); + dbus_error_free(&err); + } + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + } + + dbus_message_iter_init(reply, &reply_iter); + + if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) { + BT_ERR("Can't get reply arguments - DBUS_TYPE_ARRAY"); + dbus_message_unref(reply); + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + } + + dbus_message_iter_recurse(&reply_iter, &reply_iter_entry); + + /*Parse the dict */ + while (dbus_message_iter_get_arg_type(&reply_iter_entry) == + DBUS_TYPE_DICT_ENTRY) { + + DBusMessageIter dict_entry, dict_entry_val; + dbus_message_iter_recurse(&reply_iter_entry, &dict_entry); + dbus_message_iter_get_basic(&dict_entry, &property); + BT_DBG("String received = %s", property); + + if (g_strcmp0("codec", property) == 0) { + dbus_message_iter_next(&dict_entry); + dbus_message_iter_recurse(&dict_entry, &dict_entry_val); + if (dbus_message_iter_get_arg_type(&dict_entry_val) != + DBUS_TYPE_UINT32) + continue; + + dbus_message_iter_get_basic(&dict_entry_val, &codec); + BT_DBG("Codec = [%d]", codec); + *status = codec == BT_MSBC_CODEC_ID ? TRUE : FALSE; + } + dbus_message_iter_next(&reply_iter_entry); + } + dbus_message_unref(reply); + FN_END; + return BLUETOOTH_TELEPHONY_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_telephony_send_vendor_cmd(const char *cmd) { GError *error = NULL; int ret; - BT_DBG("+"); + FN_START; BT_TELEPHONY_CHECK_INITIALIZED(); BT_TELEPHONY_CHECK_ENABLED(); + BT_DBG("Send Vendor %s", cmd); + if (telephony_dbus_info.proxy == NULL) telephony_dbus_info.proxy = __bluetooth_telephony_get_connected_device_proxy(); @@ -1397,113 +1760,225 @@ BT_EXPORT_API int bluetooth_telephony_start_voice_recognition(void) if (telephony_dbus_info.proxy == NULL) return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; - if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "SetVoiceDial", - &error, G_TYPE_BOOLEAN, TRUE, G_TYPE_INVALID, - G_TYPE_INVALID)) { + if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "SendVendorAtCmd", + &error, + G_TYPE_STRING, cmd, + G_TYPE_INVALID, G_TYPE_INVALID)) { if (error != NULL) { ret = __bt_telephony_get_error(error->message); g_error_free(error); return ret; } + } + FN_END; + return BLUETOOTH_TELEPHONY_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_telephony_start_voice_recognition(void) +{ + DBusMessage *reply; + DBusError err; + int ret; + gboolean state = TRUE; + + FN_START; + + BT_TELEPHONY_CHECK_INITIALIZED(); + BT_TELEPHONY_CHECK_ENABLED(); - BT_DBG("-"); + reply = __bluetooth_telephony_dbus_method_send( + HFP_AGENT_PATH, HFP_AGENT_INTERFACE, + "SetVoiceDial", &err, DBUS_TYPE_BOOLEAN, &state, + DBUS_TYPE_INVALID); + + if (!reply) { + BT_ERR("Error returned in method call\n"); + if (dbus_error_is_set(&err)) { + ret = __bt_telephony_get_error(err.message); + dbus_error_free(&err); + return ret; + } + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + } + + dbus_message_unref(reply); + + FN_END; return BLUETOOTH_TELEPHONY_ERROR_NONE; } BT_EXPORT_API int bluetooth_telephony_stop_voice_recognition(void) { - GError *error = NULL; + DBusMessage *reply; + DBusError err; int ret; + gboolean state = FALSE; - BT_DBG("+"); + FN_START; BT_TELEPHONY_CHECK_INITIALIZED(); BT_TELEPHONY_CHECK_ENABLED(); - if (telephony_dbus_info.proxy == NULL) - return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + reply = __bluetooth_telephony_dbus_method_send( + HFP_AGENT_PATH, HFP_AGENT_INTERFACE, + "SetVoiceDial", &err, DBUS_TYPE_BOOLEAN, &state, + DBUS_TYPE_INVALID); - if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "SetVoiceDial", - &error, G_TYPE_BOOLEAN, - FALSE, G_TYPE_INVALID, G_TYPE_INVALID)) { - BT_ERR("Dbus Call Failed!\n"); - if (error != NULL) { - ret = __bt_telephony_get_error(error->message); - g_error_free(error); + if (!reply) { + BT_ERR("Error returned in method call\n"); + if (dbus_error_is_set(&err)) { + ret = __bt_telephony_get_error(err.message); + dbus_error_free(&err); return ret; } + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; } - BT_DBG("-"); + dbus_message_unref(reply); + + FN_END; return BLUETOOTH_TELEPHONY_ERROR_NONE; } +static void __bluetooth_telephony_sco_start_cb( + DBusPendingCall *call, gpointer user_data) +{ + DBusMessage *reply; + DBusError derr; + DBusMessage *msg = user_data; + + reply = dbus_pending_call_steal_reply(call); + dbus_error_init(&derr); + + if (dbus_set_error_from_message(&derr, reply)) { + BT_ERR("hs_sco_cb error: %s, %s", + derr.name, derr.message); + dbus_error_free(&derr); + goto done; + } + dbus_pending_call_unref(call); +done: + BT_DBG("sco_start_cb : -"); + dbus_message_unref(msg); + dbus_message_unref(reply); +} + BT_EXPORT_API int bluetooth_telephony_audio_open(void) { - GError *error = NULL; - int ret; + DBusConnection *conn; + DBusMessage *msg; + DBusPendingCall *c; - BT_DBG("+"); + FN_START; BT_TELEPHONY_CHECK_INITIALIZED(); BT_TELEPHONY_CHECK_ENABLED(); - if (telephony_dbus_info.proxy == NULL) - telephony_dbus_info.proxy = - __bluetooth_telephony_get_connected_device_proxy(); + /* Because this API is async call, so can't use dbus SMACK */ + if (__bt_telephony_check_privilege() == + BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED; + } - if (telephony_dbus_info.proxy == NULL) + conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); + if (!conn) { + BT_DBG("No System Bus found\n"); return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + } if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING) return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED; - if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "Play", &error, - G_TYPE_INVALID, G_TYPE_INVALID)) { - BT_ERR("Dbus Call Failed!"); - if (error != NULL) { - ret = __bt_telephony_get_error(error->message); - g_error_free(error); - return ret; - } + msg = dbus_message_new_method_call(HFP_AGENT_SERVICE, + HFP_AGENT_PATH, HFP_AGENT_INTERFACE, + "Play"); + if (msg == NULL) { + BT_ERR("dbus method call failed"); + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; } - BT_DBG("-"); + + if (dbus_connection_send_with_reply(conn, msg, &c, -1) == FALSE) { + BT_DBG("HFP_AGENT: send with reply failed"); + dbus_message_unref(msg); + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + } + dbus_pending_call_set_notify(c, __bluetooth_telephony_sco_start_cb, + msg, NULL); + + FN_END; return BLUETOOTH_TELEPHONY_ERROR_NONE; } +static void __bluetooth_telephony_sco_close_cb(DBusPendingCall *call, gpointer user_data) +{ + DBusMessage *reply; + DBusError derr; + DBusMessage *msg = user_data; + + reply = dbus_pending_call_steal_reply(call); + dbus_error_init(&derr); + + if (dbus_set_error_from_message(&derr, reply)) { + BT_ERR("sco_close_cb error: %s, %s", + derr.name, derr.message); + dbus_error_free(&derr); + goto done; + } + + dbus_pending_call_unref(call); +done: + BT_DBG("sco_close_cb : -"); + dbus_message_unref(msg); + dbus_message_unref(reply); +} BT_EXPORT_API int bluetooth_telephony_audio_close(void) { - GError *error = NULL; - int ret; + DBusConnection *conn; + DBusMessage *msg; + DBusPendingCall *c; - BT_DBG("+"); + FN_START; BT_TELEPHONY_CHECK_INITIALIZED(); BT_TELEPHONY_CHECK_ENABLED(); - if (telephony_dbus_info.proxy == NULL) - telephony_dbus_info.proxy = - __bluetooth_telephony_get_connected_device_proxy(); + /* Because this API is async call, so can't use dbus SMACK */ + if (__bt_telephony_check_privilege() == + BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED; + } - if (telephony_dbus_info.proxy == NULL) + conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); + if (!conn) { + BT_DBG("No System Bus found\n"); return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + } - if (telephony_info.headset_state != BLUETOOTH_STATE_PLAYING) { + if (telephony_info.headset_state != BLUETOOTH_STATE_PLAYING) return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED; + + msg = dbus_message_new_method_call(HFP_AGENT_SERVICE, + HFP_AGENT_PATH, HFP_AGENT_INTERFACE, + "Stop"); + if (msg == NULL) { + BT_ERR("dbus method call failed"); + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; } - if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "Stop", &error, - G_TYPE_INVALID, G_TYPE_INVALID)) { - BT_ERR("Dbus Call Failed"); - if (error != NULL) { - ret = __bt_telephony_get_error(error->message); - g_error_free(error); - return ret; - } + if (dbus_connection_send_with_reply(conn, msg, &c, -1) == FALSE) { + BT_DBG("HFP_AGENT: send with reply failed"); + dbus_message_unref(msg); + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; } + telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED; - BT_DBG("-"); + dbus_pending_call_set_notify(c, __bluetooth_telephony_sco_close_cb, + msg, NULL); + + FN_END; return BLUETOOTH_TELEPHONY_ERROR_NONE; } @@ -1514,16 +1989,17 @@ BT_EXPORT_API int bluetooth_telephony_call_remote_ringing(unsigned int call_id) BT_TELEPHONY_CHECK_INITIALIZED(); BT_TELEPHONY_CHECK_ENABLED(); - BT_DBG("+"); + FN_START; + BT_DBG("call_id = [%d]", call_id); /*Make sure SCO is already connected */ ret = __bluetooth_telephony_send_call_status( - CSD_CALL_STATUS_MO_ALERTING, call_id); + CSD_CALL_STATUS_MO_ALERTING, call_id, NULL); if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) { BT_ERR("send call status Failed = [%d]", ret); return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; } - BT_DBG("-"); + FN_END; return BLUETOOTH_TELEPHONY_ERROR_NONE; } @@ -1531,13 +2007,15 @@ BT_EXPORT_API int bluetooth_telephony_call_answered(unsigned int call_id, unsigned int bt_audio) { int ret; - BT_DBG("+"); + + FN_START; + BT_DBG("call_id = [%d]", call_id); BT_TELEPHONY_CHECK_INITIALIZED(); BT_TELEPHONY_CHECK_ENABLED(); ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE, - call_id); + call_id, NULL); if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) { BT_ERR("send call status Failed = [%d]", ret); return ret; @@ -1553,71 +2031,77 @@ BT_EXPORT_API int bluetooth_telephony_call_answered(unsigned int call_id, } } - BT_DBG("-"); + FN_END; return ret; } BT_EXPORT_API int bluetooth_telephony_call_end(unsigned int call_id) { int ret; - BT_DBG("+"); + + FN_START; + BT_DBG("call_id = [%d]", call_id); BT_TELEPHONY_CHECK_INITIALIZED(); BT_TELEPHONY_CHECK_ENABLED(); - ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_MT_RELEASE, - call_id); - if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) { - BT_ERR("send call status Failed = [%d]", ret); - return ret; - } if (telephony_info.call_count > 0) telephony_info.call_count = telephony_info.call_count - 1; if (telephony_info.call_count == 0) { if (bluetooth_telephony_is_sco_connected()) { ret = bluetooth_telephony_audio_close(); - if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) { + if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) BT_ERR(" Failed = [%d]", ret); - return ret; - } } } - BT_DBG("-"); + + ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_MT_RELEASE, + call_id, NULL); + if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) { + BT_ERR("send call status Failed = [%d]", ret); + return ret; + } + + FN_END; return ret; } BT_EXPORT_API int bluetooth_telephony_call_held(unsigned int call_id) { int ret; - BT_DBG("+"); + + FN_START; + BT_DBG("call_id = [%d]", call_id); BT_TELEPHONY_CHECK_INITIALIZED(); BT_TELEPHONY_CHECK_ENABLED(); ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_HOLD, - call_id); - if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) { + call_id, NULL); + if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) BT_ERR("send call status Failed = [%d]", ret); - } - BT_DBG("-"); + + FN_END; return ret; } BT_EXPORT_API int bluetooth_telephony_call_retrieved(unsigned int call_id) { int ret; - BT_DBG("+"); + + FN_START; + BT_DBG("call_id = [%d]", call_id); BT_TELEPHONY_CHECK_INITIALIZED(); BT_TELEPHONY_CHECK_ENABLED(); ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE, - call_id); - if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) { + call_id, NULL); + if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) BT_ERR("send call status Failed = [%d]", ret); - } - BT_DBG("-"); + + FN_END; return ret; } @@ -1629,7 +2113,7 @@ BT_EXPORT_API int bluetooth_telephony_call_swapped(void *call_list, GList *list = call_list; bt_telephony_call_status_info_t *call_status; - BT_DBG("+"); + FN_START; BT_TELEPHONY_CHECK_INITIALIZED(); BT_TELEPHONY_CHECK_ENABLED(); @@ -1639,6 +2123,13 @@ BT_EXPORT_API int bluetooth_telephony_call_swapped(void *call_list, return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM; } + /* Because this API is async call, so can't use dbus SMACK */ + if (__bt_telephony_check_privilege() == + BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED) { + BT_ERR("Don't have a privilege to use this API"); + return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED; + } + BT_DBG(" call_count = [%d]", call_count); for (i = 0; i < call_count; i++) { @@ -1651,11 +2142,15 @@ BT_EXPORT_API int bluetooth_telephony_call_swapped(void *call_list, call_status->call_id, call_status->call_status); + if (NULL != call_status->phone_number) + DBG_SECURE(" call number [%s]", call_status->phone_number); + switch (call_status->call_status) { case BLUETOOTH_CALL_STATE_HELD: ret = __bluetooth_telephony_send_call_status( CSD_CALL_STATUS_HOLD, - call_status->call_id); + call_status->call_id, + call_status->phone_number); if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) { BT_ERR("Failed = %d", ret); return ret; @@ -1665,7 +2160,8 @@ BT_EXPORT_API int bluetooth_telephony_call_swapped(void *call_list, case BLUETOOTH_CALL_STATE_CONNECTED: ret = __bluetooth_telephony_send_call_status( CSD_CALL_STATUS_ACTIVE, - call_status->call_id); + call_status->call_id, + call_status->phone_number); if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) { BT_ERR("Failed = [%d]", ret); return ret; @@ -1681,7 +2177,7 @@ BT_EXPORT_API int bluetooth_telephony_call_swapped(void *call_list, } } - BT_DBG("-"); + FN_END; return BLUETOOTH_TELEPHONY_ERROR_NONE; } @@ -1690,7 +2186,7 @@ BT_EXPORT_API int bluetooth_telephony_set_call_status(void *call_list, { int ret; - BT_DBG("+"); + FN_START; ret = bluetooth_telephony_call_swapped(call_list, call_count); @@ -1701,7 +2197,7 @@ BT_EXPORT_API int bluetooth_telephony_set_call_status(void *call_list, telephony_info.call_count = call_count; - BT_DBG("-"); + FN_END; return BLUETOOTH_TELEPHONY_ERROR_NONE; } @@ -1714,7 +2210,7 @@ BT_EXPORT_API int bluetooth_telephony_indicate_outgoing_call( const char *path = telephony_info.call_path; int ret; - BT_DBG("+"); + FN_START; BT_TELEPHONY_CHECK_INITIALIZED(); BT_TELEPHONY_CHECK_ENABLED(); @@ -1747,13 +2243,13 @@ BT_EXPORT_API int bluetooth_telephony_indicate_outgoing_call( if (!bluetooth_telephony_is_sco_connected()) { ret = bluetooth_telephony_audio_open(); if (ret != 0) { - BT_ERR(" Audio connection call Failed = %d", ret); + BT_ERR(" Audio connection Failed = %d", ret); return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; } } } - BT_DBG("-"); + FN_END; return BLUETOOTH_TELEPHONY_ERROR_NONE; } @@ -1765,7 +2261,7 @@ BT_EXPORT_API int bluetooth_telephony_indicate_incoming_call( const char *path = telephony_info.call_path; int ret; - BT_DBG("+"); + FN_START; BT_TELEPHONY_CHECK_INITIALIZED(); BT_TELEPHONY_CHECK_ENABLED(); @@ -1793,177 +2289,98 @@ BT_EXPORT_API int bluetooth_telephony_indicate_incoming_call( telephony_info.call_count++; BT_DBG("telephony_info.call_count = [%d]", telephony_info.call_count); - BT_DBG("-"); + FN_END; return BLUETOOTH_TELEPHONY_ERROR_NONE; } -BT_EXPORT_API int bluetooth_telephony_set_speaker_gain(unsigned short speaker_gain) +BT_EXPORT_API int bluetooth_telephony_set_speaker_gain( + unsigned short speaker_gain) { - GError *error = NULL; - int ret = BLUETOOTH_TELEPHONY_ERROR_NONE; - DBusGProxy *headset_agent_proxy = NULL; - BT_DBG("+"); - BT_DBG("set speaker_gain= [%d]", speaker_gain); - - BT_TELEPHONY_CHECK_INITIALIZED(); - BT_TELEPHONY_CHECK_ENABLED(); - - if (telephony_info.obj_path == NULL) - return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; - - if (telephony_dbus_info.proxy == NULL) - telephony_dbus_info.proxy = - __bluetooth_telephony_get_connected_device_proxy(); - - if (telephony_dbus_info.proxy == NULL) - return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; - - if (!dbus_g_proxy_call(headset_agent_proxy, "SetSpeakerGain", - &error, G_TYPE_UINT, speaker_gain, G_TYPE_INVALID, - G_TYPE_INVALID)) { - if (error != NULL) { - BT_ERR("Calling SetSpeakerGain failed: [%s]", - error->message); - g_error_free(error); - } - } + DBusMessage *reply; + DBusError err; + int ret; - BT_DBG("-"); - return ret; -} + FN_START; -BT_EXPORT_API int bluetooth_telephony_get_headset_volume(unsigned int *speaker_gain) -{ - DBusGProxy *headset_agent_proxy = NULL; - GError *error = NULL; - - BT_DBG("+"); BT_TELEPHONY_CHECK_INITIALIZED(); BT_TELEPHONY_CHECK_ENABLED(); - if (telephony_dbus_info.proxy == NULL) - telephony_dbus_info.proxy = - __bluetooth_telephony_get_connected_device_proxy(); - - if (telephony_dbus_info.proxy == NULL) - return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; - - if (telephony_info.obj_path == NULL) - return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; - - if (telephony_dbus_info.proxy == NULL) - telephony_dbus_info.proxy = - __bluetooth_telephony_get_connected_device_proxy(); + BT_DBG("set speaker_gain= [%d]", speaker_gain); - if (telephony_dbus_info.proxy == NULL) - return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + reply = __bluetooth_telephony_dbus_method_send( + HFP_AGENT_PATH, HFP_AGENT_INTERFACE, + "SetSpeakerGain", &err, DBUS_TYPE_UINT16, + &speaker_gain, DBUS_TYPE_INVALID); - if (!dbus_g_proxy_call(headset_agent_proxy, "GetSpeakerGain", - &error, G_TYPE_INVALID, G_TYPE_UINT, &speaker_gain, - G_TYPE_INVALID)) { - if (error != NULL) { - BT_ERR("Calling G`etSpeakerGain failed: [%s]", - error->message); - g_error_free(error); + if (!reply) { + BT_ERR("Error returned in method call\n"); + if (dbus_error_is_set(&err)) { + ret = __bt_telephony_get_error(err.message); + dbus_error_free(&err); + return ret; } + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; } - BT_DBG("-"); + dbus_message_unref(reply); + FN_END; + return BLUETOOTH_TELEPHONY_ERROR_NONE; } -static char *_bt_get_device_object_path(char *address) +BT_EXPORT_API int bluetooth_telephony_get_headset_volume( + unsigned int *speaker_gain) { - DBusMessage *msg; DBusMessage *reply; - DBusMessageIter reply_iter; - DBusMessageIter value_iter; DBusError err; - DBusConnection *conn; - char *object_path = NULL; - BT_DBG("+"); + int ret; + guint16 gain; - conn = _bt_get_system_conn(); - retv_if(conn == NULL, NULL); + FN_START; - msg = dbus_message_new_method_call(BLUEZ_SERVICE_NAME, BT_MANAGER_PATH, - BLUEZ_MANAGER_INTERFACE, - "GetManagedObjects"); - - retv_if(msg == NULL, NULL); + BT_TELEPHONY_CHECK_INITIALIZED(); + BT_TELEPHONY_CHECK_ENABLED(); - /* Synchronous call */ - dbus_error_init(&err); - reply = dbus_connection_send_with_reply_and_block( - conn, msg, - -1, &err); - dbus_message_unref(msg); + reply = __bluetooth_telephony_dbus_method_send( + HFP_AGENT_PATH, HFP_AGENT_INTERFACE, + "GetSpeakerGain", &err, DBUS_TYPE_INVALID); if (!reply) { - BT_ERR("Can't get managed objects"); - + BT_ERR("Error returned in method call\n"); if (dbus_error_is_set(&err)) { - BT_ERR("%s", err.message); + ret = __bt_telephony_get_error(err.message); dbus_error_free(&err); + return ret; } - return NULL; - } - - if (dbus_message_iter_init(reply, &reply_iter) == FALSE) { - BT_ERR("Fail to iterate the reply"); - return NULL; + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; } - dbus_message_iter_recurse(&reply_iter, &value_iter); - - /* signature of GetManagedObjects: a{oa{sa{sv}}} */ - while (dbus_message_iter_get_arg_type(&value_iter) == - DBUS_TYPE_DICT_ENTRY) { - DBusMessageIter msg_iter; - - dbus_message_iter_recurse(&value_iter, &msg_iter); - - object_path = __bt_extract_device_path(&msg_iter, address); - if (object_path != NULL) { - BT_DBG("Found the device path"); - break; + if (!dbus_message_get_args(reply, &err, + DBUS_TYPE_UINT16, &gain, + DBUS_TYPE_INVALID)) { + BT_ERR("Error to get features"); + if (dbus_error_is_set(&err)) { + BT_ERR("error message: %s", err.message); + dbus_error_free(&err); } - - dbus_message_iter_next(&value_iter); + dbus_message_unref(reply); + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; } - BT_DBG("-"); - return object_path; -} - -static char *__bt_extract_device_path(DBusMessageIter *msg_iter, char *address) -{ - char *object_path = NULL; - char device_address[BT_ADDRESS_STRING_SIZE] = { 0 }; - BT_DBG("+"); + *speaker_gain = gain; + BT_DBG("Get speaker_gain= [%d]", *speaker_gain); - /* Parse the signature: oa{sa{sv}}} */ - retv_if(dbus_message_iter_get_arg_type(msg_iter) != - DBUS_TYPE_OBJECT_PATH, NULL); - - dbus_message_iter_get_basic(msg_iter, &object_path); - retv_if(object_path == NULL, NULL); - - _bt_convert_device_path_to_address(object_path, device_address); - - if (g_strcmp0(address, device_address) == 0) { - return g_strdup(object_path); - } - BT_DBG("-"); - return NULL; + dbus_message_unref(reply); + FN_END; + return BLUETOOTH_TELEPHONY_ERROR_NONE; } static DBusHandlerResult __bt_telephony_adapter_filter(DBusConnection *conn, - DBusMessage *msg, void *data) + DBusMessage *msg, void *data) { int ret; char *object_path = NULL; const char *member = dbus_message_get_member(msg); - BT_DBG("+"); + FN_START; if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; @@ -1977,18 +2394,24 @@ static DBusHandlerResult __bt_telephony_adapter_filter(DBusConnection *conn, return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } - if (strcasecmp(object_path, "/org/bluez/hci0") == 0) { - BT_DBG("Adapter added [%s] \n", object_path); + if (strcasecmp(object_path, DEFAULT_ADAPTER_OBJECT_PATH) == 0) { + + BT_DBG("Adapter added [%s]", object_path); BT_DBG("BlueZ is Activated and flag need to be reset"); - BT_DBG("Send enabled to application\n"); + BT_DBG("Send enabled to application"); - ret = __bluetooth_telephony_register(); - if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) { - BT_DBG("__bluetooth_telephony_register failed\n"); + if (__bt_telephony_get_src_addr(msg)) { + BT_ERR("Fail to get the local adapter address"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } + + ret = __bluetooth_telephony_register(); + if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) + BT_ERR("__bluetooth_telephony_register failed"); } } - BT_DBG("-"); + + FN_END; return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } @@ -1996,84 +2419,107 @@ static int __bt_telephony_get_object_path(DBusMessage *msg, char **path) { DBusMessageIter item_iter; dbus_message_iter_init(msg, &item_iter); - BT_DBG("+"); + FN_START; if (dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_OBJECT_PATH) { - BT_ERR("This is bad format dbus\n"); - return BLUETOOTH_ERROR_INTERNAL; + BT_ERR("This is bad format dbus"); + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; } dbus_message_iter_get_basic(&item_iter, path); if (*path == NULL) - return BLUETOOTH_ERROR_INTERNAL; + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; - BT_DBG("-"); - return BLUETOOTH_ERROR_NONE; + FN_END; + return BLUETOOTH_TELEPHONY_ERROR_NONE; } -static void _bt_convert_device_path_to_address(const char *device_path, - char *device_address) -{ - char address[BT_ADDRESS_STRING_SIZE] = { 0 }; - char *dev_addr; - BT_DBG("+"); - - ret_if(device_path == NULL); - ret_if(device_address == NULL); - - dev_addr = strstr(device_path, "dev_"); - if (dev_addr != NULL) { - char *pos = NULL; - dev_addr += 4; - g_strlcpy(address, dev_addr, sizeof(address)); - while ((pos = strchr(address, '_')) != NULL) { - *pos = ':'; - } - g_strlcpy(device_address, address, BT_ADDRESS_STRING_SIZE); - } - BT_DBG("-"); -} - -static char *__bt_get_default_adapter_path(DBusMessageIter *msg_iter) +static int __bt_telephony_get_src_addr(DBusMessage *msg) { - char *object_path = NULL; + char *object_path; + const char *property = NULL; + char *interface_name; + DBusMessageIter item_iter; DBusMessageIter value_iter; - BT_DBG("+"); + DBusMessageIter msg_iter, dict_iter; + DBusMessageIter in_iter, in2_iter; + char *bd_addr; + FN_START; - /* Parse the signature: oa{sa{sv}}} */ - retv_if(dbus_message_iter_get_arg_type(msg_iter) != - DBUS_TYPE_OBJECT_PATH, NULL); + dbus_message_iter_init(msg, &item_iter); - dbus_message_iter_get_basic(msg_iter, &object_path); + /* signature of InterfacesAdded signal is oa{sa{sv}} */ + if (dbus_message_iter_get_arg_type(&item_iter) + != DBUS_TYPE_OBJECT_PATH) { + BT_ERR("This is bad format dbus"); + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + } - retv_if(dbus_message_iter_next(msg_iter) == FALSE, NULL); - retv_if(dbus_message_iter_get_arg_type(msg_iter) != - DBUS_TYPE_ARRAY, NULL); + dbus_message_iter_get_basic(&item_iter, &object_path); + retv_if(object_path == NULL, + BLUETOOTH_TELEPHONY_ERROR_INTERNAL); - dbus_message_iter_recurse(msg_iter, &value_iter); + if (strcasecmp(object_path, DEFAULT_ADAPTER_OBJECT_PATH) == 0) { + /* get address from here */ + retv_if(dbus_message_iter_next(&item_iter) == FALSE, + BLUETOOTH_TELEPHONY_ERROR_INTERNAL); - while (dbus_message_iter_get_arg_type(&value_iter) == - DBUS_TYPE_DICT_ENTRY) { - char *interface_name = NULL; - DBusMessageIter interface_iter; + /* signature a{sa{sv}} */ + retv_if(dbus_message_iter_get_arg_type(&item_iter) != + DBUS_TYPE_ARRAY, + BLUETOOTH_TELEPHONY_ERROR_INTERNAL); + dbus_message_iter_recurse(&item_iter, &value_iter); + while (dbus_message_iter_get_arg_type(&value_iter) == + DBUS_TYPE_DICT_ENTRY) { + dbus_message_iter_recurse(&value_iter, &msg_iter); + if (dbus_message_iter_get_arg_type(&msg_iter) + != DBUS_TYPE_STRING) { + BT_ERR("This is bad format dbus"); + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + } - dbus_message_iter_recurse(&value_iter, &interface_iter); + dbus_message_iter_get_basic(&msg_iter, &interface_name); + retv_if(interface_name == NULL, + BLUETOOTH_TELEPHONY_ERROR_INTERNAL); - retv_if(dbus_message_iter_get_arg_type(&interface_iter) != - DBUS_TYPE_STRING, NULL); + BT_DBG("interface name is %s", interface_name); - dbus_message_iter_get_basic(&interface_iter, &interface_name); + if (strcasecmp(interface_name, BLUEZ_ADAPTER_INTERFACE) == 0) { + retv_if(!dbus_message_iter_next(&msg_iter), + BLUETOOTH_TELEPHONY_ERROR_INTERNAL); + dbus_message_iter_recurse(&msg_iter, &in_iter); - if (g_strcmp0(interface_name, "org.bluez.Adapter1") == 0) { - return g_strdup(object_path); + if (dbus_message_iter_get_arg_type(&in_iter) + != DBUS_TYPE_DICT_ENTRY) { + BT_ERR("This is bad format dbus"); + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + } + + dbus_message_iter_recurse(&in_iter, &dict_iter); + dbus_message_iter_get_basic( + &dict_iter, &property); + + retv_if(property == NULL, + BLUETOOTH_TELEPHONY_ERROR_INTERNAL); + retv_if(!dbus_message_iter_next(&dict_iter), + BLUETOOTH_TELEPHONY_ERROR_INTERNAL); + + if (strcasecmp(property, "Address") == 0) { + dbus_message_iter_recurse + (&dict_iter, &in2_iter); + dbus_message_iter_get_basic + (&in2_iter, &bd_addr); + src_addr = g_strdup(bd_addr); + break; + } + } + dbus_message_iter_next(&value_iter); } - dbus_message_iter_next(&value_iter); } - BT_DBG("Adapter Not Found"); - BT_DBG("-"); - return NULL; + BT_DBG("default adapter address is src_addr = %s", src_addr); + FN_END; + return BLUETOOTH_TELEPHONY_ERROR_NONE; } - diff --git a/bt-api/bt-telephony.xml b/bt-api/bt-telephony.xml old mode 100644 new mode 100755 index 8cb4f63..54f394e --- a/bt-api/bt-telephony.xml +++ b/bt-api/bt-telephony.xml @@ -2,30 +2,14 @@ - - - - - - - - - - - - - - - - - - - - + + + + diff --git a/bt-api/include/bt-common.h b/bt-api/include/bt-common.h old mode 100644 new mode 100755 index bc67026..2531e66 --- a/bt-api/include/bt-common.h +++ b/bt-api/include/bt-common.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -26,6 +30,8 @@ #include #include #include +#include +#include #include "bluetooth-api.h" @@ -34,17 +40,43 @@ extern "C" { #endif /* __cplusplus */ #undef LOG_TAG -#define LOG_TAG "BLUETOOTH_FRWK" +#define LOG_TAG "BLUETOOTH_FRWK_API" #ifndef BT_EXPORT_API #define BT_EXPORT_API __attribute__((visibility("default"))) #endif +#define LOG_COLOR_RESET "\033[0m" +#define LOG_COLOR_RED "\033[31m" +#define LOG_COLOR_YELLOW "\033[33m" +#define LOG_COLOR_GREEN "\033[32m" +#define LOG_COLOR_BLUE "\033[36m" +#define LOG_COLOR_PURPLE "\033[35m" + #define BT_DBG(fmt, args...) \ SLOGD(fmt, ##args) +#define BT_INFO(fmt, args...) \ + SLOGI(fmt, ##args) #define BT_ERR(fmt, args...) \ SLOGE(fmt, ##args) +#define BT_INFO_C(fmt, arg...) \ + SLOGI_IF(TRUE, LOG_COLOR_GREEN" "fmt" "LOG_COLOR_RESET, ##arg) +#define BT_ERR_C(fmt, arg...) \ + SLOGI_IF(TRUE, LOG_COLOR_RED" "fmt" "LOG_COLOR_RESET, ##arg) + +#define DBG_SECURE(fmt, args...) SECURE_SLOGD(fmt, ##args) +#define ERR_SECURE(fmt, args...) SECURE_SLOGE(fmt, ##args) + +//#define FUNCTION_TRACE +#ifdef FUNCTION_TRACE +#define FN_START BT_DBG("[ENTER FUNC]") +#define FN_END BT_DBG("[EXIT FUNC]") +#else +#define FN_START +#define FN_END +#endif + #define ret_if(expr) \ do { \ if (expr) { \ @@ -84,10 +116,10 @@ extern "C" { #define BT_ALLOC_PARAMS(IP1,IP2,IP3,IP4,OP ) \ do { \ - IP1 = g_array_new(FALSE, FALSE, sizeof(gchar)); \ - IP2 = g_array_new(FALSE, FALSE, sizeof(gchar)); \ - IP3 = g_array_new(FALSE, FALSE, sizeof(gchar)); \ - IP4 = g_array_new(FALSE, FALSE, sizeof(gchar)); \ + IP1 = g_array_new(TRUE, TRUE, sizeof(gchar)); \ + IP2 = g_array_new(TRUE, TRUE, sizeof(gchar)); \ + IP3 = g_array_new(TRUE, TRUE, sizeof(gchar)); \ + IP4 = g_array_new(TRUE, TRUE, sizeof(gchar)); \ } while (0) #define BT_INIT_AGENT_PARAMS() \ @@ -120,6 +152,25 @@ extern "C" { do { \ if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED) \ { \ + BT_ERR("BT BREDR is not enabled"); \ + func BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; \ + } \ + } while (0) + +#define BT_CHECK_ENABLED_LE(func) \ + do { \ + if (bluetooth_check_adapter_le() == BLUETOOTH_ADAPTER_LE_DISABLED) \ + { \ + BT_ERR("BT LE is not enabled"); \ + func BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; \ + } \ + } while (0) + +#define BT_CHECK_ENABLED_ANY(func) \ + do { \ + if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED && \ + bluetooth_check_adapter_le() == BLUETOOTH_ADAPTER_LE_DISABLED) \ + { \ BT_ERR("BT is not enabled"); \ func BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; \ } \ @@ -128,17 +179,24 @@ extern "C" { #define BT_ADDRESS_LENGTH_MAX 6 #define BT_ADDRESS_STRING_SIZE 18 #define BT_ADAPTER_OBJECT_PATH_MAX 50 +#define BT_RFCOMM_BUFFER_LEN 1024 + +#define BT_ACCESS_DENIED_MSG "Rejected send message" #define BT_EVENT_FREEDESKTOP "org.freedesktop.DBus" #define BT_FREEDESKTOP_PATH "/org/freedesktop/DBus" +#define BT_EVENT_MANAGER "org.bluez.Manager" #define BT_MANAGER_PATH "/" + + #define BT_MANAGER_INTERFACE "org.freedesktop.DBus.ObjectManager" #define BT_ADAPTER_INTERFACE "org.bluez.Adapter1" #define BT_DEVICE_INTERFACE "org.bluez.Device1" - #define BT_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties" -#define BT_BLUEZ_HCI_PATH "/org/bluez/hci0" + + +#define BT_SERIAL_INTERFACE "org.bluez.Serial" #define BT_BLUEZ_NAME "org.bluez" #define BT_DBUS_NAME "org.projectx.bt" @@ -146,8 +204,10 @@ extern "C" { #define BT_AGENT_NAME "org.bluez.frwk_agent" #define BT_AGENT_PATH "/org/bluez/agent/frwk_agent" + #define BT_AGENT_INTERFACE "org.bluez.Agent1" + #define BT_MAX_USER_INFO 5 #define RFKILL_EVENT_SIZE 8 #define RFKILL_NODE "/dev/rfkill" @@ -177,6 +237,7 @@ typedef enum { BT_HID, BT_AUDIO, BT_AVRCP, + BT_HF, } bt_user_info_type_t; typedef struct { @@ -199,6 +260,9 @@ void _bt_input_event_cb(int event, int result, void *param, void _bt_headset_event_cb(int event, int result, void *param, void *callback, void *user_data); +void _bt_hf_event_cb(int event, int result, void *param, + void *callback, void *user_data); + void _bt_avrcp_event_cb(int event, int result, void *param, void *callback, void *user_data); @@ -216,7 +280,43 @@ void _bt_convert_addr_type_to_string(char *address, int _bt_copy_utf8_string(char *dest, const char *src, unsigned int length); -int _bt_get_adapter_path(DBusGConnection *g_conn, char *path); +gboolean _bt_utf8_validate(char *name); + +typedef struct { + char *obj_path; + char *uuid; + gboolean authentication; + gboolean authorization; + char *role; + + char *service; + +} bt_register_profile_info_t; + +int _bt_get_adapter_path(GDBusConnection *conn, char *path); +char *_bt_get_device_object_path(char *address); +int _bt_connect_profile(char *address, char *uuid, void *cb, + gpointer func_data); +int _bt_disconnect_profile(char *address, char *uuid, void *cb, + gpointer func_data); + +int _bt_cancel_discovers(char *address); +int _bt_discover_services(char *address, char *uuid, void *cb, + gpointer func_data); +int _bt_discover_service_uuids(char *address, char *remote_uuid); + +int _bt_register_profile(bt_register_profile_info_t *info, gboolean use_default_rfcomm); +int _bt_register_profile_platform(bt_register_profile_info_t *info, gboolean use_default_rfcomm); + +void _bt_unregister_profile(char *path); +GDBusNodeInfo * _bt_get_gdbus_node(const gchar *xml_data); +int __rfcomm_assign_id(void); +void __rfcomm_delete_id(int id); +void _bt_unregister_gdbus(int object_id); +typedef int (*bt_new_connection_cb) (const char *path, int fd, + bluetooth_device_address_t *address); +int _bt_register_new_conn(const char *path, bt_new_connection_cb cb); +void _bt_swap_addr(unsigned char *dst, const unsigned char *src); DBusGProxy *_bt_get_adapter_proxy(DBusGConnection *conn); @@ -228,6 +328,36 @@ DBusGConnection *_bt_get_system_gconn(void); DBusConnection *_bt_get_system_conn(void); +GDBusConnection *_bt_init_system_gdbus_conn(void); + +char *_bt_get_cookie(void); + +int _bt_get_cookie_size(void); + +int _bt_register_osp_server_in_agent(int type, char *uuid, char *path, int fd); +int _bt_unregister_osp_server_in_agent(int type, char *uuid); + +void _bt_generate_cookie(void); + +void _bt_destroy_cookie(void); + +int _bt_check_privilege(int service_type, int service_function); + +GDBusConnection *_bt_gdbus_init_system_gconn(void); + +GDBusConnection *_bt_gdbus_get_system_gconn(void); + +GVariant *_bt_get_managed_objects(void); + +void _bt_convert_device_path_to_address(const char *device_path, + char *device_address); + +#ifdef RFCOMM_DIRECT +void _bt_rfcomm_server_free_all(); + +gboolean _check_uuid_path(char *path, char *uuid); +#endif + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/bt-api/include/bt-event-handler.h b/bt-api/include/bt-event-handler.h old mode 100644 new mode 100755 index cd3ea10..7e470c5 --- a/bt-api/include/bt-event-handler.h +++ b/bt-api/include/bt-event-handler.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -34,14 +38,12 @@ extern "C" { typedef struct { int event_type; - DBusConnection *conn; - DBusHandleMessageFunction func; - char *match_rule; + guint id; + GDBusConnection *conn; void *cb; void *user_data; } bt_event_info_t; - int _bt_init_event_handler(void); int _bt_deinit_event_handler(void); @@ -50,6 +52,8 @@ int _bt_register_event(int event_type, void *event_cb, void *user_data); int _bt_unregister_event(int event_type); +bt_event_info_t *_bt_event_get_cb_data(int event_type); + void _bt_add_server(int server_fd); void _bt_remove_server(int server_fd); @@ -60,6 +64,10 @@ void _bt_set_obex_server_id(int server_type); int _bt_get_obex_server_id(void); +void _bt_register_name_owner_changed(void); + +void _bt_unregister_name_owner_changed(void); + #ifdef __cplusplus } #endif diff --git a/bt-api/include/bt-mdm.h b/bt-api/include/bt-mdm.h new file mode 100755 index 0000000..4b01f3a --- /dev/null +++ b/bt-api/include/bt-mdm.h @@ -0,0 +1,70 @@ +/* + * Bluetooth-frwk + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#ifndef _BT_MDM_H_ +#define _BT_MDM_H_ + +#include +#include +#include +#include "bluetooth-api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + BT_MDM_NO_SERVICE, + BT_MDM_ALLOWED, + BT_MDM_RESTRICTED +} bt_mdm_status_e; + +int _bt_launch_mdm_popup(char *mode); + +bt_mdm_status_e _bt_check_mdm_handsfree_only(void); + +#ifdef MDM_PHASE_2 + +bt_mdm_status_e _bt_check_mdm_pairing_restriction(void); + +bt_mdm_status_e _bt_check_mdm_transfer_restriction(void); + +bt_mdm_status_e _bt_check_mdm_hsp_restriction(void); + +bt_mdm_status_e _bt_check_mdm_a2dp_restriction(void); + +bt_mdm_status_e _bt_check_mdm_avrcp_restriction(void); + +bt_mdm_status_e _bt_check_mdm_spp_restriction(void); + +bt_mdm_status_e _bt_check_mdm_blacklist_devices(const bluetooth_device_address_t *address); + +bt_mdm_status_e _bt_check_mdm_blacklist_uuid(char *uuid); +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_SERVICE_MDM_H_*/ + diff --git a/bt-api/include/bt-request-sender.h b/bt-api/include/bt-request-sender.h old mode 100644 new mode 100755 index 5cbbee0..069a923 --- a/bt-api/include/bt-request-sender.h +++ b/bt-api/include/bt-request-sender.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -38,17 +42,29 @@ typedef struct { void _bt_deinit_proxys(void); -int _bt_send_request(int service_type, int service_function, +int _bt_sync_send_request(int service_type, int service_function, GArray *in_param1, GArray *in_param2, GArray *in_param3, GArray *in_param4, GArray **out_param1); +#define _bt_send_request(a, b, format ...) ( \ + { \ + BT_INFO_C("Sync Request => type=%s, fn=%s(0x%x)", #a, #b, b); \ + _bt_sync_send_request(a, b, format); \ + } \ + ) -int _bt_send_request_async(int service_type, int service_function, +int _bt_async_send_request(int service_type, int service_function, GArray *in_param1, GArray *in_param2, GArray *in_param3, GArray *in_param4, void *callback, void *user_data); +#define _bt_send_request_async(a, b, format ...) ( \ + { \ + BT_INFO_C("Async Request => type=%s, fn=%s(0x%x)", #a, #b, b); \ + _bt_async_send_request(a, b, format); \ + } \ + ) #ifdef __cplusplus } diff --git a/bt-api/marshal.list b/bt-api/marshal.list old mode 100644 new mode 100755 diff --git a/bt-core/CMakeLists.txt b/bt-core/CMakeLists.txt old mode 100644 new mode 100755 index 8d272bd..25837a5 --- a/bt-core/CMakeLists.txt +++ b/bt-core/CMakeLists.txt @@ -1,7 +1,13 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) PROJECT(bt-core C) -SET(SRCS bt_core.c) +SET(SRCS +bt-core-main.c +bt-core-adapter.c +bt-core-dbus-handler.c +bt-core-noti-handler.c +) + SET(APP_VENDOR tizen) SET(APP_NAME bt-core) SET(APP_DIR ${CMAKE_INSTALL_PREFIX}/bin) @@ -12,11 +18,11 @@ IF("${CMAKE_BUILD_TYPE}" STREQUAL "") ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include) INCLUDE(FindPkgConfig) -pkg_check_modules(pkgs REQUIRED dbus-glib-1 dlog vconf) +pkg_check_modules(pkgs REQUIRED dbus-glib-1 dlog vconf gio-2.0 gio-unix-2.0) FOREACH(flag ${pkgs_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") @@ -34,7 +40,8 @@ IF("${ARCH}" STREQUAL "arm") ENDIF("${ARCH}" STREQUAL "arm") FIND_PROGRAM(DBUS_BINDING_TOOL NAMES dbus-binding-tool) -EXEC_PROGRAM("${DBUS_BINDING_TOOL}" ARGS "--prefix=bt_core ${CMAKE_CURRENT_SOURCE_DIR}/bt_core.xml --mode=glib-server --output=${CMAKE_CURRENT_SOURCE_DIR}/bt_core_glue.h") +EXEC_PROGRAM("${DBUS_BINDING_TOOL}" ARGS "--prefix=bt ${CMAKE_CURRENT_SOURCE_DIR}/bt-request-service.xml --mode=glib-client --output=${CMAKE_CURRENT_SOURCE_DIR}/include/bt-request-service.h") +EXEC_PROGRAM("${DBUS_BINDING_TOOL}" ARGS "--prefix=bt_core ${CMAKE_CURRENT_SOURCE_DIR}/bt-core-adapter.xml --mode=glib-server --output=${CMAKE_CURRENT_SOURCE_DIR}/include/bt-core-adapter-method.h") ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"") ADD_DEFINITIONS("-DVENDOR=\"${APP_VENDOR}\"") @@ -53,5 +60,3 @@ SET(PREFIX ${CMAKE_INSTALL_PREFIX}) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/org.projectx.bt_core.service DESTINATION share/dbus-1/system-services) -install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/bluetooth-frwk-core.conf DESTINATION /etc/dbus-1/system.d) - diff --git a/bt-core/bluetooth-frwk-core b/bt-core/bluetooth-frwk-core new file mode 100755 index 0000000..bde729f --- /dev/null +++ b/bt-core/bluetooth-frwk-core @@ -0,0 +1,9 @@ +#!/bin/sh + +# +# Script for running BT Service during booting time +# + +if [ -x /usr/bin/bt-core ]; then + /usr/bin/bt-core & +fi diff --git a/bt-core/bt-core-adapter.c b/bt-core/bt-core-adapter.c new file mode 100755 index 0000000..bd25268 --- /dev/null +++ b/bt-core/bt-core-adapter.c @@ -0,0 +1,796 @@ +/* + * Bluetooth-frwk + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * 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 +#include + +#include "bt-core-main.h" +#include "bt-core-adapter.h" +#include "bt-core-common.h" +#include "bt-core-dbus-handler.h" +#include "bt-core-noti-handler.h" + +static bt_status_t adapter_status = BT_DEACTIVATED; +static bt_le_status_t adapter_le_status = BT_LE_DEACTIVATED; +static gboolean is_recovery_mode = FALSE; + +static int bt_status_before[BT_MODE_MAX] = { VCONFKEY_BT_STATUS_OFF, }; +static int bt_le_status_before[BT_MODE_MAX] = { 0, }; + +static void __bt_core_set_status(bt_status_t status) +{ + adapter_status = status; +} + +bt_status_t _bt_core_get_status(void) +{ + return adapter_status; +} + +static void __bt_core_set_le_status(bt_le_status_t status) +{ + adapter_le_status = status; +} + +bt_le_status_t _bt_core_get_le_status(void) +{ + return adapter_le_status; +} + +int _bt_core_get_bt_status(bt_mode_e mode) +{ + return bt_status_before[mode]; +} + +int _bt_core_get_bt_le_status(bt_mode_e mode) +{ + return bt_le_status_before[mode]; +} + +void _bt_core_set_bt_status(bt_mode_e mode, int status) +{ + bt_status_before[mode] = status; +} + +void _bt_core_set_bt_le_status(bt_mode_e mode, int status) +{ + bt_le_status_before[mode] = status; +} + +gboolean _bt_core_is_recovery_mode(void) +{ + return is_recovery_mode; +} + +gboolean _bt_core_is_flight_mode_enabled(void) +{ +#ifdef TIZEN_TELEPHONY_ENABLED + int isFlightMode = 0; + int ret = -1; + + ret = vconf_get_bool(VCONFKEY_TELEPHONY_FLIGHT_MODE, &isFlightMode); + if (ret != 0) { + BT_ERR("vconf_get_bool failed"); + } + return isFlightMode; +#else + return FALSE; +#endif +} + +static gboolean bt_core_enable_adapter(BtCore *agent, + DBusGMethodInvocation *context); + +static gboolean bt_core_disable_adapter(BtCore *agent, + DBusGMethodInvocation *context); + +static gboolean bt_core_recover_adapter(BtCore *agent, + DBusGMethodInvocation *context); + +static gboolean bt_core_enable_adapter_le(BtCore *agent, + DBusGMethodInvocation *context); + +static gboolean bt_core_disable_adapter_le(BtCore *agent, + DBusGMethodInvocation *context); + +static gboolean bt_core_reset_adapter(BtCore *agent, + DBusGMethodInvocation *context); + +static gboolean bt_core_enable_core(BtCore *agent, + DBusGMethodInvocation *context); + +static int __execute_command(const char *cmd, char *const arg_list[]); + +#include "bt-core-adapter-method.h" + + +G_DEFINE_TYPE(BtCore, bt_core, G_TYPE_OBJECT); + +/*This is part of platform provided code skeleton for client server model*/ +static void bt_core_class_init (BtCoreClass *bt_core_class) +{ + dbus_g_object_type_install_info(G_TYPE_FROM_CLASS(bt_core_class), + &dbus_glib_bt_core_object_info); +} + +/*This is part of platform provided code skeleton for client server model*/ +static void bt_core_init (BtCore *core) +{ +} + +typedef enum { + BT_CORE_ERROR_REJECT, + BT_CORE_ERROR_CANCEL, + BT_CORE_ERROR_TIMEOUT, +} BtCoreError; + +#define BT_CORE_ERROR (bt_core_error_quark()) + +static GQuark bt_core_error_quark(void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string("BtCore"); + + return quark; +} + +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +static GError *bt_core_error(BtCoreError error, const char *err_msg) +{ + return g_error_new(BT_CORE_ERROR, error, err_msg, NULL); +} + +static int __execute_command(const char *cmd, char *const arg_list[]) +{ + int pid; + int pid2; + int status = 0; + BT_DBG("+"); + + pid = fork(); + switch (pid) { + case -1: + BT_ERR("fork failed"); + return -1; + + case 0: + pid2 = fork(); + if (pid2 == -1) { + BT_ERR("fork failed"); + } else if (pid2 == 0) { + execv(cmd, arg_list); + exit(256); + } + exit(0); + break; + + default: + BT_DBG("parent : forked[%d]", pid); + waitpid(pid, &status, 0); + BT_DBG("child is terminated : %d", status); + break; + } + BT_DBG("-"); + return 0; +} + +int _bt_enable_adapter(void) +{ + int ret; + bt_status_t status; + bt_le_status_t le_status; + + BT_INFO(""); + + status = _bt_core_get_status(); + if (status != BT_DEACTIVATED) { + BT_ERR("Invalid state %d", status); + return -1; + } + + le_status = _bt_core_get_le_status(); + if (le_status == BT_LE_ACTIVATED) { + /* Turn on PSCAN, (ISCAN if needed) */ + /* Return with 0 for the Enabled response. */ + __bt_core_set_status(BT_ACTIVATED); + BT_INFO("BR/EDR is enabled."); + return 0; + } + + __bt_core_set_status(BT_ACTIVATING); + + ret = __execute_command("/usr/etc/bluetooth/bt-stack-up.sh", NULL); + if (ret < 0) { + BT_ERR("running script failed"); + ret = __execute_command("/usr/etc/bluetooth/bt-dev-end.sh", NULL); + __bt_core_set_status(BT_DEACTIVATED); + return -1; + } + + return 0; +} + +int _bt_disable_adapter(void) +{ + bt_status_t status; + bt_le_status_t le_status; + + BT_INFO_C("Disable adapter"); + + le_status = _bt_core_get_le_status(); + BT_DBG("le_status : %d", le_status); + if (le_status == BT_LE_ACTIVATED) { + /* Turn off PSCAN, (ISCAN if needed) */ + /* Return with 0 for the Disabled response. */ + __bt_core_set_status(BT_DEACTIVATED); + BT_INFO("BR/EDR is disabled. now LE only mode"); + return 0; + } + + status = _bt_core_get_status(); + if (status == BT_ACTIVATING) { + /* Forcely terminate */ + if (__execute_command("/usr/etc/bluetooth/bt-stack-down.sh", NULL) < 0) { + BT_ERR("running script failed"); + } + _bt_core_terminate(); + return 0; + } else if (status != BT_ACTIVATED) { + BT_ERR("Invalid state %d", status); + } + + __bt_core_set_status(BT_DEACTIVATING); + + if (__execute_command("/usr/etc/bluetooth/bt-stack-down.sh", NULL) < 0) { + BT_ERR("running script failed"); + __bt_core_set_status( BT_ACTIVATED); + return -1; + } + + return 0; +} + +int _bt_enable_adapter_le(void) +{ + BT_DBG(""); + + int ret; + bt_status_t status; + bt_le_status_t le_status; + le_status = _bt_core_get_le_status(); + retv_if(le_status != BT_LE_DEACTIVATED, -1); + + status = _bt_core_get_status(); + if (status == BT_DEACTIVATED) { + __bt_core_set_le_status(BT_LE_ACTIVATING); + BT_DBG("Activate BT"); + ret = __execute_command("/usr/etc/bluetooth/bt-stack-up.sh", NULL); + if (ret < 0) { + BT_ERR("running script failed"); + ret = __execute_command("/usr/etc/bluetooth/bt-dev-end.sh &", NULL); + __bt_core_set_status(BT_DEACTIVATED); + __bt_core_set_le_status(BT_LE_DEACTIVATED); + return -1; + } + } else { + __bt_core_set_le_status(BT_LE_ACTIVATED); + } + return 0; +} + +int _bt_disable_adapter_le(void) +{ + BT_DBG("+"); + + bt_status_t status; + bt_le_status_t le_status; + + le_status = _bt_core_get_le_status(); + retv_if(le_status == BT_LE_DEACTIVATED, 0); + retv_if(le_status == BT_LE_DEACTIVATING, -1); + + status = _bt_core_get_status(); + BT_DBG("status : %d", status); + + if (status == BT_DEACTIVATED) { + __bt_core_set_le_status(BT_LE_DEACTIVATING); + + if (__execute_command("/usr/etc/bluetooth/bt-stack-down.sh", NULL) < 0) { + BT_ERR("running script failed"); + __bt_core_set_le_status(BT_LE_ACTIVATED); + return -1; + } + } + + __bt_core_set_le_status(BT_LE_DEACTIVATED); + + BT_DBG("-"); + return 0; +} + +int _bt_core_service_request_adapter(int service_function) +{ + int ret = -1; + + GArray *in_param1 = NULL; + GArray *in_param2 = NULL; + GArray *in_param3 = NULL; + GArray *in_param4 = NULL; + GArray *out_param = NULL; + + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + ret = _bt_core_service_request(BT_CORE_SERVICE, service_function, + in_param1, in_param2, in_param3, in_param4, &out_param); + if (ret < 0) + BT_ERR("_bt_core_service_request_adapter() failed"); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return ret; +} + +static void __bt_core_update_status(void) +{ + int bt_status = VCONFKEY_BT_STATUS_OFF; + int bt_le_status = 0; + + if (vconf_get_int(VCONFKEY_BT_STATUS, &bt_status) < 0) + BT_ERR("no bluetooth device info, so BT was disabled at previous session"); +#ifdef ENABLE_TIZEN_2_4 + if (vconf_get_int(VCONFKEY_BT_LE_STATUS, &bt_le_status) < 0) + BT_ERR("no bluetooth le info, so BT LE was disabled at previous session"); +#endif + + BT_INFO("bt_status = %d, bt_le_status = %d", bt_status, bt_le_status); + + if (bt_status == VCONFKEY_BT_STATUS_OFF) + __bt_core_set_status(BT_DEACTIVATED); + else + __bt_core_set_status(BT_ACTIVATED); + + if (bt_le_status == 0) + __bt_core_set_le_status(BT_LE_DEACTIVATED); + else + __bt_core_set_le_status(BT_LE_ACTIVATED); +} + +static gboolean bt_core_enable_adapter(BtCore *agent, + DBusGMethodInvocation *context) +{ + char *sender = dbus_g_method_get_sender(context); + int ret; + + if (sender == NULL) + return FALSE; + + _bt_set_flightmode_request(FALSE); + if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0) + BT_ERR("Set vconf failed"); + + ret = _bt_enable_adapter(); + if (ret < 0) { + GError *error = bt_core_error(BT_CORE_ERROR_REJECT, + "Activation failed"); + dbus_g_method_return_error(context, error); + g_error_free(error); + g_free(sender); + return FALSE; + } else { + dbus_g_method_return(context); + } + + g_free(sender); + return TRUE; +} + +static gboolean bt_core_disable_adapter(BtCore *agent, + DBusGMethodInvocation *context) +{ + char *sender = dbus_g_method_get_sender(context); + int ret; + + if (sender == NULL) + return FALSE; + + _bt_set_flightmode_request(FALSE); + if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0) + BT_ERR("Set vconf failed"); + + ret = _bt_disable_adapter(); + if (ret < 0) { + GError *error = bt_core_error(BT_CORE_ERROR_REJECT, + "Deactivation failed"); + dbus_g_method_return_error(context, error); + g_error_free(error); + g_free(sender); + return FALSE; + } else { + dbus_g_method_return(context); + } + + g_free(sender); + return TRUE; +} + +static gboolean bt_core_recover_adapter(BtCore *agent, + DBusGMethodInvocation *context) +{ + int ret; + int ret_le; + + BT_INFO_C("Recover bt adapter"); + + dbus_g_method_return(context); + + _bt_set_flightmode_request(FALSE); + if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0) + BT_ERR("Set vconf failed"); + + is_recovery_mode = TRUE; + + __bt_core_update_status(); + + if (_bt_core_get_status() == BT_ACTIVATED) { + _bt_core_set_bt_status(BT_RECOVERY_MODE, 1); + _bt_core_service_request_adapter(BT_DISABLE_ADAPTER); + } + if (_bt_core_get_le_status() == BT_LE_ACTIVATED) { + _bt_core_set_bt_le_status(BT_RECOVERY_MODE, 1); + _bt_core_service_request_adapter(BT_DISABLE_ADAPTER_LE); + } + + ret = _bt_disable_adapter(); + if (ret < 0) + BT_ERR("_bt_disable_adapter() failed"); + ret_le = _bt_disable_adapter_le(); + if (ret_le < 0) + BT_ERR("_bt_disable_adapter_le() failed"); + + return TRUE; +} + +static gboolean bt_core_enable_adapter_le(BtCore *agent, + DBusGMethodInvocation *context) +{ + char *sender = dbus_g_method_get_sender(context); + int ret; + + if (sender == NULL) + return FALSE; + + ret = _bt_enable_adapter_le(); + if (ret < 0) { + GError *error = bt_core_error(BT_CORE_ERROR_REJECT, + "LE Activation failed"); + dbus_g_method_return_error(context, error); + g_error_free(error); + g_free(sender); + BT_DBG("-"); + return FALSE; + } else { + dbus_g_method_return(context); + } + + g_free(sender); + BT_DBG("-"); + return TRUE; +} + +static gboolean bt_core_disable_adapter_le(BtCore *agent, + DBusGMethodInvocation *context) +{ + BT_DBG("+"); + + char *sender = dbus_g_method_get_sender(context); + BT_DBG("sender : %s", sender); + int ret; + + if (sender == NULL) + return FALSE; + + ret = _bt_disable_adapter_le(); + if (ret < 0) { + GError *error = bt_core_error(BT_CORE_ERROR_REJECT, + "LE Deactivation failed"); + dbus_g_method_return_error(context, error); + g_error_free(error); + g_free(sender); + return FALSE; + } else { + dbus_g_method_return(context); + } + + g_free(sender); + BT_DBG("-"); + return TRUE; +} + +static int __bt_reset_adapter(void) +{ + /* Forcely terminate */ + if (__execute_command("/usr/etc/bluetooth/bt-reset-env.sh", NULL) < 0) { + BT_ERR("running script failed"); + } + _bt_core_terminate(); + return 0; +} + +static gboolean bt_core_reset_adapter(BtCore *agent, + DBusGMethodInvocation *context) +{ + char *sender = dbus_g_method_get_sender(context); + int ret; + + if (sender == NULL) + return FALSE; + + ret = __bt_reset_adapter(); + if (ret < 0) { + GError *error = bt_core_error(BT_CORE_ERROR_REJECT, + "Deactivation failed"); + dbus_g_method_return_error(context, error); + g_error_free(error); + g_free(sender); + return FALSE; + } else { + dbus_g_method_return(context); + } + + g_free(sender); + return TRUE; +} + +static gboolean __bt_core_enable_core_timeout_cb(gpointer data) +{ + BT_DBG("+"); + + _bt_core_init_vconf_value(); + + return FALSE; +} + +static gboolean bt_core_enable_core(BtCore *agent, + DBusGMethodInvocation *context) +{ + char *sender = dbus_g_method_get_sender(context); + + if (sender == NULL) + return FALSE; + + BT_DBG("+"); + + __bt_core_update_status(); + + g_timeout_add(200, (GSourceFunc)__bt_core_enable_core_timeout_cb, NULL); + + dbus_g_method_return(context); + + g_free(sender); + + BT_DBG("-"); + return TRUE; +} + +static gboolean __bt_core_recovery_cb(gpointer data) +{ + int ret = 0; + gboolean is_request_failed = FALSE; + static gboolean is_first_failure = TRUE; + + BT_DBG("+"); + + if (_bt_core_get_bt_status(BT_RECOVERY_MODE) == 1) { + ret = _bt_core_service_request_adapter(BT_ENABLE_ADAPTER); + if (ret < 0) + is_request_failed = TRUE; + } + + if (_bt_core_get_bt_le_status(BT_RECOVERY_MODE) == 1) { + ret = _bt_core_service_request_adapter(BT_ENABLE_ADAPTER_LE); + if (ret < 0) + is_request_failed = TRUE; + } + + if (is_request_failed == TRUE) { + BT_ERR("Recovery is failed."); + if (is_first_failure == TRUE) { + g_timeout_add(2000, (GSourceFunc)__bt_core_recovery_cb, NULL); + is_first_failure = FALSE; + return FALSE; + } else { + is_first_failure = TRUE; + return FALSE; + } + } else + is_first_failure = TRUE; + + if (_bt_core_get_bt_status(BT_RECOVERY_MODE) == 1) { + _bt_core_set_bt_status(BT_RECOVERY_MODE, 0); + ret = _bt_enable_adapter(); + if (ret < 0) + BT_ERR("_bt_enable_adapter() failed"); + } + if (_bt_core_get_bt_le_status(BT_RECOVERY_MODE) == 1) { + _bt_core_set_bt_le_status(BT_RECOVERY_MODE, 0); + ret = _bt_enable_adapter_le(); + if (ret < 0) + BT_ERR("_bt_enable_adapter_le() failed"); + } + + is_recovery_mode = FALSE; + + BT_DBG("-"); + + return FALSE; +} + +static gboolean __bt_core_enable_timeout_cb(gpointer data) +{ + bt_status_t adapter_status; + bt_le_status_t adapter_status_le; + + BT_DBG(""); + + if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0) + BT_ERR("Set vconf failed"); + + adapter_status = _bt_core_get_status(); + adapter_status_le = _bt_core_get_le_status(); + + if (adapter_status == BT_DEACTIVATED && + _bt_core_get_bt_status(BT_FLIGHT_MODE) != 0) { + _bt_core_set_bt_status(BT_FLIGHT_MODE, 0); + _bt_core_service_request_adapter(BT_ENABLE_ADAPTER); + _bt_enable_adapter(); + } + + if (adapter_status_le == BT_LE_DEACTIVATED && + _bt_core_get_bt_le_status(BT_FLIGHT_MODE) != 0) { + _bt_core_set_bt_le_status(BT_FLIGHT_MODE, 0); + _bt_core_service_request_adapter(BT_ENABLE_ADAPTER_LE); + _bt_enable_adapter_le(); + } + + return FALSE; +} + +static gboolean __bt_core_disable_timeout_cb(gpointer data) +{ + bt_status_t adapter_status; + bt_le_status_t adapter_status_le; + + BT_DBG(""); + + if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 1) != 0) + BT_ERR("Set vconf failed"); + + adapter_status = _bt_core_get_status(); + adapter_status_le = _bt_core_get_le_status(); + + if (adapter_status == BT_ACTIVATED) { + int bt_status_before_mode = 0; + + if (vconf_get_int(VCONFKEY_BT_STATUS, &bt_status_before_mode) == 0) + _bt_core_set_bt_status(BT_FLIGHT_MODE, bt_status_before_mode); + + _bt_core_service_request_adapter(BT_DISABLE_ADAPTER); + _bt_disable_adapter(); + } + + if (adapter_status_le == BT_LE_ACTIVATED) { + int bt_le_status_before_mode = 0; + +#ifdef ENABLE_TIZEN_2_4 + if (vconf_get_int(VCONFKEY_BT_LE_STATUS, &bt_le_status_before_mode) == 0) + _bt_core_set_bt_le_status(BT_FLIGHT_MODE, bt_le_status_before_mode); +#endif + + _bt_core_service_request_adapter(BT_DISABLE_ADAPTER_LE); + _bt_disable_adapter_le(); + } + + return FALSE; +} + +void _bt_core_adapter_added_cb(void) +{ + bt_status_t status; + bt_le_status_t le_status; + gboolean flight_mode_status; + + BT_DBG(""); + + status = _bt_core_get_status(); + BT_DBG("status : %d", status); + le_status = _bt_core_get_le_status(); + BT_DBG("le_status : %d", le_status); + + if (status == BT_ACTIVATING) + __bt_core_set_status(BT_ACTIVATED); + if (le_status == BT_LE_ACTIVATING) + __bt_core_set_le_status(BT_LE_ACTIVATED); + + flight_mode_status = _bt_core_is_flight_mode_enabled(); + + if (flight_mode_status == TRUE && _bt_is_flightmode_request() == TRUE) { + _bt_set_flightmode_request(FALSE); + g_timeout_add(2000, (GSourceFunc)__bt_core_disable_timeout_cb, NULL); + return; + } + _bt_set_flightmode_request(FALSE); + + _bt_core_terminate(); +} + +void _bt_core_adapter_removed_cb(void) +{ + int flight_mode_value = 0; + int power_saving_mode = 0; + gboolean flight_mode_status; + static int timer_id = -1; + + BT_DBG(""); + + __bt_core_set_status(BT_DEACTIVATED); + __bt_core_set_le_status(BT_LE_DEACTIVATED); + if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_OFF) != 0) + BT_ERR("Set vconf failed"); +#ifdef ENABLE_TIZEN_2_4 + if (vconf_set_int(VCONFKEY_BT_LE_STATUS, VCONFKEY_BT_LE_STATUS_OFF) != 0) + BT_ERR("Set vconf failed"); +#endif + + if (is_recovery_mode == TRUE) + { + if (timer_id < 0) + timer_id = g_timeout_add(2000, (GSourceFunc)__bt_core_recovery_cb, NULL); + return; + } + + if (vconf_get_int(BT_OFF_DUE_TO_FLIGHT_MODE, &flight_mode_value) != 0) + BT_ERR("Fail to get the flight_mode_deactivated value"); + + if (vconf_get_int(BT_OFF_DUE_TO_POWER_SAVING_MODE, &power_saving_mode) != 0) + BT_ERR("Fail to get the ps_mode_deactivated value"); + + flight_mode_status = _bt_core_is_flight_mode_enabled(); + + if (flight_mode_status == FALSE && _bt_is_flightmode_request() == TRUE) { + _bt_set_flightmode_request(FALSE); + if (timer_id < 0) + timer_id = g_timeout_add(2000, (GSourceFunc)__bt_core_enable_timeout_cb, NULL); + return; + } + _bt_set_flightmode_request(FALSE); + + if (flight_mode_value == 1 || power_saving_mode == 1){ + BT_DBG("Bt Core not terminated"); + return; + } + + _bt_core_terminate(); +} + diff --git a/bt-core/bt-core-adapter.xml b/bt-core/bt-core-adapter.xml new file mode 100755 index 0000000..82682cf --- /dev/null +++ b/bt-core/bt-core-adapter.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bt-core/bt-core-dbus-handler.c b/bt-core/bt-core-dbus-handler.c new file mode 100755 index 0000000..4895a23 --- /dev/null +++ b/bt-core/bt-core-dbus-handler.c @@ -0,0 +1,463 @@ +/* + * Bluetooth-frwk + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * 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 +#include +#include + +#include "bt-core-adapter.h" +#include "bt-core-common.h" +#include "bt-core-dbus-handler.h" +#include "bt-internal-types.h" +#include "bt-request-service.h" +#include "bt-core-noti-handler.h" +#include "bt-core-main.h" + +#define BT_SERVICE_NAME "org.projectx.bt" +#define BT_SERVICE_PATH "/org/projectx/bt_service" + +DBusGProxy *service_proxy = NULL; +DBusGConnection *service_conn = NULL; + +static GDBusConnection *service_gconn; +static GDBusProxy *service_gproxy; + +void _bt_core_fill_garray_from_variant(GVariant *var, GArray *param) +{ + char *data; + int size; + + size = g_variant_get_size(var); + if (size > 0) { + data = (char *)g_variant_get_data(var); + if (data) + param = g_array_append_vals(param, data, size); + + } +} + +static GDBusProxy *__bt_core_gdbus_init_service_proxy(void) +{ + GDBusProxy *proxy; + GError *err = NULL; + + g_type_init(); + + if (service_gconn == NULL) + service_gconn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err); + + if (!service_gconn) { + if (err) { + BT_ERR("Unable to connect to dbus: %s", err->message); + g_clear_error(&err); + } + return NULL; + } + + proxy = g_dbus_proxy_new_sync(service_gconn, + G_DBUS_PROXY_FLAGS_NONE, NULL, + BT_SERVICE_NAME, + BT_SERVICE_PATH, + BT_SERVICE_NAME, + NULL, &err); + if (!proxy) { + if (err) { + BT_ERR("Unable to create proxy: %s", err->message); + g_clear_error(&err); + } + + g_object_unref(service_gconn); + service_gconn = NULL; + return NULL; + } + + service_gproxy = proxy; + + return proxy; +} + +GDBusProxy *_bt_core_gdbus_get_service_proxy(void) +{ + return (service_gproxy) ? service_gproxy : __bt_core_gdbus_init_service_proxy(); +} + +void _bt_core_gdbus_deinit_proxys(void) +{ + if (service_gproxy) { + g_object_unref(service_proxy); + service_proxy = NULL; + } + + if (service_gconn) { + g_object_unref(service_gconn); + service_gconn = NULL; + } +} + +int _bt_core_service_request(int service_type, int service_function, + GArray *in_param1, GArray *in_param2, + GArray *in_param3, GArray *in_param4, + GArray **out_param1) +{ + GDBusProxy *proxy; + GVariant *ret; + GVariant *param1; + GVariant *param2; + GVariant *param3; + GVariant *param4; + GVariant *param5; + + int result = BLUETOOTH_ERROR_NONE; + GError *error = NULL; + GArray *in_param5 = NULL; + GArray *out_param2 = NULL; + + proxy = _bt_core_gdbus_get_service_proxy(); + if (!proxy) + return BLUETOOTH_ERROR_INTERNAL; + in_param5 = g_array_new(TRUE, TRUE, sizeof(gchar)); + + param1 = g_variant_new_from_data((const GVariantType *)"ay", + in_param1->data, in_param1->len, + TRUE, NULL, NULL); + param2 = g_variant_new_from_data((const GVariantType *)"ay", + in_param2->data, in_param2->len, + TRUE, NULL, NULL); + param3 = g_variant_new_from_data((const GVariantType *)"ay", + in_param3->data, in_param3->len, + TRUE, NULL, NULL); + param4 = g_variant_new_from_data((const GVariantType *)"ay", + in_param4->data, in_param4->len, + TRUE, NULL, NULL); + param5 = g_variant_new_from_data((const GVariantType *)"ay", + in_param5->data, in_param5->len, + TRUE, NULL, NULL); + + ret = g_dbus_proxy_call_sync(proxy, "service_request", + g_variant_new("(iii@ay@ay@ay@ay@ay)", + service_type, service_function, + BT_SYNC_REQ, param1, + param2, param3, + param4, param5), + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, &error); + + g_array_free(in_param5, TRUE); + + if (ret == NULL) { + /* dBUS-RPC is failed */ + BT_ERR("dBUS-RPC is failed"); + + if (error != NULL) { + /* dBUS gives error cause */ + BT_ERR("D-Bus API failure: errCode[%x], message[%s]", + error->code, error->message); + + g_clear_error(&error); + } else { + /* dBUS does not give error cause dBUS-RPC is failed */ + BT_ERR("error returned was NULL"); + } + + return BLUETOOTH_ERROR_INTERNAL; + } + + param1 = NULL; + param2 = NULL; + + g_variant_get(ret, "(@ay@ay)", ¶m1, ¶m2); + + if (param1) { + *out_param1 = g_array_new(TRUE, TRUE, sizeof(gchar)); + _bt_core_fill_garray_from_variant(param1, *out_param1); + g_variant_unref(param1); + } + + if (param2) { + out_param2 = g_array_new(TRUE, TRUE, sizeof(gchar)); + _bt_core_fill_garray_from_variant(param2, out_param2); + result = g_array_index(out_param2, int, 0); + g_variant_unref(param2); + g_array_free(out_param2, TRUE); + } else { + result = BLUETOOTH_ERROR_INTERNAL; + } + + g_variant_unref(ret); + + return result; +} + + +static int __bt_core_get_object_path(DBusMessage *msg, char **path) +{ + DBusMessageIter item_iter; + + dbus_message_iter_init(msg, &item_iter); + + if (dbus_message_iter_get_arg_type(&item_iter) + != DBUS_TYPE_OBJECT_PATH) { + BT_ERR("This is bad format dbus"); + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_iter_get_basic(&item_iter, path); + + if (*path == NULL) + return BLUETOOTH_ERROR_INTERNAL; + + return BLUETOOTH_ERROR_NONE; +} + +static int __bt_core_get_owner_info(DBusMessage *msg, char **name, + char **previous, char **current) +{ + DBusMessageIter item_iter; + + dbus_message_iter_init(msg, &item_iter); + + if (dbus_message_iter_get_arg_type(&item_iter) + != DBUS_TYPE_STRING) { + BT_ERR("This is bad format dbus"); + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_iter_get_basic(&item_iter, name); + + if (*name == NULL) + return BLUETOOTH_ERROR_INTERNAL; + + dbus_message_iter_next(&item_iter); + + if (dbus_message_iter_get_arg_type(&item_iter) + != DBUS_TYPE_STRING) { + BT_ERR("This is bad format dbus"); + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_iter_get_basic(&item_iter, previous); + + if (*previous == NULL) + return BLUETOOTH_ERROR_INTERNAL; + + dbus_message_iter_next(&item_iter); + + if (dbus_message_iter_get_arg_type(&item_iter) + != DBUS_TYPE_STRING) { + BT_ERR("This is bad format dbus"); + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_iter_get_basic(&item_iter, current); + + if (*current == NULL) + return BLUETOOTH_ERROR_INTERNAL; + + return BLUETOOTH_ERROR_NONE; +} + +static DBusHandlerResult __bt_core_event_filter(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + char *object_path = NULL; + const char *member = dbus_message_get_member(msg); + + if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (member == NULL) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (strcasecmp(member, "InterfacesAdded") == 0) { + if (__bt_core_get_object_path(msg, &object_path)) { + BT_ERR("Fail to get the path"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if (strcasecmp(object_path, "/org/bluez/hci0") == 0) { + _bt_core_adapter_added_cb(); + } + } else if (strcasecmp(member, "InterfacesRemoved") == 0) { + if (__bt_core_get_object_path(msg, &object_path)) { + BT_ERR("Fail to get the path"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if (strcasecmp(object_path, "/org/bluez/hci0") == 0) { + _bt_core_adapter_removed_cb(); + } + } else if (strcasecmp(member, "NameOwnerChanged") == 0) { + char *name = NULL; + char *previous = NULL; + char *current = NULL; + gboolean flight_mode_status; + + if (__bt_core_get_owner_info(msg, &name, &previous, ¤t)) { + BT_ERR("Fail to get the owner info"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if (*current != '\0') + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (vconf_get_bool(VCONFKEY_TELEPHONY_FLIGHT_MODE, &flight_mode_status) != 0) + BT_ERR("Fail to get the flight_mode status value"); + if (flight_mode_status == FALSE && _bt_is_flightmode_request() == TRUE) { + BT_DBG("flightmode requested"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if (strcasecmp(name, "org.bluez") == 0) { + BT_DBG("Bluetoothd is terminated"); + if (_bt_check_terminating_condition() == TRUE) { + _bt_disable_adapter(); + _bt_disable_adapter_le(); + _bt_core_terminate(); + } + } else if (strcasecmp(name, "org.projectx.bt") == 0) { + BT_DBG("bt-service is terminated"); + if (_bt_check_terminating_condition() == TRUE) { + _bt_disable_adapter(); + _bt_disable_adapter_le(); + _bt_core_terminate(); + } + } + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +DBusGProxy *_bt_core_register_event_filter(DBusGConnection *g_conn, + BtCore *bt_core) +{ + DBusError dbus_error; + DBusConnection *conn; + DBusGProxy *proxy; + GError *err = NULL; + guint result = 0; + + if (g_conn == NULL) + return NULL; + + conn = dbus_g_connection_get_connection(g_conn); + if (conn == NULL) + return NULL; + + proxy = dbus_g_proxy_new_for_name(g_conn, DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); + if (proxy == NULL) { + BT_ERR("proxy is NULL"); + return NULL; + } + + if (!dbus_g_proxy_call(proxy, "RequestName", &err, G_TYPE_STRING, + BT_CORE_NAME, G_TYPE_UINT, 0, G_TYPE_INVALID, + G_TYPE_UINT, &result, G_TYPE_INVALID)) { + if (err != NULL) { + BT_ERR("RequestName RPC failed[%s]\n", err->message); + g_error_free(err); + } + g_object_unref(proxy); + return NULL; + } + + if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + BT_ERR("Failed to get the primary well-known name.\n"); + g_object_unref(proxy); + return NULL; + } + + if (!dbus_connection_add_filter(conn, __bt_core_event_filter, + NULL, NULL)) { + BT_ERR("Fail to add filter"); + g_object_unref(proxy); + return NULL; + } + + dbus_error_init(&dbus_error); + + dbus_bus_add_match(conn, + "type='signal',interface='org.freedesktop.DBus'" + ",member='NameOwnerChanged'", + &dbus_error); + + if (dbus_error_is_set(&dbus_error)) { + BT_ERR("Fail to add match: %s\n", dbus_error.message); + dbus_error_free(&dbus_error); + g_object_unref(proxy); + return NULL; + } + + dbus_bus_add_match(conn, + "type='signal',interface='org.freedesktop.DBus.ObjectManager'" + ",member='InterfacesAdded'", + &dbus_error); + + if (dbus_error_is_set(&dbus_error)) { + BT_ERR("Fail to add match: %s\n", dbus_error.message); + dbus_error_free(&dbus_error); + g_object_unref(proxy); + return NULL; + } + + dbus_bus_add_match(conn, + "type='signal',interface='org.freedesktop.DBus.ObjectManager'" + ",member='InterfacesRemoved'", + &dbus_error); + + if (dbus_error_is_set(&dbus_error)) { + BT_ERR("Fail to add match: %s\n", dbus_error.message); + dbus_error_free(&dbus_error); + g_object_unref(proxy); + return NULL; + } + + dbus_g_connection_register_g_object(g_conn, BT_CORE_PATH, + G_OBJECT(bt_core)); + + return proxy; +} + +void _bt_unregister_event_filter(DBusGConnection *g_conn, + BtCore *bt_core, + DBusGProxy *dbus_proxy) +{ + DBusConnection *conn; + + if (g_conn == NULL || + bt_core == NULL || + dbus_proxy == NULL) { + BT_ERR("Invalid parameter"); + return; + } + + conn = dbus_g_connection_get_connection(g_conn); + + dbus_connection_remove_filter(conn, __bt_core_event_filter, NULL); + + dbus_g_connection_unregister_g_object(g_conn, G_OBJECT(bt_core)); + + g_object_unref(bt_core); + g_object_unref(dbus_proxy); +} + diff --git a/bt-core/bt-core-main.c b/bt-core/bt-core-main.c new file mode 100755 index 0000000..4afda78 --- /dev/null +++ b/bt-core/bt-core-main.c @@ -0,0 +1,201 @@ +/* + * Bluetooth-frwk + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * 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 +#include + +#include "bt-core-adapter.h" +#include "bt-core-dbus-handler.h" +#include "bt-core-main.h" +#include "bt-core-noti-handler.h" +#include "bt-core-common.h" + +static GMainLoop *main_loop = NULL; + +gboolean _bt_check_terminating_condition(void) +{ + int bt_off_flight_mode = 0; /* if BT was off due to FlightMode*/ + int bt_off_ps_mode = 0; + + if (_bt_core_is_recovery_mode() == TRUE) { + BT_DBG("Bt core not terminated"); + return FALSE; + } + + if (vconf_get_int(BT_OFF_DUE_TO_FLIGHT_MODE, &bt_off_flight_mode) != 0) + BT_ERR("Fail to get the BT off due to FlightMode value"); + if (vconf_get_int(BT_OFF_DUE_TO_POWER_SAVING_MODE, &bt_off_ps_mode) != 0) + BT_ERR("Fail to get the ps_mode_deactivated value"); + + if (bt_off_flight_mode == 1 || bt_off_ps_mode == 1) { + BT_DBG("Bt core not terminated"); + return FALSE; + } + + return TRUE; +} + +void _bt_core_terminate(void) +{ + if (_bt_check_terminating_condition() == FALSE) + return; + + _bt_core_gdbus_deinit_proxys(); + _bt_core_unregister_vconf_handler(); + if (main_loop) { + g_main_loop_quit(main_loop); + } else { + BT_DBG("Terminating bt-core daemon"); + exit(0); + } +} + +static void __bt_core_sigterm_handler(int signo) +{ + BT_DBG("Got the signal: %d", signo); + + _bt_core_terminate(); +} + +static gboolean __bt_check_bt_core(void *data) +{ + int bt_status = VCONFKEY_BT_STATUS_OFF; + int bt_le_status = 0; + bt_status_t status = BT_DEACTIVATED; + bt_le_status_t le_status = BT_LE_DEACTIVATED; + int flight_mode_deactivation = 0; + int bt_off_due_to_timeout = 0; + int ps_mode_deactivation = 0; + + status = _bt_core_get_status(); + le_status = _bt_core_get_le_status(); + BT_DBG("State: %d, LE State: %d", status, le_status); + + if (vconf_get_int(VCONFKEY_BT_STATUS, &bt_status) < 0) { + BT_DBG("no bluetooth device info, so BT was disabled at previous session"); + } + +#ifdef ENABLE_TIZEN_2_4 + if (vconf_get_int(VCONFKEY_BT_LE_STATUS, &bt_le_status) < 0) { + BT_ERR("no bluetooth le info, so BT LE was disabled at previous session"); + } +#endif + + if (vconf_get_int(BT_OFF_DUE_TO_FLIGHT_MODE, &flight_mode_deactivation) != 0) + BT_ERR("Fail to get the flight_mode_deactivation value"); + + if (vconf_get_int(BT_OFF_DUE_TO_POWER_SAVING_MODE, &ps_mode_deactivation) != 0) + BT_ERR("Fail to get the ps_mode_deactivation value"); + + if (vconf_get_int(BT_OFF_DUE_TO_TIMEOUT, &bt_off_due_to_timeout) != 0) + BT_ERR("Fail to get BT_OFF_DUE_TO_TIMEOUT"); + + if ((bt_status != VCONFKEY_BT_STATUS_OFF || bt_off_due_to_timeout) + && (status == BT_DEACTIVATED)) { + BT_DBG("Previous session was enabled."); + + /* Enable the BT */ + _bt_core_service_request_adapter(BT_ENABLE_ADAPTER); + _bt_enable_adapter(); + } else if (bt_status == VCONFKEY_BT_STATUS_OFF && + (flight_mode_deactivation == 1 || ps_mode_deactivation > 0)) { + _bt_core_handle_flight_mode_noti(); + _bt_core_handle_power_saving_mode_noti(); + + _bt_core_set_bt_status(BT_FLIGHT_MODE, flight_mode_deactivation); + _bt_core_set_bt_status(BT_POWER_SAVING_MODE, ps_mode_deactivation); + } + + if ((bt_le_status == 1) && (le_status == BT_LE_DEACTIVATED)) { + BT_DBG("Previous session was le enabled. Turn BT LE on automatically."); + + /* Enable the BT LE */ + _bt_core_service_request_adapter(BT_ENABLE_ADAPTER_LE); + _bt_enable_adapter_le(); + } else { + status = _bt_core_get_status(); + le_status = _bt_core_get_le_status(); + BT_DBG("State: %d, LE State: %d", status, le_status); + + if ((status != BT_ACTIVATING && status != BT_ACTIVATED) && + (le_status != BT_LE_ACTIVATING && le_status != BT_LE_ACTIVATED)) + _bt_core_terminate(); + } + + return FALSE; +} + +int main(void) +{ + DBusGConnection *conn = NULL; + GError *error = NULL; + BtCore *bt_core = NULL; + + DBusGProxy *dbus_proxy = NULL; + struct sigaction sa; + + g_type_init(); + BT_INFO_C("Starting bt-core daemeon"); + + conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error); + if (error != NULL) { + BT_ERR("ERROR: Can't get on system bus [%s]", error->message); + g_error_free(error); + goto fail; + } + + bt_core = g_object_new(BT_CORE_TYPE, NULL); + + dbus_proxy = _bt_core_register_event_filter(conn, bt_core); + if (!dbus_proxy) { + BT_ERR("__bt_core_register_event_filter failed"); + g_object_unref(bt_core); + bt_core = NULL; + goto fail; + } + + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = __bt_core_sigterm_handler; + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + + g_timeout_add(500, (GSourceFunc)__bt_check_bt_core, NULL); + + main_loop = g_main_loop_new(NULL, FALSE); + + g_main_loop_run(main_loop); + +fail: + + _bt_unregister_event_filter(conn, bt_core, dbus_proxy); + + if (main_loop) + g_main_loop_unref(main_loop); + + dbus_g_connection_unref(conn); + + BT_INFO_C("Terminating bt-core daemon"); + + return 0; +} diff --git a/bt-core/bt-core-noti-handler.c b/bt-core/bt-core-noti-handler.c new file mode 100755 index 0000000..e9d8a91 --- /dev/null +++ b/bt-core/bt-core-noti-handler.c @@ -0,0 +1,326 @@ +/* + * Bluetooth-frwk + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * 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 +#include + +#include "bt-core-adapter.h" +#include "bt-core-common.h" +#include "bt-core-noti-handler.h" + +static gboolean flightmode_request = FALSE; + +void _bt_set_flightmode_request(gboolean value) +{ + flightmode_request = value; +} + +gboolean _bt_is_flightmode_request(void) +{ + return flightmode_request; +} + +static gboolean __bt_off_cause_conflict_check(void) +{ + int flight_mode_value = 0; + int ps_mode_value = 0; + gboolean ret = FALSE; + + retv_if (vconf_get_int(BT_OFF_DUE_TO_FLIGHT_MODE, + &flight_mode_value) != 0, FALSE); + retv_if (vconf_get_int(BT_OFF_DUE_TO_POWER_SAVING_MODE, + &ps_mode_value) != 0, FALSE); + + if (flight_mode_value == 1 || ps_mode_value > 0) { + BT_DBG("Bt should not turn on"); + ret = TRUE; + } + + return ret; +} + +static void __bt_core_handle_adapter_with_flight_mode(gboolean flight_mode) +{ + bt_status_t adapter_status; + bt_le_status_t adapter_status_le; + + adapter_status = _bt_core_get_status(); + adapter_status_le = _bt_core_get_le_status(); + + BT_INFO("bt status %d, le status %d", adapter_status, adapter_status_le); + if (flight_mode == TRUE) { + BT_INFO_C("Flight mode on. Turn off BT"); + + if (adapter_status == BT_ACTIVATING || adapter_status_le == BT_LE_ACTIVATING) { + BT_INFO("BT adapter is activating. Turn off BT after activation"); + _bt_set_flightmode_request(TRUE); + return; + } + if (adapter_status != BT_ACTIVATED && adapter_status_le != BT_LE_ACTIVATED) { + BT_INFO("No need to control bt status"); + return; + } + + if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 1) != 0) + BT_ERR("Set vconf failed"); + + if (adapter_status == BT_ACTIVATED) { + int bt_status_before_mode = 0; + + if (vconf_get_int(VCONFKEY_BT_STATUS, &bt_status_before_mode) == 0) + _bt_core_set_bt_status(BT_FLIGHT_MODE, bt_status_before_mode); + + _bt_core_service_request_adapter(BT_DISABLE_ADAPTER); + _bt_disable_adapter(); + } + + if (adapter_status_le == BT_LE_ACTIVATED) { + int bt_le_status_before_mode = 0; + +#ifdef ENABLE_TIZEN_2_4 + if (vconf_get_int(VCONFKEY_BT_LE_STATUS, &bt_le_status_before_mode) == 0) + _bt_core_set_bt_le_status(BT_FLIGHT_MODE, bt_le_status_before_mode); +#endif + + _bt_core_service_request_adapter(BT_DISABLE_ADAPTER_LE); + _bt_disable_adapter_le(); + } + } else { + int flight_mode_value = 0; + + BT_INFO_C("Flight mode off. Turn on BT"); + + if (adapter_status == BT_DEACTIVATING || adapter_status_le == BT_LE_DEACTIVATING) { + BT_INFO("BT adapter is activating. Turn off BT after activation"); + _bt_set_flightmode_request(TRUE); + return; + } + if (adapter_status != BT_DEACTIVATED && adapter_status_le != BT_LE_DEACTIVATED) { + BT_INFO("No need to control bt status"); + return; + } + + if (vconf_get_int(BT_OFF_DUE_TO_FLIGHT_MODE, &flight_mode_value)) + BT_ERR("Fail get flight mode value"); + + if (flight_mode_value == 0) + return; + + if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0) + BT_ERR("Set vconf failed"); + + ret_if(__bt_off_cause_conflict_check()); + + if (adapter_status == BT_DEACTIVATED && + _bt_core_get_bt_status(BT_FLIGHT_MODE) != 0) { + _bt_core_set_bt_status(BT_FLIGHT_MODE, 0); + _bt_core_service_request_adapter(BT_ENABLE_ADAPTER); + _bt_enable_adapter(); + } + + if (adapter_status_le == BT_LE_DEACTIVATED && + _bt_core_get_bt_le_status(BT_FLIGHT_MODE) != 0) { + _bt_core_set_bt_le_status(BT_FLIGHT_MODE, 0); + _bt_core_service_request_adapter(BT_ENABLE_ADAPTER_LE); + _bt_enable_adapter_le(); + } + } +} + +static void __bt_core_handle_adapter_with_power_saving_mode(int power_saving_mode) +{ + bt_status_t adapter_status; + bt_le_status_t adapter_status_le; + + adapter_status = _bt_core_get_status(); + adapter_status_le = _bt_core_get_le_status(); + + if (power_saving_mode == 2) { + BT_DBG("Deactivate Bluetooth Service"); + if (vconf_set_int(BT_OFF_DUE_TO_POWER_SAVING_MODE, 1) != 0) + BT_ERR("Set vconf failed"); + + if (adapter_status == BT_ACTIVATED) { + int bt_status_before_mode = 0; + if (vconf_get_int(VCONFKEY_BT_STATUS, &bt_status_before_mode) == 0) + _bt_core_set_bt_status(BT_POWER_SAVING_MODE, bt_status_before_mode); + + _bt_core_service_request_adapter(BT_DISABLE_ADAPTER); + _bt_disable_adapter(); + } + if (adapter_status_le == BT_LE_ACTIVATED) { + int bt_le_status_before_mode = 0; +#ifdef ENABLE_TIZEN_2_4 + if (vconf_get_int(VCONFKEY_BT_LE_STATUS, &bt_le_status_before_mode) == 0) + _bt_core_set_bt_le_status(BT_POWER_SAVING_MODE, bt_le_status_before_mode); +#endif + /* Disable the BT LE */ + _bt_core_service_request_adapter(BT_DISABLE_ADAPTER_LE); + _bt_disable_adapter_le(); + } + } else { + int ps_mode_value = 0; + + if (vconf_get_int(BT_OFF_DUE_TO_POWER_SAVING_MODE, &ps_mode_value)) + BT_ERR("Fail get power saving mode value"); + + if (ps_mode_value == 0) + return; + + BT_DBG("Activate Bluetooth"); + if (vconf_set_int(BT_OFF_DUE_TO_POWER_SAVING_MODE, 0)) + BT_ERR("Set vconf failed"); + + ret_if(__bt_off_cause_conflict_check()); + + BT_DBG("BT status before Emergency mode() :%d", + _bt_core_get_bt_status(BT_POWER_SAVING_MODE)); + + if (adapter_status == BT_DEACTIVATED && (_bt_core_get_bt_status(BT_POWER_SAVING_MODE) != 0)) { + _bt_core_set_bt_status(BT_POWER_SAVING_MODE, 0); + _bt_core_service_request_adapter(BT_ENABLE_ADAPTER); + _bt_enable_adapter(); + } + BT_DBG("BT LE status before Emergency mode() :%d", _bt_core_get_bt_le_status(BT_POWER_SAVING_MODE)); + if (adapter_status_le == BT_LE_DEACTIVATED && _bt_core_get_bt_le_status(BT_POWER_SAVING_MODE) != 0) { + _bt_core_set_bt_le_status(BT_POWER_SAVING_MODE, 0); + /* Enable the BT LE */ + _bt_core_service_request_adapter(BT_ENABLE_ADAPTER_LE); + _bt_enable_adapter_le(); + } + } +} + +static void __bt_core_flight_mode_cb(keynode_t *node, void *data) +{ + gboolean flight_mode = FALSE; + int type; + + BT_DBG("key = %s", vconf_keynode_get_name(node)); + + type = vconf_keynode_get_type(node); + if (type != VCONF_TYPE_BOOL) { + BT_ERR("Invaild vconf key type : %d", type); + return; + } + + flight_mode = vconf_keynode_get_bool(node); + + __bt_core_handle_adapter_with_flight_mode(flight_mode); +} + +#ifndef TIZEN_WEARABLE +static void __bt_core_power_saving_mode_cb(keynode_t *node, void *data) +{ + int power_saving_mode = 0; + + DBG_SECURE("key=%s", vconf_keynode_get_name(node)); + + if (vconf_keynode_get_type(node) != VCONF_TYPE_INT) { + BT_ERR("Wrong vconf type"); + return; + } + + power_saving_mode = vconf_keynode_get_int(node); + + BT_DBG("value=%d", power_saving_mode); + + __bt_core_handle_adapter_with_power_saving_mode(power_saving_mode); +} +#endif + +void _bt_core_init_vconf_value(void) +{ + gboolean flight_mode = FALSE; + int power_saving_mode = 0; + + _bt_core_handle_flight_mode_noti(); + _bt_core_handle_power_saving_mode_noti(); + + if (vconf_get_bool(VCONFKEY_TELEPHONY_FLIGHT_MODE, &flight_mode) != 0) + BT_ERR("Fail to get the flight_mode status value"); +#ifndef TIZEN_WEARABLE +#ifdef ENABLE_TIZEN_2_4 + if (vconf_get_int(VCONFKEY_SETAPPL_PSMODE, &power_saving_mode) != 0) + BT_ERR("Fail to get the power_saving_mode status value"); +#endif +#endif + BT_DBG("flight_mode = %d, power_saving_mode = %d", flight_mode, power_saving_mode); + + if (flight_mode == TRUE) + __bt_core_handle_adapter_with_flight_mode(flight_mode); + else if (power_saving_mode > 0) + __bt_core_handle_adapter_with_power_saving_mode(power_saving_mode); + else + BT_ERR(""); +} + +void _bt_core_handle_flight_mode_noti(void) +{ +#ifdef TIZEN_TELEPHONY_ENABLED + int ret; + + BT_DBG("+"); + + ret = vconf_notify_key_changed(VCONFKEY_TELEPHONY_FLIGHT_MODE, + (vconf_callback_fn)__bt_core_flight_mode_cb, NULL); + if (ret < 0) + BT_ERR("Unable to register key handler"); + +#else + BT_DBG("Telephony is disabled"); +#endif +} + +void _bt_core_handle_power_saving_mode_noti(void) +{ +#ifndef TIZEN_WEARABLE + int ret; + + BT_DBG("+"); +#ifdef ENABLE_TIZEN_2_4 + ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_PSMODE, + (vconf_callback_fn)__bt_core_power_saving_mode_cb, NULL); +#endif + if (ret < 0) + BT_ERR("Unable to register key handler"); +#endif +} + +void _bt_core_unregister_vconf_handler(void) +{ +#ifdef TIZEN_TELEPHONY_ENABLED + vconf_ignore_key_changed(VCONFKEY_TELEPHONY_FLIGHT_MODE, + (vconf_callback_fn)__bt_core_flight_mode_cb); +#endif + +#ifndef TIZEN_WEARABLE +#ifdef ENABLE_TIZEN_2_4 + vconf_ignore_key_changed(VCONFKEY_SETAPPL_PSMODE, + (vconf_callback_fn)__bt_core_power_saving_mode_cb); +#endif +#endif + + return; +} + diff --git a/bt-core/bt-request-service.xml b/bt-core/bt-request-service.xml new file mode 100755 index 0000000..9d34048 --- /dev/null +++ b/bt-core/bt-request-service.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/bt-core/include/bt-core-adapter.h b/bt-core/include/bt-core-adapter.h new file mode 100755 index 0000000..2c8e6e8 --- /dev/null +++ b/bt-core/include/bt-core-adapter.h @@ -0,0 +1,82 @@ +/* + * Bluetooth-frwk + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _BT_CORE_ADAPTER_H_ +#define _BT_CORE_ADAPTER_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define BT_CORE_TYPE (bt_core_get_type()) + +typedef enum { + BT_DEACTIVATED, + BT_ACTIVATED, + BT_ACTIVATING, + BT_DEACTIVATING, +} bt_status_t; + +typedef enum { + BT_LE_DEACTIVATED, + BT_LE_ACTIVATED, + BT_LE_ACTIVATING, + BT_LE_DEACTIVATING, +} bt_le_status_t; + +typedef enum { + BT_POWER_SAVING_MODE, + BT_FLIGHT_MODE, + BT_RECOVERY_MODE, + BT_MODE_MAX +} bt_mode_e; + +bt_status_t _bt_core_get_status(void); +bt_le_status_t _bt_core_get_le_status(void); +int _bt_core_get_bt_status(bt_mode_e mode); /* Get the status of BT before passed mode */ +int _bt_core_get_bt_le_status(bt_mode_e mode); /* Get the status of BT LE before passed mode */ +void _bt_core_set_bt_status(bt_mode_e mode, int status); /* Set the status of BT before passed mode */ +void _bt_core_set_bt_le_status(bt_mode_e mode, int status); /* Set the status of BT LE before passed mode */ + +gboolean _bt_core_is_recovery_mode(void); +gboolean _bt_core_is_flight_mode_enabled(void); + +int _bt_enable_adapter(void); +int _bt_disable_adapter(void); +int _bt_enable_adapter_le(void); +int _bt_disable_adapter_le(void); +int _bt_core_service_request_adapter(int service_function); + +void _bt_core_adapter_added_cb(void); +void _bt_core_adapter_removed_cb(void); +GType bt_core_get_type (void); +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_CORE_ADAPTER_H_*/ diff --git a/bt-core/include/bt-core-common.h b/bt-core/include/bt-core-common.h new file mode 100755 index 0000000..fe5e86a --- /dev/null +++ b/bt-core/include/bt-core-common.h @@ -0,0 +1,101 @@ +/* + * Bluetooth-frwk + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#ifndef _BT_CORE_COMMON_H_ +#define _BT_CORE_COMMON_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#undef LOG_TAG +#define LOG_TAG "BLUETOOTH_FRWK_CORE" + +#define LOG_COLOR_RESET "\033[0m" +#define LOG_COLOR_RED "\033[31m" +#define LOG_COLOR_YELLOW "\033[33m" +#define LOG_COLOR_GREEN "\033[32m" +#define LOG_COLOR_BLUE "\033[36m" +#define LOG_COLOR_PURPLE "\033[35m" + +#define BT_DBG(fmt, args...) \ + SLOGD(fmt, ##args) +#define BT_INFO(fmt, args...) \ + SLOGI(fmt, ##args) +#define BT_ERR(fmt, args...) \ + SLOGE(fmt, ##args) + +#define BT_INFO_C(fmt, arg...) \ + SLOGI_IF(TRUE, LOG_COLOR_GREEN" "fmt" "LOG_COLOR_RESET, ##arg) +#define BT_ERR_C(fmt, arg...) \ + SLOGI_IF(TRUE, LOG_COLOR_RED" "fmt" "LOG_COLOR_RESET, ##arg) + +#define DBG_SECURE(fmt, args...) SECURE_SLOGD(fmt, ##args) +#define ERR_SECURE(fmt, args...) SECURE_SLOGE(fmt, ##args) + +#define ret_if(expr) \ + do { \ + if (expr) { \ + BT_ERR("(%s) return", #expr); \ + return; \ + } \ + } while (0) + +#define retv_if(expr, val) \ + do { \ + if (expr) { \ + BT_ERR("(%s) return", #expr); \ + return (val); \ + } \ + } while (0) + +#define BT_FREE_PARAMS(IP1,IP2,IP3,IP4,OP) \ + do { \ + if (IP1) \ + g_array_free(IP1, TRUE); \ + if (IP2) \ + g_array_free(IP2, TRUE); \ + if (IP3) \ + g_array_free(IP3, TRUE); \ + if (IP4) \ + g_array_free(IP4, TRUE); \ + if (OP) \ + g_array_free(OP, TRUE); \ + } while (0) + +#define BT_ALLOC_PARAMS(IP1,IP2,IP3,IP4,OP ) \ + do { \ + IP1 = g_array_new(TRUE, TRUE, sizeof(gchar)); \ + IP2 = g_array_new(TRUE, TRUE, sizeof(gchar)); \ + IP3 = g_array_new(TRUE, TRUE, sizeof(gchar)); \ + IP4 = g_array_new(TRUE, TRUE, sizeof(gchar)); \ + } while (0) + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_CORE_COMMON_H_*/ + diff --git a/bt-core/include/bt-core-dbus-handler.h b/bt-core/include/bt-core-dbus-handler.h new file mode 100755 index 0000000..d61d5a5 --- /dev/null +++ b/bt-core/include/bt-core-dbus-handler.h @@ -0,0 +1,80 @@ +/* + * Bluetooth-frwk + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#ifndef _BT_CORE_DBUS_HANDLER_H_ +#define _BT_CORE_DBUS_HANDLER_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#undef LOG_TAG +#define LOG_TAG "BLUETOOTH_FRWK_CORE" + +#define BT_DBG(fmt, args...) \ + SLOGD(fmt, ##args) +#define BT_INFO(fmt, args...) \ + SLOGI(fmt, ##args) +#define BT_ERR(fmt, args...) \ + SLOGE(fmt, ##args) + +#define BT_CORE_NAME "org.projectx.bt_core" +#define BT_CORE_PATH "/org/projectx/bt_core" + +typedef struct _BtCore +{ + GObject object; +} BtCore; + +typedef struct _BtCoreClass +{ + GObjectClass object_class; +} BtCoreClass; + + +DBusGProxy *_bt_core_register_event_filter(DBusGConnection *g_conn, BtCore *bt_core); +void _bt_unregister_event_filter(DBusGConnection *g_conn, BtCore *bt_core, DBusGProxy *dbus_proxy); + +int _bt_core_service_request(int service_type, int service_function, + GArray *in_param1, GArray *in_param2, + GArray *in_param3, GArray *in_param4, + GArray **out_param1); +void _bt_core_fill_garray_from_variant(GVariant *var, GArray *param); +GDBusProxy *_bt_core_gdbus_get_service_proxy(void); +void _bt_core_gdbus_deinit_proxys(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_CORE_DBUS_HANDLER_H_*/ diff --git a/bt-core/include/bt-core-main.h b/bt-core/include/bt-core-main.h new file mode 100755 index 0000000..78c6c64 --- /dev/null +++ b/bt-core/include/bt-core-main.h @@ -0,0 +1,41 @@ +/* + * Bluetooth-frwk + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _BT_CORE_MAIN_H_ +#define _BT_CORE_MAIN_H_ + +#include +#include "bt-internal-types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void _bt_core_terminate(void); +gboolean _bt_check_terminating_condition(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_CORE_MAIN_H_*/ + diff --git a/bt-core/include/bt-core-noti-handler.h b/bt-core/include/bt-core-noti-handler.h new file mode 100755 index 0000000..b2019a8 --- /dev/null +++ b/bt-core/include/bt-core-noti-handler.h @@ -0,0 +1,45 @@ +/* + * Bluetooth-frwk + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _BT_CORE_NOTI_HANDLER_H_ +#define _BT_CORE_NOTI_HANDLER_H_ + +#include "bt-internal-types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void _bt_set_flightmode_request(gboolean value); +gboolean _bt_is_flightmode_request(void); + +void _bt_core_init_vconf_value(void); + +void _bt_core_handle_flight_mode_noti(void); +void _bt_core_handle_power_saving_mode_noti(void); +void _bt_core_unregister_vconf_handler(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_CORE_NOTI_HANDLER_H_*/ diff --git a/bt-core/org.projectx.bt_core.service b/bt-core/org.projectx.bt_core.service old mode 100644 new mode 100755 diff --git a/bt-service/CMakeLists.txt b/bt-service/CMakeLists.txt old mode 100644 new mode 100755 index b835ff7..3317400 --- a/bt-service/CMakeLists.txt +++ b/bt-service/CMakeLists.txt @@ -5,10 +5,12 @@ SET(SRCS marshal.c bt-service-main.c bt-service-event-sender.c +bt-service-headset-connection.c bt-service-event-receiver.c bt-service-common.c bt-service-util.c bt-service-adapter.c +bt-service-adapter-le.c bt-service-device.c bt-service-hid.c bt-service-network.c @@ -23,20 +25,9 @@ bt-service-avrcp.c bt-request-handler.c bt-service-agent.c bt-service-gap-agent.c +bt-service-pbap.c ) -IF(LIBNOTIFY_SUPPORT) -LIST(APPEND SRCS -bt-popup.c -) -ENDIF(LIBNOTIFY_SUPPORT) - -IF(LIBNOTIFICATION_SUPPORT) -LIST(APPEND SRCS -bt-service-agent-notification.c -) -ENDIF(LIBNOTIFICATION_SUPPORT) - IF("${CMAKE_BUILD_TYPE}" STREQUAL "") SET(CMAKE_BUILD_TYPE "Release") ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") @@ -45,15 +36,29 @@ MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include) -INCLUDE(FindPkgConfig) +SET(PKG_MODULES + vconf + aul + vconf + syspopup-caller + dbus-glib-1 + alarm-service + notification + security-server + capi-content-mime-type + capi-network-connection + pkgmgr +# journal +) -IF(LIBNOTIFY_SUPPORT) - pkg_check_modules(service_pkgs REQUIRED vconf aul vconf dbus-glib-1 capi-network-tethering libprivilege-control status alarm-service notification security-server libnotify gdk-pixbuf-2.0 gtk+-3.0) -ELSEIF(LIBNOTIFICATION_SUPPORT) - pkg_check_modules(service_pkgs REQUIRED vconf aul dbus-glib-1 capi-network-tethering libprivilege-control status alarm-service notification security-server) -ELSE() - pkg_check_modules(service_pkgs REQUIRED vconf aul vconf syspopup-caller dbus-glib-1 capi-network-tethering libprivilege-control status alarm-service notification security-server) -ENDIF(LIBNOTIFY_SUPPORT) +IF("$ENV{CFLAGS}" MATCHES "-DTIZEN_NETWORK_TETHERING_ENABLE") +SET(PKG_MODULES ${PKG_MODULES} + capi-network-tethering +) +ENDIF() + +INCLUDE(FindPkgConfig) +pkg_check_modules(service_pkgs REQUIRED ${PKG_MODULES}) FOREACH(flag ${service_pkgs_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag} -Wall") @@ -78,7 +83,9 @@ EXEC_PROGRAM("${MARSHALTOOL}" ARGS "--prefix=marshal ${CMAKE_CURRENT_SOURCE_DIR} FIND_PROGRAM(DBUS_BINDING_TOOL NAMES dbus-binding-tool) EXEC_PROGRAM("${DBUS_BINDING_TOOL}" ARGS "--prefix=bt ${CMAKE_CURRENT_SOURCE_DIR}/bt-request-service.xml --mode=glib-server --output=${CMAKE_CURRENT_SOURCE_DIR}/include/bt-service-method.h") EXEC_PROGRAM("${DBUS_BINDING_TOOL}" ARGS "--prefix=bt_obex_agent ${CMAKE_CURRENT_SOURCE_DIR}/bt-service-obex-agent.xml --mode=glib-server --output=${CMAKE_CURRENT_SOURCE_DIR}/include/bt-obex-agent-method.h") -EXEC_PROGRAM("${DBUS_BINDING_TOOL}" ARGS "--prefix=gap_agent ${CMAKE_CURRENT_SOURCE_DIR}/bt-service-gap-agent.xml --mode=glib-server --output=${CMAKE_CURRENT_SOURCE_DIR}/include/bt-gap-agent-method.h") + +EXEC_PROGRAM("${DBUS_BINDING_TOOL}" ARGS "--prefix=gap_agent ${CMAKE_CURRENT_SOURCE_DIR}/bt-service-gap-agent1.xml --mode=glib-server --output=${CMAKE_CURRENT_SOURCE_DIR}/include/bt-gap-agent-method.h") + EXEC_PROGRAM("${DBUS_BINDING_TOOL}" ARGS "--prefix=bt_media_agent ${CMAKE_CURRENT_SOURCE_DIR}/bt-service-media-agent.xml --mode=glib-server --output=${CMAKE_CURRENT_SOURCE_DIR}/include/bt-media-agent-method.h") ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"") @@ -88,33 +95,21 @@ ADD_DEFINITIONS("-DAPP_DIR=\"${APP_DIR}\"") ADD_DEFINITIONS("-DAPP_LOCALEDIR=\"${APP_LOCALEDIR}\"") ADD_DEFINITIONS("-DAPP_SYSCONFDIR=\"${APP_SYSCONFDIR}\"") -IF(LIBNOTIFY_SUPPORT OR LIBNOTIFICATION_SUPPORT) - ADD_DEFINITIONS("-DDATA_DIR_ICON=\"${SHARE_INSTALL_PREFIX}\"") - MESSAGE("Icon used for notification is : ${SHARE_INSTALL_PREFIX}/icons/default/bt-icon.png") -ENDIF(LIBNOTIFY_SUPPORT OR LIBNOTIFICATION_SUPPORT) - SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie") ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${service_pkgs_LDFLAGS}) -# to permit usage of bluetooth_cancel_bonding in bt-popup.c. This build bluetooth-api first. -IF(LIBNOTIFY_SUPPORT) - ADD_DEPENDENCIES(${PROJECT_NAME} bluetooth-api) - TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${service_pkgs_LDFLAGS} bluetooth-api) -ELSE(LIBNOTIFY_SUPPORT) - TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${service_pkgs_LDFLAGS}) -ENDIF(LIBNOTIFY_SUPPORT) - - -CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/org.projectx.bt.service.in ${CMAKE_CURRENT_SOURCE_DIR}/org.projectx.bt.service) +INSTALL(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/bluetooth-frwk-service DESTINATION /etc/rc.d/init.d) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/org.projectx.bt.service DESTINATION share/dbus-1/system-services) INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/auto-pair-blacklist DESTINATION /opt/var/lib/bluetooth) - -# install booting script -CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/bluetooth-frwk-service.conf.in ${CMAKE_CURRENT_SOURCE_DIR}/bluetooth-frwk-service.conf) -install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/bluetooth-frwk-service.conf DESTINATION /etc/dbus-1/system.d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/auto-pair-blacklist DESTINATION /opt/var/lib/bluetooth/) +IF (TIZEN_WEARABLE) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/wearable/stack_info DESTINATION /usr/etc/bluetooth/) +ELSE () + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/mobile/stack_info DESTINATION /usr/etc/bluetooth/) +ENDIF (TIZEN_WEARABLE) SET(PREFIX ${CMAKE_INSTALL_PREFIX}) diff --git a/bt-service/auto-pair-blacklist b/bt-service/auto-pair-blacklist old mode 100644 new mode 100755 index b186f2c..9f15b76 --- a/bt-service/auto-pair-blacklist +++ b/bt-service/auto-pair-blacklist @@ -1,3 +1,4 @@ -AddressBlacklist=00:02:C7,00:16:FE,00:19:C1,00:1B:FB,00:1E:3D,00:21:4F,00:23:06,00:24:33,00:A0:79,00:0E:6D,00:13:E0,00:21:E8,00:60:57,00:0E:9F,00:12:1C,00:18:91,00:18:96,00:13:04,00:16:FD,00:22:A0,00:0B:4C,00:60:6F,00:23:3D,00:C0:59,00:0A:30,00:1E:AE,00:1C:D7,00:80:F0,00:12:8A,00:09:93,00:80:37,00:26:7E,00:1A:1B,00:14:9A,00:0B:24,08:76:95,00:14:09 +AddressBlacklist=00:02:C7,00:16:FE,00:19:C1,00:1B:FB,00:1E:3D,00:21:4F,00:23:06,00:24:33,00:A0:79,00:0E:6D,00:13:E0,00:21:E8,00:60:57,00:0E:9F,00:12:1C,00:18:91,00:18:96,00:13:04,00:16:FD,00:22:A0,00:0B:4C,00:60:6F,00:23:3D,00:C0:59,00:0A:30,00:1E:AE,00:1C:D7,00:80:F0,00:12:8A,00:09:93,00:80:37,00:26:7E,00:1A:1B,00:14:9A,00:0B:24,08:76:95,00:14:09,00:1E:B2 ExactNameBlacklist=Motorola IHF1000,i.TechBlueBAND,X5 Stereo v1.3,KML_CAN,SYNC,UConnect PartialNameBlacklist=BMW,Audi,Parrot,HandsFreeLink,Car,MB PhoneSystem,CAR MULTIMEDIA,MB Bluetooth,Pama +KeyboardAutoPair=00:0F:F6 diff --git a/bt-service/bluetooth-frwk-service b/bt-service/bluetooth-frwk-service new file mode 100755 index 0000000..7533d97 --- /dev/null +++ b/bt-service/bluetooth-frwk-service @@ -0,0 +1,9 @@ +#!/bin/sh + +# +# Script for running BT Service during booting time +# + +if [ -x /usr/bin/bt-service ]; then + /usr/bin/bt-service & +fi diff --git a/bt-service/bt-request-handler.c b/bt-service/bt-request-handler.c old mode 100644 new mode 100755 index 6dac47e..cdeed94 --- a/bt-service/bt-request-handler.c +++ b/bt-service/bt-request-handler.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -23,12 +27,14 @@ #include #include #include +#include #include "bluetooth-api.h" #include "bt-service-common.h" #include "bt-service-util.h" #include "bt-service-event.h" #include "bt-service-adapter.h" +#include "bt-service-adapter-le.h" #include "bt-service-device.h" #include "bt-service-hid.h" #include "bt-service-network.h" @@ -40,6 +46,7 @@ #include "bt-service-rfcomm-client.h" #include "bt-service-rfcomm-server.h" #include "bt-request-handler.h" +#include "bt-service-pbap.h" /* auto generated header by bt-request-service.xml*/ #include "bt-service-method.h" @@ -47,19 +54,19 @@ DBusGConnection *bt_service_conn; BtService *service_object; -GType bt_service_get_type (void); +GType bt_service_get_type(void); G_DEFINE_TYPE(BtService, bt_service, G_TYPE_OBJECT); /*This is part of platform provided code skeleton for client server model*/ -static void bt_service_class_init (BtServiceClass *service_class) +static void bt_service_class_init(BtServiceClass *service_class) { dbus_g_object_type_install_info(G_TYPE_FROM_CLASS(service_class), &dbus_glib_bt_object_info); } /*This is part of platform provided code skeleton for client server model*/ -static void bt_service_init (BtService *service) +static void bt_service_init(BtService *service) { } @@ -82,11 +89,20 @@ static int __bt_bluez_request(int function_name, case BT_DISABLE_ADAPTER: result = _bt_disable_adapter(); break; + case BT_RECOVER_ADAPTER: + result = _bt_recover_adapter(); + break; + case BT_ENABLE_ADAPTER_LE: + result = _bt_enable_adapter_le(); + break; + case BT_DISABLE_ADAPTER_LE: + result = _bt_disable_adapter_le(); + break; case BT_RESET_ADAPTER: result = _bt_reset_adapter(); break; case BT_CHECK_ADAPTER: { - int enabled = 0; + int enabled = BT_ADAPTER_DISABLED; result = _bt_check_adapter(&enabled); @@ -102,6 +118,14 @@ static int __bt_bluez_request(int function_name, sizeof(bluetooth_device_address_t)); break; } + case BT_GET_LOCAL_VERSION: { + bluetooth_version_t ver = { {0} }; + result = _bt_get_local_version(&ver); + + g_array_append_vals(*out_param1, &ver, + sizeof(bluetooth_version_t)); + break; + } case BT_GET_LOCAL_NAME: { bluetooth_device_name_t local_name = { {0} }; result = _bt_get_local_name(&local_name); @@ -163,19 +187,243 @@ static int __bt_bluez_request(int function_name, } case BT_START_DISCOVERY: result = _bt_start_discovery(); + break; + case BT_START_CUSTOM_DISCOVERY: { + bt_discovery_role_type_t role; + role = g_array_index(in_param1, bt_discovery_role_type_t, 0); + result = _bt_start_custom_discovery(role); + break; + } case BT_CANCEL_DISCOVERY: result = _bt_cancel_discovery(); break; - + case BT_START_LE_DISCOVERY: + result = _bt_start_le_discovery(); + break; + case BT_STOP_LE_DISCOVERY: + result = _bt_stop_le_discovery(); + break; case BT_IS_DISCOVERYING: { gboolean discovering = FALSE; discovering = _bt_is_discovering(); - g_array_append_vals(*out_param1, &discovering, sizeof(gboolean)); break; } + case BT_IS_LE_DISCOVERYING: { + gboolean le_discovering = FALSE; + le_discovering = _bt_is_le_discovering(); + g_array_append_vals(*out_param1, &le_discovering, sizeof(gboolean)); + break; + } + case BT_ENABLE_RSSI: { + bluetooth_device_address_t bd_addr; + int link_type; + bt_rssi_threshold_t rssi_threshold; + int low_threshold; + int in_range_threshold; + int high_threshold; + BT_DBG("Enable RSSI"); + + bd_addr = g_array_index(in_param1, bluetooth_device_address_t, 0); + link_type = g_array_index(in_param2, int, 0); + rssi_threshold = g_array_index(in_param3, bt_rssi_threshold_t, 0); + + low_threshold = rssi_threshold.low_threshold; + in_range_threshold = rssi_threshold.in_range_threshold; + high_threshold = rssi_threshold.high_threshold; + + result = _bt_enable_rssi(&bd_addr, link_type ,low_threshold, + in_range_threshold, high_threshold); + break; + } + case BT_GET_RSSI: { + int link_type; + bluetooth_device_address_t bd_addr; + + BT_DBG("Get RSSI Strength"); + + bd_addr = g_array_index(in_param1, bluetooth_device_address_t, 0); + link_type = g_array_index(in_param2, int, 0); + result = _bt_get_rssi_strength(&bd_addr, link_type); + break; + } + case BT_IS_CONNECTABLE: { + gboolean is_connectable; + + is_connectable = _bt_is_connectable(); + g_array_append_vals(*out_param1, &is_connectable, sizeof(gboolean)); + break; + } + case BT_SET_CONNECTABLE: { + gboolean is_connectable; + + is_connectable = g_array_index(in_param1, gboolean, 0); + + result = _bt_set_connectable(is_connectable); + break; + } + case BT_SET_ADVERTISING: { + gboolean enable = FALSE; + char *sender = NULL; + gboolean use_reserved_slot = FALSE; + + enable = g_array_index(in_param1, gboolean, 0); + use_reserved_slot = g_array_index(in_param2, gboolean, 0); + sender = dbus_g_method_get_sender(context); + result = _bt_set_advertising(enable, sender, use_reserved_slot); + g_free(sender); + break; + } + case BT_SET_CUSTOM_ADVERTISING: { + gboolean enable = FALSE; + bluetooth_advertising_params_t adv_params; + char *sender = NULL; + gboolean use_reserved_slot = FALSE; + + enable = g_array_index(in_param1, gboolean, 0); + adv_params = g_array_index(in_param2, + bluetooth_advertising_params_t, 0); + use_reserved_slot = g_array_index(in_param3, gboolean, 0); + sender = dbus_g_method_get_sender(context); + + BT_DBG("bluetooth_advertising_params_t [%f %f %d %d]", + adv_params.interval_min, adv_params.interval_max, + adv_params.filter_policy, adv_params.type); + result = _bt_set_custom_advertising(enable, &adv_params, sender, use_reserved_slot); + g_free(sender); + break; + } + case BT_GET_ADVERTISING_DATA: { + bluetooth_advertising_data_t adv = { {0} }; + int length = 0; + + result = _bt_get_advertising_data(&adv, &length); + if (result == BLUETOOTH_ERROR_NONE) { + g_array_append_vals(*out_param1, adv.data, length); + } + + break; + } + case BT_SET_ADVERTISING_DATA: { + bluetooth_advertising_data_t adv = { {0} }; + int length; + char *sender = NULL; + gboolean use_reserved_slot = FALSE; + + sender = dbus_g_method_get_sender(context); + + adv = g_array_index(in_param1, + bluetooth_advertising_data_t, 0); + length = g_array_index(in_param2, int, 0); + use_reserved_slot = g_array_index(in_param3, gboolean, 0); + + result = _bt_set_advertising_data(&adv, length, sender, use_reserved_slot); + + g_free(sender); + break; + } + case BT_GET_SCAN_RESPONSE_DATA: { + bluetooth_scan_resp_data_t rsp = { {0} }; + int length = 0; + + result = _bt_get_scan_response_data(&rsp, &length); + if (result == BLUETOOTH_ERROR_NONE) { + g_array_append_vals(*out_param1, rsp.data, length); + } + + break; + } + case BT_SET_SCAN_RESPONSE_DATA: { + bluetooth_scan_resp_data_t rsp = { {0} }; + int length; + char *sender = NULL; + gboolean use_reserved_slot = FALSE; + + sender = dbus_g_method_get_sender(context); + + rsp = g_array_index(in_param1, + bluetooth_scan_resp_data_t, 0); + length = g_array_index(in_param2, int, 0); + use_reserved_slot = g_array_index(in_param3, gboolean, 0); + + result = _bt_set_scan_response_data(&rsp, length, sender, use_reserved_slot); + + g_free(sender); + break; + } + case BT_SET_MANUFACTURER_DATA: { + bluetooth_manufacturer_data_t m_data = { 0 }; + + m_data = g_array_index(in_param1, + bluetooth_manufacturer_data_t, 0); + + result = _bt_set_manufacturer_data(&m_data); + break; + } + case BT_SET_SCAN_PARAMETERS: { + bluetooth_le_scan_params_t scan_params; + + scan_params = g_array_index(in_param1, + bluetooth_le_scan_params_t, 0); + + BT_DBG("bluetooth_le_scan_params_t [%f %f %d]", + scan_params.interval, scan_params.window, + scan_params.type); + + result = _bt_set_scan_parameters(&scan_params); + break; + } + case BT_LE_CONN_UPDATE: { + bluetooth_device_address_t local_address = { {0} }; + bluetooth_le_conn_update_t parameters = {0}; + + local_address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + parameters = g_array_index(in_param2, + bluetooth_le_conn_update_t, 0); + + result = _bt_le_conn_update(local_address.addr, + parameters.interval_min, + parameters.interval_max, + parameters.latency, + parameters.time_out); + break; + } + case BT_IS_ADVERTISING: { + gboolean advertising = FALSE; + advertising = _bt_is_advertising(); + + g_array_append_vals(*out_param1, &advertising, sizeof(gboolean)); + break; + } + case BT_ADD_WHITE_LIST: { + bluetooth_device_address_t address = { {0} }; + int addr_type = 0; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + addr_type = g_array_index(in_param2, int, 0); + + result = _bt_add_white_list(&address, addr_type); + break; + } + case BT_REMOVE_WHITE_LIST: { + bluetooth_device_address_t address = { {0} }; + int addr_type = 0; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + addr_type = g_array_index(in_param2, int, 0); + + result = _bt_remove_white_list(&address, addr_type); + break; + } + case BT_CLEAR_WHITE_LIST: { + result = _bt_clear_white_list(); + break; + } case BT_GET_BONDED_DEVICES: result = _bt_get_bonded_devices(out_param1); break; @@ -202,7 +450,22 @@ static int __bt_bluez_request(int function_name, address = g_array_index(in_param1, bluetooth_device_address_t, 0); - result = _bt_bond_device(request_id, &address, out_param1); + result = _bt_bond_device(request_id, &address, + BLUETOOTH_DEV_CONN_DEFAULT, out_param1); + break; + } + case BT_BOND_DEVICE_BY_TYPE: { + bluetooth_device_address_t address = { {0} }; + unsigned short conn_type = 0; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + conn_type = g_array_index(in_param2, + unsigned short, 0); + + result = _bt_bond_device(request_id, &address, + conn_type, out_param1); break; } case BT_CANCEL_BONDING: { @@ -340,6 +603,20 @@ static int __bt_bluez_request(int function_name, } break; } + case BT_NETWORK_SERVER_DISCONNECT: { + bluetooth_device_address_t address = { {0} }; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + result = _bt_network_server_disconnect(request_id, &address); + if (result != BLUETOOTH_ERROR_NONE) { + g_array_append_vals(*out_param1, &address, + sizeof(bluetooth_device_address_t)); + } + break; + } + case BT_AUDIO_CONNECT: { bluetooth_device_address_t address = { {0} }; @@ -400,6 +677,44 @@ static int __bt_bluez_request(int function_name, &address, out_param1); break; } + case BT_AVRCP_CONTROL_CONNECT: { + bluetooth_device_address_t address = { {0} }; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + result = _bt_audio_connect(request_id, BT_AVRCP, + &address, out_param1); + break; + } + case BT_AVRCP_CONTROL_DISCONNECT: { + bluetooth_device_address_t address = { {0} }; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + result = _bt_audio_disconnect(request_id, BT_AVRCP, + &address, out_param1); + break; + } + case BT_HF_CONNECT: { + bluetooth_device_address_t address = { {0} }; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + result = _bt_hf_connect(request_id, &address, out_param1); + break; + } + case BT_HF_DISCONNECT: { + bluetooth_device_address_t address = { {0} }; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + result = _bt_hf_disconnect(request_id, &address, out_param1); + break; + } case BT_GET_SPEAKER_GAIN: { unsigned int volume; @@ -419,6 +734,15 @@ static int __bt_bluez_request(int function_name, break; } + case BT_SET_CONTENT_PROTECT: { + gboolean status; + + status = g_array_index(in_param1, gboolean, 0); + + result = _bt_audio_set_content_protect(status); + + break; + } case BT_OOB_READ_LOCAL_DATA: { bt_oob_data_t local_oob_data; @@ -456,29 +780,28 @@ static int __bt_bluez_request(int function_name, } case BT_AVRCP_SET_TRACK_INFO: { media_metadata_t data; - media_player_settings_t properties; + media_metadata_attributes_t meta_data; memset(&data, 0x00, sizeof(media_metadata_t)); - memset(&properties, 0x00, sizeof(media_player_settings_t)); + memset(&meta_data, 0x00, sizeof(media_metadata_attributes_t)); data = g_array_index(in_param1, - media_metadata_t, 0); + media_metadata_t, 0); - properties.metadata.title = g_strdup(data.title); - properties.metadata.artists = g_malloc0(sizeof(char *)); - properties.metadata.artists[0] = g_strdup(data.artist); - properties.metadata.album = g_strdup(data.album); - properties.metadata.genres = g_malloc0(sizeof(char *)); - properties.metadata.genres[0] = g_strdup(data.genre); - properties.metadata.tracknumber = data.number; - properties.metadata.duration = data.duration; + meta_data.title = g_strdup(data.title); + meta_data.artist = g_strdup(data.artist); + meta_data.album = g_strdup(data.album); + meta_data.genre = g_strdup(data.genre); + meta_data.total_tracks = data.total_tracks; + meta_data.number = data.number; + meta_data.duration = (int64_t) data.duration; - result = _bt_avrcp_set_properties(&properties); + result = _bt_avrcp_set_track_info(&meta_data); - g_free((gpointer)properties.metadata.title); - g_free((gpointer)properties.metadata.artists); - g_free((gpointer)properties.metadata.album); - g_free((gpointer)properties.metadata.genres); + g_free((gpointer)meta_data.title); + g_free((gpointer)meta_data.artist); + g_free((gpointer)meta_data.album); + g_free((gpointer)meta_data.genre); break; } @@ -505,7 +828,93 @@ static int __bt_bluez_request(int function_name, break; } + case BT_AVRCP_HANDLE_CONTROL: { + int type; + + type = g_array_index(in_param1, + int, 0); + + result = _bt_avrcp_control_cmd(type); + + break; + } + case BT_AVRCP_CONTROL_SET_PROPERTY: { + int type; + unsigned int value; + + type = g_array_index(in_param1, int, 0); + value = g_array_index(in_param2, unsigned int, 0); + + result = _bt_avrcp_control_set_property(type, value); + + break; + } + case BT_AVRCP_CONTROL_GET_PROPERTY: { + int type; + unsigned int value; + + type = g_array_index(in_param1, + int, 0); + + result = _bt_avrcp_control_get_property(type, &value); + g_array_append_vals(*out_param1, &value, sizeof(int)); + + break; + } + case BT_AVRCP_GET_TRACK_INFO: { + media_metadata_t meta_data; + media_metadata_attributes_t metadata; + + memset(&meta_data, 0x00, sizeof(media_metadata_t)); + memset(&metadata, 0x00, sizeof(media_metadata_attributes_t)); + + result = _bt_avrcp_control_get_track_info(&metadata); + + if (BLUETOOTH_ERROR_NONE != result) + break; + + if (_bt_copy_utf8_string(meta_data.title, metadata.title, + BT_META_DATA_MAX_LEN)) + BT_ERR("Error in copying Title\n"); + if (_bt_copy_utf8_string(meta_data.artist, metadata.artist, + BT_META_DATA_MAX_LEN)) + BT_ERR("Error in copying Artist\n"); + if (_bt_copy_utf8_string(meta_data.album, metadata.album, + BT_META_DATA_MAX_LEN)) + BT_ERR("Error in copying Album\n"); + if (_bt_copy_utf8_string(meta_data.genre, metadata.genre, + BT_META_DATA_MAX_LEN)) + BT_ERR("Error in copying Genre\n"); + + if (_bt_utf8_validate(meta_data.title) == FALSE) + meta_data.title[0] = '\0'; + + if (_bt_utf8_validate(meta_data.artist) == FALSE) + meta_data.artist[0] = '\0'; + + if (_bt_utf8_validate(meta_data.album) == FALSE) + meta_data.album[0] = '\0'; + + if (_bt_utf8_validate(meta_data.genre) == FALSE) + meta_data.genre[0] = '\0'; + + meta_data.total_tracks = metadata.total_tracks; + meta_data.number = metadata.number; + meta_data.duration = metadata.duration; + + g_free((gpointer)metadata.title); + g_free((gpointer)metadata.artist); + g_free((gpointer)metadata.album); + g_free((gpointer)metadata.genre); + + g_array_append_vals(*out_param1, &meta_data, + sizeof(media_metadata_t)); + break; + } case BT_RFCOMM_CLIENT_CONNECT: { +#ifdef RFCOMM_DIRECT + result = BLUETOOTH_ERROR_NONE; +#else bluetooth_device_address_t address = { {0} }; char *input_string; int connect_type; @@ -529,6 +938,7 @@ static int __bt_bluez_request(int function_name, g_array_append_vals(*out_param1, &address, sizeof(bluetooth_device_address_t)); } +#endif break; } case BT_RFCOMM_CLIENT_CANCEL_CONNECT: @@ -542,14 +952,21 @@ static int __bt_bluez_request(int function_name, break; } case BT_RFCOMM_SOCKET_DISCONNECT: { +#ifdef RFCOMM_DIRECT + result = BLUETOOTH_ERROR_NONE; +#else int socket_fd; socket_fd = g_array_index(in_param1, int, 0); result = _bt_rfcomm_disconnect(socket_fd); +#endif break; } case BT_RFCOMM_SOCKET_WRITE: { +#ifdef RFCOMM_DIRECT + result = BLUETOOTH_ERROR_NONE; +#else int socket_fd; int length; char *buffer; @@ -559,13 +976,16 @@ static int __bt_bluez_request(int function_name, buffer = &g_array_index(in_param3, char, 0); result = _bt_rfcomm_write(socket_fd, buffer, length); +#endif break; } case BT_RFCOMM_CREATE_SOCKET: { +#ifdef RFCOMM_DIRECT + result = BLUETOOTH_ERROR_NONE; +#else char *sender; char *uuid; int socket_fd = -1; - int result; sender = dbus_g_method_get_sender(context); uuid = &g_array_index(in_param1, char, 0); @@ -580,14 +1000,19 @@ static int __bt_bluez_request(int function_name, g_array_append_vals(*out_param1, &socket_fd, sizeof(int)); g_free(sender); +#endif break; } case BT_RFCOMM_REMOVE_SOCKET: { +#ifdef RFCOMM_DIRECT + result = BLUETOOTH_ERROR_NONE; +#else int socket_fd; socket_fd = g_array_index(in_param1, int, 0); result = _bt_rfcomm_remove_socket(socket_fd); +#endif break; } case BT_RFCOMM_LISTEN: { @@ -617,18 +1042,62 @@ static int __bt_bluez_request(int function_name, int socket_fd; socket_fd = g_array_index(in_param1, int, 0); - - result = _bt_rfcomm_accept_connection(socket_fd, request_id); + BT_DBG(" socket fd %d", socket_fd); + result = _bt_rfcomm_accept_connection(); break; } case BT_RFCOMM_REJECT_CONNECTION: { int socket_fd; socket_fd = g_array_index(in_param1, int, 0); + BT_DBG(" socket fd %d", socket_fd); + result = _bt_rfcomm_reject_connection(); + break; + } + case BT_CONNECT_LE: { + bluetooth_device_address_t address = { {0} }; + gboolean auto_connect; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + auto_connect = g_array_index(in_param2, + gboolean, 0); + + result = _bt_connect_le_device(&address, auto_connect); - result = _bt_rfcomm_reject_connection(socket_fd); break; } + case BT_DISCONNECT_LE: { + bluetooth_device_address_t address = { {0} }; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + result = _bt_disconnect_le_device(&address); + + break; + } + case BT_SET_LE_PRIVACY: { + gboolean set_privacy; + + set_privacy = g_array_index(in_param1, gboolean, 0); + + result = _bt_set_le_privacy(set_privacy); + + break; + } + case BT_HDP_CONNECT: + case BT_HDP_DISCONNECT: + case BT_HDP_SEND_DATA: + + case BT_GATT_GET_PRIMARY_SERVICES: + case BT_GATT_DISCOVER_CHARACTERISTICS: + case BT_GATT_SET_PROPERTY_REQUEST: + case BT_GATT_READ_CHARACTERISTIC: + case BT_GATT_DISCOVER_CHARACTERISTICS_DESCRIPTOR: + /* Just call to check the privilege */ + break; default: result = BLUETOOTH_ERROR_INTERNAL; break; @@ -647,10 +1116,15 @@ static int __bt_obexd_request(int function_name, GArray *in_param4, GArray **out_param1) { + BT_DBG("+"); + int result; + BT_DBG("function_name : %x", function_name); + switch (function_name) { case BT_OPP_PUSH_FILES: { + BT_DBG("BT_OPP_PUSH_FILES"); int i; bluetooth_device_address_t address = { {0} }; bt_file_path_t path; @@ -670,7 +1144,7 @@ static int __bt_obexd_request(int function_name, file_path[i] = g_strdup(path.path); } - + BT_DBG("_bt_opp_client_push_files"); result = _bt_opp_client_push_files(request_id, context, &address, file_path, file_count); @@ -801,6 +1275,232 @@ static int __bt_obexd_request(int function_name, sizeof(gboolean)); break; } + case BT_PBAP_CONNECT: { + bluetooth_device_address_t address = { {0} }; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + result = _bt_pbap_connect(&address); + break; + } + case BT_PBAP_DISCONNECT: { + bluetooth_device_address_t address = { {0} }; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + result = _bt_pbap_disconnect(&address); + break; + } + case BT_PBAP_GET_PHONEBOOK_SIZE: { + bluetooth_device_address_t address = { {0} }; + bt_pbap_folder_t folder = { 0, }; + + address = g_array_index(in_param1, bluetooth_device_address_t, 0); + folder = g_array_index(in_param2, bt_pbap_folder_t, 0); + + result = _bt_pbap_get_phonebook_size(&address, folder.addressbook, + folder.folder_type); + break; + } + case BT_PBAP_GET_PHONEBOOK: { + bluetooth_device_address_t address = { {0} }; + bt_pbap_folder_t folder = { 0, }; + bt_pbap_pull_parameters_t app_param = { 0, }; + + address = g_array_index(in_param1, bluetooth_device_address_t, 0); + folder = g_array_index(in_param2, bt_pbap_folder_t, 0); + app_param = g_array_index(in_param3, bt_pbap_pull_parameters_t, 0); + + result = _bt_pbap_get_phonebook(&address, folder.addressbook, + folder.folder_type, &app_param); + break; + } + case BT_PBAP_GET_LIST: { + bluetooth_device_address_t address = { {0} }; + bt_pbap_folder_t folder = { 0, }; + bt_pbap_list_parameters_t app_param = { 0, }; + + address = g_array_index(in_param1, bluetooth_device_address_t, 0); + folder = g_array_index(in_param2, bt_pbap_folder_t, 0); + app_param = g_array_index(in_param3, bt_pbap_list_parameters_t, 0); + + result = _bt_pbap_get_list(&address, folder.addressbook, + folder.folder_type, &app_param); + break; + } + case BT_PBAP_PULL_VCARD: { + bluetooth_device_address_t address = { {0} }; + bt_pbap_folder_t folder = { 0, }; + bt_pbap_pull_vcard_parameters_t app_param = { 0, }; + + address = g_array_index(in_param1, bluetooth_device_address_t, 0); + folder = g_array_index(in_param2, bt_pbap_folder_t, 0); + app_param = g_array_index(in_param3, bt_pbap_pull_vcard_parameters_t, 0); + + result = _bt_pbap_pull_vcard(&address, folder.addressbook, + folder.folder_type, &app_param); + break; + } + case BT_PBAP_PHONEBOOK_SEARCH: { + bluetooth_device_address_t address = { {0} }; + bt_pbap_folder_t folder = { 0, }; + bt_pbap_search_parameters_t app_param = { 0, }; + + address = g_array_index(in_param1, bluetooth_device_address_t, 0); + folder = g_array_index(in_param2, bt_pbap_folder_t, 0); + app_param = g_array_index(in_param3, bt_pbap_search_parameters_t, 0); + + result = _bt_pbap_phonebook_search(&address, folder.addressbook, + folder.folder_type, &app_param); + break; + } + + default: + BT_ERR("Unknown function!"); + result = BLUETOOTH_ERROR_INTERNAL; + break; + } + + BT_DBG("-"); + + return result; +} + +static int __bt_agent_request(int function_name, + int request_type, + int request_id, + DBusGMethodInvocation *context, + GArray *in_param1, + GArray *in_param2, + GArray *in_param3, + GArray *in_param4, + GArray **out_param1) +{ + int result; + switch(function_name) { + case BT_SET_AUTHORIZATION: { + int type; + char *uuid; + char *path; + int fd; + + type = g_array_index(in_param1, int, 0); + uuid = &g_array_index(in_param2, char, 0); + path = &g_array_index(in_param3, char, 0); + fd = g_array_index(in_param4, int, 0); + result = _bt_register_osp_server_in_agent(type, uuid, path, fd); + break; + } + case BT_UNSET_AUTHORIZATION: { + int type; + char *uuid; + type = g_array_index(in_param1, int, 0); + uuid = &g_array_index(in_param2, char, 0); + result = _bt_unregister_osp_server_in_agent(type, uuid); + break; + } + default: + BT_ERR("Unknown function!"); + result = BLUETOOTH_ERROR_INTERNAL; + break; + } + + return result; +} + +static int __bt_core_request(int function_name, + int request_type, + int request_id, + DBusGMethodInvocation *context, + GArray *in_param1) +{ + int result; + + switch (function_name) { + case BT_ENABLE_ADAPTER: + { + bt_status_t status; + + status = _bt_adapter_get_status(); + + if (status == BT_ACTIVATING) { + BT_DBG("Enabling in progress"); + result = BLUETOOTH_ERROR_IN_PROGRESS; + } else if (status == BT_ACTIVATED) { + BT_DBG("Already enabled"); + result = BLUETOOTH_ERROR_DEVICE_ALREADY_ENABLED; + } else { + _bt_adapter_set_status(BT_ACTIVATING); + _bt_adapter_start_enable_timer(); + result = BLUETOOTH_ERROR_NONE; + } + + break; + } + case BT_DISABLE_ADAPTER: + { + bt_status_t status; + + status = _bt_adapter_get_status(); + if (status == BT_DEACTIVATING) { + BT_DBG("Disabling in progress"); + result = BLUETOOTH_ERROR_IN_PROGRESS; + } + else if (status == BT_DEACTIVATED) { + BT_DBG("Already disabled"); + result = BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; + } + else + { + _bt_adapter_set_status(BT_DEACTIVATING); + result = BLUETOOTH_ERROR_NONE; + } + + break; + } + case BT_ENABLE_ADAPTER_LE: + { + bt_le_status_t le_status; + + le_status = _bt_adapter_get_le_status(); + if (le_status == BT_LE_ACTIVATING) { + BT_DBG("Enabling in progress"); + result = BLUETOOTH_ERROR_IN_PROGRESS; + } + else if (le_status == BT_LE_ACTIVATED) { + BT_DBG("Already enabled"); + result = BLUETOOTH_ERROR_DEVICE_ALREADY_ENABLED; + } else { + _bt_adapter_set_le_status(BT_LE_ACTIVATING); + _bt_adapter_start_le_enable_timer(); + result = BLUETOOTH_ERROR_NONE; + } + + break; + } + case BT_DISABLE_ADAPTER_LE: + { + bt_le_status_t le_status; + + le_status = _bt_adapter_get_le_status(); + if (le_status == BT_LE_DEACTIVATING) { + BT_DBG("Disabling in progress"); + result = BLUETOOTH_ERROR_IN_PROGRESS; + } + else if (le_status == BT_LE_DEACTIVATED) { + BT_DBG("Already disabled"); + result = BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; + } + else + { + _bt_adapter_set_le_status(BT_LE_DEACTIVATING); + result = BLUETOOTH_ERROR_NONE; + } + + break; + } default: BT_ERR("Unknown function!"); result = BLUETOOTH_ERROR_INTERNAL; @@ -810,6 +1510,182 @@ static int __bt_obexd_request(int function_name, return result; } +gboolean __bt_service_check_privilege(int function_name, + int service_type, + GArray *in_param5) +{ + const char *cookie; + int ret_val; + gboolean result = TRUE; + + cookie = (const char *)&g_array_index(in_param5, char, 0); + + retv_if(cookie == NULL, FALSE); + + switch (function_name) { + case BT_SET_LOCAL_NAME: + case BT_START_DISCOVERY: + case BT_START_CUSTOM_DISCOVERY: + case BT_CANCEL_DISCOVERY: + case BT_OOB_ADD_REMOTE_DATA: + case BT_OOB_REMOVE_REMOTE_DATA: + case BT_SET_ADVERTISING: + case BT_SET_CUSTOM_ADVERTISING: + case BT_START_LE_DISCOVERY: + case BT_STOP_LE_DISCOVERY: + + case BT_BOND_DEVICE: + case BT_CANCEL_BONDING: + case BT_UNBOND_DEVICE: + case BT_SET_ALIAS: + case BT_SET_AUTHORIZATION: + case BT_UNSET_AUTHORIZATION: + case BT_SEARCH_SERVICE: + + case BT_RFCOMM_CLIENT_CONNECT: + case BT_RFCOMM_CLIENT_CANCEL_CONNECT: + case BT_RFCOMM_SOCKET_DISCONNECT: + case BT_RFCOMM_SOCKET_WRITE: + case BT_RFCOMM_CREATE_SOCKET: + case BT_RFCOMM_REMOVE_SOCKET: + + case BT_OPP_PUSH_FILES: + case BT_OPP_CANCEL_PUSH: + + case BT_OBEX_SERVER_ACCEPT_CONNECTION: + case BT_OBEX_SERVER_REJECT_CONNECTION: + case BT_OBEX_SERVER_ACCEPT_FILE: + case BT_OBEX_SERVER_REJECT_FILE: + case BT_OBEX_SERVER_SET_PATH: + case BT_OBEX_SERVER_SET_ROOT: + case BT_OBEX_SERVER_CANCEL_TRANSFER: + case BT_OBEX_SERVER_CANCEL_ALL_TRANSFERS: + + case BT_AUDIO_CONNECT: + case BT_AUDIO_DISCONNECT: + case BT_AG_CONNECT: + case BT_AG_DISCONNECT: + case BT_AV_CONNECT: + case BT_AV_DISCONNECT: + case BT_AVRCP_CONTROL_CONNECT: + case BT_AVRCP_CONTROL_DISCONNECT: + case BT_HF_CONNECT: + case BT_HF_DISCONNECT: + + case BT_HID_CONNECT: + case BT_HID_DISCONNECT: + + case BT_CONNECT_LE: + case BT_DISCONNECT_LE: + + case BT_SET_ADVERTISING_DATA: + case BT_SET_SCAN_RESPONSE_DATA: + + case BT_HDP_CONNECT: + case BT_HDP_DISCONNECT: + case BT_HDP_SEND_DATA: + + case BT_NETWORK_ACTIVATE: + case BT_NETWORK_DEACTIVATE: + case BT_NETWORK_CONNECT: + case BT_NETWORK_DISCONNECT: + case BT_NETWORK_SERVER_DISCONNECT: + + case BT_GATT_GET_PRIMARY_SERVICES: + case BT_GATT_DISCOVER_CHARACTERISTICS: + case BT_GATT_SET_PROPERTY_REQUEST: + case BT_GATT_READ_CHARACTERISTIC: + case BT_GATT_DISCOVER_CHARACTERISTICS_DESCRIPTOR: + + ret_val = security_server_check_privilege_by_cookie(cookie, + BT_PRIVILEGE_PUBLIC, "w"); + if (ret_val == SECURITY_SERVER_API_ERROR_ACCESS_DENIED) { + BT_ERR("[SMACK] Fail to access: %s", BT_PRIVILEGE_PUBLIC); + result = FALSE; + } + break; + + case BT_ENABLE_ADAPTER: + case BT_DISABLE_ADAPTER: + case BT_RESET_ADAPTER: + case BT_RECOVER_ADAPTER: + case BT_ENABLE_ADAPTER_LE: + case BT_DISABLE_ADAPTER_LE: + case BT_SET_CONNECTABLE: + case BT_SET_DISCOVERABLE_MODE: + case BT_ADD_WHITE_LIST: + case BT_REMOVE_WHITE_LIST: + case BT_CLEAR_WHITE_LIST: + case BT_SET_MANUFACTURER_DATA: + case BT_SET_SCAN_PARAMETERS: + + case BT_CANCEL_SEARCH_SERVICE: + case BT_ENABLE_RSSI: + + case BT_RFCOMM_ACCEPT_CONNECTION: + case BT_RFCOMM_REJECT_CONNECTION: + case BT_RFCOMM_LISTEN: + + case BT_AVRCP_SET_TRACK_INFO: + case BT_AVRCP_SET_PROPERTY: + case BT_AVRCP_SET_PROPERTIES: + case BT_AVRCP_HANDLE_CONTROL: + case BT_AVRCP_CONTROL_SET_PROPERTY: + case BT_AVRCP_CONTROL_GET_PROPERTY: + case BT_AVRCP_GET_TRACK_INFO: + + case BT_SET_CONTENT_PROTECT: + case BT_BOND_DEVICE_BY_TYPE: + case BT_SET_LE_PRIVACY: + case BT_LE_CONN_UPDATE: + + ret_val = security_server_check_privilege_by_cookie(cookie, + BT_PRIVILEGE_PLATFORM, "w"); + + if (ret_val == SECURITY_SERVER_API_ERROR_ACCESS_DENIED) { + BT_ERR("[SMACK] Fail to access: %s", BT_PRIVILEGE_PLATFORM); + result = FALSE; + } + break; + + case BT_CHECK_ADAPTER: + case BT_GET_RSSI: + + case BT_GET_LOCAL_NAME: + case BT_GET_LOCAL_ADDRESS: + case BT_GET_LOCAL_VERSION: + case BT_IS_SERVICE_USED: + case BT_GET_DISCOVERABLE_MODE: + case BT_GET_DISCOVERABLE_TIME: + case BT_IS_DISCOVERYING: + case BT_IS_LE_DISCOVERYING: + case BT_IS_CONNECTABLE: + case BT_GET_BONDED_DEVICES: + case BT_GET_BONDED_DEVICE: + case BT_IS_DEVICE_CONNECTED: + case BT_GET_SPEAKER_GAIN: + case BT_SET_SPEAKER_GAIN: + case BT_OOB_READ_LOCAL_DATA: + case BT_RFCOMM_CLIENT_IS_CONNECTED: + case BT_RFCOMM_IS_UUID_AVAILABLE: + case BT_GET_ADVERTISING_DATA: + case BT_GET_SCAN_RESPONSE_DATA: + case BT_IS_ADVERTISING: + + case BT_OBEX_SERVER_ALLOCATE: + case BT_OBEX_SERVER_DEALLOCATE: + + /* Non-privilege control */ + break; + default: + BT_ERR("Unknown function!"); + result = FALSE; + break; + } + + return result; +} + gboolean bt_service_request( BtService *service, int service_type, @@ -822,6 +1698,8 @@ gboolean bt_service_request( GArray *in_param5, DBusGMethodInvocation *context) { + BT_DBG("+"); + int result; int request_id = -1; GArray *out_param1 = NULL; @@ -830,11 +1708,21 @@ gboolean bt_service_request( out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar)); out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar)); + if (service_type == BT_CORE_SERVICE) { + BT_DBG("No need to check privilege from bt-core"); + } + else if (__bt_service_check_privilege(service_function, + service_type, in_param5) == FALSE) { + result = BLUETOOTH_ERROR_PERMISSION_DEINED; + goto fail; + } + if (request_type == BT_ASYNC_REQ - || service_function == BT_OBEX_SERVER_ACCEPT_CONNECTION - || service_function == BT_RFCOMM_ACCEPT_CONNECTION) { + || service_function == BT_OBEX_SERVER_ACCEPT_CONNECTION) { /* Set the timer */ request_id = _bt_assign_request_id(); + BT_DBG("Request ID: %d", request_id); + if (request_id < 0) { BT_ERR("Fail to assign the request id"); result = BLUETOOTH_ERROR_INTERNAL; @@ -842,6 +1730,8 @@ gboolean bt_service_request( } } + BT_DBG("SERVICE TYPE %d", service_type); + switch (service_type) { case BT_BLUEZ_SERVICE: result = __bt_bluez_request(service_function, request_type, @@ -854,6 +1744,19 @@ gboolean bt_service_request( in_param2, in_param3, in_param4, &out_param1); break; + case BT_AGENT_SERVICE: + result = __bt_agent_request(service_function, request_type, + request_id, context, in_param1, + in_param2, in_param3, + in_param4, &out_param1); + break; + case BT_CORE_SERVICE: + result = __bt_core_request(service_function, request_type, + request_id, context, in_param1); + break; + case BT_CHECK_PRIVILEGE: + result = BLUETOOTH_ERROR_NONE; + break; default: BT_ERR("Unknown service type"); result = BLUETOOTH_ERROR_INTERNAL; @@ -861,20 +1764,21 @@ gboolean bt_service_request( } if (result != BLUETOOTH_ERROR_NONE) { - BT_ERR("result is not error none: %x", result); goto fail; } g_array_append_vals(out_param2, &result, sizeof(int)); - if (request_type == BT_ASYNC_REQ - || service_function == BT_OBEX_SERVER_ACCEPT_CONNECTION - || service_function == BT_RFCOMM_ACCEPT_CONNECTION) { + if ((request_type == BT_ASYNC_REQ || + service_function == BT_OBEX_SERVER_ACCEPT_CONNECTION) && + service_function != BT_OPP_PUSH_FILES) { _bt_insert_request_list(request_id, service_function, NULL, context); } else { /* Return result */ - dbus_g_method_return(context, out_param1, out_param2); + if (service_type == BT_CHECK_PRIVILEGE || + service_function != BT_OPP_PUSH_FILES) + dbus_g_method_return(context, out_param1, out_param2); } g_array_free(out_param1, TRUE); @@ -882,6 +1786,7 @@ gboolean bt_service_request( return TRUE; fail: + BT_ERR_C("Request is failed [%s] [%x]", _bt_convert_error_to_string(result), result); g_array_append_vals(out_param2, &result, sizeof(int)); dbus_g_method_return(context, out_param1, out_param2); @@ -891,6 +1796,8 @@ fail: if (request_type == BT_ASYNC_REQ) _bt_delete_request_id(request_id); + BT_DBG("-"); + return FALSE; } @@ -899,7 +1806,7 @@ int _bt_service_register(void) BtService *bt_service; DBusGConnection *conn; DBusGProxy *proxy; - GError* err = NULL; + GError *err = NULL; guint result = 0; conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL); diff --git a/bt-service/bt-request-service.xml b/bt-service/bt-request-service.xml old mode 100644 new mode 100755 diff --git a/bt-service/bt-service-adapter-le.c b/bt-service/bt-service-adapter-le.c new file mode 100755 index 0000000..b34fc99 --- /dev/null +++ b/bt-service/bt-service-adapter-le.c @@ -0,0 +1,766 @@ +/* + * Bluetooth-frwk + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include + +#include "bt-internal-types.h" +#include "bt-service-common.h" +#include "bt-service-event.h" +#include "bt-service-adapter.h" +#include "bt-service-adapter-le.h" + + +#define BT_ADV_INTERVAL_MIN 20 /* msec */ +#define BT_ADV_INTERVAL_MAX 10240 +#define BT_ADV_INTERVAL_SPLIT 0.625 +#define BT_DEFAULT_ADV_MIN_INTERVAL 500 +#define BT_DEFAULT_ADV_MAX_INTERVAL 500 +#define BT_ADV_FILTER_POLICY_DEFAULT 0x00 +#define BT_ADV_TYPE_DEFAULT 0x00 +#define BT_ADV_FILTER_POLICY_ALLOW_SCAN_CONN_WL_ONLY 0x03 + +typedef struct { + int adv_inst_max; + int rpa_offloading; + int max_filter; +} bt_adapter_le_feature_info_t; + +typedef struct { + char *sender; + gboolean is_advertising; +} bt_adapter_le_adv_slot_t; + +static bluetooth_advertising_params_t adv_params = { + BT_DEFAULT_ADV_MIN_INTERVAL, + BT_DEFAULT_ADV_MAX_INTERVAL, + BT_ADV_FILTER_POLICY_DEFAULT, + BT_ADV_TYPE_DEFAULT}; +static bluetooth_advertising_data_t adv_data = { {0} }; +static int adv_data_len; +static bluetooth_scan_resp_data_t resp_data = { {0} }; +static int resp_data_len; + +static bt_adapter_le_feature_info_t le_feature_info = { 1, 0, 0 }; +static bt_adapter_le_adv_slot_t *le_adv_slot = NULL; + +void __bt_free_le_adv_slot(void) +{ + int i; + + if (le_adv_slot == NULL) + return; + + for (i = 0; i < le_feature_info.adv_inst_max; i++) { + if (le_adv_slot[i].sender) + g_free(le_adv_slot[i].sender); + } + g_free(le_adv_slot); + le_adv_slot = NULL; +} + +int _bt_service_adapter_le_init(void) +{ + le_adv_slot = g_malloc0(sizeof(bt_adapter_le_adv_slot_t) * le_feature_info.adv_inst_max); + + return BLUETOOTH_ERROR_NONE; +} + +void _bt_service_adapter_le_deinit(void) +{ + __bt_free_le_adv_slot(); +} + +gboolean _bt_update_le_feature_support(const char *item, const char *value) +{ + if (item== NULL || value == NULL) + return FALSE; + + if (g_strcmp0(item, "adv_inst_max") == 0) { + if (atoi(value) != le_feature_info.adv_inst_max) { + __bt_free_le_adv_slot(); + le_feature_info.adv_inst_max = atoi(value); + le_adv_slot = g_malloc0(sizeof(bt_adapter_le_adv_slot_t) * le_feature_info.adv_inst_max); + } + } else if (g_strcmp0(item, "rpa_offloading") == 0) { + le_feature_info.rpa_offloading = atoi(value); + } else if (g_strcmp0(item, "max_filter") == 0) { + le_feature_info.max_filter = atoi(value); + } else { + BT_DBG("No registered item"); + return FALSE; + } + + return TRUE; +} + +static gboolean __bt_is_factory_test_mode(void) +{ + int mode = 0; +#ifdef ENABLE_TIZEN_2_4 + if (vconf_get_bool(VCONFKEY_BT_DUT_MODE, &mode)) { + BT_ERR("Get the DUT Mode fail"); + return TRUE; + } +#endif + if (mode != FALSE) { + BT_INFO("DUT Test Mode !!"); + return TRUE; + } + + return FALSE; +} + +int __bt_get_available_adv_slot_id(const char *sender, gboolean use_reserved_slot) +{ + int i; + + if (le_adv_slot == NULL) + return -1; + + if (use_reserved_slot == TRUE) { + if (le_feature_info.adv_inst_max > 1) + return 0; + else if (le_adv_slot[0].sender == NULL || + g_strcmp0(le_adv_slot[0].sender, sender) == 0) + return 0; + else + return -1; + } + + for (i = 0; i < le_feature_info.adv_inst_max; i++) { + if (le_adv_slot[i].sender == NULL) + continue; + if (g_strcmp0(le_adv_slot[i].sender, sender) == 0) + return i; + } + + for (i = 0; i < le_feature_info.adv_inst_max; i++) { + if (le_adv_slot[i].sender == NULL) + return i; + } + + return -1; +} + +void __bt_register_adv_slot_owner(const char *sender, int slot_id) +{ + if (le_adv_slot[slot_id].sender == NULL) + le_adv_slot[slot_id].sender = strdup(sender); +} + +void __bt_unregister_adv_slot_owner(int slot_id) +{ + g_free(le_adv_slot[slot_id].sender); + le_adv_slot[slot_id].sender = NULL; + le_adv_slot[slot_id].is_advertising = FALSE; +} + +const char* _bt_get_adv_slot_owner(int slot_id) +{ + if (le_adv_slot == NULL) + return NULL; + + return le_adv_slot[slot_id].sender; +} + +void _bt_set_advertising_status(int slot_id, gboolean mode) +{ + le_adv_slot[slot_id].is_advertising = mode; +} + +gboolean _bt_is_advertising(void) +{ + gboolean status = FALSE; + int i; + + for (i = 0; i < le_feature_info.adv_inst_max; i++) { + if (le_adv_slot[i].is_advertising == TRUE) + status = TRUE; + } + + return status; +} + +void _bt_stop_advertising_by_terminated_process(const char* terminated_name) +{ + int i; + + if (le_adv_slot == NULL) + return; + + for (i = 0; i < le_feature_info.adv_inst_max; i++) { + if (le_adv_slot[i].sender != NULL) { + if (strcasecmp(terminated_name, le_adv_slot[i].sender) == 0) { + BT_ERR("Stop advertising by terminated process(%s).", terminated_name); + _bt_set_advertising(FALSE, terminated_name, FALSE); + } + } + } +} + +gboolean _bt_get_advertising_params(bluetooth_advertising_params_t *params) +{ + if (params == NULL) + return FALSE; + + memcpy(params, &adv_params, sizeof(bluetooth_advertising_params_t)); + + return TRUE; +} + +int _bt_set_advertising(gboolean enable, const char *sender, gboolean use_reserved_slot) +{ + DBusGProxy *proxy; + GError *error = NULL; + int slot_id; + + if (__bt_is_factory_test_mode()) { + BT_ERR("Unable to start advertising in factory binary !!"); + return BLUETOOTH_ERROR_NOT_SUPPORT; + } + + if (_bt_adapter_get_status() != BT_ACTIVATED && + _bt_adapter_get_le_status() != BT_LE_ACTIVATED) { + return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; + } + + slot_id = __bt_get_available_adv_slot_id(sender, use_reserved_slot); + if (slot_id == -1) { + BT_ERR("There is NO available slot!!"); + return BLUETOOTH_ERROR_NO_RESOURCES; + } + + if (le_adv_slot[slot_id].is_advertising == TRUE && enable == TRUE) + return BLUETOOTH_ERROR_IN_PROGRESS; + + if (le_adv_slot[slot_id].is_advertising == FALSE && enable == FALSE) + return BLUETOOTH_ERROR_NOT_IN_OPERATION; + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call(proxy, "SetAdvertising", &error, + G_TYPE_BOOLEAN, enable, + G_TYPE_INT, slot_id, + G_TYPE_INVALID, G_TYPE_INVALID); + + if (error) { + BT_ERR("SetAdvertising Fail: %s", error->message); + g_error_free(error); + return BLUETOOTH_ERROR_INTERNAL; + } + + le_adv_slot[slot_id].is_advertising = enable; + + if (enable == TRUE) + __bt_register_adv_slot_owner(sender, slot_id); + else + __bt_unregister_adv_slot_owner(slot_id); + + BT_INFO("Set advertising [%d]", enable); + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_set_custom_advertising(gboolean enable, bluetooth_advertising_params_t *params, + const char *sender, gboolean use_reserved_slot) +{ + DBusGProxy *proxy; + GError *error = NULL; + guint32 min = 0; + guint32 max = 0; + int slot_id; + + BT_CHECK_PARAMETER(params, return); + + if (__bt_is_factory_test_mode()) { + BT_ERR("Unable to start advertising in factory binary !!"); + return BLUETOOTH_ERROR_NOT_SUPPORT; + } + + if (_bt_adapter_get_status() != BT_ACTIVATED && + _bt_adapter_get_le_status() != BT_LE_ACTIVATED) { + return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; + } + + if (le_adv_slot[slot_id].is_advertising == TRUE && enable == TRUE) + return BLUETOOTH_ERROR_IN_PROGRESS; + + if (le_adv_slot[slot_id].is_advertising == FALSE && enable == FALSE) + return BLUETOOTH_ERROR_NOT_IN_OPERATION; + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + if (params->interval_min > params->interval_max || + params->interval_min < BT_ADV_INTERVAL_MIN || + params->interval_max > BT_ADV_INTERVAL_MAX) + return BLUETOOTH_ERROR_INVALID_PARAM; + + if (params->filter_policy > BLUETOOTH_ALLOW_SCAN_CONN_WHITE_LIST) + return BLUETOOTH_ERROR_INVALID_PARAM; + + if (params->type == BLUETOOTH_ADV_CONNECTABLE_DIRECT_HIGH || + params->type == BLUETOOTH_ADV_CONNECTABLE_DIRECT_LOW || + params->type == BLUETOOTH_ADV_NON_CONNECTABLE) + return BLUETOOTH_ERROR_NOT_SUPPORT; + + min = params->interval_min / BT_ADV_INTERVAL_SPLIT; + max = params->interval_max / BT_ADV_INTERVAL_SPLIT; + + slot_id = __bt_get_available_adv_slot_id(sender, use_reserved_slot); + if (slot_id == -1) { + BT_ERR("There is NO available slot!!"); + return BLUETOOTH_ERROR_NO_RESOURCES; + } + + dbus_g_proxy_call(proxy, "SetAdvertisingParameters", &error, + G_TYPE_UINT, min, + G_TYPE_UINT, max, + G_TYPE_UINT, params->filter_policy, + G_TYPE_UINT, params->type, + G_TYPE_INT, slot_id, + G_TYPE_INVALID, G_TYPE_INVALID); + + if (error) { + BT_ERR("SetAdvertisingParameters Fail: %s", error->message); + g_error_free(error); + return BLUETOOTH_ERROR_INTERNAL; + } + + adv_params.interval_min = params->interval_min; + adv_params.interval_max = params->interval_max; + adv_params.filter_policy = params->filter_policy; + adv_params.type= params->type; + + dbus_g_proxy_call(proxy, "SetAdvertising", &error, + G_TYPE_BOOLEAN, enable, + G_TYPE_INT, slot_id, + G_TYPE_INVALID, G_TYPE_INVALID); + + if (error) { + BT_ERR("SetAdvertising Fail: %s", error->message); + g_error_free(error); + return BLUETOOTH_ERROR_INTERNAL; + } + + le_adv_slot[slot_id].is_advertising = enable; + + if (enable == TRUE) + __bt_register_adv_slot_owner(sender, slot_id); + else + __bt_unregister_adv_slot_owner(slot_id); + + BT_INFO_C("Set advertising [%d]", enable); + return BLUETOOTH_ERROR_NONE; +} + +static int __bt_get_ad_data_by_type(char *in_data, int in_len, + char in_type, char **data, int *data_len) +{ + if (in_data == NULL || data == NULL || data_len == NULL) + return BLUETOOTH_ERROR_INTERNAL; + + if (in_len < 0) + return BLUETOOTH_ERROR_INTERNAL; + + int i; + int len = 0; + int type = 0; + + for (i = 0; i < in_len; i++) { + len = in_data[i]; + if (len <= 0 || i + 1 >= in_len) { + BT_ERR("Invalid advertising data"); + return BLUETOOTH_ERROR_INTERNAL; + } + + type = in_data[i + 1]; + if (type == in_type) { + i = i + 2; + len--; + break; + } + + i += len; + len = 0; + } + + if (i + len > in_len) { + BT_ERR("Invalid advertising data"); + return BLUETOOTH_ERROR_INTERNAL; + } else if (len == 0) { + BT_DBG("AD Type 0x%02x data is not set", in_type); + *data = NULL; + *data_len = 0; + return BLUETOOTH_ERROR_NONE; + } + + *data = g_memdup(&in_data[i], len); + if (*data == NULL) + return BLUETOOTH_ERROR_OUT_OF_MEMORY; + *data_len = len; + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_get_advertising_data(bluetooth_advertising_data_t *adv, int *length) +{ + BT_CHECK_PARAMETER(adv, return); + BT_CHECK_PARAMETER(length, return); + + memcpy(adv, &adv_data, sizeof(adv_data)); + *length = adv_data_len; + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_set_advertising_data(bluetooth_advertising_data_t *adv, int length, + const char *sender, gboolean use_reserved_slot) +{ + DBusGProxy *proxy; + GError *error = NULL; + GArray *arr; + int i; + char *old_mdata = NULL; + char *new_mdata = NULL; + int old_len = 0; + int new_len = 0; + int slot_id; + + if (__bt_is_factory_test_mode()) { + BT_ERR("Unable to set advertising data in factory binary !!"); + return BLUETOOTH_ERROR_NOT_SUPPORT; + } + + BT_CHECK_PARAMETER(adv, return); + + if (_bt_adapter_get_status() != BT_ACTIVATED && + _bt_adapter_get_le_status() != BT_LE_ACTIVATED) { + return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; + } + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + arr = g_array_new(TRUE, TRUE, sizeof(guint8)); + + for (i = 0; i < length; i++) + g_array_append_vals(arr, &(adv->data[i]), sizeof(guint8)); + + slot_id = __bt_get_available_adv_slot_id(sender, use_reserved_slot); + if (slot_id == -1) { + BT_ERR("There is NO available slot!!"); + return BLUETOOTH_ERROR_NO_RESOURCES; + } + + dbus_g_proxy_call(proxy, "SetAdvertisingData", &error, + DBUS_TYPE_G_UCHAR_ARRAY, arr, + G_TYPE_INT, slot_id, + G_TYPE_INVALID, G_TYPE_INVALID); + + g_array_free(arr, TRUE); + + if (error) { + BT_ERR("SetAdvertisingData Fail: %s", error->message); + g_error_free(error); + return BLUETOOTH_ERROR_INTERNAL; + } + + __bt_register_adv_slot_owner(sender, slot_id); + + __bt_get_ad_data_by_type((char *)adv_data.data, adv_data_len, 0xff, + &old_mdata, &old_len); + __bt_get_ad_data_by_type((char *)adv->data, length, 0xff, + &new_mdata, &new_len); + if (old_len != new_len || + (old_mdata && new_mdata && + memcmp(old_mdata, new_mdata, new_len))) { + _bt_send_event(BT_ADAPTER_EVENT, + BLUETOOTH_EVENT_ADVERTISING_MANUFACTURER_DATA_CHANGED, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &new_mdata, new_len, + DBUS_TYPE_INVALID); + } + g_free(new_mdata); + g_free(old_mdata); + + memset(&adv_data, 0x00, sizeof(bluetooth_advertising_data_t)); + memcpy(&adv_data, adv, length); + adv_data_len = length; + + BT_INFO("Set advertising data"); + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_get_scan_response_data(bluetooth_scan_resp_data_t *response, int *length) +{ + BT_CHECK_PARAMETER(response, return); + BT_CHECK_PARAMETER(length, return); + + memcpy(response, &resp_data, sizeof(resp_data)); + *length = resp_data_len; + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_set_scan_response_data(bluetooth_scan_resp_data_t *response, int length, + const char *sender, gboolean use_reserved_slot) +{ + DBusGProxy *proxy; + GError *error = NULL; + GArray *arr; + int i; + char *old_mdata = NULL; + char *new_mdata = NULL; + int old_len = 0; + int new_len = 0; + int slot_id; + + if (__bt_is_factory_test_mode()) { + BT_ERR("Unable to set scan response list in factory binary !!"); + return BLUETOOTH_ERROR_NOT_SUPPORT; + } + + BT_CHECK_PARAMETER(response, return); + + if (_bt_adapter_get_status() != BT_ACTIVATED && + _bt_adapter_get_le_status() != BT_LE_ACTIVATED) { + return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; + } + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + arr = g_array_new(TRUE, TRUE, sizeof(guint8)); + + for (i = 0; i < length; i++) + g_array_append_vals(arr, &(response->data[i]), sizeof(guint8)); + + slot_id = __bt_get_available_adv_slot_id(sender, use_reserved_slot); + if (slot_id == -1) { + BT_ERR("There is NO available slot!!"); + return BLUETOOTH_ERROR_NO_RESOURCES; + } + + dbus_g_proxy_call(proxy, "SetScanRespData", &error, + DBUS_TYPE_G_UCHAR_ARRAY, arr, + G_TYPE_INT, slot_id, + G_TYPE_INVALID, G_TYPE_INVALID); + + g_array_free(arr, TRUE); + + if (error) { + BT_ERR("SetScanRespData Fail: %s", error->message); + g_error_free(error); + return BLUETOOTH_ERROR_INTERNAL; + } + + __bt_register_adv_slot_owner(sender, slot_id); + + /* Compare with previous scan resp data */ + __bt_get_ad_data_by_type((char *)resp_data.data, resp_data_len, 0xff, + &old_mdata, &old_len); + __bt_get_ad_data_by_type((char *)response->data, length, 0xff, + &new_mdata, &new_len); + if (old_len != new_len || + (old_mdata && new_mdata && + memcmp(old_mdata, new_mdata, new_len))) { + _bt_send_event(BT_ADAPTER_EVENT, + BLUETOOTH_EVENT_SCAN_RESPONSE_MANUFACTURER_DATA_CHANGED, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &new_mdata, new_len, + DBUS_TYPE_INVALID); + } + g_free(new_mdata); + g_free(old_mdata); + + memset(&resp_data, 0x00, sizeof(bluetooth_scan_resp_data_t)); + memcpy(&resp_data, response, length); + resp_data_len = length; + + BT_INFO("Set scan response data"); + return BLUETOOTH_ERROR_NONE; +} + +int _bt_set_scan_parameters(bluetooth_le_scan_params_t *params) +{ + DBusGProxy *proxy; + GError *error = NULL; + guint32 itv = 0; + guint32 win = 0; + + BT_CHECK_PARAMETER(params, return); + + if (_bt_adapter_get_status() != BT_ACTIVATED && + _bt_adapter_get_le_status() != BT_LE_ACTIVATED) { + return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; + } + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + if (params->interval < BT_LE_SCAN_INTERVAL_MIN || params->interval > BT_LE_SCAN_INTERVAL_MAX) + return BLUETOOTH_ERROR_INVALID_PARAM; + + if (params->window < BT_LE_SCAN_WINDOW_MIN || params->window > BT_LE_SCAN_WINDOW_MAX) + return BLUETOOTH_ERROR_INVALID_PARAM; + + if (params->window > params->interval) + return BLUETOOTH_ERROR_INVALID_PARAM; + + itv = params->interval / BT_ADV_INTERVAL_SPLIT; + win = params->window / BT_ADV_INTERVAL_SPLIT; + + dbus_g_proxy_call(proxy, "SetScanParameters", &error, + G_TYPE_UINT, params->type, + G_TYPE_UINT, itv, + G_TYPE_UINT, win, + G_TYPE_INVALID, G_TYPE_INVALID); + + if (error) { + BT_ERR("SetScanParameters Fail: %s", error->message); + g_error_free(error); + return BLUETOOTH_ERROR_INTERNAL; + } + + _bt_set_le_discovery_type(params->type); + + BT_INFO("Set scan parameters"); + return BLUETOOTH_ERROR_NONE; +} + +int _bt_add_white_list(bluetooth_device_address_t *device_address, bluetooth_device_address_type_t address_type) +{ + DBusGProxy *proxy; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + GError *error = NULL; + + if (__bt_is_factory_test_mode()) { + BT_ERR("Unable to add white list in factory binary !!"); + return BLUETOOTH_ERROR_NOT_SUPPORT; + } + + BT_CHECK_PARAMETER(device_address, return); + + if (address_type != BLUETOOTH_DEVICE_PUBLIC_ADDRESS && + address_type != BLUETOOTH_DEVICE_RANDOM_ADDRESS) + return BLUETOOTH_ERROR_INVALID_PARAM; + + _bt_convert_addr_type_to_string(address, device_address->addr); + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call(proxy, "AddDeviceWhiteList", &error, + G_TYPE_STRING, address, + G_TYPE_UINT, address_type, + G_TYPE_INVALID, G_TYPE_INVALID); + + if (error) { + BT_ERR("AddDeviceWhiteList Fail: %s", error->message); + g_error_free(error); + return BLUETOOTH_ERROR_INTERNAL; + } + + BT_INFO("Add white list"); + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_remove_white_list(bluetooth_device_address_t *device_address, bluetooth_device_address_type_t address_type) +{ + DBusGProxy *proxy; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + GError *error = NULL; + + if (__bt_is_factory_test_mode()) { + BT_ERR("Unable to remove white list in factory binary !!"); + return BLUETOOTH_ERROR_NOT_SUPPORT; + } + + BT_CHECK_PARAMETER(device_address, return); + + if (address_type != BLUETOOTH_DEVICE_PUBLIC_ADDRESS && + address_type != BLUETOOTH_DEVICE_RANDOM_ADDRESS) + return BLUETOOTH_ERROR_INVALID_PARAM; + + _bt_convert_addr_type_to_string(address, device_address->addr); + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call(proxy, "RemoveDeviceWhiteList", &error, + G_TYPE_STRING, address, + G_TYPE_UINT, address_type, + G_TYPE_INVALID, G_TYPE_INVALID); + + if (error) { + BT_ERR("RemoveDeviceWhiteList Fail: %s", error->message); + g_error_free(error); + return BLUETOOTH_ERROR_INTERNAL; + } + + BT_INFO("Remove white list"); + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_clear_white_list(void) +{ + DBusGProxy *proxy; + GError *error = NULL; + + if (__bt_is_factory_test_mode()) { + BT_ERR("Unable to clear white list in factory binary !!"); + return BLUETOOTH_ERROR_NOT_SUPPORT; + } + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call(proxy, "ClearDeviceWhiteList", &error, + G_TYPE_INVALID, G_TYPE_INVALID); + + if (error) { + BT_ERR("ClearDeviceWhiteList Fail: %s", error->message); + g_error_free(error); + return BLUETOOTH_ERROR_INTERNAL; + } + + BT_INFO("Clear white list"); + + return BLUETOOTH_ERROR_NONE; +} + diff --git a/bt-service/bt-service-adapter.c b/bt-service/bt-service-adapter.c old mode 100644 new mode 100755 index 3f510ad..cf79210 --- a/bt-service/bt-service-adapter.c +++ b/bt-service/bt-service-adapter.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -24,13 +28,11 @@ #include #include #include -#include -#if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT) #include -#endif -#ifdef __TIZEN_MOBILE__ #include -#endif +#include +//#include + #include "alarm.h" #include "bluetooth-api.h" @@ -50,20 +52,72 @@ typedef struct { guint event_id; int timeout; time_t start_time; + gboolean alarm_init; int alarm_id; } bt_adapter_timer_t; -bt_adapter_timer_t visible_timer; +bt_adapter_timer_t visible_timer = {0, }; + static gboolean is_discovering; +static gboolean is_le_discovering; +static bt_le_discovery_type_t le_discovery_type = BT_LE_PASSIVE_SCAN; static gboolean cancel_by_user; static bt_status_t adapter_status = BT_DEACTIVATED; +static bt_le_status_t adapter_le_status = BT_LE_DEACTIVATED; static void *adapter_agent = NULL; static DBusGProxy *core_proxy = NULL; +static guint timer_id = 0; +static guint le_timer_id = 0; #define BT_CORE_NAME "org.projectx.bt_core" #define BT_CORE_PATH "/org/projectx/bt_core" #define BT_CORE_INTERFACE "org.projectx.btcore" +#define BT_DISABLE_TIME 500 /* 500 ms */ + +DBusGProxy *_bt_init_core_proxy(void) +{ + DBusGProxy *proxy; + DBusGConnection *conn; + + conn = _bt_get_system_gconn(); + if (!conn) + return NULL; + + proxy = dbus_g_proxy_new_for_name(conn, BT_CORE_NAME, + BT_CORE_PATH, BT_CORE_INTERFACE); + if (!proxy) + return NULL; + + core_proxy = proxy; + + return proxy; +} + +static DBusGProxy *__bt_get_core_proxy(void) +{ + return (core_proxy) ? core_proxy : _bt_init_core_proxy(); +} + +static gboolean __bt_is_factory_test_mode(void) +{ + int mode = 0; + +#ifdef ENABLE_TIZEN_2_4 + if (vconf_get_bool(VCONFKEY_BT_DUT_MODE, &mode)) { + BT_ERR("Get the DUT Mode fail"); + return TRUE; + } +#endif + + if (mode != FALSE) { + BT_INFO("DUT Test Mode !!"); + return TRUE; + } + + return FALSE; +} + static gboolean __bt_timeout_handler(gpointer user_data) { int result = BLUETOOTH_ERROR_NONE; @@ -86,8 +140,10 @@ static gboolean __bt_timeout_handler(gpointer user_data) visible_timer.event_id = 0; visible_timer.timeout = 0; +#ifndef TIZEN_WEARABLE if (vconf_set_int(BT_FILE_VISIBLE_TIME, 0) != 0) - BT_DBG("Set vconf failed\n"); + BT_ERR("Set vconf failed\n"); +#endif return FALSE; } @@ -96,12 +152,32 @@ static gboolean __bt_timeout_handler(gpointer user_data) static int __bt_visibility_alarm_cb(alarm_id_t alarm_id, void* user_param) { - BT_DBG("__bt_visibility_alarm_cb \n"); + BT_DBG("__bt_visibility_alarm_cb - alram id = [%d] \n", alarm_id); + + int result = BLUETOOTH_ERROR_NONE; + int timeout = 0; + + if (alarm_id != visible_timer.alarm_id) + return 0; + + if (visible_timer.event_id) { + _bt_send_event(BT_ADAPTER_EVENT, + BLUETOOTH_EVENT_DISCOVERABLE_TIMEOUT_CHANGED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INT16, &timeout, + DBUS_TYPE_INVALID); + g_source_remove(visible_timer.event_id); + visible_timer.event_id = 0; + visible_timer.timeout = 0; +#ifndef TIZEN_WEARABLE + if (vconf_set_int(BT_FILE_VISIBLE_TIME, 0) != 0) + BT_ERR("Set vconf failed\n"); +#endif + } /* Switch Off visibility in Bluez */ _bt_set_discoverable_mode(BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE, 0); visible_timer.alarm_id = 0; - alarmmgr_fini(); return 0; } @@ -113,18 +189,15 @@ static void __bt_visibility_alarm_create() result = alarmmgr_add_alarm(ALARM_TYPE_VOLATILE, visible_timer.timeout, 0, NULL, &alarm_id); if(result < 0) { - BT_DBG("Failed to create alarm error = %d\n", result); - alarmmgr_fini(); + BT_ERR("Failed to create alarm error = %d\n", result); } else { BT_DBG("Alarm created = %d\n", alarm_id); visible_timer.alarm_id = alarm_id; } } -int __bt_set_visible_time(int timeout) +static void __bt_visibility_alarm_remove() { - int result; - if (visible_timer.event_id > 0) { g_source_remove(visible_timer.event_id); visible_timer.event_id = 0; @@ -134,29 +207,41 @@ int __bt_set_visible_time(int timeout) alarmmgr_remove_alarm(visible_timer.alarm_id); visible_timer.alarm_id = 0; } +} + +int __bt_set_visible_time(int timeout) +{ + int result; + + __bt_visibility_alarm_remove(); visible_timer.timeout = timeout; +#ifndef TIZEN_WEARABLE if (vconf_set_int(BT_FILE_VISIBLE_TIME, timeout) != 0) - BT_ERR("Set vconf failed\n"); - + BT_ERR("Set vconf failed"); +#endif if (timeout <= 0) return BLUETOOTH_ERROR_NONE; - /* Take start time */ - time(&(visible_timer.start_time)); - visible_timer.event_id = g_timeout_add_seconds(1, - __bt_timeout_handler, NULL); + if (!visible_timer.alarm_init) { + /* Set Alarm timer to switch off BT */ + result = alarmmgr_init("bt-service"); + if (result != 0) + return BLUETOOTH_ERROR_INTERNAL; - /* Set Alarm timer to switch off BT */ - result = alarmmgr_init("bt-service"); - if (result != 0) - return BLUETOOTH_ERROR_INTERNAL; + visible_timer.alarm_init = TRUE; + } result = alarmmgr_set_cb(__bt_visibility_alarm_cb, NULL); if (result != 0) return BLUETOOTH_ERROR_INTERNAL; + /* Take start time */ + time(&(visible_timer.start_time)); + visible_timer.event_id = g_timeout_add_seconds(1, + __bt_timeout_handler, NULL); + __bt_visibility_alarm_create(); return BLUETOOTH_ERROR_NONE; @@ -191,227 +276,6 @@ static void __bt_get_service_list(GValue *value, bluetooth_device_info_t *dev) } } -static bt_remote_dev_info_t *__bt_parse_remote_device_info( - DBusMessageIter *item_iter) -{ - DBusMessageIter value_iter; - bt_remote_dev_info_t *dev_info; - - dbus_message_iter_recurse(item_iter, &value_iter); - - if (dbus_message_iter_get_arg_type(&value_iter) != - DBUS_TYPE_DICT_ENTRY) { - BT_DBG("No entry"); - return NULL; - } - - dev_info = g_malloc0(sizeof(bt_remote_dev_info_t)); - - while (dbus_message_iter_get_arg_type(&value_iter) == - DBUS_TYPE_DICT_ENTRY) { - char *value = NULL; - char *key; - DBusMessageIter dict_entry; - DBusMessageIter iter_dict_val; - - dbus_message_iter_recurse(&value_iter, &dict_entry); - - dbus_message_iter_get_basic(&dict_entry, &key); - - if (key == NULL) { - dbus_message_iter_next(&value_iter); - continue; - } - - if (!dbus_message_iter_next(&dict_entry)) { - dbus_message_iter_next(&value_iter); - continue; - } - dbus_message_iter_recurse(&dict_entry, &iter_dict_val); - - if (strcasecmp(key, "Address") == 0) { - const char *address = NULL; - dbus_message_iter_get_basic(&iter_dict_val, - &address); - dev_info->address = g_strdup(address); - } else if (strcasecmp(key, "Class") == 0) { - dbus_message_iter_get_basic(&iter_dict_val, - &dev_info->class); - } else if (strcasecmp(key, "Name") == 0) { - dbus_message_iter_get_basic(&iter_dict_val, - &value); - if (dev_info->name == NULL) - dev_info->name = g_strdup(value); - } else if (strcasecmp(key, "Connected") == 0) { - dbus_message_iter_get_basic(&iter_dict_val, - &dev_info->connected); - } else if (strcasecmp(key, "Paired") == 0) { - dbus_message_iter_get_basic(&iter_dict_val, - &dev_info->paired); - } else if (strcasecmp(key, "Trusted") == 0) { - dbus_message_iter_get_basic(&iter_dict_val, - &dev_info->trust); - } else if (strcasecmp(key, "RSSI") == 0) { - dbus_message_iter_get_basic(&iter_dict_val, - &dev_info->rssi); - } else if (strcasecmp(key, "UUIDs") == 0) { - DBusMessageIter uuid_iter; - DBusMessageIter tmp_iter; - int i = 0; - - dbus_message_iter_recurse(&iter_dict_val, - &uuid_iter); - tmp_iter = uuid_iter; - - /* Store the uuid count */ - while (dbus_message_iter_get_arg_type(&tmp_iter) != - DBUS_TYPE_INVALID) { - - dbus_message_iter_get_basic(&tmp_iter, - &value); - - dev_info->uuid_count++; - if (!dbus_message_iter_next(&tmp_iter)) - break; - } - - /* Store the uuids */ - if (dev_info->uuid_count > 0) { - dev_info->uuids = g_new0(char *, - dev_info->uuid_count + 1); - } else { - dbus_message_iter_next(&value_iter); - continue; - } - - while (dbus_message_iter_get_arg_type(&uuid_iter) != - DBUS_TYPE_INVALID) { - dbus_message_iter_get_basic(&uuid_iter, - &value); - dev_info->uuids[i] = g_strdup(value); - i++; - if (!dbus_message_iter_next(&uuid_iter)) { - break; - } - } - } - - dbus_message_iter_next(&value_iter); - } - - return dev_info; -} - -static void __bt_extract_remote_devinfo(DBusMessageIter *msg_iter, - GArray **dev_list) -{ - bt_remote_dev_info_t *dev_info = NULL; - char *object_path = NULL; - DBusMessageIter value_iter; - - /* Parse the signature: oa{sa{sv}}} */ - ret_if(dbus_message_iter_get_arg_type(msg_iter) != - DBUS_TYPE_OBJECT_PATH); - - dbus_message_iter_get_basic(msg_iter, &object_path); - ret_if(object_path == NULL); - - /* object array (oa) */ - ret_if(dbus_message_iter_next(msg_iter) == FALSE); - ret_if(dbus_message_iter_get_arg_type(msg_iter) != DBUS_TYPE_ARRAY); - - dbus_message_iter_recurse(msg_iter, &value_iter); - - /* string array (sa) */ - while (dbus_message_iter_get_arg_type(&value_iter) == - DBUS_TYPE_DICT_ENTRY) { - char *interface_name = NULL; - DBusMessageIter interface_iter; - - dbus_message_iter_recurse(&value_iter, &interface_iter); - - ret_if(dbus_message_iter_get_arg_type(&interface_iter) != - DBUS_TYPE_STRING); - - dbus_message_iter_get_basic(&interface_iter, &interface_name); - - ret_if(dbus_message_iter_next(&interface_iter) == FALSE); - - ret_if(dbus_message_iter_get_arg_type(&interface_iter) != - DBUS_TYPE_ARRAY); - - if (g_strcmp0(interface_name, "org.bluez.Device1") == 0) { - BT_DBG("Found a device: %s", object_path); - dev_info = __bt_parse_remote_device_info( - &interface_iter); - - if (dev_info) { - g_array_append_vals(*dev_list, dev_info, - sizeof(bt_remote_dev_info_t)); - } - } - - dbus_message_iter_next(&value_iter); - } -} - -int _bt_get_remote_found_devices(GArray **dev_list) -{ - DBusMessage *msg; - DBusMessage *reply; - DBusMessageIter reply_iter; - DBusMessageIter value_iter; - DBusError err; - DBusConnection *conn; - - conn = _bt_get_system_conn(); - retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); - - msg = dbus_message_new_method_call(BT_BLUEZ_NAME, BT_MANAGER_PATH, - BT_MANAGER_INTERFACE, - "GetManagedObjects"); - - retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL); - - /* Synchronous call */ - dbus_error_init(&err); - reply = dbus_connection_send_with_reply_and_block( - conn, msg, - -1, &err); - dbus_message_unref(msg); - - if (!reply) { - BT_ERR("Can't get managed objects"); - - if (dbus_error_is_set(&err)) { - BT_ERR("%s", err.message); - dbus_error_free(&err); - } - return BLUETOOTH_ERROR_INTERNAL; - } - - if (dbus_message_iter_init(reply, &reply_iter) == FALSE) { - BT_ERR("Fail to iterate the reply"); - return BLUETOOTH_ERROR_INTERNAL; - } - - dbus_message_iter_recurse(&reply_iter, &value_iter); - - /* signature of GetManagedObjects: a{oa{sa{sv}}} */ - while (dbus_message_iter_get_arg_type(&value_iter) == - DBUS_TYPE_DICT_ENTRY) { - DBusMessageIter msg_iter; - - dbus_message_iter_recurse(&value_iter, &msg_iter); - - __bt_extract_remote_devinfo(&msg_iter, dev_list); - - dbus_message_iter_next(&value_iter); - } - - return BLUETOOTH_ERROR_NONE; -} - static int __bt_get_bonded_device_info(gchar *device_path, bluetooth_device_info_t *dev_info) { @@ -425,6 +289,7 @@ static int __bt_get_bonded_device_info(gchar *device_path, gboolean trust; gboolean paired; gboolean connected; + GByteArray *manufacturer_data = NULL; GHashTable *hash = NULL; int ret; DBusGConnection *conn; @@ -442,7 +307,7 @@ static int __bt_get_bonded_device_info(gchar *device_path, dbus_g_proxy_call(device_proxy, "GetAll", &err, G_TYPE_STRING, BT_DEVICE_INTERFACE, - G_TYPE_INVALID, + G_TYPE_INVALID, dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), &hash, G_TYPE_INVALID); @@ -480,6 +345,9 @@ static int __bt_get_bonded_device_info(gchar *device_path, value = g_hash_table_lookup(hash, "Trusted"); trust = value ? g_value_get_boolean(value) : FALSE; + BT_DBG("paired: %d", paired); + BT_DBG("trust: %d", trust); + if ((paired == FALSE) && (trust == FALSE)) { return BLUETOOTH_ERROR_NOT_PAIRED; } @@ -490,10 +358,22 @@ static int __bt_get_bonded_device_info(gchar *device_path, value = g_hash_table_lookup(hash, "UUIDs"); __bt_get_service_list(value, dev_info); - _bt_convert_addr_string_to_type(dev_info->device_address.addr, - address); + value = g_hash_table_lookup(hash, "ManufacturerDataLen"); + dev_info->manufacturer_data.data_len = value ? g_value_get_uint(value) : 0; - _bt_divide_device_class(&dev_info->device_class, cod); + value = g_hash_table_lookup(hash, "ManufacturerData"); + manufacturer_data = value ? g_value_get_boxed(value) : NULL; + if (manufacturer_data) { + if (manufacturer_data->len > 0) { + BT_DBG("manufacturer_data->len = %d", manufacturer_data->len); + memcpy(dev_info->manufacturer_data.data, manufacturer_data->data, manufacturer_data->len); + } + } + + _bt_convert_addr_string_to_type(dev_info->device_address.addr, + address); + + _bt_divide_device_class(&dev_info->device_class, cod); g_strlcpy(dev_info->device_name.name, name, BLUETOOTH_DEVICE_NAME_LENGTH_MAX+1); @@ -517,83 +397,34 @@ void _bt_set_discovery_status(gboolean mode) is_discovering = mode; } -void _bt_set_cancel_by_user(gboolean value) +void _bt_set_le_discovery_status(gboolean mode) { - cancel_by_user = value; + is_le_discovering = mode; } -gboolean _bt_get_cancel_by_user(void) +void _bt_set_le_discovery_type(bt_le_discovery_type_t type) { - return cancel_by_user; + le_discovery_type = type; } -static void __bt_flight_mode_cb(keynode_t *node, void *data) +bt_le_discovery_type_t _bt_get_le_discovery_type(void) { - gboolean flight_mode = FALSE; - int bt_status; - - BT_DBG("key=%s\n", vconf_keynode_get_name(node)); - - bt_status = _bt_adapter_get_status(); - - if (vconf_keynode_get_type(node) == VCONF_TYPE_BOOL) { - flight_mode = vconf_keynode_get_bool(node); - - BT_DBG("value=%d\n", flight_mode); - - if (flight_mode == TRUE) { - BT_DBG("Deactivate Bluetooth Service\n"); - if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 1) != 0) - BT_DBG("Set vconf failed+\n"); - - if (bt_status == BT_ACTIVATED) - _bt_disable_adapter(); - } else { - - int value = 0; - - if (vconf_get_int(BT_OFF_DUE_TO_FLIGHT_MODE, &value)) - BT_ERR("Fail get flight mode value"); - - if (value == 0) - return; - - BT_DBG("Activate Bluetooth Service\n"); - if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0)) - BT_DBG("Set vconf failed\n"); - - if (bt_status == BT_DEACTIVATED) - _bt_enable_adapter(); - } - } + return le_discovery_type; } -#ifdef __TIZEN_MOBILE__ -static void __launch_bt_service(int status, int run_type) +void _bt_set_cancel_by_user(gboolean value) { - bundle *kb; - char status_val[5] = { 0, }; - char run_type_val[5] = { 0, }; - - snprintf(status_val, sizeof(status_val), "%d", status); - snprintf(run_type_val, sizeof(run_type_val), "%d", run_type); - - BT_DBG("status: %s, run_type: %s", status_val, run_type_val); - - kb = bundle_create(); - - bundle_add(kb, "launch-type", "setstate"); - bundle_add(kb, "status", status_val); - bundle_add(kb, "run-type", run_type_val); - - aul_launch_app("com.samsung.bluetooth", kb); + cancel_by_user = value; +} - bundle_free(kb); +gboolean _bt_get_cancel_by_user(void) +{ + return cancel_by_user; } -#endif void _bt_adapter_set_status(bt_status_t status) { + BT_INFO("adapter_status changed [%d] -> [%d]", adapter_status, status); adapter_status = status; } @@ -602,6 +433,17 @@ bt_status_t _bt_adapter_get_status(void) return adapter_status; } +void _bt_adapter_set_le_status(bt_le_status_t status) +{ + BT_INFO("adapter_le_status changed [%d] -> [%d]", adapter_le_status, status); + adapter_le_status = status; +} + +bt_le_status_t _bt_adapter_get_le_status(void) +{ + return adapter_le_status; +} + static void __bt_phone_name_changed_cb(keynode_t *node, void *data) { char *phone_name = NULL; @@ -612,6 +454,7 @@ static void __bt_phone_name_changed_cb(keynode_t *node, void *data) if (vconf_keynode_get_type(node) == VCONF_TYPE_STRING) { phone_name = vconf_keynode_get_str(node); + if (phone_name && strlen(phone_name) != 0) { if (!g_utf8_validate(phone_name, -1, (const char **)&ptr)) @@ -622,23 +465,60 @@ static void __bt_phone_name_changed_cb(keynode_t *node, void *data) } } +#ifdef TIZEN_WEARABLE +static char * __bt_change_dev_name(const char *default_name) +{ + FILE *fp = NULL; + char *buf = NULL; + char *name = NULL; + int result; + + if ((fp = fopen("/csa/bluetooth/.bd_addr", "r")) == NULL) { + BT_ERR("Unable to open bd_addr"); + return NULL; + } + + result = fseek(fp, -4, SEEK_END); + if (result < 0) { + BT_ERR("fseek is failed"); + fclose(fp); + return NULL; + } + + buf = (char *)malloc(sizeof(char) * 5); + if (buf == NULL) { + BT_ERR("malloc is failed"); + fclose(fp); + return NULL; + } + memset(buf, 0, 5); + + result = fread(buf, 1, 4, fp); + if (result) + BT_DBG("Size Read: [%d]", result); + else + BT_ERR("Error reading file: code[%d]", result); + + name = g_strdup_printf("%s (%s)", default_name, buf); + + BT_INFO("%s", name); + + free(buf); + fclose(fp); + + return name ; +} +#else static void __bt_set_visible_mode(void) { - int timeout; + int timeout = 0; if (vconf_get_int(BT_FILE_VISIBLE_TIME, &timeout) != 0) BT_ERR("Fail to get the timeout value"); /* -1: Always on */ - if (timeout == -1) { - if (_bt_set_discoverable_mode( - BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE, - timeout) != BLUETOOTH_ERROR_NONE) { - if (vconf_set_int(BT_FILE_VISIBLE_TIME, 0) != 0) - BT_ERR("Set vconf failed"); - } - } } +#endif static void __bt_set_local_name(void) { @@ -653,24 +533,36 @@ static void __bt_set_local_name(void) if (strlen(phone_name) != 0) { if (!g_utf8_validate(phone_name, -1, (const char **)&ptr)) *ptr = '\0'; + +#ifdef TIZEN_WEARABLE + if (strstr(phone_name, "(") == NULL) { + char *tmp = __bt_change_dev_name(phone_name); + if (tmp != NULL) { + free(phone_name); + phone_name = tmp; + } + } +#endif _bt_set_local_name(phone_name); } free(phone_name); } -void _bt_set_enabled(void) +static int __bt_set_enabled(void) { + int adapter_status = BT_ADAPTER_DISABLED; int result = BLUETOOTH_ERROR_NONE; - _bt_adapter_set_status(BT_ACTIVATED); + _bt_check_adapter(&adapter_status); - // register agent if it was not previously done. - if (!adapter_agent) { - BT_DBG(""); - _bt_handle_adapter_added(); + if (adapter_status == BT_ADAPTER_DISABLED) { + BT_ERR("Bluetoothd is not running"); + return BLUETOOTH_ERROR_INTERNAL; } +#ifndef TIZEN_WEARABLE __bt_set_visible_mode(); +#endif __bt_set_local_name(); @@ -684,24 +576,109 @@ void _bt_set_enabled(void) /* Send enabled event to API */ _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_ENABLED, DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID); + + return BLUETOOTH_ERROR_NONE; } -void _bt_set_disabled(void) +void _bt_set_disabled(int result) { - int result = BLUETOOTH_ERROR_NONE; + int power_off_status = 0; + int ret; + int ret_pm_ignore; + int pm_ignore_mode = 0; + + ret = vconf_get_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, &power_off_status); + BT_DBG("ret : %d, power_off_status : %d", ret, power_off_status); + + ret_pm_ignore = vconf_get_int(VCONFKEY_PM_KEY_IGNORE, &pm_ignore_mode); + + /* Update the vconf BT status in normal Deactivation case only */ + if (ret == 0 && power_off_status == VCONFKEY_SYSMAN_POWER_OFF_NONE && + ret_pm_ignore == 0 && pm_ignore_mode != VCONFKEY_PM_KEY_LOCK) { + + BT_DBG("Update vconf for BT normal Deactivation"); + + if (result == BLUETOOTH_ERROR_TIMEOUT) + if (vconf_set_int(BT_OFF_DUE_TO_TIMEOUT, 1) != 0 ) + BT_ERR("Set vconf failed"); + + /* Update Bluetooth Status to notify other modules */ + if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_OFF) != 0) + BT_ERR("Set vconf failed"); + } + + if (vconf_set_int(VCONFKEY_BT_DEVICE, VCONFKEY_BT_DEVICE_NONE) != 0) + BT_ERR("Set vconf failed\n"); _bt_adapter_set_status(BT_DEACTIVATED); + if (_bt_adapter_get_le_status() != BT_LE_DEACTIVATED) { + /* Send disabled event */ + _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_DISABLED, + DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID); + } + + BT_INFO("Adapter disabled"); +} + +static int __bt_set_le_enabled(void) +{ + BT_DBG("+"); + int result = BLUETOOTH_ERROR_NONE; + bt_status_t status; + + __bt_set_local_name(); + +#ifdef ENABLE_TIZEN_2_4 /* Update Bluetooth Status to notify other modules */ - if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_OFF) != 0) + if (vconf_set_int(VCONFKEY_BT_LE_STATUS, VCONFKEY_BT_LE_STATUS_ON) != 0) BT_ERR("Set vconf failed\n"); +#endif + /* Send enabled event to API */ + /* + _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_ENABLED, + DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID); + */ + status = _bt_adapter_get_status(); + if (status == BT_DEACTIVATED) { + BT_INFO("BREDR is off, turn off PSCAN"); + _bt_set_connectable(FALSE); + } + if (le_timer_id > 0) { + g_source_remove(le_timer_id); + le_timer_id = 0; + } - if (vconf_set_int(VCONFKEY_BT_DEVICE, VCONFKEY_BT_DEVICE_NONE) != 0) + /* Send enabled event to API */ + _bt_send_event(BT_LE_ADAPTER_EVENT, BLUETOOTH_EVENT_LE_ENABLED, + DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID); + + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; +} + +void _bt_set_le_disabled(int result) +{ + int power_off_status; + int ret; + + ret = vconf_get_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, &power_off_status); + BT_DBG("ret : %d", ret); + BT_DBG("power_off_status : %d", power_off_status); + + /* Update Bluetooth Status to notify other modules */ + BT_DBG("Update vconf for BT LE normal Deactivation"); +#ifdef ENABLE_TIZEN_2_4 + if (vconf_set_int(VCONFKEY_BT_LE_STATUS, VCONFKEY_BT_LE_STATUS_OFF) != 0) BT_ERR("Set vconf failed\n"); + _bt_adapter_set_le_status(BT_LE_DEACTIVATED); +#endif - /* Send disabled event */ - _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_DISABLED, + if (_bt_adapter_get_status() != BT_DEACTIVATED) { + /* Send disabled event */ + _bt_send_event(BT_LE_ADAPTER_EVENT, BLUETOOTH_EVENT_LE_DISABLED, DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID); + } } void *_bt_get_adapter_agent(void) @@ -709,17 +686,107 @@ void *_bt_get_adapter_agent(void) return adapter_agent; } -void _bt_handle_flight_mode_noti(void) +int _bt_enable_core(void) { + DBusGProxy *proxy; + + proxy = __bt_get_core_proxy(); + retv_if(!proxy, BLUETOOTH_ERROR_INTERNAL); + + if (dbus_g_proxy_call(proxy, "EnableCore", NULL, + G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) { + BT_ERR("Bt core call failed"); + } + + return BLUETOOTH_ERROR_NONE; +} + +static void __bt_service_flight_ps_mode_cb(keynode_t *node, void *data) +{ + gboolean flight_mode = FALSE; + int power_saving_mode = 0; + int type; + + DBG_SECURE("key=%s", vconf_keynode_get_name(node)); + type = vconf_keynode_get_type(node); + if (type == VCONF_TYPE_BOOL) { + flight_mode = vconf_keynode_get_bool(node); + if (flight_mode != TRUE) { + BT_ERR("Ignore the event"); + return; + } + } else if (type == VCONF_TYPE_INT) { + power_saving_mode = vconf_keynode_get_int(node); + if (power_saving_mode != 2) { + BT_ERR("Ignore the event"); + return; + } + } else { + BT_ERR("Invaild vconf key type : %d", type); + return; + } + + _bt_enable_core(); +} + +void _bt_service_register_vconf_handler(void) +{ + int ret; BT_DBG("+"); - vconf_notify_key_changed(VCONFKEY_TELEPHONY_FLIGHT_MODE, - __bt_flight_mode_cb, NULL); - BT_DBG("-"); + +#ifdef TIZEN_TELEPHONY_ENABLED + ret = vconf_notify_key_changed(VCONFKEY_TELEPHONY_FLIGHT_MODE, + (vconf_callback_fn)__bt_service_flight_ps_mode_cb, NULL); + if (ret < 0) + BT_ERR("Unable to register key handler"); +#else + BT_DBG("Telephony is disabled"); +#endif + +#ifndef TIZEN_WEARABLE +#ifdef ENABLE_TIZEN_2_4 + ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_PSMODE, + (vconf_callback_fn)__bt_service_flight_ps_mode_cb, NULL); + if (ret < 0) + BT_ERR("Unable to register key handler"); +#endif +#endif +} + +void _bt_service_unregister_vconf_handler(void) +{ + BT_DBG("+"); + +#ifdef TIZEN_TELEPHONY_ENABLED + vconf_ignore_key_changed(VCONFKEY_TELEPHONY_FLIGHT_MODE, + (vconf_callback_fn)__bt_service_flight_ps_mode_cb); +#endif + +#ifndef TIZEN_WEARABLE +#ifdef ENABLE_TIZEN_2_4 + vconf_ignore_key_changed(VCONFKEY_SETAPPL_PSMODE, + (vconf_callback_fn)__bt_service_flight_ps_mode_cb); +#endif +#endif } void _bt_handle_adapter_added(void) { - BT_DBG(""); + BT_DBG("+"); + bt_status_t status; + bt_le_status_t le_status; + int ret; + + if (timer_id > 0) { + BT_DBG("g_source is removed"); + g_source_remove(timer_id); + timer_id = 0; + } + + status = _bt_adapter_get_status(); + le_status = _bt_adapter_get_le_status(); + BT_DBG("status : %d", status); + BT_DBG("le_status : %d", le_status); adapter_agent = _bt_create_agent(BT_ADAPTER_AGENT_PATH, TRUE); if (!adapter_agent) { @@ -727,81 +794,173 @@ void _bt_handle_adapter_added(void) return; } -#ifdef __TIZEN_MOBILE__ - if (!aul_app_is_running("com.samsung.bluetooth")) - __launch_bt_service(0, 0); - if (_bt_register_media_player() != BLUETOOTH_ERROR_NONE) BT_ERR("Fail to register media player"); -#endif if (_bt_register_obex_server() != BLUETOOTH_ERROR_NONE) BT_ERR("Fail to init obex server"); -/* + +#ifndef TIZEN_WEARABLE if (_bt_network_activate() != BLUETOOTH_ERROR_NONE) BT_ERR("Fail to activate network"); -*/ +#endif /* add the vconf noti handler */ - vconf_notify_key_changed(VCONFKEY_SETAPPL_DEVICE_NAME_STR, + ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_DEVICE_NAME_STR, __bt_phone_name_changed_cb, NULL); + if (ret < 0) + BT_ERR("Unable to register key handler"); + + if (le_status == BT_LE_ACTIVATING) { + __bt_set_le_enabled(); + _bt_adapter_set_le_status(BT_LE_ACTIVATED); + } + if (status == BT_ACTIVATING) { + __bt_set_enabled(); + _bt_adapter_set_status(BT_ACTIVATED); + } +// journal_bt_on(); - vconf_notify_key_changed(VCONFKEY_TELEPHONY_FLIGHT_MODE, - __bt_flight_mode_cb, NULL); + _bt_service_register_vconf_handler(); } void _bt_handle_adapter_removed(void) { - BT_DBG(""); + int ret; + + _bt_adapter_set_status(BT_DEACTIVATED); +// journal_bt_off(); + + __bt_visibility_alarm_remove(); + + if (visible_timer.alarm_init) { + alarmmgr_fini(); + visible_timer.alarm_init = FALSE; + } - vconf_ignore_key_changed(VCONFKEY_SETAPPL_DEVICE_NAME_STR, + ret = vconf_ignore_key_changed(VCONFKEY_SETAPPL_DEVICE_NAME_STR, (vconf_callback_fn)__bt_phone_name_changed_cb); + if (0 != ret) { + ERR("vconf_ignore_key_changed failed\n"); + } _bt_destroy_agent(adapter_agent); adapter_agent = NULL; + _bt_reliable_terminate_service(NULL); +} + +static gboolean __bt_enable_timeout_cb(gpointer user_data) +{ + DBusGProxy *proxy; + + timer_id = 0; + + retv_if(_bt_adapter_get_status() == BT_ACTIVATED, FALSE); + + BT_ERR("EnableAdapter is failed"); + + proxy = __bt_get_core_proxy(); + if (!proxy) + return FALSE; + + /* Clean up the process */ + if (dbus_g_proxy_call(proxy, "DisableAdapter", NULL, + G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) { + BT_ERR("Bt core call failed"); + } + + _bt_set_disabled(BLUETOOTH_ERROR_TIMEOUT); + + /* Display notification */ + notification_status_message_post(BT_STR_NOT_SUPPORT); + _bt_terminate_service(NULL); + + return FALSE; } -DBusGProxy *_bt_init_core_proxy(void) +static gboolean __bt_enable_le_timeout_cb(gpointer user_data) { DBusGProxy *proxy; - DBusGConnection *conn; - conn = _bt_get_system_gconn(); - if (!conn) - return NULL; + le_timer_id = 0; - proxy = dbus_g_proxy_new_for_name(conn, BT_CORE_NAME, - BT_CORE_PATH, BT_CORE_INTERFACE); + retv_if(_bt_adapter_get_le_status() == BT_LE_ACTIVATED, FALSE); + + BT_ERR("EnableAdapterLE is failed"); + + proxy = __bt_get_core_proxy(); if (!proxy) - return NULL; + return FALSE; - core_proxy = proxy; + /* Clean up the process */ + if (dbus_g_proxy_call(proxy, "DisableAdapterLe", NULL, + G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) { + BT_ERR("Bt core call failed"); + } - return proxy; + _bt_adapter_set_le_status(BT_LE_DEACTIVATED); + + _bt_set_le_disabled(BLUETOOTH_ERROR_TIMEOUT); + + /* Display notification */ + notification_status_message_post(BT_STR_NOT_SUPPORT); + + if (_bt_adapter_get_status() == BT_DEACTIVATED) + _bt_terminate_service(NULL); + + return FALSE; } -static DBusGProxy *__bt_get_core_proxy(void) +void _bt_adapter_start_le_enable_timer(void) +{ + if (le_timer_id > 0) { + g_source_remove(le_timer_id); + le_timer_id = 0; + } + + le_timer_id = g_timeout_add(BT_ENABLE_TIMEOUT, + __bt_enable_le_timeout_cb, NULL); + + return; +} + +void _bt_adapter_start_enable_timer(void) { - return (core_proxy) ? core_proxy : _bt_init_core_proxy(); + if (timer_id > 0) { + g_source_remove(timer_id); + timer_id = 0; + } + + timer_id = g_timeout_add(BT_ENABLE_TIMEOUT, + __bt_enable_timeout_cb, NULL); + + return; } int _bt_enable_adapter(void) { DBusGProxy *proxy; GError *err = NULL; - + int ret; + bt_status_t status = _bt_adapter_get_status(); + bt_le_status_t le_status = _bt_adapter_get_le_status(); BT_DBG(""); - if (_bt_adapter_get_status() == BT_ACTIVATING) { - BT_DBG("Enabling in progress"); - return BLUETOOTH_ERROR_IN_PROGRESS; + if (status == BT_ACTIVATING) { + BT_ERR("Enabling in progress"); + return BLUETOOTH_ERROR_IN_PROGRESS; + } + + if (status == BT_ACTIVATED) { + BT_ERR("Already enabled"); + return BLUETOOTH_ERROR_DEVICE_ALREADY_ENABLED; } - if (_bt_adapter_get_status() == BT_ACTIVATED) { - BT_DBG("Already enabled"); - return BLUETOOTH_ERROR_DEVICE_ALREADY_ENABLED; + if (status == BT_DEACTIVATING || le_status == BT_LE_DEACTIVATING) { + BT_ERR("Disabling in progress"); + return BLUETOOTH_ERROR_DEVICE_BUSY; } _bt_adapter_set_status(BT_ACTIVATING); @@ -810,6 +969,16 @@ int _bt_enable_adapter(void) if (!proxy) return BLUETOOTH_ERROR_INTERNAL; + if (le_status == BT_LE_ACTIVATED) { + BT_INFO("LE Already enabled. Just turn on PSCAN"); + ret = _bt_set_connectable(TRUE); + if (ret == BLUETOOTH_ERROR_NONE) { + _bt_adapter_set_status(BT_ACTIVATED); + } else { + return BLUETOOTH_ERROR_INTERNAL; + } + } + if (dbus_g_proxy_call_with_timeout(proxy, "EnableAdapter", BT_ENABLE_TIMEOUT, &err, G_TYPE_INVALID, @@ -836,38 +1005,181 @@ int _bt_enable_adapter(void) return BLUETOOTH_ERROR_INTERNAL; } + if (le_status == BT_LE_ACTIVATED) { + __bt_set_enabled(); + } else { + _bt_adapter_start_enable_timer(); + } + return BLUETOOTH_ERROR_NONE; } -int _bt_disable_adapter(void) +static gboolean __bt_disconnect_all(void) { - DBusGProxy *proxy; + int i; + DBusGConnection *conn; + DBusGProxy *dev_proxy; + gboolean ret = FALSE; + + GArray *device_list; + bluetooth_device_info_t info; + guint size; + char *device_path = NULL; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + + + BT_DBG(""); + + conn = _bt_get_system_gconn(); + + device_list = g_array_new(FALSE, FALSE, sizeof(gchar)); + + if (_bt_get_bonded_devices(&device_list) + != BLUETOOTH_ERROR_NONE) { + g_array_free(device_list, TRUE); + return FALSE; + } + + size = (device_list->len) / sizeof(bluetooth_device_info_t); + + for (i = 0; i < size; i++) { + + info = g_array_index(device_list, + bluetooth_device_info_t, i); + + if (info.connected == TRUE) { + BT_DBG("Found Connected device"); + _bt_convert_addr_type_to_string(address, info.device_address.addr); + device_path = _bt_get_device_object_path(address); + if (device_path == NULL) + continue; + + BT_DBG("Disconnecting : %s", device_path); + + dev_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + device_path, BT_DEVICE_INTERFACE); + if (dev_proxy == NULL) + continue; + + if(!dbus_g_proxy_call(dev_proxy, "Disconnect", + NULL, G_TYPE_INVALID, G_TYPE_INVALID)) { + BT_ERR("Disconnect fail error."); + g_object_unref(dev_proxy); + return FALSE; + } + } + } + ret = TRUE; + g_array_free(device_list, TRUE); + + return ret; +} +static gboolean __bt_set_disabled_timeout_cb(gpointer user_data) +{ BT_DBG(""); + _bt_set_disabled(BLUETOOTH_ERROR_NONE); + + return FALSE; +} + +int __bt_disable_cb(void) +{ + FN_START; + DBusGProxy *proxy; + bt_le_status_t le_status; + int ret; + + _bt_adapter_set_status(BT_DEACTIVATING); + le_status = _bt_adapter_get_le_status(); + BT_DBG("le_status : %d", le_status); + if (le_status == BT_LE_ACTIVATED) { + BT_INFO("LE is enabled. Just turn off PSCAN"); + + if (_bt_is_discovering()) + _bt_cancel_discovery(); + + if (_bt_is_connectable() == FALSE) { + g_timeout_add(100, (GSourceFunc)__bt_set_disabled_timeout_cb, NULL); + } else { + ret = _bt_set_connectable(FALSE); + if (ret != BLUETOOTH_ERROR_NONE) { + BT_ERR("_bt_set_connectable fail!"); + _bt_adapter_set_status(BT_ACTIVATED); + return BLUETOOTH_ERROR_INTERNAL; + } + } + } + + proxy = __bt_get_core_proxy(); + retv_if(!proxy, BLUETOOTH_ERROR_INTERNAL); + + if (dbus_g_proxy_call(proxy, "DisableAdapter", NULL, + G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) { + BT_ERR("Bt core call failed"); + _bt_adapter_set_status(BT_ACTIVATED); + return BLUETOOTH_ERROR_INTERNAL; + } + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_disable_adapter(void) +{ + BT_DBG("+"); + int ret; if (_bt_adapter_get_status() == BT_DEACTIVATING) { - BT_DBG("Disabling in progress"); - return BLUETOOTH_ERROR_IN_PROGRESS; + BT_DBG("Disabling in progress"); + return BLUETOOTH_ERROR_IN_PROGRESS; } if (_bt_adapter_get_status() == BT_DEACTIVATED) { - BT_DBG("Already disabled"); - return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; + BT_DBG("Already disabled"); + return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; + } + + if (timer_id > 0) { + g_source_remove(timer_id); + timer_id = 0; + } + + __bt_disconnect_all(); + ret = __bt_disable_cb(); + + BT_DBG("-"); + return ret; +} + +int _bt_recover_adapter(void) +{ + BT_DBG("+"); + DBusGProxy *proxy; + + if (_bt_adapter_get_status() == BT_DEACTIVATING) { + BT_DBG("Disabling in progress"); + return BLUETOOTH_ERROR_IN_PROGRESS; + } + + if (_bt_adapter_get_status() == BT_DEACTIVATED) { + BT_DBG("Already disabled"); + return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; } _bt_adapter_set_status(BT_DEACTIVATING); proxy = __bt_get_core_proxy(); - if (!proxy) - return BLUETOOTH_ERROR_INTERNAL; + retv_if(!proxy, BLUETOOTH_ERROR_INTERNAL); - if (dbus_g_proxy_call(proxy, "DisableAdapter", NULL, + if (dbus_g_proxy_call(proxy, "RecoverAdapter", NULL, G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) { BT_ERR("Bt core call failed"); - _bt_adapter_set_status(BT_ACTIVATED); return BLUETOOTH_ERROR_INTERNAL; } + __bt_disconnect_all(); + + BT_ERR("-"); return BLUETOOTH_ERROR_NONE; } @@ -895,20 +1207,130 @@ int _bt_reset_adapter(void) return BLUETOOTH_ERROR_NONE; } -int _bt_check_adapter(int *status) -{ - BT_CHECK_PARAMETER(status, return); +int _bt_check_adapter(int *status) +{ + + char *adapter_path = NULL; + + BT_CHECK_PARAMETER(status, return); + + *status = BT_ADAPTER_DISABLED; + + adapter_path = _bt_get_adapter_path(); + + + if (adapter_path != NULL) + *status = BT_ADAPTER_ENABLED; + + g_free(adapter_path); + return BLUETOOTH_ERROR_NONE; +} + +int _bt_enable_adapter_le(void) +{ + BT_DBG("+"); + DBusGProxy *proxy; + GError *err = NULL; + bt_status_t status = _bt_adapter_get_status(); + bt_le_status_t le_status = _bt_adapter_get_le_status(); + + if (le_status == BT_LE_ACTIVATING) { + BT_ERR("Enabling in progress"); + return BLUETOOTH_ERROR_IN_PROGRESS; + } + + if (le_status == BT_LE_ACTIVATED) { + BT_ERR("Already enabled"); + return BLUETOOTH_ERROR_DEVICE_ALREADY_ENABLED; + } + + if (status == BT_DEACTIVATING || le_status == BT_LE_DEACTIVATING) { + BT_ERR("Disabling in progress"); + return BLUETOOTH_ERROR_DEVICE_BUSY; + } + + _bt_adapter_set_le_status(BT_LE_ACTIVATING); + + proxy = __bt_get_core_proxy(); + retv_if(!proxy, BLUETOOTH_ERROR_INTERNAL); + + if (dbus_g_proxy_call_with_timeout(proxy, "EnableAdapterLe", + BT_ENABLE_TIMEOUT, &err, + G_TYPE_INVALID, + G_TYPE_INVALID) == FALSE) { + + _bt_adapter_set_le_status(BT_DEACTIVATED); + + if (err != NULL) { + BT_ERR("Bt core call failed: [%s]", err->message); + g_error_free(err); + } + + /* Clean up the process */ + if (dbus_g_proxy_call(proxy, "DisableAdapterLe", NULL, + G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) { + BT_ERR("Bt core call failed"); + } + + /* Display notification */ + notification_status_message_post(BT_STR_NOT_SUPPORT); + + /* Terminate myself */ + if (_bt_adapter_get_status() == BT_DEACTIVATED) + g_idle_add((GSourceFunc)_bt_terminate_service, NULL); + return BLUETOOTH_ERROR_INTERNAL; + } + + _bt_adapter_start_le_enable_timer(); + + if (status == BT_ACTIVATED) { + _bt_adapter_set_le_status(BT_LE_ACTIVATED); + __bt_set_le_enabled(); + } + BT_DBG("le status : %d", _bt_adapter_get_le_status()); + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; +} + +int _bt_disable_adapter_le(void) +{ + BT_DBG("+"); + DBusGProxy *proxy; + bt_le_status_t bt_le_state; + + bt_le_state = _bt_adapter_get_le_status(); + if (bt_le_state == BT_LE_DEACTIVATING) { + BT_DBG("Disabling in progress"); + return BLUETOOTH_ERROR_IN_PROGRESS; + } + + if (bt_le_state == BT_LE_DEACTIVATED) { + BT_DBG("Already disabled"); + return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; + } - *status = 0; /* 0: disabled */ + _bt_adapter_set_le_status(BT_LE_DEACTIVATING); + + proxy = __bt_get_core_proxy(); + if (!proxy) + return BLUETOOTH_ERROR_INTERNAL; - if (_bt_get_adapter_power()) - *status = 1; /* 1: enabled */ + if (dbus_g_proxy_call(proxy, "DisableAdapterLe", NULL, + G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) { + BT_ERR("Bt core call failed"); + _bt_adapter_set_le_status(BT_LE_ACTIVATED); + return BLUETOOTH_ERROR_INTERNAL; + } + _bt_set_le_disabled(BLUETOOTH_ERROR_NONE); + BT_DBG("le status : %d", _bt_adapter_get_le_status()); + BT_DBG("-"); return BLUETOOTH_ERROR_NONE; } int _bt_get_local_address(bluetooth_device_address_t *local_address) { + DBusGProxy *proxy; GError *err = NULL; char *address; @@ -943,15 +1365,65 @@ int _bt_get_local_address(bluetooth_device_address_t *local_address) return BLUETOOTH_ERROR_NONE; } -int _bt_get_local_name(bluetooth_device_name_t *local_name) +int _bt_get_local_version(bluetooth_version_t *local_version) { DBusGProxy *proxy; + GHashTable *hash = NULL; + char *ver = NULL; + char *ptr = NULL; + int ret = BLUETOOTH_ERROR_NONE; + + BT_CHECK_PARAMETER(local_version, return); + GError *err = NULL; - GValue name_v = { 0 }; + GValue version_v = { 0 }; + + proxy = _bt_get_adapter_properties_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + if (!dbus_g_proxy_call(proxy, "Get", &err, + G_TYPE_STRING, BT_ADAPTER_INTERFACE, + G_TYPE_STRING, "Version", + G_TYPE_INVALID, + G_TYPE_VALUE, &version_v, + G_TYPE_INVALID)) { + if (err != NULL) { + BT_ERR("Getting property failed: [%s]\n", err->message); + g_error_free(err); + } + return BLUETOOTH_ERROR_INTERNAL; + } + + ver = (char *)g_value_get_string(&version_v); + + + if (ver && (strlen(ver) > 0)) { + /* Check the utf8 valitation & Fill the NULL in the invalid location*/ + if (!g_utf8_validate(ver, -1, (const char **)&ptr)) + *ptr = '\0'; + + g_strlcpy(local_version->version, ver, + BLUETOOTH_VERSION_LENGTH_MAX + 1); + + } else { + ret = BLUETOOTH_ERROR_INTERNAL; + } + + g_hash_table_destroy(hash); + return ret; +} + +int _bt_get_local_name(bluetooth_device_name_t *local_name) +{ + DBusGProxy *proxy; + GHashTable *hash = NULL; char *name = NULL; char *ptr = NULL; int ret = BLUETOOTH_ERROR_NONE; + GError *err = NULL; + GValue name_v = { 0 }; + BT_CHECK_PARAMETER(local_name, return); proxy = _bt_get_adapter_properties_proxy(); @@ -983,6 +1455,7 @@ int _bt_get_local_name(bluetooth_device_name_t *local_name) ret = BLUETOOTH_ERROR_INTERNAL; } + g_hash_table_destroy(hash); return ret; } @@ -996,6 +1469,7 @@ int _bt_set_local_name(char *local_name) BT_CHECK_PARAMETER(local_name, return); proxy = _bt_get_adapter_properties_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); if (!g_utf8_validate(local_name, -1, (const char **)&ptr)) @@ -1026,25 +1500,31 @@ int _bt_is_service_used(char *service_uuid, gboolean *used) char **uuids; int i; DBusGProxy *proxy; - GHashTable *hash = NULL; - GValue *value; + GError *err = NULL; + GValue uuids_v = { 0 }; int ret = BLUETOOTH_ERROR_NONE; + BT_DBG("+"); BT_CHECK_PARAMETER(service_uuid, return); BT_CHECK_PARAMETER(used, return); - proxy = _bt_get_adapter_proxy(); + proxy = _bt_get_adapter_properties_proxy(); retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - dbus_g_proxy_call(proxy, "GetProperties", NULL, - G_TYPE_INVALID, - dbus_g_type_get_map("GHashTable", G_TYPE_STRING, - G_TYPE_VALUE), &hash, G_TYPE_INVALID); - - retv_if(hash == NULL, BLUETOOTH_ERROR_INTERNAL); + if (!dbus_g_proxy_call(proxy, "Get", &err, + G_TYPE_STRING, BT_ADAPTER_INTERFACE, + G_TYPE_STRING, "UUIDs", + G_TYPE_INVALID, + G_TYPE_VALUE, &uuids_v, + G_TYPE_INVALID)) { + if (err != NULL) { + BT_ERR("Getting property failed: [%s]\n", err->message); + g_error_free(err); + } + return BLUETOOTH_ERROR_INTERNAL; + } - value = g_hash_table_lookup(hash, "UUIDs"); - uuids = g_value_get_boxed(value); + uuids = g_value_get_boxed(&uuids_v); if (uuids == NULL) { /* Normal case */ @@ -1061,10 +1541,11 @@ int _bt_is_service_used(char *service_uuid, gboolean *used) *used = FALSE; done: - g_hash_table_destroy(hash); + BT_DBG("Service Used? %d", *used); return ret; } + static gboolean __bt_get_discoverable_property(void) { DBusGProxy *proxy; @@ -1072,7 +1553,7 @@ static gboolean __bt_get_discoverable_property(void) GError *err = NULL; proxy = _bt_get_adapter_properties_proxy(); - retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + retv_if(proxy == NULL, FALSE); if (!dbus_g_proxy_call(proxy, "Get", &err, G_TYPE_STRING, BT_ADAPTER_INTERFACE, @@ -1084,7 +1565,7 @@ static gboolean __bt_get_discoverable_property(void) BT_ERR("Getting property failed: [%s]\n", err->message); g_error_free(err); } - return BLUETOOTH_ERROR_INTERNAL; + return FALSE; } return g_value_get_boolean(&discoverable_v); @@ -1111,6 +1592,7 @@ int _bt_get_discoverable_mode(int *mode) return BLUETOOTH_ERROR_NONE; } + int _bt_set_discoverable_mode(int discoverable_mode, int timeout) { int ret = BLUETOOTH_ERROR_NONE; @@ -1123,6 +1605,7 @@ int _bt_set_discoverable_mode(int discoverable_mode, int timeout) DBusGProxy *proxy; proxy = _bt_get_adapter_properties_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); g_value_init(&connectable, G_TYPE_BOOLEAN); @@ -1148,18 +1631,21 @@ int _bt_set_discoverable_mode(int discoverable_mode, int timeout) return BLUETOOTH_ERROR_INVALID_PARAM; } + BT_INFO("Req. discoverable_mode : %d, timeout : %d", + discoverable_mode, timeout); + g_value_set_boolean(&connectable, pg_scan); g_value_set_boolean(&discoverable, inq_scan); g_value_set_uint(&val_timeout, timeout); dbus_g_proxy_call(proxy, "Set", &error, G_TYPE_STRING, BT_ADAPTER_INTERFACE, - G_TYPE_STRING, "Powered", + G_TYPE_STRING, "Connectable", G_TYPE_VALUE, &connectable, G_TYPE_INVALID, G_TYPE_INVALID); if (error != NULL) { - BT_ERR("Powered set err:[%s]", error->message); + BT_ERR("Connectable set err:[%s]", error->message); g_error_free(error); ret = BLUETOOTH_ERROR_INTERNAL; goto done; @@ -1171,6 +1657,7 @@ int _bt_set_discoverable_mode(int discoverable_mode, int timeout) G_TYPE_VALUE, &discoverable, G_TYPE_INVALID, G_TYPE_INVALID); + if (error != NULL) { BT_ERR("Discoverable set err:[%s]", error->message); g_error_free(error); @@ -1194,7 +1681,7 @@ int _bt_set_discoverable_mode(int discoverable_mode, int timeout) if (discoverable_mode == BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE) timeout = -1; - __bt_set_visible_time(timeout); + ret = __bt_set_visible_time(timeout); done: g_value_unset(&val_timeout); @@ -1207,22 +1694,65 @@ done: int _bt_start_discovery(void) { DBusGProxy *proxy; + GError *err = NULL; if (_bt_is_discovering() == TRUE) { BT_ERR("BT is already in discovering"); return BLUETOOTH_ERROR_IN_PROGRESS; + } else if (_bt_is_device_creating() == TRUE) { + BT_ERR("Bonding device is going on"); + return BLUETOOTH_ERROR_DEVICE_BUSY; } proxy = _bt_get_adapter_proxy(); retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - if (!dbus_g_proxy_call(proxy, "StartDiscovery", NULL, + if (!dbus_g_proxy_call(proxy, "StartDiscovery", &err, G_TYPE_INVALID, G_TYPE_INVALID)) { + if (err != NULL) { + BT_ERR("StartDiscovery failed: [%s]\n", err->message); + g_error_free(err); + } BT_ERR("Discover start failed"); return BLUETOOTH_ERROR_INTERNAL; } - _bt_stop_discovery_timeout(); + is_discovering = TRUE; + cancel_by_user = FALSE; + /* discovery status will be change in event */ + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_start_custom_discovery(bt_discovery_role_type_t role) +{ + DBusGProxy *proxy; + + const gchar *disc_type; + + if (_bt_is_discovering() == TRUE) { + BT_ERR("BT is already in discovering"); + return BLUETOOTH_ERROR_IN_PROGRESS; + } + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + if (role == DISCOVERY_ROLE_BREDR) + disc_type = "BREDR"; + else if (role == DISCOVERY_ROLE_LE) + disc_type = "LE"; + else if (role == DISCOVERY_ROLE_LE_BREDR) + disc_type = "LE_BREDR"; + else + return BLUETOOTH_ERROR_INVALID_PARAM; + + if (!dbus_g_proxy_call(proxy, "StartCustomDiscovery", NULL, + G_TYPE_STRING, disc_type, + G_TYPE_INVALID, G_TYPE_INVALID)) { + BT_ERR("StartCustomDiscovery failed"); + return BLUETOOTH_ERROR_INTERNAL; + } is_discovering = TRUE; cancel_by_user = FALSE; @@ -1234,6 +1764,7 @@ int _bt_start_discovery(void) int _bt_cancel_discovery(void) { DBusGProxy *proxy; + GError *err = NULL; if (_bt_is_discovering() == FALSE) { BT_ERR("BT is not in discovering"); @@ -1243,9 +1774,12 @@ int _bt_cancel_discovery(void) proxy = _bt_get_adapter_proxy(); retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - if (!dbus_g_proxy_call(proxy, "StopDiscovery", NULL, + if (!dbus_g_proxy_call(proxy, "StopDiscovery", &err, G_TYPE_INVALID, G_TYPE_INVALID)) { - BT_ERR("Discover stop failed"); + if (err != NULL) { + BT_ERR("StopDiscovery failed: [%s]\n", err->message); + g_error_free(err); + } return BLUETOOTH_ERROR_INTERNAL; } @@ -1255,23 +1789,143 @@ int _bt_cancel_discovery(void) return BLUETOOTH_ERROR_NONE; } +int _bt_start_le_discovery(void) +{ + DBusGProxy *proxy; + + if (_bt_is_le_discovering() == TRUE) { + BT_ERR("BT is already in LE discovering"); + return BLUETOOTH_ERROR_IN_PROGRESS; + } + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + if (!dbus_g_proxy_call(proxy, "StartLEDiscovery", NULL, + G_TYPE_INVALID, G_TYPE_INVALID)) { + BT_ERR("LE Discover start failed"); + return BLUETOOTH_ERROR_INTERNAL; + } + + is_le_discovering = TRUE; + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_stop_le_discovery(void) +{ + DBusGProxy *proxy; + + if (_bt_is_le_discovering() == FALSE) { + BT_ERR("BT is not in LE discovering"); + return BLUETOOTH_ERROR_NOT_IN_OPERATION; + } + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + if (!dbus_g_proxy_call(proxy, "StopLEDiscovery", NULL, + G_TYPE_INVALID, G_TYPE_INVALID)) { + BT_ERR("LE Discover stop failed"); + return BLUETOOTH_ERROR_INTERNAL; + } + + return BLUETOOTH_ERROR_NONE; +} + gboolean _bt_is_discovering(void) { return is_discovering; } -gboolean _bt_get_discovering_property(void) +gboolean _bt_is_le_discovering(void) +{ + return is_le_discovering; +} + +gboolean _bt_is_connectable(void) +{ + DBusGProxy *proxy; + GValue connectable_v = { 0 }; + GError *err = NULL; + gboolean is_connectable = FALSE; + + proxy = _bt_get_adapter_properties_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + if (!dbus_g_proxy_call(proxy, "Get", &err, + G_TYPE_STRING, BT_ADAPTER_INTERFACE, + G_TYPE_STRING, "Connectable", + G_TYPE_INVALID, + G_TYPE_VALUE, &connectable_v, + G_TYPE_INVALID)) { + if (err != NULL) { + BT_ERR("Getting property failed: [%s]\n", err->message); + g_error_free(err); + } + return BLUETOOTH_ERROR_INTERNAL; + } + + is_connectable = g_value_get_boolean(&connectable_v); + BT_INFO("Get connectable [%d]", is_connectable); + + return is_connectable; +} + +int _bt_set_connectable(gboolean is_connectable) +{ + DBusGProxy *proxy; + GValue connectable = { 0 }; + GError *error = NULL; + + if (__bt_is_factory_test_mode()) { + BT_ERR("Unable to set connectable in factory binary !!"); + return BLUETOOTH_ERROR_NOT_SUPPORT; + } + + proxy = _bt_get_adapter_properties_proxy(); + + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + g_value_init(&connectable, G_TYPE_BOOLEAN); + g_value_set_boolean(&connectable, is_connectable); + + dbus_g_proxy_call(proxy, "Set", &error, + G_TYPE_STRING, BT_ADAPTER_INTERFACE, + G_TYPE_STRING, "Connectable", + G_TYPE_VALUE, &connectable, + G_TYPE_INVALID, G_TYPE_INVALID); + + g_value_unset(&connectable); + if (error != NULL) { + BT_ERR("Connectable set err:[%s]", error->message); + g_error_free(error); + return BLUETOOTH_ERROR_INTERNAL; + } + + BT_INFO("Set connectable [%d]", is_connectable); + return BLUETOOTH_ERROR_NONE; +} + +gboolean _bt_get_discovering_property(bt_discovery_role_type_t discovery_type) { + DBusGProxy *proxy; GValue discovering_v = { 0 }; GError *err = NULL; + char *discovering_type = NULL; proxy = _bt_get_adapter_properties_proxy(); retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + if (discovery_type == DISCOVERY_ROLE_BREDR) + discovering_type = "Discovering"; + else if (discovery_type == DISCOVERY_ROLE_LE) + discovering_type = "LEDiscovering"; + if (!dbus_g_proxy_call(proxy, "Get", &err, G_TYPE_STRING, BT_ADAPTER_INTERFACE, - G_TYPE_STRING, "Discovering", + G_TYPE_STRING, discovering_type, G_TYPE_INVALID, G_TYPE_VALUE, &discovering_v, G_TYPE_INVALID)) { @@ -1283,6 +1937,7 @@ gboolean _bt_get_discovering_property(void) } return g_value_get_boolean(&discovering_v); + } unsigned int _bt_get_discoverable_timeout_property(void) @@ -1415,6 +2070,22 @@ static bluetooth_device_info_t *__bt_parse_device_info(DBusMessageIter *item_ite } dev_info->service_index = i; + } else if (strcasecmp(key, "ManufacturerDataLen") == 0) { + dbus_message_iter_get_basic(&iter_dict_val, + &dev_info->manufacturer_data.data_len); + } else if (strcasecmp(key, "ManufacturerData") == 0) { + DBusMessageIter manufacturer_iter; + int i = 0; + char byte = 0; + + dbus_message_iter_recurse(&iter_dict_val, &manufacturer_iter); + + while (dbus_message_iter_get_arg_type(&manufacturer_iter) == DBUS_TYPE_BYTE) { + dbus_message_iter_get_basic(&manufacturer_iter, &byte); + dev_info->manufacturer_data.data[i] = byte; + i++; + dbus_message_iter_next(&manufacturer_iter); + } } dbus_message_iter_next(&value_iter); @@ -1466,12 +2137,13 @@ static void __bt_extract_device_info(DBusMessageIter *msg_iter, dev_info = __bt_parse_device_info(&interface_iter); if (dev_info) { - if (dev_info->paired == TRUE) { - g_array_append_vals(*dev_list, dev_info, - sizeof(bluetooth_device_info_t)); - } else { - g_free(dev_info); - } + if (dev_info->paired == FALSE) + goto not_paired; + + g_array_append_vals(*dev_list, dev_info, + sizeof(bluetooth_device_info_t)); + + g_free(dev_info); } return; @@ -1481,10 +2153,15 @@ static void __bt_extract_device_info(DBusMessageIter *msg_iter, } BT_DBG("There is no device interface"); + +not_paired: + BT_DBG("Not paired"); + g_free(dev_info); } int _bt_get_bonded_devices(GArray **dev_list) { + BT_DBG("+"); DBusMessage *msg; DBusMessage *reply; DBusMessageIter reply_iter; @@ -1519,8 +2196,9 @@ int _bt_get_bonded_devices(GArray **dev_list) } if (dbus_message_iter_init(reply, &reply_iter) == FALSE) { - BT_ERR("Fail to iterate the reply"); - return BLUETOOTH_ERROR_INTERNAL; + BT_ERR("Fail to iterate the reply"); + dbus_message_unref(reply); + return BLUETOOTH_ERROR_INTERNAL; } dbus_message_iter_recurse(&reply_iter, &value_iter); @@ -1536,7 +2214,8 @@ int _bt_get_bonded_devices(GArray **dev_list) dbus_message_iter_next(&value_iter); } - + dbus_message_unref(reply); + BT_DBG("-"); return BLUETOOTH_ERROR_NONE; } @@ -1546,6 +2225,7 @@ int _bt_get_bonded_device_info(bluetooth_device_address_t *device_address, char *object_path = NULL; DBusGProxy *adapter_proxy; char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + int ret = BLUETOOTH_ERROR_NONE; BT_CHECK_PARAMETER(device_address, return); BT_CHECK_PARAMETER(dev_info, return); @@ -1557,16 +2237,12 @@ int _bt_get_bonded_device_info(bluetooth_device_address_t *device_address, object_path = _bt_get_device_object_path(address); - retv_if(object_path == NULL, BLUETOOTH_ERROR_NOT_FOUND); + retv_if(object_path == NULL, BLUETOOTH_ERROR_NOT_PAIRED); - if (__bt_get_bonded_device_info(object_path, - dev_info) != BLUETOOTH_ERROR_NONE) { - BT_ERR("Can't get the paired device path \n"); - g_free(object_path); - return BLUETOOTH_ERROR_INTERNAL; - } + ret = __bt_get_bonded_device_info(object_path, dev_info); g_free(object_path); - return BLUETOOTH_ERROR_NONE; + + return ret; } int _bt_get_timeout_value(int *timeout) @@ -1585,3 +2261,85 @@ int _bt_get_timeout_value(int *timeout) return BLUETOOTH_ERROR_NONE; } +int _bt_set_le_privacy(gboolean set_privacy) +{ + DBusGProxy *proxy; + GError *error = NULL; + int ret = BLUETOOTH_ERROR_NONE; + + if (__bt_is_factory_test_mode()) { + BT_ERR("Unable to set le privacy in factory binary !!"); + return BLUETOOTH_ERROR_NOT_SUPPORT; + } + + if (_bt_adapter_get_status() != BT_ACTIVATED && + _bt_adapter_get_le_status() != BT_LE_ACTIVATED) { + return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; + } + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call(proxy, "SetLePrivacy", &error, + G_TYPE_BOOLEAN, set_privacy, + G_TYPE_INVALID, G_TYPE_INVALID); + + if (error) { + BT_ERR("SetLePrivacy Failed :[%s]", error->message); + if (g_strrstr(error->message, BT_SERVICE_ERR_MSG_NOT_SUPPORTED)) + ret = BLUETOOTH_ERROR_NOT_SUPPORT; + else + ret = BLUETOOTH_ERROR_INTERNAL; + g_error_free(error); + return ret; + } + + BT_INFO("SetLePrivacy as %d", set_privacy); + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_set_manufacturer_data(bluetooth_manufacturer_data_t *m_data) +{ + DBusGProxy *proxy; + GError *error = NULL; + GArray *arr; + int i; + + BT_CHECK_PARAMETER(m_data, return); + + if (_bt_adapter_get_status() != BT_ACTIVATED && + _bt_adapter_get_le_status() != BT_LE_ACTIVATED) { + return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; + } + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + arr = g_array_new(TRUE, TRUE, sizeof(guint8)); + + for (i = 0; i < (m_data->data_len) + 2; i++) + g_array_append_vals(arr, &(m_data->data[i]), sizeof(guint8)); + + dbus_g_proxy_call(proxy, "SetManufacturerData", &error, + DBUS_TYPE_G_UCHAR_ARRAY, arr, + G_TYPE_INVALID, G_TYPE_INVALID); + + g_array_free(arr, TRUE); + + if (error) { + BT_ERR("SetManufacturerData Fail: %s", error->message); + g_error_free(error); + return BLUETOOTH_ERROR_INTERNAL; + } + + _bt_send_event(BT_ADAPTER_EVENT, + BLUETOOTH_EVENT_MANUFACTURER_DATA_CHANGED, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &m_data, m_data->data_len, + DBUS_TYPE_INVALID); + + BT_INFO("Set manufacturer data"); + + return BLUETOOTH_ERROR_NONE; +} diff --git a/bt-service/bt-service-agent.c b/bt-service/bt-service-agent.c old mode 100644 new mode 100755 index d48af2a..c0a4a91 --- a/bt-service/bt-service-agent.c +++ b/bt-service/bt-service-agent.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -22,8 +26,13 @@ #include #include #include +#include #include +#include + +#ifdef TIZEN_NETWORK_TETHERING_ENABLE #include +#endif #include "bt-internal-types.h" #include "bt-service-common.h" @@ -35,18 +44,11 @@ #include "bt-service-device.h" #include "bt-service-audio.h" -#if defined(LIBNOTIFY_SUPPORT) -#include "bt-popup.h" -#elif defined(LIBNOTIFICATION_SUPPORT) -#include "bt-service-agent-notification.h" -#else -#include -#endif - #define BT_APP_AUTHENTICATION_TIMEOUT 35 #define BT_APP_AUTHORIZATION_TIMEOUT 15 #define HFP_AUDIO_GATEWAY_UUID "0000111f-0000-1000-8000-00805f9b34fb" +#define HSP_AUDIO_GATEWAY_UUID "00001112-0000-1000-8000-00805f9b34fb" #define A2DP_UUID "0000110D-0000-1000-8000-00805F9B34FB" #define AVRCP_TARGET_UUID "0000110c-0000-1000-8000-00805f9b34fb" #define OPP_UUID "00001105-0000-1000-8000-00805f9b34fb" @@ -58,8 +60,13 @@ #define GN_UUID "00001117-0000-1000-8000-00805f9b34fb" #define BNEP_UUID "0000000f-0000-1000-8000-00805f9b34fb" #define HID_UUID "00001124-0000-1000-8000-00805f9b34fb" +#define SAP_UUID_OLD "a49eb41e-cb06-495c-9f4f-bb80a90cdf00" +#define SAP_UUID_NEW "a49eb41e-cb06-495c-9f4f-aa80a90cdf4a" #define BT_AGENT_OBJECT "/org/bluez/agent/frwk_agent" + +#define BT_AGENT_INTERFACE "org.bluez.Agent1" + #define BT_AGENT_SIGNAL_RFCOMM_AUTHORIZE "RfcommAuthorize" #define BT_AGENT_SIGNAL_OBEX_AUTHORIZE "ObexAuthorize" @@ -67,6 +74,9 @@ #define BT_PASSKEY_MAX_LENGTH 4 #define BT_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS 200 +#define BT_AGENT_SYSPOPUP_MAX_ATTEMPT 3 +#define BT_PAN_MAX_CONNECTION 4 +extern guint nap_connected_device_count; static int __bt_agent_is_auto_response(uint32_t dev_class, const gchar *address, const gchar *name); @@ -82,41 +92,217 @@ static void __bt_agent_release_memory(void) stack_trim(); } -static int __syspopup_launch(gpointer user_data) +static gboolean __bt_agent_system_popup_timer_cb(gpointer user_data) { int ret; - bundle *b = (bundle *) user_data; -#if defined(LIBNOTIFY_SUPPORT) - ret = notify_launch(b); -#elif defined(LIBNOTIFICATION_SUPPORT) - ret = notification_launch(b); -#else + static int retry_count; + bundle *b = (bundle *)user_data; + retv_if(user_data == NULL, FALSE); + + ++retry_count; + ret = syspopup_launch("bt-syspopup", b); -#endif - return ret; + if (ret < 0) { + BT_ERR("Sorry! Can't launch popup, ret=%d, Re-try[%d] time..", + ret, retry_count); + if (retry_count >= BT_AGENT_SYSPOPUP_MAX_ATTEMPT) { + BT_ERR("Sorry!! Max retry %d reached", retry_count); + bundle_free(b); + retry_count = 0; + return FALSE; + } + } else { + BT_DBG("Hurray!! Finally Popup launched"); + retry_count = 0; + bundle_free(b); + } + + return (ret < 0) ? TRUE : FALSE; } -static gboolean __bt_agent_system_popup_timer_cb(gpointer user_data) +#ifdef TIZEN_WEARABLE +static void __bt_unbond_cb(DBusGProxy *proxy, DBusGProxyCall *call, + gpointer user_data) { - int ret; - bundle *b = (bundle *) user_data; + GError *err = NULL; - if (NULL == b) { - BT_DBG("There is some problem with the user data..popup can not be created\n"); + dbus_g_proxy_end_call(proxy, call, &err, G_TYPE_INVALID); + if (err != NULL) { + BT_ERR("Error occured in RemoveBonding [%s]\n", err->message); + g_error_free(err); + return; + } + + BT_INFO("Unbonding is done"); + return; +} + +static gboolean __bt_unpair_device(void) +{ + GArray *device_list; + int no_of_device; + int i; + + device_list = g_array_new(FALSE, FALSE, sizeof(gchar)); + if (device_list == NULL) { + BT_ERR("g_array_new is failed"); + return FALSE; + } + + if (_bt_get_bonded_devices(&device_list) != BLUETOOTH_ERROR_NONE) { + BT_ERR("_bt_get_bonded_devices is failed"); + g_array_free(device_list, TRUE); return FALSE; } - ret = __syspopup_launch(b); - if (0 > ret) - BT_DBG("Sorry Can not launch popup\n"); - else - BT_DBG("Hurray Popup launched \n"); + no_of_device = device_list->len / sizeof(bluetooth_device_info_t); + for (i = 0; i < no_of_device; i++) { + DBusGProxy *adapter_proxy; + bluetooth_device_info_t info; + char addr[BT_ADDRESS_STRING_SIZE] = { 0 }; + char *device_path = NULL; + + info = g_array_index(device_list, bluetooth_device_info_t, i); + if (info.device_class.major_class == + BLUETOOTH_DEVICE_MAJOR_CLASS_AUDIO) + continue; + + adapter_proxy = _bt_get_adapter_proxy(); + if (!adapter_proxy) { + BT_ERR("adapter_proxy is NULL"); + g_array_free(device_list, TRUE); + return FALSE; + } + + _bt_convert_addr_type_to_string(addr, info.device_address.addr); + device_path = _bt_get_device_object_path(addr); + if (device_path == NULL) { + BT_ERR("device_path is NULL"); + g_array_free(device_list, TRUE); + return FALSE; + } - bundle_free(b); + if (!dbus_g_proxy_begin_call(adapter_proxy, "UnpairDevice", + (DBusGProxyCallNotify)__bt_unbond_cb, + NULL, NULL, + DBUS_TYPE_G_OBJECT_PATH, device_path, + G_TYPE_INVALID)) { + BT_ERR("RemoveBonding begin failed\n"); + g_array_free(device_list, TRUE); + return FALSE; + } + BT_INFO("unbonding %s is requested", addr); + + g_array_free(device_list, TRUE); + return TRUE; + } + + g_array_free(device_list, TRUE); return FALSE; } -static int __launch_system_popup(bt_agent_event_type_t event_type, +static DBusHandlerResult __bt_popup_event_filter(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + int response; + + BT_DBG("+"); + + if (msg == NULL) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (!dbus_message_is_signal(msg, "User.Bluetooth.syspopup", "ResetResponse")) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (!dbus_message_get_args(msg, NULL, + DBUS_TYPE_INT32, &response, + DBUS_TYPE_INVALID)) { + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + BT_DBG("response = %d", response); + + BT_DBG("-"); + return DBUS_HANDLER_RESULT_HANDLED; +} + +static void __bt_register_popup_event_signal(void) +{ + DBusError dbus_error; + DBusGConnection *gconn; + DBusConnection *conn; + + BT_DBG("+\n"); + + gconn = _bt_get_system_gconn(); + if (gconn == NULL) + return; + + conn = dbus_g_connection_get_connection(gconn); + if (conn == NULL) + return; + + dbus_connection_add_filter(conn, __bt_popup_event_filter, NULL, NULL); + + dbus_error_init(&dbus_error); + dbus_bus_add_match(conn, + "type='signal',interface='User.Bluetooth.syspopup'" + ",member='ResetResponse'", &dbus_error); + if (dbus_error_is_set(&dbus_error)) { + BT_ERR("Error: %s\n", dbus_error.message); + dbus_error_free(&dbus_error); + return; + } + + BT_DBG("-\n"); + return; +} + +static gboolean __is_reset_required(const gchar *address) +{ + GArray *device_list; + uint32_t no_of_device; + uint32_t i; + bluetooth_device_info_t info; + gboolean is_required = FALSE; + + device_list = g_array_new(FALSE, FALSE, sizeof(gchar)); + if (device_list == NULL) { + BT_ERR("g_array_new is failed"); + return FALSE; + } + + if (_bt_get_bonded_devices(&device_list) != BLUETOOTH_ERROR_NONE) { + BT_ERR("_bt_get_bonded_devices is failed"); + g_array_free(device_list, TRUE); + return FALSE; + } + + no_of_device = device_list->len / sizeof(bluetooth_device_info_t); + for (i = 0; i < no_of_device; i++) { + char addr[BT_ADDRESS_STRING_SIZE] = { 0 }; + + info = g_array_index(device_list, bluetooth_device_info_t, i); + + _bt_convert_addr_type_to_string(addr, info.device_address.addr); + if (g_strcmp0(address, addr) == 0) { + BT_DBG("This device is already in paired list"); + is_required = FALSE; + break; + } + + if (info.device_class.major_class != BLUETOOTH_DEVICE_MAJOR_CLASS_AUDIO) { + is_required = TRUE; + break; + } + } + g_array_free(device_list, TRUE); + + return is_required; +} +#endif + +int _bt_launch_system_popup(bt_agent_event_type_t event_type, const char *device_name, char *passkey, const char *filename, @@ -126,11 +312,11 @@ static int __launch_system_popup(bt_agent_event_type_t event_type, bundle *b; char event_str[BT_MAX_EVENT_STR_LENGTH + 1]; - BT_DBG("_bt_agent_launch_system_popup +"); - b = bundle_create(); - if (!b) + if (!b) { + BT_ERR("Launching system popup failed"); return -1; + } bundle_add(b, "device-name", device_name); bundle_add(b, "passkey", passkey); @@ -191,7 +377,19 @@ static int __launch_system_popup(bt_agent_event_type_t event_type, g_strlcpy(event_str, "message-request", sizeof(event_str)); break; +#ifdef TIZEN_WEARABLE + case BT_AGENT_EVENT_SYSTEM_RESET_REQUEST: + __bt_register_popup_event_signal(); + g_strlcpy(event_str, "system-reset-request", sizeof(event_str)); + break; +#endif + + case BT_AGENT_EVENT_LEGACY_PAIR_FAILED_FROM_REMOTE: + g_strlcpy(event_str, "remote-legacy-pair-failed", sizeof(event_str)); + break; + default: + BT_ERR("Invalid event type"); bundle_free(b); return -1; @@ -199,17 +397,17 @@ static int __launch_system_popup(bt_agent_event_type_t event_type, bundle_add(b, "event-type", event_str); - ret = __syspopup_launch(b); + ret = syspopup_launch("bt-syspopup", b); if (0 > ret) { - BT_DBG("Popup launch failed...retry %d\n", ret); + BT_ERR("Popup launch failed...retry %d", ret); + g_timeout_add(BT_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS, - (GSourceFunc) __bt_agent_system_popup_timer_cb, - b); + (GSourceFunc)__bt_agent_system_popup_timer_cb, b); } else { bundle_free(b); } - BT_DBG("_bt_agent_launch_system_popup -%d", ret); + BT_INFO("_bt_agent_launch_system_popup"); return 0; } @@ -222,16 +420,15 @@ static gboolean __pincode_request(GapAgent *agent, DBusGProxy *device) const gchar *name; GError *error = NULL; - BT_DBG("+\n"); + BT_INFO("+"); dbus_g_proxy_call(device, "GetAll", &error, G_TYPE_STRING, BT_DEVICE_INTERFACE, G_TYPE_INVALID, - dbus_g_type_get_map("GHashTable", - G_TYPE_STRING, G_TYPE_VALUE), - &hash, G_TYPE_INVALID); + dbus_g_type_get_map("GHashTable", G_TYPE_STRING, + G_TYPE_VALUE), &hash, G_TYPE_INVALID); if (error) { - BT_DBG("error in GetAll [%s]\n", error->message); + BT_ERR("error in GetBasicProperties [%s]\n", error->message); g_error_free(error); gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL); @@ -253,7 +450,9 @@ static gboolean __pincode_request(GapAgent *agent, DBusGProxy *device) if (!name) name = address; - if (__bt_agent_is_auto_response(device_class, address, name)) { + if (_bt_is_device_creating() == TRUE && + _bt_is_bonding_device_address(address) == TRUE && + __bt_agent_is_auto_response(device_class, address, name)) { /* Use Fixed PIN "0000" for basic pairing*/ _bt_set_autopair_status_in_bonding_info(TRUE); gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT, "0000", @@ -271,11 +470,11 @@ static gboolean __pincode_request(GapAgent *agent, DBusGProxy *device) gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT, str_passkey, NULL); - __launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST, + _bt_launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST, name, str_passkey, NULL, _gap_agent_get_path(agent)); } else { - __launch_system_popup(BT_AGENT_EVENT_PIN_REQUEST, name, NULL, + _bt_launch_system_popup(BT_AGENT_EVENT_PIN_REQUEST, name, NULL, NULL, _gap_agent_get_path(agent)); } @@ -283,39 +482,34 @@ done: g_hash_table_destroy(hash); __bt_agent_release_memory(); - BT_DBG("-\n"); + BT_DBG("-"); return TRUE; } static gboolean __passkey_request(GapAgent *agent, DBusGProxy *device) { - uint32_t device_class; GHashTable *hash = NULL; GValue *value; const gchar *address; const gchar *name; GError *error = NULL; - BT_DBG("+\n"); + BT_DBG("+"); dbus_g_proxy_call(device, "GetAll", &error, G_TYPE_STRING, BT_DEVICE_INTERFACE, G_TYPE_INVALID, - dbus_g_type_get_map("GHashTable", - G_TYPE_STRING, G_TYPE_VALUE), - &hash, G_TYPE_INVALID); + dbus_g_type_get_map("GHashTable", G_TYPE_STRING, + G_TYPE_VALUE), &hash, G_TYPE_INVALID); if (error) { - BT_DBG("error in GetAll [%s]\n", error->message); + BT_ERR("error in GetBasicProperties [%s]\n", error->message); g_error_free(error); gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL); goto done; } - value = g_hash_table_lookup(hash, "Class"); - device_class = value ? g_value_get_uint(value) : 0; - value = g_hash_table_lookup(hash, "Address"); address = value ? g_value_get_string(value) : NULL; if (!address) { @@ -328,13 +522,13 @@ static gboolean __passkey_request(GapAgent *agent, DBusGProxy *device) if (!name) name = address; - __launch_system_popup(BT_AGENT_EVENT_PASSKEY_REQUEST, name, NULL, NULL, + _bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_REQUEST, name, NULL, NULL, _gap_agent_get_path(agent)); done: __bt_agent_release_memory(); g_hash_table_destroy(hash); - BT_DBG("-\n"); + BT_DBG("-"); return TRUE; } @@ -349,16 +543,15 @@ static gboolean __display_request(GapAgent *agent, DBusGProxy *device, GError *error = NULL; char *str_passkey; - BT_DBG("+\n"); + BT_DBG("+"); dbus_g_proxy_call(device, "GetAll", &error, G_TYPE_STRING, BT_DEVICE_INTERFACE, G_TYPE_INVALID, dbus_g_type_get_map("GHashTable", G_TYPE_STRING, - G_TYPE_VALUE), - &hash, G_TYPE_INVALID); + G_TYPE_VALUE), &hash, G_TYPE_INVALID); if (error) { - BT_DBG("error in GetAll [%s]\n", error->message); + BT_ERR("error in GetBasicProperties [%s]\n", error->message); g_error_free(error); gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL); @@ -379,7 +572,7 @@ static gboolean __display_request(GapAgent *agent, DBusGProxy *device, str_passkey = g_strdup_printf("%d", passkey); - __launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST, name, + _bt_launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST, name, str_passkey, NULL, _gap_agent_get_path(agent)); @@ -388,7 +581,7 @@ static gboolean __display_request(GapAgent *agent, DBusGProxy *device, done: __bt_agent_release_memory(); g_hash_table_destroy(hash); - BT_DBG("-\n"); + BT_DBG("-"); return TRUE; } @@ -396,7 +589,6 @@ done: static gboolean __confirm_request(GapAgent *agent, DBusGProxy *device, guint passkey) { - uint32_t device_class; GHashTable *hash = NULL; GValue *value; const gchar *address; @@ -404,7 +596,9 @@ static gboolean __confirm_request(GapAgent *agent, DBusGProxy *device, GError *error = NULL; char str_passkey[7]; - BT_DBG("+ passkey[%.6d]\n", passkey); + BT_DBG("+ passkey[%.6d]", passkey); + + snprintf(str_passkey, sizeof(str_passkey), "%.6d", passkey); dbus_g_proxy_call(device, "GetAll", &error, G_TYPE_STRING, BT_DEVICE_INTERFACE, @@ -413,16 +607,13 @@ static gboolean __confirm_request(GapAgent *agent, DBusGProxy *device, G_TYPE_VALUE), &hash, G_TYPE_INVALID); if (error) { - BT_DBG("error in GetAll [%s]\n", error->message); + BT_ERR("error in GetBasicProperties [%s]", error->message); g_error_free(error); gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL); goto done; } - value = g_hash_table_lookup(hash, "Class"); - device_class = value ? g_value_get_uint(value) : 0; - value = g_hash_table_lookup(hash, "Address"); address = value ? g_value_get_string(value) : NULL; if (!address) { @@ -435,16 +626,44 @@ static gboolean __confirm_request(GapAgent *agent, DBusGProxy *device, if (!name) name = address; - snprintf(str_passkey, sizeof(str_passkey), "%.6d", passkey); +#ifdef TIZEN_WEARABLE + uint32_t device_class = 0x00; + uint32_t major_class; + + value = g_hash_table_lookup(hash, "Class"); + device_class = value ? g_value_get_uint(value) : 0; + + BT_INFO("COD : 0x%X", device_class); + + major_class = (device_class & 0x1f00) >> 8; - __launch_system_popup(BT_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name, + if (major_class == BLUETOOTH_DEVICE_MAJOR_CLASS_AUDIO) { + BT_DBG("Audio device. Launch passkey pop-up"); + _bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name, + str_passkey, NULL, _gap_agent_get_path(agent)); + goto done; + } + + if (__is_reset_required(address)) { + BT_INFO("Launch system reset pop-up"); + _bt_launch_system_popup(BT_AGENT_EVENT_SYSTEM_RESET_REQUEST, name, + NULL, NULL, _gap_agent_get_path(agent)); + } else { + BT_INFO("Launch passkey pop-up"); + _bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name, + str_passkey, NULL, _gap_agent_get_path(agent)); + } +#else + _bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name, str_passkey, NULL, _gap_agent_get_path(agent)); +#endif + done: __bt_agent_release_memory(); g_hash_table_destroy(hash); - BT_DBG("-\n"); + BT_DBG("-"); return TRUE; } @@ -453,11 +672,7 @@ static gboolean __pairing_cancel_request(GapAgent *agent, const char *address) { BT_DBG("On Going Pairing is cancelled by remote\n"); - gap_agent_reply_pin_code(agent, GAP_AGENT_CANCEL, "", NULL); - -#if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT) syspopup_destroy_all(); -#endif __bt_agent_release_memory(); @@ -477,16 +692,18 @@ static gboolean __authorize_request(GapAgent *agent, DBusGProxy *device, GValue *value; const gchar *address; const gchar *name; - bool enabled; gboolean trust; gboolean paired; +#ifdef TIZEN_NETWORK_TETHERING_ENABLE + bool enabled; tethering_h tethering = NULL; + int ret = TETHERING_ERROR_NONE; +#endif GError *error = NULL; - int ret; int result = BLUETOOTH_ERROR_NONE; int request_type = BT_AGENT_EVENT_AUTHORIZE_REQUEST; - BT_DBG("+\n"); + BT_DBG("+"); /* Check if already Media connection exsist */ if (!strcasecmp(uuid, A2DP_UUID)) { @@ -495,7 +712,7 @@ static gboolean __authorize_request(GapAgent *agent, DBusGProxy *device, ret = __a2dp_authorize_request_check(); if (ret) { - BT_DBG("Already one A2DP device connected \n"); + BT_ERR("Already one A2DP device connected \n"); gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL); goto done; @@ -504,9 +721,14 @@ static gboolean __authorize_request(GapAgent *agent, DBusGProxy *device, /* Check completed */ if (!strcasecmp(uuid, HFP_AUDIO_GATEWAY_UUID) || + !strcasecmp(uuid, HSP_AUDIO_GATEWAY_UUID) || + !strcasecmp(uuid, HFP_HS_UUID) || + !strcasecmp(uuid, HSP_HS_UUID) || !strcasecmp(uuid, A2DP_UUID) || - !strcasecmp(uuid, HID_UUID) || - !strcasecmp(uuid, AVRCP_TARGET_UUID)) { + !strcasecmp(uuid, HID_UUID) || + !strcasecmp(uuid, SAP_UUID_OLD) || + !strcasecmp(uuid, SAP_UUID_NEW) || + !strcasecmp(uuid, AVRCP_TARGET_UUID)) { BT_DBG("Auto accept authorization for audio device (HFP, A2DP, AVRCP) [%s]", uuid); gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT, NULL); @@ -519,6 +741,13 @@ static gboolean __authorize_request(GapAgent *agent, DBusGProxy *device, !strcasecmp(uuid, BNEP_UUID)) { BT_DBG("Network connection request: %s", uuid); +#ifdef TIZEN_NETWORK_TETHERING_ENABLE + if (nap_connected_device_count >= + BT_PAN_MAX_CONNECTION) { + BT_ERR("Max connection exceeded"); + goto fail; + } + int ret; ret = tethering_create(&tethering); if (ret != TETHERING_ERROR_NONE) { @@ -538,25 +767,27 @@ static gboolean __authorize_request(GapAgent *agent, DBusGProxy *device, BT_ERR("BT tethering is not enabled"); goto fail; } +#endif gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT, NULL); goto done; +#ifdef TIZEN_NETWORK_TETHERING_ENABLE fail: gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL); goto done; +#endif } dbus_g_proxy_call(device, "GetAll", &error, G_TYPE_STRING, BT_DEVICE_INTERFACE, G_TYPE_INVALID, dbus_g_type_get_map("GHashTable", G_TYPE_STRING, - G_TYPE_VALUE), - &hash, G_TYPE_INVALID); + G_TYPE_VALUE), &hash, G_TYPE_INVALID); if (error) { - BT_DBG("error in GetAll [%s]\n", error->message); + BT_ERR("error in GetBasicProperties [%s]\n", error->message); g_error_free(error); gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL); @@ -581,13 +812,13 @@ fail: value = g_hash_table_lookup(hash, "Paired"); paired = value ? g_value_get_boolean(value) : 0; if ((paired == FALSE) && (trust == FALSE)) { - BT_DBG("No paired & No trusted device"); + BT_ERR("No paired & No trusted device"); gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL); goto done; } - BT_DBG("Authorization request for device [%s] Service:[%s]\n", address, + BT_INFO("Authorization request for device [%s] Service:[%s]\n", address, uuid); if (strcasecmp(uuid, OPP_UUID) == 0 && @@ -605,11 +836,9 @@ fail: if (_gap_agent_exist_osp_server(agent, BT_RFCOMM_SERVER, (char *)uuid) == TRUE) { - bt_rfcomm_server_info_t *server_info; - - server_info = _bt_rfcomm_get_server_info_using_uuid((char *)uuid); - retv_if(server_info == NULL, TRUE); - retv_if(server_info->server_type != BT_CUSTOM_SERVER, TRUE); + bt_agent_osp_server_t *osp_serv; + osp_serv = _gap_agent_get_osp_server(agent, + BT_RFCOMM_SERVER, (char *)uuid); _bt_send_event(BT_RFCOMM_SERVER_EVENT, BLUETOOTH_EVENT_RFCOMM_AUTHORIZE, @@ -617,7 +846,8 @@ fail: DBUS_TYPE_STRING, &address, DBUS_TYPE_STRING, &uuid, DBUS_TYPE_STRING, &name, - DBUS_TYPE_INT16, &server_info->control_fd, + DBUS_TYPE_STRING, &osp_serv->path, + DBUS_TYPE_INT16, &osp_serv->fd, DBUS_TYPE_INVALID); goto done; @@ -631,11 +861,11 @@ fail: request_type = BT_AGENT_EVENT_MAP_REQUEST; if (trust) { - BT_DBG("Trusted device, so authorize\n"); + BT_INFO("Trusted device, so authorize\n"); gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT, NULL); } else { - __launch_system_popup(request_type, name, NULL, NULL, + _bt_launch_system_popup(request_type, name, NULL, NULL, _gap_agent_get_path(agent)); } @@ -643,7 +873,7 @@ done: __bt_agent_release_memory(); g_hash_table_destroy(hash); - BT_DBG("-\n"); + BT_DBG("-"); return TRUE; } @@ -655,9 +885,7 @@ static gboolean __authorization_cancel_request(GapAgent *agent, gap_agent_reply_authorize(agent, GAP_AGENT_CANCEL, NULL); -#if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT) syspopup_destroy_all(); -#endif __bt_agent_release_memory(); @@ -677,8 +905,13 @@ void _bt_destroy_agent(void *agent) void* _bt_create_agent(const char *path, gboolean adapter) { GAP_AGENT_FUNC_CB func_cb; + DBusGProxy *adapter_proxy; GapAgent* agent; + adapter_proxy = _bt_get_adapter_proxy(); + if (!adapter_proxy) + return NULL; + func_cb.pincode_func = __pincode_request; func_cb.display_func = __display_request; func_cb.passkey_func = __passkey_request; @@ -689,7 +922,7 @@ void* _bt_create_agent(const char *path, gboolean adapter) agent = _gap_agent_new(); - _gap_agent_setup_dbus(agent, &func_cb, path); + _gap_agent_setup_dbus(agent, &func_cb, path, adapter_proxy); if (adapter) { if (!_gap_agent_register(agent)) { @@ -701,13 +934,14 @@ void* _bt_create_agent(const char *path, gboolean adapter) return agent; } -gboolean _bt_agent_register_osp_server(const gint type, const char *uuid) +gboolean _bt_agent_register_osp_server(const gint type, + const char *uuid, char *path, int fd) { void *agent = _bt_get_adapter_agent(); if (!agent) return FALSE; - return _gap_agent_register_osp_server(agent, type, uuid); + return _gap_agent_register_osp_server(agent, type, uuid, path, fd); } @@ -733,11 +967,39 @@ gboolean _bt_agent_reply_authorize(gboolean accept) return gap_agent_reply_authorize(agent, accept_val, NULL); } -gboolean _bt_agent_is_canceled(void *agent) +gboolean _bt_agent_is_canceled(void) { + void *agent = _bt_get_adapter_agent(); + if (!agent) + return FALSE; + return _gap_agent_is_canceled(agent); } +void _bt_agent_set_canceled(gboolean value) +{ + void *agent = _bt_get_adapter_agent(); + if (!agent) + return; + + return _gap_agent_set_canceled(agent, value); +} + +int _bt_agent_reply_cancellation(void) +{ + void *agent = _bt_get_adapter_agent(); + + if (!agent) + return BLUETOOTH_ERROR_INTERNAL; + + if (gap_agent_reply_confirmation(agent, GAP_AGENT_CANCEL, NULL) != TRUE) { + BT_ERR("Fail to reply agent"); + return BLUETOOTH_ERROR_INTERNAL; + } + + return BLUETOOTH_ERROR_NONE; +} + static gboolean __bt_agent_is_hid_keyboard(uint32_t dev_class) { switch ((dev_class & 0x1f00) >> 8) { @@ -757,7 +1019,7 @@ static gboolean __bt_agent_find_device_by_address_exactname(char *buffer, const char *address) { char *pch; - char *last; + char *last = NULL; pch = strtok_r(buffer, "= ,", &last); @@ -777,7 +1039,7 @@ static gboolean __bt_agent_find_device_by_partial_name(char *buffer, const char *partial_name) { char *pch; - char *last; + char *last = NULL; pch = strtok_r(buffer, "= ,", &last); @@ -803,12 +1065,12 @@ static gboolean __bt_agent_is_device_blacklist(const char *address, long size; size_t result; - BT_DBG("+ \n"); + BT_DBG("+"); fp = fopen(BT_AGENT_AUTO_PAIR_BLACKLIST_FILE, "r"); if (fp == NULL) { - BT_DBG("fopen failed \n"); + BT_ERR("Unable to open blacklist file"); return FALSE; } @@ -826,18 +1088,18 @@ static gboolean __bt_agent_is_device_blacklist(const char *address, result = fread((char *)buffer, 1, size, fp); fclose(fp); if (result != size) { - BT_DBG("Read Error\n"); + BT_ERR("Read Error"); g_free(buffer); return FALSE; } - BT_DBG("Buffer = %s\n", buffer); + BT_DBG("Buffer = %s", buffer); lines = g_strsplit_set(buffer, BT_AGENT_NEW_LINE, 0); g_free(buffer); if (lines == NULL) { - BT_DBG("No lines in the file \n"); + BT_ERR("No lines in the file"); return FALSE; } @@ -854,12 +1116,16 @@ static gboolean __bt_agent_is_device_blacklist(const char *address, if (__bt_agent_find_device_by_partial_name(lines[i], name)) goto done; + if (g_str_has_prefix(lines[i], "KeyboardAutoPair")) + if (__bt_agent_find_device_by_address_exactname( + lines[i], address)) + goto done; } g_strfreev(lines); - BT_DBG("- \n"); + BT_DBG("-"); return FALSE; done: - BT_DBG("Found the device\n"); + BT_DBG("Found the device"); g_strfreev(lines); return TRUE; } @@ -868,6 +1134,7 @@ static gboolean __bt_agent_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_LOWER_ADDRESS_LENGTH]; BT_DBG("bt_agent_is_headset_class, %d +", dev_class); @@ -897,9 +1164,29 @@ static gboolean __bt_agent_is_auto_response(uint32_t dev_class, 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_agent_is_device_blacklist(lap_address, name) != TRUE) { + BT_DBG("Device is not black listed\n"); + return FALSE; + } else { + BT_ERR("Device is black listed\n"); + return TRUE; + } + } } - if (!is_headset) + if ((!is_headset) && (!is_mouse)) return FALSE; /* Get the LAP(Lower Address part) */ @@ -909,7 +1196,7 @@ static gboolean __bt_agent_is_auto_response(uint32_t dev_class, BT_DBG("Address 3 byte = %s\n", lap_address); if (__bt_agent_is_device_blacklist(lap_address, name)) { - BT_DBG("Device is black listed\n"); + BT_ERR("Device is black listed\n"); return FALSE; } @@ -936,7 +1223,8 @@ static int __bt_agent_generate_passkey(char *passkey, int size) for (i = 0; i < size; i++) { len = read(random_fd, &value, sizeof(value)); - passkey[i] = '0' + (value % 10); + if (len > 0) + passkey[i] = '0' + (value % 10); } close(random_fd); diff --git a/bt-service/bt-service-audio.c b/bt-service/bt-service-audio.c old mode 100644 new mode 100755 index f9d287b..b888c3a --- a/bt-service/bt-service-audio.c +++ b/bt-service/bt-service-audio.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -22,9 +26,7 @@ #include #include #include -#if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT) #include -#endif #include "bluetooth-api.h" #include "bt-internal-types.h" @@ -32,9 +34,18 @@ #include "bt-service-audio.h" #include "bt-service-adapter.h" #include "bt-service-common.h" +#include "bt-service-device.h" #include "bt-service-event.h" #include "bt-service-util.h" +#include "bt-service-headset-connection.h" + +#ifdef TIZEN_SUPPORT_DUAL_HF +#ifdef TIZEN_WEARABLE +#define VCONF_KEY_BT_HOST_BT_MAC_ADDR "db/wms/host_bt_mac" +#endif +#endif + typedef struct { unsigned int type; int device_state; @@ -45,11 +56,16 @@ static GList *g_connected_list; static bt_headset_wait_t *g_wait_data; +static bt_audio_function_data_t *pdata; + static void __bt_remove_device_from_wait_list(); static void __bt_free_wait_data(); -static void __bt_audio_request_cb(DBusGProxy *proxy, DBusGProxyCall *call, +static gboolean __bt_device_support_uuid(char *remote_address, + bt_audio_type_t type); + +static void __bt_hf_request_cb(DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) { GError *g_error = NULL; @@ -80,12 +96,138 @@ static void __bt_audio_request_cb(DBusGProxy *proxy, DBusGProxyCall *call, if (g_error == NULL) goto dbus_return; - BT_ERR("Audio Connect Dbus Call Error: %s\n", g_error->message); + BT_ERR("HFG request Dbus Call Error: %s\n", g_error->message); + + result = BLUETOOTH_ERROR_INTERNAL; + +dbus_return: + if (req_info->context == NULL) + goto done; + + out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar)); + out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar)); + + g_array_append_vals(out_param1, func_data->address, + BT_ADDRESS_STR_LEN); + g_array_append_vals(out_param2, &result, sizeof(int)); + + dbus_g_method_return(req_info->context, out_param1, out_param2); + + g_array_free(out_param1, TRUE); + g_array_free(out_param2, TRUE); + + _bt_delete_request_list(req_info->req_id); +done: + if (g_error) + g_error_free(g_error); + + if (func_data) { + g_free(func_data->address); + g_free(func_data); + } +} + +void _bt_audio_check_pending_connect() +{ + BT_DBG("+"); + bluetooth_device_address_t device_address; + + if (pdata == NULL) + return; + + if (pdata->pending == BT_PENDING_CONNECT) { + + _bt_convert_addr_string_to_type(device_address.addr, + pdata->address); + + _bt_audio_connect(pdata->req_id, + BT_AUDIO_A2DP, + &device_address, + pdata->out_param); + + g_free(pdata->address); + g_free(pdata); + pdata = NULL; + } + + BT_DBG("-"); + return; +} + +static void __bt_audio_request_cb(DBusGProxy *proxy, DBusGProxyCall *call, + gpointer user_data) +{ + GError *g_error = NULL; + GArray *out_param1 = NULL; + GArray *out_param2 = NULL; + int result = BLUETOOTH_ERROR_NONE; + + bt_audio_function_data_t *func_data; + + request_info_t *req_info; + + dbus_g_proxy_end_call(proxy, call, &g_error, G_TYPE_INVALID); + + g_object_unref(proxy); + + func_data = user_data; + + if (func_data == NULL) { + /* Send reply */ + BT_ERR("func_data == NULL"); + goto done; + } + + if (func_data->pending != BT_PENDING_NONE && g_error == NULL) { + + bluetooth_device_address_t device_address; + _bt_convert_addr_string_to_type(device_address.addr, + func_data->address); + + if (func_data->pending == BT_PENDING_CONNECT) { + + if (__bt_device_support_uuid(func_data->address, + BT_AUDIO_A2DP)) { + + pdata = g_new0(bt_audio_function_data_t, 1); + pdata->req_id = func_data->req_id; + pdata->out_param = func_data->out_param; + pdata->address = strdup(func_data->address); + pdata->pending = func_data->pending; + } else + goto check_req_info; + + } else { + + if (_bt_is_service_connected(func_data->address + , BT_AUDIO_A2DP)) { + _bt_audio_disconnect(func_data->req_id, + BT_AUDIO_A2DP, + &device_address, + func_data->out_param); + } else + goto check_req_info; + } + + goto done; + } + +check_req_info: + req_info = _bt_get_request_info(func_data->req_id); + if (req_info == NULL) { + BT_ERR("req_info == NULL"); + goto done; + } + + if (g_error == NULL) + goto dbus_return; + + BT_ERR("Audio Connect/Disconnect Dbus Call Error: %s\n", g_error->message); result = BLUETOOTH_ERROR_INTERNAL; /* Remove the device from the list */ - _bt_remove_headset_from_list(BT_AUDIO_ALL, func_data->address); + _bt_remove_headset_from_list(func_data->type, func_data->address); /* Error, check if any waiting device is there */ if (g_wait_data == NULL) @@ -94,21 +236,23 @@ static void __bt_audio_request_cb(DBusGProxy *proxy, DBusGProxyCall *call, if (g_strcmp0(g_wait_data->address, func_data->address) != 0) { bluetooth_device_address_t device_address; _bt_convert_addr_string_to_type(device_address.addr, - g_wait_data->address); + g_wait_data->address); _bt_audio_connect(g_wait_data->req_id, g_wait_data->type, &device_address, g_wait_data->out_param1); } /* Event will be sent by the event reciever */ dbus_return: - if (req_info->context == NULL) + if (req_info->context == NULL) { + BT_DBG("req_info->context is NULL"); goto done; + } out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar)); out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar)); g_array_append_vals(out_param1, func_data->address, - BT_ADDRESS_STR_LEN); + BT_ADDRESS_STR_LEN); g_array_append_vals(out_param2, &result, sizeof(int)); dbus_g_method_return(req_info->context, out_param1, out_param2); @@ -135,6 +279,7 @@ static char *__bt_get_audio_path(bluetooth_device_address_t *address) DBusGProxy *audio_proxy; DBusGProxy *adapter_proxy; DBusGConnection *g_conn; + GError *error = NULL; retv_if(address == NULL, NULL); @@ -146,14 +291,23 @@ static char *__bt_get_audio_path(bluetooth_device_address_t *address) _bt_convert_addr_type_to_string(addr_str, address->addr); - object_path = _bt_get_device_object_path(addr_str); + dbus_g_proxy_call(adapter_proxy, "FindDevice", + &error, G_TYPE_STRING, addr_str, + G_TYPE_INVALID, DBUS_TYPE_G_OBJECT_PATH, + &object_path, G_TYPE_INVALID); + + if (error != NULL) { + BT_ERR("Failed to Find device: %s\n", error->message); + g_error_free(error); + return NULL; + } - retv_if(object_path == NULL, BLUETOOTH_ERROR_NOT_FOUND); + retv_if(object_path == NULL, NULL); audio_proxy = dbus_g_proxy_new_for_name(g_conn, - BT_BLUEZ_NAME, - object_path, - BT_HFP_AGENT_INTERFACE); + BT_BLUEZ_NAME, + object_path, + BT_HEADSET_INTERFACE); retv_if(audio_proxy == NULL, NULL); @@ -174,11 +328,12 @@ static char *__bt_get_connected_audio_path(void) device_list = g_array_new(FALSE, FALSE, sizeof(gchar)); if (_bt_get_bonded_devices(&device_list) - != BLUETOOTH_ERROR_NONE) { + != BLUETOOTH_ERROR_NONE) { g_array_free(device_list, TRUE); return NULL; } + size = device_list->len; size = (device_list->len) / sizeof(bluetooth_device_info_t); for (i = 0; i < size; i++) { @@ -224,10 +379,10 @@ static void __bt_remove_device_from_wait_list() out_param_1 = g_array_new(FALSE, FALSE, sizeof(gchar)); out_param_2 = g_array_new(FALSE, FALSE, sizeof(gchar)); g_array_append_vals(out_param_1, g_wait_data->address, - BT_ADDRESS_STR_LEN); + BT_ADDRESS_STR_LEN); g_array_append_vals(out_param_2, &result, sizeof(int)); dbus_g_method_return(req_info->context, - out_param_1, out_param_2); + out_param_1, out_param_2); g_array_free(out_param_1, TRUE); g_array_free(out_param_2, TRUE); _bt_delete_request_list(g_wait_data->req_id); @@ -238,8 +393,6 @@ static void __bt_set_headset_disconnection_type(const char *address) bt_connected_headset_data_t *connected_device; GList *node; - BT_DBG("__bt_set_headset_disconnection_type \n"); - node = g_list_first(g_connected_list); while (node != NULL) { connected_device = node->data; @@ -255,8 +408,6 @@ gboolean _bt_is_headset_type_connected(int type, char *address) { GList *node; - BT_DBG("_bt_is_headset_type_connected \n"); - node = g_list_first(g_connected_list); while (node != NULL) { bt_connected_headset_data_t *connected_device = node->data; @@ -273,20 +424,78 @@ gboolean _bt_is_headset_type_connected(int type, char *address) return FALSE; } -static gboolean __bt_is_headset_connected(int type, int req_id, +#ifdef TIZEN_SUPPORT_DUAL_HF +gboolean __bt_is_companion_device(const char *addr) +{ +#ifdef TIZEN_WEARABLE + char *host_device_address = NULL; + host_device_address = vconf_get_str(VCONF_KEY_BT_HOST_BT_MAC_ADDR); + + if (!host_device_address) { + BT_INFO("Failed to get a companion device address"); + return FALSE; + } + + if (g_strcmp0(host_device_address, addr) == 0) { + BT_INFO("addr[%s] is companion device", addr); + return TRUE; + } + + return FALSE; +#else + /* TODO : Need to add companion device check condition for Phone models */ + return FALSE; +#endif +} +#endif + +static int __bt_is_headset_connected(int type, int req_id, const char *address, GArray **out_param1) { - gboolean connected; + gboolean connected = FALSE; char connected_address[BT_ADDRESS_STRING_SIZE + 1]; bluetooth_device_address_t device_address; - - BT_DBG("__bt_is_headset_connected \n"); + bt_connected_headset_data_t *connected_device = NULL; +#ifdef TIZEN_SUPPORT_DUAL_HF + gboolean is_companion_device = FALSE; +#endif /* Check if any other headset is connected */ - connected = _bt_is_headset_type_connected(type, connected_address); + GList *node = NULL;; + + node = g_list_first(g_connected_list); + while (node != NULL) { + connected_device = node->data; + if ((connected_device->type & type) == type) { + g_strlcpy(connected_address, connected_device->device_address, + BT_ADDRESS_STRING_SIZE + 1); +#ifdef TIZEN_SUPPORT_DUAL_HF + is_companion_device = __bt_is_companion_device(connected_address); + BT_INFO(" is_companion_device[%d]", is_companion_device); + + if (!is_companion_device) { + connected = TRUE; + break; + } +#else + connected = TRUE; + break; +#endif + } + node = g_list_next(node); + } if (!connected) - return FALSE; + return BLUETOOTH_ERROR_NOT_CONNECTED; + + BT_DBG("connected headset %s", connected_address); + + if (g_strcmp0(connected_address, address) == 0) + return BLUETOOTH_ERROR_ALREADY_CONNECT; +#ifdef TIZEN_SUPPORT_DUAL_HF + else if (TRUE == __bt_is_companion_device(address)) + return BLUETOOTH_ERROR_NOT_CONNECTED; +#endif /* If already one device is waiting, remove current waiting device and add new */ if (g_wait_data != NULL) { @@ -310,8 +519,8 @@ static gboolean __bt_is_headset_connected(int type, int req_id, /* Convert BD adress from string type */ _bt_convert_addr_string_to_type(device_address.addr, connected_address); - _bt_audio_disconnect(0, type, &device_address, NULL); - return TRUE; + _bt_audio_disconnect(0, connected_device->type & type, &device_address, NULL); + return BLUETOOTH_ERROR_NONE; } void _bt_set_audio_wait_data_flag(gboolean flag) @@ -326,6 +535,12 @@ bt_headset_wait_t *_bt_get_audio_wait_data(void) return g_wait_data; } +void _bt_rel_wait_data(void) +{ + BT_DBG("_bt_rel_wait_data \n"); + __bt_free_wait_data(); +} + void _bt_add_headset_to_list(int type, int status, const char *address) { bt_connected_headset_data_t *connected_device; @@ -340,7 +555,8 @@ void _bt_add_headset_to_list(int type, int status, const char *address) if (g_strcmp0(device->device_address, address) == 0) { BT_DBG("Address match, update connection type \n"); - device->type |= type; + if (status == BT_STATE_CONNECTED) + device->type |= type; device->device_state = status; return; } @@ -348,13 +564,34 @@ void _bt_add_headset_to_list(int type, int status, const char *address) } connected_device = g_malloc0(sizeof(bt_connected_headset_data_t)); - connected_device->type |= type; connected_device->device_state = status; + if (status == BT_STATE_CONNECTED) + connected_device->type |= type; g_strlcpy(connected_device->device_address, address, - sizeof(connected_device->device_address)); + sizeof(connected_device->device_address)); g_connected_list = g_list_append(g_connected_list, connected_device); } +int _bt_get_device_state_from_list(int type, const char *address) +{ + GList *node; + bt_connected_headset_data_t *device; + + BT_DBG("+"); + node = g_list_first(g_connected_list); + while (node != NULL) { + device = (bt_connected_headset_data_t *)node->data; + if (g_strcmp0(device->device_address, address) == 0) { + BT_DBG("Device found"); + return device->device_state; + } + node = g_list_next(node); + } + + BT_DBG("Device not found"); + return BLUETOOTH_ERROR_INTERNAL; +} + void _bt_remove_headset_from_list(int type, const char *address) { GList *node; @@ -387,6 +624,10 @@ void _bt_remove_headset_from_list(int type, const char *address) if (connected_device->type & BT_AUDIO_ALL) connected_device->type &= ~(BT_AUDIO_ALL); break; + case BT_AVRCP: + if (connected_device->type & BT_AVRCP) + connected_device->type &= ~(BT_AVRCP); + break; } BT_DBG("Connection type = %x\n", connected_device->type); @@ -400,23 +641,105 @@ void _bt_remove_headset_from_list(int type, const char *address) } } +static gboolean __bt_device_support_uuid(char *remote_address, + bt_audio_type_t type) +{ + GArray *dev_list = NULL; + int size,i,j; + bluetooth_device_info_t info; + char bond_address[BT_ADDRESS_STRING_SIZE] = { 0 }; + gboolean ret = FALSE; + + BT_DBG("+"); + + dev_list = g_array_new (FALSE, FALSE, sizeof(gchar)); + + _bt_get_bonded_devices(&dev_list); + size = (dev_list->len) / sizeof(bluetooth_device_info_t); + + for (i=0; i < size; i++) { + info = g_array_index(dev_list, bluetooth_device_info_t, i); + _bt_convert_addr_type_to_string(bond_address, + info.device_address.addr); + if (strcmp(bond_address, remote_address) != 0) + continue; + + BT_INFO("Device address Matched"); + j = 0; + while (j != info.service_index) { + if (type == BT_AUDIO_HSP) { + if (strcmp(info.uuids[j], HFP_HS_UUID) == 0) { + BT_INFO("HFP HS UUID exists"); + ret = TRUE; + goto end; + } + } else if (type == BT_AUDIO_A2DP) { + if (strcmp(info.uuids[j], A2DP_SINK_UUID) == 0) { + BT_INFO("A2DP SINK UUID exists"); + ret = TRUE; + goto end; + } + } + j++; + } + } +end: + g_array_free(dev_list, TRUE); + BT_DBG("-"); + return ret; +} + +gboolean _bt_is_service_connected(char* address, int type) +{ + GList *node; + + node = g_list_first(g_connected_list); + while (node != NULL) { + bt_connected_headset_data_t *conn_device = node->data; + + if ((g_strcmp0(conn_device->device_address, address) == 0) && + (conn_device->type & type)) { + BT_INFO("Service connected"); + return TRUE; + } + + node = g_list_next(node); + } + BT_INFO("Service not connected"); + return FALSE; +} + int _bt_audio_connect(int request_id, int type, bluetooth_device_address_t *device_address, GArray **out_param1) { int result = BLUETOOTH_ERROR_NONE; - gchar *device_path = NULL; - char *uuid = NULL; char address[BT_ADDRESS_STRING_SIZE] = { 0 }; - bt_function_data_t *func_data; DBusGProxy *adapter_proxy; - DBusGProxy *profile_proxy; DBusGConnection *g_conn; + int ret; + char *uuid; + int value = BLUETOOTH_ERROR_NONE; + bt_audio_function_data_t *func_data; BT_CHECK_PARAMETER(device_address, return); + adapter_proxy = _bt_get_adapter_proxy(); + retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + g_conn = _bt_get_system_gconn(); + retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL); + _bt_convert_addr_type_to_string(address, device_address->addr); + func_data = g_malloc0(sizeof(bt_audio_function_data_t)); + + func_data->address = g_strdup(address); + func_data->req_id = request_id; + func_data->type = type; + func_data->pending = BT_PENDING_NONE; + func_data->out_param = out_param1; + switch (type) { case BT_AUDIO_HSP: uuid = HFP_HS_UUID; @@ -424,88 +747,53 @@ int _bt_audio_connect(int request_id, int type, case BT_AUDIO_A2DP: uuid = A2DP_SINK_UUID; break; + case BT_AVRCP: + uuid = AVRCP_TARGET_UUID; + break; case BT_AUDIO_ALL: - uuid = GENERIC_AUDIO_UUID; + if (__bt_device_support_uuid(address, BT_AUDIO_HSP)) { + uuid = HFP_HS_UUID; + func_data->pending = BT_PENDING_CONNECT; + } else if (__bt_device_support_uuid(address, BT_AUDIO_A2DP)) { + uuid = A2DP_SINK_UUID; + } else { + BT_ERR("No audio role supported"); + result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND; + goto fail; + } break; default: BT_ERR("Unknown role"); result = BLUETOOTH_ERROR_INTERNAL; goto fail; } + BT_INFO("Connecting to service %s", uuid); - if (__bt_is_headset_connected(type, request_id, address, out_param1)) - return BLUETOOTH_ERROR_NONE; - - adapter_proxy = _bt_get_adapter_proxy(); - if (adapter_proxy == NULL) { - result = BLUETOOTH_ERROR_INTERNAL; - goto fail; - } - - device_path = _bt_get_device_object_path(address); - if (device_path == NULL) { - result = BLUETOOTH_ERROR_INTERNAL; - goto fail; - } - - g_conn = _bt_get_system_gconn(); - if (g_conn == NULL) { - result = BLUETOOTH_ERROR_INTERNAL; - goto fail; - } - - profile_proxy = dbus_g_proxy_new_for_name(g_conn, BT_BLUEZ_NAME, - device_path, BT_DEVICE_INTERFACE); - - g_free(device_path); - - if (profile_proxy == NULL) { - result = BLUETOOTH_ERROR_INTERNAL; - goto fail; - } - - func_data = g_malloc0(sizeof(bt_function_data_t)); - func_data->address = g_strdup(address); - func_data->req_id = request_id; + value = __bt_is_headset_connected(type, request_id, address, out_param1); - if (g_strcmp0(uuid, GENERIC_AUDIO_UUID) == 0){ - if (!dbus_g_proxy_begin_call(profile_proxy, "Connect", - (DBusGProxyCallNotify)__bt_audio_request_cb, - func_data, NULL, - G_TYPE_INVALID)) { - BT_ERR("Audio connect Dbus Call Error"); - g_object_unref(profile_proxy); + if (value == BLUETOOTH_ERROR_ALREADY_CONNECT) { + return BLUETOOTH_ERROR_ALREADY_CONNECT; + } else if (value == BLUETOOTH_ERROR_NOT_CONNECTED) { + _bt_headset_set_local_connection(TRUE); + ret = _bt_connect_profile(address, uuid, + __bt_audio_request_cb, func_data); + if (ret != BLUETOOTH_ERROR_NONE) { + BT_ERR("_bt_connect_profile Error"); + _bt_headset_set_local_connection(FALSE); g_free(func_data->address); g_free(func_data); - - result = BLUETOOTH_ERROR_INTERNAL; - goto fail; + return ret; } - }else { - if (!dbus_g_proxy_begin_call(profile_proxy, "ConnectProfile", - (DBusGProxyCallNotify)__bt_audio_request_cb, - func_data, NULL, - G_TYPE_STRING, uuid, - G_TYPE_INVALID)) { - BT_ERR("Audio connect Dbus Call Error"); - g_object_unref(profile_proxy); - - g_free(func_data->address); - g_free(func_data); - result = BLUETOOTH_ERROR_INTERNAL; - goto fail; - } + /* Add data to the connected list */ + _bt_add_headset_to_list(type, BT_STATE_CONNECTING, address); } - /* Add data to the connected list */ - _bt_add_headset_to_list(type, BT_STATE_CONNECTING, address); - __bt_free_wait_data(); return BLUETOOTH_ERROR_NONE; fail: g_array_append_vals(*out_param1, address, - BT_ADDRESS_STR_LEN); + BT_ADDRESS_STR_LEN); return result; } @@ -515,18 +803,32 @@ int _bt_audio_disconnect(int request_id, int type, GArray **out_param1) { int result = BLUETOOTH_ERROR_NONE; - gchar *device_path = NULL; - char *uuid = NULL; char address[BT_ADDRESS_STRING_SIZE] = { 0 }; - bt_function_data_t *func_data; + bt_audio_function_data_t *func_data; DBusGProxy *adapter_proxy; - DBusGProxy *profile_proxy; DBusGConnection *g_conn; + GList *node; + int ret; + char *uuid; BT_CHECK_PARAMETER(device_address, return); + adapter_proxy = _bt_get_adapter_proxy(); + retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + g_conn = _bt_get_system_gconn(); + retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL); + _bt_convert_addr_type_to_string(address, device_address->addr); + func_data = g_malloc0(sizeof(bt_audio_function_data_t)); + + func_data->address = g_strdup(address); + func_data->req_id = request_id; + func_data->pending = BT_PENDING_NONE; + func_data->out_param = out_param1; + func_data->type = type; + switch (type) { case BT_AUDIO_HSP: uuid = HFP_HS_UUID; @@ -534,22 +836,102 @@ int _bt_audio_disconnect(int request_id, int type, case BT_AUDIO_A2DP: uuid = A2DP_SINK_UUID; break; + case BT_AVRCP: + uuid = AVRCP_TARGET_UUID; + break; case BT_AUDIO_ALL: - uuid = GENERIC_AUDIO_UUID; + if (_bt_is_service_connected(address, BT_AUDIO_HSP)) { + uuid = HFP_HS_UUID; + func_data->pending = BT_PENDING_DISCONNECT; + } else if (_bt_is_service_connected(address, BT_AUDIO_A2DP)) { + uuid = A2DP_SINK_UUID; + } else { + BT_ERR("No audio service connected"); + result = BLUETOOTH_ERROR_NOT_CONNECTED; + goto fail; + } break; default: BT_ERR("Unknown role"); - return BLUETOOTH_ERROR_INTERNAL; - } - - adapter_proxy = _bt_get_adapter_proxy(); - if (adapter_proxy == NULL) { result = BLUETOOTH_ERROR_INTERNAL; goto fail; } - device_path = _bt_get_device_object_path(address); - if (device_path == NULL) { + BT_INFO("Disconnecting service %s", uuid); + ret = _bt_disconnect_profile(address, uuid, + __bt_audio_request_cb, func_data); + + if (ret != BLUETOOTH_ERROR_NONE) { + BT_ERR("_bt_disconnect_profile Error"); + g_free(func_data->address); + g_free(func_data); + return ret; + } + + /* + * This logic is added for dual HF mode issue. + */ + node = g_list_first(g_connected_list); + while (node != NULL) { + bt_connected_headset_data_t *connected_device = node->data; + + if (g_strcmp0(connected_device->device_address, address) == 0) { + BT_DBG("Connection type update"); + type = connected_device->type; + break; + } + node = g_list_next(node); + } + _bt_add_headset_to_list(type, BT_STATE_DISCONNECTING, address); + + return BLUETOOTH_ERROR_NONE; +fail: + if (out_param1 != NULL) + g_array_append_vals(*out_param1, address, + BT_ADDRESS_STR_LEN); + + return result; +} + +void _bt_remove_from_connected_list(const char *address) +{ + bt_connected_headset_data_t *connected_device; + GList *node; + + node = g_list_first(g_connected_list); + while (node != NULL) { + connected_device = node->data; + if (connected_device != NULL && + g_strcmp0(connected_device->device_address, address) == 0) { + BT_ERR("Device is removed from the list"); + g_connected_list = g_list_remove(g_connected_list, connected_device); + g_free(connected_device); + return; + } + node = g_list_next(node); + } +} + +int _bt_hf_connect(int request_id, + bluetooth_device_address_t *device_address, + GArray **out_param1) +{ + int result = BLUETOOTH_ERROR_NONE; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + bt_function_data_t *func_data; + DBusGProxy *adapter_proxy; + DBusGConnection *g_conn; + + int ret; + char *uuid; + + + BT_CHECK_PARAMETER(device_address, return); + + _bt_convert_addr_type_to_string(address, device_address->addr); + + adapter_proxy = _bt_get_adapter_proxy(); + if (adapter_proxy == NULL) { result = BLUETOOTH_ERROR_INTERNAL; goto fail; } @@ -560,76 +942,85 @@ int _bt_audio_disconnect(int request_id, int type, goto fail; } - profile_proxy = dbus_g_proxy_new_for_name(g_conn, BT_BLUEZ_NAME, - device_path, BT_DEVICE_INTERFACE); + func_data = g_malloc0(sizeof(bt_function_data_t)); - g_free(device_path); + func_data->address = g_strdup(address); + func_data->req_id = request_id; + uuid = g_strdup(HFP_AG_UUID); + + BT_DBG("Connecting to service %s", uuid); + + ret = _bt_connect_profile(address, uuid, + __bt_hf_request_cb, func_data); + + if (ret != BLUETOOTH_ERROR_NONE) { + BT_ERR("_bt_connect_profile Error"); + g_free(func_data->address); + g_free(func_data); + g_free(uuid); + return ret; + } + g_free(uuid); + return BLUETOOTH_ERROR_NONE; +fail: + if (out_param1 != NULL) + g_array_append_vals(*out_param1, address, + BT_ADDRESS_STR_LEN); + + return result; +} - if (profile_proxy == NULL) { +int _bt_hf_disconnect(int request_id, + bluetooth_device_address_t *device_address, + GArray **out_param1) +{ + int result = BLUETOOTH_ERROR_NONE; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + bt_function_data_t *func_data; + DBusGProxy *adapter_proxy; + DBusGConnection *g_conn; + + int ret; + char *uuid; + + BT_CHECK_PARAMETER(device_address, return); + + _bt_convert_addr_type_to_string(address, device_address->addr); + + adapter_proxy = _bt_get_adapter_proxy(); + if (adapter_proxy == NULL) { result = BLUETOOTH_ERROR_INTERNAL; goto fail; } - if (g_wait_data != NULL) { - if (g_strcmp0(uuid, GENERIC_AUDIO_UUID) == 0){ - if (!dbus_g_proxy_begin_call(profile_proxy, - "Disconnect",NULL, NULL, NULL, - G_TYPE_INVALID)) { - BT_ERR("Audio disconnect Dbus Call Error"); - g_object_unref(profile_proxy); - return BLUETOOTH_ERROR_INTERNAL; - } - } else { - if (!dbus_g_proxy_begin_call(profile_proxy, - "DisconnectProfile",NULL, NULL, NULL, - G_TYPE_STRING, uuid, - G_TYPE_INVALID)) { - BT_ERR("Audio disconnect Dbus Call Error"); - g_object_unref(profile_proxy); - return BLUETOOTH_ERROR_INTERNAL; - } - } - } else { - func_data = g_malloc0(sizeof(bt_function_data_t)); - func_data->address = g_strdup(address); - func_data->req_id = request_id; - if (g_strcmp0(uuid, GENERIC_AUDIO_UUID) == 0){ - if (!dbus_g_proxy_begin_call(profile_proxy, - "Disconnect", - (DBusGProxyCallNotify)__bt_audio_request_cb, - func_data, NULL, - G_TYPE_INVALID)) { - BT_ERR("Audio disconnect Dbus Call Error"); - g_object_unref(profile_proxy); - - g_free(func_data->address); - g_free(func_data); - - result = BLUETOOTH_ERROR_INTERNAL; - goto fail; - } - } else { - if (!dbus_g_proxy_begin_call(profile_proxy, - "DisconnectProfile", - (DBusGProxyCallNotify)__bt_audio_request_cb, - func_data, NULL, - G_TYPE_STRING, uuid, - G_TYPE_INVALID)) { - BT_ERR("Audio disconnect Dbus Call Error"); - g_object_unref(profile_proxy); - - g_free(func_data->address); - g_free(func_data); - - result = BLUETOOTH_ERROR_INTERNAL; - goto fail; - } - } + g_conn = _bt_get_system_gconn(); + if (g_conn == NULL) { + result = BLUETOOTH_ERROR_INTERNAL; + goto fail; } + func_data = g_malloc0(sizeof(bt_function_data_t)); + + func_data->address = g_strdup(address); + func_data->req_id = request_id; + uuid = g_strdup(HFP_AG_UUID); + + BT_DBG("Disconnecting service %s", uuid); + ret = _bt_disconnect_profile(address, uuid, + __bt_hf_request_cb, func_data); + + if (ret != BLUETOOTH_ERROR_NONE) { + BT_ERR("_bt_disconnect_profile Error"); + g_free(func_data->address); + g_free(func_data); + g_free(uuid); + return ret; + } + g_free(uuid); return BLUETOOTH_ERROR_NONE; fail: - g_array_append_vals(*out_param1, address, + if (out_param1 != NULL) + g_array_append_vals(*out_param1, address, BT_ADDRESS_STR_LEN); return result; @@ -654,7 +1045,7 @@ int _bt_audio_get_speaker_gain(unsigned int *gain) retv_if(device_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED); profile_proxy = dbus_g_proxy_new_for_name(g_conn, BT_BLUEZ_NAME, - device_path, BT_HFP_AGENT_INTERFACE); + device_path, BT_HEADSET_INTERFACE); g_free(device_path); @@ -694,7 +1085,7 @@ int _bt_audio_set_speaker_gain(unsigned int gain) retv_if(device_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED); msg = dbus_message_new_method_call(BT_BLUEZ_NAME, - device_path, BT_HFP_AGENT_INTERFACE, + device_path, BT_HEADSET_INTERFACE, "SetProperty"); g_free(device_path); @@ -721,3 +1112,40 @@ int _bt_audio_set_speaker_gain(unsigned int gain) return ret; } + +int _bt_audio_set_content_protect(gboolean status) +{ + DBusConnection *conn; + DBusMessage *signal; + + BT_DBG("+\n"); + + conn = _bt_get_system_conn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_DBG("Content Protection status = [%d] \n", status); + + /*Emit Content protection Status change signal with value*/ + signal = dbus_message_new_signal(BT_CONTENT_PROTECTION_PATH, + BT_CONTENT_PROTECTION_INTERFACE, + "ProtectionRequired"); + if (!signal) + goto err; + + if (!dbus_message_append_args(signal, + DBUS_TYPE_BOOLEAN, &status, + DBUS_TYPE_INVALID)) { + BT_ERR("Signal appending failed\n"); + dbus_message_unref(signal); + goto err; + } + + dbus_connection_send(conn, signal, NULL); + dbus_message_unref(signal); + + BT_DBG("-\n"); + return BLUETOOTH_ERROR_NONE; + +err: + return BLUETOOTH_ERROR_INTERNAL; +} diff --git a/bt-service/bt-service-avrcp.c b/bt-service/bt-service-avrcp.c old mode 100644 new mode 100755 index f71e011..e3e1e4c --- a/bt-service/bt-service-avrcp.c +++ b/bt-service/bt-service-avrcp.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -23,9 +27,7 @@ #include #include #include -#if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT) #include -#endif #include "bluetooth-api.h" #include "bt-internal-types.h" @@ -34,6 +36,7 @@ #include "bt-service-avrcp.h" #include "bt-service-event.h" #include "bt-service-util.h" +#include "bt-service-audio.h" struct player_settinngs_t { int key; @@ -48,266 +51,150 @@ static struct player_settinngs_t loopstatus_settings[] = { { REPEAT_INVALID, "" } }; -static struct player_settinngs_t playback_status[] = { - { STATUS_STOPPED, "Stopped" }, - { STATUS_PLAYING, "Playing" }, - { STATUS_PAUSED, "Paused" }, + +static struct player_settinngs_t shuffle_settings[] = { + { SHUFFLE_INVALID, "" }, + { SHUFFLE_MODE_OFF, "off" }, + { SHUFFLE_ALL_TRACK, "alltracks" }, + { SHUFFLE_GROUP, "group" }, + { SHUFFLE_INVALID, "" } +}; + +static struct player_settinngs_t player_status[] = { + { STATUS_STOPPED, "stopped" }, + { STATUS_PLAYING, "playing" }, + { STATUS_PAUSED, "paused" }, + { STATUS_FORWARD_SEEK, "forward-seek" }, + { STATUS_REVERSE_SEEK, "reverse-seek" }, + { STATUS_ERROR, "error" }, { STATUS_INVALID, "" } }; -static struct player_settinngs_t repeat_settings[] = { +static struct player_settinngs_t repeat_status[] = { { REPEAT_INVALID, "" }, { REPEAT_MODE_OFF, "off" }, { REPEAT_SINGLE_TRACK, "singletrack" }, { REPEAT_ALL_TRACK, "alltracks" }, + { REPEAT_GROUP, "group" }, { REPEAT_INVALID, "" } }; -typedef struct { - GObject parent; -} BtMediaAgent; - -typedef struct { - GObjectClass parent; -} BtMediaAgentClass; - -GType bt_media_agent_get_type(void); +static struct player_settinngs_t equalizer_status[] = { + { EQUALIZER_INVALID, "" }, + { EQUALIZER_OFF, "off" }, + { EQUALIZER_ON, "on" }, + { EQUALIZER_INVALID, "" }, +}; +static struct player_settinngs_t scan_status[] = { + { SCAN_INVALID, "" }, + { SCAN_MODE_OFF, "off" }, + { SCAN_ALL_TRACK, "alltracks" }, + { SCAN_GROUP, "group" }, + { SCAN_INVALID, "" }, +}; DBusConnection *g_bt_dbus_conn = NULL; +static char *avrcp_control_path = NULL; -#define BT_MEDIA_TYPE_AGENT (bt_media_agent_get_type()) -#define BT_MEDIA_GET_AGENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), BT_MEDIA_TYPE_AGENT, BtMediaAgent)) -#define BT_MEDIA_IS_AGENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), BT_MEDIA_TYPE_AGENT)) -#define BT_MEDIA_AGENT_CLASS(class) (G_TYPE_CHECK_CLASS_CAST((class), BT_MEDIA_TYPE_AGENT, \ - BtMediaAgentClass)) -#define BT_MEDIA_GET_AGENT_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), BT_MEDIA_TYPE_AGENT, \ - BtMediaAgentClass)) -#define BT_MEDIA_IS_AGENT_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE((class), BT_MEDIA_TYPE_AGENT)) - -G_DEFINE_TYPE(BtMediaAgent, bt_media_agent, G_TYPE_OBJECT) - -static gboolean bt_media_agent_set_property(BtMediaAgent *agent, - const char *property, GValue *value, - DBusGMethodInvocation *context); - -static BtMediaAgent *bt_media_obj = NULL; - -#include "bt-media-agent-method.h" - -typedef enum { - BT_MEDIA_AGENT_ERROR_INVALID_PARAM, - BT_MEDIA_AGENT_ERROR_NOT_AVAILABLE, - BT_MEDIA_AGENT_ERROR_BUSY, -} BtMediaAgentError; - -#define BT_MEDIA_AGENT_ERROR (bt_media_agent_error_quark()) - -static GQuark bt_media_agent_error_quark(void) -{ - static GQuark quark = 0; - if (!quark) - quark = g_quark_from_static_string("agent"); - - return quark; -} - -#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } - -static GError *bt_media_agent_error(BtMediaAgentError error, const char *err_msg) -{ - return g_error_new(BT_MEDIA_AGENT_ERROR, error, err_msg, NULL); -} - -static void bt_media_agent_init(BtMediaAgent *agent) -{ - BT_DBG("agent %p\n", agent); -} - -static void bt_media_agent_finalize(GObject *agent) -{ - BT_DBG("Free agent %p\n", agent); - - G_OBJECT_CLASS(bt_media_agent_parent_class)->finalize(agent); -} - -static void bt_media_agent_class_init(BtMediaAgentClass *klass) -{ - GObjectClass *object_class = (GObjectClass *) klass; - - BT_DBG("class %p\n", klass); - - object_class->finalize = bt_media_agent_finalize; - - dbus_g_object_type_install_info(BT_MEDIA_TYPE_AGENT, - &dbus_glib_bt_media_agent_object_info); -} - -static BtMediaAgent *__bt_media_agent_new(void) -{ - BtMediaAgent *agent; - - agent = BT_MEDIA_GET_AGENT(g_object_new(BT_MEDIA_TYPE_AGENT, NULL)); - - BT_DBG("agent %p\n", agent); - - return agent; -} - -static gboolean bt_media_agent_set_property(BtMediaAgent *agent, - const char *property, GValue *val, - DBusGMethodInvocation *context) -{ - BT_DBG("property %s\n", property); - - dbus_g_method_return(context); - return TRUE; -} - -static const char *loopstatus_to_repeat(const char *value) -{ - if (strcasecmp(value, "None") == 0) - return "off"; - else if (strcasecmp(value, "Track") == 0) - return "singletrack"; - else if (strcasecmp(value, "Playlist") == 0) - return "alltracks"; - - return NULL; -} - -void set_shuffle(DBusMessageIter *iter) -{ - dbus_bool_t shuffle; - const char *value; - unsigned int status; - - if (dbus_message_iter_get_arg_type(iter) != - DBUS_TYPE_BOOLEAN) { - BT_DBG("Invalid arguments in method call"); - return; - } - - dbus_message_iter_get_basic(iter, &shuffle); - value = shuffle ? "alltracks" : "off"; - - if (g_strcmp0(value, "alltracks") == 0) - status = SHUFFLE_ALL_TRACK; - else if (g_strcmp0(value, "off") == 0) - status = SHUFFLE_MODE_OFF; - else - status = SHUFFLE_INVALID; - - _bt_send_event(BT_AVRCP_EVENT, - BLUETOOTH_EVENT_AVRCP_SETTING_SHUFFLE_STATUS, - DBUS_TYPE_UINT32, &status, - DBUS_TYPE_INVALID); -} - -void set_loopstatus(DBusMessageIter *iter) +static DBusHandlerResult _bt_avrcp_handle_set_property(DBusConnection *connection, + DBusMessage *message, void *user_data) { - const char *value; + BT_DBG("+"); + const gchar *value; unsigned int status; + gboolean shuffle_status; + DBusMessageIter args; + const char *property = NULL; + const char *interface = NULL; + DBusMessage *reply = NULL; + DBusHandlerResult result = DBUS_HANDLER_RESULT_HANDLED; + DBusMessageIter entry; + int type; - if (dbus_message_iter_get_arg_type(iter) != - DBUS_TYPE_STRING) { - BT_DBG("Invalid arguments in method call"); - return; - } - - dbus_message_iter_get_basic(iter, &value); - - value = loopstatus_to_repeat(value); - - if (g_strcmp0(value, "singletrack") == 0) - status = REPEAT_SINGLE_TRACK; - else if (g_strcmp0(value, "alltracks") == 0) - status = REPEAT_ALL_TRACK; - else if (g_strcmp0(value, "off") == 0) - status = REPEAT_MODE_OFF; - else - status = REPEAT_INVALID; - - _bt_send_event(BT_AVRCP_EVENT, - BLUETOOTH_EVENT_AVRCP_SETTING_REPEAT_STATUS, - DBUS_TYPE_UINT32, &status, - DBUS_TYPE_INVALID); -} - -static DBusHandlerResult bt_properties_message(DBusConnection *connection, - DBusMessage *message) -{ - DBusMessageIter iter, sub; - const char *name, *interface; - DBusMessage *reply; - if (!dbus_message_iter_init(message, &iter)){ - reply = dbus_message_new_error(message, - DBUS_ERROR_INVALID_ARGS, "No arguments given"); - goto done; - } + dbus_message_iter_init(message, &args); + dbus_message_iter_get_basic(&args, &interface); + dbus_message_iter_next(&args); - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING){ - reply = dbus_message_new_error(message, - DBUS_ERROR_INVALID_ARGS, "Invalid argument type"); - goto done; + if (g_strcmp0(interface, BT_MEDIA_PLAYER_INTERFACE) != 0) { + result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; } - dbus_message_iter_get_basic(&iter, &interface); - dbus_message_iter_next(&iter); + dbus_message_iter_get_basic(&args, &property); + dbus_message_iter_next(&args); + dbus_message_iter_recurse(&args, &entry); + type = dbus_message_iter_get_arg_type(&entry); - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING){ - reply = dbus_message_new_error(message, - DBUS_ERROR_INVALID_ARGS, "Invalid argument type"); - goto done; - } + BT_DBG("property %s\n", property); - dbus_message_iter_get_basic(&iter, &name); - dbus_message_iter_next(&iter); + if (g_strcmp0(property, "Shuffle") == 0) { + if (type != DBUS_TYPE_BOOLEAN) { + BT_DBG("Error"); + reply = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, + "Invalid arguments"); + dbus_connection_send(connection, reply, NULL); + result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + dbus_message_iter_get_basic(&entry, &shuffle_status); + BT_DBG("value %d\n", shuffle_status); + if (shuffle_status == TRUE) + status = SHUFFLE_ALL_TRACK; + else + status = SHUFFLE_MODE_OFF; - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT){ - reply = dbus_message_new_error(message, - DBUS_ERROR_INVALID_ARGS, "Invalid argument type"); - goto done; - } + _bt_send_event(BT_AVRCP_EVENT, + BLUETOOTH_EVENT_AVRCP_SETTING_SHUFFLE_STATUS, + DBUS_TYPE_UINT32, &status, + DBUS_TYPE_INVALID); - dbus_message_iter_recurse(&iter, &sub); + } else if (g_strcmp0(property, "LoopStatus") == 0) { + if (type != DBUS_TYPE_STRING) { + BT_DBG("Error"); + reply = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, + "Invalid arguments"); + dbus_connection_send(connection, reply, NULL); + result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + dbus_message_iter_get_basic(&entry, &value); + BT_DBG("value %s\n", value); + + if (g_strcmp0(value, "Track") == 0) + status = REPEAT_SINGLE_TRACK; + else if (g_strcmp0(value, "Playlist") == 0) + status = REPEAT_ALL_TRACK; + else if (g_strcmp0(value, "None") == 0) + status = REPEAT_MODE_OFF; + else + status = REPEAT_INVALID; - if (g_strcmp0(interface, BT_MEDIA_PLAYER_INTERFACE) == 0){ - if (g_strcmp0(name, "LoopStatus") == 0) - set_loopstatus(&sub); - else if (g_strcmp0(name, "Shuffle") == 0) - set_shuffle(&sub); + _bt_send_event(BT_AVRCP_EVENT, + BLUETOOTH_EVENT_AVRCP_SETTING_REPEAT_STATUS, + DBUS_TYPE_UINT32, &status, + DBUS_TYPE_INVALID); } +finish: + if (reply) + dbus_message_unref(reply); - reply = dbus_message_new_method_return(message); - if (reply == NULL) - return DBUS_HANDLER_RESULT_NEED_MEMORY; - -done: - dbus_connection_send(connection, reply, NULL); - dbus_message_unref(reply); - - return DBUS_HANDLER_RESULT_HANDLED; + return result; } -static DBusHandlerResult bt_dbus_message(DBusConnection *connection, - DBusMessage *message, void *user_data) +static DBusHandlerResult _bt_avrcp_message_handle(DBusConnection *conn, DBusMessage *msg, void *user_data) { - const char *interface; - - interface = dbus_message_get_interface(message); - - if (interface == NULL) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + BT_DBG("+"); - if (g_strcmp0(interface, BT_PROPERTIES_INTERFACE) == 0) - return bt_properties_message(connection, message); + if (dbus_message_is_method_call(msg, DBUS_INTERFACE_PROPERTIES, "Set")) + return _bt_avrcp_handle_set_property(conn, msg, user_data); + BT_DBG("-"); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } static DBusObjectPathVTable bt_object_table = { - .message_function = bt_dbus_message, + .message_function = _bt_avrcp_message_handle, }; gboolean bt_dbus_register_object_path(DBusConnection *connection, @@ -316,7 +203,6 @@ gboolean bt_dbus_register_object_path(DBusConnection *connection, if (!dbus_connection_register_object_path(connection, path, &bt_object_table, NULL)) return FALSE; - return TRUE; } @@ -326,47 +212,6 @@ void bt_dbus_unregister_object_path(DBusConnection *connection, dbus_connection_unregister_object_path(connection, path); } -static inline void bt_dbus_queue_dispatch(DBusConnection *conn, - DBusDispatchStatus status) -{ - if (status == DBUS_DISPATCH_DATA_REMAINS){ - dbus_connection_ref(conn); - while (dbus_connection_dispatch(conn) - == DBUS_DISPATCH_DATA_REMAINS) - ; - - dbus_connection_unref(conn); - } -} - -static void bt_dbus_dispatch_status(DBusConnection *conn, - DBusDispatchStatus status, void *data) -{ - if (!dbus_connection_get_is_connected(conn)) - return; - - bt_dbus_queue_dispatch(conn, status); -} - -DBusConnection *bt_dbus_setup_private(DBusBusType type, DBusError *error) -{ - DBusConnection *conn; - DBusDispatchStatus status; - - conn = dbus_bus_get_private(type, error); - - if (conn == NULL) - return NULL; - - dbus_connection_set_dispatch_status_function(conn, - bt_dbus_dispatch_status, NULL, NULL); - - status = dbus_connection_get_dispatch_status(conn); - bt_dbus_queue_dispatch(conn, status); - - return conn; -} - static void __bt_media_append_variant(DBusMessageIter *iter, int type, void *value) { @@ -403,173 +248,135 @@ static void __bt_media_append_dict_entry(DBusMessageIter *iter, dbus_message_iter_close_container(iter, &dict_entry); } -static void __bt_media_append_array_variant(DBusMessageIter *iter, int type, - void *val, int n_elements) +static gboolean __bt_media_emit_property_changed( + DBusConnection *connection, + const char *path, + const char *interface, + const char *name, + int type, + void *property) { - DBusMessageIter variant, array; - char type_sig[2] = { type, '\0' }; - char array_sig[3] = { DBUS_TYPE_ARRAY, type, '\0' }; - - dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, - array_sig, &variant); - - dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY, - type_sig, &array); - - if (dbus_type_is_fixed(type) == TRUE) { - dbus_message_iter_append_fixed_array(&array, type, val, - n_elements); - } else if (type == DBUS_TYPE_STRING || - type == DBUS_TYPE_OBJECT_PATH) { - const char ***str_array = val; - int i; - - for (i = 0; i < n_elements; i++) - dbus_message_iter_append_basic(&array, type, - &((*str_array)[i])); - } + DBusMessage *sig; + DBusMessageIter entry, dict; + gboolean ret; - dbus_message_iter_close_container(&variant, &array); - dbus_message_iter_close_container(iter, &variant); -} + sig = dbus_message_new_signal(path, DBUS_INTERFACE_PROPERTIES, + "PropertiesChanged"); + retv_if(sig == NULL, FALSE); -static void __bt_media_append_array(DBusMessageIter *dict, const char *key, - int type, void *val, int n_elements) -{ - DBusMessageIter entry; + dbus_message_iter_init_append(sig, &entry); + dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &interface); + dbus_message_iter_open_container(&entry, DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); - dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY, - NULL, &entry); + __bt_media_append_dict_entry(&dict, + name, type, property); - BT_DBG("key = %s", key); - dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key); + dbus_message_iter_close_container(&entry, &dict); - __bt_media_append_array_variant(&entry, type, val, n_elements); + ret = dbus_connection_send(connection, sig, NULL); + dbus_message_unref(sig); - dbus_message_iter_close_container(dict, &entry); + return ret; } -static void __bt_media_append_metadata_variant(DBusMessageIter *iter, - const char *key, int type, void *property, int count) +void _bt_set_control_device_path(const char *path) { - DBusMessageIter value, metadata; - - dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}", - &value); - - dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY, - DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING - DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING - DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &metadata); - if (type == DBUS_TYPE_ARRAY) - __bt_media_append_array(&metadata, key, - DBUS_TYPE_STRING, property, count); - else - __bt_media_append_dict_entry(&metadata, key, type, property); + ret_if(path == NULL); - dbus_message_iter_close_container(&value, &metadata); - dbus_message_iter_close_container(iter, &value); + g_free(avrcp_control_path); + BT_DBG("control_path = %s", path); + avrcp_control_path = g_strdup(path); } -static void __bt_media_append_metadata_dict_entry(DBusMessageIter *iter, - const char *key, int type, void *property, int count) +void _bt_remove_control_device_path(const char *path) { - DBusMessageIter dict_entry; - const char *str_ptr; - char * metadata = "Metadata"; + ret_if(path == NULL); - if (type == DBUS_TYPE_STRING) { - str_ptr = *((const char **)property); - ret_if(str_ptr == NULL); + if (avrcp_control_path && + !g_strcmp0(avrcp_control_path, path)) { + BT_DBG("control_path = %s", path); + g_free(avrcp_control_path); + avrcp_control_path = NULL; } - - dbus_message_iter_open_container(iter, - DBUS_TYPE_DICT_ENTRY, - NULL, &dict_entry); - - dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &metadata); - - __bt_media_append_metadata_variant(&dict_entry, key, type, property, count); - - dbus_message_iter_close_container(iter, &dict_entry); } -static void __bt_metadata_append_property_changed(DBusMessageIter *property_dict, - media_metadata_attributes_t *metadata) +static char *__bt_get_control_device_path(void) { - if(property_dict == NULL || metadata == NULL) - return + char *adapter_path; + char *control_path; + char connected_address[BT_ADDRESS_STRING_SIZE + 1]; + + BT_DBG("+"); - __bt_media_append_metadata_dict_entry(property_dict, - "xesam:title", - DBUS_TYPE_STRING, &metadata->title, 0); + retv_if(avrcp_control_path != NULL, avrcp_control_path); - __bt_media_append_array(property_dict, - "xesam:artist", - DBUS_TYPE_ARRAY,&metadata->artist, 1); + retv_if(!_bt_is_headset_type_connected(BT_AVRCP, + connected_address), NULL); - __bt_media_append_metadata_dict_entry(property_dict, - "xesam:album", - DBUS_TYPE_STRING, &metadata->album, 0); + BT_DBG("device address = %s", connected_address); - __bt_media_append_array(property_dict, - "xesam:genre", - DBUS_TYPE_ARRAY,&metadata->genre, 1); + adapter_path = _bt_get_device_object_path(connected_address); + retv_if(adapter_path == NULL, NULL); - __bt_media_append_metadata_dict_entry(property_dict, - "mpris:length", - DBUS_TYPE_INT64, &metadata->duration, 0); + control_path = g_strdup_printf(BT_MEDIA_CONTROL_PATH, adapter_path); + g_free(adapter_path); - __bt_media_append_metadata_dict_entry(property_dict, - "xesam:trackNumber", - DBUS_TYPE_INT32, &metadata->tracknumber, 0); + avrcp_control_path = control_path; + BT_DBG("control_path = %s", control_path); + return control_path; } -static gboolean __bt_media_emit_property_changed( - DBusConnection *connection, - const char *path, - const char *interface, - const char *name, - int type, - void *property) +static int __bt_media_send_control_msg(const char *name) { - DBusMessage *sig; - DBusMessageIter entry, dict; - gboolean ret; + DBusMessage *msg; + DBusMessage *reply; + DBusError err; + DBusConnection *conn; + char *control_path; - BT_DBG("+"); - sig = dbus_message_new_signal(path, DBUS_INTERFACE_PROPERTIES, - "PropertiesChanged"); - retv_if(sig == NULL, FALSE); + retv_if(name == NULL, BLUETOOTH_ERROR_INTERNAL); - dbus_message_iter_init_append(sig, &entry); - dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &interface); + conn = _bt_get_system_conn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); - dbus_message_iter_open_container(&entry, DBUS_TYPE_ARRAY, - DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING - DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING - DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); + control_path = __bt_get_control_device_path(); + retv_if(control_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED); + BT_DBG("control_path %s", control_path); - if (g_strcmp0(name, "Metadata") == 0) - __bt_metadata_append_property_changed(&dict, - (media_metadata_attributes_t *)property); - else - __bt_media_append_dict_entry(&dict, - name, type, property); + msg = dbus_message_new_method_call(BT_BLUEZ_NAME, control_path, + BT_PLAYER_CONTROL_INTERFACE, name); - dbus_message_iter_close_container(&entry, &dict); + retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL); - ret = dbus_connection_send(connection, sig, NULL); - dbus_message_unref(sig); + dbus_error_init(&err); + reply = dbus_connection_send_with_reply_and_block(conn, + msg, -1, &err); + dbus_message_unref(msg); - BT_DBG("-"); + if (!reply) { + BT_ERR("Error in Sending Control Command"); - return ret; + if (dbus_error_is_set(&err)) { + BT_ERR("%s", err.message); + dbus_error_free(&err); + } + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_unref(reply); + + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; } + int _bt_register_media_player(void) { + BT_DBG("+"); DBusMessage *msg; DBusMessage *reply; DBusMessageIter iter; @@ -579,47 +386,35 @@ int _bt_register_media_player(void) char *adapter_path; DBusConnection *conn; DBusGConnection *gconn; + gboolean shuffle_status; media_player_settings_t player_settings = {0,}; - media_metadata_attributes_t metadata = {0,}; - player_settings.loopstatus = REPEAT_MODE_OFF; - player_settings.playbackstatus = STATUS_STOPPED; - player_settings.shuffle = FALSE; + player_settings.repeat = REPEAT_MODE_OFF; + + player_settings.shuffle = SHUFFLE_MODE_OFF; + player_settings.status = STATUS_STOPPED; player_settings.position = 0; - metadata.title = "\0"; - metadata.album = "\0"; - metadata.tracknumber = 0; - metadata.duration = 0; gconn = _bt_get_system_gconn(); retv_if(gconn == NULL, BLUETOOTH_ERROR_INTERNAL); - conn = bt_dbus_setup_private(DBUS_BUS_SYSTEM, NULL); + conn = _bt_get_system_conn(); retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); g_bt_dbus_conn = conn; - if (!bt_media_obj) { - bt_media_obj = __bt_media_agent_new(); - - retv_if(bt_media_obj == NULL, BLUETOOTH_ERROR_INTERNAL); - - dbus_g_connection_register_g_object(gconn, - BT_MEDIA_OBJECT_PATH, - G_OBJECT(bt_media_obj)); - } if (!bt_dbus_register_object_path(conn, BT_MEDIA_OBJECT_PATH)){ BT_DBG("Could not register interface %s", - MPRIS_PLAYER_INTERFACE); + BT_MEDIA_PLAYER_INTERFACE); } adapter_path = _bt_get_adapter_path(); retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL); msg = dbus_message_new_method_call(BT_BLUEZ_NAME, adapter_path, - BT_MEDIA_INTERFACE, "RegisterPlayer"); + BT_MEDIA_INTERFACE, "RegisterPlayer"); g_free(adapter_path); @@ -633,94 +428,61 @@ int _bt_register_media_player(void) dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING - DBUS_TYPE_STRING_AS_STRING - DBUS_TYPE_VARIANT_AS_STRING + DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &property_dict); __bt_media_append_dict_entry(&property_dict, "LoopStatus", DBUS_TYPE_STRING, - &loopstatus_settings[player_settings.loopstatus].property); + &loopstatus_settings[player_settings.repeat].property); + + if (player_settings.shuffle == SHUFFLE_MODE_OFF) + shuffle_status = FALSE; + else + shuffle_status = TRUE; __bt_media_append_dict_entry(&property_dict, "Shuffle", DBUS_TYPE_BOOLEAN, - &player_settings.shuffle); + &shuffle_status); __bt_media_append_dict_entry(&property_dict, "PlaybackStatus", DBUS_TYPE_STRING, - &playback_status[player_settings.playbackstatus].property); + &player_status[player_settings.status].property); + __bt_media_append_dict_entry(&property_dict, "Position", - DBUS_TYPE_INT64, &player_settings.position); - - __bt_media_append_metadata_dict_entry(&property_dict, - "xesam:title", - DBUS_TYPE_STRING, &metadata.title, 0); - - metadata.artists = g_malloc0(sizeof(char *)); - metadata.artists[0] = ""; - - __bt_media_append_metadata_dict_entry(&property_dict, - "xesam:artist", - DBUS_TYPE_ARRAY, &metadata.artists, 1); - - __bt_media_append_metadata_dict_entry(&property_dict, - "xesam:album", - DBUS_TYPE_STRING, &metadata.album, 0); - - metadata.genres = g_malloc0(sizeof(char *)); - metadata.genres[0] = ""; - - __bt_media_append_metadata_dict_entry(&property_dict, - "xesam:genre", - DBUS_TYPE_ARRAY, &metadata.genres, 1); - - __bt_media_append_metadata_dict_entry(&property_dict, - "mpris:length", - DBUS_TYPE_INT64, &metadata.duration, 0); - - __bt_media_append_metadata_dict_entry(&property_dict, - "xesam:trackNumber", - DBUS_TYPE_INT32, &metadata.tracknumber, 0); + DBUS_TYPE_UINT32, &player_settings.position); dbus_message_iter_close_container(&iter, &property_dict); dbus_error_init(&err); reply = dbus_connection_send_with_reply_and_block(conn, - msg, -1, &err); + msg, -1, &err); dbus_message_unref(msg); if (!reply) { - BT_DBG("Error in registering the Music Player \n"); + BT_ERR("Error in registering the Music Player \n"); if (dbus_error_is_set(&err)) { BT_ERR("%s", err.message); dbus_error_free(&err); return BLUETOOTH_ERROR_INTERNAL; } - - if (bt_media_obj) { - dbus_g_connection_unregister_g_object(gconn, - G_OBJECT(bt_media_obj)); - g_object_unref(bt_media_obj); - bt_media_obj = NULL; - } } if (reply) dbus_message_unref(reply); - g_free(metadata.artist); - g_free(metadata.genre); - + BT_DBG("-"); return BLUETOOTH_ERROR_NONE; } int _bt_unregister_media_player(void) { + BT_DBG("+"); DBusMessage *msg; DBusMessage *reply; DBusError err; @@ -737,6 +499,7 @@ int _bt_unregister_media_player(void) msg = dbus_message_new_method_call(BT_BLUEZ_NAME, adapter_path, BT_MEDIA_INTERFACE, "UnregisterPlayer"); + g_free(adapter_path); retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL); @@ -758,7 +521,7 @@ int _bt_unregister_media_player(void) BT_ERR("Error in unregistering the Music Player \n"); if (dbus_error_is_set(&err)) { - BT_DBG("%s", err.message); + BT_ERR("%s", err.message); dbus_error_free(&err); return BLUETOOTH_ERROR_INTERNAL; } @@ -766,22 +529,158 @@ int _bt_unregister_media_player(void) dbus_message_unref(reply); } - if (bt_media_obj) { - dbus_g_connection_unregister_g_object(_bt_get_system_gconn(), - G_OBJECT(bt_media_obj)); - g_object_unref(bt_media_obj); - bt_media_obj = NULL; - } - bt_dbus_unregister_object_path(conn, BT_MEDIA_OBJECT_PATH); g_bt_dbus_conn = NULL; + BT_DBG("-"); return BLUETOOTH_ERROR_NONE; } -int _bt_avrcp_set_interal_property(int type, media_player_settings_t *properties) +static void __bt_media_append_metadata_entry(DBusMessageIter *metadata, + void *key_type, void *value, int type) { - DBusConnection *conn; + BT_DBG("+"); + DBusMessageIter string_entry; + + dbus_message_iter_open_container(metadata, + DBUS_TYPE_DICT_ENTRY, + NULL, &string_entry); + + dbus_message_iter_append_basic(&string_entry, DBUS_TYPE_STRING, key_type); + + __bt_media_append_variant(&string_entry, type, value); + + dbus_message_iter_close_container(metadata, &string_entry); + BT_DBG("-"); +} + +static void __bt_media_append_metadata_array(DBusMessageIter *metadata, + void *key_type, void *value, int type) +{ + BT_DBG("+"); + DBusMessageIter string_entry, variant, array; + char array_sig[3] = { type, DBUS_TYPE_STRING, '\0' }; + + dbus_message_iter_open_container(metadata, + DBUS_TYPE_DICT_ENTRY, + NULL, &string_entry); + dbus_message_iter_append_basic(&string_entry, DBUS_TYPE_STRING, key_type); + + dbus_message_iter_open_container(&string_entry, DBUS_TYPE_VARIANT, + array_sig, &variant); + + dbus_message_iter_open_container(&variant, type, + DBUS_TYPE_STRING_AS_STRING, &array); + dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING, value); + + dbus_message_iter_close_container(&variant, &array); + dbus_message_iter_close_container(&string_entry, &variant); + dbus_message_iter_close_container(metadata, &string_entry); + BT_DBG("-"); +} + +int _bt_avrcp_set_track_info(media_metadata_attributes_t *meta_data) +{ + BT_DBG("+"); + DBusMessage *sig; + DBusMessageIter iter; + DBusMessageIter property_dict, metadata_dict, metadata_variant, metadata; + DBusConnection *conn; + char *interface = BT_MEDIA_PLAYER_INTERFACE; + char * metadata_str = "Metadata"; + const char *key_type; + + retv_if(meta_data == NULL, BLUETOOTH_ERROR_INTERNAL); + + conn = g_bt_dbus_conn; + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + sig = dbus_message_new_signal(BT_MEDIA_OBJECT_PATH, DBUS_INTERFACE_PROPERTIES, + "PropertiesChanged"); + retv_if(sig == NULL, FALSE); + + dbus_message_iter_init_append(sig, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface); + + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &property_dict); + + dbus_message_iter_open_container(&property_dict, + DBUS_TYPE_DICT_ENTRY, + NULL, &metadata_dict); + + dbus_message_iter_append_basic(&metadata_dict, DBUS_TYPE_STRING, &metadata_str); + + dbus_message_iter_open_container(&metadata_dict, DBUS_TYPE_VARIANT, "a{sv}", + &metadata_variant); + + dbus_message_iter_open_container(&metadata_variant, DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &metadata); + + if (meta_data->title) { + key_type = "xesam:title"; + __bt_media_append_metadata_entry(&metadata, &key_type, + &meta_data->title, DBUS_TYPE_STRING); + } + + if (meta_data->artist) { + key_type = "xesam:artist"; + __bt_media_append_metadata_array(&metadata, &key_type, + &meta_data->artist, DBUS_TYPE_ARRAY); + } + + if (meta_data->album) { + key_type = "xesam:album"; + __bt_media_append_metadata_entry(&metadata, &key_type, + &meta_data->album, DBUS_TYPE_STRING); + } + + if (meta_data->genre) { + key_type = "xesam:genre"; + __bt_media_append_metadata_array(&metadata, &key_type, + &meta_data->genre, DBUS_TYPE_ARRAY); + } + + if (0 != meta_data->total_tracks) { + key_type = "xesam:totalTracks"; + __bt_media_append_metadata_entry(&metadata, &key_type, + &meta_data->total_tracks, DBUS_TYPE_INT32); + } + + if (0 != meta_data->number) { + key_type = "xesam:trackNumber"; + __bt_media_append_metadata_entry(&metadata, &key_type, + &meta_data->number, DBUS_TYPE_INT32); + } + + if (0 != meta_data->duration) { + key_type = "mpris:length"; + __bt_media_append_metadata_entry(&metadata, &key_type, + &meta_data->duration, DBUS_TYPE_INT64); + } + + dbus_message_iter_close_container(&metadata_variant, &metadata); + dbus_message_iter_close_container(&metadata_dict, &metadata_variant); + dbus_message_iter_close_container(&property_dict, &metadata_dict); + dbus_message_iter_close_container(&iter, &property_dict); + + if (!dbus_connection_send(conn, sig, NULL)) + BT_ERR("Unable to send TrackChanged signal\n"); + + dbus_message_unref(sig); + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; +} + + +int _bt_avrcp_set_interal_property(int type, media_player_settings_t *properties) +{ + BT_DBG("+"); + DBusConnection *conn; int value; media_metadata_attributes_t meta_data; dbus_bool_t shuffle; @@ -790,8 +689,8 @@ int _bt_avrcp_set_interal_property(int type, media_player_settings_t *properties retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); switch (type) { - case LOOPSTATUS: - value = properties->loopstatus; + case REPEAT: + value = properties->repeat; if (!__bt_media_emit_property_changed( conn, BT_MEDIA_OBJECT_PATH, @@ -799,16 +698,16 @@ int _bt_avrcp_set_interal_property(int type, media_player_settings_t *properties "LoopStatus", DBUS_TYPE_STRING, &loopstatus_settings[value].property)) { - BT_DBG("Error sending the PropertyChanged signal \n"); + BT_ERR("Error sending the PropertyChanged signal \n"); return BLUETOOTH_ERROR_INTERNAL; } break; case SHUFFLE: value = properties->shuffle; - if (g_strcmp0(repeat_settings[value].property, "alltracks") == 0) - shuffle = 1; - else + if (g_strcmp0(shuffle_settings[value].property, "off") == 0) shuffle = 0; + else + shuffle = 1; if (!__bt_media_emit_property_changed( conn, @@ -821,15 +720,15 @@ int _bt_avrcp_set_interal_property(int type, media_player_settings_t *properties return BLUETOOTH_ERROR_INTERNAL; } break; - case PLAYBACKSTATUS: - value = properties->playbackstatus; + case STATUS: + value = properties->status; if (!__bt_media_emit_property_changed( conn, BT_MEDIA_OBJECT_PATH, BT_MEDIA_PLAYER_INTERFACE, "PlaybackStatus", DBUS_TYPE_STRING, - &playback_status[value].property)) { + &player_status[value].property)) { BT_DBG("Error sending the PropertyChanged signal \n"); return BLUETOOTH_ERROR_INTERNAL; } @@ -864,23 +763,24 @@ int _bt_avrcp_set_interal_property(int type, media_player_settings_t *properties BT_DBG("Invalid Type\n"); return BLUETOOTH_ERROR_INTERNAL; } - + BT_DBG("-"); return BLUETOOTH_ERROR_NONE; } int _bt_avrcp_set_properties(media_player_settings_t *properties) { - if (_bt_avrcp_set_interal_property(LOOPSTATUS, - properties) != BLUETOOTH_ERROR_NONE) { - return BLUETOOTH_ERROR_INTERNAL; - } + BT_DBG("+"); + if (_bt_avrcp_set_interal_property(REPEAT, + properties) != BLUETOOTH_ERROR_NONE) { + return BLUETOOTH_ERROR_INTERNAL; + } if (_bt_avrcp_set_interal_property(SHUFFLE, properties) != BLUETOOTH_ERROR_NONE) { return BLUETOOTH_ERROR_INTERNAL; } - if (_bt_avrcp_set_interal_property(PLAYBACKSTATUS, + if (_bt_avrcp_set_interal_property(STATUS, properties) != BLUETOOTH_ERROR_NONE) { return BLUETOOTH_ERROR_INTERNAL; } @@ -894,25 +794,24 @@ int _bt_avrcp_set_properties(media_player_settings_t *properties) properties) != BLUETOOTH_ERROR_NONE) { return BLUETOOTH_ERROR_INTERNAL; } - + BT_DBG("-"); return BLUETOOTH_ERROR_NONE; } int _bt_avrcp_set_property(int type, unsigned int value) { - media_player_settings_t properties; - BT_DBG("+"); + media_player_settings_t properties; switch (type) { - case LOOPSTATUS: - properties.loopstatus = value; + case REPEAT: + properties.repeat = value; break; case SHUFFLE: properties.shuffle = value; break; - case PLAYBACKSTATUS: - properties.playbackstatus = value; + case STATUS: + properties.status = value; break; case POSITION: properties.position = value; @@ -922,9 +821,572 @@ int _bt_avrcp_set_property(int type, unsigned int value) return BLUETOOTH_ERROR_INTERNAL; } - _bt_avrcp_set_interal_property(type, &properties); + if (_bt_avrcp_set_interal_property(type, + &properties) != BLUETOOTH_ERROR_NONE) + return BLUETOOTH_ERROR_INTERNAL; BT_DBG("-"); return BLUETOOTH_ERROR_NONE; } + +int _bt_avrcp_control_cmd(int type) +{ + int ret = BLUETOOTH_ERROR_INTERNAL; + BT_DBG("+"); + + switch (type) { + case PLAY: + ret = __bt_media_send_control_msg("Play"); + break; + case PAUSE: + ret = __bt_media_send_control_msg("Pause"); + break; + case STOP: + ret = __bt_media_send_control_msg("Stop"); + break; + case NEXT: + ret = __bt_media_send_control_msg("Next"); + break; + case PREVIOUS: + ret = __bt_media_send_control_msg("Previous"); + break; + case FAST_FORWARD: + ret = __bt_media_send_control_msg("FastForward"); + break; + case REWIND: + ret = __bt_media_send_control_msg("Rewind"); + break; + default: + BT_DBG("Invalid Type\n"); + return BLUETOOTH_ERROR_INTERNAL; + } + BT_DBG("-"); + return ret; +} + +DBusGProxy *__bt_get_control_properties_proxy(void) +{ + DBusGProxy *proxy; + char *control_path; + DBusGConnection *conn; + + control_path = __bt_get_control_device_path(); + retv_if(control_path == NULL, NULL); + BT_DBG("control_path = %s", control_path); + + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, NULL); + + proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + control_path, BT_PROPERTIES_INTERFACE); + return proxy; +} + +static int __bt_media_attr_to_event(const char *str) +{ + if (!strcasecmp(str, "Equalizer")) + return BLUETOOTH_EVENT_AVRCP_CONTROL_EQUALIZER_STATUS; + else if (!strcasecmp(str, "Repeat")) + return BLUETOOTH_EVENT_AVRCP_CONTROL_REPEAT_STATUS; + else if (!strcasecmp(str, "Shuffle")) + return BLUETOOTH_EVENT_AVRCP_CONTROL_SHUFFLE_STATUS; + else if (!strcasecmp(str, "Scan")) + return BLUETOOTH_EVENT_AVRCP_CONTROL_SCAN_STATUS; + else if (!strcasecmp(str, "Position")) + return BLUETOOTH_EVENT_AVRCP_SONG_POSITION_STATUS; + else if (!strcasecmp(str, "Track")) + return BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED; + else if (!strcasecmp(str, "Status")) + return BLUETOOTH_EVENT_AVRCP_PLAY_STATUS_CHANGED; + + return 0; +} + +static int __bt_media_attr_to_type(const char *str) +{ + if (!strcasecmp(str, "Equalizer")) + return EQUALIZER; + else if (!strcasecmp(str, "Repeat")) + return REPEAT; + else if (!strcasecmp(str, "Shuffle")) + return SHUFFLE; + else if (!strcasecmp(str, "Scan")) + return SCAN; + else if (!strcasecmp(str, "Position")) + return POSITION; + else if (!strcasecmp(str, "Track")) + return METADATA; + else if (!strcasecmp(str, "Status")) + return STATUS; + + return 0; +} + +static const char *__bt_media_type_to_str(int type) +{ + switch (type) { + case EQUALIZER: + return "Equalizer"; + case REPEAT: + return "Repeat"; + case SHUFFLE: + return "Shuffle"; + case SCAN: + return "Scan"; + case POSITION: + return "Position"; + case METADATA: + return "Track"; + case STATUS: + return "Status"; + } + return NULL; +} + +static int __bt_media_attrval_to_val(int type, const char *value) +{ + int ret = 0; + + switch (type) { + case EQUALIZER: + if (!strcmp(value, "off")) + ret = EQUALIZER_OFF; + else if (!strcmp(value, "on")) + ret = EQUALIZER_ON; + else + ret = EQUALIZER_INVALID; + break; + + case REPEAT: + if (!strcmp(value, "off")) + ret = REPEAT_MODE_OFF; + else if (!strcmp(value, "singletrack")) + ret = REPEAT_SINGLE_TRACK; + else if (!strcmp(value, "alltracks")) + ret = REPEAT_ALL_TRACK; + else if (!strcmp(value, "group")) + ret = REPEAT_GROUP; + else + ret = REPEAT_INVALID; + break; + + case SHUFFLE: + if (!strcmp(value, "off")) + ret = SHUFFLE_MODE_OFF; + else if (!strcmp(value, "alltracks")) + ret = SHUFFLE_ALL_TRACK; + else if (!strcmp(value, "group")) + ret = SHUFFLE_GROUP; + else + ret = SHUFFLE_INVALID; + break; + + case SCAN: + if (!strcmp(value, "off")) + ret = SCAN_MODE_OFF; + else if (!strcmp(value, "alltracks")) + ret = SCAN_ALL_TRACK; + else if (!strcmp(value, "group")) + ret = SCAN_GROUP; + else + ret = SCAN_INVALID; + break; + + case STATUS: + if (!strcmp(value, "stopped")) + ret = STATUS_STOPPED; + else if (!strcmp(value, "playing")) + ret = STATUS_PLAYING; + else if (!strcmp(value, "paused")) + ret = STATUS_PAUSED; + else if (!strcmp(value, "forward-seek")) + ret = STATUS_FORWARD_SEEK; + else if (!strcmp(value, "reverse-seek")) + ret = STATUS_REVERSE_SEEK; + else if (!strcmp(value, "error")) + ret = STATUS_ERROR; + else + ret = STATUS_INVALID; + } + return ret; +} + +int _bt_avrcp_control_get_property(int type, unsigned int *value) +{ + DBusGProxy *proxy; + char *name = NULL; + int ret = BLUETOOTH_ERROR_NONE; + GError *err = NULL; + GValue attr_value = { 0 }; + + BT_CHECK_PARAMETER(value, return); + + proxy = __bt_get_control_properties_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED); + + if (!dbus_g_proxy_call(proxy, "Get", &err, + G_TYPE_STRING, BT_PLAYER_CONTROL_INTERFACE, + G_TYPE_STRING, __bt_media_type_to_str(type), + G_TYPE_INVALID, + G_TYPE_VALUE, &attr_value, + G_TYPE_INVALID)) { + if (err != NULL) { + BT_ERR("Getting property failed: [%s]\n", err->message); + g_error_free(err); + } + g_object_unref(proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + g_object_unref(proxy); + + switch (type) { + case EQUALIZER: + case REPEAT: + case SHUFFLE: + case SCAN: + case STATUS: + name = (char *)g_value_get_string(&attr_value); + *value = __bt_media_attrval_to_val(type, name); + BT_DBG("Type[%s] and Value[%s]", __bt_media_type_to_str(type), name); + break; + case POSITION: + *value = g_value_get_uint(&attr_value); + break; + default: + BT_DBG("Invalid Type\n"); + ret = BLUETOOTH_ERROR_INTERNAL; + } + + return ret; +} + +int _bt_avrcp_control_set_property(int type, unsigned int value) +{ + GValue attr_value = { 0 }; + DBusGProxy *proxy; + GError *error = NULL; + + proxy = __bt_get_control_properties_proxy(); + + retv_if(proxy == NULL, BLUETOOTH_ERROR_NOT_CONNECTED); + g_value_init(&attr_value, G_TYPE_STRING); + + switch (type) { + case EQUALIZER: + g_value_set_string(&attr_value, equalizer_status[value].property); + BT_DBG("equalizer_status %s", equalizer_status[value].property); + break; + case REPEAT: + g_value_set_string(&attr_value, repeat_status[value].property); + BT_DBG("repeat_status %s", repeat_status[value].property); + break; + case SHUFFLE: + g_value_set_string(&attr_value, shuffle_settings[value].property); + BT_DBG("shuffle_settings %s", shuffle_settings[value].property); + break; + case SCAN: + g_value_set_string(&attr_value, scan_status[value].property); + BT_DBG("scan_status %s", scan_status[value].property); + break; + default: + BT_ERR("Invalid property type: %d", type); + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_g_proxy_call(proxy, "Set", &error, + G_TYPE_STRING, BT_PLAYER_CONTROL_INTERFACE, + G_TYPE_STRING, __bt_media_type_to_str(type), + G_TYPE_VALUE, &attr_value, + G_TYPE_INVALID, G_TYPE_INVALID); + + g_value_unset(&attr_value); + g_object_unref(proxy); + + if (error) { + BT_ERR("SetProperty Fail: %s", error->message); + g_error_free(error); + return BLUETOOTH_ERROR_INTERNAL; + } + + return BLUETOOTH_ERROR_NONE; +} + +static gboolean __bt_avrcp_control_parse_metadata( + char **value_string, + unsigned int *value_uint, + int type, + DBusMessageIter *iter) +{ + if (dbus_message_iter_get_arg_type(iter) != type) + return FALSE; + + if (type == DBUS_TYPE_STRING) { + char *value; + dbus_message_iter_get_basic(iter, &value); + *value_string = g_strdup(value); + } else if (type == DBUS_TYPE_UINT32) { + int value; + dbus_message_iter_get_basic(iter, &value); + *value_uint = value; + } else + return FALSE; + + return TRUE; +} + + +static int __bt_avrcp_control_parse_properties( + media_metadata_attributes_t *metadata, + DBusMessageIter *iter) +{ + DBusMessageIter dict; + DBusMessageIter var; + int ctype; + char *value_string; + unsigned int value_uint; + + ctype = dbus_message_iter_get_arg_type(iter); + if (ctype != DBUS_TYPE_ARRAY) { + BT_ERR("ctype error %d", ctype); + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_iter_recurse(iter, &dict); + + while ((ctype = dbus_message_iter_get_arg_type(&dict)) != + DBUS_TYPE_INVALID) { + DBusMessageIter entry; + const char *key; + + if (ctype != DBUS_TYPE_DICT_ENTRY) { + BT_ERR("ctype error %d", ctype); + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_iter_recurse(&dict, &entry); + if (dbus_message_iter_get_arg_type(&entry) != + DBUS_TYPE_STRING) { + BT_ERR("ctype not DBUS_TYPE_STRING"); + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_iter_get_basic(&entry, &key); + dbus_message_iter_next(&entry); + + if (dbus_message_iter_get_arg_type(&entry) != + DBUS_TYPE_VARIANT) { + BT_ERR("ctype not DBUS_TYPE_VARIANT"); + return FALSE; + } + + dbus_message_iter_recurse(&entry, &var); + + BT_ERR("Key value is %s", key); + + if (strcasecmp(key, "Title") == 0) { + if (!__bt_avrcp_control_parse_metadata(&value_string, + &value_uint, DBUS_TYPE_STRING, &var)) + return BLUETOOTH_ERROR_INTERNAL; + BT_DBG("Value : %s ", value_string); + metadata->title = value_string; + } else if (strcasecmp(key, "Artist") == 0) { + if (!__bt_avrcp_control_parse_metadata(&value_string, + &value_uint, DBUS_TYPE_STRING, &var)) + return BLUETOOTH_ERROR_INTERNAL; + BT_DBG("Value : %s ", value_string); + metadata->artist = value_string; + } else if (strcasecmp(key, "Album") == 0) { + if (!__bt_avrcp_control_parse_metadata(&value_string, + &value_uint, DBUS_TYPE_STRING, &var)) + return BLUETOOTH_ERROR_INTERNAL; + BT_DBG("Value : %s ", value_string); + metadata->album = value_string; + } else if (strcasecmp(key, "Genre") == 0) { + if (!__bt_avrcp_control_parse_metadata(&value_string, + &value_uint, DBUS_TYPE_STRING, &var)) + return BLUETOOTH_ERROR_INTERNAL; + BT_DBG("Value : %s ", value_string); + metadata->genre = value_string; + } else if (strcasecmp(key, "Duration") == 0) { + if (!__bt_avrcp_control_parse_metadata(&value_string, + &value_uint, DBUS_TYPE_UINT32, &var)) + return BLUETOOTH_ERROR_INTERNAL; + metadata->duration = value_uint; + } else if (strcasecmp(key, "NumberOfTracks") == 0) { + if (!__bt_avrcp_control_parse_metadata(&value_string, + &value_uint, DBUS_TYPE_UINT32, &var)) + return BLUETOOTH_ERROR_INTERNAL; + metadata->total_tracks = value_uint; + } else if (strcasecmp(key, "TrackNumber") == 0) { + if (!__bt_avrcp_control_parse_metadata(&value_string, + &value_uint, DBUS_TYPE_UINT32, &var)) + return BLUETOOTH_ERROR_INTERNAL; + metadata->number = value_uint; + } else + BT_DBG("%s not supported, ignoring", key); + dbus_message_iter_next(&dict); + } + + if (!metadata->title) + metadata->title = g_strdup(""); + if (!metadata->artist) + metadata->artist = g_strdup(""); + if (!metadata->album) + metadata->album = g_strdup(""); + if (!metadata->genre) + metadata->genre = g_strdup(""); + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_avrcp_control_get_track_info(media_metadata_attributes_t *metadata) +{ + DBusMessage *msg; + DBusMessage *reply; + DBusError err; + DBusConnection *conn; + char *control_path; + char *interface_name; + char *property_name; + DBusMessageIter arr, iter; + int ret = BLUETOOTH_ERROR_NONE; + + retv_if(metadata == NULL, BLUETOOTH_ERROR_INTERNAL); + + conn = _bt_get_system_conn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + control_path = __bt_get_control_device_path(); + retv_if(control_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED); + BT_DBG("control_path %s", control_path); + + msg = dbus_message_new_method_call(BT_BLUEZ_NAME, control_path, + BT_PROPERTIES_INTERFACE, "Get"); + + retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL); + + interface_name = g_strdup(BT_PLAYER_CONTROL_INTERFACE); + property_name = g_strdup("Track"); + + dbus_message_append_args(msg, + DBUS_TYPE_STRING, &interface_name, + DBUS_TYPE_STRING, &property_name, + DBUS_TYPE_INVALID); + + dbus_error_init(&err); + reply = dbus_connection_send_with_reply_and_block(conn, + msg, -1, &err); + + g_free(interface_name); + g_free(property_name); + dbus_message_unref(msg); + + if (!reply) { + BT_ERR("Error in getting Metadata"); + if (dbus_error_is_set(&err)) { + BT_ERR("%s", err.message); + dbus_error_free(&err); + } + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_iter_init(reply, &iter); + dbus_message_iter_recurse(&iter, &arr); + + ret = __bt_avrcp_control_parse_properties(metadata, &arr); + dbus_message_unref(reply); + + BT_DBG("-"); + return ret; +} + +void _bt_handle_avrcp_control_event(DBusMessageIter *msg_iter, const char *path) +{ + DBusMessageIter value_iter; + DBusMessageIter dict_iter; + DBusMessageIter item_iter; + const char *property = NULL; + + dbus_message_iter_recurse(msg_iter, &item_iter); + + if (dbus_message_iter_get_arg_type(&item_iter) + != DBUS_TYPE_DICT_ENTRY) { + BT_ERR("This is bad format dbus"); + return; + } + + dbus_message_iter_recurse(&item_iter, &dict_iter); + + dbus_message_iter_get_basic(&dict_iter, &property); + ret_if(property == NULL); + + BT_DBG("property : %s ", property); + ret_if(!dbus_message_iter_next(&dict_iter)); + + if ((strcasecmp(property, "Equalizer") == 0) || + (strcasecmp(property, "Repeat") == 0) || + (strcasecmp(property, "Shuffle") == 0) || + (strcasecmp(property, "Scan") == 0) || + (strcasecmp(property, "Status") == 0)) { + + const char *valstr; + int type, value; + + dbus_message_iter_recurse(&dict_iter, &value_iter); + dbus_message_iter_get_basic(&value_iter, &valstr); + BT_DBG("Value : %s ", valstr); + type = __bt_media_attr_to_type(property); + value = __bt_media_attrval_to_val(type, valstr); + + /* Send event to application */ + _bt_send_event(BT_AVRCP_CONTROL_EVENT, + __bt_media_attr_to_event(property), + DBUS_TYPE_UINT32, &value, + DBUS_TYPE_INVALID); + } else if (strcasecmp(property, "Position") == 0) { + unsigned int value; + + dbus_message_iter_recurse(&dict_iter, &value_iter); + dbus_message_iter_get_basic(&value_iter, &value); + BT_DBG("Value : %d ", value); + + /* Send event to application */ + _bt_send_event(BT_AVRCP_CONTROL_EVENT, + __bt_media_attr_to_event(property), + DBUS_TYPE_UINT32, &value, + DBUS_TYPE_INVALID); + } else if (strcasecmp(property, "Track") == 0) { + int ret = BLUETOOTH_ERROR_NONE; + media_metadata_attributes_t metadata; + + dbus_message_iter_recurse(&dict_iter, &value_iter); + memset(&metadata, 0x00, sizeof(media_metadata_attributes_t)); + + ret = __bt_avrcp_control_parse_properties( + &metadata, &value_iter); + if (BLUETOOTH_ERROR_NONE != ret) + return; + + /* Send event to application */ + _bt_send_event(BT_AVRCP_CONTROL_EVENT, + BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED, + DBUS_TYPE_STRING, &metadata.title, + DBUS_TYPE_STRING, &metadata.artist, + DBUS_TYPE_STRING, &metadata.album, + DBUS_TYPE_STRING, &metadata.genre, + DBUS_TYPE_UINT32, &metadata.total_tracks, + DBUS_TYPE_UINT32, &metadata.number, + DBUS_TYPE_UINT32, &metadata.duration, + DBUS_TYPE_INVALID); + + g_free(metadata.title); + g_free(metadata.artist); + g_free(metadata.album); + g_free(metadata.genre); + } else { + BT_DBG("Preprty not handled"); + } + + BT_DBG("-"); +} diff --git a/bt-service/bt-service-common.c b/bt-service/bt-service-common.c old mode 100644 new mode 100755 index 028b455..d788de8 --- a/bt-service/bt-service-common.c +++ b/bt-service/bt-service-common.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -27,6 +31,7 @@ #include #include #include +#include #include "bluetooth-api.h" #include "bt-service-common.h" @@ -36,6 +41,8 @@ static DBusGConnection *system_conn; static DBusGConnection *session_conn; static DBusGProxy *manager_proxy; static DBusGProxy *adapter_proxy; +static void *net_conn; + static DBusGProxy *adapter_properties_proxy; static DBusGProxy *__bt_init_manager_proxy(void) @@ -63,6 +70,9 @@ static DBusGProxy *__bt_init_adapter_proxy(void) { DBusGProxy *manager_proxy; DBusGProxy *proxy; + char *adapter_path = NULL; + + g_type_init(); if (system_conn == NULL) { system_conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL); @@ -72,8 +82,13 @@ static DBusGProxy *__bt_init_adapter_proxy(void) manager_proxy = _bt_get_manager_proxy(); retv_if(manager_proxy == NULL, NULL); + adapter_path = _bt_get_adapter_path(); + retv_if(adapter_path == NULL, NULL); + proxy = dbus_g_proxy_new_for_name(system_conn, BT_BLUEZ_NAME, - BT_BLUEZ_HCI_PATH, BT_ADAPTER_INTERFACE); + adapter_path, BT_ADAPTER_INTERFACE); + + g_free(adapter_path); retv_if(proxy == NULL, NULL); @@ -86,6 +101,7 @@ static DBusGProxy *__bt_init_adapter_properties_proxy(void) { DBusGProxy *manager_proxy; DBusGProxy *proxy; + char *adapter_path = NULL; g_type_init(); @@ -97,8 +113,13 @@ static DBusGProxy *__bt_init_adapter_properties_proxy(void) manager_proxy = _bt_get_manager_proxy(); retv_if(manager_proxy == NULL, NULL); + adapter_path = _bt_get_adapter_path(); + retv_if(adapter_path == NULL, NULL); + proxy = dbus_g_proxy_new_for_name(system_conn, BT_BLUEZ_NAME, - BT_BLUEZ_HCI_PATH, BT_PROPERTIES_INTERFACE); + adapter_path, BT_PROPERTIES_INTERFACE); + + g_free(adapter_path); retv_if(proxy == NULL, NULL); @@ -152,48 +173,60 @@ DBusConnection *_bt_get_system_conn(void) DBusGProxy *_bt_get_manager_proxy(void) { - return (manager_proxy) ? manager_proxy : __bt_init_manager_proxy(); + if (manager_proxy) { + const char *path = dbus_g_proxy_get_path(manager_proxy); + if (path == NULL) { + BT_ERR("Already proxy released hence creating new proxy"); + return __bt_init_manager_proxy(); + } + return manager_proxy; + } + return __bt_init_manager_proxy(); } -DBusGProxy *_bt_get_adapter_proxy(void) +static void *__bt_init_net_conn(void) { - return (adapter_proxy) ? adapter_proxy : __bt_init_adapter_proxy(); + int result; + connection_h connection = NULL; + + if (net_conn == NULL) { + result = connection_create(&connection); + + if (result != CONNECTION_ERROR_NONE || + connection == NULL) { + BT_DBG("connection_create() failed: %d", result); + net_conn = NULL; + return NULL; + } + net_conn = connection; + } + return net_conn; } -DBusGProxy *_bt_get_adapter_properties_proxy(void) +void *_bt_get_net_conn(void) { - return (adapter_properties_proxy) ? adapter_properties_proxy : - __bt_init_adapter_properties_proxy(); + return (net_conn) ? net_conn : __bt_init_net_conn(); } -gboolean _bt_get_adapter_power(void) +DBusGProxy *_bt_get_adapter_proxy(void) { - DBusGProxy *proxy = NULL; - gboolean powered; - GValue powered_v = { 0 }; - GError *err = NULL; - - proxy = _bt_get_adapter_properties_proxy(); - retv_if(proxy == NULL, FALSE); - - if (!dbus_g_proxy_call(proxy, "Get", &err, - G_TYPE_STRING, BT_ADAPTER_INTERFACE, - G_TYPE_STRING, "Powered", - G_TYPE_INVALID, - G_TYPE_VALUE, &powered_v, - G_TYPE_INVALID)) { - if (err != NULL) { - BT_ERR("Getting property failed: [%s]\n", err->message); - g_error_free(err); + if (adapter_proxy) { + const char *path = dbus_g_proxy_get_path(adapter_proxy); + if (path == NULL) { + BT_ERR("Already proxy released hence creating new proxy"); + return __bt_init_adapter_proxy(); } - return FALSE; - } - powered = (gboolean)g_value_get_boolean(&powered_v); + return adapter_proxy; + } + return __bt_init_adapter_proxy(); - BT_DBG("powered = %d", powered); +} - return powered; +DBusGProxy *_bt_get_adapter_properties_proxy(void) +{ + return (adapter_properties_proxy) ? adapter_properties_proxy : + __bt_init_adapter_properties_proxy(); } static char *__bt_extract_adapter_path(DBusMessageIter *msg_iter) @@ -279,8 +312,9 @@ char *_bt_get_adapter_path(void) } if (dbus_message_iter_init(reply, &reply_iter) == FALSE) { - BT_ERR("Fail to iterate the reply"); - return NULL; + BT_ERR("Fail to iterate the reply"); + dbus_message_unref(reply); + return NULL; } dbus_message_iter_recurse(&reply_iter, &value_iter); @@ -300,6 +334,7 @@ char *_bt_get_adapter_path(void) dbus_message_iter_next(&value_iter); } + dbus_message_unref(reply); return adapter_path; } @@ -315,7 +350,6 @@ void _bt_deinit_bluez_proxy(void) g_object_unref(adapter_proxy); adapter_proxy = NULL; } - if (adapter_properties_proxy) { g_object_unref(adapter_properties_proxy); adapter_properties_proxy = NULL; @@ -324,7 +358,7 @@ void _bt_deinit_bluez_proxy(void) void _bt_deinit_proxys(void) { - + int ret; _bt_deinit_bluez_proxy(); if (system_conn) { @@ -337,6 +371,12 @@ void _bt_deinit_proxys(void) session_conn = NULL; } + if (net_conn) { + ret = connection_destroy(net_conn); + net_conn = NULL; + if (ret != 0) + BT_ERR("connection_destroy failed : %d", ret); + } } void _bt_convert_device_path_to_address(const char *device_path, @@ -374,7 +414,7 @@ void _bt_convert_addr_string_to_type(unsigned char *addr, for (i = 0; i < BT_ADDRESS_LENGTH_MAX; i++) { addr[i] = strtol(address, &ptr, 16); - if (ptr != NULL) { + if (ptr[0] != '\0') { if (ptr[0] != ':') return; @@ -424,6 +464,7 @@ void _bt_free_device_info(bt_remote_dev_info_t *dev_info) g_free(dev_info->address); g_free(dev_info->name); + g_free(dev_info->manufacturer_data); if (dev_info->uuids) { for (i = 0; dev_info->uuids[i] != NULL; i++) @@ -435,9 +476,67 @@ void _bt_free_device_info(bt_remote_dev_info_t *dev_info) g_free(dev_info); } -int _bt_register_osp_server_in_agent(int type, char *uuid) +void _bt_free_le_device_info(bt_remote_le_dev_info_t *le_dev_info) +{ + ret_if(le_dev_info == NULL); + + g_free(le_dev_info->adv_data); + g_free(le_dev_info); +} + +int _bt_copy_utf8_string(char *dest, const char *src, unsigned int length) +{ + int i; + const char *p = src; + char *next; + int count; + + if (dest == NULL || src == NULL) + return BLUETOOTH_ERROR_INVALID_PARAM; + + BT_DBG("+src : %s", src); + BT_DBG("+dest : %s", dest); + + i = 0; + while (*p != '\0' && i < length) { + next = g_utf8_next_char(p); + count = next - p; + + while (count > 0 && ((i + count) < length)) { + dest[i++] = *p; + p++; + count --; + } + p = next; + } + return BLUETOOTH_ERROR_NONE; +} + +gboolean _bt_utf8_validate(char *name) +{ + BT_DBG("+"); + gunichar2 *u16; + glong items_written = 0; + + if (FALSE == g_utf8_validate(name, -1, NULL)) + return FALSE; + + u16 = g_utf8_to_utf16(name, -1, NULL, &items_written, NULL); + if (u16 == NULL) + return FALSE; + + g_free(u16); + + if (items_written != g_utf8_strlen(name, -1)) + return FALSE; + + BT_DBG("-"); + return TRUE; +} + +int _bt_register_osp_server_in_agent(int type, char *uuid, char *path, int fd) { - if (!_bt_agent_register_osp_server( type, uuid)) + if (!_bt_agent_register_osp_server( type, uuid, path, fd)) return BLUETOOTH_ERROR_INTERNAL; return BLUETOOTH_ERROR_NONE; @@ -494,37 +593,6 @@ int _bt_set_non_blocking_tty(int sk) return BLUETOOTH_ERROR_NONE; } -gboolean _bt_is_headset_class(int dev_class) -{ - gboolean is_headset = 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; - } - - return is_headset; -} - static char *__bt_extract_device_path(DBusMessageIter *msg_iter, char *address) { char *object_path = NULL; @@ -583,8 +651,9 @@ char *_bt_get_device_object_path(char *address) } if (dbus_message_iter_init(reply, &reply_iter) == FALSE) { - BT_ERR("Fail to iterate the reply"); - return NULL; + BT_ERR("Fail to iterate the reply"); + dbus_message_unref(reply); + return NULL; } dbus_message_iter_recurse(&reply_iter, &value_iter); @@ -604,7 +673,149 @@ char *_bt_get_device_object_path(char *address) dbus_message_iter_next(&value_iter); } + dbus_message_unref(reply); return object_path; } +char *_bt_get_profile_uuid128(bt_profile_type_t profile_type) +{ + switch(profile_type) { + case BT_PROFILE_CONN_RFCOMM: + return strdup(RFCOMM_UUID_STR); + case BT_PROFILE_CONN_A2DP: + return strdup(A2DP_SINK_UUID); + case BT_PROFILE_CONN_HSP: + return strdup(HFP_HS_UUID); + case BT_PROFILE_CONN_HID: + return strdup(HID_UUID); + case BT_PROFILE_CONN_NAP: + return strdup(NAP_UUID); + case BT_PROFILE_CONN_HFG: + return strdup(HFP_AG_UUID); + case BT_PROFILE_CONN_GATT: + case BT_PROFILE_CONN_ALL: /* NULL UUID will connect to both the audio profiles*/ + default: + return NULL; + }; +} + +char *_bt_convert_error_to_string(int error) +{ + switch (error) { + case BLUETOOTH_ERROR_CANCEL: + return "CANCELLED"; + case BLUETOOTH_ERROR_INVALID_PARAM: + return "INVALID_PARAMETER"; + case BLUETOOTH_ERROR_INVALID_DATA: + return "INVALID DATA"; + case BLUETOOTH_ERROR_MEMORY_ALLOCATION: + case BLUETOOTH_ERROR_OUT_OF_MEMORY: + return "OUT_OF_MEMORY"; + case BLUETOOTH_ERROR_TIMEOUT: + return "TIMEOUT"; + case BLUETOOTH_ERROR_NO_RESOURCES: + return "NO_RESOURCES"; + case BLUETOOTH_ERROR_INTERNAL: + return "INTERNAL"; + case BLUETOOTH_ERROR_NOT_SUPPORT: + return "NOT_SUPPORT"; + case BLUETOOTH_ERROR_DEVICE_NOT_ENABLED: + return "NOT_ENABLED"; + case BLUETOOTH_ERROR_DEVICE_ALREADY_ENABLED: + return "ALREADY_ENABLED"; + case BLUETOOTH_ERROR_DEVICE_BUSY: + return "DEVICE_BUSY"; + case BLUETOOTH_ERROR_ACCESS_DENIED: + return "ACCESS_DENIED"; + case BLUETOOTH_ERROR_MAX_CLIENT: + return "MAX_CLIENT"; + case BLUETOOTH_ERROR_NOT_FOUND: + return "NOT_FOUND"; + case BLUETOOTH_ERROR_SERVICE_SEARCH_ERROR: + return "SERVICE_SEARCH_ERROR"; + case BLUETOOTH_ERROR_PARING_FAILED: + return "PARING_FAILED"; + case BLUETOOTH_ERROR_NOT_PAIRED: + return "NOT_PAIRED"; + case BLUETOOTH_ERROR_SERVICE_NOT_FOUND: + return "SERVICE_NOT_FOUND"; + case BLUETOOTH_ERROR_NOT_CONNECTED: + return "NOT_CONNECTED"; + case BLUETOOTH_ERROR_ALREADY_CONNECT: + return "ALREADY_CONNECT"; + case BLUETOOTH_ERROR_CONNECTION_BUSY: + return "CONNECTION_BUSY"; + case BLUETOOTH_ERROR_CONNECTION_ERROR: + return "CONNECTION_ERROR"; + case BLUETOOTH_ERROR_MAX_CONNECTION: + return "MAX_CONNECTION"; + case BLUETOOTH_ERROR_NOT_IN_OPERATION: + return "NOT_IN_OPERATION"; + case BLUETOOTH_ERROR_CANCEL_BY_USER: + return "CANCEL_BY_USER"; + case BLUETOOTH_ERROR_REGISTRATION_FAILED: + return "REGISTRATION_FAILED"; + case BLUETOOTH_ERROR_IN_PROGRESS: + return "IN_PROGRESS"; + case BLUETOOTH_ERROR_AUTHENTICATION_FAILED: + return "AUTHENTICATION_FAILED"; + case BLUETOOTH_ERROR_HOST_DOWN: + return "HOST_DOWN"; + case BLUETOOTH_ERROR_END_OF_DEVICE_LIST: + return "END_OF_DEVICE_LIST"; + case BLUETOOTH_ERROR_AGENT_ALREADY_EXIST: + return "AGENT_ALREADY_EXIST"; + case BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST: + return "AGENT_DOES_NOT_EXIST"; + case BLUETOOTH_ERROR_ALREADY_INITIALIZED: + return "ALREADY_INITIALIZED"; + case BLUETOOTH_ERROR_PERMISSION_DEINED: + return "PERMISSION_DEINED"; + case BLUETOOTH_ERROR_ALREADY_DEACTIVATED: + return "ALREADY_DEACTIVATED"; + case BLUETOOTH_ERROR_NOT_INITIALIZED: + return "NOT_INITIALIZED"; + default: + return "UNKNOWN"; + } +} + +char * _bt_convert_disc_reason_to_string(int reason) +{ + switch(reason) { + case 1: + return "Link loss"; + case 2: + return "Connection terminated by local host"; + case 3: + return "Remote user terminated connection"; + case 0: + default: + return "Unknown"; + } +} + +void _bt_logging_connection(gboolean connect, int addr_type) +{ + static int le_conn = 0; + static int le_disc = 0; + static int edr_conn = 0; + static int edr_disc = 0; + + if (connect) { + if (addr_type) + le_conn++; + else + edr_conn++; + } else { + if (addr_type) + le_disc++; + else + edr_disc++; + } + + BT_INFO("[PM] Number of LE conn: %d disc: %d, Number of BR/EDR conn: %d disc: %d", + le_conn, le_disc, edr_conn, edr_disc); +} + diff --git a/bt-service/bt-service-device.c b/bt-service/bt-service-device.c old mode 100644 new mode 100755 index 6c68d6a..54060f3 --- a/bt-service/bt-service-device.c +++ b/bt-service/bt-service-device.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -22,9 +26,7 @@ #include #include #include -#if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT) #include -#endif #include "bluetooth-api.h" #include "bt-internal-types.h" @@ -35,16 +37,32 @@ #include "bt-service-rfcomm-client.h" #include "bt-service-util.h" #include "bt-service-agent.h" +#include "bt-service-network.h" +#include "bt-service-adapter.h" + +#define BT_SYSPOPUP_IPC_RESPONSE_OBJECT "/org/projectx/bt_syspopup_res" +#define BT_SYSPOPUP_INTERFACE "User.Bluetooth.syspopup" +#define BT_SYSPOPUP_METHOD_RESPONSE "Response" + +#define BT_LE_CONN_INTERVAL_MIN 7.5 /* msec */ +#define BT_LE_CONN_INTERVAL_MAX 4000 /* msec */ +#define BT_LE_CONN_SUPER_TO_MIN 100 /* msec */ +#define BT_LE_CONN_SUPER_TO_MAX 32000 /* msec */ +#define BT_LE_CONN_INTERVAL_SPLIT 1.25 /* msec */ +#define BT_LE_CONN_TO_SPLIT 10 /* msec */ typedef struct { int req_id; + int result; char *addr; gboolean is_autopair; DBusGProxy *device_proxy; DBusGProxy *adapter_proxy; + void *agent; + unsigned short conn_type; } bt_funcion_data_t; -gboolean is_deivce_creating; +gboolean is_device_creating; bt_funcion_data_t *bonding_info; bt_funcion_data_t *searching_info; @@ -54,10 +72,158 @@ bt_funcion_data_t *searching_info; static void __bt_bond_device_cb(DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data); +static int __bt_retry_bond(void); + + +static void __bt_decline_pair_request() +{ + GArray *out_param1; + GArray *out_param2; + request_info_t *req_info; + bluetooth_device_info_t dev_info; + bt_remote_dev_info_t *remote_dev_info; + + BT_DBG("+"); + if (bonding_info) { + req_info = _bt_get_request_info(bonding_info->req_id); + if (req_info == NULL) { + BT_ERR("req_info == NULL"); + goto done; + } + remote_dev_info = _bt_get_remote_device_info(bonding_info->addr); + } else { + BT_DBG("bonding_info is NULL"); + BT_DBG("-"); + return; + } + + + + /* Send the event to application */ + if (remote_dev_info != NULL) { + _bt_send_event(BT_ADAPTER_EVENT, + BLUETOOTH_EVENT_BONDING_FINISHED, + DBUS_TYPE_INT32, &bonding_info->result, + DBUS_TYPE_STRING, &bonding_info->addr, + DBUS_TYPE_UINT32, &remote_dev_info->class, + DBUS_TYPE_INT16, &remote_dev_info->rssi, + DBUS_TYPE_STRING, &remote_dev_info->name, + DBUS_TYPE_BOOLEAN, &remote_dev_info->paired, + DBUS_TYPE_BOOLEAN, &remote_dev_info->connected, + DBUS_TYPE_BOOLEAN, &remote_dev_info->trust, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, + &remote_dev_info->uuids, remote_dev_info->uuid_count, + DBUS_TYPE_INT16, &remote_dev_info->manufacturer_data_len, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &remote_dev_info->manufacturer_data, remote_dev_info->manufacturer_data_len, + DBUS_TYPE_INVALID); + + _bt_free_device_info(remote_dev_info); + } + + if (req_info->context == NULL) + goto done; + + out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar)); + out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar)); + + memset(&dev_info, 0x00, sizeof(bluetooth_device_info_t)); + _bt_convert_addr_string_to_type(dev_info.device_address.addr, + bonding_info->addr); + + g_array_append_vals(out_param1, &dev_info, + sizeof(bluetooth_device_info_t)); + g_array_append_vals(out_param2, &bonding_info->result, sizeof(int)); + + dbus_g_method_return(req_info->context, out_param1, out_param2); + + g_array_free(out_param1, TRUE); + g_array_free(out_param2, TRUE); + + _bt_delete_request_list(req_info->req_id); +done: + + g_free(bonding_info->addr); + g_free(bonding_info); + bonding_info = NULL; + + BT_DBG("-"); +} + +#ifdef TIZEN_WEARABLE +static gboolean __bt_syspopup_timer_cb(gpointer user_data) +{ + int ret; + bundle *b; + retv_if(user_data == NULL, FALSE); + + b = (bundle *)user_data; + + ret = syspopup_launch("bt-syspopup", b); + if (ret < 0) { + BT_ERR("Sorry!! Cannot launch popup return = %d, Retrying...", ret); + } else { + BT_DBG("Hurray!!! Finally Popup launched"); + bundle_free(b); + } + return (ret < 0) ? TRUE : FALSE; +} + +static gboolean __bt_launch_unable_to_pairing_syspopup(int result) +{ + BT_DBG("+"); + int ret = 0; + bundle *b = NULL; + DBusGConnection *conn; + + conn = _bt_get_system_gconn(); + if (conn == NULL) + return FALSE; + + b = bundle_create(); + if (b == NULL) + return FALSE; + + bundle_add(b, "event-type", "unable-to-pairing"); + + if (result == BLUETOOTH_ERROR_TIMEOUT ) + bundle_add(b, "error", "timeout"); + else if (result == BLUETOOTH_ERROR_AUTHENTICATION_FAILED) + bundle_add(b, "error", "authfailed"); + else + bundle_add(b, "error", "error"); + + ret = syspopup_launch("bt-syspopup", b); + if (0 > ret) { + BT_ERR("Popup launch failed...retry %d \n", ret); + g_timeout_add(200, (GSourceFunc) __bt_syspopup_timer_cb, + b); + } else { + bundle_free(b); + } + + BT_DBG("-"); + return TRUE; +} +#endif gboolean _bt_is_device_creating(void) { - return is_deivce_creating; + return is_device_creating; +} + +gboolean _bt_is_bonding_device_address(const char *address) +{ + if (bonding_info == NULL || bonding_info->addr == NULL) + return FALSE; + + if (g_strcmp0(bonding_info->addr, address) == 0) { + BT_DBG("[%s] is bonding device", address); + return TRUE; + } + + BT_DBG("[%s] is NOT bonding device", address); + return FALSE; } void _bt_set_autopair_status_in_bonding_info(gboolean is_autopair) @@ -127,11 +293,6 @@ void __bt_cancel_search_service_done(void) _bt_delete_request_list(req_info->req_id); done: - if (searching_info->device_proxy) - g_object_unref(searching_info->device_proxy); - - if (searching_info->adapter_proxy) - g_object_unref(searching_info->adapter_proxy); g_free(searching_info->addr); g_free(searching_info); @@ -174,6 +335,7 @@ bt_remote_dev_info_t *_bt_get_remote_device_info(char *address) GHashTable *hash = NULL; GValue *value; const gchar *name; + GByteArray *manufacturer_data = NULL; DBusGConnection *conn; retv_if(address == NULL, NULL); @@ -181,6 +343,7 @@ bt_remote_dev_info_t *_bt_get_remote_device_info(char *address) adapter_proxy = _bt_get_adapter_proxy(); retv_if(adapter_proxy == NULL, NULL); + object_path = _bt_get_device_object_path(address); retv_if(object_path == NULL, NULL); @@ -199,7 +362,7 @@ bt_remote_dev_info_t *_bt_get_remote_device_info(char *address) dbus_g_proxy_call(device_proxy, "GetAll", NULL, G_TYPE_STRING, BT_DEVICE_INTERFACE, - G_TYPE_INVALID, + G_TYPE_INVALID, dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), &hash, G_TYPE_INVALID); @@ -212,7 +375,7 @@ bt_remote_dev_info_t *_bt_get_remote_device_info(char *address) name = value ? g_value_get_string(value) : NULL; if (name != NULL) - BT_DBG("Alias Name [%s]", name); + DBG_SECURE("Alias Name [%s]", name); else { value = g_hash_table_lookup(hash, "Name"); name = value ? g_value_get_string(value) : NULL; @@ -227,18 +390,40 @@ bt_remote_dev_info_t *_bt_get_remote_device_info(char *address) value = g_hash_table_lookup(hash, "Trusted"); dev_info->trust = value ? g_value_get_boolean(value) : FALSE; + value = g_hash_table_lookup(hash, "Paired"); + dev_info->paired = value ? g_value_get_boolean(value) : FALSE; + + BT_DBG("Paired %d", dev_info->paired ); + value = g_hash_table_lookup(hash, "RSSI"); dev_info->rssi = value ? g_value_get_int(value) : 0; + value = g_hash_table_lookup(hash, "LastAddrType"); + dev_info->addr_type = value ? g_value_get_uchar(value) : 0; + value = g_hash_table_lookup(hash, "UUIDs"); __bt_get_uuids(value, dev_info); + value = g_hash_table_lookup(hash, "ManufacturerDataLen"); + dev_info->manufacturer_data_len = value ? g_value_get_uint(value) : 0; + if (dev_info->manufacturer_data_len > BLUETOOTH_MANUFACTURER_DATA_LENGTH_MAX) { + BT_ERR("manufacturer_data_len is too long(len = %d)", dev_info->manufacturer_data_len); + dev_info->manufacturer_data_len = BLUETOOTH_MANUFACTURER_DATA_LENGTH_MAX; + } + + value = g_hash_table_lookup(hash, "ManufacturerData"); + manufacturer_data = value ? g_value_get_boxed(value) : NULL; + if (manufacturer_data) { + if (dev_info->manufacturer_data_len > 0) { + BT_DBG("manufacturer_data_len = %d", dev_info->manufacturer_data_len); + dev_info->manufacturer_data = g_malloc0(dev_info->manufacturer_data_len); + memcpy(dev_info->manufacturer_data, manufacturer_data->data, dev_info->manufacturer_data_len); + } + } + dev_info->address = g_strdup(address); dev_info->name = g_strdup(name); - value = g_hash_table_lookup(hash, "Paired"); - dev_info->paired = value ? g_value_get_boolean(value) : FALSE; - g_hash_table_destroy(hash); } else { BT_ERR("Hash is NULL\n"); @@ -273,7 +458,7 @@ static gboolean __ignore_auto_pairing_request(const char *address) fp = fopen(BT_AGENT_AUTO_PAIR_BLACKLIST_FILE, "r"); if (fp == NULL) { - BT_DBG("fopen failed \n"); + BT_ERR("fopen failed \n"); return FALSE; } @@ -282,7 +467,7 @@ static gboolean __ignore_auto_pairing_request(const char *address) rewind(fp); if (size < 0) { - BT_DBG("Get file size failed \n"); + BT_ERR("Get file size failed \n"); fclose(fp); return FALSE; } @@ -291,7 +476,7 @@ static gboolean __ignore_auto_pairing_request(const char *address) result = fread((char *)buffer, 1, size, fp); fclose(fp); if (result != size) { - BT_DBG("Read Error\n"); + BT_ERR("Read Error\n"); g_free(buffer); return FALSE; } @@ -318,7 +503,7 @@ static gboolean __ignore_auto_pairing_request(const char *address) fp = fopen(BT_AGENT_AUTO_PAIR_BLACKLIST_FILE, "w"); if (fp == NULL) { - BT_DBG("fopen failed \n"); + BT_ERR("fopen failed \n"); g_free(buffer); return FALSE; } @@ -336,48 +521,29 @@ static gboolean __ignore_auto_pairing_request(const char *address) static int __bt_retry_bond(void) { - DBusGProxy *device_proxy; - char *device_path; - DBusGConnection *conn; - BT_CHECK_PARAMETER(bonding_info, return); BT_CHECK_PARAMETER(bonding_info->addr, return); - conn = _bt_get_system_gconn(); - retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); - - device_path = _bt_get_device_object_path(bonding_info->addr); - - if (device_path == NULL) { - BT_ERR("No searched device"); - return BLUETOOTH_ERROR_NOT_PAIRED; - } - - if (bonding_info->device_proxy) { - device_proxy = bonding_info->device_proxy; - } else { - device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, - device_path, BT_DEVICE_INTERFACE); - } - - g_free(device_path); - retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - - is_deivce_creating = TRUE; - bonding_info->device_proxy = device_proxy; - - if (!dbus_g_proxy_begin_call_with_timeout(device_proxy, "Pair", + if (!dbus_g_proxy_begin_call_with_timeout(bonding_info->device_proxy, + "Pair", (DBusGProxyCallNotify) __bt_bond_device_cb, NULL, NULL, BT_MAX_DBUS_TIMEOUT, - G_TYPE_INVALID, + G_TYPE_UCHAR, bonding_info->conn_type, G_TYPE_INVALID)) { - BT_ERR("Pair call fail"); - is_deivce_creating = FALSE; - g_object_unref(device_proxy); - return BLUETOOTH_ERROR_INTERNAL; + BT_ERR("RePair call fail"); + + g_object_unref(bonding_info->device_proxy); + goto fail; } + return BLUETOOTH_ERROR_NONE; + +fail: + __bt_decline_pair_request(); + is_device_creating = FALSE; + + return BLUETOOTH_ERROR_INTERNAL; } @@ -393,16 +559,20 @@ static int __bt_remove_and_bond(void) adapter_proxy = _bt_get_adapter_proxy(); retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - device_path = _bt_get_device_object_path(bonding_info->addr); + dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL, + G_TYPE_STRING, bonding_info->addr, + G_TYPE_INVALID, DBUS_TYPE_G_OBJECT_PATH, + &device_path, + G_TYPE_INVALID); - retv_if (device_path == NULL, BLUETOOTH_ERROR_INTERNAL); + retv_if(device_path == NULL, BLUETOOTH_ERROR_INTERNAL); - dbus_g_proxy_call(adapter_proxy, "RemoveDevice", + dbus_g_proxy_call(adapter_proxy, "UnpairDevice", &err, DBUS_TYPE_G_OBJECT_PATH, device_path, G_TYPE_INVALID, G_TYPE_INVALID); g_free(device_path); if (err != NULL) { - BT_ERR("RemoveDevice Fail: %s", err->message); + BT_ERR("UnpairDevice Fail: %s", err->message); g_error_free(err); return BLUETOOTH_ERROR_INTERNAL; } @@ -412,12 +582,13 @@ static int __bt_remove_and_bond(void) static int __bt_cancel_and_bond(void) { - BT_CHECK_PARAMETER(bonding_info, return); - BT_CHECK_PARAMETER(bonding_info->device_proxy, return); + int ret = BLUETOOTH_ERROR_NONE; - dbus_g_proxy_call_no_reply(bonding_info->device_proxy, - "CancelPairing", - G_TYPE_INVALID, G_TYPE_INVALID); + ret = _bt_agent_reply_cancellation(); + if (ret != BLUETOOTH_ERROR_NONE){ + BT_ERR("Fail to call reply cancellation"); + return ret; + } return __bt_retry_bond(); } @@ -435,15 +606,12 @@ static void __bt_bond_device_cb(DBusGProxy *proxy, DBusGProxyCall *call, bt_remote_dev_info_t *remote_dev_info; /* Terminate ALL system popup */ -#if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT) syspopup_destroy_all(); -#endif dbus_g_proxy_end_call(proxy, call, &err, G_TYPE_INVALID); - g_object_unref(proxy); - is_deivce_creating = FALSE; + is_device_creating = FALSE; if (bonding_info == NULL) { /* Send reply */ @@ -453,8 +621,6 @@ static void __bt_bond_device_cb(DBusGProxy *proxy, DBusGProxyCall *call, return; } - bonding_info->device_proxy = NULL; - req_info = _bt_get_request_info(bonding_info->req_id); if (req_info == NULL) { BT_ERR("req_info == NULL"); @@ -462,20 +628,20 @@ static void __bt_bond_device_cb(DBusGProxy *proxy, DBusGProxyCall *call, } if (err != NULL) { - BT_ERR("Error occured in Pair [%s]", err->message); + BT_ERR("Error occured in CreateBonding [%s]", err->message); if (!strcmp(err->message, "Already Exists")) { - BT_DBG("Existing Bond, remove and retry"); + BT_INFO("Existing Bond, remove and retry"); ret_if(__bt_remove_and_bond() == BLUETOOTH_ERROR_NONE); result = BLUETOOTH_ERROR_PARING_FAILED; + } else if (_bt_agent_is_canceled() || + !strcmp(err->message, "Authentication Canceled")) { + result = BLUETOOTH_ERROR_CANCEL_BY_USER; } else if (!strcmp(err->message, "Authentication Rejected")) { result = BLUETOOTH_ERROR_ACCESS_DENIED; -// } else if (_bt_agent_is_canceled(bonding_info->agent) || -// !strcmp(err->message, "Authentication Canceled")) { -// result = BLUETOOTH_ERROR_CANCEL_BY_USER; } else if (!strcmp(err->message, "In Progress")) { - BT_DBG("Bond in progress, cancel and retry"); + BT_INFO("Bond in progress, cancel and retry"); ret_if(__bt_cancel_and_bond() == BLUETOOTH_ERROR_NONE); result = BLUETOOTH_ERROR_PARING_FAILED; @@ -497,12 +663,32 @@ static void __bt_bond_device_cb(DBusGProxy *proxy, DBusGProxyCall *call, G_TYPE_STRING, bonding_info->addr, G_TYPE_INVALID, G_TYPE_INVALID); + result = BLUETOOTH_ERROR_INTERNAL; + } else if (!strcmp(err->message, "Connection Timeout")) { + /* Pairing request timeout */ + result = BLUETOOTH_ERROR_TIMEOUT; + } else if (!strcmp(err->message, "Authentication Timeout")) { + /* Pairing request timeout */ result = BLUETOOTH_ERROR_TIMEOUT; } else { + BT_DBG("Default case"); result = BLUETOOTH_ERROR_PARING_FAILED; } } + if (result == BLUETOOTH_ERROR_PARING_FAILED || + result == BLUETOOTH_ERROR_AUTHENTICATION_FAILED || + result == BLUETOOTH_ERROR_TIMEOUT || + result == BLUETOOTH_ERROR_HOST_DOWN) { + bonding_info->result = result; +#ifdef TIZEN_WEARABLE + __bt_launch_unable_to_pairing_syspopup(result); +#endif + } + + g_object_unref(proxy); + bonding_info->device_proxy = NULL; + if (result != BLUETOOTH_ERROR_NONE) goto dbus_return; @@ -522,6 +708,9 @@ static void __bt_bond_device_cb(DBusGProxy *proxy, DBusGProxyCall *call, DBUS_TYPE_BOOLEAN, &remote_dev_info->trust, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &remote_dev_info->uuids, remote_dev_info->uuid_count, + DBUS_TYPE_INT16, &remote_dev_info->manufacturer_data_len, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &remote_dev_info->manufacturer_data, remote_dev_info->manufacturer_data_len, DBUS_TYPE_INVALID); _bt_free_device_info(remote_dev_info); @@ -538,6 +727,9 @@ dbus_return: _bt_convert_addr_string_to_type(dev_info.device_address.addr, bonding_info->addr); + if (_bt_adapter_get_status() != BT_ACTIVATED) + result = BLUETOOTH_ERROR_NOT_IN_OPERATION; + g_array_append_vals(out_param1, &dev_info, sizeof(bluetooth_device_info_t)); g_array_append_vals(out_param2, &result, sizeof(int)); @@ -552,26 +744,39 @@ done: if (err) g_error_free(err); + _bt_agent_set_canceled(FALSE); + + g_free(bonding_info->addr); g_free(bonding_info); bonding_info = NULL; - } int _bt_bond_device(int request_id, bluetooth_device_address_t *device_address, - GArray **out_param1) + unsigned short conn_type, GArray **out_param1) { DBusGProxy *proxy; char address[BT_ADDRESS_STRING_SIZE] = { 0 }; bluetooth_device_info_t dev_info; + DBusGConnection *conn; char *device_path = NULL; + DBusGProxy *adapter_proxy; + GError *error = NULL; BT_CHECK_PARAMETER(device_address, return); if (bonding_info) { BT_ERR("Bonding in progress"); + + memset(&dev_info, 0x00, sizeof(bluetooth_device_info_t)); + memcpy(dev_info.device_address.addr, device_address->addr, + BLUETOOTH_ADDRESS_LENGTH); + + g_array_append_vals(*out_param1, &dev_info, + sizeof(bluetooth_device_info_t)); + return BLUETOOTH_ERROR_DEVICE_BUSY; } @@ -584,7 +789,32 @@ int _bt_bond_device(int request_id, if (device_path == NULL) { BT_ERR("No searched device"); - return BLUETOOTH_ERROR_NOT_PAIRED; + + adapter_proxy = _bt_get_adapter_proxy(); + retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call(adapter_proxy, "CreateDevice", &error, + G_TYPE_STRING, address, + G_TYPE_INVALID, G_TYPE_INVALID); + + if (error != NULL) { + BT_ERR("CreateDevice Fail: %s", error->message); + g_error_free(error); + } + + device_path = _bt_get_device_object_path(address); + if (device_path == NULL) { + memset(&dev_info, 0x00, sizeof(bluetooth_device_info_t)); + memcpy(dev_info.device_address.addr, device_address->addr, + BLUETOOTH_ADDRESS_LENGTH); + + g_array_append_vals(*out_param1, &dev_info, + sizeof(bluetooth_device_info_t)); + + return BLUETOOTH_ERROR_NOT_PAIRED; + } else { + BT_INFO("device_path is created[%s]", device_path); + } } proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, @@ -596,52 +826,23 @@ int _bt_bond_device(int request_id, bonding_info = g_malloc0(sizeof(bt_funcion_data_t)); bonding_info->addr = g_strdup(address); bonding_info->req_id = request_id; + bonding_info->device_proxy = proxy; + bonding_info->conn_type = conn_type; - is_deivce_creating = TRUE; + is_device_creating = TRUE; if (!dbus_g_proxy_begin_call_with_timeout(proxy, "Pair", (DBusGProxyCallNotify) __bt_bond_device_cb, NULL, NULL, BT_MAX_DBUS_TIMEOUT, - G_TYPE_INVALID, + G_TYPE_UCHAR, conn_type, G_TYPE_INVALID)) { BT_ERR("Pair call fail"); g_object_unref(proxy); + bonding_info->device_proxy = NULL; goto fail; } - - -/* To Do: We need to check if we can pair the specific device using 'pair' API of bluez 5.x */ -#if 0 - if (!strncmp(address, SMB_MOUSE_LAP_ADDR, strlen(SMB_MOUSE_LAP_ADDR))) { - bluetooth_device_address_t device_addr = { {0} }; - BT_ERR("This device don't support pairing. So skip pairing."); - if (!dbus_g_proxy_begin_call(proxy, "CreateDevice", - (DBusGProxyCallNotify)__bt_bond_device_cb, - NULL, NULL, - G_TYPE_STRING, device_addr, - G_TYPE_INVALID)) { - BT_ERR("CreateDevice failed"); - goto fail; - } - - _bt_convert_addr_string_to_type(device_addr.addr, address); - if (_bt_set_authorization(&device_addr, TRUE)) - BT_ERR("_bt_set_authorization failed [%s]", address); - - } else { - if (!dbus_g_proxy_begin_call_with_timeout(proxy, "CreatePairedDevice", - (DBusGProxyCallNotify) __bt_bond_device_cb, - NULL, NULL, BT_MAX_DBUS_TIMEOUT, - G_TYPE_STRING, address, - DBUS_TYPE_G_OBJECT_PATH, BT_DEVICE_AGENT_PATH, - G_TYPE_STRING, "DisplayYesNo", - G_TYPE_INVALID)) { - BT_ERR("CreatePairedDevice call fail"); - goto fail; - } - } -#endif +/* TODO: We need to check if we can pair the specific device using 'pair' API of bluez 5.x */ return BLUETOOTH_ERROR_NONE; fail: @@ -652,7 +853,7 @@ fail: g_array_append_vals(*out_param1, &dev_info, sizeof(bluetooth_device_info_t)); - is_deivce_creating = FALSE; + is_device_creating = FALSE; g_free(bonding_info->addr); g_free(bonding_info); @@ -663,13 +864,17 @@ fail: int _bt_cancel_bonding(void) { + int ret = BLUETOOTH_ERROR_NONE; + retv_if(bonding_info == NULL, BLUETOOTH_ERROR_NOT_IN_OPERATION); - retv_if(bonding_info->device_proxy == NULL, - BLUETOOTH_ERROR_NOT_IN_OPERATION); - dbus_g_proxy_call_no_reply(bonding_info->device_proxy, - "CancelPairing", - G_TYPE_INVALID, G_TYPE_INVALID); + ret = _bt_agent_reply_cancellation(); + if (ret != BLUETOOTH_ERROR_NONE){ + BT_ERR("Fail to call reply cancellation"); + return ret; + } + + _bt_agent_set_canceled(TRUE); return BLUETOOTH_ERROR_NONE; } @@ -704,10 +909,8 @@ static void __bt_unbond_cb(DBusGProxy *proxy, DBusGProxyCall *call, if (err != NULL) { BT_ERR("Error occured in RemoveBonding [%s]\n", err->message); result = BLUETOOTH_ERROR_INTERNAL; - goto dbus_return; } -dbus_return: if (req_info->context == NULL) goto done; @@ -745,9 +948,13 @@ int _bt_unbond_device(int request_id, { char *device_path = NULL; bt_funcion_data_t *unbonding_info; - DBusGProxy *adapter_proxy; + DBusGProxy *adapter_proxy = NULL; + DBusGProxy *device_proxy = NULL; + DBusGConnection *conn; int result = BLUETOOTH_ERROR_INTERNAL; bluetooth_device_info_t dev_info; + GValue paired = { 0 }; + GError *error = NULL; BT_CHECK_PARAMETER(device_address, return); @@ -770,7 +977,38 @@ int _bt_unbond_device(int request_id, goto fail; } - if (!dbus_g_proxy_begin_call(adapter_proxy, "RemoveDevice", + conn = _bt_get_system_gconn(); + if (conn == NULL) { + BT_ERR("conn is NULL"); + result = BLUETOOTH_ERROR_INTERNAL; + goto fail; + } + + device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + device_path, BT_PROPERTIES_INTERFACE); + if (device_proxy != NULL) { + if (!dbus_g_proxy_call(device_proxy, "Get", &error, + G_TYPE_STRING, BT_DEVICE_INTERFACE, + G_TYPE_STRING, "Paired", + G_TYPE_INVALID, + G_TYPE_VALUE, &paired, + G_TYPE_INVALID)) { + if (error != NULL) { + BT_ERR("Getting property failed: [%s]\n", error->message); + g_error_free(error); + } + } else { + if (g_value_get_boolean(&paired) == FALSE) { + BT_ERR("No paired device"); + g_object_unref(device_proxy); + result = BLUETOOTH_ERROR_NOT_PAIRED; + goto fail; + } + } + g_object_unref(device_proxy); + } + + if (!dbus_g_proxy_begin_call(adapter_proxy, "UnpairDevice", (DBusGProxyCallNotify) __bt_unbond_cb, (gpointer)unbonding_info, NULL, DBUS_TYPE_G_OBJECT_PATH, device_path, @@ -801,21 +1039,20 @@ static void __bt_discover_cb(DBusGProxy *proxy, DBusGProxyCall *call, GHashTable *hash = NULL; GArray *out_param1; GArray *out_param2; - GValue uuid_v = { 0 }; int result = BLUETOOTH_ERROR_NONE; bluetooth_device_info_t dev_info; bt_remote_dev_info_t *remote_dev_info; request_info_t *req_info; dbus_g_proxy_end_call(proxy, call, &err, - G_TYPE_VALUE, &uuid_v, + dbus_g_type_get_map("GHashTable", G_TYPE_UINT, G_TYPE_STRING), &hash, G_TYPE_INVALID); g_object_unref(proxy); if (searching_info == NULL) { /* Send reply */ - BT_ERR("searching_info == NULL"); + BT_ERR("unbonding_info == NULL"); goto done; } @@ -868,6 +1105,9 @@ event: DBUS_TYPE_BOOLEAN, &remote_dev_info->trust, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &remote_dev_info->uuids, remote_dev_info->uuid_count, + DBUS_TYPE_INT16, &remote_dev_info->manufacturer_data_len, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &remote_dev_info->manufacturer_data, remote_dev_info->manufacturer_data_len, DBUS_TYPE_INVALID); _bt_free_device_info(remote_dev_info); @@ -907,117 +1147,26 @@ done: } } -static void __bt_create_device_cb(DBusGProxy *proxy, DBusGProxyCall *call, - gpointer user_data) +int _bt_search_device(int request_id, + bluetooth_device_address_t *device_address) { - GError *err = NULL; char *device_path = NULL; - GArray *out_param1; - GArray *out_param2; - int result = BLUETOOTH_ERROR_NONE; - bluetooth_device_info_t dev_info; - bt_remote_dev_info_t *remote_dev_info; - request_info_t *req_info; + DBusGProxy *device_proxy = NULL; + DBusGConnection *conn; - is_deivce_creating = FALSE; + DBusGProxy *adapter_proxy; + int result = BLUETOOTH_ERROR_INTERNAL; - dbus_g_proxy_end_call(proxy, call, &err, - DBUS_TYPE_G_OBJECT_PATH, &device_path, - G_TYPE_INVALID); - g_free(device_path); - if (searching_info == NULL) { - /* Send reply */ - BT_ERR("searching_info == NULL"); - goto done; - } - - req_info = _bt_get_request_info(searching_info->req_id); - if (req_info == NULL) { - BT_ERR("req_info == NULL"); - goto done; - } - - if (err != NULL) { - BT_ERR("Error occured in Proxy call [%s]\n", err->message); - result = BLUETOOTH_ERROR_CONNECTION_ERROR; - goto dbus_return; - } - - remote_dev_info = _bt_get_remote_device_info(searching_info->addr); - - /* Send the event to application */ - if (remote_dev_info != NULL) { - _bt_send_event(BT_ADAPTER_EVENT, - BLUETOOTH_EVENT_SERVICE_SEARCHED, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &searching_info->addr, - DBUS_TYPE_UINT32, &remote_dev_info->class, - DBUS_TYPE_INT16, &remote_dev_info->rssi, - DBUS_TYPE_STRING, &remote_dev_info->name, - DBUS_TYPE_BOOLEAN, &remote_dev_info->paired, - DBUS_TYPE_BOOLEAN, &remote_dev_info->connected, - DBUS_TYPE_BOOLEAN, &remote_dev_info->trust, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, - &remote_dev_info->uuids, remote_dev_info->uuid_count, - DBUS_TYPE_INVALID); - - _bt_free_device_info(remote_dev_info); - } - -dbus_return: - if (req_info->context == NULL) - goto done; - - out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar)); - out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar)); - - memset(&dev_info, 0x00, sizeof(bluetooth_device_info_t)); - _bt_convert_addr_string_to_type(dev_info.device_address.addr, - searching_info->addr); - - g_array_append_vals(out_param1, &dev_info, - sizeof(bluetooth_device_info_t)); - g_array_append_vals(out_param2, &result, sizeof(int)); - - dbus_g_method_return(req_info->context, out_param1, out_param2); - - g_array_free(out_param1, TRUE); - g_array_free(out_param2, TRUE); - - _bt_delete_request_list(req_info->req_id); -done: - if (err) - g_error_free(err); - - if (searching_info) { - g_free(searching_info->addr); - g_free(searching_info); - searching_info = NULL; - } -} - -int _bt_search_device(int request_id, - bluetooth_device_address_t *device_address) -{ - char *device_path = NULL; - DBusGProxy *adapter_proxy; - DBusGProxy *device_proxy = NULL; - DBusGConnection *conn; - int result = BLUETOOTH_ERROR_INTERNAL; - - BT_CHECK_PARAMETER(device_address, return); - - if (searching_info) { - BT_ERR("Service searching in progress"); - return BLUETOOTH_ERROR_DEVICE_BUSY; + BT_CHECK_PARAMETER(device_address, return); + + if (searching_info) { + BT_ERR("Service searching in progress"); + return BLUETOOTH_ERROR_DEVICE_BUSY; } adapter_proxy = _bt_get_adapter_proxy(); retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - conn = _bt_get_system_gconn(); - retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); - /* allocate user data so that it can be retrieved in callback */ searching_info = g_malloc0(sizeof(bt_funcion_data_t)); searching_info->addr = g_malloc0(BT_ADDRESS_STRING_SIZE); @@ -1026,46 +1175,31 @@ int _bt_search_device(int request_id, _bt_convert_addr_type_to_string(searching_info->addr, device_address->addr); + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + device_path = _bt_get_device_object_path(searching_info->addr); if (device_path == NULL) { - /* Not support this function in bluez 5.2 */ BT_ERR("No paired device"); + result = BLUETOOTH_ERROR_NOT_PAIRED; goto fail; - - is_deivce_creating = TRUE; - - if (!dbus_g_proxy_begin_call(adapter_proxy, - "CreateDevice", - (DBusGProxyCallNotify)__bt_create_device_cb, - (gpointer)searching_info, NULL, - G_TYPE_STRING, searching_info->addr, - G_TYPE_INVALID)) { - BT_ERR("CreateDevice failed"); - result = BLUETOOTH_ERROR_INTERNAL; - is_deivce_creating = FALSE; - goto fail; - } - - searching_info->adapter_proxy = device_proxy; - - return BLUETOOTH_ERROR_NONE; } device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, - device_path, BT_PROPERTIES_INTERFACE); + device_path, BT_DEVICE_INTERFACE); g_free(device_path); if (device_proxy == NULL) { result = BLUETOOTH_ERROR_INTERNAL; goto fail; } - if (!dbus_g_proxy_begin_call(device_proxy, "Get", - (DBusGProxyCallNotify)__bt_discover_cb, - (gpointer)searching_info, NULL, - G_TYPE_STRING, BT_DEVICE_INTERFACE, - G_TYPE_STRING, "UUIDs", - G_TYPE_INVALID)) { + if (!dbus_g_proxy_begin_call(device_proxy, "DiscoverServices", + (DBusGProxyCallNotify)__bt_discover_cb, + (gpointer)searching_info, NULL, + G_TYPE_STRING, "", + G_TYPE_INVALID)) { BT_ERR("DiscoverServices failed"); goto fail; } @@ -1094,23 +1228,7 @@ int _bt_cancel_search_device(void) "CancelDiscovery", &err, G_TYPE_INVALID, G_TYPE_INVALID); - } else if (searching_info->adapter_proxy) { - dbus_g_proxy_call(searching_info->adapter_proxy, - "CancelDeviceCreation", - &err, - G_TYPE_STRING, searching_info->addr, - G_TYPE_INVALID); - } else { - BT_ERR("No proxy info"); - return BLUETOOTH_ERROR_NOT_IN_OPERATION; - } - - if (err != NULL) { - BT_ERR("Error occured [%s]\n", err->message); - g_error_free(err); - return BLUETOOTH_ERROR_INTERNAL; } - __bt_cancel_search_service_done(); return BLUETOOTH_ERROR_NONE; @@ -1249,6 +1367,63 @@ done: return ret; } +int _bt_is_gatt_connected(bluetooth_device_address_t *device_address, + gboolean *is_connected) +{ + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + char *object_path = NULL; + + DBusGProxy *device_proxy; + GError *error = NULL; + GValue *value; + GHashTable *hash = NULL; + DBusGConnection *conn; + int ret = BLUETOOTH_ERROR_NONE; + + BT_CHECK_PARAMETER(device_address, return); + + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + _bt_convert_addr_type_to_string(address, device_address->addr); + + object_path = _bt_get_device_object_path(address); + retv_if(object_path == NULL, BLUETOOTH_ERROR_NOT_PAIRED); + + device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + object_path, BT_PROPERTIES_INTERFACE); + g_free(object_path); + retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call(device_proxy, "GetAll", &error, + G_TYPE_STRING, BT_DEVICE_INTERFACE, + G_TYPE_INVALID, + dbus_g_type_get_map("GHashTable", G_TYPE_STRING, + G_TYPE_VALUE), &hash, G_TYPE_INVALID); + + if (error != NULL) { + BT_ERR("Error occured in Proxy call [%s]\n", error->message); + g_error_free(error); + g_object_unref(device_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + + if (hash == NULL) { + g_object_unref(device_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + + value = g_hash_table_lookup(hash, "GattConnected"); + *is_connected = g_value_get_boolean(value); + + BT_DBG("gatt is connected : %d", *is_connected); + + g_hash_table_destroy(hash); + g_object_unref(device_proxy); + + return ret; +} + int _bt_is_device_connected(bluetooth_device_address_t *device_address, int connection_type, gboolean *is_connected) { @@ -1260,14 +1435,20 @@ int _bt_is_device_connected(bluetooth_device_address_t *device_address, GError *error = NULL; GHashTable *hash = NULL; GValue *value = NULL; - char *interface = NULL; + + dbus_bool_t val = FALSE; + char *uuid; retv_if(device_address == NULL, BLUETOOTH_ERROR_INVALID_PARAM); retv_if(is_connected == NULL, BLUETOOTH_ERROR_INVALID_PARAM); + *is_connected = FALSE; + if (connection_type == BLUETOOTH_RFCOMM_SERVICE) return _bt_rfcomm_is_device_connected(device_address, is_connected); + else if (connection_type == BLUETOOTH_GATT_SERVICE) + return _bt_is_gatt_connected(device_address, is_connected); adapter_proxy = _bt_get_adapter_proxy(); retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); @@ -1277,66 +1458,405 @@ int _bt_is_device_connected(bluetooth_device_address_t *device_address, _bt_convert_addr_type_to_string(address, device_address->addr); - dbus_g_proxy_call(adapter_proxy, "FindDevice", - &error, G_TYPE_STRING, address, - G_TYPE_INVALID, DBUS_TYPE_G_OBJECT_PATH, - &object_path, G_TYPE_INVALID); + if(connection_type == BLUETOOTH_NAP_SERVER_SERVICE) { + object_path = _bt_get_adapter_path(); + device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + object_path, BT_NETWORK_SERVER_INTERFACE); + g_free(object_path); + if (device_proxy == NULL) { + BT_DBG("Device don't have this service"); + return BLUETOOTH_ERROR_INTERNAL; + } + dbus_g_proxy_call(device_proxy, "GetProperties", NULL, + G_TYPE_STRING, address, + G_TYPE_INVALID, + dbus_g_type_get_map("GHashTable", + G_TYPE_STRING, G_TYPE_VALUE), + &hash, G_TYPE_INVALID); + if (hash != NULL) { + value = g_hash_table_lookup(hash, "Connected"); + *is_connected = value ? g_value_get_boolean(value) : FALSE; + g_hash_table_destroy(hash); + } + } else if(connection_type == BLUETOOTH_NAP_SERVICE) { + return _bt_is_network_connected(_bt_get_net_conn(), + device_address->addr, is_connected); + } else { + uuid = _bt_get_profile_uuid128(connection_type); + if (uuid == NULL) { + BT_ERR("uuid is NULL"); + return BLUETOOTH_ERROR_INTERNAL; + } - if (error != NULL) { - BT_ERR("Failed to Find device: %s", error->message); - g_error_free(error); - return BLUETOOTH_ERROR_NOT_PAIRED; - } + BT_DBG("uuid: %s", uuid); - retv_if(object_path == NULL, BLUETOOTH_ERROR_INTERNAL); + object_path = _bt_get_device_object_path(address); + retv_if(object_path == NULL, BLUETOOTH_ERROR_NOT_PAIRED); - switch (connection_type) { - case BLUETOOTH_HSP_SERVICE: - interface = BT_HFP_AGENT_INTERFACE; - break; - case BLUETOOTH_A2DP_SERVICE: - interface = BT_SINK_INTERFACE; - break; - case BLUETOOTH_HID_SERVICE: - interface = BT_INPUT_INTERFACE; - break; - default: - BT_DBG("Unknown type!"); + device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + object_path, BT_DEVICE_INTERFACE); g_free(object_path); - return BLUETOOTH_ERROR_INVALID_PARAM; + if (device_proxy == NULL) { + BT_DBG("Device don't have this service"); + g_free(uuid); + return BLUETOOTH_ERROR_INTERNAL; + } + dbus_g_proxy_call(device_proxy, "IsConnectedProfile", &error, + G_TYPE_STRING, uuid, + G_TYPE_INVALID, + G_TYPE_BOOLEAN, &val, + G_TYPE_INVALID); + + if (error != NULL) { + BT_ERR("Failed to get properties: %s\n", error->message); + g_error_free(error); + } + + *is_connected = val; + g_free(uuid); } - BT_DBG("Interface name: %s", interface); + g_object_unref(device_proxy); + return BLUETOOTH_ERROR_NONE; +} - device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, object_path, interface); - g_free(object_path); - if (device_proxy == NULL) { - BT_DBG("Device don't have this service"); - is_connected = FALSE; - return BLUETOOTH_ERROR_NONE; +int _bt_connect_le_device(const bluetooth_device_address_t *bd_addr, gboolean auto_connect) +{ + char device_address[BT_ADDRESS_STRING_SIZE] = { 0 }; + gchar *device_path = NULL; + GError *error = NULL; + DBusGProxy *device_proxy = NULL; + DBusGProxy *adapter_proxy; + DBusGConnection *conn; + int ret = BLUETOOTH_ERROR_NONE; + + BT_CHECK_PARAMETER(bd_addr, return); + + _bt_convert_addr_type_to_string(device_address, + (unsigned char *)bd_addr->addr); + + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + adapter_proxy = _bt_get_adapter_proxy(); + retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + device_path = _bt_get_device_object_path(device_address); + if (device_path == NULL) { + BT_DBG("device_path NULL"); + ret = BLUETOOTH_ERROR_INTERNAL; + return ret; } - dbus_g_proxy_call(device_proxy, "GetProperties", &error, - G_TYPE_INVALID, - dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), - &hash, G_TYPE_INVALID); - if (error != NULL) { - BT_DBG("Failed to get properties: %s\n", error->message); + retv_if(device_path == NULL, BLUETOOTH_ERROR_INTERNAL); + + device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + device_path, BT_DEVICE_INTERFACE); + g_free(device_path); + retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call(device_proxy, "ConnectLE", &error, + G_TYPE_BOOLEAN, auto_connect, G_TYPE_INVALID, + G_TYPE_INVALID); + if (error) { + BT_ERR("ConnectLE Call Error %s[%s]", error->message, device_address); g_error_free(error); g_object_unref(device_proxy); - is_connected = FALSE; - return BLUETOOTH_ERROR_NONE; + return BLUETOOTH_ERROR_INTERNAL; } - if (hash != NULL) { - value = g_hash_table_lookup(hash, "Connected"); - *is_connected = value ? g_value_get_boolean(value) : FALSE; - g_hash_table_destroy(hash); - } else { - *is_connected = FALSE; + g_object_unref(device_proxy); + + return ret; +} + +int _bt_disconnect_le_device(const bluetooth_device_address_t *bd_addr) +{ + char device_address[BT_ADDRESS_STRING_SIZE] = { 0 }; + gchar *device_path = NULL; + GError *error = NULL; + DBusGProxy *device_proxy = NULL; + DBusGProxy *adapter_proxy; + DBusGConnection *conn; + int ret = BLUETOOTH_ERROR_NONE; + + BT_CHECK_PARAMETER(bd_addr, return); + + _bt_convert_addr_type_to_string(device_address, + (unsigned char *)bd_addr->addr); + + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + adapter_proxy = _bt_get_adapter_proxy(); + retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + device_path = _bt_get_device_object_path(device_address); + if (device_path == NULL) { + BT_DBG("device_path NULL"); + ret = BLUETOOTH_ERROR_INTERNAL; + return ret; + } + + retv_if(device_path == NULL, BLUETOOTH_ERROR_INTERNAL); + + device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + device_path, BT_DEVICE_INTERFACE); + g_free(device_path); + retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call(device_proxy, "DisconnectLE", &error, G_TYPE_INVALID, G_TYPE_INVALID); + if (error) { + BT_ERR("DisconnectLE Call Error %s[%s]", error->message, device_address); + g_error_free(error); + g_object_unref(device_proxy); + return BLUETOOTH_ERROR_INTERNAL; } g_object_unref(device_proxy); + + return ret; +} + +int _bt_connect_profile(char *address, char *uuid, + void *cb, gpointer func_data) +{ + char *object_path; + DBusGProxy *proxy; + DBusGConnection *conn; + DBusGProxy *adapter_proxy; + GError *error = NULL; + + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + object_path = _bt_get_device_object_path(address); + if (object_path == NULL) { + BT_ERR("No searched device"); + + adapter_proxy = _bt_get_adapter_proxy(); + retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call(adapter_proxy, "CreateDevice", &error, + G_TYPE_STRING, address, + G_TYPE_INVALID, G_TYPE_INVALID); + + if (error != NULL) { + BT_ERR("CreateDevice Fail: %s", error->message); + g_error_free(error); + } + + object_path = _bt_get_device_object_path(address); + } + retv_if(object_path == NULL, BLUETOOTH_ERROR_INTERNAL); + + proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + object_path, BT_DEVICE_INTERFACE); + g_free(object_path); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + if (!dbus_g_proxy_begin_call(proxy, "ConnectProfile", + (DBusGProxyCallNotify)cb, + func_data, NULL, + G_TYPE_STRING, uuid, + G_TYPE_INVALID)) { + BT_ERR("Connect Dbus Call Error"); + g_object_unref(proxy); + return BLUETOOTH_ERROR_INTERNAL; + } return BLUETOOTH_ERROR_NONE; } +int _bt_disconnect_profile(char *address, char *uuid, + void *cb, gpointer func_data) +{ + char *object_path; + DBusGProxy *proxy; + DBusGConnection *conn; + + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + object_path = _bt_get_device_object_path(address); + retv_if(object_path == NULL, BLUETOOTH_ERROR_INTERNAL); + + proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + object_path, BT_DEVICE_INTERFACE); + g_free(object_path); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + if (!dbus_g_proxy_begin_call(proxy, "DisconnectProfile", + (DBusGProxyCallNotify)cb, + func_data, NULL, + G_TYPE_STRING, uuid, + G_TYPE_INVALID)) { + BT_ERR("Connect Dbus Call Error"); + g_object_unref(proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + return BLUETOOTH_ERROR_NONE; +} + +int _bt_enable_rssi(bluetooth_device_address_t *bd_addr, int link_type, + int low_threshold, int in_range_threshold, int high_threshold) +{ + int ret = BLUETOOTH_ERROR_NONE; + DBusGProxy *proxy; + GError *error = NULL; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + + BT_CHECK_PARAMETER(bd_addr, return); + BT_DBG("BD Address [%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X] Link Type[%d]", + bd_addr->addr[0], bd_addr->addr[1], + bd_addr->addr[2], bd_addr->addr[3], + bd_addr->addr[4], bd_addr->addr[5], + link_type); + BT_DBG("Enable RSSI: [Threshold %d %d %d]", low_threshold, + in_range_threshold, high_threshold); + + _bt_convert_addr_type_to_string(address, bd_addr->addr); + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + if (!dbus_g_proxy_call(proxy, "EnableRssi", &error, + G_TYPE_STRING, address, + G_TYPE_INT, link_type, + G_TYPE_INT, low_threshold, + G_TYPE_INT, in_range_threshold, + G_TYPE_INT, high_threshold, + G_TYPE_INVALID, G_TYPE_INVALID)) { + BT_ERR("Failed to Enable RSSI"); + ret = BLUETOOTH_ERROR_INTERNAL; + if (error != NULL) { + BT_ERR("Dbus Call Error:[%s]", error->message); + g_error_free(error); + ret = BLUETOOTH_ERROR_INTERNAL; + } + } + + return ret; +} + +int _bt_get_rssi_strength(bluetooth_device_address_t *bd_addr, + int link_type) +{ + int ret = BLUETOOTH_ERROR_NONE; + DBusGProxy *proxy; + GError *error = NULL; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + + BT_CHECK_PARAMETER(bd_addr, return); + BT_DBG("BD Address [%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X] Link Type[%d]", + bd_addr->addr[0], bd_addr->addr[1], + bd_addr->addr[2], bd_addr->addr[3], + bd_addr->addr[4], bd_addr->addr[5], + link_type); + + _bt_convert_addr_type_to_string(address, bd_addr->addr); + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + if (!dbus_g_proxy_call(proxy, "GetRssiStrength", &error, + G_TYPE_STRING, address, + G_TYPE_INT, link_type, + G_TYPE_INVALID, G_TYPE_INVALID)) { + BT_ERR("Failed to get Raw RSSI"); + ret = BLUETOOTH_ERROR_INTERNAL; + if (error != NULL) { + BT_ERR("Dbus Call Error:[%s]", error->message); + g_error_free(error); + ret = BLUETOOTH_ERROR_INTERNAL; + } + } + + return ret; +} + +int _bt_le_conn_update(unsigned char *device_address, + guint16 interval_min, guint16 interval_max, + guint16 latency, guint16 time_out) +{ + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + gchar *device_path = NULL; + GError *error = NULL; + DBusGProxy *device_proxy = NULL; + DBusGConnection *conn; + guint32 min, max, to; + int ret = BLUETOOTH_ERROR_NONE; + + BT_DBG("+"); + + BT_CHECK_PARAMETER(device_address, return); + + BT_DBG("Min interval: %u, Max interval: %u, Latency: %u, Supervision timeout: %u", + interval_min, interval_max, latency, time_out); + + if (interval_min > interval_max || + interval_min < BT_LE_CONN_INTERVAL_MIN || + interval_max > BT_LE_CONN_INTERVAL_MAX) { + ret = BLUETOOTH_ERROR_INVALID_PARAM; + goto fail; + } + + min = interval_min / BT_LE_CONN_INTERVAL_SPLIT; + max = interval_max / BT_LE_CONN_INTERVAL_SPLIT; + + if (time_out < BT_LE_CONN_SUPER_TO_MIN || + time_out > BT_LE_CONN_SUPER_TO_MAX) { + ret = BLUETOOTH_ERROR_INVALID_PARAM; + goto fail; + } + + to = time_out / BT_LE_CONN_TO_SPLIT; + + if (latency > ((to / max) - 1)) { + ret = BLUETOOTH_ERROR_INVALID_PARAM; + goto fail; + } + + _bt_convert_addr_type_to_string(address, device_address); + + BT_DBG("Remote device address: %s", address); + + device_path = _bt_get_device_object_path(address); + + if (device_path == NULL) { + BT_DBG("device_path NULL"); + ret = BLUETOOTH_ERROR_INTERNAL; + goto fail; + } + + conn = _bt_get_system_gconn(); + if (conn == NULL) { + BT_DBG("conn NULL"); + ret = BLUETOOTH_ERROR_INTERNAL; + goto fail; + } + + device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + device_path, BT_DEVICE_INTERFACE); + g_free(device_path); + retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call(device_proxy, "LeConnUpdate", &error, + G_TYPE_UINT, min, + G_TYPE_UINT, max, + G_TYPE_UINT, latency, + G_TYPE_UINT, to, + G_TYPE_INVALID, G_TYPE_INVALID); + if (error) { + BT_ERR("LeConnUpdate Call Error %s[%s]", + error->message, address); + g_error_free(error); + g_object_unref(device_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + + g_object_unref(device_proxy); + BT_DBG("-"); + +fail: + return ret; +} diff --git a/bt-service/bt-service-event-receiver.c b/bt-service/bt-service-event-receiver.c old mode 100644 new mode 100755 index f0ae7a7..69b79ef --- a/bt-service/bt-service-event-receiver.c +++ b/bt-service/bt-service-event-receiver.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -25,6 +29,7 @@ #include #include #include +//#include #include "bluetooth-api.h" #include "bt-internal-types.h" @@ -33,34 +38,128 @@ #include "bt-service-event.h" #include "bt-service-main.h" #include "bt-service-adapter.h" +#include "bt-service-adapter-le.h" #include "bt-service-device.h" +#include "bt-service-avrcp.h" #include "bt-service-obex-server.h" #include "bt-service-rfcomm-server.h" -#include "bt-service-opp-client.h" #include "bt-service-audio.h" +#include "bt-service-agent.h" +#include "bt-service-pbap.h" +#include "bt-service-headset-connection.h" +#include "bt-service-opp-client.h" -static DBusGConnection *manager_conn = NULL; -static DBusGConnection *obexd_conn = NULL; +static DBusGConnection *manager_conn; +static DBusGConnection *obexd_conn; +static GList *p_cache_list = NULL; static DBusGConnection *opc_obexd_conn = NULL; -static GList *g_list = NULL; + static guint event_id; +guint nap_connected_device_count = 0; +static guint hid_connected_device_count = 0; +static GList *p_adv_ind_list; + +typedef struct { + char *addr; + int data_len; + char *data; +} bt_le_adv_info_t; + +typedef struct { + bt_remote_dev_info_t *dev_info; +} bt_cache_info_t; + +/** + * obexd connection type + */ +typedef enum { + OBEX_OPP = (1 << 1), + OBEX_FTP = (1 << 2), + OBEX_BIP = (1 << 3), + OBEX_PBAP = (1 << 4), + OBEX_IRMC = (1 << 5), + OBEX_PCSUITE = (1 << 6), + OBEX_SYNCEVOLUTION = (1 << 7), + OBEX_MAS = (1 << 8), +} bluetooth_obex_connection_type_t; + +void _bt_handle_property_changed_event(DBusMessage *msg); +void _bt_opc_property_changed_event(DBusMessage *msg); +int _bt_register_service_event(DBusGConnection *g_conn, int event_type); +void _bt_unregister_service_event(DBusGConnection *g_conn, int event_type); +void _bt_opp_client_event_deinit(void); + +static void __bt_free_bt_le_adv_info_t(bt_le_adv_info_t *adv_info) +{ + g_free(adv_info->addr); + g_free(adv_info->data); + g_free(adv_info); +} + +static bt_le_adv_info_t *__bt_get_adv_ind_info(char *addr) +{ + retv_if(!addr, NULL); + bt_le_adv_info_t *adv_info = NULL; + GList *current = g_list_first((GList *)p_adv_ind_list); + while(current && current->data) { + adv_info = (bt_le_adv_info_t *)current->data; + retv_if(adv_info && !g_strcmp0(adv_info->addr, addr), adv_info); + current = g_list_next(current); + } + return NULL; +} + +static void __bt_add_adv_ind_info(bt_le_adv_info_t *adv_info) +{ + ret_if(!adv_info); + if (__bt_get_adv_ind_info(adv_info->addr) != NULL) { + BT_ERR("adv_info is already added"); + __bt_free_bt_le_adv_info_t(adv_info); + return; + } + p_adv_ind_list = g_list_append(p_adv_ind_list, adv_info); +} + +static void __bt_del_adv_ind_info(char *addr) +{ + ret_if(!addr); + ret_if(!p_adv_ind_list); + bt_le_adv_info_t *adv_info = NULL; + GList *current = g_list_first((GList *)p_adv_ind_list); + while(current && current->data) { + adv_info = (bt_le_adv_info_t *)current->data; + if (adv_info && !g_strcmp0(adv_info->addr, addr)) { + p_adv_ind_list = g_list_remove(p_adv_ind_list, adv_info); + __bt_free_bt_le_adv_info_t(adv_info); + return; + } + current = g_list_next(current); + } +} + +static void __bt_free_cache_info(bt_cache_info_t *cache_info) +{ + ret_if(cache_info == NULL); + + _bt_free_device_info(cache_info->dev_info); + g_free(cache_info); +} -static bt_remote_dev_info_t *__bt_parse_device_properties(DBusMessageIter *item_iter) +static gboolean __bt_parse_device_properties(DBusMessageIter *item_iter, + bt_remote_dev_info_t *dev_info) { + BT_DBG("+"); DBusMessageIter value_iter; char *value; - bt_remote_dev_info_t *dev_info; dbus_message_iter_recurse(item_iter, &value_iter); if (dbus_message_iter_get_arg_type(&value_iter) != DBUS_TYPE_DICT_ENTRY) { BT_DBG("No entry"); - return NULL; + return FALSE; } - dev_info = g_malloc0(sizeof(bt_remote_dev_info_t)); - while (dbus_message_iter_get_arg_type(&value_iter) == DBUS_TYPE_DICT_ENTRY) { char *key; @@ -82,569 +181,588 @@ static bt_remote_dev_info_t *__bt_parse_device_properties(DBusMessageIter *item_ } dbus_message_iter_recurse(&dict_entry, &iter_dict_val); - if (strcasecmp(key, "Address") == 0) { - const char *address = NULL; - dbus_message_iter_get_basic(&iter_dict_val, &address); - dev_info->address = g_strdup(address); - } else if (strcasecmp(key, "Class") == 0) { - dbus_message_iter_get_basic(&iter_dict_val, &dev_info->class); - } else if (strcasecmp(key, "Name") == 0) { - dbus_message_iter_get_basic(&iter_dict_val, &value); - if (dev_info->name == NULL) - dev_info->name = g_strdup(value); - } else if (strcasecmp(key, "Connected") == 0) { - dbus_message_iter_get_basic(&iter_dict_val, + if (dev_info) { + if (strcasecmp(key, "Address") == 0) { + const char *address = NULL; + dbus_message_iter_get_basic(&iter_dict_val, &address); + dev_info->address = g_strdup(address); + } else if (strcasecmp(key, "Class") == 0) { + dbus_message_iter_get_basic(&iter_dict_val, &dev_info->class); + } else if (strcasecmp(key, "name") == 0) { + dbus_message_iter_get_basic(&iter_dict_val, &value); + if (dev_info->name == NULL) + dev_info->name = g_strdup(value); + } else if (strcasecmp(key, "Connected") == 0) { + dbus_message_iter_get_basic(&iter_dict_val, &dev_info->connected); - } else if (strcasecmp(key, "Paired") == 0) { - dbus_message_iter_get_basic(&iter_dict_val, + } else if (strcasecmp(key, "paired") == 0) { + dbus_message_iter_get_basic(&iter_dict_val, &dev_info->paired); - } else if (strcasecmp(key, "Trusted") == 0) { - dbus_message_iter_get_basic(&iter_dict_val, + } else if (strcasecmp(key, "Trusted") == 0) { + dbus_message_iter_get_basic(&iter_dict_val, &dev_info->trust); - } else if (strcasecmp(key, "RSSI") == 0) { - dbus_message_iter_get_basic(&iter_dict_val, + } else if (strcasecmp(key, "RSSI") == 0) { + dbus_message_iter_get_basic(&iter_dict_val, &dev_info->rssi); - } else if (strcasecmp(key, "UUIDs") == 0) { - DBusMessageIter uuid_iter; - DBusMessageIter tmp_iter; - int i = 0; + } else if (strcasecmp(key, "LastAddrType") == 0) { + dbus_message_iter_get_basic(&iter_dict_val, + &dev_info->addr_type); + } else if (strcasecmp(key, "UUIDs") == 0) { + DBusMessageIter uuid_iter; + DBusMessageIter tmp_iter; + int i = 0; - dbus_message_iter_recurse(&iter_dict_val, &uuid_iter); + dbus_message_iter_recurse(&iter_dict_val, &uuid_iter); - tmp_iter = uuid_iter; + tmp_iter = uuid_iter; - /* Store the uuid count */ - while (dbus_message_iter_get_arg_type(&tmp_iter) != DBUS_TYPE_INVALID) { - dbus_message_iter_get_basic(&tmp_iter, + /* Store the uuid count */ + while (dbus_message_iter_get_arg_type(&tmp_iter) != DBUS_TYPE_INVALID) { + dbus_message_iter_get_basic(&tmp_iter, &value); - dev_info->uuid_count++; - if (!dbus_message_iter_next(&tmp_iter)) - break; - } + dev_info->uuid_count++; + if (!dbus_message_iter_next(&tmp_iter)) + break; + } - /* Store the uuids */ - if (dev_info->uuid_count > 0) { - dev_info->uuids = g_new0(char *, - dev_info->uuid_count + 1); - } else { - dbus_message_iter_next(&value_iter); - continue; - } + /* Store the uuids */ + if (dev_info->uuid_count > 0) { + dev_info->uuids = g_new0(char *, + dev_info->uuid_count + 1); + } else { + dbus_message_iter_next(&value_iter); + continue; + } - while (dbus_message_iter_get_arg_type(&uuid_iter) != DBUS_TYPE_INVALID) { - dbus_message_iter_get_basic(&uuid_iter, + while (dbus_message_iter_get_arg_type(&uuid_iter) != DBUS_TYPE_INVALID) { + dbus_message_iter_get_basic(&uuid_iter, &value); - dev_info->uuids[i] = g_strdup(value); - i++; - if (!dbus_message_iter_next(&uuid_iter)) { - break; + dev_info->uuids[i] = g_strdup(value); + i++; + if (!dbus_message_iter_next(&uuid_iter)) { + break; + } + } + } else if (strcasecmp(key, "ManufacturerDataLen") == 0) { + dbus_message_iter_get_basic(&iter_dict_val, + &dev_info->manufacturer_data_len); + + if (dev_info->manufacturer_data_len > BLUETOOTH_MANUFACTURER_DATA_LENGTH_MAX) { + BT_ERR("manufacturer_data_len is too long(len = %d)", dev_info->manufacturer_data_len); + dev_info->manufacturer_data_len = BLUETOOTH_MANUFACTURER_DATA_LENGTH_MAX; } - } + if (dev_info->manufacturer_data_len == 0) + dev_info->manufacturer_data = g_strdup(""); + } else if (strcasecmp(key, "ManufacturerData") == 0) { + DBusMessageIter manufacturer_iter; + int i = 0; + int len = 0; + char *manufacturer_data = NULL; + char byte = 0; + + dbus_message_iter_recurse(&iter_dict_val, &manufacturer_iter); + len = dbus_message_iter_get_array_len(&manufacturer_iter); + + dev_info->manufacturer_data = g_malloc0(len); + manufacturer_data = dev_info->manufacturer_data; + + while (dbus_message_iter_get_arg_type(&manufacturer_iter) == DBUS_TYPE_BYTE) { + dbus_message_iter_get_basic(&manufacturer_iter, &byte); + manufacturer_data[i] = byte; + i++; + dbus_message_iter_next(&manufacturer_iter); + } + } } dbus_message_iter_next(&value_iter); } - return dev_info; + BT_DBG("-"); + return TRUE; } -void __bt_parse_media_properties(DBusMessageIter *item_iter) +static gboolean __bt_parse_interface(DBusMessage *msg, + bt_remote_dev_info_t *dev_info) { + BT_DBG("+"); + + DBusMessageIter msg_iter; DBusMessageIter value_iter; - char *address = NULL; - char *uuid = NULL; - int result = BLUETOOTH_ERROR_NONE; + char *object_path = NULL; - dbus_message_iter_recurse(item_iter, &value_iter); + retv_if(dbus_message_iter_init(msg, &msg_iter) == FALSE, FALSE); - if (dbus_message_iter_get_arg_type(&value_iter) != - DBUS_TYPE_DICT_ENTRY) { - BT_DBG("No entry"); - return; - } + dbus_message_iter_get_basic(&msg_iter, &object_path); + retv_if(object_path == NULL, FALSE); + + /* object array (oa) */ + retv_if(dbus_message_iter_next(&msg_iter) == FALSE, FALSE); + retv_if(dbus_message_iter_get_arg_type(&msg_iter) != + DBUS_TYPE_ARRAY, FALSE); + + dbus_message_iter_recurse(&msg_iter, &value_iter); + /* string array (sa) */ while (dbus_message_iter_get_arg_type(&value_iter) == DBUS_TYPE_DICT_ENTRY) { - char *key; - DBusMessageIter dict_entry; - DBusMessageIter iter_dict_val; + char *interface_name = NULL; + DBusMessageIter interface_iter; - dbus_message_iter_recurse(&value_iter, &dict_entry); - dbus_message_iter_get_basic(&dict_entry, &key); + dbus_message_iter_recurse(&value_iter, &interface_iter); - if (key == NULL) { - dbus_message_iter_next(&value_iter); - continue; - } + retv_if(dbus_message_iter_get_arg_type(&interface_iter) != + DBUS_TYPE_STRING, FALSE); - if (!dbus_message_iter_next(&dict_entry)) { - dbus_message_iter_next(&value_iter); - continue; - } + dbus_message_iter_get_basic(&interface_iter, &interface_name); - dbus_message_iter_recurse(&dict_entry, &iter_dict_val); + retv_if(dbus_message_iter_next(&interface_iter) == FALSE, FALSE); - BT_DBG("key: %s", key); + retv_if(dbus_message_iter_get_arg_type(&interface_iter) != + DBUS_TYPE_ARRAY, FALSE); - if (strcasecmp(key, "Device") == 0) { - char *object_path = NULL; + BT_DBG("interface: %s", interface_name); - dbus_message_iter_get_basic(&iter_dict_val, &object_path); - address = g_malloc0(BT_ADDRESS_STRING_SIZE); - _bt_convert_device_path_to_address(object_path, address); + if (g_strcmp0(interface_name, "org.bluez.Device1") == 0) { + BT_DBG("Found a device: %s", object_path); - }else if (strcasecmp(key, "UUID") == 0) { - dbus_message_iter_get_basic(&iter_dict_val, &uuid); + if (__bt_parse_device_properties(&interface_iter, + dev_info) == FALSE) { + BT_ERR("Fail to parse the properies"); + return FALSE; + } else { + return TRUE; + } } dbus_message_iter_next(&value_iter); } - if (address != NULL && uuid != NULL){ - int event = BLUETOOTH_EVENT_AV_CONNECTED; - char connected_address[BT_ADDRESS_STRING_SIZE + 1]; - bluetooth_device_address_t device_address; - gboolean connected; + BT_DBG("-"); - _bt_send_event(BT_HEADSET_EVENT, event, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID); + return FALSE; +} - connected = _bt_is_headset_type_connected(BT_AUDIO_A2DP, - connected_address); - if (connected) { - if (g_strcmp0(connected_address, address) != 0) { - _bt_convert_addr_string_to_type( - device_address.addr, - connected_address); - _bt_audio_disconnect(0, BT_AUDIO_A2DP, - &device_address, NULL); - } - } +char *__bt_get_headset_name(char *address) +{ + bluetooth_device_address_t device_address = { {0} }; + bluetooth_device_info_t dev_info; - _bt_add_headset_to_list(BT_AUDIO_A2DP, - BT_STATE_CONNECTED, address); + retv_if(address == NULL, strdup("")); - g_free(address); - } + _bt_convert_addr_string_to_type(device_address.addr, address); + + memset(&dev_info, 0x00, sizeof(bluetooth_device_info_t)); + + _bt_get_bonded_device_info(&device_address, &dev_info); + + return g_strdup(dev_info.device_name.name); } -static void __bt_parse_audio_properties(DBusMessage *msg) +static int __bt_get_owner_info(DBusMessage *msg, char **name, + char **previous, char **current) { - DBusMessageIter msg_iter; - DBusMessageIter value_iter; - - ret_if(dbus_message_iter_init(msg, &msg_iter) == FALSE); + DBusMessageIter item_iter; - /* object array (oa) */ - ret_if(dbus_message_iter_next(&msg_iter) == FALSE); - ret_if(dbus_message_iter_get_arg_type(&msg_iter) != - DBUS_TYPE_ARRAY); + dbus_message_iter_init(msg, &item_iter); - dbus_message_iter_recurse(&msg_iter, &value_iter); + if (dbus_message_iter_get_arg_type(&item_iter) + != DBUS_TYPE_STRING) { + BT_ERR("This is bad format dbus"); + return BLUETOOTH_ERROR_INTERNAL; + } - /* string array (sa) */ - while (dbus_message_iter_get_arg_type(&value_iter) == - DBUS_TYPE_DICT_ENTRY) { - char *interface_name = NULL; - DBusMessageIter interface_iter; + dbus_message_iter_get_basic(&item_iter, name); - dbus_message_iter_recurse(&value_iter, &interface_iter); + retv_if(*name == NULL, BLUETOOTH_ERROR_INTERNAL); - ret_if(dbus_message_iter_get_arg_type(&interface_iter) != - DBUS_TYPE_STRING); + dbus_message_iter_next(&item_iter); - dbus_message_iter_get_basic(&interface_iter, &interface_name); + if (dbus_message_iter_get_arg_type(&item_iter) + != DBUS_TYPE_STRING) { + BT_ERR("This is bad format dbus"); + return BLUETOOTH_ERROR_INTERNAL; + } - ret_if(dbus_message_iter_next(&interface_iter) == FALSE); + dbus_message_iter_get_basic(&item_iter, previous); - ret_if(dbus_message_iter_get_arg_type(&interface_iter) != - DBUS_TYPE_ARRAY); + retv_if(*previous == NULL, BLUETOOTH_ERROR_INTERNAL); - BT_DBG("interface: %s", interface_name); + dbus_message_iter_next(&item_iter); - if (g_strcmp0(interface_name, - "org.bluez.MediaTransport1") == 0) { - __bt_parse_media_properties(&interface_iter); - return; - } - dbus_message_iter_next(&value_iter); + if (dbus_message_iter_get_arg_type(&item_iter) + != DBUS_TYPE_STRING) { + BT_ERR("This is bad format dbus"); + return BLUETOOTH_ERROR_INTERNAL; } - return; + dbus_message_iter_get_basic(&item_iter, current); + + retv_if(*current == NULL, BLUETOOTH_ERROR_INTERNAL); + + return BLUETOOTH_ERROR_NONE; } -static int __bt_parse_event(DBusMessage *msg) +static int __bt_get_agent_signal_info(DBusMessage *msg, char **address, + char **name, char **uuid) { - DBusMessageIter msg_iter; - DBusMessageIter value_iter; + BT_DBG("+"); - retv_if(dbus_message_iter_init(msg, &msg_iter) == FALSE, 0); + DBusMessageIter item_iter; - /* object array (oa) */ - retv_if(dbus_message_iter_next(&msg_iter) == FALSE, 0); - retv_if(dbus_message_iter_get_arg_type(&msg_iter) != - DBUS_TYPE_ARRAY, 0); + dbus_message_iter_init(msg, &item_iter); - dbus_message_iter_recurse(&msg_iter, &value_iter); + if (dbus_message_iter_get_arg_type(&item_iter) + != DBUS_TYPE_STRING) { + BT_ERR("This is bad format dbus"); + return BLUETOOTH_ERROR_INTERNAL; + } - /* string array (sa) */ - while (dbus_message_iter_get_arg_type(&value_iter) == - DBUS_TYPE_DICT_ENTRY) { - char *interface_name = NULL; - DBusMessageIter interface_iter; + dbus_message_iter_get_basic(&item_iter, address); - dbus_message_iter_recurse(&value_iter, &interface_iter); + dbus_message_iter_next(&item_iter); - retv_if(dbus_message_iter_get_arg_type(&interface_iter) != - DBUS_TYPE_STRING, 0); + if (dbus_message_iter_get_arg_type(&item_iter) + != DBUS_TYPE_STRING) { + BT_ERR("This is bad format dbus"); + return BLUETOOTH_ERROR_INTERNAL; + } - dbus_message_iter_get_basic(&interface_iter, - &interface_name); + dbus_message_iter_get_basic(&item_iter, name); - retv_if(dbus_message_iter_next(&interface_iter) == FALSE, - 0); + dbus_message_iter_next(&item_iter); - retv_if(dbus_message_iter_get_arg_type(&interface_iter) != - DBUS_TYPE_ARRAY, 0); + if (dbus_message_iter_get_arg_type(&item_iter) + != DBUS_TYPE_STRING) { + BT_ERR("This is bad format dbus"); + return BLUETOOTH_ERROR_INTERNAL; + } - BT_DBG("interface: %s", interface_name); + dbus_message_iter_get_basic(&item_iter, uuid); - if (g_strcmp0(interface_name, - "org.bluez.Device1") == 0) { - return BT_DEVICE_EVENT; - }else if (g_strcmp0(interface_name, - "org.bluez.MediaTransport1") == 0) { - return BT_MEDIA_TRANSFER_EVENT; - } - dbus_message_iter_next(&value_iter); - } + BT_DBG("-"); - return 0; + return BLUETOOTH_ERROR_NONE; } -static int __bt_parse_remove_event(DBusMessage *msg) +void __bt_set_device_values(gboolean connected, int state) { - DBusMessageIter msg_iter; - DBusMessageIter value_iter; - - retv_if(dbus_message_iter_init(msg, &msg_iter) == - FALSE, 0); + int bt_device_state = VCONFKEY_BT_DEVICE_NONE; - retv_if(dbus_message_iter_next(&msg_iter) == FALSE, - 0); - retv_if(dbus_message_iter_get_arg_type(&msg_iter) != - DBUS_TYPE_ARRAY, 0); + if (vconf_get_int(VCONFKEY_BT_DEVICE, &bt_device_state) != 0) { + BT_ERR("vconf_get_int failed"); + } - dbus_message_iter_recurse(&msg_iter, &value_iter); + if (connected == TRUE) + bt_device_state |= state; + else if (bt_device_state & state) + bt_device_state ^= state; - while (dbus_message_iter_get_arg_type(&value_iter) - != DBUS_TYPE_INVALID) { - char *key; + if (vconf_set_int(VCONFKEY_BT_DEVICE, bt_device_state) != 0) { + BT_ERR("vconf_set_int failed"); + } +} - dbus_message_iter_get_basic(&value_iter, &key); +gboolean _bt_discovery_finished_cb(gpointer user_data) +{ + int result = BLUETOOTH_ERROR_NONE; + event_id = 0; - if (key == NULL) { - dbus_message_iter_next(&value_iter); - continue; + if (_bt_get_discovering_property(DISCOVERY_ROLE_BREDR) == FALSE) { + if (_bt_get_cancel_by_user() == TRUE) { + result = BLUETOOTH_ERROR_CANCEL_BY_USER; } - BT_DBG("key = %s", key); + _bt_set_cancel_by_user(FALSE); + _bt_set_discovery_status(FALSE); + _bt_send_event(BT_ADAPTER_EVENT, + BLUETOOTH_EVENT_DISCOVERY_FINISHED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + } - if (g_strcmp0(key, "org.bluez.MediaTransport1") == 0) { - return BT_MEDIA_TRANSFER_EVENT; - }else if (g_strcmp0(key, "org.bluez.Device1") == 0) { - return BT_DEVICE_EVENT; - } - dbus_message_iter_next(&value_iter); - } - - return 0; + return FALSE; } -gboolean _bt_parse_audio_remove_properties(DBusMessage *msg) +static gboolean __bt_le_discovery_finished_cb(gpointer user_data) { - DBusMessageIter msg_iter; - DBusMessageIter value_iter; - char *object_path = NULL; - char *address = NULL; int result = BLUETOOTH_ERROR_NONE; - bt_headset_wait_t *wait_list; - - retv_if(dbus_message_iter_init(msg, &msg_iter) == FALSE, FALSE); - - dbus_message_iter_get_basic(&msg_iter, &object_path); - retv_if(object_path == NULL, FALSE); - - address = g_malloc0(BT_ADDRESS_STRING_SIZE); - _bt_convert_device_path_to_address(object_path, address); - - retv_if(dbus_message_iter_next(&msg_iter) == FALSE, FALSE); - retv_if(dbus_message_iter_get_arg_type(&msg_iter) != - DBUS_TYPE_ARRAY, FALSE); - - dbus_message_iter_recurse(&msg_iter, &value_iter); - - while (dbus_message_iter_get_arg_type(&value_iter) - != DBUS_TYPE_INVALID) { - char *key; - - dbus_message_iter_get_basic(&value_iter, &key); + event_id = 0; - if (key == NULL) { - dbus_message_iter_next(&value_iter); - continue; + if (_bt_get_discovering_property(DISCOVERY_ROLE_LE) == FALSE) { + if (_bt_get_cancel_by_user() == TRUE) { + result = BLUETOOTH_ERROR_CANCEL_BY_USER; } - BT_DBG("key = %s", key); - - if (g_strcmp0(key, "org.bluez.MediaTransport1") == 0) { - int event = BLUETOOTH_EVENT_AV_DISCONNECTED; - - _bt_send_event(BT_HEADSET_EVENT, event, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID); - - /* Remove data from the connected list */ - _bt_remove_headset_from_list(BT_AUDIO_A2DP, address); - wait_list = _bt_get_audio_wait_data(); - - if (wait_list == NULL) { - g_free(address); - return TRUE; - } - - if (((wait_list->type == BT_AUDIO_ALL) && - (wait_list->ag_flag == TRUE)) || - (wait_list->type == BT_AUDIO_A2DP) || - (wait_list->disconnection_type == BT_AUDIO_A2DP)) { - bluetooth_device_address_t device_address; - _bt_convert_addr_string_to_type( - device_address.addr, - wait_list->address); - - _bt_audio_connect(wait_list->req_id, - wait_list->type, - &device_address, - wait_list->out_param1); - } - - g_free(address); - return TRUE; - } - dbus_message_iter_next(&value_iter); + _bt_set_cancel_by_user(FALSE); + _bt_set_le_discovery_status(FALSE); + _bt_send_event(BT_LE_ADAPTER_EVENT, + BLUETOOTH_EVENT_LE_DISCOVERY_FINISHED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); } - g_free(address); return FALSE; } -static bt_remote_dev_info_t *__bt_parse_interface(DBusMessage *msg) +void __bt_update_remote_cache_devinfo(const char *address, gboolean paired_status) { - DBusMessageIter msg_iter; - DBusMessageIter value_iter; - char *object_path = NULL; - bt_remote_dev_info_t *dev_info = NULL; - - retv_if(dbus_message_iter_init(msg, &msg_iter) == FALSE, NULL); - - dbus_message_iter_get_basic(&msg_iter, &object_path); - retv_if(object_path == NULL, NULL); - - /* object array (oa) */ - retv_if(dbus_message_iter_next(&msg_iter) == FALSE, NULL); - retv_if(dbus_message_iter_get_arg_type(&msg_iter) != - DBUS_TYPE_ARRAY, NULL); - - dbus_message_iter_recurse(&msg_iter, &value_iter); - - /* string array (sa) */ - while (dbus_message_iter_get_arg_type(&value_iter) == - DBUS_TYPE_DICT_ENTRY) { - char *interface_name = NULL; - DBusMessageIter interface_iter; - - dbus_message_iter_recurse(&value_iter, &interface_iter); - - retv_if(dbus_message_iter_get_arg_type(&interface_iter) != - DBUS_TYPE_STRING, NULL); - - dbus_message_iter_get_basic(&interface_iter, &interface_name); - - retv_if(dbus_message_iter_next(&interface_iter) == FALSE, NULL); + BT_DBG("+"); - retv_if(dbus_message_iter_get_arg_type(&interface_iter) != - DBUS_TYPE_ARRAY, NULL); + ret_if(address == NULL); - BT_DBG("interface: %s", interface_name); + GList * node; + bt_cache_info_t *cache_info; + bt_remote_dev_info_t *dev_info; - if (g_strcmp0(interface_name, "org.bluez.Device1") == 0) { - BT_DBG("Found a device: %s", object_path); + node = g_list_first(p_cache_list); - dev_info = __bt_parse_device_properties(&interface_iter); + while (node != NULL){ + cache_info = (bt_cache_info_t *)node->data; - if (dev_info == NULL) { - BT_ERR("Fail to parse the properies"); - return NULL; - } + if (cache_info == NULL) { + node = g_list_next(node); + continue; } - dbus_message_iter_next(&value_iter); + dev_info = cache_info->dev_info; + if (strcasecmp(dev_info->address, + address) == 0) { + BT_DBG("Device Found"); + if (paired_status == TRUE) + cache_info->dev_info->paired = TRUE; + else + cache_info->dev_info->paired = FALSE; + break; + } + node = g_list_next(node); } - - return dev_info; + BT_DBG("-"); } -char *__bt_get_headset_name(char *address) +static void __bt_device_remote_connected_properties( + bt_remote_dev_info_t *remote_dev_info, + char *address, gboolean connected) { - bluetooth_device_address_t device_address = { {0} }; - bluetooth_device_info_t dev_info; + int result = BLUETOOTH_ERROR_NONE; + int i; - retv_if(address == NULL, strdup("")); + BT_DBG("+"); - _bt_convert_addr_string_to_type(device_address.addr, address); + if (remote_dev_info->uuid_count > 0 ) { + for (i = 0; iuuid_count; i++) { + char *uuid = remote_dev_info->uuids[i]; + if (strcasecmp(uuid, HID_UUID) == 0){ + int event = BLUETOOTH_EVENT_NONE; - memset(&dev_info, 0x00, sizeof(bluetooth_device_info_t)); + event = (connected == TRUE) ? + BLUETOOTH_HID_CONNECTED : + BLUETOOTH_HID_DISCONNECTED; - _bt_get_bonded_device_info(&device_address, &dev_info); + _bt_send_event(BT_HID_EVENT, event, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_INVALID); + break; + } + } + } - return g_strdup(dev_info.device_name.name); + BT_DBG("-"); } -static int __bt_get_owner_info(DBusMessage *msg, char **name, - char **previous, char **current) +void _bt_handle_adapter_event(DBusMessage *msg) { - DBusMessageIter item_iter; - - dbus_message_iter_init(msg, &item_iter); - - if (dbus_message_iter_get_arg_type(&item_iter) - != DBUS_TYPE_STRING) { - BT_ERR("This is bad format dbus\n"); - return BLUETOOTH_ERROR_INTERNAL; - } + BT_DBG("+"); - dbus_message_iter_get_basic(&item_iter, name); + int result = BLUETOOTH_ERROR_NONE; + DBusMessageIter item_iter; + const char *member = dbus_message_get_member(msg); - retv_if(*name == NULL, BLUETOOTH_ERROR_INTERNAL); + ret_if(member == NULL); - dbus_message_iter_next(&item_iter); + if (strcasecmp(member, "DeviceCreated") == 0) { + const char *object_path = NULL; + char *address; + bt_remote_dev_info_t *remote_dev_info; - if (dbus_message_iter_get_arg_type(&item_iter) - != DBUS_TYPE_STRING) { - BT_ERR("This is bad format dbus\n"); - return BLUETOOTH_ERROR_INTERNAL; - } + ret_if(_bt_is_device_creating() == FALSE); - dbus_message_iter_get_basic(&item_iter, previous); + /* Bonding from remote device */ + address = g_malloc0(BT_ADDRESS_STRING_SIZE); - retv_if(*previous == NULL, BLUETOOTH_ERROR_INTERNAL); + dbus_message_iter_init(msg, &item_iter); + dbus_message_iter_get_basic(&item_iter, &object_path); + dbus_message_iter_next(&item_iter); - dbus_message_iter_next(&item_iter); + _bt_convert_device_path_to_address(object_path, address); - if (dbus_message_iter_get_arg_type(&item_iter) - != DBUS_TYPE_STRING) { - BT_ERR("This is bad format dbus\n"); - return BLUETOOTH_ERROR_INTERNAL; - } + remote_dev_info = _bt_get_remote_device_info(address); + if (remote_dev_info == NULL) { + g_free(address); + return; + } - dbus_message_iter_get_basic(&item_iter, current); + _bt_free_device_info(remote_dev_info); + g_free(address); + } else if (strcasecmp(member, "InterfacesRemoved") == 0) { + const char *object_path = NULL; + char *address; + bt_cache_info_t *cache_info; + bt_remote_dev_info_t *dev_info; + GList * node; - retv_if(*current == NULL, BLUETOOTH_ERROR_INTERNAL); + /* Bonding from remote device */ + address = g_malloc0(BT_ADDRESS_STRING_SIZE); - return BLUETOOTH_ERROR_NONE; -} + dbus_message_iter_init(msg, &item_iter); + dbus_message_iter_get_basic(&item_iter, &object_path); + dbus_message_iter_next(&item_iter); -static int __bt_get_agent_signal_info(DBusMessage *msg, char **address, - char **name, char **uuid) -{ - DBusMessageIter item_iter; + _bt_convert_device_path_to_address(object_path, address); - dbus_message_iter_init(msg, &item_iter); + node = g_list_first(p_cache_list); - if (dbus_message_iter_get_arg_type(&item_iter) - != DBUS_TYPE_STRING) { - BT_ERR("This is bad format dbus\n"); - return BLUETOOTH_ERROR_INTERNAL; - } + while (node != NULL){ + cache_info = (bt_cache_info_t *)node->data; - dbus_message_iter_get_basic(&item_iter, address); + if (cache_info == NULL) { + node = g_list_next(node); + continue; + } - dbus_message_iter_next(&item_iter); + dev_info = cache_info->dev_info; + if (strcasecmp(dev_info->address, + address) == 0) { + p_cache_list = g_list_remove(p_cache_list, + cache_info); + __bt_free_cache_info(cache_info); + break; + } + node = g_list_next(node); + } - if (dbus_message_iter_get_arg_type(&item_iter) - != DBUS_TYPE_STRING) { - BT_ERR("This is bad format dbus\n"); - return BLUETOOTH_ERROR_INTERNAL; - } + g_free(address); + } else if (strcasecmp(member, "AdvertisingEnabled") == 0) { + BT_DBG("Advertising Enabled"); + int slot_id; + const char *sender; + gboolean status = FALSE; - dbus_message_iter_get_basic(&item_iter, name); + dbus_message_iter_init(msg, &item_iter); - dbus_message_iter_next(&item_iter); + dbus_message_iter_get_basic(&item_iter, &slot_id); + dbus_message_iter_next(&item_iter); + dbus_message_iter_get_basic(&item_iter, &status); - if (dbus_message_iter_get_arg_type(&item_iter) - != DBUS_TYPE_STRING) { - BT_ERR("This is bad format dbus\n"); - return BLUETOOTH_ERROR_INTERNAL; - } + BT_DBG("Advertising Enabled : slot_id [%d] status [%d]", slot_id, status); - dbus_message_iter_get_basic(&item_iter, uuid); + /* Send event to application */ + _bt_set_advertising_status(slot_id, status); - return BLUETOOTH_ERROR_NONE; -} + sender = _bt_get_adv_slot_owner(slot_id); + if (status) { + bluetooth_advertising_params_t adv_params = {0, }; -gboolean _bt_stop_discovery_timeout_cb(gpointer user_data) -{ - DBusGProxy *adapter_proxy; + _bt_get_advertising_params(&adv_params); + _bt_send_event_to_dest(sender, BT_ADAPTER_EVENT, + BLUETOOTH_EVENT_ADVERTISING_STARTED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_DOUBLE, &adv_params.interval_min, + DBUS_TYPE_DOUBLE, &adv_params.interval_max, + DBUS_TYPE_INVALID); + } else { + _bt_send_event_to_dest(sender, BT_ADAPTER_EVENT, + BLUETOOTH_EVENT_ADVERTISING_STOPPED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + } + } else if (strcasecmp(member, "RssiEnabled") == 0) { + BT_DBG("RSSI Enabled"); + gboolean status = FALSE; + char *address = NULL; + int link_type; - event_id = 0; + dbus_message_iter_init(msg, &item_iter); + dbus_message_iter_get_basic(&item_iter, &address); + dbus_message_iter_next(&item_iter); + dbus_message_iter_get_basic(&item_iter, &link_type); + dbus_message_iter_next(&item_iter); + dbus_message_iter_get_basic(&item_iter, &status); - adapter_proxy = _bt_get_adapter_proxy(); - retv_if(adapter_proxy == NULL, FALSE); + BT_DBG("RSSI Enabled [%s %d]", address, status); + _bt_send_event(BT_DEVICE_EVENT, + BLUETOOTH_EVENT_RSSI_ENABLED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_INT32, &link_type, + DBUS_TYPE_BOOLEAN, &status, + DBUS_TYPE_INVALID); + } else if (strcasecmp(member, "RssiAlert") == 0) { + BT_DBG("RSSI Alert"); + int alert_type; + int rssi_dbm; + int link_type; + char *address = NULL; - /* Need to stop searching */ - dbus_g_proxy_call(adapter_proxy, - "StopDiscovery", - NULL, - G_TYPE_INVALID, - G_TYPE_INVALID); + dbus_message_iter_init(msg, &item_iter); + dbus_message_iter_get_basic(&item_iter, &address); + dbus_message_iter_next(&item_iter); + dbus_message_iter_get_basic(&item_iter, &link_type); + dbus_message_iter_next(&item_iter); + dbus_message_iter_get_basic(&item_iter, &alert_type); + dbus_message_iter_next(&item_iter); + dbus_message_iter_get_basic(&item_iter, &rssi_dbm); - return FALSE; -} + BT_DBG("RSSI Alert: [Address %s LinkType %d] [Type %d DBM %d]", + address, alert_type, rssi_dbm); -void _bt_stop_discovery_timeout(void) -{ - if (event_id > 0) - return; + _bt_send_event(BT_DEVICE_EVENT, + BLUETOOTH_EVENT_RSSI_ALERT, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_INT32, &link_type, + DBUS_TYPE_INT32, &alert_type, + DBUS_TYPE_INT32, &rssi_dbm, + DBUS_TYPE_INVALID); + } else if (strcasecmp(member, "RawRssi") == 0) { + BT_DBG("RSSI Raw"); + int rssi_dbm; + int link_type; + char *address = NULL; - event_id = g_timeout_add(BT_STOP_DISCOVERY_TIMEOUT, - (GSourceFunc)_bt_stop_discovery_timeout_cb, NULL); -} + dbus_message_iter_init(msg, &item_iter); + dbus_message_iter_get_basic(&item_iter, &address); + dbus_message_iter_next(&item_iter); + dbus_message_iter_get_basic(&item_iter, &link_type); + dbus_message_iter_next(&item_iter); + dbus_message_iter_get_basic(&item_iter, &rssi_dbm); -static gboolean __bt_discovery_finished() -{ - int result = BLUETOOTH_ERROR_NONE; + BT_DBG("Raw RSSI: [Address %s] [Link Type %d][RSSI DBM %d]", + address, link_type, rssi_dbm); - if (_bt_get_cancel_by_user() == TRUE) { - result = BLUETOOTH_ERROR_CANCEL_BY_USER; + _bt_send_event(BT_DEVICE_EVENT, + BLUETOOTH_EVENT_RAW_RSSI, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_INT32, &link_type, + DBUS_TYPE_INT32, &rssi_dbm, + DBUS_TYPE_INVALID); + } else if (strcasecmp(member, BT_HARDWARE_ERROR) == 0) { + BT_ERR_C("Hardware error received from BLUEZ"); + _bt_recover_adapter(); + } else if (strcasecmp(member, BT_TX_TIMEOUT_ERROR) == 0) { + BT_ERR_C("Tx timeout error received from BLUEZ"); + _bt_recover_adapter(); } - - _bt_set_cancel_by_user(FALSE); - _bt_set_discovery_status(FALSE); - _bt_send_event(BT_ADAPTER_EVENT, - BLUETOOTH_EVENT_DISCOVERY_FINISHED, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_INVALID); - - return FALSE; + BT_DBG("-"); } -void __bt_adapter_property_changed_event(DBusMessageIter *msg_iter, const char *path) +static void __bt_adapter_property_changed_event(DBusMessageIter *msg_iter, const char *path) { + DBusGProxy *adapter_proxy; int mode = 0; int result = BLUETOOTH_ERROR_NONE; DBusMessageIter value_iter; @@ -657,154 +775,294 @@ void __bt_adapter_property_changed_event(DBusMessageIter *msg_iter, const char * if (dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_DICT_ENTRY) { - BT_ERR("This is bad format dbus\n"); + BT_ERR("This is bad format dbus"); return; } - dbus_message_iter_recurse(&item_iter, &dict_iter); + do { + dbus_message_iter_recurse(&item_iter, &dict_iter); - dbus_message_iter_get_basic(&dict_iter, &property); - ret_if(property == NULL); + dbus_message_iter_get_basic(&dict_iter, &property); + ret_if(property == NULL); - ret_if(!dbus_message_iter_next(&dict_iter)); + ret_if(!dbus_message_iter_next(&dict_iter)); - if (strcasecmp(property, "Discovering") == 0) { - gboolean discovering = FALSE; + if (strcasecmp(property, "Discovering") == 0) { + gboolean discovering = FALSE; - dbus_message_iter_recurse(&dict_iter, &value_iter); - dbus_message_iter_get_basic(&value_iter, &discovering); + dbus_message_iter_recurse(&dict_iter, &value_iter); + dbus_message_iter_get_basic(&value_iter, &discovering); - /* Send event to application */ - if (discovering == TRUE) { - _bt_set_discovery_status(TRUE); - _bt_send_event(BT_ADAPTER_EVENT, - BLUETOOTH_EVENT_DISCOVERY_STARTED, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_INVALID); - _bt_get_temp_remote_devinfo(); - } else { - if (event_id > 0){ - g_source_remove(event_id); - event_id = 0; + /* Send event to application */ + if (discovering == TRUE) { + _bt_set_discovery_status(TRUE); + _bt_send_event(BT_ADAPTER_EVENT, + BLUETOOTH_EVENT_DISCOVERY_STARTED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + } else { + ret_if(event_id > 0); + + adapter_proxy = _bt_get_adapter_proxy(); + ret_if(adapter_proxy == NULL); + + /* Need to stop searching */ + dbus_g_proxy_call(adapter_proxy, + "StopDiscovery", + NULL, + G_TYPE_INVALID, + G_TYPE_INVALID); + + event_id = g_timeout_add(BT_DISCOVERY_FINISHED_DELAY, + (GSourceFunc)_bt_discovery_finished_cb, NULL); } - __bt_discovery_finished(); - } - } else if (strcasecmp(property, "Alias") == 0) { - char *name = NULL; + } else if (strcasecmp(property, "LEDiscovering") == 0) { + gboolean le_discovering = FALSE; - dbus_message_iter_recurse(&dict_iter, &value_iter); - dbus_message_iter_get_basic(&value_iter, &name); + dbus_message_iter_recurse(&dict_iter, &value_iter); + dbus_message_iter_get_basic(&value_iter, &le_discovering); - /* Send event to application */ - _bt_send_event(BT_ADAPTER_EVENT, - BLUETOOTH_EVENT_LOCAL_NAME_CHANGED, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID); - } else if (strcasecmp(property, "Powered") == 0) { - gboolean power = FALSE; + /* Send event to application */ + if (le_discovering == TRUE) { + _bt_set_le_discovery_status(TRUE); + _bt_send_event(BT_LE_ADAPTER_EVENT, + BLUETOOTH_EVENT_LE_DISCOVERY_STARTED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + } else { + ret_if(event_id > 0); - dbus_message_iter_recurse(&dict_iter, &value_iter); - dbus_message_iter_get_basic(&value_iter, &power); + adapter_proxy = _bt_get_adapter_proxy(); + ret_if(adapter_proxy == NULL); - BT_DBG("power state changed: %d", power); + /* Need to stop searching */ + dbus_g_proxy_call(adapter_proxy, + "LEStopDiscovery", + NULL, + G_TYPE_INVALID, + G_TYPE_INVALID); - if (power == TRUE) - _bt_set_enabled(); - else - _bt_set_disabled(); + event_id = g_timeout_add(BT_DISCOVERY_FINISHED_DELAY, + (GSourceFunc)__bt_le_discovery_finished_cb, NULL); + } + } else if (strcasecmp(property, "Name") == 0) { + char *name = NULL; - } else if (strcasecmp(property, "Discoverable") == 0) { - gboolean discoverable = FALSE; + dbus_message_iter_recurse(&dict_iter, &value_iter); + dbus_message_iter_get_basic(&value_iter, &name); - dbus_message_iter_recurse(&dict_iter, &value_iter); - dbus_message_iter_get_basic(&value_iter, &discoverable); + /* Send event to application */ + _bt_send_event(BT_ADAPTER_EVENT, + BLUETOOTH_EVENT_LOCAL_NAME_CHANGED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_INVALID); + } else if (strcasecmp(property, "Alias") == 0) { + char *alias = NULL; - if (discoverable == FALSE) { - if (_bt_get_discoverable_timeout_property() > 0) { - DBusGProxy *adapter_proxy; - g_value_init(&timeout, G_TYPE_UINT); - g_value_set_uint(&timeout, 0); + dbus_message_iter_recurse(&dict_iter, &value_iter); + dbus_message_iter_get_basic(&value_iter, &alias); - adapter_proxy = _bt_get_adapter_properties_proxy(); - ret_if(adapter_proxy == NULL); + /* Send event to application */ + _bt_send_event(BT_ADAPTER_EVENT, + BLUETOOTH_EVENT_LOCAL_NAME_CHANGED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &alias, + DBUS_TYPE_INVALID); + } else if (strcasecmp(property, "Discoverable") == 0) { + gboolean discoverable = FALSE; + + dbus_message_iter_recurse(&dict_iter, &value_iter); + dbus_message_iter_get_basic(&value_iter, &discoverable); + + if (discoverable == FALSE) { + if (_bt_get_discoverable_timeout_property() > 0) { + g_value_init(&timeout, G_TYPE_UINT); + g_value_set_uint(&timeout, 0); + + adapter_proxy = _bt_get_adapter_properties_proxy(); + ret_if(adapter_proxy == NULL); + + dbus_g_proxy_call_no_reply(adapter_proxy, "Set", + G_TYPE_STRING, BT_ADAPTER_INTERFACE, + G_TYPE_STRING, "DiscoverableTimeout", + G_TYPE_VALUE, &timeout, + G_TYPE_INVALID); + + g_value_unset(&timeout); + } + + mode = BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE; + + /* Send event to application */ + BT_INFO("[Connectable]"); + _bt_send_event(BT_ADAPTER_EVENT, + BLUETOOTH_EVENT_DISCOVERABLE_MODE_CHANGED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INT16, &mode, + DBUS_TYPE_INVALID); + } else { + _bt_get_discoverable_mode(&mode); - dbus_g_proxy_call_no_reply(adapter_proxy, "Set", - G_TYPE_STRING, BT_ADAPTER_INTERFACE, - G_TYPE_STRING, "DiscoverableTimeout", - G_TYPE_VALUE, &timeout, - G_TYPE_INVALID); + /* Event will be sent by "DiscoverableTimeout" signal */ + if (mode != BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE) + return; - g_value_unset(&timeout); + /* Send event to application */ + BT_INFO("[General Discoverable]"); + _bt_send_event(BT_ADAPTER_EVENT, + BLUETOOTH_EVENT_DISCOVERABLE_MODE_CHANGED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INT16, &mode, + DBUS_TYPE_INVALID); } + } else if (strcasecmp(property, "DiscoverableTimeout") == 0) { + _bt_get_discoverable_mode(&mode); - mode = BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE; + /* Event was already sent by "Discoverable" signal */ + if (mode == BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE || + mode == BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE) + return; /* Send event to application */ + BT_INFO("[Limited Discoverable (Timeout %u secs)]", + _bt_get_discoverable_timeout_property()); + _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_DISCOVERABLE_MODE_CHANGED, DBUS_TYPE_INT32, &result, DBUS_TYPE_INT16, &mode, DBUS_TYPE_INVALID); - } else { - _bt_get_discoverable_mode(&mode); + } else if (strcasecmp(property, "Powered") == 0) { + /* TODO: Need to check this operation!! */ + gboolean powered = FALSE; + int bt_state; - /* Event will be sent by "DiscoverableTimeout" signal */ - ret_if(mode != BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE); + dbus_message_iter_recurse(&dict_iter, &value_iter); + dbus_message_iter_get_basic(&value_iter, &powered); + BT_DBG("Powered = %d", powered); + if (powered == FALSE) { + if (vconf_get_int(VCONFKEY_BT_STATUS, &bt_state) == 0 && + bt_state != VCONFKEY_BT_STATUS_OFF) { + _bt_disable_adapter(); + } +#ifdef ENABLE_TIZEN_2_4 + if (vconf_get_int(VCONFKEY_BT_LE_STATUS, &bt_state) == 0 && + bt_state != VCONFKEY_BT_LE_STATUS_OFF) { + _bt_set_le_disabled(BLUETOOTH_ERROR_NONE); + } +#endif + } + } else if (strcasecmp(property, "Connectable") == 0) { + gboolean connectable = FALSE; + + dbus_message_iter_recurse(&dict_iter, &value_iter); + dbus_message_iter_get_basic(&value_iter, &connectable); + + BT_DBG("Connectable property is changed : %d", connectable); - /* Send event to application */ _bt_send_event(BT_ADAPTER_EVENT, - BLUETOOTH_EVENT_DISCOVERABLE_MODE_CHANGED, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_INT16, &mode, + BLUETOOTH_EVENT_CONNECTABLE_CHANGED, + DBUS_TYPE_BOOLEAN, &connectable, DBUS_TYPE_INVALID); - } - } else if (strcasecmp(property, "DiscoverableTimeout") == 0) { - _bt_get_discoverable_mode(&mode); - /* Event was already sent by "Discoverable" signal */ - ret_if(mode == BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE); + if (_bt_adapter_get_status() == BT_DEACTIVATING && + _bt_adapter_get_le_status() == BT_LE_ACTIVATED && + connectable == 0) + _bt_set_disabled(BLUETOOTH_ERROR_NONE); + } else if (strcasecmp(property, "SupportedLEFeatures") == 0) { + char *name = NULL; + char *val = NULL; + DBusMessageIter array_iter; - /* Send event to application */ - _bt_send_event(BT_ADAPTER_EVENT, - BLUETOOTH_EVENT_DISCOVERABLE_MODE_CHANGED, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_INT16, &mode, - DBUS_TYPE_INVALID); - } + dbus_message_iter_recurse(&dict_iter, &value_iter); + + if(dbus_message_iter_get_arg_type(&value_iter) == DBUS_TYPE_ARRAY) { + dbus_message_iter_recurse(&value_iter, &array_iter); + + while (dbus_message_iter_get_arg_type(&array_iter) != + DBUS_TYPE_INVALID) { + dbus_message_iter_get_basic(&array_iter, &name); + if (!dbus_message_iter_next(&array_iter)) + break; + + dbus_message_iter_get_basic(&array_iter, &val); + + BT_DBG("name[%s] value[%s]", name, val); + + if (FALSE == _bt_update_le_feature_support(name, val)) + BT_INFO("Fail to update LE feature info"); + + if (!dbus_message_iter_next(&array_iter)) + break; + } + } + } else { + BT_DBG("property : [%s]", property); + } + } while(dbus_message_iter_next(&item_iter)); } -static void __bt_device_remote_connected_properties( - bt_remote_dev_info_t *remote_dev_info, - char *address, gboolean connected) +static void __bt_obex_property_changed_event(DBusMessageIter *msg_iter, const char *path) { - int result = BLUETOOTH_ERROR_NONE; - int i; - BT_DBG("+"); - if (remote_dev_info->uuid_count > 0 ) { - for (i = 0; iuuid_count; i++) { - char *uuid = remote_dev_info->uuids[i]; - if (strcasecmp(uuid, HID_UUID) == 0){ - int event = (connected == TRUE) ? - BLUETOOTH_HID_CONNECTED : - BLUETOOTH_HID_DISCONNECTED; + DBusMessageIter value_iter; + DBusMessageIter dict_iter; + DBusMessageIter item_iter; + const char *property = NULL; - _bt_send_event(BT_HID_EVENT, event, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID); - break; + dbus_message_iter_recurse(msg_iter, &item_iter); + + if (dbus_message_iter_get_arg_type(&item_iter) + != DBUS_TYPE_DICT_ENTRY) { + BT_ERR("This is bad format dbus"); + return; + } + + do { + dbus_message_iter_recurse(&item_iter, &dict_iter); + + dbus_message_iter_get_basic(&dict_iter, &property); + ret_if(property == NULL); + + ret_if(!dbus_message_iter_next(&dict_iter)); + + BT_DBG("property :%s", property); + + if (strcasecmp(property, "Status") == 0) { + const char *status; + dbus_message_iter_recurse(&dict_iter, &value_iter); + dbus_message_iter_get_basic(&value_iter, &status); + + if (strcasecmp(status, "active") == 0){ + _bt_obex_transfer_started(path); + } else if (strcasecmp(status, "complete") == 0) { + _bt_obex_transfer_completed(path, TRUE); + _bt_pbap_obex_transfer_completed(path, TRUE); + } else if (strcasecmp(status, "error") == 0){ + _bt_obex_transfer_completed(path, FALSE); + _bt_pbap_obex_transfer_completed(path, FALSE); } + } else if (strcasecmp(property, "Transferred") == 0) { + static int transferred = 0; + dbus_message_iter_recurse(&dict_iter, &value_iter); + dbus_message_iter_get_basic(&value_iter, &transferred); + + _bt_obex_transfer_progress(path,transferred); } - } + + dbus_message_iter_next(&item_iter); + } while (dbus_message_iter_get_arg_type(&item_iter) == + DBUS_TYPE_DICT_ENTRY); BT_DBG("-"); } -void __bt_device_property_changed_event(DBusMessageIter *msg_iter, const char *path) +static void __bt_device_property_changed_event(DBusMessageIter *msg_iter, const char *path) { + BT_DBG("+"); + int event; int result = BLUETOOTH_ERROR_NONE; DBusMessageIter value_iter; @@ -816,13 +1074,13 @@ void __bt_device_property_changed_event(DBusMessageIter *msg_iter, const char *p dbus_message_iter_recurse(msg_iter, &item_iter); - do { - if (dbus_message_iter_get_arg_type(&item_iter) - != DBUS_TYPE_DICT_ENTRY) { - BT_ERR("This is bad format dbus\n"); - return; - } + if (dbus_message_iter_get_arg_type(&item_iter) + != DBUS_TYPE_DICT_ENTRY) { + BT_ERR("This is bad format dbus"); + return; + } + do { dbus_message_iter_recurse(&item_iter, &dict_iter); dbus_message_iter_get_basic(&dict_iter, &property); @@ -851,6 +1109,7 @@ void __bt_device_property_changed_event(DBusMessageIter *msg_iter, const char *p if (remote_dev_info != NULL) { __bt_device_remote_connected_properties( remote_dev_info, address, connected); + _bt_free_device_info(remote_dev_info); } /* Send event to application */ @@ -861,16 +1120,75 @@ void __bt_device_property_changed_event(DBusMessageIter *msg_iter, const char *p DBUS_TYPE_INVALID); g_free(address); + } else if (strcasecmp(property, "RSSI") == 0) { + bt_remote_dev_info_t *remote_dev_info; + + address = g_malloc0(BT_ADDRESS_STRING_SIZE); + + _bt_convert_device_path_to_address(path, address); + BT_DBG("address: %s", address); + + remote_dev_info = _bt_get_remote_device_info(address); + if (remote_dev_info == NULL) { + g_free(address); + return; + } + BT_DBG("Address type %d", remote_dev_info->addr_type); + + if (remote_dev_info && remote_dev_info->addr_type == 0) { + BT_DBG("Name %s", remote_dev_info->name); + + _bt_send_event(BT_ADAPTER_EVENT, + BLUETOOTH_EVENT_REMOTE_DEVICE_FOUND, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &remote_dev_info->address, + DBUS_TYPE_UINT32, &remote_dev_info->class, + DBUS_TYPE_INT16, &remote_dev_info->rssi, + DBUS_TYPE_STRING, &remote_dev_info->name, + DBUS_TYPE_BOOLEAN, &remote_dev_info->paired, + DBUS_TYPE_BOOLEAN, &remote_dev_info->connected, + DBUS_TYPE_BOOLEAN, &remote_dev_info->trust, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, + &remote_dev_info->uuids, remote_dev_info->uuid_count, + DBUS_TYPE_INT16, &remote_dev_info->manufacturer_data_len, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &remote_dev_info->manufacturer_data, remote_dev_info->manufacturer_data_len, + DBUS_TYPE_INVALID); + } + _bt_free_device_info(remote_dev_info); + g_free(address); + } else if (strcasecmp(property, "GattConnected") == 0) { + gboolean gatt_connected = FALSE; + + dbus_message_iter_recurse(&dict_iter, &value_iter); + dbus_message_iter_get_basic(&value_iter, &gatt_connected); + + event = gatt_connected ? BLUETOOTH_EVENT_GATT_CONNECTED : + BLUETOOTH_EVENT_GATT_DISCONNECTED; + + address = g_malloc0(BT_ADDRESS_STRING_SIZE); + + _bt_convert_device_path_to_address(path, address); + BT_DBG("gatt_connected: %d", gatt_connected); + BT_DBG("address: %s", address); + + /* Send event to application */ + _bt_send_event(BT_DEVICE_EVENT, + event, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_INVALID); + + g_free(address); } else if (strcasecmp(property, "Paired") == 0) { gboolean paired = FALSE; - GList *node; + bt_remote_dev_info_t *remote_dev_info; dbus_message_iter_recurse(&dict_iter, &value_iter); dbus_message_iter_get_basic(&value_iter, &paired); - ret_if(paired == FALSE); - + _bt_agent_set_canceled(FALSE); /* BlueZ sends paired signal for each paired device */ /* during activation, We should ignore this, otherwise*/ /* application thinks that a new device got paired */ @@ -889,21 +1207,25 @@ void __bt_device_property_changed_event(DBusMessageIter *msg_iter, const char *p return; } - node = g_list_first(g_list); - - while (node != NULL) { - bt_remote_dev_info_t *dev_info; - dev_info = (bt_remote_dev_info_t *)node->data; - if (strcasecmp(dev_info->address, address) == 0) { - g_list = g_list_remove(g_list, dev_info); - _bt_free_device_info(dev_info); + if(paired == FALSE) { + BT_INFO("Unpaired: %s", address); + __bt_update_remote_cache_devinfo(address, FALSE); + _bt_send_event(BT_ADAPTER_EVENT, + BLUETOOTH_EVENT_BONDED_DEVICE_REMOVED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_INVALID); + } else { + BT_INFO("Paired: %s", address); + __bt_update_remote_cache_devinfo(address, TRUE); + + if (_bt_is_device_creating() == TRUE) { + BT_DBG("Try to Pair by me"); + _bt_free_device_info(remote_dev_info); + g_free(address); + return; } - node = g_list_next(node); - } - if (_bt_is_device_creating() == TRUE) { - BT_DBG("Try to Pair by me or already paired"); - } else { _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_BONDING_FINISHED, DBUS_TYPE_INT32, &result, @@ -916,16 +1238,183 @@ void __bt_device_property_changed_event(DBusMessageIter *msg_iter, const char *p DBUS_TYPE_BOOLEAN, &remote_dev_info->trust, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &remote_dev_info->uuids, remote_dev_info->uuid_count, + DBUS_TYPE_INT16, &remote_dev_info->manufacturer_data_len, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &remote_dev_info->manufacturer_data, remote_dev_info->manufacturer_data_len, DBUS_TYPE_INVALID); } + _bt_free_device_info(remote_dev_info); + g_free(address); + } else if (strcasecmp(property, "LegacyPaired") == 0) { + gboolean paired = FALSE; + bt_remote_dev_info_t *remote_dev_info; + + if (_bt_adapter_get_status() != BT_ACTIVATED) { + BT_DBG("BT is not activated, so ignore this"); + return; + } + + dbus_message_iter_recurse(&dict_iter, &value_iter); + dbus_message_iter_get_basic(&value_iter, &paired); + address = g_malloc0(BT_ADDRESS_STRING_SIZE); + BT_DBG("LegacyPaired: %d", paired); + _bt_convert_device_path_to_address(path, address); + + remote_dev_info = _bt_get_remote_device_info(address); + if (remote_dev_info == NULL) { + g_free(address); + return; + } + + BT_DBG("LegacyPairing Failed with %s. Show Error Popup", + remote_dev_info->name); + _bt_launch_system_popup(BT_AGENT_EVENT_LEGACY_PAIR_FAILED_FROM_REMOTE, + remote_dev_info->name, NULL, NULL, NULL); + + _bt_free_device_info(remote_dev_info); + g_free(address); + } else if (strcasecmp(property, "Trusted") == 0) { + gboolean trusted = FALSE; + + dbus_message_iter_recurse(&dict_iter, &value_iter); + dbus_message_iter_get_basic(&value_iter, &trusted); + + event = trusted ? BLUETOOTH_EVENT_DEVICE_AUTHORIZED : + BLUETOOTH_EVENT_DEVICE_UNAUTHORIZED; + + address = g_malloc0(BT_ADDRESS_STRING_SIZE); + + _bt_convert_device_path_to_address(path, address); + + BT_DBG("trusted: %d", trusted); + BT_DBG("address: %s", address); + + /* Send event to application */ + _bt_send_event(BT_DEVICE_EVENT, + event, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_INVALID); + + g_free(address); + } + dbus_message_iter_next(&item_iter); + } while (dbus_message_iter_get_arg_type(&item_iter) == + DBUS_TYPE_DICT_ENTRY); + BT_DBG("-"); +} + +static void __bt_media_control_changed_event(DBusMessageIter *msg_iter, const char *path) +{ + int event; + int result = BLUETOOTH_ERROR_NONE; + DBusMessageIter value_iter; + DBusMessageIter dict_iter; + DBusMessageIter item_iter; + const char *property = NULL; + char *address; + bt_remote_dev_info_t *remote_dev_info; + + dbus_message_iter_recurse(msg_iter, &item_iter); + + if (dbus_message_iter_get_arg_type(&item_iter) + != DBUS_TYPE_DICT_ENTRY) { + BT_ERR("This is bad format dbus"); + return; + } + + dbus_message_iter_recurse(&item_iter, &dict_iter); + + dbus_message_iter_get_basic(&dict_iter, &property); + ret_if(property == NULL); + + ret_if(!dbus_message_iter_next(&dict_iter)); + + if (strcasecmp(property, "Connected") == 0) { + gboolean connected = FALSE; + + dbus_message_iter_recurse(&dict_iter, &value_iter); + dbus_message_iter_get_basic(&value_iter, &connected); + + event = connected ? BLUETOOTH_EVENT_AVRCP_CONNECTED : + BLUETOOTH_EVENT_AVRCP_DISCONNECTED; + + address = g_malloc0(BT_ADDRESS_STRING_SIZE); + + _bt_convert_device_path_to_address(path, address); + + BT_DBG("connected: %d", connected); + BT_DBG("address: %s", address); + + remote_dev_info = _bt_get_remote_device_info(address); + + if (remote_dev_info != NULL) { + __bt_device_remote_connected_properties( + remote_dev_info, address, connected); + _bt_free_device_info(remote_dev_info); + } + + /* Send event to application */ + _bt_send_event(BT_AVRCP_EVENT, + event, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_INVALID); + g_free(address); + } + + BT_DBG("-"); +} + +void _bt_handle_property_changed_event(DBusMessage *msg) +{ + DBusMessageIter item_iter; + const char *member = dbus_message_get_member(msg); + const char *interface_name = NULL; + + ret_if(member == NULL); + + dbus_message_iter_init(msg, &item_iter); - _bt_free_device_info(remote_dev_info); - g_free(address); - } - } while (dbus_message_iter_next(&item_iter)); + if (dbus_message_iter_get_arg_type(&item_iter) + != DBUS_TYPE_STRING) { + BT_ERR("This is bad format dbus"); + return; + } + + dbus_message_iter_get_basic(&item_iter, &interface_name); + + ret_if(interface_name == NULL); + + ret_if(dbus_message_iter_next(&item_iter) == FALSE); + + ret_if(dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_ARRAY); + + if (strcasecmp(interface_name, BT_ADAPTER_INTERFACE) == 0) { + __bt_adapter_property_changed_event(&item_iter, + dbus_message_get_path(msg)); + } else if (strcasecmp(interface_name, BT_DEVICE_INTERFACE) == 0) { + __bt_device_property_changed_event(&item_iter, + dbus_message_get_path(msg)); + } else if (strcasecmp(interface_name, BT_OBEX_TRANSFER_INTERFACE) == 0) { + BT_DBG("BT_OBEX_TRANSFER_INTERFACE"); + __bt_obex_property_changed_event(&item_iter, + dbus_message_get_path(msg)); + } else if (strcasecmp(interface_name, BT_MEDIA_CONTROL_INTERFACE) == 0) { + __bt_media_control_changed_event(&item_iter, + dbus_message_get_path(msg)); + } else if (strcasecmp(interface_name, BT_PLAYER_CONTROL_INTERFACE) == 0) { + _bt_handle_avrcp_control_event(&item_iter, + dbus_message_get_path(msg)); + } else if (strcasecmp(interface_name, BT_NETWORK_CLIENT_INTERFACE) == 0) { + BT_DBG("BT_NETWORK_CLIENT_INTERFACE"); + _bt_handle_network_client_event(&item_iter, + dbus_message_get_path(msg)); + } } -void __bt_obex_property_changed_event(DBusMessageIter *msg_iter, const char *path) +void __bt_opc_property_changed_event(DBusMessageIter *msg_iter, + const char *path) { DBusMessageIter value_iter; DBusMessageIter dict_iter; @@ -935,8 +1424,8 @@ void __bt_obex_property_changed_event(DBusMessageIter *msg_iter, const char *pat dbus_message_iter_recurse(msg_iter, &item_iter); if (dbus_message_iter_get_arg_type(&item_iter) - != DBUS_TYPE_DICT_ENTRY) { - BT_ERR("This is bad format dbus\n"); + != DBUS_TYPE_DICT_ENTRY) { + BT_ERR("This is bad format dbus"); return; } @@ -948,26 +1437,65 @@ void __bt_obex_property_changed_event(DBusMessageIter *msg_iter, const char *pat ret_if(!dbus_message_iter_next(&dict_iter)); if (strcasecmp(property, "Status") == 0) { - const char *status; + const char *status = NULL; dbus_message_iter_recurse(&dict_iter, &value_iter); dbus_message_iter_get_basic(&value_iter, &status); - if (strcasecmp(status, "active") == 0){ - _bt_obex_transfer_started(path); + BT_INFO("Status is %s", status); + + if(strcasecmp(status, "active") == 0){ + _bt_obex_client_started(path); }else if (strcasecmp(status, "complete") == 0) { - _bt_obex_transfer_completed(path, TRUE); + _bt_obex_client_completed(path, TRUE); }else if (strcasecmp(status, "error") == 0){ - _bt_obex_transfer_completed(path, FALSE); + _bt_obex_client_completed(path, FALSE); } } else if (strcasecmp(property, "Transferred") == 0) { static int transferred = 0; dbus_message_iter_recurse(&dict_iter, &value_iter); dbus_message_iter_get_basic(&value_iter, &transferred); - _bt_obex_transfer_progress(path,transferred); + _bt_obex_client_progress(path, transferred); + } else { + BT_DBG("property : [%s]", property); + } +} + +void _bt_opc_property_changed_event(DBusMessage *msg) +{ + DBusMessageIter item_iter; + const char *member = dbus_message_get_member(msg); + const char *interface_name = NULL; + + ret_if(member == NULL); + + dbus_message_iter_init(msg, &item_iter); + + if (dbus_message_iter_get_arg_type(&item_iter) + != DBUS_TYPE_STRING) { + BT_ERR("This is bad format dbus"); + return; + } + + dbus_message_iter_get_basic(&item_iter, &interface_name); + + ret_if(interface_name == NULL); + + BT_DBG("interface: %s", interface_name); + + ret_if(dbus_message_iter_next(&item_iter) == FALSE); + + ret_if(dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_ARRAY); + + if (strcasecmp(interface_name, BT_OBEX_TRANSFER_INTERFACE) == 0) { + __bt_opc_property_changed_event(&item_iter, + dbus_message_get_path(msg)); + } else { + BT_DBG("interface_name : [%s]", interface_name); } } + void _bt_handle_input_event(DBusMessage *msg) { int result = BLUETOOTH_ERROR_NONE; @@ -977,6 +1505,7 @@ void _bt_handle_input_event(DBusMessage *msg) const char *member = dbus_message_get_member(msg); const char *path = dbus_message_get_path(msg); const char *property = NULL; + bt_remote_dev_info_t *remote_dev_info; ret_if(member == NULL); @@ -984,7 +1513,7 @@ void _bt_handle_input_event(DBusMessage *msg) if (dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_STRING) { - BT_ERR("This is bad format dbus\n"); + BT_ERR("This is bad format dbus"); return; } @@ -993,7 +1522,7 @@ void _bt_handle_input_event(DBusMessage *msg) ret_if(property == NULL); if (strcasecmp(property, "Connected") == 0) { - int event; + int event = BLUETOOTH_EVENT_NONE; char *address; dbus_message_iter_next(&item_iter); @@ -1013,6 +1542,42 @@ void _bt_handle_input_event(DBusMessage *msg) DBUS_TYPE_STRING, &address, DBUS_TYPE_INVALID); + /* Check HID connection type (Keyboard or Mouse) and update the status */ + remote_dev_info = _bt_get_remote_device_info(address); + + if (property_flag == TRUE) { + hid_connected_device_count++; + __bt_set_device_values(TRUE, + VCONFKEY_BT_DEVICE_HID_CONNECTED); + } else { + hid_connected_device_count--; + if (hid_connected_device_count == 0) + __bt_set_device_values(FALSE, + VCONFKEY_BT_DEVICE_HID_CONNECTED); + } + + if (remote_dev_info != NULL) { + BT_DBG("HID device class [%x]", remote_dev_info->class); + if (remote_dev_info->class & + BLUETOOTH_DEVICE_MINOR_CLASS_KEY_BOARD) { +#ifdef ENABLE_TIZEN_2_4 + __bt_set_device_values(property_flag, + VCONFKEY_BT_DEVICE_HID_KEYBOARD_CONNECTED); +#endif + + } + + if (remote_dev_info->class & + BLUETOOTH_DEVICE_MINOR_CLASS_POINTING_DEVICE) + { +#ifdef ENABLE_TIZEN_2_4 + __bt_set_device_values(property_flag, + VCONFKEY_BT_DEVICE_HID_MOUSE_CONNECTED); +#endif + } + _bt_free_device_info(remote_dev_info); + } + g_free(address); } } @@ -1035,11 +1600,15 @@ void _bt_handle_network_server_event(DBusMessage *msg) return; } + __bt_set_device_values(TRUE, + VCONFKEY_BT_DEVICE_PAN_CONNECTED); + _bt_send_event(BT_NETWORK_EVENT, BLUETOOTH_EVENT_NETWORK_SERVER_CONNECTED, DBUS_TYPE_INT32, &result, DBUS_TYPE_STRING, &device, DBUS_TYPE_STRING, &address, DBUS_TYPE_INVALID); + nap_connected_device_count++; } else if (strcasecmp(member, "PeerDisconnected") == 0) { if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &device, @@ -1048,6 +1617,10 @@ void _bt_handle_network_server_event(DBusMessage *msg) BT_ERR("Unexpected parameters in signal"); return; } + nap_connected_device_count--; + if (nap_connected_device_count == 0) + __bt_set_device_values(FALSE, + VCONFKEY_BT_DEVICE_PAN_CONNECTED); _bt_send_event(BT_NETWORK_EVENT, BLUETOOTH_EVENT_NETWORK_SERVER_DISCONNECTED, DBUS_TYPE_INT32, &result, @@ -1057,20 +1630,23 @@ void _bt_handle_network_server_event(DBusMessage *msg) } } -void __bt_handle_network_client_event(DBusMessageIter *msg_iter, const char *path) +void _bt_handle_network_client_event(DBusMessageIter *msg_iter, + const char *path) { + BT_DBG("+"); + int result = BLUETOOTH_ERROR_NONE; DBusMessageIter item_iter; - DBusMessageIter value_iter; DBusMessageIter dict_iter; + DBusMessageIter value_iter; gboolean property_flag = FALSE; const char *property = NULL; dbus_message_iter_recurse(msg_iter, &item_iter); if (dbus_message_iter_get_arg_type(&item_iter) - != DBUS_TYPE_DICT_ENTRY) { - BT_ERR("This is bad format dbus\n"); + != DBUS_TYPE_DICT_ENTRY) { + BT_ERR("This is bad format dbus"); return; } @@ -1078,7 +1654,6 @@ void __bt_handle_network_client_event(DBusMessageIter *msg_iter, const char *pat dbus_message_iter_get_basic(&dict_iter, &property); ret_if(property == NULL); - ret_if(!dbus_message_iter_next(&dict_iter)); if (strcasecmp(property, "Connected") == 0) { @@ -1092,10 +1667,18 @@ void __bt_handle_network_client_event(DBusMessageIter *msg_iter, const char *pat _bt_convert_device_path_to_address(path, address); + BT_DBG("property_flag %d", property_flag); if (property_flag == TRUE) { event = BLUETOOTH_EVENT_NETWORK_CONNECTED; + nap_connected_device_count++; + __bt_set_device_values(TRUE, + VCONFKEY_BT_DEVICE_PAN_CONNECTED); } else { event = BLUETOOTH_EVENT_NETWORK_DISCONNECTED; + nap_connected_device_count--; + if (nap_connected_device_count == 0) + __bt_set_device_values(FALSE, + VCONFKEY_BT_DEVICE_PAN_CONNECTED); } _bt_send_event(BT_NETWORK_EVENT, event, @@ -1105,10 +1688,12 @@ void __bt_handle_network_client_event(DBusMessageIter *msg_iter, const char *pat g_free(address); } + BT_DBG("-"); } void _bt_handle_device_event(DBusMessage *msg) { + int event; int result = BLUETOOTH_ERROR_NONE; DBusMessageIter item_iter; DBusMessageIter value_iter; @@ -1125,7 +1710,7 @@ void _bt_handle_device_event(DBusMessage *msg) if (dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_STRING) { - BT_ERR("This is bad format dbus\n"); + BT_ERR("This is bad format dbus"); return; } @@ -1133,24 +1718,20 @@ void _bt_handle_device_event(DBusMessage *msg) ret_if(property == NULL); - if (strcasecmp(property, "Connected") == 0) { - int event; + if (strcasecmp(property, "GattConnected") == 0) { gboolean connected = FALSE; - dbus_message_iter_next(&item_iter); - dbus_message_iter_recurse(&item_iter, &value_iter); - dbus_message_iter_get_basic(&value_iter, &connected); - - event = connected ? BLUETOOTH_EVENT_DEVICE_CONNECTED : - BLUETOOTH_EVENT_DEVICE_DISCONNECTED; + char *address; address = g_malloc0(BT_ADDRESS_STRING_SIZE); - _bt_convert_device_path_to_address(path, address); - BT_DBG("connected: %d", connected); - BT_DBG("address: %s", address); + dbus_message_iter_next(&item_iter); + dbus_message_iter_recurse(&item_iter, &value_iter); + dbus_message_iter_get_basic(&value_iter, &connected); + + event = connected ? BLUETOOTH_EVENT_GATT_CONNECTED : + BLUETOOTH_EVENT_GATT_DISCONNECTED; - /* Send event to application */ _bt_send_event(BT_DEVICE_EVENT, event, DBUS_TYPE_INT32, &result, @@ -1202,109 +1783,358 @@ void _bt_handle_device_event(DBusMessage *msg) DBUS_TYPE_BOOLEAN, &remote_dev_info->trust, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &remote_dev_info->uuids, remote_dev_info->uuid_count, + DBUS_TYPE_INT16, &remote_dev_info->manufacturer_data_len, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &remote_dev_info->manufacturer_data, remote_dev_info->manufacturer_data_len, DBUS_TYPE_INVALID); _bt_free_device_info(remote_dev_info); g_free(address); - } - } -} -void __bt_handle_media_control_event(DBusMessageIter *msg_iter, - const char *path) -{ - int result = BLUETOOTH_ERROR_NONE; - DBusMessageIter item_iter; - DBusMessageIter value_iter; - DBusMessageIter dict_iter; - gboolean property_flag = FALSE; - const char *property = NULL; + } else if (strcasecmp(property, "UUIDs") == 0) { + /* Once we get the updated uuid information after + * reverse service search, update it to application */ - dbus_message_iter_recurse(msg_iter, &item_iter); + bt_remote_dev_info_t *remote_dev_info; - if (dbus_message_iter_get_arg_type(&item_iter) - != DBUS_TYPE_DICT_ENTRY) { - BT_ERR("This is bad format dbus\n"); - return; - } + ret_if(_bt_is_device_creating() == TRUE); - dbus_message_iter_recurse(&item_iter, &dict_iter); + address = g_malloc0(BT_ADDRESS_STRING_SIZE); - dbus_message_iter_get_basic(&dict_iter, &property); - ret_if(property == NULL); + _bt_convert_device_path_to_address(path, address); - ret_if(!dbus_message_iter_next(&dict_iter)); + remote_dev_info = _bt_get_remote_device_info(address); + if (remote_dev_info == NULL) { + g_free(address); + return; + } - if (strcasecmp(property, "Connected") == 0) { - int event; - char *address; + BT_DBG("UUID's count = %d", remote_dev_info->uuid_count); + if (remote_dev_info->paired && remote_dev_info->uuid_count) + _bt_send_event(BT_ADAPTER_EVENT, + BLUETOOTH_EVENT_SERVICE_SEARCHED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_UINT32, &remote_dev_info->class, + DBUS_TYPE_INT16, &remote_dev_info->rssi, + DBUS_TYPE_STRING, &remote_dev_info->name, + DBUS_TYPE_BOOLEAN, &remote_dev_info->paired, + DBUS_TYPE_BOOLEAN, &remote_dev_info->connected, + DBUS_TYPE_BOOLEAN, &remote_dev_info->trust, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, + &remote_dev_info->uuids, remote_dev_info->uuid_count, + DBUS_TYPE_INVALID); - dbus_message_iter_recurse(&dict_iter, &value_iter); - dbus_message_iter_get_basic(&value_iter, &property_flag); + _bt_free_device_info(remote_dev_info); + g_free(address); + } + } else if (strcasecmp(member, "DeviceConnected") == 0) { + unsigned char addr_type = 0; + + dbus_message_iter_init(msg, &item_iter); + dbus_message_iter_get_basic(&item_iter, &addr_type); address = g_malloc0(BT_ADDRESS_STRING_SIZE); _bt_convert_device_path_to_address(path, address); - event = (property_flag == TRUE) ? - BLUETOOTH_EVENT_AV_CONNECTED : - BLUETOOTH_EVENT_AV_DISCONNECTED; + BT_INFO("Address : %s Type : %d", address, addr_type); + BT_ERR_C("Connected [%s]", !addr_type ? "BREDR" : "LE"); - _bt_send_event(BT_AVRCP_EVENT, event, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID); + _bt_logging_connection(TRUE, addr_type); +// journal_bt_connected(); + + /*Send event to application*/ + _bt_send_event(BT_DEVICE_EVENT, + BLUETOOTH_EVENT_DEVICE_CONNECTED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_BYTE, &addr_type, + DBUS_TYPE_INVALID); g_free(address); - } -} + } else if (strcasecmp(member, "Disconnected") == 0) { + unsigned char disc_reason = 0; + unsigned char addr_type = 0; + gboolean sending = FALSE; -void _bt_handle_property_changed_event(DBusMessage *msg) -{ - DBusMessageIter item_iter; - const char *member = dbus_message_get_member(msg); - const char *interface_name = NULL; + if (!dbus_message_get_args(msg, NULL, + DBUS_TYPE_BYTE, &addr_type, + DBUS_TYPE_BYTE, &disc_reason, + DBUS_TYPE_INVALID)) + return; + + result = disc_reason; + + address = g_malloc0(BT_ADDRESS_STRING_SIZE); + + _bt_convert_device_path_to_address(path, address); +// journal_bt_disconnected(); + + /* 0x00 BDADDR_BRDER + 0x01 BDADDR_LE_PUBLIC + 0x02 BDADDR_LE_RANDOM */ + BT_INFO("Address : %s Type : %d", address, addr_type); + BT_ERR_C("Disconnected [%s] [%d : %s]", !addr_type ? "BREDR" : "LE", + disc_reason, _bt_convert_disc_reason_to_string(disc_reason)); + + _bt_headset_set_local_connection(FALSE); + _bt_logging_connection(FALSE, addr_type); + + /*Check for any OPP transfer on the device and cancel + * the transfer + */ + _bt_obex_check_pending_transfer(address); + _bt_opp_client_is_sending(&sending); + if(sending == TRUE) + _bt_opp_client_check_pending_transfer(address); + + _bt_send_event(BT_DEVICE_EVENT, + BLUETOOTH_EVENT_DEVICE_DISCONNECTED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_BYTE, &addr_type, + DBUS_TYPE_INVALID); + + g_free(address); + } else if (strcasecmp(member, "ProfileStateChanged") == 0) { + int state = 0; + char *profile_uuid = NULL; + bt_headset_wait_t *wait_list; + + if (!dbus_message_get_args(msg, NULL, + DBUS_TYPE_STRING, &profile_uuid, + DBUS_TYPE_INT32, &state, + DBUS_TYPE_INVALID)) { + return; + } + address = g_malloc0(BT_ADDRESS_STRING_SIZE); + + _bt_convert_device_path_to_address(path, address); + + BT_DBG("Address: %s", address); + BT_DBG("Profile UUID: %s", profile_uuid); + BT_DBG("State: %d", state); + + if ((strcmp(profile_uuid, A2DP_SINK_UUID) == 0) && + (state == BT_PROFILE_STATE_CONNECTED)) { + + int event = BLUETOOTH_EVENT_AV_CONNECTED; + char connected_address[BT_ADDRESS_STRING_SIZE + 1]; + bluetooth_device_address_t device_address; + gboolean connected; + bt_headset_wait_t *wait_list; + + __bt_set_device_values(TRUE, + VCONFKEY_BT_DEVICE_A2DP_HEADSET_CONNECTED); + + __bt_connection_manager_set_state(address, event); + + if (_bt_headset_get_local_connection() == FALSE) + _bt_start_timer_for_connection(address, BT_AUDIO_HSP); + else { + /* Connection Started from local device therefore no need to + * intiate connection for pending profile */ + _bt_headset_set_local_connection(FALSE); + } + + _bt_send_event(BT_HEADSET_EVENT, event, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_INVALID); + + connected = _bt_is_headset_type_connected(BT_AUDIO_A2DP, + connected_address); + if (connected) { + if (g_strcmp0(connected_address, address) != 0) { + _bt_convert_addr_string_to_type( + device_address.addr, + connected_address); + _bt_audio_disconnect(0, BT_AUDIO_A2DP, + &device_address, NULL); + } + } + + _bt_add_headset_to_list(BT_AUDIO_A2DP, + BT_STATE_CONNECTED, address); + + wait_list = _bt_get_audio_wait_data(); + if (wait_list != NULL && + (g_strcmp0(wait_list->address, address) == 0)) + _bt_rel_wait_data(); + + } else if ((strcmp(profile_uuid, A2DP_SINK_UUID) == 0) && + (state == BT_PROFILE_STATE_DISCONNECTED)) { + + int event = BLUETOOTH_EVENT_AV_DISCONNECTED; + + if (!_bt_is_service_connected(address, BT_AUDIO_A2DP)) { + g_free(address); + return; + } + + __bt_set_device_values(FALSE, + VCONFKEY_BT_DEVICE_A2DP_HEADSET_CONNECTED); + + __bt_connection_manager_set_state(address, event); + + _bt_send_event(BT_HEADSET_EVENT, event, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_INVALID); + + /* Remove data from the connected list */ + _bt_remove_headset_from_list(BT_AUDIO_A2DP, address); + wait_list = _bt_get_audio_wait_data(); + + if (wait_list == NULL) { + g_free(address); + return; + } + + if (((wait_list->type == BT_AUDIO_ALL) && + (wait_list->ag_flag == TRUE)) || + (wait_list->type == BT_AUDIO_A2DP) || + (wait_list->disconnection_type == BT_AUDIO_A2DP)) { + bluetooth_device_address_t device_address; + _bt_convert_addr_string_to_type( + device_address.addr, + wait_list->address); + + _bt_audio_connect(wait_list->req_id, + wait_list->type, + &device_address, + wait_list->out_param1); + } + } else if (strcmp(profile_uuid, AVRCP_TARGET_UUID) == 0) { + + if (state == BT_PROFILE_STATE_CONNECTED) { + int event = BLUETOOTH_EVENT_AVRCP_CONTROL_CONNECTED; + char connected_address[BT_ADDRESS_STRING_SIZE + 1]; + bluetooth_device_address_t device_address; + gboolean connected; + + _bt_send_event(BT_AVRCP_CONTROL_EVENT, event, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_INVALID); + connected = _bt_is_headset_type_connected( + BT_AVRCP, + connected_address); + if (connected) { + if (g_strcmp0(connected_address, + address) != 0) { + _bt_convert_addr_string_to_type( + device_address.addr, + connected_address); + _bt_audio_disconnect(0, + BT_AVRCP, + &device_address, NULL); + } + } + BT_DBG("device Path: %s", path); + _bt_add_headset_to_list(BT_AVRCP, + BT_STATE_CONNECTED, address); + } else if (state == BT_PROFILE_STATE_DISCONNECTED) { + int event = BLUETOOTH_EVENT_AVRCP_CONTROL_DISCONNECTED; - ret_if(member == NULL); + _bt_send_event(BT_AVRCP_CONTROL_EVENT, event, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_INVALID); - dbus_message_iter_init(msg, &item_iter); + /* Remove data from the connected list */ + _bt_remove_headset_from_list(BT_AVRCP, address); + } + } else if ((strcmp(profile_uuid, HID_UUID) == 0) && + ((state == BT_PROFILE_STATE_CONNECTED) || + (state == BT_PROFILE_STATE_DISCONNECTED))) { + int event; + if (state == BT_PROFILE_STATE_CONNECTED) + event = BLUETOOTH_HID_CONNECTED; + else + event = BLUETOOTH_HID_DISCONNECTED; - if (dbus_message_iter_get_arg_type(&item_iter) - != DBUS_TYPE_STRING) { - BT_ERR("This is bad format dbus\n"); - return; - } + _bt_send_event(BT_HID_EVENT, event, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_INVALID); + } + g_free(address); + } else if (strcasecmp(member, "AdvReport") == 0) { - dbus_message_iter_get_basic(&item_iter, &interface_name); + bt_remote_le_dev_info_t *le_dev_info = NULL; + char *buffer = NULL; + int buffer_len = 0; + bt_le_adv_info_t *adv_info = NULL; - ret_if(interface_name == NULL); + ret_if(_bt_is_le_discovering() == FALSE); - BT_DBG("interface: %s", interface_name); + le_dev_info = g_malloc0(sizeof(bt_remote_le_dev_info_t)); - ret_if(dbus_message_iter_next(&item_iter) == FALSE); + if (!dbus_message_get_args(msg, NULL, + DBUS_TYPE_STRING, &le_dev_info->address, + DBUS_TYPE_BYTE, &le_dev_info->addr_type, + DBUS_TYPE_BYTE, &le_dev_info->adv_type, + DBUS_TYPE_INT32, &le_dev_info->rssi, + DBUS_TYPE_INT32, &le_dev_info->adv_data_len, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &buffer, &buffer_len, + DBUS_TYPE_INVALID)) { + g_free(le_dev_info); + return; + } - ret_if(dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_ARRAY); + le_dev_info->adv_data = g_memdup(buffer, buffer_len); - if (strcasecmp(interface_name, BT_ADAPTER_INTERFACE) == 0) { - __bt_adapter_property_changed_event(&item_iter, - dbus_message_get_path(msg)); - } else if (strcasecmp(interface_name, BT_DEVICE_INTERFACE) == 0) { - __bt_device_property_changed_event(&item_iter, - dbus_message_get_path(msg)); - } else if (strcasecmp(interface_name, - BT_OBEX_TRANSFER_INTERFACE) == 0) { - __bt_obex_property_changed_event(&item_iter, - dbus_message_get_path(msg)); - } else if (strcasecmp(interface_name, - BT_MEDIA_CONTROL_INTERFACE) == 0) { - __bt_handle_media_control_event(&item_iter, - dbus_message_get_path(msg)); - } else if (strcasecmp(interface_name, - BT_NETWORK_CLIENT_INTERFACE) == 0) { - __bt_handle_network_client_event(&item_iter, - dbus_message_get_path(msg)); - } else { - BT_DBG("No bluez interface"); + if (_bt_get_le_discovery_type() == BT_LE_PASSIVE_SCAN) { + int len = 0; + _bt_send_event(BT_LE_ADAPTER_EVENT, + BLUETOOTH_EVENT_REMOTE_LE_DEVICE_FOUND, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &le_dev_info->address, + DBUS_TYPE_INT16, &le_dev_info->addr_type, + DBUS_TYPE_INT16, &le_dev_info->rssi, + DBUS_TYPE_INT16, &le_dev_info->adv_data_len, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &le_dev_info->adv_data, le_dev_info->adv_data_len, + DBUS_TYPE_INT16, &len, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &le_dev_info->adv_data, len, + DBUS_TYPE_INVALID); + _bt_free_le_device_info(le_dev_info); + return; + } + + if (le_dev_info->adv_type != BT_LE_ADV_SCAN_RSP) { /* ADV_IND */ + adv_info = g_malloc0(sizeof(bt_le_adv_info_t)); + adv_info->addr = g_strdup(le_dev_info->address); + adv_info->data_len = le_dev_info->adv_data_len; + adv_info->data = g_malloc0(le_dev_info->adv_data_len); + memcpy(adv_info->data, le_dev_info->adv_data, + le_dev_info->adv_data_len); + + __bt_add_adv_ind_info(adv_info); + + } else { /* SCAN_RSP */ + adv_info = __bt_get_adv_ind_info(le_dev_info->address); + if (adv_info) { + _bt_send_event(BT_LE_ADAPTER_EVENT, + BLUETOOTH_EVENT_REMOTE_LE_DEVICE_FOUND, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &le_dev_info->address, + DBUS_TYPE_INT16, &le_dev_info->addr_type, + DBUS_TYPE_INT16, &le_dev_info->rssi, + DBUS_TYPE_INT16, &adv_info->data_len, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &adv_info->data, adv_info->data_len, + DBUS_TYPE_INT16, &le_dev_info->adv_data_len, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &le_dev_info->adv_data, le_dev_info->adv_data_len, + DBUS_TYPE_INVALID); + __bt_del_adv_ind_info(le_dev_info->address); + } + } + _bt_free_le_device_info(le_dev_info); } } @@ -1333,11 +2163,21 @@ void __bt_set_audio_values(gboolean connected, char *address) BT_ERR("vconf_get_str failed"); } +#ifdef TIZEN_SUPPORT_DUAL_HF + if ((connected == TRUE) && + (FALSE == __bt_is_companion_device(address))) { + bt_device_state |= VCONFKEY_BT_DEVICE_HEADSET_CONNECTED; + } else if ((bt_device_state & VCONFKEY_BT_DEVICE_HEADSET_CONNECTED) && + (FALSE == __bt_is_companion_device(address))) { + bt_device_state ^= VCONFKEY_BT_DEVICE_HEADSET_CONNECTED; + } +#else if (connected == TRUE) { bt_device_state |= VCONFKEY_BT_DEVICE_HEADSET_CONNECTED; } else if (bt_device_state & VCONFKEY_BT_DEVICE_HEADSET_CONNECTED) { bt_device_state ^= VCONFKEY_BT_DEVICE_HEADSET_CONNECTED; } +#endif if (vconf_set_int(VCONFKEY_BT_DEVICE, bt_device_state) != 0) { @@ -1361,7 +2201,7 @@ void _bt_handle_headset_event(DBusMessage *msg) if (dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_STRING) { - BT_ERR("This is bad format dbus\n"); + BT_ERR("This is bad format dbus"); return; } @@ -1369,9 +2209,12 @@ void _bt_handle_headset_event(DBusMessage *msg) ret_if(property == NULL); + BT_DBG("Property = %s \n", property); + /* We allow only 1 headset connection (HSP or HFP)*/ if (strcasecmp(property, "Connected") == 0) { int event = BLUETOOTH_EVENT_NONE; + bt_headset_wait_t *wait_list; char *address; dbus_message_iter_next(&item_iter); @@ -1384,10 +2227,21 @@ void _bt_handle_headset_event(DBusMessage *msg) if (property_flag == TRUE) { event = BLUETOOTH_EVENT_AG_CONNECTED; + if (_bt_headset_get_local_connection() == FALSE) + _bt_start_timer_for_connection(address, BT_AUDIO_A2DP); + else + _bt_headset_set_local_connection(FALSE); } else { + int previous_state; + event = BLUETOOTH_EVENT_AG_DISCONNECTED; - } + previous_state = _bt_get_device_state_from_list(BT_AUDIO_HSP, address); + if (previous_state == BT_STATE_DISCONNECTING) + _bt_send_hf_local_term_event(address); + } + /* Set the State machine here */ + __bt_connection_manager_set_state(address, event); __bt_set_audio_values(property_flag, address); _bt_send_event(BT_HEADSET_EVENT, event, @@ -1395,16 +2249,41 @@ void _bt_handle_headset_event(DBusMessage *msg) DBUS_TYPE_STRING, &address, DBUS_TYPE_INVALID); + if (event == BLUETOOTH_EVENT_AG_DISCONNECTED) { + /* Remove data from the connected list */ + _bt_remove_headset_from_list(BT_AUDIO_HSP, address); + + wait_list = _bt_get_audio_wait_data(); + if (wait_list == NULL) { + g_free(address); + return; + } + + bluetooth_device_address_t device_address; + + _bt_set_audio_wait_data_flag(TRUE); + + _bt_convert_addr_string_to_type(device_address.addr, + wait_list->address); + _bt_audio_connect(wait_list->req_id, wait_list->type, + &device_address, wait_list->out_param1); + _bt_rel_wait_data(); + } else if (event == BLUETOOTH_EVENT_AG_CONNECTED) { + /* Add data to the connected list */ + _bt_add_headset_to_list(BT_AUDIO_HSP, + BT_STATE_CONNECTED, address); + + wait_list = _bt_get_audio_wait_data(); + if (wait_list != NULL && + (g_strcmp0(wait_list->address, address) == 0)) + _bt_rel_wait_data(); + + BT_INFO("Check A2DP pending connect"); + _bt_audio_check_pending_connect(); + } g_free(address); } else if (strcasecmp(property, "State") == 0) { - int event = BLUETOOTH_EVENT_NONE; - int sco_connected = FALSE; char *state = NULL; - char *address; - - address = g_malloc0(BT_ADDRESS_STRING_SIZE); - - _bt_convert_device_path_to_address(path, address); dbus_message_iter_next(&item_iter); dbus_message_iter_recurse(&item_iter, &value_iter); @@ -1412,28 +2291,15 @@ void _bt_handle_headset_event(DBusMessage *msg) /* This code assumes we support only 1 headset connection */ /* Need to use the headset list, if we support multi-headsets */ - if (strcasecmp(property, "Playing") == 0) { - event = BLUETOOTH_EVENT_AG_AUDIO_CONNECTED; - sco_connected = TRUE; - } else if (strcasecmp(property, "connected") == 0 || - strcasecmp(property, "disconnected") == 0) { - event = BLUETOOTH_EVENT_AG_AUDIO_DISCONNECTED; - sco_connected = FALSE; + if (strcasecmp(state, "Playing") == 0) { + BT_DBG("Playing: Sco Connected"); + } else if (strcasecmp(state, "connected") == 0 || + strcasecmp(state, "disconnected") == 0) { + BT_DBG("connected/disconnected: Sco Disconnected"); } else { - BT_ERR("Not handled state"); - g_free(address); + BT_ERR("Not handled state - %s", state); return; } - - if (vconf_set_bool(VCONFKEY_BT_HEADSET_SCO, sco_connected) < 0) - BT_ERR("vconf_set_bool - Failed\n"); - - _bt_send_event(BT_HEADSET_EVENT, event, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID); - - g_free(address); } else if (strcasecmp(property, "SpeakerGain") == 0) { guint16 spkr_gain; char *address; @@ -1475,6 +2341,125 @@ void _bt_handle_headset_event(DBusMessage *msg) } } +void _bt_handle_sink_event(DBusMessage *msg) +{ + int result = BLUETOOTH_ERROR_NONE; + DBusMessageIter item_iter; + DBusMessageIter value_iter; + const char *member = dbus_message_get_member(msg); + const char *path = dbus_message_get_path(msg); + const char *property = NULL; + + bt_headset_wait_t *wait_list; + + ret_if(member == NULL); + + dbus_message_iter_init(msg, &item_iter); + + if (dbus_message_iter_get_arg_type(&item_iter) + != DBUS_TYPE_STRING) { + BT_ERR("This is bad format dbus"); + return; + } + + dbus_message_iter_get_basic(&item_iter, &property); + + ret_if(property == NULL); + + BT_DBG("Property: %s", property); + + if (strcasecmp(property, "State") == 0) { + + const char *value; + + dbus_message_iter_next(&item_iter); + dbus_message_iter_recurse(&item_iter, &value_iter); + dbus_message_iter_get_basic(&value_iter, &value); + + BT_DBG("value: %s", value); + + if (g_strcmp0(value, "disconnected") == 0) { + char *address; + + address = g_malloc0(BT_ADDRESS_STRING_SIZE); + + _bt_convert_device_path_to_address(path, address); + + __bt_set_device_values(FALSE, + VCONFKEY_BT_DEVICE_A2DP_HEADSET_CONNECTED); + + _bt_send_event(BT_HEADSET_EVENT, + BLUETOOTH_EVENT_AV_DISCONNECTED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_INVALID); + + /* Remove data from the connected list */ + _bt_remove_headset_from_list(BT_AUDIO_A2DP, address); + wait_list = _bt_get_audio_wait_data(); + if (wait_list == NULL) { + g_free(address); + return; + } + + if (((wait_list->type == BT_AUDIO_ALL) && + (wait_list->ag_flag == TRUE)) || + (wait_list->type == BT_AUDIO_A2DP) || + (wait_list->disconnection_type == BT_AUDIO_A2DP)) { + bluetooth_device_address_t device_address; + _bt_convert_addr_string_to_type( + device_address.addr, + wait_list->address); + + _bt_audio_connect(wait_list->req_id, + wait_list->type, + &device_address, + wait_list->out_param1); + } + g_free(address); + }else if (strcasecmp(value, "Connected") == 0) { + char *address; + char connected_address[BT_ADDRESS_STRING_SIZE + 1]; + bluetooth_device_address_t device_address; + gboolean connected; + + address = g_malloc0(BT_ADDRESS_STRING_SIZE); + + _bt_convert_device_path_to_address(path, address); + + __bt_set_device_values(TRUE, + VCONFKEY_BT_DEVICE_A2DP_HEADSET_CONNECTED); + + _bt_send_event(BT_HEADSET_EVENT, + BLUETOOTH_EVENT_AV_CONNECTED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_INVALID); + + /* Check for existing Media device to disconnect */ + connected = _bt_is_headset_type_connected(BT_AUDIO_A2DP, + connected_address); + if (connected) { + /* Match connected device address */ + if (g_strcmp0(connected_address, address) != 0) { + /* Convert BD adress from string type */ + _bt_convert_addr_string_to_type( + device_address.addr, + connected_address); + _bt_audio_disconnect(0, BT_AUDIO_A2DP, + &device_address, NULL); + } + } + + /* Add data to the connected list */ + _bt_add_headset_to_list(BT_AUDIO_A2DP, + BT_STATE_CONNECTED, address); + + g_free(address); + } + } +} + void _bt_handle_agent_event(DBusMessage *msg) { const char *member = dbus_message_get_member(msg); @@ -1522,7 +2507,7 @@ static int __bt_get_object_path(DBusMessage *msg, char **path) if (dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_OBJECT_PATH) { - BT_ERR("This is bad format dbus\n"); + BT_ERR("This is bad format dbus"); return BLUETOOTH_ERROR_INTERNAL; } @@ -1534,18 +2519,111 @@ static int __bt_get_object_path(DBusMessage *msg, char **path) return BLUETOOTH_ERROR_NONE; } -static void __bt_devices_list_free() +static int __bt_parse_event(DBusMessage *msg) +{ + DBusMessageIter msg_iter; + DBusMessageIter value_iter; + + retv_if(dbus_message_iter_init(msg, &msg_iter) == FALSE, 0); + + /* object array (oa) */ + retv_if(dbus_message_iter_next(&msg_iter) == FALSE, 0); + retv_if(dbus_message_iter_get_arg_type(&msg_iter) != + DBUS_TYPE_ARRAY, 0); + + dbus_message_iter_recurse(&msg_iter, &value_iter); + + /* string array (sa) */ + while (dbus_message_iter_get_arg_type(&value_iter) == + DBUS_TYPE_DICT_ENTRY) { + char *interface_name = NULL; + DBusMessageIter interface_iter; + + dbus_message_iter_recurse(&value_iter, &interface_iter); + + retv_if(dbus_message_iter_get_arg_type(&interface_iter) != + DBUS_TYPE_STRING, 0); + + dbus_message_iter_get_basic(&interface_iter, + &interface_name); + + retv_if(dbus_message_iter_next(&interface_iter) == FALSE, + 0); + + retv_if(dbus_message_iter_get_arg_type(&interface_iter) != + DBUS_TYPE_ARRAY, 0); + + BT_DBG("interface: %s", interface_name); + + if (g_strcmp0(interface_name, + BT_DEVICE_INTERFACE) == 0) { + return BT_DEVICE_EVENT; + } else if (g_strcmp0(interface_name, + BT_MEDIATRANSPORT_INTERFACE) == 0) { + return BT_MEDIA_TRANSFER_EVENT; + } else if (g_strcmp0(interface_name, + BT_PLAYER_CONTROL_INTERFACE) == 0) { + return BT_AVRCP_CONTROL_EVENT; + } + dbus_message_iter_next(&value_iter); + } + + return 0; +} + +static int __bt_parse_remove_event(DBusMessage *msg) +{ + DBusMessageIter msg_iter; + DBusMessageIter value_iter; + + retv_if(dbus_message_iter_init(msg, &msg_iter) == + FALSE, 0); + + retv_if(dbus_message_iter_next(&msg_iter) == FALSE, + 0); + retv_if(dbus_message_iter_get_arg_type(&msg_iter) != + DBUS_TYPE_ARRAY, 0); + + dbus_message_iter_recurse(&msg_iter, &value_iter); + + while (dbus_message_iter_get_arg_type(&value_iter) + != DBUS_TYPE_INVALID) { + char *key; + + dbus_message_iter_get_basic(&value_iter, &key); + + if (key == NULL) { + dbus_message_iter_next(&value_iter); + continue; + } + + BT_DBG("key = %s", key); + + if (g_strcmp0(key, BT_MEDIATRANSPORT_INTERFACE) == 0) { + return BT_MEDIA_TRANSFER_EVENT; + } else if (g_strcmp0(key, BT_DEVICE_INTERFACE) == 0) { + return BT_DEVICE_EVENT; + } else if (g_strcmp0(key, BT_PLAYER_CONTROL_INTERFACE) == 0) { + return BT_AVRCP_CONTROL_EVENT; + } + dbus_message_iter_next(&value_iter); + } + + return 0; +} + +static void __bt_devices_list_free(void) { + bt_cache_info_t *cache_info; GList *node; - node = g_list_first(g_list); + node = g_list_first(p_cache_list); while (node != NULL){ - bt_remote_dev_info_t *dev_info; - dev_info = (bt_remote_dev_info_t *)node->data; + cache_info = (bt_cache_info_t *)node->data; - g_list = g_list_remove(g_list, dev_info); - _bt_free_device_info(dev_info); + p_cache_list = g_list_remove(p_cache_list, cache_info); + __bt_free_cache_info(cache_info); node = g_list_next(node); } @@ -1556,142 +2634,101 @@ static DBusHandlerResult __bt_manager_event_filter(DBusConnection *conn, { const char *member = dbus_message_get_member(msg); bt_event_type_t bt_event; + int result = BLUETOOTH_ERROR_NONE; if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; retv_if(member == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - BT_DBG("interface: %s | member: %s", dbus_message_get_interface(msg), member); - if (strcasecmp(member, "InterfacesAdded") == 0) { char *object_path = NULL; + BT_DBG("InterfacesAdded"); + if (__bt_get_object_path(msg, &object_path)) { BT_ERR("Fail to get the path"); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } - bt_event = __bt_parse_event(msg); + if (strcasecmp(object_path, BT_BLUEZ_HCI_PATH) == 0) { + _bt_handle_adapter_added(); + } else { + bt_event = __bt_parse_event(msg); + if (bt_event == BT_DEVICE_EVENT) { + bt_cache_info_t *cache_info; + bt_remote_dev_info_t *dev_info; + + retv_if(_bt_is_discovering() == FALSE && + _bt_is_le_discovering() == FALSE, + DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - if (bt_event == BT_DEVICE_EVENT) { - bt_remote_dev_info_t *dev_info; - int result = BLUETOOTH_ERROR_NONE; + cache_info = g_malloc0(sizeof(bt_cache_info_t)); + dev_info = g_malloc0(sizeof(bt_remote_dev_info_t)); + cache_info->dev_info = dev_info; - retv_if(_bt_is_discovering() == FALSE, - DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + if (__bt_parse_interface(msg, dev_info) == FALSE) { + BT_ERR("Fail to parse the properies"); + __bt_free_cache_info(cache_info); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } - dev_info = __bt_parse_interface(msg); + if (dev_info->addr_type != BDADDR_BREDR) { + /* Whenever emit the property changed from bluez, + some property doesn't reach to bt-service. + So LE device is handled as AdvReport signal */ + __bt_free_cache_info(cache_info); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } - if (dev_info == NULL) { - BT_ERR("Fail to parse the properies"); - return - DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + if (dev_info->name == NULL) + /* If Remote device name is NULL or still RNR is not done + * then display address as name. + */ + dev_info->name = g_strdup(dev_info->address); - if (dev_info->name == NULL) - dev_info->name = g_strdup(""); + _bt_send_event(BT_ADAPTER_EVENT, + BLUETOOTH_EVENT_REMOTE_DEVICE_FOUND, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &dev_info->address, + DBUS_TYPE_UINT32, &dev_info->class, + DBUS_TYPE_INT16, &dev_info->rssi, + DBUS_TYPE_STRING, &dev_info->name, + DBUS_TYPE_BOOLEAN, &dev_info->paired, + DBUS_TYPE_BOOLEAN, &dev_info->connected, + DBUS_TYPE_BOOLEAN, &dev_info->trust, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, + &dev_info->uuids, dev_info->uuid_count, + DBUS_TYPE_INT16, &dev_info->manufacturer_data_len, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &dev_info->manufacturer_data, dev_info->manufacturer_data_len, + DBUS_TYPE_INVALID); - _bt_send_event(BT_ADAPTER_EVENT, - BLUETOOTH_EVENT_REMOTE_DEVICE_FOUND, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &dev_info->address, - DBUS_TYPE_UINT32, &dev_info->class, - DBUS_TYPE_INT16, &dev_info->rssi, - DBUS_TYPE_STRING, &dev_info->name, - DBUS_TYPE_BOOLEAN, &dev_info->paired, - DBUS_TYPE_BOOLEAN, - &dev_info->connected, - DBUS_TYPE_BOOLEAN, &dev_info->trust, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, - &dev_info->uuids, dev_info->uuid_count, - DBUS_TYPE_INVALID); - g_list = g_list_append(g_list, dev_info); - } else if (bt_event == BT_MEDIA_TRANSFER_EVENT) { - __bt_parse_audio_properties(msg); + p_cache_list = g_list_append(p_cache_list, cache_info); + } else if (bt_event == BT_AVRCP_CONTROL_EVENT) { + BT_DBG("Device path : %s ", object_path); + _bt_set_control_device_path(object_path); + } } - } else if (strcasecmp(member, "InterfacesRemoved") == 0) { - bt_event = __bt_parse_remove_event(msg); - if (bt_event == BT_MEDIA_TRANSFER_EVENT){ - _bt_parse_audio_remove_properties(msg); - } else if (bt_event == BT_DEVICE_EVENT) { - char *object_path = NULL; - if (__bt_get_object_path(msg, &object_path)) { - BT_ERR("Fail to get the path"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - - if (strncasecmp(object_path, BT_BLUEZ_HCI_DEV_PATH, strlen(BT_BLUEZ_HCI_DEV_PATH)) == 0) { - int result = BLUETOOTH_ERROR_NONE; - char *address; - bt_remote_dev_info_t *dev_info; - GList * node; - gboolean is_in_glist = FALSE; - - BT_DBG("device interface removed | path: %s", object_path); - - /* Remove bonding from remote device */ - address = g_malloc0(BT_ADDRESS_STRING_SIZE); - - _bt_convert_device_path_to_address(object_path, address); - - node = g_list_first(g_list); - - while (node != NULL) { - dev_info = (bt_remote_dev_info_t *)node->data; - if (strcasecmp(dev_info->address, address) == 0) { - is_in_glist = TRUE; - - BT_DBG("Bluez removes device %s, send device disappear event", dev_info->name); - _bt_send_event(BT_ADAPTER_EVENT, - BLUETOOTH_EVENT_REMOTE_DEVICE_DISAPPEARED, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &dev_info->address, - DBUS_TYPE_UINT32, &dev_info->class, - DBUS_TYPE_INT16, &dev_info->rssi, - DBUS_TYPE_STRING, &dev_info->name, - DBUS_TYPE_BOOLEAN, &dev_info->paired, - DBUS_TYPE_BOOLEAN, &dev_info->connected, - DBUS_TYPE_BOOLEAN, &dev_info->trust, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, - &dev_info->uuids, dev_info->uuid_count, - DBUS_TYPE_INVALID); - - g_list = g_list_remove(g_list, dev_info); - _bt_free_device_info(dev_info); - break; - } - node = g_list_next(node); - } - /* if device is not in glist, we need to trig destroy bonding event */ - if (!is_in_glist) { - BT_DBG("send bt bond destroy event"); - _bt_send_event(BT_ADAPTER_EVENT, - BLUETOOTH_EVENT_BONDED_DEVICE_REMOVED, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID); - } - g_free(address); - } - } else { - char *object_path = NULL; - if (__bt_get_object_path(msg, &object_path)) { - BT_ERR("Fail to get the path"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + if ((bt_event != 0) && (bt_event != BT_MEDIA_TRANSFER_EVENT)) { + _bt_handle_adapter_event(msg); + if (bt_event == BT_AVRCP_CONTROL_EVENT) { + char *object_path = NULL; + result = __bt_get_object_path(msg, &object_path); + if (result == BLUETOOTH_ERROR_NONE) + _bt_remove_control_device_path(object_path); } } + } else if (strcasecmp(member, "NameOwnerChanged") == 0) { gboolean value; char *name = NULL; char *previous = NULL; char *current = NULL; - BT_DBG("NameOwnerChanged"); - if (__bt_get_owner_info(msg, &name, &previous, ¤t)) { BT_ERR("Fail to get the owner info"); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; @@ -1700,8 +2737,11 @@ static DBusHandlerResult __bt_manager_event_filter(DBusConnection *conn, if (*current != '\0') return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - if (strcasecmp(name, "org.bluez") == 0) { + if (strcasecmp(name, BT_BLUEZ_NAME) == 0) { BT_DBG("Bluetoothd is terminated"); + if (_bt_adapter_get_status() != BT_DEACTIVATING) { + __bt_disable_cb(); + } _bt_handle_adapter_removed(); __bt_devices_list_free(); } @@ -1719,14 +2759,27 @@ static DBusHandlerResult __bt_manager_event_filter(DBusConnection *conn, /* The obex server was terminated abnormally */ _bt_rfcomm_server_check_termination(name); } + + /* Stop advertising started by terminated process */ + _bt_stop_advertising_by_terminated_process(name); } else if (dbus_message_has_interface(msg, BT_PROPERTIES_INTERFACE)) { + const char *path = dbus_message_get_path(msg); + + if (strncmp(path, BT_MEDIA_OBJECT_PATH, + strlen(BT_MEDIA_OBJECT_PATH)) == 0) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + _bt_handle_property_changed_event(msg); + } else if (dbus_message_has_interface(msg, BT_ADAPTER_INTERFACE)) { + _bt_handle_adapter_event(msg); } else if (dbus_message_has_interface(msg, BT_INPUT_INTERFACE)) { _bt_handle_input_event(msg); } else if (dbus_message_has_interface(msg, BT_NETWORK_SERVER_INTERFACE)) { _bt_handle_network_server_event(msg); - } else if (dbus_message_has_interface(msg, BT_HFP_AGENT_INTERFACE)) { + } else if (dbus_message_has_interface(msg, BT_HEADSET_INTERFACE)) { _bt_handle_headset_event(msg); + } else if (dbus_message_has_interface(msg, BT_SINK_INTERFACE)) { + _bt_handle_sink_event(msg); } else if (dbus_message_has_interface(msg, BT_AGENT_INTERFACE)) { _bt_handle_agent_event(msg); } else if (dbus_message_has_interface(msg, BT_DEVICE_INTERFACE)) { @@ -1743,7 +2796,7 @@ static gboolean __bt_is_obexd_event(DBusMessage *msg) if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) return FALSE; - retv_if(member == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + retv_if(member == NULL, FALSE); if (dbus_message_has_interface(msg, BT_PROPERTIES_INTERFACE)) { @@ -1754,7 +2807,7 @@ static gboolean __bt_is_obexd_event(DBusMessage *msg) if (dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_STRING) { - BT_ERR("This is bad format dbus\n"); + BT_ERR("This is bad format dbus"); return FALSE; } @@ -1769,93 +2822,82 @@ static gboolean __bt_is_obexd_event(DBusMessage *msg) retv_if(dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_ARRAY, FALSE); - if (strcasecmp(interface_name, BT_OBEX_TRANSFER_INTERFACE) == 0) - return TRUE; + if (strcasecmp(interface_name, BT_OBEX_TRANSFER_INTERFACE) == 0) { + BT_DBG("BT_OBEX_TRANSFER_INTERFACE"); + return TRUE; + } } return FALSE; } -void __bt_opc_property_changed_event(DBusMessageIter *msg_iter, - const char *path) +static DBusHandlerResult __bt_obexd_event_filter(DBusConnection *conn, + DBusMessage *msg, void *data) { - DBusMessageIter value_iter; - DBusMessageIter dict_iter; - DBusMessageIter item_iter; - const char *property = NULL; - - dbus_message_iter_recurse(msg_iter, &item_iter); - - if (dbus_message_iter_get_arg_type(&item_iter) - != DBUS_TYPE_DICT_ENTRY) { - BT_ERR("This is bad format dbus\n"); - return; - } - - dbus_message_iter_recurse(&item_iter, &dict_iter); - - dbus_message_iter_get_basic(&dict_iter, &property); - ret_if(property == NULL); + const char *member = dbus_message_get_member(msg); + char *object_path = NULL; - ret_if(!dbus_message_iter_next(&dict_iter)); + if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - if (strcasecmp(property, "Status") == 0) { - const char *status = NULL; - dbus_message_iter_recurse(&dict_iter, &value_iter); - dbus_message_iter_get_basic(&value_iter, &status); + retv_if(member == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - if(strcasecmp(status, "active") == 0){ - _bt_obex_client_started(path); - }else if (strcasecmp(status, "complete") == 0) { - _bt_obex_client_completed(TRUE); - }else if (strcasecmp(status, "error") == 0){ - _bt_obex_client_completed(FALSE); + if (strcasecmp(member, "InterfacesAdded") == 0) { + BT_DBG("InterfacesAdded"); + if (__bt_get_object_path(msg, &object_path)) { + BT_ERR("Fail to get the path"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } - } else if (strcasecmp(property, "Transferred") == 0) { - static int transferred = 0; - dbus_message_iter_recurse(&dict_iter, &value_iter); - dbus_message_iter_get_basic(&value_iter, &transferred); - - _bt_obex_client_progress(transferred); - } -} - -void _bt_opc_property_changed_event(DBusMessage *msg) -{ - DBusMessageIter item_iter; - const char *member = dbus_message_get_member(msg); - const char *interface_name = NULL; - - ret_if(member == NULL); - dbus_message_iter_init(msg, &item_iter); + BT_INFO("object_path = [%s]", object_path); - if (dbus_message_iter_get_arg_type(&item_iter) - != DBUS_TYPE_STRING) { - BT_ERR("This is bad format dbus\n"); - return; - } + /*Handle OPP_SERVER_CONNECTED_EVENT here */ + if (strncmp(object_path, BT_SESSION_BASEPATH_SERVER, + strlen(BT_SESSION_BASEPATH_SERVER)) != 0) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - dbus_message_iter_get_basic(&item_iter, &interface_name); + if (g_strrstr(object_path, "session") && g_strrstr(object_path, "transfer")) { + BT_DBG("Obex_Server_Session_Transfer connected"); + _bt_obex_transfer_connected(); + } + } else if (strcasecmp(member, "InterfacesRemoved") == 0) { + /*Handle OPP_SERVER_DISCONNECTED_EVENT here */ + BT_DBG("InterfacesRemoved"); + if (__bt_get_object_path(msg, &object_path)) { + BT_ERR("Fail to get the path"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } - ret_if(interface_name == NULL); + BT_INFO("object_path = [%s]", object_path); - BT_DBG("interface: %s", interface_name); + if (strncmp(object_path, BT_SESSION_BASEPATH_SERVER, + strlen(BT_SESSION_BASEPATH_SERVER)) != 0) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - ret_if(dbus_message_iter_next(&item_iter) == FALSE); + if (g_strrstr(object_path, "session") && g_strrstr(object_path, "transfer")) { + BT_DBG("Obex_Server_Session_Transfer disconnected"); + _bt_obex_transfer_disconnected(); + } + } else if (__bt_is_obexd_event(msg) == TRUE) { + const char *path = dbus_message_get_path(msg); - ret_if(dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_ARRAY); + if (strncmp(path, BT_SESSION_BASEPATH_SERVER, + strlen(BT_SESSION_BASEPATH_SERVER)) != 0 && + strncmp(path, BT_SESSION_BASEPATH_CLIENT, + strlen(BT_SESSION_BASEPATH_CLIENT)) != 0) { + BT_DBG("DBUS_HANDLER_RESULT_NOT_YET_HANDLED"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } - if (strcasecmp(interface_name, BT_OBEX_TRANSFER_INTERFACE) == 0) { - __bt_opc_property_changed_event(&item_iter, - dbus_message_get_path(msg)); - } else { - BT_DBG("No bluez interface"); + _bt_handle_property_changed_event(msg); } + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } static gboolean __bt_is_obexd_client_event(DBusMessage *msg) { + BT_DBG("+"); + const char *member = dbus_message_get_member(msg); if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) @@ -1871,7 +2913,7 @@ static gboolean __bt_is_obexd_client_event(DBusMessage *msg) if (dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_STRING) { - BT_ERR("This is bad format dbus\n"); + BT_ERR("This is bad format dbus"); return FALSE; } @@ -1888,10 +2930,14 @@ static gboolean __bt_is_obexd_client_event(DBusMessage *msg) != DBUS_TYPE_ARRAY, FALSE); if (strcasecmp(interface_name, - BT_OBEX_TRANSFER_INTERFACE) == 0) + BT_OBEX_TRANSFER_INTERFACE) == 0) { + BT_DBG("-"); return TRUE; + } } + BT_DBG("-"); + return FALSE; } @@ -1910,6 +2956,8 @@ static DBusHandlerResult __bt_opc_event_filter(DBusConnection *conn, }else if (strcasecmp(member, "InterfacesRemoved") == 0) { char *object_path = NULL; + BT_DBG("InterfacesRemoved"); + if (__bt_get_object_path(msg, &object_path)) { BT_ERR("Fail to get the path"); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; @@ -1918,9 +2966,14 @@ static DBusHandlerResult __bt_opc_event_filter(DBusConnection *conn, BT_DBG("object_path =%s",object_path); if (strncmp(object_path, BT_SESSION_BASEPATH_CLIENT, - strlen(BT_SESSION_BASEPATH_CLIENT)) != 0 - || strstr(object_path, "transfer") == NULL) + strlen(BT_SESSION_BASEPATH_CLIENT)) != 0 + || strstr(object_path, "transfer") == NULL) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + else if (strncmp(object_path, BT_SESSION_BASEPATH_CLIENT, + strlen(BT_SESSION_BASEPATH_CLIENT)) == 0) { + BT_DBG("Going to call opc disconnected"); + _bt_opc_disconnected(object_path); + } _bt_sending_files(); @@ -1928,8 +2981,10 @@ static DBusHandlerResult __bt_opc_event_filter(DBusConnection *conn, const char *path = dbus_message_get_path(msg); if (strncmp(path, BT_SESSION_BASEPATH_CLIENT, - strlen(BT_SESSION_BASEPATH_CLIENT)) != 0) + strlen(BT_SESSION_BASEPATH_CLIENT)) != 0) { + BT_DBG("NOT BT_SESSION_BASEPATH_CLIENT"); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } _bt_opc_property_changed_event(msg); } @@ -1937,31 +2992,46 @@ static DBusHandlerResult __bt_opc_event_filter(DBusConnection *conn, return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } -static DBusHandlerResult __bt_obexd_event_filter(DBusConnection *conn, - DBusMessage *msg, void *data) +int _bt_opp_client_event_init(void) { - const char *member = dbus_message_get_member(msg); + GError *error = NULL; - if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + if (opc_obexd_conn == NULL) { + opc_obexd_conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error); + if (error != NULL) { + BT_ERR("ERROR: Can't get on session bus [%s]", + error->message); + g_error_free(error); + return BLUETOOTH_ERROR_INTERNAL; + } - retv_if(member == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + retv_if(opc_obexd_conn == NULL, BLUETOOTH_ERROR_INTERNAL); + } - if (__bt_is_obexd_event(msg) == TRUE){ - const char *path = dbus_message_get_path(msg); + if (_bt_register_service_event(opc_obexd_conn, + BT_OPP_CLIENT_EVENT) != BLUETOOTH_ERROR_NONE) { + dbus_g_connection_unref(opc_obexd_conn); + opc_obexd_conn = NULL; + return BLUETOOTH_ERROR_INTERNAL; + } - if (strncmp(path, BT_SESSION_BASEPATH_SERVER, - strlen(BT_SESSION_BASEPATH_SERVER)) != 0) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + return BLUETOOTH_ERROR_NONE; +} - _bt_handle_property_changed_event(msg); +void _bt_opp_client_event_deinit(void) +{ + if (opc_obexd_conn) { + _bt_unregister_service_event(opc_obexd_conn, + BT_OPP_CLIENT_EVENT); + dbus_g_connection_unref(opc_obexd_conn); + opc_obexd_conn = NULL; } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } int _bt_register_service_event(DBusGConnection *g_conn, int event_type) { + BT_DBG("+"); + DBusError dbus_error; char *match1 = NULL; char *match2 = NULL; @@ -2011,18 +3081,28 @@ int _bt_register_service_event(DBusGConnection *g_conn, int event_type) break; case BT_HEADSET_EVENT: match1 = g_strdup_printf(EVENT_MATCH_RULE, - BT_HFP_AGENT_INTERFACE); + BT_HEADSET_INTERFACE); match2 = g_strdup_printf(EVENT_MATCH_RULE, BT_SINK_INTERFACE); break; case BT_OPP_SERVER_EVENT: + BT_ERR("BT_OPP_SERVER_EVENT: register service event"); event_func = __bt_obexd_event_filter; match1 = g_strdup_printf(MANAGER_EVENT_MATCH_RULE, BT_PROPERTIES_INTERFACE, BT_PROPERTIES_CHANGED); + + match2 = g_strdup_printf(MANAGER_EVENT_MATCH_RULE, + BT_MANAGER_INTERFACE, + BT_INTERFACES_ADDED); + + match3 = g_strdup_printf(MANAGER_EVENT_MATCH_RULE, + BT_MANAGER_INTERFACE, + BT_INTERFACES_REMOVED); break; case BT_OPP_CLIENT_EVENT: + BT_ERR("BT_OPP_CLIENT_EVENT: register service event"); event_func = __bt_opc_event_filter; match1 = g_strdup_printf(MANAGER_EVENT_MATCH_RULE, BT_PROPERTIES_INTERFACE, @@ -2087,22 +3167,29 @@ int _bt_register_service_event(DBusGConnection *g_conn, int event_type) goto fail; } - g_free(match1); - g_free(match2); g_free(match3); g_free(match4); + g_free(match1); + g_free(match2); + return BLUETOOTH_ERROR_NONE; fail: g_free(match1); g_free(match2); + g_free(match3); g_free(match4); + + BT_DBG("-"); + return BLUETOOTH_ERROR_INTERNAL; } void _bt_unregister_service_event(DBusGConnection *g_conn, int event_type) { + BT_DBG("+"); + DBusConnection *conn; DBusHandleMessageFunction event_func; @@ -2127,10 +3214,13 @@ void _bt_unregister_service_event(DBusGConnection *g_conn, int event_type) ret_if(conn == NULL); dbus_connection_remove_filter(conn, event_func, NULL); + BT_DBG("-"); } static int __bt_init_manager_receiver(void) { + BT_DBG("+"); + GError *error = NULL; if (manager_conn == NULL) { @@ -2169,11 +3259,14 @@ fail: manager_conn = NULL; } + BT_DBG("-"); + return BLUETOOTH_ERROR_INTERNAL; } static int __bt_init_obexd_receiver(void) { + BT_DBG("+"); GError *error = NULL; if (obexd_conn == NULL) { @@ -2192,12 +3285,16 @@ static int __bt_init_obexd_receiver(void) return BLUETOOTH_ERROR_INTERNAL; } + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; } /* To receive the event from bluez */ int _bt_init_service_event_receiver(void) { + BT_DBG("+"); + int result; result = __bt_init_manager_receiver(); @@ -2207,11 +3304,15 @@ int _bt_init_service_event_receiver(void) if (result != BLUETOOTH_ERROR_NONE) BT_ERR("Fail to init obexd receiver"); + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; } -void _bt_deinit_service_event_reciever(void) +void _bt_deinit_service_event_receiver(void) { + BT_DBG("+"); + _bt_unregister_service_event(manager_conn, BT_MANAGER_EVENT); _bt_unregister_service_event(obexd_conn, BT_OPP_SERVER_EVENT); @@ -2228,68 +3329,6 @@ void _bt_deinit_service_event_reciever(void) if (event_id > 0) g_source_remove(event_id); -} - -int _bt_opp_client_event_init(void) -{ - GError *error = NULL; - - if (opc_obexd_conn == NULL) { - opc_obexd_conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error); - if (error != NULL) { - BT_ERR("ERROR: Can't get on session bus [%s]", - error->message); - g_error_free(error); - } - - retv_if(opc_obexd_conn == NULL, BLUETOOTH_ERROR_INTERNAL); - } - - if (_bt_register_service_event(opc_obexd_conn, - BT_OPP_CLIENT_EVENT) != BLUETOOTH_ERROR_NONE) { - dbus_g_connection_unref(opc_obexd_conn); - opc_obexd_conn = NULL; - return BLUETOOTH_ERROR_INTERNAL; - } - - return BLUETOOTH_ERROR_NONE; -} - -void _bt_opp_client_event_deinit(void) -{ - if (opc_obexd_conn) { - _bt_unregister_service_event(opc_obexd_conn, - BT_OPP_CLIENT_EVENT); - dbus_g_connection_unref(opc_obexd_conn); - opc_obexd_conn = NULL; - } -} - -void _bt_get_temp_remote_devinfo(void) -{ - bt_remote_dev_info_t *dev_info; - GList *node; - int result = BLUETOOTH_ERROR_NONE; - - node = g_list_first(g_list); - while (node != NULL) { - dev_info = (bt_remote_dev_info_t *)node->data; - - _bt_send_event(BT_ADAPTER_EVENT, - BLUETOOTH_EVENT_REMOTE_DEVICE_FOUND, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &dev_info->address, - DBUS_TYPE_UINT32, &dev_info->class, - DBUS_TYPE_INT16, &dev_info->rssi, - DBUS_TYPE_STRING, &dev_info->name, - DBUS_TYPE_BOOLEAN, &dev_info->paired, - DBUS_TYPE_BOOLEAN, &dev_info->connected, - DBUS_TYPE_BOOLEAN, &dev_info->trust, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, - &dev_info->uuids, dev_info->uuid_count, - DBUS_TYPE_INVALID); - - node = g_list_next(node); - } + BT_DBG("-"); } diff --git a/bt-service/bt-service-event-sender.c b/bt-service/bt-service-event-sender.c old mode 100644 new mode 100755 index 1856d53..2799eba --- a/bt-service/bt-service-event-sender.c +++ b/bt-service/bt-service-event-sender.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -29,9 +33,12 @@ #include "bt-service-event.h" static DBusConnection *event_conn; +static DBusConnection *hf_local_term_event_conn; int _bt_send_event(int event_type, int event, int type, ...) { + BT_DBG("+"); + DBusMessage *msg; char *path; char *signal; @@ -39,10 +46,15 @@ int _bt_send_event(int event_type, int event, int type, ...) retv_if(event_conn == NULL, BLUETOOTH_ERROR_INTERNAL); + BT_DBG("event_type [%d], event [%d]", event_type, event); + switch (event_type) { case BT_ADAPTER_EVENT: path = BT_ADAPTER_PATH; break; + case BT_LE_ADAPTER_EVENT: + path = BT_LE_ADAPTER_PATH; + break; case BT_DEVICE_EVENT: path = BT_DEVICE_PATH; break; @@ -55,6 +67,9 @@ int _bt_send_event(int event_type, int event, int type, ...) case BT_AVRCP_EVENT: path = BT_AVRCP_PATH; break; + case BT_AVRCP_CONTROL_EVENT: + path = BT_AVRCP_CONTROL_PATH; + break; case BT_NETWORK_EVENT: path = BT_NETWORK_PATH; break; @@ -64,6 +79,9 @@ int _bt_send_event(int event_type, int event, int type, ...) case BT_OPP_SERVER_EVENT: path = BT_OPP_SERVER_PATH; break; + case BT_PBAP_CLIENT_EVENT: + path = BT_PBAP_CLIENT_PATH; + break; case BT_RFCOMM_CLIENT_EVENT: path = BT_RFCOMM_CLIENT_PATH; break; @@ -82,6 +100,12 @@ int _bt_send_event(int event_type, int event, int type, ...) case BLUETOOTH_EVENT_DISABLED: signal = BT_DISABLED; break; + case BLUETOOTH_EVENT_LE_ENABLED: + signal = BT_LE_ENABLED; + break; + case BLUETOOTH_EVENT_LE_DISABLED: + signal = BT_LE_DISABLED; + break; case BLUETOOTH_EVENT_LOCAL_NAME_CHANGED: signal = BT_ADAPTER_NAME_CHANGED; break; @@ -91,50 +115,116 @@ int _bt_send_event(int event_type, int event, int type, ...) case BLUETOOTH_EVENT_DISCOVERABLE_TIMEOUT_CHANGED: signal = BT_DISCOVERABLE_TIMEOUT_CHANGED; break; + case BLUETOOTH_EVENT_CONNECTABLE_CHANGED: + signal = BT_CONNECTABLE_CHANGED; + break; case BLUETOOTH_EVENT_DISCOVERY_STARTED: signal = BT_DISCOVERY_STARTED; break; case BLUETOOTH_EVENT_REMOTE_DEVICE_FOUND: signal = BT_DEVICE_FOUND; break; - case BLUETOOTH_EVENT_REMOTE_DEVICE_DISAPPEARED: - signal = BT_DEVICE_DISAPPEARED; - break; case BLUETOOTH_EVENT_DISCOVERY_FINISHED: signal = BT_DISCOVERY_FINISHED; break; + case BLUETOOTH_EVENT_LE_DISCOVERY_STARTED: + signal = BT_LE_DISCOVERY_STARTED; + break; + case BLUETOOTH_EVENT_REMOTE_LE_DEVICE_FOUND: + signal = BT_LE_DEVICE_FOUND; + break; + case BLUETOOTH_EVENT_LE_DISCOVERY_FINISHED: + signal = BT_LE_DISCOVERY_FINISHED; + break; + case BLUETOOTH_EVENT_ADVERTISING_STARTED: + signal = BT_ADVERTISING_STARTED; + break; + case BLUETOOTH_EVENT_ADVERTISING_STOPPED: + signal = BT_ADVERTISING_STOPPED; + break; + case BLUETOOTH_EVENT_ADVERTISING_MANUFACTURER_DATA_CHANGED: + signal = BT_ADVERTISING_MANUFACTURER_DATA_CHANGED; + break; + case BLUETOOTH_EVENT_SCAN_RESPONSE_MANUFACTURER_DATA_CHANGED: + signal = BT_SCAN_RESPONSE_MANUFACTURER_DATA_CHANGED; + break; + case BLUETOOTH_EVENT_MANUFACTURER_DATA_CHANGED: + signal = BT_MANUFACTURER_DATA_CHANGED; + break; case BLUETOOTH_EVENT_BONDING_FINISHED: signal = BT_BOND_CREATED; break; case BLUETOOTH_EVENT_BONDED_DEVICE_REMOVED: signal = BT_BOND_DESTROYED; break; + case BLUETOOTH_EVENT_DEVICE_AUTHORIZED: + signal = BT_DEVICE_AUTHORIZED; + break; + case BLUETOOTH_EVENT_DEVICE_UNAUTHORIZED: + signal = BT_DEVICE_UNAUTHORIZED; + break; + case BLUETOOTH_EVENT_RSSI_ENABLED: + signal = BT_RSSI_MONITORING_ENABLED; + break; + case BLUETOOTH_EVENT_RSSI_ALERT: + signal = BT_RSSI_ALERT; + break; + case BLUETOOTH_EVENT_RAW_RSSI: + signal = BT_RAW_RSSI_EVENT; + break; case BLUETOOTH_EVENT_SERVICE_SEARCHED: signal = BT_SERVICE_SEARCHED; break; case BLUETOOTH_HID_CONNECTED: signal = BT_INPUT_CONNECTED; + BT_INFO_C("Connected [HID]"); break; case BLUETOOTH_HID_DISCONNECTED: signal = BT_INPUT_DISCONNECTED; + BT_INFO_C("Disconnected [HID]"); + break; + case BLUETOOTH_PBAP_CONNECTED: + signal = BT_PBAP_CONNECTED; + BT_INFO_C("Connected [PBAP Client]"); + break; + case BLUETOOTH_PBAP_PHONEBOOK_SIZE: + signal = BT_PBAP_PHONEBOOK_SIZE; + break; + case BLUETOOTH_PBAP_PHONEBOOK_PULL: + signal = BT_PBAP_PHONEBOOK_PULL; + break; + case BLUETOOTH_PBAP_VCARD_LIST: + signal = BT_PBAP_VCARD_LIST; + break; + case BLUETOOTH_PBAP_VCARD_PULL: + signal = BT_PBAP_VCARD_PULL; + break; + case BLUETOOTH_PBAP_PHONEBOOK_SEARCH: + signal = BT_PBAP_SEARCH_PHONEBOOK; break; case BLUETOOTH_EVENT_AG_CONNECTED: signal = BT_HEADSET_CONNECTED; + BT_INFO_C("Connected [HSP/HFP]"); break; case BLUETOOTH_EVENT_AG_DISCONNECTED: signal = BT_HEADSET_DISCONNECTED; + BT_INFO_C("Disconnected [HSP/HFP]"); break; case BLUETOOTH_EVENT_AV_CONNECTED: signal = BT_STEREO_HEADSET_CONNECTED; + BT_INFO_C("Connected [A2DP]"); break; case BLUETOOTH_EVENT_AV_DISCONNECTED: signal = BT_STEREO_HEADSET_DISCONNECTED; + BT_INFO_C("Disconnected [A2DP]"); break; case BLUETOOTH_EVENT_AG_AUDIO_CONNECTED: signal = BT_SCO_CONNECTED; + BT_INFO_C("Connected [SCO]"); break; case BLUETOOTH_EVENT_AG_AUDIO_DISCONNECTED: signal = BT_SCO_DISCONNECTED; + BT_INFO_C("Disonnected [SCO]"); break; case BLUETOOTH_EVENT_AG_SPEAKER_GAIN: signal = BT_SPEAKER_GAIN; @@ -144,21 +234,33 @@ int _bt_send_event(int event_type, int event, int type, ...) break; case BLUETOOTH_EVENT_NETWORK_CONNECTED: signal = BT_NETWORK_CONNECTED; + BT_INFO_C("Connected [Newwork]"); break; case BLUETOOTH_EVENT_NETWORK_DISCONNECTED: signal = BT_NETWORK_DISCONNECTED; + BT_INFO_C("Disconnected [Newwork]"); break; case BLUETOOTH_EVENT_NETWORK_SERVER_CONNECTED: signal = BT_NETWORK_SERVER_CONNECTED; + BT_INFO_C("Connected [Network Server]"); break; case BLUETOOTH_EVENT_NETWORK_SERVER_DISCONNECTED: signal = BT_NETWORK_SERVER_DISCONNECTED; + BT_INFO_C("Disconnected [Network Server]"); break; case BLUETOOTH_EVENT_OPC_CONNECTED: signal = BT_OPP_CONNECTED; + BT_INFO_C("Connected [OPP]"); break; case BLUETOOTH_EVENT_OPC_DISCONNECTED: signal = BT_OPP_DISCONNECTED; + BT_INFO_C("Disconnected [OPP]"); + break; + case BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_CONNECTED: + signal = BT_TRANSFER_CONNECTED; + break; + case BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_DISCONNECTED: + signal = BT_TRANSFER_DISCONNECTED; break; case BLUETOOTH_EVENT_OPC_TRANSFER_STARTED: case BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_STARTED: @@ -197,28 +299,60 @@ int _bt_send_event(int event_type, int event, int type, ...) case BLUETOOTH_EVENT_DEVICE_DISCONNECTED: signal = BT_DEVICE_DISCONNECTED; break; + case BLUETOOTH_EVENT_AVRCP_CONNECTED: + case BLUETOOTH_EVENT_AVRCP_CONTROL_CONNECTED: + signal = BT_AVRCP_CONNECTED; + BT_INFO_C("Connected [AVRCP]"); + break; + case BLUETOOTH_EVENT_AVRCP_DISCONNECTED: + case BLUETOOTH_EVENT_AVRCP_CONTROL_DISCONNECTED: + signal = BT_AVRCP_DISCONNECTED; + BT_INFO_C("Disconnected [AVRCP]"); + break; case BLUETOOTH_EVENT_AVRCP_SETTING_SHUFFLE_STATUS: + case BLUETOOTH_EVENT_AVRCP_CONTROL_SHUFFLE_STATUS: signal = BT_MEDIA_SHUFFLE_STATUS; break; case BLUETOOTH_EVENT_AVRCP_SETTING_EQUALIZER_STATUS: + case BLUETOOTH_EVENT_AVRCP_CONTROL_EQUALIZER_STATUS: signal = BT_MEDIA_EQUALIZER_STATUS; break; case BLUETOOTH_EVENT_AVRCP_SETTING_REPEAT_STATUS: + case BLUETOOTH_EVENT_AVRCP_CONTROL_REPEAT_STATUS: signal = BT_MEDIA_REPEAT_STATUS; break; case BLUETOOTH_EVENT_AVRCP_SETTING_SCAN_STATUS: + case BLUETOOTH_EVENT_AVRCP_CONTROL_SCAN_STATUS: signal = BT_MEDIA_SCAN_STATUS; break; + case BLUETOOTH_EVENT_AVRCP_SONG_POSITION_STATUS: + signal = BT_MEDIA_POSITION_STATUS; + break; + case BLUETOOTH_EVENT_AVRCP_PLAY_STATUS_CHANGED: + signal = BT_MEDIA_PLAY_STATUS; + break; + case BLUETOOTH_EVENT_AVRCP_TRACK_CHANGED: + signal = BT_MEDIA_TRACK_CHANGE; + break; + case BLUETOOTH_EVENT_GATT_CONNECTED: + signal = BT_GATT_CONNECTED; + break; + case BLUETOOTH_EVENT_GATT_DISCONNECTED: + signal = BT_GATT_DISCONNECTED; + break; default: BT_ERR("Unknown event"); return BLUETOOTH_ERROR_INTERNAL; } + BT_DBG("Path : %s", path); + BT_INFO_C("Signal : %s", signal); + msg = dbus_message_new_signal(path, BT_EVENT_SERVICE, signal); if (msg == NULL) { - BT_ERR("Message is NULL\n"); + BT_ERR("Message is NULL"); return BLUETOOTH_ERROR_INTERNAL; } @@ -236,7 +370,7 @@ int _bt_send_event(int event_type, int event, int type, ...) } if (!dbus_connection_send(event_conn, msg, NULL)) { - BT_ERR("send failed\n"); + BT_ERR("send failed"); dbus_message_unref(msg); return BLUETOOTH_ERROR_INTERNAL; } @@ -244,9 +378,113 @@ int _bt_send_event(int event_type, int event, int type, ...) dbus_connection_flush(event_conn); dbus_message_unref(msg); + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; } +int _bt_send_event_to_dest(const char* dest, int event_type, int event, int type, ...) +{ + BT_DBG("+"); + + DBusMessage *msg; + char *path; + char *signal; + va_list arguments; + + retv_if(event_conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_DBG("event_type [%d], event [%d]", event_type, event); + + switch (event_type) { + case BT_ADAPTER_EVENT: + path = BT_ADAPTER_PATH; + break; + default: + BT_ERR("Unknown event"); + return BLUETOOTH_ERROR_INTERNAL; + } + + switch (event) { + case BLUETOOTH_EVENT_ADVERTISING_STARTED: + signal = BT_ADVERTISING_STARTED; + break; + case BLUETOOTH_EVENT_ADVERTISING_STOPPED: + signal = BT_ADVERTISING_STOPPED; + break; + default: + BT_ERR("Unknown event"); + return BLUETOOTH_ERROR_INTERNAL; + } + + BT_DBG("Path : %s", path); + BT_INFO_C("Signal : %s", signal); + + msg = dbus_message_new_signal(path, BT_EVENT_SERVICE, + signal); + + if (msg == NULL) { + BT_ERR("Message is NULL"); + return BLUETOOTH_ERROR_INTERNAL; + } + + if (dbus_message_set_destination(msg, dest) == FALSE) + BT_ERR("Setting destination is failed"); + + if (type) { + /* Set the arguments of the dbus message */ + va_start(arguments, type); + + if (!dbus_message_append_args_valist(msg, type, arguments)) { + dbus_message_unref(msg); + va_end(arguments); + return BLUETOOTH_ERROR_INTERNAL; + } + + va_end(arguments); + } + + if (!dbus_connection_send(event_conn, msg, NULL)) { + BT_ERR("send failed"); + dbus_message_unref(msg); + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_connection_flush(event_conn); + dbus_message_unref(msg); + + BT_DBG("-"); + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_send_hf_local_term_event(char *address) +{ + DBusMessage *msg; + char *signal = BT_HF_LOCAL_TERM; + + retv_if(hf_local_term_event_conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + msg = dbus_message_new_signal(BT_HF_LOCAL_TERM_EVENT_PATH, + BT_HF_LOCAL_TERM_EVENT_INTERFACE, signal); + if (msg == NULL) { + BT_ERR("Message is NULL\n"); + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_append_args(msg, DBUS_TYPE_STRING, &address, DBUS_TYPE_INVALID); + + if (!dbus_connection_send(hf_local_term_event_conn, msg, NULL)) { + BT_ERR("send failed\n"); + dbus_message_unref(msg); + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_connection_flush(hf_local_term_event_conn); + dbus_message_unref(msg); + + return BLUETOOTH_ERROR_NONE; +} /* To send the event from service daemon to application*/ int _bt_init_service_event_sender(void) @@ -289,3 +527,42 @@ void _bt_deinit_service_event_sender(void) } } +int _bt_init_hf_local_term_event_sender(void) +{ + DBusConnection *conn; + DBusError err; + int ret; + + if (hf_local_term_event_conn) { + BT_ERR("Event handler is already exist"); + return BLUETOOTH_ERROR_INTERNAL; + } + + conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, NULL); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_error_init(&err); + + ret = dbus_bus_request_name(conn, BT_HF_LOCAL_TERM_EVENT_INTERFACE, + DBUS_NAME_FLAG_REPLACE_EXISTING, &err); + + if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + if (dbus_error_is_set(&err) == TRUE) { + BT_ERR("Event init failed, %s", err.message); + dbus_error_free(&err); + } + return BLUETOOTH_ERROR_INTERNAL; + } + + hf_local_term_event_conn = conn; + + return BLUETOOTH_ERROR_NONE; +} + +void _bt_deinit_hf_local_term_event_sender(void) +{ + if (hf_local_term_event_conn) { + dbus_connection_close(hf_local_term_event_conn); + hf_local_term_event_conn = NULL; + } +} diff --git a/bt-service/bt-service-gap-agent.c b/bt-service/bt-service-gap-agent.c old mode 100644 new mode 100755 index 3dd00e3..a049805 --- a/bt-service/bt-service-gap-agent.c +++ b/bt-service/bt-service-gap-agent.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -23,10 +27,12 @@ #include #include +#include "bt-internal-types.h" #include "bt-service-common.h" #include "bt-service-agent.h" #include "bt-service-gap-agent.h" #include "bt-service-adapter.h" +#include "bt-service-device.h" static DBusGConnection *connection = NULL; @@ -43,7 +49,9 @@ struct _GapAgentPrivate { gchar *busname; gchar *path; DBusGProxy *adapter; + DBusGProxy *agent_manager; + DBusGProxy *dbus_proxy; GapAgentExecType exec_type; @@ -68,7 +76,7 @@ static gboolean gap_agent_request_passkey(GapAgent *agent, const char *path, DBusGMethodInvocation *context); static gboolean gap_agent_display_passkey(GapAgent *agent, const char *path, - guint passkey, + guint passkey, guint16 entered, DBusGMethodInvocation *context); static gboolean gap_agent_request_confirmation(GapAgent *agent, @@ -81,8 +89,8 @@ static gboolean gap_agent_authorize_service(GapAgent *agent, const char *path, DBusGMethodInvocation *context); static gboolean gap_agent_request_authorization(GapAgent *agent, - const char *path, - DBusGMethodInvocation *context); + const char *path, + DBusGMethodInvocation *context); static gboolean gap_agent_cancel(GapAgent *agent, DBusGMethodInvocation *context); @@ -125,12 +133,12 @@ static GError *gap_agent_error(GapAgentError error, const char *err_msg) static void gap_agent_init(GapAgent *agent) { - BT_DBG("agent %p\n", agent); + BT_DBG("agent %p", agent); } static void gap_agent_finalize(GObject *agent) { - BT_DBG("Free agent %p\n", agent); + BT_DBG("Free agent %p", agent); G_OBJECT_CLASS(gap_agent_parent_class)->finalize(agent); } @@ -140,7 +148,7 @@ static void gap_agent_class_init(GapAgentClass *klass) GObjectClass *object_class = (GObjectClass *) klass; GError *error = NULL; - BT_DBG("class %p\n", klass); + BT_DBG("class %p", klass); g_type_class_add_private(klass, sizeof(GapAgentPrivate)); @@ -149,7 +157,7 @@ static void gap_agent_class_init(GapAgentClass *klass) connection = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error); if (error != NULL) { - g_printerr("Connecting to system bus failed: %s\n", + g_printerr("Connecting to system bus failed: %s", error->message); g_error_free(error); } @@ -164,7 +172,7 @@ GapAgent *_gap_agent_new(void) agent = GAP_GET_AGENT(g_object_new(GAP_TYPE_AGENT, NULL)); - BT_DBG("agent %p\n", agent); + BT_DBG("agent %p", agent); return agent; } @@ -176,15 +184,15 @@ static gboolean gap_agent_request_pin_code(GapAgent *agent, GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); char *sender = dbus_g_method_get_sender(context); DBusGProxy *device; - DBusGConnection *conn; gboolean result; char *addr; + DBusGConnection *conn; + if (sender == NULL) return FALSE; - BT_DBG("Request PIN : agent %p sender %s priv->busname %s Device Path :%s\n", - agent, sender, priv->busname, path); + BT_INFO("Request pin code, Device Path :%s", path); if (g_strcmp0(sender, priv->busname) != 0) { g_free(sender); @@ -204,11 +212,10 @@ static gboolean gap_agent_request_pin_code(GapAgent *agent, device = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, path, BT_PROPERTIES_INTERFACE); - if (device == NULL) { GError *error = gap_agent_error(GAP_AGENT_ERROR_REJECT, "No proxy for device"); - BT_DBG("Fail to make device proxy\n"); + BT_ERR("Fail to make device proxy"); dbus_g_method_return_error(context, error); g_error_free(error); g_free(sender); @@ -243,14 +250,14 @@ static gboolean gap_agent_request_passkey(GapAgent *agent, const char *path, GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); char *sender = dbus_g_method_get_sender(context); DBusGProxy *device; - DBusGConnection *conn; gboolean result; char *addr; + DBusGConnection *conn; if (sender == NULL) return FALSE; - BT_DBG("Request passkey : agent %p sender %s priv->busname %s Device Path :%s\n", agent, + BT_INFO("Request passkey : agent %p sender %s priv->busname %s Device Path :%s", agent, sender, priv->busname, path); if (g_strcmp0(sender, priv->busname) != 0) { @@ -275,7 +282,7 @@ static gboolean gap_agent_request_passkey(GapAgent *agent, const char *path, if (device == NULL) { GError *error = gap_agent_error(GAP_AGENT_ERROR_REJECT, "No proxy for device"); - BT_DBG("Fail to make device proxy\n"); + BT_ERR("Fail to make device proxy"); dbus_g_method_return_error(context, error); g_error_free(error); g_free(sender); @@ -306,20 +313,25 @@ static gboolean gap_agent_request_passkey(GapAgent *agent, const char *path, } static gboolean gap_agent_display_passkey(GapAgent *agent, const char *path, - guint passkey, + guint passkey, guint16 entered, DBusGMethodInvocation *context) { GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); char *sender = dbus_g_method_get_sender(context); DBusGProxy *device; - DBusGConnection *conn; gboolean result; + DBusGConnection *conn; if (sender == NULL) return FALSE; - BT_DBG("Request passkey display : agent %p sender %s priv->busname %s Device Path :%s\n", - agent, sender, priv->busname, path); + /* Do not show popup for Key event while typing*/ + if (entered) { + g_free(sender); + return FALSE; + } + BT_INFO("Request passkey display : agent %p sender %s priv->busname %s Device Path :%s\n", + agent, sender, priv->busname, path); if (g_strcmp0(sender, priv->busname) != 0) { g_free(sender); @@ -343,7 +355,7 @@ static gboolean gap_agent_display_passkey(GapAgent *agent, const char *path, if (device == NULL) { GError *error = gap_agent_error(GAP_AGENT_ERROR_REJECT, "No proxy for device"); - BT_DBG("Fail to make device proxy\n"); + BT_ERR("Fail to make device proxy"); dbus_g_method_return_error(context, error); g_error_free(error); g_free(sender); @@ -368,15 +380,14 @@ static gboolean gap_agent_request_confirmation(GapAgent *agent, GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); char *sender = dbus_g_method_get_sender(context); DBusGProxy *device; - DBusGConnection *conn; gboolean result; char *addr; + DBusGConnection *conn; if (sender == NULL) return FALSE; - BT_DBG("Request passkey confirmation : agent %p sender %s priv->busname %s Device Path :%s\n", - agent, sender, priv->busname, path); + BT_INFO("Request passkey confirmation, Device Path :%s", path); if (g_strcmp0(sender, priv->busname) != 0) { g_free(sender); @@ -396,11 +407,10 @@ static gboolean gap_agent_request_confirmation(GapAgent *agent, device = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, path, BT_PROPERTIES_INTERFACE); - if (device == NULL) { GError *error = gap_agent_error(GAP_AGENT_ERROR_REJECT, "No proxy for device"); - BT_DBG("Fail to make device proxy\n"); + BT_ERR("Fail to make device proxy"); dbus_g_method_return_error(context, error); g_error_free(error); g_free(sender); @@ -443,7 +453,7 @@ static gboolean gap_agent_authorize_service(GapAgent *agent, const char *path, if (sender == NULL) return FALSE; - BT_DBG("Request authorization : agent %p sender %s priv->busname %s Device Path :%s\n", agent, + BT_DBG("Request authorization : agent %p sender %s priv->busname %s Device Path :%s", agent, sender, priv->busname, path); if (g_strcmp0(sender, priv->busname) != 0) { @@ -502,12 +512,11 @@ static gboolean gap_agent_request_authorization(GapAgent *agent, const char *path, DBusGMethodInvocation *context) { - BT_DBG(""); - dbus_g_method_return(context); return TRUE; } + static gboolean gap_agent_confirm_mode_change(GapAgent *agent, const char *mode, DBusGMethodInvocation *context) @@ -528,7 +537,7 @@ static gboolean gap_agent_cancel(GapAgent *agent, if (sender == NULL) return FALSE; - BT_DBG("Cancelled : agent %p sender %s\n", agent, sender); + BT_DBG("Cancelled : agent %p sender %s", agent, sender); if (g_strcmp0(sender, priv->busname) != 0) { g_free(sender); @@ -557,6 +566,10 @@ static gboolean gap_agent_cancel(GapAgent *agent, g_error_free(error); } + /* 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; @@ -634,8 +647,10 @@ static void __gap_agent_remove_osp_servers(GSList *osp_servers) } gboolean _gap_agent_register_osp_server(GapAgent *agent, - const gint type, - const char *uuid) + const gint type, + const char *uuid, + const char *path, + int fd) { bt_agent_osp_server_t *server; @@ -653,9 +668,11 @@ gboolean _gap_agent_register_osp_server(GapAgent *agent, server = g_malloc0(sizeof(bt_agent_osp_server_t)); server->type = type; - - if (type == BT_RFCOMM_SERVER) + if (type == BT_RFCOMM_SERVER) { server->uuid = g_strdup(uuid); + server->path = g_strdup(path); + server->fd = fd; + } priv->osp_servers = g_slist_append(priv->osp_servers, server); @@ -700,7 +717,7 @@ gboolean gap_agent_reply_pin_code(GapAgent *agent, const guint accept, const char *pin_code, DBusGMethodInvocation *context) { - BT_DBG("+\n"); + BT_DBG("+"); GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); @@ -734,7 +751,7 @@ gboolean gap_agent_reply_pin_code(GapAgent *agent, const guint accept, priv->reply_context = NULL; memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr)); - BT_DBG("-\n"); + BT_DBG("-"); return TRUE; } @@ -743,7 +760,7 @@ gboolean gap_agent_reply_passkey(GapAgent *agent, const guint accept, const char *passkey, DBusGMethodInvocation *context) { - BT_DBG("+\n"); + BT_DBG("+"); GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); @@ -778,7 +795,7 @@ gboolean gap_agent_reply_passkey(GapAgent *agent, const guint accept, priv->reply_context = NULL; memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr)); - BT_DBG("-\n"); + BT_DBG("-"); return TRUE; } @@ -786,7 +803,7 @@ gboolean gap_agent_reply_passkey(GapAgent *agent, const guint accept, gboolean gap_agent_reply_confirmation(GapAgent *agent, const guint accept, DBusGMethodInvocation *context) { - BT_DBG("+\n"); + BT_DBG("+"); GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); @@ -820,7 +837,7 @@ gboolean gap_agent_reply_confirmation(GapAgent *agent, const guint accept, priv->reply_context = NULL; memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr)); - BT_DBG("-\n"); + BT_DBG("-"); return TRUE; } @@ -830,7 +847,7 @@ gboolean gap_agent_reply_authorize(GapAgent *agent, const guint accept, { gboolean ret = TRUE; - BT_DBG("+\n"); + BT_DBG("+"); GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); @@ -838,6 +855,19 @@ gboolean gap_agent_reply_authorize(GapAgent *agent, const guint accept, priv->reply_context != NULL) { if (accept == GAP_AGENT_ACCEPT) { dbus_g_method_return(priv->reply_context); + } else if (accept == GAP_AGENT_ACCEPT_ALWAYS) { + bluetooth_device_address_t addr = {{0,}}; + int result; + + _bt_convert_addr_string_to_type(addr.addr, + priv->authorize_addr); + + result = _bt_set_authorization(&addr, TRUE); + if (result == BLUETOOTH_ERROR_NONE) { + BT_INFO("[%s] Device added to trusted", priv->authorize_addr); + } + + dbus_g_method_return(priv->reply_context); } else { GError *error = NULL; switch (accept) { @@ -861,7 +891,7 @@ gboolean gap_agent_reply_authorize(GapAgent *agent, const guint accept, } else { GError *error = gap_agent_error(GAP_AGENT_ERROR_REJECT, "No context"); - BT_DBG("No context"); + BT_ERR("No context"); if (context) dbus_g_method_return_error(context, error); @@ -874,7 +904,7 @@ gboolean gap_agent_reply_authorize(GapAgent *agent, const guint accept, priv->reply_context = NULL; memset(priv->authorize_addr, 0x00, sizeof(priv->authorize_addr)); - BT_DBG("-\n"); + BT_DBG("-"); return ret; } @@ -882,7 +912,7 @@ gboolean gap_agent_reply_authorize(GapAgent *agent, const guint accept, static gboolean gap_agent_get_discoverable_timeout(GapAgent *agent, DBusGMethodInvocation *context) { - BT_DBG("+\n"); + BT_DBG("+"); int timeout; @@ -890,7 +920,7 @@ static gboolean gap_agent_get_discoverable_timeout(GapAgent *agent, dbus_g_method_return(context, timeout); - BT_DBG("-\n"); + BT_DBG("-"); return TRUE; } @@ -981,7 +1011,8 @@ static gboolean __gap_agent_unregister(GapAgent *agent) } void _gap_agent_setup_dbus(GapAgent *agent, GAP_AGENT_FUNC_CB *func_cb, - const char *path) + const char *path, + DBusGProxy *adapter) { GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); GObject *object; @@ -1003,12 +1034,13 @@ void _gap_agent_setup_dbus(GapAgent *agent, GAP_AGENT_FUNC_CB *func_cb, memset(priv->authorize_addr, 0x00, sizeof(priv->authorize_addr)); priv->reply_context = NULL; + BT_DBG("patt: %s", path); + proxy = dbus_g_proxy_new_for_name_owner(connection, BT_BLUEZ_NAME, path, BT_AGENT_INTERFACE, NULL); - if (proxy != NULL) { priv->busname = g_strdup(dbus_g_proxy_get_bus_name(proxy)); g_object_unref(proxy); @@ -1031,10 +1063,8 @@ void _gap_agent_reset_dbus(GapAgent *agent) priv->osp_servers = NULL; } - if (priv->adapter) { - g_object_unref(priv->adapter); - priv->adapter = NULL; - } + g_object_ref(priv->adapter); + priv->adapter = NULL; g_free(priv->path); priv->path = NULL; @@ -1058,6 +1088,23 @@ gboolean _gap_agent_exist_osp_server(GapAgent *agent, int type, char *uuid) return FALSE; } +bt_agent_osp_server_t *_gap_agent_get_osp_server(GapAgent *agent, int type, + char *uuid) +{ + GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); + bt_agent_osp_server_t *osp_serv = NULL; + if (priv == NULL) + return NULL; + + osp_serv = __gap_agent_find_server(priv->osp_servers, + type, uuid); + if (!osp_serv) { + return NULL; + } + + return osp_serv; +} + gchar* _gap_agent_get_path(GapAgent *agent) { GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); @@ -1071,3 +1118,10 @@ gboolean _gap_agent_is_canceled(GapAgent *agent) return priv->canceled; } + +void _gap_agent_set_canceled(GapAgent *agent, gboolean value) +{ + GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); + + priv->canceled = value; +} diff --git a/bt-service/bt-service-gap-agent.xml b/bt-service/bt-service-gap-agent.xml old mode 100644 new mode 100755 index ca79727..f3438cb --- a/bt-service/bt-service-gap-agent.xml +++ b/bt-service/bt-service-gap-agent.xml @@ -1,7 +1,7 @@ - + @@ -26,12 +26,7 @@ - - - - - - + diff --git a/bt-service/bt-service-gap-agent1.xml b/bt-service/bt-service-gap-agent1.xml new file mode 100755 index 0000000..477b018 --- /dev/null +++ b/bt-service/bt-service-gap-agent1.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bt-service/bt-service-headset-connection.c b/bt-service/bt-service-headset-connection.c new file mode 100755 index 0000000..422f9ba --- /dev/null +++ b/bt-service/bt-service-headset-connection.c @@ -0,0 +1,267 @@ +/* + * Bluetooth-frwk + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include "bluetooth-api.h" +#include "bt-internal-types.h" + +#include "bt-service-common.h" +#include "bt-service-event.h" +#include "bt-service-main.h" +#include "bt-service-adapter.h" +#include "bt-service-device.h" +#include "bt-service-audio.h" +#include "bt-service-headset-connection.h" + +#include "bt-service-opp-client.h" + + + +static GList *p_connection_list = NULL; +typedef enum { + BLUETOOTH_NONE_CONNECTED = 0x00, + BLUETOOTH_HFP_CONNECTED , + BLUETOOTH_A2DP_CONNECTED, + BLUETOOTH_ALL_CONNECTED, +} bluetooth_state_type_t; + +typedef struct { + bluetooth_state_type_t state; + bluetooth_device_info_t dev_info; + int connection_type; +} bt_connection_node_info_t; + +gboolean connection_local = FALSE; + + +void _bt_headset_set_local_connection(gboolean value) +{ + BT_INFO("setting connection_local to %d", value); + connection_local = value; +} + +gboolean _bt_headset_get_local_connection() +{ + return connection_local; +} + +//gint compare_state(GList *data, bluetooth_state_type_t state) +gint compare_state(gconstpointer list_data, gconstpointer conn_state) +{ + GList *data = (GList *) list_data; + bluetooth_state_type_t *state = (bluetooth_state_type_t *)conn_state; + bt_connection_node_info_t *p_data = (bt_connection_node_info_t *) data; + if (p_data->state == *state) { + BT_INFO("State Already Added"); + return 0; + } + return 1; +} + +gboolean connect_remote_media_audio(gpointer user_data) +{ + bt_connection_node_info_t *conn_info = + (bt_connection_node_info_t *) user_data; + GList *list = NULL; + bluetooth_state_type_t state; + + char remote_address[BT_ADDRESS_STRING_SIZE] = { 0 }; + _bt_convert_addr_type_to_string(remote_address, conn_info->dev_info.device_address.addr); + if (p_connection_list == NULL) { + BT_INFO("None of device connected and this hasbeen triggered"); + return FALSE; + } + if (conn_info->connection_type == BT_AUDIO_A2DP) { + state = BLUETOOTH_A2DP_CONNECTED; + list = g_list_find_custom(p_connection_list, + &state, compare_state); + if (list == NULL) { + BT_INFO("Head Set didn't initiated a2dp connection"); + BT_INFO("local device initiating A2DP connection"); + _bt_audio_connect(0, BT_AUDIO_A2DP, + &conn_info->dev_info.device_address, NULL); + } else { + BT_INFO("A2DP Connection Already exists"); + } + g_free(conn_info); + } else { + state = BLUETOOTH_HFP_CONNECTED; + list = g_list_find_custom(p_connection_list, + &state, compare_state); + if (list == NULL) { + BT_INFO("Headset didn't initiated HFP connection"); + BT_INFO("local device intiating HFP Connection"); + _bt_audio_connect(0, BT_AUDIO_HSP, + &conn_info->dev_info.device_address, NULL); + } else { + BT_INFO("HFP Connection Already exists"); + } + g_free(conn_info); + } + return FALSE; +} + +void _bt_get_bluetooth_device_info(char *remote_address, bluetooth_device_info_t *device) +{ + GArray *dev_list = NULL; + int size,i=0; + bluetooth_device_info_t info; + char bond_address[BT_ADDRESS_STRING_SIZE] = { 0 }; + dev_list = g_array_new (FALSE, FALSE, sizeof(gchar)); + if (device == NULL) + return; + _bt_get_bonded_devices(&dev_list); + size = (dev_list->len) / sizeof(bluetooth_device_info_t); + for (i=0; i < size; i++) { + info = g_array_index(dev_list, bluetooth_device_info_t, i); + _bt_convert_addr_type_to_string(bond_address, info.device_address.addr); + if (strcmp(bond_address, remote_address) == 0) { + BT_INFO("Match found"); + memcpy(device, &info, sizeof(bluetooth_device_info_t)); + g_array_free(dev_list, TRUE); + return; + } + } + g_array_free(dev_list, TRUE); + return; +} + +void _bt_headset_add_timer_function(int connection_type, bluetooth_device_info_t *info) +{ + bt_connection_node_info_t *pass_conn_info = NULL; + + if (info == NULL) + return; + + pass_conn_info = g_new0(bt_connection_node_info_t, 1); + pass_conn_info->connection_type = connection_type; + memcpy(&pass_conn_info->dev_info, info, sizeof(bluetooth_device_info_t)); + /* This need to be freed in timer function */ + g_timeout_add(CONNECT_TIMEOUT, connect_remote_media_audio, + pass_conn_info); + return; +} + +void _bt_start_timer_for_connection(char *remote_address, int connection_type) +{ + GArray *dev_list = NULL; + int size,i=0,j; + bluetooth_device_info_t info; + char bond_address[BT_ADDRESS_STRING_SIZE] = { 0 }; + dev_list = g_array_new (FALSE, FALSE, sizeof(gchar)); + _bt_get_bonded_devices(&dev_list); + size = (dev_list->len) / sizeof(bluetooth_device_info_t); + + for (i=0; i < size; i++) { + info = g_array_index(dev_list, bluetooth_device_info_t, i); + j = 0; + _bt_convert_addr_type_to_string(bond_address, + info.device_address.addr); + if (strcmp(bond_address, remote_address) != 0) + continue; + BT_INFO("Device address Matched"); + + while (j != info.service_index) { + BT_INFO("UUID %s", info.uuids[j]); + if (connection_type == BT_AUDIO_A2DP) { + if (strcmp(info.uuids[j], A2DP_SINK_UUID) == 0) { + BT_INFO("Remote Device has A2DP Sink Support start timer"); + _bt_headset_add_timer_function(BT_AUDIO_A2DP, &info); + goto end; + } + } else { + if (strcmp(info.uuids[j], HFP_HS_UUID) == 0) { + BT_INFO("Remote Device has HFP Sink Support start timer"); + _bt_headset_add_timer_function(BT_AUDIO_HSP, &info); + goto end; + } + } + j++; + } + } +end: + g_array_free(dev_list, TRUE); +} + +void __bt_connection_manager_set_state(char *remote_address, int event) +{ + bt_connection_node_info_t *info = g_new0(bt_connection_node_info_t, 1); + + char bond_address[BT_ADDRESS_STRING_SIZE] = { 0 }; + if (event == BLUETOOTH_EVENT_AG_CONNECTED) { + info->state = BLUETOOTH_HFP_CONNECTED; + _bt_get_bluetooth_device_info(remote_address, &info->dev_info); + _bt_convert_addr_type_to_string(bond_address, + info->dev_info.device_address.addr); + BT_INFO("Adding HFP Connected device to list"); + p_connection_list = g_list_append(p_connection_list, info); + } + else if (event == BLUETOOTH_EVENT_AG_DISCONNECTED) { + /* Delete coresponding node */ + BT_INFO("Deleting HFP Connected device from list"); + GList *list = NULL; + bluetooth_state_type_t state; + bt_connection_node_info_t *h_conn; + state = BLUETOOTH_HFP_CONNECTED; + list = g_list_find_custom(p_connection_list, + &state, compare_state); + if (list == NULL) { + BT_INFO("Didn't found any device with HFP State"); + return; + } + h_conn = list->data; + p_connection_list = g_list_remove(p_connection_list, h_conn); + g_free(h_conn); + } else if (event == BLUETOOTH_EVENT_AV_CONNECTED) { + info->state = BLUETOOTH_A2DP_CONNECTED; + _bt_get_bluetooth_device_info(remote_address, &info->dev_info); + _bt_convert_addr_type_to_string(bond_address, + info->dev_info.device_address.addr); + BT_INFO("Adding A2DP Connected device to list"); + p_connection_list = g_list_append(p_connection_list, info); + } else if (event == BLUETOOTH_EVENT_AV_DISCONNECTED) { + BT_INFO("Deleting A2DP Connected device from list"); + bt_connection_node_info_t *a_conn; + GList *list = NULL; + bluetooth_state_type_t state; + state = BLUETOOTH_A2DP_CONNECTED; + list = g_list_find_custom(p_connection_list, + &state, compare_state); + if (list == NULL) { + BT_INFO("Didn't found any device with A2DP State"); + return; + } + a_conn = list->data; + p_connection_list = g_list_remove(p_connection_list, a_conn); + g_free(a_conn); + } +} + diff --git a/bt-service/bt-service-hid.c b/bt-service/bt-service-hid.c old mode 100644 new mode 100755 index 2b96f38..ce35fdc --- a/bt-service/bt-service-hid.c +++ b/bt-service/bt-service-hid.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -22,11 +26,11 @@ #include #include #include -#if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT) #include -#endif #include "bluetooth-api.h" + #include "bt-service-common.h" +#include "bt-service-device.h" #include "bt-service-hid.h" #include "bt-service-event.h" #include "bt-service-util.h" @@ -63,10 +67,8 @@ static void __bt_hid_connect_cb(DBusGProxy *proxy, DBusGProxyCall *call, if (g_error != NULL) { BT_ERR("Hidh Connect Dbus Call Error: %s\n", g_error->message); result = BLUETOOTH_ERROR_INTERNAL; - goto dbus_return; } -dbus_return: if (req_info->context == NULL) goto done; @@ -86,6 +88,7 @@ dbus_return: g_array_free(out_param2, TRUE); _bt_delete_request_list(req_info->req_id); + BT_DBG("HID Connected.."); done: if (g_error) g_error_free(g_error); @@ -128,10 +131,8 @@ static void __bt_hid_disconnect_cb(DBusGProxy *proxy, DBusGProxyCall *call, if (g_error != NULL) { BT_ERR("Hidh Connect Dbus Call Error: %s\n", g_error->message); result = BLUETOOTH_ERROR_INTERNAL; - goto dbus_return; } -dbus_return: if (req_info->context == NULL) goto done; @@ -169,100 +170,71 @@ done: int _bt_hid_connect(int request_id, bluetooth_device_address_t *device_address) { - gchar *device_path = NULL; char address[BT_ADDRESS_STRING_SIZE] = { 0 }; bt_function_data_t *func_data; DBusGProxy *adapter_proxy; - DBusGProxy *hid_proxy; DBusGConnection *conn; - BT_CHECK_PARAMETER(device_address, return); + int ret; + char *uuid; - _bt_convert_addr_type_to_string(address, device_address->addr); + BT_CHECK_PARAMETER(device_address, return); adapter_proxy = _bt_get_adapter_proxy(); retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - device_path = _bt_get_device_object_path(address); - if (device_path == NULL) { - BT_ERR("No paired device"); - return BLUETOOTH_ERROR_NOT_PAIRED; - } - conn = _bt_get_system_gconn(); retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); - hid_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, - device_path, BT_DEVICE_INTERFACE); + _bt_convert_addr_type_to_string(address, device_address->addr); - g_free(device_path); - retv_if(hid_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); func_data = g_malloc0(sizeof(bt_function_data_t)); func_data->address = g_strdup(address); func_data->req_id = request_id; + uuid = HID_UUID; - if (!dbus_g_proxy_begin_call(hid_proxy, "Connect", - (DBusGProxyCallNotify)__bt_hid_connect_cb, - func_data, NULL, - G_TYPE_INVALID)) { - BT_ERR("Hidh connect Dbus Call Error"); - g_object_unref(hid_proxy); + ret = _bt_connect_profile(address, uuid, + __bt_hid_connect_cb, func_data); - g_free(func_data->address); - g_free(func_data); - return BLUETOOTH_ERROR_INTERNAL; + if (ret != BLUETOOTH_ERROR_NONE) { + BT_ERR("_bt_connect_profile Error"); + return ret; } - return BLUETOOTH_ERROR_NONE; } int _bt_hid_disconnect(int request_id, bluetooth_device_address_t *device_address) { - gchar *device_path = NULL; char address[BT_ADDRESS_STRING_SIZE] = { 0 }; bt_function_data_t *func_data; DBusGProxy *adapter_proxy; - DBusGProxy *hid_proxy; DBusGConnection *conn; - BT_CHECK_PARAMETER(device_address, return); + int ret; - _bt_convert_addr_type_to_string(address, device_address->addr); + BT_CHECK_PARAMETER(device_address, return); adapter_proxy = _bt_get_adapter_proxy(); retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - device_path = _bt_get_device_object_path(address); - if (device_path == NULL) { - BT_ERR("No paired device"); - return BLUETOOTH_ERROR_NOT_PAIRED; - } - conn = _bt_get_system_gconn(); retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); - hid_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, - device_path, BT_DEVICE_INTERFACE); + _bt_convert_addr_type_to_string(address, device_address->addr); - g_free(device_path); - retv_if(hid_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); func_data = g_malloc0(sizeof(bt_function_data_t)); func_data->address = g_strdup(address); func_data->req_id = request_id; - if (!dbus_g_proxy_begin_call(hid_proxy, "Disconnect", - (DBusGProxyCallNotify)__bt_hid_disconnect_cb, - func_data, NULL, - G_TYPE_INVALID)) { - BT_ERR("Hidh disconnect Dbus Call Error"); - g_object_unref(hid_proxy); + ret = _bt_disconnect_profile(address, HID_UUID, + __bt_hid_disconnect_cb, func_data); - g_free(func_data->address); - g_free(func_data); - return BLUETOOTH_ERROR_INTERNAL; + if (ret != BLUETOOTH_ERROR_NONE) { + BT_ERR("_bt_disconnect_profile Error"); + return ret; } return BLUETOOTH_ERROR_NONE; diff --git a/bt-service/bt-service-main.c b/bt-service/bt-service-main.c old mode 100644 new mode 100755 index 5841c39..b290494 --- a/bt-service/bt-service-main.c +++ b/bt-service/bt-service-main.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -21,7 +25,6 @@ #include #include #include -#include #include #include "bt-internal-types.h" @@ -31,14 +34,19 @@ #include "bt-service-util.h" #include "bt-request-handler.h" #include "bt-service-adapter.h" +#include "bt-service-adapter-le.h" static GMainLoop *main_loop; -static gboolean terminated; +static gboolean terminated = FALSE; static void __bt_release_service(void) { + _bt_service_unregister_vconf_handler(); + + _bt_service_adapter_le_deinit(); _bt_deinit_service_event_sender(); - _bt_deinit_service_event_reciever(); + _bt_deinit_hf_local_term_event_sender(); + _bt_deinit_service_event_receiver(); _bt_service_unregister(); @@ -58,23 +66,34 @@ static void __bt_sigterm_handler(int signo) gboolean _bt_terminate_service(gpointer user_data) { - int value; - - if (vconf_get_int(BT_OFF_DUE_TO_FLIGHT_MODE, &value) != 0) - BT_ERR("Fail to get the flight_mode_deactivated value"); - - if (value == 1) { - BT_DBG("Bt service not terminated"); + int bt_status = VCONFKEY_BT_STATUS_OFF; - _bt_deinit_bluez_proxy(); + if (vconf_get_int(VCONFKEY_BT_STATUS, &bt_status) < 0) { + BT_ERR("no bluetooth device info, so BT was disabled at previous session"); + } else { + if (bt_status != VCONFKEY_BT_STATUS_OFF) { + if(vconf_set_int(VCONFKEY_BT_STATUS, + VCONFKEY_BT_STATUS_OFF) != 0) + BT_ERR("Set vconf failed\n"); + } + } - return FALSE; +#ifdef ENABLE_TIZEN_2_4 + if (vconf_get_int(VCONFKEY_BT_LE_STATUS, &bt_status) < 0) { + BT_ERR("no bluetooth device info, so BT was disabled at previous session"); + } else { + if (bt_status != VCONFKEY_BT_LE_STATUS_OFF) { + if(vconf_set_int(VCONFKEY_BT_LE_STATUS, + VCONFKEY_BT_LE_STATUS_OFF) != 0) + BT_ERR("Set vconf failed\n"); + } } +#endif if (main_loop != NULL) { g_main_loop_quit(main_loop); } else { - BT_DBG("main_loop == NULL"); + BT_ERR("main_loop == NULL"); __bt_release_service(); terminated = TRUE; exit(0); @@ -83,44 +102,96 @@ gboolean _bt_terminate_service(gpointer user_data) return FALSE; } -/* align bt-service state (adapter_status and vconf keys) on BlueZ state */ +gboolean _bt_reliable_terminate_service(gpointer user_data) +{ + _bt_deinit_service_event_receiver(); + + _bt_deinit_proxys(); + + _bt_clear_request_list(); + + _bt_set_disabled(BLUETOOTH_ERROR_NONE); + + _bt_service_adapter_le_deinit(); + _bt_deinit_service_event_sender(); + _bt_deinit_hf_local_term_event_sender(); + + _bt_service_unregister(); + + terminated = TRUE; + + BT_INFO_C("Terminating the bt-service daemon"); + + if (main_loop != NULL) { + g_main_loop_quit(main_loop); + } else { + exit(0); + } + + return FALSE; +} + static gboolean __bt_check_bt_service(void *data) { int bt_status = VCONFKEY_BT_STATUS_OFF; + int bt_le_status = 0; + bt_status_t status = BT_DEACTIVATED; + bt_le_status_t le_status = BT_LE_DEACTIVATED; int flight_mode_deactivation = 0; + int bt_off_due_to_timeout = 0; +#if 0 + int ps_mode_deactivation = 0; +#endif - int adapter_enabled = 0; + status = _bt_adapter_get_status(); + le_status = _bt_adapter_get_le_status(); + BT_DBG("State: %d, LE State: %d", status, le_status); if (vconf_get_int(VCONFKEY_BT_STATUS, &bt_status) < 0) { BT_DBG("no bluetooth device info, so BT was disabled at previous session"); } - if (vconf_get_int(BT_OFF_DUE_TO_FLIGHT_MODE, &flight_mode_deactivation) != 0) - BT_ERR("Fail to get the flight_mode_deactivated value"); +#ifdef ENABLE_TIZEN_2_4 + if (vconf_get_int(VCONFKEY_BT_LE_STATUS, &bt_le_status) < 0) { + BT_ERR("no bluetooth le info, so BT LE was disabled at previous session"); + } +#endif - _bt_check_adapter(&adapter_enabled); + if (vconf_get_int(BT_OFF_DUE_TO_FLIGHT_MODE, &flight_mode_deactivation) != 0) + BT_ERR("Fail to get the flight_mode_deactivation value"); - BT_DBG("get bt adapter status: %d when starting bt-service ", adapter_enabled); +#if 0 + if (vconf_get_int(BT_OFF_DUE_TO_POWER_SAVING_MODE, &ps_mode_deactivation) != 0) + BT_ERR("Fail to get the ps_mode_deactivation value"); +#endif - _bt_adapter_set_status(adapter_enabled); + if (vconf_get_int(BT_OFF_DUE_TO_TIMEOUT, &bt_off_due_to_timeout) != 0) + BT_ERR("Fail to get BT_OFF_DUE_TO_TIMEOUT"); - if (adapter_enabled != bt_status) { - BT_DBG("align vconf bt status key with real bluetooth status"); - if (vconf_set_int(VCONFKEY_BT_STATUS, adapter_enabled) != 0) - BT_ERR("Set vconf key %s failed", VCONFKEY_BT_STATUS); + if ((bt_status != VCONFKEY_BT_STATUS_OFF || bt_off_due_to_timeout) + && (status == BT_DEACTIVATED)) { + BT_DBG("Previous session was enabled."); - bt_status = adapter_enabled; + /* Enable the BT */ + _bt_enable_adapter(); + } else if (bt_status == VCONFKEY_BT_STATUS_OFF && flight_mode_deactivation == 1) { + _bt_enable_core(); } - if (bt_status == VCONFKEY_BT_STATUS_OFF && flight_mode_deactivation == 1) { - BT_ERR("call _bt_handle_flight_mode_noti()"); - _bt_handle_flight_mode_noti(); - return FALSE; - } + if ((bt_le_status == 1) && (le_status == BT_LE_DEACTIVATED)) { + BT_DBG("Previous session was le enabled. Turn BT LE on automatically."); - if (adapter_enabled == TRUE) { - BT_DBG(""); - _bt_handle_adapter_added(); + /* Enable the BT LE */ + _bt_enable_adapter_le(); + } else { + status = _bt_adapter_get_status(); + le_status = _bt_adapter_get_le_status(); + BT_DBG("State: %d, LE State: %d", status, le_status); + + if ((status != BT_ACTIVATING && status != BT_ACTIVATED) && + (le_status != BT_LE_ACTIVATING && le_status != BT_LE_ACTIVATED)){ + _bt_terminate_service(NULL); + } } return FALSE; @@ -129,16 +200,14 @@ static gboolean __bt_check_bt_service(void *data) int main(void) { struct sigaction sa; - BT_DBG("Starting the bt-service daemon"); + BT_INFO_C("Starting the bt-service daemon"); memset(&sa, 0, sizeof(sa)); sa.sa_handler = __bt_sigterm_handler; sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); - if (perm_app_set_privilege("bluetooth-frwk-service", NULL, NULL) != - PC_OPERATION_SUCCESS) - BT_ERR("Failed to set app privilege.\n"); + g_type_init(); /* Event reciever Init */ if (_bt_init_service_event_receiver() != BLUETOOTH_ERROR_NONE) { @@ -152,16 +221,26 @@ int main(void) return 0; } + if (_bt_init_hf_local_term_event_sender() != BLUETOOTH_ERROR_NONE) { + BT_ERR("Fail to init core event sender"); + return 0; + } + if (_bt_service_register() != BLUETOOTH_ERROR_NONE) { BT_ERR("Fail to register service"); return 0; } + if (_bt_service_adapter_le_init() != BLUETOOTH_ERROR_NONE) { + BT_ERR("Fail to init le"); + return 0; + } + _bt_init_request_id(); _bt_init_request_list(); - g_idle_add((GSourceFunc)__bt_check_bt_service, NULL); + g_timeout_add(500, (GSourceFunc)__bt_check_bt_service, NULL); if (terminated == TRUE) { __bt_release_service(); @@ -171,12 +250,14 @@ int main(void) main_loop = g_main_loop_new(NULL, FALSE); g_main_loop_run(main_loop); + BT_DBG("g_main_loop_quit called!"); if (main_loop != NULL) { g_main_loop_unref(main_loop); } - __bt_release_service(); + if (terminated == FALSE) + __bt_release_service(); return 0; } diff --git a/bt-service/bt-service-mdm.c b/bt-service/bt-service-mdm.c new file mode 100755 index 0000000..1b9e4a1 --- /dev/null +++ b/bt-service/bt-service-mdm.c @@ -0,0 +1,650 @@ +/* + * Bluetooth-frwk + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * 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. + * + */ + +#ifdef TIZEN_MDM_ENABLE +#include + +#include "bt-internal-types.h" +#include "bt-service-common.h" +#include "bt-service-main.h" +#include "bt-service-mdm.h" +#include "bt-service-opp-client.h" +#include "bt-service-obex-server.h" +#include "bt-service-rfcomm-client.h" +#include "bt-service-rfcomm-server.h" +#include "bt-service-adapter.h" +#include "bt-service-device.h" +#include "bt-service-network.h" +#include "bt-service-pbap.h" + +policy_receiver_handle mdm_handle; + +static int __bt_mdm_is_profile_connected(bluetooth_device_address_t *device_address, + char *profile_uuid, gboolean *is_connected) +{ + char *object_path = NULL; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + DBusGProxy *device_proxy = NULL; + DBusGProxy *adapter_proxy = NULL; + DBusGConnection *conn; + GError *error = NULL; + GHashTable *hash = NULL; + GValue *value = NULL; + dbus_bool_t val = FALSE; + + retv_if(device_address == NULL, BLUETOOTH_ERROR_INVALID_PARAM); + retv_if(profile_uuid == NULL, BLUETOOTH_ERROR_INVALID_PARAM); + retv_if(is_connected == NULL, BLUETOOTH_ERROR_INVALID_PARAM); + + *is_connected = FALSE; + + if (g_strcmp0(profile_uuid, RFCOMM_UUID_STR) == 0) + return _bt_rfcomm_is_device_connected(device_address, + is_connected); + else if (g_strcmp0(profile_uuid, GATT_UUID) == 0) + return _bt_is_gatt_connected(device_address, is_connected); + + adapter_proxy = _bt_get_adapter_proxy(); + retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + _bt_convert_addr_type_to_string(address, device_address->addr); + + if (g_strcmp0(profile_uuid, NAP_UUID) == 0) { + object_path = _bt_get_adapter_path(); + device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + object_path, BT_NETWORK_SERVER_INTERFACE); + g_free(object_path); + if (device_proxy == NULL) { + BT_DBG("Device don't have this service"); + return BLUETOOTH_ERROR_INTERNAL; + } + dbus_g_proxy_call(device_proxy, "GetProperties", NULL, + G_TYPE_STRING, address, + G_TYPE_INVALID, + dbus_g_type_get_map("GHashTable", + G_TYPE_STRING, G_TYPE_VALUE), + &hash, G_TYPE_INVALID); + if (hash != NULL) { + value = g_hash_table_lookup(hash, "Connected"); + *is_connected = value ? g_value_get_boolean(value) : FALSE; + g_hash_table_destroy(hash); + } + } else if (g_strcmp0(profile_uuid, PANU_UUID) == 0) + return _bt_is_network_connected(_bt_get_net_conn(), + device_address->addr, is_connected); + else { + object_path = _bt_get_device_object_path(address); + retv_if(object_path == NULL, BLUETOOTH_ERROR_NOT_PAIRED); + + device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + object_path, BT_DEVICE_INTERFACE); + g_free(object_path); + if (device_proxy == NULL) { + BT_DBG("Device don't have this service"); + return BLUETOOTH_ERROR_INTERNAL; + } + dbus_g_proxy_call(device_proxy, "IsConnectedProfile", &error, + G_TYPE_STRING, profile_uuid, + G_TYPE_INVALID, + G_TYPE_BOOLEAN, &val, + G_TYPE_INVALID); + if (error != NULL) { + BT_ERR("Failed to get properties: %s\n", error->message); + g_error_free(error); + } + + *is_connected = val; + } + + if (device_proxy) + g_object_unref(device_proxy); + + return BLUETOOTH_ERROR_NONE; +} + +static int __bt_mdm_get_connected_profile_address(char *address, char *UUID) +{ + int err; + int ret = FALSE; + int i; + gboolean is_connected = FALSE; + GArray *device_list = NULL; + bluetooth_device_info_t info; + guint size; + + device_list = g_array_new(FALSE, FALSE, sizeof(gchar)); + + if (_bt_get_bonded_devices(&device_list) + != BLUETOOTH_ERROR_NONE) { + g_array_free(device_list, TRUE); + return ret; + } + + size = (device_list->len) / sizeof(bluetooth_device_info_t); + BT_DBG("g arrary size : [%d]", size); + + for (i = 0; i < size; i++) { + + info = g_array_index(device_list, + bluetooth_device_info_t, i); + + if (info.connected == TRUE) { + BT_DBG("Found Connected device[%s]", info.device_name.name); + err = __bt_mdm_is_profile_connected(&info.device_address, + UUID, &is_connected); + + if (err == BLUETOOTH_ERROR_NONE) { + if (is_connected) { + BT_DBG("connected device name : %s", info.device_name.name); + _bt_convert_addr_type_to_string(address, (unsigned char *)info.device_address.addr); + ret = TRUE; + break; + } + } + + } + } + g_array_free(device_list, TRUE); + + return ret; +} + +static void __bt_mdm_mode_changed(int mode) +{ + int visible = BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE; + + BT_DBG("allow mode: %d", mode); + + switch (mode) { + case MDM_BT_ALLOWED: + BT_DBG("MDM_BT_ALLOWED"); + /* Nothing to do */ + break; + case MDM_BT_HANDSFREE_ONLY: + BT_DBG("MDM_BT_HANDSFREE_ONLY"); + + _bt_get_discoverable_mode(&visible); + ret_if(visible == BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE); + + _bt_set_discoverable_mode(BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE, 0); + + _bt_opp_client_cancel_all_transfers(); + + _bt_obex_server_cancel_all_transfers(); + + _bt_rfcomm_client_disconnect_all(); + + _bt_rfcomm_server_disconnect_all_connection(); + + _bt_launch_mdm_popup("MDM_POLICY_DISABLE_BT_HANDSFREE"); + + break; + case MDM_BT_RESTRICTED: + BT_DBG("MDM_BT_RESTRICTED"); + + _bt_launch_mdm_popup("MDM_POLICY_DISABLE_BT"); + + /* deactivate BT */ + _bt_disable_adapter(); + break; + default: + BT_DBG("Unknown mode"); + break; + } + + BT_DBG("-"); +} + +static void __bt_mdm_discoverable_state_changed(int state) +{ + int visible = BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE; + + BT_DBG("state: %d", state); + + switch (state) { + case MDM_ALLOWED: + BT_DBG("MDM_ALLOWED"); + /* Nothing to do */ + break; + case MDM_RESTRICTED: + BT_DBG("MDM_RESTRICTED"); + + _bt_get_discoverable_mode(&visible); + ret_if(visible == BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE); + + _bt_set_discoverable_mode(BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE, 0); + break; + default: + BT_DBG("Unknown mode"); + break; + } +} + +static void __bt_mdm_limited_discoverable_state_changed(int state) +{ + int visible = BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE; + int timeout = 0; + + BT_DBG("state: %d", state); + + switch (state) { + case MDM_ALLOWED: + BT_DBG("MDM_ALLOWED"); + if (vconf_get_int(BT_FILE_VISIBLE_TIME, &timeout) != 0) + BT_ERR("Fail to get the timeout value"); + else { + if (timeout != -1) { + BT_DBG("_bt_set_discoverable_mode"); + if (_bt_set_discoverable_mode( + BLUETOOTH_DISCOVERABLE_MODE_TIME_LIMITED_DISCOVERABLE, + timeout) != BLUETOOTH_ERROR_NONE) { + if (vconf_set_int(BT_FILE_VISIBLE_TIME, 0) != 0) + BT_ERR("Set vconf failed"); + } + } + } + + break; + case MDM_RESTRICTED: + BT_DBG("MDM_RESTRICTED"); + + _bt_get_discoverable_mode(&visible); + ret_if(visible == BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE); + + _bt_set_discoverable_mode(BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE, + 0); + break; + default: + BT_DBG("Unknown mode"); + break; + } +} + +static int __bt_mdm_idle_cb(void *data) +{ + int *status = data; + int mode; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + + retv_if(status == NULL, FALSE); + + BT_DBG("policy: %d", *status); + + if (mdm_get_service() != MDM_RESULT_SUCCESS) return BT_MDM_NO_SERVICE; + + switch (*status) { + case MDM_BT_MODE_CHANGED: + mode = mdm_get_allow_bluetooth_mode(); + __bt_mdm_mode_changed(mode); + break; + case MDM_BT_OUTGOING_CALL_CHANGED: + BT_DBG("MDM_BT_OUTGOING_CALL_CHANGED"); + break; + case MDM_BT_A2DP_PROFILE_CHANGED: + BT_DBG("MDM_BT_A2DP_PROFILE_CHANGED"); +#ifdef MDM_PHASE_2 + if (mdm_get_bluetooth_profile_state(BLUETOOTH_A2DP_PROFILE) + == MDM_RESTRICTED) { + if (__bt_mdm_get_connected_profile_address(address, + A2DP_SINK_UUID)) + _bt_disconnect_profile(address, A2DP_SINK_UUID, + NULL, NULL); + } +#endif + break; + case MDM_BT_AVRCP_PROFILE_CHANGED: + BT_DBG("MDM_BT_AVRCP_PROFILE_CHANGED"); +#ifdef MDM_PHASE_2 + if (mdm_get_bluetooth_profile_state(BLUETOOTH_AVRCP_PROFILE) + == MDM_RESTRICTED) { + if (__bt_mdm_get_connected_profile_address(address, + AVRCP_REMOTE_UUID)) + _bt_disconnect_profile(address, AVRCP_REMOTE_UUID, + NULL, NULL); + } +#endif + break; + case MDM_BT_BPP_PROFILE_CHANGED: + BT_DBG("MDM_BT_BPP_PROFILE_CHANGED"); + break; + case MDM_BT_DUN_PROFILE_CHANGED: + BT_DBG("MDM_BT_DUN_PROFILE_CHANGED"); + break; + case MDM_BT_FTP_PROFILE_CHANGED: + BT_DBG("MDM_BT_FTP_PROFILE_CHANGED"); + break; + case MDM_BT_HFP_PROFILE_CHANGED: + BT_DBG("MDM_BT_HFP_PROFILE_CHANGED"); +#ifdef MDM_PHASE_2 + if (mdm_get_bluetooth_profile_state(BLUETOOTH_HFP_PROFILE) + == MDM_RESTRICTED) { + if (__bt_mdm_get_connected_profile_address(address, + HFP_HS_UUID)) + _bt_disconnect_profile(address, HFP_HS_UUID, + NULL, NULL); + } +#endif + break; + case MDM_BT_HSP_PROFILE_CHANGED: + BT_DBG("MDM_BT_HSP_PROFILE_CHANGED"); +#ifdef MDM_PHASE_2 + if (mdm_get_bluetooth_profile_state(BLUETOOTH_HSP_PROFILE) + == MDM_RESTRICTED) { + if (__bt_mdm_get_connected_profile_address(address, + HSP_HS_UUID)) + _bt_disconnect_profile(address, HSP_HS_UUID, + NULL, NULL); + } +#endif + break; + case MDM_BT_PBAP_PROFILE_CHANGED: + BT_DBG("MDM_BT_PBAP_PROFILE_CHANGED"); +#ifdef MDM_PHASE_2 + if (mdm_get_bluetooth_profile_state(BLUETOOTH_PBAP_PROFILE) + == MDM_RESTRICTED) { + if (__bt_mdm_get_connected_profile_address(address, + OBEX_PSE_UUID)) { + bluetooth_device_address_t addr; + _bt_convert_addr_string_to_type(addr.addr, + address); + _bt_pbap_disconnect(&addr); + } + } +#endif + break; + case MDM_BT_SAP_PROFILE_CHANGED: + BT_DBG("MDM_BT_SAP_PROFILE_CHANGED"); + break; + case MDM_BT_SPP_PROFILE_CHANGED: + BT_DBG("MDM_BT_SPP_PROFILE_CHANGED"); + break; + case MDM_BT_DESKTOP_CONNECTIVITY_STATE_CHANGED: + BT_DBG("MDM_BT_DESKTOP_CONNECTIVITY_STATE_CHANGED"); + break; + case MDM_BT_DISCOVERABLE_STATE_CHANGED: + BT_DBG("MDM_BT_DISCOVERABLE_STATE_CHANGED"); +#ifdef MDM_PHASE_2 + mode = mdm_get_bluetooth_discoverable_state(); + __bt_mdm_discoverable_state_changed(mode); +#endif + break; + case MDM_BT_PARINIG_STATE_CHANGED: + BT_DBG("MDM_BT_PARINIG_STATE_CHANGED"); + break; + case MDM_BT_LIMITED_DISCOVERABLE_STATE_CHANGED: + BT_DBG("MDM_BT_LIMITED_DISCOVERABLE_STATE_CHANGED"); +#ifdef MDM_PHASE_2 + mode = mdm_get_bluetooth_limited_discoverable_state(); + __bt_mdm_limited_discoverable_state_changed(mode); +#endif + break; + case MDM_BT_DATA_TRANSFER_CHANGED: + BT_DBG("MDM_BT_DATA_TRANSFER_CHANGED"); +#ifdef MDM_PHASE_2 + mode = mdm_get_bluetooth_data_transfer_state(); + if (mode == MDM_RESTRICTED) { + _bt_opp_client_cancel_all_transfers(); + _bt_obex_server_cancel_all_transfers(); + } +#endif + break; + default: + BT_DBG("Unknown mode"); + break; + } + + g_free(status); + + mdm_release_service(); + + BT_DBG("-"); + return FALSE; +} + +static void __bt_mdm_policy_changed_cb(int status, void *data) +{ + int *mdm_status; + + BT_DBG("policy: %d", status); + + mdm_status = g_malloc0(sizeof(int)); + + *mdm_status = status; + + g_idle_add((GSourceFunc)__bt_mdm_idle_cb, mdm_status); +} + +void _bt_init_mdm_handle(void) +{ + mdm_handle = mdm_register_policy_receiver(MDM_POLICY_ON_BT, + NULL, + __bt_mdm_policy_changed_cb); + if (mdm_handle == (policy_receiver_handle)NULL) + BT_ERR("MDM register failed\n"); +} + +void _bt_deinit_mdm_handle(void) +{ + if(mdm_handle != (policy_receiver_handle)NULL) { + mdm_deregister_policy_receiver(mdm_handle); + mdm_handle = (policy_receiver_handle)NULL; + } + + mdm_release_service(); +} + +int _bt_launch_mdm_popup(char *mode) +{ + int ret = 0; + bundle *b; + + b = bundle_create(); + retv_if(b == NULL, BLUETOOTH_ERROR_INTERNAL); + + bundle_add(b, "mode", mode); + + ret = syspopup_launch(BT_MDM_SYSPOPUP, b); + + if (ret < 0) + BT_DBG("Popup launch failed: %d\n", ret); + + bundle_free(b); + + return ret; +} + +bt_mdm_status_e _bt_check_mdm_allow_restriction(void) +{ + mdm_bt_allow_t mode; + + if (mdm_get_service() != MDM_RESULT_SUCCESS) return BT_MDM_NO_SERVICE; + + mode = mdm_get_allow_bluetooth_mode(); + mdm_release_service(); + + return (mode == MDM_BT_RESTRICTED) ? BT_MDM_RESTRICTED : BT_MDM_ALLOWED; +} + +#ifdef MDM_PHASE_2 +bt_mdm_status_e _bt_check_mdm_desktop_connectivity_restriction(void) +{ + bt_mdm_status_e mdm_status = BT_MDM_ALLOWED; + + if (mdm_get_service() != MDM_RESULT_SUCCESS) + return BT_MDM_NO_SERVICE; + + if (mdm_get_bluetooth_desktop_connectivity_state() == MDM_RESTRICTED) { + /* Not allow to visible on */ + BT_ERR("Desktop connection is restricted"); + mdm_status = BT_MDM_RESTRICTED; + } + mdm_release_service(); + + return mdm_status; +} + +bt_mdm_status_e _bt_check_mdm_visible_restriction(void) +{ + bt_mdm_status_e mdm_status = BT_MDM_ALLOWED; + + if (mdm_get_service() != MDM_RESULT_SUCCESS) return BT_MDM_NO_SERVICE; + + if (mdm_get_bluetooth_discoverable_state() == MDM_RESTRICTED || + mdm_get_allow_bluetooth_mode() == MDM_BT_HANDSFREE_ONLY) { + /* Not allow to visible on */ + BT_ERR("Restricted to set visible mode"); + mdm_status = BT_MDM_RESTRICTED; + } + mdm_release_service(); + + return mdm_status; +} + +bt_mdm_status_e _bt_check_mdm_limited_discoverable_mode(void) +{ + bt_mdm_status_e mdm_status = BT_MDM_ALLOWED; + + if (mdm_get_service() != MDM_RESULT_SUCCESS) return BT_MDM_NO_SERVICE; + + if (mdm_get_bluetooth_limited_discoverable_state() == MDM_RESTRICTED) { + BT_ERR("limited discoverable mode"); + mdm_status = BT_MDM_RESTRICTED; + } + mdm_release_service(); + + return mdm_status; +} + +bt_mdm_status_e _bt_check_mdm_blacklist_devices(bluetooth_device_address_t *address) +{ + mdm_data_t *lp_data; + GList *blacklist; + char *device_name; + bluetooth_device_info_t dev_info; + bt_mdm_status_e mdm_status = BT_MDM_ALLOWED; + + if (mdm_get_service() != MDM_RESULT_SUCCESS) return BT_MDM_NO_SERVICE; + + memset(&dev_info, 0x00, sizeof(bluetooth_device_info_t)); + + if (_bt_get_bonded_device_info(address, + &dev_info) != BLUETOOTH_ERROR_NONE) { + BT_ERR("Not paired device"); + goto release; + } + + lp_data = mdm_get_bluetooth_devices_from_blacklist(); + if (lp_data == NULL) { + BT_ERR("No blacklist"); + goto release; + } + + for (blacklist = (GList *)lp_data->data; blacklist; blacklist = blacklist->next) { + device_name = blacklist->data; + + DBG_SECURE("blacklist name: %s", device_name); + + if (g_strcmp0(dev_info.device_name.name, + device_name) == 0) { + mdm_status = BT_MDM_RESTRICTED; + break; + } + } + + mdm_free_data(lp_data); +release : + mdm_release_service(); + return mdm_status; +} + +mdm_bt_profile_t convert_uuid_string_to_type(const char* uuid) +{ + retv_if (uuid == NULL, MDM_BT_PROFILE_NONE); + + if (!strcasecmp(uuid, BT_A2DP_UUID)) + return BLUETOOTH_A2DP_PROFILE; + else if (!strcasecmp(uuid, BT_AVRCP_TARGET_UUID)) + return BLUETOOTH_AVRCP_PROFILE; + else if (!strcasecmp(uuid, BT_FTP_UUID)) + return BLUETOOTH_FTP_PROFILE; + else if (!strcasecmp(uuid, BT_HFP_AUDIO_GATEWAY_UUID)) + return BLUETOOTH_HFP_PROFILE; + else if (!strcasecmp(uuid, HSP_AG_UUID)) + return BLUETOOTH_HSP_PROFILE; + else if (!strcasecmp(uuid, OBEX_PSE_UUID)) + return BLUETOOTH_PBAP_PROFILE; + else if (!strcasecmp(uuid, BT_SPP_UUID)) + return BLUETOOTH_SPP_PROFILE; + + return MDM_BT_PROFILE_NONE; +} + +bt_mdm_status_e _bt_check_mdm_blacklist_uuid(char *uuid) +{ + mdm_data_t *lp_data; + GList *blacklist; + char *blacklist_uuid; + bt_mdm_status_e mdm_status = BT_MDM_ALLOWED; + + retv_if (uuid == NULL, mdm_status); + + if (mdm_get_service() != MDM_RESULT_SUCCESS) return BT_MDM_NO_SERVICE; + + lp_data = mdm_get_bluetooth_uuids_from_blacklist(); + if (lp_data == NULL) { + BT_ERR("No blacklist"); + goto release; + } + + for (blacklist = (GList *)lp_data->data; blacklist; blacklist = blacklist->next) { + blacklist_uuid = blacklist->data; + + BT_DBG("blacklist_uuid: %s", blacklist_uuid); + + if (g_strcmp0(blacklist_uuid, uuid) == 0) { + mdm_status = BT_MDM_RESTRICTED; + break; + } + } + + if (mdm_status == BT_MDM_ALLOWED) { + mdm_bt_profile_t profile; + profile = convert_uuid_string_to_type(uuid); + if (mdm_get_bluetooth_profile_state(profile) == MDM_RESTRICTED) { + BT_ERR("Restricted UUID"); + mdm_status = BT_MDM_RESTRICTED; + } + } + + mdm_free_data(lp_data); + +release : + mdm_release_service(); + return mdm_status; +} +#endif +#endif + diff --git a/bt-service/bt-service-media-agent.xml b/bt-service/bt-service-media-agent.xml old mode 100644 new mode 100755 index d3fcb57..d7c2afe --- a/bt-service/bt-service-media-agent.xml +++ b/bt-service/bt-service-media-agent.xml @@ -8,4 +8,10 @@ + + + + + + diff --git a/bt-service/bt-service-network.c b/bt-service/bt-service-network.c old mode 100644 new mode 100755 index fd5ae9b..772a743 --- a/bt-service/bt-service-network.c +++ b/bt-service/bt-service-network.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -22,14 +26,113 @@ #include #include #include -#if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT) +#include #include -#endif +#include + #include "bluetooth-api.h" #include "bt-service-network.h" #include "bt-service-common.h" #include "bt-service-event.h" #include "bt-service-util.h" +#include "bt-internal-types.h" + +void _bt_util_addr_type_to_addr_net_string(char *address, + unsigned char *addr) +{ + ret_if(address == NULL); + ret_if(addr == NULL); + + snprintf(address, BT_ADDRESS_STR_LEN, "%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X", addr[0], + addr[1], addr[2], addr[3], addr[4], addr[5]); +} + +static connection_profile_h __bt_get_net_profile(void *connection, + connection_iterator_type_e type, + unsigned char *address) +{ + int result; + gchar **split_string; + char net_address[BT_ADDRESS_STR_LEN + 1] = { 0 }; + char *profile_name = NULL; + connection_profile_iterator_h profile_iter; + connection_profile_h profile_h; + connection_profile_type_e profile_type; + + retv_if(connection == NULL, NULL); + retv_if(address == NULL, NULL); + + BT_DBG("net_conn: %x", connection); + + _bt_util_addr_type_to_addr_net_string(net_address, address); + + result = connection_get_profile_iterator(connection, + type, + &profile_iter); + if (result != CONNECTION_ERROR_NONE) { + BT_ERR("Fail to get profile iterator [%d]", result); + return NULL; + } + + while (connection_profile_iterator_has_next(profile_iter)) { + profile_name = NULL; + profile_h = NULL; + split_string = NULL; + + if (connection_profile_iterator_next(profile_iter, + &profile_h) != CONNECTION_ERROR_NONE) { + BT_ERR("Fail to get profile handle"); + return NULL; + } + + if (connection_profile_get_type(profile_h, + &profile_type) != CONNECTION_ERROR_NONE) { + BT_ERR("Fail to get profile type"); + continue; + } + + if (profile_type != CONNECTION_PROFILE_TYPE_BT) + continue; + + if (connection_profile_get_name(profile_h, + &profile_name) != CONNECTION_ERROR_NONE) { + BT_ERR("Fail to get profile name"); + return NULL; + } + + split_string = g_strsplit(profile_name, "_", 3); + + g_free(profile_name); + + if (g_strv_length(split_string) < 3) + continue; + + if (g_ascii_strcasecmp(split_string[2], net_address) == 0) { + BT_DBG("matched profile"); + g_strfreev(split_string); + return profile_h; + } + + g_strfreev(split_string); + } + + return NULL; +} + +int _bt_is_network_connected(void *connection, unsigned char *address, + gboolean *is_connected) +{ + void *handle = NULL; + handle = __bt_get_net_profile(connection, + CONNECTION_ITERATOR_TYPE_CONNECTED, + address); + if(handle) + *is_connected = TRUE; + else + *is_connected = FALSE; + + return BLUETOOTH_ERROR_NONE; +} static void __bt_network_connect_cb(DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) @@ -64,10 +167,8 @@ static void __bt_network_connect_cb(DBusGProxy *proxy, DBusGProxyCall *call, if (g_error != NULL) { BT_ERR("Network Connect Dbus Call Error: %s\n", g_error->message); result = BLUETOOTH_ERROR_INTERNAL; - goto dbus_return; } -dbus_return: if (req_info->context == NULL) goto done; @@ -129,10 +230,8 @@ static void __bt_network_disconnect_cb(DBusGProxy *proxy, DBusGProxyCall *call, if (g_error != NULL) { BT_ERR("Network Connect Dbus Call Error: %s\n", g_error->message); result = BLUETOOTH_ERROR_INTERNAL; - goto dbus_return; } -dbus_return: if (req_info->context == NULL) goto done; @@ -212,6 +311,7 @@ int _bt_network_deactivate(void) GError *err = NULL; DBusGConnection *conn; DBusGProxy *server_proxy; + int ret = BLUETOOTH_ERROR_NONE; conn = _bt_get_system_gconn(); retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); @@ -234,15 +334,19 @@ int _bt_network_deactivate(void) G_TYPE_INVALID, G_TYPE_INVALID)) { if (err != NULL) { BT_ERR("Network server unregister Error: %s\n", err->message); + if (g_strcmp0(err->message, + "Operation currently not available") == 0) { + ret = BLUETOOTH_ERROR_ALREADY_DEACTIVATED; + } else { + ret = BLUETOOTH_ERROR_INTERNAL; + } g_error_free(err); } - g_object_unref(server_proxy); - return BLUETOOTH_ERROR_INTERNAL; } g_object_unref(server_proxy); - return BLUETOOTH_ERROR_NONE; + return ret; } int _bt_network_connect(int request_id, int role, @@ -362,3 +466,48 @@ int _bt_network_disconnect(int request_id, return BLUETOOTH_ERROR_NONE; } + +int _bt_network_server_disconnect(int request_id, + bluetooth_device_address_t *device_address) +{ + gchar *adapter_path = NULL; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + bt_function_data_t *func_data; + DBusGProxy *profile_proxy; + DBusGConnection *conn; + + BT_CHECK_PARAMETER(device_address, return); + + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + adapter_path = _bt_get_adapter_path(); + if (adapter_path == NULL) { + BT_ERR("No adapter found"); + return BLUETOOTH_ERROR_INTERNAL; + } + + _bt_convert_addr_type_to_string(address, device_address->addr); + + profile_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + adapter_path, BT_NETWORK_SERVER_INTERFACE); + g_free(adapter_path); + retv_if(profile_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + func_data = g_malloc0(sizeof(bt_function_data_t)); + + func_data->address = g_strdup(address); + func_data->req_id = request_id; + + if (!dbus_g_proxy_begin_call(profile_proxy, "Disconnect", + (DBusGProxyCallNotify)__bt_network_disconnect_cb, + func_data, NULL, G_TYPE_STRING, address, + G_TYPE_INVALID)) { + BT_ERR("network server disconnect Dbus Call Error"); + g_free(func_data->address); + g_free(func_data); + g_object_unref(profile_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + + return BLUETOOTH_ERROR_NONE; +} diff --git a/bt-service/bt-service-obex-agent.c b/bt-service/bt-service-obex-agent.c old mode 100644 new mode 100755 index e381cc2..f6f28d6 --- a/bt-service/bt-service-obex-agent.c +++ b/bt-service/bt-service-obex-agent.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -16,7 +20,6 @@ * limitations under the License. * */ - #include #include #include @@ -60,6 +63,7 @@ typedef struct { G_DEFINE_TYPE(BtObexAgent, bt_obex_agent, G_TYPE_OBJECT) + gboolean bt_obex_agent_authorize_push(BtObexAgent *agent, const char *path, DBusGMethodInvocation *context) { @@ -83,6 +87,27 @@ fail: return FALSE; } +gboolean bt_obex_agent_authorize(BtObexAgent *agent, const char *path, + const char *bdaddress, const char *name, + const char *type, gint length, gint time, + DBusGMethodInvocation *context) +{ + bt_obex_agent_info *info; + + info = BT_OBEX_AGENT_GET_PRIVATE(agent); + + if (info == NULL) + goto fail; + + if (info->authorize_cb == NULL) + goto fail; + + return TRUE; +fail: + dbus_g_method_return(context, ""); + return FALSE; +} + gboolean bt_obex_agent_request(BtObexAgent *agent, const char *path, DBusGMethodInvocation *context) { @@ -132,6 +157,8 @@ fail: gboolean bt_obex_agent_progress(BtObexAgent *agent, const char *path, guint64 transferred, DBusGMethodInvocation *context) { + BT_DBG("+"); + bt_obex_agent_info *info; char *sender; gboolean result; @@ -164,10 +191,13 @@ gboolean bt_obex_agent_progress(BtObexAgent *agent, const char *path, g_object_unref(proxy); + BT_DBG("-"); + return result; fail: BT_ERR("Fail case"); dbus_g_method_return(context, ""); + BT_DBG("-"); return FALSE; } diff --git a/bt-service/bt-service-obex-agent.xml b/bt-service/bt-service-obex-agent.xml old mode 100644 new mode 100755 index bb2ca44..6971a31 --- a/bt-service/bt-service-obex-agent.xml +++ b/bt-service/bt-service-obex-agent.xml @@ -1,7 +1,7 @@ - + @@ -28,10 +28,22 @@ - + + + + + + + + + + + + + diff --git a/bt-service/bt-service-obex-server.c b/bt-service/bt-service-obex-server.c old mode 100644 new mode 100755 index e534dce..296d1c6 --- a/bt-service/bt-service-obex-server.c +++ b/bt-service/bt-service-obex-server.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -37,25 +41,31 @@ #include "bt-service-agent.h" #define BT_OBEX_SERVER_AGENT_PATH "/org/obex/server_agent" + #define BT_OBEX_SERVICE "org.bluez.obex" #define BT_OBEX_MANAGER "org.bluez.obex.AgentManager1" #define BT_OBEX_PATH "/org/bluez/obex" + typedef struct { char *filename; + char *file_path; char *path; char *type; char *device_name; int transfer_id; gint64 file_size; + char *address; } bt_transfer_info_t; typedef struct { DBusGMethodInvocation *reply_context; gint64 file_size; char *filename; + char *file_path; char *device_name; char *transfer_path; + char *address; } bt_auth_info_t; typedef struct { @@ -104,6 +114,27 @@ static bt_transfer_info_t *__bt_find_transfer_by_id(int transfer_id) return NULL; } +bt_transfer_info_t *__bt_find_transfer_by_address(const char *address) +{ + BT_DBG("+"); + GSList *l; + bt_transfer_info_t *transfer; + + retv_if(address == NULL, NULL); + + for (l = transfers; l != NULL; l = l->next) { + transfer = l->data; + + if (transfer == NULL) + continue; + + if (g_strcmp0(transfer->address, address) == 0) + return transfer; + } + BT_DBG("-"); + return NULL; +} + static bt_transfer_info_t *__bt_find_transfer_by_path(const char *transfer_path) { GSList *l; @@ -140,6 +171,7 @@ static void __bt_free_auth_info(bt_auth_info_t *auto_info) g_free(auto_info->filename); g_free(auto_info->transfer_path); g_free(auto_info->device_name); + g_free(auto_info->address); g_free(auto_info); } @@ -149,11 +181,37 @@ static void __bt_free_transfer_info(bt_transfer_info_t *transfer_info) g_free(transfer_info->path); g_free(transfer_info->filename); + g_free(transfer_info->file_path); g_free(transfer_info->type); g_free(transfer_info->device_name); + g_free(transfer_info->address); g_free(transfer_info); } +void _bt_obex_check_pending_transfer(const char *address) +{ + BT_DBG("+"); + bt_transfer_info_t *transfer_info = __bt_find_transfer_by_address(address); + if (transfer_info != NULL) { + int result = BLUETOOTH_ERROR_CANCEL; + _bt_send_event(BT_OPP_SERVER_EVENT, + BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_COMPLETED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &transfer_info->filename, + DBUS_TYPE_STRING, &transfer_info->type, + DBUS_TYPE_STRING, &transfer_info->device_name, + DBUS_TYPE_STRING, &transfer_info->file_path, + DBUS_TYPE_UINT64, &transfer_info->file_size, + DBUS_TYPE_INT32, &transfer_info->transfer_id, + DBUS_TYPE_INT32, &agent_info.server_type, + DBUS_TYPE_INVALID); + + transfers = g_slist_remove(transfers, transfer_info); + __bt_free_transfer_info(transfer_info); + } + BT_DBG("-"); +} + static char *__bt_get_remote_device_name(const char *bdaddress) { char *device_path = NULL; @@ -221,6 +279,22 @@ static DBusGProxy *__bt_get_transfer_proxy(const char *transfer_path) proxy = dbus_g_proxy_new_for_name(conn, BT_OBEX_SERVICE_NAME, transfer_path, + BT_OBEX_TRANSFER_INTERFACE); + + return proxy; +} + +static DBusGProxy *__bt_get_transfer_properties_proxy(const char *transfer_path) +{ + DBusGConnection *conn; + DBusGProxy *proxy; + + conn = _bt_get_session_gconn(); + retv_if(conn == NULL, NULL); + + proxy = dbus_g_proxy_new_for_name(conn, + BT_OBEX_SERVICE_NAME, + transfer_path, BT_PROPERTIES_INTERFACE); return proxy; @@ -237,11 +311,10 @@ static int __bt_get_transfer_properties(bt_transfer_info_t *transfer_info, BT_CHECK_PARAMETER(transfer_info, return); BT_CHECK_PARAMETER(transfer_path, return); - transfer_proxy = __bt_get_transfer_proxy(transfer_path); + transfer_proxy = __bt_get_transfer_properties_proxy(transfer_path); retv_if(transfer_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - dbus_g_proxy_call(transfer_proxy, "GetAll", NULL, G_TYPE_STRING, BT_OBEX_TRANSFER_INTERFACE, G_TYPE_INVALID, @@ -259,6 +332,7 @@ static int __bt_get_transfer_properties(bt_transfer_info_t *transfer_info, goto fail; value = g_hash_table_lookup(hash, "Name"); + transfer_info->filename = value ? g_strdup(g_value_get_string(value)) : NULL; if (!transfer_info->filename) goto fail; @@ -273,6 +347,12 @@ static int __bt_get_transfer_properties(bt_transfer_info_t *transfer_info, bdaddress = value ? (char *)g_value_get_string(value) : NULL; if (!bdaddress) goto fail; + transfer_info->address = g_strdup(bdaddress); + + value = g_hash_table_lookup(hash, "Filename"); + transfer_info->file_path = value ? g_strdup(g_value_get_string(value)) : NULL; + if (!transfer_info->file_path) + transfer_info->file_path = g_strdup(transfer_info->filename); transfer_info->device_name = __bt_get_remote_device_name(bdaddress); if (!transfer_info->device_name) @@ -294,25 +374,25 @@ static gboolean __bt_authorize_cb(DBusGMethodInvocation *context, { char *device_name = NULL; int result = BLUETOOTH_ERROR_NONE; - DBusGProxy *transfer_proxy; + DBusGProxy *transfer_properties_proxy; GHashTable *hash = NULL; GValue *value; char * bdaddress = NULL; BT_DBG(" path [%s] \n", path); - transfer_proxy = __bt_get_transfer_proxy(path); + transfer_properties_proxy = __bt_get_transfer_properties_proxy(path); - retv_if(transfer_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + retv_if(transfer_properties_proxy == NULL, FALSE); - dbus_g_proxy_call(transfer_proxy, "GetAll", NULL, + dbus_g_proxy_call(transfer_properties_proxy, "GetAll", NULL, G_TYPE_STRING, BT_OBEX_TRANSFER_INTERFACE, G_TYPE_INVALID, dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), &hash, G_TYPE_INVALID); if (hash == NULL) { - g_object_unref(transfer_proxy); + g_object_unref(transfer_properties_proxy); return FALSE; } @@ -321,6 +401,7 @@ static gboolean __bt_authorize_cb(DBusGMethodInvocation *context, agent_info.auth_info = g_malloc(sizeof(bt_auth_info_t)); agent_info.auth_info->reply_context = context; + agent_info.auth_info->transfer_path = g_strdup(path); value = g_hash_table_lookup(hash, "Name"); @@ -331,6 +412,7 @@ static gboolean __bt_authorize_cb(DBusGMethodInvocation *context, value = g_hash_table_lookup(hash, "Address"); bdaddress = value ? (char *)g_value_get_string(value) : NULL; + agent_info.auth_info->address = g_strdup(bdaddress); device_name = __bt_get_remote_device_name(bdaddress); @@ -340,7 +422,7 @@ static gboolean __bt_authorize_cb(DBusGMethodInvocation *context, agent_info.auth_info->device_name = device_name; g_hash_table_destroy(hash); - g_object_unref(transfer_proxy); + g_object_unref(transfer_properties_proxy); if (agent_info.server_type == BT_CUSTOM_SERVER) { /* No need to send the event */ @@ -378,6 +460,8 @@ void _bt_obex_transfer_started(const char *transfer_path) transfer_info->path = g_strdup(agent_info.auth_info->transfer_path); transfer_info->device_name = g_strdup(agent_info.auth_info->device_name); transfer_info->transfer_id = __bt_get_transfer_id(transfer_path); + transfer_info->file_path = agent_info.auth_info->file_path; + transfer_info->address = g_strdup(agent_info.auth_info->address); } else { if (__bt_get_transfer_properties(transfer_info, transfer_path) < 0) { BT_ERR("Get Properties failed"); @@ -438,6 +522,7 @@ done: void _bt_obex_transfer_progress(const char *transfer_path, int transferred) { + BT_DBG("+"); bt_transfer_info_t *transfer_info; int progress = 0; int result = BLUETOOTH_ERROR_NONE; @@ -445,9 +530,6 @@ void _bt_obex_transfer_progress(const char *transfer_path, transfer_info = __bt_find_transfer_by_path(transfer_path); ret_if(transfer_info == NULL); - if (transfer_info->file_size <= 0) - return; - progress = (int)(((gdouble)transferred / (gdouble)transfer_info->file_size) * 100); @@ -461,11 +543,14 @@ void _bt_obex_transfer_progress(const char *transfer_path, DBUS_TYPE_INT32, &progress, DBUS_TYPE_INT32, &agent_info.server_type, DBUS_TYPE_INVALID); + + BT_DBG("-"); } void _bt_obex_transfer_completed(const char *transfer_path, gboolean success) { bt_transfer_info_t *transfer_info; + int result; BT_DBG("Transfer [%s] Success [%d] \n", transfer_path, success); @@ -473,7 +558,36 @@ void _bt_obex_transfer_completed(const char *transfer_path, gboolean success) : BLUETOOTH_ERROR_CANCEL; transfer_info = __bt_find_transfer_by_path(transfer_path); - ret_if(transfer_info == NULL); + + if (transfer_info == NULL) { + BT_DBG("Very small files receiving case, did not get Active status from obexd"); + if (agent_info.auth_info == NULL || + g_strcmp0(transfer_path, + agent_info.auth_info->transfer_path) != 0) { + BT_ERR("auth_info is NULL, returning"); + return; + } + + transfer_info = g_new0(bt_transfer_info_t, 1); + + transfer_info->filename = g_strdup(agent_info.auth_info->filename); + transfer_info->file_size = agent_info.auth_info->file_size; + transfer_info->type = g_strdup(TRANSFER_PUT); + transfer_info->path = g_strdup(agent_info.auth_info->transfer_path); + transfer_info->device_name = g_strdup(agent_info.auth_info->device_name); + transfer_info->transfer_id = __bt_get_transfer_id(transfer_path); + transfer_info->file_path = agent_info.auth_info->file_path; + + _bt_send_event(BT_OPP_SERVER_EVENT, + BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_STARTED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &transfer_info->filename, + DBUS_TYPE_STRING, &transfer_info->type, + DBUS_TYPE_UINT64, &transfer_info->file_size, + DBUS_TYPE_INT32, &transfer_info->transfer_id, + DBUS_TYPE_INT32, &agent_info.server_type, + DBUS_TYPE_INVALID); + } _bt_send_event(BT_OPP_SERVER_EVENT, BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_COMPLETED, @@ -481,6 +595,7 @@ void _bt_obex_transfer_completed(const char *transfer_path, gboolean success) DBUS_TYPE_STRING, &transfer_info->filename, DBUS_TYPE_STRING, &transfer_info->type, DBUS_TYPE_STRING, &transfer_info->device_name, + DBUS_TYPE_STRING, &transfer_info->file_path, DBUS_TYPE_UINT64, &transfer_info->file_size, DBUS_TYPE_INT32, &transfer_info->transfer_id, DBUS_TYPE_INT32, &agent_info.server_type, @@ -490,6 +605,34 @@ void _bt_obex_transfer_completed(const char *transfer_path, gboolean success) __bt_free_transfer_info(transfer_info); } +void _bt_obex_transfer_connected() +{ + BT_DBG("+"); + + int result = BLUETOOTH_ERROR_NONE; + + _bt_send_event(BT_OPP_SERVER_EVENT, + BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_CONNECTED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + + BT_DBG("-"); +} + +void _bt_obex_transfer_disconnected() +{ + BT_DBG("+"); + + int result = BLUETOOTH_ERROR_NONE; + + _bt_send_event(BT_OPP_SERVER_EVENT, + BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_DISCONNECTED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + + BT_DBG("-"); +} + int _bt_register_obex_server(void) { DBusGConnection *g_conn; @@ -568,7 +711,7 @@ gboolean __bt_check_folder_path(const char *dest_path) { DIR *dp; - retv_if(dest_path == NULL, TRUE); + retv_if(dest_path == NULL, FALSE); dp = opendir(dest_path); @@ -608,7 +751,7 @@ int _bt_obex_server_allocate(char *sender, const char *dest_path, int app_pid, g agent_info.custom_server->sender = g_strdup(sender); agent_info.custom_server->app_pid = app_pid; agent_info.server_type = BT_CUSTOM_SERVER; - _bt_register_osp_server_in_agent(BT_OBEX_SERVER, NULL); + _bt_register_osp_server_in_agent(BT_OBEX_SERVER, NULL, NULL, -1); } return BLUETOOTH_ERROR_NONE; @@ -630,7 +773,7 @@ int _bt_obex_server_deallocate(int app_pid, gboolean is_native) if (agent_info.custom_server) { agent_info.server_type = BT_CUSTOM_SERVER; _bt_register_osp_server_in_agent(BT_OBEX_SERVER, - NULL); + NULL, NULL, -1); } } else { retv_if(agent_info.custom_server == NULL, @@ -681,6 +824,7 @@ int _bt_obex_server_accept_authorize(const char *filename, gboolean is_native) file_path); agent_info.auth_info->reply_context = NULL; + agent_info.auth_info->file_path = g_strdup(file_path); return BLUETOOTH_ERROR_NONE; } @@ -709,11 +853,12 @@ int _bt_obex_server_reject_authorize(void) int _bt_obex_server_set_destination_path(const char *dest_path, gboolean is_native) { - DIR *dp = NULL; bt_server_info_t *server_info; BT_CHECK_PARAMETER(dest_path, return); + DIR *dp = NULL; + dp = opendir(dest_path); if (dp == NULL) { @@ -787,8 +932,7 @@ int _bt_obex_server_cancel_transfer(int transfer_id) retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); - dbus_g_proxy_call_no_reply(proxy, "Cancel", - G_TYPE_INVALID, G_TYPE_INVALID); + dbus_g_proxy_call_no_reply(proxy, "Cancel", G_TYPE_INVALID, G_TYPE_INVALID); g_object_unref(proxy); diff --git a/bt-service/bt-service-oob.c b/bt-service/bt-service-oob.c old mode 100644 new mode 100755 index e517701..d436b5d --- a/bt-service/bt-service-oob.c +++ b/bt-service/bt-service-oob.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -202,7 +206,7 @@ int _bt_oob_remove_remote_data( if (!reply) { BT_ERR("Error in RemoveRemoteData \n"); if (dbus_error_is_set(&err)) { - BT_DBG("%s", err.message); + BT_ERR("%s", err.message); dbus_error_free(&err); g_free(dev_addr); return BLUETOOTH_ERROR_INTERNAL; diff --git a/bt-service/bt-service-opp-client.c b/bt-service/bt-service-opp-client.c old mode 100644 new mode 100755 index 41d5583..4aec7b7 --- a/bt-service/bt-service-opp-client.c +++ b/bt-service/bt-service-opp-client.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -22,6 +26,7 @@ #include #include #include +#include #include "bluetooth-api.h" #include "bt-internal-types.h" @@ -35,12 +40,14 @@ static GSList *transfer_list = NULL; bt_sending_info_t *sending_info; +static int file_offset = 0; + +static gboolean __bt_sending_release(); +static void _bt_remove_session(); static int __bt_opp_client_start_sending(int request_id, char *address, char **file_name_array, int file_count); -static gboolean __bt_sending_release(); - static GQuark __bt_opc_error_quark(void) { static GQuark quark = 0; @@ -57,6 +64,10 @@ static void __bt_free_transfer_info(bt_transfer_info_t *info) if (info->proxy) g_object_unref(info->proxy); + if (info->properties_proxy) + g_object_unref(info->properties_proxy); + + g_free(info->transfer_name); g_free(info->file_name); g_free(info); @@ -70,6 +81,7 @@ static void __bt_free_sending_info(bt_sending_info_t *info) __bt_free_transfer_info(info->transfer_info); g_free(info->file_name_array); + g_free(info->address); g_free(info); } @@ -82,9 +94,12 @@ static void __bt_value_free(GValue *value) static gboolean __bt_cancel_push_cb(gpointer data) { + BT_DBG("+"); + int result = BLUETOOTH_ERROR_CANCEL_BY_USER; retv_if(sending_info == NULL, FALSE); + sending_info->result = result; /* Send the event in only error none case */ _bt_send_event(BT_OPP_CLIENT_EVENT, @@ -99,31 +114,34 @@ static gboolean __bt_cancel_push_cb(gpointer data) _bt_opp_client_event_deinit(); - /* Operate remain works */ + BT_DBG("Length of transfer list is %d", g_slist_length(transfer_list)); + + /*Operate remain works*/ if (g_slist_length(transfer_list) > 0) { bt_sending_data_t *node = NULL; node = transfer_list->data; if (node == NULL) { - BT_DBG("data is NULL"); + BT_ERR("data is NULL"); return FALSE; } transfer_list = g_slist_remove(transfer_list, node); if (__bt_opp_client_start_sending(node->request_id, - node->address, - node->file_path, + node->address, node->file_path, node->file_count) != BLUETOOTH_ERROR_NONE) { - BT_DBG("Fail to start sending"); + BT_ERR("Fail to start sending"); } } - + BT_DBG("-"); return FALSE; } -gboolean _bt_obex_client_progress(int transferred) +gboolean _bt_obex_client_progress(const char *transfer_path, int transferred) { + BT_DBG("+"); + int percentage_progress; gint64 size; int result = BLUETOOTH_ERROR_NONE; @@ -131,6 +149,12 @@ gboolean _bt_obex_client_progress(int transferred) retv_if(sending_info == NULL, TRUE); retv_if(sending_info->transfer_info == NULL, TRUE); + if (g_strcmp0(sending_info->transfer_info->transfer_path, + transfer_path) != 0) { + BT_INFO("Path mismatch, previous transfer failed! Returning"); + return FALSE; + } + size = sending_info->transfer_info->size; if (size != 0) @@ -139,6 +163,9 @@ gboolean _bt_obex_client_progress(int transferred) else percentage_progress = 0; + sending_info->transfer_info->transfer_status = BT_TRANSFER_STATUS_PROGRESS; + sending_info->result = result; + /* Send the event in only error none case */ _bt_send_event(BT_OPP_CLIENT_EVENT, BLUETOOTH_EVENT_OPC_TRANSFER_PROGRESS, @@ -149,40 +176,90 @@ gboolean _bt_obex_client_progress(int transferred) DBUS_TYPE_INT32, &sending_info->request_id, DBUS_TYPE_INVALID); + BT_DBG("-"); + return TRUE; } -gboolean _bt_obex_client_completed(gboolean success) +gboolean _bt_obex_client_completed(const char *transfer_path, gboolean success) { + BT_DBG("+"); + int result = BLUETOOTH_ERROR_NONE; - BT_DBG("Success [%d] \n", success); + retv_if(sending_info == NULL, TRUE); + retv_if(sending_info->transfer_info == NULL, TRUE); - result = (success == TRUE) ? BLUETOOTH_ERROR_NONE - : BLUETOOTH_ERROR_CANCEL; + if (g_strcmp0(sending_info->transfer_info->transfer_path, + transfer_path) != 0) { + BT_INFO("Path mismatch, previous transfer failed! Returning"); + return FALSE; + } - /* Send the event in only error none case */ - _bt_send_event(BT_OPP_CLIENT_EVENT, - BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &sending_info->transfer_info->file_name, - DBUS_TYPE_UINT64, &sending_info->transfer_info->size, - DBUS_TYPE_INT32, &sending_info->request_id, - DBUS_TYPE_INVALID); + result = (success == TRUE) ? BLUETOOTH_ERROR_NONE : BLUETOOTH_ERROR_CANCEL; + + sending_info->transfer_info->transfer_status = BT_TRANSFER_STATUS_COMPLETED; + sending_info->result = result; + + if (!success) { /*In case of remote device reject, we need to send BLUETOOTH_EVENT_OPC_DISCONNECTED */ + BT_DBG("completed with error"); + if (!sending_info->is_canceled) { + _bt_send_event(BT_OPP_CLIENT_EVENT, + BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &sending_info->transfer_info->file_name, + DBUS_TYPE_UINT64, &sending_info->transfer_info->size, + DBUS_TYPE_INT32, &sending_info->request_id, + DBUS_TYPE_INVALID); + + __bt_free_transfer_info(sending_info->transfer_info); + sending_info->transfer_info = NULL; + /* Reset the file offset as we will cancelled remaining files also */ + file_offset = 0; + } + + _bt_send_event(BT_OPP_CLIENT_EVENT, + BLUETOOTH_EVENT_OPC_DISCONNECTED, + DBUS_TYPE_INT32, &sending_info->result, + DBUS_TYPE_STRING, &sending_info->address, + DBUS_TYPE_INT32, &sending_info->request_id, + DBUS_TYPE_INVALID); + + __bt_sending_release(); + /* Sending info should not freed after sending_release it's + * already freed in that API and if any pending request is + * present then it recreate sending_info again. + * And if we free it here then CreateSession method call will + * made but RemoveSession method call will not done. + */ + } else { + BT_DBG("complete success"); + /* Send the event in only error none case */ + _bt_send_event(BT_OPP_CLIENT_EVENT, + BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &sending_info->transfer_info->file_name, + DBUS_TYPE_UINT64, &sending_info->transfer_info->size, + DBUS_TYPE_INT32, &sending_info->request_id, + DBUS_TYPE_INVALID); + + __bt_free_transfer_info(sending_info->transfer_info); + sending_info->transfer_info = NULL; + } + + BT_DBG("-"); return TRUE; } gboolean _bt_obex_client_started(const char *transfer_path) { - GValue *value; - const char *transfer_name; - const char *file_name; - int size; + BT_DBG("+"); + int result = BLUETOOTH_ERROR_NONE; - GHashTable *hash = NULL; GError *error; DBusGConnection *g_conn; + DBusGProxy *properties_proxy; DBusGProxy *transfer_proxy; if (sending_info == NULL || sending_info->is_canceled == TRUE) { @@ -192,44 +269,24 @@ gboolean _bt_obex_client_started(const char *transfer_path) /* Get the session bus. */ g_conn = _bt_get_session_gconn(); - retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL); + retv_if(g_conn == NULL, FALSE); - __bt_free_transfer_info(sending_info->transfer_info); + properties_proxy = dbus_g_proxy_new_for_name(g_conn, BT_OBEXD_DBUS_NAME, + transfer_path, BT_PROPERTIES_INTERFACE); - sending_info->transfer_info = g_malloc0(sizeof(bt_transfer_info_t)); + retv_if(properties_proxy == NULL, FALSE); + + sending_info->transfer_info->properties_proxy = properties_proxy; transfer_proxy = dbus_g_proxy_new_for_name(g_conn, BT_OBEXD_DBUS_NAME, - transfer_path, BT_PROPERTIES_INTERFACE); + transfer_path, BT_OBEX_TRANSFER_INTERFACE); retv_if(transfer_proxy == NULL, FALSE); sending_info->transfer_info->proxy = transfer_proxy; - if (!dbus_g_proxy_call(transfer_proxy, "GetAll", NULL, - G_TYPE_STRING, BT_OBEX_TRANSFER_INTERFACE, - G_TYPE_INVALID, - dbus_g_type_get_map("GHashTable", G_TYPE_STRING, - G_TYPE_VALUE), &hash, G_TYPE_INVALID)) - goto fail; - - if (hash == NULL) - goto fail; - - value = g_hash_table_lookup(hash, "Name"); - transfer_name = value ? g_value_get_string(value) : NULL; - - value = g_hash_table_lookup(hash, "Filename"); - file_name = value ? g_value_get_string(value) : NULL; - - value = g_hash_table_lookup(hash, "Size"); - size = value ? g_value_get_uint64(value) : 0; - - sending_info->transfer_info->transfer_name = g_strdup(transfer_name); - sending_info->transfer_info->file_name = g_strdup(file_name); - sending_info->transfer_info->size = size; - sending_info->result = BLUETOOTH_ERROR_NONE; - - g_hash_table_destroy(hash); + sending_info->transfer_info->transfer_status = BT_TRANSFER_STATUS_STARTED; + sending_info->result = result; _bt_send_event(BT_OPP_CLIENT_EVENT, BLUETOOTH_EVENT_OPC_TRANSFER_STARTED, @@ -239,6 +296,7 @@ gboolean _bt_obex_client_started(const char *transfer_path) DBUS_TYPE_INT32, &sending_info->request_id, DBUS_TYPE_INVALID); + BT_DBG("-"); return TRUE; canceled: error = g_error_new(__bt_opc_error_quark(), BT_OBEX_AGENT_ERROR_CANCEL, @@ -246,24 +304,8 @@ canceled: g_error_free(error); + BT_DBG("-"); return FALSE; -fail: - result = BLUETOOTH_ERROR_INTERNAL; - - /* Send the event in only error none case */ - _bt_send_event(BT_OPP_CLIENT_EVENT, - BLUETOOTH_EVENT_OPC_DISCONNECTED, - DBUS_TYPE_INT32, &result, - DBUS_TYPE_STRING, &sending_info->address, - DBUS_TYPE_INT32, &sending_info->request_id, - DBUS_TYPE_INVALID); - - __bt_free_sending_info(sending_info); - sending_info = NULL; - - _bt_opp_client_event_deinit(); - - return TRUE; } static void __bt_free_sending_data(gpointer data) @@ -284,66 +326,136 @@ static void __bt_free_sending_data(gpointer data) g_free(info); } -static void __bt_send_files_cb(DBusGProxy *proxy, DBusGProxyCall *call, - void *user_data) +static void __bt_sending_release_cb(DBusGProxy *proxy, DBusGProxyCall *call, + void *user_data) { + BT_DBG("+"); + ret_if(sending_info == NULL); + GError *error = NULL; int result = BLUETOOTH_ERROR_NONE; if (dbus_g_proxy_end_call(proxy, call, &error, - G_TYPE_INVALID) == FALSE) { - + G_TYPE_INVALID) == FALSE) { BT_ERR("%s", error->message); g_error_free(error); result = BLUETOOTH_ERROR_INTERNAL; + } else { + file_offset = 0; + BT_DBG("Session Removed"); } - g_object_unref(proxy); - ret_if(sending_info == NULL); - - sending_info->sending_proxy = NULL; - + sending_info->result = result; /* Send the event in only error none case */ _bt_send_event(BT_OPP_CLIENT_EVENT, - BLUETOOTH_EVENT_OPC_CONNECTED, - DBUS_TYPE_INT32, &result, + BLUETOOTH_EVENT_OPC_DISCONNECTED, + DBUS_TYPE_INT32, &sending_info->result, DBUS_TYPE_STRING, &sending_info->address, DBUS_TYPE_INT32, &sending_info->request_id, DBUS_TYPE_INVALID); - if (result != BLUETOOTH_ERROR_NONE) { - __bt_free_sending_info(sending_info); - sending_info = NULL; + __bt_free_sending_info(sending_info); + sending_info = NULL; + + _bt_opp_client_event_deinit(); + + /* Operate remain works */ + if (g_slist_length(transfer_list) > 0) { + bt_sending_data_t *data = NULL; + + data = transfer_list->data; + if (data == NULL) + goto fail; + + transfer_list = g_slist_remove(transfer_list, data); + + BT_DBG("calling __bt_opp_client_start_sending"); + + if (__bt_opp_client_start_sending(data->request_id, + data->address, data->file_path, + data->file_count) != BLUETOOTH_ERROR_NONE) { + goto fail; + } } + + return; +fail: + g_slist_free_full(transfer_list, + (GDestroyNotify)__bt_free_sending_data); + transfer_list = NULL; + + BT_DBG("-"); + + return; } static void _bt_remove_session() { DBusGConnection *g_conn; DBusGProxy *session_proxy; + DBusGProxyCall *proxy_call; g_conn = _bt_get_session_gconn(); ret_if(g_conn == NULL); session_proxy = dbus_g_proxy_new_for_name(g_conn, BT_OBEXD_DBUS_NAME, - BT_OBEX_CLIENT_PATH, BT_OBEX_CLIENT_INTERFACE); + BT_OBEX_CLIENT_PATH, + BT_OBEX_CLIENT_INTERFACE); ret_if(session_proxy == NULL); - dbus_g_proxy_call(session_proxy, "RemoveSession", - NULL, DBUS_TYPE_G_OBJECT_PATH, sending_info->session_path, + proxy_call = dbus_g_proxy_begin_call(session_proxy, "RemoveSession", + __bt_sending_release_cb, NULL, NULL, + DBUS_TYPE_G_OBJECT_PATH, sending_info->session_path, G_TYPE_INVALID); + if (proxy_call == NULL) { + BT_ERR("Fail to Remove session"); + g_object_unref(session_proxy); + } } static gboolean __bt_sending_release() { + BT_DBG("+"); + retv_if(sending_info == NULL, FALSE); _bt_remove_session(); + BT_DBG("-"); + return TRUE; +} + +void _bt_opc_disconnected(const char *session_path) +{ + BT_DBG("+"); + + ret_if(sending_info == NULL); + + if (g_strcmp0(sending_info->session_path, + session_path) != 0) { + BT_INFO("Path mismatch, previous transfer failed! Returning"); + return; + } + + if (sending_info->transfer_info) { + BT_INFO("sending_info is not NULL"); + if (sending_info->transfer_info->transfer_status == BT_TRANSFER_STATUS_PROGRESS || + sending_info->transfer_info->transfer_status == BT_TRANSFER_STATUS_STARTED) { + BT_INFO("Abnormal termination"); + + _bt_send_event(BT_OPP_CLIENT_EVENT, + BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE, + DBUS_TYPE_INT32, &sending_info->result, + DBUS_TYPE_STRING, &sending_info->transfer_info->file_name, + DBUS_TYPE_UINT64, &sending_info->transfer_info->size, + DBUS_TYPE_INT32, &sending_info->request_id, + DBUS_TYPE_INVALID); + __bt_free_transfer_info(sending_info->transfer_info); + } + } - /* Send the event in only error none case */ _bt_send_event(BT_OPP_CLIENT_EVENT, BLUETOOTH_EVENT_OPC_DISCONNECTED, DBUS_TYPE_INT32, &sending_info->result, @@ -351,44 +463,29 @@ static gboolean __bt_sending_release() DBUS_TYPE_INT32, &sending_info->request_id, DBUS_TYPE_INVALID); + __bt_free_sending_info(sending_info); sending_info = NULL; - _bt_opp_client_event_deinit(); - - /* Operate remain works */ - if (g_slist_length(transfer_list) > 0) { - bt_sending_data_t *data = NULL; - - data = transfer_list->data; - if (data == NULL) - goto fail; - - transfer_list = g_slist_remove(transfer_list, data); - - if (__bt_opp_client_start_sending(data->request_id, - data->address, - data->file_path, - data->file_count) != BLUETOOTH_ERROR_NONE) { - goto fail; - } - } - - return TRUE; -fail: - g_slist_free_full(transfer_list, - (GDestroyNotify)__bt_free_sending_data); - transfer_list = NULL; - return TRUE; + BT_DBG("-"); } -void _bt_sending_files() +void _bt_sending_files(void) { + BT_DBG("+"); + DBusGConnection *g_conn; DBusGProxy *client_proxy; - static int file_offset = 0; + GError *err = NULL; + char *path = NULL; + GHashTable *hash = NULL; + GValue *value = NULL; + const char *transfer_name; + const char *file_name; + int size; + char *mimetype = NULL; + char *ext = NULL; - BT_DBG("+"); if (sending_info == NULL) return; @@ -405,10 +502,54 @@ void _bt_sending_files() ret_if(client_proxy == NULL); - dbus_g_proxy_call(client_proxy, "SendFile",NULL, + BT_DBG("Calling SendFile"); + ext = strrchr(sending_info->file_name_array[file_offset], '.'); + + if(!strcmp(ext+1, "imy")) + mimetype = g_strdup("audio/imelody"); + + if (!dbus_g_proxy_call(client_proxy, "SendFile", &err, G_TYPE_STRING, sending_info->file_name_array[file_offset], - G_TYPE_INVALID); + G_TYPE_STRING, mimetype, + G_TYPE_INVALID, DBUS_TYPE_G_OBJECT_PATH, &path, + dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), + &hash, G_TYPE_INVALID)) { + if (err != NULL) { + BT_ERR("Calling SendFile failed: [%s]\n", err->message); + g_error_free(err); + } + g_free(mimetype); + return; + } + + g_free(mimetype); + + if (hash == NULL) + return; + + __bt_free_transfer_info(sending_info->transfer_info); + + sending_info->transfer_info = g_malloc0(sizeof(bt_transfer_info_t)); + + value = g_hash_table_lookup(hash, "Name"); + transfer_name = value ? g_value_get_string(value) : NULL; + + value = g_hash_table_lookup(hash, "Filename"); + file_name = value ? g_value_get_string(value) : NULL; + + value = g_hash_table_lookup(hash, "Size"); + size = value ? g_value_get_uint64(value) : 0; + + sending_info->transfer_info->transfer_name = g_strdup(transfer_name); + sending_info->transfer_info->file_name = g_strdup(file_name); + sending_info->transfer_info->size = size; + sending_info->transfer_info->transfer_path = path; + sending_info->transfer_info->transfer_status = BT_TRANSFER_STATUS_QUEUED; + sending_info->result = BLUETOOTH_ERROR_NONE; + + g_hash_table_destroy(hash); + file_offset++; }else{ file_offset = 0; @@ -421,6 +562,8 @@ void _bt_sending_files() static void __bt_create_session_cb(DBusGProxy *proxy, DBusGProxyCall *call, void *user_data) { + BT_DBG("+"); + GError *error = NULL; int result = BLUETOOTH_ERROR_NONE; char *session_path = NULL; @@ -433,13 +576,16 @@ static void __bt_create_session_cb(DBusGProxy *proxy, DBusGProxyCall *call, result = BLUETOOTH_ERROR_INTERNAL; }else{ - sending_info->session_path = g_strdup(session_path); - } - + BT_DBG("Session created"); + if(sending_info != NULL) + sending_info->session_path = g_strdup(session_path); +} + g_free(session_path); g_object_unref(proxy); ret_if(sending_info == NULL); sending_info->sending_proxy = NULL; + sending_info->result = result; /* Send the event in only error none case */ _bt_send_event(BT_OPP_CLIENT_EVENT, @@ -450,21 +596,30 @@ static void __bt_create_session_cb(DBusGProxy *proxy, DBusGProxyCall *call, DBUS_TYPE_INVALID); if (result != BLUETOOTH_ERROR_NONE) { + BT_ERR("Calling __bt_sending_release"); + __bt_sending_release(); + __bt_free_sending_info(sending_info); sending_info = NULL; }else { + BT_DBG("Calling sending_files"); _bt_sending_files(); } + BT_DBG("-"); + } static int __bt_opp_client_start_sending(int request_id, char *address, char **file_name_array, int file_count) { + BT_DBG("+"); + GHashTable *hash; GValue *value; DBusGConnection *g_conn; DBusGProxy *client_proxy; DBusGProxyCall *proxy_call; + int i; BT_CHECK_PARAMETER(address, return); @@ -479,19 +634,24 @@ static int __bt_opp_client_start_sending(int request_id, char *address, retv_if(client_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + BT_DBG("client_proxy is not NULL"); + hash = g_hash_table_new_full(g_str_hash, g_str_equal, - NULL, (GDestroyNotify)__bt_value_free); + NULL, (GDestroyNotify)__bt_value_free); value = g_new0(GValue, 1); g_value_init(value, G_TYPE_STRING); + g_value_set_string(value, "OPP"); g_hash_table_insert(hash, "Target", value); + BT_DBG("Hash Table success"); __bt_free_sending_info(sending_info); sending_info = g_malloc0(sizeof(bt_sending_info_t)); sending_info->address = g_strdup(address); sending_info->request_id = request_id; + sending_info->file_count = file_count; sending_info->file_offset = 0; sending_info->file_name_array = g_new0(char *, file_count + 1); @@ -503,6 +663,9 @@ static int __bt_opp_client_start_sending(int request_id, char *address, _bt_opp_client_event_deinit(); _bt_opp_client_event_init(); + //_bt_obex_client_started(agent_path); + + BT_DBG("Going to call CreateSession"); proxy_call = dbus_g_proxy_begin_call(client_proxy, "CreateSession", __bt_create_session_cb, NULL, NULL, @@ -520,20 +683,28 @@ static int __bt_opp_client_start_sending(int request_id, char *address, return BLUETOOTH_ERROR_INTERNAL; } + BT_DBG("After CreateSession"); + sending_info->sending_proxy = proxy_call; g_hash_table_destroy(hash); + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; } + int _bt_opp_client_push_files(int request_id, DBusGMethodInvocation *context, bluetooth_device_address_t *remote_address, char **file_path, int file_count) { + BT_DBG("+"); char address[BT_ADDRESS_STRING_SIZE] = { 0 }; bt_sending_data_t *data; + GArray *out_param1 = NULL; GArray *out_param2 = NULL; + int result = BLUETOOTH_ERROR_NONE; int i; @@ -545,7 +716,9 @@ int _bt_opp_client_push_files(int request_id, DBusGMethodInvocation *context, if (sending_info == NULL) { result = __bt_opp_client_start_sending(request_id, - address, file_path, file_count); + address, file_path, file_count); + if (result != BLUETOOTH_ERROR_NONE) + return result; } else { /* Insert data in the queue */ data = g_malloc0(sizeof(bt_sending_data_t)); @@ -556,7 +729,7 @@ int _bt_opp_client_push_files(int request_id, DBusGMethodInvocation *context, for (i = 0; i < file_count; i++) { data->file_path[i] = g_strdup(file_path[i]); - BT_DBG("file[%d]: %s", i, data->file_path[i]); + DBG_SECURE("file[%d]: %s", i, data->file_path[i]); } transfer_list = g_slist_append(transfer_list, data); @@ -574,22 +747,43 @@ int _bt_opp_client_push_files(int request_id, DBusGMethodInvocation *context, g_array_free(out_param1, TRUE); g_array_free(out_param2, TRUE); + BT_DBG("-"); + return result; } int _bt_opp_client_cancel_push(void) { + BT_DBG("+"); + DBusGConnection *g_conn; DBusGProxy *client_proxy; + int result = BLUETOOTH_ERROR_CANCEL_BY_USER; retv_if(sending_info == NULL, BLUETOOTH_ERROR_NOT_IN_OPERATION); sending_info->is_canceled = TRUE; + sending_info->result = result; if (sending_info->transfer_info) { + BT_DBG("calling cancel in Bluez"); dbus_g_proxy_call_no_reply(sending_info->transfer_info->proxy, "Cancel", G_TYPE_INVALID, G_TYPE_INVALID); + + _bt_send_event(BT_OPP_CLIENT_EVENT, + BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &sending_info->transfer_info->file_name, + DBUS_TYPE_UINT64, &sending_info->transfer_info->size, + DBUS_TYPE_INT32, &sending_info->request_id, + DBUS_TYPE_INVALID); + + if (result == BLUETOOTH_ERROR_CANCEL_BY_USER) { + BT_ERR("result is not BLUETOOTH_ERROR_NONE"); + __bt_sending_release(); + file_offset = 0; + } } else { retv_if(sending_info->sending_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); @@ -599,7 +793,6 @@ int _bt_opp_client_cancel_push(void) client_proxy = dbus_g_proxy_new_for_name(g_conn, BT_OBEX_SERVICE_NAME, BT_OBEX_CLIENT_PATH, BT_OBEX_CLIENT_INTERFACE); - retv_if(client_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); dbus_g_proxy_cancel_call(client_proxy, @@ -608,11 +801,14 @@ int _bt_opp_client_cancel_push(void) g_idle_add(__bt_cancel_push_cb, NULL); } + BT_DBG("-"); + return BLUETOOTH_ERROR_NONE; } int _bt_opp_client_cancel_all_transfers(void) { + BT_DBG("+"); if (transfer_list) { g_slist_free_full(transfer_list, (GDestroyNotify)__bt_free_sending_data); @@ -621,7 +817,7 @@ int _bt_opp_client_cancel_all_transfers(void) } _bt_opp_client_cancel_push(); - + BT_DBG("-"); return BLUETOOTH_ERROR_NONE; } @@ -633,3 +829,44 @@ int _bt_opp_client_is_sending(gboolean *sending) return BLUETOOTH_ERROR_NONE; } + +void _bt_opp_client_check_pending_transfer(const char *address) +{ + BT_DBG("+"); + + int result = BLUETOOTH_ERROR_CANCEL; + + ret_if(sending_info == NULL); + ret_if(sending_info->transfer_info == NULL); + + if (g_strcmp0(sending_info->address, address) == 0) { + BT_INFO("Address Match.Cancel current transfer"); + sending_info->transfer_info->transfer_status = BT_TRANSFER_STATUS_COMPLETED; + sending_info->result = result; + + if (!sending_info->is_canceled) { + _bt_send_event(BT_OPP_CLIENT_EVENT, + BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &sending_info->transfer_info->file_name, + DBUS_TYPE_UINT64, &sending_info->transfer_info->size, + DBUS_TYPE_INT32, &sending_info->request_id, + DBUS_TYPE_INVALID); + + __bt_free_transfer_info(sending_info->transfer_info); + sending_info->transfer_info = NULL; + /* Reset the file offset as we will cancelled remaining files also */ + file_offset = 0; + } + + _bt_send_event(BT_OPP_CLIENT_EVENT, + BLUETOOTH_EVENT_OPC_DISCONNECTED, + DBUS_TYPE_INT32, &sending_info->result, + DBUS_TYPE_STRING, &sending_info->address, + DBUS_TYPE_INT32, &sending_info->request_id, + DBUS_TYPE_INVALID); + + __bt_sending_release(); + } + BT_DBG("-"); +} diff --git a/bt-service/bt-service-pbap.c b/bt-service/bt-service-pbap.c new file mode 100755 index 0000000..8b22924 --- /dev/null +++ b/bt-service/bt-service-pbap.c @@ -0,0 +1,1321 @@ +/* + + * Bluetooth-frwk + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * 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 +#include +#include +#include +#include +#include +#include + +#include "bt-internal-types.h" +#include "bt-service-common.h" +//#include "bt-service-agent.h" +//#include "bt-service-gap-agent.h" +//#include "bt-service-adapter.h" +#include "bt-service-event.h" +//#include "bt-service-rfcomm-server.h" +//#include "bt-service-device.h" +//#include "bt-service-audio.h" +#include "bt-service-pbap.h" +#include +#include + +#define PBAP_UUID "0000112f-0000-1000-8000-00805f9b34fb" +#define PBAP_OBEX_CLIENT_SERVICE "org.bluez.obex" +#define PBAP_OBEX_CLIENT_PATH "/org/bluez/obex" +#define PBAP_OBEX_CLIENT_INTERFACE "org.bluez.obex.Client1" + +#define PBAP_SESSION_SERVICE "org.bluez.obex" +#define PBAP_SESSION_INTERFACE "org.bluez.obex.PhonebookAccess1" +#define PBAP_VCARDLIST_MAXLENGTH 256 + +typedef enum { +PBAP_FIELD_ALL, +PBAP_FIELD_VERSION, +PBAP_FIELD_FN, +PBAP_FIELD_N, +PBAP_FIELD_PHOTO, +PBAP_FIELD_BDAY, +PBAP_FIELD_ADR, +PBAP_FIELD_LABEL, +PBAP_FIELD_TEL, +PBAP_FIELD_EMAIL, +PBAP_FIELD_MAILER, +PBAP_FIELD_TZ, +PBAP_FIELD_GEO, +PBAP_FIELD_TITLE, +PBAP_FIELD_ROLE, +PBAP_FIELD_LOGO, +PBAP_FIELD_AGENT, +PBAP_FIELD_ORG, +PBAP_FIELD_NOTE, +PBAP_FIELD_REV, +PBAP_FIELD_SOUND, +PBAP_FIELD_URL, +PBAP_FIELD_UID, +PBAP_FIELD_KEY, +PBAP_FIELD_NICKNAME, +PBAP_FIELD_CATEGORIES, +PBAP_FIELD_PROID, +PBAP_FIELD_CLASS, +PBAP_FIELD_SORT_STRING, +PBAP_FIELD_X_IRMC_CALL_DATETIME, +} bt_pbap_field_e; + +char *SOURCE[] = { + "int", //Phone memory + "sim" // SIM memory +}; + +char *TYPE[] = { + "pb", //Phonebook for the saved contacts + "ich", //Incoming call history + "och", //Outgoing call history + "mch", //Missed call history + "cch", //Combined Call History cch = ich + och + mch +}; + +char *FORMAT[] = { + "vcard21", // vCard Format 2.1 (Default) + "vcard30", // vCard Format 3.0 +}; + +char *ORDER[] = { + "indexed", // Index (default) + "alphanumeric", // Alphanumeric + "phonetic", // Phonetic +}; + +char *SEARCH_FIELD[] = { + "name", // Search by Name(default) + "number", // Search by Phone Number + "sound", // Search by phonetic sound +}; + +static char *g_pbap_session_path = NULL; +static DBusGConnection *dbus_connection = NULL; +static DBusGProxy *g_pbap_proxy = NULL; + +static struct { + int type; + int folder; +} selected_path = { -1, -1}; + +typedef enum { + PBAP_NONE, + GET_SIZE, + PULL_ALL, + GET_LIST, + GET_VCARD, + PB_SEARCH, +} bt_pbap_operation_e; + +typedef struct { + bt_pbap_operation_e operation; + void *data; + void *app_param; +} bt_pbap_data_t; + +typedef struct { + char *path; + char *filename; + char *remote_device; + bt_pbap_operation_e operation; +} bt_pbap_transfer_info_t; + +static GSList *transfers; + +int __bt_pbap_call_get_phonebook_size(DBusGProxy *proxy, bt_pbap_data_t *pbap_data); +int __bt_pbap_call_get_phonebook(DBusGProxy *proxy, bt_pbap_data_t *pbap_data); +int __bt_pbap_call_get_vcards_list(DBusGProxy *proxy, bt_pbap_data_t *pbap_data); +int __bt_pbap_call_get_vcard(DBusGProxy *proxy, bt_pbap_data_t *pbap_data); +int __bt_pbap_call_search_phonebook(DBusGProxy *proxy, bt_pbap_data_t *pbap_data); + +static void __bt_pbap_free_data(bt_pbap_data_t *pbap_data) +{ + g_free(pbap_data->app_param); + g_free(pbap_data->data); + g_free(pbap_data); +} + +static bt_pbap_transfer_info_t *__bt_find_transfer_by_path(const char *transfer_path) +{ + GSList *l; + bt_pbap_transfer_info_t *transfer; + + retv_if(transfer_path == NULL, NULL); + + for (l = transfers; l != NULL; l = l->next) { + transfer = l->data; + + if (transfer == NULL) + continue; + + if (g_strcmp0(transfer->path, transfer_path) == 0) + return transfer; + } + + return NULL; +} + +static void __bt_free_transfer_info(bt_pbap_transfer_info_t *transfer_info) +{ + ret_if(transfer_info == NULL); + + g_free(transfer_info->path); + g_free(transfer_info->filename); + g_free(transfer_info->remote_device); + g_free(transfer_info); +} + +void _bt_pbap_obex_transfer_completed(const char *transfer_path, gboolean transfer_status) +{ + bt_pbap_transfer_info_t *transfer_info; + int result = 0; + int success = transfer_status; + BT_DBG("Transfer [%s] Success [%d] \n", transfer_path, success); + + result = (success == TRUE) ? BLUETOOTH_ERROR_NONE + : BLUETOOTH_ERROR_CANCEL; + + transfer_info = __bt_find_transfer_by_path(transfer_path); + ret_if(transfer_info == NULL); + + BT_DBG("Remote Device [%s] FileName: [%s] Operation[%d]", + transfer_info->remote_device, transfer_info->filename, + transfer_info->operation); + + switch(transfer_info->operation) { + case PULL_ALL: { + _bt_send_event(BT_PBAP_CLIENT_EVENT, + BLUETOOTH_PBAP_PHONEBOOK_PULL, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &transfer_info->remote_device, + DBUS_TYPE_STRING, &transfer_info->filename, + DBUS_TYPE_INT32, &success, + DBUS_TYPE_INVALID); + break; + } + case GET_VCARD: { + _bt_send_event(BT_PBAP_CLIENT_EVENT, + BLUETOOTH_PBAP_VCARD_PULL, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &transfer_info->remote_device, + DBUS_TYPE_STRING, &transfer_info->filename, + DBUS_TYPE_INT32, &success, + DBUS_TYPE_INVALID); + break; + } + default: + BT_INFO("Case not handled"); + break; + + } + transfers = g_slist_remove(transfers, transfer_info); + __bt_free_transfer_info(transfer_info); +} + +void __bt_pbap_connect_cb(DBusGProxy *proxy, + DBusGProxyCall *call, void *user_data) +{ + char *session_path = NULL; + char *address_string = user_data; + GError *g_error = NULL; + int connected = -1; + int result = BLUETOOTH_ERROR_CANCEL; + + BT_DBG("Address = %s", address_string); + if (!dbus_g_proxy_end_call(proxy, call, &g_error, + DBUS_TYPE_G_OBJECT_PATH, &session_path, + G_TYPE_INVALID)) { + BT_ERR("Error Code[%d]: Message %s \n", g_error->code, g_error->message); + g_error_free(g_error); + } else { + g_pbap_session_path = g_strdup(session_path); + BT_DBG("Session Path = %s\n", g_pbap_session_path); + result = BLUETOOTH_ERROR_NONE; + connected = 1; + } + + _bt_send_event(BT_PBAP_CLIENT_EVENT, + BLUETOOTH_PBAP_CONNECTED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address_string, + DBUS_TYPE_INT32, &connected, + DBUS_TYPE_INVALID); + + g_free(address_string); + g_free(session_path); + BT_DBG("-"); +} + +int _bt_pbap_connect(const bluetooth_device_address_t *address) +{ + BT_DBG("+"); + GHashTable *hash; + GValue *tgt_value; + GError *error = NULL; + char address_string[18] = { 0, }; + char *ptr = NULL; + + BT_CHECK_PARAMETER(address, return); + + /* check if already connected */ + if (g_pbap_session_path) + return BLUETOOTH_ERROR_ALREADY_CONNECT; + + BT_DBG("BD Address [%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X]", + address->addr[0], address->addr[1], + address->addr[2], address->addr[3], + address->addr[4], address->addr[5]); + + _bt_convert_addr_type_to_string(address_string, (unsigned char *)address->addr); + BT_DBG("Address String: %s", address_string); + dbus_connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error); + if (error != NULL) { + BT_ERR("Couldn't connect to system bus[%s]\n", error->message); + g_error_free(error); + return EXIT_FAILURE; + } + BT_DBG("#2"); + g_pbap_proxy = dbus_g_proxy_new_for_name(dbus_connection, + PBAP_OBEX_CLIENT_SERVICE, + PBAP_OBEX_CLIENT_PATH, + PBAP_OBEX_CLIENT_INTERFACE); + if (!g_pbap_proxy) { + BT_ERR("Failed to get a proxy for D-Bus\n"); + return -1; + } + BT_DBG("#3"); + hash = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, (GDestroyNotify)g_free); + BT_DBG("#4"); + tgt_value = g_new0(GValue, 1); + g_value_init(tgt_value, G_TYPE_STRING); + g_value_set_string(tgt_value, "pbap"); + g_hash_table_insert(hash, "Target", tgt_value); + BT_DBG("#5"); + + ptr = g_strdup(address_string); + if (!dbus_g_proxy_begin_call(g_pbap_proxy, "CreateSession", + (DBusGProxyCallNotify)__bt_pbap_connect_cb, + ptr, NULL, + G_TYPE_STRING, ptr, + dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), + hash, G_TYPE_INVALID)) { + BT_ERR("Connect Dbus Call Error"); + g_free(ptr); + g_object_unref(g_pbap_proxy); + g_hash_table_destroy(hash); + return BLUETOOTH_ERROR_INTERNAL; + } + + g_hash_table_destroy(hash); + + BT_DBG("-"); + return 0; +} + +void __bt_pbap_disconnect_cb(DBusGProxy *proxy, + DBusGProxyCall *call, void *user_data) +{ + char *address_string = user_data; + GError *g_error = NULL; + int connected = -1; + int result = BLUETOOTH_ERROR_INTERNAL ; + + BT_DBG("Address = %s", address_string); + if (!dbus_g_proxy_end_call(proxy, call, &g_error, G_TYPE_INVALID)) { + BT_ERR("Error Code[%d]: Message %s \n", g_error->code, g_error->message); + g_error_free(g_error); + } else { + g_free(g_pbap_session_path); + g_pbap_session_path = NULL; + result = BLUETOOTH_ERROR_NONE; + selected_path.folder = -1; + selected_path.type = -1; + connected = 0; + } + + g_object_unref(proxy); + _bt_send_event(BT_PBAP_CLIENT_EVENT, + BLUETOOTH_PBAP_CONNECTED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address_string, + DBUS_TYPE_INT32, &connected, + DBUS_TYPE_INVALID); + + g_free(address_string); + BT_DBG("-"); +} + +int _bt_pbap_disconnect(const bluetooth_device_address_t *address) +{ + BT_DBG("+"); + char address_string[18] = { 0, }; + char *ptr = NULL; + BT_CHECK_PARAMETER(address, return); + + /* check if connected */ + if (g_pbap_session_path == NULL) + return BLUETOOTH_ERROR_NOT_CONNECTED; + + BT_DBG("BD Address [%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X]", + address->addr[0], address->addr[1], + address->addr[2], address->addr[3], + address->addr[4], address->addr[5]); + + _bt_convert_addr_type_to_string(address_string, (unsigned char *)address->addr); + BT_DBG("Address String: %s", address_string); + BT_DBG("Session Path: %s", g_pbap_session_path); + + ptr = g_strdup(address_string); + if (!dbus_g_proxy_begin_call(g_pbap_proxy, "RemoveSession", + (DBusGProxyCallNotify)__bt_pbap_disconnect_cb, + ptr, NULL, + DBUS_TYPE_G_OBJECT_PATH, g_pbap_session_path, + G_TYPE_INVALID)) { + g_free(ptr); + BT_ERR("Disconnect Dbus Call Error"); + return BLUETOOTH_ERROR_INTERNAL; + } + + return 0; +} + +void __bt_pbap_select_cb(DBusGProxy *proxy, + DBusGProxyCall *call, void *user_data) +{ + BT_DBG("+"); + GError *g_error = NULL; + bt_pbap_data_t *pbap_data = user_data; + char *address_string = pbap_data->data; + + BT_DBG("Address = %s", address_string); + if (dbus_g_proxy_end_call(proxy, call, &g_error, G_TYPE_INVALID)) { + switch (pbap_data->operation) { + case GET_SIZE: { + __bt_pbap_call_get_phonebook_size(proxy, pbap_data); + break; + } + case PULL_ALL: { + __bt_pbap_call_get_phonebook(proxy, pbap_data); + break; + } + case GET_LIST: { + __bt_pbap_call_get_vcards_list(proxy, pbap_data); + break; + } + case GET_VCARD: { + __bt_pbap_call_get_vcard(proxy, pbap_data); + break; + } + case PB_SEARCH: { + __bt_pbap_call_search_phonebook(proxy, pbap_data); + break; + } + default: { + g_object_unref(proxy); + __bt_pbap_free_data(pbap_data); + } + } // End of Case + } else { + g_object_unref(proxy); + __bt_pbap_free_data(pbap_data); + } + + BT_DBG("-"); +} + + +void __bt_pbap_get_phonebook_size_cb(DBusGProxy *proxy, + DBusGProxyCall *call, void *user_data) +{ + BT_DBG("+"); + GError *g_error = NULL; + int result = BLUETOOTH_ERROR_INTERNAL; + bt_pbap_data_t *pbap_data = user_data; + char *address_string = pbap_data->data; + unsigned int size = 0; + + BT_DBG("Address = %s", address_string); + if (!dbus_g_proxy_end_call(proxy, call, &g_error, + G_TYPE_UINT, &size, + G_TYPE_INVALID)) { + BT_ERR("Error Code[%d]: Message %s \n", g_error->code, g_error->message); + g_error_free(g_error); + } else { + BT_ERR("Success"); + result = BLUETOOTH_ERROR_NONE; + } + BT_DBG("Size of Phonebook: %d", size); + _bt_send_event(BT_PBAP_CLIENT_EVENT, + BLUETOOTH_PBAP_PHONEBOOK_SIZE, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address_string, + DBUS_TYPE_INT32, &size, + DBUS_TYPE_INVALID); + g_object_unref(proxy); + __bt_pbap_free_data(pbap_data); + BT_DBG("-"); +} + +void __bt_pbap_get_phonebook_cb(DBusGProxy *proxy, + DBusGProxyCall *call, void *user_data) +{ + BT_DBG("+"); + GError *g_error = NULL; + bt_pbap_data_t *pbap_data = user_data; + char *address_string = pbap_data->data; + GHashTable *properties; + GValue *value = { 0 }; + bt_pbap_transfer_info_t *transfer_info; + char *transfer = NULL; + const gchar *filename = NULL; + + BT_DBG("Address = %s", address_string); + if (!dbus_g_proxy_end_call(proxy, call, &g_error, + DBUS_TYPE_G_OBJECT_PATH, &transfer, + dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), + &properties, + G_TYPE_INVALID)) { + BT_ERR("Error Code[%d]: Message %s \n", g_error->code, g_error->message); + g_error_free(g_error); + } else { + if (properties != NULL) { + value = g_hash_table_lookup(properties, "Filename"); + filename = value ? g_value_get_string(value) : NULL; + } + + BT_DBG("Transfer Path: %s", transfer); + BT_DBG("File Name: %s", filename); + transfer_info = g_new0(bt_pbap_transfer_info_t, 1); + transfer_info->path = transfer; + transfer_info->remote_device = g_strdup(address_string); + transfer_info->filename = (char *)filename; + transfer_info->operation = PULL_ALL; + transfers = g_slist_append(transfers, transfer_info); + } + + g_object_unref(proxy); + __bt_pbap_free_data(pbap_data); + BT_DBG("-"); +} + +void __bt_pbap_get_vcard_list_cb(DBusGProxy *proxy, + DBusGProxyCall *call, void *user_data) +{ + BT_DBG("+"); + GError *g_error = NULL; + int i; + int result = BLUETOOTH_ERROR_INTERNAL; + GPtrArray *vcardlist = NULL; + bt_pbap_data_t *pbap_data = user_data; + char *address_string = pbap_data->data; + char **vcard_list = NULL; + char list_entry[PBAP_VCARDLIST_MAXLENGTH] = { 0, }; + int length = 0; + + BT_DBG("Address = %s", address_string); + if (!dbus_g_proxy_end_call(proxy, call, &g_error, + dbus_g_type_get_collection("GPtrArray", dbus_g_type_get_struct("GValueArray", + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID)), + &vcardlist, G_TYPE_INVALID)) { + BT_ERR("Error Code[%d]: Message %s \n", g_error->code, g_error->message); + g_error_free(g_error); + vcard_list = g_new0(char *, length + 1); + } else { + BT_DBG("vcardlist len %d", vcardlist->len); + length = vcardlist->len; + result = BLUETOOTH_ERROR_NONE; + + vcard_list = g_new0(char *, length + 1); + + GValue *v = g_new0(GValue, 1);//g_ptr_array_index(vcardlist, 0); + gchar *elname, *elval; + g_value_init(v, dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID)); + for (i = 0; i < length; i++) { + g_value_set_boxed(v, g_ptr_array_index(vcardlist, i)); + if (dbus_g_type_struct_get (v, 0, &elname, 1, &elval, G_MAXUINT)) { + memset(list_entry, 0, PBAP_VCARDLIST_MAXLENGTH); + g_snprintf (list_entry, PBAP_VCARDLIST_MAXLENGTH - 1, + "", elname, elval); + //If possible send as Array of + BT_DBG("%s", list_entry); + vcard_list[i] = g_strdup(list_entry); + } + } + } + + _bt_send_event(BT_PBAP_CLIENT_EVENT, + BLUETOOTH_PBAP_VCARD_LIST, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address_string, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, + &vcard_list, length, + DBUS_TYPE_INVALID); + + g_object_unref(proxy); + __bt_pbap_free_data(pbap_data); + BT_DBG("-"); +} + +void __bt_pbap_get_vcard_cb(DBusGProxy *proxy, + DBusGProxyCall *call, void *user_data) +{ + BT_DBG("+"); + GError *g_error = NULL; + bt_pbap_data_t *pbap_data = user_data; + char *address_string = pbap_data->data; + GHashTable *properties; + GValue *value = { 0 }; + bt_pbap_transfer_info_t *transfer_info; + char *transfer = NULL; + const gchar *filename = NULL; + + BT_DBG("Address = %s", address_string); + if (!dbus_g_proxy_end_call(proxy, call, &g_error, + DBUS_TYPE_G_OBJECT_PATH, &transfer, + dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), + &properties, + G_TYPE_INVALID)) { + BT_ERR("Error Code[%d]: Message %s \n", g_error->code, g_error->message); + g_error_free(g_error); + } else { + if (properties != NULL) { + value = g_hash_table_lookup(properties, "Filename"); + filename = value ? g_value_get_string(value) : NULL; + } + + BT_DBG("Transfer Path: %s", transfer); + BT_DBG("File Name: %s", filename); + transfer_info = g_new0(bt_pbap_transfer_info_t, 1); + transfer_info->path = transfer; + transfer_info->remote_device = g_strdup(address_string); + transfer_info->filename = (char *)filename; + transfer_info->operation = GET_VCARD; + transfers = g_slist_append(transfers, transfer_info); + } + + g_object_unref(proxy); + __bt_pbap_free_data(pbap_data); + BT_DBG("-"); +} + +void __bt_pbap_search_phonebook_cb(DBusGProxy *proxy, + DBusGProxyCall *call, void *user_data) +{ + BT_DBG("+"); + GError *g_error = NULL; + int i; + GPtrArray *vcardlist = NULL; + bt_pbap_data_t *pbap_data = user_data; + char *address_string = pbap_data->data; + char **vcard_list = NULL; + char list_entry[PBAP_VCARDLIST_MAXLENGTH] = { 0, }; + int length = 0; + int result = BLUETOOTH_ERROR_INTERNAL; + + BT_DBG("Address = %s", address_string); + if (!dbus_g_proxy_end_call(proxy, call, &g_error, + dbus_g_type_get_collection("GPtrArray", dbus_g_type_get_struct("GValueArray", + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID)), + &vcardlist, G_TYPE_INVALID)) { + BT_ERR("Error Code[%d]: Message %s \n", g_error->code, g_error->message); + g_error_free(g_error); + } else { + BT_DBG("vcardlist len %d", vcardlist->len); + length = vcardlist->len; + result = BLUETOOTH_ERROR_NONE; + + vcard_list = g_new0(char *, length + 1); + + GValue *v = g_new0(GValue, 1);//g_ptr_array_index(vcardlist, 0); + gchar *elname, *elval; + g_value_init(v, dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID)); + for (i = 0; i < length; i++) { + g_value_set_boxed(v, g_ptr_array_index(vcardlist, i)); + if (dbus_g_type_struct_get (v, 0, &elname, 1, &elval, G_MAXUINT)) { + memset(list_entry, 0, PBAP_VCARDLIST_MAXLENGTH); + g_snprintf (list_entry, PBAP_VCARDLIST_MAXLENGTH - 1, + "", elname, elval); + //If possible send as Array of + BT_DBG("%s", list_entry); + vcard_list[i] = g_strdup(list_entry); + } + } + } + + _bt_send_event(BT_PBAP_CLIENT_EVENT, + BLUETOOTH_PBAP_PHONEBOOK_SEARCH, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address_string, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, + &vcard_list, length, + DBUS_TYPE_INVALID); + g_object_unref(proxy); + __bt_pbap_free_data(pbap_data); + BT_DBG("-"); +} + +int __bt_pbap_call_get_phonebook_size(DBusGProxy *proxy, bt_pbap_data_t *pbap_data) +{ + BT_DBG("+"); + if (!dbus_g_proxy_begin_call(proxy, "GetSize", + (DBusGProxyCallNotify)__bt_pbap_get_phonebook_size_cb, + pbap_data, NULL, + G_TYPE_INVALID)) { + BT_ERR("GetSize Dbus Call Error"); + __bt_pbap_free_data(pbap_data); + return BLUETOOTH_ERROR_INTERNAL; + } + + return BLUETOOTH_ERROR_NONE; + BT_DBG("-"); +} + +int __bt_pbap_call_get_phonebook(DBusGProxy *proxy, bt_pbap_data_t *pbap_data) +{ + BT_DBG("+"); + GHashTable *filters; + GValue *max_count; + GValue *format; + GValue *order; + GValue *offset; + char *format_str = NULL; + char *order_str = NULL; + char *target_file = "/opt/usr/media/Downloads/pb.vcf"; + bt_pbap_pull_parameters_t *app_param = pbap_data->app_param; + + filters = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, (GDestroyNotify)g_free); + + /* Add Format Filter only if other than vCard 2.1 (default)*/ + if (app_param->format > 0) { + format_str = g_strdup(FORMAT[app_param->format]); + format = g_new0(GValue, 1); + g_value_init(format, G_TYPE_STRING); + g_value_set_string(format, format_str); + g_hash_table_insert(filters, "Format", format); + g_free(format_str); + } + + /* Add Order Filter only if other than Indexed (default)*/ + if (app_param->order > 0) { + order_str = g_strdup(ORDER[app_param->order]); + order = g_new0(GValue, 1); + g_value_init(order, G_TYPE_STRING); + g_value_set_string(order, order_str); + g_hash_table_insert(filters, "Order", order); + g_free(order_str); + } + + max_count = g_new0(GValue, 1); + g_value_init(max_count, G_TYPE_UINT); + g_value_set_uint(max_count, app_param->maxlist); + g_hash_table_insert(filters, "MaxCount", max_count); + + /* Add Offset Filter only if other than 0 (default)*/ + if (app_param->offset > 0) { + offset = g_new0(GValue, 1); + g_value_init(offset, G_TYPE_UINT); + g_value_set_uint(offset, app_param->offset); + g_hash_table_insert(filters, "Offset", offset); + } + +//**************************** +// Add code for Fields +// +//**************************** + + if (!dbus_g_proxy_begin_call(proxy, "PullAll", + (DBusGProxyCallNotify)__bt_pbap_get_phonebook_cb, + pbap_data, NULL, + G_TYPE_STRING, target_file, + dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), + filters, + G_TYPE_INVALID)) { + BT_ERR("GetSize Dbus Call Error"); + g_hash_table_destroy(filters); + return BLUETOOTH_ERROR_INTERNAL; + } + g_hash_table_destroy(filters); + + return BLUETOOTH_ERROR_NONE; + BT_DBG("-"); +} + +int __bt_pbap_call_get_vcards_list(DBusGProxy *proxy, bt_pbap_data_t *pbap_data) +{ + BT_DBG("+"); + GHashTable *filters; + GValue *max_count; + GValue *order; + GValue *offset; + char *order_str = NULL; + bt_pbap_list_parameters_t *app_param = pbap_data->app_param; + + filters = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, (GDestroyNotify)g_free); + + /* Add Order Filter only if other than Indexed (default)*/ + if (app_param->order > 0) { + order_str = g_strdup(ORDER[app_param->order]); + order = g_new0(GValue, 1); + g_value_init(order, G_TYPE_STRING); + g_value_set_string(order, order_str); + g_hash_table_insert(filters, "Order", order); + g_free(order_str); + } + + max_count = g_new0(GValue, 1); + g_value_init(max_count, G_TYPE_UINT); + g_value_set_uint(max_count, app_param->maxlist); + g_hash_table_insert(filters, "MaxCount", max_count); + + /* Add Offset Filter only if other than 0 (default)*/ + if (app_param->offset > 0) { + offset = g_new0(GValue, 1); + g_value_init(offset, G_TYPE_UINT); + g_value_set_uint(offset, app_param->offset); + g_hash_table_insert(filters, "Offset", offset); + } + + if (!dbus_g_proxy_begin_call(proxy, "List", + (DBusGProxyCallNotify)__bt_pbap_get_vcard_list_cb, + pbap_data, NULL, + dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), + filters, + G_TYPE_INVALID)) { + BT_ERR("List Dbus Call Error"); + g_hash_table_destroy(filters); + return BLUETOOTH_ERROR_INTERNAL; + } + + g_hash_table_destroy(filters); + + return BLUETOOTH_ERROR_NONE; + BT_DBG("-"); +} + +int __bt_pbap_call_get_vcard(DBusGProxy *proxy, bt_pbap_data_t *pbap_data) +{ + BT_DBG("+"); + GHashTable *filters; + GValue *format; + char *format_str = NULL; + char *target_file = "/opt/usr/media/Downloads/pb.vcf"; + char *vcard_handle = NULL; + char vcard[10] = { 0, }; + + bt_pbap_pull_vcard_parameters_t *app_param = pbap_data->app_param; + + filters = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, (GDestroyNotify)g_free); + + /* Add Format Filter only if other than vCard 2.1 (default)*/ + if (app_param->format > 0) { + format_str = g_strdup(FORMAT[app_param->format]); + format = g_new0(GValue, 1); + g_value_init(format, G_TYPE_STRING); + g_value_set_string(format, format_str); + g_hash_table_insert(filters, "Format", format); + g_free(format_str); + } + + +//**************************** +// Add code for Fields +// +//**************************** + + sprintf(vcard, "%d.vcf", app_param->index); + BT_DBG("Handle: %s", vcard); + vcard_handle = g_strdup(vcard); + + if (!dbus_g_proxy_begin_call(proxy, "Pull", + (DBusGProxyCallNotify)__bt_pbap_get_vcard_cb, + pbap_data, NULL, + G_TYPE_STRING, vcard_handle, + G_TYPE_STRING, target_file, + dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), + filters, + G_TYPE_INVALID)) { + BT_ERR("GetSize Dbus Call Error"); + g_hash_table_destroy(filters); + g_free(vcard_handle); + return BLUETOOTH_ERROR_INTERNAL; + } + + g_hash_table_destroy(filters); + g_free(vcard_handle); + + return BLUETOOTH_ERROR_NONE; + BT_DBG("-"); + +} + +int __bt_pbap_call_search_phonebook(DBusGProxy *proxy, bt_pbap_data_t *pbap_data) +{ + BT_DBG("+"); + GHashTable *filters; + GValue *max_count; + GValue *order; + GValue *offset; + char *order_str = NULL; + char *field = NULL; + char *value = NULL; + bt_pbap_search_parameters_t *app_param = pbap_data->app_param; + + filters = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, (GDestroyNotify)g_free); + + /* Add Order Filter only if other than Indexed (default)*/ + if (app_param->order > 0) { + order_str = g_strdup(ORDER[app_param->order]); + order = g_new0(GValue, 1); + g_value_init(order, G_TYPE_STRING); + g_value_set_string(order, order_str); + g_hash_table_insert(filters, "Order", order); + g_free(order_str); + } + + max_count = g_new0(GValue, 1); + g_value_init(max_count, G_TYPE_UINT); + g_value_set_uint(max_count, app_param->maxlist); + g_hash_table_insert(filters, "MaxCount", max_count); + + /* Add Offset Filter only if other than 0 (default)*/ + if (app_param->offset > 0) { + offset = g_new0(GValue, 1); + g_value_init(offset, G_TYPE_UINT); + g_value_set_uint(offset, app_param->offset); + g_hash_table_insert(filters, "Offset", offset); + } + + field = g_strdup(SEARCH_FIELD[app_param->search_attribute]); + value = g_strdup(app_param->search_value); + if (!dbus_g_proxy_begin_call(proxy, "Search", + (DBusGProxyCallNotify)__bt_pbap_search_phonebook_cb, + pbap_data, NULL, + G_TYPE_STRING, field, + G_TYPE_STRING, value, + dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), + filters, + G_TYPE_INVALID)) { + BT_ERR("List Dbus Call Error"); + g_hash_table_destroy(filters); + g_free(field); + g_free(value); + return BLUETOOTH_ERROR_INTERNAL; + } + + g_hash_table_destroy(filters); + g_free(field); + g_free(value); + + return BLUETOOTH_ERROR_NONE; + BT_DBG("-"); +} + +int _bt_pbap_get_phonebook_size(const bluetooth_device_address_t *address, + int source, int type) +{ + BT_DBG("+"); + DBusGProxy *g_pbap_session_proxy = NULL; + char address_string[18] = { 0, }; + char *source_string = NULL; + char *type_string = NULL; + bt_pbap_data_t *pbap_data = NULL; + + BT_CHECK_PARAMETER(address, return); + + /* check if connected */ + if (g_pbap_session_path == NULL) { + BT_ERR("NOT CONNECTED"); + return BLUETOOTH_ERROR_NOT_CONNECTED; + } + + BT_DBG("BD Address [%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X]", + address->addr[0], address->addr[1], + address->addr[2], address->addr[3], + address->addr[4], address->addr[5]); + + _bt_convert_addr_type_to_string(address_string, (unsigned char *)address->addr); + BT_DBG("Address String: %s", address_string); + BT_DBG("Session Path = %s\n", g_pbap_session_path); + g_pbap_session_proxy = dbus_g_proxy_new_for_name(dbus_connection, + PBAP_SESSION_SERVICE, + g_pbap_session_path, + PBAP_SESSION_INTERFACE); + if (!g_pbap_session_proxy) { + BT_ERR("Failed to get a proxy for D-Bus\n"); + return -1; + } + + pbap_data = g_new0(bt_pbap_data_t, 1); + pbap_data->operation = GET_SIZE; + pbap_data->data = g_strdup(address_string); + + if (source == selected_path.folder && type == selected_path.type) { + return __bt_pbap_call_get_phonebook_size(g_pbap_session_proxy, pbap_data); + } + + source_string = g_strdup(SOURCE[source]); + type_string = g_strdup(TYPE[type]); + + BT_DBG("Address[%s] Source[%s] Type[%s]", + address_string, source_string, type_string); + + if (!dbus_g_proxy_begin_call(g_pbap_session_proxy, "Select", + (DBusGProxyCallNotify)__bt_pbap_select_cb, + pbap_data, NULL, + G_TYPE_STRING, source_string, + G_TYPE_STRING, type_string, + G_TYPE_INVALID)) { + BT_ERR("Select Dbus Call Error"); + g_free(source_string); + g_free(type_string); + g_object_unref(g_pbap_session_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + + selected_path.folder = source; + selected_path.type = type; + + g_free(source_string); + g_free(type_string); + + return 0; +} + +int _bt_pbap_get_phonebook(const bluetooth_device_address_t *address, + int source, int type, bt_pbap_pull_parameters_t *app_param) +{ + BT_DBG("+"); + DBusGProxy *g_pbap_session_proxy = NULL; + char address_string[18] = { 0, }; + char *source_string = NULL; + char *type_string = NULL; + + bt_pbap_data_t *pbap_data = NULL; + bt_pbap_pull_parameters_t *param = NULL; + + BT_CHECK_PARAMETER(address, return); + + /* check if connected */ + if (g_pbap_session_path == NULL) { + BT_ERR("NOT CONNECTED"); + return BLUETOOTH_ERROR_NOT_CONNECTED; + } + + BT_DBG("BD Address [%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X]", + address->addr[0], address->addr[1], + address->addr[2], address->addr[3], + address->addr[4], address->addr[5]); + + _bt_convert_addr_type_to_string(address_string, (unsigned char *)address->addr); + BT_DBG("Address String: %s", address_string); + + BT_DBG("Session Path = %s\n", g_pbap_session_path); + g_pbap_session_proxy = dbus_g_proxy_new_for_name(dbus_connection, + PBAP_SESSION_SERVICE, + g_pbap_session_path, + PBAP_SESSION_INTERFACE); + if (!g_pbap_session_proxy) { + BT_ERR("Failed to get a proxy for D-Bus\n"); + return -1; + } + + pbap_data = g_new0(bt_pbap_data_t, 1); + pbap_data->operation = PULL_ALL; + pbap_data->data = g_strdup(address_string); + param = g_new0(bt_pbap_pull_parameters_t, 1); + memcpy(param, app_param, sizeof(bt_pbap_pull_parameters_t)); + pbap_data->app_param = param; + + if (source == selected_path.folder && type == selected_path.type) { + return __bt_pbap_call_get_phonebook(g_pbap_session_proxy, pbap_data); + } + + source_string = g_strdup(SOURCE[source]); + type_string = g_strdup(TYPE[type]); + + BT_DBG("Address[%s] Source[%s] Type[%s]", + address_string, source_string, type_string); + + if (!dbus_g_proxy_begin_call(g_pbap_session_proxy, "Select", + (DBusGProxyCallNotify)__bt_pbap_select_cb, + pbap_data, NULL, + G_TYPE_STRING, source_string, + G_TYPE_STRING, type_string, + G_TYPE_INVALID)) { + BT_ERR("Select Dbus Call Error"); + g_free(source_string); + g_free(type_string); + g_object_unref(g_pbap_session_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + + selected_path.folder = source; + selected_path.type = type; + + g_free(source_string); + g_free(type_string); + + return 0; +} + +int _bt_pbap_get_list(const bluetooth_device_address_t *address, int source, + int type, bt_pbap_list_parameters_t *app_param) +{ + BT_DBG("+"); + DBusGProxy *g_pbap_session_proxy = NULL; + char address_string[18] = { 0, }; + char *source_string = NULL; + char *type_string = NULL; + + bt_pbap_data_t *pbap_data = NULL; + bt_pbap_list_parameters_t *param = NULL; + + BT_CHECK_PARAMETER(address, return); + + /* check if connected */ + if (g_pbap_session_path == NULL) { + BT_ERR("NOT CONNECTED"); + return BLUETOOTH_ERROR_NOT_CONNECTED; + } + + BT_DBG("BD Address [%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X]", + address->addr[0], address->addr[1], + address->addr[2], address->addr[3], + address->addr[4], address->addr[5]); + + _bt_convert_addr_type_to_string(address_string, (unsigned char *)address->addr); + BT_DBG("Address String: %s", address_string); + + BT_DBG("Session Path = %s\n", g_pbap_session_path); + g_pbap_session_proxy = dbus_g_proxy_new_for_name(dbus_connection, + PBAP_SESSION_SERVICE, + g_pbap_session_path, + PBAP_SESSION_INTERFACE); + if (!g_pbap_session_proxy) { + BT_ERR("Failed to get a proxy for D-Bus\n"); + return -1; + } + + pbap_data = g_new0(bt_pbap_data_t, 1); + pbap_data->operation = GET_LIST; + pbap_data->data = g_strdup(address_string); + param = g_new0(bt_pbap_list_parameters_t, 1); + memcpy(param, app_param, sizeof(bt_pbap_list_parameters_t)); + pbap_data->app_param = param; + + if (source == selected_path.folder && type == selected_path.type) { + return __bt_pbap_call_get_vcards_list(g_pbap_session_proxy, pbap_data); + } + + source_string = g_strdup(SOURCE[source]); + type_string = g_strdup(TYPE[type]); + + BT_DBG("Address[%s] Source[%s] Type[%s]", + address_string, source_string, type_string); + + if (!dbus_g_proxy_begin_call(g_pbap_session_proxy, "Select", + (DBusGProxyCallNotify)__bt_pbap_select_cb, + pbap_data, NULL, + G_TYPE_STRING, source_string, + G_TYPE_STRING, type_string, + G_TYPE_INVALID)) { + BT_ERR("Select Dbus Call Error"); + g_free(source_string); + g_free(type_string); + g_object_unref(g_pbap_session_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + + selected_path.folder = source; + selected_path.type = type; + + g_free(source_string); + g_free(type_string); + + return 0; +} + + +int _bt_pbap_pull_vcard(const bluetooth_device_address_t *address, + int source, int type, bt_pbap_pull_vcard_parameters_t *app_param) +{ + BT_DBG("+"); + DBusGProxy *g_pbap_session_proxy = NULL; + char address_string[18] = { 0, }; + char *source_string = NULL; + char *type_string = NULL; + bt_pbap_data_t *pbap_data = NULL; + bt_pbap_pull_vcard_parameters_t *param = NULL; + + BT_CHECK_PARAMETER(address, return); + + /* check if connected */ + if (g_pbap_session_path == NULL) { + BT_ERR("NOT CONNECTED"); + return BLUETOOTH_ERROR_NOT_CONNECTED; + } + + BT_DBG("BD Address [%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X]", + address->addr[0], address->addr[1], + address->addr[2], address->addr[3], + address->addr[4], address->addr[5]); + + _bt_convert_addr_type_to_string(address_string, (unsigned char *)address->addr); + BT_DBG("Address String: %s", address_string); + + BT_DBG("Session Path = %s\n", g_pbap_session_path); + g_pbap_session_proxy = dbus_g_proxy_new_for_name(dbus_connection, + PBAP_SESSION_SERVICE, + g_pbap_session_path, + PBAP_SESSION_INTERFACE); + if (!g_pbap_session_proxy) { + BT_ERR("Failed to get a proxy for D-Bus\n"); + return -1; + } + + pbap_data = g_new0(bt_pbap_data_t, 1); + pbap_data->operation = GET_VCARD; + pbap_data->data = g_strdup(address_string); + param = g_new0(bt_pbap_pull_vcard_parameters_t, 1); + memcpy(param, app_param, sizeof(bt_pbap_pull_vcard_parameters_t)); + pbap_data->app_param = param; + + if (source == selected_path.folder && type == selected_path.type) { + return __bt_pbap_call_get_vcard(g_pbap_session_proxy, pbap_data); + } + + source_string = g_strdup(SOURCE[source]); + type_string = g_strdup(TYPE[type]); + + BT_DBG("Address[%s] Source[%s] Type[%s]", + address_string, source_string, type_string); + + if (!dbus_g_proxy_begin_call(g_pbap_session_proxy, "Select", + (DBusGProxyCallNotify)__bt_pbap_select_cb, + pbap_data, NULL, + G_TYPE_STRING, source_string, + G_TYPE_STRING, type_string, + G_TYPE_INVALID)) { + BT_ERR("Select Dbus Call Error"); + g_free(source_string); + g_free(type_string); + g_object_unref(g_pbap_session_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + + selected_path.folder = source; + selected_path.type = type; + + g_free(source_string); + g_free(type_string); + + return 0; +} + +int _bt_pbap_phonebook_search(const bluetooth_device_address_t *address, + int source, int type, bt_pbap_search_parameters_t *app_param) +{ + BT_DBG("+"); + DBusGProxy *g_pbap_session_proxy = NULL; + char address_string[18] = { 0, }; + char *source_string = NULL; + char *type_string = NULL; + bt_pbap_data_t *pbap_data = NULL; + bt_pbap_search_parameters_t *param = NULL; + + BT_CHECK_PARAMETER(address, return); + + /* check if connected */ + if (g_pbap_session_path == NULL) { + BT_ERR("NOT CONNECTED"); + return BLUETOOTH_ERROR_NOT_CONNECTED; + } + + BT_DBG("BD Address [%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X]", + address->addr[0], address->addr[1], + address->addr[2], address->addr[3], + address->addr[4], address->addr[5]); + + _bt_convert_addr_type_to_string(address_string, (unsigned char *)address->addr); + BT_DBG("Address String: %s", address_string); + + BT_DBG("Session Path = %s\n", g_pbap_session_path); + g_pbap_session_proxy = dbus_g_proxy_new_for_name(dbus_connection, + PBAP_SESSION_SERVICE, + g_pbap_session_path, + PBAP_SESSION_INTERFACE); + if (!g_pbap_session_proxy) { + BT_ERR("Failed to get a proxy for D-Bus\n"); + return -1; + } + + pbap_data = g_new0(bt_pbap_data_t, 1); + pbap_data->operation = PB_SEARCH; + pbap_data->data = g_strdup(address_string); + param = g_new0(bt_pbap_search_parameters_t, 1); + memcpy(param, app_param, sizeof(bt_pbap_search_parameters_t)); + pbap_data->app_param = param; + + if (source == selected_path.folder && type == selected_path.type) { + return __bt_pbap_call_search_phonebook(g_pbap_session_proxy, pbap_data); + } + + source_string = g_strdup(SOURCE[source]); + type_string = g_strdup(TYPE[type]); + + BT_DBG("Address[%s] Source[%s] Type[%s]", + address_string, source_string, type_string); + + if (!dbus_g_proxy_begin_call(g_pbap_session_proxy, "Select", + (DBusGProxyCallNotify)__bt_pbap_select_cb, + pbap_data, NULL, + G_TYPE_STRING, source_string, + G_TYPE_STRING, type_string, + G_TYPE_INVALID)) { + BT_ERR("Select Dbus Call Error"); + g_object_unref(g_pbap_session_proxy); + g_free(source_string); + g_free(type_string); + return BLUETOOTH_ERROR_INTERNAL; + } + + selected_path.folder = source; + selected_path.type = type; + + g_free(source_string); + g_free(type_string); + + return 0; +} + diff --git a/bt-service/bt-service-rfcomm-client.c b/bt-service/bt-service-rfcomm-client.c old mode 100644 new mode 100755 index 5bb64c3..ebbf517 --- a/bt-service/bt-service-rfcomm-client.c +++ b/bt-service/bt-service-rfcomm-client.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -23,7 +27,6 @@ #include #include #include -#include #include "bluetooth-api.h" #include "bt-internal-types.h" @@ -70,7 +73,7 @@ static int __bt_rfcomm_open_socket(char *dev_node) socket_fd = open(dev_node, O_RDWR | O_NOCTTY); if (socket_fd < 0) { - BT_ERR("\nCan't open TTY : %s(%d)",dev_node, errno); + BT_ERR("Can't open TTY : %s(%d)", dev_node, socket_fd); return socket_fd; } @@ -309,7 +312,7 @@ static void __bt_rfcomm_connected_cb(DBusGProxy *proxy, DBusGProxyCall *call, } if (err != NULL) { - BT_ERR("Error occurred in connecting port [%s]", err->message); + BT_ERR("Error occured in connecting port [%s]", err->message); if (!strcmp("Host is down", err->message)) result = BLUETOOTH_ERROR_HOST_DOWN; @@ -319,13 +322,22 @@ static void __bt_rfcomm_connected_cb(DBusGProxy *proxy, DBusGProxyCall *call, goto dbus_return; } - BT_DBG("Success Connect REMOTE Device RFCOMM Node[%s]", rfcomm_device_node); + BT_INFO("Succss Connect REMOTE Device RFCOMM Node[%s]", rfcomm_device_node); socket_fd = __bt_rfcomm_open_socket(rfcomm_device_node); if (socket_fd < 0) { - BT_ERR("Fail to open socket: %d", socket_fd); - goto dbus_return; + int retry_count = 10; + do { + BT_ERR("Fail to open socket[%d] retry_count[%d]", socket_fd, retry_count); + usleep(10*1000); /* 10 ms */ + socket_fd = __bt_rfcomm_open_socket(rfcomm_device_node); + } while (socket_fd < 0 && retry_count-- > 0); + + if (socket_fd < 0) { + BT_ERR("Fail to open socket: %d", socket_fd); + goto dbus_return; + } } client_info = g_malloc0(sizeof(bt_rfcomm_info_t)); @@ -335,6 +347,7 @@ static void __bt_rfcomm_connected_cb(DBusGProxy *proxy, DBusGProxyCall *call, client_info->address = g_strdup(rfcomm_info->address); client_info->uuid = g_strdup(rfcomm_info->uuid); client_info->io_channel = g_io_channel_unix_new(socket_fd); + g_io_channel_set_encoding(client_info->io_channel, NULL, NULL); client_info->io_event = g_io_add_watch(client_info->io_channel, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, __bt_rfcomm_client_data_received_cb, @@ -636,27 +649,12 @@ int _bt_rfcomm_write(int socket_fd, char *buf, int length) { int wbytes = 0; int written; - int new_length; - char *ptr = NULL; - - retv_if(buf == NULL, BLUETOOTH_ERROR_INVALID_PARAM); - - /* Check the utf8 validation & Fill the NULL in the invalid location*/ - if (!g_utf8_validate(buf, -1, (const char **)&ptr)) - *ptr = '\0'; - /* After calling g_utf8_validate, it is possible to be NULL */ retv_if(buf == NULL, BLUETOOTH_ERROR_INVALID_PARAM); - new_length = strlen(buf); - if (new_length < length) { - length = new_length; - } - - /*some times user may send huge data */ + /* Sometimes user may send huge data */ while (wbytes < length) { - written = write(socket_fd, buf + wbytes, - length - wbytes); + written = write(socket_fd, buf + wbytes, length - wbytes); if (written <= 0) { BT_ERR("write failed..\n"); return BLUETOOTH_ERROR_NOT_IN_OPERATION; diff --git a/bt-service/bt-service-rfcomm-server.c b/bt-service/bt-service-rfcomm-server.c old mode 100644 new mode 100755 index 4a8695a..a879cd2 --- a/bt-service/bt-service-rfcomm-server.c +++ b/bt-service/bt-service-rfcomm-server.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -67,7 +71,7 @@ int __bt_rfcomm_assign_server_id(void) while (server_id_used[index] == TRUE) { if (index == latest_id) { /* No available ID */ - BT_DBG("All request ID is used"); + BT_ERR("All request ID is used"); return -1; } @@ -219,7 +223,7 @@ int __bt_rfcomm_get_socket(int server_id) result = _bt_set_socket_non_blocking(socket_fd); if (result != BLUETOOTH_ERROR_NONE) { - BT_DBG("Cannot set the tty"); + BT_ERR("Cannot set the tty"); goto fail; } @@ -277,13 +281,12 @@ int _bt_rfcomm_create_socket(char *sender, char *uuid) BT_ERR("Enable Error: %s\n", error->message); g_error_free(error); } - g_object_unref(serial_proxy); goto fail; } socket_fd = __bt_rfcomm_get_socket(server_id); if (socket_fd < 0) { - BT_DBG("Can't get socket"); + BT_ERR("Can't get socket"); goto fail; } @@ -556,7 +559,7 @@ static gboolean __bt_rfcomm_server_connected_cb(GIOChannel *chan, req_info = _bt_get_request_info(server_info->accept_id); if (req_info == NULL || req_info->context == NULL) { - BT_DBG("info is NULL"); + BT_ERR("info is NULL"); goto done; } @@ -603,7 +606,7 @@ int _bt_rfcomm_listen(int socket_fd, int max_pending, gboolean is_native) retv_if(server_info->control_io != NULL, BLUETOOTH_ERROR_DEVICE_BUSY); if (listen(socket_fd, max_pending) != 0) { - BT_DBG("Fail to listen"); + BT_ERR("Fail to listen"); return BLUETOOTH_ERROR_INTERNAL; } @@ -628,7 +631,7 @@ int _bt_rfcomm_listen(int socket_fd, int max_pending, gboolean is_native) } else { server_info->server_type = BT_CUSTOM_SERVER; _bt_register_osp_server_in_agent(BT_RFCOMM_SERVER, - server_info->uuid); + server_info->uuid, NULL, -1); } return BLUETOOTH_ERROR_NONE; @@ -649,7 +652,7 @@ int _bt_rfcomm_remove_socket(int socket_fd) NULL, G_TYPE_INVALID, G_TYPE_INVALID)) { - BT_DBG("Fail to disable"); + BT_ERR("Fail to disable"); } } @@ -659,7 +662,7 @@ int _bt_rfcomm_remove_socket(int socket_fd) G_TYPE_STRING, server_info->serial_path, G_TYPE_INVALID, G_TYPE_INVALID)) { - BT_DBG("Fail to remove proxy"); + BT_ERR("Fail to remove proxy"); } } @@ -785,78 +788,25 @@ int _bt_rfcomm_is_uuid_available(char *uuid, gboolean *available) return BLUETOOTH_ERROR_NONE; } -gboolean __bt_rfcomm_server_accept_timeout_cb(gpointer user_data) -{ - bt_rfcomm_server_info_t *server_info; - request_info_t *req_info; - GArray *out_param1; - GArray *out_param2; - int result = BLUETOOTH_ERROR_TIMEOUT; - - server_info = (bt_rfcomm_server_info_t *)user_data; - - /* Already reply in __bt_rfcomm_server_connected_cb */ - retv_if(server_info == NULL, FALSE); - retv_if(server_info->accept_id == 0, FALSE); - - req_info = _bt_get_request_info(server_info->accept_id); - if (req_info == NULL || req_info->context == NULL) { - BT_ERR("info is NULL"); - return FALSE; - } - - server_info->accept_id = 0; - - out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar)); - out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar)); - - g_array_append_vals(out_param2, &result, sizeof(int)); - - dbus_g_method_return(req_info->context, out_param1, out_param2); - - g_array_free(out_param1, TRUE); - g_array_free(out_param2, TRUE); - - _bt_delete_request_list(req_info->req_id); - - return FALSE; -} - /* To support the BOT */ -int _bt_rfcomm_accept_connection(int server_fd, int request_id) +int _bt_rfcomm_accept_connection(void) { - bt_rfcomm_server_info_t *server_info; - - server_info = __bt_rfcomm_get_server_info(server_fd); - retv_if(server_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM); - retv_if(server_info->server_type != BT_CUSTOM_SERVER, - BLUETOOTH_ERROR_INVALID_PARAM); - + BT_DBG("+"); if (!_bt_agent_reply_authorize(TRUE)) return BLUETOOTH_ERROR_INTERNAL; - server_info->accept_id = request_id; - - g_timeout_add(BT_SERVER_ACCEPT_TIMEOUT, - (GSourceFunc)__bt_rfcomm_server_accept_timeout_cb, - server_info); - + BT_DBG("-"); return BLUETOOTH_ERROR_NONE; } /* To support the BOT */ -int _bt_rfcomm_reject_connection(int server_fd) +int _bt_rfcomm_reject_connection(void) { - bt_rfcomm_server_info_t *server_info; - - server_info = __bt_rfcomm_get_server_info(server_fd); - retv_if(server_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM); - retv_if(server_info->server_type != BT_CUSTOM_SERVER, - BLUETOOTH_ERROR_INVALID_PARAM); - + BT_DBG("+"); if (!_bt_agent_reply_authorize(FALSE)) return BLUETOOTH_ERROR_INTERNAL; + BT_DBG("-"); return BLUETOOTH_ERROR_NONE; } diff --git a/bt-service/bt-service-util.c b/bt-service/bt-service-util.c old mode 100644 new mode 100755 index 5afbc4e..7a2b94f --- a/bt-service/bt-service-util.c +++ b/bt-service/bt-service-util.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -129,6 +133,7 @@ int _bt_delete_request_list(int req_id) if (info->req_id == req_id) { req_list = g_slist_remove(req_list, info); + _bt_delete_request_id(info->req_id); g_free(info); return BLUETOOTH_ERROR_NONE; } diff --git a/bt-service/include/bt-request-handler.h b/bt-service/include/bt-request-handler.h old mode 100644 new mode 100755 index a01ad63..83296dd --- a/bt-service/include/bt-request-handler.h +++ b/bt-service/include/bt-request-handler.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -17,6 +21,7 @@ * */ + #ifndef _BT_REQUEST_HANDLER_H_ #define _BT_REQUEST_HANDLER_H_ diff --git a/bt-service/include/bt-service-adapter-le.h b/bt-service/include/bt-service-adapter-le.h new file mode 100755 index 0000000..6102f45 --- /dev/null +++ b/bt-service/include/bt-service-adapter-le.h @@ -0,0 +1,74 @@ +/* + * Bluetooth-frwk + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#ifndef _BT_SERVICE_ADAPTER_LE_H_ +#define _BT_SERVICE_ADAPTER_LE_H_ + +#include +#include +#include "bluetooth-api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int _bt_service_adapter_le_init(void); + +void _bt_service_adapter_le_deinit(void); + +gboolean _bt_update_le_feature_support(const char *item, const char *value); + +const char* _bt_get_adv_slot_owner(int slot_id); + +void _bt_set_advertising_status(int slot_id, gboolean mode); + +gboolean _bt_is_advertising(void); + +void _bt_stop_advertising_by_terminated_process(const char* terminated_name); + +int _bt_set_advertising(gboolean enable, const char *sender, gboolean use_reserved_slot); + +int _bt_set_custom_advertising(gboolean enable, bluetooth_advertising_params_t *params, const char *sender, gboolean use_reserved_slot); + +int _bt_get_advertising_data(bluetooth_advertising_data_t *adv, int *length); + +int _bt_set_advertising_data(bluetooth_advertising_data_t *data, int length, const char *sender, gboolean use_reserved_slot); + +int _bt_get_scan_response_data(bluetooth_scan_resp_data_t *response, int *length); + +int _bt_set_scan_response_data(bluetooth_scan_resp_data_t *response, int length, const char *sender, gboolean use_reserved_slot); + +int _bt_set_scan_parameters(bluetooth_le_scan_params_t *params); + +int _bt_add_white_list(bluetooth_device_address_t *device_address, bluetooth_device_address_type_t address_type); + +int _bt_remove_white_list(bluetooth_device_address_t *device_address, bluetooth_device_address_type_t address_type); + +int _bt_clear_white_list(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_SERVICE_ADAPTER_LE_H_*/ + diff --git a/bt-service/include/bt-service-adapter.h b/bt-service/include/bt-service-adapter.h old mode 100644 new mode 100755 index 5d1275d..30f970a --- a/bt-service/include/bt-service-adapter.h +++ b/bt-service/include/bt-service-adapter.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -17,6 +21,7 @@ * */ + #ifndef _BT_SERVICE_ADAPTER_H_ #define _BT_SERVICE_ADAPTER_H_ @@ -28,6 +33,11 @@ extern "C" { #endif +#define BT_LE_SCAN_INTERVAL_MIN 2.5 +#define BT_LE_SCAN_INTERVAL_MAX 10240 +#define BT_LE_SCAN_WINDOW_MIN 2.5 +#define BT_LE_SCAN_WINDOW_MAX 10240 + typedef enum { BT_DEACTIVATED, BT_ACTIVATED, @@ -35,28 +45,56 @@ typedef enum { BT_DEACTIVATING, } bt_status_t; +typedef enum { + BT_LE_DEACTIVATED, + BT_LE_ACTIVATED, + BT_LE_ACTIVATING, + BT_LE_DEACTIVATING, +} bt_le_status_t; + +typedef enum { + BT_LE_PASSIVE_SCAN = 0x00, + BT_LE_ACTIVE_SCAN +} bt_le_discovery_type_t; + int _bt_enable_adapter(void); int _bt_disable_adapter(void); +int _bt_recover_adapter(void); + +int _bt_enable_adapter_le(void); + +int _bt_disable_adapter_le(void); + int _bt_reset_adapter(void); +int _bt_enable_core(void); + void _bt_handle_adapter_added(void); void _bt_handle_adapter_removed(void); int _bt_check_adapter(int *status); -void _bt_set_enabled(void); +void *_bt_get_adapter_agent(void); -void _bt_set_disabled(void); +void _bt_service_register_vconf_handler(void); -void *_bt_get_adapter_agent(void); +void _bt_service_unregister_vconf_handler(void); void _bt_set_discovery_status(gboolean mode); +void _bt_set_le_discovery_status(gboolean mode); + +void _bt_set_le_discovery_type(bt_le_discovery_type_t type); + +bt_le_discovery_type_t _bt_get_le_discovery_type(void); + int _bt_get_local_address(bluetooth_device_address_t *local_address); +int _bt_get_local_version(bluetooth_version_t *local_version); + int _bt_get_local_name(bluetooth_device_name_t *local_name); int _bt_set_local_name(char *local_name); @@ -67,10 +105,20 @@ int _bt_get_discoverable_mode(int *mode); int _bt_set_discoverable_mode(int discoverable_mode, int timeout); +gboolean _bt_is_connectable(void); + +int _bt_set_connectable(gboolean connectable); + int _bt_start_discovery(void); +int _bt_start_custom_discovery(bt_discovery_role_type_t role); + int _bt_cancel_discovery(void); +int _bt_start_le_discovery(void); + +int _bt_stop_le_discovery(void); + int _bt_get_bonded_devices(GArray **dev_list); int _bt_get_bonded_device_info(bluetooth_device_address_t *device_address, @@ -80,11 +128,21 @@ int _bt_get_timeout_value(int *timeout); gboolean _bt_is_discovering(void); +gboolean _bt_is_le_discovering(void); + +int _bt_enable_rssi(bluetooth_device_address_t *bd_addr, int link_type, + int low_threshold, int in_range_threshold, int high_threshold); + +int _bt_get_rssi_strength(bluetooth_device_address_t *bd_addr, + int link_type); + +gboolean _bt_get_advertising_params(bluetooth_advertising_params_t *params); + gboolean _bt_get_cancel_by_user(void); void _bt_set_cancel_by_user(gboolean value); -gboolean _bt_get_discovering_property(void); +gboolean _bt_get_discovering_property(bt_discovery_role_type_t discovery_type); unsigned int _bt_get_discoverable_timeout_property(void); @@ -92,9 +150,21 @@ void _bt_adapter_set_status(bt_status_t status); bt_status_t _bt_adapter_get_status(void); -void _bt_handle_flight_mode_noti(void); +void _bt_adapter_set_le_status(bt_le_status_t status); + +bt_le_status_t _bt_adapter_get_le_status(void); + +void _bt_adapter_start_enable_timer(void); + +void _bt_adapter_start_le_enable_timer(void); + +void _bt_set_disabled(int result); + +void _bt_set_le_disabled(int result); + +int _bt_set_le_privacy(gboolean set_privacy); -int _bt_get_remote_found_devices(GArray **dev_list); +int _bt_set_manufacturer_data(bluetooth_manufacturer_data_t *m_data); #ifdef __cplusplus } diff --git a/bt-service/include/bt-service-agent.h b/bt-service/include/bt-service-agent.h old mode 100644 new mode 100755 index 0b0937e..8b9040e --- a/bt-service/include/bt-service-agent.h +++ b/bt-service/include/bt-service-agent.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -46,7 +50,9 @@ #define BT_AGENT_FAIL -1 #define BT_AGENT_ERROR_NONE 0 +#ifndef TIZEN_WEARABLE #define BT_FILE_VISIBLE_TIME "file/private/libug-setting-bluetooth-efl/visibility_time" +#endif typedef enum { HS_PROFILE_UUID = ((unsigned short)0x1108), /** + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -17,6 +21,7 @@ * */ + #ifndef _BT_SERVICE_AUDIO_H_ #define _BT_SERVICE_AUDIO_H_ @@ -38,17 +43,37 @@ typedef struct { } bt_headset_wait_t; typedef enum { + BT_PENDING_NONE = 0x00, + BT_PENDING_CONNECT, + BT_PENDING_DISCONNECT +} bt_pending_request_t; + +typedef struct { + int req_id; + char *address; + bt_pending_request_t pending; + GArray **out_param; + int type; +} bt_audio_function_data_t; + +typedef enum { BT_AUDIO_HSP = 0x01, BT_AUDIO_A2DP, BT_AUDIO_ALL, + BT_AVRCP } bt_audio_type_t; typedef enum { BT_STATE_NONE = 0x00, BT_STATE_CONNECTING, BT_STATE_CONNECTED, + BT_STATE_DISCONNECTING, + BT_STATE_DISCONNECTED } bt_headset_device_state_t; +#define BT_CONTENT_PROTECTION_PATH "/org/tizen/bluetooth/a2dpcontentprotection" +#define BT_CONTENT_PROTECTION_INTERFACE "org.tizen.bluetooth.A2dpContentProtection" + int _bt_audio_connect(int request_id, int type, bluetooth_device_address_t *device_address, GArray **out_param1); @@ -57,19 +82,40 @@ int _bt_audio_disconnect(int request_id, int type, bluetooth_device_address_t *device_address, GArray **out_param1); +int _bt_hf_connect(int request_id, + bluetooth_device_address_t *device_address, + GArray **out_param1); + +int _bt_hf_disconnect(int request_id, + bluetooth_device_address_t *device_address, + GArray **out_param1); + int _bt_audio_get_speaker_gain(unsigned int *gain); int _bt_audio_set_speaker_gain(unsigned int gain); +int _bt_audio_set_content_protect(gboolean status); + void _bt_set_audio_wait_data_flag(gboolean flag); bt_headset_wait_t *_bt_get_audio_wait_data(void); +void _bt_rel_wait_data(void); + void _bt_add_headset_to_list(int type, int status, const char *address); void _bt_remove_headset_from_list(int type, const char *address); gboolean _bt_is_headset_type_connected(int type, char *address); +void _bt_remove_from_connected_list(const char *address); + +int _bt_get_device_state_from_list(int type, const char *address); + +void _bt_remove_from_connected_list(const char *address); + +void _bt_audio_check_pending_connect(); + +gboolean _bt_is_service_connected(char *address, int type); #ifdef __cplusplus } diff --git a/bt-service/include/bt-service-avrcp.h b/bt-service/include/bt-service-avrcp.h old mode 100644 new mode 100755 index 4dd8952..cf9e736 --- a/bt-service/include/bt-service-avrcp.h +++ b/bt-service/include/bt-service-avrcp.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -17,6 +21,7 @@ * */ + #ifndef _BT_SERVICE_AVRCP_H_ #define _BT_SERVICE_AVRCP_H_ @@ -32,17 +37,29 @@ extern "C" { #endif -#define BLUEZ_MEDIA_PLAYER_INTERFACE "org.bluez.MediaPlayer" #define BT_MEDIA_OBJECT_PATH "/Musicplayer" +#define BT_MEDIA_CONTROL_PATH "%s/player0" + int _bt_register_media_player(void); int _bt_unregister_media_player(void); +int _bt_avrcp_set_track_info(media_metadata_attributes_t *meta_data); + int _bt_avrcp_set_properties(media_player_settings_t *properties); int _bt_avrcp_set_property(int type, unsigned int value); +int _bt_avrcp_control_cmd(int type); + +int _bt_avrcp_control_set_property(int type, unsigned int value); + +int _bt_avrcp_control_get_property(int type, unsigned int *value); + +int _bt_avrcp_control_get_track_info(media_metadata_attributes_t *metadata); + +void _bt_handle_avrcp_control_event(DBusMessageIter *msg_iter, const char *path); #ifdef __cplusplus } diff --git a/bt-service/include/bt-service-common.h b/bt-service/include/bt-service-common.h old mode 100644 new mode 100755 index 944be45..dea1b61 --- a/bt-service/include/bt-service-common.h +++ b/bt-service/include/bt-service-common.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -17,6 +21,7 @@ * */ + #ifndef _BT_SERVICE_COMMON_H_ #define _BT_SERVICE_COMMON_H_ @@ -34,11 +39,36 @@ extern "C" { #undef LOG_TAG #define LOG_TAG "BLUETOOTH_FRWK_SERVICE" +#ifdef FUNCTION_TRACE +#define FN_START BT_DBG("[ENTER FUNC]") +#define FN_END BT_DBG("[EXIT FUNC]") +#else +#define FN_START +#define FN_END +#endif + +#define LOG_COLOR_RESET "\033[0m" +#define LOG_COLOR_RED "\033[31m" +#define LOG_COLOR_YELLOW "\033[33m" +#define LOG_COLOR_GREEN "\033[32m" +#define LOG_COLOR_BLUE "\033[36m" +#define LOG_COLOR_PURPLE "\033[35m" + #define BT_DBG(fmt, args...) \ SLOGD(fmt, ##args) +#define BT_INFO(fmt, args...) \ + SLOGI(fmt, ##args) #define BT_ERR(fmt, args...) \ SLOGE(fmt, ##args) +#define BT_INFO_C(fmt, arg...) \ + SLOGI_IF(TRUE, LOG_COLOR_GREEN" "fmt" "LOG_COLOR_RESET, ##arg) +#define BT_ERR_C(fmt, arg...) \ + SLOGI_IF(TRUE, LOG_COLOR_RED" "fmt" "LOG_COLOR_RESET, ##arg) + +#define DBG_SECURE(fmt, args...) SECURE_SLOGD(fmt, ##args) +#define ERR_SECURE(fmt, args...) SECURE_SLOGE(fmt, ##args) + #define ret_if(expr) \ do { \ if (expr) { \ @@ -74,7 +104,7 @@ extern "C" { #define BT_AGENT_NEW_LINE "\r\n" #define BT_MAX_DBUS_TIMEOUT 45000 -#define BT_ENABLE_TIMEOUT 5000 /* 5 seconds */ +#define BT_ENABLE_TIMEOUT 20000 /* 20 seconds */ #define BT_DISCOVERY_FINISHED_DELAY 200 #define MANAGER_EVENT_MATCH_RULE \ @@ -95,59 +125,78 @@ extern "C" { "was broken." #define BT_BLUEZ_NAME "org.bluez" + #define BT_BLUEZ_PATH "/org/bluez" #define BT_BLUEZ_HCI_PATH "/org/bluez/hci0" -#define BT_BLUEZ_HCI_DEV_PATH "/org/bluez/hci0/dev" #define BT_AGENT_NAME "org.bluez.frwk_agent" #define BT_AGENT_PATH "/org/bluez/agent/frwk_agent" #define BT_DEVICE_AGENT_PATH "/org/tizen/device_agent" #define BT_ADAPTER_AGENT_PATH "/org/tizen/adapter_agent" #define BT_MANAGER_PATH "/" + + #define BT_MANAGER_INTERFACE "org.freedesktop.DBus.ObjectManager" #define BT_ADAPTER_INTERFACE "org.bluez.Adapter1" #define BT_AGENT_INTERFACE "org.bluez.Agent1" #define BT_AGENT_MANAGER_INTERFACE "org.bluez.AgentManager1" #define BT_DEVICE_INTERFACE "org.bluez.Device1" -#define BT_INPUT_INTERFACE "org.bluez.Input" -#define BT_NETWORK_INTERFACE "org.bluez.Network1" #define BT_NETWORK_SERVER_INTERFACE "org.bluez.NetworkServer1" +#define BT_MEDIA_INTERFACE "org.bluez.Media1" +#define BT_MEDIA_PLAYER_INTERFACE "org.mpris.MediaPlayer2.Player" +#define BT_MEDIATRANSPORT_INTERFACE "org.bluez.MediaTransport1" +#define BT_MEDIA_CONTROL_INTERFACE "org.bluez.MediaControl1" +#define BT_PLAYER_CONTROL_INTERFACE "org.bluez.MediaPlayer1" + +#define BT_INPUT_INTERFACE "org.bluez.Input" +#define BT_NETWORK_INTERFACE "org.bluez.Network" #define BT_NETWORK_CLIENT_INTERFACE "org.bluez.Network1" #define BT_SERIAL_INTERFACE "org.bluez.Serial" #define BT_SERIAL_MANAGER_INTERFACE "org.bluez.SerialProxyManager" #define BT_SERIAL_PROXY_INTERFACE "org.bluez.SerialProxy" -#define BT_HFP_AGENT_INTERFACE "Org.Hfp.App.Interface" #define BT_SINK_INTERFACE "org.bluez.AudioSink" #define BT_AUDIO_INTERFACE "org.bluez.Audio" +#define BT_HEADSET_INTERFACE "org.bluez.Headset" #define BT_OOB_INTERFACE "org.bluez.OutOfBand" -#define BT_MEDIA_INTERFACE "org.bluez.Media1" -#define BT_MEDIA_PLAYER_INTERFACE "org.mpris.MediaPlayer2.Player" -#define BT_OBEXD_DBUS_NAME "org.bluez.obex" -#define BT_OBEXD_MANAGER_INTERFACE "org.bluez.obex.AgentManager1" -#define BT_OBEXD_TRANSFER_INTERFACE "org.bluez.obex.Transfer1" +#define BT_HANDSFREE_GATEWAY_INTERFACE "org.bluez.HandsfreeGateway" +#define BT_OBEXD_INTERFACE "org.openobex" +#define BT_OBEXD_MANAGER_INTERFACE "org.openobex.Manager" +#define BT_OBEXD_TRANSFER_INTERFACE "org.openobex.Transfer" + #define BT_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties" -#define BT_MEDIA_CONTROL_INTERFACE "org.bluez.MediaControl1" -#define MPRIS_PLAYER_INTERFACE "org.mpris.MediaPlayer2.Player" -#define BT_OBEX_SERVICE_NAME "org.bluez.obex" +#define BT_OBEX_SERVICE_NAME "org.bluez.obex" #define BT_OBEX_CLIENT_PATH "/org/bluez/obex" #define BT_OBEX_CLIENT_INTERFACE "org.bluez.obex.Client1" -#define BT_OBEX_OBJECT_PUSH_INTERFACE "org.bluez.obex.ObjectPush1" + + + #define BT_OBEX_TRANSFER_INTERFACE "org.bluez.obex.Transfer1" #define BT_OBEX_AGENT_INTERFACE "org.bluez.obex.Agent1" -#define BT_SESSION_BASEPATH_SERVER "/org/bluez/obex/server" -#define BT_SESSION_BASEPATH_CLIENT "/org/bluez/obex/client" + + +#define BT_OBEXD_DBUS_NAME "org.bluez.obex" +#define BT_OBEX_OBJECT_PUSH_INTERFACE "org.bluez.obex.ObjectPush1" + #define BT_FREEDESKTOP_INTERFACE "org.freedesktop.DBus" #define BT_FREEDESKTOP_PATH "/org/freedesktop/DBus" + #define BT_INTERFACES_ADDED "InterfacesAdded" #define BT_INTERFACES_REMOVED "InterfacesRemoved" #define BT_NAME_OWNER_CHANGED "NameOwnerChanged" #define BT_PROPERTIES_CHANGED "PropertiesChanged" -#define DBUS_INTERFACE_OBJECT_MANAGER "/" + + +#define BT_SESSION_BASEPATH_SERVER "/org/bluez/obex/server" +#define BT_SESSION_BASEPATH_CLIENT "/org/bluez/obex/client" + +#define BT_SERVICE_ERR_MSG_NOT_SUPPORTED "Operation is not supported" + +/* UUID */ #define GENERIC_AUDIO_UUID "00001203-0000-1000-8000-00805f9b34fb" #define HSP_HS_UUID "00001108-0000-1000-8000-00805f9b34fb" @@ -166,13 +215,62 @@ extern "C" { #define HID_UUID "00001124-0000-1000-8000-00805f9b34fb" #define PNP_UUID "00001200-0000-1000-8000-00805f9b34fb" +#define RFCOMM_UUID_STR "00000003-0000-1000-8000-00805f9b34fb" +#define PANU_UUID "00001115-0000-1000-8000-00805f9b34fb" +#define NAP_UUID "00001116-0000-1000-8000-00805f9b34fb" +#define OBEX_PSE_UUID "0000112f-0000-1000-8000-00805f9b34fb" +#define GATT_UUID "00001801-0000-1000-8000-00805f9b34fb" + +/* Privilege */ +#define BT_PRIVILEGE_PUBLIC "bt-service::public" +#define BT_PRIVILEGE_PLATFORM "bt-service::platform" + +/* BD Address type */ +#define BDADDR_BREDR 0x00 +#define BDADDR_LE_PUBLIC 0x01 +#define BDADDR_LE_RANDOM 0x02 + +/* Advertising report event types */ +#define BT_LE_ADV_IND 0x00 +#define BT_LE_ADV_DIRECT_IND 0x01 +#define BT_LE_ADV_SCAN_IND 0x02 +#define BT_LE_ADV_NONCONN_IND 0x03 +#define BT_LE_ADV_SCAN_RSP 0x04 + +/* Profile states matched to btd_service_state_t of bluez service.h */ +typedef enum { + BT_PROFILE_STATE_UNAVAILABLE, + BT_PROFILE_STATE_DISCONNECTED, + BT_PROFILE_STATE_CONNECTING, + BT_PROFILE_STATE_CONNECTED, + BT_PROFILE_STATE_DISCONNECTING, +} bt_profile_state_t; -#define BT_STOP_DISCOVERY_TIMEOUT 1000*15 +typedef enum { + BT_ADV_IND_INFO = 0x00, + BT_SCAN_RSP_INFO = 0x01, +} bt_le_device_info_type_t; typedef enum { - BT_OBEX_SERVER = 0x00, - BT_RFCOMM_SERVER = 0x01, -} bt_osp_server_type_t; + BT_PROFILE_CONN_RFCOMM= 0x01, + BT_PROFILE_CONN_A2DP= 0x02, + BT_PROFILE_CONN_HSP= 0x04, + BT_PROFILE_CONN_HID= 0x08, + BT_PROFILE_CONN_NAP= 0x10, + BT_PROFILE_CONN_HFG= 0x20, + BT_PROFILE_CONN_GATT= 0x40, + BT_PROFILE_CONN_ALL= 0x80, +} bt_profile_type_t; + +typedef struct { + char *address; + int addr_type; + int rssi; + int adv_type; + bt_le_device_info_type_t dev_type; + int adv_data_len; + char *adv_data; +} bt_remote_le_dev_info_t; typedef struct { int rssi; @@ -184,6 +282,12 @@ typedef struct { gboolean paired; gboolean connected; gboolean trust; + char *manufacturer_data; + int manufacturer_data_len; + guchar addr_type; +#if 0 /* Should match with bt_dev_info_t in bluetooth-api.h */ + bt_remote_le_dev_info_t le_dev_info; +#endif } bt_remote_dev_info_t; /* RFCOMM client /server will use this structure*/ @@ -207,15 +311,25 @@ DBusGConnection *_bt_get_system_gconn(void); DBusGConnection *_bt_get_session_gconn(void); +void *_bt_get_net_conn(void); + DBusGProxy *_bt_get_manager_proxy(void); DBusGProxy *_bt_get_adapter_proxy(void); DBusGProxy *_bt_get_adapter_properties_proxy(void); -char *_bt_get_adapter_path(void); +char *_bt_get_device_object_path(char *address); -gboolean _bt_get_adapter_power(void); +char *_bt_get_profile_uuid128(bt_profile_type_t profile_type); + +char *_bt_convert_error_to_string(int error); + +char * _bt_convert_disc_reason_to_string(int reason); + +void _bt_logging_connection(gboolean connect, int addr_type); + +char *_bt_get_adapter_path(void); void _bt_deinit_proxys(void); @@ -235,7 +349,13 @@ void _bt_divide_device_class(bluetooth_device_class_t *device_class, void _bt_free_device_info(bt_remote_dev_info_t *dev_info); -int _bt_register_osp_server_in_agent(int type, char *uuid); +void _bt_free_le_device_info(bt_remote_le_dev_info_t *le_dev_info); + +int _bt_copy_utf8_string(char *dest, const char *src, unsigned int length); + +gboolean _bt_utf8_validate(char *name); + +int _bt_register_osp_server_in_agent(int type, char *uuid, char *path, int fd); int _bt_unregister_osp_server_in_agent(int type, char *uuid); @@ -243,10 +363,6 @@ int _bt_set_socket_non_blocking(int socket_fd); int _bt_set_non_blocking_tty(int sk); -gboolean _bt_is_headset_class(int dev_class); - -char *_bt_get_device_object_path(char *address); - void _bt_deinit_bluez_proxy(void); #ifdef __cplusplus diff --git a/bt-service/include/bt-service-device.h b/bt-service/include/bt-service-device.h old mode 100644 new mode 100755 index 04694bb..7642a19 --- a/bt-service/include/bt-service-device.h +++ b/bt-service/include/bt-service-device.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -17,6 +21,7 @@ * */ + #ifndef _BT_SERVICE_DEVICE_H_ #define _BT_SERVICE_DEVICE_H_ @@ -30,7 +35,7 @@ extern "C" { int _bt_bond_device(int request_id, bluetooth_device_address_t *device_address, - GArray **out_param1); + unsigned short conn_type, GArray **out_param1); int _bt_cancel_bonding(void); @@ -49,6 +54,9 @@ int _bt_set_alias(bluetooth_device_address_t *device_address, int _bt_set_authorization(bluetooth_device_address_t *device_address, gboolean authorize); +int _bt_is_gatt_connected(bluetooth_device_address_t *device_address, + gboolean *is_connected); + int _bt_is_device_connected(bluetooth_device_address_t *device_address, int connection_type, gboolean *is_connected); @@ -58,6 +66,22 @@ void _bt_set_autopair_status_in_bonding_info(gboolean is_autopair); bt_remote_dev_info_t *_bt_get_remote_device_info(char *address); +gboolean _bt_is_bonding_device_address(const char *address); + +int _bt_connect_le_device(const bluetooth_device_address_t *bd_addr, gboolean auto_connect); + +int _bt_disconnect_le_device(const bluetooth_device_address_t *bd_addr); + +int _bt_le_conn_update(unsigned char *device_address, + guint16 interval_min, guint16 interval_max, + guint16 latency, guint16 time_out); + +int _bt_connect_profile(char *address, char *uuid, + void *cb, gpointer func_data); + +int _bt_disconnect_profile(char *address, char *uuid, + void *cb, gpointer func_data); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/bt-service/include/bt-service-event.h b/bt-service/include/bt-service-event.h old mode 100644 new mode 100755 index 650c82a..ea0eca7 --- a/bt-service/include/bt-service-event.h +++ b/bt-service/include/bt-service-event.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -17,6 +21,7 @@ * */ + #ifndef _BT_SERVICE_EVENT_H_ #define _BT_SERVICE_EVENT_H_ @@ -32,14 +37,14 @@ int _bt_init_service_event_sender(void); void _bt_deinit_service_event_sender(void); int _bt_init_service_event_receiver(void); -void _bt_deinit_service_event_reciever(void); +void _bt_deinit_service_event_receiver(void); int _bt_opp_client_event_init(void); void _bt_opp_client_event_deinit(void); -void _bt_get_temp_remote_devinfo(void); - -void _bt_stop_discovery_timeout(void); +int _bt_send_hf_local_term_event(char *address); +int _bt_init_hf_local_term_event_sender(void); +void _bt_deinit_hf_local_term_event_sender(void); #ifdef __cplusplus } diff --git a/bt-service/include/bt-service-gap-agent.h b/bt-service/include/bt-service-gap-agent.h old mode 100644 new mode 100755 index edb21bc..610e13b --- a/bt-service/include/bt-service-gap-agent.h +++ b/bt-service/include/bt-service-gap-agent.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -75,6 +79,7 @@ typedef enum { GAP_AGENT_REJECT, GAP_AGENT_CANCEL, GAP_AGENT_TIMEOUT, + GAP_AGENT_ACCEPT_ALWAYS, } GAP_AGENT_ACCEPT_TYPE_T; struct _GapAgent { @@ -87,7 +92,7 @@ struct _GapAgentClass { GapAgent *_gap_agent_new(void); void _gap_agent_setup_dbus(GapAgent *agent, GAP_AGENT_FUNC_CB *func_cb, - const char *path); + const char *path, DBusGProxy *adapter); gboolean _gap_agent_register(GapAgent *agent); void _gap_agent_reset_dbus(GapAgent *agent); @@ -104,13 +109,20 @@ gboolean gap_agent_reply_authorize(GapAgent *agent, const guint accept, gboolean _gap_agent_exist_osp_server(GapAgent *agent, int type, char *uuid); +bt_agent_osp_server_t *_gap_agent_get_osp_server(GapAgent *agent, int type, + char *uuid); + gchar* _gap_agent_get_path(GapAgent *agent); gboolean _gap_agent_is_canceled(GapAgent *agent); +void _gap_agent_set_canceled(GapAgent *agent, gboolean value); + gboolean _gap_agent_register_osp_server(GapAgent *agent, const gint type, - const char *uuid); + const char *uuid, + const char *path, + int fd); gboolean _gap_agent_unregister_osp_server(GapAgent *agent, const gint type, diff --git a/bt-service/include/bt-service-headset-connection.h b/bt-service/include/bt-service-headset-connection.h new file mode 100755 index 0000000..3b86193 --- /dev/null +++ b/bt-service/include/bt-service-headset-connection.h @@ -0,0 +1,39 @@ +/* + * Bluetooth-frwk + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef __BT_SERVICE_HEADSET_CONNECTION__ +#define __BT_SERVICE_HEADSET_CONNECTION__ + +#undef LOG_TAG +#define LOG_TAG "BLUETOOTH_FRWK_SERVICE" +#define ERR(fmt, args...) SLOGE(fmt, ##args) + +#define CONNECT_TIMEOUT (3 * 1000) + +void _bt_headset_set_local_connection(gboolean value); +gboolean _bt_headset_get_local_connection(); +void _bt_start_timer_for_connection(char *remote_address, int connection_type); +void __bt_connection_manager_set_state(char *remote_address, int event); + + +#endif diff --git a/bt-service/include/bt-service-hid.h b/bt-service/include/bt-service-hid.h old mode 100644 new mode 100755 index 349982e..588897d --- a/bt-service/include/bt-service-hid.h +++ b/bt-service/include/bt-service-hid.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -17,6 +21,7 @@ * */ + #ifndef _BT_SERVICE_HID_H_ #define _BT_SERVICE_HID_H_ diff --git a/bt-service/include/bt-service-main.h b/bt-service/include/bt-service-main.h old mode 100644 new mode 100755 index 798da4b..632e67e --- a/bt-service/include/bt-service-main.h +++ b/bt-service/include/bt-service-main.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -17,6 +21,7 @@ * */ + #ifndef _BT_SERVICE_MAIN_H_ #define _BT_SERVICE_MAIN_H_ @@ -28,6 +33,8 @@ extern "C" { gboolean _bt_terminate_service(gpointer user_data); +gboolean _bt_reliable_terminate_service(gpointer user_data); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/bt-service/include/bt-service-mdm.h b/bt-service/include/bt-service-mdm.h new file mode 100755 index 0000000..94c9c77 --- /dev/null +++ b/bt-service/include/bt-service-mdm.h @@ -0,0 +1,69 @@ +/* + * Bluetooth-frwk + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#ifndef _BT_SERVICE_MDM_H_ +#define _BT_SERVICE_MDM_H_ + +#include +#include + +#include + +#include "bluetooth-api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + BT_MDM_NO_SERVICE, + BT_MDM_ALLOWED, + BT_MDM_RESTRICTED +} bt_mdm_status_e; + +void _bt_init_mdm_handle(void); + +void _bt_deinit_mdm_handle(void); + +int _bt_launch_mdm_popup(char *mode); + +bt_mdm_status_e _bt_check_mdm_allow_restriction(void); + +#ifdef MDM_PHASE_2 +bt_mdm_status_e _bt_check_mdm_desktop_connectivity_restriction(void); + +bt_mdm_status_e _bt_check_mdm_visible_restriction(void); + +bt_mdm_status_e _bt_check_mdm_limited_discoverable_mode(void); + +bt_mdm_status_e _bt_check_mdm_blacklist_devices(bluetooth_device_address_t *address); + +bt_mdm_status_e _bt_check_mdm_blacklist_uuid(char *uuid); +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_SERVICE_MDM_H_*/ + diff --git a/bt-service/include/bt-service-network.h b/bt-service/include/bt-service-network.h old mode 100644 new mode 100755 index 16536c6..199da3f --- a/bt-service/include/bt-service-network.h +++ b/bt-service/include/bt-service-network.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -17,6 +21,7 @@ * */ + #ifndef _BT_SERVICE_NETWORK_H_ #define _BT_SERVICE_NETWORK_H_ @@ -43,6 +48,13 @@ int _bt_network_connect(int request_id, int role, int _bt_network_disconnect(int request_id, bluetooth_device_address_t *device_address); +int _bt_network_server_disconnect(int request_id, + bluetooth_device_address_t *device_address); + +void *_bt_network_connected_profile(void *connection, unsigned char *address); + +int _bt_is_network_connected(void *connection, unsigned char *address, + gboolean *is_connected); #ifdef __cplusplus } diff --git a/bt-service/include/bt-service-obex-agent.h b/bt-service/include/bt-service-obex-agent.h old mode 100644 new mode 100755 index 703be7b..36dc0f6 --- a/bt-service/include/bt-service-obex-agent.h +++ b/bt-service/include/bt-service-obex-agent.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -110,6 +114,11 @@ gboolean bt_obex_agent_request(BtObexAgent *agent, const char *path, gboolean bt_obex_agent_authorize_push(BtObexAgent *agent, const char *path, DBusGMethodInvocation *context); +gboolean bt_obex_agent_authorize(BtObexAgent *agent, const char *path, + const char *bdaddress, const char *name, + const char *type, gint length, gint time, + DBusGMethodInvocation *context); + gboolean bt_obex_agent_progress(BtObexAgent *agent, const char *path, guint64 transferred, DBusGMethodInvocation *context); diff --git a/bt-service/include/bt-service-obex-server.h b/bt-service/include/bt-service-obex-server.h old mode 100644 new mode 100755 index a102569..571f1f2 --- a/bt-service/include/bt-service-obex-server.h +++ b/bt-service/include/bt-service-obex-server.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -17,6 +21,7 @@ * */ + #ifndef _BT_SERVICE_OBEX_SERVER_H_ #define _BT_SERVICE_OBEX_SERVER_H_ @@ -62,14 +67,18 @@ int _bt_obex_server_reject_connection(void); int _bt_obex_server_is_receiving(gboolean *receiving); -void _bt_obex_transfer_started(const char *transfer_path); void _bt_obex_transfer_progress(const char *transfer_path, int transferred); - void _bt_obex_transfer_completed(const char *transfer_path, gboolean success); +void _bt_obex_transfer_started(const char *transfer_path); + +void _bt_obex_check_pending_transfer(const char *address); + +void _bt_obex_transfer_connected(void); +void _bt_obex_transfer_disconnected(void); #ifdef __cplusplus } diff --git a/bt-service/include/bt-service-oob.h b/bt-service/include/bt-service-oob.h old mode 100644 new mode 100755 index aca9a4a..71dff87 --- a/bt-service/include/bt-service-oob.h +++ b/bt-service/include/bt-service-oob.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -17,6 +21,7 @@ * */ + #ifndef _BT_SERVICE_OOB_H_ #define _BT_SERVICE_OOB_H_ diff --git a/bt-service/include/bt-service-opp-client.h b/bt-service/include/bt-service-opp-client.h old mode 100644 new mode 100755 index 8f6b5a6..0205240 --- a/bt-service/include/bt-service-opp-client.h +++ b/bt-service/include/bt-service-opp-client.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -17,6 +21,7 @@ * */ + #ifndef _BT_SERVICE_OPP_CLIENT_H_ #define _BT_SERVICE_OPP_CLIENT_H_ @@ -31,24 +36,36 @@ extern "C" { #define BT_OBEX_CLIENT_AGENT_PATH "/org/obex/client_agent" +typedef enum { + BT_TRANSFER_STATUS_QUEUED = 0x00, + BT_TRANSFER_STATUS_STARTED, + BT_TRANSFER_STATUS_PROGRESS, + BT_TRANSFER_STATUS_COMPLETED, +} bt_transfer_status_t; + typedef struct { char path[BT_FILE_PATH_MAX]; } bt_file_path_t; typedef struct { DBusGProxy *proxy; + DBusGProxy *properties_proxy; char *transfer_name; char *file_name; + char *transfer_path; + bt_transfer_status_t transfer_status; gint64 size; } bt_transfer_info_t; typedef struct { int request_id; int result; + int file_count; int file_offset; char **file_name_array; char *session_path; + char *address; gboolean is_canceled; DBusGProxyCall *sending_proxy; @@ -62,6 +79,7 @@ typedef struct { int request_id; } bt_sending_data_t; + int _bt_opp_client_push_files(int request_id, DBusGMethodInvocation *context, bluetooth_device_address_t *remote_address, char **file_path, int file_count); @@ -72,13 +90,17 @@ int _bt_opp_client_cancel_all_transfers(void); int _bt_opp_client_is_sending(gboolean *sending); -void _bt_sending_files(); +void _bt_sending_files(void); -gboolean _bt_obex_client_progress(int transferred); +void _bt_opc_disconnected(const char *session_path); + +gboolean _bt_obex_client_progress(const char *transfer_path, int transferred); gboolean _bt_obex_client_started(const char *transfer_path); -gboolean _bt_obex_client_completed(gboolean success); +gboolean _bt_obex_client_completed(const char *transfer_path, gboolean success); + +void _bt_opp_client_check_pending_transfer(const char *address); #ifdef __cplusplus } diff --git a/bt-service/include/bt-service-pbap.h b/bt-service/include/bt-service-pbap.h new file mode 100755 index 0000000..3880972 --- /dev/null +++ b/bt-service/include/bt-service-pbap.h @@ -0,0 +1,63 @@ +/* + * Bluetooth-frwk + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef BT_SERVICE_PBAP_H +#define BT_SERVICE_PBAP_H + +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#undef LOG_TAG +#define LOG_TAG "BLUETOOTH_FRWK_SERVICE" +#define ERR(fmt, args...) SLOGE(fmt, ##args) + +int _bt_pbap_connect(const bluetooth_device_address_t *address); + +int _bt_pbap_disconnect(const bluetooth_device_address_t *address); + +int _bt_pbap_get_phonebook_size(const bluetooth_device_address_t *address, + int source, int type); + +int _bt_pbap_get_phonebook(const bluetooth_device_address_t *address, + int source, int type, bt_pbap_pull_parameters_t *app_param); + +int _bt_pbap_get_list(const bluetooth_device_address_t *address, int source, + int type, bt_pbap_list_parameters_t *app_param); + +int _bt_pbap_pull_vcard(const bluetooth_device_address_t *address, + int source, int type, bt_pbap_pull_vcard_parameters_t *app_param); + +int _bt_pbap_phonebook_search(const bluetooth_device_address_t *address, + int source, int type, bt_pbap_search_parameters_t *app_param); + +void _bt_pbap_obex_transfer_completed(const char *transfer_path, gboolean transfer_status); +#endif diff --git a/bt-service/include/bt-service-rfcomm-client.h b/bt-service/include/bt-service-rfcomm-client.h old mode 100644 new mode 100755 index 3465bcb..1bbd75b --- a/bt-service/include/bt-service-rfcomm-client.h +++ b/bt-service/include/bt-service-rfcomm-client.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, diff --git a/bt-service/include/bt-service-rfcomm-server.h b/bt-service/include/bt-service-rfcomm-server.h old mode 100644 new mode 100755 index 88e98c6..c238e43 --- a/bt-service/include/bt-service-rfcomm-server.h +++ b/bt-service/include/bt-service-rfcomm-server.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -60,9 +64,9 @@ int _bt_rfcomm_listen(int socket_fd, int max_pending, gboolean is_native); int _bt_rfcomm_is_uuid_available(char *uuid, gboolean *available); -int _bt_rfcomm_accept_connection(int server_fd, int request_id); +int _bt_rfcomm_accept_connection(void); -int _bt_rfcomm_reject_connection(int server_fd); +int _bt_rfcomm_reject_connection(void); int _bt_rfcomm_server_disconnect(int data_fd); diff --git a/bt-service/include/bt-service-util.h b/bt-service/include/bt-service-util.h old mode 100644 new mode 100755 index c22b374..d1984bd --- a/bt-service/include/bt-service-util.h +++ b/bt-service/include/bt-service-util.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -17,6 +21,7 @@ * */ + #ifndef _BT_SERVICE_UTIL_H_ #define _BT_SERVICE_UTIL_H_ diff --git a/bt-service/include/stacktrim.h b/bt-service/include/stacktrim.h old mode 100644 new mode 100755 index df18d59..07ca59d --- a/bt-service/include/stacktrim.h +++ b/bt-service/include/stacktrim.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, diff --git a/bt-service/marshal.list b/bt-service/marshal.list old mode 100644 new mode 100755 diff --git a/bt-service/mobile/stack_info b/bt-service/mobile/stack_info new file mode 100755 index 0000000..52a9c7a --- /dev/null +++ b/bt-service/mobile/stack_info @@ -0,0 +1,10 @@ +Bluez 5.16, +HFP AG 1.6 +HSP AG 1.2 +A2DP Source 1.2 +AVRCP Target 1.3 +GAVDP 1.2 +OPP 1.1 +PBAP PSE 1.1 +PAN NAP 1.0 +PAN USER 1.0 diff --git a/bt-service/org.projectx.bt.service b/bt-service/org.projectx.bt.service new file mode 100755 index 0000000..7444ab5 --- /dev/null +++ b/bt-service/org.projectx.bt.service @@ -0,0 +1,5 @@ +[D-BUS Service] +Name=org.projectx.bt +Exec=/bin/false +User=root +SystemdService=bluetooth-frwk.service diff --git a/bt-service/wearable/stack_info b/bt-service/wearable/stack_info new file mode 100755 index 0000000..ea7c1ea --- /dev/null +++ b/bt-service/wearable/stack_info @@ -0,0 +1,7 @@ +Bluez 5.16, +HFP 1.6 +HSP AG 1.2 +SPP 1.1 +A2DP Source 1.2 +AVRCP Target 1.3 +GAVDP 1.2 diff --git a/include/bluetooth-api.h b/include/bluetooth-api.h old mode 100644 new mode 100755 index d006dc7..6fdd6dc --- a/include/bluetooth-api.h +++ b/include/bluetooth-api.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -38,13 +42,18 @@ extern "C" { */ #define BLUETOOTH_ADDRESS_LENGTH 6 /**< This specifies bluetooth device address length */ +#define BLUETOOTH_VERSION_LENGTH_MAX 30 /**< This specifies bluetooth device version length */ #define BLUETOOTH_INTERFACE_NAME_LENGTH 16 #define BLUETOOTH_DEVICE_NAME_LENGTH_MAX 248 /**< This specifies maximum device name length */ +#define BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX 31 /**< This specifies maximum AD data length */ +#define BLUETOOTH_SCAN_RESP_DATA_LENGTH_MAX 31 /**< This specifies maximum LE Scan response data length */ +#define BLUETOOTH_MANUFACTURER_DATA_LENGTH_MAX 240 /**< This specifies maximum manufacturer data length */ #define BLUETOOTH_MAX_SERVICES_FOR_DEVICE 40 /**< This specifies maximum number of services a device can support */ #define BLUETOOTH_UUID_STRING_MAX 50 +#define BLUETOOTH_PATH_STRING 50 #define BLUETOOTH_OOB_DATA_LENGTH 16 /** @@ -54,6 +63,17 @@ extern "C" { #define RFCOMM_ROLE_CLIENT 2 /** + * This is RFCOMM default Channel Value + */ +#define RFCOMM_DEFAULT_PROFILE_CHANNEL 0 + +/** + * This is maximum length for search value string for PBAP Phonebook Search + */ +#define BLUETOOTH_PBAP_MAX_SEARCH_VALUE_LENGTH 100 + + +/** * This is Bluetooth error code */ #define BLUETOOTH_ERROR_BASE ((int)0) /**< Error code base */ @@ -135,6 +155,24 @@ extern "C" { #define BLUETOOTH_ERROR_ALREADY_INITIALIZED ((int)BLUETOOTH_ERROR_BASE - 0x23) /**< Already initialized */ +#define BLUETOOTH_ERROR_PERMISSION_DEINED ((int)BLUETOOTH_ERROR_BASE - 0x24) + /**< Permission deined */ + +#define BLUETOOTH_ERROR_ALREADY_DEACTIVATED ((int)BLUETOOTH_ERROR_BASE - 0x25) + /**< Nap already done */ + +#define BLUETOOTH_ERROR_NOT_INITIALIZED ((int)BLUETOOTH_ERROR_BASE - 0x26) + /**< Not initialized */ + +/** +* Device disconnect reason +*/ +typedef enum { + BLUETOOTH_DEVICE_DISCONNECT_UNKNOWN, + BLUETOOTH_DEVICE_DISCONNECT_TIMEOUT, + BLUETOOTH_DEVICE_DISCONNECT_LOCAL_HOST, + BLUETOOTH_DEVICE_DISCONNECT_REMOTE, +} bluetooth_device_disconnect_reason_t; /** * This is Bluetooth device address type, fixed to 6 bytes ##:##:##:##:##:## @@ -144,6 +182,22 @@ typedef struct { } bluetooth_device_address_t; /** + * This is Bluetooth device address type + */ +typedef enum +{ + BLUETOOTH_DEVICE_PUBLIC_ADDRESS = 0x00, + BLUETOOTH_DEVICE_RANDOM_ADDRESS +} bluetooth_device_address_type_t; + +/** + * This is Bluetooth version + */ +typedef struct { + char version[BLUETOOTH_VERSION_LENGTH_MAX + 1]; +} bluetooth_version_t; + +/** * This is Bluetooth device name type, maximum size of Bluetooth device name is 248 bytes */ typedef struct { @@ -151,6 +205,14 @@ typedef struct { } bluetooth_device_name_t; /** + * This is Bluetooth manufacturer specific data, maximum size of data is 240 bytes + */ +typedef struct { + int data_len; /**< manafacturer specific data length */ + char data[BLUETOOTH_MANUFACTURER_DATA_LENGTH_MAX]; +} bluetooth_manufacturer_data_t; + +/** * Adapter state */ typedef enum { @@ -161,6 +223,16 @@ typedef enum { } bluetooth_adapter_state_t; /** + * Adapter state + */ +typedef enum { + BLUETOOTH_ADAPTER_LE_DISABLED, /**< Bluetooth adapter le is disabled */ + BLUETOOTH_ADAPTER_LE_ENABLED, /**< Bluetooth adapter le is enabled */ + BLUETOOTH_ADAPTER_LE_CHANGING_ENABLE, /**< Bluetooth adapter le is currently enabling */ + BLUETOOTH_ADAPTER_LE_CHANGING_DISABLE, /**< Bluetooth adapter le is currently disabling */ +} bluetooth_adapter_le_state_t; + +/** * Discoverable mode */ typedef enum { @@ -192,8 +264,123 @@ typedef enum { BLUETOOTH_A2DP_SERVICE = 0x02, BLUETOOTH_HSP_SERVICE = 0x04, BLUETOOTH_HID_SERVICE = 0x08, + BLUETOOTH_NAP_SERVICE = 0x10, + BLUETOOTH_HFG_SERVICE = 0x20, + BLUETOOTH_GATT_SERVICE = 0x40, + BLUETOOTH_NAP_SERVER_SERVICE = 0x80, } bluetooth_service_type_t; +/** + * Service type + */ +typedef enum { + BLUETOOTH_DEV_CONN_DEFAULT = 0xFF, /* represents that connection + * type can both BR/EDR and LE */ + BLUETOOTH_DEV_CONN_BREDR = 0x00, + BLUETOOTH_DEV_CONN_LE = 0x01, +} bluetooth_conn_type_t; + +/** + * Service type + */ +typedef enum { + BLUETOOTH_CODEC_ID_CVSD = 0x01, + BLUETOOTH_CODEC_ID_MSBC = 0x02, +} bluetooth_codec_type_t; + +/** + * Service type + */ +typedef enum { + BLUETOOTH_HF_AUDIO_DISCONNECTED = 0x00, + BLUETOOTH_HF_AUDIO_CONNECTED = 0x01, +} bluetooth_hf_audio_connected_type_t; + +/** + * Advertising data + */ +typedef struct { + guint8 data[BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX]; +} bluetooth_advertising_data_t; + +/** + * Scan response data + */ +typedef struct { + guint8 data[BLUETOOTH_SCAN_RESP_DATA_LENGTH_MAX]; +} bluetooth_scan_resp_data_t; + +/** + * Advertising filter policy + */ +typedef enum { + BLUETOOTH_ALLOW_SCAN_CONN_ALL = 0x00, + BLUETOOTH_ALLOW_CONN_ALL_SCAN_WHITE_LIST = 0x01, + BLUETOOTH_ALLOW_SCAN_ALL_CONN_WHITE_LIST = 0x02, + BLUETOOTH_ALLOW_SCAN_CONN_WHITE_LIST = 0x03, +} bluetooth_advertising_filter_policy_t; + +/** + * Advertising type + */ +typedef enum { + BLUETOOTH_ADV_CONNECTABLE = 0x00, /* ADV_IND */ + BLUETOOTH_ADV_CONNECTABLE_DIRECT_HIGH = 0x01, /* ADV_DIRECT_IND, high duty cycle */ + BLUETOOTH_ADV_SCANNABLE = 0x02, /* ADV_SCAN_IND */ + BLUETOOTH_ADV_NON_CONNECTABLE = 0x03, /* ADV_NONCOND_IND */ + BLUETOOTH_ADV_CONNECTABLE_DIRECT_LOW = 0x04, /* ADV_DIRECT_IND, low duty cycle */ +} bluetooth_advertising_type_t; + +typedef enum +{ + BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_BROADCAST = 0x01, + BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ = 0x02, + BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE_NO_RESPONSE = 0x04, + BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE = 0x08, + BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY = 0x10, + BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE = 0x20, + BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_SIGNED_WRITE = 0x40, + BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_EXTENDED_PROPS = 0x80 +}bt_gatt_characteristic_property_t; + +/** +* Advertising parameters +*/ +typedef struct { + float interval_min; + float interval_max; + guint8 filter_policy; + guint8 type; +} bluetooth_advertising_params_t; + +/** +* LE Scan parameters +*/ +typedef struct { + int type; /**< passive 0, active 1 */ + float interval; /**< LE scan interval */ + float window; /**< LE scan window */ +} bluetooth_le_scan_params_t; + +/* + LE Connection Update + */ +typedef struct { + guint16 interval_min; + guint16 interval_max; + guint16 latency; + guint16 time_out; +} bluetooth_le_conn_update_t; + +/** + * Samsung XSAT Vendor dependent command + */ +typedef struct { + gint app_id; + char *message; +} bluetooth_vendor_dep_at_cmd_t; + + #define BLUETOOTH_EVENT_BASE ((int)(0x0000)) /**< No event */ #define BLUETOOTH_EVENT_GAP_BASE ((int)(BLUETOOTH_EVENT_BASE + 0x0010)) /**< Base ID for GAP Event */ @@ -216,6 +403,12 @@ typedef enum { /**< Base ID for Audio events */ #define BLUETOOTH_EVENT_HID_BASE ((int)(BLUETOOTH_EVENT_AUDIO_BASE + 0x0020)) /**< Base ID for HID events */ +#define BLUETOOTH_EVENT_ADVERTISING_BASE ((int)(BLUETOOTH_EVENT_HID_BASE + 0x0020)) + /**< Base ID for Advertising events */ +#define BLUETOOTH_EVENT_PBAP_CLIENT_BASE ((int)(BLUETOOTH_EVENT_ADVERTISING_BASE + 0x0020)) + /**< Base ID for PBAP Client events */ +#define BLUETOOTH_EVENT_AVRCP_CONTROL_BASE ((int)(BLUETOOTH_EVENT_PBAP_CLIENT_BASE + 0x0020)) + /**< Base ID for AVRCP events */ /** * Bluetooth event type @@ -225,6 +418,8 @@ typedef enum { BLUETOOTH_EVENT_ENABLED, /**< Bluetooth event adpater enabled */ BLUETOOTH_EVENT_DISABLED, /**< Bluetooth event adpater disabled */ + BLUETOOTH_EVENT_LE_ENABLED, /**< Bluetooth event adpater enabled */ + BLUETOOTH_EVENT_LE_DISABLED, /**< Bluetooth event adpater disabled */ BLUETOOTH_EVENT_LOCAL_NAME_CHANGED, /**< Bluetooth event local name changed*/ BLUETOOTH_EVENT_DISCOVERABLE_TIMEOUT_REQUESTED, /**< Bluetooth event Discoverable timeout requested*/ @@ -232,8 +427,10 @@ typedef enum { BLUETOOTH_EVENT_DISCOVERY_OPTION_REQUESTED, /**< Bluetooth event discovery option */ BLUETOOTH_EVENT_DISCOVERY_STARTED, /**< Bluetooth event discovery started */ BLUETOOTH_EVENT_DISCOVERY_FINISHED, /**< Bluetooth event discovery finished */ - BLUETOOTH_EVENT_REMOTE_DEVICE_FOUND, /**< Bluetooth event remote deice found */ + BLUETOOTH_EVENT_LE_DISCOVERY_STARTED, /**< Bluetooth event LE discovery started */ + BLUETOOTH_EVENT_LE_DISCOVERY_FINISHED, /**< Bluetooth event LE discovery finished */ + BLUETOOTH_EVENT_REMOTE_LE_DEVICE_FOUND, /**< Bluetooth event remote deice found (LE dev) */ BLUETOOTH_EVENT_REMOTE_DEVICE_NAME_UPDATED,/**< Bluetooth event remote device name updated*/ BLUETOOTH_EVENT_BONDING_FINISHED, /**< Bluetooth event bonding completed */ BLUETOOTH_EVENT_BONDED_DEVICE_REMOVED, /**< Bluetooth event bonding removed */ @@ -242,7 +439,11 @@ typedef enum { BLUETOOTH_EVENT_DEVICE_AUTHORIZED, /**< Bluetooth event authorize device */ BLUETOOTH_EVENT_DEVICE_UNAUTHORIZED, /**< Bluetooth event unauthorize device */ BLUETOOTH_EVENT_DISCOVERABLE_TIMEOUT_CHANGED, /**< Bluetooth event mode changed */ - BLUETOOTH_EVENT_REMOTE_DEVICE_DISAPPEARED, /**< Bluetooth event remote device disappeared*/ + BLUETOOTH_EVENT_CONNECTABLE_CHANGED, /**< Bluetooth event connectable changed */ + + BLUETOOTH_EVENT_RSSI_ENABLED, /**< Bluetooth event RSSI monitoring enabled */ + BLUETOOTH_EVENT_RSSI_ALERT, /**< Bluetooth event RSSI Alert */ + BLUETOOTH_EVENT_RAW_RSSI, /**< Bluetooth event Raw RSSI */ BLUETOOTH_EVENT_SERVICE_SEARCHED = BLUETOOTH_EVENT_SDP_BASE, /**< Bluetooth event serice search base id */ @@ -287,12 +488,22 @@ typedef enum { BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_PROGRESS,/* Obex Server transfer progress event*/ BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_COMPLETED,/* Obex Server transfer complete event*/ BLUETOOTH_EVENT_OBEX_SERVER_CONNECTION_AUTHORIZE, + BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_CONNECTED, /* Obex Transfer connected event */ + BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_DISCONNECTED, /* Obex Transfer disconnected event */ BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED = BLUETOOTH_EVENT_GATT_BASE, /**result); + device_info = (bluetooth_device_info_t *)param->param_data; + memcpy(&searched_device, &device_info->device_address, + sizeof(bluetooth_device_address_t)); + printf("dev [%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X]", + device_info->device_address.addr[0], + device_info->device_address.addr[1], + device_info->device_address.addr[2], + device_info->device_address.addr[3], + device_info->device_address.addr[4], + device_info->device_address.addr[5]); + break; + } + + case BLUETOOTH_EVENT_LE_DISCOVERY_FINISHED: + printf("BLUETOOTH_EVENT_LE_DISCOVERY_FINISHED, result[0x%04x]", param->result); + break; + } +} + +int ret = 0; +ret = bluetooth_start_discovery(); + +@endcode + * + */ +int bluetooth_start_le_discovery(void); + +/** + * @fn int bluetooth_stop_le_discovery (void) + * @brief Cancel the on-going device LE discovery operation + * + * + * This function stops the on-going device discovery operation. This API has to be called after the + * bluetooth_start_le_discovery API and before the BLUETOOTH_EVENT_LE_DISCOVERY_FINISHED event comes of + * the bluetooth_start_le_discovery API + * + * + * This function is a asynchronous call. + * If the call is success to cancel discovey then the application will receive + * BLUETOOTH_EVENT_LE_DISCOVERY_FINISHED event through registered callback function + * with an error code BLUETOOTH_ERROR_CANCEL. In the case of failure the error code will be + * BLUETOOTH_ERROR_NONE + * + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is not enabled \n + * BLUETOOTH_ERROR_NOT_IN_OPERATION - No Discovery operation in progess to cancel \n + * BLUETOOTH_ERROR_ACCESS_DENIED - Currently in discovery but it is requested from + other application \n + * BLUETOOTH_ERROR_INTERNAL - Internel IPC error \n + * @remark None + * @see bluetooth_start_discovery +@code +void bt_event_callback(int event, bluetooth_event_param_t *param) +{ + switch(event) + { + case BLUETOOTH_EVENT_LE_DISCOVERY_FINISHED: + TC_PRT("BLUETOOTH_EVENT_LE_DISCOVERY_FINISHED, result[0x%04x]", param->result); + break; + } +} + +.. + +int ret = 0; + +ret = bluetooth_stop_le_discovery(); +@endcode + */ +int bluetooth_stop_le_discovery(void); + +/** * @fn int bluetooth_is_discovering(void) * @brief Check for the device discovery is in-progress or not. * @@ -1550,6 +2268,71 @@ ret = bluetooth_is_discovering (); int bluetooth_is_discovering(void); /** + * @fn int bluetooth_is_le_discovering(void) + * @brief Check for the device LE discovery is in-progress or not. + * + * This API is used to check the current status of the LE Discovery operation.If discovery is in\ + * progress normally other operations are not allowed. + * If a device discovery is in progress, we have to either cancel the discovery operation or wait + * for the BLUETOOTH_EVENT_LE_DISCOVERY_FINISHED + * event before performing other operations. This API is used to get for the current discovery + * operation status and using bluetooth_stop_le_discovery() + * we can cancell the ongoing LE discovery process. + * Before calling this API, make sure that the adapter is enabled. There is no callback event for + * this API. + * + * This function checks whether the device LE discovery is started or not. + * + * This function is a synchronous call. + * + * + * @return BLUETOOTH_ERROR_NONE - Discovery is not in progress \n + * BLUETOOTH_ERROR_NONE+1 - Discovery in progress \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is not enabled \n + * + * @remark None + * @see bluetooth_start_le_discovery, bluetooth_stop_le_discovery + +@code +int ret = 0; +ret = bluetooth_is_le_discovering (); +@endcode + */ +int bluetooth_is_le_discovering(void); + +/** + * @fn int bluetooth_enable_rssi(const bluetooth_device_address_t *remote_address, + int link_type, bt_rssi_threshold_t rssi_threshold) + * @brief Enable RSSI monitoring + * + * This function enables RSSI monitoring and sets threshold for a connection + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * + * @remark None + * @see bluetooth_get_rssi_strength + */ +int bluetooth_enable_rssi(const bluetooth_device_address_t *remote_address, + int link_type, bt_rssi_threshold_t *rssi_threshold); + +/** + * @fn int bluetooth_get_rssi_strength(const bluetooth_device_address_t *remote_address, int link_type) + * @brief Gets Raw RSSI signal Strength + * + * This function gives the Raw RSSI signal strength for a connection. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * + * @remark None + * @see bluetooth_enable_rssi + */ +int bluetooth_get_rssi_strength(const bluetooth_device_address_t *remote_address, int link_type); + +int bluetooth_set_connectable(gboolean is_connectable); + +int bluetooth_is_connectable(gboolean *is_connectable); + +/** * @fn int bluetooth_bond_device(const bluetooth_device_address_t *device_address) * @brief Initiate a bonding process * @@ -1634,6 +2417,52 @@ ret = bluetooth_bond_device(&device_address); int bluetooth_bond_device(const bluetooth_device_address_t *device_address); /** + * @fn int bluetooth_bond_device_by_type(const bluetooth_device_address_t *device_address, + * bluetooth_conn_type_t conn_type) + * @brief Initiate a bonding process + * + * + * This function initiates a bonding procedure with a peer device on the basis of connection type (BLE or BREDR). + * The bonding procedure enables authentication and optionally encryption on the Bluetooth link. + * + * Bonding is applied to the discovered device to which we need a secure connection. We cannot + * inititate the bonding request to the devices already in the paired list. + * + * Usually we call this API after the device discovery. + * This function is a asynchronous call. + * + * Response will be received through BLUETOOTH_EVENT_BONDING_FINISHED event. It can any of the below + * mentioed result code + * BLUETOOTH_ERROR_PARING_FAILED - Pairing faied \n + * BLUETOOTH_ERROR_ACCESS_DENIED - Authetication rejected \n + * BLUETOOTH_ERROR_CANCEL_BY_USER - Cancelled by the user \n + * BLUETOOTH_ERROR_PARING_FAILED - Pairing failed \n + * BLUETOOTH_ERROR_TIMEOUT - Timeout has haapened \n + * + * If the remote user is not responding with in a specific time(60 seconds), then a timeout happens + * and BLUETOOTH_EVENT_BONDING_FINISHED callback event is called with and BLUETOOTH_ERROR_TIMEOUT + * result code + * + * The bonding operation can be cancelled by calling bluetooth_cancel_bonding(). + * + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid parameter \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is not enabled \n + * BLUETOOTH_ERROR_DEVICE_BUSY - Adapter is busy or Discovery is in Progress \n + * BLUETOOTH_ERROR_INVALID_DATA - Invalid BD address \n + * @exception None + * @param[in] device_address This indicates an address of the device with which pairing + * should be initiated + * @param[in] conn_type This Indicates the connection type to be used for pairing in case of + * dual mode devices + * @remark None + * @see bluetooth_cancel_bonding + */ +int bluetooth_bond_device_by_type(const bluetooth_device_address_t *device_address, + bluetooth_conn_type_t conn_type); + +/** * @fn int bluetooth_cancel_bonding(void) * @brief Cancel the on-going bonding process * @@ -2230,7 +3059,7 @@ int bluetooth_rfcomm_listen(int socket_fd, int max_pending_connection); * @remark None * @see bluetooth_rfcomm_reject_connection */ -int bluetooth_rfcomm_accept_connection(int server_fd, int *client_fd); +int bluetooth_rfcomm_accept_connection(int server_fd); /** * @fn int bluetooth_rfcomm_reject_connection() @@ -2425,6 +3254,8 @@ int bluetooth_rfcomm_write(int fd, const char *buf, int length); * @remark None */ gboolean bluetooth_rfcomm_is_client_connected(void); +int bluetooth_rfcomm_client_is_connected(bluetooth_device_address_t *device_address, gboolean *connected); +int bluetooth_rfcomm_server_is_connected(bluetooth_device_address_t *device_address, gboolean *connected); /** * @fn int bluetooth_network_activate_server(void) @@ -2511,6 +3342,26 @@ int bluetooth_network_connect(const bluetooth_device_address_t *device_address, */ int bluetooth_network_disconnect(const bluetooth_device_address_t *device_address); +/** + * @fn int bluetooth_network_server_disconnect(const bluetooth_device_address_t *device_address) + * @brief Disconnect the device from the network + * + * This function is an asynchronous call. + * The network server disconnect request is responded by + * BLUETOOTH_EVENT_NETWORK_SERVER_DISCONNECTED event. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid parameter \n + * BLUETOOTH_ERROR_INTERNAL - Internal Error \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Not enabled \n + * + * @exception None + * @param[in] device_address This indicates an address of the connected client device + * @remark None + * @see bluetooth_network_activate_server + */ +int bluetooth_network_server_disconnect(const bluetooth_device_address_t *device_address); + /*HDP - API's*/ /** @@ -2687,7 +3538,6 @@ int bluetooth_opc_init(void); * BLUETOOTH_ERROR_INTERNAL - Internal Error \n * BLUETOOTH_ERROR_NO_RESOURCES - Not resource available \n * BLUETOOTH_ERROR_IN_PROGRESS -Already one push in progress \n - * BLUETOOTH_ERROR_ACCESS_DENIED - Not allowed by MDM policy \n * * @exception None * @param[in] device_address The remote device Bd address. @@ -3245,6 +4095,31 @@ int bluetooth_gatt_get_characteristics_property(const char *char_handle, bt_gatt_char_property_t *characteristic); /** + * @fn int bluetooth_gatt_get_char_descriptor_property(const char *char_handle, + * bt_gatt_char_property_t *characteristic); + * + * @brief Provides characteristic descriptor value along with its UUID. + * + * This function is a synchronous call. + * The output parameter needs to be freed by calling bluetooth_gatt_free_desc_property() + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INTERNAL - Internal Error \n + * BLUETOOTH_ERROR_INVALID_PARAM -Invalid Parameters \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is disabled \n + * + * @exception None + * @param[in] desc_handle - Handle for Characteristic descriptor. + * @param[out] descriptor - Structure containing remote characteristic descriptor property. + * + * @remark None + * @see bluetooth_gatt_free_desc_property() + */ +int bluetooth_gatt_get_char_descriptor_property(const char *desc_handle, + bt_gatt_char_descriptor_property_t *descriptor); + + +/** * @fn int bluetooth_gatt_set_characteristics_value(const char *char_handle, * const guint8 *value, int length) * @@ -3269,13 +4144,12 @@ int bluetooth_gatt_set_characteristics_value(const char *char_handle, const guint8 *value, int length); /** - * @fn int bluetooth_gatt_get_service_from_uuid(bluetooth_device_address_t *address, - * const char *service_uuid, - * bt_gatt_service_property_t *service) + * @fn int bluetooth_gatt_set_characteristics_value_request(const char *char_handle, + * const guint8 *value, int length) * - * @brief Gets the service property from a device based on a particular uuid + * @brief Set characteristic value request. * - * This function is a synchronous call. + * This function is an asynchronous call. * * @return BLUETOOTH_ERROR_NONE - Success \n * BLUETOOTH_ERROR_INTERNAL - Internal Error \n @@ -3283,12 +4157,57 @@ int bluetooth_gatt_set_characteristics_value(const char *char_handle, * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is disabled \n * * @exception None - * @param[in] address - BD address of the remote device - * @param[in] service_uuid - uuid of the service. - * @param[out] service - Structure containing the service property. - * - * @remark None - * @see None + * @param[in] char_handle - Handle for Characteristic property. + * @param[in] value - New value to set for characteristic property. + * @param[in] length - Length of the value to be set. + * + * @remark None + * @see None + */ +int bluetooth_gatt_set_characteristics_value_request(const char *char_handle, + const guint8 *value, int length); + +/** + * @fn int bluetooth_gatt_read_characteristic_value(const char *char_handle) + * + * @brief Read characteristic value. + * + * This function is a asynchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INTERNAL - Internal Error \n + * BLUETOOTH_ERROR_INVALID_PARAM -Invalid Parameters \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is disabled \n + * + * @exception None + * @param[in] char_handle - Handle for Characteristic property. + * + * @remark None + * @see None + */ +int bluetooth_gatt_read_characteristic_value(const char *char_handle); + +/** + * @fn int bluetooth_gatt_get_service_from_uuid(bluetooth_device_address_t *address, + * const char *service_uuid, + * bt_gatt_service_property_t *service) + * + * @brief Gets the service property from a device based on a particular uuid + * + * This function is a synchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INTERNAL - Internal Error \n + * BLUETOOTH_ERROR_INVALID_PARAM -Invalid Parameters \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is disabled \n + * + * @exception None + * @param[in] address - BD address of the remote device + * @param[in] service_uuid - uuid of the service. + * @param[out] service - Structure containing the service property. + * + * @remark None + * @see None */ int bluetooth_gatt_get_service_from_uuid(bluetooth_device_address_t *address, const char *service_uuid, @@ -3376,6 +4295,689 @@ int bluetooth_gatt_free_service_property(bt_gatt_service_property_t *svc_pty); int bluetooth_gatt_free_char_property(bt_gatt_char_property_t *char_pty); /** + * @fn int bluetooth_gatt_free_desc_property(bt_gatt_char_descriptor_property_t *desc_pty); + * + * @brief Releases the memory allocated by bluetooth_gatt_get_char_descriptor_property() + * + * This function is a synchronous call. + * The input parameter is obtained by calling bluetooth_gatt_get_char_descriptor_property() + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INVALID_PARAM -Invalid Parameters \n + * + * @exception None + * @param[in] desc_pty - GATT characteristics descriptor property structure. + * + * @remark None + * @see bluetooth_gatt_get_char_descriptor_property() + */ + int bluetooth_gatt_free_desc_property(bt_gatt_char_descriptor_property_t *desc_pty); + + + int bluetooth_connect_le(const bluetooth_device_address_t *device_address, gboolean auto_connect); + + int bluetooth_disconnect_le(const bluetooth_device_address_t *device_address); + + /** + * @fn int bluetooth_gatt_discover_characteristic_descriptor(const char *characteristic_handle); + * + * @brief Discovers the characteristic descriptor value of a characteristic within its definition, asynchronously + * + * The input parameter is obtained by calling bluetooth_gatt_get_characteristics_property() + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INVALID_PARAM -Invalid Parameters \n + * + * @exception None + * @param[in] characteristic_handle - The characteristic handle for which characteristic descriptor has to be discovered. + * + * @remark None + */ +int bluetooth_gatt_discover_characteristic_descriptor(const char *characteristic_handle); + +/** + * @fn int bluetooth_gatt_read_descriptor_value(const char *desc_handle) + * + * @brief Read characteristic descriptor value. + * + * This function is a asynchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INTERNAL - Internal Error \n + * BLUETOOTH_ERROR_INVALID_PARAM -Invalid Parameters \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is disabled \n + * + * @exception None + * @param[in] desc_handle - Handle for Characteristic descriptor + * + * @remark None + * @see None + */ + int bluetooth_gatt_read_descriptor_value(const char *desc_handle); + +/** + * @fn int bluetooth_gatt_write_descriptor_value(const char *desc_handle, + * const guint8 *value, int length); + * + * @brief Set characteristic descriptor value. + * + * This function is a asynchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INTERNAL - Internal Error \n + * BLUETOOTH_ERROR_INVALID_PARAM -Invalid Parameters \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is disabled \n + * + * @exception None + * @param[in] desc_handle - Handle for Characteristic descriptor + * @param[in] value - New value to set for characteristic descriptor + * @param[in] length - Length of the value to be set. + * + * @remark None + * @see None + */ + int bluetooth_gatt_write_descriptor_value(const char *desc_handle, + const guint8 *value, int length); + +/* @fn int bluetooth_gatt_init(void) +* +* @brief Initializes the gatt service. +* +* This function is a synchronous call. +* @return BLUETOOTH_ERROR_NONE - Success \n +* BLUETOOTH_ERROR_INTERNAL - Internal Error \n +* BLUETOOTH_ERROR_INVALID_PARAM -Invalid Parameters \n +* BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is disabled \n +* +* @exception None +* @remark Adapter should be enabled +* @see bluetooth_gatt_deinit() +*/ +int bluetooth_gatt_init(void); + +/* @fn int bluetooth_gatt_init(void) +* +* @brief DeInitializes the gatt service. +* +* This function is a synchronous call. +* @return BLUETOOTH_ERROR_NONE - Success \n +* BLUETOOTH_ERROR_INTERNAL - Internal Error \n +* BLUETOOTH_ERROR_INVALID_PARAM -Invalid Parameters \n +* BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is disabled \n +* +* @exception None +* @remark Adapter should be enabled +* @see bluetooth_gatt_init() +*/ +int bluetooth_gatt_deinit(void); + +/* @fn int bluetooth_gatt_add_service(const char *svc_uuid, + unsigned char **svc_path) +* +* @brief Exports a new gatt service to the service interface. +* +* This function is a synchronous call. +* +* @return BLUETOOTH_ERROR_NONE - Success \n +* BLUETOOTH_ERROR_INTERNAL - Internal Error \n +* BLUETOOTH_ERROR_INVALID_PARAM -Invalid Parameters \n +* BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is disabled \n +* +* @exception None +* @param[in] svc_uuid Gatt service uuid. +* @param[out] svc_path service object path of the exported service. +* @remark Adapter should be enabled +* @see bluetooth_gatt_init() +*/ +int bluetooth_gatt_add_service(const char *svc_uuid, + char **svc_path); + +/* @fn int bluetooth_gatt_add_new_characteristic( + const char *svc_path, const char *char_uuid, + bt_gatt_characteristic_property_t *properties, + int flags_length, char **char_path);; +* +* @brief Exports a new gatt characteristic to the characteristic interface. +* +* This function is a synchronous call. +* @return BLUETOOTH_ERROR_NONE - Success \n +* BLUETOOTH_ERROR_INTERNAL - Internal Error \n +* BLUETOOTH_ERROR_INVALID_PARAM -Invalid Parameters \n +* BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is disabled \n +* @exception None +* @param[in] svc_path service object path of the exported service. +* @param[in] char_uuid Gatt service uuid. +* @param[in] properties GATT characteristic properties. +* @param[out] char_path characteristic object path of the exported characteristic. +* +* @remark Adapter should be enabled +* @see bluetooth_gatt_add_service() +*/ +int bluetooth_gatt_add_new_characteristic( + const char *svc_path, const char *char_uuid, + bt_gatt_characteristic_property_t properties, + char **char_path); + +/* @fn bluetooth_gatt_set_characteristic_value( + const char *characteristic, const char *char_value, + int value_length); +* +* @brief adds gatt charactertisic value to the given charactertistic path. +* +* This function is a synchronous call. +* @return BLUETOOTH_ERROR_NONE - Success \n +* BLUETOOTH_ERROR_INTERNAL - Internal Error \n +* BLUETOOTH_ERROR_INVALID_PARAM -Invalid Parameters \n +* BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is disabled \n +* @exception None +* @param[in] char_value Value of the GATT characteristic to be added. +* @param[in] value_length length of the chantacteristic value.. +* @param[out] characteristic characteristic object path.. +* +* @remark Adapter should be enabled +* @see bluetooth_gatt_add_service() +*/ +int bluetooth_gatt_set_characteristic_value( + const char *characteristic, const char *char_value, + int value_length); + +/* @fn int bluetooth_gatt_add_descriptor(const char *desc_uuid, + const char *desc_value, int value_length, + const char *permissions, const char *char_path, + char **desc_path); +* +* @brief Exports a new gatt descriptor to the descriptor interface. +* +* This function is a synchronous call. +* +* @return BLUETOOTH_ERROR_NONE - Success \n +* BLUETOOTH_ERROR_INTERNAL - Internal Error \n +* BLUETOOTH_ERROR_INVALID_PARAM -Invalid Parameters \n +* BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is disabled \n +* +* @exception None +* @param[in] desc_uuid Gatt descriptor uuid. +* @param[in] desc_value GATT descriptor value. +* @param[in] value_length Length of GATT descriptor value. +* @param[in] permissions descriptor permissions. +* @param[in] char_path characteristics object path of the exported character. +* +* @remark Adapter should be enabled +* @see bluetooth_gatt_add_service() +* @see bluetooth_gatt_add_characteristics() +*/ +int bluetooth_gatt_add_descriptor(const char *char_path, + const char *desc_uuid, + char **desc_path); + +/* @fn int bluetooth_gatt_set_descriptor_value( + const char *desc_path, const char *desc_value, + int value_length); +* +* @brief Adds value to the given descriptor handle. +* +* This function is a synchronous call. +* +* @return BLUETOOTH_ERROR_NONE - Success \n +* BLUETOOTH_ERROR_INTERNAL - Internal Error \n +* BLUETOOTH_ERROR_INVALID_PARAM -Invalid Parameters \n +* BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is disabled \n +* +* @exception None +* @param[in] desc_value GATT descriptor value. +* @param[in] value_length Length of GATT descriptor value. +* @param[in] desc_path descriptor path to which the value needs to be added. +* +* @remark Adapter should be enabled +* @see bluetooth_gatt_add_service() +* @see bluetooth_gatt_add_characteristics() +*/ +int bluetooth_gatt_set_descriptor_value( + const char *desc_path, const char *desc_value, + int value_length); + +/* @fn int bluetooth_gatt_get_service(const char *svc_uuid); +* +* @brief Reads the Service registered on manager interface. +* +* This function is a synchronous call. +* +* @return BLUETOOTH_ERROR_NONE - Success \n +* BLUETOOTH_ERROR_INTERNAL - Internal Error \n +* BLUETOOTH_ERROR_INVALID_PARAM -Invalid Parameters \n +* BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is disabled \n +* +* @exception None +* @param[in] svc_uuid Gatt Service uuid. +* +* @remark Adapter should be enabled and service should be registered. +* @see bluetooth_gatt_register_service() +*/ +int bluetooth_gatt_get_service(const char *svc_uuid); + +/* @fn int bluetooth_gatt_register_service(const char *svc_path) +* +* @brief Registers the given service path with the bluez gatt server. +* +* This function is a synchronous call. +* +* @return BLUETOOTH_ERROR_NONE - Success \n +* BLUETOOTH_ERROR_INTERNAL - Internal Error \n +* BLUETOOTH_ERROR_INVALID_PARAM -Invalid Parameters \n +* BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is disabled \n +* +* @exception None +* @param[in] svc_path service object path of the exported service. +* +* @remark Adapter should be enabled +* @see bluetooth_gatt_add_service() +* @see bluetooth_gatt_add_characteristics() +* @see bluetooth_gatt_add_descriptor() +*/ +int bluetooth_gatt_register_service(const char *svc_path); + +/* @fn int bluetooth_gatt_unregister_service(const char *svc_path) +* +* @brief Removes(unregister) service from the bluez gatt server db. +* +* This function is a synchronous call. +* +* @return BLUETOOTH_ERROR_NONE - Success \n +* BLUETOOTH_ERROR_INTERNAL - Internal Error \n +* BLUETOOTH_ERROR_INVALID_PARAM -Invalid Parameters \n +* BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is disabled \n +* +* @exception None +* @param[in] svc_path service object path of the exported service. +* +* @remark Adapter should be enabled +* @see bluetooth_gatt_add_service() +* @see bluetooth_gatt_add_characteristics() +* @see bluetooth_gatt_add_descriptor() +* @see bluetooth_gatt_register_service() +*/ +int bluetooth_gatt_unregister_service(const char *svc_path); + +/* @fn int bluetooth_gatt_delete_services(void) +* +* @brief deletes (unregisters) all services from the gatt server database.. +* +* This function is a synchronous call. +* +* @return BLUETOOTH_ERROR_NONE - Success \n +* BLUETOOTH_ERROR_INTERNAL - Internal Error \n +* BLUETOOTH_ERROR_INVALID_PARAM -Invalid Parameters \n +* BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is disabled \n +* +* @exception None +* +* @remark Adapter should be enabled +* @see bluetooth_gatt_add_service() +* @see bluetooth_gatt_add_characteristics() +* @see bluetooth_gatt_add_descriptor() +* @see bluetooth_gatt_register_service() +* @see bluetooth_gatt_unregister_service() +*/ +int bluetooth_gatt_delete_services(void); + +/* @fn int bluetooth_gatt_update_characteristic(void) +* +* @brief updates the given characteristic with a new value +* +* This function is a synchronous call. +* +* @return BLUETOOTH_ERROR_NONE - Success \n +* BLUETOOTH_ERROR_INTERNAL - Internal Error \n +* BLUETOOTH_ERROR_INVALID_PARAM -Invalid Parameters \n +* BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is disabled \n +* +* @exception None +* +* @remark Adapter should be enabled +* @see bluetooth_gatt_add_service() +* @see bluetooth_gatt_add_characteristics() +* @see bluetooth_gatt_add_descriptor() +* @see bluetooth_gatt_register_service() +* @see bluetooth_gatt_unregister_service() +*/ +int bluetooth_gatt_update_characteristic(const char *char_path, + const char* char_value, int value_length); + +/** + * @fn int bluetooth_set_advertising(gboolean enable); + * + * @brief Set advertising status. + * + * This function is used to enable or disable LE advertising. + * Once advertising is enabled, Advertising data is transmitted in the advertising packets + * + * This function is a synchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is not enabled \n + * BLUETOOTH_ERROR_INTERNAL - Internal IPC error \n + * + * @exception None + * @param[in] enable - The status of advertising + * + * @remark None + * @see bluetooth_set_advertising_data + */ +int bluetooth_set_advertising(gboolean enable); + +/** + * @fn int bluetooth_set_custom_advertising(gboolean enable, float interval_min, float interval_max, + * guint8 filter_policy); + * + * @brief Set advertising status along with interval value. + * + * This function is used to enable or disable LE advertising. + * Interval_min and Interval_max is used to set the best advertising interval. + * Once advertising is enabled, Advertising data is transmitted in the advertising packets + * + * This function is a synchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is not enabled \n + * BLUETOOTH_ERROR_INTERNAL - Internal IPC error \n + * + * @exception None + * @param[in] enable - The status of advertising + * @param[in] interval_min - Minimum interval of advertising (msec) + * @param[in] interval_max - Maximum interval of advertising (msec) + * @param[in] filter_policy - Advertising filter policy + * + * @remark None + * @see bluetooth_set_advertising_data + */ +int bluetooth_set_custom_advertising(gboolean enable, + bluetooth_advertising_params_t *params); + +/** + * @fn int bluetooth_get_advertising_data(bluetooth_advertising_data_t *value, int *length); + * @brief Get the advertising data + * + * This function is used to get advertising data. + * Before calling this API, the adapter should be enabled. + * + * This function is a synchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is not enabled \n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid parameter (NULL buffer)\n + * BLUETOOTH_ERROR_INTERNAL - Internal IPC error \n + * + * @param[out] value - Advertising data structure. + * @param[out] length - The length of Advertising data. + * + * @remark None +@code +bluetooth_advertising_data_t *value = { {0} }; +int length; +int ret = 0; +ret = bluetooth_get_advertising_data(&value, &length); +@endcode + */ +int bluetooth_get_advertising_data(bluetooth_advertising_data_t *value, int *length); + +/** + * @fn int bluetooth_set_advertising_data(const bluetooth_advertising_data_t *value, int length); + * + * @brief Set advertising data with value + * + * This function is used to set advertising data and Maximum size of advertising data + * is 28 byte (Except Flag) + * + * This function is a synchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is not enabled \n + * BLUETOOTH_ERROR_INTERNAL - Internal IPC error \n + * + * @exception None + * @param[in] value - Advertising data structure. + * + * @remark None + */ +int bluetooth_set_advertising_data(const bluetooth_advertising_data_t *value, int length); + +/** + * @fn int bluetooth_get_scan_response_data(bluetooth_scan_resp_data_t *value, int *length); + * @brief Get the LE scan response data + * + * This function is used to get scan response data. + * Before calling this API, the adapter should be enabled. + * + * This function is a synchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is not enabled \n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid parameter (NULL buffer)\n + * BLUETOOTH_ERROR_INTERNAL - Internal IPC error \n + * + * @param[out] value - Scan response data structure. + * @param[out] length - The length of Scan response data. + * + * @remark None +@code +bluetooth_scan_resp_data_t *value = { {0} }; +int length; +int ret = 0; +ret = bluetooth_get_scan_response_data(&value, &length); +@endcode + */ +int bluetooth_get_scan_response_data(bluetooth_scan_resp_data_t *value, int *length); + +/** + * @fn int bluetooth_set_scan_response_data(const bluetooth_scan_resp_data_t *value, int length); + * + * @brief Set scan response data with value + * + * This function is used to set scan response data and Maximum size of scan response data is 31 byte + * + * This function is a synchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is not enabled \n + * BLUETOOTH_ERROR_INTERNAL - Internal IPC error \n + * + * @exception None + * @param[in] value - LE Scan response data structure. + * + * @remark None + */ +int bluetooth_set_scan_response_data(const bluetooth_scan_resp_data_t *value, int length); + +/** + * @fn int bluetooth_set_scan_parameters(bluetooth_le_scan_params_t *params); + * + * @brief Set scan interval and window + * + * This function is used to set LE scan interval and window size + * + * This function is a synchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is not enabled \n + * BLUETOOTH_ERROR_INTERNAL - Internal IPC error \n + * + * @exception None + * @param[in] interval - Interval of LE scan (msec) + * @param[in] window - Window size of LE scan (msec) + * + * @remark None + */ +int bluetooth_set_scan_parameters(bluetooth_le_scan_params_t *params); + +/** + * @fn int bluetooth_is_advertising(void) + * @brief Check for the advertising is in-progress or not. + * + * This API is used to check the current status of the advertising procedure. + * Before calling this API, make sure that the adapter is enabled. There is no callback event for + * this API. + * + * This function checks whether the advertising is started or not. + * + * This function is a synchronous call. + * + * @param[out] is_advertising The advertising status: (@c TRUE = in progress, @c false = not in progress) + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is not enabled \n + * + * @remark None + * @see bluetooth_set_advertising, bluetooth_set_custom_advertising + +@code +int ret; +gboolean is_advertising = 0; + +ret = bluetooth_is_advertising(&is_advertising); +@endcode + */ +int bluetooth_is_advertising(gboolean *is_advertising); + +/** + * @fn int bluetooth_add_white_list(bluetooth_device_address_t *address, bluetooth_device_address_type_t address_type) + * @brief Add LE device to white list + * + * This API is used to add LE device to white list + * Before calling this API, make sure that the adapter is enabled. There is no callback event for + * this API. + * + * + * This function is a synchronous call. + * + * @param[in] address The address of remote device + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is not enabled \n + * + * @remark None + * @see bluetooth_set_custom_advertising + */ +int bluetooth_add_white_list(bluetooth_device_address_t *address, bluetooth_device_address_type_t address_type); + +/** + * @fn int bluetooth_remove_white_list(bluetooth_device_address_t *address, bluetooth_device_address_type_t address_type) + * @brief Remove LE device from white list + * + * This API is used to remove LE device from white list + * Before calling this API, make sure that the adapter is enabled. There is no callback event for + * this API. + * + * + * This function is a synchronous call. + * + * @param[in] address The address of remote device + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is not enabled \n + * + * @remark None + * @see bluetooth_set_custom_advertising + */ +int bluetooth_remove_white_list(bluetooth_device_address_t *address, bluetooth_device_address_type_t address_type); + +/** + * @fn int bluetooth_clear_white_list(void) + * @brief Clear white list + * + * This API is used to clear white list + * Before calling this API, make sure that the adapter is enabled. There is no callback event for + * this API. + * + * + * This function is a synchronous call. + * + * @param[in] address The address of remote device + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is not enabled \n + * + * @remark None + * @see bluetooth_set_custom_advertising + */ +int bluetooth_clear_white_list(void); + +/** + * @fn int bluetooth_le_conn_update(bluetooth_device_address_t *address, + * const bluetooth_le_conn_update_t *parameters) + * @brief update connection paramter of LE connection. + * + * This function is a synchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INTERNAL - Internal Error \n + * + * @exception None + * @param[in] address - remote device address value. + * @param[in] parameters - new connection parameters. + * + * @remark None + * @see bluetooth_bond_device + */ +int bluetooth_le_conn_update(const bluetooth_device_address_t *address, + const bluetooth_le_conn_update_t *parameters); + + +/** + * @fn int bluetooth_enable_le_privacy(gboolean enable_privacy); + * + * @brief Enable/Disable LE Privacy feature. + * + * This function is used to enable or disable LE Privacy feature. + * Once Privacy feature is enabled, Adapter can use Random Address for more security. + * + * This function is a synchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is not enabled \n + * BLUETOOTH_ERROR_INTERNAL - Internal IPC error \n + * + * @exception None + * @param[in] enable_privacy - The status of Privacy feature to be activated/deactivated[True/False]. + * + * @remark None + */ +int bluetooth_enable_le_privacy(gboolean enable_privacy); + +int bluetooth_pbap_init(void); +int bluetooth_pbap_deinit(void); +int bluetooth_pbap_connect(const bluetooth_device_address_t *address); +int bluetooth_pbap_disconnect(const bluetooth_device_address_t *address); +int bluetooth_pbap_get_phonebook_size(const bluetooth_device_address_t *address, + bt_pbap_folder_t *folder); +int bluetooth_pbap_get_phonebook(const bluetooth_device_address_t *address, + bt_pbap_folder_t *folder, bt_pbap_pull_parameters_t *app_param); +int bluetooth_pbap_get_list(const bluetooth_device_address_t *address, + bt_pbap_folder_t *folder, bt_pbap_list_parameters_t *app_param); +int bluetooth_pbap_pull_vcard(const bluetooth_device_address_t *address, + bt_pbap_folder_t *folder, bt_pbap_pull_vcard_parameters_t *app_param); +int bluetooth_pbap_phonebook_search(const bluetooth_device_address_t *address, + bt_pbap_folder_t *folder, bt_pbap_search_parameters_t *app_param); + +/** + * @fn int bluetooth_set_manufacturer_data(const bluetooth_manufacturer_data_t *value); + * + * @brief Set manufacturer data with value + * + * This function is used to set manufacturer data. + * + * This function is a synchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is not enabled \n + * BLUETOOTH_ERROR_INTERNAL - Internal IPC error \n + * + * @exception None + * @param[in] value - Manufacturer data structure. + * + * @remark None + */ +int bluetooth_set_manufacturer_data(const bluetooth_manufacturer_data_t *value); +/** * @} */ diff --git a/include/bluetooth-audio-api.h b/include/bluetooth-audio-api.h old mode 100644 new mode 100755 index 88c318e..72d7df2 --- a/include/bluetooth-audio-api.h +++ b/include/bluetooth-audio-api.h @@ -1,13 +1,16 @@ /* - * bluetooth-frwk + * bluetooth-audio-api * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * GirishAshok Joshi * * 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 + * 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, @@ -184,6 +187,60 @@ int bluetooth_ag_get_headset_volume(unsigned int *speaker_gain); */ int bluetooth_ag_set_speaker_gain(unsigned int speaker_gain); +typedef struct { + int event; + int result; + void *param_data; + void *user_data; +} bt_hf_event_param_t; + +typedef void (*bt_hf_func_ptr) (int, bt_hf_event_param_t *, void *); + + +int bluetooth_hf_init(bt_hf_func_ptr cb, void *user_data); + +int bluetooth_hf_deinit(void); + +int bluetooth_hf_connect(bluetooth_device_address_t *remote_address); + +int bluetooth_hf_disconnect(bluetooth_device_address_t *remote_address); + +int bluetooth_hf_answer_call(); + +int bluetooth_hf_terminate_call(); + +int bluetooth_hf_initiate_call(char *number); + +int bluetooth_hf_voice_recognition(unsigned int status); + +int bluetooth_hf_audio_disconnect(void); + +int bluetooth_hf_set_speaker_gain(unsigned int speaker_gain); + +int bluetooth_hf_send_dtmf(char *dtmf); + +int bluetooth_hf_send_xsat_cmd(int app_id, char *xsat_cmd); + +int bluetooth_hf_swap_call(void); + +int bluetooth_hf_release_all_call(void); + +int bluetooth_hf_release_and_accept(void); + +int bluetooth_hf_join_call(void); + +int bluetooth_hf_get_call_list(void *call_list, bt_hf_call_status_info_t **call_status); + +int bluetooth_hf_free_call_list(bt_hf_call_list_s *call_list); + +int bluetooth_hf_request_call_list(bt_hf_call_list_s **call_list); + +int bluetooth_hf_get_codec(unsigned int *codec_id); + +int bluetooth_hf_get_audio_connected(unsigned int *audio_connected); + +int bluetooth_hf_is_hf_connected(gboolean *hf_connected); + #ifdef __cplusplus } #endif /*__cplusplus*/ diff --git a/include/bluetooth-hid-api.h b/include/bluetooth-hid-api.h old mode 100644 new mode 100755 index 3880d76..fbffc40 --- a/include/bluetooth-hid-api.h +++ b/include/bluetooth-hid-api.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, diff --git a/include/bluetooth-media-control.h b/include/bluetooth-media-control.h old mode 100644 new mode 100755 index 906be7c..1e69798 --- a/include/bluetooth-media-control.h +++ b/include/bluetooth-media-control.h @@ -1,13 +1,18 @@ /* - * bluetooth-frwk + * bluetooth-media-control + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * - *Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. * * 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 + * 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, @@ -24,27 +29,23 @@ extern "C" { #endif /*__cplusplus*/ -#include - #define BT_MEDIA_ERROR_NONE ((int)0) #define BT_MEDIA_ERROR_BASE ((int)0) #define BT_MEDIA_ERROR_INTERNAL ((int)BT_MEDIA_ERROR_BASE - 0x01) #define BT_MEDIA_ERROR_ALREADY_INITIALIZED ((int)BT_MEDIA_ERROR_BASE - 0x02) +#define BT_MEDIA_ERROR_NOT_CONNECTED ((int)BT_MEDIA_ERROR_BASE - 0x15) typedef enum { - PLAYBACKSTATUS = 0x1, + EQUALIZER = 0x01, + REPEAT, SHUFFLE, - LOOPSTATUS, + SCAN, POSITION, METADATA, - EQUALIZER = 0x02, /* bluez 4.101 */ - REPEAT, /* bluez 4.101 */ - SCAN, /* bluez 4.101 */ - STATUS, /* bluez 4.101 */ + STATUS } media_player_property_type; -/* bluez 4.101 */ typedef enum { EQUALIZER_OFF = 0x01, EQUALIZER_ON, @@ -55,28 +56,17 @@ typedef enum { REPEAT_MODE_OFF = 0x01, REPEAT_SINGLE_TRACK, REPEAT_ALL_TRACK, - REPEAT_GROUP, /* bluez 4.101 */ + REPEAT_GROUP, REPEAT_INVALID, } media_player_repeat_status; typedef enum { - STATUS_STOPPED = 0x00, - STATUS_PLAYING, - STATUS_PAUSED, - STATUS_FORWARD_SEEK, /* bluez 4.101 */ - STATUS_REVERSE_SEEK, /* bluez 4.101 */ - STATUS_ERROR, /* bluez 4.101 */ - STATUS_INVALID -} media_player_status; - -typedef enum { SHUFFLE_MODE_OFF = 0x01, SHUFFLE_ALL_TRACK, SHUFFLE_GROUP, SHUFFLE_INVALID, } media_player_shuffle_status; -/* bluez 4.101 */ typedef enum { SCAN_MODE_OFF = 0x01, SCAN_ALL_TRACK, @@ -84,30 +74,44 @@ typedef enum { SCAN_INVALID, } media_player_scan_status; +typedef enum { + STATUS_STOPPED = 0x00, + STATUS_PLAYING, + STATUS_PAUSED, + STATUS_FORWARD_SEEK, + STATUS_REVERSE_SEEK, + STATUS_ERROR, + STATUS_INVALID +} media_player_status; + +typedef enum { + PLAY = 0x01, + PAUSE, + STOP, + NEXT, + PREVIOUS, + FAST_FORWARD, + REWIND +} media_player_control_cmd; + typedef struct { const char *title; - const char **artists; + const char *artist; const char *album; - const char **genres; - unsigned int tracknumber; - const char *artist; /* bluez 4.101 */ - const char *genre; /* bluez 4.101 */ - unsigned int total_tracks; /* bluez 4.101 */ - unsigned int number; /* bluez 4.101 */ - unsigned int duration; + const char *genre; + unsigned int total_tracks; + unsigned int number; + int64_t duration; } media_metadata_attributes_t; typedef struct { - media_player_repeat_status loopstatus; - media_player_status playbackstatus; - gboolean shuffle_mode; - gint64 position; - media_metadata_attributes_t metadata; - media_player_equalizer_status equalizer; /* bluez 4.101 */ - media_player_repeat_status repeat; /* bluez 4.101 */ - media_player_shuffle_status shuffle; /* bluez 4.101 */ - media_player_scan_status scan; /* bluez 4.101 */ - media_player_status status; /* bluez 4.101 */ + media_player_equalizer_status equalizer; + media_player_repeat_status repeat; + media_player_shuffle_status shuffle; + media_player_scan_status scan; + media_player_status status; + unsigned int position; + media_metadata_attributes_t metadata; } media_player_settings_t; typedef struct { @@ -213,6 +217,123 @@ int bluetooth_media_player_change_property( int bluetooth_media_player_change_track( media_metadata_attributes_t *metadata); +/** + * @fn int bluetooth_media_control_init(media_cb_func_ptr callback_ptr, void *user_data) + * @brief Initialize AVRCP control and register the callback + * + * This function is a synchronous call. + * + * @param[in] callback_ptr - Callback function (AVRCP connected / Disconnected) + * @param[in] user_data - User data + * + * @return BT_MEDIA_ERROR_NONE - Success \n + * BT_MEDIA_ERROR_ALREADY_INITIALIZED - Already initialized \n + * BT_MEDIA_ERROR_INTERNAL - Internal error \n + * + * @remark None + * + */ +int bluetooth_media_control_init(media_cb_func_ptr callback_ptr, + void *user_data); + +/** + * @fn int bluetooth_media_control_deinit(void) + * @brief Deinitialize AVRCP Control and deregister callback + * + * This function is a synchronous call. + * + * @return BT_MEDIA_CONTROL_SUCCESS - Success \n + * BT_MEDIA_CONTROL_ERROR - Error \n + * + * @remark None + * + */ + int bluetooth_media_control_deinit(void); + +/** + * @brief The function bluetooth_media_control_connect is called to establish an AVRCP + * control role connection with the specified device. + * + * @param[in] remote_address Bluetooth device address. + * @return int Zero on Success or reason for error if any. + * + */ +int bluetooth_media_control_connect(bluetooth_device_address_t *remote_address); + +/** + * @brief The function bluetooth_media_control_disconnect is called to disconnect an + * existing AVRCP Control role connection with the specified device. + * + * @param[in] remote_address Bluetooth device address. + * @return int Zero on Success or reason for error if any. + * + */ +int bluetooth_media_control_disconnect(bluetooth_device_address_t *remote_address); + +/** + * @brief The function bluetooth_media_control_command is called to send + * the AVRCP Control command like Play, Pause, FF, Rewind to the target device. + * + * @param[in] type media_player_control_cmd. + * @return int Zero on Success or reason for error if any. + * + */ +int bluetooth_media_control_command(media_player_control_cmd type); + +/** + * @fn int bluetooth_media_control_set_property(media_player_property_type type, unsigned int value) + * @brief Notifies the remote bluetooth target with change in music control settings + * + * This function is a asynchronous call. + * No event for this api. + * + * @return BT_MEDIA_CONTROL_SUCCESS - Success \n + * BT_MEDIA_CONTROL_ERROR - Error \n + * + * @exception None + * @param[in] setting - The music control properties + * + * @remark None + * @see None + */ + int bluetooth_media_control_set_property(media_player_property_type type, unsigned int value); + +/** + * @fn int bluetooth_media_control_get_property(media_player_property_type type, unsigned int *value) + * @brief reads the setting of the remote bluetooth target with change in music control settings + * + * This function is a asynchronous call. + * No event for this api. + * + * @return BT_MEDIA_CONTROL_SUCCESS - Success \n + * BT_MEDIA_CONTROL_ERROR - Error \n + * + * @exception None + * @param[in] setting - The music control properties + * + * @remark None + * @see None + */ +int bluetooth_media_control_get_property(media_player_property_type type, unsigned int *value); + +/** + * @fn int bluetooth_media_control_get_track_info(media_metadata_attributes_t *metadata) + * @brief reads the track metadata from the remote target player. + * + * This function is a asynchronous call. + * No event for this api. + * + * @return BT_MEDIA_CONTROL_SUCCESS - Success \n + * BT_MEDIA_CONTROL_ERROR - Error \n + * + * @exception None + * @param[in] metadata - The music meta data information. + * + * @remark None + * @see None + */ + int bluetooth_media_control_get_track_info(media_metadata_attributes_t *metadata); + #ifdef __cplusplus } #endif /*__cplusplus*/ diff --git a/include/bluetooth-scmst-api.h b/include/bluetooth-scmst-api.h new file mode 100755 index 0000000..e01c650 --- /dev/null +++ b/include/bluetooth-scmst-api.h @@ -0,0 +1,30 @@ +/* + * bluetooth-scmst-api.h + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * + * 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 +#include + +int bluetooth_a2dp_set_content_protection(gboolean status); + + diff --git a/include/bluetooth-telephony-api.h b/include/bluetooth-telephony-api.h old mode 100644 new mode 100755 index 50582d1..b8e76f1 --- a/include/bluetooth-telephony-api.h +++ b/include/bluetooth-telephony-api.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-telephony * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * GirishAshok Joshi + * Chanyeol Park * * 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 + * 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, @@ -61,6 +65,8 @@ typedef void (*bt_telephony_func_ptr)(int, void *, void *); ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x0D) #define BLUETOOTH_TELEPHONY_ERROR_OPERATION_NOT_AVAILABLE \ ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x0E) +#define BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED \ + ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x0F) #define BT_ADDRESS_STR_LEN 18 #define BT_ADAPTER_PATH_LEN 50 @@ -115,7 +121,7 @@ typedef enum { CSD_CALL_STATUS_SWAP_INITIATED, } bt_telephony_call_status_t; -#define BLUETOOTH_EVENT_TYPE_TELEPHONY_BASE (unsigned int)(0x00100) +#define BLUETOOTH_EVENT_TYPE_TELEPHONY_BASE (unsigned int)(0x00500) typedef enum { BLUETOOTH_EVENT_TELEPHONY_ANSWER_CALL = BLUETOOTH_EVENT_TYPE_TELEPHONY_BASE, @@ -134,6 +140,7 @@ typedef enum { BLUETOOTH_EVENT_TELEPHONY_SET_SPEAKER_GAIN, BLUETOOTH_EVENT_TELEPHONY_SET_MIC_GAIN, BLUETOOTH_EVENT_TELEPHONY_NREC_CHANGED, + BLUETOOTH_EVENT_TELEPHONY_VENDOR_AT_CMD, } bluetooth_telephony_event_type; typedef enum { @@ -150,6 +157,7 @@ typedef enum { typedef struct { unsigned int call_id; bt_telephony_call_state_t call_status; + char *phone_number; } bt_telephony_call_status_info_t; /** @@ -304,6 +312,23 @@ gboolean bluetooth_telephony_is_sco_connected(void); int bluetooth_telephony_is_nrec_enabled(gboolean *status); /** + * @brief The function bluetooth_telephony_is_nrec_enabled to check + * for wide band speech status + * + * @return int Zero on Success or reason for error if any. + * + */ + int bluetooth_telephony_is_wbs_mode(gboolean *status); + +/** + * @brief This function send XSAT vendor specific AT command + * + * @return int Zero on Success or reason for error if any. + */ + int bluetooth_telephony_send_vendor_cmd(const char *cmd); + + +/** * @brief This function sends request to enable voice recognition feature * * @return int Zero on Success or reason for error if any. diff --git a/include/bt-internal-types.h b/include/bt-internal-types.h old mode 100644 new mode 100755 index abede65..71426a3 --- a/include/bt-internal-types.h +++ b/include/bt-internal-types.h @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -17,6 +21,7 @@ * */ + #ifndef _BT_INTERNAL_TYPES_H_ #define _BT_INTERNAL_TYPES_H_ @@ -45,8 +50,8 @@ typedef enum { typedef enum { BT_MANAGER_EVENT = 0x01, - BT_OBJECT_MANAGER_EVENT, BT_ADAPTER_EVENT, + BT_LE_ADAPTER_EVENT, BT_DEVICE_EVENT, BT_HID_EVENT, BT_NETWORK_EVENT, @@ -54,17 +59,28 @@ typedef enum { BT_AVRCP_EVENT, BT_OPP_CLIENT_EVENT, BT_OPP_SERVER_EVENT, + BT_PBAP_CLIENT_EVENT, BT_RFCOMM_CLIENT_EVENT, BT_RFCOMM_SERVER_EVENT, BT_AGENT_EVENT, + BT_OBJECT_MANAGER_EVENT, BT_MEDIA_TRANSFER_EVENT, + BT_HF_AGENT_EVENT, + BT_AVRCP_CONTROL_EVENT, /* Will be added */ } bt_event_type_t; typedef enum { + BT_OBEX_SERVER = 0x00, + BT_RFCOMM_SERVER = 0x01, +} bt_osp_server_type_t; + +typedef enum { BT_BLUEZ_SERVICE = 0x00, BT_OBEX_SERVICE, BT_AGENT_SERVICE, + BT_CORE_SERVICE, + BT_CHECK_PRIVILEGE, } bt_service_type_t; typedef enum { @@ -72,11 +88,21 @@ typedef enum { BT_RFCOMM_CHANNEL, } bt_rfcomm_connect_type_t; +typedef enum { + BT_ADAPTER_DISABLED = 0x00, + BT_ADAPTER_ENABLED, +} bt_adapter_status_t; + +typedef enum { + BT_ADAPTER_LE_DISABLED = 0x00, + BT_ADAPTER_LE_ENABLED, +} bt_adapter_le_status_t; + #define BT_ADDRESS_STR_LEN 18 #define BT_DBUS_TIMEOUT_MAX 50000 #define BT_SERVER_ACCEPT_TIMEOUT 2000 /* 2 seconds */ #define BT_FILE_PATH_MAX 256 -#define BT_NAME_MAX 256 +#define BT_META_DATA_MAX_LEN 512 + 1 #define BT_HFP_AUDIO_GATEWAY_UUID "0000111f-0000-1000-8000-00805f9b34fb" #define BT_A2DP_UUID "0000110D-0000-1000-8000-00805F9B34FB" @@ -98,26 +124,53 @@ typedef enum { #define BT_FUNC_AVRCP_BASE ((int)(BT_FUNC_OOB_BASE + 0x0020)) #define BT_FUNC_OPP_BASE ((int)(BT_FUNC_AVRCP_BASE + 0x0020)) #define BT_FUNC_RFCOMM_BASE ((int)(BT_FUNC_OPP_BASE + 0x0020)) +#define BT_FUNC_PBAP_BASE ((int)(BT_FUNC_RFCOMM_BASE + 0x0020)) +#define BT_FUNC_HDP_BASE ((int)(BT_FUNC_PBAP_BASE + 0x0020)) +#define BT_FUNC_GATT_BASE ((int)(BT_FUNC_HDP_BASE + 0x0020)) typedef enum { BT_CHECK_ADAPTER = BT_FUNC_BASE, BT_ENABLE_ADAPTER, BT_DISABLE_ADAPTER, + BT_RECOVER_ADAPTER, BT_SET_DISCOVERABLE_TIME, BT_GET_DISCOVERABLE_TIME, BT_IGNORE_AUTO_PAIRING, BT_GET_LOCAL_ADDRESS, + BT_GET_LOCAL_VERSION, BT_GET_LOCAL_NAME, BT_SET_LOCAL_NAME, BT_IS_SERVICE_USED, BT_GET_DISCOVERABLE_MODE, BT_SET_DISCOVERABLE_MODE, BT_START_DISCOVERY, + BT_START_CUSTOM_DISCOVERY, BT_CANCEL_DISCOVERY, + BT_START_LE_DISCOVERY, + BT_STOP_LE_DISCOVERY, BT_IS_DISCOVERYING, + BT_IS_LE_DISCOVERYING, + BT_ENABLE_RSSI, + BT_GET_RSSI, + BT_IS_CONNECTABLE, + BT_SET_CONNECTABLE, BT_GET_BONDED_DEVICES, BT_RESET_ADAPTER, + BT_SET_ADVERTISING, + BT_SET_CUSTOM_ADVERTISING, + BT_GET_ADVERTISING_DATA, + BT_SET_ADVERTISING_DATA, + BT_SET_SCAN_PARAMETERS, + BT_GET_SCAN_RESPONSE_DATA, + BT_SET_SCAN_RESPONSE_DATA, + BT_IS_ADVERTISING, + BT_SET_MANUFACTURER_DATA, + BT_LE_CONN_UPDATE, + BT_ADD_WHITE_LIST, + BT_REMOVE_WHITE_LIST, + BT_CLEAR_WHITE_LIST, BT_BOND_DEVICE = BT_FUNC_DEVICE_BASE, + BT_BOND_DEVICE_BY_TYPE, BT_CANCEL_BONDING, BT_UNBOND_DEVICE, BT_SEARCH_SERVICE, @@ -125,6 +178,7 @@ typedef enum { BT_GET_BONDED_DEVICE, BT_SET_ALIAS, BT_SET_AUTHORIZATION, + BT_UNSET_AUTHORIZATION, BT_IS_DEVICE_CONNECTED, BT_HID_CONNECT = BT_FUNC_HID_BASE, BT_HID_DISCONNECT, @@ -132,20 +186,30 @@ typedef enum { BT_NETWORK_DEACTIVATE, BT_NETWORK_CONNECT, BT_NETWORK_DISCONNECT, + BT_NETWORK_SERVER_DISCONNECT, BT_AUDIO_CONNECT = BT_FUNC_AUDIO_BASE, BT_AUDIO_DISCONNECT, BT_AG_CONNECT, BT_AG_DISCONNECT, BT_AV_CONNECT, BT_AV_DISCONNECT, + BT_HF_CONNECT, + BT_HF_DISCONNECT, BT_GET_SPEAKER_GAIN, BT_SET_SPEAKER_GAIN, + BT_SET_CONTENT_PROTECT, BT_OOB_READ_LOCAL_DATA = BT_FUNC_OOB_BASE, BT_OOB_ADD_REMOTE_DATA, BT_OOB_REMOVE_REMOTE_DATA, BT_AVRCP_SET_TRACK_INFO = BT_FUNC_AVRCP_BASE, BT_AVRCP_SET_PROPERTY, BT_AVRCP_SET_PROPERTIES, + BT_AVRCP_CONTROL_CONNECT, + BT_AVRCP_CONTROL_DISCONNECT, + BT_AVRCP_HANDLE_CONTROL, + BT_AVRCP_CONTROL_SET_PROPERTY, + BT_AVRCP_CONTROL_GET_PROPERTY, + BT_AVRCP_GET_TRACK_INFO, BT_OPP_PUSH_FILES = BT_FUNC_OPP_BASE, BT_OPP_CANCEL_PUSH, BT_OPP_IS_PUSHING_FILES, @@ -172,14 +236,35 @@ typedef enum { BT_RFCOMM_IS_UUID_AVAILABLE, BT_RFCOMM_ACCEPT_CONNECTION, BT_RFCOMM_REJECT_CONNECTION, + BT_PBAP_CONNECT = BT_FUNC_PBAP_BASE, + BT_PBAP_DISCONNECT, + BT_PBAP_GET_PHONEBOOK_SIZE, + BT_PBAP_GET_PHONEBOOK, + BT_PBAP_GET_LIST, + BT_PBAP_PULL_VCARD, + BT_PBAP_PHONEBOOK_SEARCH, + BT_ENABLE_ADAPTER_LE, + BT_DISABLE_ADAPTER_LE, + + BT_CONNECT_LE, + BT_DISCONNECT_LE, + BT_SET_LE_PRIVACY, + BT_HDP_CONNECT = BT_FUNC_HDP_BASE, + BT_HDP_DISCONNECT, + BT_HDP_SEND_DATA, + BT_GATT_GET_PRIMARY_SERVICES = BT_FUNC_GATT_BASE, + BT_GATT_DISCOVER_CHARACTERISTICS, + BT_GATT_SET_PROPERTY_REQUEST, + BT_GATT_READ_CHARACTERISTIC, + BT_GATT_DISCOVER_CHARACTERISTICS_DESCRIPTOR, } bt_function_t; typedef struct { - char title[BT_NAME_MAX]; - char artist[BT_NAME_MAX]; - char album[BT_NAME_MAX]; - char genre[BT_NAME_MAX]; + char title[BT_META_DATA_MAX_LEN]; + char artist[BT_META_DATA_MAX_LEN]; + char album[BT_META_DATA_MAX_LEN]; + char genre[BT_META_DATA_MAX_LEN]; unsigned int total_tracks; unsigned int number; unsigned int duration; @@ -190,12 +275,22 @@ typedef struct { /* Need to convert the design ID */ #define BT_STR_NOT_SUPPORT "Not support" +#ifndef TIZEN_WEARABLE #define BT_FILE_VISIBLE_TIME "file/private/libug-setting-bluetooth-efl/visibility_time" -#define BT_OFF_DUE_TO_FLIGHT_MODE "file/private/bt-service/flight_mode_deactivated" +#endif + +#define BT_OFF_DUE_TO_FLIGHT_MODE "file/private/bt-core/flight_mode_deactivated" +#define BT_OFF_DUE_TO_POWER_SAVING_MODE "file/private/bt-core/powersaving_mode_deactivated" +#define BT_OFF_DUE_TO_TIMEOUT "file/private/bt-service/bt_off_due_to_timeout" #define BT_EVENT_SERVICE "org.projectx.bt_event" +#define BT_HF_AGENT_SERVICE "org.bluez.HandsfreeAgent" +#define BT_HF_SERVICE_INTERFACE "org.tizen.HfApp" +#define BT_CORE_EVENT_INTERFACE "org.projectx.bt_core_event" +#define BT_HF_LOCAL_TERM_EVENT_INTERFACE "org.projectx.bt_hf_local_term" #define BT_ADAPTER_PATH "/org/projectx/bt/adapter" +#define BT_LE_ADAPTER_PATH "/org/projectx/bt/le/adapter" #define BT_DEVICE_PATH "/org/projectx/bt/device" #define BT_HID_PATH "/org/projectx/bt/hid" #define BT_HEADSET_PATH "/org/projectx/bt/headset" @@ -203,26 +298,52 @@ typedef struct { #define BT_NETWORK_PATH "/org/projectx/bt/newtork" #define BT_OPP_CLIENT_PATH "/org/projectx/bt/opp_client" #define BT_OPP_SERVER_PATH "/org/projectx/bt/opp_server" +#define BT_PBAP_CLIENT_PATH "/org/projectx/bt/pbap_client" #define BT_RFCOMM_CLIENT_PATH "/org/projectx/bt/rfcomm_client" #define BT_RFCOMM_SERVER_PATH "/org/projectx/bt/rfcomm_server" - +#define BT_HF_AGENT_PATH "/org/bluez/handsfree_agent" +#define BT_CORE_EVENT_PATH "/org/projectx/bt/bt_core" +#define BT_HF_LOCAL_TERM_EVENT_PATH "/org/projectx/bt/hf_local_term" +#define BT_AVRCP_CONTROL_PATH "/org/projectx/bt/avrcp_control" #define BT_ENABLED "Enabled" #define BT_DISABLED "Disabled" +#define BT_LE_ENABLED "LeEnabled" +#define BT_LE_DISABLED "LeDisabled" #define BT_DISCOVERABLE_MODE_CHANGED "DiscoverableModeChanged" #define BT_DISCOVERABLE_TIMEOUT_CHANGED "DiscoverableTimeoutChanged" +#define BT_CONNECTABLE_CHANGED "ConnectableChanged" #define BT_ADAPTER_NAME_CHANGED "AdapterNameChanged" #define BT_DISCOVERY_STARTED "DiscoveryStarted" #define BT_DISCOVERY_FINISHED "DiscoveryFinished" #define BT_DEVICE_FOUND "DeviceFound" -#define BT_DEVICE_DISAPPEARED "DeviceDisappeared" +#define BT_LE_DISCOVERY_STARTED "LEDiscoveryStarted" +#define BT_LE_DISCOVERY_FINISHED "LEDiscoveryFinished" +#define BT_LE_DEVICE_FOUND "LEDeviceFound" +#define BT_ADVERTISING_STARTED "AdvertisingStarted" +#define BT_ADVERTISING_STOPPED "AdvertisingStopped" +#define BT_ADVERTISING_MANUFACTURER_DATA_CHANGED "AdvertisingManufacturerDataChanged" +#define BT_SCAN_RESPONSE_MANUFACTURER_DATA_CHANGED "ScanResponseManufacturerDataChanged" +#define BT_MANUFACTURER_DATA_CHANGED "ManufacturerDataChanged" #define BT_DEVICE_CONNECTED "DeviceConnected" #define BT_DEVICE_DISCONNECTED "DeviceDisconnected" +#define BT_DEVICE_PROFILE_STATE_CHANGED "ProfileStateChanged" #define BT_BOND_CREATED "BondCreated" #define BT_BOND_DESTROYED "BondDestroyed" +#define BT_DEVICE_AUTHORIZED "DeviceAuthorized" +#define BT_DEVICE_UNAUTHORIZED "DeviceUnauthorized" +#define BT_RSSI_MONITORING_ENABLED "RssiMonitoringEnabled" +#define BT_RSSI_ALERT "RssiMonitoringAlert" +#define BT_RAW_RSSI_EVENT "RawRssiEvent" #define BT_SERVICE_SEARCHED "ServiceSearched" #define BT_INPUT_CONNECTED "InputConnected" #define BT_INPUT_DISCONNECTED "InputDisconnected" +#define BT_PBAP_CONNECTED "PbapConnected" +#define BT_PBAP_PHONEBOOK_SIZE "PbapPhonebookSize" +#define BT_PBAP_PHONEBOOK_PULL "PbapPhonebookPull" +#define BT_PBAP_VCARD_LIST "PbapvCardList" +#define BT_PBAP_VCARD_PULL "PbapvCardPull" +#define BT_PBAP_SEARCH_PHONEBOOK "PbapSearchPhonebook" #define BT_HEADSET_CONNECTED "HeadsetConnected" #define BT_HEADSET_DISCONNECTED "HeadsetDisconnected" #define BT_STEREO_HEADSET_CONNECTED "StereoHeadsetConnected" @@ -231,12 +352,18 @@ typedef struct { #define BT_SCO_DISCONNECTED "ScoDisconnected" #define BT_SPEAKER_GAIN "SpeakerGain" #define BT_MICROPHONE_GAIN "MicrophoneGain" +#define BT_HF_RING "Ring" +#define BT_HF_CALL_TERMINATED "CallTerminated" +#define BT_HF_CALL_STARTED "CallStarted" +#define BT_HF_CALL_ENDED "CallEnded" #define BT_NETWORK_CONNECTED "NetworkConnected" #define BT_NETWORK_DISCONNECTED "NetworkDisconnected" #define BT_NETWORK_SERVER_CONNECTED "NetworkServerConnected" #define BT_NETWORK_SERVER_DISCONNECTED "NetworkServerDisconnected" #define BT_OPP_CONNECTED "OppConnected" #define BT_OPP_DISCONNECTED "OppDisconnected" +#define BT_TRANSFER_CONNECTED "TransferConnected" +#define BT_TRANSFER_DISCONNECTED "TransferDisonnected" #define BT_TRANSFER_STARTED "TransferStarted" #define BT_TRANSFER_PROGRESS "TransferProgress" #define BT_TRANSFER_COMPLETED "TransferCompleted" @@ -246,10 +373,21 @@ typedef struct { #define BT_RFCOMM_DATA_RECEIVED "RfcommDataReceived" #define BT_RFCOMM_CONNECTED "RfcommConnected" #define BT_RFCOMM_DISCONNECTED "RfcommDisconnected" +#define BT_AVRCP_CONNECTED "AvrcpConnected" +#define BT_AVRCP_DISCONNECTED "AvrcpDisconnected" #define BT_MEDIA_SHUFFLE_STATUS "MediaShuffleStatus" #define BT_MEDIA_EQUALIZER_STATUS "MediaEqualizerStatus" #define BT_MEDIA_REPEAT_STATUS "MediaRepeatStatus" #define BT_MEDIA_SCAN_STATUS "MediaScanStatus" +#define BT_MEDIA_PLAY_STATUS "MediaPlayStatus" +#define BT_MEDIA_POSITION_STATUS "MediaPositionStatus" +#define BT_MEDIA_TRACK_CHANGE "MediaTrackStatus" +#define BT_NAME_OWNER_CHANGED "NameOwnerChanged" +#define BT_GATT_CONNECTED "GattConnected" +#define BT_GATT_DISCONNECTED "GattDisconnected" +#define BT_HARDWARE_ERROR "HardwareError" +#define BT_TX_TIMEOUT_ERROR "TxTimeoutError" +#define BT_HF_LOCAL_TERM "HandsfreeLocalTermination" #ifdef __cplusplus } diff --git a/packaging/bluetooth-frwk-mobile.service b/packaging/bluetooth-frwk-mobile.service new file mode 100755 index 0000000..09010da --- /dev/null +++ b/packaging/bluetooth-frwk-mobile.service @@ -0,0 +1,13 @@ +[Unit] +Description=Bluetooth service +After=dbus.socket dbus.service +Requires=dbus.socket + +[Service] +Type=dbus +BusName=org.projectx.bt +ExecStart=/usr/bin/bt-service +KillMode=process + +[Install] +WantedBy=multi-user.target diff --git a/packaging/bluetooth-frwk-wearable.service b/packaging/bluetooth-frwk-wearable.service new file mode 100755 index 0000000..09010da --- /dev/null +++ b/packaging/bluetooth-frwk-wearable.service @@ -0,0 +1,13 @@ +[Unit] +Description=Bluetooth service +After=dbus.socket dbus.service +Requires=dbus.socket + +[Service] +Type=dbus +BusName=org.projectx.bt +ExecStart=/usr/bin/bt-service +KillMode=process + +[Install] +WantedBy=multi-user.target diff --git a/packaging/bluetooth-frwk.manifest b/packaging/bluetooth-frwk.manifest old mode 100644 new mode 100755 diff --git a/packaging/bluetooth-frwk.spec b/packaging/bluetooth-frwk.spec old mode 100644 new mode 100755 index 2de005f..b2c6668 --- a/packaging/bluetooth-frwk.spec +++ b/packaging/bluetooth-frwk.spec @@ -1,49 +1,52 @@ -%bcond_with bluetooth_frwk_libnotify -%bcond_with bluetooth_frwk_libnotification -%bcond_with x +%define _dumpdir /opt/etc/dump.d/module.d +%define _varlibdir /opt/var/lib Name: bluetooth-frwk -Summary: Bluetooth framework for BlueZ and Obexd -Version: 0.2.55 -Release: 0 +Summary: Bluetooth framework for BlueZ and Obexd. This package is Bluetooth framework based on BlueZ and Obexd stack. +Version: 0.2.146 +Release: 1 Group: Network & Connectivity/Bluetooth -License: Apache-2.0 +License: Apache License, Version 2.0 Source0: %{name}-%{version}.tar.gz Source1001: bluetooth-frwk.manifest -Source1002: bt-icon.png URL: https://review.tizen.org/git/?p=platform/core/connectivity/bluetooth-frwk.git;a=summary +Requires: sys-assert Requires: dbus -Requires: bluetooth-tools +Requires: syspopup BuildRequires: pkgconfig(aul) BuildRequires: pkgconfig(dbus-glib-1) BuildRequires: pkgconfig(dlog) BuildRequires: pkgconfig(glib-2.0) -%if %{with bluetooth_frwk_libnotify} -BuildRequires: pkgconfig(libnotify) -BuildRequires: pkgconfig(gdk-pixbuf-2.0) -BuildRequires: pkgconfig(gtk+-3.0) -%elif %{without bluetooth_frwk_libnotification} +BuildRequires: pkgconfig(gio-2.0) +BuildRequires: pkgconfig(gio-unix-2.0) BuildRequires: pkgconfig(syspopup-caller) -Requires: syspopup -%endif BuildRequires: pkgconfig(vconf) BuildRequires: pkgconfig(libxml-2.0) BuildRequires: pkgconfig(dbus-1) -%if %{with x} BuildRequires: pkgconfig(utilX) -%endif -BuildRequires: pkgconfig(capi-network-tethering) -BuildRequires: pkgconfig(libprivilege-control) -BuildRequires: pkgconfig(status) +BuildRequires: pkgconfig(capi-network-connection) BuildRequires: pkgconfig(alarm-service) BuildRequires: pkgconfig(notification) BuildRequires: pkgconfig(security-server) +BuildRequires: pkgconfig(capi-content-mime-type) +BuildRequires: pkgconfig(appcore-efl) +BuildRequires: pkgconfig(pkgmgr) +#BuildRequires: pkgconfig(journal) + +%if "%{?tizen_profile_name}" == "mobile" +BuildRequires: pkgconfig(capi-network-tethering) +%endif + BuildRequires: cmake -BuildRequires: pkgconfig(libtzplatform-config) +#Requires(post): vconf +#Requires(postun): eglibc +#Requires: psmisc Requires(post): /usr/bin/vconftool Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig +Requires(postun): eglibc +Requires: psmisc %description Bluetooth framework for BlueZ and Obexd. This package is Bluetooth framework based on BlueZ and Obexd stack. @@ -71,72 +74,91 @@ This package is Bluetooth Service daemon to manage BT services. Summary: Bluetooth Core daemon Group: Network & Connectivity/Bluetooth Requires: %{name} = %{version}-%{release} -Requires: connman %description core This package is Bluetooth core daemon to manage activation / deactivation. +%package test +Summary: Bluetooth test application +Group: Network & Connectivity/Bluetooth +Requires: %{name} = %{version}-%{release} + +%description test +This package is Bluetooth test application. + %prep %setup -q cp %{SOURCE1001} . %build +export CFLAGS="$CFLAGS -DTIZEN_DEBUG_ENABLE" +export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE" +export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE" -%ifarch x86_64 -export CFLAGS="${CFLAGS} -Wall -g -fvisibility=hidden -fPIC" -export LDFLAGS="${LDFLAGS} -Wl,--rpath=%{_libdir} -Wl,--as-needed -Wl,--unresolved-symbols=ignore-in-shared-libs" -%else -export CFLAGS="${CFLAGS} -fpie" -export LDFLAGS="${LDFLAGS} -Wl,--rpath=%{_libdir} -Wl,--as-needed -Wl,--unresolved-symbols=ignore-in-shared-libs -pie" +%if "%{?tizen_profile_name}" == "mobile" +export CFLAGS="$CFLAGS -DTIZEN_NETWORK_TETHERING_ENABLE" %endif -%cmake . \ --DTZ_SYS_USER_GROUP=%TZ_SYS_USER_GROUP \ --DTZ_SYS_DEFAULT_USER=%TZ_SYS_DEFAULT_USER \ -%if %{with bluetooth_frwk_libnotify} - -DLIBNOTIFY_SUPPORT=On \ +%if "%{?tizen_profile_name}" == "wearable" +export CFLAGS="$CFLAGS -DTIZEN_WEARABLE" +%define _servicefile packaging/bluetooth-frwk-wearable.service %else - -DLIBNOTIFY_SUPPORT=Off \ +%define _servicefile packaging/bluetooth-frwk-mobile.service %endif -%if %{with bluetooth_frwk_libnotification} - -DLIBNOTIFICATION_SUPPORT=On +%define _servicedir multi-user.target.wants + +%if "%{?tizen_profile_name}" == "mobile" %else - -DLIBNOTIFICATION_SUPPORT=Off +export CFLAGS="$CFLAGS -DTIZEN_TELEPHONY_ENABLED" %endif -%__make +export LDFLAGS+=" -Wl,--rpath=/usr/lib -Wl,--as-needed -Wl,--unresolved-symbols=ignore-in-shared-libs -pie" + +export CFLAGS+=" -fpie -DRFCOMM_DIRECT " +cmake . -DCMAKE_INSTALL_PREFIX=/usr + +make + +%cmake \ +%if "%{?tizen_profile_name}" == "wearable" + -DTIZEN_WEARABLE=YES \ +%else + -DTIZEN_WEARABLE=NO \ +%endif %install rm -rf %{buildroot} %make_install -mkdir -p %{buildroot}%{_unitdir_user} -install -m 0644 bt-service/bluetooth-frwk-service.service %{buildroot}%{_unitdir_user} +install -D -m 0644 LICENSE %{buildroot}%{_datadir}/license/bluetooth-frwk +install -D -m 0644 LICENSE %{buildroot}%{_datadir}/license/bluetooth-frwk-service +install -D -m 0644 LICENSE %{buildroot}%{_datadir}/license/bluetooth-frwk-devel -%if %{with bluetooth_frwk_libnotify} || %{with bluetooth_frwk_libnotification} -mkdir -p %{buildroot}%{_datadir}/icons/default -install -m 0644 %{SOURCE1002} %{buildroot}%{_datadir}/icons/default/bt-icon.png -%endif +mkdir -p %{buildroot}%{_libdir}/systemd/system/%{_servicedir} +install -m 0644 %{_servicefile} %{buildroot}%{_libdir}/systemd/system/bluetooth-frwk.service +ln -s ../bluetooth-frwk.service %{buildroot}%{_libdir}/systemd/system/%{_servicedir}/bluetooth-frwk.service -# On IVI bt-service needs to be run as 'app' even if there is a 'guest' user. -%if "%{profile}"=="ivi" -sed -i 's/%TZ_SYS_DEFAULT_USER/app/' %{buildroot}%{_datadir}/dbus-1/system-services/org.projectx.bt.service -%endif +mkdir -p %{buildroot}%{_dumpdir} +install -m 0755 bluetooth_log_dump.sh %{buildroot}%{_dumpdir} %post -/sbin/ldconfig -vconftool set -f -t int db/bluetooth/status "0" -g 6520 -vconftool set -f -t int file/private/bt-service/flight_mode_deactivated "0" -g 6520 -i -vconftool set -f -t string memory/bluetooth/sco_headset_name "" -g 6520 -i -vconftool set -f -t int memory/bluetooth/device "0" -g 6520 -i -vconftool set -f -t int memory/bluetooth/btsco "0" -g 6520 -i -# set 'User' smack label to vconf keys in order to allow bt-service to access them. -chsmack -a 'User' %TZ_SYS_CONFIG/db/bluetooth/status -chsmack -a 'User' %TZ_SYS_CONFIG/file/private/bt-service/flight_mode_deactivated -chsmack -a 'User' %TZ_SYS_CONFIG/memory_init/memory/bluetooth/sco_headset_name -chsmack -a 'User' %TZ_SYS_CONFIG/memory_init/memory/bluetooth/device -chsmack -a 'User' %TZ_SYS_CONFIG/memory_init/memory/bluetooth/btsco +%if "%{?tizen_profile_name}" == "wearable" +vconftool set -tf int db/bluetooth/status "1" -g 5000 -s tizen::vconf::public::r::platform::rw +%else +vconftool set -tf int db/bluetooth/status "0" -g 5000 -s tizen::vconf::public::r::platform::rw +%endif +vconftool set -tf int db/bluetooth/lestatus "0" -g 5000 -s tizen::vconf::public::r::platform::rw +vconftool set -tf int file/private/bt-core/flight_mode_deactivated "0" -g 5000 -i -s tizen::vconf::platform::rw +vconftool set -tf int file/private/bt-core/powersaving_mode_deactivated "0" -g 5000 -i -s tizen::vconf::platform::rw +vconftool set -tf int file/private/bt-service/bt_off_due_to_timeout "0" -g 5000 -i -s tizen::vconf::platform::rw +vconftool set -tf string memory/bluetooth/sco_headset_name "" -g 5000 -i -s tizen::vconf::platform::rw +vconftool set -tf int memory/bluetooth/device "0" -g 5000 -i -s tizen::vconf::platform::rw +vconftool set -tf bool memory/bluetooth/dutmode "0" -g 5000 -i -s tizen::vconf::platform::rw + +%post service +mkdir -p %{_sysconfdir}/systemd/default-extra-dependencies/ignore-units.d/ +ln -sf %{_libdir}/systemd/system/bluetooth-frwk.service %{_sysconfdir}/systemd/default-extra-dependencies/ignore-units.d/ %postun -p /sbin/ldconfig @@ -144,34 +166,47 @@ chsmack -a 'User' %TZ_SYS_CONFIG/memory_init/memory/bluetooth/btsco %manifest %{name}.manifest %defattr(-, root, root) %{_libdir}/libbluetooth-api.so.* +%{_datadir}/license/bluetooth-frwk +%{_libdir}/systemd/system/%{_servicedir}/bluetooth-frwk.service +%{_libdir}/systemd/system/bluetooth-frwk.service %files devel -%manifest %{name}.manifest %defattr(-, root, root) %{_includedir}/bt-service/bluetooth-api.h %{_includedir}/bt-service/bluetooth-hid-api.h %{_includedir}/bt-service/bluetooth-audio-api.h %{_includedir}/bt-service/bluetooth-telephony-api.h %{_includedir}/bt-service/bluetooth-media-control.h +%{_includedir}/bt-service/bluetooth-scmst-api.h %{_libdir}/pkgconfig/bluetooth-api.pc %{_libdir}/libbluetooth-api.so +%{_datadir}/license/bluetooth-frwk-devel %files service %manifest %{name}.manifest %defattr(-, root, root) +%{_sysconfdir}/rc.d/init.d/bluetooth-frwk-service %{_datadir}/dbus-1/system-services/org.projectx.bt.service - %{_bindir}/bt-service -%{_unitdir_user}/bluetooth-frwk-service.service -%attr(0666,-,-) /opt/var/lib/bluetooth/auto-pair-blacklist -%{_sysconfdir}/dbus-1/system.d/bluetooth-frwk-service.conf -%if %{with bluetooth_frwk_libnotify} || %{with bluetooth_frwk_libnotification} -%{_datadir}/icons/default/bt-icon.png -%endif +%{_bindir}/bluetooth-frwk-test +%{_bindir}/bluetooth-gatt-test +%{_bindir}/bluetooth-advertising-test +%{_varlibdir}/bluetooth +%{_prefix}/etc/bluetooth +%attr(0666,-,-) %{_varlibdir}/bluetooth/auto-pair-blacklist +%attr(0666,-,-) %{_prefix}/etc/bluetooth/stack_info +%{_dumpdir}/bluetooth_log_dump.sh +%{_datadir}/license/bluetooth-frwk-service %files core %manifest %{name}.manifest %defattr(-, root, root) %{_datadir}/dbus-1/system-services/org.projectx.bt_core.service %{_bindir}/bt-core -%{_sysconfdir}/dbus-1/system.d/bluetooth-frwk-core.conf + +%files test +%manifest %{name}.manifest +%defattr(-, root, root) +%{_bindir}/bluetooth-frwk-test +%{_bindir}/bluetooth-gatt-test +%{_bindir}/bluetooth-advertising-test diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt old mode 100644 new mode 100755 index a04a9ff..4c628e3 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -37,3 +37,5 @@ INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin) #ADD_SUBDIRECTORY(media-control) #ADD_SUBDIRECTORY(telephony) ADD_SUBDIRECTORY(gatt-test) +#ADD_SUBDIRECTORY(handsfree) +ADD_SUBDIRECTORY(le-adv) diff --git a/test/bluetooth-frwk-test.c b/test/bluetooth-frwk-test.c old mode 100644 new mode 100755 index 78b17b0..aed8087 --- a/test/bluetooth-frwk-test.c +++ b/test/bluetooth-frwk-test.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-frwk * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -51,6 +55,11 @@ int server_fd = 0; int g_ret_client_fd1 = -1, g_ret_client_fd2 = -1; const char *g_hdp_app_handle1 = NULL; const char *g_hdp_app_handle2 = NULL; + +char *svc_obj_path = NULL; +char *char_obj_path = NULL; +char *desc_obj_path = NULL; + int selection; int hdp_manual_mode = 1; const char * rfcomm_test_uuid_spp ="00001101-0000-1000-8000-00805F9B34FB"; @@ -93,6 +102,7 @@ tc_table_t tc_table[] = {"bluetooth_get_local_address" , 6}, {"bluetooth_get_local_name" , 7}, {"bluetooth_set_local_name" , 8}, + {"bluetooth_get_local_version" , 90}, {"bluetooth_is_service_used" , 9}, {"bluetooth_get_discoverable_mode" , 10}, {"bluetooth_set_discoverable_mode(CONNECTABLE)" , 11}, @@ -113,6 +123,7 @@ tc_table_t tc_table[] = {"bluetooth_cancel_service_search" , 26}, {"bluetooth_is_device_connected" , 27}, {"bluetooth_reset_adapter" , 28}, + {"bluetooth_set_manufacturer_data" , 91}, {"bluetooth_audio_init" , 29}, {"bluetooth_audio_deinit" , 30}, @@ -174,7 +185,17 @@ tc_table_t tc_table[] = {"bluetooth_rfcomm_is_server_uuid_available" , 86}, {"bluetooth_rfcomm_accept_connection" , 87}, {"bluetooth_rfcomm_reject_connection" , 88}, - + {"bluetooth_start_custom_discovery" , 89}, + + {"bluetooth_gatt_init", 92}, + {"bluetooth_gatt_deinit", 93}, + {"bluetooth_gatt_add_service", 94}, + {"bluetooth_gatt_add_characteristics", 95}, + {"bluetooth_gatt_add_descriptor", 96}, + {"bluetooth_gatt_register_service", 97}, + {"bluetooth_gatt_update_characteristic", 98}, + {"bluetooth_gatt_unregister_service", 99}, + {"bluetooth_gatt_delete_services", 100}, #if 0 {"bluetooth_rfcomm_is_server_uuid_available" , 26}, @@ -245,6 +266,7 @@ int test_input_callback(void *data) int ret = 0; int test_id = (int)data; + TC_PRT("TC : %s", tc_table[test_id - 1].tc_name); switch (test_id) { case 0x00ff: @@ -253,7 +275,6 @@ int test_input_callback(void *data) break; case 1: - TC_PRT("TC : %s", tc_table[0].tc_name); bluetooth_register_callback(bt_event_callback, NULL); if (ret < 0) { @@ -263,7 +284,6 @@ int test_input_callback(void *data) break; case 2: - TC_PRT("TC : %s", tc_table[1].tc_name); bluetooth_unregister_callback(); if (ret < 0) { @@ -273,7 +293,6 @@ int test_input_callback(void *data) break; case 3: - TC_PRT("TC : %s", tc_table[2].tc_name); ret = bluetooth_enable_adapter(); if (ret < 0) { @@ -283,7 +302,6 @@ int test_input_callback(void *data) break; case 4: - TC_PRT("TC : %s", tc_table[3].tc_name); ret = bluetooth_disable_adapter(); if (ret < 0) { @@ -294,7 +312,6 @@ int test_input_callback(void *data) case 5: { - TC_PRT("TC : %s", tc_table[4].tc_name); ret = bluetooth_check_adapter(); TC_PRT("state: %d", ret); break; @@ -303,8 +320,6 @@ int test_input_callback(void *data) case 6: { bluetooth_device_address_t address = {{0}}; - - TC_PRT("TC : %s", tc_table[5].tc_name); ret = bluetooth_get_local_address(&address); if (ret < 0) { @@ -321,7 +336,6 @@ int test_input_callback(void *data) { bluetooth_device_name_t local_name = {{0}}; - TC_PRT("TC : %s", tc_table[6].tc_name); ret = bluetooth_get_local_name(&local_name); if (ret < 0) { @@ -338,7 +352,6 @@ int test_input_callback(void *data) snprintf(local_name.name, sizeof(local_name.name), "bt-frwk-pid-%d", getpid()); - TC_PRT("TC : %s", tc_table[7].tc_name); ret = bluetooth_set_local_name(&local_name); if (ret < 0) { @@ -347,11 +360,24 @@ int test_input_callback(void *data) break; } + case 90: + { + bluetooth_version_t local_version = {{0}}; + snprintf(local_version.version, sizeof(local_version.version), + "version%d", getpid()); + + ret = bluetooth_get_local_version(&local_version); + if (ret < 0) + TC_PRT("%s failed with [0x%04x]", tc_table[89].tc_name, ret); + else + TC_PRT("version: %s", local_version.version); + break; + } + case 9: { - gboolean used = FALSE; + gboolean used = FALSE; - TC_PRT("TC : %s", tc_table[8].tc_name); ret = bluetooth_is_service_used(rfcomm_test_uuid_spp, &used); if (ret < 0) { @@ -365,7 +391,6 @@ int test_input_callback(void *data) case 10: { bluetooth_discoverable_mode_t mode; - TC_PRT("TC : %s", tc_table[9].tc_name); ret = bluetooth_get_discoverable_mode(&mode); if (ret < 0) { @@ -381,7 +406,6 @@ int test_input_callback(void *data) case 11: { bluetooth_discoverable_mode_t mode = BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE; - TC_PRT("TC : %s", tc_table[10].tc_name); ret = bluetooth_set_discoverable_mode(mode, 0); if (ret < 0) { @@ -397,7 +421,6 @@ int test_input_callback(void *data) case 12: { bluetooth_discoverable_mode_t mode = BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE; - TC_PRT("TC : %s", tc_table[11].tc_name); ret = bluetooth_set_discoverable_mode(mode, 0); if (ret < 0) { @@ -413,7 +436,6 @@ int test_input_callback(void *data) case 13: { bluetooth_discoverable_mode_t mode = BLUETOOTH_DISCOVERABLE_MODE_TIME_LIMITED_DISCOVERABLE; - TC_PRT("TC : %s", tc_table[12].tc_name); ret = bluetooth_set_discoverable_mode(mode, 5); if (ret < 0) { @@ -427,7 +449,6 @@ int test_input_callback(void *data) } case 14: - TC_PRT("TC : %s", tc_table[13].tc_name); ret = bluetooth_start_discovery(0,0,0); if (ret < 0) { @@ -436,7 +457,6 @@ int test_input_callback(void *data) break; case 15: - TC_PRT("TC : %s", tc_table[14].tc_name); ret = bluetooth_cancel_discovery(); if (ret < 0) { @@ -446,7 +466,6 @@ int test_input_callback(void *data) case 16: { - TC_PRT("TC : %s", tc_table[15].tc_name); ret = bluetooth_is_discovering(); if (ret < 0) { @@ -461,9 +480,6 @@ int test_input_callback(void *data) case 17: /*Get paired device list */ { - - TC_PRT("TC : %s", tc_table[16].tc_name); - GPtrArray *devinfo = NULL; devinfo = g_ptr_array_new(); TC_PRT("g pointer arrary count : [%d]", devinfo->len); @@ -507,8 +523,6 @@ int test_input_callback(void *data) //bluetooth_device_address_t device_address={{0x58,0x17,0x0C,0xEC,0x6A,0xF3}}; /* MW600 */ bluetooth_device_address_t device_address={{0x00,0x0D,0xFD,0x24,0x5E,0xFF}}; /* Motorola S9 */ - TC_PRT("TC : %s", tc_table[17].tc_name); - TC_PRT("dev [%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X]", \ device_address.addr[0], device_address.addr[1], device_address.addr[2], \ device_address.addr[3], device_address.addr[4], device_address.addr[5]); @@ -524,8 +538,6 @@ int test_input_callback(void *data) case 19: /*Cancel bonding */ { - - TC_PRT("TC : %s", tc_table[18].tc_name); ret = bluetooth_cancel_bonding(); if (ret < 0) { @@ -539,8 +551,6 @@ int test_input_callback(void *data) { bluetooth_device_address_t device_address={{0x00,0x19,0x0E,0x01,0x61,0x17}}; /* DO-DH79-PYUN04 */ //bluetooth_device_address_t device_address={{0x00,0x16,0x38,0xC3,0x1F,0xD2}}; - - TC_PRT("TC : %s", tc_table[19].tc_name); ret = bluetooth_unbond_device(&device_address); if (ret < 0) { @@ -578,8 +588,6 @@ int test_input_callback(void *data) { bluetooth_device_address_t device_address={{0x00,0x16,0x38,0xC3,0x1F,0xD2}}; - TC_PRT("TC : %s", tc_table[21].tc_name); - ret = bluetooth_set_alias(&device_address, "Renamed device"); if (ret < 0) TC_PRT("%s failed with [0x%04x]", tc_table[21].tc_name, ret); @@ -590,8 +598,6 @@ int test_input_callback(void *data) { bluetooth_device_address_t device_address={{0x00,0x16,0x38,0xC3,0x1F,0xD2}}; - TC_PRT("TC : %s", tc_table[22].tc_name); - ret = bluetooth_authorize_device(&device_address, TRUE); if (ret < 0) TC_PRT("%s failed with [0x%04x]", tc_table[22].tc_name, ret); @@ -601,8 +607,6 @@ int test_input_callback(void *data) { bluetooth_device_address_t device_address={{0x00,0x16,0x38,0xC3,0x1F,0xD2}}; - TC_PRT("TC : %s", tc_table[23].tc_name); - ret = bluetooth_authorize_device(&device_address, FALSE); if (ret < 0) TC_PRT("%s failed with [0x%04x]", tc_table[23].tc_name, ret); @@ -612,8 +616,6 @@ int test_input_callback(void *data) { bluetooth_device_address_t device_address={{0x00,0x19,0x0E,0x01,0x61,0x17}}; /* DO-DH79-PYUN04 */ - TC_PRT("TC : %s", tc_table[24].tc_name); - ret = bluetooth_search_service(&device_address); if (ret < 0) TC_PRT("%s failed with [0x%04x]", tc_table[24].tc_name, ret); @@ -621,8 +623,6 @@ int test_input_callback(void *data) } case 26: { - TC_PRT("TC : %s", tc_table[25].tc_name); - ret = bluetooth_cancel_service_search(); if (ret < 0) TC_PRT("%s failed with [0x%04x]", tc_table[24].tc_name, ret); @@ -633,8 +633,6 @@ int test_input_callback(void *data) gboolean connected = FALSE; bluetooth_device_address_t device_address={{0x00,0x1B,0x66,0x01,0x23,0x1C}}; /* Gennheiser PX210BT */ - TC_PRT("TC : %s", tc_table[26].tc_name); - ret = bluetooth_is_device_connected(&device_address, BLUETOOTH_A2DP_SERVICE, &connected); if (ret < 0) TC_PRT("%s failed with [0x%04x]", tc_table[24].tc_name, ret); @@ -644,18 +642,27 @@ int test_input_callback(void *data) } case 28: { - TC_PRT("TC : %s", tc_table[27].tc_name); - ret = bluetooth_reset_adapter(); if (ret < 0) TC_PRT("%s failed with [0x%04x]", tc_table[27].tc_name, ret); break; } + case 91: + { + bluetooth_manufacturer_data_t m_data; + guint8 data[6] = {0x05, 0xFF, 0x02, 0x03, 0x04, 0x05}; + TC_PRT("%x %x %x %x %x %x", data[0], data[1], data[2], data[3], + data[4], data[5]); + memcpy(m_data.data, data, sizeof(data)); + m_data.data_len = sizeof(data) - 2; + ret = bluetooth_set_manufacturer_data(&m_data); + if (ret < 0) + TC_PRT("%s failed with [0x%04x]", tc_table[90].tc_name, ret); + break; + } case 29: { - TC_PRT("TC : %s", tc_table[28].tc_name); - ret = bluetooth_audio_init(bt_audio_event_callback, NULL); if (ret < 0) TC_PRT("%s failed with [0x%04x]", tc_table[28].tc_name, ret); @@ -663,8 +670,6 @@ int test_input_callback(void *data) } case 30: { - TC_PRT("TC : %s", tc_table[29].tc_name); - ret = bluetooth_audio_deinit(); if (ret < 0) TC_PRT("%s failed with [0x%04x]", tc_table[29].tc_name, ret); @@ -676,8 +681,6 @@ int test_input_callback(void *data) //bluetooth_device_address_t device_address={{0x58,0x17,0x0C,0xEC,0x6A,0xF3}}; bluetooth_device_address_t device_address={{0x00,0x0D,0xFD,0x24,0x5E,0xFF}}; /* Motorola S9 */ - TC_PRT("TC : %s", tc_table[30].tc_name); - ret = bluetooth_audio_connect(&device_address); if (ret < 0) TC_PRT("%s failed with [0x%04x]", tc_table[30].tc_name, ret); @@ -689,8 +692,6 @@ int test_input_callback(void *data) //bluetooth_device_address_t device_address={{0x58,0x17,0x0C,0xEC,0x6A,0xF3}}; bluetooth_device_address_t device_address={{0x00,0x0D,0xFD,0x24,0x5E,0xFF}}; /* Motorola S9 */ - TC_PRT("TC : %s", tc_table[31].tc_name); - ret = bluetooth_audio_disconnect(&device_address); if (ret < 0) TC_PRT("%s failed with [0x%04x]", tc_table[31].tc_name, ret); @@ -701,8 +702,6 @@ int test_input_callback(void *data) /* MW600 */ bluetooth_device_address_t device_address={{0x58,0x17,0x0C,0xEC,0x6A,0xF3}}; - TC_PRT("TC : %s", tc_table[32].tc_name); - ret = bluetooth_ag_connect(&device_address); if (ret < 0) TC_PRT("%s failed with [0x%04x]", tc_table[32].tc_name, ret); @@ -713,8 +712,6 @@ int test_input_callback(void *data) /* MW600 */ bluetooth_device_address_t device_address={{0x58,0x17,0x0C,0xEC,0x6A,0xF3}}; - TC_PRT("TC : %s", tc_table[33].tc_name); - ret = bluetooth_ag_disconnect(&device_address); if (ret < 0) TC_PRT("%s failed with [0x%04x]", tc_table[33].tc_name, ret); @@ -725,8 +722,6 @@ int test_input_callback(void *data) /* MW600 */ bluetooth_device_address_t device_address={{0x58,0x17,0x0C,0xEC,0x6A,0xF3}}; - TC_PRT("TC : %s", tc_table[34].tc_name); - ret = bluetooth_av_connect(&device_address); if (ret < 0) TC_PRT("%s failed with [0x%04x]", tc_table[34].tc_name, ret); @@ -737,8 +732,6 @@ int test_input_callback(void *data) /* MW600 */ bluetooth_device_address_t device_address={{0x58,0x17,0x0C,0xEC,0x6A,0xF3}}; - TC_PRT("TC : %s", tc_table[35].tc_name); - ret = bluetooth_av_disconnect(&device_address); if (ret < 0) TC_PRT("%s failed with [0x%04x]", tc_table[35].tc_name, ret); @@ -752,7 +745,7 @@ int test_input_callback(void *data) if (ret < 0) TC_PRT("failed with [0x%04x]", ret); - TC_PRT("volume: %u", volume); + TC_PRT("volume: %d", volume); break; } case 38: @@ -814,6 +807,7 @@ int test_input_callback(void *data) } case 40: { + ret = bluetooth_get_local_address(&g_local_oob_data.address); TC_PRT("hash_len: %d\n", g_local_oob_data.oob_data.hash_len); TC_PRT("randomizer_len: %d\n", g_local_oob_data.oob_data.randomizer_len); @@ -1024,7 +1018,8 @@ int test_input_callback(void *data) } case 73: { - ret = bluetooth_rfcomm_write(g_ret_client_fd1, "123456789 12345", 20); + const char rd_data[] = "123456789 12345"; + ret = bluetooth_rfcomm_write(g_ret_client_fd1, rd_data, sizeof(rd_data)); if (ret < 0) TC_PRT("Failed with [0x%04x]", ret); @@ -1104,7 +1099,7 @@ int test_input_callback(void *data) } case 87: { - ret = bluetooth_rfcomm_accept_connection(server_fd, &client_fd); + ret = bluetooth_rfcomm_accept_connection(server_fd); if (ret < 0) TC_PRT("Failed with [0x%04x]", ret); TC_PRT("client fd: %d", client_fd); @@ -1117,6 +1112,101 @@ int test_input_callback(void *data) TC_PRT("Failed with [0x%04x]", ret); break; } + case 89: + ret = bluetooth_start_custom_discovery(DISCOVERY_ROLE_LE, + 0,0,0); + if (ret < 0) + { + TC_PRT("failed with [0x%04x]", ret); + } + break; + case 92: { + ret = bluetooth_gatt_init(); + if (ret < 0) + { + TC_PRT("gatt init failed with [0x%04x]", ret); + } + break; + } + case 93: { + ret = bluetooth_gatt_deinit(); + if (ret < 0) + { + TC_PRT("gatt deinit failed with [0x%04x]", ret); + } + break; + } + case 94: { + char *service_uuid = g_strdup("00001802-0000-1000-8000-00805f9b34fb"); + + ret = bluetooth_gatt_add_service(service_uuid, + &svc_obj_path); + g_free(service_uuid); + + TC_PRT("service obj_path is %s", svc_obj_path); + } + break; + + case 95: { + /* testing with dummy values*/ + char *char_uuid = g_strdup("00002a06-0000-1000-8000-00805f9b34fb"); + bt_gatt_characteristic_property_t props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ | + BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE | + BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_NOTIFY | + BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE; + + ret = bluetooth_gatt_add_new_characteristic( + svc_obj_path, char_uuid, + props, &char_obj_path); + g_free(char_uuid); + + TC_PRT("characteristic obj_path is %s", char_obj_path); + + break; + } + + case 96: { + char *desc_uuid = g_strdup("000026ff-0000-1000-8000-00805f9b34fb"); + + ret = bluetooth_gatt_add_descriptor(char_obj_path, + desc_uuid, &desc_obj_path); + + TC_PRT("add descriptor error is %d", ret); + g_free(desc_uuid); + + break; + } + case 97: { + ret = bluetooth_gatt_register_service(svc_obj_path); + + TC_PRT("register service error is %d", ret); + + break; + } + case 98: { + char char_data[4] = {10, 20, 30, 40}; + int char_length = 4; + ret = bluetooth_gatt_update_characteristic(char_obj_path, + char_data, char_length); + + TC_PRT("update_characteristic error is %d", ret); + + break; + } + case 99: { + ret = bluetooth_gatt_unregister_service(svc_obj_path); + + TC_PRT("service removed with error is %d", ret); + + break; + } + case 100: { + ret = bluetooth_gatt_delete_services(); + + TC_PRT("services deleted with error is %d", ret); + + break; + } default: break; } @@ -1148,17 +1238,6 @@ void cleanup() } } -int timeout_callback(void *data) -{ - TC_PRT("timeout callback"); - timeout_status = -1; - - g_main_loop_quit(main_loop); - - return FALSE; -} - - void bt_hid_event_callback(int event, hid_event_param_t* param, void *user_data) { TC_PRT(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); @@ -1222,6 +1301,27 @@ void bt_event_callback(int event, bluetooth_event_param_t* param, void *user_dat break; } + case BLUETOOTH_EVENT_REMOTE_LE_DEVICE_FOUND: + { + int i; + bluetooth_le_device_info_t *le_device_info = NULL; + TC_PRT("BLUETOOTH_EVENT_REMOTE_LE_DEVICE_FOUND, result [0x%04x]", param->result); + le_device_info = (bluetooth_le_device_info_t *)param->param_data; + TC_PRT("dev[%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X]", \ + le_device_info->device_address.addr[0], le_device_info->device_address.addr[1], le_device_info->device_address.addr[2], \ + le_device_info->device_address.addr[3], le_device_info->device_address.addr[4], le_device_info->device_address.addr[5]); + TC_PRT("addr_type : %d", le_device_info->addr_type); + TC_PRT("rssi : %d", le_device_info->rssi); + TC_PRT("adv_ind_data_len :%d" , le_device_info->adv_ind_data.data_len); + TC_PRT("scan_resp_data_len :%d" , le_device_info->scan_resp_data.data_len); + + for (i=0; iadv_ind_data.data_len; i++) + TC_PRT("adv_ind_data[%d] : [0x%x]",i ,le_device_info->adv_ind_data.data.data[i]); + for (i=0; iscan_resp_data.data_len; i++) + TC_PRT("scan_resp_data[%d] : [0x%x]",i ,le_device_info->scan_resp_data.data.data[i]); + break; + } + case BLUETOOTH_EVENT_REMOTE_DEVICE_NAME_UPDATED: { bluetooth_device_info_t *device_info = NULL; @@ -1485,7 +1585,10 @@ void bt_event_callback(int event, bluetooth_event_param_t* param, void *user_dat case BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_COMPLETED: TC_PRT("BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_COMPLETED"); break; - + case BLUETOOTH_EVENT_MANUFACTURER_DATA_CHANGED: + { TC_PRT("BLUETOOTH_EVENT_MANUFACTURER_DATA_CHANGED"); + break; + } #if 0 case BLUETOOTH_EVENT_GATT_PRIM_SVC_DISCOVERED: { diff --git a/test/gatt-test/CMakeLists.txt b/test/gatt-test/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/test/gatt-test/TFXF4E2.tmp b/test/gatt-test/TFXF4E2.tmp new file mode 100755 index 0000000..e69de29 diff --git a/test/gatt-test/bluetooth-gatt-test.c b/test/gatt-test/bluetooth-gatt-test.c old mode 100644 new mode 100755 index 1648197..29d72f7 --- a/test/gatt-test/bluetooth-gatt-test.c +++ b/test/gatt-test/bluetooth-gatt-test.c @@ -154,8 +154,8 @@ static void __accept_bdaddress(bluetooth_device_address_t *device_address) static void __accept_alert_level() { TC_PRT("Enter alert level \n 0 - no alert 1 - mild alert 2 - High alert : "); - scanf("%d", &g_alert_level); - TC_PRT("You have selected alert level %d ", g_alert_level); + scanf("%u", &g_alert_level); + TC_PRT("You have selected alert level %u ", g_alert_level); } int test_input_callback(void *data) diff --git a/test/handsfree/CMakeLists.txt b/test/handsfree/CMakeLists.txt new file mode 100755 index 0000000..0f76c64 --- /dev/null +++ b/test/handsfree/CMakeLists.txt @@ -0,0 +1,32 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(bluetooth-hf-test C) + +SET(SRCS bluetooth-hf-test.c) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/bt-api/) + +INCLUDE(FindPkgConfig) +pkg_check_modules(package REQUIRED dlog dbus-glib-1 glib-2.0 gthread-2.0) + +FOREACH(flag ${package_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") +IF("${ARCH}" STREQUAL "arm") + ADD_DEFINITIONS("-DTARGET") + MESSAGE("add -DTARGET") +ENDIF("${ARCH}" STREQUAL "arm") + +ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"") +ADD_DEFINITIONS("-DFACTORYFS=\"$ENV{FACTORYFS}\"") + +ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${package_LDFLAGS} -L${CMAKE_SOURCE_DIR}/bt-api/ -lbluetooth-api) + +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin) diff --git a/test/handsfree/bluetooth-hf-test.c b/test/handsfree/bluetooth-hf-test.c new file mode 100755 index 0000000..ce21548 --- /dev/null +++ b/test/handsfree/bluetooth-hf-test.c @@ -0,0 +1,540 @@ +/* + * Bluetooth-telephony + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * 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. + * + */ + +/** + * @file bluetooth-telephony-test.c + * @brief This is the source file for bluetooth telephony test suite. + */ + +#include +#include +#include +#include +#include + +#include "bluetooth-audio-api.h" +#include "bluetooth-api.h" + +#define PRT(format, args...) printf("%s:%d() "format, \ + __FUNCTION__, __LINE__, ##args) +#define TC_PRT(format, args...) PRT(format"\n", ##args) + +GMainLoop *main_loop = NULL; +static int timeout_status = 0; +#define DEFAULT_CALL_ID 1 +/*Change this number with Testing SIM*/ +#define TEST_NUMBER "9980785507" +#define BLUETOOTH_HF_SPEAKER_GAIN 2 + +typedef struct { + const char *tc_name; + int tc_code; +} tc_table_t; + +tc_table_t tc_table[] = { + /*HF Application*/ + {"bluetooth_hf_init", 1}, + {"bluetooth_hf_deinit", 2}, + {"Answer Call", 3}, + {"Terminate Call", 4}, + {"Initiate Call", 5}, + {"Last number Redial ", 6}, + {"(PTS) Connect last bonded device", 7}, + {"Disconnect", 8}, + {"(PTS) Voice Recognition Enable", 9}, + {"Voice RecognitionDisable", 10}, + {"SCO disconnect", 11}, + {"Speaker gain", 12}, + {"Dual Tone mulitple frequency", 13}, + {"Send AT+XSAT=appid command", 14}, + {"Release All Call(CHLD=0)", 15}, + {"Release and Accept(CHLD=1)", 16}, + {"Swap call (CHLD=2)", 17}, + {"Join Call (CHLD=3)", 18}, + {"(PTS) Initiate Codec based SCO", 19}, + {"(PTS) Unbond all devices", 20}, + {"Get Current Codec", 21}, + {"Get Call List", 22}, + {"Get Audio Connected Status", 23}, + {"Is Handsfree Connected?", 24}, + + /* -----------------------------------------*/ + {"Finish", 0x00ff}, + {NULL, 0x0000}, + +}; + +#define tc_result(success, tc_index) \ + TC_PRT("Test case [%d - %s] %s", tc_table[tc_index].tc_code, \ + tc_table[tc_index].tc_name, \ + ((success == TC_PASS) ? "Success" : "Failed")); + +void tc_usage_print(void) +{ + int i = 0; + + while (tc_table[i].tc_name) { + if (tc_table[i].tc_code != 0x00ff) { + TC_PRT("Key %d : usage %s", tc_table[i].tc_code, + tc_table[i].tc_name); + } else { + TC_PRT("Key %d : usage %s\n\n", 0x00ff, + tc_table[i].tc_name); + } + + i++; + } +} +void bt_event_callback(int event, bluetooth_event_param_t *param, void *user_data) +{ + GMainLoop *main_loop = (GMainLoop*) user_data; + + switch(event) + { + // Code for each event + default: + break; + } +} + +void hf_event_handler(int event, void *data, void *user_data) +{ + bt_hf_event_param_t *hf_event; + + if (data == NULL) + return; + hf_event = data; + + TC_PRT("HF event : [0x%04x]", event); + + switch (event) { + case BLUETOOTH_EVENT_HF_CONNECTED: + TC_PRT("BLUETOOTH_EVENT_HF_CONNECTED"); + break; + + case BLUETOOTH_EVENT_HF_DISCONNECTED: + TC_PRT("BLUETOOTH_EVENT_HF_DISCONNECTED"); + break; + + case BLUETOOTH_EVENT_HF_AUDIO_CONNECTED: + TC_PRT("BLUETOOTH_EVENT_HF_AUDIO_CONNECTED"); + break; + + case BLUETOOTH_EVENT_HF_AUDIO_DISCONNECTED: + TC_PRT("BLUETOOTH_EVENT_HF_AUDIO_DISCONNECTED"); + break; + + case BLUETOOTH_EVENT_HF_RING_INDICATOR: + TC_PRT("BLUETOOTH_EVENT_HF_RING_INDICATOR"); + if (hf_event->param_data) + TC_PRT("Phone number %s", hf_event->param_data); + break; + + case BLUETOOTH_EVENT_HF_CALL_WAITING: + TC_PRT("BLUETOOTH_EVENT_HF_CALL_WAITING"); + if (hf_event->param_data) + TC_PRT("Waiting Phone number %s", hf_event->param_data); + break; + + case BLUETOOTH_EVENT_HF_CALL_TERMINATED: + TC_PRT("BLUETOOTH_EVENT_HF_CALL_TERMINATED"); + break; + + case BLUETOOTH_EVENT_HF_CALL_STARTED: + TC_PRT("BLUETOOTH_EVENT_HF_CALL_STARTED"); + break; + + case BLUETOOTH_EVENT_HF_CALL_ENDED: + TC_PRT("BLUETOOTH_EVENT_HF_CALL_ENDED"); + break; + + case BLUETOOTH_EVENT_HF_CALL_UNHOLD: + TC_PRT("BLUETOOTH_EVENT_HF_CALL_UNHOLD"); + break; + + case BLUETOOTH_EVENT_HF_CALL_SWAPPED: + TC_PRT("BLUETOOTH_EVENT_HF_CALL_SWAPPED"); + break; + + case BLUETOOTH_EVENT_HF_CALL_ON_HOLD: + TC_PRT("BLUETOOTH_EVENT_HF_CALL_ON_HOLD"); + break; + + case BLUETOOTH_EVENT_HF_CALL_STATUS: + { + TC_PRT("BLUETOOTH_EVENT_HF_CALL_STATUS"); + int i; + bt_hf_call_list_s * call_list = hf_event->param_data; + bt_hf_call_status_info_t **call_info; + TC_PRT("call_list length : %d ", call_list->count); + call_info = g_malloc0(sizeof(bt_hf_call_status_info_t *) * + call_list->count); + bluetooth_hf_get_call_list(call_list->list, call_info); + + for (i= 0; i < call_list->count; i++) { + TC_PRT("Phone Number : %s ", call_info[i]->number); + TC_PRT("Direction (in -1, out 0 : %d ", call_info[i]->direction); + TC_PRT("Call status : %d ", call_info[i]->status); + TC_PRT("MultyParty : %d ", call_info[i]->mpart); + TC_PRT("Call ID : %d ", call_info[i]->idx); + } + g_free(call_info); + break; + } + case BLUETOOTH_EVENT_HF_VOICE_RECOGNITION_ENABLED: + TC_PRT("BLUETOOTH_EVENT_HF_VOICE_RECOGNITION_ENABLED"); + break; + + case BLUETOOTH_EVENT_HF_VOICE_RECOGNITION_DISABLED: + TC_PRT("BLUETOOTH_EVENT_HF_VOICE_RECOGNITION_DISABLED"); + break; + + case BLUETOOTH_EVENT_HF_VOLUME_SPEAKER: + { + unsigned int *value; + value = hf_event->param_data; + TC_PRT("BLUETOOTH_EVENT_HF_VOLUME_SPEAKER - value = %d", *value); + break; + } + case BLUETOOTH_EVENT_HF_VENDOR_DEP_CMD: + { + bluetooth_vendor_dep_at_cmd_t *cmd = hf_event->param_data; + TC_PRT("BLUETOOTH_EVENT_HF_VENDOR_DEP_CMD - appid = %d, msg = %s", + cmd->app_id, cmd->message); + break; + } + + default: + break; + } +} + +static int __bt_unbond_all_bonded_devices(void) +{ + int ret; + int i; + bluetooth_device_info_t *ptr; + + GPtrArray *dev_list = NULL; + dev_list = g_ptr_array_new(); + TC_PRT("g pointer arrary count : [%d]", dev_list->len); + + ret = bluetooth_get_bonded_device_list(&dev_list); + if (ret < 0) { + TC_PRT("failed bluetooth_get_bonded_device_list"); + g_ptr_array_free(dev_list, TRUE); + return 1; + } + TC_PRT("g pointer arrary count : [%d]", dev_list->len); + + if (dev_list->len == 0) { + TC_PRT("No paired device found"); + g_ptr_array_free(dev_list, TRUE); + return 1; + } + + for (i = 0; i < dev_list->len; i++) { + ptr = g_ptr_array_index(dev_list, i); + if (ptr == NULL) + continue; + TC_PRT("[%d] Unbond %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", i + 1, + ptr->device_address.addr[0], ptr->device_address.addr[1], + ptr->device_address.addr[2], ptr->device_address.addr[3], + ptr->device_address.addr[4], ptr->device_address.addr[5]); + bluetooth_unbond_device(&ptr->device_address); + + } + g_ptr_array_foreach(dev_list, (GFunc)g_free, NULL); + g_ptr_array_free(dev_list, TRUE); + return 0; + +} +static int __bt_get_last_bonded_device(bluetooth_device_address_t *device_address) +{ + int ret; + int i; + bluetooth_device_info_t *ptr; + + GPtrArray *dev_list = NULL; + dev_list = g_ptr_array_new(); + TC_PRT("g pointer arrary count : [%d]", dev_list->len); + + ret = bluetooth_get_bonded_device_list(&dev_list); + if (ret < 0) { + TC_PRT("failed bluetooth_get_bonded_device_list"); + g_ptr_array_free(dev_list, TRUE); + return 1; + } + TC_PRT("g pointer arrary count : [%d]", dev_list->len); + + if (dev_list->len == 0) { + TC_PRT("No paired device found"); + g_ptr_array_free(dev_list, TRUE); + return 1; + } + + for (i = 0; i < dev_list->len; i++) { + ptr = g_ptr_array_index(dev_list, i); + if (ptr == NULL) + continue; + TC_PRT("[%d] %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", i + 1, + ptr->device_address.addr[0], ptr->device_address.addr[1], + ptr->device_address.addr[2], ptr->device_address.addr[3], + ptr->device_address.addr[4], ptr->device_address.addr[5]); + memcpy(device_address->addr, ptr->device_address.addr, + sizeof(bluetooth_device_address_t)); + } + g_ptr_array_foreach(dev_list, (GFunc)g_free, NULL); + g_ptr_array_free(dev_list, TRUE); + return 0; + +} + +int test_input_callback(void *data) +{ + int ret; + int test_id = (int)data; + + switch (test_id) { + case 0x00ff: + TC_PRT("Finished"); + g_main_loop_quit(main_loop); + break; + + case 1: + bluetooth_hf_init(hf_event_handler, NULL); + break; + case 2: + bluetooth_hf_deinit(); + break; + case 3: + bluetooth_hf_answer_call(); + break; + case 4: + bluetooth_hf_terminate_call(); + break; + case 5: + ret = bluetooth_hf_initiate_call(TEST_NUMBER); + TC_PRT("ret = %d", ret); + break; + case 6: + bluetooth_hf_initiate_call(NULL); + break; + case 7: + { bluetooth_device_address_t device_address = { {0} }; + ret = __bt_get_last_bonded_device(&device_address); + if (ret != 0) { + TC_PRT("Error in getting last bonded device....."); + return FALSE; + } + + bluetooth_hf_connect(&device_address); + break; + } + case 8: + { + bluetooth_device_address_t device_address = { {0} }; + ret = __bt_get_last_bonded_device(&device_address); + if (ret != 0) { + TC_PRT("Error in getting last bonded device....."); + return FALSE; + } + + bluetooth_hf_disconnect(&device_address); + break; + } + case 9: + bluetooth_hf_voice_recognition(1); + break; + + case 10: + bluetooth_hf_voice_recognition(0); + break; + case 11: + bluetooth_hf_audio_disconnect(); + break; + case 12: + bluetooth_hf_set_speaker_gain(BLUETOOTH_HF_SPEAKER_GAIN); + break; + case 13: + bluetooth_hf_send_dtmf("1"); + break; + case 14: + /* get the Call Time from AG for DC lauch */ + bluetooth_hf_send_xsat_cmd(11, "Q_CT,1,01025561613"); + break; + case 15: + bluetooth_hf_release_all_call(); + break; + case 16: + bluetooth_hf_release_and_accept(); + break; + case 17: + bluetooth_hf_swap_call(); + break; + case 18: + bluetooth_hf_join_call(); + break; + case 19: + system("dbus-send --system --print-reply --dest=org.bluez.hf_agent /org/bluez/handsfree_agent org.tizen.HfApp.SendAtCmd string:AT+BCC"); + break; + case 20: + { + ret = bluetooth_register_callback(bt_event_callback, NULL); + ret = __bt_unbond_all_bonded_devices(); + if (ret != 0) { + TC_PRT("Error in getting last bonded device....."); + return FALSE; + } + + break; + } + case 21: + { + unsigned int current_codec; + bluetooth_hf_get_codec(¤t_codec); + if (current_codec == BLUETOOTH_CODEC_ID_CVSD) + TC_PRT("current_codec is CVSD"); + else + TC_PRT("current_codec is. MSBC"); + break; + } + case 22: + { + int i; + bt_hf_call_list_s * call_list = NULL; + bt_hf_call_status_info_t **call_info = NULL; + bluetooth_hf_request_call_list(&call_list); + if(call_list == NULL) { + TC_PRT("call_list is NULL"); + break; + } + TC_PRT("call_list length : %d ", call_list->count); + call_info = g_malloc0(sizeof(bt_hf_call_status_info_t *) * + call_list->count); + bluetooth_hf_get_call_list(call_list->list, call_info); + + for (i= 0; i < call_list->count; i++) { + TC_PRT("Phone Number : %s ", call_info[i]->number); + TC_PRT("Direction (in -1, out 0 : %d ", call_info[i]->direction); + TC_PRT("Call status : %d ", call_info[i]->status); + TC_PRT("MultyParty : %d ", call_info[i]->mpart); + TC_PRT("Call ID : %d ", call_info[i]->idx); + } + g_free(call_info); + bluetooth_hf_free_call_list(call_list); + break; + } + case 23: + { + unsigned int sco_audio_connected; + bluetooth_hf_get_audio_connected(&sco_audio_connected); + if (sco_audio_connected == BLUETOOTH_HF_AUDIO_CONNECTED) + TC_PRT("SCO Audio is connected"); + else + TC_PRT("SCO Audio is disconnected"); + break; + } + case 24: + { + gboolean hf_connected; + bluetooth_hf_is_hf_connected(&hf_connected); + if (hf_connected == BLUETOOTH_HF_AUDIO_CONNECTED) + TC_PRT("HF is connected"); + else + TC_PRT("HF is disconnected"); + break; + } + default: + break; + } + + return 0; +} + +void startup() +{ + TC_PRT("bluetooth framework TC startup"); + + if (!g_thread_supported()) { + g_thread_init(NULL); + } + + dbus_g_thread_init(); + + g_type_init(); + main_loop = g_main_loop_new(NULL, FALSE); +} + +void cleanup() +{ + TC_PRT("bluetooth framework TC cleanup"); + if (main_loop != NULL) { + g_main_loop_unref(main_loop); + } +} + +static gboolean key_event_cb(GIOChannel *chan, GIOCondition cond , + gpointer data) +{ + char buf[10] = {0}; + + unsigned int len = 0; + int test_id; + memset(buf, 0, sizeof(buf)); + + if (g_io_channel_read(chan, buf, sizeof(buf), &len) != + G_IO_ERROR_NONE) { + + printf("IO Channel read error"); + return FALSE; + + } + printf("%s\n", buf); + tc_usage_print(); + + test_id = atoi(buf); + + if (test_id) + g_idle_add(test_input_callback, (void *)test_id); + + return TRUE; +} + +int main() +{ + startup(); + + GIOChannel *key_io; + key_io = g_io_channel_unix_new(fileno(stdin)); + + g_io_add_watch(key_io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, + key_event_cb, NULL); + g_io_channel_unref(key_io); + + + g_main_loop_run(main_loop); + + cleanup(); + return 0; +} diff --git a/test/le-adv/CMakeLists.txt b/test/le-adv/CMakeLists.txt new file mode 100755 index 0000000..eecfc22 --- /dev/null +++ b/test/le-adv/CMakeLists.txt @@ -0,0 +1,33 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(bluetooth-advertising-test C) + +SET(SRCS bluetooth-advertising-test.c) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../lib) + +INCLUDE(FindPkgConfig) +pkg_check_modules(package REQUIRED dlog dbus-glib-1 glib-2.0 gthread-2.0) + +FOREACH(flag ${package_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") +IF("${ARCH}" STREQUAL "arm") + ADD_DEFINITIONS("-DTARGET") + MESSAGE("add -DTARGET") +ENDIF("${ARCH}" STREQUAL "arm") + +ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"") +ADD_DEFINITIONS("-DFACTORYFS=\"$ENV{FACTORYFS}\"") + +ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${package_LDFLAGS} -L${CMAKE_CURRENT_SOURCE_DIR}/../../bt-api -lbluetooth-api) + +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin) diff --git a/test/le-adv/bluetooth-advertising-test.c b/test/le-adv/bluetooth-advertising-test.c new file mode 100755 index 0000000..c54bc9a --- /dev/null +++ b/test/le-adv/bluetooth-advertising-test.c @@ -0,0 +1,393 @@ +/* + * Bluetooth-frwk + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park + * + * 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. + * + */ + +/** + * @file bluetooth-gatt-test.c + * @brief This is the source file for bluetooth framework test suite. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bluetooth-api.h" + + +#define PRT(format, args...) printf("%s:%d() "format, __FUNCTION__, __LINE__, ##args) +#define TC_PRT(format, args...) PRT(format"\n", ##args) + +#define TC_PASS 1 +#define TC_FAIL 0 + +GMainLoop *main_loop = NULL; + +typedef struct +{ + const char *tc_name; + int tc_code; +} tc_table_t; + +tc_table_t tc_table[] = +{ + {"SetAdvertising ON" , 1}, + {"SetAdvertising OFF" , 2}, + {"SetCustomAdvertising ON, filter 0x03" , 3}, + {"SetCustomAdvertising ON, filter 0x00" , 4}, + {"SetAdvertisingData" , 5}, + {"SetScanParameters" ,6}, + {"SetScanResponseData" ,7}, + {"Start LE Scan" ,8}, + {"Stop LE Scan" ,9}, + {"IsAdvertising" ,10}, + {"Add White List" ,11}, + {"Remove White List" ,12}, + {"Clear White List" ,13}, + {"Set Connectable ON" ,14}, + {"Set Connectable OFF" ,15}, + + /* -----------------------------------------*/ + {"Finish" , 0x00ff}, + {NULL , 0x0000}, + +}; + +#define tc_result(success, tc_index) \ + TC_PRT("Test case [%d - %s] %s", tc_table[tc_index].tc_code, tc_table[tc_index].tc_name, ((success == TC_PASS)?"Success":"Failed")); + + +void tc_usage_print(void) +{ + int i = 0; + + while (tc_table[i].tc_name) { + if (tc_table[i].tc_code != 0x00ff) { + TC_PRT("Key %d : usage %s", tc_table[i].tc_code, + tc_table[i].tc_name); + } else { + TC_PRT("Key %d : usage %s\n\n", 0x00ff, + tc_table[i].tc_name); + } + + i++; + } +} + +int test_input_callback(void *data) +{ + int ret = 0; + int test_id = (int)data; + bluetooth_advertising_params_t params; + + switch (test_id) { + case 0x00ff: + TC_PRT("Finished"); + g_main_loop_quit(main_loop); + break; + case 1: + TC_PRT("SetAdvertising ON"); + ret = bluetooth_set_advertising(TRUE); + break; + case 2: + TC_PRT("SetAdvertising OFF"); + ret = bluetooth_set_advertising(FALSE); + break; + case 3: + TC_PRT("SetCustomAdvertising ON, Filter 0x03"); + params.interval_min = 1280; + params.interval_max = 1280; + params.filter_policy = 0x03; + params.type = 0x00; + ret = bluetooth_set_custom_advertising(TRUE, ¶ms); + break; + case 4: + TC_PRT("SetCustomAdvertising ON, Filter 0x00"); + params.interval_min = 1280; + params.interval_max = 1280; + params.filter_policy = 0x00; + params.type = 0x00; + ret = bluetooth_set_custom_advertising(TRUE, ¶ms); + break; + case 5: { + TC_PRT("SetAdvertisingData"); + bluetooth_advertising_data_t adv; + guint8 data[6] = {0x05, 0xFF, 0x02, 0x03, 0x04, 0x05}; + + TC_PRT("%x %x %x %x %x %x", data[0], data[1], data[2], data[3], + data[4], data[5]); + memcpy(adv.data, data, sizeof(data)); + ret = bluetooth_set_advertising_data(&adv, sizeof(data)); + break; + } + case 6: + TC_PRT("SetScanParameters"); + // ret = bluetooth_set_scan_parameters(1280, 160 /* 80 */); + break; + case 7: { + TC_PRT("SetScanResponseData"); + bluetooth_scan_resp_data_t rsp; + guint8 data[7] = {0x06, 0xFF, 0x02, 0x03, 0x04, 0x05, 0x06}; + + TC_PRT("%x %x %x %x %x %x %x", data[0], data[1], data[2], + data[3], data[4], data[5], data[6]); + memcpy(rsp.data, data, sizeof(data)); + ret = bluetooth_set_scan_response_data(&rsp, sizeof(data)); + break; + } + case 8: + TC_PRT("Start LE Scan"); + ret = bluetooth_start_le_discovery(); + break; + case 9: + TC_PRT("Stop LE Scan"); + ret = bluetooth_stop_le_discovery(); + break; + case 10: { + TC_PRT("IsAdvertising"); + gboolean advertising = FALSE; + int ret; + + ret = bluetooth_is_advertising(&advertising); + if (ret == BLUETOOTH_ERROR_NONE) + TC_PRT("Advertising is %s", advertising ? "started" : "stopped"); + else + TC_PRT("bluetooth_is_advertising failed with [%d]", ret); + break; + } + case 11: { + bluetooth_device_address_t device_address={{0x00,0x19,0x0E,0x11,0x56,0x06}}; + + TC_PRT("Add White List"); + + ret = bluetooth_add_white_list(&device_address, BLUETOOTH_DEVICE_PUBLIC_ADDRESS); + if (ret != BLUETOOTH_ERROR_NONE) + TC_PRT("bluetooth_add_white_list failed with [%d]", ret); + + break; + } + case 12: { + bluetooth_device_address_t device_address={{0x00,0x19,0x0E,0x11,0x56,0x06}}; + + TC_PRT("Remove White List"); + + ret = bluetooth_remove_white_list(&device_address, BLUETOOTH_DEVICE_PUBLIC_ADDRESS); + if (ret != BLUETOOTH_ERROR_NONE) + TC_PRT("bluetooth_remove_white_list failed with [%d]", ret); + + break; + } + case 13: { + TC_PRT("Clear White List"); + + ret = bluetooth_clear_white_list(); + if (ret != BLUETOOTH_ERROR_NONE) + TC_PRT("bluetooth_clear_white_list failed with [%d]", ret); + + break; + } + case 14: { + TC_PRT("Set Connectable ON"); + + ret = bluetooth_set_connectable(TRUE); + if (ret != BLUETOOTH_ERROR_NONE) + TC_PRT("bt_adapter_set_connectable failed with [%d]", ret); + + break; + } + case 15: { + TC_PRT("Set Connectable OFF"); + + ret = bluetooth_set_connectable(FALSE); + if (ret != BLUETOOTH_ERROR_NONE) + TC_PRT("bt_adapter_set_connectable failed with [%d]", ret); + + break; + } + + default: + break; + } + + TC_PRT("Result : %d", ret); + return 0; +} + +void startup() +{ + TC_PRT("bluetooth framework TC startup"); + + if (!g_thread_supported()) + g_thread_init(NULL); + + dbus_g_thread_init(); + + g_type_init(); + main_loop = g_main_loop_new(NULL, FALSE); +} + +void cleanup() +{ + TC_PRT("bluetooth framework TC cleanup"); + if ( main_loop != NULL) + g_main_loop_unref(main_loop); +} + +void bt_event_callback(int event, bluetooth_event_param_t* param, + void *user_data) +{ + TC_PRT(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); + TC_PRT("bt event callback 0x%04x", event); + switch(event) { + case BLUETOOTH_EVENT_DISCOVERY_STARTED: + TC_PRT("BLUETOOTH_EVENT_DISCOVERY_STARTED, result [0x%04x]", param->result); + break; + + case BLUETOOTH_EVENT_LE_DISCOVERY_STARTED: + TC_PRT("BLUETOOTH_EVENT_LE_DISCOVERY_STARTED, result [0x%04x]", param->result); + break; + + case BLUETOOTH_EVENT_LE_DISCOVERY_FINISHED: + TC_PRT("BLUETOOTH_EVENT_LE_DISCOVERY_FINISHED, result [0x%04x]", param->result); + break; + + case BLUETOOTH_EVENT_REMOTE_LE_DEVICE_FOUND: + TC_PRT("LE device founded"); + bluetooth_le_device_info_t *le_device_info = NULL; + le_device_info = (bluetooth_le_device_info_t *)param->param_data; + TC_PRT("dev [%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X]", \ + le_device_info->device_address.addr[0], le_device_info->device_address.addr[1], le_device_info->device_address.addr[2], \ + le_device_info->device_address.addr[3], le_device_info->device_address.addr[4], le_device_info->device_address.addr[5]); + + break; + + case BLUETOOTH_EVENT_REMOTE_DEVICE_FOUND: + { + bluetooth_device_info_t *device_info = NULL; + TC_PRT("BLUETOOTH_EVENT_REMOTE_DEVICE_FOUND, result [0x%04x]", param->result); + device_info = (bluetooth_device_info_t *)param->param_data; + TC_PRT("dev [%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X]", \ + device_info->device_address.addr[0], device_info->device_address.addr[1], device_info->device_address.addr[2], \ + device_info->device_address.addr[3], device_info->device_address.addr[4], device_info->device_address.addr[5]); + break; + } + + case BLUETOOTH_EVENT_REMOTE_DEVICE_NAME_UPDATED: + { + bluetooth_device_info_t *device_info = NULL; + TC_PRT("BLUETOOTH_EVENT_REMOTE_DEVICE_NAME_UPDATED, result [0x%04x]", param->result); + device_info = (bluetooth_device_info_t *)param->param_data; + TC_PRT("dev [%s] [%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X]", device_info->device_name.name, \ + device_info->device_address.addr[0], device_info->device_address.addr[1], device_info->device_address.addr[2], \ + device_info->device_address.addr[3], device_info->device_address.addr[4], device_info->device_address.addr[5]); + break; + } + + case BLUETOOTH_EVENT_DISCOVERY_FINISHED: + TC_PRT("BLUETOOTH_EVENT_DISCOVERY_FINISHED, result [0x%04x]", param->result); + break; + + case BLUETOOTH_EVENT_ADVERTISING_STARTED: + TC_PRT("BLUETOOTH_EVENT_ADVERTISING_STARTED, result [0x%04x], " + "interval_min [%f ms], interval_max [%f ms]", + param->result, + ((bluetooth_advertising_params_t *)param->param_data)->interval_min, + ((bluetooth_advertising_params_t *)param->param_data)->interval_max); + break; + + case BLUETOOTH_EVENT_ADVERTISING_STOPPED: + TC_PRT("BLUETOOTH_EVENT_ADVERTISING_STOPPED, result [0x%04x]", param->result); + break; + + default: + TC_PRT("received event [0x%04x]", event); + break; + } + TC_PRT("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); +} + +static gboolean key_event_cb(GIOChannel *chan, GIOCondition cond, gpointer data) +{ + char buf[10] = {0}; + unsigned int len = 0; + int test_id; + + if (g_io_channel_read(chan, buf, sizeof(buf), &len) != + G_IO_ERROR_NONE) { + printf("IO Channel read error"); + return FALSE; + } + printf("%s\n",buf); + tc_usage_print(); + + test_id = atoi(buf); + + if (test_id) + g_idle_add(test_input_callback, (void*)test_id); + + return TRUE; +} + +int main() +{ + int ret_val; + GIOChannel *key_io; + + startup(); + + /* Register callback function */ + TC_PRT("TC : %s", tc_table[0].tc_name); + ret_val = bluetooth_register_callback(bt_event_callback, NULL); + if (ret_val >= BLUETOOTH_ERROR_NONE) { + TC_PRT("bluetooth_register_callback returned Success"); + tc_result(TC_PASS, 0); + } else { + TC_PRT("bluetooth_register_callback returned failiure [0x%04x]", ret_val); + tc_result(TC_FAIL, 0); + return 0; + } + + ret_val = bluetooth_check_adapter(); + if (ret_val < BLUETOOTH_ERROR_NONE) { + TC_PRT("bluetooth_check_adapter returned failiure [0x%04x]", ret_val); + tc_result(TC_FAIL, 3); + } else { + TC_PRT("BT state [0x%04x]", ret_val); + tc_result(TC_PASS, 3); + } + + key_io = g_io_channel_unix_new(fileno(stdin)); + + g_io_add_watch(key_io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, + key_event_cb, NULL); + g_io_channel_unref(key_io); + + g_main_loop_run(main_loop); + + cleanup(); + return 0; +} diff --git a/test/media-control/CMakeLists.txt b/test/media-control/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/test/media-control/bluetooth-media-control-test.c b/test/media-control/bluetooth-media-control-test.c old mode 100644 new mode 100755 index 8456323..4fb3b63 --- a/test/media-control/bluetooth-media-control-test.c +++ b/test/media-control/bluetooth-media-control-test.c @@ -1,13 +1,18 @@ /* - * bluetooth-frwk + * bluetooth-media-control + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. * * 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 + * 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, diff --git a/test/telephony/CMakeLists.txt b/test/telephony/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/test/telephony/bluetooth-telephony-test.c b/test/telephony/bluetooth-telephony-test.c old mode 100644 new mode 100755 index 33ac589..45be199 --- a/test/telephony/bluetooth-telephony-test.c +++ b/test/telephony/bluetooth-telephony-test.c @@ -1,13 +1,17 @@ /* - * bluetooth-frwk + * Bluetooth-telephony * - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hocheol Seo + * Girishashok Joshi + * Chanyeol Park * * 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 + * 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, @@ -64,6 +68,9 @@ tc_table_t tc_table[] = { {"Voice Recognition Start", 83}, {"Voice Recognition Stop", 84}, {"NREC Status", 85}, + {"WBS Status", 86}, + {"Vendor dep AT CMD [+XSAT: 11,DUAL,DUAL]", 87}, + /* -----------------------------------------*/ {"Finish", 0x00ff}, {NULL, 0x0000}, @@ -147,6 +154,9 @@ void telephony_event_handler(int event, void *data, void *user_data) nrec = bt_event->param_data; TC_PRT("NREC status = [%d]", *nrec); break; + case BLUETOOTH_EVENT_TELEPHONY_VENDOR_AT_CMD: + TC_PRT("BLUETOOTH_EVENT_TELEPHONY_VENDOR_AT_CMD %s", bt_event->param_data); + break; } default: @@ -252,6 +262,30 @@ int test_input_callback(void *data) break; } + case 86: { + int ret; + gboolean status = FALSE; + + ret = bluetooth_telephony_is_wbs_mode(&status); + + if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) + TC_PRT("Error getting WBS Status\n"); + + TC_PRT("WBS status = %d\n", status); + break; + } + case 87: { + int ret = 0; + + TC_PRT("Vendor dependent AT Command\n"); + + ret = bluetooth_telephony_send_vendor_cmd("+XSAT: 11,DUAL,DUAL"); + + if (ret == BLUETOOTH_TELEPHONY_ERROR_NONE) { + TC_PRT("No error\n"); + } + break; + } default: break; } @@ -281,16 +315,6 @@ void cleanup() } } -int timeout_callback(void *data) -{ - TC_PRT("timeout callback"); - timeout_status = -1; - - g_main_loop_quit(main_loop); - - return FALSE; -} - static gboolean key_event_cb(GIOChannel *chan, GIOCondition cond , gpointer data) { -- 2.7.4