From 5f5b6fa5e56703d0d16409aee366a7701888a583 Mon Sep 17 00:00:00 2001 From: Jinkun Jang Date: Wed, 13 Mar 2013 01:47:08 +0900 Subject: [PATCH] Tizen 2.1 base --- AUTHORS | 2 + CMakeLists.txt | 9 + LICENSE.APLv2 | 204 ++ NOTICE | 3 + bluetooth-frwk.manifest | 5 + bt-api/CMakeLists.txt | 81 + bt-api/bluetooth-api.pc.in | 11 + bt-api/bt-adapter.c | 366 +++ bt-api/bt-audio.c | 248 ++ bt-api/bt-avrcp.c | 140 + bt-api/bt-common.c | 378 +++ bt-api/bt-device.c | 246 ++ bt-api/bt-event-handler.c | 1829 ++++++++++++ bt-api/bt-gatt.c | 615 ++++ bt-api/bt-gatt.xml | 14 + bt-api/bt-hdp.c | 1180 ++++++++ bt-api/bt-hid.c | 111 + bt-api/bt-network.c | 115 + bt-api/bt-obex-server.c | 390 +++ bt-api/bt-oob.c | 97 + bt-api/bt-opp-client.c | 140 + bt-api/bt-request-sender.c | 406 +++ bt-api/bt-request-service.xml | 21 + bt-api/bt-rfcomm-client.c | 159 + bt-api/bt-rfcomm-server.c | 238 ++ bt-api/bt-service-api.pc.in | 11 + bt-api/bt-telephony.c | 1851 ++++++++++++ bt-api/bt-telephony.xml | 31 + bt-api/include/bt-common.h | 231 ++ bt-api/include/bt-event-handler.h | 66 + bt-api/include/bt-request-sender.h | 57 + bt-api/marshal.list | 5 + bt-core/CMakeLists.txt | 55 + bt-core/bt_core.c | 458 +++ bt-core/bt_core.h | 61 + bt-core/bt_core.xml | 15 + bt-core/org.projectx.bt_core.service | 4 + bt-service/CMakeLists.txt | 86 + bt-service/auto-pair-blacklist | 3 + bt-service/bluetooth-frwk-service | 13 + bt-service/bluetooth-frwk-service.service | 14 + bt-service/bt-request-handler.c | 962 ++++++ bt-service/bt-request-service.xml | 21 + bt-service/bt-service-adapter.c | 1138 +++++++ bt-service/bt-service-agent.c | 854 ++++++ bt-service/bt-service-audio.c | 445 +++ bt-service/bt-service-avrcp.c | 758 +++++ bt-service/bt-service-common.c | 389 +++ bt-service/bt-service-device.c | 1328 +++++++++ bt-service/bt-service-event-receiver.c | 1311 +++++++++ bt-service/bt-service-event-sender.c | 288 ++ bt-service/bt-service-gap-agent.c | 952 ++++++ bt-service/bt-service-gap-agent.xml | 75 + bt-service/bt-service-hid.c | 263 ++ bt-service/bt-service-main.c | 183 ++ bt-service/bt-service-media-agent.xml | 11 + bt-service/bt-service-network.c | 362 +++ bt-service/bt-service-obex-agent.c | 439 +++ bt-service/bt-service-obex-agent.xml | 42 + bt-service/bt-service-obex-server.c | 880 ++++++ bt-service/bt-service-oob.c | 213 ++ bt-service/bt-service-opp-client.c | 620 ++++ bt-service/bt-service-rfcomm-client.c | 767 +++++ bt-service/bt-service-rfcomm-server.c | 932 ++++++ bt-service/bt-service-util.c | 148 + bt-service/include/bt-request-handler.h | 69 + bt-service/include/bt-service-adapter.h | 95 + bt-service/include/bt-service-agent.h | 125 + bt-service/include/bt-service-audio.h | 56 + bt-service/include/bt-service-avrcp.h | 53 + bt-service/include/bt-service-common.h | 212 ++ bt-service/include/bt-service-device.h | 65 + bt-service/include/bt-service-event.h | 42 + bt-service/include/bt-service-gap-agent.h | 119 + bt-service/include/bt-service-hid.h | 41 + bt-service/include/bt-service-main.h | 35 + bt-service/include/bt-service-network.h | 51 + bt-service/include/bt-service-obex-agent.h | 136 + bt-service/include/bt-service-obex-server.h | 78 + bt-service/include/bt-service-oob.h | 44 + bt-service/include/bt-service-opp-client.h | 76 + bt-service/include/bt-service-rfcomm-client.h | 56 + bt-service/include/bt-service-rfcomm-server.h | 76 + bt-service/include/bt-service-util.h | 62 + bt-service/include/stacktrim.h | 64 + bt-service/marshal.list | 18 + bt-service/org.projectx.bt.service | 4 + debian/bluetooth-frwk-agent.install.in | 8 + debian/bluetooth-map-agent.install.in | 2 + debian/bluetooth-pb-agent.install.in | 2 + debian/changelog | 1915 ++++++++++++ debian/compat | 1 + debian/control | 46 + debian/libbluetooth-frwk-0.install.in | 1 + debian/libbluetooth-frwk-0.postinst | 14 + debian/libbluetooth-frwk-dev.install.in | 2 + debian/rules | 155 + include/bluetooth-api.h | 3270 +++++++++++++++++++++ include/bluetooth-audio-api.h | 190 ++ include/bluetooth-hid-api.h | 136 + include/bluetooth-media-control.h | 206 ++ include/bluetooth-telephony-api.h | 345 +++ include/bt-internal-types.h | 264 ++ packaging/bluetooth-frwk.spec | 118 + test/CMakeLists.txt | 38 + test/bluetooth-frwk-test.c | 1634 ++++++++++ test/media-control/CMakeLists.txt | 32 + test/media-control/bluetooth-media-control-test.c | 233 ++ test/telephony/CMakeLists.txt | 32 + test/telephony/bluetooth-telephony-test.c | 337 +++ 110 files changed, 33908 insertions(+) create mode 100644 AUTHORS create mode 100644 CMakeLists.txt create mode 100644 LICENSE.APLv2 create mode 100644 NOTICE create mode 100644 bluetooth-frwk.manifest create mode 100644 bt-api/CMakeLists.txt create mode 100644 bt-api/bluetooth-api.pc.in create mode 100644 bt-api/bt-adapter.c create mode 100644 bt-api/bt-audio.c create mode 100644 bt-api/bt-avrcp.c create mode 100644 bt-api/bt-common.c create mode 100644 bt-api/bt-device.c create mode 100644 bt-api/bt-event-handler.c create mode 100644 bt-api/bt-gatt.c create mode 100644 bt-api/bt-gatt.xml create mode 100644 bt-api/bt-hdp.c create mode 100644 bt-api/bt-hid.c create mode 100644 bt-api/bt-network.c create mode 100644 bt-api/bt-obex-server.c create mode 100644 bt-api/bt-oob.c create mode 100644 bt-api/bt-opp-client.c create mode 100644 bt-api/bt-request-sender.c create mode 100644 bt-api/bt-request-service.xml create mode 100644 bt-api/bt-rfcomm-client.c create mode 100644 bt-api/bt-rfcomm-server.c create mode 100644 bt-api/bt-service-api.pc.in create mode 100644 bt-api/bt-telephony.c create mode 100644 bt-api/bt-telephony.xml create mode 100644 bt-api/include/bt-common.h create mode 100644 bt-api/include/bt-event-handler.h create mode 100644 bt-api/include/bt-request-sender.h create mode 100644 bt-api/marshal.list create mode 100644 bt-core/CMakeLists.txt create mode 100644 bt-core/bt_core.c create mode 100644 bt-core/bt_core.h create mode 100644 bt-core/bt_core.xml create mode 100644 bt-core/org.projectx.bt_core.service create mode 100644 bt-service/CMakeLists.txt create mode 100644 bt-service/auto-pair-blacklist create mode 100644 bt-service/bluetooth-frwk-service create mode 100644 bt-service/bluetooth-frwk-service.service create mode 100644 bt-service/bt-request-handler.c create mode 100644 bt-service/bt-request-service.xml create mode 100644 bt-service/bt-service-adapter.c create mode 100644 bt-service/bt-service-agent.c create mode 100644 bt-service/bt-service-audio.c create mode 100644 bt-service/bt-service-avrcp.c create mode 100644 bt-service/bt-service-common.c create mode 100644 bt-service/bt-service-device.c create mode 100644 bt-service/bt-service-event-receiver.c create mode 100644 bt-service/bt-service-event-sender.c create mode 100644 bt-service/bt-service-gap-agent.c create mode 100644 bt-service/bt-service-gap-agent.xml create mode 100644 bt-service/bt-service-hid.c create mode 100644 bt-service/bt-service-main.c create mode 100644 bt-service/bt-service-media-agent.xml create mode 100644 bt-service/bt-service-network.c create mode 100644 bt-service/bt-service-obex-agent.c create mode 100644 bt-service/bt-service-obex-agent.xml create mode 100644 bt-service/bt-service-obex-server.c create mode 100644 bt-service/bt-service-oob.c create mode 100644 bt-service/bt-service-opp-client.c create mode 100644 bt-service/bt-service-rfcomm-client.c create mode 100644 bt-service/bt-service-rfcomm-server.c create mode 100644 bt-service/bt-service-util.c create mode 100644 bt-service/include/bt-request-handler.h create mode 100644 bt-service/include/bt-service-adapter.h create mode 100644 bt-service/include/bt-service-agent.h create mode 100644 bt-service/include/bt-service-audio.h create mode 100644 bt-service/include/bt-service-avrcp.h create mode 100644 bt-service/include/bt-service-common.h create mode 100644 bt-service/include/bt-service-device.h create mode 100644 bt-service/include/bt-service-event.h create mode 100644 bt-service/include/bt-service-gap-agent.h create mode 100644 bt-service/include/bt-service-hid.h create mode 100644 bt-service/include/bt-service-main.h create mode 100644 bt-service/include/bt-service-network.h create mode 100644 bt-service/include/bt-service-obex-agent.h create mode 100644 bt-service/include/bt-service-obex-server.h create mode 100644 bt-service/include/bt-service-oob.h create mode 100644 bt-service/include/bt-service-opp-client.h create mode 100644 bt-service/include/bt-service-rfcomm-client.h create mode 100644 bt-service/include/bt-service-rfcomm-server.h create mode 100644 bt-service/include/bt-service-util.h create mode 100644 bt-service/include/stacktrim.h create mode 100644 bt-service/marshal.list create mode 100644 bt-service/org.projectx.bt.service create mode 100644 debian/bluetooth-frwk-agent.install.in create mode 100644 debian/bluetooth-map-agent.install.in create mode 100644 debian/bluetooth-pb-agent.install.in create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/control create mode 100644 debian/libbluetooth-frwk-0.install.in create mode 100644 debian/libbluetooth-frwk-0.postinst create mode 100644 debian/libbluetooth-frwk-dev.install.in create mode 100755 debian/rules create mode 100644 include/bluetooth-api.h create mode 100644 include/bluetooth-audio-api.h create mode 100644 include/bluetooth-hid-api.h create mode 100644 include/bluetooth-media-control.h create mode 100644 include/bluetooth-telephony-api.h create mode 100644 include/bt-internal-types.h create mode 100644 packaging/bluetooth-frwk.spec create mode 100644 test/CMakeLists.txt create mode 100644 test/bluetooth-frwk-test.c create mode 100644 test/media-control/CMakeLists.txt create mode 100644 test/media-control/bluetooth-media-control-test.c create mode 100644 test/telephony/CMakeLists.txt create mode 100644 test/telephony/bluetooth-telephony-test.c diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..46d1687 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,2 @@ +Jinmin Jung +DoHyun Pyun diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..5cf4d1a --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,9 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) + +ADD_SUBDIRECTORY(bt-api) + +ADD_SUBDIRECTORY(bt-service) + +ADD_SUBDIRECTORY(bt-core) + +#ADD_SUBDIRECTORY(test) diff --git a/LICENSE.APLv2 b/LICENSE.APLv2 new file mode 100644 index 0000000..a06208b --- /dev/null +++ b/LICENSE.APLv2 @@ -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/NOTICE b/NOTICE new file mode 100644 index 0000000..0e0f016 --- /dev/null +++ b/NOTICE @@ -0,0 +1,3 @@ +Copyright (c) Samsung Electronics Co., Ltd. All rights reserved. +Except as noted, this software is licensed under Apache License, Version 2. +Please, see the LICENSE.APLv2 file for Apache License terms and conditions. diff --git a/bluetooth-frwk.manifest b/bluetooth-frwk.manifest new file mode 100644 index 0000000..75b0fa5 --- /dev/null +++ b/bluetooth-frwk.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/bt-api/CMakeLists.txt b/bt-api/CMakeLists.txt new file mode 100644 index 0000000..1db2e69 --- /dev/null +++ b/bt-api/CMakeLists.txt @@ -0,0 +1,81 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(bt-service-api C) + +SET(SRCS +bt-common.c +bt-adapter.c +bt-device.c +bt-hid.c +bt-network.c +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 +bt-rfcomm-client.c +bt-rfcomm-server.c +bt-request-sender.c +bt-event-handler.c +) + +SET(HEADERS +bluetooth-api.h +bluetooth-hid-api.h +bluetooth-audio-api.h +bluetooth-telephony-api.h +bluetooth-media-control.h) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(EXEC_PREFIX "\${prefix}") +SET(LIBDIR "\${prefix}/lib") +SET(INCLUDEDIR "\${prefix}/include") +SET(VERSION_MAJOR 1) +SET(VERSION ${VERSION_MAJOR}.0.0) + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include) + +INCLUDE(FindPkgConfig) +pkg_check_modules(packages REQUIRED dlog dbus-glib-1 gobject-2.0 gmodule-2.0 vconf +libxml-2.0 syspopup-caller) + +FOREACH(flag ${packages_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -Wall") +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g ") + +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") + +FIND_PROGRAM(MARSHALTOOL NAMES glib-genmarshal) +EXEC_PROGRAM("${MARSHALTOOL}" ARGS "--prefix=marshal ${CMAKE_CURRENT_SOURCE_DIR}/marshal.list --header > ${CMAKE_CURRENT_SOURCE_DIR}/include/marshal.h") +EXEC_PROGRAM("${MARSHALTOOL}" ARGS "--prefix=marshal ${CMAKE_CURRENT_SOURCE_DIR}/marshal.list --body > ${CMAKE_CURRENT_SOURCE_DIR}/marshal.c") + +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-client --output=${CMAKE_CURRENT_SOURCE_DIR}/include/bt-request-service.h") +EXEC_PROGRAM("${DBUS_BINDING_TOOL}" ARGS "--prefix=bluetooth_gatt ${CMAKE_CURRENT_SOURCE_DIR}/bt-gatt.xml --mode=glib-server --output=${CMAKE_CURRENT_SOURCE_DIR}/include/bt-gatt-glue.h") +EXEC_PROGRAM("${DBUS_BINDING_TOOL}" ARGS "--prefix=bluetooth_telephony_method ${CMAKE_CURRENT_SOURCE_DIR}/bt-telephony.xml --mode=glib-server --output=${CMAKE_CURRENT_SOURCE_DIR}/include/bt-telephony-glue.h") + +ADD_LIBRARY(bluetooth-api SHARED ${SRCS}) +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/pkgconfig) +INSTALL(TARGETS bluetooth-api DESTINATION lib COMPONENT RuntimeLibraries) + +FOREACH(hfile ${HEADERS}) + INSTALL(FILES ${CMAKE_SOURCE_DIR}/include/${hfile} DESTINATION include/bt-service) +ENDFOREACH(hfile) diff --git a/bt-api/bluetooth-api.pc.in b/bt-api/bluetooth-api.pc.in new file mode 100644 index 0000000..c7210a4 --- /dev/null +++ b/bt-api/bluetooth-api.pc.in @@ -0,0 +1,11 @@ +prefix=@PREFIX@ +exec_prefix=@EXEC_PREFIX@ +libdir=@LIBDIR@ +includedir=@INCLUDEDIR@ + +Name: bluetooth-api +Description: SAMSUNG Linux platform Bluetooth framework API +Version: @VERSION@ +Requires: dlog dbus-glib-1 vconf +Libs: -L${libdir} -lbluetooth-api +Cflags: -I${includedir} -I${includedir}/bt-service diff --git a/bt-api/bt-adapter.c b/bt-api/bt-adapter.c new file mode 100644 index 0000000..ebdfc91 --- /dev/null +++ b/bt-api/bt-adapter.c @@ -0,0 +1,366 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 int __bt_fill_device_list(GArray *out_param2, GPtrArray **dev_list) +{ + int i; + guint size; + bluetooth_device_info_t info; + + BT_CHECK_PARAMETER(out_param2); + BT_CHECK_PARAMETER(dev_list); + + size = out_param2->len; + retv_if(size == 0, BLUETOOTH_ERROR_NONE); + + size = (out_param2->len) / sizeof(bluetooth_device_info_t); + + for (i = 0; i < size; i++) { + bluetooth_device_info_t *dev_info = NULL; + + info = g_array_index(out_param2, + bluetooth_device_info_t, i); + + dev_info = g_memdup(&info, sizeof(bluetooth_device_info_t)); + + if (dev_info) { + g_ptr_array_add(*dev_list, (gpointer)dev_info); + } + } + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_check_adapter(void) +{ + int ret; + + ret = _bt_get_adapter_path(_bt_get_system_gconn(), NULL); + + return ret == BLUETOOTH_ERROR_NONE ? BLUETOOTH_ADAPTER_ENABLED : + BLUETOOTH_ADAPTER_DISABLED; +} + +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); + + retv_if(bluetooth_check_adapter() == BLUETOOTH_ADAPTER_ENABLED, + BLUETOOTH_ERROR_DEVICE_ALREADY_ENABLED); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_ENABLE_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_disable_adapter(void) +{ + int result; + + BT_CHECK_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, + 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_local_address(bluetooth_device_address_t *local_address) +{ + int result; + + BT_CHECK_PARAMETER(local_address); + BT_CHECK_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_GET_LOCAL_ADDRESS, + in_param1, in_param2, in_param3, in_param4, &out_param); + + if (result == BLUETOOTH_ERROR_NONE) { + *local_address = g_array_index(out_param, + bluetooth_device_address_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); + BT_CHECK_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_GET_LOCAL_NAME, + in_param1, in_param2, in_param3, in_param4, &out_param); + + if (result == BLUETOOTH_ERROR_NONE) { + *local_name = g_array_index(out_param, + bluetooth_device_name_t, 0); + } + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_set_local_name(const bluetooth_device_name_t *local_name) +{ + int result; + + BT_CHECK_PARAMETER(local_name); + BT_CHECK_ENABLED(); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, local_name, sizeof(bluetooth_device_name_t)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_SET_LOCAL_NAME, + 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_service_used(const char *service_uuid, + gboolean *used) +{ + int result; + char uuid[BLUETOOTH_UUID_STRING_MAX]; + + BT_CHECK_PARAMETER(service_uuid); + BT_CHECK_PARAMETER(used); + BT_CHECK_ENABLED(); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_strlcpy(uuid, service_uuid, sizeof(uuid)); + g_array_append_vals(in_param1, uuid, BLUETOOTH_UUID_STRING_MAX); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_IS_SERVICE_USED, + in_param1, in_param2, in_param3, in_param4, &out_param); + + if (result == BLUETOOTH_ERROR_NONE) { + *used = g_array_index(out_param, gboolean, 0); + } + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_get_discoverable_mode(bluetooth_discoverable_mode_t * + discoverable_mode_ptr) +{ + int result; + int timeout = 0; + + BT_CHECK_PARAMETER(discoverable_mode_ptr); + + /* 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; + } + + 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_DISCOVERABLE_MODE, + 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); + } + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_set_discoverable_mode(bluetooth_discoverable_mode_t discoverable_mode, + int timeout) +{ + int result; + + BT_CHECK_ENABLED(); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, &discoverable_mode, sizeof(int)); + g_array_append_vals(in_param2, &timeout, sizeof(int)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_SET_DISCOVERABLE_MODE, + 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_timeout_value(int *timeout) +{ + int result; + + BT_CHECK_PARAMETER(timeout); + BT_CHECK_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_GET_DISCOVERABLE_TIME, + in_param1, in_param2, in_param3, in_param4, &out_param); + + if (result == BLUETOOTH_ERROR_NONE) { + *timeout = 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_start_discovery(unsigned short max_response, + unsigned short discovery_duration, + unsigned int classOfDeviceMask) +{ + int result; + + BT_CHECK_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_START_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; + + BT_CHECK_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_CANCEL_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_discovering(void) +{ + int result; + int is_discovering = FALSE; + + BT_CHECK_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_IS_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; +} + +BT_EXPORT_API int bluetooth_get_bonded_device_list(GPtrArray **dev_list) +{ + int result; + + BT_CHECK_PARAMETER(dev_list); + BT_CHECK_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_GET_BONDED_DEVICES, + in_param1, in_param2, in_param3, in_param4, &out_param); + + 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; +} + diff --git a/bt-api/bt-audio.c b/bt-api/bt-audio.c new file mode 100644 index 0000000..450ceab --- /dev/null +++ b/bt-api/bt-audio.c @@ -0,0 +1,248 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "bluetooth-api.h" +#include "bluetooth-audio-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_audio_init(bt_audio_func_ptr cb, void *user_data) +{ + int ret; + + 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_AUDIO, (void *)cb, user_data); + + /* Register All events */ + _bt_register_event(BT_HEADSET_EVENT , (void *)cb, user_data); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_audio_deinit(void) +{ + _bt_unregister_event(BT_HEADSET_EVENT); + + _bt_set_user_data(BT_AUDIO, NULL, NULL); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_audio_connect(bluetooth_device_address_t *remote_address) +{ + int result; + bt_user_info_t *user_info; + + BT_CHECK_PARAMETER(remote_address); + BT_CHECK_ENABLED(); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + user_info = _bt_get_user_data(BT_AUDIO); + retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + + g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t)); + + result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_AUDIO_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_audio_disconnect(bluetooth_device_address_t *remote_address) +{ + int result; + bt_user_info_t *user_info; + + BT_CHECK_PARAMETER(remote_address); + BT_CHECK_ENABLED(); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + user_info = _bt_get_user_data(BT_AUDIO); + retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + + g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t)); + + result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_AUDIO_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_ag_connect(bluetooth_device_address_t *remote_address) +{ + int result; + bt_user_info_t *user_info; + + BT_CHECK_PARAMETER(remote_address); + BT_CHECK_ENABLED(); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + user_info = _bt_get_user_data(BT_AUDIO); + retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + + g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t)); + + result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_AG_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_ag_disconnect(bluetooth_device_address_t *remote_address) +{ + int result; + bt_user_info_t *user_info; + + BT_CHECK_PARAMETER(remote_address); + BT_CHECK_ENABLED(); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + user_info = _bt_get_user_data(BT_AUDIO); + retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + + g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t)); + + result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_AG_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_av_connect(bluetooth_device_address_t *remote_address) +{ + int result; + bt_user_info_t *user_info; + + BT_CHECK_PARAMETER(remote_address); + BT_CHECK_ENABLED(); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + user_info = _bt_get_user_data(BT_AUDIO); + retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + + g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t)); + + result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_AV_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_av_disconnect(bluetooth_device_address_t *remote_address) +{ + int result; + bt_user_info_t *user_info; + + BT_CHECK_PARAMETER(remote_address); + BT_CHECK_ENABLED(); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + user_info = _bt_get_user_data(BT_AUDIO); + retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + + g_array_append_vals(in_param1, remote_address, sizeof(bluetooth_device_address_t)); + + result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_AV_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_ag_get_headset_volume(unsigned int *speaker_gain) +{ + int result; + + BT_CHECK_PARAMETER(speaker_gain); + BT_CHECK_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_GET_SPEAKER_GAIN, + in_param1, in_param2, in_param3, in_param4, &out_param); + + if (result == BLUETOOTH_ERROR_NONE) { + *speaker_gain = g_array_index(out_param, + unsigned int, 0); + } + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_ag_set_speaker_gain(unsigned int speaker_gain) +{ + int result; + + BT_CHECK_ENABLED(); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, &speaker_gain, sizeof(unsigned int)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_SET_SPEAKER_GAIN, + 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-avrcp.c b/bt-api/bt-avrcp.c new file mode 100644 index 0000000..8e166df --- /dev/null +++ b/bt-api/bt-avrcp.c @@ -0,0 +1,140 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "bluetooth-api.h" +#include "bluetooth-media-control.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_media_player_init(media_cb_func_ptr callback_ptr, + void *user_data) +{ + int ret; + + /* Register AVRCP events */ + ret = _bt_register_event(BT_AVRCP_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_player_deinit(void) +{ + int ret; + + ret = _bt_unregister_event(BT_AVRCP_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_player_change_property( + media_player_property_type type, + unsigned int value) +{ + int result; + + BT_CHECK_ENABLED(); + + 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_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_player_set_properties( + media_player_settings_t *setting) +{ + int result; + + BT_CHECK_PARAMETER(setting); + BT_CHECK_ENABLED(); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, setting, sizeof(media_player_settings_t)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_AVRCP_SET_PROPERTIES, + 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_player_change_track( + media_metadata_attributes_t *metadata) +{ + int result; + media_metadata_t meta_data; + + BT_CHECK_PARAMETER(metadata); + BT_CHECK_ENABLED(); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + memset(&meta_data, 0x00, sizeof(media_metadata_t)); + + g_strlcpy(meta_data.title, metadata->title, BT_NAME_MAX); + g_strlcpy(meta_data.artist, metadata->artist, BT_NAME_MAX); + g_strlcpy(meta_data.album, metadata->album, BT_NAME_MAX); + g_strlcpy(meta_data.genre, metadata->genre, BT_NAME_MAX); + 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)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_AVRCP_SET_TRACK_INFO, + 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-common.c b/bt-api/bt-common.c new file mode 100644 index 0000000..9629991 --- /dev/null +++ b/bt-api/bt-common.c @@ -0,0 +1,378 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "bluetooth-api.h" +#include "bluetooth-audio-api.h" +#include "bluetooth-hid-api.h" +#include "bluetooth-media-control.h" +#include "bt-internal-types.h" + +#include "bt-common.h" +#include "bt-request-sender.h" +#include "bt-event-handler.h" + +static bt_user_info_t user_info[BT_MAX_USER_INFO]; +static DBusGConnection *system_conn = NULL; + +void _bt_print_device_address_t(const bluetooth_device_address_t *addr) +{ + BT_DBG("%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", addr->addr[0], addr->addr[1], addr->addr[2], + addr->addr[3], addr->addr[4], addr->addr[5]); +} + +void _bt_set_user_data(int type, void *callback, void *user_data) +{ + user_info[type].cb = callback; + user_info[type].user_data = user_data; +} + +bt_user_info_t *_bt_get_user_data(int type) +{ + return &user_info[type]; +} + +void _bt_common_event_cb(int event, int result, void *param, + void *callback, void *user_data) +{ + bluetooth_event_param_t bt_event = { 0, }; + bt_event.event = event; + bt_event.result = result; + bt_event.param_data = param; + + if (callback) + ((bluetooth_cb_func_ptr)callback)(bt_event.event, &bt_event, + user_data); +} + +void _bt_input_event_cb(int event, int result, void *param, + void *callback, void *user_data) +{ + hid_event_param_t bt_event = { 0, }; + bt_event.event = event; + bt_event.result = result; + bt_event.param_data = param; + + if (callback) + ((hid_cb_func_ptr)callback)(bt_event.event, &bt_event, + user_data); +} + +void _bt_headset_event_cb(int event, int result, void *param, + void *callback, void *user_data) +{ + bt_audio_event_param_t bt_event = { 0, }; + bt_event.event = event; + bt_event.result = result; + bt_event.param_data = param; + + if (callback) + ((bt_audio_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) +{ + media_event_param_t bt_event = { 0, }; + bt_event.event = event; + bt_event.result = result; + bt_event.param_data = param; + + if (callback) + ((media_cb_func_ptr)callback)(bt_event.event, &bt_event, + user_data); +} + +void _bt_divide_device_class(bluetooth_device_class_t *device_class, + unsigned int cod) +{ + ret_if(device_class == NULL); + + device_class->major_class = (unsigned short)(cod & 0x00001F00) >> 8; + device_class->minor_class = (unsigned short)((cod & 0x000000FC)); + device_class->service_class = (unsigned long)((cod & 0x00FF0000)); + + if (cod & 0x002000) { + device_class->service_class |= + BLUETOOTH_DEVICE_SERVICE_CLASS_LIMITED_DISCOVERABLE_MODE; + } +} + +void _bt_convert_addr_string_to_type(unsigned char *addr, + const char *address) +{ + int i; + char *ptr = NULL; + + ret_if(address == NULL); + ret_if(addr == NULL); + + for (i = 0; i < BT_ADDRESS_LENGTH_MAX; i++) { + addr[i] = strtol(address, &ptr, 16); + if (ptr != NULL) { + if (ptr[0] != ':') + return; + + address = ptr + 1; + } + } +} + +void _bt_convert_addr_type_to_string(char *address, + unsigned char *addr) +{ + ret_if(address == NULL); + ret_if(addr == NULL); + + g_snprintf(address, BT_ADDRESS_STRING_SIZE, + "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", + addr[0], addr[1], addr[2], + addr[3], addr[4], addr[5]); +} + +int _bt_get_adapter_path(DBusGConnection *conn, char *path) +{ + GError *err = NULL; + DBusGProxy *manager_proxy = NULL; + char *adapter_path = NULL; + int ret = BLUETOOTH_ERROR_NONE; + + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + manager_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + BT_MANAGER_PATH, BT_MANAGER_INTERFACE); + + retv_if(manager_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + 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 BLUETOOTH_ERROR_INTERNAL; + } + + if (adapter_path == NULL || strlen(adapter_path) >= BT_ADAPTER_OBJECT_PATH_MAX) { + BT_ERR("Adapter path is inproper\n"); + ret = BLUETOOTH_ERROR_INTERNAL; + goto done; + } + + if (path) + g_strlcpy(path, adapter_path, BT_ADAPTER_OBJECT_PATH_MAX); +done: + g_free(adapter_path); + g_object_unref(manager_proxy); + + return ret; +} + +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); + + 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; +} + +void _bt_device_path_to_address(const char *device_path, char *device_address) +{ + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + char *dev_addr = NULL; + + if (!device_path || !device_address) + return; + + 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); + } +} + +DBusGConnection *__bt_init_system_gconn(void) +{ + g_type_init(); + + if (system_conn == NULL) + system_conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL); + + return system_conn; +} + +DBusGConnection *_bt_get_system_gconn(void) +{ + return (system_conn) ? system_conn : __bt_init_system_gconn(); +} + +DBusConnection *_bt_get_system_conn(void) +{ + DBusGConnection *g_conn; + + if (system_conn == NULL) { + g_conn = __bt_init_system_gconn(); + } else { + g_conn = system_conn; + } + + retv_if(g_conn == NULL, NULL); + + return dbus_g_connection_get_connection(g_conn); +} + +BT_EXPORT_API int bluetooth_is_supported(void) +{ + int is_supported = 0; + int len = 0; + int fd = -1; + rfkill_event event; + + fd = open(RFKILL_NODE, O_RDONLY); + if (fd < 0) { + BT_DBG("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"); + close(fd); + return BLUETOOTH_ERROR_INTERNAL; + } + + while (1) { + len = read(fd, &event, sizeof(event)); + if (len < 0) { + BT_DBG("Fail to read events"); + break; + } + + if (len != RFKILL_EVENT_SIZE) { + BT_DBG("The size is wrong\n"); + continue; + } + + if (event.type == RFKILL_TYPE_BLUETOOTH) { + is_supported = 1; + break; + } + } + + close(fd); + + BT_DBG("supported: %d", is_supported); + + return is_supported; +} + +BT_EXPORT_API int bluetooth_register_callback(bluetooth_cb_func_ptr callback_ptr, void *user_data) +{ + int ret; + + __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_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); + + return BLUETOOTH_ERROR_NONE; +} + +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); + + _bt_set_user_data(BT_COMMON, NULL, NULL); + + if (system_conn) { + dbus_g_connection_unref(system_conn); + system_conn = NULL; + } + + return BLUETOOTH_ERROR_NONE; +} + diff --git a/bt-api/bt-device.c b/bt-api/bt-device.c new file mode 100644 index 0000000..118435e --- /dev/null +++ b/bt-api/bt-device.c @@ -0,0 +1,246 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "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_bond_device(const bluetooth_device_address_t *device_address) +{ + int result; + bt_user_info_t *user_info; + + BT_CHECK_PARAMETER(device_address); + BT_CHECK_ENABLED(); + + 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, 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_cancel_bonding(void) +{ + int result; + + BT_CHECK_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_CANCEL_BONDING, + 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_unbond_device(const bluetooth_device_address_t *device_address) +{ + int result; + bt_user_info_t *user_info; + + BT_CHECK_PARAMETER(device_address); + BT_CHECK_ENABLED(); + + 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, device_address, sizeof(bluetooth_device_address_t)); + + result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_UNBOND_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_get_bonded_device(const bluetooth_device_address_t *device_address, + bluetooth_device_info_t *dev_info) +{ + int result; + + BT_CHECK_PARAMETER(device_address); + BT_CHECK_PARAMETER(dev_info); + BT_CHECK_ENABLED(); + + 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_GET_BONDED_DEVICE, + in_param1, in_param2, in_param3, in_param4, &out_param); + + if (result == BLUETOOTH_ERROR_NONE) { + if (out_param->len > 0) { + *dev_info = g_array_index(out_param, + bluetooth_device_info_t, 0); + } else { + BT_DBG("out_param length is 0!!"); + } + } + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_get_remote_device(const bluetooth_device_address_t *device_address) +{ + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_search_service(const bluetooth_device_address_t *device_address) +{ + int result; + bt_user_info_t *user_info; + + BT_CHECK_PARAMETER(device_address); + BT_CHECK_ENABLED(); + + 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, device_address, sizeof(bluetooth_device_address_t)); + + result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_SEARCH_SERVICE, + 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_cancel_service_search(void) +{ + int result; + + BT_CHECK_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_CANCEL_SEARCH_SERVICE, + 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_alias(const bluetooth_device_address_t *device_address, + const char *alias) +{ + int result; + char alias_name[BLUETOOTH_DEVICE_NAME_LENGTH_MAX]; + + BT_CHECK_PARAMETER(device_address); + BT_CHECK_PARAMETER(alias); + BT_CHECK_ENABLED(); + + 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_strlcpy(alias_name, alias, sizeof(alias_name)); + g_array_append_vals(in_param2, alias_name, BLUETOOTH_DEVICE_NAME_LENGTH_MAX); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_SET_ALIAS, + 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_authorize_device(const bluetooth_device_address_t *device_address, + gboolean authorized) +{ + int result; + + BT_CHECK_PARAMETER(device_address); + BT_CHECK_ENABLED(); + + 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, &authorized, sizeof(gboolean)); + + result = _bt_send_request(BT_BLUEZ_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); + + return result; +} + +BT_EXPORT_API int bluetooth_is_device_connected(const bluetooth_device_address_t *device_address, + bluetooth_service_type_t type, + gboolean *is_connected) +{ + int result; + + BT_CHECK_PARAMETER(device_address); + BT_CHECK_PARAMETER(is_connected); + BT_CHECK_ENABLED(); + + 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, &type, sizeof(int)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_IS_DEVICE_CONNECTED, + in_param1, in_param2, in_param3, in_param4, &out_param); + + if (result == BLUETOOTH_ERROR_NONE) { + *is_connected = g_array_index(out_param, gboolean, 0); + } + + 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 new file mode 100644 index 0000000..f55b748 --- /dev/null +++ b/bt-api/bt-event-handler.c @@ -0,0 +1,1829 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "bluetooth-api.h" +#include "bluetooth-audio-api.h" +#include "bt-internal-types.h" + +#include "bt-common.h" +#include "bt-event-handler.h" +#include "bt-request-sender.h" + +typedef struct { + int server_fd; +} bt_server_info_t; + +typedef struct { + int request_id; +} bt_sending_info_t; + +static int obex_server_id; +static gboolean is_initialized; +static GSList *sending_list = NULL; +static GSList *server_list = NULL; +static GSList *event_list = NULL; + +void _bt_add_push_request_id(int request_id) +{ + bt_sending_info_t *info; + + info = g_new0(bt_sending_info_t, 1); + info->request_id = request_id; + + sending_list = g_slist_append(sending_list, info); +} + +static gboolean __bt_is_request_id_exist(int request_id) +{ + GSList *l; + bt_sending_info_t *info; + + for (l = sending_list; l != NULL; l = g_slist_next(l)) { + info = l->data; + if (info == NULL) + continue; + + retv_if(info->request_id == request_id, TRUE); + } + + return FALSE; +} + +static void __bt_remove_push_request_id(int request_id) +{ + GSList *l; + bt_sending_info_t *info; + + for (l = sending_list; l != NULL; l = g_slist_next(l)) { + info = l->data; + if (info == NULL) + continue; + + if (info->request_id == request_id) { + sending_list = g_slist_remove(sending_list, (void *)info); + g_free(info); + break; + } + } +} + +static void __bt_remove_all_push_request_id(void) +{ + GSList *l; + bt_sending_info_t *info; + + for (l = sending_list; l != NULL; l = g_slist_next(l)) { + info = l->data; + g_free(info); + } + + g_slist_free(sending_list); + sending_list = NULL; +} + +static void __bt_remove_all_server(void) +{ + GSList *l; + bt_server_info_t *info; + + for (l = server_list; l != NULL; l = g_slist_next(l)) { + info = l->data; + g_free(info); + } + + g_slist_free(server_list); + server_list = NULL; +} + +static gboolean __bt_is_server_exist(int server_fd) +{ + GSList *l; + bt_server_info_t *info; + + for (l = server_list; l != NULL; l = g_slist_next(l)) { + info = l->data; + if (info == NULL) + continue; + + retv_if(info->server_fd == server_fd, TRUE); + } + + return FALSE; +} + +static void __bt_get_uuid_info(bluetooth_device_info_t *dev_info, + char **uuids, + int uuid_count) +{ + int i; + char **parts; + + ret_if(dev_info == NULL); + ret_if(uuids == NULL); + ret_if(uuid_count <= 0); + + dev_info->service_index = uuid_count; + + for (i = 0; uuids[i] != NULL && i < uuid_count; i++) { + g_strlcpy(dev_info->uuids[i], uuids[i], BLUETOOTH_UUID_STRING_MAX); + + parts = g_strsplit(uuids[i], "-", -1); + + if (parts == NULL || parts[0] == NULL) { + g_strfreev(parts); + continue; + } + + dev_info->service_list_array[i] = g_ascii_strtoull(parts[0], NULL, 16); + g_strfreev(parts); + } +} + +static bluetooth_device_info_t *__bt_get_device_info_in_message(DBusMessage *msg, int *ret) +{ + bluetooth_device_info_t *dev_info; + char *address = NULL; + char *name = NULL; + char **uuids = NULL; + unsigned int class = 0; + int rssi = 0; + gboolean paired = FALSE; + gboolean connected = FALSE; + gboolean trust = FALSE; + int uuid_count = 0; + 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"); + return NULL; + } + + 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); + + _bt_divide_device_class(&dev_info->device_class, class); + + _bt_convert_addr_string_to_type(dev_info->device_address.addr, + address); + + if (uuid_count > 0) + __bt_get_uuid_info(dev_info, uuids, uuid_count); + + *ret = result; + + return dev_info; +} + +static DBusHandlerResult __bt_adapter_event_filter(DBusConnection *conn, + DBusMessage *msg, void *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; + + if (!dbus_message_has_interface(msg, BT_EVENT_SERVICE)) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (!dbus_message_has_path(msg, BT_ADAPTER_PATH)) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + + retv_if(member == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + + 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; + } + + if (result == BLUETOOTH_ERROR_NONE) { + if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0) + BT_ERR("Set vconf failed\n"); + } + + _bt_common_event_cb(BLUETOOTH_EVENT_ENABLED, + result, NULL, + event_info->cb, event_info->user_data); + } else if (strcasecmp(member, BT_DISABLED) == 0) { + _bt_common_event_cb(BLUETOOTH_EVENT_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(); + } else if (strcasecmp(member, 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; + } + + _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) { + 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; + } + + _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; + + 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; + } + + _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) { + _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; + } + + _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; + + device_info = __bt_get_device_info_in_message(msg, &result); + retv_if(device_info == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + + 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(event, + result, device_info, + event_info->cb, event_info->user_data); + + g_free(device_info); + } else if (strcasecmp(member, BT_BOND_CREATED) == 0) { + bluetooth_device_info_t *device_info; + + device_info = __bt_get_device_info_in_message(msg, &result); + + _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; + 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_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) { + bluetooth_device_info_t *device_info; + bt_sdp_info_t sdp_info; + + device_info = __bt_get_device_info_in_message(msg, &result); + + memset(&sdp_info, 0x00, sizeof(bt_sdp_info_t)); + + sdp_info.service_index = device_info->service_index; + + memcpy(&sdp_info.device_addr, + &device_info->device_address, + BLUETOOTH_ADDRESS_LENGTH); + + memcpy(sdp_info.service_list_array, + device_info->service_list_array, + BLUETOOTH_MAX_SERVICES_FOR_DEVICE); + + memcpy(sdp_info.uuids, + device_info->uuids, + BLUETOOTH_MAX_SERVICES_FOR_DEVICE * BLUETOOTH_UUID_STRING_MAX); + + _bt_common_event_cb(BLUETOOTH_EVENT_SERVICE_SEARCHED, + result, &sdp_info, + event_info->cb, event_info->user_data); + + g_free(device_info); + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusHandlerResult __bt_device_event_filter(DBusConnection *conn, + DBusMessage *msg, void *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; + + if (!dbus_message_has_interface(msg, BT_EVENT_SERVICE)) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (!dbus_message_has_path(msg, BT_DEVICE_PATH)) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + + retv_if(member == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + + if (strcasecmp(member, BT_DEVICE_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_DBG("Unexpected parameters in signal"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + _bt_convert_addr_string_to_type(dev_address.addr, + address); + + _bt_common_event_cb(BLUETOOTH_EVENT_DEVICE_CONNECTED, + result, &dev_address, + event_info->cb, event_info->user_data); + } else if (strcasecmp(member, BT_DEVICE_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_DBG("Unexpected parameters in signal"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + _bt_convert_addr_string_to_type(dev_address.addr, + address); + + _bt_common_event_cb(BLUETOOTH_EVENT_DEVICE_DISCONNECTED, + 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) +{ + 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; + + if (!dbus_message_has_interface(msg, BT_EVENT_SERVICE)) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (!dbus_message_has_path(msg, BT_HID_PATH)) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + retv_if(member == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + + if (strcasecmp(member, BT_INPUT_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_DBG("Unexpected parameters in signal"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + _bt_convert_addr_string_to_type(dev_address.addr, + address); + + _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; + 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; + } + + BT_DBG("address: %s", address); + + _bt_convert_addr_string_to_type(dev_address.addr, + address); + + _bt_input_event_cb(BLUETOOTH_HID_DISCONNECTED, + 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) +{ + 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; + + if (!dbus_message_has_interface(msg, BT_EVENT_SERVICE)) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + 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) { + 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; + } + + _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) { + 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; + } + + _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) { + 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; + } + + _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) { + 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; + } + + _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) { + 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; + } + 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) { + 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; + } + 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) +{ + 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; + + 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; + 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_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; + 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_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; + 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; + } + + memset(&network_info, 0x00, sizeof(bluetooth_network_device_info_t)); + + _bt_convert_addr_string_to_type(network_info.device_address.addr, + address); + + _bt_print_device_address_t(&network_info.device_address); + g_strlcpy(network_info.interface_name, device, BLUETOOTH_INTERFACE_NAME_LENGTH); + + BT_DBG("name: %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; + 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; + } + + memset(&network_info, 0x00, sizeof(bluetooth_network_device_info_t)); + + _bt_convert_addr_string_to_type(network_info.device_address.addr, + address); + + _bt_print_device_address_t(&network_info.device_address); + + _bt_common_event_cb(BLUETOOTH_EVENT_NETWORK_SERVER_DISCONNECTED, + 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) +{ + 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; + + if (!dbus_message_has_interface(msg, BT_EVENT_SERVICE)) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (!dbus_message_has_path(msg, BT_AVRCP_PATH)) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + retv_if(member == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + + if (strcasecmp(member, 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; + } + + _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) { + 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; + } + + _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) { + 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; + } + _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) { + 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; + } + _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) { + 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; + } + _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) { + 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; + } + _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) +{ + 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; + + if (!dbus_message_has_interface(msg, BT_EVENT_SERVICE)) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (!dbus_message_has_path(msg, BT_OPP_CLIENT_PATH)) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + retv_if(member == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + + if (strcasecmp(member, BT_OPP_CONNECTED) == 0) { + 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; + } + + if (__bt_is_request_id_exist(request_id) == FALSE) { + BT_ERR("Different request id!"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + _bt_convert_addr_string_to_type(dev_address.addr, + address); + + _bt_common_event_cb(BLUETOOTH_EVENT_OPC_CONNECTED, + result, &dev_address, + event_info->cb, event_info->user_data); + + if (result != BLUETOOTH_ERROR_NONE) { + __bt_remove_push_request_id(request_id); + } + } else if (strcasecmp(member, BT_OPP_DISCONNECTED) == 0) { + 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; + } + + if (__bt_is_request_id_exist(request_id) == FALSE) { + BT_ERR("Different request id!"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + _bt_convert_addr_string_to_type(dev_address.addr, + address); + + _bt_common_event_cb(BLUETOOTH_EVENT_OPC_DISCONNECTED, + result, &dev_address, + 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; + 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; + } + + if (__bt_is_request_id_exist(request_id) == FALSE) { + BT_ERR("Different request id!"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + memset(&transfer_info, 0x00, sizeof(bt_opc_transfer_info_t)); + + transfer_info.filename = g_strdup(file_name); + transfer_info.size = size; + + _bt_common_event_cb(BLUETOOTH_EVENT_OPC_TRANSFER_STARTED, + result, &transfer_info, + event_info->cb, event_info->user_data); + + g_free(transfer_info.filename); + } else if (strcasecmp(member, BT_TRANSFER_PROGRESS) == 0) { + 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; + } + + if (__bt_is_request_id_exist(request_id) == FALSE) { + BT_ERR("Different request id!"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + memset(&transfer_info, 0x00, sizeof(bt_opc_transfer_info_t)); + + transfer_info.filename = g_strdup(file_name); + transfer_info.size = size; + transfer_info.percentage = progress; + + _bt_common_event_cb(BLUETOOTH_EVENT_OPC_TRANSFER_PROGRESS, + result, &transfer_info, + event_info->cb, event_info->user_data); + + g_free(transfer_info.filename); + } else if (strcasecmp(member, BT_TRANSFER_COMPLETED) == 0) { + 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; + } + + if (__bt_is_request_id_exist(request_id) == FALSE) { + BT_ERR("Different request id!"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + memset(&transfer_info, 0x00, sizeof(bt_opc_transfer_info_t)); + + transfer_info.filename = g_strdup(file_name); + transfer_info.size = size; + + _bt_common_event_cb(BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE, + result, &transfer_info, + event_info->cb, event_info->user_data); + + 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) +{ + 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; + + if (!dbus_message_has_interface(msg, BT_EVENT_SERVICE)) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + 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) { + /* Native only event */ + 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; + } + + /* OSP server: Don't get this event */ + retv_if(obex_server_id == BT_CUSTOM_SERVER, + DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + + memset(&auth_info, 0x00, sizeof(bt_obex_server_authorize_into_t)); + + auth_info.filename = g_strdup(file_name); + auth_info.length = size; + + _bt_common_event_cb(BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_AUTHORIZE, + result, &auth_info, + event_info->cb, event_info->user_data); + + g_free(auth_info.filename); + } else if (strcasecmp(member, BT_CONNECTION_AUTHORIZED) == 0) { + /* OSP only event */ + char *address = NULL; + 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; + } + + /* Native server: Don't get this event */ + retv_if(obex_server_id == BT_NATIVE_SERVER, + DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + + _bt_convert_addr_string_to_type(dev_address.addr, + address); + + _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; + 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; + } + + /* Other server's event */ + retv_if(obex_server_id != server_type && + server_type != BT_FTP_SERVER, + DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + + 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.file_size = size; + transfer_info.transfer_id = transfer_id; + + _bt_common_event_cb(BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_STARTED, + result, &transfer_info, + event_info->cb, event_info->user_data); + + 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; + 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; + } + + /* Other server's event */ + retv_if(obex_server_id != server_type && + server_type != BT_FTP_SERVER, + DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + + 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.file_size = size; + transfer_info.transfer_id = transfer_id; + transfer_info.percentage = progress; + + _bt_common_event_cb(BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_PROGRESS, + result, &transfer_info, + event_info->cb, event_info->user_data); + + 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; + 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; + } + + /* Other server's event */ + retv_if(obex_server_id != server_type && + server_type != BT_FTP_SERVER, + DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + + 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_size = size; + transfer_info.transfer_id = transfer_id; + + _bt_common_event_cb(BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_COMPLETED, + result, &transfer_info, + event_info->cb, event_info->user_data); + + g_free(transfer_info.filename); + g_free(transfer_info.type); + g_free(transfer_info.device_name); + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusHandlerResult __bt_rfcomm_client_event_filter(DBusConnection *conn, + DBusMessage *msg, void *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; + + if (!dbus_message_has_interface(msg, BT_EVENT_SERVICE)) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (!dbus_message_has_path(msg, BT_RFCOMM_CLIENT_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; + 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; + } + + memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t)); + conn_info.device_role = RFCOMM_ROLE_CLIENT; + g_strlcpy(conn_info.uuid, uuid, BLUETOOTH_UUID_STRING_MAX); + conn_info.socket_fd = socket_fd; + _bt_convert_addr_string_to_type(conn_info.device_addr.addr, + address); + + _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; + 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; + } + + memset(&disconn_info, 0x00, sizeof(bluetooth_rfcomm_disconnection_t)); + disconn_info.device_role = RFCOMM_ROLE_CLIENT; + g_strlcpy(disconn_info.uuid, uuid, BLUETOOTH_UUID_STRING_MAX); + disconn_info.socket_fd = socket_fd; + _bt_convert_addr_string_to_type(disconn_info.device_addr.addr, + address); + + _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; + int buffer_len = 0; + int socket_fd = 0; + bluetooth_rfcomm_received_data_t data_r; + + 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; + } + + data_r.socket_fd = socket_fd; + data_r.buffer_size = buffer_len; + data_r.buffer = g_memdup(buffer, buffer_len); + + _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_DATA_RECEIVED, + result, &data_r, + event_info->cb, event_info->user_data); + + g_free(data_r.buffer); + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusHandlerResult __bt_rfcomm_server_event_filter(DBusConnection *conn, + DBusMessage *msg, void *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; + + 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; + 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; + } + + memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t)); + conn_info.device_role = RFCOMM_ROLE_SERVER; + g_strlcpy(conn_info.uuid, uuid, BLUETOOTH_UUID_STRING_MAX); + conn_info.socket_fd = socket_fd; + _bt_convert_addr_string_to_type(conn_info.device_addr.addr, + address); + + _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; + 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; + } + + memset(&disconn_info, 0x00, sizeof(bluetooth_rfcomm_disconnection_t)); + disconn_info.device_role = RFCOMM_ROLE_SERVER; + g_strlcpy(disconn_info.uuid, uuid, BLUETOOTH_UUID_STRING_MAX); + disconn_info.socket_fd = socket_fd; + _bt_convert_addr_string_to_type(disconn_info.device_addr.addr, + address); + + _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) { + /* OSP only event */ + bluetooth_rfcomm_connection_request_t req_ind; + char *address = NULL; + char *uuid = NULL; + char *name = 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; + } + + /* Don't send the authorized event to other server */ + retv_if(__bt_is_server_exist(socket_fd) == FALSE, + DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + + memset(&req_ind, 0x00, sizeof(bluetooth_rfcomm_connection_request_t)); + _bt_convert_addr_string_to_type(req_ind.device_addr.addr, + address); + + req_ind.socket_fd = socket_fd; + + _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) { + /* 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; + } + + retv_if(__bt_is_server_exist(socket_fd) == FALSE, + DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + + _bt_remove_server(socket_fd); + } else if (strcasecmp(member, BT_RFCOMM_DATA_RECEIVED) == 0) { + char *buffer = NULL; + int buffer_len = 0; + int socket_fd = 0; + bluetooth_rfcomm_received_data_t data_r; + + 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; + } + + data_r.socket_fd = socket_fd; + data_r.buffer_size = buffer_len; + data_r.buffer = g_memdup(buffer, buffer_len); + + _bt_common_event_cb(BLUETOOTH_EVENT_RFCOMM_DATA_RECEIVED, + result, &data_r, + event_info->cb, event_info->user_data); + + g_free(data_r.buffer); + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static void __bt_remove_all_events(void) +{ + GSList *l; + bt_event_info_t *info; + + for (l = event_list; l != NULL; l = g_slist_next(l)) { + info = l->data; + + if (info) + _bt_unregister_event(info->event_type); + } + + g_slist_free(event_list); + event_list = NULL; +} + +static gboolean __bt_event_is_registered(int event_type) +{ + GSList *l; + bt_event_info_t *info; + + for (l = event_list; l != NULL; l = g_slist_next(l)) { + info = l->data; + if (info == NULL) + continue; + + retv_if(info->event_type == event_type, TRUE); + } + + return FALSE; +} + +bt_event_info_t* __bt_event_get_cb_data(int event_type) +{ + GSList *l; + bt_event_info_t *info; + + for (l = event_list; l != NULL; l = g_slist_next(l)) { + info = l->data; + if (info == NULL) + continue; + + if (info->event_type == event_type) + return info; + } + + return NULL; +} + +void _bt_add_server(int server_fd) +{ + bt_server_info_t *info; + + info = g_new0(bt_server_info_t, 1); + info->server_fd = server_fd; + + server_list = g_slist_append(server_list, info); +} + +void _bt_remove_server(int server_fd) +{ + GSList *l; + bt_server_info_t *info; + + for (l = server_list; l != NULL; l = g_slist_next(l)) { + info = l->data; + if (info == NULL) + continue; + + if (info->server_fd == server_fd) { + server_list = g_slist_remove(server_list, (void *)info); + } + + g_free(info); + } +} + +void _bt_set_obex_server_id(int server_type) +{ + obex_server_id = server_type; +} + +int _bt_get_obex_server_id(void) +{ + return obex_server_id; +} + +int _bt_init_event_handler(void) +{ + if (is_initialized == TRUE) { + BT_ERR("Connection already exist"); + return BLUETOOTH_ERROR_ALREADY_INITIALIZED; + } + + __bt_remove_all_events(); + + is_initialized = TRUE; + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_deinit_event_handler(void) +{ + if (is_initialized == FALSE) { + BT_ERR("Connection dose not exist"); + return BLUETOOTH_ERROR_INTERNAL; + } + + __bt_remove_all_events(); + + is_initialized = FALSE; + + return BLUETOOTH_ERROR_NONE; +} + +static void __bt_event_data_free(void *data) +{ + bt_event_info_t *cb_data = data; + + ret_if(cb_data == NULL); + + if (cb_data->conn) + dbus_connection_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; + bt_event_info_t *cb_data; + + if (is_initialized == FALSE) + _bt_init_event_handler(); + + if (__bt_event_is_registered(event_type) == TRUE) { + BT_ERR("The event is already registed"); + return BLUETOOTH_ERROR_ALREADY_INITIALIZED; + } + + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + break; + default: + BT_ERR("Unknown event"); + 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->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; + } + + g_free(match); + + 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; + bt_event_info_t *cb_data; + + if (is_initialized == FALSE) { + BT_ERR("Event is not registered"); + return BLUETOOTH_ERROR_INTERNAL; + } + + if (__bt_event_is_registered(event_type) == FALSE) { + BT_ERR("Not registered event"); + return BLUETOOTH_ERROR_INTERNAL; + } + + cb_data = __bt_event_get_cb_data(event_type); + + if (cb_data == NULL) { + BT_ERR("No matched event data"); + return BLUETOOTH_ERROR_INTERNAL; + } + + connection_type = cb_data->conn; + event_func = cb_data->func; + + 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_connection_remove_filter(connection_type, event_func, + (void *)cb_data); + + return BLUETOOTH_ERROR_NONE; +} diff --git a/bt-api/bt-gatt.c b/bt-api/bt-gatt.c new file mode 100644 index 0000000..10e1da3 --- /dev/null +++ b/bt-api/bt-gatt.c @@ -0,0 +1,615 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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; + +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) { + _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; + + path = g_malloc0(gp->len * 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) { + _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); +} + +BT_EXPORT_API int bluetooth_gatt_free_primary_services(bt_gatt_handle_info_t *prim_svc) +{ + BT_DBG("+"); + + BT_CHECK_PARAMETER(prim_svc); + + g_strfreev(prim_svc->handle); + + 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); + + g_free(svc_pty->uuid); + g_strfreev(svc_pty->handle_info.handle); + + 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); + + g_free(char_pty->uuid); + g_free(char_pty->name); + g_free(char_pty->description); + g_free(char_pty->val); + + 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; + DBusGProxy *device_proxy = NULL; + GHashTable *hash = NULL; + GValue *value = NULL; + GPtrArray *gp_array = NULL; + DBusGProxy *adapter_proxy; + DBusGConnection *conn; + int ret = BLUETOOTH_ERROR_INTERNAL; + + BT_DBG("+"); + + BT_CHECK_PARAMETER(address); + BT_CHECK_PARAMETER(prim_svc); + + BT_CHECK_ENABLED(); + + _bt_convert_addr_type_to_string(device_address, + (unsigned char *)address->addr); + + BT_DBG("bluetooth address [%s]\n", device_address); + + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + adapter_proxy = _bt_get_adapter_proxy(conn); + retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call(adapter_proxy, "FindDevice", &error, + G_TYPE_STRING, device_address, G_TYPE_INVALID, + DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID); + if (error) { + BT_ERR("FindDevice Call Error %s[%s]", error->message, device_address); + g_error_free(error); + g_object_unref(adapter_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + + g_object_unref(adapter_proxy); + + 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, "GetProperties", &error, G_TYPE_INVALID, + dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), + &hash, G_TYPE_INVALID); + if (error) { + BT_ERR("GetProperties 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); + + retv_if(hash == NULL, BLUETOOTH_ERROR_INTERNAL); + + value = g_hash_table_lookup(hash, "Services"); + if (value == NULL) { + BT_ERR("value == NULL"); + goto done; + } + + gp_array = g_value_get_boxed(value); + 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); + ret = BLUETOOTH_ERROR_NONE; +done: + g_hash_table_destroy(hash); + 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); + + BT_CHECK_ENABLED(); + + 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; + + BT_CHECK_PARAMETER(service_handle); + BT_CHECK_PARAMETER(service); + + BT_CHECK_ENABLED(); + + 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); + if (error != NULL) { + BT_ERR("GetProperties Call Error %s\n", error->message); + g_error_free(error); + g_object_unref(service_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + g_object_unref(service_proxy); + + retv_if(hash == NULL, BLUETOOTH_ERROR_INTERNAL); + + 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 (NULL != gp_array) { + service->handle_info.count = gp_array->len; + service->handle_info.handle = __get_string_array_from_gptr_array(gp_array); + g_ptr_array_free(gp_array, TRUE); + } + 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; + + BT_CHECK_PARAMETER(service_handle); + + BT_CHECK_ENABLED(); + + 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); + g_error_free(error); + g_object_unref(watch_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + + 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; + + BT_CHECK_PARAMETER(service_handle); + + BT_CHECK_ENABLED(); + + 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); + g_error_free(error); + g_object_unref(watch_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + + 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; + + BT_CHECK_PARAMETER(char_handle); + BT_CHECK_PARAMETER(characteristic); + + BT_CHECK_ENABLED(); + + 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); + g_error_free(error); + g_object_unref(characteristic_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + g_object_unref(characteristic_proxy); + + retv_if(hash == NULL, BLUETOOTH_ERROR_INTERNAL); + + 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) { + BT_DBG("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; + } + + g_byte_array_free(gb_array, TRUE); + } else { + characteristic->val = NULL; + characteristic->val_len = 0; + } + 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) +{ + DBusGProxy *characteristic_proxy = NULL; + GValue *val; + GByteArray *gbarray; + GError *error = NULL; + DBusGConnection *conn; + + BT_CHECK_PARAMETER(char_handle); + BT_CHECK_PARAMETER(value); + retv_if(length == 0, BLUETOOTH_ERROR_INVALID_PARAM); + + BT_CHECK_ENABLED(); + + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_DBG("Requested characteristic handle:%s \n ", char_handle); + + 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); + + gbarray = g_byte_array_new(); + g_byte_array_append(gbarray, (guint8 *)value, length); + + val = g_new0(GValue, 1); + g_value_init(val, DBUS_TYPE_G_UCHAR_ARRAY); + g_value_take_boxed(val, gbarray); + + dbus_g_proxy_call(characteristic_proxy, "SetProperty", + &error, G_TYPE_STRING, "Value", + G_TYPE_VALUE, val, G_TYPE_INVALID, G_TYPE_INVALID); + + g_object_unref(characteristic_proxy); + g_free(val); + + if (error) { + BT_ERR("Set value Fail: %s", error->message); + g_error_free(error); + return BLUETOOTH_ERROR_INTERNAL; + } + + return BLUETOOTH_ERROR_NONE; +} diff --git a/bt-api/bt-gatt.xml b/bt-api/bt-gatt.xml new file mode 100644 index 0000000..a2f7bd9 --- /dev/null +++ b/bt-api/bt-gatt.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/bt-api/bt-hdp.c b/bt-api/bt-hdp.c new file mode 100644 index 0000000..23c9cb7 --- /dev/null +++ b/bt-api/bt-hdp.c @@ -0,0 +1,1180 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 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" + +typedef struct { + char *obj_channel_path; + int fd; +} hdp_obj_info_t; + +typedef struct { + void *app_handle; + GSList *obj_info; +} hdp_app_list_t; + + +/********************************************************************** +* Static Functions declaration * +***********************************************************************/ +static int __bt_hdp_internal_create_application(unsigned int data_type, + int role, + bt_hdp_qos_type_t channel_type, + char **app_handle); + +static DBusHandlerResult __bt_hdp_internal_event_filter(DBusConnection *sys_conn, + DBusMessage *msg, + void *data); + +static void __bt_hdp_internal_handle_connect(DBusMessage *msg); + +static void __bt_hdp_internal_handle_disconnect(DBusMessage *msg); + +static void __bt_hdp_internal_handle_property_changed(DBusMessage *msg); + +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 gboolean __bt_hdp_internal_data_received(GIOChannel *gio, + GIOCondition cond, + gpointer data); + +static int __bt_hdp_internal_destroy_application(const char *app_handle); + +static void __bt_hdp_internal_remove_filter(void); + +static hdp_app_list_t *__bt_hdp_internal_gslist_find_app_handler(void *app_handle); + +static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_fd(int fd); + +static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_path(const char *obj_channel_path); + +/*Global Variables*/ +static DBusConnection *g_hdp_dus_conn; + +static GSList *g_app_list = NULL; + +/********************************************************************** +* Health device APIs (HDP) * +***********************************************************************/ + +BT_EXPORT_API int bluetooth_hdp_activate(unsigned short data_type, + bt_hdp_role_type_t role, + bt_hdp_qos_type_t channel_type, + char **app_handle) +{ + int result = BLUETOOTH_ERROR_NONE; + + BT_DBG("+"); + + BT_CHECK_ENABLED(); + + /*For source role is mandatory */ + if (role == HDP_ROLE_SOURCE && channel_type == HDP_QOS_ANY) { + BT_DBG("For source, type is mandatory - Reliable/Streaming"); + return BLUETOOTH_ERROR_INVALID_PARAM; + } + + result = __bt_hdp_internal_create_application(data_type, role, + channel_type, app_handle); + + return result; +} + +static void __bt_hdp_obj_info_free(hdp_obj_info_t *info) +{ + if (info) { + close(info->fd); + g_free(info->obj_channel_path); + g_free(info); + } +} + +static int __bt_hdp_internal_create_application(unsigned int data_type, + int role, + bt_hdp_qos_type_t channel_type, + char **app_handle) +{ + DBusMessage *msg; + DBusMessage *reply; + const char *svalue; + const char *key_type; + char *app_path; + hdp_app_list_t *list; + DBusError err; + DBusMessageIter iter; + DBusMessageIter array_iter; + DBusMessageIter entry; + DBusMessageIter variant; + guint16 value; + DBusConnection *conn; + int ret = BLUETOOTH_ERROR_NONE; + + BT_DBG("+"); + + conn = _bt_get_system_conn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + msg = dbus_message_new_method_call(BT_BLUEZ_NAME, "/org/bluez", + BLUEZ_HDP_MANAGER_INTERFACE, + "CreateApplication"); + + retv_if(msg == NULL, BLUETOOTH_ERROR_NO_RESOURCES); + + dbus_message_iter_init_append(msg, &iter); + 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, + &array_iter); + + key_type = "DataType"; + value = (guint16) data_type; + dbus_message_iter_open_container(&array_iter, DBUS_TYPE_DICT_ENTRY, + NULL, &entry); + dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key_type); + dbus_message_iter_open_container(&entry, + DBUS_TYPE_VARIANT, DBUS_TYPE_UINT16_AS_STRING, &variant); + dbus_message_iter_append_basic(&variant, DBUS_TYPE_UINT16, &value); + dbus_message_iter_close_container(&entry, &variant); + dbus_message_iter_close_container(&array_iter, &entry); + + key_type = "Role"; + + /*0-Source,1-Sink*/ + svalue = (role == HDP_ROLE_SINK) ? "Sink" : "Source"; + dbus_message_iter_open_container(&array_iter, DBUS_TYPE_DICT_ENTRY, + NULL, &entry); + dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key_type); + dbus_message_iter_open_container(&entry, + DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &variant); + dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING, &svalue); + dbus_message_iter_close_container(&entry, &variant); + dbus_message_iter_close_container(&array_iter, &entry); + + key_type = "Description"; + svalue = "Health Device"; + dbus_message_iter_open_container(&array_iter, DBUS_TYPE_DICT_ENTRY, + NULL, &entry); + dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key_type); + dbus_message_iter_open_container(&entry, + DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &variant); + dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING, &svalue); + dbus_message_iter_close_container(&entry, &variant); + dbus_message_iter_close_container(&array_iter, &entry); + + if (role == HDP_ROLE_SOURCE) { + key_type = "ChannelType"; + if (channel_type == HDP_QOS_RELIABLE) + svalue = "Reliable"; + else if (channel_type == HDP_QOS_STREAMING) + svalue = "Streaming"; + + dbus_message_iter_open_container(&array_iter, + DBUS_TYPE_DICT_ENTRY, NULL, &entry); + dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, + &key_type); + dbus_message_iter_open_container(&entry, + DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, + &variant); + dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING, + &svalue); + dbus_message_iter_close_container(&entry, &variant); + dbus_message_iter_close_container(&array_iter, &entry); + } + + dbus_message_iter_close_container(&iter, &array_iter); + + dbus_error_init(&err); + + reply = dbus_connection_send_with_reply_and_block( + conn, msg, + -1, &err); + dbus_message_unref(msg); + + if (!reply) { + BT_ERR(" HDP:dbus Can't create application"); + + if (dbus_error_is_set(&err)) { + BT_ERR("%s", err.message); + dbus_error_free(&err); + } + return BLUETOOTH_ERROR_INTERNAL; + } + + if (!dbus_message_get_args(reply, &err, DBUS_TYPE_OBJECT_PATH, + &app_path, DBUS_TYPE_INVALID)) { + + BT_ERR(" HDP: Can't get reply arguments from Dbus"); + + if (dbus_error_is_set(&err)) { + BT_ERR("Error: %s", err.message); + dbus_error_free(&err); + } + + dbus_message_unref(reply); + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_unref(reply); + + BT_DBG("Created health application: %s", (char *)app_path); + + ret = __bt_hdp_internal_add_filter(); + + if (ret != BLUETOOTH_ERROR_NONE) { + BT_ERR("Funtion failed"); + return ret; + } + + list = g_new0(hdp_app_list_t, 1); + list->app_handle = (void *)g_strdup(app_path); + *app_handle = list->app_handle; + + g_app_list = g_slist_append(g_app_list, list); + + return BLUETOOTH_ERROR_NONE; +} + +static int __bt_hdp_internal_add_filter(void) +{ + DBusError dbus_error; + + BT_DBG("+"); + + /*Single process only one signal registration is required */ + if (g_hdp_dus_conn) { + BT_ERR("g_hdp_dus_conn already exist"); + goto done; + } + + /* Add the filter for HDP client functions */ + dbus_error_init(&dbus_error); + + g_hdp_dus_conn = _bt_get_system_conn(); + retv_if(g_hdp_dus_conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_connection_add_filter(g_hdp_dus_conn, + __bt_hdp_internal_event_filter, NULL, NULL); + + dbus_bus_add_match(g_hdp_dus_conn, + "type='signal',interface=" BLUEZ_HDP_DEVICE_INTERFACE, + &dbus_error); + + if (dbus_error_is_set(&dbus_error)) { + BT_ERR("Fail to add dbus filter signal\n"); + dbus_error_free(&dbus_error); + g_hdp_dus_conn = NULL; + return BLUETOOTH_ERROR_INTERNAL; + } + +done: + BT_DBG("-\n"); + return BLUETOOTH_ERROR_NONE; + +} + +static DBusHandlerResult __bt_hdp_internal_event_filter(DBusConnection *sys_conn, + DBusMessage *msg, void *data) +{ + const char *path = dbus_message_get_path(msg); + + if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + BT_DBG("Path = %s\n", path); + if (path == NULL || g_strcmp0(path, "/") == 0) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (dbus_message_is_signal(msg, BLUEZ_HDP_DEVICE_INTERFACE, + "ChannelConnected")) + __bt_hdp_internal_handle_connect(msg); + + else if (dbus_message_is_signal(msg, BLUEZ_HDP_DEVICE_INTERFACE, + "ChannelDeleted")) + __bt_hdp_internal_handle_disconnect(msg); + + else if (dbus_message_is_signal(msg, BLUEZ_HDP_DEVICE_INTERFACE, + "PropertyChanged")) + __bt_hdp_internal_handle_property_changed(msg); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +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_DBG("Path = %s", path); + + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, + &obj_channel_path, DBUS_TYPE_INVALID)) { + BT_ERR("Unexpected parameters in ChannelConnected signal"); + return; + } + + BT_DBG("Channel connected, Path = %s", obj_channel_path); + + 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, &conn_ind, + user_info->cb, user_info->user_data); + } + } + + BT_DBG("-"); +} + +static void __bt_hdp_internal_handle_disconnect(DBusMessage *msg) +{ + const char *path = dbus_message_get_path(msg); + const char *obj_channel_path; + char address[BT_ADDRESS_STRING_SIZE] = { 0, }; + bluetooth_device_address_t device_addr = { {0} }; + bt_hdp_disconnected_t dis_ind; + hdp_obj_info_t *info; + bt_user_info_t *user_info; + + BT_DBG("+********Signal - ChannelDeleted ******\n\n"); + BT_DBG("Path = %s", path); + + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, + &obj_channel_path, DBUS_TYPE_INVALID)) { + BT_ERR("Unexpected parameters in ChannelDeleted signal"); + return; + } + + BT_DBG("Channel Deleted, Path = %s", obj_channel_path); + + info = __bt_hdp_internal_gslist_obj_find_using_path(obj_channel_path); + if (!info) { + BT_ERR("No obj info for ob_channel_path [%s]\n", obj_channel_path); + return; + } + + /*Since bluetoothd is not sending the ChannelDeleted signal */ + _bt_device_path_to_address(path, address); + + _bt_convert_addr_string_to_type(device_addr.addr, address); + + dis_ind.channel_id = info->fd; + dis_ind.device_address = device_addr; + + user_info = _bt_get_user_data(BT_COMMON); + + if (user_info) { + _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED, + BLUETOOTH_ERROR_NONE, &dis_ind, + user_info->cb, user_info->user_data); + } + + BT_DBG(" Removed connection from list\n"); + + __bt_hdp_obj_info_free(info); + +} + +static void __bt_hdp_internal_handle_property_changed(DBusMessage *msg) +{ + const char *path = dbus_message_get_path(msg); + DBusMessageIter item_iter; + DBusMessageIter value_iter; + const char *property; + const char *obj_main_channel_path; + + BT_DBG("+*******Signal - PropertyChanged*******\n"); + BT_DBG("Path = %s", path); + + 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"); + return; + } + + dbus_message_iter_get_basic(&item_iter, &property); + + ret_if(property == NULL); + + BT_DBG("Property (%s)\n", property); + + if (0 == g_strcmp0(property, "MainChannel")) { + BT_DBG("Property MainChannel received"); + + dbus_message_iter_next(&item_iter); + + dbus_message_iter_recurse(&item_iter, &value_iter); + + dbus_message_iter_get_basic(&value_iter, + &obj_main_channel_path); + BT_DBG("Path = %s", path); + + BT_DBG("Main Channel Path = %s", obj_main_channel_path); + } + BT_DBG("-*************\n"); +} + +static int __bt_hdp_internal_acquire_fd(const char *path) +{ + char address[BT_ADDRESS_STRING_SIZE] = { 0, }; + bluetooth_device_address_t device_addr = { {0} }; + DBusMessageIter reply_iter; + DBusMessageIter reply_iter_entry; + const char *property; + char *type_qos = NULL; + char *device = NULL;; + char *app_handle = NULL;; + hdp_app_list_t *list = NULL;; + DBusMessage *msg; + DBusMessage *reply; + DBusConnection *conn; + bt_hdp_connected_t conn_ind; + DBusError err; + int fd; + bt_user_info_t *user_info; + + BT_DBG("+"); + + conn = _bt_get_system_conn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + msg = dbus_message_new_method_call(BT_BLUEZ_NAME, path, + BLUEZ_HDP_CHANNEL_INTERFACE, + "Acquire"); + + retv_if(msg == NULL, BLUETOOTH_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(" HDP:****** dbus Can't create application ****"); + + if (dbus_error_is_set(&err)) { + BT_ERR("%s", err.message); + dbus_error_free(&err); + } + + return BLUETOOTH_ERROR_INTERNAL; + } + + if (!dbus_message_get_args(reply, &err, DBUS_TYPE_UNIX_FD, &fd, + DBUS_TYPE_INVALID)) { + BT_ERR(" HDP:dbus Can't get reply arguments"); + + if (dbus_error_is_set(&err)) { + BT_ERR("%s", err.message); + dbus_error_free(&err); + } + goto error; + } + + dbus_message_unref(reply); + + 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"); + + retv_if(msg == NULL, BLUETOOTH_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(" HDP:dbus Can't get the reply"); + + if (dbus_error_is_set(&err)) { + BT_ERR("%s", err.message); + dbus_error_free(&err); + } + + return BLUETOOTH_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\n"); + goto error; + } + + 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\n", property); + + if (g_strcmp0("Type", 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_STRING) + continue; + + dbus_message_iter_get_basic(&dict_entry_val, &type_qos); + + } else if (g_strcmp0("Device", 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_OBJECT_PATH) + continue; + + dbus_message_iter_get_basic(&dict_entry_val, &device); + + } else if (g_strcmp0("Application", 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_OBJECT_PATH) + continue; + + dbus_message_iter_get_basic(&dict_entry_val, + &app_handle); + } + dbus_message_iter_next(&reply_iter_entry); + } + + BT_DBG("QOS = %s, Device = %s, Apphandler = %s", + type_qos, device, app_handle); + + if (NULL == type_qos || NULL == app_handle) { + BT_ERR("Pasing failed\n"); + goto error; + } + + list = __bt_hdp_internal_gslist_find_app_handler((void *)app_handle); + + /*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); + goto error; + } + + hdp_obj_info_t *info = g_new0(hdp_obj_info_t, 1); + info->fd = fd; + info->obj_channel_path = g_strdup(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); + + conn_ind.app_handle = app_handle; + conn_ind.channel_id = fd; + conn_ind.device_address = device_addr; + conn_ind.type = (g_strcmp0(type_qos, "Reliable") == 0) ? + HDP_QOS_RELIABLE : HDP_QOS_STREAMING; + + BT_DBG("Going to give callback\n"); + + user_info = _bt_get_user_data(BT_COMMON); + + if (user_info) { + _bt_common_event_cb(BLUETOOTH_EVENT_HDP_CONNECTED, + BLUETOOTH_ERROR_NONE, &conn_ind, + user_info->cb, user_info->user_data); + } + + dbus_message_unref(reply); + + BT_DBG("Updated fd in the list*\n"); + BT_DBG("-\n"); + + return BLUETOOTH_ERROR_NONE; + error: + dbus_message_unref(reply); + return BLUETOOTH_ERROR_INTERNAL; +} + +static void __bt_hdp_internal_watch_fd(int file_desc, const char *path) +{ + GIOChannel *gio; + + BT_DBG("+"); + + gio = g_io_channel_unix_new(file_desc); + + 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, + __bt_hdp_internal_data_received, (void *)path); + BT_DBG("-"); +} + + +static void __bt_hdp_internal_handle_disconnect_cb(int sk, const char *path) +{ + char address[BT_ADDRESS_STRING_SIZE] = { 0, }; + bluetooth_device_address_t device_addr = { {0} }; + bt_hdp_disconnected_t dis_ind; + hdp_obj_info_t *info; + bt_user_info_t *user_info; + + BT_DBG("******** Socket Error ******\n"); + + info = __bt_hdp_internal_gslist_obj_find_using_path(path); + ret_if(info == NULL); + + /*Since bluetoothd is not sending the ChannelDeleted signal */ + _bt_device_path_to_address(path, address); + + _bt_convert_addr_string_to_type(device_addr.addr, address); + + dis_ind.channel_id = sk; + dis_ind.device_address = device_addr; + + user_info = _bt_get_user_data(BT_COMMON); + + if (user_info) { + _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DISCONNECTED, + BLUETOOTH_ERROR_NONE, &dis_ind, + user_info->cb, user_info->user_data); + } + + BT_DBG(" Removed connection from list\n"); + + __bt_hdp_obj_info_free(info); +} + +static gboolean __bt_hdp_internal_data_received(GIOChannel *gio, + GIOCondition cond, gpointer data) +{ + char buff[HDP_BUFFER_SIZE] = { 0, }; + int sk; + int act_read; + bt_hdp_data_ind_t data_ind = { 0, }; + const char *path = (const char *)data; + bt_user_info_t *user_info; + + BT_DBG("+"); + + sk = g_io_channel_unix_get_fd(gio); + + if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) { + BT_DBG("GIOCondition %d.............path = %s\n", cond, path); + __bt_hdp_internal_handle_disconnect_cb(sk, path); + return FALSE; + } + + act_read = recv(sk, (void *)buff, sizeof(buff), 0); + + if (act_read > 0) { + BT_DBG("Received data of %d\n", act_read); + } else { + BT_DBG("Read failed.....\n"); + return FALSE; + } + + data_ind.channel_id = sk; + data_ind.buffer = buff; + data_ind.size = act_read; + + user_info = _bt_get_user_data(BT_COMMON); + + if (user_info) { + _bt_common_event_cb(BLUETOOTH_EVENT_HDP_DATA_RECEIVED, + BLUETOOTH_ERROR_NONE, &data_ind, + user_info->cb, user_info->user_data); + } + + BT_DBG("-\n"); + + return TRUE; +} + +BT_EXPORT_API int bluetooth_hdp_deactivate(const char *app_handle) +{ + BT_DBG("+"); + + BT_CHECK_ENABLED(); + BT_CHECK_PARAMETER(app_handle); + + return __bt_hdp_internal_destroy_application(app_handle); +} + +static hdp_app_list_t *__bt_hdp_internal_gslist_find_app_handler(void *app_handle) +{ + GSList *l; + + retv_if(g_app_list == NULL, NULL); + + BT_DBG("List length = %d\n", g_slist_length(g_app_list)); + + for (l = g_app_list; l != NULL; l = l->next) { + hdp_app_list_t *list = l->data; + + if (list) { + if (0 == g_strcmp0((char *)list->app_handle, + (char *)app_handle)) + return list; + } + } + return NULL; +} + +static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_fd(int fd) +{ + GSList *l; + GSList *iter; + + retv_if(g_app_list == NULL, NULL); + + BT_DBG("List length = %d\n", g_slist_length(g_app_list)); + + for (l = g_app_list; l != NULL; l = l->next) { + hdp_app_list_t *list = l->data; + if (!list) + return NULL; + + for (iter = list->obj_info; iter != NULL; iter = iter->next) { + hdp_obj_info_t *info = iter->data; + if (!info) + return NULL; + + if (fd == info->fd) + return info; + } + } + return NULL; +} + +static hdp_obj_info_t *__bt_hdp_internal_gslist_obj_find_using_path(const char *obj_channel_path) +{ + GSList *l; + GSList *iter; + hdp_obj_info_t *info = NULL; + + retv_if(g_app_list == NULL, NULL); + + BT_DBG("List length = %d\n", g_slist_length(g_app_list)); + for (l = g_app_list; l != NULL; l = l->next) { + hdp_app_list_t *list = l->data; + if (!list) + return NULL; + + for (iter = list->obj_info; iter != NULL; iter = iter->next) { + info = iter->data; + if (!info) + return NULL; + + if (0 == g_strcmp0(info->obj_channel_path, obj_channel_path)) { + list->obj_info = g_slist_remove(list->obj_info, info); + return info; + } + } + } + return NULL; +} + +static gboolean __bt_hdp_internal_destroy_application_cb(gpointer data) +{ + const char *app_handle; + hdp_app_list_t *list = NULL; + app_handle = (const char *)data; + + BT_DBG("+"); + + list = __bt_hdp_internal_gslist_find_app_handler((void *)app_handle); + if (NULL == list) { + BT_DBG("**** list not found for %s ******\n", app_handle); + return FALSE; + } + + g_app_list = g_slist_remove(g_app_list, list); + + g_free(list->app_handle); + g_slist_foreach(list->obj_info, (GFunc)__bt_hdp_obj_info_free, NULL); + g_free(list); + + BT_DBG("List length = %d\n", g_slist_length(g_app_list)); + + if (0 == g_slist_length(g_app_list)) + __bt_hdp_internal_remove_filter(); + BT_DBG("-"); + return FALSE; +} + +static int __bt_hdp_internal_destroy_application(const char *app_handle) +{ + DBusMessage *msg; + DBusMessage *reply; + 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, "/org/bluez", + BLUEZ_HDP_MANAGER_INTERFACE, "DestroyApplication"); + + retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &app_handle, + DBUS_TYPE_INVALID); + + dbus_error_init(&err); + + reply = dbus_connection_send_with_reply_and_block(conn, msg, + -1, &err); + dbus_message_unref(msg); + if (!reply) { + BT_ERR(" HDP:dbus Can't Destroy application"); + + 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("Destroyed health application: %s", (char *)app_handle); + + g_idle_add(__bt_hdp_internal_destroy_application_cb, + (gpointer)app_handle); + + return BLUETOOTH_ERROR_NONE; +} + +static void __bt_hdp_internal_remove_filter(void) +{ + BT_DBG("+"); + + ret_if(g_hdp_dus_conn == NULL); + + dbus_connection_remove_filter(g_hdp_dus_conn, + __bt_hdp_internal_event_filter, NULL); + + g_hdp_dus_conn = NULL; /*should not unref here, bcz no ++reff */ + + BT_DBG("-"); +} + +BT_EXPORT_API int bluetooth_hdp_send_data(unsigned int channel_id, + const char *buffer, + unsigned int size) +{ + int wbytes = 0; + int written = 0; + + BT_DBG("+"); + + BT_CHECK_ENABLED(); + + if ((channel_id == 0) || (NULL == buffer) || (size == 0)) { + BT_DBG("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; + } + } + + return BLUETOOTH_ERROR_NONE; +} + + +static void __bt_hdp_connect_request_cb(DBusGProxy *hdp_proxy, DBusGProxyCall *call, + gpointer user_data) +{ + GError *g_error = NULL; + char *obj_connect_path = NULL; + bt_hdp_connected_t *conn_ind = user_data; + bt_user_info_t *user_info; + + dbus_g_proxy_end_call(hdp_proxy, call, &g_error, + DBUS_TYPE_G_OBJECT_PATH, &obj_connect_path, G_TYPE_INVALID); + + g_object_unref(hdp_proxy); + + if (g_error != NULL) { + BT_ERR("HDP connection 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_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); + g_free(obj_connect_path); + } + g_free((void *)conn_ind->app_handle); + g_free(conn_ind); +} + + +BT_EXPORT_API int bluetooth_hdp_connect(const char *app_handle, + bt_hdp_qos_type_t channel_type, + const bluetooth_device_address_t *device_address) +{ + GError *err = NULL; + DBusGConnection *conn = NULL; + DBusGProxy *hdp_proxy = NULL; + bt_hdp_connected_t *param; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + char default_adapter_path[BT_ADAPTER_OBJECT_PATH_MAX + 1] = { 0 }; + char *dev_path = NULL; + char *role; + + BT_DBG("+"); + + BT_CHECK_ENABLED(); + BT_CHECK_PARAMETER(app_handle); + BT_CHECK_PARAMETER(device_address); + + if (channel_type == HDP_QOS_RELIABLE) { + role = "Reliable"; + } else if (channel_type == HDP_QOS_STREAMING) { + role = "Streaming"; + } else if (channel_type == HDP_QOS_ANY) { + role = "Any"; + } else { + BT_ERR("Invalid channel_type %d", channel_type); + return BLUETOOTH_ERROR_ACCESS_DENIED; + } + + conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &err); + + if (err != NULL) { + BT_DBG("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) { + BT_ERR("Could not get adapter path\n"); + dbus_g_connection_unref(conn); + return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; + } + + _bt_convert_addr_type_to_string(address, + (unsigned char *)device_address->addr); + + BT_DBG("create conection to %s", address); + + dev_path = g_strdup_printf("%s/dev_%s", default_adapter_path, address); + + if (dev_path == NULL) { + dbus_g_connection_unref(conn); + return BLUETOOTH_ERROR_MEMORY_ALLOCATION; + } + + g_strdelimit(dev_path, ":", '_'); + + BT_DBG("path: %s", dev_path); + + hdp_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, dev_path, + BLUEZ_HDP_DEVICE_INTERFACE); + dbus_g_connection_unref(conn); + + if (hdp_proxy == NULL) { + BT_DBG("Failed to get the HDP server proxy\n"); + g_free(dev_path); + return BLUETOOTH_ERROR_NOT_PAIRED; + } + + BT_DBG("app path %s\n", app_handle); + + param = g_new0(bt_hdp_connected_t, 1); + param->app_handle = g_strdup(app_handle); + memcpy(¶m->device_address, device_address, BLUETOOTH_ADDRESS_LENGTH); + param->type = channel_type; + + if (!dbus_g_proxy_begin_call(hdp_proxy, "CreateChannel", + (DBusGProxyCallNotify) __bt_hdp_connect_request_cb, + param, /* user_data */ + NULL, /* destroy */ + DBUS_TYPE_G_OBJECT_PATH, app_handle, + G_TYPE_STRING, role, + G_TYPE_INVALID)) { + BT_ERR("HDP connection Dbus Call Error"); + g_free(dev_path); + g_free((void *)param->app_handle); + g_free(param); + g_object_unref(hdp_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + + g_free(dev_path); + return BLUETOOTH_ERROR_NONE; +} + +static void __bt_hdp_disconnect_request_cb(DBusGProxy *hdp_proxy, DBusGProxyCall *call, + gpointer user_data) +{ + GError *g_error = NULL; + bt_hdp_disconnected_t *disconn_ind = user_data; + bt_user_info_t *user_info; + + dbus_g_proxy_end_call(hdp_proxy, call, &g_error, G_TYPE_INVALID); + + g_object_unref(hdp_proxy); + + 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 { + BT_DBG("HDP disconnection Dbus Call is done\n"); + } + + g_free(disconn_ind); +} + +BT_EXPORT_API int bluetooth_hdp_disconnect(unsigned int channel_id, + const bluetooth_device_address_t *device_address) +{ + GError *err = NULL; + DBusGConnection *conn = NULL; + DBusGProxy *hdp_proxy = NULL; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + char default_adapter_path[BT_ADAPTER_OBJECT_PATH_MAX + 1] = { 0 }; + char *dev_path = NULL; + bt_hdp_disconnected_t *param; + + BT_DBG("+\n"); + + BT_CHECK_ENABLED(); + BT_CHECK_PARAMETER(device_address); + + 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); + return BLUETOOTH_ERROR_INVALID_PARAM; + } + + conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &err); + + if (err != NULL) { + 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) { + BT_ERR("Could not get adapter path\n"); + dbus_g_connection_unref(conn); + return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; + } + + _bt_convert_addr_type_to_string(address, + (unsigned char *)device_address->addr); + + BT_DBG("create conection to %s\n", address); + + dev_path = g_strdup_printf("%s/dev_%s", default_adapter_path, address); + + if (dev_path == NULL) { + dbus_g_connection_unref(conn); + return BLUETOOTH_ERROR_MEMORY_ALLOCATION; + } + + g_strdelimit(dev_path, ":", '_'); + + BT_DBG("path %s\n", dev_path); + + hdp_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, dev_path, + BLUEZ_HDP_DEVICE_INTERFACE); + + dbus_g_connection_unref(conn); + + if (hdp_proxy == NULL) { + BT_ERR("Failed to get the HDP proxy\n"); + g_free(dev_path); + return BLUETOOTH_ERROR_NOT_PAIRED; + } + + param = g_new0(bt_hdp_disconnected_t, 1); + param->channel_id = channel_id; + memcpy(¶m->device_address, device_address, BLUETOOTH_ADDRESS_LENGTH); + + if (!dbus_g_proxy_begin_call(hdp_proxy, "DestroyChannel", + (DBusGProxyCallNotify) __bt_hdp_disconnect_request_cb, + param, /* user_data */ + NULL, /* destroy */ + DBUS_TYPE_G_OBJECT_PATH, info->obj_channel_path, + G_TYPE_INVALID)) { + BT_ERR("HDP connection Dbus Call Error"); + g_free(dev_path); + g_free(param); + g_object_unref(hdp_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + + g_free(dev_path); + + return BLUETOOTH_ERROR_NONE; +} diff --git a/bt-api/bt-hid.c b/bt-api/bt-hid.c new file mode 100644 index 0000000..a1a06bb --- /dev/null +++ b/bt-api/bt-hid.c @@ -0,0 +1,111 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "bluetooth-api.h" +#include "bluetooth-hid-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_hid_init(hid_cb_func_ptr callback_ptr, void *user_data) +{ + int ret; + + /* Register AVRCP events */ + ret = _bt_register_event(BT_HID_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_HID, (void *)callback_ptr, user_data); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_hid_deinit(void) +{ + int ret; + + ret = _bt_unregister_event(BT_HID_EVENT); + + if (ret != BLUETOOTH_ERROR_NONE) { + BT_ERR("Fail to deinit the event handler"); + return ret; + } + + _bt_set_user_data(BT_HID, NULL, NULL); + + return BLUETOOTH_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_hid_connect(hid_device_address_t *device_address) +{ + int result; + bt_user_info_t *user_info; + + BT_CHECK_PARAMETER(device_address); + BT_CHECK_ENABLED(); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + user_info = _bt_get_user_data(BT_HID); + retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + + g_array_append_vals(in_param1, device_address, sizeof(bluetooth_device_address_t)); + + result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_HID_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_hid_disconnect(hid_device_address_t *device_address) +{ + int result; + bt_user_info_t *user_info; + + BT_CHECK_PARAMETER(device_address); + BT_CHECK_ENABLED(); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + user_info = _bt_get_user_data(BT_HID); + retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + + g_array_append_vals(in_param1, device_address, sizeof(bluetooth_device_address_t)); + + result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_HID_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-network.c b/bt-api/bt-network.c new file mode 100644 index 0000000..64399eb --- /dev/null +++ b/bt-api/bt-network.c @@ -0,0 +1,115 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "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_network_activate_server() +{ + int result; + + BT_CHECK_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_NETWORK_ACTIVATE, + 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_network_deactivate_server(void) +{ + int result; + + BT_CHECK_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_NETWORK_DEACTIVATE, + 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_network_connect(const bluetooth_device_address_t *device_address, + bluetooth_network_role_t role, + char *custom_uuid) +{ + int result; + bt_user_info_t *user_info; + + BT_CHECK_PARAMETER(device_address); + BT_CHECK_ENABLED(); + + 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, device_address, + sizeof(bluetooth_device_address_t)); + g_array_append_vals(in_param2, &role, sizeof(int)); + + result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_NETWORK_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_network_disconnect(const bluetooth_device_address_t *device_address) +{ + int result; + bt_user_info_t *user_info; + + BT_CHECK_PARAMETER(device_address); + BT_CHECK_ENABLED(); + + 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, device_address, + sizeof(bluetooth_device_address_t)); + + result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_NETWORK_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 new file mode 100644 index 0000000..24ad868 --- /dev/null +++ b/bt-api/bt-obex-server.c @@ -0,0 +1,390 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "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_obex_server_init(const char *dst_path) +{ + int result; + int app_pid; + bt_user_info_t *user_info; + gboolean native_service = TRUE; + char path[BT_FILE_PATH_MAX]; + + BT_CHECK_ENABLED(); + + if (_bt_get_obex_server_id() != BT_NO_SERVER) + return BLUETOOTH_ERROR_AGENT_ALREADY_EXIST; + + user_info = _bt_get_user_data(BT_COMMON); + retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + app_pid = getpid(); + + g_strlcpy(path, dst_path, sizeof(path)); + g_array_append_vals(in_param1, path, BT_FILE_PATH_MAX); + g_array_append_vals(in_param2, &native_service, sizeof(gboolean)); + g_array_append_vals(in_param3, &app_pid, sizeof(int)); + + result = _bt_send_request(BT_OBEX_SERVICE, BT_OBEX_SERVER_ALLOCATE, + in_param1, in_param2, in_param3, in_param4, &out_param); + + if (result == BLUETOOTH_ERROR_NONE) { + _bt_set_obex_server_id(BT_NATIVE_SERVER); + _bt_register_event(BT_OPP_SERVER_EVENT, user_info->cb, + user_info->user_data); + } 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_obex_server_deinit(void) +{ + int result; + int app_pid; + gboolean native_service = TRUE; + + BT_CHECK_ENABLED(); + + if (_bt_get_obex_server_id() != BT_NATIVE_SERVER) + return BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST; + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + app_pid = getpid(); + + g_array_append_vals(in_param1, &native_service, sizeof(gboolean)); + g_array_append_vals(in_param2, &app_pid, sizeof(int)); + + result = _bt_send_request(BT_OBEX_SERVICE, BT_OBEX_SERVER_DEALLOCATE, + in_param1, in_param2, in_param3, in_param4, &out_param); + + _bt_set_obex_server_id(BT_NO_SERVER); + _bt_unregister_event(BT_OPP_SERVER_EVENT); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_obex_server_init_without_agent(const char *dst_path) +{ + int result; + int app_pid; + bt_user_info_t *user_info; + gboolean native_service = FALSE; + char path[BT_FILE_PATH_MAX]; + + BT_CHECK_ENABLED(); + + if (_bt_get_obex_server_id() != BT_NO_SERVER) + return BLUETOOTH_ERROR_AGENT_ALREADY_EXIST; + + user_info = _bt_get_user_data(BT_COMMON); + retv_if(user_info == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + app_pid = getpid(); + + g_strlcpy(path, dst_path, sizeof(path)); + g_array_append_vals(in_param1, path, BT_FILE_PATH_MAX); + g_array_append_vals(in_param2, &native_service, sizeof(gboolean)); + g_array_append_vals(in_param3, &app_pid, sizeof(int)); + + result = _bt_send_request(BT_OBEX_SERVICE, BT_OBEX_SERVER_ALLOCATE, + in_param1, in_param2, in_param3, in_param4, &out_param); + + if (result == BLUETOOTH_ERROR_NONE) { + _bt_set_obex_server_id(BT_CUSTOM_SERVER); + _bt_register_event(BT_OPP_SERVER_EVENT, user_info->cb, + user_info->user_data); + } 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_obex_server_deinit_without_agent(void) +{ + int result; + int app_pid; + gboolean native_service = FALSE; + + BT_CHECK_ENABLED(); + + /* Can't call this API after using bluetooth_obex_server_init + in same process */ + if (_bt_get_obex_server_id() != BT_CUSTOM_SERVER) + return BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST; + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + app_pid = getpid(); + + g_array_append_vals(in_param1, &native_service, sizeof(gboolean)); + g_array_append_vals(in_param2, &app_pid, sizeof(int)); + + result = _bt_send_request(BT_OBEX_SERVICE, BT_OBEX_SERVER_DEALLOCATE, + in_param1, in_param2, in_param3, in_param4, &out_param); + + _bt_set_obex_server_id(BT_NO_SERVER); + _bt_unregister_event(BT_OPP_SERVER_EVENT); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API gboolean bluetooth_obex_server_is_activated(void) +{ + int result; + gboolean is_activated = FALSE; + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + result = _bt_send_request(BT_OBEX_SERVICE, BT_OBEX_SERVER_IS_ACTIVATED, + in_param1, in_param2, in_param3, in_param4, &out_param); + + if (result == BLUETOOTH_ERROR_NONE) { + is_activated = g_array_index(out_param, gboolean, 0); + } else { + BT_ERR("Fail to send request"); + } + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return is_activated; +} + +BT_EXPORT_API int bluetooth_obex_server_accept_connection(void) +{ + int result; + + /* Can't use this API in native server + In native server, bt-agent will control the connection + using system popup */ + if (_bt_get_obex_server_id() != BT_CUSTOM_SERVER) + return BLUETOOTH_ERROR_INTERNAL; + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + result = _bt_send_request(BT_OBEX_SERVICE, BT_OBEX_SERVER_ACCEPT_CONNECTION, + 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_obex_server_reject_connection(void) +{ + int result; + + /* Can't use this API in native server + In native server, bt-agent will control the connection + using system popup */ + if (_bt_get_obex_server_id() != BT_CUSTOM_SERVER) + return BLUETOOTH_ERROR_INTERNAL; + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + result = _bt_send_request(BT_OBEX_SERVICE, BT_OBEX_SERVER_REJECT_CONNECTION, + 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_obex_server_accept_authorize(const char *filename) +{ + int result; + char name[BT_FILE_PATH_MAX]; + + BT_CHECK_PARAMETER(filename); + BT_CHECK_ENABLED(); + + if (_bt_get_obex_server_id() != BT_NATIVE_SERVER) + return BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST; + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_strlcpy(name, filename, sizeof(name)); + g_array_append_vals(in_param1, name, BT_FILE_PATH_MAX); + + result = _bt_send_request(BT_OBEX_SERVICE, BT_OBEX_SERVER_ACCEPT_FILE, + 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_obex_server_reject_authorize(void) +{ + int result; + + BT_CHECK_ENABLED(); + + if (_bt_get_obex_server_id() != BT_NATIVE_SERVER) + return BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST; + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + result = _bt_send_request(BT_OBEX_SERVICE, BT_OBEX_SERVER_REJECT_FILE, + 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_obex_server_set_destination_path(const char *dst_path) +{ + int result; + int server_id; + gboolean native_service = FALSE; + char path[BT_FILE_PATH_MAX]; + + BT_CHECK_PARAMETER(dst_path); + BT_CHECK_ENABLED(); + + server_id = _bt_get_obex_server_id(); + + retv_if(server_id == BT_NO_SERVER, + BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + native_service = (server_id == BT_NATIVE_SERVER) ? TRUE : FALSE; + + g_strlcpy(path, dst_path, sizeof(path)); + g_array_append_vals(in_param1, path, BT_FILE_PATH_MAX); + g_array_append_vals(in_param2, &native_service, sizeof(native_service)); + + result = _bt_send_request(BT_OBEX_SERVICE, BT_OBEX_SERVER_SET_PATH, + 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_obex_server_set_root(const char *root) +{ + int result; + char root_path[BT_FILE_PATH_MAX]; + + BT_CHECK_PARAMETER(root); + BT_CHECK_ENABLED(); + + if (_bt_get_obex_server_id() == BT_NO_SERVER) + return BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST; + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_strlcpy(root_path, root, sizeof(root_path)); + g_array_append_vals(in_param1, root_path, BT_FILE_PATH_MAX); + + result = _bt_send_request(BT_OBEX_SERVICE, BT_OBEX_SERVER_SET_ROOT, + 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_obex_server_cancel_transfer(int transfer_id) +{ + int result; + int server_type; + int service_function = BT_OBEX_SERVER_CANCEL_TRANSFER; + + BT_CHECK_ENABLED(); + + server_type = _bt_get_obex_server_id(); + + if (server_type == BT_NO_SERVER) + return BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST; + else if (server_type == BT_CUSTOM_SERVER) + service_function = BT_OBEX_SERVER_CANCEL_ALL_TRANSFERS; + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, &transfer_id, sizeof(int)); + + result = _bt_send_request(BT_OBEX_SERVICE, 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; +} + +BT_EXPORT_API int bluetooth_obex_server_cancel_all_transfers(void) +{ + int result; + + BT_CHECK_ENABLED(); + + if (_bt_get_obex_server_id() == BT_NO_SERVER) + return BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST; + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + result = _bt_send_request(BT_OBEX_SERVICE, BT_OBEX_SERVER_CANCEL_ALL_TRANSFERS, + 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-oob.c b/bt-api/bt-oob.c new file mode 100644 index 0000000..40ef24a --- /dev/null +++ b/bt-api/bt-oob.c @@ -0,0 +1,97 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "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_oob_read_local_data(bt_oob_data_t *local_oob_data) +{ + int result; + + BT_CHECK_PARAMETER(local_oob_data); + BT_CHECK_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_OOB_READ_LOCAL_DATA, + in_param1, in_param2, in_param3, in_param4, &out_param); + + if (result == BLUETOOTH_ERROR_NONE) { + *local_oob_data = g_array_index(out_param, + bt_oob_data_t, 0); + } + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_oob_add_remote_data( + const bluetooth_device_address_t *remote_device_address, + bt_oob_data_t *remote_oob_data) +{ + int result; + + BT_CHECK_PARAMETER(remote_device_address); + BT_CHECK_PARAMETER(remote_oob_data); + BT_CHECK_ENABLED(); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, remote_device_address, + sizeof(bluetooth_device_address_t)); + + g_array_append_vals(in_param2, remote_oob_data, sizeof(bt_oob_data_t)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_OOB_ADD_REMOTE_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_oob_remove_remote_data( + const bluetooth_device_address_t *remote_device_address) +{ + int result; + + BT_CHECK_PARAMETER(remote_device_address); + BT_CHECK_ENABLED(); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, remote_device_address, + sizeof(bluetooth_device_address_t)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_OOB_REMOVE_REMOTE_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-opp-client.c b/bt-api/bt-opp-client.c new file mode 100644 index 0000000..f1b3300 --- /dev/null +++ b/bt-api/bt-opp-client.c @@ -0,0 +1,140 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "bluetooth-api.h" +#include "bt-internal-types.h" + +#include "bt-common.h" +#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; + unsigned long size = 0; + + while (files[file_count] != NULL) { + size = size + strlen(files[file_count]); + file_count++; + } + + *count = file_count; + *file_size = size; +} + +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); + + return _bt_register_event(BT_OPP_CLIENT_EVENT, user_info->cb, user_info->user_data); +} + +BT_EXPORT_API int bluetooth_opc_deinit(void) +{ + return _bt_unregister_event(BT_OPP_CLIENT_EVENT); +} + +BT_EXPORT_API int bluetooth_opc_push_files(bluetooth_device_address_t *remote_address, + char **file_name_array) +{ + int result; + int i; + int file_count; + unsigned long size; + bt_user_info_t *user_info; + char filename[BT_FILE_PATH_MAX]; + + BT_CHECK_PARAMETER(remote_address); + BT_CHECK_PARAMETER(file_name_array); + BT_CHECK_ENABLED(); + + __bt_get_file_size(file_name_array, &size, &file_count); + retv_if(file_count == 0, BLUETOOTH_ERROR_INVALID_PARAM); + + 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++) { + g_strlcpy(filename, file_name_array[i], sizeof(filename)); + g_array_append_vals(in_param2, filename, BT_FILE_PATH_MAX); + } + + g_array_append_vals(in_param3, &file_count, sizeof(int)); + + result = _bt_send_request_async(BT_OBEX_SERVICE, BT_OPP_PUSH_FILES, + 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_opc_cancel_push(void) +{ + int result; + + BT_CHECK_ENABLED(); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + result = _bt_send_request(BT_OBEX_SERVICE, BT_OPP_CANCEL_PUSH, + 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 gboolean bluetooth_opc_session_is_exist(void) +{ + int result; + gboolean exist = FALSE; + + BT_CHECK_ENABLED(); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + result = _bt_send_request(BT_OBEX_SERVICE, BT_OPP_IS_PUSHING_FILES, + in_param1, in_param2, in_param3, in_param4, &out_param); + + if (result == BLUETOOTH_ERROR_NONE) { + exist = g_array_index(out_param, gboolean, 0); + } else { + BT_ERR("Fail to send request"); + } + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + diff --git a/bt-api/bt-request-sender.c b/bt-api/bt-request-sender.c new file mode 100644 index 0000000..2438cb3 --- /dev/null +++ b/bt-api/bt-request-sender.c @@ -0,0 +1,406 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "bluetooth-hid-api.h" +#include "bluetooth-audio-api.h" +#include "bt-internal-types.h" + +#include "bt-common.h" +#include "bt-request-sender.h" +#include "bt-event-handler.h" + +/* auto generated header by bt-request-service.xml*/ +#include "bt-request-service.h" + +static GSList *sending_requests; + +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; +} + +DBusGProxy *_bt_init_service_proxy(void) +{ + DBusGProxy *proxy; + + g_type_init(); + + if (service_conn == NULL) { + service_conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL); + retv_if(service_conn == NULL, NULL); + } + + proxy = dbus_g_proxy_new_for_name(service_conn, BT_DBUS_NAME, BT_SERVICE_PATH, + BT_DBUS_NAME); + + if (proxy == NULL) { + dbus_g_connection_unref(service_conn); + service_conn = NULL; + return NULL; + } + + service_proxy = proxy; + + return proxy; +} + +void _bt_deinit_proxys(void) +{ + __bt_remove_all_sending_requests(); + + if (service_proxy) { + 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; + } +} + +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); + + switch (service_function) { + case BT_BOND_DEVICE: + *event_type = BT_ADAPTER_EVENT; + *event = BLUETOOTH_EVENT_BONDING_FINISHED; + ret_if(output == NULL); + *param_data = &g_array_index(output, + bluetooth_device_info_t, 0); + break; + case BT_UNBOND_DEVICE: + *event_type = BT_ADAPTER_EVENT; + *event = BLUETOOTH_EVENT_BONDED_DEVICE_REMOVED; + ret_if(output == NULL); + *param_data = &g_array_index(output, + bluetooth_device_info_t, 0); + break; + case BT_SEARCH_SERVICE: + *event_type = BT_ADAPTER_EVENT; + *event = BLUETOOTH_EVENT_SERVICE_SEARCHED; + ret_if(output == NULL); + *param_data = &g_array_index(output, + bluetooth_device_info_t, 0); + break; + case BT_HID_CONNECT: + *event_type = BT_HID_EVENT; + *event = BLUETOOTH_HID_CONNECTED; + ret_if(output == NULL); + *param_data = &g_array_index(output, + bluetooth_device_address_t, 0); + break; + case BT_HID_DISCONNECT: + *event_type = BT_HID_EVENT; + *event = BLUETOOTH_HID_DISCONNECTED; + ret_if(output == NULL); + *param_data = &g_array_index(output, + bluetooth_device_address_t, 0); + break; + case BT_AUDIO_CONNECT: + case BT_AG_CONNECT: + *event_type = BT_HEADSET_EVENT; + *event = BLUETOOTH_EVENT_AG_CONNECTED; + ret_if(output == NULL); + *param_data = &g_array_index(output, char, 0); + break; + case BT_AUDIO_DISCONNECT: + case BT_AG_DISCONNECT: + *event_type = BT_HEADSET_EVENT; + *event = BLUETOOTH_EVENT_AG_DISCONNECTED; + ret_if(output == NULL); + *param_data = &g_array_index(output, char, 0); + break; + case BT_AV_CONNECT: + *event_type = BT_HEADSET_EVENT; + *event = BLUETOOTH_EVENT_AV_CONNECTED; + ret_if(output == NULL); + *param_data = &g_array_index(output, char, 0); + break; + case BT_AV_DISCONNECT: + *event_type = BT_HEADSET_EVENT; + *event = BLUETOOTH_EVENT_AV_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; + ret_if(output == NULL); + *param_data = &g_array_index(output, + bluetooth_device_address_t, 0); + break; + case BT_NETWORK_DISCONNECT: + *event_type = BT_ADAPTER_EVENT; + *event = BLUETOOTH_EVENT_NETWORK_DISCONNECTED; + ret_if(output == NULL); + *param_data = &g_array_index(output, + bluetooth_device_address_t, 0); + break; + case BT_RFCOMM_CLIENT_CONNECT: + *event_type = BT_RFCOMM_CLIENT_EVENT; + *event = BLUETOOTH_EVENT_RFCOMM_CONNECTED; + ret_if(output == NULL); + *param_data = &g_array_index(output, + bluetooth_rfcomm_connection_t, 0); + + break; + default: + BT_ERR("Unknown function"); + return; + } +} + +/* +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) +{ + bluetooth_event_param_t bt_event; + bt_req_info_t *cb_data = userdata; + int result = BLUETOOTH_ERROR_NONE; + int event_type = BT_ADAPTER_EVENT; + int request_id; + + 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); + result = BLUETOOTH_ERROR_TIMEOUT; + + ret_if(cb_data == NULL); + + __bt_get_event_info(cb_data->service_function, NULL, + &bt_event.event, &event_type, + &bt_event.param_data); + } else { + ret_if(out_param2 == NULL); + + result = g_array_index(out_param2, int, 0); + + ret_if(cb_data == NULL); + + __bt_get_event_info(cb_data->service_function, out_param1, + &bt_event.event, &event_type, + &bt_event.param_data); + + if (result == BLUETOOTH_ERROR_NONE) { + if (cb_data->service_function == BT_OPP_PUSH_FILES) { + request_id = g_array_index(out_param1, int, 0); + _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) + goto done; + + /* Only if fail case, call the callback function*/ + bt_event.result = result; + + if (event_type == BT_ADAPTER_EVENT || event_type == BT_RFCOMM_CLIENT_EVENT) { + ((bluetooth_cb_func_ptr)cb_data->cb)(bt_event.event, + &bt_event, + cb_data->user_data); + } else if (event_type == BT_HID_EVENT) { + ((hid_cb_func_ptr)cb_data->cb)(bt_event.event, + (hid_event_param_t *)&bt_event, + cb_data->user_data); + } else if (event_type == BT_HEADSET_EVENT) { + ((bt_audio_func_ptr)cb_data->cb)(bt_event.event, + (bt_audio_event_param_t *)&bt_event, + cb_data->user_data); + } +done: + sending_requests = g_slist_remove(sending_requests, (void *)cb_data); + + g_free(cb_data); +} + +int _bt_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; + GError *error = NULL; + GArray *in_param5 = NULL; + GArray *out_param2 = NULL; + DBusGProxy *proxy; + + switch (service_type) { + case BT_BLUEZ_SERVICE: + case BT_OBEX_SERVICE: + proxy = __bt_get_service_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + in_param5 = g_array_new(FALSE, FALSE, sizeof(gchar)); + + 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); + + 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 != 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); + + g_error_free(error); + } + else { + /* dBUS does not give error cause dBUS-RPC is failed */ + BT_ERR("error returned was NULL"); + } + + return result; + } + + BT_DBG("dBUS RPC is successfully done. type=%d, function=0x%x", + service_type, service_function); + + return result; +} + +int _bt_send_request_async(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; + + cb_data = g_new0(bt_req_info_t, 1); + + cb_data->service_function = service_function; + cb_data->cb = callback; + cb_data->user_data = user_data; + + 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); + + in_param5 = g_array_new(FALSE, FALSE, sizeof(gchar)); + + 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); + + if (proxy_call == NULL) { + + BT_ERR("dBUS-RPC is failed"); + g_array_free(in_param5, TRUE); + g_free(cb_data); + return BLUETOOTH_ERROR_INTERNAL; + } + + 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 new file mode 100644 index 0000000..9d34048 --- /dev/null +++ b/bt-api/bt-request-service.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/bt-api/bt-rfcomm-client.c b/bt-api/bt-rfcomm-client.c new file mode 100644 index 0000000..f8b0c4d --- /dev/null +++ b/bt-api/bt-rfcomm-client.c @@ -0,0 +1,159 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "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_rfcomm_connect(const bluetooth_device_address_t *remote_bt_address, + const char *remote_uuid) +{ + int result; + int connect_type; + bt_user_info_t *user_info; + char uuid[BLUETOOTH_UUID_STRING_MAX]; + + BT_CHECK_PARAMETER(remote_bt_address); + BT_CHECK_PARAMETER(remote_uuid); + BT_CHECK_ENABLED(); + + 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); + + /* connect_type: BT_RFCOMM_UUID / BT_RFCOMM_CHANNEL*/ + /* In now, we only support to connecty using UUID */ + connect_type = BT_RFCOMM_UUID; + + g_array_append_vals(in_param1, remote_bt_address, + sizeof(bluetooth_device_address_t)); + + g_strlcpy(uuid, remote_uuid, sizeof(uuid)); + g_array_append_vals(in_param2, uuid, BLUETOOTH_UUID_STRING_MAX); + + g_array_append_vals(in_param3, &connect_type, sizeof(int)); + + result = _bt_send_request_async(BT_BLUEZ_SERVICE, + BT_RFCOMM_CLIENT_CONNECT, + in_param1, in_param2, + in_param3, in_param4, + user_info->cb, user_info->user_data); + + BT_DBG("result: %x", result); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API gboolean bluetooth_rfcomm_is_client_connected(void) +{ + int result; + int connected = FALSE; + + BT_CHECK_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_RFCOMM_CLIENT_IS_CONNECTED, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_DBG("result: %x", result); + + if (result == BLUETOOTH_ERROR_NONE) { + connected = 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 connected; +} + +BT_EXPORT_API int bluetooth_rfcomm_disconnect(int socket_fd) +{ + int result; + int service_function; + + BT_CHECK_ENABLED(); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + /* Support the OSP */ + if (socket_fd == -1) { + /* Cancel connect */ + service_function = BT_RFCOMM_CLIENT_CANCEL_CONNECT; + } else { + g_array_append_vals(in_param1, &socket_fd, sizeof(int)); + service_function = BT_RFCOMM_SOCKET_DISCONNECT; + } + + result = _bt_send_request(BT_BLUEZ_SERVICE, service_function, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_DBG("result: %x", result); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_rfcomm_write(int fd, const char *buf, int length) +{ + int result; + char *buffer; + + BT_CHECK_PARAMETER(buf); + BT_CHECK_ENABLED(); + retv_if(length <= 0, BLUETOOTH_ERROR_INVALID_PARAM); + + 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); + + g_array_append_vals(in_param1, &fd, sizeof(int)); + g_array_append_vals(in_param2, &length, sizeof(int)); + g_array_append_vals(in_param3, buffer, length); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_SOCKET_WRITE, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_DBG("result: %x", result); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_free(buffer); + + return result; +} + diff --git a/bt-api/bt-rfcomm-server.c b/bt-api/bt-rfcomm-server.c new file mode 100644 index 0000000..a6a2350 --- /dev/null +++ b/bt-api/bt-rfcomm-server.c @@ -0,0 +1,238 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "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_rfcomm_create_socket(const char *uuid) +{ + int result; + int socket_fd = -1; + char uuid_str[BLUETOOTH_UUID_STRING_MAX]; + + BT_CHECK_ENABLED(); + BT_CHECK_PARAMETER(uuid); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_strlcpy(uuid_str, uuid, sizeof(uuid_str)); + g_array_append_vals(in_param1, uuid_str, BLUETOOTH_UUID_STRING_MAX); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_CREATE_SOCKET, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_DBG("result: %x", result); + + if (result == BLUETOOTH_ERROR_NONE) { + socket_fd = 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 socket_fd; +} + +BT_EXPORT_API int bluetooth_rfcomm_remove_socket(int socket_fd) +{ + int result; + + BT_CHECK_ENABLED(); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, &socket_fd, sizeof(int)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_REMOVE_SOCKET, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_DBG("result: %x", result); + + if (result == BLUETOOTH_ERROR_NONE) { + _bt_remove_server(socket_fd); + } + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_rfcomm_server_disconnect(int socket_fd) +{ + int result; + + BT_CHECK_ENABLED(); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, &socket_fd, sizeof(int)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_SOCKET_DISCONNECT, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_DBG("result: %x", result); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API gboolean bluetooth_rfcomm_is_server_uuid_available(const char *uuid) +{ + int result; + gboolean available = TRUE; + char uuid_str[BLUETOOTH_UUID_STRING_MAX]; + + retv_if(uuid == NULL, FALSE); + retv_if(bluetooth_check_adapter() == + BLUETOOTH_ADAPTER_DISABLED, FALSE); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_strlcpy(uuid_str, uuid, sizeof(uuid_str)); + g_array_append_vals(in_param1, uuid_str, BLUETOOTH_UUID_STRING_MAX); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_IS_UUID_AVAILABLE, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_DBG("result: %x", result); + + if (result == BLUETOOTH_ERROR_NONE) { + available = g_array_index(out_param, gboolean, 0); + } + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + BT_DBG("available: %d", available); + + return available; +} + +BT_EXPORT_API int bluetooth_rfcomm_listen_and_accept(int socket_fd, int max_pending_connection) +{ + int result; + gboolean native_service = TRUE; + + BT_CHECK_ENABLED(); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, &socket_fd, sizeof(int)); + g_array_append_vals(in_param2, &max_pending_connection, sizeof(int)); + g_array_append_vals(in_param3, &native_service, sizeof(gboolean)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_LISTEN, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_DBG("result: %x", result); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_rfcomm_listen(int socket_fd, int max_pending_connection) +{ + int result; + gboolean native_service = FALSE; + + BT_CHECK_ENABLED(); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, &socket_fd, sizeof(int)); + g_array_append_vals(in_param2, &max_pending_connection, sizeof(int)); + g_array_append_vals(in_param3, &native_service, sizeof(gboolean)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_LISTEN, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_DBG("result: %x", result); + + if (result == BLUETOOTH_ERROR_NONE) { + _bt_add_server(socket_fd); + } + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_rfcomm_accept_connection(int server_fd, int *client_fd) +{ + int result; + + BT_CHECK_ENABLED(); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, &server_fd, sizeof(int)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_ACCEPT_CONNECTION, + in_param1, in_param2, in_param3, in_param4, &out_param); + + 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; +} + +BT_EXPORT_API int bluetooth_rfcomm_reject_connection(int server_fd) +{ + int result; + + BT_CHECK_ENABLED(); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, &server_fd, sizeof(int)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_REJECT_CONNECTION, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_DBG("result: %x", result); + + 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 new file mode 100644 index 0000000..d0d81d4 --- /dev/null +++ b/bt-api/bt-service-api.pc.in @@ -0,0 +1,11 @@ +prefix=@PREFIX@ +exec_prefix=@EXEC_PREFIX@ +libdir=@LIBDIR@ +includedir=@INCLUDEDIR@ + +Name: bt-service +Description: TIZEN Linux platform Bluetooth Service API +Version: @VERSION@ +Requires: dlog dbus-glib-1 vconf +Libs: -L${libdir} -lbt-service-api +Cflags: -I${includedir} -I${includedir}/bt-service diff --git a/bt-api/bt-telephony.c b/bt-api/bt-telephony.c new file mode 100644 index 0000000..b1bdca2 --- /dev/null +++ b/bt-api/bt-telephony.c @@ -0,0 +1,1851 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "bt-common.h" +#include "bluetooth-telephony-api.h" +#include "marshal.h" + +typedef struct { + DBusGConnection *conn; + DBusGProxy *proxy; + DBusGProxy *dbus_proxy; + DBusGProxy *manager_proxy; +} telephony_dbus_info_t; + +typedef struct { + bt_telephony_func_ptr cb; + unsigned int call_count; + char *obj_path; + char address[BT_ADDRESS_STR_LEN]; + char call_path[BT_AUDIO_CALL_PATH_LEN]; + bluetooth_headset_state_t headset_state; + void *user_data; +} bt_telephony_info_t; + +#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.bluez.Manager" +#define BLUEZ_ADAPTER_INTERFACE "org.bluez.Adapter" +#define BLUEZ_DEVICE_INTERFACE "org.bluez.Device" + +#define HFP_AGENT_SERVICE "org.bluez.hfp_agent" +#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 BT_TELEPHONY_CHECK_ENABLED() \ + do { \ + if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED) \ + { \ + BT_ERR("BT is not enabled"); \ + return BLUETOOTH_TELEPHONY_ERROR_NOT_ENABLED; \ + } \ + } while (0) + +static gboolean is_initialized = FALSE; +#define BT_TELEPHONY_CHECK_INITIALIZED() \ + do { \ + if (is_initialized == FALSE) \ + { \ + BT_ERR("Bluetooth telephony not initilized"); \ + return BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED; \ + } \ + } while (0) + +#define BLUETOOTH_TELEPHONY_METHOD (bluetooth_telephony_method_get_type()) +#define BLUETOOTH_TELEPHONY_METHOD_GET_OBJECT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethod)) + +#define BLUETOOTH_TELEPHONY_METHOD_IS_OBJECT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), \ + BLUETOOTH_TELEPHONY_METHOD)) + +#define BLUETOOTH_TELEPHONY_METHOD_CLASS(class) \ + (G_TYPE_CHECK_CLASS_CAST((class), \ + BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethodClass)) + +#define BLUETOOTH_TELEPHONY_METHOD_GET_AGENT_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), \ + BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethodClass)) + +#define BLUETOOTH_TELEPHONY_METHOD_IS_AGENT_CLASS(class) \ + (G_TYPE_CHECK_CLASS_TYPE((class), BLUETOOTH_TELEPHONY_METHOD)) + +#define BLUETOOTH_TELEPHONY_METHOD_AGENT_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), \ + BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethodPrivate)) + +typedef struct _BluetoothTelephonyMethod BluetoothTelephonyMethod; +typedef struct _BluetoothTelephonyMethodClass BluetoothTelephonyMethodClass; + +struct _BluetoothTelephonyMethod { + GObject parent; +}; + +struct _BluetoothTelephonyMethodClass { + GObjectClass parent_class; +}; + +BluetoothTelephonyMethod *bluetooth_telephony_method_new(void); +GType bluetooth_telephony_method_get_type(void); + +G_DEFINE_TYPE(BluetoothTelephonyMethod, bluetooth_telephony_method, G_TYPE_OBJECT) + + +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 gboolean bluetooth_telephony_method_send_dtmf( + BluetoothTelephonyMethod *object, + gchar *dtmf, DBusGMethodInvocation *context); + +#include "bt-telephony-glue.h" + +static GObject *object; +static bt_telephony_info_t telephony_info; +static telephony_dbus_info_t telephony_dbus_info; +static gboolean is_active = FALSE; + +/*Function Declaration*/ +static int __bt_telephony_get_error(const char *error_message); +static void __bt_telephony_event_cb(int event, int result, void *param_data); +static GQuark __bluetooth_telephony_error_quark(void); +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); +static GError *__bluetooth_telephony_error(bluetooth_telephony_error_t error, + const char *err_msg); + +static DBusHandlerResult __bluetooth_telephony_event_filter( + DBusConnection *conn, + DBusMessage *msg, void *data); + +static void __bluetooth_telephony_adapter_added_cb(DBusGProxy *manager_proxy, + const char *adapter_path, gpointer user_data); +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 int __bluetooth_telephony_get_connected_device(void); +static DBusGProxy *__bluetooth_telephony_get_connected_device_proxy(void); + +/*Function Definition*/ +static int __bt_telephony_get_error(const char *error_message) +{ + if (error_message == NULL) { + BT_DBG("Error message NULL\n"); + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + } + + BT_DBG("Error message = %s \n", error_message); + if (g_strcmp0(error_message, "NotAvailable") == 0) + return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE; + else if (g_strcmp0(error_message, "NotConnected") == 0) + return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED; + else if (g_strcmp0(error_message, "InProgress") == 0) + return BLUETOOTH_TELEPHONY_ERROR_BUSY; + else if (g_strcmp0(error_message, "InvalidArguments") == 0) + return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM; + else if (g_strcmp0(error_message, "AlreadyExists") == 0) + return BLUETOOTH_TELEPHONY_ERROR_ALREADY_EXSIST; + else if (g_strcmp0(error_message, "Already Connected") == 0) + return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED; + else if (g_strcmp0(error_message, "No memory") == 0) + return BLUETOOTH_TELEPHONY_ERROR_NO_MEMORY; + else if (g_strcmp0(error_message, "I/O error") == 0) + 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 + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; +} + +static void __bt_telephony_event_cb(int event, int result, void *param_data) +{ + telephony_event_param_t bt_event = { 0, }; + + bt_event.event = event; + bt_event.result = result; + bt_event.param_data = param_data; + + ret_if(telephony_info.cb == NULL); + telephony_info.cb(bt_event.event, &bt_event, telephony_info.user_data); + return; +} + +static GQuark __bluetooth_telephony_error_quark(void) +{ + static GQuark quark = 0; + + quark = g_quark_from_static_string("telephony"); + + return quark; +} + +static DBusMessage* __bluetooth_telephony_dbus_method_send(const char *path, + const char *interface, const char *method, DBusError *err, int type, ...) +{ + DBusMessage *msg; + DBusMessage *reply; + va_list args; + + BT_DBG("+"); + + msg = dbus_message_new_method_call(HFP_AGENT_SERVICE, + 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); + + reply = dbus_connection_send_with_reply_and_block( + dbus_g_connection_get_connection(telephony_dbus_info.conn), + msg, -1, err); + dbus_message_unref(msg); + + BT_DBG("-"); + return reply; +} + +static int __bluetooth_telephony_send_call_status( + bt_telephony_call_status_t call_status, + unsigned int call_id) +{ + DBusMessage *reply; + DBusError err; + char *path = g_strdup(telephony_info.call_path); + int ret; + + BT_DBG("+"); + + reply = __bluetooth_telephony_dbus_method_send( + HFP_AGENT_PATH, HFP_AGENT_INTERFACE, + "ChangeCallStatus", &err, DBUS_TYPE_STRING, &path, + DBUS_TYPE_INT32, &call_status, + DBUS_TYPE_INT32, &call_id, DBUS_TYPE_INVALID); + g_free(path); + + 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); + + return BLUETOOTH_TELEPHONY_ERROR_NONE; +} + +static GError *__bluetooth_telephony_error(bluetooth_telephony_error_t error, + const char *err_msg) +{ + return g_error_new(BLUETOOTH_TELEPHONY_ERROR, error, err_msg, NULL); +} + +static void bluetooth_telephony_method_init(BluetoothTelephonyMethod *object) +{ + BT_DBG("+"); + BT_DBG("agent %p\n", object); + BT_DBG("-"); +} + +static void __bluetooth_telephony_method_finalize( + BluetoothTelephonyMethod *object) +{ + BT_DBG("+"); + G_OBJECT_CLASS(bluetooth_telephony_method_parent_class)->finalize(( + GObject *)object); + BT_DBG("-"); +} + +static BluetoothTelephonyMethod *__bluetooth_telephony_method_new(void) +{ + BluetoothTelephonyMethod *obj; + + BT_DBG("+"); + obj = g_object_new(BLUETOOTH_TELEPHONY_METHOD, NULL); + BT_DBG("-"); + + return obj; +} + +static void bluetooth_telephony_method_class_init( + BluetoothTelephonyMethodClass *klass) +{ + GObjectClass *object_class = NULL; + BT_DBG("+"); + + object_class = G_OBJECT_CLASS(klass); + object_class->finalize = (void *)__bluetooth_telephony_method_finalize; + + /*Registration of the Framework methods */ + dbus_g_object_type_install_info(BLUETOOTH_TELEPHONY_METHOD, + &dbus_glib_bluetooth_telephony_method_object_info); + BT_DBG("-"); + return; +} + +static gboolean bluetooth_telephony_method_answer( + BluetoothTelephonyMethod *object, + guint callid, DBusGMethodInvocation *context) +{ + telephony_event_callid_t call_data = { 0, }; + + BT_DBG("+"); + 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; +} + +static gboolean bluetooth_telephony_method_release( + BluetoothTelephonyMethod *object, + guint callid, DBusGMethodInvocation *context) +{ + telephony_event_callid_t call_data = { 0, }; + + BT_DBG("+"); + BT_DBG("call_id = [%d]\n", 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; + +} + +static gboolean bluetooth_telephony_method_reject( + BluetoothTelephonyMethod *object, + guint callid, DBusGMethodInvocation *context) +{ + telephony_event_callid_t call_data = { 0, }; + + BT_DBG("+"); + 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; +} + +static gboolean bluetooth_telephony_method_threeway( + BluetoothTelephonyMethod *object, + guint value, DBusGMethodInvocation *context) +{ + int event = 0; + GError *err; + + BT_DBG("+"); + BT_DBG("chld value = [%d]", value); + + switch (value) { + case 0: + event = BLUETOOTH_EVENT_TELEPHONY_CHLD_0_RELEASE_ALL_HELD_CALL; + break; + case 1: + event = BLUETOOTH_EVENT_TELEPHONY_CHLD_1_RELEASE_ALL_ACTIVE_CALL; + break; + case 2: + event = BLUETOOTH_EVENT_TELEPHONY_CHLD_2_ACTIVE_HELD_CALL; + break; + case 3: + event = BLUETOOTH_EVENT_TELEPHONY_CHLD_3_MERGE_CALL; + 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; + } + + BT_DBG("event = [%d]", event); + + __bt_telephony_event_cb(event, + BLUETOOTH_TELEPHONY_ERROR_NONE, NULL); + dbus_g_method_return(context); + BT_DBG("-"); + return TRUE; +} + +static gboolean bluetooth_telephony_method_send_dtmf( + BluetoothTelephonyMethod *object, + gchar *dtmf, DBusGMethodInvocation *context) +{ + telephony_event_dtmf_t call_data = { 0, }; + GError *err; + + BT_DBG("+"); + + if (dtmf == NULL) { + BT_DBG("Number dial failed\n"); + err = __bluetooth_telephony_error( + BLUETOOTH_TELEPHONY_ERROR_INVALID_DTMF, + "Invalid dtmf"); + dbus_g_method_return_error(context, err); + g_error_free(err); + return FALSE; + } + + BT_DBG("Dtmf = %s \n", dtmf); + + call_data.dtmf = g_strdup(dtmf); + + __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_SEND_DTMF, + BLUETOOTH_TELEPHONY_ERROR_NONE, (void *)&call_data); + + dbus_g_method_return(context); + g_free(call_data.dtmf); + BT_DBG("-"); + return TRUE; +} + +static void __bluetooth_handle_nrec_status_change(DBusMessage *msg) +{ + gboolean status = FALSE; + + if (!dbus_message_get_args(msg, NULL, + DBUS_TYPE_BOOLEAN, &status, + DBUS_TYPE_INVALID)) { + BT_DBG("Error Getting parameters\n"); + return; + } + BT_DBG("NREC status = %d\n", status); + + __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_NREC_CHANGED, + BLUETOOTH_TELEPHONY_ERROR_NONE, (void *)&status); + +} + +static DBusHandlerResult __bluetooth_telephony_event_filter( + DBusConnection *conn, + DBusMessage *msg, void *data) +{ + const char *path = dbus_message_get_path(msg); + char *dev_addr = NULL; + DBusMessageIter item_iter; + DBusMessageIter value_iter; + const char *property; + + /* Check NREC status change Signal*/ + if (dbus_message_is_signal(msg, HFP_AGENT_SERVICE, + HFP_NREC_STATUS_CHANGE)) { + __bluetooth_handle_nrec_status_change(msg); + return DBUS_HANDLER_RESULT_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; + + dbus_message_iter_init(msg, &item_iter); + if (dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_STRING) { + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + dbus_message_iter_get_basic(&item_iter, &property); + + if (property == NULL) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + BT_DBG("Property (%s)\n", property); + + if (g_strcmp0(property, "State") == 0) { + char *state = NULL; + dbus_message_iter_next(&item_iter); + 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"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + BT_DBG("State %s\n", state); + + if (g_strcmp0(state, "connected") == 0) { + telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED; + } else if (g_strcmp0(state, "playing") == 0) { + telephony_info.headset_state = BLUETOOTH_STATE_PLAYING; + } 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); + } + + telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED; + } + + return DBUS_HANDLER_RESULT_HANDLED; + } + + if (g_strcmp0(property, "Connected") == 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); + BT_DBG("Connected %d\n", connected); + + if (connected) { + /*Get device address*/ + if (path != NULL) + dev_addr = strstr(path, "dev_"); + + if (dev_addr != NULL) { + dev_addr += 4; + g_strlcpy(telephony_info.address, + dev_addr, + sizeof(telephony_info.address)); + g_strdelimit(telephony_info.address, "_", ':'); + BT_DBG("address is %s", + telephony_info.address); + + telephony_info.headset_state = + BLUETOOTH_STATE_CONNECTED; + + if (telephony_dbus_info.proxy != NULL) { + g_object_unref(telephony_dbus_info.proxy); + telephony_dbus_info.proxy = NULL; + } + + telephony_dbus_info.proxy = + __bluetooth_telephony_get_connected_device_proxy(); + + BT_DBG("Headset Connected"); + + __bt_telephony_event_cb( + BLUETOOTH_EVENT_TELEPHONY_HFP_CONNECTED, + BLUETOOTH_TELEPHONY_ERROR_NONE, NULL); + } + } else { /*Device disconnected*/ + memset(telephony_info.address, 0x00, + sizeof(telephony_info.address)); + telephony_info.headset_state = + BLUETOOTH_STATE_DISCONNETED; + + if (telephony_dbus_info.proxy != NULL) { + g_object_unref(telephony_dbus_info.proxy); + telephony_dbus_info.proxy = NULL; + } + + BT_DBG("Headset Disconnected"); + + __bt_telephony_event_cb( + BLUETOOTH_EVENT_TELEPHONY_HFP_DISCONNECTED, + BLUETOOTH_TELEPHONY_ERROR_NONE, NULL); + } + return DBUS_HANDLER_RESULT_HANDLED; + } + + if (g_strcmp0(property, "SpeakerGain") == 0) { + unsigned int spkr_gain; + guint16 gain; + dbus_message_iter_next(&item_iter); + dbus_message_iter_recurse(&item_iter, &value_iter); + dbus_message_iter_get_basic(&value_iter, &gain); + + spkr_gain = (unsigned int)gain; + BT_DBG("spk_gain[%d]\n", spkr_gain); + + __bt_telephony_event_cb( + BLUETOOTH_EVENT_TELEPHONY_SET_SPEAKER_GAIN, + BLUETOOTH_TELEPHONY_ERROR_NONE, + (void *)&spkr_gain); + + return DBUS_HANDLER_RESULT_HANDLED; + } + + if (g_strcmp0(property, "MicrophoneGain") == 0) { + unsigned int mic_gain; + guint16 gain; + dbus_message_iter_next(&item_iter); + dbus_message_iter_recurse(&item_iter, &value_iter); + dbus_message_iter_get_basic(&value_iter, &gain); + + mic_gain = (unsigned int)gain; + BT_DBG("mic_gain[%d]\n", mic_gain); + + __bt_telephony_event_cb( + BLUETOOTH_EVENT_TELEPHONY_SET_MIC_GAIN, + BLUETOOTH_TELEPHONY_ERROR_NONE, + (void *)&mic_gain); + + return DBUS_HANDLER_RESULT_HANDLED; + } + + if (g_strcmp0(property, "Playing") == 0) { + gboolean audio_sink_playing = FALSE; + dbus_message_iter_next(&item_iter); + dbus_message_iter_recurse(&item_iter, &value_iter); + 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( + BLUETOOTH_EVENT_TELEPHONY_AUDIO_DISCONNECTED, + BLUETOOTH_TELEPHONY_ERROR_NONE, NULL); + } + + return DBUS_HANDLER_RESULT_HANDLED; + } + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static void __bluetooth_telephony_adapter_added_cb(DBusGProxy *manager_proxy, + const char *adapter_path, gpointer user_data) +{ + int ret; + DBusError dbus_error; + DBusConnection *conn; + + BT_DBG("Adapter added [%s] \n", adapter_path); + + if (strstr(adapter_path, "hci0")) { + BT_DBG("BlueZ is Activated and flag need to be reset"); + BT_DBG("Send enabled to application\n"); + + ret = __bluetooth_telephony_register(); + if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) { + BT_DBG("__bluetooth_telephony_register failed\n"); + return; + } + + dbus_error_init(&dbus_error); + 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='" BLUEZ_HEADSET_INTERFACE + "',member='PropertyChanged'", &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_DBG("Fail to add dbus filter signal\n"); + dbus_error_free(&dbus_error); + __bluetooth_telephony_unregister(); + dbus_connection_remove_filter(dbus_g_connection_get_connection( + telephony_dbus_info.conn), + __bluetooth_telephony_event_filter, NULL); + } + } +} + +static int __bluetooth_telephony_proxy_init(void) +{ + BT_DBG("+"); + + object = (GObject *)__bluetooth_telephony_method_new(); + + if (NULL == object) + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + + BT_DBG("telephony_object = %x", object); + + dbus_g_connection_register_g_object(telephony_dbus_info.conn, + telephony_info.call_path, G_OBJECT(object)); + + BT_DBG("-"); + return BLUETOOTH_TELEPHONY_ERROR_NONE; +} + +static void __bluetooth_telephony_proxy_deinit(void) +{ + BT_DBG("+"); + + dbus_g_connection_unregister_g_object(telephony_dbus_info.conn, + G_OBJECT(object)); + + g_object_unref(object); + object = NULL; + + BT_DBG("-"); + return; +} + +static int __bluetooth_telephony_register(void) +{ + DBusMessage *reply; + DBusError err; + char *path = g_strdup(telephony_info.call_path); + int ret; + + BT_DBG("+"); + + reply = __bluetooth_telephony_dbus_method_send( + HFP_AGENT_PATH, HFP_AGENT_INTERFACE, + "RegisterApplication", &err, DBUS_TYPE_STRING, &path, + DBUS_TYPE_INVALID); + + g_free(path); + 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); + BT_DBG("-"); + return BLUETOOTH_TELEPHONY_ERROR_NONE; +} + +static int __bluetooth_telephony_unregister(void) +{ + DBusMessage *reply; + DBusError err; + char *path = g_strdup(telephony_info.call_path); + int ret; + + BT_DBG("+"); + + reply = __bluetooth_telephony_dbus_method_send( + HFP_AGENT_PATH, HFP_AGENT_INTERFACE, + "UnregisterApplication", &err, DBUS_TYPE_STRING, &path, + DBUS_TYPE_INVALID); + + g_free(path); + 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); + BT_DBG("+"); + return BLUETOOTH_TELEPHONY_ERROR_NONE; +} + +static int __bluetooth_get_default_adapter_path(DBusGConnection *GConn, + char *path) +{ + GError *err = NULL; + char *adapter_path = NULL; + + BT_DBG("+"); + + if (!dbus_g_proxy_call(telephony_dbus_info.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]", + err->message); + g_error_free(err); + } + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + } + + if (adapter_path == NULL) { + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + } + + if (strlen(adapter_path) >= BT_ADAPTER_PATH_LEN) { + BT_ERR("Path too long.\n"); + g_free(adapter_path); + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + } + + BT_DBG("path = %s", adapter_path); + g_strlcpy(path, adapter_path, BT_ADAPTER_PATH_LEN); + g_free(adapter_path); + BT_DBG("-"); + return BLUETOOTH_TELEPHONY_ERROR_NONE; +} + +static int __bluetooth_telephony_get_connected_device(void) +{ + DBusGProxy *list_proxy = NULL; + DBusGProxy *device_proxy = NULL; + GPtrArray *gp_array = NULL; + GError *error = NULL; + gchar *gp_path = NULL; + GHashTable *list_hash; + GHashTable *device_hash; + GValue *value = {0}; + gboolean playing = FALSE; + gboolean connected = FALSE; + const gchar *address; + char object_path[BT_ADAPTER_PATH_LEN] = {0}; + int i = 0; + DBusGProxy *proxy = NULL; + + BT_DBG("+"); + + /*Get default adapter path*/ + if (__bluetooth_get_default_adapter_path(telephony_dbus_info.conn, + object_path) < 0) + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + /*Get List of All devices*/ + list_proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn, + BLUEZ_SERVICE_NAME, object_path, + BLUEZ_ADAPTER_INTERFACE); + + if (list_proxy == NULL) + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + + dbus_g_proxy_call(list_proxy, "ListDevices", &error, G_TYPE_INVALID, + dbus_g_type_get_collection("GPtrArray", + DBUS_TYPE_G_OBJECT_PATH), + &gp_array, G_TYPE_INVALID); + + if (error != NULL) { + g_error_free(error); + goto done; + } + + if (gp_array == NULL) + goto done; + + /*Check for headset devices*/ + for (i = 0; i < gp_array->len; i++) { + list_hash = NULL; + device_hash = NULL; + gp_path = g_ptr_array_index(gp_array, i); + + if (gp_path == NULL) + goto done; + + proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn, + BLUEZ_SERVICE_NAME, gp_path, + BLUEZ_DEVICE_INTERFACE); + + if (proxy == NULL) + goto done; + + dbus_g_proxy_call(proxy, "GetProperties", NULL, + 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; + + /*Check for Connection*/ + device_proxy = dbus_g_proxy_new_for_name( + telephony_dbus_info.conn, + BLUEZ_SERVICE_NAME, gp_path, + BLUEZ_HEADSET_INTERFACE); + + if (device_proxy == NULL) { + g_hash_table_destroy(list_hash); + goto done; + } + + dbus_g_proxy_call(device_proxy, "GetProperties", + &error, G_TYPE_INVALID, + dbus_g_type_get_map("GHashTable", + G_TYPE_STRING, G_TYPE_VALUE), + &device_hash, G_TYPE_INVALID); + + if (error == NULL) { + value = g_hash_table_lookup(device_hash, + "Connected"); + connected = value ? g_value_get_boolean( + value) : FALSE; + 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)); + value = g_hash_table_lookup(device_hash, + "Playing"); + playing = value ? g_value_get_boolean( + value) : FALSE; + if (playing) + telephony_info.headset_state = + BLUETOOTH_STATE_PLAYING; + else + telephony_info.headset_state = + BLUETOOTH_STATE_CONNECTED; + + g_hash_table_destroy(device_hash); + g_hash_table_destroy(list_hash); + goto done; + } + g_hash_table_destroy(device_hash); + } else { + g_error_free(error); + } + + g_hash_table_destroy(list_hash); + g_object_unref(proxy); + proxy = NULL; + g_free(gp_path); + gp_path = NULL; + } +done: + if (list_proxy) + g_object_unref(list_proxy); + if (device_proxy) + g_object_unref(device_proxy); + if (proxy) + g_object_unref(proxy); + g_free(gp_path); + g_ptr_array_free(gp_array, TRUE); + BT_DBG("-"); + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; +} + +static DBusGProxy *__bluetooth_telephony_get_connected_device_proxy(void) +{ + DBusGProxy *proxy = NULL; + char object_path[BT_ADAPTER_PATH_LEN] = {0}; + GError *error = NULL; + DBusGProxy *default_proxy; + + BT_DBG("+"); + + /*Get default adapter path*/ + if (__bluetooth_get_default_adapter_path(telephony_dbus_info.conn, + object_path) < 0) + return NULL; + + /*Get List of All devices*/ + default_proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn, + BLUEZ_SERVICE_NAME, object_path, + BLUEZ_ADAPTER_INTERFACE); + + if (default_proxy == NULL) + return NULL; + + if (strlen(telephony_info.address) == 0) + __bluetooth_telephony_get_connected_device(); + + if (strlen(telephony_info.address) == 0) { + g_object_unref(default_proxy); + return NULL; + } + + if (telephony_info.obj_path) { + g_free(telephony_info.obj_path); + telephony_info.obj_path = NULL; + } + + dbus_g_proxy_call(default_proxy, "FindDevice", &error, + G_TYPE_STRING, telephony_info.address, + G_TYPE_INVALID, DBUS_TYPE_G_OBJECT_PATH, + &telephony_info.obj_path, + G_TYPE_INVALID); + if (error != NULL) { + BT_ERR("dbus_g_proxy_call Failed!\n"); + g_error_free(error); + g_object_unref(default_proxy); + return NULL; + } + + if (telephony_info.obj_path == NULL) { + g_object_unref(default_proxy); + return NULL; + } + + proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn, + BLUEZ_SERVICE_NAME, telephony_info.obj_path, + BLUEZ_HEADSET_INTERFACE); + + g_object_unref(default_proxy); + + return proxy; +} + +BT_EXPORT_API int bluetooth_telephony_init(bt_telephony_func_ptr cb, + void *user_data) +{ + DBusError dbus_error; + DBusConnection *conn; + int ret = BLUETOOTH_TELEPHONY_ERROR_NONE; + GError *error = NULL; + char object_path[BT_ADAPTER_PATH_LEN] = {0}; + BT_DBG("+"); + + g_type_init(); + + if (is_initialized == TRUE) { + BT_ERR("Bluetooth telephony already initilized"); + return BLUETOOTH_TELEPHONY_ERROR_ALREADY_INITIALIZED; + } + + is_initialized = TRUE; + + telephony_dbus_info.conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error); + if (!telephony_dbus_info.conn) { + if (NULL != error) { + BT_ERR("dbus_g_bus_get() failed:[%d:%s]\n", + error->code, error->message); + g_error_free(error); + } + is_initialized = FALSE; + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + } + + /* Call Path */ + snprintf(telephony_info.call_path, sizeof(telephony_info.call_path), + CSD_CALL_APP_PATH, getpid()); + BT_DBG("Call Path = %s", telephony_info.call_path); + memset(telephony_info.address, 0x00, sizeof(telephony_info.address)); + + if (__bluetooth_telephony_proxy_init()) { + BT_ERR("__bluetooth_telephony_proxy_init failed\n"); + dbus_g_connection_unref(telephony_dbus_info.conn); + telephony_dbus_info.conn = NULL; + is_initialized = FALSE; + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + } + + telephony_dbus_info.manager_proxy = dbus_g_proxy_new_for_name( + telephony_dbus_info.conn, + BLUEZ_SERVICE_NAME, + "/", BLUEZ_MANAGER_INTERFACE); + + if (telephony_dbus_info.manager_proxy == NULL) { + BT_ERR("Could not create a manager proxy\n"); + __bluetooth_telephony_proxy_deinit(); + dbus_g_connection_unref(telephony_dbus_info.conn); + telephony_dbus_info.conn = NULL; + is_initialized = FALSE; + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + } + + telephony_dbus_info.dbus_proxy = dbus_g_proxy_new_for_name( + telephony_dbus_info.conn, DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); + + if (NULL == telephony_dbus_info.dbus_proxy) { + __bluetooth_telephony_proxy_deinit(); + dbus_g_connection_unref(telephony_dbus_info.conn); + telephony_dbus_info.conn = NULL; + g_object_unref(telephony_dbus_info.manager_proxy); + telephony_dbus_info.manager_proxy = NULL; + is_initialized = FALSE; + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + } + + /*Add Signal callback for BT enabled*/ + dbus_g_proxy_add_signal(telephony_dbus_info.manager_proxy, + "AdapterAdded", + DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); + dbus_g_proxy_connect_signal(telephony_dbus_info.manager_proxy, + "AdapterAdded", + G_CALLBACK(__bluetooth_telephony_adapter_added_cb), + NULL, NULL); + + /*Callback and user applicaton data*/ + telephony_info.cb = cb; + telephony_info.user_data = user_data; + + dbus_error_init(&dbus_error); + 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='" BLUEZ_HEADSET_INTERFACE + "',member='PropertyChanged'", &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); + dbus_connection_remove_filter(dbus_g_connection_get_connection( + telephony_dbus_info.conn), + __bluetooth_telephony_event_filter, NULL); + goto fail; + } + + /*Check for BT status*/ + ret = __bluetooth_get_default_adapter_path(telephony_dbus_info.conn, + object_path); + if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) + return BLUETOOTH_TELEPHONY_ERROR_NONE; + + /*Bluetooth is active, therefore set the flag */ + is_active = TRUE; + + ret = __bluetooth_telephony_register(); + if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) { + BT_ERR("__bluetooth_telephony_register failed\n"); + goto fail; + } + + BT_DBG("-"); + return ret; +fail: + telephony_info.cb = NULL; + telephony_info.user_data = NULL; + telephony_info.call_count = 0; + + __bluetooth_telephony_proxy_deinit(); + + /*Remove BT enabled signal*/ + dbus_g_proxy_disconnect_signal( + telephony_dbus_info.manager_proxy, + "AdapterAdded", + G_CALLBACK(__bluetooth_telephony_adapter_added_cb), + NULL); + + dbus_g_connection_unref(telephony_dbus_info.conn); + telephony_dbus_info.conn = NULL; + g_object_unref(telephony_dbus_info.manager_proxy); + telephony_dbus_info.manager_proxy = NULL; + g_object_unref(telephony_dbus_info.dbus_proxy); + telephony_dbus_info.dbus_proxy = NULL; + is_initialized = FALSE; + return ret; +} + +BT_EXPORT_API int bluetooth_telephony_deinit(void) +{ + BT_DBG("+"); + + BT_TELEPHONY_CHECK_INITIALIZED(); + + is_initialized = FALSE; + + dbus_connection_remove_filter(dbus_g_connection_get_connection( + telephony_dbus_info.conn), + __bluetooth_telephony_event_filter, NULL); + + if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_ENABLED) + __bluetooth_telephony_unregister(); + + __bluetooth_telephony_proxy_deinit(); + + telephony_info.cb = NULL; + telephony_info.user_data = NULL; + telephony_info.call_count = 0; + + /*Remove BT enabled signal*/ + dbus_g_proxy_disconnect_signal( + telephony_dbus_info.manager_proxy, + "AdapterAdded", + G_CALLBACK(__bluetooth_telephony_adapter_added_cb), + 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; + + g_object_unref(telephony_dbus_info.dbus_proxy); + telephony_dbus_info.dbus_proxy = NULL; + + BT_DBG("-"); + return BLUETOOTH_TELEPHONY_ERROR_NONE; +} + +BT_EXPORT_API gboolean bluetooth_telephony_is_sco_connected(void) +{ + BT_DBG("+"); + + if (telephony_dbus_info.conn == NULL) { + BT_ERR("Bluetooth telephony not initilized"); + 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) + return FALSE; + + if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING) + return TRUE; + + BT_DBG("-"); + return FALSE; +} + +BT_EXPORT_API int bluetooth_telephony_is_nrec_enabled(gboolean *status) +{ + DBusMessage* reply; + DBusError err; + DBusMessageIter reply_iter; + DBusMessageIter reply_iter_entry; + const char *property; + + BT_DBG("+"); + + BT_TELEPHONY_CHECK_INITIALIZED(); + BT_TELEPHONY_CHECK_ENABLED(); + + if (status == NULL) + return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM; + + 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\n"); + if (dbus_error_is_set(&err)) { + BT_DBG("Error message = %s \n", 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\n"); + 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\n", property); + + if (g_strcmp0("nrec", 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_BOOLEAN) + continue; + + dbus_message_iter_get_basic(&dict_entry_val, status); + BT_DBG("NREC status = [%d]", *status); + } + dbus_message_iter_next(&reply_iter_entry); + } + dbus_message_unref(reply); + BT_DBG("-"); + return BLUETOOTH_TELEPHONY_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_telephony_start_voice_recognition(void) +{ + GError *error = NULL; + int ret; + + 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 (!dbus_g_proxy_call(telephony_dbus_info.proxy, "SetVoiceDial", + &error, G_TYPE_BOOLEAN, TRUE, G_TYPE_INVALID, + G_TYPE_INVALID)) { + if (error != NULL) { + ret = __bt_telephony_get_error(error->message); + g_error_free(error); + return ret; + } + } + + BT_DBG("-"); + return BLUETOOTH_TELEPHONY_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_telephony_stop_voice_recognition(void) +{ + GError *error = NULL; + int ret; + + BT_DBG("+"); + + BT_TELEPHONY_CHECK_INITIALIZED(); + BT_TELEPHONY_CHECK_ENABLED(); + + 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, + 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); + return ret; + } + } + + BT_DBG("-"); + return BLUETOOTH_TELEPHONY_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_telephony_audio_open(void) +{ + GError *error = NULL; + int ret; + + 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.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; + } + } + BT_DBG("-"); + return BLUETOOTH_TELEPHONY_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_telephony_audio_close(void) +{ + GError *error = NULL; + int ret; + + 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.headset_state != BLUETOOTH_STATE_PLAYING) { + return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED; + } + + 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; + } + } + + BT_DBG("-"); + return BLUETOOTH_TELEPHONY_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_telephony_call_remote_ringing(unsigned int call_id) +{ + int ret; + + BT_TELEPHONY_CHECK_INITIALIZED(); + BT_TELEPHONY_CHECK_ENABLED(); + + BT_DBG("+"); + + /*Make sure SCO is already connected */ + ret = __bluetooth_telephony_send_call_status( + CSD_CALL_STATUS_MO_ALERTING, call_id); + if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) { + BT_ERR("send call status Failed = [%d]", ret); + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + } + BT_DBG("-"); + return BLUETOOTH_TELEPHONY_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_telephony_call_answered(unsigned int call_id, + unsigned int bt_audio) +{ + int ret; + BT_DBG("+"); + + 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) { + BT_ERR("send call status Failed = [%d]", ret); + return ret; + } + + if (bt_audio) { + if (!bluetooth_telephony_is_sco_connected()) { + ret = bluetooth_telephony_audio_open(); + if (ret != 0) { + BT_ERR("Audio connection call Failed = %d", ret); + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + } + } + } + + BT_DBG("-"); + return ret; +} + +BT_EXPORT_API int bluetooth_telephony_call_end(unsigned int call_id) +{ + int ret; + BT_DBG("+"); + + 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) { + BT_ERR(" Failed = [%d]", ret); + return ret; + } + } + } + BT_DBG("-"); + return ret; +} + +BT_EXPORT_API int bluetooth_telephony_call_held(unsigned int call_id) +{ + int ret; + BT_DBG("+"); + + 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) { + BT_ERR("send call status Failed = [%d]", ret); + } + BT_DBG("-"); + return ret; +} + +BT_EXPORT_API int bluetooth_telephony_call_retrieved(unsigned int call_id) +{ + int ret; + BT_DBG("+"); + + 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) { + BT_ERR("send call status Failed = [%d]", ret); + } + BT_DBG("-"); + return ret; +} + +BT_EXPORT_API int bluetooth_telephony_call_swapped(void *call_list, + unsigned int call_count) +{ + int i; + int ret; + GList *list = call_list; + bt_telephony_call_status_info_t *call_status; + + BT_DBG("+"); + + BT_TELEPHONY_CHECK_INITIALIZED(); + BT_TELEPHONY_CHECK_ENABLED(); + + if (NULL == list) { + BT_ERR("call_list is invalid"); + return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM; + } + + BT_DBG(" call_count = [%d]", call_count); + + for (i = 0; i < call_count; i++) { + call_status = g_list_nth_data(list, i); + + if (NULL == call_status) + continue; + + BT_DBG(" %d : Call id [%d] status[%d]", i, + call_status->call_id, + call_status->call_status); + + switch (call_status->call_status) { + case BLUETOOTH_CALL_STATE_HELD: + ret = __bluetooth_telephony_send_call_status( + CSD_CALL_STATUS_HOLD, + call_status->call_id); + if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) { + BT_ERR("Failed = %d", ret); + return ret; + } + break; + + case BLUETOOTH_CALL_STATE_CONNECTED: + ret = __bluetooth_telephony_send_call_status( + CSD_CALL_STATUS_ACTIVE, + call_status->call_id); + if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) { + BT_ERR("Failed = [%d]", ret); + return ret; + } + break; + + default: + if ((call_status->call_status < BLUETOOTH_CALL_STATE_NONE) || + (call_status->call_status >= BLUETOOTH_CALL_STATE_ERROR)) { + BT_ERR("Unknown Call state"); + return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE; + } + } + } + + BT_DBG("-"); + return BLUETOOTH_TELEPHONY_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_telephony_set_call_status(void *call_list, + unsigned int call_count) +{ + int ret; + + BT_DBG("+"); + + ret = bluetooth_telephony_call_swapped(call_list, call_count); + + if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) { + BT_ERR("Failed = [%d]", ret); + return ret; + } + + telephony_info.call_count = call_count; + + BT_DBG("-"); + return BLUETOOTH_TELEPHONY_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_telephony_indicate_outgoing_call( + const char *ph_number, unsigned int call_id, + unsigned int bt_audio) +{ + DBusMessage *reply; + DBusError err; + const char *path = telephony_info.call_path; + int ret; + + BT_DBG("+"); + + BT_TELEPHONY_CHECK_INITIALIZED(); + BT_TELEPHONY_CHECK_ENABLED(); + + if (NULL == ph_number) + return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM; + + reply = __bluetooth_telephony_dbus_method_send( + HFP_AGENT_PATH, HFP_AGENT_INTERFACE, + "OutgoingCall", &err, DBUS_TYPE_STRING, &path, + DBUS_TYPE_STRING, &ph_number, DBUS_TYPE_INT32, + &call_id, 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); + + telephony_info.call_count++; + BT_DBG(" ag_info.ag_call_count = [%d]", telephony_info.call_count); + + if (bt_audio) { + if (!bluetooth_telephony_is_sco_connected()) { + ret = bluetooth_telephony_audio_open(); + if (ret != 0) { + BT_ERR(" Audio connection call Failed = %d", ret); + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + } + } + } + + BT_DBG("-"); + return BLUETOOTH_TELEPHONY_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_telephony_indicate_incoming_call( + const char *ph_number, unsigned int call_id) +{ + DBusMessage *reply; + DBusError err; + const char *path = telephony_info.call_path; + int ret; + + BT_DBG("+"); + + BT_TELEPHONY_CHECK_INITIALIZED(); + BT_TELEPHONY_CHECK_ENABLED(); + + if (NULL == ph_number) + return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM; + + reply = __bluetooth_telephony_dbus_method_send( + HFP_AGENT_PATH, HFP_AGENT_INTERFACE, + "IncomingCall", &err, DBUS_TYPE_STRING, &path, + DBUS_TYPE_STRING, &ph_number, DBUS_TYPE_INT32, + &call_id, 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); + + telephony_info.call_count++; + BT_DBG("telephony_info.call_count = [%d]", telephony_info.call_count); + BT_DBG("-"); + return BLUETOOTH_TELEPHONY_ERROR_NONE; +} + +BT_EXPORT_API int bluetooth_telephony_set_speaker_gain(unsigned short speaker_gain) +{ + DBusMessage *msg; + DBusMessageIter iter; + DBusMessageIter value; + DBusConnection *conn; + char *spkr_gain_str = "SpeakerGain"; + int ret = BLUETOOTH_TELEPHONY_ERROR_NONE; + + BT_DBG("+"); + BT_DBG("set speaker_gain= [%d]", speaker_gain); + + BT_TELEPHONY_CHECK_INITIALIZED(); + BT_TELEPHONY_CHECK_ENABLED(); + + conn = dbus_g_connection_get_connection(telephony_dbus_info.conn); + + if (telephony_info.obj_path == NULL) + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + + msg = dbus_message_new_method_call(BLUEZ_SERVICE_NAME, + telephony_info.obj_path, BLUEZ_HEADSET_INTERFACE, + "SetProperty"); + + if (NULL != msg) { + char sig[2] = {DBUS_TYPE_UINT16, '\0'}; + + dbus_message_iter_init_append(msg, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, + &spkr_gain_str); + dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, + sig, &value); + dbus_message_iter_append_basic(&value, DBUS_TYPE_UINT16, + &speaker_gain); + dbus_message_iter_close_container(&iter, &value); + + if (dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_METHOD_CALL) + dbus_message_set_no_reply(msg, TRUE); + if (!dbus_connection_send(conn, msg, NULL)) { + BT_ERR("bluetooth_telephony_set_speaker_gain : dbus sending failed"); + ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + } + dbus_message_unref(msg); + } else + ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + + BT_DBG("-"); + return ret; +} + +BT_EXPORT_API int bluetooth_telephony_get_headset_volume(unsigned int *speaker_gain) +{ + GHashTable *hash = NULL; + GValue *value = NULL; + GError *error = NULL; + int ret; + + 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 (!dbus_g_proxy_call(telephony_dbus_info.proxy, "GetProperties", &error, + G_TYPE_INVALID, + dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), + &hash, 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 (hash == NULL) + return BLUETOOTH_TELEPHONY_ERROR_INTERNAL; + + value = g_hash_table_lookup(hash, "SpeakerGain"); + *speaker_gain = g_value_get_uint(value); + g_hash_table_destroy(hash); + BT_DBG("-"); + return BLUETOOTH_TELEPHONY_ERROR_NONE; +} diff --git a/bt-api/bt-telephony.xml b/bt-api/bt-telephony.xml new file mode 100644 index 0000000..8cb4f63 --- /dev/null +++ b/bt-api/bt-telephony.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bt-api/include/bt-common.h b/bt-api/include/bt-common.h new file mode 100644 index 0000000..693878d --- /dev/null +++ b/bt-api/include/bt-common.h @@ -0,0 +1,231 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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_COMMON_H_ +#define _BT_COMMON_H_ + +#include +#include +#include +#include +#include + +#include "bluetooth-api.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#undef LOG_TAG +#define LOG_TAG "BLUETOOTH_FRWK" + +#ifndef BT_EXPORT_API +#define BT_EXPORT_API __attribute__((visibility("default"))) +#endif + +#define BT_DBG(fmt, args...) \ + SLOGD(fmt, ##args) +#define BT_ERR(fmt, args...) \ + 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_INIT_PARAMS() \ + GArray *in_param1 = NULL; \ + GArray *in_param2 = NULL; \ + GArray *in_param3 = NULL; \ + GArray *in_param4 = NULL; \ + GArray *out_param = NULL; + +#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(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)); \ + } while (0) + +#define BT_INIT_AGENT_PARAMS() \ + GArray *in_param = NULL; \ + GArray *out_param = NULL; + +#define BT_FREE_AGENT_PARAMS(IP,OP) \ + do { \ + if (IP) \ + g_array_free(IP, TRUE); \ + if (OP) \ + g_array_free(OP, TRUE); \ + } while (0) + +#define BT_ALLOC_AGENT_PARAMS(IP,OP) \ + do { \ + IP = g_array_new(FALSE, FALSE, sizeof(gchar)); \ + } while (0) + +#define BT_CHECK_PARAMETER(arg) \ + do { \ + if (arg == NULL) \ + { \ + BT_ERR("INVALID PARAMETER"); \ + return BLUETOOTH_ERROR_INVALID_PARAM; \ + } \ + } while (0) + +#define BT_CHECK_ENABLED() \ + do { \ + if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED) \ + { \ + BT_ERR("BT is not enabled"); \ + return BLUETOOTH_ERROR_DEVICE_NOT_ENABLED; \ + } \ + } while (0) + +#define BT_ADDRESS_LENGTH_MAX 6 +#define BT_ADDRESS_STRING_SIZE 18 +#define BT_ADAPTER_OBJECT_PATH_MAX 50 + +#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.bluez.Manager" +#define BT_ADAPTER_INTERFACE "org.bluez.Adapter" +#define BT_DEVICE_INTERFACE "org.bluez.Device" + +#define BT_BLUEZ_NAME "org.bluez" +#define BT_DBUS_NAME "org.projectx.bt" +#define BT_SERVICE_PATH "/org/projectx/bt_service" + +#define BT_AGENT_NAME "org.bluez.frwk_agent" +#define BT_AGENT_PATH "/org/bluez/agent/frwk_agent" +#define BT_AGENT_INTERFACE "org.bluez.Agent" + +#define BT_MAX_USER_INFO 5 +#define RFKILL_EVENT_SIZE 8 +#define RFKILL_NODE "/dev/rfkill" + +typedef enum { + RFKILL_TYPE_ALL = 0, + RFKILL_TYPE_WLAN, + RFKILL_TYPE_BLUETOOTH, + RFKILL_TYPE_UWB, + RFKILL_TYPE_WIMAX, + RFKILL_TYPE_WWAN, + RFKILL_TYPE_GPS, + RFKILL_TYPE_FM, + NUM_RFKILL_TYPES, +} rfkill_type; + +typedef struct { + unsigned int idx; + unsigned char type; + unsigned char op; + unsigned char soft; + unsigned char hard; +} rfkill_event; + +typedef enum { + BT_COMMON = 0x00, + BT_HID, + BT_AUDIO, + BT_AVRCP, +} bt_user_info_type_t; + +typedef struct { + void *cb; + void *user_data; +} bt_user_info_t; + +void _bt_set_user_data(int type, void *callback, void *user_data); + +void _bt_print_device_address_t(const bluetooth_device_address_t *addr); + +bt_user_info_t* _bt_get_user_data(int type); + +void _bt_common_event_cb(int event, int result, void *param, + void *callback, void *user_data); + +void _bt_input_event_cb(int event, int result, void *param, + void *callback, void *user_data); + +void _bt_headset_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); + +void _bt_opp_client_event_cb(int event, int result, void *param, + void *callback, void *user_data); + +void _bt_divide_device_class(bluetooth_device_class_t *device_class, + unsigned int cod); + +void _bt_convert_addr_string_to_type(unsigned char *addr, + const char *address); + +void _bt_convert_addr_type_to_string(char *address, + unsigned char *addr); + +int _bt_get_adapter_path(DBusGConnection *conn, char *path); + +DBusGProxy *_bt_get_adapter_proxy(DBusGConnection *conn); + +void _bt_device_path_to_address(const char *device_path, char *device_address); + +DBusGConnection *__bt_init_system_gconn(void); + +DBusGConnection *_bt_get_system_gconn(void); + +DBusConnection *_bt_get_system_conn(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_COMMON_H_*/ + diff --git a/bt-api/include/bt-event-handler.h b/bt-api/include/bt-event-handler.h new file mode 100644 index 0000000..307d2cc --- /dev/null +++ b/bt-api/include/bt-event-handler.h @@ -0,0 +1,66 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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_EVENT_HANDLER_H_ +#define _BT_EVENT_HANDLER_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define EVENT_MATCH_RULE \ + "type='signal'," \ + "interface='%s'," \ + "path='%s'" + +typedef struct { + int event_type; + DBusConnection *conn; + DBusHandleMessageFunction func; + void *cb; + void *user_data; +} bt_event_info_t; + + +int _bt_init_event_handler(void); + +int _bt_deinit_event_handler(void); + +int _bt_register_event(int event_type, void *event_cb, void *user_data); + +int _bt_unregister_event(int event_type); + +void _bt_add_server(int server_fd); + +void _bt_remove_server(int server_fd); + +void _bt_add_push_request_id(int request_id); + +void _bt_set_obex_server_id(int server_type); + +int _bt_get_obex_server_id(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _BT_EVENT_HANDLER_H_ */ diff --git a/bt-api/include/bt-request-sender.h b/bt-api/include/bt-request-sender.h new file mode 100644 index 0000000..5cbbee0 --- /dev/null +++ b/bt-api/include/bt-request-sender.h @@ -0,0 +1,57 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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_REQUEST_SENDER_H_ +#define _BT_REQUEST_SENDER_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + int service_function; + DBusGProxy *proxy; + DBusGProxyCall *proxy_call; + void *cb; + void *user_data; +} bt_req_info_t; + +void _bt_deinit_proxys(void); + +int _bt_send_request(int service_type, int service_function, + GArray *in_param1, GArray *in_param2, + GArray *in_param3, GArray *in_param4, + GArray **out_param1); + + +int _bt_send_request_async(int service_type, int service_function, + GArray *in_param1, GArray *in_param2, + GArray *in_param3, GArray *in_param4, + void *callback, void *user_data); + + +#ifdef __cplusplus +} +#endif + +#endif /* _BT_REQUEST_SENDER_H_ */ diff --git a/bt-api/marshal.list b/bt-api/marshal.list new file mode 100644 index 0000000..3116498 --- /dev/null +++ b/bt-api/marshal.list @@ -0,0 +1,5 @@ +# DBUS Signal argument converting list for bluetooth telephony lib +VOID:UINT +VOID:INT +VOID:STRING,UINT +VOID:STRING diff --git a/bt-core/CMakeLists.txt b/bt-core/CMakeLists.txt new file mode 100644 index 0000000..1536cdc --- /dev/null +++ b/bt-core/CMakeLists.txt @@ -0,0 +1,55 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(bt-core C) + +SET(SRCS bt_core.c) +SET(APP_VENDOR tizen) +SET(APP_NAME bt-core) +SET(APP_DIR ${CMAKE_INSTALL_PREFIX}/bin) +SET(APP_SYSCONFDIR ${CMAKE_INSTALL_PREFIX}/etc) + +IF("${CMAKE_BUILD_TYPE}" STREQUAL "") + SET(CMAKE_BUILD_TYPE "Release") +ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") +MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) + +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs REQUIRED dbus-glib-1 dlog vconf) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") +SET(CMAKE_C_FLAGS_RELEASE "-O2") + +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") + +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") + +ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"") +ADD_DEFINITIONS("-DVENDOR=\"${APP_VENDOR}\"") +ADD_DEFINITIONS("-DAPPNAME=\"${APP_NAME}\"") +ADD_DEFINITIONS("-DAPP_DIR=\"${APP_DIR}\"") +ADD_DEFINITIONS("-DAPP_SYSCONFDIR=\"${APP_SYSCONFDIR}\"") + +SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed") + +ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS}) + +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) + +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/org.projectx.bt_core.service DESTINATION share/dbus-1/services) + diff --git a/bt-core/bt_core.c b/bt-core/bt_core.c new file mode 100644 index 0000000..0a17410 --- /dev/null +++ b/bt-core/bt_core.c @@ -0,0 +1,458 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "bt_core.h" +#include "bt-internal-types.h" + +static GMainLoop *main_loop = NULL; + +typedef enum { + BT_DEACTIVATED, + BT_ACTIVATED, + BT_ACTIVATING, + BT_DEACTIVATING, +} bt_status_t; + +static bt_status_t adapter_status = BT_DEACTIVATED; + +static void __bt_core_terminate(void) +{ + if (main_loop) + g_main_loop_quit(main_loop); + else + exit(0); +} + +static void __bt_core_set_status(bt_status_t status) +{ + adapter_status = status; +} + +static bt_status_t __bt_core_get_status(void) +{ + return adapter_status; +} + +static gboolean bt_core_enable_adapter(BtCore *agent, + DBusGMethodInvocation *context); + +static gboolean bt_core_disable_adapter(BtCore *agent, + DBusGMethodInvocation *context); + +static gboolean bt_core_reset_adapter(BtCore *agent, + DBusGMethodInvocation *context); + +#include "bt_core_glue.h" + +GType bt_core_get_type (void); + + +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 __bt_enable_adapter(void) +{ + int ret; + bt_status_t status; + + BT_DBG(""); + + status = __bt_core_get_status(); + if (status != BT_DEACTIVATED) { + BT_DBG("Invalid state %d", status); + return -1; + } + + __bt_core_set_status(BT_ACTIVATING); + + ret = system("/usr/etc/bluetooth/bt-stack-up.sh &"); + if (ret < 0) { + BT_DBG("running script failed"); + ret = system("/usr/etc/bluetooth/bt-dev-end.sh &"); + __bt_core_set_status(BT_DEACTIVATED); + return -1; + } + + return 0; +} + +static int __bt_disable_adapter(void) +{ + bt_status_t status; + + BT_DBG(""); + + status = __bt_core_get_status(); + if (status == BT_ACTIVATING) { + /* Forcely terminate */ + if (system("/usr/etc/bluetooth/bt-stack-down.sh &") < 0) { + BT_DBG("running script failed"); + } + __bt_core_terminate(); + return 0; + } else if (status != BT_ACTIVATED) { + BT_DBG("Invalid state %d", status); + return -1; + } + + __bt_core_set_status(BT_DEACTIVATING); + + if (system("/usr/etc/bluetooth/bt-stack-down.sh &") < 0) { + BT_DBG("running script failed"); + __bt_core_set_status( BT_ACTIVATED); + return -1; + } + + return 0; +} + +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; + + 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; + + 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 int __bt_reset_adapter(void) +{ + /* Forcely terminate */ + if (system("/usr/etc/bluetooth/bt-reset-env.sh &") < 0) { + BT_DBG("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 void __name_owner_changed(DBusGProxy *object, const char *name, + const char *prev, const char *new, + gpointer user_data) +{ + if (g_strcmp0(name, "org.bluez") == 0 && *new == '\0') { + BT_DBG("BlueZ is terminated"); + __bt_disable_adapter(); + __bt_core_terminate(); + } else if (g_strcmp0(name, "org.projectx.bt") == 0 && *new == '\0') { + BT_DBG("bt-service is terminated abnormally"); + __bt_disable_adapter(); + } +} + +static DBusGProxy * __bt_core_register(DBusGConnection *conn, BtCore *bt_core) +{ + DBusGProxy *proxy; + GError *err = NULL; + guint result = 0; + + proxy = dbus_g_proxy_new_for_name(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; + } + + dbus_g_proxy_add_signal(proxy, "NameOwnerChanged", G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_INVALID); + + dbus_g_proxy_connect_signal(proxy, "NameOwnerChanged", + G_CALLBACK(__name_owner_changed), + NULL, NULL); + + dbus_g_connection_register_g_object(conn, BT_CORE_PATH, + G_OBJECT(bt_core)); + + return proxy; +} + +static void __bt_core_unregister(DBusGConnection *conn, BtCore *bt_core, + DBusGProxy *dbus_proxy) +{ + if (!bt_core || !dbus_proxy) + return; + + dbus_g_proxy_disconnect_signal(dbus_proxy, "NameOwnerChanged", + G_CALLBACK(__name_owner_changed), + NULL); + + dbus_g_connection_unregister_g_object(conn, G_OBJECT(bt_core)); + + g_object_unref(bt_core); + g_object_unref(dbus_proxy); + +} + +static void __adapter_added_cb(DBusGProxy *manager_proxy, + const char *adapter_path, + gpointer user_data) +{ + BT_DBG(""); + + __bt_core_set_status(BT_ACTIVATED); +} + +static void __adapter_removed_cb(DBusGProxy *manager_proxy, + const char *adapter_path, + gpointer user_data) +{ + BT_DBG(""); + + __bt_core_set_status(BT_DEACTIVATED); + + __bt_core_terminate(); +} + +static DBusGProxy *__bt_core_manager_init(DBusGConnection *conn) +{ + DBusGProxy *manager_proxy; + + manager_proxy = dbus_g_proxy_new_for_name(conn, "org.bluez", "/", + "org.bluez.Manager"); + if (manager_proxy == NULL) { + BT_ERR("ERROR: Can't make manager proxy"); + return NULL; + } + + dbus_g_proxy_add_signal(manager_proxy, "AdapterAdded", + DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); + dbus_g_proxy_connect_signal(manager_proxy, "AdapterAdded", + G_CALLBACK(__adapter_added_cb), + NULL, NULL); + + dbus_g_proxy_add_signal(manager_proxy, "AdapterRemoved", + DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); + dbus_g_proxy_connect_signal(manager_proxy, "AdapterRemoved", + G_CALLBACK(__adapter_removed_cb), + NULL, NULL); + + return manager_proxy; + + +} + +static void __bt_core_manager_exit(DBusGProxy *manager_proxy) +{ + if (!manager_proxy) + return; + + dbus_g_proxy_disconnect_signal(manager_proxy, "AdapterAdded", + G_CALLBACK(__adapter_added_cb), + NULL); + + dbus_g_proxy_disconnect_signal(manager_proxy, "AdapterRemoved", + G_CALLBACK(__adapter_removed_cb), + NULL); + + g_object_unref(manager_proxy); +} + +static void __bt_core_sigterm_handler(int signo) +{ + BT_DBG("Got the signal: %d", signo); + + __bt_core_terminate(); +} + +int main() +{ + DBusGConnection *conn = NULL; + GError *error = NULL; + BtCore *bt_core; + DBusGProxy *manager_proxy = NULL; + DBusGProxy *dbus_proxy = NULL; + struct sigaction sa; + + BT_DBG("+"); + + g_type_init(); + + 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); + return FALSE; + } + + bt_core = g_object_new(BT_CORE_TYPE, NULL); + if (bt_core == NULL) { + BT_ERR("bt_service is NULL"); + goto fail; + } + + dbus_proxy = __bt_core_register(conn, bt_core); + if (!dbus_proxy) { + BT_ERR("__bt_core_register failed"); + g_object_unref(bt_core); + bt_core = NULL; + goto fail; + } + + manager_proxy = __bt_core_manager_init(conn); + if (!manager_proxy) { + BT_ERR("__bt_core_manager_init failed"); + goto fail; + } + + main_loop = g_main_loop_new(NULL, FALSE); + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = __bt_core_sigterm_handler; + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + + g_main_loop_run(main_loop); + +fail: + __bt_core_unregister(conn, bt_core, dbus_proxy); + + __bt_core_manager_exit(manager_proxy); + + if (main_loop) + g_main_loop_unref(main_loop); + + dbus_g_connection_unref(conn); + + BT_DBG("-"); + return FALSE; +} diff --git a/bt-core/bt_core.h b/bt-core/bt_core.h new file mode 100644 index 0000000..ae83e63 --- /dev/null +++ b/bt-core/bt_core.h @@ -0,0 +1,61 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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_H_ +#define _BT_CORE_H_ + +#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_ERR(fmt, args...) \ + SLOGE(fmt, ##args) + +#define BT_CORE_NAME "org.projectx.bt_core" +#define BT_CORE_PATH "/org/projectx/bt_core" + +#define BT_CORE_TYPE (bt_core_get_type()) + +typedef struct _BtCore +{ + GObject object; +} BtCore; + +typedef struct _BtCoreClass +{ + GObjectClass object_class; +} BtCoreClass; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_CORE_H_*/ diff --git a/bt-core/bt_core.xml b/bt-core/bt_core.xml new file mode 100644 index 0000000..40a7f37 --- /dev/null +++ b/bt-core/bt_core.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/bt-core/org.projectx.bt_core.service b/bt-core/org.projectx.bt_core.service new file mode 100644 index 0000000..f8778e4 --- /dev/null +++ b/bt-core/org.projectx.bt_core.service @@ -0,0 +1,4 @@ +[D-BUS Service] +Name=org.projectx.bt_core +Exec=/usr/bin/bt-core +User=root diff --git a/bt-service/CMakeLists.txt b/bt-service/CMakeLists.txt new file mode 100644 index 0000000..8961e16 --- /dev/null +++ b/bt-service/CMakeLists.txt @@ -0,0 +1,86 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(bt-service C) + +SET(SRCS +marshal.c +bt-service-main.c +bt-service-event-sender.c +bt-service-event-receiver.c +bt-service-common.c +bt-service-util.c +bt-service-adapter.c +bt-service-device.c +bt-service-hid.c +bt-service-network.c +bt-service-audio.c +bt-service-oob.c +bt-service-obex-agent.c +bt-service-opp-client.c +bt-service-obex-server.c +bt-service-rfcomm-client.c +bt-service-rfcomm-server.c +bt-service-avrcp.c +bt-request-handler.c +bt-service-agent.c +bt-service-gap-agent.c +) + +IF("${CMAKE_BUILD_TYPE}" STREQUAL "") + SET(CMAKE_BUILD_TYPE "Release") +ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") +MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include) + +INCLUDE(FindPkgConfig) +pkg_check_modules(service_pkgs REQUIRED vconf aul vconf syspopup-caller dbus-glib-1 libprivilege-control status) + +FOREACH(flag ${service_pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag} -Wall") +ENDFOREACH(flag) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC") +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") +SET(CMAKE_C_FLAGS_RELEASE "-O2") +SET(APP_SYSCONFDIR /opt/var/lib/bluetooth) + +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") + +FIND_PROGRAM(MARSHALTOOL NAMES glib-genmarshal) +EXEC_PROGRAM("${MARSHALTOOL}" ARGS "--prefix=marshal ${CMAKE_CURRENT_SOURCE_DIR}/marshal.list --header > ${CMAKE_CURRENT_SOURCE_DIR}/include/marshal.h") +EXEC_PROGRAM("${MARSHALTOOL}" ARGS "--prefix=marshal ${CMAKE_CURRENT_SOURCE_DIR}/marshal.list --body > ${CMAKE_CURRENT_SOURCE_DIR}/marshal.c") + +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=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}\"") +ADD_DEFINITIONS("-DVENDOR=\"${APP_VENDOR}\"") +ADD_DEFINITIONS("-DAPPNAME=\"${APP_NAME}\"") +ADD_DEFINITIONS("-DAPP_DIR=\"${APP_DIR}\"") +ADD_DEFINITIONS("-DAPP_LOCALEDIR=\"${APP_LOCALEDIR}\"") +ADD_DEFINITIONS("-DAPP_SYSCONFDIR=\"${APP_SYSCONFDIR}\"") + +SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie") + +ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${service_pkgs_LDFLAGS}) + +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/org.projectx.bt.service DESTINATION share/dbus-1/services) +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin) + +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/auto-pair-blacklist DESTINATION /opt/var/lib/bluetooth) + +# install booting script +INSTALL(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/bluetooth-frwk-service DESTINATION /etc/rc.d/init.d) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) + diff --git a/bt-service/auto-pair-blacklist b/bt-service/auto-pair-blacklist new file mode 100644 index 0000000..b186f2c --- /dev/null +++ b/bt-service/auto-pair-blacklist @@ -0,0 +1,3 @@ +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 +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 diff --git a/bt-service/bluetooth-frwk-service b/bt-service/bluetooth-frwk-service new file mode 100644 index 0000000..674d59e --- /dev/null +++ b/bt-service/bluetooth-frwk-service @@ -0,0 +1,13 @@ +#!/bin/sh + +# +# Script for running BT Service during booting time +# + +if [ -x /usr/bin/bt-service ]; then + if [ -d /sys/fs/cgroup/systemd ]; then + export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/app/dbus/user_bus_socket; + fi + + /usr/bin/bt-service & +fi diff --git a/bt-service/bluetooth-frwk-service.service b/bt-service/bluetooth-frwk-service.service new file mode 100644 index 0000000..8a493cc --- /dev/null +++ b/bt-service/bluetooth-frwk-service.service @@ -0,0 +1,14 @@ +# bt-service check previous BT-connection status and re-activate BT when boot. + +[Unit] +Description=Bluetooth Framework Service + +[Service] +Type=dbus +BusName=org.projectx.bt +Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/app/dbus/user_bus_socket +ExecStart=/usr/bin/bt-service +RemainAfterExit=yes + +[Install] +WantedBy=bluetooth.target diff --git a/bt-service/bt-request-handler.c b/bt-service/bt-request-handler.c new file mode 100644 index 0000000..1f11666 --- /dev/null +++ b/bt-service/bt-request-handler.c @@ -0,0 +1,962 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "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-device.h" +#include "bt-service-hid.h" +#include "bt-service-network.h" +#include "bt-service-audio.h" +#include "bt-service-oob.h" +#include "bt-service-avrcp.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-request-handler.h" + +/* auto generated header by bt-request-service.xml*/ +#include "bt-service-method.h" + +DBusGConnection *bt_service_conn; +BtService *service_object; + +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) +{ + 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 int __bt_bluez_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 = BLUETOOTH_ERROR_NONE; + + switch (function_name) { + case BT_ENABLE_ADAPTER: + result = _bt_enable_adapter(); + break; + case BT_DISABLE_ADAPTER: + result = _bt_disable_adapter(); + break; + case BT_RESET_ADAPTER: + result = _bt_reset_adapter(); + break; + case BT_CHECK_ADAPTER: { + int enabled = 0; + + result = _bt_check_adapter(&enabled); + + g_array_append_vals(*out_param1, &enabled, + sizeof(int)); + break; + } + case BT_GET_LOCAL_ADDRESS: { + bluetooth_device_address_t local_address = { {0} }; + result = _bt_get_local_address(&local_address); + + g_array_append_vals(*out_param1, &local_address, + sizeof(bluetooth_device_address_t)); + break; + } + case BT_GET_LOCAL_NAME: { + bluetooth_device_name_t local_name = { {0} }; + result = _bt_get_local_name(&local_name); + + g_array_append_vals(*out_param1, &local_name, + sizeof(bluetooth_device_name_t)); + + break; + } + case BT_SET_LOCAL_NAME: { + bluetooth_device_name_t local_name = { {0} }; + + local_name = g_array_index(in_param1, + bluetooth_device_name_t, 0); + + result = _bt_set_local_name(local_name.name); + + break; + } + case BT_IS_SERVICE_USED: { + char *uuid; + gboolean used = FALSE; + + uuid = &g_array_index(in_param1, char, 0); + + result = _bt_is_service_used(uuid, &used); + + if (result == BLUETOOTH_ERROR_NONE) { + g_array_append_vals(*out_param1, &used, + sizeof(gboolean)); + } + break; + } + case BT_GET_DISCOVERABLE_MODE: { + int mode = BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE; + + result = _bt_get_discoverable_mode(&mode); + + g_array_append_vals(*out_param1, &mode, sizeof(int)); + break; + } + case BT_SET_DISCOVERABLE_MODE: { + int mode = BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE; + int time = 0; + + mode = g_array_index(in_param1, int, 0); + time = g_array_index(in_param2, int, 0); + + result = _bt_set_discoverable_mode(mode, time); + break; + } + case BT_GET_DISCOVERABLE_TIME: { + int timeout = 0; + + result = _bt_get_timeout_value(&timeout); + + g_array_append_vals(*out_param1, &timeout, sizeof(int)); + break; + } + case BT_START_DISCOVERY: + result = _bt_start_discovery(); + break; + + case BT_CANCEL_DISCOVERY: + result = _bt_cancel_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_GET_BONDED_DEVICES: + result = _bt_get_bonded_devices(out_param1); + break; + + case BT_GET_BONDED_DEVICE: { + bluetooth_device_address_t address = { {0} }; + bluetooth_device_info_t dev_info; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + memset(&dev_info, 0x00, sizeof(bluetooth_device_info_t)); + result = _bt_get_bonded_device_info(&address, &dev_info); + + if (result == BLUETOOTH_ERROR_NONE) { + g_array_append_vals(*out_param1, &dev_info, + sizeof(bluetooth_device_info_t)); + } + break; + } + case BT_BOND_DEVICE: { + bluetooth_device_address_t address = { {0} }; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + result = _bt_bond_device(request_id, &address, out_param1); + break; + } + case BT_CANCEL_BONDING: { + result = _bt_cancel_bonding(); + break; + } + case BT_UNBOND_DEVICE: { + bluetooth_device_address_t address = { {0} }; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + result = _bt_unbond_device(request_id, &address, out_param1); + + break; + } + case BT_SET_ALIAS: { + bluetooth_device_address_t address = { {0} }; + const char *local_name; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + local_name = &g_array_index(in_param2, char, 0); + + result = _bt_set_alias(&address, local_name); + break; + } + case BT_SEARCH_SERVICE: { + bluetooth_device_address_t address = { {0} }; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + result = _bt_search_device(request_id, &address); + if (result != BLUETOOTH_ERROR_NONE) { + g_array_append_vals(*out_param1, &address, + sizeof(bluetooth_device_address_t)); + } + break; + } + case BT_CANCEL_SEARCH_SERVICE: { + result = _bt_cancel_search_device(); + break; + } + case BT_SET_AUTHORIZATION: { + bluetooth_device_address_t address = { {0} }; + gboolean authorize; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + authorize = g_array_index(in_param2, gboolean, 0); + + result = _bt_set_authorization(&address, authorize); + break; + } + case BT_IS_DEVICE_CONNECTED: { + bluetooth_device_address_t address = { {0} }; + int type; + gboolean connected = FALSE; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + type = g_array_index(in_param2, int, 0); + + result = _bt_is_device_connected(&address, type, &connected); + + if (result == BLUETOOTH_ERROR_NONE) { + g_array_append_vals(*out_param1, &connected, + sizeof(gboolean)); + } + + break; + } + case BT_HID_CONNECT: { + bluetooth_device_address_t address = { {0} }; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + result = _bt_hid_connect(request_id, &address); + if (result != BLUETOOTH_ERROR_NONE) { + g_array_append_vals(*out_param1, &address, + sizeof(bluetooth_device_address_t)); + } + break; + } + case BT_HID_DISCONNECT: { + bluetooth_device_address_t address = { {0} }; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + result = _bt_hid_disconnect(request_id, &address); + if (result != BLUETOOTH_ERROR_NONE) { + g_array_append_vals(*out_param1, &address, + sizeof(bluetooth_device_address_t)); + } + break; + } + case BT_NETWORK_ACTIVATE: + result = _bt_network_activate(); + break; + case BT_NETWORK_DEACTIVATE: + result = _bt_network_deactivate(); + break; + case BT_NETWORK_CONNECT: { + bluetooth_device_address_t address = { {0} }; + int role; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + role = g_array_index(in_param2, int, 0); + + result = _bt_network_connect(request_id, role, &address); + if (result != BLUETOOTH_ERROR_NONE) { + g_array_append_vals(*out_param1, &address, + sizeof(bluetooth_device_address_t)); + } + break; + } + case BT_NETWORK_DISCONNECT: { + bluetooth_device_address_t address = { {0} }; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + result = _bt_network_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} }; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + result = _bt_audio_connect(request_id, BT_AUDIO_ALL, + &address, out_param1); + break; + } + case BT_AUDIO_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_AUDIO_ALL, + &address, out_param1); + break; + } + case BT_AG_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_AUDIO_HSP, + &address, out_param1); + break; + } + case BT_AG_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_AUDIO_HSP, + &address, out_param1); + break; + } + case BT_AV_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_AUDIO_A2DP, + &address, out_param1); + break; + } + case BT_AV_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_AUDIO_A2DP, + &address, out_param1); + break; + } + case BT_GET_SPEAKER_GAIN: { + unsigned int volume; + + result = _bt_audio_get_speaker_gain(&volume); + + g_array_append_vals(*out_param1, &volume, + sizeof(unsigned int)); + break; + } + case BT_SET_SPEAKER_GAIN: { + unsigned int volume; + + volume = g_array_index(in_param1, + unsigned int, 0); + + result = _bt_audio_set_speaker_gain(volume); + + break; + } + case BT_OOB_READ_LOCAL_DATA: { + bt_oob_data_t local_oob_data; + + memset(&local_oob_data, 0x00, sizeof(bt_oob_data_t)); + result = _bt_oob_read_local_data(&local_oob_data); + + g_array_append_vals(*out_param1, &local_oob_data, + sizeof(bt_oob_data_t)); + + break; + } + case BT_OOB_ADD_REMOTE_DATA: { + bluetooth_device_address_t address = { {0} }; + bt_oob_data_t local_oob_data; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + local_oob_data = g_array_index(in_param2, + bt_oob_data_t, 0); + + result = _bt_oob_add_remote_data(&address, &local_oob_data); + + break; + } + case BT_OOB_REMOVE_REMOTE_DATA: { + bluetooth_device_address_t address = { {0} }; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + result = _bt_oob_remove_remote_data(&address); + + break; + } + case BT_AVRCP_SET_TRACK_INFO: { + media_metadata_t data; + media_metadata_attributes_t meta_data; + + memset(&data, 0x00, sizeof(media_metadata_t)); + memset(&meta_data, 0x00, sizeof(media_metadata_attributes_t)); + + data = g_array_index(in_param1, + media_metadata_t, 0); + + 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 = data.duration; + + result = _bt_avrcp_set_track_info(&meta_data); + + 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; + } + case BT_AVRCP_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_set_property(type, value); + + break; + } + case BT_AVRCP_SET_PROPERTIES: { + media_player_settings_t properties; + + memset(&properties, 0x00, sizeof(media_player_settings_t)); + + properties = g_array_index(in_param1, + media_player_settings_t, 0); + + result = _bt_avrcp_set_properties(&properties); + + break; + } + case BT_RFCOMM_CLIENT_CONNECT: { + bluetooth_device_address_t address = { {0} }; + char *input_string; + int connect_type; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + input_string = &g_array_index(in_param2, char, 0); + + connect_type = g_array_index(in_param3, int, 0); + + if (connect_type == BT_RFCOMM_UUID) { + result = _bt_rfcomm_connect_using_uuid(request_id, + &address, input_string); + } else { + result = _bt_rfcomm_connect_using_channel(request_id, + &address, input_string); + } + + if (result != BLUETOOTH_ERROR_NONE) { + g_array_append_vals(*out_param1, &address, + sizeof(bluetooth_device_address_t)); + } + break; + } + case BT_RFCOMM_CLIENT_CANCEL_CONNECT: + result = _bt_rfcomm_cancel_connect(); + break; + case BT_RFCOMM_CLIENT_IS_CONNECTED: { + gboolean connected = FALSE; + result = _bt_rfcomm_is_connected(&connected); + + g_array_append_vals(*out_param1, &connected, sizeof(gboolean)); + break; + } + case BT_RFCOMM_SOCKET_DISCONNECT: { + int socket_fd; + + socket_fd = g_array_index(in_param1, int, 0); + + result = _bt_rfcomm_disconnect(socket_fd); + break; + } + case BT_RFCOMM_SOCKET_WRITE: { + int socket_fd; + int length; + char *buffer; + + socket_fd = g_array_index(in_param1, int, 0); + length = g_array_index(in_param2, int, 0); + buffer = &g_array_index(in_param3, char, 0); + + result = _bt_rfcomm_write(socket_fd, buffer, length); + break; + } + case BT_RFCOMM_CREATE_SOCKET: { + 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); + + result = _bt_rfcomm_create_socket(sender, uuid); + + if (result > 0) { + socket_fd = result; + result = BLUETOOTH_ERROR_NONE; + } + + g_array_append_vals(*out_param1, &socket_fd, sizeof(int)); + + g_free(sender); + break; + } + case BT_RFCOMM_REMOVE_SOCKET: { + int socket_fd; + + socket_fd = g_array_index(in_param1, int, 0); + + result = _bt_rfcomm_remove_socket(socket_fd); + break; + } + case BT_RFCOMM_LISTEN: { + int socket_fd; + int pending; + gboolean is_native; + + socket_fd = g_array_index(in_param1, int, 0); + pending = g_array_index(in_param2, int, 0); + is_native = g_array_index(in_param3, gboolean, 0); + + result = _bt_rfcomm_listen(socket_fd, pending, is_native); + break; + } + case BT_RFCOMM_IS_UUID_AVAILABLE: { + gboolean available = TRUE; + char *uuid; + + uuid = &g_array_index(in_param1, char, 0); + + result = _bt_rfcomm_is_uuid_available(uuid, &available); + + g_array_append_vals(*out_param1, &available, sizeof(gboolean)); + break; + } + case BT_RFCOMM_ACCEPT_CONNECTION: { + int socket_fd; + + socket_fd = g_array_index(in_param1, int, 0); + + result = _bt_rfcomm_accept_connection(socket_fd, request_id); + break; + } + case BT_RFCOMM_REJECT_CONNECTION: { + int socket_fd; + + socket_fd = g_array_index(in_param1, int, 0); + + result = _bt_rfcomm_reject_connection(socket_fd); + break; + } + default: + result = BLUETOOTH_ERROR_INTERNAL; + break; + } + + return result; +} + +static int __bt_obexd_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_OPP_PUSH_FILES: { + int i; + bluetooth_device_address_t address = { {0} }; + bt_file_path_t path; + char **file_path; + int file_count; + + address = g_array_index(in_param1, + bluetooth_device_address_t, 0); + + file_count = g_array_index(in_param3, int, 0); + + file_path = g_new0(char *, file_count + 1); + + for (i = 0; i < file_count; i++) { + path = g_array_index(in_param2, + bt_file_path_t, i); + + file_path[i] = g_strdup(path.path); + } + + result = _bt_opp_client_push_files(request_id, context, + &address, file_path, + file_count); + + for (i = 0; i < file_count; i++) { + g_free(file_path[i]); + } + + g_free(file_path); + + break; + } + case BT_OPP_CANCEL_PUSH: { + result = _bt_opp_client_cancel_push(); + + break; + } + case BT_OPP_IS_PUSHING_FILES: { + gboolean is_sending = FALSE; + + result = _bt_opp_client_is_sending(&is_sending); + + g_array_append_vals(*out_param1, &is_sending, + sizeof(gboolean)); + break; + } + case BT_OBEX_SERVER_ALLOCATE: { + int app_pid; + gboolean is_native; + char *path; + char *sender; + + sender = dbus_g_method_get_sender(context); + path = &g_array_index(in_param1, char, 0); + is_native = g_array_index(in_param2, gboolean, 0); + app_pid = g_array_index(in_param3, int, 0); + + result = _bt_obex_server_allocate(sender, path, app_pid, is_native); + + g_free(sender); + break; + } + case BT_OBEX_SERVER_DEALLOCATE: { + int app_pid; + gboolean is_native; + + is_native = g_array_index(in_param1, gboolean, 0); + app_pid = g_array_index(in_param2, int, 0); + + result = _bt_obex_server_deallocate(app_pid, is_native); + break; + } + case BT_OBEX_SERVER_IS_ACTIVATED: { + gboolean is_activated = FALSE; + + result = _bt_obex_server_is_activated(&is_activated); + + g_array_append_vals(*out_param1, &is_activated, + sizeof(gboolean)); + + break; + } + case BT_OBEX_SERVER_ACCEPT_CONNECTION: { + result = _bt_obex_server_accept_connection(request_id); + + break; + } + case BT_OBEX_SERVER_REJECT_CONNECTION: { + result = _bt_obex_server_reject_connection(); + + break; + } + case BT_OBEX_SERVER_ACCEPT_FILE: { + char *file_name; + + file_name = &g_array_index(in_param1, char, 0); + + result = _bt_obex_server_accept_authorize(file_name, TRUE); + + break; + } + case BT_OBEX_SERVER_REJECT_FILE: { + result = _bt_obex_server_reject_authorize(); + + break; + } + case BT_OBEX_SERVER_SET_PATH: { + gboolean is_native; + char *destination_path; + + destination_path = &g_array_index(in_param1, char, 0); + is_native = g_array_index(in_param2, gboolean, 0); + + result = _bt_obex_server_set_destination_path(destination_path, + is_native); + + break; + } + case BT_OBEX_SERVER_SET_ROOT: { + char *root; + + root = &g_array_index(in_param1, char, 0); + + result = _bt_obex_server_set_root(root); + + break; + } + case BT_OBEX_SERVER_CANCEL_TRANSFER: { + int transfer_id; + + transfer_id = g_array_index(in_param1, int, 0); + + result = _bt_obex_server_cancel_transfer(transfer_id); + + break; + } + case BT_OBEX_SERVER_CANCEL_ALL_TRANSFERS: { + result = _bt_obex_server_cancel_all_transfers(); + + break; + } + default: + BT_ERR("Unknown function!"); + result = BLUETOOTH_ERROR_INTERNAL; + break; + } + + return result; +} + +gboolean bt_service_request( + BtService *service, + int service_type, + int service_function, + int request_type, + GArray *in_param1, + GArray *in_param2, + GArray *in_param3, + GArray *in_param4, + GArray *in_param5, + DBusGMethodInvocation *context) +{ + int result; + int request_id = -1; + GArray *out_param1 = NULL; + GArray *out_param2 = NULL; + + out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar)); + out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar)); + + if (request_type == BT_ASYNC_REQ + || service_function == BT_OBEX_SERVER_ACCEPT_CONNECTION + || service_function == BT_RFCOMM_ACCEPT_CONNECTION) { + /* Set the timer */ + request_id = _bt_assign_request_id(); + if (request_id < 0) { + BT_ERR("Fail to assign the request id"); + result = BLUETOOTH_ERROR_INTERNAL; + goto fail; + } + } + + switch (service_type) { + case BT_BLUEZ_SERVICE: + result = __bt_bluez_request(service_function, request_type, + request_id, context, in_param1, in_param2, + in_param3, in_param4, &out_param1); + break; + case BT_OBEX_SERVICE: + result = __bt_obexd_request(service_function, request_type, + request_id, context, in_param1, + in_param2, in_param3, + in_param4, &out_param1); + break; + default: + BT_ERR("Unknown service type"); + result = BLUETOOTH_ERROR_INTERNAL; + goto fail; + } + + 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) { + _bt_insert_request_list(request_id, service_function, + NULL, context); + } else { + /* Return result */ + dbus_g_method_return(context, out_param1, out_param2); + } + + g_array_free(out_param1, TRUE); + g_array_free(out_param2, TRUE); + + return TRUE; +fail: + g_array_append_vals(out_param2, &result, sizeof(int)); + dbus_g_method_return(context, out_param1, out_param2); + + g_array_free(out_param1, TRUE); + g_array_free(out_param2, TRUE); + + if (request_type == BT_ASYNC_REQ) + _bt_delete_request_id(request_id); + + return FALSE; +} + +int _bt_service_register(void) +{ + BtService *bt_service; + DBusGConnection *conn; + DBusGProxy *proxy; + GError* err = NULL; + guint result = 0; + + conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + proxy = dbus_g_proxy_new_for_name(conn, DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); + + if (proxy == NULL) { + BT_ERR("proxy is NULL"); + goto fail; + } + + if (!dbus_g_proxy_call(proxy, "RequestName", &err, G_TYPE_STRING, + BT_SERVICE_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); + + goto fail; + } + + g_object_unref(proxy); + + if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + BT_ERR("Failed to get the primary well-known name.\n"); + goto fail; + } + + bt_service = g_object_new(BT_SERVICE_TYPE, NULL); + if (bt_service == NULL) { + BT_ERR("bt_service is NULL"); + goto fail; + } + + dbus_g_connection_register_g_object(conn, BT_SERVICE_PATH, + G_OBJECT(bt_service)); + + service_object = bt_service; + bt_service_conn = conn; + + return BLUETOOTH_ERROR_NONE; + +fail: + if (bt_service_conn) { + dbus_g_connection_unref(bt_service_conn); + bt_service_conn = NULL; + } + + return BLUETOOTH_ERROR_INTERNAL; +} + +void _bt_service_unregister(void) +{ + if (bt_service_conn) { + if (service_object) { + dbus_g_connection_unregister_g_object(bt_service_conn, + G_OBJECT(service_object)); + g_object_unref(service_object); + service_object = NULL; + } + + dbus_g_connection_unref(bt_service_conn); + bt_service_conn = NULL; + } +} + diff --git a/bt-service/bt-request-service.xml b/bt-service/bt-request-service.xml new file mode 100644 index 0000000..9d34048 --- /dev/null +++ b/bt-service/bt-request-service.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/bt-service/bt-service-adapter.c b/bt-service/bt-service-adapter.c new file mode 100644 index 0000000..ab3201f --- /dev/null +++ b/bt-service/bt-service-adapter.c @@ -0,0 +1,1138 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "bluetooth-api.h" +#include "bt-internal-types.h" + +#include "bt-service-common.h" +#include "bt-service-event.h" +#include "bt-service-adapter.h" +#include "bt-service-util.h" +#include "bt-service-network.h" +#include "bt-service-obex-server.h" +#include "bt-service-agent.h" +#include "bt-service-main.h" +#include "bt-service-avrcp.h" + +typedef struct { + guint event_id; + int timeout; +} bt_adapter_timer_t; + +bt_adapter_timer_t visible_timer; +static gboolean is_discovering; +static gboolean cancel_by_user; +static bt_status_t adapter_status = BT_DEACTIVATED; +static void *adapter_agent = NULL; +static DBusGProxy *core_proxy = NULL; + +#define BT_CORE_NAME "org.projectx.bt_core" +#define BT_CORE_PATH "/org/projectx/bt_core" +#define BT_CORE_INTERFACE "org.projectx.btcore" + + +static gboolean __bt_timeout_handler(gpointer user_data) +{ + int result = BLUETOOTH_ERROR_NONE; + + visible_timer.timeout--; + + /* Send event to application */ + _bt_send_event(BT_ADAPTER_EVENT, + BLUETOOTH_EVENT_DISCOVERABLE_TIMEOUT_CHANGED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INT16, &visible_timer.timeout, + DBUS_TYPE_INVALID); + + if (visible_timer.timeout <= 0) { + g_source_remove(visible_timer.event_id); + visible_timer.event_id = 0; + visible_timer.timeout = 0; + + if (vconf_set_int(BT_FILE_VISIBLE_TIME, 0) != 0) + BT_DBG("Set vconf failed\n"); + + return FALSE; + } + + return TRUE; +} + +int __bt_set_visible_time(int timeout) +{ + if (visible_timer.event_id > 0) { + g_source_remove(visible_timer.event_id); + visible_timer.event_id = 0; + } + + visible_timer.timeout = timeout; + + if (vconf_set_int(BT_FILE_VISIBLE_TIME, timeout) != 0) + BT_ERR("Set vconf failed\n"); + + if (timeout <= 0) + return BLUETOOTH_ERROR_NONE; + + visible_timer.event_id = g_timeout_add_seconds(1, + __bt_timeout_handler, NULL); + + return BLUETOOTH_ERROR_NONE; +} + +static void __bt_get_service_list(GValue *value, bluetooth_device_info_t *dev) +{ + int i; + char **uuids; + char **parts; + + ret_if(value == NULL); + ret_if(dev == NULL); + + uuids = g_value_get_boxed(value); + ret_if(uuids == NULL); + + dev->service_index = 0; + + for (i = 0; uuids[i] != NULL; i++) { + g_strlcpy(dev->uuids[i], uuids[i], BLUETOOTH_UUID_STRING_MAX); + + parts = g_strsplit(uuids[i], "-", -1); + + if (parts == NULL || parts[0] == NULL) + break; + + dev->service_list_array[i] = g_ascii_strtoull(parts[0], NULL, 16); + g_strfreev(parts); + + dev->service_index++; + } +} + +static int __bt_get_bonded_device_info(gchar *device_path, + bluetooth_device_info_t *dev_info) +{ + GValue *value = { 0 }; + GError *err = NULL; + DBusGProxy *device_proxy; + const gchar *address; + const gchar *name; + unsigned int cod; + gint rssi; + gboolean trust; + gboolean paired; + gboolean connected; + GHashTable *hash = NULL; + int ret; + DBusGConnection *conn; + + BT_CHECK_PARAMETER(device_path); + BT_CHECK_PARAMETER(dev_info); + + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + device_path, BT_DEVICE_INTERFACE); + + retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call(device_proxy, "GetProperties", &err, + G_TYPE_INVALID, + dbus_g_type_get_map("GHashTable", G_TYPE_STRING, + G_TYPE_VALUE), &hash, G_TYPE_INVALID); + + g_object_unref(device_proxy); + + if (err != NULL) { + BT_ERR("Error occured in Proxy call [%s]\n", err->message); + g_error_free(err); + return BLUETOOTH_ERROR_INTERNAL; + } + + if (hash != NULL) { + value = g_hash_table_lookup(hash, "Paired"); + paired = g_value_get_boolean(value); + + value = g_hash_table_lookup(hash, "Address"); + address = value ? g_value_get_string(value) : NULL; + + value = g_hash_table_lookup(hash, "Alias"); + name = value ? g_value_get_string(value) : NULL; + + if (name != NULL) + BT_DBG("Alias Name [%s]", name); + else { + value = g_hash_table_lookup(hash, "Name"); + name = value ? g_value_get_string(value) : NULL; + } + + value = g_hash_table_lookup(hash, "Class"); + cod = value ? g_value_get_uint(value) : 0; + + value = g_hash_table_lookup(hash, "Connected"); + connected = value ? g_value_get_boolean(value) : FALSE; + + value = g_hash_table_lookup(hash, "Trusted"); + trust = value ? g_value_get_boolean(value) : FALSE; + + if ((paired == FALSE) && (trust == FALSE)) { + return BLUETOOTH_ERROR_NOT_PAIRED; + } + + value = g_hash_table_lookup(hash, "RSSI"); + rssi = value ? g_value_get_int(value) : 0; + + 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); + + _bt_divide_device_class(&dev_info->device_class, cod); + + g_strlcpy(dev_info->device_name.name, name, + BLUETOOTH_DEVICE_NAME_LENGTH_MAX+1); + + dev_info->rssi = rssi; + dev_info->trust = trust; + dev_info->paired = paired; + dev_info->connected = connected; + g_hash_table_destroy(hash); + ret = BLUETOOTH_ERROR_NONE; + } else { + BT_ERR("Hash is NULL\n"); + ret = BLUETOOTH_ERROR_INTERNAL; + } + + return ret; +} + +void _bt_set_discovery_status(gboolean mode) +{ + is_discovering = mode; +} + +void _bt_set_cancel_by_user(gboolean value) +{ + cancel_by_user = value; +} + +gboolean _bt_get_cancel_by_user(void) +{ + return cancel_by_user; +} + +static void __bt_flight_mode_cb(keynode_t *node, void *data) +{ + 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(); + } + } +} + +static void __launch_bt_service(int status, int run_type) +{ + 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); + + bundle_free(kb); +} + +static void __bt_adapter_set_status(bt_status_t status) +{ + adapter_status = status; +} + +bt_status_t _bt_adapter_get_status(void) +{ + return adapter_status; +} + +static void __bt_phone_name_changed_cb(keynode_t *node, void *data) +{ + char *phone_name = NULL; + char *ptr = NULL; + + if (node == NULL) + return; + + 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)) + *ptr = '\0'; + + _bt_set_local_name(phone_name); + } + } +} + +static void __bt_set_visible_mode(void) +{ + int timeout; + + 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"); + } + } +} + +static void __bt_set_local_name(void) +{ + char *phone_name = NULL; + char *ptr = NULL; + + phone_name = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR); + + if (!phone_name) + return; + + if (strlen(phone_name) != 0) { + if (!g_utf8_validate(phone_name, -1, (const char **)&ptr)) + *ptr = '\0'; + _bt_set_local_name(phone_name); + } + free(phone_name); +} + +static int __bt_set_enabled(void) +{ + int enabled = FALSE; + int result = BLUETOOTH_ERROR_NONE; + + _bt_check_adapter(&enabled); + + if (enabled == FALSE) { + BT_ERR("Bluetoothd is not running"); + return BLUETOOTH_ERROR_INTERNAL; + } + + __bt_set_visible_mode(); + + __bt_set_local_name(); + + /* Update Bluetooth Status to notify other modules */ + if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_ON) != 0) + BT_ERR("Set vconf failed\n"); + + if (vconf_set_int(VCONFKEY_BT_DEVICE, VCONFKEY_BT_DEVICE_NONE) != 0) + BT_ERR("Set vconf failed\n"); + + /* 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; +} + +static void __bt_set_disabled(int result) +{ + /* Update Bluetooth Status to notify other modules */ + if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_OFF) != 0) + BT_ERR("Set vconf failed\n"); + + if (vconf_set_int(VCONFKEY_BT_DEVICE, VCONFKEY_BT_DEVICE_NONE) != 0) + BT_ERR("Set vconf failed\n"); + + /* Send disabled event */ + _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_DISABLED, + DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID); +} + +void *_bt_get_adapter_agent(void) +{ + return adapter_agent; +} + +void _bt_handle_flight_mode_noti(void) +{ + BT_DBG("+"); + vconf_notify_key_changed(VCONFKEY_TELEPHONY_FLIGHT_MODE, + __bt_flight_mode_cb, NULL); + BT_DBG("-"); +} + +void _bt_handle_adapter_added(void) +{ + adapter_agent = _bt_create_agent(BT_ADAPTER_AGENT_PATH, TRUE); + if (!adapter_agent) { + BT_ERR("Fail to register agent"); + return; + } + + 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"); + + if (_bt_register_obex_server() != BLUETOOTH_ERROR_NONE) + BT_ERR("Fail to init obex server"); + + /* add the vconf noti handler */ + vconf_notify_key_changed(VCONFKEY_SETAPPL_DEVICE_NAME_STR, + __bt_phone_name_changed_cb, NULL); + + vconf_notify_key_changed(VCONFKEY_TELEPHONY_FLIGHT_MODE, + __bt_flight_mode_cb, NULL); + + __bt_set_enabled(); + + __bt_adapter_set_status(BT_ACTIVATED); +} + +void _bt_handle_adapter_removed(void) +{ + __bt_adapter_set_status(BT_DEACTIVATED); + + vconf_ignore_key_changed(VCONFKEY_SETAPPL_DEVICE_NAME_STR, + (vconf_callback_fn)__bt_phone_name_changed_cb); + + _bt_destroy_agent(adapter_agent); + adapter_agent = NULL; + + __bt_set_disabled(BLUETOOTH_ERROR_NONE); + + _bt_terminate_service(NULL); +} + +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(); +} + +gboolean __bt_enable_timeout_cb(gpointer user_data) +{ + DBusGProxy *proxy; + + retv_if(_bt_adapter_get_status() == BT_ACTIVATED, FALSE); + + proxy = __bt_get_core_proxy(); + if (!proxy) + return BLUETOOTH_ERROR_INTERNAL; + + /* 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_adapter_set_status(BT_DEACTIVATED); + + __bt_set_disabled(BLUETOOTH_ERROR_TIMEOUT); + + /* Display notification */ + status_message_post(BT_STR_NOT_SUPPORT); + + _bt_terminate_service(NULL); + + return FALSE; +} + +int _bt_enable_adapter(void) +{ + DBusGProxy *proxy; + GError *err = NULL; + + BT_DBG(""); + + if (_bt_adapter_get_status() == BT_ACTIVATING) { + BT_DBG("Enabling in progress"); + return BLUETOOTH_ERROR_IN_PROGRESS; + } + + if (_bt_adapter_get_status() == BT_ACTIVATED) { + BT_DBG("Already enabled"); + return BLUETOOTH_ERROR_DEVICE_ALREADY_ENABLED; + } + + __bt_adapter_set_status(BT_ACTIVATING); + + proxy = __bt_get_core_proxy(); + if (!proxy) + return BLUETOOTH_ERROR_INTERNAL; + + if (dbus_g_proxy_call_with_timeout(proxy, "EnableAdapter", + BT_ENABLE_TIMEOUT, &err, + G_TYPE_INVALID, + G_TYPE_INVALID) == FALSE) { + + __bt_adapter_set_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, "DisableAdapter", NULL, + G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) { + BT_ERR("Bt core call failed"); + } + + /* Display notification */ + status_message_post(BT_STR_NOT_SUPPORT); + + /* Terminate myself */ + g_idle_add((GSourceFunc)_bt_terminate_service, NULL); + return BLUETOOTH_ERROR_INTERNAL; + } + + g_timeout_add(BT_ENABLE_TIMEOUT, + (GSourceFunc)__bt_enable_timeout_cb, + NULL); + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_disable_adapter(void) +{ + DBusGProxy *proxy; + + BT_DBG(""); + + 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; + + 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_reset_adapter(void) +{ + DBusGProxy *proxy; + + BT_DBG(""); + + proxy = __bt_get_core_proxy(); + if (!proxy) + return BLUETOOTH_ERROR_INTERNAL; + + if (dbus_g_proxy_call(proxy, "ResetAdapter", NULL, + G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) { + BT_ERR("Bt core call failed"); + return BLUETOOTH_ERROR_INTERNAL; + } + + /* Terminate myself */ + if (_bt_adapter_get_status() == BT_DEACTIVATED) { + g_idle_add((GSourceFunc)_bt_terminate_service, NULL); + } + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_check_adapter(int *status) +{ + DBusGProxy *proxy; + char *adapter_path = NULL; + + BT_CHECK_PARAMETER(status); + + *status = 0; /* 0: disabled */ + + proxy = _bt_get_manager_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + if (!dbus_g_proxy_call(proxy, "DefaultAdapter", NULL, + G_TYPE_INVALID, DBUS_TYPE_G_OBJECT_PATH, + &adapter_path, G_TYPE_INVALID)) { + BT_ERR("Fait to get DefaultAdapter"); + return BLUETOOTH_ERROR_NONE; + } + + if (adapter_path != NULL) + *status = 1; /* 1: enabled */ + + g_free(adapter_path); + return BLUETOOTH_ERROR_NONE; +} + +int _bt_get_local_address(bluetooth_device_address_t *local_address) +{ + DBusGProxy *proxy; + GHashTable *hash = NULL; + GValue *value; + char *address = NULL; + + BT_CHECK_PARAMETER(local_address); + + proxy = _bt_get_adapter_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); + + if (hash != NULL) { + value = g_hash_table_lookup(hash, "Address"); + address = (char *)(value ? g_value_dup_string(value) : NULL); + g_hash_table_destroy(hash); + } + + if (address) { + _bt_convert_addr_string_to_type(local_address->addr, address); + g_free(address); + } else { + return BLUETOOTH_ERROR_INTERNAL; + } + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_get_local_name(bluetooth_device_name_t *local_name) +{ + DBusGProxy *proxy; + GHashTable *hash = NULL; + GValue *value; + char *name = NULL; + char *ptr = NULL; + int ret = BLUETOOTH_ERROR_NONE; + + BT_CHECK_PARAMETER(local_name); + + proxy = _bt_get_adapter_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); + + if (hash != NULL) { + value = g_hash_table_lookup(hash, "Name"); + name = (char *)(value ? g_value_get_string(value) : NULL); + } + + if (name && (strlen(name) > 0)) { + /* Check the utf8 valitation & Fill the NULL in the invalid location*/ + if (!g_utf8_validate(name, -1, (const char **)&ptr)) + *ptr = '\0'; + + g_strlcpy(local_name->name, name, + BLUETOOTH_DEVICE_NAME_LENGTH_MAX + 1); + } else { + ret = BLUETOOTH_ERROR_INTERNAL; + } + + g_hash_table_destroy(hash); + return ret; +} + +int _bt_set_local_name(char *local_name) +{ + GValue name = { 0 }; + DBusGProxy *proxy; + GError *error = NULL; + char *ptr = NULL; + + BT_CHECK_PARAMETER(local_name); + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + if (!g_utf8_validate(local_name, -1, (const char **)&ptr)) + *ptr = '\0'; + + g_value_init(&name, G_TYPE_STRING); + g_value_set_string(&name, local_name); + + dbus_g_proxy_call(proxy, "SetProperty", + &error, G_TYPE_STRING, "Name", + G_TYPE_VALUE, &name, G_TYPE_INVALID, G_TYPE_INVALID); + + g_value_unset(&name); + + if (error) { + BT_ERR("SetProperty Fail: %s", error->message); + g_error_free(error); + return BLUETOOTH_ERROR_INTERNAL; + } + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_is_service_used(char *service_uuid, gboolean *used) +{ + char **uuids; + int i; + DBusGProxy *proxy; + GHashTable *hash = NULL; + GValue *value; + int ret = BLUETOOTH_ERROR_NONE; + + BT_CHECK_PARAMETER(service_uuid); + BT_CHECK_PARAMETER(used); + + proxy = _bt_get_adapter_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); + + value = g_hash_table_lookup(hash, "UUIDs"); + uuids = g_value_get_boxed(value); + + if (uuids == NULL) { + /* Normal case */ + *used = FALSE; + goto done; + } + + for (i = 0; uuids[i] != NULL; i++) { + if (strcasecmp(uuids[i], service_uuid) == 0) { + *used = TRUE; + goto done; + } + } + + *used = FALSE; +done: + g_hash_table_destroy(hash); + return ret; +} + +int _bt_get_discoverable_mode(int *mode) +{ + DBusGProxy *proxy; + GHashTable *hash = NULL; + GValue *value; + GValue *timeout_value; + + BT_CHECK_PARAMETER(mode); + + proxy = _bt_get_adapter_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); + + value = g_hash_table_lookup(hash, "Discoverable"); + timeout_value = g_hash_table_lookup(hash, "DiscoverableTimeout"); + + retv_if(value == NULL, BLUETOOTH_ERROR_INTERNAL); + + if (g_value_get_boolean(value)) { + if (g_value_get_uint(timeout_value) == 0) + *mode = BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE; + else + *mode = BLUETOOTH_DISCOVERABLE_MODE_TIME_LIMITED_DISCOVERABLE; + } else { + *mode = BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE; + } + g_hash_table_destroy(hash); + return BLUETOOTH_ERROR_NONE; +} + +int _bt_set_discoverable_mode(int discoverable_mode, int timeout) +{ + int ret = BLUETOOTH_ERROR_NONE; + gboolean inq_scan; + gboolean pg_scan; + GError *error = NULL; + GValue connectable = { 0 }; + GValue discoverable = { 0 }; + GValue val_timeout = { 0 }; + DBusGProxy *proxy; + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + g_value_init(&connectable, G_TYPE_BOOLEAN); + g_value_init(&discoverable, G_TYPE_BOOLEAN); + g_value_init(&val_timeout, G_TYPE_UINT); + + switch (discoverable_mode) { + case BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE: + pg_scan = TRUE; + inq_scan = FALSE; + timeout = 0; + break; + case BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE: + pg_scan = TRUE; + inq_scan = TRUE; + timeout = 0; + break; + case BLUETOOTH_DISCOVERABLE_MODE_TIME_LIMITED_DISCOVERABLE: + inq_scan = TRUE; + pg_scan = TRUE; + break; + default: + return BLUETOOTH_ERROR_INVALID_PARAM; + } + + 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, "SetProperty", &error, + G_TYPE_STRING, "Powered", + G_TYPE_VALUE, &connectable, + G_TYPE_INVALID, G_TYPE_INVALID); + + if (error != NULL) { + BT_ERR("Powered set err:[%s]", error->message); + g_error_free(error); + ret = BLUETOOTH_ERROR_INTERNAL; + goto done; + } + + dbus_g_proxy_call(proxy, "SetProperty", &error, + G_TYPE_STRING, "Discoverable", + 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); + ret = BLUETOOTH_ERROR_INTERNAL; + goto done; + } + + dbus_g_proxy_call(proxy, "SetProperty", &error, + G_TYPE_STRING, "DiscoverableTimeout", + G_TYPE_VALUE, &val_timeout, + G_TYPE_INVALID, G_TYPE_INVALID); + + if (error != NULL) { + BT_ERR("Timeout set err:[%s]", error->message); + g_error_free(error); + ret = BLUETOOTH_ERROR_INTERNAL; + goto done; + } + + if (discoverable_mode == BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE) + timeout = -1; + + __bt_set_visible_time(timeout); + +done: + g_value_unset(&val_timeout); + g_value_unset(&connectable); + g_value_unset(&discoverable); + + return ret; +} + +int _bt_start_discovery(void) +{ + DBusGProxy *proxy; + + 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 (!dbus_g_proxy_call(proxy, "StartDiscovery", NULL, + G_TYPE_INVALID, G_TYPE_INVALID)) { + BT_ERR("Discover start failed"); + return BLUETOOTH_ERROR_INTERNAL; + } + + is_discovering = TRUE; + cancel_by_user = FALSE; + /* discovery status will be change in event */ + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_cancel_discovery(void) +{ + DBusGProxy *proxy; + + if (_bt_is_discovering() == FALSE) { + BT_ERR("BT is not in 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, "StopDiscovery", NULL, + G_TYPE_INVALID, G_TYPE_INVALID)) { + BT_ERR("Discover stop failed"); + return BLUETOOTH_ERROR_INTERNAL; + } + + cancel_by_user = TRUE; + /* discovery status will be change in event */ + + return BLUETOOTH_ERROR_NONE; +} + +gboolean _bt_is_discovering(void) +{ + return is_discovering; +} + +gboolean _bt_get_discoverying_property(void) +{ + DBusGProxy *proxy; + GHashTable *hash = NULL; + GValue *value; + gboolean is_discover = FALSE; + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, FALSE); + + 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, FALSE); + + value = g_hash_table_lookup(hash, "Discovering"); + is_discover = g_value_get_boolean(value); + g_hash_table_destroy(hash); + return is_discover; +} + +int _bt_get_discoverable_timeout_property(void) +{ + DBusGProxy *proxy; + GHashTable *hash = NULL; + GValue *value; + unsigned int disc_to; + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, 0); + + 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, 0); + + value = g_hash_table_lookup(hash, "DiscoverableTimeout"); + disc_to = g_value_get_uint(value); + g_hash_table_destroy(hash); + return disc_to; +} + +int _bt_get_bonded_devices(GArray **dev_list) +{ + int i; + GPtrArray *gp_array = NULL; + GError *error = NULL; + DBusGProxy *proxy; + + BT_CHECK_PARAMETER(dev_list); + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call(proxy, "ListDevices", &error, + G_TYPE_INVALID, dbus_g_type_get_collection("GPtrArray", + DBUS_TYPE_G_OBJECT_PATH), &gp_array, G_TYPE_INVALID); + + if (error != NULL) { + BT_ERR("ListDevices error: [%s]\n", error->message); + g_error_free(error); + return BLUETOOTH_ERROR_INTERNAL; + } + + retv_if(gp_array == NULL, BLUETOOTH_ERROR_NONE); + retv_if(gp_array->len == 0, BLUETOOTH_ERROR_NONE); + + for (i = 0; i < gp_array->len; i++) { + bluetooth_device_info_t dev_info; + gchar *gp_path = g_ptr_array_index(gp_array, i); + + if (gp_path == NULL) + continue; + + memset(&dev_info, 0x00, sizeof(bluetooth_device_info_t)); + + if (__bt_get_bonded_device_info(gp_path, + &dev_info) == BLUETOOTH_ERROR_NONE) { + + g_array_append_vals(*dev_list, &dev_info, + sizeof(bluetooth_device_info_t)); + } else { + BT_ERR("Can't get the paired device path \n"); + break; + } + } + + g_ptr_array_free(gp_array, TRUE); + return BLUETOOTH_ERROR_NONE; +} + +int _bt_get_bonded_device_info(bluetooth_device_address_t *device_address, + bluetooth_device_info_t *dev_info) +{ + char *object_path = NULL; + DBusGProxy *adapter_proxy; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + + BT_CHECK_PARAMETER(device_address); + BT_CHECK_PARAMETER(dev_info); + + adapter_proxy = _bt_get_adapter_proxy(); + retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + _bt_convert_addr_type_to_string(address, device_address->addr); + + dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL, + G_TYPE_STRING, address, G_TYPE_INVALID, + DBUS_TYPE_G_OBJECT_PATH, &object_path, + G_TYPE_INVALID); + + retv_if(object_path == NULL, BLUETOOTH_ERROR_NOT_FOUND); + + 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; + } + g_free(object_path); + return BLUETOOTH_ERROR_NONE; +} + +int _bt_get_timeout_value(int *timeout) +{ + *timeout = 0; + + *timeout = visible_timer.timeout; + + return BLUETOOTH_ERROR_NONE; +} + diff --git a/bt-service/bt-service-agent.c b/bt-service/bt-service-agent.c new file mode 100644 index 0000000..d4b4d73 --- /dev/null +++ b/bt-service/bt-service-agent.c @@ -0,0 +1,854 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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" + +#define BT_APP_AUTHENTICATION_TIMEOUT 35 +#define BT_APP_AUTHORIZATION_TIMEOUT 15 + +#define HFP_AUDIO_GATEWAY_UUID "0000111f-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" +#define FTP_UUID "00001106-0000-1000-8000-00805f9b34fb" +#define SPP_UUID "00001101-0000-1000-8000-00805f9b34fb" +#define PBAP_UUID "0000112f-0000-1000-8000-00805f9b34fb" +#define MAP_UUID "00001132-0000-1000-8000-00805f9b34fb" + +#define BT_AGENT_OBJECT "/org/bluez/agent/frwk_agent" +#define BT_AGENT_INTERFACE "org.bluez.Agent" +#define BT_AGENT_SIGNAL_RFCOMM_AUTHORIZE "RfcommAuthorize" +#define BT_AGENT_SIGNAL_OBEX_AUTHORIZE "ObexAuthorize" + +#define BT_PIN_MAX_LENGTH 16 +#define BT_PASSKEY_MAX_LENGTH 6 + +#define BT_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS 200 + +static int __bt_agent_is_auto_response(uint32_t dev_class, const gchar *address, + const gchar *name); +static gboolean __bt_agent_is_hid_keyboard(uint32_t dev_class); +static int __bt_agent_generate_passkey(char *passkey, int size); + +static void __bt_agent_release_memory(void) +{ + /* Release Malloc Memory*/ + malloc_trim(0); + + /* Release Stack Memory*/ + stack_trim(); +} + +static gboolean __bt_agent_system_popup_timer_cb(gpointer user_data) +{ + int ret; + bundle *b = (bundle *) user_data; + + if (NULL == b) { + BT_DBG("There is some problem with the user data..popup can not be created\n"); + return FALSE; + } + ret = syspopup_launch("bt-syspopup", b); + + if (0 > ret) + BT_DBG("Sorry Can not launch popup\n"); + else + BT_DBG("Hurray Popup launched \n"); + + bundle_free(b); + return FALSE; +} + +static int __launch_system_popup(bt_agent_event_type_t event_type, + const char *device_name, + char *passkey, + const char *filename, + const char *agent_path) +{ + int ret; + bundle *b; + char event_str[BT_MAX_EVENT_STR_LENGTH + 1]; + + BT_DBG("_bt_agent_launch_system_popup +"); + + b = bundle_create(); + if (!b) + return -1; + + bundle_add(b, "device-name", device_name); + bundle_add(b, "passkey", passkey); + bundle_add(b, "file", filename); + bundle_add(b, "agent-path", agent_path); + + switch (event_type) { + case BT_AGENT_EVENT_PIN_REQUEST: + g_strlcpy(event_str, "pin-request", sizeof(event_str)); + break; + + case BT_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST: + g_strlcpy(event_str, "passkey-confirm-request", + sizeof(event_str)); + break; + + case BT_AGENT_EVENT_PASSKEY_REQUEST: + g_strlcpy(event_str, "passkey-request", sizeof(event_str)); + break; + + case BT_AGENT_EVENT_PASSKEY_DISPLAY_REQUEST: + g_strlcpy(event_str, "passkey-display-request", + sizeof(event_str)); + break; + + case BT_AGENT_EVENT_AUTHORIZE_REQUEST: + g_strlcpy(event_str, "authorize-request", + sizeof(event_str)); + break; + + case BT_AGENT_EVENT_CONFIRM_MODE_REQUEST: + g_strlcpy(event_str, "confirm-mode-request", + sizeof(event_str)); + break; + + case BT_AGENT_EVENT_FILE_RECEIVED: + g_strlcpy(event_str, "file-received", sizeof(event_str)); + break; + + case BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST: + g_strlcpy(event_str, "keyboard-passkey-request", + sizeof(event_str)); + break; + + case BT_AGENT_EVENT_TERMINATE: + g_strlcpy(event_str, "terminate", sizeof(event_str)); + break; + + case BT_AGENT_EVENT_EXCHANGE_REQUEST: + g_strlcpy(event_str, "exchange-request", sizeof(event_str)); + break; + + case BT_AGENT_EVENT_PBAP_REQUEST: + g_strlcpy(event_str, "phonebook-request", sizeof(event_str)); + break; + + case BT_AGENT_EVENT_MAP_REQUEST: + g_strlcpy(event_str, "message-request", sizeof(event_str)); + break; + + default: + bundle_free(b); + return -1; + + } + + bundle_add(b, "event-type", event_str); + + ret = syspopup_launch("bt-syspopup", b); + if (0 > ret) { + BT_DBG("Popup launch failed...retry %d\n", ret); + g_timeout_add(BT_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS, + (GSourceFunc) __bt_agent_system_popup_timer_cb, + b); + } else { + bundle_free(b); + } + + BT_DBG("_bt_agent_launch_system_popup -%d", ret); + return 0; +} + +static gboolean __pincode_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"); + + dbus_g_proxy_call(device, "GetProperties", &error, + 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 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) { + gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL); + goto done; + } + + value = g_hash_table_lookup(hash, "Name"); + name = value ? g_value_get_string(value) : NULL; + if (!name) + name = address; + + if (__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", + NULL); + } else if (__bt_agent_is_hid_keyboard(device_class)) { + char str_passkey[7] = { 0 }; + + __bt_agent_generate_passkey(str_passkey, sizeof(str_passkey)); + + gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT, + str_passkey, NULL); + + __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, + NULL, _gap_agent_get_path(agent)); + } + +done: + g_hash_table_destroy(hash); + __bt_agent_release_memory(); + + BT_DBG("-\n"); + + 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"); + + dbus_g_proxy_call(device, "GetProperties", &error, + 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 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) { + gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL); + goto done; + } + + value = g_hash_table_lookup(hash, "Name"); + name = value ? g_value_get_string(value) : NULL; + if (!name) + name = address; + + __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"); + + return TRUE; +} + +static gboolean __display_request(GapAgent *agent, DBusGProxy *device, + guint passkey) +{ + GHashTable *hash = NULL; + GValue *value; + const gchar *address; + const gchar *name; + GError *error = NULL; + char *str_passkey; + + BT_DBG("+\n"); + + dbus_g_proxy_call(device, "GetProperties", &error, + 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 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, "Address"); + address = value ? g_value_get_string(value) : NULL; + if (!address) { + gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL); + goto done; + } + + value = g_hash_table_lookup(hash, "Name"); + name = value ? g_value_get_string(value) : NULL; + if (!name) + name = address; + + str_passkey = g_strdup_printf("%d", passkey); + + __launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST, name, + str_passkey, NULL, + _gap_agent_get_path(agent)); + + g_free(str_passkey); + +done: + __bt_agent_release_memory(); + g_hash_table_destroy(hash); + BT_DBG("-\n"); + + return TRUE; +} + +static gboolean __confirm_request(GapAgent *agent, DBusGProxy *device, + guint passkey) +{ + uint32_t device_class; + GHashTable *hash = NULL; + GValue *value; + const gchar *address; + const gchar *name; + GError *error = NULL; + char str_passkey[7]; + + BT_DBG("+ passkey[%.6d]\n", passkey); + + snprintf(str_passkey, sizeof(str_passkey), "%.6d", passkey); + + dbus_g_proxy_call(device, "GetProperties", &error, + 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 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) { + gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL); + goto done; + } + + value = g_hash_table_lookup(hash, "Name"); + name = value ? g_value_get_string(value) : NULL; + if (!name) + name = address; + + __launch_system_popup(BT_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name, + str_passkey, NULL, + _gap_agent_get_path(agent)); + +done: + __bt_agent_release_memory(); + g_hash_table_destroy(hash); + + BT_DBG("-\n"); + + return TRUE; +} + +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); + + syspopup_destroy_all(); + + __bt_agent_release_memory(); + + return TRUE; +} + +static gboolean __authorize_request(GapAgent *agent, DBusGProxy *device, + const char *uuid) +{ + GHashTable *hash = NULL; + GValue *value; + const gchar *address; + const gchar *name; + gboolean trust; + gboolean paired; + GError *error = NULL; + int result = BLUETOOTH_ERROR_NONE; + int request_type = BT_AGENT_EVENT_AUTHORIZE_REQUEST; + + BT_DBG("+\n"); + + if (!strcasecmp(uuid, HFP_AUDIO_GATEWAY_UUID) || + !strcasecmp(uuid, A2DP_UUID) || + !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); + + goto done; + } + + dbus_g_proxy_call(device, "GetProperties", &error, 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 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, "Address"); + address = value ? g_value_get_string(value) : NULL; + if (!address) { + gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL); + goto done; + } + + value = g_hash_table_lookup(hash, "Alias"); + name = value ? g_value_get_string(value) : NULL; + if (!name) + name = address; + + value = g_hash_table_lookup(hash, "Trusted"); + trust = value ? g_value_get_boolean(value) : 0; + + 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"); + gap_agent_reply_authorize(agent, + GAP_AGENT_REJECT, NULL); + goto done; + } + + BT_DBG("Authorization request for device [%s] Service:[%s]\n", address, + uuid); + + if (strcasecmp(uuid, OPP_UUID) == 0 && + _gap_agent_exist_osp_server(agent, BT_OBEX_SERVER, + NULL) == TRUE) { + _bt_send_event(BT_OPP_SERVER_EVENT, + BLUETOOTH_EVENT_OBEX_SERVER_CONNECTION_AUTHORIZE, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_INVALID); + + goto done; + } + + 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_send_event(BT_RFCOMM_SERVER_EVENT, + BLUETOOTH_EVENT_RFCOMM_AUTHORIZE, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_STRING, &uuid, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_INT16, &server_info->control_fd, + DBUS_TYPE_INVALID); + + goto done; + } + + if (!strcasecmp(uuid, OPP_UUID)) + request_type = BT_AGENT_EVENT_EXCHANGE_REQUEST; + else if (!strcasecmp(uuid, PBAP_UUID)) + request_type = BT_AGENT_EVENT_PBAP_REQUEST; + else if (!strcasecmp(uuid, MAP_UUID)) + request_type = BT_AGENT_EVENT_MAP_REQUEST; + + if (trust) { + BT_DBG("Trusted device, so authorize\n"); + gap_agent_reply_authorize(agent, + GAP_AGENT_ACCEPT, NULL); + } else { + __launch_system_popup(request_type, name, NULL, NULL, + _gap_agent_get_path(agent)); + } + +done: + __bt_agent_release_memory(); + g_hash_table_destroy(hash); + + BT_DBG("-\n"); + + return TRUE; +} + +static gboolean __authorization_cancel_request(GapAgent *agent, + const char *address) +{ + BT_DBG("On Going Authorization is cancelled by remote\n"); + + gap_agent_reply_authorize(agent, GAP_AGENT_CANCEL, NULL); + + syspopup_destroy_all(); + + __bt_agent_release_memory(); + + return TRUE; +} + +void _bt_destroy_agent(void *agent) +{ + if (!agent) + return; + + _gap_agent_reset_dbus(agent); + + g_object_unref(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; + func_cb.confirm_func = __confirm_request; + func_cb.authorize_func = __authorize_request; + func_cb.pairing_cancel_func = __pairing_cancel_request; + func_cb.authorization_cancel_func = __authorization_cancel_request; + + agent = _gap_agent_new(); + + _gap_agent_setup_dbus(agent, &func_cb, path, adapter_proxy); + + if (adapter) { + if (!_gap_agent_register(agent)) { + _bt_destroy_agent(agent); + return NULL; + } + } + + return agent; +} + +gboolean _bt_agent_register_osp_server(const gint type, const char *uuid) +{ + void *agent = _bt_get_adapter_agent(); + if (!agent) + return FALSE; + + return _gap_agent_register_osp_server(agent, type, uuid); + +} + +gboolean _bt_agent_unregister_osp_server(const gint type, const char *uuid) +{ + void *agent = _bt_get_adapter_agent(); + if (!agent) + return FALSE; + + return _gap_agent_unregister_osp_server(agent, type, uuid); +} + +gboolean _bt_agent_reply_authorize(gboolean accept) +{ + guint accept_val; + + void *agent = _bt_get_adapter_agent(); + if (!agent) + return FALSE; + + accept_val = accept ? GAP_AGENT_ACCEPT : GAP_AGENT_REJECT; + + return gap_agent_reply_authorize(agent, accept_val, NULL); +} + +gboolean _bt_agent_is_canceled(void *agent) +{ + return _gap_agent_is_canceled(agent); +} + +static gboolean __bt_agent_is_hid_keyboard(uint32_t dev_class) +{ + switch ((dev_class & 0x1f00) >> 8) { + case 0x05: + switch ((dev_class & 0xc0) >> 6) { + case 0x01: + /* input-keyboard" */ + return TRUE; + } + break; + } + + return FALSE; +} + +static gboolean __bt_agent_find_device_by_address_exactname(char *buffer, + const char *address) +{ + char *pch; + char *last; + + pch = strtok_r(buffer, "= ,", &last); + + if (pch == NULL) + return FALSE; + + while ((pch = strtok_r(NULL, ",", &last))) { + if (0 == g_strcmp0(pch, address)) { + BT_DBG("Match found\n"); + return TRUE; + } + } + return FALSE; +} + +static gboolean __bt_agent_find_device_by_partial_name(char *buffer, + const char *partial_name) +{ + char *pch; + char *last; + + pch = strtok_r(buffer, "= ,", &last); + + if (pch == NULL) + return FALSE; + + while ((pch = strtok_r(NULL, ",", &last))) { + if (g_str_has_prefix(partial_name, pch)) { + BT_DBG("Match found\n"); + return TRUE; + } + } + return FALSE; +} + +static gboolean __bt_agent_is_device_blacklist(const char *address, + const char *name) +{ + char *buffer; + char **lines; + int i; + FILE *fp; + long size; + size_t result; + + BT_DBG("+ \n"); + + fp = fopen(BT_AGENT_AUTO_PAIR_BLACKLIST_FILE, "r"); + + if (fp == NULL) { + BT_DBG("fopen failed \n"); + return FALSE; + } + + fseek(fp, 0, SEEK_END); + size = ftell(fp); + if (size <= 0) { + BT_DBG("size is not a positive number"); + fclose(fp); + return FALSE; + } + + rewind(fp); + + buffer = g_malloc0(sizeof(char) * size); + result = fread((char *)buffer, 1, size, fp); + fclose(fp); + if (result != size) { + BT_DBG("Read Error\n"); + g_free(buffer); + return FALSE; + } + + BT_DBG("Buffer = %s\n", 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"); + return FALSE; + } + + for (i = 0; lines[i] != NULL; i++) { + if (g_str_has_prefix(lines[i], "AddressBlacklist")) + if (__bt_agent_find_device_by_address_exactname( + lines[i], address)) + goto done; + if (g_str_has_prefix(lines[i], "ExactNameBlacklist")) + if (__bt_agent_find_device_by_address_exactname( + lines[i], name)) + goto done; + if (g_str_has_prefix(lines[i], "PartialNameBlacklist")) + if (__bt_agent_find_device_by_partial_name(lines[i], + name)) + goto done; + } + g_strfreev(lines); + BT_DBG("- \n"); + return FALSE; +done: + BT_DBG("Found the device\n"); + g_strfreev(lines); + return TRUE; +} + +static gboolean __bt_agent_is_auto_response(uint32_t dev_class, + const gchar *address, const gchar *name) +{ + gboolean is_headset = FALSE; + char lap_address[BT_LOWER_ADDRESS_LENGTH]; + + BT_DBG("bt_agent_is_headset_class, %d +", dev_class); + + if (address == NULL) + return FALSE; + + switch ((dev_class & 0x1f00) >> 8) { + case 0x04: + switch ((dev_class & 0xfc) >> 2) { + case 0x01: + case 0x02: + /* Headset */ + is_headset = TRUE; + break; + case 0x06: + /* Headphone */ + is_headset = TRUE; + break; + case 0x0b: /* VCR */ + case 0x0c: /* Video Camera */ + case 0x0d: /* Camcorder */ + break; + default: + /* Other audio device */ + is_headset = TRUE; + break; + } + break; + } + + if (!is_headset) + return FALSE; + + /* Get the LAP(Lower Address part) */ + g_strlcpy(lap_address, address, sizeof(lap_address)); + + BT_DBG("Device address = %s\n", address); + 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"); + return FALSE; + } + + return TRUE; +} + +static int __bt_agent_generate_passkey(char *passkey, int size) +{ + int i; + ssize_t len; + int random_fd; + unsigned int value = 0; + + if (passkey == NULL) + return -1; + + if (size <= 0) + return -1; + + random_fd = open("/dev/urandom", O_RDONLY); + + if (random_fd < 0) + return -1; + + for (i = 0; i < size - 1; i++) { + len = read(random_fd, &value, sizeof(value)); + passkey[i] = '0' + (value % 10); + } + + close(random_fd); + + passkey[size - 1] = '\0'; + + BT_DBG("passkey: %s", passkey); + + return 0; +} diff --git a/bt-service/bt-service-audio.c b/bt-service/bt-service-audio.c new file mode 100644 index 0000000..ef41cc0 --- /dev/null +++ b/bt-service/bt-service-audio.c @@ -0,0 +1,445 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "bluetooth-api.h" +#include "bt-internal-types.h" + +#include "bt-service-audio.h" +#include "bt-service-adapter.h" +#include "bt-service-common.h" +#include "bt-service-event.h" +#include "bt-service-util.h" + +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_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; + } + + 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) { + BT_ERR("Audio Connect Dbus Call Error: %s\n", g_error->message); + result = BLUETOOTH_ERROR_INTERNAL; + goto dbus_return; + } + + /* Event will be sent by the event reciever */ +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); + } +} + +static char *__bt_get_audio_path(bluetooth_device_address_t *address) +{ + + char *object_path = NULL; + char addr_str[BT_ADDRESS_STRING_SIZE + 1] = { 0 }; + DBusGProxy *audio_proxy; + DBusGProxy *adapter_proxy; + DBusGConnection *g_conn; + GError *error = NULL; + + retv_if(address == NULL, NULL); + + g_conn = _bt_get_system_gconn(); + retv_if(g_conn == NULL, NULL); + + adapter_proxy = _bt_get_adapter_proxy(); + retv_if(adapter_proxy == NULL, NULL); + + _bt_convert_addr_type_to_string(addr_str, address->addr); + + 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, NULL); + + audio_proxy = dbus_g_proxy_new_for_name(g_conn, + BT_BLUEZ_NAME, + object_path, + BT_HEADSET_INTERFACE); + retv_if(audio_proxy == NULL, NULL); + + g_object_unref(audio_proxy); + + return object_path; +} + +static char *__bt_get_connected_audio_path(void) +{ + int i; + guint size; + char *audio_path = NULL; + GArray *device_list; + bluetooth_device_info_t info; + + /* allocate the g_pointer_array */ + 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 NULL; + } + + size = device_list->len; + 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) { + audio_path = __bt_get_audio_path(&info.device_address); + if (audio_path) + break; + } + } + + g_array_free(device_list, TRUE); + + return audio_path; +} + +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 *interface; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + bt_function_data_t *func_data; + DBusGProxy *adapter_proxy; + DBusGProxy *profile_proxy; + DBusGConnection *g_conn; + + BT_CHECK_PARAMETER(device_address); + + _bt_convert_addr_type_to_string(address, device_address->addr); + + switch (type) { + case BT_AUDIO_HSP: + interface = BT_HEADSET_INTERFACE; + break; + case BT_AUDIO_A2DP: + interface = BT_SINK_INTERFACE; + break; + case BT_AUDIO_ALL: + interface = BT_AUDIO_INTERFACE; + break; + default: + BT_ERR("Unknown role"); + result = BLUETOOTH_ERROR_INTERNAL; + goto fail; + } + + adapter_proxy = _bt_get_adapter_proxy(); + if (adapter_proxy == NULL) { + result = BLUETOOTH_ERROR_INTERNAL; + goto fail; + } + + g_conn = _bt_get_system_gconn(); + if (g_conn == NULL) { + result = BLUETOOTH_ERROR_INTERNAL; + goto fail; + } + + dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL, + G_TYPE_STRING, address, G_TYPE_INVALID, + DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID); + + if (device_path == NULL) { + BT_ERR("No paired device"); + result = BLUETOOTH_ERROR_NOT_PAIRED; + goto fail; + } + + profile_proxy = dbus_g_proxy_new_for_name(g_conn, BT_BLUEZ_NAME, + device_path, 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; + + 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); + + g_free(func_data->address); + g_free(func_data); + + result = BLUETOOTH_ERROR_INTERNAL; + goto fail; + } + + return BLUETOOTH_ERROR_NONE; +fail: + g_array_append_vals(*out_param1, address, + BT_ADDRESS_STR_LEN); + + return result; +} + +int _bt_audio_disconnect(int request_id, int type, + bluetooth_device_address_t *device_address, + GArray **out_param1) +{ + int result = BLUETOOTH_ERROR_NONE; + gchar *device_path = NULL; + char *interface; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + bt_function_data_t *func_data; + DBusGProxy *adapter_proxy; + DBusGProxy *profile_proxy; + DBusGConnection *g_conn; + + BT_CHECK_PARAMETER(device_address); + + _bt_convert_addr_type_to_string(address, device_address->addr); + + switch (type) { + case BT_AUDIO_HSP: + interface = BT_HEADSET_INTERFACE; + break; + case BT_AUDIO_A2DP: + interface = BT_SINK_INTERFACE; + break; + case BT_AUDIO_ALL: + interface = BT_AUDIO_INTERFACE; + 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; + } + + g_conn = _bt_get_system_gconn(); + if (g_conn == NULL) { + result = BLUETOOTH_ERROR_INTERNAL; + goto fail; + } + + dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL, + G_TYPE_STRING, address, G_TYPE_INVALID, + DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID); + + if (device_path == NULL) { + BT_ERR("No paired device"); + result = BLUETOOTH_ERROR_NOT_PAIRED; + goto fail; + } + + profile_proxy = dbus_g_proxy_new_for_name(g_conn, BT_BLUEZ_NAME, + device_path, 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; + + 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; + } + + return BLUETOOTH_ERROR_NONE; +fail: + g_array_append_vals(*out_param1, address, + BT_ADDRESS_STR_LEN); + + return result; +} + +int _bt_audio_get_speaker_gain(unsigned int *gain) +{ + char *device_path = NULL; + DBusGProxy *adapter_proxy; + DBusGProxy *profile_proxy; + DBusGConnection *g_conn; + GHashTable *hash = NULL; + GValue *value; + + 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); + + device_path = __bt_get_connected_audio_path(); + 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_HEADSET_INTERFACE); + + g_free(device_path); + + retv_if(profile_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call(profile_proxy, "GetProperties", NULL, + G_TYPE_INVALID, + dbus_g_type_get_map("GHashTable", + G_TYPE_STRING, G_TYPE_VALUE), + &hash, G_TYPE_INVALID); + + g_object_unref(profile_proxy); + + retv_if(hash == NULL, BLUETOOTH_ERROR_INTERNAL); + + value = g_hash_table_lookup(hash, "SpeakerGain"); + *gain = value ? g_value_get_uint(value) : 0; + g_hash_table_destroy(hash); + return BLUETOOTH_ERROR_NONE; +} + +int _bt_audio_set_speaker_gain(unsigned int gain) +{ + char *device_path = NULL; + char *gain_str = "SpeakerGain"; + char sig[2] = {DBUS_TYPE_UINT16, '\0'}; + int ret = BLUETOOTH_ERROR_NONE; + DBusMessage *msg; + DBusMessageIter iter; + DBusMessageIter value; + DBusConnection *conn; + + conn = _bt_get_system_conn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + device_path = __bt_get_connected_audio_path(); + retv_if(device_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED); + + msg = dbus_message_new_method_call(BT_BLUEZ_NAME, + device_path, BT_HEADSET_INTERFACE, + "SetProperty"); + + g_free(device_path); + + retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_message_iter_init_append(msg, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, + &gain_str); + dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, + sig, &value); + dbus_message_iter_append_basic(&value, DBUS_TYPE_UINT16, + &gain); + dbus_message_iter_close_container(&iter, &value); + + if (dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_METHOD_CALL) + dbus_message_set_no_reply(msg, TRUE); + + if (!dbus_connection_send(conn, msg, NULL)) { + BT_ERR("Dbus sending failed\n"); + ret = BLUETOOTH_ERROR_INTERNAL; + } + dbus_message_unref(msg); + + return ret; +} diff --git a/bt-service/bt-service-avrcp.c b/bt-service/bt-service-avrcp.c new file mode 100644 index 0000000..19b85af --- /dev/null +++ b/bt-service/bt-service-avrcp.c @@ -0,0 +1,758 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "bluetooth-api.h" +#include "bt-internal-types.h" + +#include "bt-service-common.h" +#include "bt-service-avrcp.h" +#include "bt-service-event.h" +#include "bt-service-util.h" + +struct player_settinngs_t { + int key; + const char *property; +}; + +static struct player_settinngs_t equalizer_settings[] = { + { EQUALIZER_INVALID, "" }, + { EQUALIZER_OFF, "off" }, + { EQUALIZER_ON, "on" }, + { EQUALIZER_INVALID, "" } +}; + +static struct player_settinngs_t repeat_settings[] = { + { REPEAT_INVALID, "" }, + { REPEAT_MODE_OFF, "off" }, + { REPEAT_SINGLE_TRACK, "singletrack" }, + { REPEAT_ALL_TRACK, "alltracks" }, + { REPEAT_GROUP, "group" }, + { REPEAT_INVALID, "" } +}; + +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 scan_settings[] = { + { SCAN_INVALID, "" }, + { SCAN_MODE_OFF, "off" }, + { SCAN_ALL_TRACK, "alltracks" }, + { SCAN_GROUP, "group" }, + { SCAN_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, "" } +}; + +typedef struct { + GObject parent; +} BtMediaAgent; + +typedef struct { + GObjectClass parent; +} BtMediaAgentClass; + +GType bt_media_agent_get_type(void); + +#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) +{ + GError *error; + const gchar *value; + unsigned int status; + + BT_DBG("property %s\n", property); + + if (!(G_VALUE_TYPE (val) == G_TYPE_STRING)) { + error = bt_media_agent_error( + BT_MEDIA_AGENT_ERROR_INVALID_PARAM, + "Invalid Arguments"); + dbus_g_method_return_error(context, error); + g_error_free(error); + return FALSE; + } + value = g_value_get_string (val); + BT_DBG("value %s\n", value); + + if (g_strcmp0(property, "Shuffle") == 0) { + if (g_strcmp0(value, "alltracks") == 0) + status = SHUFFLE_ALL_TRACK; + else if (g_strcmp0(value, "group") == 0) + status = SHUFFLE_GROUP; + 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); + + } else if (g_strcmp0(property, "Equalizer") == 0) { + status = (g_strcmp0(value, "off") == 0) ? EQUALIZER_OFF : EQUALIZER_ON; + + _bt_send_event(BT_AVRCP_EVENT, + BLUETOOTH_EVENT_AVRCP_SETTING_EQUALIZER_STATUS, + DBUS_TYPE_UINT32, &status, + DBUS_TYPE_INVALID); + + } else if (g_strcmp0(property, "Repeat") == 0) { + 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, "group") == 0) + status = REPEAT_GROUP; + 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); + } else if (g_strcmp0(property, "Scan") == 0) { + if (g_strcmp0(value, "alltracks") == 0) + status = SCAN_ALL_TRACK; + else if (g_strcmp0(value, "group") == 0) + status = SCAN_GROUP; + else if (g_strcmp0(value, "off") == 0) + status = SCAN_MODE_OFF; + else + status = SCAN_INVALID; + + _bt_send_event(BT_AVRCP_EVENT, + BLUETOOTH_EVENT_AVRCP_SETTING_SCAN_STATUS, + DBUS_TYPE_UINT32, &status, + DBUS_TYPE_INVALID); + } + dbus_g_method_return(context); + return TRUE; + +} + +static void __bt_media_append_variant(DBusMessageIter *iter, + int type, void *value) +{ + const char *sig; + DBusMessageIter value_iter; + + switch (type) { + case DBUS_TYPE_BOOLEAN: + sig = DBUS_TYPE_BOOLEAN_AS_STRING; + break; + case DBUS_TYPE_STRING: + sig = DBUS_TYPE_STRING_AS_STRING; + break; + case DBUS_TYPE_BYTE: + sig = DBUS_TYPE_BYTE_AS_STRING; + break; + case DBUS_TYPE_UINT16: + sig = DBUS_TYPE_UINT16_AS_STRING; + break; + case DBUS_TYPE_UINT32: + sig = DBUS_TYPE_UINT32_AS_STRING; + break; + case DBUS_TYPE_INT16: + sig = DBUS_TYPE_INT16_AS_STRING; + break; + case DBUS_TYPE_INT32: + sig = DBUS_TYPE_INT32_AS_STRING; + break; + case DBUS_TYPE_OBJECT_PATH: + sig = DBUS_TYPE_OBJECT_PATH_AS_STRING; + break; + default: + sig = DBUS_TYPE_VARIANT_AS_STRING; + break; + } + + dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, sig, + &value_iter); + + dbus_message_iter_append_basic(&value_iter, type, value); + + dbus_message_iter_close_container(iter, &value_iter); +} + +static gboolean __bt_media_emit_property_changed( + DBusConnection *connection, + const char *path, + const char *interface, + const char *name, + int type, + void *property) +{ + DBusMessage *sig; + DBusMessageIter entry; + gboolean ret; + + sig = dbus_message_new_signal(path, interface, + "PropertyChanged"); + retv_if(sig == NULL, FALSE); + + dbus_message_iter_init_append(sig, &entry); + dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &name); + + __bt_media_append_variant(&entry, type, property); + + ret = dbus_connection_send(connection, sig, NULL); + dbus_message_unref(sig); + + return ret; +} + +static void __bt_media_append_dict_entry(DBusMessageIter *iter, + const char *key, int type, void *property) +{ + DBusMessageIter dict_entry; + const char *str_ptr; + + if (type == DBUS_TYPE_STRING) { + str_ptr = *((const char **)property); + ret_if(str_ptr == NULL); + } + + dbus_message_iter_open_container(iter, + DBUS_TYPE_DICT_ENTRY, + NULL, &dict_entry); + + dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &key); + + __bt_media_append_variant(&dict_entry, type, property); + + dbus_message_iter_close_container(iter, &dict_entry); +} + +int _bt_register_media_player(void) +{ + DBusMessage *msg; + DBusMessage *reply; + DBusMessageIter iter; + DBusMessageIter property_dict; + DBusMessageIter metadata_dict; + DBusError err; + char *object; + char *adapter_path; + DBusConnection *conn; + DBusGConnection *gconn; + + media_player_settings_t player_settings = {0,}; + media_metadata_attributes_t metadata = {0,}; + + player_settings.equalizer = EQUALIZER_OFF; + player_settings.repeat = REPEAT_MODE_OFF; + player_settings.shuffle = SHUFFLE_MODE_OFF; + player_settings.scan = SCAN_MODE_OFF; + player_settings.status = STATUS_STOPPED; + player_settings.position = 0; + + metadata.title = "\0"; + metadata.artist = "\0"; + metadata.album = "\0"; + metadata.genre = "\0"; + metadata.total_tracks = 0; + metadata.number = 0; + metadata.duration = 0; + + gconn = _bt_get_system_gconn(); + retv_if(gconn == NULL, BLUETOOTH_ERROR_INTERNAL); + + conn = _bt_get_system_conn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + 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)); + } + + 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"); + + g_free(adapter_path); + + retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL); + + object = g_strdup(BT_MEDIA_OBJECT_PATH); + + dbus_message_iter_init_append(msg, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &object); + g_free(object); + + 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); + + __bt_media_append_dict_entry(&property_dict, + "Equalizer", + DBUS_TYPE_STRING, + &equalizer_settings[player_settings.equalizer].property); + + __bt_media_append_dict_entry(&property_dict, + "Repeat", + DBUS_TYPE_STRING, + &repeat_settings[player_settings.repeat].property); + + __bt_media_append_dict_entry(&property_dict, + "Shuffle", + DBUS_TYPE_STRING, + &shuffle_settings[player_settings.shuffle].property); + + __bt_media_append_dict_entry(&property_dict, + "Scan", + DBUS_TYPE_STRING, + &scan_settings[player_settings.scan].property); + + __bt_media_append_dict_entry(&property_dict, + "Status", + DBUS_TYPE_STRING, + &player_status[player_settings.status].property); + + __bt_media_append_dict_entry(&property_dict, + "Position", + DBUS_TYPE_UINT32, &player_settings.position); + + dbus_message_iter_close_container(&iter, &property_dict); + + dbus_message_iter_init_append(msg, &iter); + 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, &metadata_dict); + + __bt_media_append_dict_entry(&metadata_dict, + "Title", + DBUS_TYPE_STRING, &metadata.title); + + __bt_media_append_dict_entry(&metadata_dict, + "Artist", + DBUS_TYPE_STRING, &metadata.artist); + + __bt_media_append_dict_entry(&metadata_dict, + "Album", + DBUS_TYPE_STRING, &metadata.album); + + __bt_media_append_dict_entry(&metadata_dict, + "Genre", + DBUS_TYPE_STRING, &metadata.genre); + + __bt_media_append_dict_entry(&metadata_dict, + "NumberOfTracks", + DBUS_TYPE_UINT32, &metadata.total_tracks); + + __bt_media_append_dict_entry(&metadata_dict, + "Number", + DBUS_TYPE_UINT32, &metadata.number); + + __bt_media_append_dict_entry(&metadata_dict, + "Duration", + DBUS_TYPE_UINT32, &metadata.duration); + + dbus_message_iter_close_container(&iter, &metadata_dict); + + 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 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); + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_unregister_media_player(void) +{ + DBusMessage *msg; + DBusMessage *reply; + DBusError err; + char *object; + char *adapter_path; + DBusConnection *conn; + + conn = _bt_get_system_conn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + 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, "UnregisterPlayer"); + + retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL); + + object = g_strdup(BT_MEDIA_OBJECT_PATH); + + dbus_message_append_args(msg, + DBUS_TYPE_OBJECT_PATH, &object, + DBUS_TYPE_INVALID); + + g_free(object); + + 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 in unregistering the Music Player \n"); + + if (dbus_error_is_set(&err)) { + BT_DBG("%s", err.message); + dbus_error_free(&err); + return BLUETOOTH_ERROR_INTERNAL; + } + } else { + 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; + } + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_avrcp_set_track_info(media_metadata_attributes_t *meta_data) +{ + DBusMessage *signal; + DBusMessageIter iter; + DBusMessageIter metadata_dict; + DBusConnection *conn; + + retv_if(meta_data == NULL, BLUETOOTH_ERROR_INTERNAL); + + conn = _bt_get_system_conn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + signal = dbus_message_new_signal(BT_MEDIA_OBJECT_PATH, + BT_MEDIA_PLAYER_INTERFACE, "TrackChanged"); + + retv_if(signal == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_message_iter_init_append(signal, &iter); + + 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, &metadata_dict); + + if (meta_data->title) { + __bt_media_append_dict_entry(&metadata_dict, + "Title", + DBUS_TYPE_STRING, &meta_data->title); + } + + if (meta_data->artist) { + __bt_media_append_dict_entry(&metadata_dict, + "Artist", + DBUS_TYPE_STRING, &meta_data->artist); + } + + if (meta_data->album) { + __bt_media_append_dict_entry(&metadata_dict, + "Album", + DBUS_TYPE_STRING, &meta_data->album); + } + + if (meta_data->genre) { + __bt_media_append_dict_entry(&metadata_dict, + "Genre", + DBUS_TYPE_STRING, &meta_data->genre); + } + + if (0 != meta_data->total_tracks) + __bt_media_append_dict_entry(&metadata_dict, + "NumberOfTracks", + DBUS_TYPE_UINT32, &meta_data->total_tracks); + + if (0 != meta_data->number) + __bt_media_append_dict_entry(&metadata_dict, + "Number", + DBUS_TYPE_UINT32, &meta_data->number); + + if (0 != meta_data->duration) + __bt_media_append_dict_entry(&metadata_dict, + "Duration", + DBUS_TYPE_UINT32, &meta_data->duration); + + dbus_message_iter_close_container(&iter, &metadata_dict); + + if (!dbus_connection_send(conn, signal, NULL)) + BT_ERR("Unable to send TrackChanged signal\n"); + + dbus_message_unref(signal); + + return BLUETOOTH_ERROR_NONE; +} + + +int _bt_avrcp_set_properties(media_player_settings_t *properties) +{ + if (_bt_avrcp_set_property(EQUALIZER, + properties->equalizer) != BLUETOOTH_ERROR_NONE) { + return BLUETOOTH_ERROR_INTERNAL; + } + + if (_bt_avrcp_set_property(REPEAT, + properties->repeat) != BLUETOOTH_ERROR_NONE) { + return BLUETOOTH_ERROR_INTERNAL; + } + + if (_bt_avrcp_set_property(SHUFFLE, + properties->shuffle) != BLUETOOTH_ERROR_NONE) { + return BLUETOOTH_ERROR_INTERNAL; + } + + if (_bt_avrcp_set_property(SCAN, + properties->scan) != BLUETOOTH_ERROR_NONE) { + return BLUETOOTH_ERROR_INTERNAL; + } + + if (_bt_avrcp_set_property(STATUS, + properties->status) != BLUETOOTH_ERROR_NONE) { + return BLUETOOTH_ERROR_INTERNAL; + } + + if (_bt_avrcp_set_property(POSITION, + properties->position) != BLUETOOTH_ERROR_NONE) { + return BLUETOOTH_ERROR_INTERNAL; + } + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_avrcp_set_property(int type, unsigned int value) +{ + DBusConnection *conn; + + conn = _bt_get_system_conn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + switch (type) { + case EQUALIZER: + if (!__bt_media_emit_property_changed( + conn, + BT_MEDIA_OBJECT_PATH, + BT_MEDIA_PLAYER_INTERFACE, + "Equalizer", + DBUS_TYPE_STRING, + &equalizer_settings[value].property)) { + BT_ERR("Error sending the PropertyChanged signal \n"); + return BLUETOOTH_ERROR_INTERNAL; + } + break; + case REPEAT: + if (!__bt_media_emit_property_changed( + conn, + BT_MEDIA_OBJECT_PATH, + BT_MEDIA_PLAYER_INTERFACE, + "Repeat", + DBUS_TYPE_STRING, + &repeat_settings[value].property)) { + BT_ERR("Error sending the PropertyChanged signal \n"); + return BLUETOOTH_ERROR_INTERNAL; + } + break; + case SHUFFLE: + if (!__bt_media_emit_property_changed( + conn, + BT_MEDIA_OBJECT_PATH, + BT_MEDIA_PLAYER_INTERFACE, + "Shuffle", + DBUS_TYPE_STRING, + &shuffle_settings[value].property)) { + BT_ERR("Error sending the PropertyChanged signal \n"); + return BLUETOOTH_ERROR_INTERNAL; + } + break; + case SCAN: + if (!__bt_media_emit_property_changed( + conn, + BT_MEDIA_OBJECT_PATH, + BT_MEDIA_PLAYER_INTERFACE, + "Scan", + DBUS_TYPE_STRING, + &scan_settings[value].property)) { + BT_ERR("Error sending the PropertyChanged signal \n"); + return BLUETOOTH_ERROR_INTERNAL; + } + break; + case STATUS: + if (!__bt_media_emit_property_changed( + conn, + BT_MEDIA_OBJECT_PATH, + BT_MEDIA_PLAYER_INTERFACE, + "Status", + DBUS_TYPE_STRING, + &player_status[value].property)) { + BT_ERR("Error sending the PropertyChanged signal \n"); + return BLUETOOTH_ERROR_INTERNAL; + } + break; + case POSITION: + if (!__bt_media_emit_property_changed( + conn, + BT_MEDIA_OBJECT_PATH, + BT_MEDIA_PLAYER_INTERFACE, + "Position", + DBUS_TYPE_UINT32, + &value)) { + BT_ERR("Error sending the PropertyChanged signal \n"); + return BLUETOOTH_ERROR_INTERNAL; + } + break; + default: + BT_ERR("Invalid Type\n"); + return BLUETOOTH_ERROR_INTERNAL; + } + + return BLUETOOTH_ERROR_NONE; +} + diff --git a/bt-service/bt-service-common.c b/bt-service/bt-service-common.c new file mode 100644 index 0000000..109babe --- /dev/null +++ b/bt-service/bt-service-common.c @@ -0,0 +1,389 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "bluetooth-api.h" +#include "bt-service-common.h" +#include "bt-service-agent.h" + +static DBusGConnection *system_conn; +static DBusGConnection *session_conn; +static DBusGProxy *manager_proxy; +static DBusGProxy *adapter_proxy; + +static DBusGProxy *__bt_init_manager_proxy(void) +{ + DBusGProxy *proxy; + + g_type_init(); + + if (system_conn == NULL) { + system_conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL); + retv_if(system_conn == NULL, NULL); + } + + proxy = dbus_g_proxy_new_for_name(system_conn, BT_BLUEZ_NAME, + BT_MANAGER_PATH, BT_MANAGER_INTERFACE); + + retv_if(proxy == NULL, NULL); + + manager_proxy = proxy; + + return proxy; +} + +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); + retv_if(system_conn == NULL, NULL); + } + + manager_proxy = _bt_get_manager_proxy(); + retv_if(manager_proxy == NULL, NULL); + + if (!dbus_g_proxy_call(manager_proxy, "DefaultAdapter", NULL, + G_TYPE_INVALID, DBUS_TYPE_G_OBJECT_PATH, + &adapter_path, G_TYPE_INVALID)) { + BT_ERR("Fait to get DefaultAdapter"); + return NULL; + } + + adapter_path = g_strdup(adapter_path); + retv_if(adapter_path == NULL, NULL); + + proxy = dbus_g_proxy_new_for_name(system_conn, BT_BLUEZ_NAME, + adapter_path, BT_ADAPTER_INTERFACE); + + g_free(adapter_path); + + retv_if(proxy == NULL, NULL); + + adapter_proxy = proxy; + + return proxy; +} + +DBusGConnection *__bt_init_system_gconn(void) +{ + g_type_init(); + + if (system_conn == NULL) + system_conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL); + + return system_conn; +} + +DBusGConnection *__bt_init_session_conn(void) +{ + if (session_conn == NULL) + session_conn = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); + + return session_conn; +} + +DBusGConnection *_bt_get_session_gconn(void) +{ + return (session_conn) ? session_conn : __bt_init_session_conn(); +} + +DBusGConnection *_bt_get_system_gconn(void) +{ + return (system_conn) ? system_conn : __bt_init_system_gconn(); +} + +DBusConnection *_bt_get_system_conn(void) +{ + DBusGConnection *g_conn; + + if (system_conn == NULL) { + g_conn = __bt_init_system_gconn(); + } else { + g_conn = system_conn; + } + + retv_if(g_conn == NULL, NULL); + + return dbus_g_connection_get_connection(g_conn); +} + +DBusGProxy *_bt_get_manager_proxy(void) +{ + return (manager_proxy) ? manager_proxy : __bt_init_manager_proxy(); +} + +DBusGProxy *_bt_get_adapter_proxy(void) +{ + return (adapter_proxy) ? adapter_proxy : __bt_init_adapter_proxy(); +} + +char *_bt_get_adapter_path(void) +{ + char *adapter_path = NULL; + DBusGProxy *proxy; + GError *err = NULL; + + proxy = _bt_get_manager_proxy(); + + if (!dbus_g_proxy_call(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); + } + return NULL; + } + + return adapter_path; +} + +void _bt_deinit_bluez_proxy(void) +{ + if (manager_proxy) { + g_object_unref(manager_proxy); + manager_proxy = NULL; + } + + if (adapter_proxy) { + g_object_unref(adapter_proxy); + adapter_proxy = NULL; + } +} + +void _bt_deinit_proxys(void) +{ + + _bt_deinit_bluez_proxy(); + + if (system_conn) { + dbus_g_connection_unref(system_conn); + system_conn = NULL; + } + + if (session_conn) { + dbus_g_connection_unref(session_conn); + session_conn = NULL; + } + +} + +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); + } +} + + +void _bt_convert_addr_string_to_type(unsigned char *addr, + const char *address) +{ + int i; + char *ptr = NULL; + + ret_if(address == NULL); + ret_if(addr == NULL); + + for (i = 0; i < BT_ADDRESS_LENGTH_MAX; i++) { + addr[i] = strtol(address, &ptr, 16); + if (ptr != NULL) { + if (ptr[0] != ':') + return; + + address = ptr + 1; + } + } +} + +void _bt_convert_addr_type_to_string(char *address, + unsigned char *addr) +{ + ret_if(address == NULL); + ret_if(addr == NULL); + + snprintf(address, BT_ADDRESS_STRING_SIZE, + "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", + addr[0], addr[1], addr[2], + addr[3], addr[4], addr[5]); +} + +void _bt_print_device_address_t(const bluetooth_device_address_t *addr) +{ + BT_DBG("%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", addr->addr[0], addr->addr[1], addr->addr[2], + addr->addr[3], addr->addr[4], addr->addr[5]); +} + +void _bt_divide_device_class(bluetooth_device_class_t *device_class, + unsigned int cod) +{ + ret_if(device_class == NULL); + + device_class->major_class = (unsigned short)(cod & 0x00001F00) >> 8; + device_class->minor_class = (unsigned short)((cod & 0x000000FC)); + device_class->service_class = (unsigned long)((cod & 0x00FF0000)); + + if (cod & 0x002000) { + device_class->service_class |= + BLUETOOTH_DEVICE_SERVICE_CLASS_LIMITED_DISCOVERABLE_MODE; + } +} + +void _bt_free_device_info(bt_remote_dev_info_t *dev_info) +{ + int i; + + ret_if(dev_info == NULL); + + g_free(dev_info->address); + g_free(dev_info->name); + + if (dev_info->uuids) { + for (i = 0; dev_info->uuids[i] != NULL; i++) + g_free(dev_info->uuids[i]); + + g_free(dev_info->uuids); + } + + g_free(dev_info); +} + +int _bt_register_osp_server_in_agent(int type, char *uuid) +{ + if (!_bt_agent_register_osp_server( type, uuid)) + return BLUETOOTH_ERROR_INTERNAL; + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_unregister_osp_server_in_agent(int type, char *uuid) +{ + if (!_bt_agent_unregister_osp_server( type, uuid)) + return BLUETOOTH_ERROR_INTERNAL; + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_set_socket_non_blocking(int socket_fd) +{ + /* Set Nonblocking */ + long arg; + + arg = fcntl(socket_fd, F_GETFL); + + if (arg < 0) + return -errno; + + if (arg & O_NONBLOCK) { + BT_ERR("Already Non-blocking \n"); + } + + arg |= O_NONBLOCK; + + if (fcntl(socket_fd, F_SETFL, arg) < 0) + return -errno; + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_set_non_blocking_tty(int sk) +{ + struct termios ti = {0,}; + int err; + + err = _bt_set_socket_non_blocking(sk); + + if (err < 0) { + BT_ERR("Error in set non blocking!\n"); + return err; + } + + tcflush(sk, TCIOFLUSH); + + /* Switch tty to RAW mode */ + cfmakeraw(&ti); + tcsetattr(sk, TCSANOW, &ti); + + 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; +} + diff --git a/bt-service/bt-service-device.c b/bt-service/bt-service-device.c new file mode 100644 index 0000000..88183bf --- /dev/null +++ b/bt-service/bt-service-device.c @@ -0,0 +1,1328 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "bluetooth-api.h" +#include "bt-internal-types.h" + +#include "bt-service-common.h" +#include "bt-service-event.h" +#include "bt-service-device.h" +#include "bt-service-rfcomm-client.h" +#include "bt-service-util.h" +#include "bt-service-agent.h" + +typedef struct { + int req_id; + char *addr; + gboolean is_autopair; + DBusGProxy *device_proxy; + DBusGProxy *adapter_proxy; + void *agent; +} bt_funcion_data_t; + +gboolean is_deivce_creating; +bt_funcion_data_t *bonding_info; +bt_funcion_data_t *searching_info; + +/* This HID Mouse does not support pairing precedure. need to skip it. */ +#define SMB_MOUSE_LAP_ADDR "00:12:A1" + +static void __bt_bond_device_cb(DBusGProxy *proxy, DBusGProxyCall *call, + gpointer user_data); + + +gboolean _bt_is_device_creating(void) +{ + return is_deivce_creating; +} + +void _bt_set_autopair_status_in_bonding_info(gboolean is_autopair) +{ + ret_if(bonding_info == NULL); + bonding_info->is_autopair = is_autopair; +} + +void _bt_device_path_to_address(const char *device_path, + char *device_address) +{ + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + char *dev_addr; + char *pos; + + ret_if(device_path == NULL); + ret_if(device_address == NULL); + + dev_addr = strstr(device_path, "dev_"); + ret_if(dev_addr == 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); +} + +void __bt_cancel_search_service_done(void) +{ + int result = BLUETOOTH_ERROR_CANCEL_BY_USER; + request_info_t *req_info; + bluetooth_device_info_t dev_info; + GArray *out_param1; + GArray *out_param2; + + ret_if(searching_info == NULL); + + req_info = _bt_get_request_info(searching_info->req_id); + if (req_info == NULL) { + BT_ERR("req_info == NULL"); + goto done; + } + + 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 (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); + searching_info = NULL; +} + +static void __bt_get_uuids(GValue *value, bt_remote_dev_info_t *info) +{ + int i = 0; + char **uuid_value; + + ret_if(value == NULL); + ret_if(info == NULL); + + info->uuid_count = 0; + + uuid_value = g_value_get_boxed(value); + ret_if(uuid_value == NULL); + + while (uuid_value[i]) { + i++; + } + ret_if(i == 0); + + info->uuid_count = i; + + info->uuids = g_new0(char *, info->uuid_count + 1); + + for (i = 0; uuid_value[i] != NULL; i++) { + info->uuids[i] = g_strdup(uuid_value[i]); + } +} + +bt_remote_dev_info_t *_bt_get_remote_device_info(char *address) +{ + bt_remote_dev_info_t *dev_info; + char *object_path = NULL; + DBusGProxy *adapter_proxy; + DBusGProxy *device_proxy; + GHashTable *hash = NULL; + GValue *value; + const gchar *name; + DBusGConnection *conn; + + retv_if(address == NULL, NULL); + + adapter_proxy = _bt_get_adapter_proxy(); + retv_if(adapter_proxy == NULL, NULL); + + dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL, + G_TYPE_STRING, address, G_TYPE_INVALID, + DBUS_TYPE_G_OBJECT_PATH, &object_path, + G_TYPE_INVALID); + + retv_if(object_path == NULL, NULL); + + conn = _bt_get_system_gconn(); + if (conn == NULL) { + BT_ERR("conn == NULL"); + g_free(object_path); + return NULL; + } + + device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + object_path, BT_DEVICE_INTERFACE); + g_free(object_path); + retv_if(device_proxy == NULL, NULL); + + dbus_g_proxy_call(device_proxy, "GetProperties", NULL, + G_TYPE_INVALID, + dbus_g_type_get_map("GHashTable", G_TYPE_STRING, + G_TYPE_VALUE), &hash, G_TYPE_INVALID); + + g_object_unref(device_proxy); + + dev_info = g_malloc0(sizeof(bt_remote_dev_info_t)); + + if (hash != NULL) { + value = g_hash_table_lookup(hash, "Alias"); + name = value ? g_value_get_string(value) : NULL; + + if (name != NULL) + BT_DBG("Alias Name [%s]", name); + else { + value = g_hash_table_lookup(hash, "Name"); + name = value ? g_value_get_string(value) : NULL; + } + + value = g_hash_table_lookup(hash, "Class"); + dev_info->class = value ? g_value_get_uint(value) : 0; + + value = g_hash_table_lookup(hash, "Connected"); + dev_info->connected = value ? g_value_get_boolean(value) : FALSE; + + value = g_hash_table_lookup(hash, "Trusted"); + dev_info->trust = value ? g_value_get_boolean(value) : FALSE; + + value = g_hash_table_lookup(hash, "RSSI"); + dev_info->rssi = value ? g_value_get_int(value) : 0; + + value = g_hash_table_lookup(hash, "UUIDs"); + __bt_get_uuids(value, dev_info); + + dev_info->address = g_strdup(address); + dev_info->name = g_strdup(name); + dev_info->paired = TRUE; + g_hash_table_destroy(hash); + } else { + BT_ERR("Hash is NULL\n"); + g_free(dev_info); + dev_info = NULL; + } + + return dev_info; +} + +static gboolean __ignore_auto_pairing_request(const char *address) +{ + gchar *buffer; + char **lines; + int i; + char lap_address[BT_LOWER_ADDRESS_LENGTH + 1] = {0,}; + char *temp_buffer; + FILE *fp; + long size; + size_t result; + + BT_DBG("+\n"); + + if (address == NULL) + return FALSE; + + /* Get the LAP(Lower Address part) */ + /* User BT_LOWER_ADDRESS_LENGTH+1 for lap_address to accomodate + a "," */ + snprintf(lap_address, sizeof(lap_address), ",%s", address); + + fp = fopen(BT_AGENT_AUTO_PAIR_BLACKLIST_FILE, "r"); + + if (fp == NULL) { + BT_DBG("fopen failed \n"); + return FALSE; + } + + fseek(fp, 0, SEEK_END); + size = ftell(fp); + rewind(fp); + + if (size < 0) { + BT_DBG("Get file size failed \n"); + fclose(fp); + return FALSE; + } + + buffer = g_malloc0(sizeof(char) * size); + result = fread((char *)buffer, 1, size, fp); + fclose(fp); + if (result != size) { + BT_DBG("Read Error\n"); + g_free(buffer); + return FALSE; + } + + BT_DBG("Buffer = %s\n", buffer); + + lines = g_strsplit_set(buffer, BT_AGENT_NEW_LINE, 0); + g_free(buffer); + + if (lines == NULL) + return FALSE; + + /* Write the data and insert new device data */ + for (i = 0; lines[i] != NULL; i++) { + if (g_str_has_prefix(lines[i], "AddressBlacklist")) { + temp_buffer = g_strconcat(lines[i], lap_address, NULL); + g_free(lines[i]); + lines[i] = temp_buffer; + } + } + buffer = g_strjoinv(BT_AGENT_NEW_LINE, lines); + g_strfreev(lines); + + fp = fopen(BT_AGENT_AUTO_PAIR_BLACKLIST_FILE, "w"); + + if (fp == NULL) { + BT_DBG("fopen failed \n"); + g_free(buffer); + return FALSE; + } + + BT_DBG("Buffer = %s\n", buffer); + fwrite(buffer, 1, strlen(buffer), fp); + fclose(fp); + + g_free(buffer); + + BT_DBG("-\n"); + + return FALSE; +} + +static int __bt_retry_bond(void) +{ + DBusGProxy *adapter_proxy; + + BT_CHECK_PARAMETER(bonding_info); + BT_CHECK_PARAMETER(bonding_info->addr); + + adapter_proxy = _bt_get_adapter_proxy(); + retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + is_deivce_creating = TRUE; + + if (!dbus_g_proxy_begin_call_with_timeout(adapter_proxy, "CreatePairedDevice", + (DBusGProxyCallNotify) __bt_bond_device_cb, + NULL, NULL, BT_MAX_DBUS_TIMEOUT, + G_TYPE_STRING, bonding_info->addr, + DBUS_TYPE_G_OBJECT_PATH, BT_DEVICE_AGENT_PATH, + G_TYPE_STRING, "DisplayYesNo", + G_TYPE_INVALID)) { + BT_ERR("CreatePairedDevice call fail"); + is_deivce_creating = FALSE; + return BLUETOOTH_ERROR_NO_RESOURCES; + } + + return BLUETOOTH_ERROR_NONE; +} + + +static int __bt_remove_and_bond(void) +{ + DBusGProxy *adapter_proxy; + GError *err = NULL; + char *device_path = NULL; + + BT_CHECK_PARAMETER(bonding_info); + BT_CHECK_PARAMETER(bonding_info->addr); + + adapter_proxy = _bt_get_adapter_proxy(); + retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + 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); + + dbus_g_proxy_call(adapter_proxy, "RemoveDevice", + &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); + g_error_free(err); + return BLUETOOTH_ERROR_INTERNAL; + } + + return __bt_retry_bond(); +} + +static int __bt_cancel_and_bond(void) +{ + DBusGProxy *adapter_proxy; + GError *err = NULL; + + BT_CHECK_PARAMETER(bonding_info); + BT_CHECK_PARAMETER(bonding_info->addr); + + adapter_proxy = _bt_get_adapter_proxy(); + retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call(adapter_proxy, "CancelDeviceCreation", &err, + G_TYPE_STRING, bonding_info->addr, + G_TYPE_INVALID, G_TYPE_INVALID); + + if (err != NULL) { + BT_ERR("CancelCreation Fail: %s", err->message); + g_error_free(err); + return BLUETOOTH_ERROR_INTERNAL; + } + + return __bt_retry_bond(); +} + + +static void __bt_bond_device_cb(DBusGProxy *proxy, DBusGProxyCall *call, + gpointer user_data) +{ + int result = BLUETOOTH_ERROR_NONE; + char *device_path = NULL; + GError *err = NULL; + 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; + + /* Terminate ALL system popup */ + syspopup_destroy_all(); + + dbus_g_proxy_end_call(proxy, call, &err, + DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID); + g_free(device_path); + is_deivce_creating = FALSE; + + if (bonding_info == NULL) { + /* Send reply */ + BT_ERR("bonding_info == NULL"); + goto done; + } + + req_info = _bt_get_request_info(bonding_info->req_id); + if (req_info == NULL) { + BT_ERR("req_info == NULL"); + goto done; + } + + if (err != NULL) { + BT_ERR("Error occured in CreateBonding [%s]", err->message); + + if (!strcmp(err->message, "Already Exists")) { + BT_DBG("Existing Bond, remove and retry"); + ret_if(__bt_remove_and_bond() == BLUETOOTH_ERROR_NONE); + + result = BLUETOOTH_ERROR_PARING_FAILED; + } 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"); + ret_if(__bt_cancel_and_bond() == BLUETOOTH_ERROR_NONE); + + result = BLUETOOTH_ERROR_PARING_FAILED; + } else if (!strcmp(err->message, "Authentication Failed")) { + if (bonding_info->is_autopair == TRUE) { + _bt_set_autopair_status_in_bonding_info(FALSE); + __ignore_auto_pairing_request(bonding_info->addr); + } + result = BLUETOOTH_ERROR_AUTHENTICATION_FAILED; + } else if (!strcmp(err->message, "Page Timeout")) { + /* This is the special case + As soon as call bluetooth_bond_device, try to cancel bonding. + In this case, before completing to call 'CreatePairedDevice' method + the procedure is stopped. So 'Cancle' error is not return. + */ + result = BLUETOOTH_ERROR_HOST_DOWN; + } else if (!strcmp(err->message, BT_TIMEOUT_MESSAGE)) { + dbus_g_proxy_call(proxy, "CancelDeviceCreation", NULL, + G_TYPE_STRING, bonding_info->addr, + G_TYPE_INVALID, G_TYPE_INVALID); + + result = BLUETOOTH_ERROR_TIMEOUT; + } else { + result = BLUETOOTH_ERROR_PARING_FAILED; + } + } + + if (result != BLUETOOTH_ERROR_NONE) + goto dbus_return; + + remote_dev_info = _bt_get_remote_device_info(bonding_info->addr); + + /* Send the event to application */ + if (remote_dev_info != NULL) { + _bt_send_event(BT_ADAPTER_EVENT, + BLUETOOTH_EVENT_BONDING_FINISHED, + DBUS_TYPE_INT32, &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_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, + bonding_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); + + _bt_destroy_agent(bonding_info->agent); + + 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) +{ + DBusGProxy *proxy; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + void *agent; + bluetooth_device_info_t dev_info; + + BT_CHECK_PARAMETER(device_address); + + if (bonding_info) { + BT_ERR("Bonding in progress"); + return BLUETOOTH_ERROR_DEVICE_BUSY; + } + + proxy = _bt_get_adapter_proxy(); + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + _bt_convert_addr_type_to_string(address, device_address->addr); + + agent = _bt_create_agent(BT_DEVICE_AGENT_PATH, FALSE); + retv_if(agent == NULL, BLUETOOTH_ERROR_INTERNAL); + + bonding_info = g_malloc0(sizeof(bt_funcion_data_t)); + bonding_info->addr = g_strdup(address); + bonding_info->req_id = request_id; + bonding_info->agent = agent; + + is_deivce_creating = TRUE; + + 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; + } + } + + return BLUETOOTH_ERROR_NONE; +fail: + 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)); + + is_deivce_creating = FALSE; + + _bt_destroy_agent(agent); + + g_free(bonding_info->addr); + g_free(bonding_info); + bonding_info = NULL; + + return BLUETOOTH_ERROR_INTERNAL; +} + +int _bt_cancel_bonding(void) +{ + DBusGProxy *adapter_proxy; + + retv_if(bonding_info == NULL, BLUETOOTH_ERROR_NOT_IN_OPERATION); + + adapter_proxy = _bt_get_adapter_proxy(); + retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call_no_reply(adapter_proxy, "CancelDeviceCreation", + G_TYPE_STRING, bonding_info->addr, + G_TYPE_INVALID, G_TYPE_INVALID); + + return BLUETOOTH_ERROR_NONE; +} + +static void __bt_unbond_cb(DBusGProxy *proxy, DBusGProxyCall *call, + gpointer user_data) +{ + GError *err = NULL; + GArray *out_param1; + GArray *out_param2; + int result = BLUETOOTH_ERROR_NONE; + bt_funcion_data_t *unbonding_info; + bluetooth_device_info_t dev_info; + request_info_t *req_info; + + dbus_g_proxy_end_call(proxy, call, &err, G_TYPE_INVALID); + + unbonding_info = user_data; + + if (unbonding_info == NULL) { + /* Send reply */ + BT_ERR("unbonding_info == NULL"); + goto done; + } + + req_info = _bt_get_request_info(unbonding_info->req_id); + if (req_info == NULL) { + BT_ERR("req_info == NULL"); + goto done; + } + + 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; + + 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, + unbonding_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); + + _bt_delete_request_list(req_info->req_id); + + g_array_free(out_param1, TRUE); + g_array_free(out_param2, TRUE); + +done: + if (err) + g_error_free(err); + + if (unbonding_info) { + g_free(unbonding_info->addr); + g_free(unbonding_info); + } +} + +int _bt_unbond_device(int request_id, + bluetooth_device_address_t *device_address, + GArray **out_param1) +{ + char *device_path = NULL; + bt_funcion_data_t *unbonding_info; + DBusGProxy *adapter_proxy; + int result = BLUETOOTH_ERROR_INTERNAL; + bluetooth_device_info_t dev_info; + + BT_CHECK_PARAMETER(device_address); + + adapter_proxy = _bt_get_adapter_proxy(); + retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + /* allocate user data so that it can be retrieved in callback */ + unbonding_info = g_malloc0(sizeof(bt_funcion_data_t)); + unbonding_info->addr = g_malloc0(BT_ADDRESS_STRING_SIZE); + unbonding_info->req_id = request_id; + + _bt_convert_addr_type_to_string(unbonding_info->addr, + device_address->addr); + + dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL, + G_TYPE_STRING, unbonding_info->addr, + G_TYPE_INVALID, + DBUS_TYPE_G_OBJECT_PATH, &device_path, + G_TYPE_INVALID); + + if (device_path == NULL) { + BT_ERR("No paired device"); + result = BLUETOOTH_ERROR_NOT_PAIRED; + goto fail; + } + + if (!dbus_g_proxy_begin_call(adapter_proxy, "RemoveDevice", + (DBusGProxyCallNotify) __bt_unbond_cb, + (gpointer)unbonding_info, NULL, + DBUS_TYPE_G_OBJECT_PATH, device_path, + G_TYPE_INVALID)) { + BT_ERR("RemoveBonding begin failed\n"); + goto fail; + } + g_free(device_path); + return BLUETOOTH_ERROR_NONE; + +fail: + memset(&dev_info, 0x00, sizeof(bluetooth_device_info_t)); + _bt_convert_addr_string_to_type(dev_info.device_address.addr, + unbonding_info->addr); + + g_array_append_vals(*out_param1, &dev_info, + sizeof(bluetooth_device_info_t)); + g_free(device_path); + g_free(unbonding_info->addr); + g_free(unbonding_info); + return result; +} + +static void __bt_discover_cb(DBusGProxy *proxy, DBusGProxyCall *call, + gpointer user_data) +{ + GError *err = NULL; + GHashTable *hash = 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; + + 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 (searching_info == NULL) { + /* Send reply */ + BT_ERR("unbonding_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); + + 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 { + result = BLUETOOTH_ERROR_CONNECTION_ERROR; + } + + if (result == BLUETOOTH_ERROR_HOST_DOWN || + result == BLUETOOTH_ERROR_CONNECTION_ERROR) { + remote_dev_info = _bt_get_remote_device_info(searching_info->addr); + if (remote_dev_info && remote_dev_info->uuids != NULL && + remote_dev_info->uuid_count > 0) { + result = BLUETOOTH_ERROR_NONE; + goto event; + } + _bt_free_device_info(remote_dev_info); + } + goto dbus_return; + } + + remote_dev_info = _bt_get_remote_device_info(searching_info->addr); + +event: + /* 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); + + g_hash_table_destroy(hash); + + if (searching_info) { + g_free(searching_info->addr); + g_free(searching_info); + searching_info = NULL; + } +} + +static void __bt_create_device_cb(DBusGProxy *proxy, DBusGProxyCall *call, + gpointer user_data) +{ + 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; + + is_deivce_creating = FALSE; + + 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); + + 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); + searching_info->req_id = request_id; + + _bt_convert_addr_type_to_string(searching_info->addr, + device_address->addr); + + dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL, + G_TYPE_STRING, searching_info->addr, + G_TYPE_INVALID, + DBUS_TYPE_G_OBJECT_PATH, &device_path, + G_TYPE_INVALID); + + if (device_path == NULL) { + BT_ERR("No paired device"); + + 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_DEVICE_INTERFACE); + g_free(device_path); + if (device_proxy == NULL) { + result = BLUETOOTH_ERROR_INTERNAL; + goto fail; + } + 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; + } + + searching_info->device_proxy = device_proxy; + + return BLUETOOTH_ERROR_NONE; +fail: + if (device_proxy) + g_object_unref(device_proxy); + + g_free(searching_info->addr); + g_free(searching_info); + searching_info = NULL; + return result; +} + +int _bt_cancel_search_device(void) +{ + GError *err = NULL; + + retv_if(searching_info == NULL, BLUETOOTH_ERROR_NOT_IN_OPERATION); + + if (searching_info->device_proxy) { + dbus_g_proxy_call(searching_info->device_proxy, + "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; +} + +int _bt_set_alias(bluetooth_device_address_t *device_address, + const char *alias) +{ + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + gchar *device_path = NULL; + DBusGProxy *adapter_proxy; + DBusGProxy *device_proxy; + GError *error = NULL; + GValue name = { 0 }; + DBusGConnection *conn; + + BT_CHECK_PARAMETER(device_address); + BT_CHECK_PARAMETER(alias); + + 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); + + dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL, + G_TYPE_STRING, address, G_TYPE_INVALID, + DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID); + + if (device_path == NULL) { + BT_ERR("No paired device"); + return BLUETOOTH_ERROR_NOT_PAIRED; + } + + 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); + g_value_init(&name, G_TYPE_STRING); + g_value_set_string(&name, alias); + + dbus_g_proxy_call(device_proxy, "SetProperty", &error, + G_TYPE_STRING, "Alias", G_TYPE_VALUE, + &name, G_TYPE_INVALID); + + g_object_unref(device_proxy); + + g_value_unset(&name); + + if (error) { + BT_ERR("SetProperty error: [%s]", error->message); + g_error_free(error); + return BLUETOOTH_ERROR_INTERNAL; + } + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_set_authorization(bluetooth_device_address_t *device_address, + gboolean authorize) +{ + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + gchar *device_path = NULL; + DBusGProxy *adapter_proxy; + DBusGProxy *device_proxy; + gboolean previous_value; + GError *error = NULL; + GValue trusted = { 0 }; + GValue *value; + GHashTable *hash = NULL; + DBusGConnection *conn; + int ret = BLUETOOTH_ERROR_NONE; + + BT_CHECK_PARAMETER(device_address); + + 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); + + dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL, + G_TYPE_STRING, address, G_TYPE_INVALID, + DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID); + + if (device_path == NULL) { + BT_ERR("No paired device"); + return BLUETOOTH_ERROR_NOT_PAIRED; + } + + 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, "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("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, "Trusted"); + previous_value = value ? g_value_get_boolean(value) : FALSE; + + /* If the input is same with previous value, return error. */ + if (previous_value == authorize) { + BT_ERR("Same value: %d", previous_value); + g_object_unref(device_proxy); + ret = BLUETOOTH_ERROR_INVALID_PARAM; + goto done; + } + + g_value_init(&trusted, G_TYPE_BOOLEAN); + g_value_set_boolean(&trusted, authorize); + + dbus_g_proxy_call(device_proxy, "SetProperty", &error, + G_TYPE_STRING, "Trusted", G_TYPE_VALUE, + &trusted, G_TYPE_INVALID); + + g_object_unref(device_proxy); + + g_value_unset(&trusted); + + if (error) { + BT_ERR("SetProperty error: [%s]", error->message); + g_error_free(error); + ret = BLUETOOTH_ERROR_INTERNAL; + } +done: + g_hash_table_destroy(hash); + + return ret; +} + +int _bt_is_device_connected(bluetooth_device_address_t *device_address, + int connection_type, 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; + char *interface = NULL; + + retv_if(device_address == NULL, BLUETOOTH_ERROR_INVALID_PARAM); + retv_if(is_connected == NULL, BLUETOOTH_ERROR_INVALID_PARAM); + + if (connection_type == BLUETOOTH_RFCOMM_SERVICE) + return _bt_rfcomm_is_device_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); + + 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 (error != NULL) { + BT_ERR("Failed to Find device: %s", error->message); + g_error_free(error); + return BLUETOOTH_ERROR_NOT_PAIRED; + } + + retv_if(object_path == NULL, BLUETOOTH_ERROR_INTERNAL); + + switch (connection_type) { + case BLUETOOTH_HSP_SERVICE: + interface = BT_HEADSET_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!"); + g_free(object_path); + return BLUETOOTH_ERROR_INVALID_PARAM; + } + + BT_DBG("Interface name: %s", interface); + + 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; + } + 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); + g_error_free(error); + g_object_unref(device_proxy); + is_connected = FALSE; + return BLUETOOTH_ERROR_NONE; + } + + 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 BLUETOOTH_ERROR_NONE; +} + diff --git a/bt-service/bt-service-event-receiver.c b/bt-service/bt-service-event-receiver.c new file mode 100644 index 0000000..4d2cb76 --- /dev/null +++ b/bt-service/bt-service-event-receiver.c @@ -0,0 +1,1311 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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-obex-server.h" +#include "bt-service-rfcomm-server.h" + +static DBusGConnection *manager_conn; +static DBusGConnection *obexd_conn; + +static guint event_id; + +static gboolean __bt_parse_device_properties(DBusMessageIter *item_iter, + bt_remote_dev_info_t *dev_info) +{ + DBusMessageIter value_iter; + char *value; + + if (dbus_message_iter_get_arg_type(item_iter) != DBUS_TYPE_ARRAY) + return FALSE; + + dbus_message_iter_recurse(item_iter, &value_iter); + + while (dbus_message_iter_get_arg_type(&value_iter) == + DBUS_TYPE_DICT_ENTRY) { + 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, "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 { + 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 TRUE; +} + +char *__bt_get_headset_name(char *address) +{ + bluetooth_device_address_t device_address = { {0} }; + bluetooth_device_info_t dev_info; + + retv_if(address == NULL, strdup("")); + + _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 int __bt_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\n"); + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_iter_get_basic(&item_iter, name); + + retv_if(*name == NULL, 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\n"); + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_iter_get_basic(&item_iter, previous); + + retv_if(*previous == NULL, 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\n"); + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_iter_get_basic(&item_iter, current); + + retv_if(*current == NULL, BLUETOOTH_ERROR_INTERNAL); + + return BLUETOOTH_ERROR_NONE; +} + +static int __bt_get_agent_signal_info(DBusMessage *msg, char **address, + char **name, char **uuid) +{ + 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; + } + + dbus_message_iter_get_basic(&item_iter, address); + + 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\n"); + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_iter_get_basic(&item_iter, name); + + 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\n"); + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_message_iter_get_basic(&item_iter, uuid); + + return BLUETOOTH_ERROR_NONE; +} + +gboolean _bt_discovery_finished_cb(gpointer user_data) +{ + int result = BLUETOOTH_ERROR_NONE; + event_id = 0; + + if (_bt_get_discoverying_property() == FALSE) { + if (_bt_get_cancel_by_user() == TRUE) { + result = BLUETOOTH_ERROR_CANCEL_BY_USER; + } + + _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; +} + +void _bt_handle_adapter_event(DBusMessage *msg) +{ + int mode = 0; + int result = BLUETOOTH_ERROR_NONE; + DBusGProxy *adapter_proxy; + DBusMessageIter item_iter; + DBusMessageIter value_iter; + GValue timeout = { 0 }; + const char *member = dbus_message_get_member(msg); + const char *property = NULL; + + ret_if(member == NULL); + + if (strcasecmp(member, "PropertyChanged") == 0) { + 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; + } + + dbus_message_iter_get_basic(&item_iter, &property); + + ret_if(property == NULL); + + if (strcasecmp(property, "Discovering") == 0) { + gboolean discovering = FALSE; + dbus_message_iter_next(&item_iter); + dbus_message_iter_recurse(&item_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); + } 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); + } + } else if (strcasecmp(property, "Name") == 0) { + char *name = NULL; + dbus_message_iter_next(&item_iter); + dbus_message_iter_recurse(&item_iter, &value_iter); + dbus_message_iter_get_basic(&value_iter, &name); + + /* 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, "Discoverable") == 0) { + gboolean discoverable = FALSE; + dbus_message_iter_next(&item_iter); + dbus_message_iter_recurse(&item_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_proxy(); + ret_if(adapter_proxy == NULL); + + dbus_g_proxy_call_no_reply(adapter_proxy, "SetProperty", + 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_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); + + /* Event will be sent by "DiscoverableTimeout" signal */ + ret_if(mode != BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE); + + /* 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); + } + } 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); + + /* 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); + } + } else if (strcasecmp(member, "DeviceFound") == 0) { + const char *bdaddr; + bt_remote_dev_info_t *dev_info; + + ret_if(_bt_is_discovering() == FALSE); + + dev_info = g_malloc0(sizeof(bt_remote_dev_info_t)); + + dbus_message_iter_init(msg, &item_iter); + dbus_message_iter_get_basic(&item_iter, &bdaddr); + dbus_message_iter_next(&item_iter); + + dev_info->address = g_strdup(bdaddr); + + if (__bt_parse_device_properties(&item_iter, dev_info) == FALSE) { + BT_ERR("Fail to parse the properies"); + _bt_free_device_info(dev_info); + return; + } + + 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_INVALID); + + _bt_free_device_info(dev_info); + } else if (strcasecmp(member, "DeviceCreated") == 0) { + const char *object_path = NULL; + char *address; + bt_remote_dev_info_t *remote_dev_info; + + ret_if(_bt_is_device_creating() == FALSE); + + /* Bonding from remote device */ + address = g_malloc0(BT_ADDRESS_STRING_SIZE); + + dbus_message_iter_init(msg, &item_iter); + dbus_message_iter_get_basic(&item_iter, &object_path); + dbus_message_iter_next(&item_iter); + + _bt_convert_device_path_to_address(object_path, address); + + remote_dev_info = _bt_get_remote_device_info(address); + if (remote_dev_info == NULL) { + g_free(address); + return; + } + + _bt_free_device_info(remote_dev_info); + g_free(address); + } else if (strcasecmp(member, "DeviceRemoved") == 0) { + const char *object_path = NULL; + char *address; + + /* Bonding from remote device */ + address = g_malloc0(BT_ADDRESS_STRING_SIZE); + + dbus_message_iter_init(msg, &item_iter); + dbus_message_iter_get_basic(&item_iter, &object_path); + dbus_message_iter_next(&item_iter); + + _bt_convert_device_path_to_address(object_path, address); + + _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); + } +} + +void _bt_handle_input_event(DBusMessage *msg) +{ + int result = BLUETOOTH_ERROR_NONE; + DBusMessageIter item_iter; + DBusMessageIter value_iter; + gboolean property_flag = FALSE; + const char *member = dbus_message_get_member(msg); + const char *path = dbus_message_get_path(msg); + const char *property = 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\n"); + return; + } + + dbus_message_iter_get_basic(&item_iter, &property); + + ret_if(property == NULL); + + if (strcasecmp(property, "Connected") == 0) { + int event = BLUETOOTH_EVENT_NONE; + char *address; + + dbus_message_iter_next(&item_iter); + dbus_message_iter_recurse(&item_iter, &value_iter); + dbus_message_iter_get_basic(&value_iter, &property_flag); + + address = g_malloc0(BT_ADDRESS_STRING_SIZE); + + _bt_convert_device_path_to_address(path, address); + + event = (property_flag == TRUE) ? + BLUETOOTH_HID_CONNECTED : + BLUETOOTH_HID_DISCONNECTED; + + _bt_send_event(BT_HID_EVENT, event, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_INVALID); + + g_free(address); + } + } + +void _bt_handle_network_server_event(DBusMessage *msg) +{ + int result = BLUETOOTH_ERROR_NONE; + char *address = NULL; + char *device = NULL; + const char *member = dbus_message_get_member(msg); + + ret_if(member == NULL); + + if (strcasecmp(member, "PeerConnected") == 0) { + if (!dbus_message_get_args(msg, NULL, + DBUS_TYPE_STRING, &device, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_INVALID)) { + BT_ERR("Unexpected parameters in signal"); + return; + } + + _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); + } else if (strcasecmp(member, "PeerDisconnected") == 0) { + if (!dbus_message_get_args(msg, NULL, + DBUS_TYPE_STRING, &device, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_INVALID)) { + BT_ERR("Unexpected parameters in signal"); + return; + } + + _bt_send_event(BT_NETWORK_EVENT, BLUETOOTH_EVENT_NETWORK_SERVER_DISCONNECTED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &device, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_INVALID); + } +} + +void _bt_handle_network_client_event(DBusMessage *msg) +{ + int result = BLUETOOTH_ERROR_NONE; + DBusMessageIter item_iter; + DBusMessageIter value_iter; + gboolean property_flag = FALSE; + const char *member = dbus_message_get_member(msg); + const char *path = dbus_message_get_path(msg); + const char *property = 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\n"); + return; + } + + dbus_message_iter_get_basic(&item_iter, &property); + + ret_if(property == NULL); + + if (strcasecmp(property, "Connected") == 0) { + int event = BLUETOOTH_EVENT_NONE; + char *address; + + dbus_message_iter_next(&item_iter); + dbus_message_iter_recurse(&item_iter, &value_iter); + dbus_message_iter_get_basic(&value_iter, &property_flag); + + address = g_malloc0(BT_ADDRESS_STRING_SIZE); + + _bt_convert_device_path_to_address(path, address); + + if (property_flag == TRUE) { + event = BLUETOOTH_EVENT_NETWORK_CONNECTED; + } else { + event = BLUETOOTH_EVENT_NETWORK_DISCONNECTED; + } + + _bt_send_event(BT_NETWORK_EVENT, event, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_INVALID); + + g_free(address); + } +} + +void _bt_handle_device_event(DBusMessage *msg) +{ + int event; + int result = BLUETOOTH_ERROR_NONE; + DBusMessageIter item_iter; + DBusMessageIter value_iter; + char *address; + const char *member = dbus_message_get_member(msg); + const char *path = dbus_message_get_path(msg); + const char *property = NULL; + + ret_if(path == NULL); + ret_if(member == NULL); + + if (strcasecmp(member, "PropertyChanged") == 0) { + 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; + } + + dbus_message_iter_get_basic(&item_iter, &property); + + ret_if(property == NULL); + + if (strcasecmp(property, "Connected") == 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; + + 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); + + /* 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; + bt_remote_dev_info_t *remote_dev_info; + dbus_message_iter_next(&item_iter); + dbus_message_iter_recurse(&item_iter, &value_iter); + dbus_message_iter_get_basic(&value_iter, &paired); + + ret_if(paired == FALSE); + + /* BlueZ sends paired signal for each paired device */ + /* during activation, We should ignore this, otherwise*/ + /* application thinks that a new device got paired */ + if (_bt_adapter_get_status() != BT_ACTIVATED) { + BT_DBG("BT is not activated, so ignore this"); + return; + } + + if (_bt_is_device_creating() == TRUE) { + BT_DBG("Try to Pair by me"); + return; + } + + address = g_malloc0(BT_ADDRESS_STRING_SIZE); + + _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_send_event(BT_ADAPTER_EVENT, + BLUETOOTH_EVENT_BONDING_FINISHED, + 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); + + _bt_free_device_info(remote_dev_info); + g_free(address); + } + } +} + +void __bt_set_audio_values(gboolean connected, char *address) +{ + char *name = NULL; + int bt_device_state = VCONFKEY_BT_DEVICE_NONE; + + /* Set the headset name */ + if (connected == TRUE) { + name = __bt_get_headset_name(address); + } else { + name = g_strdup(""); + } + + if (vconf_set_str(VCONFKEY_BT_HEADSET_NAME, + name) != 0) { + BT_ERR("vconf_set_str failed"); + } + + g_free(name); + + /* Set the headset state */ + if (vconf_get_int(VCONFKEY_BT_DEVICE, + &bt_device_state) != 0) { + BT_ERR("vconf_get_str failed"); + } + + 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; + } + + if (vconf_set_int(VCONFKEY_BT_DEVICE, + bt_device_state) != 0) { + BT_ERR("vconf_set_int failed"); + } +} + +void _bt_handle_headset_event(DBusMessage *msg) +{ + int result = BLUETOOTH_ERROR_NONE; + DBusMessageIter item_iter; + DBusMessageIter value_iter; + gboolean property_flag = FALSE; + const char *member = dbus_message_get_member(msg); + const char *path = dbus_message_get_path(msg); + const char *property = 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\n"); + return; + } + + dbus_message_iter_get_basic(&item_iter, &property); + + ret_if(property == NULL); + + /* We allow only 1 headset connection (HSP or HFP)*/ + if (strcasecmp(property, "Connected") == 0) { + int event = BLUETOOTH_EVENT_NONE; + char *address; + + dbus_message_iter_next(&item_iter); + dbus_message_iter_recurse(&item_iter, &value_iter); + dbus_message_iter_get_basic(&value_iter, &property_flag); + + address = g_malloc0(BT_ADDRESS_STRING_SIZE); + + _bt_convert_device_path_to_address(path, address); + + if (property_flag == TRUE) { + event = BLUETOOTH_EVENT_AG_CONNECTED; + } else { + event = BLUETOOTH_EVENT_AG_DISCONNECTED; + } + + __bt_set_audio_values(property_flag, address); + + _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, "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); + dbus_message_iter_get_basic(&value_iter, &state); + + /* 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; + } else { + BT_ERR("Not handled state"); + g_free(address); + 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; + + 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); + dbus_message_iter_get_basic(&value_iter, &spkr_gain); + + _bt_send_event(BT_HEADSET_EVENT, BLUETOOTH_EVENT_AG_SPEAKER_GAIN, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_UINT16, &spkr_gain, + DBUS_TYPE_INVALID); + + g_free(address); + } else if (strcasecmp(property, "MicrophoneGain") == 0) { + guint16 mic_gain; + 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); + dbus_message_iter_get_basic(&value_iter, &mic_gain); + + _bt_send_event(BT_HEADSET_EVENT, BLUETOOTH_EVENT_AG_MIC_GAIN, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_UINT16, &mic_gain, + DBUS_TYPE_INVALID); + + g_free(address); + } +} + +void _bt_handle_sink_event(DBusMessage *msg) +{ + int result = BLUETOOTH_ERROR_NONE; + DBusMessageIter item_iter; + DBusMessageIter value_iter; + gboolean property_flag = FALSE; + const char *member = dbus_message_get_member(msg); + const char *path = dbus_message_get_path(msg); + const char *property = 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\n"); + return; + } + + dbus_message_iter_get_basic(&item_iter, &property); + + ret_if(property == NULL); + + if (strcasecmp(property, "Connected") == 0) { + int event = BLUETOOTH_EVENT_NONE; + char *address; + + dbus_message_iter_next(&item_iter); + dbus_message_iter_recurse(&item_iter, &value_iter); + dbus_message_iter_get_basic(&value_iter, &property_flag); + + 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_send_event(BT_HEADSET_EVENT, event, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_INVALID); + + _bt_send_event(BT_AVRCP_EVENT, event, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_INVALID); + + g_free(address); + } +} + +void _bt_handle_agent_event(DBusMessage *msg) +{ + const char *member = dbus_message_get_member(msg); + int result = BLUETOOTH_ERROR_NONE; + char *address = NULL; + char *name = NULL; + char *uuid = NULL; + + ret_if(member == NULL); + + if (strcasecmp(member, "ObexAuthorize") == 0) { + __bt_get_agent_signal_info(msg, &address, &name, &uuid); + + _bt_send_event(BT_OPP_SERVER_EVENT, + BLUETOOTH_EVENT_OBEX_SERVER_CONNECTION_AUTHORIZE, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_INVALID); + } else if (strcasecmp(member, "RfcommAuthorize") == 0) { + bt_rfcomm_server_info_t *server_info; + + __bt_get_agent_signal_info(msg, &address, &name, &uuid); + + server_info = _bt_rfcomm_get_server_info_using_uuid(uuid); + ret_if(server_info == NULL); + ret_if(server_info->server_type != BT_CUSTOM_SERVER); + + _bt_send_event(BT_RFCOMM_SERVER_EVENT, + BLUETOOTH_EVENT_RFCOMM_AUTHORIZE, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &address, + DBUS_TYPE_STRING, &uuid, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_INT16, &server_info->control_fd, + DBUS_TYPE_INVALID); + } +} + +static DBusHandlerResult __bt_manager_event_filter(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + 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; + + retv_if(member == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + + if (strcasecmp(member, "AdapterAdded") == 0) { + BT_DBG("AdapterAdded"); + _bt_handle_adapter_added(); + } else if (strcasecmp(member, "AdapterRemoved") == 0) { + BT_DBG("AdapterRemoved"); + } else if (strcasecmp(member, "NameOwnerChanged") == 0) { + gboolean value; + char *name = NULL; + char *previous = NULL; + char *current = NULL; + + if (__bt_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 (strcasecmp(name, "org.bluez") == 0) { + BT_DBG("Bluetoothd is terminated"); + _bt_handle_adapter_removed(); + } + + _bt_obex_server_check_allocation(&value); + + if (value == TRUE) { + /* Check if the obex server was terminated abnormally */ + _bt_obex_server_check_termination(name); + } + + _bt_rfcomm_server_check_existence(&value); + + if (value == TRUE) { + /* The obex server was terminated abnormally */ + _bt_rfcomm_server_check_termination(name); + } + } 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_NETWORK_CLIENT_INTERFACE)) { + _bt_handle_network_client_event(msg); + } 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)) { + _bt_handle_device_event(msg); + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusHandlerResult __bt_obexd_event_filter(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + const char *path = dbus_message_get_path(msg); + 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; + + retv_if(member == NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + + if (strcasecmp(member, "TransferStarted") == 0) { + char *transfer_path = NULL; + + if (!dbus_message_get_args(msg, NULL, + DBUS_TYPE_OBJECT_PATH, &transfer_path, + DBUS_TYPE_INVALID)) { + BT_ERR("Unexpected parameters in signal"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + _bt_obex_transfer_started(transfer_path); + } else if (strcasecmp(member, "Progress") == 0) { + gint total = 0; + gint transfer = 0; + + if (!dbus_message_get_args(msg, NULL, + DBUS_TYPE_INT32, &total, + DBUS_TYPE_INT32, &transfer, + DBUS_TYPE_INVALID)) { + BT_ERR("Unexpected parameters in signal"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + _bt_obex_transfer_progress(path, total, transfer); + } else if (strcasecmp(member, "TransferCompleted") == 0) { + char *transfer_path = NULL; + gboolean success; + + if (!dbus_message_get_args(msg, NULL, + DBUS_TYPE_OBJECT_PATH, &transfer_path, + DBUS_TYPE_BOOLEAN, &success, + DBUS_TYPE_INVALID)) { + BT_ERR("Unexpected parameters in signal"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + _bt_obex_transfer_completed(transfer_path, success); + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +int _bt_register_service_event(DBusGConnection *g_conn, int event_type) +{ + DBusError dbus_error; + char *match1 = NULL; + char *match2 = NULL; + DBusConnection *conn; + DBusHandleMessageFunction event_func = NULL; + + retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + conn = dbus_g_connection_get_connection(g_conn); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + switch (event_type) { + case BT_MANAGER_EVENT: + event_func = __bt_manager_event_filter; + match1 = g_strdup_printf(MANAGER_EVENT_MATCH_RULE, + BT_MANAGER_INTERFACE, + BT_MANAGER_PATH); + + match2 = g_strdup_printf(MANAGER_EVENT_MATCH_RULE, + BT_FREEDESKTOP_INTERFACE, + BT_FREEDESKTOP_PATH); + break; + case BT_DEVICE_EVENT: + match1 = g_strdup_printf(EVENT_MATCH_RULE, + BT_DEVICE_INTERFACE); + break; + case BT_HID_EVENT: + match1 = g_strdup_printf(EVENT_MATCH_RULE, + BT_INPUT_INTERFACE); + break; + case BT_NETWORK_EVENT: + match1 = g_strdup_printf(EVENT_MATCH_RULE, + BT_NETWORK_SERVER_INTERFACE); + + match2 = g_strdup_printf(EVENT_MATCH_RULE, + BT_NETWORK_CLIENT_INTERFACE); + break; + case BT_HEADSET_EVENT: + match1 = g_strdup_printf(EVENT_MATCH_RULE, + BT_HEADSET_INTERFACE); + + match2 = g_strdup_printf(EVENT_MATCH_RULE, + BT_SINK_INTERFACE); + break; + case BT_OPP_SERVER_EVENT: + event_func = __bt_obexd_event_filter; + match1 = g_strdup_printf(MANAGER_EVENT_MATCH_RULE, + BT_OBEXD_MANAGER_INTERFACE, + BT_MANAGER_PATH); + + match2 = g_strdup_printf(EVENT_MATCH_RULE, + BT_OBEXD_TRANSFER_INTERFACE); + break; + default: + BT_ERR("Unknown event"); + return BLUETOOTH_ERROR_INTERNAL; + } + + if (event_func) { + if (!dbus_connection_add_filter(conn, event_func, + NULL, NULL)) { + BT_ERR("Fail to add filter"); + goto fail; + } + } + + dbus_error_init(&dbus_error); + + if (match1) + dbus_bus_add_match(conn, match1, &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; + } + + if (match2) + dbus_bus_add_match(conn, match2, &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; + } + + g_free(match1); + g_free(match2); + + return BLUETOOTH_ERROR_NONE; +fail: + g_free(match1); + g_free(match2); + return BLUETOOTH_ERROR_INTERNAL; +} + +void _bt_unregister_service_event(DBusGConnection *g_conn, int event_type) +{ + DBusConnection *conn; + DBusHandleMessageFunction event_func; + + ret_if(g_conn == NULL); + conn = dbus_g_connection_get_connection(g_conn); + + switch (event_type) { + case BT_MANAGER_EVENT: + event_func = __bt_manager_event_filter; + break; + case BT_OPP_SERVER_EVENT: + event_func = __bt_obexd_event_filter; + break; + default: + BT_ERR("Unknown event"); + return; + } + + ret_if(conn == NULL); + + dbus_connection_remove_filter(conn, event_func, NULL); +} + +static int __bt_init_manager_receiver(void) +{ + GError *error = NULL; + + if (manager_conn == NULL) { + manager_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); + } + retv_if(manager_conn == NULL, BLUETOOTH_ERROR_INTERNAL); + } + + if (_bt_register_service_event(manager_conn, + BT_MANAGER_EVENT) != BLUETOOTH_ERROR_NONE) + goto fail; + + if (_bt_register_service_event(manager_conn, + BT_DEVICE_EVENT) != BLUETOOTH_ERROR_NONE) + goto fail; + + if (_bt_register_service_event(manager_conn, + BT_HID_EVENT) != BLUETOOTH_ERROR_NONE) + goto fail; + + if (_bt_register_service_event(manager_conn, + BT_HEADSET_EVENT) != BLUETOOTH_ERROR_NONE) + goto fail; + + if (_bt_register_service_event(manager_conn, + BT_NETWORK_EVENT) != BLUETOOTH_ERROR_NONE) + goto fail; + + return BLUETOOTH_ERROR_NONE; +fail: + if (manager_conn) { + dbus_g_connection_unref(manager_conn); + manager_conn = NULL; + } + + return BLUETOOTH_ERROR_INTERNAL; +} + +static int __bt_init_obexd_receiver(void) +{ + GError *error = NULL; + + if (obexd_conn == NULL) { + 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(obexd_conn == NULL, BLUETOOTH_ERROR_INTERNAL); + } + + if (_bt_register_service_event(obexd_conn, + BT_OPP_SERVER_EVENT) != BLUETOOTH_ERROR_NONE) { + dbus_g_connection_unref(obexd_conn); + obexd_conn = NULL; + return BLUETOOTH_ERROR_INTERNAL; + } + + return BLUETOOTH_ERROR_NONE; +} + +/* To receive the event from bluez */ +int _bt_init_service_event_receiver(void) +{ + int result; + + result = __bt_init_manager_receiver(); + retv_if(result != BLUETOOTH_ERROR_NONE, result); + + result = __bt_init_obexd_receiver(); + if (result != BLUETOOTH_ERROR_NONE) + BT_ERR("Fail to init obexd receiver"); + + return BLUETOOTH_ERROR_NONE; +} + +void _bt_deinit_service_event_reciever(void) +{ + _bt_unregister_service_event(manager_conn, BT_MANAGER_EVENT); + + _bt_unregister_service_event(obexd_conn, BT_OPP_SERVER_EVENT); + + if (manager_conn) { + dbus_g_connection_unref(manager_conn); + manager_conn = NULL; + } + + if (obexd_conn) { + dbus_g_connection_unref(obexd_conn); + obexd_conn = NULL; + } + + if (event_id > 0) + g_source_remove(event_id); +} diff --git a/bt-service/bt-service-event-sender.c b/bt-service/bt-service-event-sender.c new file mode 100644 index 0000000..1b64048 --- /dev/null +++ b/bt-service/bt-service-event-sender.c @@ -0,0 +1,288 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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-internal-types.h" + +#include "bt-service-common.h" +#include "bt-service-event.h" + +static DBusConnection *event_conn; + +int _bt_send_event(int event_type, int event, int type, ...) +{ + DBusMessage *msg; + char *path; + char *signal; + va_list arguments; + + retv_if(event_conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + switch (event_type) { + case BT_ADAPTER_EVENT: + path = BT_ADAPTER_PATH; + break; + case BT_DEVICE_EVENT: + path = BT_DEVICE_PATH; + break; + case BT_HID_EVENT: + path = BT_HID_PATH; + break; + case BT_HEADSET_EVENT: + path = BT_HEADSET_PATH; + break; + case BT_AVRCP_EVENT: + path = BT_AVRCP_PATH; + break; + case BT_NETWORK_EVENT: + path = BT_NETWORK_PATH; + break; + case BT_OPP_CLIENT_EVENT: + path = BT_OPP_CLIENT_PATH; + break; + case BT_OPP_SERVER_EVENT: + path = BT_OPP_SERVER_PATH; + break; + case BT_RFCOMM_CLIENT_EVENT: + path = BT_RFCOMM_CLIENT_PATH; + break; + case BT_RFCOMM_SERVER_EVENT: + path = BT_RFCOMM_SERVER_PATH; + break; + default: + BT_ERR("Unknown event"); + return BLUETOOTH_ERROR_INTERNAL; + } + + switch (event) { + case BLUETOOTH_EVENT_ENABLED: + signal = BT_ENABLED; + break; + case BLUETOOTH_EVENT_DISABLED: + signal = BT_DISABLED; + break; + case BLUETOOTH_EVENT_LOCAL_NAME_CHANGED: + signal = BT_ADAPTER_NAME_CHANGED; + break; + case BLUETOOTH_EVENT_DISCOVERABLE_MODE_CHANGED: + signal = BT_DISCOVERABLE_MODE_CHANGED; + break; + case BLUETOOTH_EVENT_DISCOVERABLE_TIMEOUT_CHANGED: + signal = BT_DISCOVERABLE_TIMEOUT_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_DISCOVERY_FINISHED: + signal = BT_DISCOVERY_FINISHED; + 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_SERVICE_SEARCHED: + signal = BT_SERVICE_SEARCHED; + break; + case BLUETOOTH_HID_CONNECTED: + signal = BT_INPUT_CONNECTED; + break; + case BLUETOOTH_HID_DISCONNECTED: + signal = BT_INPUT_DISCONNECTED; + break; + case BLUETOOTH_EVENT_AG_CONNECTED: + signal = BT_HEADSET_CONNECTED; + break; + case BLUETOOTH_EVENT_AG_DISCONNECTED: + signal = BT_HEADSET_DISCONNECTED; + break; + case BLUETOOTH_EVENT_AV_CONNECTED: + signal = BT_STEREO_HEADSET_CONNECTED; + break; + case BLUETOOTH_EVENT_AV_DISCONNECTED: + signal = BT_STEREO_HEADSET_DISCONNECTED; + break; + case BLUETOOTH_EVENT_AG_AUDIO_CONNECTED: + signal = BT_SCO_CONNECTED; + break; + case BLUETOOTH_EVENT_AG_AUDIO_DISCONNECTED: + signal = BT_SCO_DISCONNECTED; + break; + case BLUETOOTH_EVENT_AG_SPEAKER_GAIN: + signal = BT_SPEAKER_GAIN; + break; + case BLUETOOTH_EVENT_AG_MIC_GAIN: + signal = BT_MICROPHONE_GAIN; + break; + case BLUETOOTH_EVENT_NETWORK_CONNECTED: + signal = BT_NETWORK_CONNECTED; + break; + case BLUETOOTH_EVENT_NETWORK_DISCONNECTED: + signal = BT_NETWORK_DISCONNECTED; + break; + case BLUETOOTH_EVENT_NETWORK_SERVER_CONNECTED: + signal = BT_NETWORK_SERVER_CONNECTED; + break; + case BLUETOOTH_EVENT_NETWORK_SERVER_DISCONNECTED: + signal = BT_NETWORK_SERVER_DISCONNECTED; + break; + case BLUETOOTH_EVENT_OPC_CONNECTED: + signal = BT_OPP_CONNECTED; + break; + case BLUETOOTH_EVENT_OPC_DISCONNECTED: + signal = BT_OPP_DISCONNECTED; + break; + case BLUETOOTH_EVENT_OPC_TRANSFER_STARTED: + case BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_STARTED: + signal = BT_TRANSFER_STARTED; + break; + case BLUETOOTH_EVENT_OPC_TRANSFER_PROGRESS: + case BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_PROGRESS: + signal = BT_TRANSFER_PROGRESS; + break; + case BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE: + case BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_COMPLETED: + signal = BT_TRANSFER_COMPLETED; + break; + case BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_AUTHORIZE: + signal = BT_TRANSFER_AUTHORIZED; + break; + case BLUETOOTH_EVENT_OBEX_SERVER_CONNECTION_AUTHORIZE: + case BLUETOOTH_EVENT_RFCOMM_AUTHORIZE: + signal = BT_CONNECTION_AUTHORIZED; + break; + case BLUETOOTH_EVENT_RFCOMM_CONNECTED: + signal = BT_RFCOMM_CONNECTED; + break; + case BLUETOOTH_EVENT_RFCOMM_DISCONNECTED: + signal = BT_RFCOMM_DISCONNECTED; + break; + case BLUETOOTH_EVENT_RFCOMM_DATA_RECEIVED: + signal = BT_RFCOMM_DATA_RECEIVED; + break; + case BLUETOOTH_EVENT_RFCOMM_SERVER_REMOVED: + signal = BT_RFCOMM_SERVER_REMOVED; + break; + case BLUETOOTH_EVENT_DEVICE_CONNECTED: + signal = BT_DEVICE_CONNECTED; + break; + case BLUETOOTH_EVENT_DEVICE_DISCONNECTED: + signal = BT_DEVICE_DISCONNECTED; + break; + case BLUETOOTH_EVENT_AVRCP_SETTING_SHUFFLE_STATUS: + signal = BT_MEDIA_SHUFFLE_STATUS; + break; + case BLUETOOTH_EVENT_AVRCP_SETTING_EQUALIZER_STATUS: + signal = BT_MEDIA_EQUALIZER_STATUS; + break; + case BLUETOOTH_EVENT_AVRCP_SETTING_REPEAT_STATUS: + signal = BT_MEDIA_REPEAT_STATUS; + break; + case BLUETOOTH_EVENT_AVRCP_SETTING_SCAN_STATUS: + signal = BT_MEDIA_SCAN_STATUS; + break; + default: + BT_ERR("Unknown event"); + return BLUETOOTH_ERROR_INTERNAL; + } + + msg = dbus_message_new_signal(path, BT_EVENT_SERVICE, + signal); + + if (msg == NULL) { + BT_ERR("Message is NULL\n"); + return BLUETOOTH_ERROR_INTERNAL; + } + + 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\n"); + dbus_message_unref(msg); + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_connection_flush(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) +{ + DBusConnection *conn; + DBusError err; + int ret; + + if (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_EVENT_SERVICE, + 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; + } + + event_conn = conn; + + return BLUETOOTH_ERROR_NONE; +} + +void _bt_deinit_service_event_sender(void) +{ + if (event_conn) { + dbus_connection_close(event_conn); + event_conn = NULL; + } +} + diff --git a/bt-service/bt-service-gap-agent.c b/bt-service/bt-service-gap-agent.c new file mode 100644 index 0000000..8b6ddf7 --- /dev/null +++ b/bt-service/bt-service-gap-agent.c @@ -0,0 +1,952 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "bt-service-common.h" +#include "bt-service-agent.h" +#include "bt-service-gap-agent.h" +#include "bt-service-adapter.h" + +static DBusGConnection *connection = NULL; + +typedef enum { + GAP_AGENT_EXEC_NO_OPERATION, + GAP_AGENT_EXEC_PAIRING, + GAP_AGENT_EXEC_AUTHORZATION, + GAP_AGENT_EXEC_CONFIRM_MODE, +} GapAgentExecType; + +typedef struct _GapAgentPrivate GapAgentPrivate; + +struct _GapAgentPrivate { + gchar *busname; + gchar *path; + DBusGProxy *adapter; + DBusGProxy *dbus_proxy; + + GapAgentExecType exec_type; + DBusGMethodInvocation *reply_context; + + char pairing_addr[18]; + char authorize_addr[18]; + + GSList *osp_servers; + + GAP_AGENT_FUNC_CB cb; + gboolean canceled; +}; + +G_DEFINE_TYPE(GapAgent, gap_agent, G_TYPE_OBJECT); + +static gboolean gap_agent_request_pin_code(GapAgent *agent, + const char *path, + DBusGMethodInvocation *context); + +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, + DBusGMethodInvocation *context); + +static gboolean gap_agent_request_confirmation(GapAgent *agent, + const char *path, + guint passkey, + DBusGMethodInvocation *context); + +static gboolean gap_agent_authorize(GapAgent *agent, const char *path, + const char *uuid, + DBusGMethodInvocation *context); + +static gboolean gap_agent_cancel(GapAgent *agent, + DBusGMethodInvocation *context); + +static gboolean gap_agent_release(GapAgent *agent, + DBusGMethodInvocation *context); + +static gboolean gap_agent_confirm_mode_change(GapAgent *agent, + const char *mode, + DBusGMethodInvocation *context); + +static gboolean gap_agent_get_discoverable_timeout(GapAgent *agent, + DBusGMethodInvocation *context); + +#include "bt-gap-agent-method.h" + +typedef enum { + GAP_AGENT_ERROR_REJECT, + GAP_AGENT_ERROR_CANCEL, + GAP_AGENT_ERROR_TIMEOUT, +} GapAgentError; + +#define GAP_AGENT_ERROR (gap_agent_error_quark()) + +static GQuark gap_agent_error_quark(void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string("agent"); + + return quark; +} + +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +static GError *gap_agent_error(GapAgentError error, const char *err_msg) +{ + return g_error_new(GAP_AGENT_ERROR, error, err_msg, NULL); +} + +static void gap_agent_init(GapAgent *agent) +{ + BT_DBG("agent %p\n", agent); +} + +static void gap_agent_finalize(GObject *agent) +{ + BT_DBG("Free agent %p\n", agent); + + G_OBJECT_CLASS(gap_agent_parent_class)->finalize(agent); +} + +static void gap_agent_class_init(GapAgentClass *klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; + GError *error = NULL; + + BT_DBG("class %p\n", klass); + + g_type_class_add_private(klass, sizeof(GapAgentPrivate)); + + object_class->finalize = gap_agent_finalize; + + connection = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error); + + if (error != NULL) { + g_printerr("Connecting to system bus failed: %s\n", + error->message); + g_error_free(error); + } + + dbus_g_object_type_install_info(GAP_TYPE_AGENT, + &dbus_glib_gap_agent_object_info); +} + +GapAgent *_gap_agent_new(void) +{ + GapAgent *agent; + + agent = GAP_GET_AGENT(g_object_new(GAP_TYPE_AGENT, NULL)); + + BT_DBG("agent %p\n", agent); + + return agent; +} + +static gboolean gap_agent_request_pin_code(GapAgent *agent, + const char *path, + DBusGMethodInvocation *context) +{ + GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); + char *sender = dbus_g_method_get_sender(context); + DBusGProxy *device; + gboolean result; + char *addr; + + 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); + + if (g_strcmp0(sender, priv->busname) != 0) { + g_free(sender); + return FALSE; + } + + if (!priv->cb.passkey_func) { + g_free(sender); + return FALSE; + } + + device = dbus_g_proxy_new_from_proxy(priv->adapter, + BLUEZ_DEVICE_INTERFACE, 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"); + dbus_g_method_return_error(context, error); + g_error_free(error); + g_free(sender); + return FALSE; + } + + priv->exec_type = GAP_AGENT_EXEC_PAIRING; + priv->reply_context = context; + + addr = strstr(path, "dev_"); + if (addr != NULL) { + char *pos = NULL; + addr += 4; + g_strlcpy(priv->pairing_addr, addr, sizeof(priv->pairing_addr)); + + while ((pos = strchr(priv->pairing_addr, '_')) != NULL) { + *pos = ':'; + } + } + + result = priv->cb.pincode_func(agent, device); + + g_object_unref(device); + + g_free(sender); + return result; +} + +static gboolean gap_agent_request_passkey(GapAgent *agent, const char *path, + DBusGMethodInvocation *context) +{ + GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); + char *sender = dbus_g_method_get_sender(context); + DBusGProxy *device; + gboolean result; + char *addr; + + if (sender == NULL) + return FALSE; + + BT_DBG("Request passkey : 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); + return FALSE; + } + + if (!priv->cb.passkey_func) { + g_free(sender); + return FALSE; + } + + device = dbus_g_proxy_new_from_proxy(priv->adapter, + BLUEZ_DEVICE_INTERFACE, + 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"); + dbus_g_method_return_error(context, error); + g_error_free(error); + g_free(sender); + return FALSE; + } + + priv->exec_type = GAP_AGENT_EXEC_PAIRING; + priv->reply_context = context; + + addr = strstr(path, "dev_"); + if (addr != NULL) { + char *pos = NULL; + addr += 4; + g_strlcpy(priv->pairing_addr, addr, sizeof(priv->pairing_addr)); + + while ((pos = strchr(priv->pairing_addr, '_')) != NULL) { + *pos = ':'; + } + } + + result = priv->cb.passkey_func(agent, device); + + g_object_unref(device); + + g_free(sender); + return result; + +} + +static gboolean gap_agent_display_passkey(GapAgent *agent, const char *path, + guint passkey, + DBusGMethodInvocation *context) +{ + GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); + char *sender = dbus_g_method_get_sender(context); + DBusGProxy *device; + gboolean result; + + 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); + + if (g_strcmp0(sender, priv->busname) != 0) { + g_free(sender); + return FALSE; + } + + if (!priv->cb.display_func) { + g_free(sender); + return FALSE; + } + + device = dbus_g_proxy_new_from_proxy(priv->adapter, + BLUEZ_DEVICE_INTERFACE, + 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"); + dbus_g_method_return_error(context, error); + g_error_free(error); + g_free(sender); + return FALSE; + } + + dbus_g_method_return(context); + + result = priv->cb.display_func(agent, device, passkey); + + g_object_unref(device); + + g_free(sender); + return result; +} + +static gboolean gap_agent_request_confirmation(GapAgent *agent, + const char *path, + guint passkey, + DBusGMethodInvocation *context) +{ + GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); + char *sender = dbus_g_method_get_sender(context); + DBusGProxy *device; + gboolean result; + char *addr; + + 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); + + if (g_strcmp0(sender, priv->busname) != 0) { + g_free(sender); + return FALSE; + } + + if (!priv->cb.confirm_func) { + g_free(sender); + return FALSE; + } + + device = dbus_g_proxy_new_from_proxy(priv->adapter, + BLUEZ_DEVICE_INTERFACE, + 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"); + dbus_g_method_return_error(context, error); + g_error_free(error); + g_free(sender); + return FALSE; + } + + priv->exec_type = GAP_AGENT_EXEC_PAIRING; + priv->reply_context = context; + + addr = strstr(path, "dev_"); + if (addr != NULL) { + char *pos = NULL; + addr += 4; + g_strlcpy(priv->pairing_addr, addr, sizeof(priv->pairing_addr)); + + while ((pos = strchr(priv->pairing_addr, '_')) != NULL) { + *pos = ':'; + } + } + + result = priv->cb.confirm_func(agent, device, passkey); + + g_object_unref(device); + + g_free(sender); + return result; +} + +static gboolean gap_agent_authorize(GapAgent *agent, const char *path, + const char *uuid, + DBusGMethodInvocation *context) +{ + GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); + char *sender = dbus_g_method_get_sender(context); + DBusGProxy *device; + gboolean result; + char *addr; + + if (sender == NULL) + return FALSE; + + BT_DBG("Request authorization : 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); + return FALSE; + } + + if (!priv->cb.authorize_func) { + g_free(sender); + return FALSE; + } + + device = dbus_g_proxy_new_from_proxy(priv->adapter, + BLUEZ_DEVICE_INTERFACE, + 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"); + dbus_g_method_return_error(context, error); + g_error_free(error); + g_free(sender); + return FALSE; + } + + priv->exec_type = GAP_AGENT_EXEC_AUTHORZATION; + priv->reply_context = context; + + addr = strstr(path, "dev_"); + if (addr != NULL) { + char *pos = NULL; + addr += 4; + g_strlcpy(priv->authorize_addr, addr, + sizeof(priv->authorize_addr)); + + while ((pos = strchr(priv->authorize_addr, '_')) != NULL) { + *pos = ':'; + } + } + + result = priv->cb.authorize_func(agent, device, uuid); + + g_object_unref(device); + + g_free(sender); + return result; +} + +static gboolean gap_agent_confirm_mode_change(GapAgent *agent, + const char *mode, + DBusGMethodInvocation *context) +{ + BT_DBG(""); + + dbus_g_method_return(context); + return TRUE; +} + +static gboolean gap_agent_cancel(GapAgent *agent, + DBusGMethodInvocation *context) +{ + GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); + char *sender = dbus_g_method_get_sender(context); + gboolean result = FALSE; + + if (sender == NULL) + return FALSE; + + BT_DBG("Cancelled : agent %p sender %s\n", agent, sender); + + if (g_strcmp0(sender, priv->busname) != 0) { + g_free(sender); + return FALSE; + } + + if (priv->cb.authorization_cancel_func && + priv->exec_type == GAP_AGENT_EXEC_AUTHORZATION) { + result = priv->cb.authorization_cancel_func(agent, + priv->authorize_addr); + memset(priv->authorize_addr, 0x00, + sizeof(priv->authorize_addr)); + } else if (priv->cb.pairing_cancel_func && + priv->exec_type == GAP_AGENT_EXEC_PAIRING) { + result = priv->cb.pairing_cancel_func(agent, + priv->pairing_addr); + memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr)); + } + + if (priv->exec_type != GAP_AGENT_EXEC_CONFIRM_MODE && + priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION && + priv->reply_context != NULL) { + GError *error = gap_agent_error(GAP_AGENT_ERROR_REJECT, + "Rejected by remote cancel"); + dbus_g_method_return_error(priv->reply_context, error); + g_error_free(error); + } + + priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION; + priv->reply_context = NULL; + + g_free(sender); + return result; +} + +static gboolean gap_agent_release(GapAgent *agent, + DBusGMethodInvocation *context) +{ + GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); + char *sender = dbus_g_method_get_sender(context); + + if (sender == NULL) + return FALSE; + + BT_DBG("Released : agent %p sender %s\n", agent, sender); + + if (g_strcmp0(sender, priv->busname) != 0) { + g_free(sender); + return FALSE; + } + + dbus_g_method_return(context); + + priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION; + priv->reply_context = NULL; + + memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr)); + memset(priv->authorize_addr, 0x00, sizeof(priv->authorize_addr)); + + g_free(sender); + return TRUE; +} + +static bt_agent_osp_server_t *__gap_agent_find_server(GSList *servers, + int type, + const char *uuid) +{ + GSList *l; + bt_agent_osp_server_t *transfer; + + for (l = servers; l != NULL; l = l->next) { + transfer = l->data; + + if (transfer == NULL) + continue; + + /* No uuid in obex server */ + if (type == BT_OBEX_SERVER && + transfer->type == BT_OBEX_SERVER) + return transfer; + + if (g_strcmp0(transfer->uuid, uuid) == 0) + return transfer; + } + + return NULL; +} + +static void __gap_agent_remove_osp_servers(GSList *osp_servers) +{ + GSList *l; + bt_agent_osp_server_t *server; + + for (l = osp_servers; l != NULL; l = g_slist_next(l)) { + server = l->data; + + if (server == NULL) + continue; + + g_free(server->uuid); + g_free(server); + } +} + +gboolean _gap_agent_register_osp_server(GapAgent *agent, + const gint type, + const char *uuid) +{ + bt_agent_osp_server_t *server; + + BT_DBG("+"); + + GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); + + if (priv == NULL) + return FALSE; + + /* type: BT_OBEX_SERVER / BT_RFCOMM_SERVER*/ + if (type > BT_RFCOMM_SERVER) + return FALSE; + + server = g_malloc0(sizeof(bt_agent_osp_server_t)); + + server->type = type; + + if (type == BT_RFCOMM_SERVER) + server->uuid = g_strdup(uuid); + + priv->osp_servers = g_slist_append(priv->osp_servers, server); + + BT_DBG("-"); + + return TRUE; +} + +gboolean _gap_agent_unregister_osp_server(GapAgent *agent, + const gint type, + const char *uuid) +{ + bt_agent_osp_server_t *server; + + BT_DBG("+"); + + GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); + + if (priv == NULL) + return FALSE; + + /* type: BT_OBEX_SERVER / BT_RFCOMM_SERVER*/ + if (type > BT_RFCOMM_SERVER) + return FALSE; + + server = __gap_agent_find_server(priv->osp_servers, type, uuid); + + if (server == NULL) + return FALSE; + + priv->osp_servers = g_slist_remove(priv->osp_servers, server); + + g_free(server->uuid); + g_free(server); + + BT_DBG("-"); + + return TRUE; +} + +gboolean gap_agent_reply_pin_code(GapAgent *agent, const guint accept, + const char *pin_code, + DBusGMethodInvocation *context) +{ + BT_DBG("+\n"); + + GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); + + if (priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION && + priv->reply_context != NULL) { + if (accept == GAP_AGENT_ACCEPT) { + dbus_g_method_return(priv->reply_context, pin_code); + priv->canceled = FALSE; + } else { + GError *error = NULL; + switch (accept) { + case GAP_AGENT_CANCEL: + error = gap_agent_error(GAP_AGENT_ERROR_CANCEL, + "CanceledbyUser"); + priv->canceled = TRUE; + break; + case GAP_AGENT_TIMEOUT: + case GAP_AGENT_REJECT: + default: + error = gap_agent_error(GAP_AGENT_ERROR_REJECT, + "Pairing request rejected"); + priv->canceled = FALSE; + break; + } + dbus_g_method_return_error(priv->reply_context, error); + g_error_free(error); + } + } + + priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION; + priv->reply_context = NULL; + memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr)); + + BT_DBG("-\n"); + + return TRUE; +} + +gboolean gap_agent_reply_passkey(GapAgent *agent, const guint accept, + const char *passkey, + DBusGMethodInvocation *context) +{ + BT_DBG("+\n"); + + GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); + + if (priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION && + priv->reply_context != NULL) { + if (accept == GAP_AGENT_ACCEPT) { + guint pass_key = atoi(passkey); + dbus_g_method_return(priv->reply_context, pass_key); + priv->canceled = FALSE; + } else { + GError *error = NULL; + switch (accept) { + case GAP_AGENT_CANCEL: + error = gap_agent_error(GAP_AGENT_ERROR_CANCEL, + "CanceledbyUser"); + priv->canceled = TRUE; + break; + case GAP_AGENT_TIMEOUT: + case GAP_AGENT_REJECT: + default: + error = gap_agent_error(GAP_AGENT_ERROR_REJECT, + "Passkey request rejected"); + priv->canceled = FALSE; + break; + } + dbus_g_method_return_error(priv->reply_context, error); + g_error_free(error); + } + } + + priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION; + priv->reply_context = NULL; + memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr)); + + BT_DBG("-\n"); + + return TRUE; +} + +gboolean gap_agent_reply_confirmation(GapAgent *agent, const guint accept, + DBusGMethodInvocation *context) +{ + BT_DBG("+\n"); + + GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); + + if (priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION && + priv->reply_context != NULL) { + if (accept == GAP_AGENT_ACCEPT) { + dbus_g_method_return(priv->reply_context); + priv->canceled = FALSE; + } else { + GError *error = NULL; + switch (accept) { + case GAP_AGENT_CANCEL: + error = gap_agent_error(GAP_AGENT_ERROR_CANCEL, + "CanceledbyUser"); + priv->canceled = TRUE; + break; + case GAP_AGENT_TIMEOUT: + case GAP_AGENT_REJECT: + default: + error = gap_agent_error(GAP_AGENT_ERROR_REJECT, + "Confirmation request rejected"); + priv->canceled = FALSE; + break; + } + dbus_g_method_return_error(priv->reply_context, error); + g_error_free(error); + } + } + + priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION; + priv->reply_context = NULL; + memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr)); + + BT_DBG("-\n"); + + return TRUE; +} + +gboolean gap_agent_reply_authorize(GapAgent *agent, const guint accept, + DBusGMethodInvocation *context) +{ + gboolean ret = TRUE; + + BT_DBG("+\n"); + + GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); + + if (priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION && + priv->reply_context != NULL) { + if (accept == GAP_AGENT_ACCEPT) { + dbus_g_method_return(priv->reply_context); + } else { + GError *error = NULL; + switch (accept) { + case GAP_AGENT_CANCEL: + error = gap_agent_error(GAP_AGENT_ERROR_CANCEL, + "CanceledbyUser"); + break; + case GAP_AGENT_TIMEOUT: + case GAP_AGENT_REJECT: + default: + error = gap_agent_error(GAP_AGENT_ERROR_REJECT, + "Authorization request rejected"); + break; + } + dbus_g_method_return_error(priv->reply_context, error); + g_error_free(error); + } + + if (context) + dbus_g_method_return(context); + } else { + GError *error = gap_agent_error(GAP_AGENT_ERROR_REJECT, + "No context"); + BT_DBG("No context"); + + if (context) + dbus_g_method_return_error(context, error); + + g_error_free(error); + ret = FALSE; + } + + priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION; + priv->reply_context = NULL; + memset(priv->authorize_addr, 0x00, sizeof(priv->authorize_addr)); + + BT_DBG("-\n"); + + return ret; +} + +static gboolean gap_agent_get_discoverable_timeout(GapAgent *agent, + DBusGMethodInvocation *context) +{ + BT_DBG("+\n"); + + int timeout; + + _bt_get_timeout_value(&timeout); + + dbus_g_method_return(context, timeout); + + BT_DBG("-\n"); + + return TRUE; +} + +gboolean _gap_agent_register(GapAgent *agent) +{ + GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); + GError *error = NULL; + + dbus_g_proxy_call(priv->adapter, "RegisterAgent", &error, + DBUS_TYPE_G_OBJECT_PATH, priv->path, + G_TYPE_STRING, "DisplayYesNo", G_TYPE_INVALID, + G_TYPE_INVALID); + if (error != NULL) { + BT_DBG("Agent registration failed: %s\n", error->message); + g_error_free(error); + return FALSE; + } + + return TRUE; +} + +void _gap_agent_setup_dbus(GapAgent *agent, GAP_AGENT_FUNC_CB *func_cb, + const char *path, + DBusGProxy *adapter) +{ + GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); + GObject *object; + DBusGProxy *proxy; + + priv->path = g_strdup(path); + + object = dbus_g_connection_lookup_g_object(connection, priv->path); + if (object != NULL) + g_object_unref(object); + + dbus_g_connection_register_g_object(connection, priv->path, + G_OBJECT(agent)); + + memcpy(&priv->cb, func_cb, sizeof(GAP_AGENT_FUNC_CB)); + + priv->exec_type = GAP_AGENT_EXEC_NO_OPERATION; + memset(priv->pairing_addr, 0x00, sizeof(priv->pairing_addr)); + memset(priv->authorize_addr, 0x00, sizeof(priv->authorize_addr)); + priv->reply_context = NULL; + + priv->adapter = g_object_ref(adapter); + + proxy = dbus_g_proxy_new_for_name_owner(connection, + dbus_g_proxy_get_bus_name(priv->adapter), + dbus_g_proxy_get_path(priv->adapter), + dbus_g_proxy_get_interface(priv->adapter), + NULL); + if (proxy != NULL) { + priv->busname = g_strdup(dbus_g_proxy_get_bus_name(proxy)); + g_object_unref(proxy); + } else + priv->busname = g_strdup(dbus_g_proxy_get_bus_name(adapter)); +} + +void _gap_agent_reset_dbus(GapAgent *agent) +{ + GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); + + dbus_g_connection_unregister_g_object(connection, G_OBJECT(agent)); + + if (priv->osp_servers) { + __gap_agent_remove_osp_servers(priv->osp_servers); + g_slist_free(priv->osp_servers); + priv->osp_servers = NULL; + } + + g_object_ref(priv->adapter); + priv->adapter = NULL; + + g_free(priv->path); + priv->path = NULL; + + g_free(priv->busname); + priv->busname = NULL; +} + +gboolean _gap_agent_exist_osp_server(GapAgent *agent, int type, char *uuid) +{ + GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); + + if (priv == NULL) + return FALSE; + + if (__gap_agent_find_server(priv->osp_servers, + type, uuid) != NULL) { + return TRUE; + } + + return FALSE; +} + +gchar* _gap_agent_get_path(GapAgent *agent) +{ + GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); + + return priv->path; +} + +gboolean _gap_agent_is_canceled(GapAgent *agent) +{ + GapAgentPrivate *priv = GAP_AGENT_GET_PRIVATE(agent); + + return priv->canceled; +} diff --git a/bt-service/bt-service-gap-agent.xml b/bt-service/bt-service-gap-agent.xml new file mode 100644 index 0000000..f3438cb --- /dev/null +++ b/bt-service/bt-service-gap-agent.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bt-service/bt-service-hid.c b/bt-service/bt-service-hid.c new file mode 100644 index 0000000..4b7a829 --- /dev/null +++ b/bt-service/bt-service-hid.c @@ -0,0 +1,263 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "bluetooth-api.h" +#include "bt-service-common.h" +#include "bt-service-hid.h" +#include "bt-service-event.h" +#include "bt-service-util.h" + +static void __bt_hid_connect_cb(DBusGProxy *proxy, DBusGProxyCall *call, + gpointer user_data) +{ + GError *g_error = NULL; + GArray *out_param1 = NULL; + GArray *out_param2 = NULL; + bluetooth_device_address_t device_addr = { {0} }; + int result = BLUETOOTH_ERROR_NONE; + bt_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; + } + + 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) { + 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; + + out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar)); + out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar)); + + _bt_convert_addr_string_to_type(device_addr.addr, + func_data->address); + + g_array_append_vals(out_param1, &device_addr, + sizeof(bluetooth_device_address_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 (g_error) + g_error_free(g_error); + + if (func_data) { + g_free(func_data->address); + g_free(func_data); + } +} + +static void __bt_hid_disconnect_cb(DBusGProxy *proxy, DBusGProxyCall *call, + gpointer user_data) +{ + GError *g_error = NULL; + GArray *out_param1 = NULL; + GArray *out_param2 = NULL; + bluetooth_device_address_t device_addr = { {0} }; + int result = BLUETOOTH_ERROR_NONE; + bt_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; + } + + 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) { + 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; + + out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar)); + out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar)); + + _bt_convert_addr_string_to_type(device_addr.addr, + func_data->address); + + g_array_append_vals(out_param1, &device_addr, + sizeof(bluetooth_device_address_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 (g_error) + g_error_free(g_error); + + if (func_data) { + g_free(func_data->address); + g_free(func_data); + } +} + + +/********************************************************************** +* HID APIs * +***********************************************************************/ + +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); + + 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); + + dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL, + G_TYPE_STRING, address, G_TYPE_INVALID, + DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID); + + if (device_path == NULL) { + BT_ERR("No paired device"); + return BLUETOOTH_ERROR_NOT_PAIRED; + } + + hid_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + device_path, BT_INPUT_INTERFACE); + 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, "Connect", + (DBusGProxyCallNotify)__bt_hid_connect_cb, + func_data, NULL, G_TYPE_INVALID)) { + BT_ERR("Hidh connect Dbus Call Error"); + g_object_unref(hid_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + + 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); + + 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); + + dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL, + G_TYPE_STRING, address, G_TYPE_INVALID, + DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID); + + if (device_path == NULL) { + BT_ERR("No paired device"); + return BLUETOOTH_ERROR_NOT_PAIRED; + } + + hid_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + device_path, BT_INPUT_INTERFACE); + 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); + return BLUETOOTH_ERROR_INTERNAL; + } + + return BLUETOOTH_ERROR_NONE; +} diff --git a/bt-service/bt-service-main.c b/bt-service/bt-service-main.c new file mode 100644 index 0000000..c3a13f8 --- /dev/null +++ b/bt-service/bt-service-main.c @@ -0,0 +1,183 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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-internal-types.h" +#include "bt-service-common.h" +#include "bt-service-event.h" +#include "bt-service-main.h" +#include "bt-service-util.h" +#include "bt-request-handler.h" +#include "bt-service-adapter.h" + +static GMainLoop *main_loop; +static gboolean terminated; + +static void __bt_release_service(void) +{ + _bt_deinit_service_event_sender(); + _bt_deinit_service_event_reciever(); + + _bt_service_unregister(); + + _bt_deinit_proxys(); + + _bt_clear_request_list(); +} + +static void __bt_sigterm_handler(int signo) +{ + BT_DBG("Get the signal: %d", signo); + + _bt_terminate_service(NULL); +} + +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"); + + _bt_deinit_bluez_proxy(); + + return FALSE; + } + + if (main_loop != NULL) { + g_main_loop_quit(main_loop); + } else { + BT_DBG("main_loop == NULL"); + __bt_release_service(); + terminated = TRUE; + exit(0); + } + + return FALSE; +} + +static gboolean __bt_check_bt_service(void *data) +{ + int bt_status = VCONFKEY_BT_STATUS_OFF; + int flight_mode_deactivation = 0; + + 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"); + + if (bt_status != VCONFKEY_BT_STATUS_OFF) { + BT_DBG("Previous session was enabled."); + + /* Enable the BT */ + _bt_enable_adapter(); + } else if (bt_status == VCONFKEY_BT_STATUS_OFF && + flight_mode_deactivation == 1) { + _bt_handle_flight_mode_noti(); + } else { + bt_status_t status = _bt_adapter_get_status(); + int adapter_enabled = 0; + + _bt_check_adapter(&adapter_enabled); + + BT_DBG("State: %d", status); + BT_DBG("Adapter enabled: %d", adapter_enabled); + + if (adapter_enabled == 1) { + _bt_handle_adapter_added(); + return FALSE; + } + + if (status != BT_ACTIVATING && status != BT_ACTIVATED) { + _bt_terminate_service(NULL); + } + } + + return FALSE; +} + +int main(int argc, char *argv[]) +{ + struct sigaction sa; + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = __bt_sigterm_handler; + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + + g_type_init(); + + if (set_app_privilege("bluetooth-frwk-service", NULL, NULL) != + PC_OPERATION_SUCCESS) + BT_ERR("Failed to set app privilege.\n"); + + /* Event reciever Init */ + if (_bt_init_service_event_receiver() != BLUETOOTH_ERROR_NONE) { + BT_ERR("Fail to init event reciever"); + return 0; + } + + /* Event sender Init */ + if (_bt_init_service_event_sender() != BLUETOOTH_ERROR_NONE) { + BT_ERR("Fail to init event sender"); + return 0; + } + + if (_bt_service_register() != BLUETOOTH_ERROR_NONE) { + BT_ERR("Fail to register service"); + return 0; + } + + _bt_init_request_id(); + + _bt_init_request_list(); + + g_idle_add((GSourceFunc)__bt_check_bt_service, NULL); + + if (terminated == TRUE) { + __bt_release_service(); + return 0; + } + + main_loop = g_main_loop_new(NULL, FALSE); + + g_main_loop_run(main_loop); + + if (main_loop != NULL) { + g_main_loop_unref(main_loop); + } + + __bt_release_service(); + + BT_DBG("-"); + + return 0; +} + diff --git a/bt-service/bt-service-media-agent.xml b/bt-service/bt-service-media-agent.xml new file mode 100644 index 0000000..d3fcb57 --- /dev/null +++ b/bt-service/bt-service-media-agent.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/bt-service/bt-service-network.c b/bt-service/bt-service-network.c new file mode 100644 index 0000000..81d0d59 --- /dev/null +++ b/bt-service/bt-service-network.c @@ -0,0 +1,362 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "bluetooth-api.h" +#include "bt-service-network.h" +#include "bt-service-common.h" +#include "bt-service-event.h" +#include "bt-service-util.h" + +static void __bt_network_connect_cb(DBusGProxy *proxy, DBusGProxyCall *call, + gpointer user_data) +{ + GError *g_error = NULL; + char *device = NULL; + GArray *out_param1 = NULL; + GArray *out_param2 = NULL; + bluetooth_device_address_t device_addr = { {0} }; + int result = BLUETOOTH_ERROR_NONE; + bt_function_data_t *func_data; + request_info_t *req_info; + + dbus_g_proxy_end_call(proxy, call, &g_error, G_TYPE_STRING, &device, G_TYPE_INVALID); + + g_object_unref(proxy); + + func_data = user_data; + + if (func_data == NULL) { + /* Send reply */ + BT_ERR("func_data == NULL"); + goto done; + } + + 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) { + 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; + + out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar)); + out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar)); + + _bt_convert_addr_string_to_type(device_addr.addr, + func_data->address); + + g_array_append_vals(out_param1, &device_addr, + sizeof(bluetooth_device_address_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 (g_error) + g_error_free(g_error); + + if (func_data) { + g_free(func_data->address); + g_free(func_data); + } +} + +static void __bt_network_disconnect_cb(DBusGProxy *proxy, DBusGProxyCall *call, + gpointer user_data) +{ + GError *g_error = NULL; + GArray *out_param1 = NULL; + GArray *out_param2 = NULL; + bluetooth_device_address_t device_addr = { {0} }; + int result = BLUETOOTH_ERROR_NONE; + bt_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; + } + + 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) { + 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; + + out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar)); + out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar)); + + _bt_convert_addr_string_to_type(device_addr.addr, + func_data->address); + + g_array_append_vals(out_param1, &device_addr, + sizeof(bluetooth_device_address_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 (g_error) + g_error_free(g_error); + + if (func_data) { + g_free(func_data->address); + g_free(func_data); + } +} + +int _bt_network_activate(void) +{ + int ret = BLUETOOTH_ERROR_NONE; + char *adapter_path; + GError *err = NULL; + DBusGConnection *conn; + DBusGProxy *server_proxy; + + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + adapter_path = _bt_get_adapter_path(); + retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL); + + server_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + adapter_path, BT_NETWORK_SERVER_INTERFACE); + + g_free(adapter_path); + + if (server_proxy == NULL) { + BT_ERR("Failed to get the network server proxy\n"); + return BLUETOOTH_ERROR_INTERNAL; + } + + if (!dbus_g_proxy_call(server_proxy, "Register", &err, + G_TYPE_STRING, NAP_UUID_NAME, + G_TYPE_STRING, NET_BRIDGE_INTERFACE, + G_TYPE_INVALID, G_TYPE_INVALID)) { + if (err != NULL) { + BT_ERR("Network server register Error: %s\n", err->message); + if (g_strcmp0(err->message, "Already Exists") == 0) { + ret = BLUETOOTH_ERROR_ALREADY_INITIALIZED; + } else { + ret = BLUETOOTH_ERROR_INTERNAL; + } + g_error_free(err); + } + } + + g_object_unref(server_proxy); + + return ret; +} + +int _bt_network_deactivate(void) +{ + char *adapter_path; + GError *err = NULL; + DBusGConnection *conn; + DBusGProxy *server_proxy; + + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + adapter_path = _bt_get_adapter_path(); + retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL); + + server_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + adapter_path, BT_NETWORK_SERVER_INTERFACE); + + g_free(adapter_path); + + if (server_proxy == NULL) { + BT_ERR("Failed to get the network server proxy\n"); + return BLUETOOTH_ERROR_INTERNAL; + } + + if (!dbus_g_proxy_call(server_proxy, "Unregister", &err, + G_TYPE_STRING, NAP_UUID_NAME, + G_TYPE_INVALID, G_TYPE_INVALID)) { + if (err != NULL) { + BT_ERR("Network server unregister Error: %s\n", err->message); + g_error_free(err); + } + g_object_unref(server_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + + g_object_unref(server_proxy); + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_network_connect(int request_id, int role, + bluetooth_device_address_t *device_address) +{ + gchar *device_path = NULL; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + char remote_role[BLUETOOTH_UUID_STRING_MAX] = { 0 }; + bt_function_data_t *func_data; + DBusGProxy *adapter_proxy; + DBusGProxy *profile_proxy; + DBusGConnection *conn; + + BT_CHECK_PARAMETER(device_address); + + switch (role) { + case BLUETOOTH_NETWORK_PANU_ROLE: + g_strlcpy(remote_role, PANU_UUID_NAME, BLUETOOTH_UUID_STRING_MAX); + break; + + case BLUETOOTH_NETWORK_NAP_ROLE: + g_strlcpy(remote_role, NAP_UUID_NAME, BLUETOOTH_UUID_STRING_MAX); + break; + + case BLUETOOTH_NETWORK_GN_ROLE: + g_strlcpy(remote_role, GN_UUID_NAME, BLUETOOTH_UUID_STRING_MAX); + break; + default: + BT_ERR("Unknown role"); + return BLUETOOTH_ERROR_INTERNAL; + } + + 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); + + dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL, + G_TYPE_STRING, address, G_TYPE_INVALID, + DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID); + + if (device_path == NULL) { + BT_ERR("No paired device"); + return BLUETOOTH_ERROR_NOT_PAIRED; + } + + profile_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + device_path, BT_NETWORK_CLIENT_INTERFACE); + g_free(device_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, "Connect", + (DBusGProxyCallNotify)__bt_network_connect_cb, + func_data, NULL, + G_TYPE_STRING, remote_role, + G_TYPE_INVALID)) { + BT_ERR("network connect Dbus Call Error"); + g_object_unref(profile_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_network_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 *profile_proxy; + DBusGConnection *conn; + + BT_CHECK_PARAMETER(device_address); + + 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); + + dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL, + G_TYPE_STRING, address, G_TYPE_INVALID, + DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID); + + if (device_path == NULL) { + BT_ERR("No paired device"); + return BLUETOOTH_ERROR_NOT_PAIRED; + } + + profile_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + device_path, BT_NETWORK_CLIENT_INTERFACE); + g_free(device_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_INVALID)) { + BT_ERR("network disconnect Dbus Call Error"); + 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 new file mode 100644 index 0000000..28f8e08 --- /dev/null +++ b/bt-service/bt-service-obex-agent.c @@ -0,0 +1,439 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "bluetooth-api.h" +#include "bt-service-common.h" +#include "bt-service-event.h" +#include "bt-service-util.h" +#include "bt-service-obex-agent.h" +#include "marshal.h" +#include "bt-obex-agent-method.h" + +static DBusGConnection *obex_conn = NULL; + +typedef struct { + gchar *name; + gchar *path; + + /* callback data */ + gpointer authorize_data; + gpointer release_data; + gpointer request_data; + gpointer progress_data; + gpointer complete_data; + gpointer error_data; + + /* callback function */ + bt_obex_authorize_cb authorize_cb; + bt_obex_release_cb release_cb; + bt_obex_request_cb request_cb; + bt_obex_progress_cb progress_cb; + bt_obex_complete_cb complete_cb; + bt_obex_error_cb error_cb; +} bt_obex_agent_info; + +#define BT_OBEX_AGENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), \ + BT_OBEX_TYPE_AGENT, bt_obex_agent_info)) + +G_DEFINE_TYPE(BtObexAgent, bt_obex_agent, G_TYPE_OBJECT) + +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; + gboolean result; + + info = BT_OBEX_AGENT_GET_PRIVATE(agent); + + if (info == NULL) + goto fail; + + if (info->authorize_cb == NULL) + goto fail; + + result = info->authorize_cb(context, path, bdaddress, + name, type, length, + time, info->authorize_data); + + return result; +fail: + dbus_g_method_return(context, ""); + return FALSE; +} + +gboolean bt_obex_agent_request(BtObexAgent *agent, const char *path, + DBusGMethodInvocation *context) +{ + char *sender; + bt_obex_agent_info *info; + DBusGProxy *proxy; + gboolean result; + + info = BT_OBEX_AGENT_GET_PRIVATE(agent); + + if (info == NULL) + goto fail; + + if (obex_conn == NULL) + goto fail; + + sender = dbus_g_method_get_sender(context); + + BT_DBG("sender %s", sender); + + if (info->name == NULL) { + info->name = sender; + } else { + if (g_strcmp0(sender, info->name) != 0) { + g_free(sender); + goto fail; + } + g_free(sender); + } + + if (info->request_cb == NULL) + goto fail; + + proxy = dbus_g_proxy_new_for_name(obex_conn, BT_OBEX_SERVICE_NAME, + path, BT_OBEX_TRANSFER_INTERFACE); + + result = info->request_cb(context, proxy, info->request_data); + g_object_unref(proxy); + + return result; +fail: + BT_ERR("Fail case"); + dbus_g_method_return(context, ""); + return FALSE; +} + +gboolean bt_obex_agent_progress(BtObexAgent *agent, const char *path, + guint64 transferred, DBusGMethodInvocation *context) +{ + bt_obex_agent_info *info; + char *sender; + gboolean result; + DBusGProxy *proxy; + + info = BT_OBEX_AGENT_GET_PRIVATE(agent); + + if (info == NULL) + goto fail; + + if (obex_conn == NULL) + goto fail; + + sender = dbus_g_method_get_sender(context); + + if (g_strcmp0(sender, info->name) != 0) { + g_free(sender); + goto fail; + } + + g_free(sender); + + if (info->progress_cb == NULL) + goto fail; + + proxy = dbus_g_proxy_new_for_name(obex_conn, BT_OBEX_SERVICE_NAME, + path, BT_OBEX_TRANSFER_INTERFACE); + + result = info->progress_cb(context, proxy, transferred, info->progress_data); + + g_object_unref(proxy); + + return result; +fail: + BT_ERR("Fail case"); + dbus_g_method_return(context, ""); + return FALSE; +} + +gboolean bt_obex_agent_error(BtObexAgent *agent, const char *path, + const char *message, DBusGMethodInvocation *context) +{ + bt_obex_agent_info *info; + char *sender; + DBusGProxy *proxy; + gboolean result; + + info = BT_OBEX_AGENT_GET_PRIVATE(agent); + + if (info == NULL) + goto fail; + + if (obex_conn == NULL) + goto fail; + + sender = dbus_g_method_get_sender(context); + + if (g_strcmp0(sender, info->name) != 0) { + g_free(sender); + goto fail; + } + + g_free(sender); + + if (info->error_cb == NULL) + goto fail; + + proxy = dbus_g_proxy_new_for_name(obex_conn, BT_OBEX_SERVICE_NAME, + path, BT_OBEX_TRANSFER_INTERFACE); + + result = info->error_cb(context, proxy, message, info->progress_data); + + g_object_unref(proxy); + + return result; +fail: + BT_ERR("Fail case"); + dbus_g_method_return(context, ""); + return FALSE; +} + +gboolean bt_obex_agent_complete(BtObexAgent *agent, const char *path, + DBusGMethodInvocation *context) +{ + bt_obex_agent_info *info; + char *sender; + DBusGProxy *proxy; + gboolean result; + + info = BT_OBEX_AGENT_GET_PRIVATE(agent); + + if (info == NULL) + goto fail; + + if (obex_conn == NULL) + goto fail; + + sender = dbus_g_method_get_sender(context); + + if (g_strcmp0(sender, info->name) != 0) { + g_free(sender); + goto fail; + } + + g_free(sender); + + if (info->complete_cb == NULL) + goto fail; + + proxy = dbus_g_proxy_new_for_name(obex_conn, BT_OBEX_SERVICE_NAME, + path, BT_OBEX_TRANSFER_INTERFACE); + + result = info->complete_cb(context, proxy, info->complete_data); + + g_object_unref(proxy); + + return result; +fail: + BT_ERR("Fail case"); + dbus_g_method_return(context, ""); + return FALSE; +} + +gboolean bt_obex_agent_release(BtObexAgent *agent, DBusGMethodInvocation *context) +{ + bt_obex_agent_info *info; + char *sender; + gboolean result; + + info = BT_OBEX_AGENT_GET_PRIVATE(agent); + + if (info == NULL) + goto fail; + + sender = dbus_g_method_get_sender(context); + + if (info->name) { + /*In H2 if user denies auth,release will come without request and hence + info->name will be NULL */ + if (g_strcmp0(sender, info->name) != 0) { + g_free(sender); + goto fail; + } + } + g_free(sender); + + if (info->release_cb == NULL) + goto fail; + + result = info->release_cb(context, info->release_data); + + return result; +fail: + BT_ERR("Fail case"); + dbus_g_method_return(context, ""); + return FALSE; +} + +static void bt_obex_agent_init(BtObexAgent *agent) +{ + BT_DBG("agent %p", agent); +} + +static void bt_obex_agent_finalize(GObject *agent) +{ + bt_obex_agent_info *info; + + info = BT_OBEX_AGENT_GET_PRIVATE(agent); + + if (info) { + g_free(info->path); + g_free(info->name); + } + + G_OBJECT_CLASS(bt_obex_agent_parent_class)->finalize(agent); +} + +static void bt_obex_agent_class_init(BtObexAgentClass *agent_class) +{ + GObjectClass *object_class; + GError *error = NULL; + + object_class = (GObjectClass *)agent_class; + + g_type_class_add_private(agent_class, sizeof(bt_obex_agent_info)); + + object_class->finalize = bt_obex_agent_finalize; + + obex_conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error); + + if (error != NULL) { + BT_ERR("Fail to get dbus: %s", error->message); + g_error_free(error); + } + + dbus_g_object_type_install_info(BT_OBEX_TYPE_AGENT, + &dbus_glib_bt_obex_agent_object_info); +} + +BtObexAgent *_bt_obex_agent_new(void) +{ + BtObexAgent *agent; + + agent = BT_OBEX_AGENT(g_object_new(BT_OBEX_TYPE_AGENT, NULL)); + + return agent; +} + +gboolean _bt_obex_setup(BtObexAgent *agent, const char *path) +{ + bt_obex_agent_info *info; + DBusGProxy *proxy; + GObject *object; + + info = BT_OBEX_AGENT_GET_PRIVATE(agent); + + retv_if(obex_conn == NULL, FALSE); + retv_if(info == NULL, FALSE); + retv_if(info->path != NULL, FALSE); + + info->path = g_strdup(path); + + proxy = dbus_g_proxy_new_for_name_owner(obex_conn, BT_OBEX_SERVICE_NAME, + BT_OBEX_CLIENT_PATH, + BT_OBEX_AGENT_INTERFACE, NULL); + g_free(info->name); + + if (proxy != NULL) { + info->name = g_strdup(dbus_g_proxy_get_bus_name(proxy)); + g_object_unref(proxy); + } else { + info->name = NULL; + } + + object = dbus_g_connection_lookup_g_object(obex_conn, info->path); + if (object != NULL) + g_object_unref(object); + + dbus_g_connection_register_g_object(obex_conn, info->path, G_OBJECT(agent)); + + dbus_g_object_register_marshaller(marshal_VOID__OBJECT_BOOLEAN, + G_TYPE_NONE, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_BOOLEAN, + G_TYPE_INVALID); + + dbus_g_object_register_marshaller(marshal_VOID__INT_INT, + G_TYPE_NONE, G_TYPE_INT, G_TYPE_INT, G_TYPE_INVALID); + return TRUE; +} + +void _bt_obex_set_authorize_cb(BtObexAgent *agent, + bt_obex_authorize_cb func, gpointer data) +{ + bt_obex_agent_info *info = BT_OBEX_AGENT_GET_PRIVATE(agent); + + info->authorize_cb = func; + info->authorize_data = data; +} + +void _bt_obex_set_release_cb(BtObexAgent *agent, + bt_obex_release_cb func, gpointer data) +{ + bt_obex_agent_info *info = BT_OBEX_AGENT_GET_PRIVATE(agent); + + info->release_cb = func; + info->release_data = data; +} + +void _bt_obex_set_request_cb(BtObexAgent *agent, + bt_obex_request_cb func, gpointer data) +{ + bt_obex_agent_info *info = BT_OBEX_AGENT_GET_PRIVATE(agent); + + info->request_cb = func; + info->request_data = data; +} + +void _bt_obex_set_progress_cb(BtObexAgent *agent, + bt_obex_progress_cb func, gpointer data) +{ + bt_obex_agent_info *info = BT_OBEX_AGENT_GET_PRIVATE(agent); + + info->progress_cb = func; + info->progress_data = data; +} + +void _bt_obex_set_complete_cb(BtObexAgent *agent, + bt_obex_complete_cb func, gpointer data) +{ + bt_obex_agent_info *info = BT_OBEX_AGENT_GET_PRIVATE(agent); + + info->complete_cb = func; + info->complete_data = data; +} + +void _bt_obex_set_error_cb(BtObexAgent *agent, + bt_obex_error_cb func, gpointer data) +{ + bt_obex_agent_info *info = BT_OBEX_AGENT_GET_PRIVATE(agent); + + info->error_cb = func; + info->error_data = data; +} diff --git a/bt-service/bt-service-obex-agent.xml b/bt-service/bt-service-obex-agent.xml new file mode 100644 index 0000000..5915005 --- /dev/null +++ b/bt-service/bt-service-obex-agent.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bt-service/bt-service-obex-server.c b/bt-service/bt-service-obex-server.c new file mode 100644 index 0000000..a9cfb85 --- /dev/null +++ b/bt-service/bt-service-obex-server.c @@ -0,0 +1,880 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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-util.h" +#include "bt-service-obex-agent.h" +#include "bt-service-obex-server.h" +#include "bt-service-agent.h" + +#define BT_OBEX_SERVER_AGENT_PATH "/org/obex/server_agent" +#define BT_OBEX_SERVICE "org.openobex" +#define BT_OBEX_MANAGER "org.openobex.Manager" + +typedef struct { + char *filename; + char *path; + char *type; + char *device_name; + int transfer_id; + gint64 file_size; +} bt_transfer_info_t; + +typedef struct { + DBusGMethodInvocation *reply_context; + gint64 file_size; + char *filename; + char *device_name; + char *transfer_path; +} bt_auth_info_t; + +typedef struct { + char *dest_path; + char *sender; + int app_pid; +} bt_server_info_t; + +typedef struct { + BtObexAgent *obex_agent; + DBusGProxy *proxy; + int server_type; + int accept_id; + bt_auth_info_t *auth_info; + bt_server_info_t *native_server; + bt_server_info_t *custom_server; +} bt_obex_agent_info_t; + +static GSList *transfers; +static bt_obex_agent_info_t agent_info; + +static GQuark __bt_obex_error_quark(void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string("agent"); + + return quark; +} + +static bt_transfer_info_t *__bt_find_transfer_by_id(int transfer_id) +{ + GSList *l; + bt_transfer_info_t *transfer; + + for (l = transfers; l != NULL; l = l->next) { + transfer = l->data; + + if (transfer == NULL) + continue; + + if (transfer->transfer_id == transfer_id) + return transfer; + } + + return NULL; +} + +static bt_transfer_info_t *__bt_find_transfer_by_path(const char *transfer_path) +{ + GSList *l; + bt_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_server_info(bt_server_info_t *server_info) +{ + ret_if(server_info == NULL); + + g_free(server_info->sender); + g_free(server_info->dest_path); + g_free(server_info); +} + +static void __bt_free_auth_info(bt_auth_info_t *auto_info) +{ + ret_if(auto_info == NULL); + + g_free(auto_info->filename); + g_free(auto_info->transfer_path); + g_free(auto_info->device_name); + g_free(auto_info); +} + +static void __bt_free_transfer_info(bt_transfer_info_t *transfer_info) +{ + ret_if(transfer_info == NULL); + + g_free(transfer_info->path); + g_free(transfer_info->filename); + g_free(transfer_info->type); + g_free(transfer_info->device_name); + g_free(transfer_info); +} + +static char *__bt_get_remote_device_name(const char *bdaddress) +{ + GError *error = NULL; + char *device_path = NULL; + char *name = NULL; + GHashTable *hash = NULL; + GValue *value; + DBusGProxy *device_proxy; + DBusGProxy *adapter_proxy; + DBusGConnection *conn; + + retv_if(bdaddress == NULL, NULL); + + adapter_proxy = _bt_get_adapter_proxy(); + retv_if(adapter_proxy == NULL, NULL); + + conn = _bt_get_system_gconn(); + retv_if(conn == NULL, NULL); + + dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL, + G_TYPE_STRING, bdaddress, G_TYPE_INVALID, + DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID); + + retv_if(device_path == NULL, NULL); + + 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, NULL); + if (!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) { + BT_ERR( "error in GetBasicProperties [%s]\n", error->message); + g_error_free(error); + } + g_object_unref(device_proxy); + return NULL; + } + + if (hash != NULL) { + value = g_hash_table_lookup(hash, "Alias"); + name = value ? g_value_dup_string(value) : NULL; + g_hash_table_destroy(hash); + } + + g_object_unref(device_proxy); + + return name; +} + +static int __bt_get_transfer_id(const char *path) +{ + char *tmp = NULL; + if (path == NULL) + return -1; + + tmp = strrchr(path, 'r') + 1; + retv_if(tmp == NULL, -1); + + return atoi(tmp); +} + +static DBusGProxy *__bt_get_transfer_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_OBEXD_INTERFACE, + transfer_path, + BT_OBEXD_TRANSFER_INTERFACE); + + return proxy; +} + +static int __bt_get_transfer_properties(bt_transfer_info_t *transfer_info, + const char *transfer_path) +{ + GHashTable *hash = NULL; + GValue *value; + DBusGProxy *transfer_proxy; + + BT_CHECK_PARAMETER(transfer_info); + BT_CHECK_PARAMETER(transfer_path); + + transfer_proxy = __bt_get_transfer_proxy(transfer_path); + + retv_if(transfer_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call(transfer_proxy, "GetProperties", NULL, + 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); + return BLUETOOTH_ERROR_INTERNAL; + } + + value = g_hash_table_lookup(hash, "Operation"); + transfer_info->type = value ? g_strdup(g_value_get_string(value)) : NULL; + + value = g_hash_table_lookup(hash, "Filename"); + transfer_info->filename = value ? g_strdup(g_value_get_string(value)) : NULL; + + value = g_hash_table_lookup(hash, "Size"); + transfer_info->file_size = value ? g_value_get_uint64(value) : 0; + + transfer_info->path = g_strdup(transfer_path); + transfer_info->transfer_id = __bt_get_transfer_id(transfer_path); + + transfer_info->device_name = g_strdup(""); + + g_hash_table_destroy(hash); + + return BLUETOOTH_ERROR_NONE; +} + +static gboolean __bt_authorize_cb(DBusGMethodInvocation *context, + const char *path, + const char *bdaddress, + const char *name, + const char *type, + gint length, + gint time, + gpointer user_data) +{ + char *device_name = NULL; + int result = BLUETOOTH_ERROR_NONE; + + BT_DBG(" File name [%s] Address [%s] Type [%s] length [%d] path [%s] \n", + name, bdaddress, type, length, path); + + __bt_free_auth_info(agent_info.auth_info); + + agent_info.auth_info = g_malloc(sizeof(bt_auth_info_t)); + + agent_info.auth_info->reply_context = context; + agent_info.auth_info->filename = g_strdup(name); + agent_info.auth_info->file_size = length; + agent_info.auth_info->transfer_path = g_strdup(path); + + device_name = __bt_get_remote_device_name(bdaddress); + + if (!device_name) + device_name = g_strdup(bdaddress); + + agent_info.auth_info->device_name = device_name; + + if (agent_info.server_type == BT_CUSTOM_SERVER) { + /* No need to send the event */ + _bt_obex_server_accept_authorize(agent_info.auth_info->filename, FALSE); + return TRUE; + } + + _bt_send_event(BT_OPP_SERVER_EVENT, + BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_AUTHORIZE, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &agent_info.auth_info->filename, + DBUS_TYPE_UINT64, &agent_info.auth_info->file_size, + DBUS_TYPE_INVALID); + + return TRUE; +} + +void _bt_obex_transfer_started(const char *transfer_path) +{ + bt_transfer_info_t *transfer_info; + request_info_t *req_info; + GArray *out_param1 = NULL; + GArray *out_param2 = NULL; + int result = BLUETOOTH_ERROR_NONE; + + BT_DBG("%s", transfer_path); + + transfer_info = g_malloc0(sizeof(bt_transfer_info_t)); + + if (agent_info.auth_info != NULL + && g_strcmp0(transfer_path, agent_info.auth_info->transfer_path) == 0) { + 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); + } else { + if (__bt_get_transfer_properties(transfer_info, transfer_path) < 0) { + BT_ERR("Get Properties failed"); + __bt_free_auth_info(agent_info.auth_info); + __bt_free_transfer_info(transfer_info); + agent_info.auth_info = NULL; + return; + } + agent_info.server_type = BT_FTP_SERVER; + } + + __bt_free_auth_info(agent_info.auth_info); + agent_info.auth_info = NULL; + + if (agent_info.server_type == BT_CUSTOM_SERVER) { + if (agent_info.custom_server == NULL) { + __bt_free_transfer_info(transfer_info); + return; + } + + req_info = _bt_get_request_info(agent_info.accept_id); + if (req_info == NULL || req_info->context == NULL) { + BT_ERR("info is NULL"); + goto done; + } + + agent_info.accept_id = 0; + result = BLUETOOTH_ERROR_NONE; + + 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); + } +done: + transfers = g_slist_append(transfers, transfer_info); + + BT_DBG("Transfer id %d\n", transfer_info->transfer_id); + + _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); +} + +void _bt_obex_transfer_progress(const char *transfer_path, + int total, + int transferred) +{ + bt_transfer_info_t *transfer_info; + int progress = 0; + int result = BLUETOOTH_ERROR_NONE; + + transfer_info = __bt_find_transfer_by_path(transfer_path); + ret_if(transfer_info == NULL); + + progress = (int)(((gdouble)transferred /(gdouble)total) * 100); + + _bt_send_event(BT_OPP_SERVER_EVENT, + BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_PROGRESS, + 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, &progress, + DBUS_TYPE_INT32, &agent_info.server_type, + DBUS_TYPE_INVALID); +} + +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); + + result = (success == TRUE) ? BLUETOOTH_ERROR_NONE + : BLUETOOTH_ERROR_CANCEL; + + transfer_info = __bt_find_transfer_by_path(transfer_path); + ret_if(transfer_info == NULL); + + _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_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); +} + +int _bt_register_obex_server(void) +{ + DBusGConnection *g_conn; + DBusGProxy *manager_proxy; + GError *g_error = NULL; + + /* Get the session bus. */ + g_conn = _bt_get_session_gconn(); + retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + if (!agent_info.obex_agent) { + agent_info.obex_agent = _bt_obex_agent_new(); + + retv_if(agent_info.obex_agent == NULL, BLUETOOTH_ERROR_INTERNAL); + + _bt_obex_setup(agent_info.obex_agent, BT_OBEX_SERVER_AGENT_PATH); + + _bt_obex_set_authorize_cb(agent_info.obex_agent, + __bt_authorize_cb, NULL); + } + + manager_proxy = dbus_g_proxy_new_for_name(g_conn, BT_OBEX_SERVICE, + "/", BT_OBEX_MANAGER); + + if (manager_proxy == NULL) { + g_object_unref(agent_info.obex_agent); + agent_info.obex_agent = NULL; + return BLUETOOTH_ERROR_INTERNAL; + } + + dbus_g_proxy_call(manager_proxy, "RegisterAgent", &g_error, + DBUS_TYPE_G_OBJECT_PATH, BT_OBEX_SERVER_AGENT_PATH, + G_TYPE_INVALID, G_TYPE_INVALID); + if (g_error != NULL) { + BT_ERR("Agent registration failed: %s\n", g_error->message); + g_object_unref(agent_info.obex_agent); + agent_info.obex_agent = NULL; + g_object_unref(manager_proxy); + g_error_free(g_error); + return BLUETOOTH_ERROR_INTERNAL; + } + + agent_info.proxy = manager_proxy; + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_unregister_obex_server(void) +{ + GError *g_error = NULL; + + retv_if(agent_info.obex_agent == NULL, + BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST); + + retv_if(agent_info.proxy == NULL, + BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call(agent_info.proxy, "UnregisterAgent", &g_error, + DBUS_TYPE_G_OBJECT_PATH, BT_OBEX_SERVER_AGENT_PATH, + G_TYPE_INVALID, G_TYPE_INVALID); + if (g_error != NULL) { + BT_ERR("Agent unregistration failed: %s", g_error->message); + g_error_free(g_error); + } + + g_object_unref(agent_info.proxy); + agent_info.proxy = NULL; + + g_object_unref(agent_info.obex_agent); + agent_info.obex_agent = NULL; + + return BLUETOOTH_ERROR_NONE; +} + +gboolean __bt_check_folder_path(const char *dest_path) +{ + DIR *dp; + + retv_if(dest_path == NULL, TRUE); + + dp = opendir(dest_path); + + if (dp == NULL) { + BT_ERR("The directory does not exist"); + return FALSE; + } + + closedir(dp); + + return TRUE; +} + +int _bt_obex_server_allocate(char *sender, const char *dest_path, int app_pid, gboolean is_native) +{ + if (__bt_check_folder_path(dest_path) == FALSE) + return BLUETOOTH_ERROR_INVALID_PARAM; + + if (is_native == TRUE) { + retv_if(agent_info.native_server, + BLUETOOTH_ERROR_DEVICE_BUSY); + + /* Force to change the control to native */ + agent_info.native_server = g_malloc0(sizeof(bt_server_info_t)); + agent_info.native_server->dest_path = g_strdup(dest_path); + agent_info.native_server->sender = g_strdup(sender); + agent_info.native_server->app_pid = app_pid; + agent_info.server_type = BT_NATIVE_SERVER; + _bt_unregister_osp_server_in_agent(BT_OBEX_SERVER, NULL); + } else { + retv_if(agent_info.custom_server, + BLUETOOTH_ERROR_DEVICE_BUSY); + + /* Force to change the control to custom */ + agent_info.custom_server = g_malloc0(sizeof(bt_server_info_t)); + agent_info.custom_server->dest_path = g_strdup(dest_path); + 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); + } + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_obex_server_deallocate(int app_pid, gboolean is_native) +{ + if (is_native == TRUE) { + retv_if(agent_info.native_server == NULL, + BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST); + + retv_if(agent_info.native_server->app_pid != app_pid, + BLUETOOTH_ERROR_ACCESS_DENIED); + + __bt_free_server_info(agent_info.native_server); + agent_info.native_server = NULL; + + /* Change the control to custom */ + if (agent_info.custom_server) { + agent_info.server_type = BT_CUSTOM_SERVER; + _bt_register_osp_server_in_agent(BT_OBEX_SERVER, + NULL); + } + } else { + retv_if(agent_info.custom_server == NULL, + BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST); + + retv_if(agent_info.custom_server->app_pid != app_pid, + BLUETOOTH_ERROR_ACCESS_DENIED); + + __bt_free_server_info(agent_info.custom_server); + agent_info.custom_server = NULL; + + _bt_unregister_osp_server_in_agent(BT_OBEX_SERVER, NULL); + + /* Change the control to native */ + if (agent_info.native_server) + agent_info.server_type = BT_NATIVE_SERVER; + } + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_obex_server_accept_authorize(const char *filename, gboolean is_native) +{ + char file_path[BT_FILE_PATH_MAX] = { 0 }; + bt_server_info_t *server_info; + + BT_CHECK_PARAMETER(filename); + + retv_if(agent_info.auth_info == NULL, BLUETOOTH_ERROR_INTERNAL); + + retv_if(agent_info.auth_info->reply_context == NULL, + BLUETOOTH_ERROR_INTERNAL); + + if (is_native == TRUE) + server_info = agent_info.native_server; + else + server_info = agent_info.custom_server; + + retv_if(server_info == NULL, BLUETOOTH_ERROR_INTERNAL); + + if (server_info->dest_path != NULL) + snprintf(file_path, sizeof(file_path), "%s/%s", + server_info->dest_path, filename); + else + snprintf(file_path, sizeof(file_path), "%s", filename); + + dbus_g_method_return(agent_info.auth_info->reply_context, + file_path); + + agent_info.auth_info->reply_context = NULL; + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_obex_server_reject_authorize(void) +{ + GError *g_error; + + retv_if(agent_info.auth_info->reply_context == NULL, + BLUETOOTH_ERROR_INTERNAL); + + g_error = g_error_new(__bt_obex_error_quark(), + BT_OBEX_AGENT_ERROR_CANCEL, + "CancelledByUser"); + + dbus_g_method_return_error(agent_info.auth_info->reply_context, + g_error); + g_error_free(g_error); + + __bt_free_auth_info(agent_info.auth_info); + agent_info.auth_info = NULL; + + return BLUETOOTH_ERROR_NONE; +} + +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); + + dp = opendir(dest_path); + + if (dp == NULL) { + BT_ERR("The directory does not exist"); + return BLUETOOTH_ERROR_INVALID_PARAM; + } + + closedir(dp); + + if (is_native == TRUE) + server_info = agent_info.native_server; + else + server_info = agent_info.custom_server; + + retv_if(server_info == NULL, + BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST); + + g_free(server_info->dest_path); + server_info->dest_path = g_strdup(dest_path); + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_obex_server_set_root(const char *root) +{ + GError *g_error = NULL; + GValue folder = { 0 }; + DIR *dp = NULL; + + BT_CHECK_PARAMETER(root); + + retv_if(agent_info.proxy == NULL, + BLUETOOTH_ERROR_INTERNAL); + + dp = opendir(root); + + if (dp == NULL) { + BT_ERR("The directory does not exist"); + return BLUETOOTH_ERROR_INVALID_PARAM; + } + + closedir(dp); + + g_value_init(&folder, G_TYPE_STRING); + g_value_set_string(&folder, root); + + dbus_g_proxy_call(agent_info.proxy, "SetProperty", + &g_error, G_TYPE_STRING, "Root", + G_TYPE_VALUE, &folder, G_TYPE_INVALID, G_TYPE_INVALID); + + g_value_unset(&folder); + + if (g_error) { + BT_ERR("SetProperty Fail: %s", g_error->message); + g_error_free(g_error); + return BLUETOOTH_ERROR_INTERNAL; + } + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_obex_server_cancel_transfer(int transfer_id) +{ + bt_transfer_info_t *transfer = NULL; + DBusGProxy *proxy; + + transfer = __bt_find_transfer_by_id(transfer_id); + retv_if(transfer == NULL, BLUETOOTH_ERROR_NOT_FOUND); + + proxy = __bt_get_transfer_proxy(transfer->path); + + retv_if(proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call_no_reply(proxy, "Cancel", + G_TYPE_INVALID, G_TYPE_INVALID); + + g_object_unref(proxy); + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_obex_server_cancel_all_transfers(void) +{ + GSList *l; + bt_transfer_info_t *transfer; + + for (l = transfers; l != NULL; l = l->next) { + transfer = l->data; + + if (transfer == NULL) + continue; + + _bt_obex_server_cancel_transfer(transfer->transfer_id); + } + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_obex_server_is_activated(gboolean *activated) +{ + BT_CHECK_PARAMETER(activated); + + if (agent_info.custom_server) { + *activated = TRUE; + } else { + *activated = FALSE; + } + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_obex_server_check_allocation(gboolean *allocation) +{ + BT_CHECK_PARAMETER(allocation); + + if (agent_info.native_server || agent_info.custom_server) { + *allocation = TRUE; + } else { + *allocation = FALSE; + } + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_obex_server_check_termination(char *sender) +{ + BT_CHECK_PARAMETER(sender); + + if (agent_info.native_server) { + if (g_strcmp0(sender, agent_info.native_server->sender) == 0) { + _bt_obex_server_deallocate(agent_info.native_server->app_pid, + TRUE); + } + } + + if (agent_info.custom_server) { + if (g_strcmp0(sender, agent_info.custom_server->sender) == 0) { + _bt_obex_server_deallocate(agent_info.custom_server->app_pid, + FALSE); + } + } + + return BLUETOOTH_ERROR_NONE; +} + +gboolean __bt_obex_server_accept_timeout_cb(gpointer user_data) +{ + request_info_t *req_info; + GArray *out_param1; + GArray *out_param2; + int result = BLUETOOTH_ERROR_TIMEOUT; + + /* Already reply in _bt_obex_transfer_started */ + retv_if(agent_info.accept_id == 0, FALSE); + + req_info = _bt_get_request_info(agent_info.accept_id); + if (req_info == NULL || req_info->context == NULL) { + BT_ERR("info is NULL"); + return FALSE; + } + + agent_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_obex_server_accept_connection(int request_id) +{ + if (!_bt_agent_reply_authorize(TRUE)) + return BLUETOOTH_ERROR_INTERNAL; + + agent_info.accept_id = request_id; + + g_timeout_add(BT_SERVER_ACCEPT_TIMEOUT, + (GSourceFunc)__bt_obex_server_accept_timeout_cb, + NULL); + + return BLUETOOTH_ERROR_NONE; +} + +/* To support the BOT */ +int _bt_obex_server_reject_connection(void) +{ + if (!_bt_agent_reply_authorize(FALSE)) + return BLUETOOTH_ERROR_INTERNAL; + + return BLUETOOTH_ERROR_NONE; +} + diff --git a/bt-service/bt-service-oob.c b/bt-service/bt-service-oob.c new file mode 100644 index 0000000..a81e425 --- /dev/null +++ b/bt-service/bt-service-oob.c @@ -0,0 +1,213 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "bluetooth-api.h" +#include "bt-service-common.h" +#include "bt-service-oob.h" +#include "bt-service-event.h" + +int _bt_oob_read_local_data(bt_oob_data_t *local_oob_data) +{ + DBusMessage *msg; + DBusMessage *reply; + DBusError err; + char *adapter_path; + unsigned char *local_hash = NULL; + unsigned char *local_randomizer = NULL; + DBusConnection *conn; + + BT_CHECK_PARAMETER(local_oob_data); + + conn = _bt_get_system_conn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + 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_OOB_INTERFACE, "ReadLocalData"); + + g_free(adapter_path); + + retv_if(msg == NULL, BLUETOOTH_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 in ReadLocalData \n"); + if (dbus_error_is_set(&err)) { + BT_ERR("%s", err.message); + dbus_error_free(&err); + } + return BLUETOOTH_ERROR_INTERNAL; + } + + if (!dbus_message_get_args(reply, NULL, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &local_hash, &local_oob_data->hash_len, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &local_randomizer, &local_oob_data->randomizer_len, + DBUS_TYPE_INVALID)) { + BT_ERR("Error in reading arguments\n"); + dbus_message_unref(reply); + return BLUETOOTH_ERROR_INVALID_DATA; + } + + if (NULL != local_hash) + memcpy(local_oob_data->hash, local_hash, local_oob_data->hash_len); + + if (NULL != local_randomizer) + memcpy(local_oob_data->randomizer, local_randomizer, + local_oob_data->randomizer_len); + + dbus_message_unref(reply); + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_oob_add_remote_data( + bluetooth_device_address_t *remote_device_address, + bt_oob_data_t *remote_oob_data) +{ + DBusMessage *msg; + DBusMessage *reply; + DBusError err; + char *dev_addr; + char *adapter_path; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + unsigned char *remote_hash; + unsigned char *remote_randomizer; + DBusConnection *conn; + + BT_CHECK_PARAMETER(remote_device_address); + BT_CHECK_PARAMETER(remote_oob_data); + + conn = _bt_get_system_conn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + adapter_path = _bt_get_adapter_path(); + retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL); + + _bt_convert_addr_type_to_string(address, + remote_device_address->addr); + + msg = dbus_message_new_method_call(BT_BLUEZ_NAME, adapter_path, + BT_OOB_INTERFACE, "AddRemoteData"); + + retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_DBG("remote hash len = [%d] and remote random len = [%d]\n", + remote_oob_data->hash_len, remote_oob_data->randomizer_len); + + remote_hash = remote_oob_data->hash; + remote_randomizer = remote_oob_data->randomizer; + + dev_addr = g_strdup(address); + + dbus_message_append_args(msg, + DBUS_TYPE_STRING, &dev_addr, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &remote_hash, remote_oob_data->hash_len, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &remote_randomizer, remote_oob_data->randomizer_len, + DBUS_TYPE_INVALID); + + 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 in AddRemoteData \n"); + if (dbus_error_is_set(&err)) { + BT_ERR("%s", err.message); + dbus_error_free(&err); + g_free(dev_addr); + return BLUETOOTH_ERROR_INTERNAL; + } + } + + g_free(dev_addr); + dbus_message_unref(reply); + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_oob_remove_remote_data( + bluetooth_device_address_t *remote_device_address) +{ + DBusMessage *msg; + DBusMessage *reply; + DBusError err; + char *dev_addr; + char *adapter_path; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + DBusConnection *conn; + + BT_CHECK_PARAMETER(remote_device_address); + + conn = _bt_get_system_conn(); + retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + adapter_path = _bt_get_adapter_path(); + retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL); + + _bt_convert_addr_type_to_string(address, + remote_device_address->addr); + + msg = dbus_message_new_method_call(BT_BLUEZ_NAME, adapter_path, + BT_OOB_INTERFACE, "RemoveRemoteData"); + + retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL); + + dev_addr = g_strdup(address); + + dbus_message_append_args(msg, DBUS_TYPE_STRING, + &dev_addr, DBUS_TYPE_INVALID); + + 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 in RemoveRemoteData \n"); + if (dbus_error_is_set(&err)) { + BT_DBG("%s", err.message); + dbus_error_free(&err); + g_free(dev_addr); + return BLUETOOTH_ERROR_INTERNAL; + } + } + + g_free(dev_addr); + dbus_message_unref(reply); + + return BLUETOOTH_ERROR_NONE; +} + diff --git a/bt-service/bt-service-opp-client.c b/bt-service/bt-service-opp-client.c new file mode 100644 index 0000000..c0c7d08 --- /dev/null +++ b/bt-service/bt-service-opp-client.c @@ -0,0 +1,620 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "bluetooth-api.h" +#include "bt-internal-types.h" + +#include "bt-service-common.h" +#include "bt-service-event.h" +#include "bt-service-util.h" +#include "bt-service-opp-client.h" +#include "bt-service-obex-agent.h" + +static BtObexAgent *opc_obex_agent = NULL; +static GSList *transfer_list = NULL; + +bt_sending_info_t *sending_info; + +static gboolean __bt_release_callback(DBusGMethodInvocation *context, + gpointer user_data); + +static gboolean __bt_request_callback(DBusGMethodInvocation *context, + DBusGProxy *transfer, + gpointer user_data); + +static gboolean __bt_progress_callback(DBusGMethodInvocation *context, + DBusGProxy *transfer, + guint64 transferred, + gpointer user_data); + +static gboolean __bt_complete_callback(DBusGMethodInvocation *context, + DBusGProxy *transfer, + gpointer user_data); + +static gboolean __bt_error_callback(DBusGMethodInvocation *context, + DBusGProxy *transfer, + const char *message, + gpointer user_data); + + +static int __bt_opp_client_start_sending(int request_id, char *address, + char **file_name_array); + +static int __bt_opp_client_agent_init(void) +{ + opc_obex_agent = _bt_obex_agent_new(); + retv_if(opc_obex_agent == NULL, BLUETOOTH_ERROR_INTERNAL); + + _bt_obex_set_release_cb(opc_obex_agent, + __bt_release_callback, NULL); + _bt_obex_set_request_cb(opc_obex_agent, + __bt_request_callback, NULL); + _bt_obex_set_progress_cb(opc_obex_agent, + __bt_progress_callback, NULL); + _bt_obex_set_complete_cb(opc_obex_agent, + __bt_complete_callback, NULL); + _bt_obex_set_error_cb(opc_obex_agent, + __bt_error_callback, NULL); + + _bt_obex_setup(opc_obex_agent, BT_OBEX_CLIENT_AGENT_PATH); + + return BLUETOOTH_ERROR_NONE; +} + +static void __bt_opp_client_agent_deinit(void) +{ + ret_if(opc_obex_agent == NULL); + + g_object_unref(opc_obex_agent); + opc_obex_agent = NULL; +} + +static GQuark __bt_opc_error_quark(void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string("agent"); + + return quark; +} + +static void __bt_free_transfer_info(bt_transfer_info_t *info) +{ + ret_if(info == NULL); + + if (info->proxy) + g_object_unref(info->proxy); + + g_free(info->transfer_name); + g_free(info->file_name); + g_free(info); +} + +static void __bt_free_sending_info(bt_sending_info_t *info) +{ + ret_if(info == NULL); + + /* Free the sending variable */ + __bt_free_transfer_info(info->transfer_info); + + g_free(info->address); + g_free(info); +} + +static void __bt_value_free(GValue *value) +{ + g_value_unset(value); + g_free(value); +} + +static gboolean __bt_cancel_push_cb(gpointer data) +{ + int result = BLUETOOTH_ERROR_CANCEL_BY_USER; + + retv_if(sending_info == NULL, FALSE); + + /* Send the event in only error none case */ + _bt_send_event(BT_OPP_CLIENT_EVENT, + BLUETOOTH_EVENT_OPC_CONNECTED, + 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_agent_deinit(); + + /* 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"); + return FALSE; + } + + transfer_list = g_slist_remove(transfer_list, node); + + if (__bt_opp_client_start_sending(node->request_id, + node->address, + node->file_path) != BLUETOOTH_ERROR_NONE) { + BT_DBG("Fail to start sending"); + } + } + + return FALSE; +} + +static gboolean __bt_progress_callback(DBusGMethodInvocation *context, + DBusGProxy *transfer, + guint64 transferred, + gpointer user_data) +{ + int percentage_progress; + gint64 size; + int result = BLUETOOTH_ERROR_NONE; + + dbus_g_method_return(context); + + retv_if(sending_info == NULL, TRUE); + retv_if(sending_info->transfer_info == NULL, TRUE); + + size = sending_info->transfer_info->size; + + if (size != 0) + percentage_progress = (int)(((gdouble)transferred / + (gdouble)size) * 100); + else + percentage_progress = 0; + + /* Send the event in only error none case */ + _bt_send_event(BT_OPP_CLIENT_EVENT, + BLUETOOTH_EVENT_OPC_TRANSFER_PROGRESS, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &sending_info->transfer_info->file_name, + DBUS_TYPE_UINT64, &sending_info->transfer_info->size, + DBUS_TYPE_INT32, &percentage_progress, + DBUS_TYPE_INT32, &sending_info->request_id, + DBUS_TYPE_INVALID); + + return TRUE; +} + +static gboolean __bt_complete_callback(DBusGMethodInvocation *context, + DBusGProxy *transfer, + gpointer user_data) +{ + int result = BLUETOOTH_ERROR_NONE; + + dbus_g_method_return(context); + + /* 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); + + return TRUE; +} + +static gboolean __bt_request_callback(DBusGMethodInvocation *context, + DBusGProxy *transfer, + gpointer user_data) +{ + GValue *value; + const char *transfer_name; + const char *file_name; + int size; + int result = BLUETOOTH_ERROR_NONE; + GHashTable *hash = NULL; + GError *error; + + if (sending_info == NULL || sending_info->is_canceled == TRUE) { + result = BLUETOOTH_ERROR_CANCEL_BY_USER; + goto canceled; + } + + dbus_g_method_return(context, ""); + + __bt_free_transfer_info(sending_info->transfer_info); + + sending_info->transfer_info = g_malloc0(sizeof(bt_transfer_info_t)); + sending_info->transfer_info->proxy = g_object_ref(transfer); + + dbus_g_proxy_call(transfer, "GetProperties", NULL, + G_TYPE_INVALID, + dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), + &hash, G_TYPE_INVALID); + + 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); + + _bt_send_event(BT_OPP_CLIENT_EVENT, + BLUETOOTH_EVENT_OPC_TRANSFER_STARTED, + 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); + + return TRUE; +canceled: + error = g_error_new(__bt_opc_error_quark(), BT_OBEX_AGENT_ERROR_CANCEL, + "CancelledByUser"); + + dbus_g_method_return_error(context, error); + g_error_free(error); + + 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_agent_deinit(); + + return TRUE; +} + +static void __bt_free_sending_data(gpointer data) +{ + int i; + bt_sending_data_t *info = data; + + ret_if(info == NULL); + + for (i = 0; i < info->file_count; i++) { + g_free(info->file_path[i]); + } + + _bt_delete_request_id(info->request_id); + + g_free(info->file_path); + g_free(info->address); + g_free(info); +} + +static gboolean __bt_release_callback(DBusGMethodInvocation *context, + gpointer user_data) +{ + dbus_g_method_return(context); + + retv_if(sending_info == NULL, FALSE); + + /* 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, + 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_agent_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) != BLUETOOTH_ERROR_NONE) { + goto fail; + } + } + + return TRUE; +fail: + g_slist_free_full(transfer_list, + (GDestroyNotify)__bt_free_sending_data); + transfer_list = NULL; + return TRUE; +} + +static gboolean __bt_error_callback(DBusGMethodInvocation *context, + DBusGProxy *transfer, + const char *message, + gpointer user_data) +{ + int result; + + dbus_g_method_return(context); + + retv_if(sending_info == NULL, FALSE); + retv_if(sending_info->transfer_info == NULL, FALSE); + + if (sending_info->is_canceled == TRUE) { + result = BLUETOOTH_ERROR_CANCEL_BY_USER; + } else if (g_strcmp0(message, "Forbidden") == 0) { + result = BLUETOOTH_ERROR_ACCESS_DENIED; + } else if (g_str_has_prefix(message, + "Transport endpoint is not connected") == TRUE) { + result = BLUETOOTH_ERROR_NOT_CONNECTED; + } else if (g_strcmp0(message, "Database full") == 0) { + result = BLUETOOTH_ERROR_OUT_OF_MEMORY; + } else { + result = BLUETOOTH_ERROR_INTERNAL; + } + + sending_info->result = result; + + /* 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); + return TRUE; +} + +static void __bt_send_files_cb(DBusGProxy *proxy, DBusGProxyCall *call, + void *user_data) +{ + GError *error = NULL; + int result = BLUETOOTH_ERROR_NONE; + + if (dbus_g_proxy_end_call(proxy, call, &error, + G_TYPE_INVALID) == FALSE) { + + BT_ERR("%s", error->message); + g_error_free(error); + + result = BLUETOOTH_ERROR_INTERNAL; + } + + g_object_unref(proxy); + ret_if(sending_info == NULL); + + sending_info->sending_proxy = NULL; + + /* Send the event in only error none case */ + _bt_send_event(BT_OPP_CLIENT_EVENT, + BLUETOOTH_EVENT_OPC_CONNECTED, + DBUS_TYPE_INT32, &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; + } +} + +static int __bt_opp_client_start_sending(int request_id, char *address, + char **file_name_array) +{ + GHashTable *hash; + GValue *value; + DBusGConnection *g_conn; + DBusGProxy *client_proxy; + DBusGProxyCall *proxy_call; + char *agent_path; + + BT_CHECK_PARAMETER(address); + BT_CHECK_PARAMETER(file_name_array); + + /* Get the session bus. */ + g_conn = _bt_get_session_gconn(); + retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + client_proxy = dbus_g_proxy_new_for_name(g_conn, BT_OBEX_SERVICE_NAME, + "/", BT_OBEX_CLIENT_INTERFACE); + + retv_if(client_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + hash = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, (GDestroyNotify)__bt_value_free); + + value = g_new0(GValue, 1); + g_value_init(value, G_TYPE_STRING); + g_value_set_string(value, address); + g_hash_table_insert(hash, "Destination", value); + + __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; + + __bt_opp_client_agent_deinit(); + __bt_opp_client_agent_init(); + + agent_path = g_strdup(BT_OBEX_CLIENT_AGENT_PATH); + + proxy_call = dbus_g_proxy_begin_call(client_proxy, "SendFiles", + __bt_send_files_cb, NULL, NULL, + dbus_g_type_get_map("GHashTable", G_TYPE_STRING, + G_TYPE_VALUE), hash, + G_TYPE_STRV, file_name_array, + DBUS_TYPE_G_OBJECT_PATH, agent_path, + G_TYPE_INVALID); + + g_free(agent_path); + + if (proxy_call == NULL) { + BT_ERR("Fail to Send files"); + g_hash_table_destroy(hash); + g_object_unref(client_proxy); + __bt_free_sending_info(sending_info); + __bt_opp_client_agent_deinit(); + sending_info = NULL; + return BLUETOOTH_ERROR_INTERNAL; + } + + sending_info->sending_proxy = proxy_call; + g_hash_table_destroy(hash); + + 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) +{ + 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; + + BT_CHECK_PARAMETER(remote_address); + BT_CHECK_PARAMETER(file_path); + + /* Implement the queue */ + _bt_convert_addr_type_to_string(address, remote_address->addr); + + if (sending_info == NULL) { + result = __bt_opp_client_start_sending(request_id, + address, file_path); + } else { + /* Insert data in the queue */ + data = g_malloc0(sizeof(bt_sending_data_t)); + data->file_path = g_new0(char *, file_count + 1); + data->address = g_strdup(address); + data->file_count = file_count; + data->request_id = request_id; + + 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]); + } + + transfer_list = g_slist_append(transfer_list, data); + } + + out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar)); + out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar)); + + g_array_append_vals(out_param1, &request_id, + sizeof(int)); + g_array_append_vals(out_param2, &result, sizeof(int)); + + dbus_g_method_return(context, out_param1, out_param2); + + g_array_free(out_param1, TRUE); + g_array_free(out_param2, TRUE); + + return result; +} + +int _bt_opp_client_cancel_push(void) +{ + DBusGConnection *g_conn; + DBusGProxy *client_proxy; + + retv_if(sending_info == NULL, BLUETOOTH_ERROR_NOT_IN_OPERATION); + + sending_info->is_canceled = TRUE; + + if (sending_info->transfer_info) { + dbus_g_proxy_call_no_reply(sending_info->transfer_info->proxy, + "Cancel", G_TYPE_INVALID, + G_TYPE_INVALID); + } else { + retv_if(sending_info->sending_proxy == NULL, + BLUETOOTH_ERROR_INTERNAL); + + g_conn = _bt_get_session_gconn(); + retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL); + + client_proxy = dbus_g_proxy_new_for_name(g_conn, BT_OBEX_SERVICE_NAME, + "/", BT_OBEX_CLIENT_INTERFACE); + + retv_if(client_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_cancel_call(client_proxy, + sending_info->sending_proxy); + + g_idle_add(__bt_cancel_push_cb, NULL); + } + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_opp_client_cancel_all_transfers(void) +{ + if (transfer_list) { + g_slist_free_full(transfer_list, + (GDestroyNotify)__bt_free_sending_data); + + transfer_list = NULL; + } + + _bt_opp_client_cancel_push(); + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_opp_client_is_sending(gboolean *sending) +{ + BT_CHECK_PARAMETER(sending); + + *sending = sending_info ? TRUE : FALSE; + + return BLUETOOTH_ERROR_NONE; +} diff --git a/bt-service/bt-service-rfcomm-client.c b/bt-service/bt-service-rfcomm-client.c new file mode 100644 index 0000000..dfa9681 --- /dev/null +++ b/bt-service/bt-service-rfcomm-client.c @@ -0,0 +1,767 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "bluetooth-api.h" +#include "bt-internal-types.h" + +#include "bt-service-common.h" +#include "bt-service-event.h" +#include "bt-service-util.h" +#include "bt-service-rfcomm-client.h" +#include "bt-service-rfcomm-server.h" + +typedef struct { + int req_id; + char *channel; + char *address; + char *uuid; + DBusGProxy *rfcomm_proxy; +} rfcomm_function_data_t; + +rfcomm_function_data_t *rfcomm_info; +GSList *client_list; + +static bt_rfcomm_info_t *__bt_rfcomm_get_client_info(int socket_fd) +{ + GSList *l; + bt_rfcomm_info_t *client_info; + + for (l = client_list; l != NULL; l = l->next) { + client_info = l->data; + + if (client_info == NULL) + continue; + + if (socket_fd == client_info->fd) + return client_info; + } + + return NULL; +} + +static int __bt_rfcomm_open_socket(char *dev_node) +{ + int socket_fd; + + socket_fd = open(dev_node, O_RDWR | O_NOCTTY); + + if (socket_fd < 0) { + BT_ERR("\nCan't open TTY : %s(%d)"); + return socket_fd; + } + + BT_DBG("/dev/rfcomm fd = %d", socket_fd); + + if (_bt_set_non_blocking_tty(socket_fd) < 0) { + /* Even if setting the tty fails we will continue */ + BT_ERR("Unable to set /dev/rfcomm fd = %d", socket_fd); + } + + return socket_fd; +} + +static int __bt_rfcomm_disconnect_request(int socket_fd) +{ + DBusGConnection *conn; + DBusGProxy *adapter_proxy; + DBusGProxy *rfcomm_proxy; + GError *error = NULL; + bt_rfcomm_info_t *client_info; + gchar *device_path = NULL; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + + retv_if(address == NULL, BLUETOOTH_ERROR_INVALID_PARAM); + + 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); + + client_info = __bt_rfcomm_get_client_info(socket_fd); + retv_if(client_info == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL, + G_TYPE_STRING, client_info->address, G_TYPE_INVALID, + DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID); + + retv_if(device_path == NULL, BLUETOOTH_ERROR_NOT_PAIRED); + + rfcomm_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + device_path, BT_SERIAL_INTERFACE); + + BT_DBG("device path: %s", device_path); + g_free(device_path); + + retv_if(rfcomm_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + BT_DBG("device node: %s", client_info->dev_node); + if (!dbus_g_proxy_call(rfcomm_proxy, "Disconnect", + &error, + G_TYPE_STRING, client_info->dev_node, + G_TYPE_INVALID, G_TYPE_INVALID)) { + if (error) { + BT_ERR("Disconnect Call Error, %s", error->message); + g_error_free(error); + } + g_object_unref(rfcomm_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + g_object_unref(rfcomm_proxy); + + return BLUETOOTH_ERROR_NONE; +} + +static int __bt_rfcomm_disconnect_cb(void *data) +{ + int result = BLUETOOTH_ERROR_NONE; + bt_rfcomm_info_t *client_info = data; + + retv_if(client_info == NULL, BLUETOOTH_ERROR_INTERNAL); + + _bt_send_event(BT_RFCOMM_CLIENT_EVENT, + BLUETOOTH_EVENT_RFCOMM_DISCONNECTED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &client_info->address, + DBUS_TYPE_STRING, &client_info->uuid, + DBUS_TYPE_INT16, &client_info->fd, + DBUS_TYPE_INVALID); + + client_list = g_slist_remove(client_list, client_info); + + g_source_remove(client_info->io_event); + close(client_info->fd); + g_free(client_info->dev_node); + g_free(client_info->address); + g_free(client_info->uuid); + g_free(client_info); + + return BLUETOOTH_ERROR_NONE; +} + +static int __bt_rfcomm_cancel_connect_cb(void *data) +{ + int result = BLUETOOTH_ERROR_CANCEL_BY_USER; + bluetooth_rfcomm_connection_t conn_info; + request_info_t *req_info; + GArray *out_param1; + GArray *out_param2; + + retv_if(rfcomm_info == NULL, BLUETOOTH_ERROR_INTERNAL); + + req_info = _bt_get_request_info(rfcomm_info->req_id); + + retv_if(req_info == NULL, BLUETOOTH_ERROR_INTERNAL); + retv_if(req_info->context == NULL, BLUETOOTH_ERROR_INTERNAL); + + memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t)); + conn_info.device_role = RFCOMM_ROLE_CLIENT; + g_strlcpy(conn_info.uuid, rfcomm_info->uuid, + BLUETOOTH_UUID_STRING_MAX); + conn_info.socket_fd = -1; + _bt_convert_addr_string_to_type(conn_info.device_addr.addr, + rfcomm_info->address); + + out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar)); + out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar)); + + g_array_append_vals(out_param1, &conn_info, + sizeof(bluetooth_rfcomm_connection_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); + + g_object_unref(rfcomm_info->rfcomm_proxy); + g_free(rfcomm_info->address); + g_free(rfcomm_info->uuid); + g_free(rfcomm_info->channel); + g_free(rfcomm_info); + rfcomm_info = NULL; + + return BLUETOOTH_ERROR_NONE; +} + +static int __bt_rfcomm_terminate_client(int socket_fd) +{ + BT_DBG("+"); + + int result; + bt_rfcomm_info_t *client_info; + + client_info = __bt_rfcomm_get_client_info(socket_fd); + retv_if(client_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM); + + result = __bt_rfcomm_disconnect_request(socket_fd); + + if (result != BLUETOOTH_ERROR_NONE) { + BT_ERR("Fail to disconnect socket"); + return result; + } + + /* Send the disconnected event after return the function */ + g_idle_add((GSourceFunc)__bt_rfcomm_disconnect_cb, client_info); + + return BLUETOOTH_ERROR_NONE; +} + +static gboolean __bt_rfcomm_client_data_received_cb(GIOChannel *chan, + GIOCondition cond, + gpointer data) +{ + char *buffer = NULL; + gsize len; + int result = BLUETOOTH_ERROR_NONE; + bt_rfcomm_info_t *client_info = data; + + BT_DBG("condition: %d", cond); + + retv_if(client_info == NULL, FALSE); + + if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) { + BT_ERR("Unix client disconnected (fd=%d)\n", client_info->fd); + __bt_rfcomm_terminate_client(client_info->fd); + return FALSE; + } + + buffer = g_malloc0(BT_RFCOMM_BUFFER_MAX + 1); + + if (g_io_channel_read_chars(chan, buffer, BT_RFCOMM_BUFFER_MAX, + &len, NULL) == G_IO_STATUS_ERROR) { + BT_ERR("IO Channel read error client"); + g_free(buffer); + __bt_rfcomm_terminate_client(client_info->fd); + return FALSE; + } + + if (len == 0) { + BT_ERR("Read failed len=%d, fd=%d\n", len, client_info->fd); + g_free(buffer); + __bt_rfcomm_terminate_client(client_info->fd); + return FALSE; + } + + BT_DBG("%s - clientfd = %d", buffer, client_info->fd); + + _bt_send_event(BT_RFCOMM_CLIENT_EVENT, + BLUETOOTH_EVENT_RFCOMM_DATA_RECEIVED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INT16, &client_info->fd, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &buffer, len, + DBUS_TYPE_INVALID); + + g_free(buffer); + + return TRUE; +} + +static void __bt_rfcomm_connected_cb(DBusGProxy *proxy, DBusGProxyCall *call, + gpointer user_data) +{ + BT_DBG("+\n"); + GError *err = NULL; + gchar *rfcomm_device_node; + int socket_fd = -1; + int result = BLUETOOTH_ERROR_NONE; + bt_rfcomm_info_t *client_info = NULL; + request_info_t *req_info; + bluetooth_rfcomm_connection_t conn_info; + GArray *out_param1; + GArray *out_param2; + + dbus_g_proxy_end_call(proxy, call, &err, + G_TYPE_STRING, &rfcomm_device_node, G_TYPE_INVALID); + + g_object_unref(proxy); + + if (rfcomm_info == NULL) { + BT_ERR("rfcomm_info == NULL"); + goto done; + } + + if (err != NULL) { + BT_ERR("Error occured in connecting port [%s]", err->message); + + if (!strcmp("Host is down", err->message)) + result = BLUETOOTH_ERROR_HOST_DOWN; + else + result = BLUETOOTH_ERROR_CONNECTION_ERROR; + + goto dbus_return; + } + + BT_DBG("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; + } + + client_info = g_malloc0(sizeof(bt_rfcomm_info_t)); + + client_info->fd = socket_fd; + client_info->dev_node = g_strdup(rfcomm_device_node); + 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); + 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, + client_info); + + g_io_channel_set_close_on_unref(client_info->io_channel, TRUE); + g_io_channel_set_flags(client_info->io_channel, + G_IO_FLAG_NONBLOCK, NULL); + + client_list = g_slist_append(client_list, client_info); + + _bt_send_event(BT_RFCOMM_CLIENT_EVENT, + BLUETOOTH_EVENT_RFCOMM_CONNECTED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &rfcomm_info->address, + DBUS_TYPE_STRING, &rfcomm_info->uuid, + DBUS_TYPE_INT16, &socket_fd, + DBUS_TYPE_INVALID); + +dbus_return: + req_info = _bt_get_request_info(rfcomm_info->req_id); + + if (req_info == NULL || req_info->context == NULL) + goto done; + + memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t)); + conn_info.device_role = RFCOMM_ROLE_CLIENT; + g_strlcpy(conn_info.uuid, rfcomm_info->uuid, + BLUETOOTH_UUID_STRING_MAX); + + if (client_info) + conn_info.socket_fd = client_info->fd; + else + conn_info.socket_fd = -1; + + _bt_convert_addr_string_to_type(conn_info.device_addr.addr, + rfcomm_info->address); + + out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar)); + out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar)); + + g_array_append_vals(out_param1, &conn_info, + sizeof(bluetooth_rfcomm_connection_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); + + ret_if(rfcomm_info == NULL); + + g_free(rfcomm_info->address); + g_free(rfcomm_info->uuid); + g_free(rfcomm_info->channel); + g_free(rfcomm_info); + rfcomm_info = NULL; +} + +static void __bt_rfcomm_discover_services_cb(DBusGProxy *proxy, DBusGProxyCall *call, + gpointer user_data) +{ + GError *err = NULL; + GHashTable *hash = NULL; + const char *dev_path = NULL; + DBusGConnection *conn; + DBusGProxy *rfcomm_proxy; + int result = BLUETOOTH_ERROR_NONE; + GArray *out_param1; + GArray *out_param2; + request_info_t *req_info; + bluetooth_rfcomm_connection_t conn_info; + + dbus_g_proxy_end_call(proxy, call, &err, + dbus_g_type_get_map("GHashTable", + G_TYPE_UINT, G_TYPE_STRING), + &hash, G_TYPE_INVALID); + + if (err != NULL) { + BT_ERR("Error occured in Proxy call [%s]\n", err->message); + result = BLUETOOTH_ERROR_CONNECTION_ERROR; + g_error_free(err); + goto fail; + } + + g_hash_table_destroy(hash); + + if (rfcomm_info == NULL) { + result = BLUETOOTH_ERROR_INTERNAL; + goto fail; + } + + conn = _bt_get_system_gconn(); + if (conn == NULL) { + BT_ERR("ERROR: Can't get on system bus"); + result = BLUETOOTH_ERROR_INTERNAL; + goto fail; + } + + dev_path = dbus_g_proxy_get_path(proxy); + + rfcomm_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + dev_path, + BT_SERIAL_INTERFACE); + + g_object_unref(proxy); + proxy = NULL; + + if (rfcomm_proxy == NULL) { + BT_ERR("Failed to get the rfcomm proxy\n"); + result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND; + goto fail; + } + + rfcomm_info->rfcomm_proxy = rfcomm_proxy; + + if (!dbus_g_proxy_begin_call(rfcomm_proxy, "Connect", + (DBusGProxyCallNotify)__bt_rfcomm_connected_cb, + NULL, /*user_data*/ + NULL, /*destroy*/ + G_TYPE_STRING, rfcomm_info->uuid, + G_TYPE_INVALID)) { + BT_ERR("RFCOMM connect Dbus Call Error"); + g_object_unref(rfcomm_proxy); + result = BLUETOOTH_ERROR_INTERNAL; + goto fail; + } + + BT_DBG("-\n"); + + return; +fail: + if (proxy) + g_object_unref(proxy); + + ret_if(rfcomm_info == NULL); + + req_info = _bt_get_request_info(rfcomm_info->req_id); + + if (req_info && req_info->context) { + memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t)); + + conn_info.device_role = RFCOMM_ROLE_CLIENT; + g_strlcpy(conn_info.uuid, rfcomm_info->uuid, + BLUETOOTH_UUID_STRING_MAX); + + conn_info.socket_fd = -1; + _bt_convert_addr_string_to_type(conn_info.device_addr.addr, + rfcomm_info->address); + + out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar)); + out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar)); + + g_array_append_vals(out_param1, &conn_info, + sizeof(bluetooth_rfcomm_connection_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); + } + + g_free(rfcomm_info->address); + g_free(rfcomm_info->uuid); + g_free(rfcomm_info); + rfcomm_info = NULL; +} + +int _bt_rfcomm_connect_using_uuid(int request_id, + bluetooth_device_address_t *device_address, + char *remote_uuid) +{ + DBusGConnection *conn; + DBusGProxy *adapter_proxy; + DBusGProxy *device_proxy; + gchar *device_path = NULL; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + + BT_CHECK_PARAMETER(address); + BT_CHECK_PARAMETER(remote_uuid); + retv_if(rfcomm_info != NULL, 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); + + _bt_convert_addr_type_to_string(address, device_address->addr); + + dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL, + G_TYPE_STRING, address, G_TYPE_INVALID, + DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID); + + retv_if(device_path == NULL, BLUETOOTH_ERROR_NOT_PAIRED); + + 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); + + rfcomm_info = g_malloc0(sizeof(rfcomm_function_data_t)); + rfcomm_info->address = g_strdup(address); + rfcomm_info->uuid = g_strdup(remote_uuid); + rfcomm_info->req_id = request_id; + + if (!dbus_g_proxy_begin_call(device_proxy, "DiscoverServices", + (DBusGProxyCallNotify)__bt_rfcomm_discover_services_cb, + NULL, NULL, + G_TYPE_STRING, rfcomm_info->uuid, + G_TYPE_INVALID)) { + BT_ERR("Could not call dbus proxy\n"); + g_object_unref(device_proxy); + g_free(rfcomm_info->address); + g_free(rfcomm_info->uuid); + g_free(rfcomm_info); + rfcomm_info = NULL; + return BLUETOOTH_ERROR_INTERNAL; + } + + return BLUETOOTH_ERROR_NONE; +} + +/* Range of the Channel : 0 <= channel <= 30 */ +int _bt_rfcomm_connect_using_channel(int request_id, + bluetooth_device_address_t *device_address, + char *channel) +{ + DBusGConnection *conn; + DBusGProxy *adapter_proxy; + DBusGProxy *device_proxy; + gchar *device_path = NULL; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + + BT_CHECK_PARAMETER(address); + retv_if(rfcomm_info != NULL, 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); + + _bt_convert_addr_type_to_string(address, device_address->addr); + + dbus_g_proxy_call(adapter_proxy, "FindDevice", NULL, + G_TYPE_STRING, address, G_TYPE_INVALID, + DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID); + + retv_if(device_path == NULL, BLUETOOTH_ERROR_NOT_PAIRED); + + device_proxy = dbus_g_proxy_new_for_name(conn, BT_BLUEZ_NAME, + device_path, + BT_SERIAL_INTERFACE); + g_free(device_path); + retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL); + + rfcomm_info = g_malloc0(sizeof(rfcomm_function_data_t)); + rfcomm_info->address = g_strdup(address); + rfcomm_info->channel = g_strdup(channel); + rfcomm_info->req_id = request_id; + rfcomm_info->rfcomm_proxy = device_proxy; + + if (!dbus_g_proxy_begin_call(device_proxy, "Connect", + (DBusGProxyCallNotify)__bt_rfcomm_connected_cb, + NULL, /*user_data*/ + NULL, /*destroy*/ + G_TYPE_STRING, channel, + G_TYPE_INVALID)) { + BT_ERR("RFCOMM connect Dbus Call Error"); + g_object_unref(device_proxy); + return BLUETOOTH_ERROR_INTERNAL; + } + + BT_DBG("-\n"); + + return BLUETOOTH_ERROR_NONE; +} + +/* Be used in RFCOMM client /server */ +int _bt_rfcomm_disconnect(int socket_fd) +{ + bt_rfcomm_info_t *socket_info; + + socket_info = __bt_rfcomm_get_client_info(socket_fd); + if (socket_info == NULL) + return _bt_rfcomm_server_disconnect(socket_fd); + + return __bt_rfcomm_terminate_client(socket_fd); +} + +/* Be used in RFCOMM client /server */ +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 */ + while (wbytes < length) { + written = write(socket_fd, buf + wbytes, + length - wbytes); + if (written <= 0) { + BT_ERR("write failed..\n"); + return BLUETOOTH_ERROR_NOT_IN_OPERATION; + } + + /* Synchronize the sending buffer */ + sync(); + fsync(socket_fd); + + wbytes += written; + } + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_rfcomm_cancel_connect(void) +{ + GError *error = NULL; + char *input_param; + + BT_DBG("+"); + + retv_if(rfcomm_info == NULL, BLUETOOTH_ERROR_NOT_IN_OPERATION); + retv_if(rfcomm_info->rfcomm_proxy == NULL, + BLUETOOTH_ERROR_INTERNAL); + + if (rfcomm_info->uuid) + input_param = rfcomm_info->uuid; + else + input_param = rfcomm_info->channel; + + retv_if(input_param == NULL, BLUETOOTH_ERROR_INTERNAL); + + if (!dbus_g_proxy_call(rfcomm_info->rfcomm_proxy, + "Disconnect", + &error, + G_TYPE_STRING, input_param, + G_TYPE_INVALID, G_TYPE_INVALID)) { + if (error) { + BT_ERR("Disconnect Dbus Call Error, %s", error->message); + g_error_free(error); + } + return BLUETOOTH_ERROR_INTERNAL; + } + + /* Send the connected event after return the function */ + g_idle_add((GSourceFunc) __bt_rfcomm_cancel_connect_cb, NULL); + + BT_DBG("-"); + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_rfcomm_is_connected(gboolean *connected) +{ + BT_CHECK_PARAMETER(connected); + + *connected = (client_list == NULL || g_slist_length(client_list) == 0) ? + FALSE : TRUE; + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_rfcomm_is_device_connected(bluetooth_device_address_t *device_address, + gboolean *connected) +{ + GSList *l; + bt_rfcomm_info_t *client_info; + char address[BT_ADDRESS_STRING_SIZE] = { 0 }; + + BT_CHECK_PARAMETER(device_address); + BT_CHECK_PARAMETER(connected); + + _bt_convert_addr_type_to_string(address, device_address->addr); + + *connected = FALSE; + + for (l = client_list; l != NULL; l = l->next) { + client_info = l->data; + + if (client_info == NULL) + continue; + + if (g_strcmp0(address, client_info->address) == 0) { + *connected = TRUE; + return BLUETOOTH_ERROR_NONE; + } + } + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_rfcomm_client_disconnect_all(void) +{ + GSList *l; + bt_rfcomm_info_t *client_info; + + for (l = client_list; l != NULL; l = l->next) { + client_info = l->data; + + if (client_info == NULL) + continue; + + _bt_rfcomm_disconnect(client_info->fd); + } + + return BLUETOOTH_ERROR_NONE; +} + diff --git a/bt-service/bt-service-rfcomm-server.c b/bt-service/bt-service-rfcomm-server.c new file mode 100644 index 0000000..bb6354e --- /dev/null +++ b/bt-service/bt-service-rfcomm-server.c @@ -0,0 +1,932 @@ +/* + * bluetooth-frwk + * + * Copyright (c) 2012 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 + * + * 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 "bluetooth-api.h" +#include "bt-internal-types.h" + +#include "bt-service-common.h" +#include "bt-service-event.h" +#include "bt-service-util.h" +#include "bt-service-rfcomm-client.h" +#include "bt-service-rfcomm-server.h" +#include "bt-service-agent.h" + +/* Range of RFCOMM server ID : 0 ~ 244 */ +#define BT_RFCOMM_SERVER_ID_MAX 245 + +#define BT_RFCOMM_PROXY_ADDRESS "x00/bluez/rfcomm" +#define BT_RFCOMM_SOCKET_ADDRESS "/bluez/rfcomm" + +typedef struct { + int data_fd; + char *uuid; + char *remote_address; +} bt_rfcomm_event_info_t; + +GSList *server_list; +static int latest_id = -1; +static gboolean server_id_used[BT_RFCOMM_SERVER_ID_MAX]; + +int __bt_rfcomm_assign_server_id(void) +{ + int index; + + BT_DBG("latest_id: %d", latest_id); + + index = latest_id + 1; + + if (index >= BT_RFCOMM_SERVER_ID_MAX) + index = 0; + + BT_DBG("index: %d", index); + + while (server_id_used[index] == TRUE) { + if (index == latest_id) { + /* No available ID */ + BT_DBG("All request ID is used"); + return -1; + } + + index++; + + if (index >= BT_RFCOMM_SERVER_ID_MAX) + index = 0; + } + + latest_id = index; + server_id_used[index] = TRUE; + + BT_DBG("Assigned Id: %d", latest_id); + + return latest_id; +} + +void __bt_rfcomm_delete_server_id(int server_id) +{ + ret_if(server_id >= BT_RFCOMM_SERVER_ID_MAX); + ret_if(server_id < 0); + + server_id_used[server_id] = FALSE; + + /* Next server will use this ID */ + latest_id = server_id - 1; +} + + +static bt_rfcomm_server_info_t *__bt_rfcomm_get_server_info(int control_fd) +{ + GSList *l; + bt_rfcomm_server_info_t *server_info; + + retv_if(control_fd <= 0, NULL); + + for (l = server_list; l != NULL; l = l->next) { + server_info = l->data; + + if (server_info == NULL) + continue; + + if (control_fd == server_info->control_fd) + return server_info; + } + + return NULL; +} + +static bt_rfcomm_server_info_t *__bt_rfcomm_get_server_info_using_data_fd(int data_fd) +{ + GSList *l; + bt_rfcomm_server_info_t *server_info; + + retv_if(data_fd <= 0, NULL); + + for (l = server_list; l != NULL; l = l->next) { + server_info = l->data; + + if (server_info == NULL) + continue; + + if (data_fd == server_info->data_fd) + return server_info; + } + + return NULL; +} + +static DBusGProxy *__bt_rfcomm_get_serial_manager_proxy(void) +{ + DBusGProxy *proxy; + DBusGConnection *g_conn; + char *adapter_path; + + BT_DBG("+"); + + g_conn = _bt_get_system_gconn(); + retv_if(g_conn == NULL, NULL); + + adapter_path = _bt_get_adapter_path(); + retv_if(adapter_path == NULL, NULL); + + proxy = dbus_g_proxy_new_for_name(g_conn, BT_BLUEZ_NAME, + adapter_path, BT_SERIAL_MANAGER_INTERFACE); + + g_free(adapter_path); + + BT_DBG("-"); + + return proxy; +} + +static DBusGProxy *__bt_get_serial_proxy(char *serial_path) +{ + DBusGProxy *proxy; + DBusGConnection *g_conn; + + g_conn = _bt_get_system_gconn(); + retv_if(g_conn == NULL, NULL); + + proxy = dbus_g_proxy_new_for_name(g_conn, BT_BLUEZ_NAME, + serial_path, BT_SERIAL_PROXY_INTERFACE); + + return proxy; +} + +static char *__bt_rfcomm_get_proxy_address(int server_id) +{ + BT_DBG("+"); + + return g_strdup_printf("%s%d", + BT_RFCOMM_PROXY_ADDRESS, + server_id); +} + +int __bt_rfcomm_get_socket(int server_id) +{ + int result; + int socket_fd; + char *socket_address = NULL; + struct sockaddr_un server_addr; + + retv_if(server_id < 0, -1); + + socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); + retv_if(socket_fd < 0, -1); + + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sun_family = PF_UNIX; + + socket_address = g_strdup_printf("%s%d", + BT_RFCOMM_SOCKET_ADDRESS, + server_id); + + BT_DBG("socket_address: %s", socket_address); + + g_strlcpy(server_addr.sun_path + 1, socket_address, + sizeof(server_addr.sun_path)); + + if (bind(socket_fd, (struct sockaddr *)&server_addr, + sizeof(server_addr)) < 0) { + BT_ERR("Can't Bind Sock"); + goto fail; + } + + BT_DBG("socket_fd = %d", socket_fd); + + result = _bt_set_socket_non_blocking(socket_fd); + + if (result != BLUETOOTH_ERROR_NONE) { + BT_DBG("Cannot set the tty"); + goto fail; + } + + g_free(socket_address); + return socket_fd; +fail: + g_free(socket_address); + close(socket_fd); + return -1; +} + +int _bt_rfcomm_create_socket(char *sender, char *uuid) +{ + DBusGProxy *serial_manager = NULL; + DBusGProxy *serial_proxy = NULL; + GError *error = NULL; + char *proxy_address = NULL; + char *serial_path = NULL; + int server_id; + int socket_fd; + bt_rfcomm_server_info_t *server_info; + + BT_CHECK_PARAMETER(uuid); + + server_id = __bt_rfcomm_assign_server_id(); + retv_if(server_id < 0, BLUETOOTH_ERROR_INTERNAL); + + serial_manager = __bt_rfcomm_get_serial_manager_proxy(); + if (serial_manager == NULL) + goto fail; + + proxy_address = __bt_rfcomm_get_proxy_address(server_id); + if (proxy_address == NULL) + goto fail; + + dbus_g_proxy_call(serial_manager, "CreateProxy", NULL, + G_TYPE_STRING, uuid, + G_TYPE_STRING, proxy_address, + G_TYPE_INVALID, + G_TYPE_STRING, &serial_path, + G_TYPE_INVALID); + + if (serial_path == NULL) + goto fail; + + BT_DBG("serial_path: %s", serial_path); + + serial_proxy = __bt_get_serial_proxy(serial_path); + if (serial_proxy == NULL) + goto fail; + + if (!dbus_g_proxy_call(serial_proxy, "Enable", &error, + G_TYPE_INVALID, G_TYPE_INVALID)) { + if (error != NULL) { + 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"); + goto fail; + } + + server_info = g_malloc0(sizeof(bt_rfcomm_server_info_t)); + server_info->server_id = server_id; + server_info->serial_proxy = serial_proxy; + server_info->manager_proxy = serial_manager; + server_info->serial_path = g_strdup(serial_path); + server_info->uuid = g_strdup(uuid); + server_info->sender = g_strdup(sender); + server_info->control_fd = socket_fd; + + server_list = g_slist_append(server_list, server_info); + + g_free(proxy_address); + + return socket_fd; +fail: + __bt_rfcomm_delete_server_id(server_id); + g_free(proxy_address); + + if (serial_manager) { + if (serial_path) { + dbus_g_proxy_call(serial_manager, "RemoveProxy", NULL, + G_TYPE_STRING, serial_path, + G_TYPE_INVALID, + G_TYPE_INVALID); + } + g_object_unref(serial_manager); + } + + if (serial_proxy) + g_object_unref(serial_proxy); + + return BLUETOOTH_ERROR_INTERNAL; +} + +static gboolean __bt_rfcomm_server_data_received_cb(GIOChannel *chan, + GIOCondition cond, + gpointer data) +{ + char *buffer = NULL; + gsize len; + int result = BLUETOOTH_ERROR_NONE; + bt_rfcomm_server_info_t *server_info = data; + + retv_if(server_info == NULL, FALSE); + + if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) { + BT_ERR("Unix server disconnected: %d", server_info->data_fd); + _bt_rfcomm_server_disconnect(server_info->data_fd); + return FALSE; + } + + buffer = g_malloc0(BT_RFCOMM_BUFFER_MAX + 1); + + if (g_io_channel_read_chars(chan, buffer, BT_RFCOMM_BUFFER_MAX, &len, NULL) == + G_IO_STATUS_ERROR) { + BT_ERR("IO Channel read error server"); + g_free(buffer); + _bt_rfcomm_server_disconnect(server_info->data_fd); + return FALSE; + } + + if (len == 0) { + BT_ERR("Read failed len=%d, fd=%d\n", + len, server_info->data_fd); + g_free(buffer); + _bt_rfcomm_server_disconnect(server_info->data_fd); + return FALSE; + } + + _bt_send_event(BT_RFCOMM_SERVER_EVENT, + BLUETOOTH_EVENT_RFCOMM_DATA_RECEIVED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INT16, &server_info->data_fd, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &buffer, len, + DBUS_TYPE_INVALID); + + g_free(buffer); + + return TRUE; +} + +int __bt_rfcomm_server_get_address(bt_rfcomm_server_info_t *server_info) +{ + DBusMessage *msg; + DBusMessage *reply; + DBusError error; + DBusMessageIter reply_iter; + DBusMessageIter reply_iter_entry; + DBusConnection *conn; + const char *property; + + BT_CHECK_PARAMETER(server_info); + + /* GetInfo Proxy Part */ + msg = dbus_message_new_method_call(BT_BLUEZ_NAME, + server_info->serial_path, + BT_SERIAL_PROXY_INTERFACE, + "GetInfo"); + + retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL); + + dbus_error_init(&error); + + conn = _bt_get_system_conn(); + + reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &error); + dbus_message_unref(msg); + + if (reply == NULL) { + BT_ERR("Can't Call GetInfo Proxy"); + if (dbus_error_is_set(&error)) { + BT_ERR("%s", error.message); + dbus_error_free(&error); + } + return BLUETOOTH_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"); + goto fail; + } + + 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; + DBusMessageIter dict_entry_val; + + dbus_message_iter_recurse(&reply_iter_entry, &dict_entry); + + dbus_message_iter_get_basic(&dict_entry, &property); + + if (g_strcmp0("connected", property) == 0) { + dbus_bool_t value; + + dbus_message_iter_next(&dict_entry); + dbus_message_iter_recurse(&dict_entry, &dict_entry_val); + dbus_message_iter_get_basic(&dict_entry_val, &value); + + if (value == FALSE) + goto fail; + + /*Parsing the address */ + dbus_message_iter_next(&reply_iter_entry); + 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("address", property) == 0) { + if (!dbus_message_iter_next(&dict_entry)) { + BT_ERR("Failed getting next dict entry\n"); + goto fail; + } + + if (dbus_message_iter_get_arg_type(&dict_entry) != + DBUS_TYPE_VARIANT) { + BT_ERR("Failed get arg type varient\n"); + goto fail; + } + + /*Getting the value of the varient*/ + dbus_message_iter_recurse(&dict_entry, + &dict_entry_val); + + if (dbus_message_iter_get_arg_type(&dict_entry_val) != + DBUS_TYPE_STRING) { + BT_ERR("Failed get arg type string\n"); + goto fail; + } + + /*get value string address*/ + dbus_message_iter_get_basic(&dict_entry_val, &property); + + BT_DBG("Address = %s\n", property); + + g_free(server_info->remote_address); + server_info->remote_address = g_strdup(property); + } + + } + + dbus_message_iter_next(&reply_iter_entry); + } + + dbus_message_unref(reply); + + return BLUETOOTH_ERROR_NONE; + +fail: + dbus_message_unref(reply); + return BLUETOOTH_ERROR_INTERNAL; +} + +static gboolean __bt_rfcomm_server_connected_cb(GIOChannel *chan, + GIOCondition cond, + gpointer data) +{ + bt_rfcomm_server_info_t *server_info; + request_info_t *req_info; + int client_sock; + int addr_len; + struct sockaddr_un sock_addr; + int result = BLUETOOTH_ERROR_NONE; + + BT_DBG("rfcomm_server.server_io_channel has %d", cond); + + server_info = data; + retv_if(server_info == NULL, FALSE); + + if (cond & G_IO_NVAL) + return FALSE; + + if (cond & (G_IO_HUP | G_IO_ERR)) { + _bt_rfcomm_remove_socket(server_info->control_fd); + return FALSE; + } + + memset(&sock_addr, 0, sizeof(struct sockaddr_un)); + addr_len = sizeof(struct sockaddr_un); + + client_sock = accept(server_info->control_fd, + (struct sockaddr *)&sock_addr, + (socklen_t *)&addr_len); + + if (client_sock < 0) { + BT_ERR("Server Accept Error"); + return TRUE; + + } else { + BT_DBG("Accept Client Sock.(%d)\n", client_sock); + + } + + if (_bt_set_non_blocking_tty(client_sock) < 0) { + /* Even if setting the tty fails we will continue */ + BT_ERR("Setting the tty properties failed(%d)\n", client_sock); + } + + server_info->data_fd = client_sock; + server_info->data_io = g_io_channel_unix_new(client_sock); + + g_io_channel_set_encoding(server_info->data_io, NULL, NULL); + g_io_channel_set_flags(server_info->data_io, G_IO_FLAG_NONBLOCK, NULL); + g_io_channel_set_close_on_unref(server_info->data_io, TRUE); + + server_info->data_id = + g_io_add_watch(server_info->data_io, + G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, + __bt_rfcomm_server_data_received_cb, server_info); + + g_io_channel_unref(server_info->data_io); + + __bt_rfcomm_server_get_address(server_info); + + if (server_info->remote_address == NULL) + server_info->remote_address = g_strdup(""); + + if (server_info->server_type == BT_CUSTOM_SERVER) { + int result; + GArray *out_param1; + GArray *out_param2; + + req_info = _bt_get_request_info(server_info->accept_id); + if (req_info == NULL || req_info->context == NULL) { + BT_DBG("info is NULL"); + goto done; + } + + server_info->accept_id = 0; + result = BLUETOOTH_ERROR_NONE; + + out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar)); + out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar)); + + g_array_append_vals(out_param1, &server_info->data_fd, + sizeof(int)); + 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: + _bt_send_event(BT_RFCOMM_SERVER_EVENT, + BLUETOOTH_EVENT_RFCOMM_CONNECTED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &server_info->remote_address, + DBUS_TYPE_STRING, &server_info->uuid, + DBUS_TYPE_INT16, &server_info->data_fd, + DBUS_TYPE_INVALID); + + BT_DBG("-"); + return TRUE; +} + + +int _bt_rfcomm_listen(int socket_fd, int max_pending, gboolean is_native) +{ + int io_id; + bt_rfcomm_server_info_t *server_info; + GIOChannel *io_channel; + + server_info = __bt_rfcomm_get_server_info(socket_fd); + retv_if(server_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM); + retv_if(server_info->control_io != NULL, BLUETOOTH_ERROR_DEVICE_BUSY); + + if (listen(socket_fd, max_pending) != 0) { + BT_DBG("Fail to listen"); + return BLUETOOTH_ERROR_INTERNAL; + } + + io_channel = g_io_channel_unix_new(socket_fd); + server_info->control_io = io_channel; + + g_io_channel_set_close_on_unref(io_channel, TRUE); + g_io_channel_set_encoding(io_channel, NULL, NULL); + g_io_channel_set_flags(io_channel, G_IO_FLAG_NONBLOCK, NULL); + + io_id = g_io_add_watch(io_channel, + G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, + __bt_rfcomm_server_connected_cb, + server_info); + + server_info->control_id = io_id; + g_io_channel_unref(io_channel); + + /* BT_CUSTOM_SERVER / BT_NATIVE_SERVER*/ + if (is_native) { + server_info->server_type = BT_NATIVE_SERVER; + } else { + server_info->server_type = BT_CUSTOM_SERVER; + _bt_register_osp_server_in_agent(BT_RFCOMM_SERVER, + server_info->uuid); + } + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_rfcomm_remove_socket(int socket_fd) +{ + bt_rfcomm_server_info_t *server_info; + int result = BLUETOOTH_ERROR_NONE; + + BT_DBG("+"); + + server_info = __bt_rfcomm_get_server_info(socket_fd); + retv_if(server_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM); + + if (server_info->serial_proxy) { + if (!dbus_g_proxy_call(server_info->serial_proxy, "Disable", + NULL, + G_TYPE_INVALID, + G_TYPE_INVALID)) { + BT_DBG("Fail to disable"); + } + } + + if (server_info->manager_proxy && server_info->serial_path) { + if (!dbus_g_proxy_call(server_info->manager_proxy, + "RemoveProxy", NULL, + G_TYPE_STRING, server_info->serial_path, + G_TYPE_INVALID, + G_TYPE_INVALID)) { + BT_DBG("Fail to remove proxy"); + } + } + + if (server_info->server_type == BT_CUSTOM_SERVER) { + _bt_unregister_osp_server_in_agent(BT_RFCOMM_SERVER, + server_info->uuid); + } + + _bt_send_event(BT_RFCOMM_SERVER_EVENT, + BLUETOOTH_EVENT_RFCOMM_SERVER_REMOVED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INT16, &server_info->data_fd, + DBUS_TYPE_INVALID); + + _bt_rfcomm_server_disconnect(server_info->data_fd); + + if (server_info->control_id > 0) + g_source_remove(server_info->control_id); + + if (server_info->control_fd > 0) + close(server_info->control_fd); + + server_list = g_slist_remove(server_list, server_info); + + g_free(server_info->serial_path); + g_free(server_info->uuid); + g_free(server_info->sender); + g_free(server_info); + + BT_DBG("-"); + + return BLUETOOTH_ERROR_NONE; +} + +static int __bt_rfcomm_server_disconnect_cb(void *data) +{ + bt_rfcomm_event_info_t *event_info = data; + int result = BLUETOOTH_ERROR_NONE; + + retv_if(event_info == NULL, BLUETOOTH_ERROR_NONE); + retv_if(event_info->uuid == NULL, BLUETOOTH_ERROR_NONE); + + if (event_info->remote_address == NULL) + event_info->remote_address = g_strdup(""); + + _bt_send_event(BT_RFCOMM_SERVER_EVENT, + BLUETOOTH_EVENT_RFCOMM_DISCONNECTED, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_STRING, &event_info->remote_address, + DBUS_TYPE_STRING, &event_info->uuid, + DBUS_TYPE_INT16, &event_info->data_fd, + DBUS_TYPE_INVALID); + + g_free(event_info->uuid); + g_free(event_info->remote_address); + g_free(event_info); + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_rfcomm_server_disconnect(int data_fd) +{ + bt_rfcomm_server_info_t *server_info; + bt_rfcomm_event_info_t *event_info; + + BT_DBG("+"); + + retv_if(data_fd <= 0, BLUETOOTH_ERROR_INVALID_PARAM); + + server_info = __bt_rfcomm_get_server_info_using_data_fd(data_fd); + retv_if(server_info == NULL, BLUETOOTH_ERROR_INVALID_PARAM); + + if (server_info->data_id > 0) + g_source_remove(server_info->data_id); + + if (server_info->data_fd > 0) + close(server_info->data_fd); + + event_info = g_malloc0(sizeof(bt_rfcomm_event_info_t)); + event_info->data_fd = server_info->data_fd; + event_info->remote_address = g_strdup(server_info->remote_address); + event_info->uuid = g_strdup(server_info->uuid); + + /* Send the disconnected event after return the function */ + g_idle_add((GSourceFunc)__bt_rfcomm_server_disconnect_cb, event_info); + + g_free(server_info->remote_address); + server_info->remote_address = NULL; + server_info->data_fd = -1; + server_info->data_id = 0; + server_info->data_io = NULL; + + BT_DBG("-"); + + return BLUETOOTH_ERROR_NONE; +} + +/* To support the BOT */ +int _bt_rfcomm_is_uuid_available(char *uuid, gboolean *available) +{ + GSList *l; + bt_rfcomm_server_info_t *server_info; + + BT_CHECK_PARAMETER(uuid); + BT_CHECK_PARAMETER(available); + + *available = FALSE; + + for (l = server_list; l != NULL; l = l->next) { + server_info = l->data; + + if (server_info == NULL) + continue; + + if (g_ascii_strcasecmp(uuid, server_info->uuid) == 0) { + *available = TRUE; + return BLUETOOTH_ERROR_NONE; + } + } + + 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) +{ + 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); + + 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); + + return BLUETOOTH_ERROR_NONE; +} + +/* To support the BOT */ +int _bt_rfcomm_reject_connection(int server_fd) +{ + 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); + + if (!_bt_agent_reply_authorize(FALSE)) + return BLUETOOTH_ERROR_INTERNAL; + + return BLUETOOTH_ERROR_NONE; +} + +bt_rfcomm_server_info_t *_bt_rfcomm_get_server_info_using_uuid(char *uuid) +{ + GSList *l; + bt_rfcomm_server_info_t *server_info; + + retv_if(uuid == NULL, NULL); + + for (l = server_list; l != NULL; l = l->next) { + server_info = l->data; + + if (server_info == NULL) + continue; + + if (g_strcmp0(server_info->uuid, uuid) == 0) + return server_info; + } + + return NULL; +} + +int _bt_rfcomm_server_disconnect_all_connection(void) +{ + GSList *l; + bt_rfcomm_server_info_t *server_info; + + for (l = server_list; l != NULL; l = l->next) { + server_info = l->data; + + if (server_info == NULL) + continue; + + _bt_rfcomm_disconnect(server_info->data_fd); + } + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_rfcomm_server_check_existence(gboolean *existence) +{ + BT_CHECK_PARAMETER(existence); + + if (server_list && g_slist_length(server_list) > 0) { + *existence = TRUE; + } else { + *existence = FALSE; + } + + return BLUETOOTH_ERROR_NONE; +} + +int _bt_rfcomm_server_check_termination(char *name) +{ + GSList *l; + bt_rfcomm_server_info_t *server_info; + + BT_CHECK_PARAMETER(name); + + for (l = server_list; l != NULL; l = l->next) { + server_info = l->data; + + if (server_info == NULL) + continue; + + if (g_strcmp0(server_info->sender, name) == 0) { + _bt_rfcomm_remove_socket(server_info->control_fd); + } + } + + return BLUETOOTH_ERROR_NONE; +} + + diff --git a/bt-service/bt-service-util.c b/bt-service/bt-service-util.c new file mode 100644 index 0000000..5afbc4e --- /dev/null +++ b/bt-service/bt-service-util.c @@ -0,0 +1,148 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 "bluetooth-api.h" +#include "bt-service-common.h" +#include "bt-service-util.h" + +static GSList *req_list = NULL; + +/* available request id : 0 ~ 244 */ +#define BT_REQUEST_ID_RANGE_MAX 245 + +static int assigned_id; +static gboolean req_id_used[BT_REQUEST_ID_RANGE_MAX]; + +void _bt_init_request_id(void) +{ + assigned_id = 0; + memset(req_id_used, 0x00, BT_REQUEST_ID_RANGE_MAX); +} + +int _bt_assign_request_id(void) +{ + int index; + + index = assigned_id + 1; + + if (index >= BT_REQUEST_ID_RANGE_MAX) + index = 0; + + while (req_id_used[index] == TRUE) { + if (index == assigned_id) { + /* No available ID */ + BT_ERR("All request ID is used"); + return -1; + } + + index++; + + if (index >= BT_REQUEST_ID_RANGE_MAX) + index = 0; + } + + assigned_id = index; + req_id_used[index] = TRUE; + + return assigned_id; +} + +void _bt_delete_request_id(int request_id) +{ + ret_if(request_id >= BT_REQUEST_ID_RANGE_MAX); + ret_if(request_id < 0); + + req_id_used[request_id] = FALSE; +} + +void _bt_init_request_list(void) +{ + _bt_clear_request_list(); +} + +/* insert request next to head */ +int _bt_insert_request_list(int req_id, int service_function, + char *name, DBusGMethodInvocation *context) +{ + request_info_t *info; + + info = g_malloc0(sizeof(request_info_t)); + + info->req_id = req_id; + info->service_function = service_function; + info->context = context; + + req_list = g_slist_append(req_list, info); + + return BLUETOOTH_ERROR_NONE; +} + +request_info_t *_bt_get_request_info(int req_id) +{ + GSList *l; + request_info_t *info; + + for (l = req_list; l != NULL; l = g_slist_next(l)) { + info = l->data; + if (info == NULL) + continue; + + if (info->req_id == req_id) + return info; + } + + return NULL; +} + +/* delete request which has the target req_id */ +int _bt_delete_request_list(int req_id) +{ + GSList *l; + request_info_t *info; + + for (l = req_list; l != NULL; l = g_slist_next(l)) { + info = l->data; + if (info == NULL) + continue; + + if (info->req_id == req_id) { + req_list = g_slist_remove(req_list, info); + g_free(info); + return BLUETOOTH_ERROR_NONE; + } + } + + return BLUETOOTH_ERROR_NOT_FOUND; +} + +void _bt_clear_request_list(void) +{ + if (req_list) { + g_slist_foreach(req_list, (GFunc)g_free, NULL); + g_slist_free(req_list); + req_list = NULL; + } +} + diff --git a/bt-service/include/bt-request-handler.h b/bt-service/include/bt-request-handler.h new file mode 100644 index 0000000..a01ad63 --- /dev/null +++ b/bt-service/include/bt-request-handler.h @@ -0,0 +1,69 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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_REQUEST_HANDLER_H_ +#define _BT_REQUEST_HANDLER_H_ + +#include +#include +#include +#include + +#include "bt-internal-types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BT_SERVICE_NAME "org.projectx.bt" +#define BT_SERVICE_PATH "/org/projectx/bt_service" + +#define BT_SERVICE_TYPE (bt_service_get_type()) + +typedef struct _BtService +{ + GObject object; +} BtService; + +typedef struct _BtServiceClass +{ + GObjectClass object_class; +} BtServiceClass; + +gboolean bt_service_request( + BtService *service, + int service_type, + int service_function, + int request_type, + GArray* in_param1, + GArray* in_param2, + GArray* in_param3, + GArray* in_param4, + GArray* in_param5, + DBusGMethodInvocation *context); + +int _bt_service_register(void); + +void _bt_service_unregister(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_REQUEST_HANDLER_H_*/ + diff --git a/bt-service/include/bt-service-adapter.h b/bt-service/include/bt-service-adapter.h new file mode 100644 index 0000000..2eb26d0 --- /dev/null +++ b/bt-service/include/bt-service-adapter.h @@ -0,0 +1,95 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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_H_ +#define _BT_SERVICE_ADAPTER_H_ + +#include +#include +#include "bluetooth-api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + BT_DEACTIVATED, + BT_ACTIVATED, + BT_ACTIVATING, + BT_DEACTIVATING, +} bt_status_t; + +int _bt_enable_adapter(void); + +int _bt_disable_adapter(void); + +int _bt_reset_adapter(void); + +void _bt_handle_adapter_added(void); + +void _bt_handle_adapter_removed(void); + +int _bt_check_adapter(int *status); + +void *_bt_get_adapter_agent(void); + +void _bt_set_discovery_status(gboolean mode); + +int _bt_get_local_address(bluetooth_device_address_t *local_address); + +int _bt_get_local_name(bluetooth_device_name_t *local_name); + +int _bt_set_local_name(char *local_name); + +int _bt_is_service_used(char *service_uuid, gboolean *used); + +int _bt_get_discoverable_mode(int *mode); + +int _bt_set_discoverable_mode(int discoverable_mode, int timeout); + +int _bt_start_discovery(void); + +int _bt_cancel_discovery(void); + +int _bt_get_bonded_devices(GArray **dev_list); + +int _bt_get_bonded_device_info(bluetooth_device_address_t *device_address, + bluetooth_device_info_t *dev_info); + +int _bt_get_timeout_value(int *timeout); + +gboolean _bt_is_discovering(void); + +gboolean _bt_get_cancel_by_user(void); + +void _bt_set_cancel_by_user(gboolean value); + +gboolean _bt_get_discoverying_property(void); + +int _bt_get_discoverable_timeout_property(void); + +bt_status_t _bt_adapter_get_status(void); + +void _bt_handle_flight_mode_noti(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_SERVICE_ADAPTER_H_*/ + diff --git a/bt-service/include/bt-service-agent.h b/bt-service/include/bt-service-agent.h new file mode 100644 index 0000000..0b0937e --- /dev/null +++ b/bt-service/include/bt-service-agent.h @@ -0,0 +1,125 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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_AGENT_H +#define BT_SERVICE_AGENT_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) + +#define BT_AGENT_PADDING_SIZE 4096 +#define BT_MAX_SERVICES_FOR_DEVICE 20 /**< This specifies maximum number of services a + device can support */ +#define BT_MAX_EVENT_STR_LENGTH 50 +#define BT_AGENT_ADDR_SIZE 18 + +/* Define Error type */ +#define BT_AGENT_FAIL -1 +#define BT_AGENT_ERROR_NONE 0 + +#define BT_FILE_VISIBLE_TIME "file/private/libug-setting-bluetooth-efl/visibility_time" + +typedef enum { + HS_PROFILE_UUID = ((unsigned short)0x1108), /** +#include +#include "bluetooth-api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + BT_AUDIO_HSP = 0x00, + BT_AUDIO_A2DP, + BT_AUDIO_ALL, +} bt_audio_type_t; + + +int _bt_audio_connect(int request_id, int type, + bluetooth_device_address_t *device_address, + GArray **out_param1); + +int _bt_audio_disconnect(int request_id, int type, + 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); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_SERVICE_AUDIO_H_*/ + diff --git a/bt-service/include/bt-service-avrcp.h b/bt-service/include/bt-service-avrcp.h new file mode 100644 index 0000000..c7309ec --- /dev/null +++ b/bt-service/include/bt-service-avrcp.h @@ -0,0 +1,53 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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_AVRCP_H_ +#define _BT_SERVICE_AVRCP_H_ + +#include +#include +#include +#include + +#include "bluetooth-api.h" +#include "bluetooth-media-control.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BLUEZ_MEDIA_PLAYER_INTERFACE "org.bluez.MediaPlayer" +#define BT_MEDIA_OBJECT_PATH "/Musicplayer" + +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); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_SERVICE_AVRCP_H_*/ + diff --git a/bt-service/include/bt-service-common.h b/bt-service/include/bt-service-common.h new file mode 100644 index 0000000..3b79f3a --- /dev/null +++ b/bt-service/include/bt-service-common.h @@ -0,0 +1,212 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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_COMMON_H_ +#define _BT_SERVICE_COMMON_H_ + +#include +#include +#include +#include + +#include "bluetooth-api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#undef LOG_TAG +#define LOG_TAG "BLUETOOTH_FRWK_SERVICE" + +#define BT_DBG(fmt, args...) \ + SLOGD(fmt, ##args) +#define BT_ERR(fmt, args...) \ + 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_CHECK_PARAMETER(arg) \ + do { \ + if (arg == NULL) \ + { \ + BT_ERR("INVALID PARAMETER"); \ + return BLUETOOTH_ERROR_INVALID_PARAM; \ + } \ + } while (0) + +#define BT_CHANNEL_LENGTH_MAX 5 +#define BT_ADDRESS_LENGTH_MAX 6 +#define BT_ADDRESS_STRING_SIZE 18 +#define BT_RFCOMM_BUFFER_MAX 1024 +#define BT_LOWER_ADDRESS_LENGTH 9 + +#define BT_AGENT_AUTO_PAIR_BLACKLIST_FILE (APP_SYSCONFDIR"/auto-pair-blacklist") +#define BT_AGENT_NEW_LINE "\r\n" + +#define BT_MAX_DBUS_TIMEOUT 45000 +#define BT_ENABLE_TIMEOUT 5000 /* 5 seconds */ +#define BT_DISCOVERY_FINISHED_DELAY 200 + +#define MANAGER_EVENT_MATCH_RULE \ + "type='signal'," \ + "interface='%s'," \ + "path='%s'" + +#define EVENT_MATCH_RULE \ + "type='signal'," \ + "interface='%s'," + +#define BT_TEMINATING_WAIT_TIME 200 + +#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." + +#define BT_BLUEZ_NAME "org.bluez" +#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.bluez.Manager" +#define BT_ADAPTER_INTERFACE "org.bluez.Adapter" +#define BT_AGENT_INTERFACE "org.bluez.Agent" +#define BT_DEVICE_INTERFACE "org.bluez.Device" +#define BT_INPUT_INTERFACE "org.bluez.Input" +#define BT_NETWORK_INTERFACE "org.bluez.Network" +#define BT_NETWORK_SERVER_INTERFACE "org.bluez.NetworkServer" +#define BT_NETWORK_CLIENT_INTERFACE "org.bluez.Network" +#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_HEADSET_INTERFACE "org.bluez.Headset" +#define BT_SINK_INTERFACE "org.bluez.AudioSink" +#define BT_AUDIO_INTERFACE "org.bluez.Audio" +#define BT_OOB_INTERFACE "org.bluez.OutOfBand" +#define BT_MEDIA_INTERFACE "org.bluez.Media" +#define BT_MEDIA_PLAYER_INTERFACE "org.bluez.MediaPlayer" +#define BT_OBEXD_INTERFACE "org.openobex" +#define BT_OBEXD_MANAGER_INTERFACE "org.openobex.Manager" +#define BT_OBEXD_TRANSFER_INTERFACE "org.openobex.Transfer" + +#define BT_OBEX_SERVICE_NAME "org.openobex.client" + +#define BT_OBEX_CLIENT_PATH "/" +#define BT_OBEX_CLIENT_INTERFACE "org.openobex.Client" +#define BT_OBEX_TRANSFER_INTERFACE "org.openobex.Transfer" +#define BT_OBEX_AGENT_INTERFACE "org.openobex.Agent" + +#define BT_FREEDESKTOP_INTERFACE "org.freedesktop.DBus" +#define BT_FREEDESKTOP_PATH "/org/freedesktop/DBus" + +typedef enum { + BT_OBEX_SERVER = 0x00, + BT_RFCOMM_SERVER = 0x01, +} bt_osp_server_type_t; + +typedef struct { + int rssi; + int class; + char *address; + char *name; + char **uuids; + int uuid_count; + gboolean paired; + gboolean connected; + gboolean trust; +} bt_remote_dev_info_t; + +/* RFCOMM client /server will use this structure*/ +typedef struct { + int fd; + GIOChannel *io_channel; + guint io_event; + char *dev_node; + char *address; + char *uuid; +} bt_rfcomm_info_t; + +typedef struct { + int req_id; + char *address; +} bt_function_data_t; + +DBusConnection *_bt_get_system_conn(void); + +DBusGConnection *_bt_get_system_gconn(void); + +DBusGConnection *_bt_get_session_gconn(void); + +DBusGProxy *_bt_get_manager_proxy(void); + +DBusGProxy *_bt_get_adapter_proxy(void); + +char *_bt_get_adapter_path(void); + +void _bt_deinit_proxys(void); + +void _bt_convert_device_path_to_address(const char *device_path, + char *device_address); + +void _bt_convert_addr_string_to_type(unsigned char *addr, + const char *address); + +void _bt_convert_addr_type_to_string(char *address, + unsigned char *addr); + +void _bt_print_device_address_t(const bluetooth_device_address_t *addr); + +void _bt_divide_device_class(bluetooth_device_class_t *device_class, + unsigned int cod); + +void _bt_free_device_info(bt_remote_dev_info_t *dev_info); + +int _bt_register_osp_server_in_agent(int type, char *uuid); + +int _bt_unregister_osp_server_in_agent(int type, char *uuid); + +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); + +void _bt_deinit_bluez_proxy(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_COMMON_H_*/ + diff --git a/bt-service/include/bt-service-device.h b/bt-service/include/bt-service-device.h new file mode 100644 index 0000000..04694bb --- /dev/null +++ b/bt-service/include/bt-service-device.h @@ -0,0 +1,65 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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_DEVICE_H_ +#define _BT_SERVICE_DEVICE_H_ + +#include +#include +#include "bluetooth-api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int _bt_bond_device(int request_id, + bluetooth_device_address_t *device_address, + GArray **out_param1); + +int _bt_cancel_bonding(void); + +int _bt_unbond_device(int request_id, + bluetooth_device_address_t *device_address, + GArray **out_param1); + +int _bt_cancel_search_device(void); + +int _bt_search_device(int request_id, + bluetooth_device_address_t *device_address); + +int _bt_set_alias(bluetooth_device_address_t *device_address, + const char *alias); + +int _bt_set_authorization(bluetooth_device_address_t *device_address, + gboolean authorize); + +int _bt_is_device_connected(bluetooth_device_address_t *device_address, + int connection_type, gboolean *is_connected); + +gboolean _bt_is_device_creating(void); + +void _bt_set_autopair_status_in_bonding_info(gboolean is_autopair); + +bt_remote_dev_info_t *_bt_get_remote_device_info(char *address); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_SERVICE_ADAPTER_H_*/ + diff --git a/bt-service/include/bt-service-event.h b/bt-service/include/bt-service-event.h new file mode 100644 index 0000000..c108be5 --- /dev/null +++ b/bt-service/include/bt-service-event.h @@ -0,0 +1,42 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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_EVENT_H_ +#define _BT_SERVICE_EVENT_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int _bt_send_event(int event_type, int event, int type, ...); + +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); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_SERVICE_EVENT_H_*/ + diff --git a/bt-service/include/bt-service-gap-agent.h b/bt-service/include/bt-service-gap-agent.h new file mode 100644 index 0000000..271171b --- /dev/null +++ b/bt-service/include/bt-service-gap-agent.h @@ -0,0 +1,119 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 SC_CORE_AGENT_H +#define SC_CORE_AGENT_H + +#include +#include +#include +#include + +#define BLUEZ_DEVICE_INTERFACE "org.bluez.Device" + +#define GAP_TYPE_AGENT (gap_agent_get_type()) +#define GAP_GET_AGENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GAP_TYPE_AGENT, GapAgent)) +#define GAP_IS_AGENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GAP_TYPE_AGENT)) + +#define GAP_AGENT_CLASS(class) (G_TYPE_CHECK_CLASS_CAST((class), GAP_TYPE_AGENT, \ + GapAgentClass)) +#define GAP_GET_AGENT_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GAP_TYPE_AGENT, \ + GapAgentClass)) +#define GAP_IS_AGENT_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE((class), GAP_TYPE_AGENT)) + +#define GAP_AGENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), GAP_TYPE_AGENT, \ + GapAgentPrivate)) + +typedef struct _GapAgent GapAgent; +typedef struct _GapAgentClass GapAgentClass; + +typedef gboolean(*GapAgentPasskeyFunc) (GapAgent *agent, + DBusGProxy *device); +typedef gboolean(*GapAgentDisplayFunc) (GapAgent *agent, DBusGProxy *device, + guint passkey); +typedef gboolean(*GapAgentConfirmFunc) (GapAgent *agent, DBusGProxy *device, + guint passkey); +typedef gboolean(*GapAgentAuthorizeFunc) (GapAgent *agent, + DBusGProxy *device, + const char *uuid); +typedef gboolean(*GapAgentConfirmModeFunc) (GapAgent *agent, + const char *mode, const char *sender, + gboolean need_popup, void *data); +typedef gboolean(*GapAgentCancelFunc) (GapAgent *agent, + const char *address); +typedef gboolean(*GapAgentIgnoreAutoPairingFunc) (const char *address); +typedef uint8_t bool_t; + +typedef struct { + GapAgentPasskeyFunc pincode_func; + GapAgentDisplayFunc display_func; + GapAgentPasskeyFunc passkey_func; + GapAgentConfirmFunc confirm_func; + GapAgentAuthorizeFunc authorize_func; + GapAgentCancelFunc pairing_cancel_func; + GapAgentCancelFunc authorization_cancel_func; +} GAP_AGENT_FUNC_CB; + +typedef enum { + GAP_AGENT_ACCEPT, + GAP_AGENT_REJECT, + GAP_AGENT_CANCEL, + GAP_AGENT_TIMEOUT, +} GAP_AGENT_ACCEPT_TYPE_T; + +struct _GapAgent { + GObject parent; +}; + +struct _GapAgentClass { + GObjectClass parent_class; +}; + +GapAgent *_gap_agent_new(void); +void _gap_agent_setup_dbus(GapAgent *agent, GAP_AGENT_FUNC_CB *func_cb, + const char *path, DBusGProxy *adapter); +gboolean _gap_agent_register(GapAgent *agent); +void _gap_agent_reset_dbus(GapAgent *agent); + +gboolean gap_agent_reply_pin_code(GapAgent *agent, const guint accept, + const char *pin_code, + DBusGMethodInvocation *context); +gboolean gap_agent_reply_passkey(GapAgent *agent, const guint accept, + const char *passkey, + DBusGMethodInvocation *context); +gboolean gap_agent_reply_confirmation(GapAgent *agent, const guint accept, + DBusGMethodInvocation *context); +gboolean gap_agent_reply_authorize(GapAgent *agent, const guint accept, + DBusGMethodInvocation *context); + +gboolean _gap_agent_exist_osp_server(GapAgent *agent, int type, char *uuid); + +gchar* _gap_agent_get_path(GapAgent *agent); + +gboolean _gap_agent_is_canceled(GapAgent *agent); + +gboolean _gap_agent_register_osp_server(GapAgent *agent, + const gint type, + const char *uuid); + +gboolean _gap_agent_unregister_osp_server(GapAgent *agent, + const gint type, + const char *uuid); + +#endif diff --git a/bt-service/include/bt-service-hid.h b/bt-service/include/bt-service-hid.h new file mode 100644 index 0000000..349982e --- /dev/null +++ b/bt-service/include/bt-service-hid.h @@ -0,0 +1,41 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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_HID_H_ +#define _BT_SERVICE_HID_H_ + +#include +#include +#include "bluetooth-api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int _bt_hid_connect(int request_id, + bluetooth_device_address_t *device_address); + +int _bt_hid_disconnect(int request_id, + bluetooth_device_address_t *device_address); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_SERVICE_HID_H_*/ + diff --git a/bt-service/include/bt-service-main.h b/bt-service/include/bt-service-main.h new file mode 100644 index 0000000..798da4b --- /dev/null +++ b/bt-service/include/bt-service-main.h @@ -0,0 +1,35 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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_MAIN_H_ +#define _BT_SERVICE_MAIN_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +gboolean _bt_terminate_service(gpointer user_data); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_SERVICE_MAIN_H_*/ + diff --git a/bt-service/include/bt-service-network.h b/bt-service/include/bt-service-network.h new file mode 100644 index 0000000..16536c6 --- /dev/null +++ b/bt-service/include/bt-service-network.h @@ -0,0 +1,51 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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_NETWORK_H_ +#define _BT_SERVICE_NETWORK_H_ + +#include +#include +#include "bluetooth-api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NAP_UUID_NAME "nap" +#define GN_UUID_NAME "gn" +#define PANU_UUID_NAME "panu" +#define NET_BRIDGE_INTERFACE "pan0" + +int _bt_network_activate(void); + +int _bt_network_deactivate(void); + +int _bt_network_connect(int request_id, int role, + bluetooth_device_address_t *device_address); + +int _bt_network_disconnect(int request_id, + bluetooth_device_address_t *device_address); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_SERVICE_NETWORK_H_*/ + diff --git a/bt-service/include/bt-service-obex-agent.h b/bt-service/include/bt-service-obex-agent.h new file mode 100644 index 0000000..7094bb3 --- /dev/null +++ b/bt-service/include/bt-service-obex-agent.h @@ -0,0 +1,136 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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_OBEX_AGENT_H +#define __BT_SERVICE_OBEX_AGENT_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + BT_OBEX_AGENT_ERROR_REJECT, + BT_OBEX_AGENT_ERROR_CANCEL, + BT_OBEX_AGENT_ERROR_TIMEOUT, +} bt_agent_error_t; + +G_BEGIN_DECLS +typedef struct { + GObject parent; +} BtObexAgent; + +typedef struct { + GObjectClass parent_class; +} BtObexAgentClass; + +GType bt_obex_agent_get_type(void); + +#define BT_OBEX_TYPE_AGENT (bt_obex_agent_get_type()) +#define BT_OBEX_AGENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), BT_OBEX_TYPE_AGENT, BtObexAgent)) +#define BT_OBEX_AGENT_CLASS(agent_class) (G_TYPE_CHECK_CLASS_CAST((agent_class), BT_OBEX_TYPE_AGENT, BtObexAgentClass)) +#define BT_OBEX_GET_AGENT_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), BT_OBEX_TYPE_AGENT, BtObexAgentClass)) + +typedef gboolean(*bt_obex_authorize_cb)(DBusGMethodInvocation *context, + const char *path, + const char *bdaddress, + const char *name, + const char *type, + gint length, + gint time, + gpointer data); + +typedef gboolean(*bt_obex_request_cb)(DBusGMethodInvocation *context, + DBusGProxy *transfer, + gpointer data); + +typedef gboolean(*bt_obex_progress_cb)(DBusGMethodInvocation *context, + DBusGProxy *transfer, + guint64 transferred, + gpointer data); + +typedef gboolean(*bt_obex_error_cb)(DBusGMethodInvocation *context, + DBusGProxy *transfer, + const char *message, + gpointer data); + +typedef gboolean(*bt_obex_complete_cb)(DBusGMethodInvocation *context, + DBusGProxy *transfer, + gpointer data); + +typedef gboolean(*bt_obex_release_cb)(DBusGMethodInvocation *context, + gpointer data); + +G_END_DECLS + +void _bt_obex_set_authorize_cb(BtObexAgent *agent, + bt_obex_authorize_cb func, + gpointer data); + +void _bt_obex_set_request_cb(BtObexAgent *agent, + bt_obex_request_cb func, + gpointer data); + +void _bt_obex_set_progress_cb(BtObexAgent *agent, + bt_obex_progress_cb func, + gpointer data); + +void _bt_obex_set_error_cb(BtObexAgent *agent, + bt_obex_error_cb func, + gpointer data); + +void _bt_obex_set_complete_cb(BtObexAgent *agent, + bt_obex_complete_cb func, + gpointer data); + +void _bt_obex_set_release_cb(BtObexAgent *agent, + bt_obex_release_cb func, + gpointer data); + +BtObexAgent *_bt_obex_agent_new(void); + +gboolean _bt_obex_setup(BtObexAgent *agent, const char *path); + +gboolean bt_obex_agent_request(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); + +gboolean bt_obex_agent_complete(BtObexAgent *agent, const char *path, + DBusGMethodInvocation *context); + +gboolean bt_obex_agent_release(BtObexAgent *agent, DBusGMethodInvocation *context); + +gboolean bt_obex_agent_error(BtObexAgent *agent, const char *path, + const char *message, DBusGMethodInvocation *context); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __BT_SERVICE_OBEX_AGENT_H */ diff --git a/bt-service/include/bt-service-obex-server.h b/bt-service/include/bt-service-obex-server.h new file mode 100644 index 0000000..b409acb --- /dev/null +++ b/bt-service/include/bt-service-obex-server.h @@ -0,0 +1,78 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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_OBEX_SERVER_H_ +#define _BT_SERVICE_OBEX_SERVER_H_ + +#include +#include +#include "bluetooth-api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int _bt_register_obex_server(void); + +int _bt_unregister_obex_server(void); + +int _bt_obex_server_allocate(char *sender, const char *dest_path, int app_pid, + gboolean is_native); + +int _bt_obex_server_deallocate(int app_pid, gboolean is_native); + +int _bt_obex_server_accept_authorize(const char *filename, gboolean is_native); + +int _bt_obex_server_reject_authorize(void); + +int _bt_obex_server_set_destination_path(const char *dest_path, + gboolean is_native); + +int _bt_obex_server_set_root(const char *root); + +int _bt_obex_server_cancel_transfer(int transfer_id); + +int _bt_obex_server_cancel_all_transfers(void); + +int _bt_obex_server_is_activated(gboolean *activated); + +int _bt_obex_server_check_allocation(gboolean *allocation); + +int _bt_obex_server_check_termination(char *sender); + +int _bt_obex_server_accept_connection(int request_id); + +int _bt_obex_server_reject_connection(void); + + +void _bt_obex_transfer_started(const char *transfer_path); + +void _bt_obex_transfer_progress(const char *transfer_path, + int total, + int transferred); + +void _bt_obex_transfer_completed(const char *transfer_path, gboolean success); + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_SERVICE_OBEX_SERVER_H_*/ + diff --git a/bt-service/include/bt-service-oob.h b/bt-service/include/bt-service-oob.h new file mode 100644 index 0000000..aca9a4a --- /dev/null +++ b/bt-service/include/bt-service-oob.h @@ -0,0 +1,44 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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_OOB_H_ +#define _BT_SERVICE_OOB_H_ + +#include +#include +#include "bluetooth-api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int _bt_oob_read_local_data(bt_oob_data_t *local_oob_data); + +int _bt_oob_add_remote_data( + bluetooth_device_address_t *remote_device_address, + bt_oob_data_t *remote_oob_data); + +int _bt_oob_remove_remote_data( + bluetooth_device_address_t *remote_device_address); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_SERVICE_OOB_H_*/ + diff --git a/bt-service/include/bt-service-opp-client.h b/bt-service/include/bt-service-opp-client.h new file mode 100644 index 0000000..67b65a0 --- /dev/null +++ b/bt-service/include/bt-service-opp-client.h @@ -0,0 +1,76 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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_OPP_CLIENT_H_ +#define _BT_SERVICE_OPP_CLIENT_H_ + +#include +#include +#include "bluetooth-api.h" +#include "bt-internal-types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BT_OBEX_CLIENT_AGENT_PATH "/org/obex/client_agent" + +typedef struct { + char path[BT_FILE_PATH_MAX]; +} bt_file_path_t; + +typedef struct { + DBusGProxy *proxy; + char *transfer_name; + char *file_name; + gint64 size; +} bt_transfer_info_t; + +typedef struct { + int request_id; + int result; + char *address; + gboolean is_canceled; + DBusGProxyCall *sending_proxy; + bt_transfer_info_t *transfer_info; +} bt_sending_info_t; + +typedef struct { + char *address; + char **file_path; + int file_count; + 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); + +int _bt_opp_client_cancel_push(void); + +int _bt_opp_client_cancel_all_transfers(void); + +int _bt_opp_client_is_sending(gboolean *sending); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_SERVICE_OPP_CLIENT_H_*/ + diff --git a/bt-service/include/bt-service-rfcomm-client.h b/bt-service/include/bt-service-rfcomm-client.h new file mode 100644 index 0000000..3465bcb --- /dev/null +++ b/bt-service/include/bt-service-rfcomm-client.h @@ -0,0 +1,56 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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_RFCOMM_CLIENT_H_ +#define _BT_SERVICE_RFCOMM_CLIENT_H_ + +#include +#include +#include "bluetooth-api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int _bt_rfcomm_connect_using_uuid(int request_id, + bluetooth_device_address_t *device_address, + char *remote_uuid); + +int _bt_rfcomm_connect_using_channel(int request_id, + bluetooth_device_address_t *device_address, + char *channel); + +int _bt_rfcomm_disconnect(int socket_fd); + +int _bt_rfcomm_write(int socket_fd, char *buf, int length); + +int _bt_rfcomm_cancel_connect(void); + +int _bt_rfcomm_is_device_connected(bluetooth_device_address_t *device_address, + gboolean *connected); + +int _bt_rfcomm_is_connected(gboolean *connected); + +int _bt_rfcomm_client_disconnect_all(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_SERVICE_RFCOMM_CLIENT_H_*/ + diff --git a/bt-service/include/bt-service-rfcomm-server.h b/bt-service/include/bt-service-rfcomm-server.h new file mode 100644 index 0000000..88e98c6 --- /dev/null +++ b/bt-service/include/bt-service-rfcomm-server.h @@ -0,0 +1,76 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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_RFCOMM_SERVER_H_ +#define _BT_SERVICE_RFCOMM_SERVER_H_ + +#include +#include +#include "bluetooth-api.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_SERVICE_RFCOMM_SERVER_H_*/ + +typedef struct { + int server_id; + int accept_id; + int server_type; + int control_fd; + int data_fd; + guint control_id; + guint data_id; + char *serial_path; + char *uuid; + char *sender; + char *remote_address; + GIOChannel *control_io; + GIOChannel *data_io; + DBusGProxy *serial_proxy; + DBusGProxy *manager_proxy; +} bt_rfcomm_server_info_t; + +int _bt_rfcomm_create_socket(char *sender, char *uuid); + +int _bt_rfcomm_remove_socket(int socket_fd); + +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_reject_connection(int server_fd); + +int _bt_rfcomm_server_disconnect(int data_fd); + +bt_rfcomm_server_info_t *_bt_rfcomm_get_server_info_using_uuid(char *uuid); + +int _bt_rfcomm_server_disconnect_all_connection(void); + +int _bt_rfcomm_server_check_existence(gboolean *existence); + +int _bt_rfcomm_server_check_termination(char *name); + diff --git a/bt-service/include/bt-service-util.h b/bt-service/include/bt-service-util.h new file mode 100644 index 0000000..c22b374 --- /dev/null +++ b/bt-service/include/bt-service-util.h @@ -0,0 +1,62 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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_UTIL_H_ +#define _BT_SERVICE_UTIL_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define BT_NODE_NAME_LEN 50 + +typedef struct { + int req_id; + int service_function; + char name[BT_NODE_NAME_LEN]; + DBusGMethodInvocation *context; +} request_info_t; + + +void _bt_init_request_id(void); + +int _bt_assign_request_id(void); + +void _bt_delete_request_id(int request_id); + + +void _bt_init_request_list(void); + +int _bt_insert_request_list(int req_id, int service_function, + char *name, DBusGMethodInvocation *context); + +int _bt_delete_request_list(int req_id); + +request_info_t *_bt_get_request_info(int req_id); + +void _bt_clear_request_list(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_SERVICE_UTIL_H_*/ + diff --git a/bt-service/include/stacktrim.h b/bt-service/include/stacktrim.h new file mode 100644 index 0000000..df18d59 --- /dev/null +++ b/bt-service/include/stacktrim.h @@ -0,0 +1,64 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 __STACKTRIM_H__ +#define __STACKTRIM_H__ + +#include +#include +#include +#include + +#define BUF_SIZE 256 +#define PAGE_SIZE (1 << 12) +#define _ALIGN_UP(addr, size) (((addr)+((size)-1))&(~((size)-1))) +#define _ALIGN_DOWN(addr, size) ((addr)&(~((size)-1))) +#define PAGE_ALIGN(addr) _ALIGN_DOWN(addr, PAGE_SIZE) + +static inline void stack_trim(void) +{ +#ifdef STACK_FLUSH + unsigned int sp; + char buf[BUF_SIZE]; + FILE *file; + unsigned int stacktop; + int found = 0; + + asm volatile ("mov %0,sp " : "=r"(sp)); + + sprintf(buf, "/proc/%d/maps", getpid()); + file = fopen(buf, "r"); + while (fgets(buf, BUF_SIZE, file) != NULL) { + if (strstr(buf, "[stack]")) { + found = 1; + break; + } + } + fclose(file); + + if (found) { + sscanf(buf, "%x-", &stacktop); + if (madvise((void *)PAGE_ALIGN(stacktop), PAGE_ALIGN(sp) - stacktop, + MADV_DONTNEED) < 0) + perror("stack madvise fail"); + } +#endif +} + +#endif /* __STACKTRIM_H__ */ diff --git a/bt-service/marshal.list b/bt-service/marshal.list new file mode 100644 index 0000000..96af15b --- /dev/null +++ b/bt-service/marshal.list @@ -0,0 +1,18 @@ +# DBUS Signal argument converting list for bluetooth frwk lib +VOID:STRING +VOID:STRING,UINT,INT +VOID:STRING,STRING +VOID:STRING,STRING,INT +VOID:UINT +VOID:STRING,STRING,INT,UINT +VOID:STRING,VARIANT +# for BlueZ4 +VOID:STRING,BOXED +# for obex +VOID:STRING,STRING,UINT64 +VOID:UINT64 +VOID:STRING,STRING,STRING +# for obexd +VOID:OBJECT,BOOLEAN +VOID:INT,INT + diff --git a/bt-service/org.projectx.bt.service b/bt-service/org.projectx.bt.service new file mode 100644 index 0000000..629e8c2 --- /dev/null +++ b/bt-service/org.projectx.bt.service @@ -0,0 +1,4 @@ +[D-BUS Service] +Name=org.projectx.bt +Exec=/bin/sh -c 'if [ -d /sys/fs/cgroup/systemd ] ; then export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/app/dbus/user_bus_socket; fi; exec /usr/bin/bt-service' +User=app \ No newline at end of file diff --git a/debian/bluetooth-frwk-agent.install.in b/debian/bluetooth-frwk-agent.install.in new file mode 100644 index 0000000..ec23a04 --- /dev/null +++ b/debian/bluetooth-frwk-agent.install.in @@ -0,0 +1,8 @@ +@PREFIX@/bin/bluetooth-agent +@PREFIX@/share/dbus-1/services/org.bluez.frwk_agent.service +/etc/* +@PREFIX@/bin/bluetooth-pb-agent +@PREFIX@/share/dbus-1/services/org.bluez.pb_agent.service + +@PREFIX@/bin/bluetooth-map-agent +@PREFIX@/share/dbus-1/services/org.bluez.map_agent.service diff --git a/debian/bluetooth-map-agent.install.in b/debian/bluetooth-map-agent.install.in new file mode 100644 index 0000000..163ceb6 --- /dev/null +++ b/debian/bluetooth-map-agent.install.in @@ -0,0 +1,2 @@ +@PREFIX@/bin/bluetooth-map-agent +@PREFIX@/share/dbus-1/services/org.bluez.map_agent.service diff --git a/debian/bluetooth-pb-agent.install.in b/debian/bluetooth-pb-agent.install.in new file mode 100644 index 0000000..aecabfd --- /dev/null +++ b/debian/bluetooth-pb-agent.install.in @@ -0,0 +1,2 @@ +@PREFIX@/bin/bluetooth-pb-agent +@PREFIX@/share/dbus-1/services/org.bluez.pb_agent.service diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..29ee273 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,1915 @@ +bluetooth-frwk (0.2.53) unstable; urgency=low + + * Tagging and Package upload + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.53 + + -- DoHyun Pyun Fri, 11 Jan 2013 10:18:22 +0900 + +bluetooth-frwk (0.2.52) unstable; urgency=low + + * Tagging and Package upload + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.52 + + -- DoHyun Pyun Tue, 08 Jan 2013 13:29:25 +0900 + +bluetooth-frwk (0.2.51) unstable; urgency=low + + * Tagging and Package upload + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.51 + + -- Sunil Kumar Behera Wed, 26 Dec 2012 15:49:14 +0530 + +bluetooth-frwk (0.2.50) unstable; urgency=low + + * Fix the JIRA issue (S1-11315) + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.50 + + -- DoHyun Pyun Wed, 26 Dec 2012 08:54:26 +0900 + +bluetooth-frwk (0.2.49) unstable; urgency=low + + * Fix the PLM issue + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.49 + + -- DoHyun Pyun Thu, 20 Dec 2012 15:53:54 +0900 + +bluetooth-frwk (0.2.48) unstable; urgency=low + + * Fix the PLM issue + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.48 + + -- Chethan T N Fri, 14 Dec 2012 19:15:00 +0900 + +bluetooth-frwk (0.2.47) unstable; urgency=low + + * Re-upload the package + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.47 + + -- DoHyun Pyun Wed, 05 Dec 2012 15:06:37 +0900 + +bluetooth-frwk (0.2.46) unstable; urgency=low + + * Add the timeout error in BT activation + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.46 + + -- DoHyun Pyun Wed, 05 Dec 2012 10:19:20 +0900 + +bluetooth-frwk (0.2.45) unstable; urgency=low + + * Tagging and package upload + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.45 + + -- Chethan T N Mon, 03 Dec 2012 20:21:45 +0900 + +bluetooth-frwk (0.2.44) unstable; urgency=low + + * Fix the but about writing socket data + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.44 + + -- DoHyun Pyun Thu, 29 Nov 2012 15:26:27 +0900 + +bluetooth-frwk (0.2.43) unstable; urgency=low + + * Fix PLM issue P121112-4416 + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.43 + + -- Divya yadav Wed, 28 Nov 2012 19:24:22 +0530 + +bluetooth-frwk (0.2.42) unstable; urgency=low + + * Fix PLM issue P121112-4416, change auto pair file path + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.42 + + -- Divya yadav Mon, 26 Nov 2012 19:38:43 +0530 + +bluetooth-frwk (0.2.41) unstable; urgency=low + + * Fix PLM issue P121126-0741 + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.41 + + -- DoHyun Pyun Mon, 26 Nov 2012 18:09:36 +0900 + +bluetooth-frwk (0.2.40) unstable; urgency=low + + * Tagging and Upload + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.40 + + -- Sunil Kumar Behera Thu, 22 Nov 2012 19:26:07 +0530 + +bluetooth-frwk (0.2.39) unstable; urgency=low + + * Fix the crash in bluetooth_telephony_deinit + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.39 + + -- DoHyun Pyun Thu, 22 Nov 2012 14:29:49 +0900 + +bluetooth-frwk (0.2.38) unstable; urgency=low + + * Fix the problem about RFCOMM / obex server + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.38 + + -- DoHyun Pyun Tue, 20 Nov 2012 17:18:52 +0900 + +bluetooth-frwk (0.2.37) unstable; urgency=low + + * Fix the problem that bt-service was not killed + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.37 + + -- DoHyun Pyun Tue, 20 Nov 2012 16:06:26 +0900 + +bluetooth-frwk (0.2.36) unstable; urgency=low + + * Package upload for PLM Issue P121116-6694 and P121116-6258 fix + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.36 + + -- Divya yadav Mon, 19 Nov 2012 17:41:34 +0530 + +bluetooth-frwk (0.2.35) unstable; urgency=low + + * Enable the BT using script only + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.35 + + -- DoHyun Pyun Mon, 19 Nov 2012 15:53:33 +0900 + +bluetooth-frwk (0.2.34) unstable; urgency=low + + * Fix the bug about BT activation + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.34 + + -- DoHyun Pyun Mon, 19 Nov 2012 14:09:02 +0900 + +bluetooth-frwk (0.2.33) unstable; urgency=low + + * Package upload for PLM Issue P121112-4416 fix + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.33 + + -- Divya yadav Thu, 15 Nov 2012 13:37:41 +0530 + +bluetooth-frwk (0.2.32) unstable; urgency=low + + * Fix the issue that do not receive the event from bt-service + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.32 + + -- DoHyun Pyun Wed, 14 Nov 2012 18:02:37 +0900 + +bluetooth-frwk (0.2.31) unstable; urgency=low + + * Package upload for PLM Issue P121108-4098 fix + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.31 + + -- Chethan T N Wed, 14 Nov 2012 15:04:53 +0900 + +bluetooth-frwk (0.2.30) unstable; urgency=low + + * Upload the package + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.30 + + -- DoHyun Pyun Wed, 14 Nov 2012 08:45:06 +0900 + +bluetooth-frwk (0.2.29) unstable; urgency=low + + * Added support for NREC feature + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.29 + + -- Chethan T N Thu, 08 Nov 2012 17:05:38 +0900 + +bluetooth-frwk (0.2.28) unstable; urgency=low + + * Add g_type_init in bluetooth_telephony_init API + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.28 + + -- DoHyun Pyun Wed, 07 Nov 2012 19:10:54 +0900 + +bluetooth-frwk (0.2.27) unstable; urgency=low + + * Add g_type_init in bluetooth_telephony_init API + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.27 + + -- DoHyun Pyun Wed, 07 Nov 2012 15:10:43 +0900 + +bluetooth-frwk (0.2.26) unstable; urgency=low + + * Update version number + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.26 + + -- Jaekyun Lee Tue, 06 Nov 2012 16:20:45 +0900 + +bluetooth-frwk (0.2.25) unstable; urgency=low + + * Support contacts-service2 + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.25 + + -- Jaekyun Lee Tue, 06 Nov 2012 12:54:51 +0900 + +bluetooth-frwk (0.2.24) unstable; urgency=low + + * Merged BT agent to BT service + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.24 + + -- Divya yadav Sat, 03 Nov 2012 10:39:22 +0530 + +bluetooth-frwk (0.2.23) unstable; urgency=low + + * Merged BT agent to BT service + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.23 + + -- Jaganath K Fri, 02 Nov 2012 16:40:09 +0530 + +bluetooth-frwk (0.2.22) unstable; urgency=low + + * Remove bt-agent process + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.22 + + -- DoHyun Pyun Wed, 31 Oct 2012 13:41:05 +0900 + +bluetooth-frwk (0.2.21) unstable; urgency=low + + * Handle abnormal terminations of the servers + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.21 + + -- DoHyun Pyun Wed, 24 Oct 2012 13:22:55 +0900 + +bluetooth-frwk (0.2.20) unstable; urgency=low + + * Implement bluetooth_is_device_connected API + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.20 + + -- DoHyun Pyun Thu, 18 Oct 2012 11:52:05 +0900 + +bluetooth-frwk (0.2.19) unstable; urgency=low + + * Add device events + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.19 + + -- DoHyun Pyun Tue, 16 Oct 2012 11:13:15 +0900 + +bluetooth-frwk (0.2.18) unstable; urgency=low + + * Assign the transfer ID + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.18 + + -- DoHyun Pyun Fri, 12 Oct 2012 15:38:00 +0900 + +bluetooth-frwk (0.2.17) unstable; urgency=low + + * Copy the license file in target + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.17 + + -- DoHyun Pyun Thu, 11 Oct 2012 14:04:53 +0900 + +bluetooth-frwk (0.2.16) unstable; urgency=low + + * Implement MDM phase II + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.16 + + -- DoHyun Pyun Wed, 10 Oct 2012 13:45:06 +0900 + +bluetooth-frwk (0.2.15) stable; urgency=low + + * Fix the crash in remove socket + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.15 + + -- DoHyun Pyun Tue, 09 Oct 2012 13:51:26 +0900 + +bluetooth-frwk (0.2.14) unstable; urgency=low + + * Fix the crash in OPP sending + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.14 + + -- DoHyun Pyun Fri, 05 Oct 2012 16:01:00 +0900 + +bluetooth-frwk (0.2.13) unstable; urgency=low + + * Fix the crash in OPP sending + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.13 + + -- DoHyun Pyun Fri, 28 Sep 2012 12:34:28 +0900 + +bluetooth-frwk (0.2.12) unstable; urgency=low + + * Fix the bug about RFCOMM + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.12 + + -- DoHyun Pyun Tue, 25 Sep 2012 16:39:29 +0900 + +bluetooth-frwk (0.2.11) unstable; urgency=low + + * Package upload for PLM Issue P120919-5037 Fix + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.11 + + -- Chethan T N Fri, 21 Sep 2012 18:59:23 +0530 + +bluetooth-frwk (0.2.10) unstable; urgency=low + + * Modify the code about passkey show + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.10 + + -- DoHyun Pyun Fri, 21 Sep 2012 20:25:23 +0900 + +bluetooth-frwk (0.2.9) unstable; urgency=low + + * Implement the FRWK + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.9 + + -- DoHyun Pyun Fri, 21 Sep 2012 12:44:20 +0900 + +bluetooth-frwk (0.2.8) unstable; urgency=low + + * Apply smack manifest file + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.8 + + -- Sangki Park Fri, 21 Sep 2012 10:14:48 +0900 + +bluetooth-frwk (0.2.7) unstable; urgency=low + + * Implement new FRWK + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.7 + + -- DoHyun Pyun Thu, 20 Sep 2012 11:31:15 +0900 + +bluetooth-frwk (0.2.6) unstable; urgency=low + + * Implement new FRWK + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.6 + + -- DoHyun Pyun Wed, 19 Sep 2012 14:54:42 +0900 + +bluetooth-frwk (0.2.5) unstable; urgency=low + + * Implement new FRWK + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.5 + + -- DoHyun Pyun Tue, 18 Sep 2012 17:52:04 +0900 + +bluetooth-frwk (0.2.4) unstable; urgency=low + + * Implement new FRWK + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.4 + + -- DoHyun Pyun Tue, 18 Sep 2012 13:42:30 +0900 + +bluetooth-frwk (0.2.3) unstable; urgency=low + + * Implement new FRWK + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.3 + + -- DoHyun Pyun Mon, 17 Sep 2012 20:05:08 +0900 + +bluetooth-frwk (0.2.1) unstable; urgency=low + + * Implement new FRWK + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.2.1 + + -- DoHyun Pyun Mon, 17 Sep 2012 13:37:01 +0900 + +bluetooth-frwk (0.1.93) unstable; urgency=low + + * Tagging and upload the package + * Git: magnolia/framework/connectivity/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.93 + + -- Sangki Park Thu, 13 Sep 2012 10:51:48 +0900 + +bluetooth-frwk (0.1.92) unstable; urgency=low + + * Tagging and upload the package + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.92 + + -- DoHyun Pyun Tue, 11 Sep 2012 16:31:23 +0900 + +bluetooth-frwk (0.1.91) unstable; urgency=low + + * Tagging and upload the package + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.91 + + -- DoHyun Pyun Tue, 11 Sep 2012 10:04:32 +0900 + +bluetooth-frwk (0.1.90) unstable; urgency=low + + * Tagging and upload the package + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.90 + + -- DoHyun Pyun Mon, 10 Sep 2012 15:43:33 +0900 + +bluetooth-frwk (0.1.89) unstable; urgency=low + + * Tagging and upload the package + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.89 + + -- DoHyun Pyun Mon, 10 Sep 2012 11:00:03 +0900 + +bluetooth-frwk (0.1.88) unstable; urgency=low + + * Tagging and upload the package + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.88 + + -- DoHyun Pyun Fri, 07 Sep 2012 15:23:55 +0900 + +bluetooth-frwk (0.1.87) unstable; urgency=low + + * Tagging and upload the package + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.87 + + -- DoHyun Pyun Tue, 04 Sep 2012 09:47:19 +0900 + +bluetooth-frwk (0.1.86) unstable; urgency=low + + * Tagging and upload the package + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.86 + + -- DoHyun Pyun Sat, 01 Sep 2012 13:32:17 +0900 + +bluetooth-frwk (0.1.85) unstable; urgency=low + + * Tagging and upload the package + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.85 + + -- DoHyun Pyun Sat, 01 Sep 2012 09:06:39 +0900 + +bluetooth-frwk (0.1.84) unstable; urgency=low + + * Tagging and upload the package + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.84 + + -- DoHyun Pyun Fri, 31 Aug 2012 09:39:10 +0900 + +bluetooth-frwk (0.1.83) unstable; urgency=low + + * Tagging and upload the package + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.83 + + -- DoHyun Pyun Tue, 28 Aug 2012 14:19:47 +0900 + +bluetooth-frwk (0.1.82) unstable; urgency=low + + * Tagging and upload the package + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.82 + + -- DoHyun Pyun Tue, 28 Aug 2012 14:19:02 +0900 + + +bluetooth-frwk (0.1.81) unstable; urgency=low + + * Tagging and upload the package + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.81 + + -- DoHyun Pyun Thu, 23 Aug 2012 12:54:50 +0900 + +bluetooth-frwk (0.1.80) unstable; urgency=low + + * Tagging and upload the package + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.80 + + -- DoHyun Pyun Fri, 17 Aug 2012 13:02:55 +0900 + +bluetooth-frwk (0.1.79) unstable; urgency=low + + * Tagging and upload the package + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.79 + + -- DoHyun Pyun Thu, 16 Aug 2012 17:11:17 +0900 + +bluetooth-frwk (0.1.78) unstable; urgency=low + + * Tagging and upload the package + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.78 + + -- DoHyun Pyun Wed, 08 Aug 2012 17:01:37 +0900 + +bluetooth-frwk (0.1.77) unstable; urgency=low + + * Tagging and upload the package + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.77 + + -- DoHyun Pyun Wed, 08 Aug 2012 12:16:50 +0900 + +bluetooth-frwk (0.1.76) unstable; urgency=low + + * Tagging and upload the package + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.76 + + -- Sunil Kumar Behera Tue, 07 Aug 2012 15:58:21 +0530 + +bluetooth-frwk (0.1.75) unstable; urgency=low + + * Tagging and upload the package + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.75 + + -- Sunil Kumar Behera Tue, 07 Aug 2012 09:29:55 +0530 + +bluetooth-frwk (0.1.74) unstable; urgency=low + + * Tagging and upload the package + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.74 + + -- DoHyun Pyun Mon, 06 Aug 2012 18:01:12 +0900 + +bluetooth-frwk (0.1.73) unstable; urgency=low + + * Replace deprecated APIs about glib-2.3.0 + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.73 + + -- DoHyun Pyun Wed, 01 Aug 2012 13:50:43 +0900 + +bluetooth-frwk (0.1.72) unstable; urgency=low + + * Taging and upload the package + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.72 + + -- Chethan T N Tue, 31 Jul 2012 18:09:09 +0530 + +bluetooth-frwk (0.1.71) unstable; urgency=low + + * Re-upload the package + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.71 + + -- DoHyun Pyun Thu, 26 Jul 2012 08:34:33 +0900 + +bluetooth-frwk (0.1.70) unstable; urgency=low + + * Tagging and upload the package + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.70 + + -- DoHyun Pyun Wed, 25 Jul 2012 10:56:30 +0900 + +bluetooth-frwk (0.1.69) unstable; urgency=low + + * Tagging and upload the package + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.69 + + -- DoHyun Pyun Fri, 20 Jul 2012 14:07:19 +0900 + +bluetooth-frwk (0.1.68) unstable; urgency=low + + * Tagging and upload the package + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.68 + + -- DoHyun Pyun Thu, 19 Jul 2012 16:59:27 +0900 + +bluetooth-frwk (0.1.67) unstable; urgency=low + + * Upload package for changes + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.67 + + -- DoHyun Pyun Wed, 18 Jul 2012 12:44:25 +0900 + +bluetooth-frwk (0.1.66) unstable; urgency=low + + * Upload package for changes + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.66 + + -- DoHyun Pyun Tue, 10 Jul 2012 17:56:58 +0900 + +bluetooth-frwk (0.1.65) unstable; urgency=low + + * Upload package for changes. + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.65 + + -- Sunil Kumar Behera Wed, 20 Jun 2012 13:02:11 +0530 + +bluetooth-frwk (0.1.64) unstable; urgency=low + + * Implement the requirements from OSP + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.64 + + -- DoHyun Pyun Wed, 13 Jun 2012 09:12:44 +0900 + +bluetooth-frwk (0.1.63) unstable; urgency=low + + * Upload the changes + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.63 + + -- Chethan T N Tue, 22 May 2012 11:26:43 +0530 + +bluetooth-frwk (0.1.62) unstable; urgency=low + + * Upload the changes + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.62 + + -- DoHyun Pyun Mon, 21 May 2012 11:05:02 +0900 + +bluetooth-frwk (0.1.61) unstable; urgency=low + + * Upload the changes + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.61 + + -- DoHyun Pyun Fri, 18 May 2012 17:44:58 +0900 + +bluetooth-frwk (0.1.60) unstable; urgency=low + + * Upload the changes + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.60 + + -- DoHyun Pyun Mon, 14 May 2012 08:59:54 +0900 + +bluetooth-frwk (0.1.59) unstable; urgency=low + + * Use the MDM system popup + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.59 + + -- DoHyun Pyun Tue, 08 May 2012 08:58:56 +0900 + +bluetooth-frwk (0.1.58) unstable; urgency=low + + * Upload the changes + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.58 + + -- Sunil Kumar Behera Thu, 26 Apr 2012 12:03:49 +0530 + +bluetooth-frwk (0.1.57) unstable; urgency=low + + * Upload the changes + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.57 + + -- DoHyun Pyun Tue, 24 Apr 2012 11:43:25 +0900 + +bluetooth-frwk (0.1.56) unstable; urgency=low + + * Upload the changes + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.56 + + -- DoHyun Pyun Thu, 19 Apr 2012 08:57:02 +0900 + +bluetooth-frwk (0.1.55) unstable; urgency=low + + * Implement the MDM handsfree mode + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.55 + + -- DoHyun Pyun Tue, 10 Apr 2012 08:36:02 +0900 + +bluetooth-frwk (0.1.54) unstable; urgency=low + + * Add the authorize API to support BADA + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.54 + + -- DoHyun Pyun Fri, 30 Mar 2012 16:43:59 +0900 + +bluetooth-frwk (0.1.53) unstable; urgency=low + + * Revert session bus (agent) to system bus + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.53 + + -- Chanyeol Park Sun, 25 Mar 2012 16:51:41 +0900 + +bluetooth-frwk (0.1.52) unstable; urgency=low + + * fixed dbus bus type to session bus + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.52 + + -- Jaekyun Lee Sat, 24 Mar 2012 16:35:23 +0900 + +bluetooth-frwk (0.1.51) unstable; urgency=low + + * Set the agent timer + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.51 + + -- DoHyun Pyun Tue, 20 Mar 2012 14:53:10 +0900 + +bluetooth-frwk (0.1.50) unstable; urgency=low + + * Upload the changes + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.50 + + -- DoHyun Pyun Fri, 24 Feb 2012 09:50:40 +0900 + +bluetooth-frwk (0.1.49) unstable; urgency=low + + * Upload the changes + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.49 + + -- DoHyun Pyun Tue, 14 Feb 2012 13:23:45 +0900 + +bluetooth-frwk (0.1.48) unstable; urgency=low + + * Fix the cancel discovery issue + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.48 + + -- DoHyun Pyun Wed, 01 Feb 2012 15:22:45 +0900 + +bluetooth-frwk (0.1.47) unstable; urgency=low + + * Add the code to get MDM service / release MDM service + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.47 + + -- DoHyun Pyun Tue, 31 Jan 2012 17:01:18 +0900 + +bluetooth-frwk (0.1.46) unstable; urgency=low + + * Remove bluetooth-frwk-test dpkg + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.46 + + -- Chanyeol Park Thu, 26 Jan 2012 16:39:08 +0900 + +bluetooth-frwk (0.1.45) unstable; urgency=low + + * Restrict BT enable, if mdm_get_allow_bluetooth_mode is MDM_BT_RESTRICTED + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.45 + + -- DoHyun Pyun Mon, 16 Jan 2012 15:36:42 +0900 + +bluetooth-frwk (0.1.44) unstable; urgency=low + + * Fix the spelling of API name (sessioin -> session) + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.44 + + -- DoHyun Pyun Thu, 05 Jan 2012 17:53:01 +0900 + +bluetooth-frwk (0.1.43) unstable; urgency=low + + * Increase the version number to upload + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.43 + + -- DoHyun Pyun Mon, 02 Jan 2012 10:32:04 +0900 + +bluetooth-frwk (0.1.42) unstable; urgency=low + + * Upload the package to changes + * Git: slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.42 + + -- DoHyun Pyun Fri, 30 Dec 2011 07:59:59 +0900 + +bluetooth-frwk (0.1.41) unstable; urgency=low + + * Remove the input parameter of get_transfers dbus method for obexd + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.41 + + -- DoHyun Pyun Mon, 21 Nov 2011 18:07:12 +0900 + +bluetooth-frwk (0.1.40) unstable; urgency=low + + * Modify the bluetooth_is_supported API + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.40 + + -- DoHyun Pyun Mon, 14 Nov 2011 17:16:28 +0900 + +bluetooth-frwk (0.1.39) unstable; urgency=low + + * Add the 2 APIs for the MDM service + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.39 + + -- DoHyun Pyun Fri, 11 Nov 2011 08:35:55 +0900 + +bluetooth-frwk (0.1.38) unstable; urgency=low + + * Add the full values of the uuid in service list information (Support the CAPI) + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.38 + + -- DoHyun Pyun Tue, 08 Nov 2011 15:08:35 +0900 + +bluetooth-frwk (0.1.37) unstable; urgency=low + + * Fix the prevent defect (CID: 57479) + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.37 + + -- DoHyun Pyun Fri, 28 Oct 2011 14:50:31 +0900 + +bluetooth-frwk (0.1.36) unstable; urgency=low + + * Change bluetooth_set_discoverable_mode API to sync call (Support the CAPI) + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.36 + + -- DoHyun Pyun Wed, 26 Oct 2011 17:21:32 +0900 + +bluetooth-frwk (0.1.35) unstable; urgency=low + + * Modify the error types + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.35 + + -- DoHyun Pyun Tue, 25 Oct 2011 10:18:24 +0900 + +bluetooth-frwk (0.1.34) unstable; urgency=low + + * Modify bluetooth_set_local_name / bluetooth_get_local_name API + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.34 + + -- DoHyun Pyun Wed, 19 Oct 2011 12:57:12 +0900 + +bluetooth-frwk (0.1.33) unstable; urgency=low + + * Change the bluetooth_set_local_name to synchronous call (Support BADA / CAPI) + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.33 + + -- DoHyun Pyun Wed, 12 Oct 2011 14:47:55 +0900 + +bluetooth-frwk (0.1.32) unstable; urgency=low + + * Arrange the error type (Support the CAPI) + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.32 + + -- DoHyun Pyun Wed, 12 Oct 2011 13:48:15 +0900 + +bluetooth-frwk (0.1.31) unstable; urgency=low + + * Fix the bug about device name (CQ H0100134651) + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.31 + + -- DoHyun Pyun Thu, 06 Oct 2011 19:32:56 +0900 + +bluetooth-frwk (0.1.30) unstable; urgency=low + + * Don't call the AUL, if the beat-bluetooth process is not running + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.30 + + -- DoHyun Pyun Thu, 06 Oct 2011 18:56:01 +0900 + +bluetooth-frwk (0.1.29) unstable; urgency=low + + * Return the paired device only in bluetooth_get_bonded_device_list + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.29 + + -- DoHyun Pyun Tue, 04 Oct 2011 08:38:03 +0900 + +bluetooth-frwk (0.1.28) unstable; urgency=low + + * Modify the contact-service API + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.28 + + -- DoHyun Pyun Mon, 26 Sep 2011 17:21:23 +0900 + +bluetooth-frwk (0.1.27) unstable; urgency=low + + * Upload the package + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.27 + + -- DoHyun Pyun Wed, 07 Sep 2011 16:34:10 +0900 + +bluetooth-frwk (0.1.26) unstable; urgency=low + + * Upload the package + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.26 + + -- DoHyun Pyun Wed, 07 Sep 2011 08:54:01 +0900 + +bluetooth-frwk (0.1.25) unstable; urgency=low + + * Upload the package + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.25 + + -- DoHyun Pyun Tue, 06 Sep 2011 08:30:18 +0900 + +bluetooth-frwk (0.1.24) unstable; urgency=low + + * Upload the package + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.24 + + -- DoHyun Pyun Fri, 02 Sep 2011 08:37:37 +0900 + +bluetooth-frwk (0.1.23) unstable; urgency=low + + * Upload the package + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.23 + + -- DoHyun Pyun Mon, 29 Aug 2011 19:17:05 +0900 + +bluetooth-frwk (0.1.22) unstable; urgency=low + + * Upload package for changes + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.22 + + -- DoHyun Pyun Fri, 12 Aug 2011 15:57:26 +0900 + +bluetooth-frwk (0.1.21) unstable; urgency=low + + * Upload package for changes + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.21 + + -- DoHyun Pyun Tue, 09 Aug 2011 08:33:57 +0900 + +bluetooth-frwk (0.1.20) unstable; urgency=low + + * Remove the system popup when the remote device cancel the event (H0100131180) + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.20 + + -- DoHyun Pyun Mon, 01 Aug 2011 08:27:40 +0900 + +bluetooth-frwk (0.1.19) unstable; urgency=low + + * Upload package + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.19 + + -- Jaganath K Thu, 07 Jul 2011 13:16:30 +0530 + +bluetooth-frwk (0.1.18) unstable; urgency=low + + * Fix the bus in stop discoverying + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.18 + + -- DoHyun Pyun Thu, 07 Jul 2011 15:29:07 +0900 + +bluetooth-frwk (0.1.17) unstable; urgency=low + + * Add the bluetooth_get_bonded_device API + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.17 + + -- DoHyun Pyun Tue, 28 Jun 2011 15:44:17 +0900 + +bluetooth-frwk (0.1.16) unstable; urgency=low + + * Upload package for changes + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.16 + + -- Sunil Kumar Behera Fri, 24 Jun 2011 17:40:21 +0530 + +bluetooth-frwk (0.1.15) unstable; urgency=low + + * Fix dbus system bus double unref problem + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.15 + + -- Chanyeol Park Wed, 22 Jun 2011 21:56:17 +0900 + +bluetooth-frwk (0.1.14) unstable; urgency=low + + * Add the network API for BT tethering + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.14 + + -- DoHyun Pyun Fri, 17 Jun 2011 13:26:44 +0900 + +bluetooth-frwk (0.1.13) unstable; urgency=low + + * Add the NULL check routine + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.13 + + -- DoHyun Pyun Fri, 10 Jun 2011 11:16:56 +0900 + +bluetooth-frwk (0.1.12) unstable; urgency=low + + * Fix de-init session bug + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.12 + + -- Chanyeol Park Thu, 09 Jun 2011 21:57:11 +0900 + +bluetooth-frwk (0.1.11) unstable; urgency=low + + * Upload package for changes + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.11 + + -- Sunil Kumar Behera Tue, 07 Jun 2011 19:19:13 +0530 + +bluetooth-frwk (0.1.10) stable; urgency=low + + * Modify the 'BT enable' check routine + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.10 + + -- DoHyun Pyun Mon, 30 May 2011 16:36:11 +0900 + +bluetooth-frwk (0.1.9) unstable; urgency=low + + * Fix the BS when the process is terminated without deleting the g_timer. (Defect H0100127300) + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.9 + + -- DoHyun Pyun Fri, 27 May 2011 13:58:01 +0900 + +bluetooth-frwk (0.1.8) unstable; urgency=low + + * Add the uuid values for developers + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.8 + + -- DoHyun Pyun Wed, 25 May 2011 11:07:33 +0900 + +bluetooth-frwk (0.1.7) unstable; urgency=low + + * Add the 'user_data' parameter in bluetooth_register_callback + * Modify the DTS makefile to sbs + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.7 + + -- DoHyun Pyun Fri, 20 May 2011 09:01:34 +0900 + +bluetooth-frwk (0.1.6) unstable; urgency=low + + * Fix Crash while receive image + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.6 + + -- Chanyeol Park Thu, 19 May 2011 20:19:04 +0900 + +bluetooth-frwk (0.1.5) unstable; urgency=low + + * Show the ticker noti when the file recieved (Defect H0100126544) + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.5 + + -- DoHyun Pyun Fri, 13 May 2011 17:35:58 +0900 + +bluetooth-frwk (0.1.4) unstable; urgency=low + + * Correct the code about variable memory. + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.4 + + -- DoHyun Pyun Wed, 04 May 2011 11:00:59 +0900 + +bluetooth-frwk (0.1.3) unstable; urgency=low + + * Add the event signal of the authorized (Requested by CAPI part) + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.3 + -- DoHyun Pyun Mon, 02 May 2011 18:11:50 +0900 + +bluetooth-frwk (0.1.2) unstable; urgency=low + + * Remove the obex-agent.h file in install + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.2 + + -- DoHyun Pyun Thu, 28 Apr 2011 11:39:33 +0900 + +bluetooth-frwk (0.1.1) unstable; urgency=low + + * Increase the version + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.1 + + -- DoHyun Pyun Thu, 28 Apr 2011 11:23:53 +0900 + +bluetooth-frwk (0.1.0) unstable; urgency=low + + * Release ug-obexd init dpkg + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.1.0 + + -- DoHyun Pyun Tue, 26 Apr 2011 11:24:07 +0900 + +bluetooth-frwk (0.0.94) unstable; urgency=low + + * Add the package dependency of the dbus-glib-1 + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.94 + + -- DoHyun Pyun Wed, 06 Apr 2011 13:16:52 +0900 + +bluetooth-frwk (0.0.93) unstable; urgency=low + + * Fix the build break + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.93 + + -- DoHyun Pyun Wed, 06 Apr 2011 13:01:04 +0900 + +bluetooth-frwk (0.0.92) unstable; urgency=low + + * Re-upload package + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.92 + + -- DoHyun Pyun Mon, 07 Mar 2011 15:33:50 +0900 + +bluetooth-frwk (0.0.91) unstable; urgency=low + + * Upload package + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.91 + + -- DoHyun Pyun Mon, 07 Mar 2011 10:07:43 +0900 + +bluetooth-frwk (0.0.90) unstable; urgency=low + + * Modify the API and test case + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.90 + + -- DoHyun Pyun Fri, 04 Mar 2011 17:22:45 +0900 + +bluetooth-frwk (0.0.89) unstable; urgency=low + + * Modify the headset check-routin in auto-pairing + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.89 + + -- DoHyun Pyun Thu, 03 Mar 2011 11:16:27 +0900 + +bluetooth-frwk (0.0.88) unstable; urgency=low + + * Uploading Package + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.88 + + -- Jaganath Tue, 22 Feb 2011 13:05:13 +0530 + +bluetooth-frwk (0.0.87) unstable; urgency=low + + * Remove the authorizing popup in enable / diable adapter + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.87 + + -- DoHyun Pyun Fri, 11 Feb 2011 10:54:00 +0900 + +bluetooth-frwk (0.0.86) unstable; urgency=low + + * Fix the prevent defect (FOWARD NULL / BUFFER OVERFLOW) + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.86 + + -- DoHyun Pyun Thu, 10 Feb 2011 09:33:29 +0900 + +bluetooth-frwk (0.0.85) unstable; urgency=low + + * Implement bt_get_bonded_device_list API + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.85 + + -- DoHyun Pyun Thu, 20 Jan 2011 19:10:41 +0900 + +bluetooth-frwk (0.0.84) unstable; urgency=low + + * Move the popup UI to bt-syspopup + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.84 + + -- DoHyun Pyun Thu, 06 Jan 2011 14:38:09 +0900 + +bluetooth-frwk (0.0.83) unstable; urgency=low + + * BT name request fucntion returns error, when BT is not activated + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.83 + + -- ChanYeol Park Tue, 04 Jan 2011 14:03:28 +0900 + +bluetooth-frwk (0.0.82) unstable; urgency=low + + * Made the Adapter.GetProperties Sync during device enable + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.82 + + -- Syam Sidhardhan Fri, 24 Dec 2010 15:36:19 +0530 + +bluetooth-frwk (0.0.81) unstable; urgency=low + + * Block the elm_exit when END key press + * Git: 165.213.180.234:slp/pkgs/b/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.81 + + -- DoHyun Pyun Thu, 09 Dec 2010 16:24:25 +0900 + +bluetooth-frwk (0.0.80) unstable; urgency=low + + * Enable the auto-pairing in headset case + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.80 + + -- DoHyun Pyun Fri, 26 Nov 2010 13:59:34 +0900 + +bluetooth-frwk (0.0.79) unstable; urgency=low + + * Add auto-pairing code in headset case + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.79 + + -- DoHyun Pyun Wed, 24 Nov 2010 19:02:16 +0900 + +bluetooth-frwk (0.0.78) unstable; urgency=low + + * Change the AUL name + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.78 + + -- DoHyun Pyun Wed, 24 Nov 2010 13:18:10 +0900 + +bluetooth-frwk (0.0.77) unstable; urgency=low + + * Pop the navigation bar when the passkey view destroy + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.77 + + -- DoHyun Pyun Mon, 22 Nov 2010 19:59:09 +0900 + +bluetooth-frwk (0.0.76) unstable; urgency=low + + * Focus in the entry view + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.76 + + -- DoHyun Pyun Wed, 17 Nov 2010 20:37:56 +0900 + +bluetooth-frwk (0.0.75) unstable; urgency=low + + * Fixed Get Bonded device list end of indication, updated the doxygen PG + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.75 + + -- Syam Sidhardhan Wed, 17 Nov 2010 15:54:34 +0530 + +bluetooth-frwk (0.0.74) unstable; urgency=low + + * Modify the condition value about flight mode + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.74 + + -- DoHyun Pyun Wed, 10 Nov 2010 09:49:55 +0900 + +bluetooth-frwk (0.0.73) unstable; urgency=low + + * Upload package + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.73 + + -- DoHyun Pyun Tue, 09 Nov 2010 17:29:38 +0900 + +bluetooth-frwk (0.0.72) unstable; urgency=low + + * Rollback codes + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.72 + + -- DoHyun Pyun Tue, 09 Nov 2010 16:36:52 +0900 + +bluetooth-frwk (0.0.71) unstable; urgency=low + + * Remove evas_object_del after elm_navigationbar_pop + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.71 + + -- DoHyun Pyun Tue, 09 Nov 2010 15:19:12 +0900 + +bluetooth-frwk (0.0.70) unstable; urgency=low + + * Set the intial timeout value to zero + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.70 + + -- DoHyun Pyun Mon, 08 Nov 2010 13:44:37 +0900 + +bluetooth-frwk (0.0.69) unstable; urgency=low + + * Display the indicator + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.69 + + -- DoHyun Pyun Fri, 05 Nov 2010 14:12:31 +0900 + +bluetooth-frwk (0.0.68) unstable; urgency=low + + * Implemented the get bonded device list through DBUS + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.68 + + -- Syam Sidhardhan Thu, 04 Nov 2010 12:50:06 +0530 + +bluetooth-frwk (0.0.67) unstable; urgency=low + + * Move the popup over lock screen + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.67 + + -- DoHyun Pyun Wed, 03 Nov 2010 20:54:43 +0900 + +bluetooth-frwk (0.0.66) unstable; urgency=low + + * Add the homepage in control file + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.66 + + -- DoHyun Pyun Fri, 29 Oct 2010 17:13:06 +0900 + +bluetooth-frwk (0.0.65) unstable; urgency=low + + * Moved the sc_core_agent from btstack + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.65 + + -- DoHyun Pyun Fri, 29 Oct 2010 11:00:30 +0900 + +bluetooth-frwk (0.0.64) unstable; urgency=low + + * Modify / Add files about LiMo Contribution + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.64 + + -- DoHyun Pyun Mon, 25 Oct 2010 21:35:37 +0900 + +bluetooth-frwk (0.0.63) unstable; urgency=low + + * Show the IME when the passkey input + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.63 + + -- DoHyun Pyun Thu, 21 Oct 2010 17:48:55 +0900 + +bluetooth-frwk (0.0.62) unstable; urgency=low + + * Fix Device Property Changed UUIDs signal call back bug + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.62 + + -- DoHyun Pyun Thu, 21 Oct 2010 11:25:34 +0900 + +bluetooth-frwk (0.0.61) unstable; urgency=low + + * Upload package + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.61 + + -- Hye-Jin Kim Wed, 20 Oct 2010 16:48:47 +0900 + +bluetooth-frwk (0.0.60) unstable; urgency=low + + * Modified the rfcomm connect API + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.60 + + -- Syam Sidhardhan Tue, 19 Oct 2010 11:13:38 +0530 + +bluetooth-frwk (0.0.59) unstable; urgency=low + + * Reupload the package + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.59 + + -- DoHyun Pyun Wed, 13 Oct 2010 20:25:41 +0900 + +bluetooth-frwk (0.0.58) unstable; urgency=low + + * Move the bt-agent script to rc.5 + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.58 + + -- DoHyun Pyun Wed, 13 Oct 2010 18:11:18 +0900 + +bluetooth-frwk (0.0.57) unstable; urgency=low + + * Implemented bluetooth_get_bonded_device_list API + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.57 + + -- Syam Sidhardhan Fri, 08 Oct 2010 18:32:51 +0530 + +bluetooth-frwk (0.0.56) unstable; urgency=low + + * Upload the package + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.56 + + -- DoHyun Pyun Wed, 06 Oct 2010 16:41:39 +0900 + +bluetooth-frwk (0.0.55) unstable; urgency=low + + * Modify the TETware code + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.55 + + -- DoHyun Pyun Wed, 06 Oct 2010 16:08:56 +0900 + +bluetooth-frwk (0.0.54) unstable; urgency=low + + * Update the Programming Guide + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.54 + + -- DoHyun Pyun Fri, 01 Oct 2010 15:22:54 +0900 + +bluetooth-frwk (0.0.53) unstable; urgency=low + + * Modify the visibility + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.53 + + -- DoHyun Pyun Fri, 01 Oct 2010 13:42:02 +0900 + +bluetooth-frwk (0.0.52) unstable; urgency=low + + * Modify the BT aul to the backgroud mode + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.52 + + -- DoHyun Pyun Fri, 01 Oct 2010 09:00:45 +0900 + +bluetooth-frwk (0.0.51) unstable; urgency=low + + * Upload the package + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.51 + + -- Syam Sidhardhan Thu, 30 Sep 2010 18:20:43 +0530 + +bluetooth-frwk (0.0.50) unstable; urgency=low + + * Upload the package + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.50 + + -- DoHyun Pyun Fri, 17 Sep 2010 19:39:58 +0900 + +bluetooth-frwk (0.0.49) unstable; urgency=low + + * Fix the TETware code + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.49 + + -- DoHyun Pyun Fri, 17 Sep 2010 19:02:30 +0900 + +bluetooth-frwk (0.0.48) unstable; urgency=low + + * Add the TETware code + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.48 + + -- DoHyun Pyun Fri, 17 Sep 2010 10:47:01 +0900 + +bluetooth-frwk (0.0.47) unstable; urgency=low + + * Upload package + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.47 + + -- DoHyun Pyun Thu, 16 Sep 2010 09:35:21 +0900 + +bluetooth-frwk (0.0.46) unstable; urgency=low + + * Added the Connected event and made connect Async + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.46 + + -- Syam Sidhardhan Tue, 14 Sep 2010 12:48:33 +0530 + +bluetooth-frwk (0.0.45) unstable; urgency=low + + * Modify the GAP API + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.45 + + -- DoHyun Pyun Tue, 14 Sep 2010 16:02:42 +0900 + +bluetooth-frwk (0.0.44) unstable; urgency=low + + * Apply new font guide + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.44 + + -- DoHyun Pyun Sat, 11 Sep 2010 10:16:37 +0900 + +bluetooth-frwk (0.0.43) unstable; urgency=low + + * Repacke for EFL upgrade + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.43 + + -- DoHyun Pyun Fri, 10 Sep 2010 19:09:14 +0900 + +bluetooth-frwk (0.0.42) unstable; urgency=low + + * Added the support for Rfcomm api's multiple server and client with in + single process + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.42 + + -- Syam Sidhardhan Mon, 06 Sep 2010 18:50:55 +0530 + +bluetooth-frwk (0.0.41) unstable; urgency=low + + * Fixed the socket fd leak during the ACL link break when the client is connected + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.41 + + -- Syam Sidhardhan Tue, 31 Aug 2010 21:36:19 +0530 + +bluetooth-frwk (0.0.40) unstable; urgency=low + + * Added device address to the connection status structure + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.40 + + -- Syam Sidhardhan Tue, 31 Aug 2010 14:30:32 +0530 + +bluetooth-frwk (0.0.39) unstable; urgency=low + + * Added rfcomm API's + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.39 + + -- Syam Sidhardhan Mon, 30 Aug 2010 21:37:52 +0530 + +bluetooth-frwk (0.0.38) unstable; urgency=low + + * Code cleanup + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.38 + + -- DoHyun Pyun Mon, 30 Aug 2010 14:23:28 +0900 + +bluetooth-frwk (0.0.37) unstable; urgency=low + + * Add the SLP-DevGuide files + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.37 + + -- DoHyun Pyun Thu, 26 Aug 2010 08:25:20 +0900 + +bluetooth-frwk (0.0.36) unstable; urgency=low + + * Fix the prevent defect + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.36 + + -- DoHyun Pyun Tue, 24 Aug 2010 21:04:28 +0900 + +bluetooth-frwk (0.0.35) unstable; urgency=low + + * Modify the doxygen comments + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.35 + + -- DoHyun Pyun Fri, 20 Aug 2010 18:15:04 +0900 + +bluetooth-frwk (0.0.34) unstable; urgency=low + + * Apply the beat winset + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.34 + + -- DoHyun Pyun Fri, 20 Aug 2010 09:53:49 +0900 + +bluetooth-frwk (0.0.33) unstable; urgency=low + + * Apply the beat winset + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.33 + + -- DoHyun Pyun Tue, 17 Aug 2010 16:38:31 +0900 + +bluetooth-frwk (0.0.32) unstable; urgency=low + + * Chane elm_notify APIs to elm_popup APIs + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.32 + + -- Hye-Jin Kim Tue, 10 Aug 2010 10:04:18 +0900 + +bluetooth-frwk (0.0.31) unstable; urgency=low + + * Call the AUL message when agent start + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.31 + + -- DoHyun Pyun Fri, 06 Aug 2010 18:16:42 +0900 + +bluetooth-frwk (0.0.30) unstable; urgency=low + + * Apply new appcore + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.30 + + -- DoHyun Pyun Thu, 05 Aug 2010 22:05:49 +0900 + +bluetooth-frwk (0.0.29) unstable; urgency=low + + * Fix disabled event code + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.29 + + -- Seung-Woo Kim Tue, 03 Aug 2010 16:35:28 +0900 + +bluetooth-frwk (0.0.28) unstable; urgency=low + + * Fix the bug about discovering (Adjust the range of unsigned int) + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.28 + + -- DoHyun Pyun Fri, 30 Jul 2010 15:30:25 +0900 + +bluetooth-frwk (0.0.27) unstable; urgency=low + + * Fix print log format + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.27 + + -- Seung-Woo Kim Fri, 30 Jul 2010 09:41:25 +0900 + +bluetooth-frwk (0.0.25) unstable; urgency=low + + * Fix password entry in input view to show the last inputed value + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.25 + + -- Seung-Woo Kim Fri, 23 Jul 2010 19:50:35 +0900 + +bluetooth-frwk (0.0.24) unstable; urgency=low + + * Add missing major class enum and fix wrong discoverable mode value in + visibility changed event + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.24 + + -- Seung-Woo Kim Thu, 22 Jul 2010 22:23:04 +0900 + +bluetooth-frwk (0.0.23) unstable; urgency=low + + * Fix theme setting envrionment string + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.23 + + -- Seung-Woo Kim Thu, 22 Jul 2010 19:58:50 +0900 + +bluetooth-frwk (0.0.22) unstable; urgency=low + + * Fix to send proper device information after pairing + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.22 + + -- Seung-Woo Kim Tue, 20 Jul 2010 20:44:54 +0900 + +bluetooth-frwk (0.0.21) unstable; urgency=low + + * Fix doxygen group for SDK document + * Git: 165.213.180.234:/git/slp/pkgs/bluetooth-frwk + * Tag: bluetooth-frwk_0.0.21 + + -- Seung-Woo Kim Thu, 15 Jul 2010 14:10:23 +0900 + +bluetooth-frwk (0.0.20) unstable; urgency=low + + * Fix to show IME on paring by adding focusing option + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/bluetooth-frwk-0 + * Tag: bluetooth-frwk_0.0.20 + + -- Seung-Woo Kim Tue, 13 Jul 2010 11:39:37 +0900 + +bluetooth-frwk (0.0.19) unstable; urgency=low + + * Add window layer lower API to hide function + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/bluetooth-frwk-0 + * Tag: bluetooth-frwk_0.0.19 + + -- Seung-Woo Kim Mon, 12 Jul 2010 19:25:21 +0900 + +bluetooth-frwk (0.0.18) unstable; urgency=low + + * Fix PIN code length display in agent as scalable UI + * Fix input method framework API to new version + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/bluetooth-frwk-0 + * Tag: bluetooth-frwk_0.0.18 + + -- Seung-Woo Kim Mon, 12 Jul 2010 14:58:55 +0900 + +bluetooth-frwk (0.0.17) unstable; urgency=low + + * Fix set local name after enabling + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/bluetooth-frwk-0 + * Tag: bluetooth-frwk_0.0.17 + + -- Seung-Woo Kim Thu, 08 Jul 2010 19:45:40 +0900 + +bluetooth-frwk (0.0.16) unstable; urgency=low + + * Fix set discoverable mode with no timeout + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/bluetooth-frwk-0 + * Tag: bluetooth-frwk_0.0.16 + + -- Seung-Woo Kim Thu, 08 Jul 2010 19:18:47 +0900 + +bluetooth-frwk (0.0.15) unstable; urgency=low + + * Modify the maintainer list + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/bluetooth-frwk-0 + * Tag: bluetooth-frwk_0.0.15 + + -- DoHyun Pyun Thu, 08 Jul 2010 10:52:24 +0900 + +bluetooth-frwk (0.0.14) unstable; urgency=low + + * Fix struct for doc + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/bluetooth-frwk-0 + * Tag: bluetooth-frwk_0.0.14 + + -- Seung-Woo Kim Mon, 05 Jul 2010 19:06:41 +0900 + +bluetooth-frwk (0.0.13) unstable; urgency=low + + * Enable SDP API, Add GAP API implementation + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/bluetooth-frwk-0 + * Tag: bluetooth-frwk_0.0.13 + + -- chanyeol.park Thu, 24 Jun 2010 13:57:12 +0900 + +bluetooth-frwk (0.0.12) unstable; urgency=low + + * Add func,line info in dlog + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/bluetooth-frwk-0 + * Tag: bluetooth-frwk_0.0.12 + + -- chanyeol.park Wed, 16 Jun 2010 20:59:12 +0900 + +bluetooth-frwk (0.0.11) unstable; urgency=low + + * Dlog api changes applied + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/bluetooth-frwk-0 + * Tag: bluetooth-frwk_0.0.11 + + -- Shriram Joshi Tue, 15 Jun 2010 19:44:16 +0530 + +bluetooth-frwk (0.0.10) unstable; urgency=low + + * Add show/hide win_main evas object + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/bluetooth-frwk-0 + * Tag: bluetooth-frwk_0.0.10 + + -- chanyeol.park Tue, 15 Jun 2010 17:34:49 +0900 + +bluetooth-frwk (0.0.9) unstable; urgency=low + + * Fix Window Show/Hide operation + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/bluetooth-frwk-0 + * Tag: bluetooth-frwk_0.0.9 + + -- chanyeol.park Tue, 15 Jun 2010 15:15:24 +0900 + +bluetooth-frwk (0.0.8) unstable; urgency=low + + * Hide Agent during booting time with BT activation state + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/bluetooth-frwk-0 + * Tag: bluetooth-frwk_0.0.8 + + -- chanyeol.park Tue, 15 Jun 2010 12:15:52 +0900 + +bluetooth-frwk (0.0.7) unstable; urgency=low + + * Modify bool as gboolean + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/bluetooth-frwk-0 + * Tag: bluetooth-frwk_0.0.7 + + -- chanyeol.park Mon, 14 Jun 2010 18:34:36 +0900 + +bluetooth-frwk (0.0.6) unstable; urgency=low + + * Fix debug dpkg option + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/bluetooth-frwk-0 + * Tag: bluetooth-frwk_0.0.6 + + -- chanyeol.park Sat, 12 Jun 2010 15:20:57 +0900 + +bluetooth-frwk (0.0.5) unstable; urgency=low + + * Add agent activation/deactivation mechanism + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/bluetooth-frwk-0 + * Tag: bluetooth-frwk_0.0.5 + + -- chanyeol.park Thu, 10 Jun 2010 21:49:46 +0900 + +bluetooth-frwk (0.0.4) unstable; urgency=low + + * Temporarily Remove Adapter Signal Handle + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/bluetooth-frwk-0 + * Tag: bluetooth-frwk_0.0.4 + + -- chanyeol.park Wed, 09 Jun 2010 13:55:31 +0900 + +bluetooth-frwk (0.0.3) unstable; urgency=low + + * Add more APIs for GAP + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/bluetooth-frwk-0 + * Tag: bluetooth-frwk_0.0.3 + + -- Seung-Woo Kim Mon, 31 May 2010 22:56:59 +0900 + +bluetooth-frwk (0.0.2) unstable; urgency=low + + * Add Doxygen generate flag in control + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/bluetooth-frwk-0 + * Tag: bluetooth-frwk_0.0.2 + + -- Seung-Woo Kim Mon, 31 May 2010 11:21:26 +0900 + +bluetooth-frwk (0.0.1) unstable; urgency=low + + * Initial Release. + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/bluetooth-frwk-0 + * Tag: bluetooth-frwk_0.0.1 + + -- Seung-Woo Kim Sat, 29 May 2010 18:44:49 +0900 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..454e854 --- /dev/null +++ b/debian/control @@ -0,0 +1,46 @@ +Source: bluetooth-frwk +Section: devel +Priority: optional +Maintainer: DoHyun Pyun , Hocheol Seo , ChanYeol Park +Uploaders: Girishashok Joshi , Sunil Behera , Syam Sidhardhan +Build-Depends: debhelper (>= 5), libslp-setting-dev, dlog-dev,libxml2-dev, libaul-1-dev, syspopup-caller-dev, libcontacts-service-dev, libdbus-glib-1-dev, libglib2.0-dev, email-service-dev, libslp-msg-service-dev +Standards-Version: 3.7.2 +Homepage: N/A + +Package: libbluetooth-frwk-0 +Section: libs +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, bluetooth-frwk-agent (= ${Source-Version}), dbus, bluez +Description: Bluetooth framework for BlueZ + This package is Bluetooth framework based on BlueZ stack. + This package contains API set for BT GAP, BT SDP, and BT RFCOMM. + +Package: libbluetooth-frwk-dev +Section: devel +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, libbluetooth-frwk-0 (= ${Source-Version}), libslp-setting-dev, dlog-dev, libxml2-dev, libdbus-glib-1-dev, libglib2.0-dev +XB-Generate-Docs: yes +Description: Bluetooth framework for BlueZ + This package is development files for Bluetooth framework based on BlueZ stack. + This package contains API set for BT GAP, BT SDP, and BT RFCOMM. + +Package: bluetooth-frwk-agent +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, libappcore-efl-0, libaul-1 +Description: Bluetooth Agent for pairing and authorization + This package is Bluetooth useraction Agent to response pairing, authorization, and mode change with BlueZ. + +Package: bt-service +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, libbluetooth-frwk-0 (= ${Source-Version}) +Description: Bluetooth service deamon + This package is Bluetooth service daemon. + +Package: bluetooth-frwk-dbg +Section: debug +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, libbluetooth-frwk-0 (= ${Source-Version}) +Description: Bluetooth framework (unstripped) + The package contains detached debugging symbols for the binary packages + produced by the bluetooth-frwk soruce. + diff --git a/debian/libbluetooth-frwk-0.install.in b/debian/libbluetooth-frwk-0.install.in new file mode 100644 index 0000000..fef5120 --- /dev/null +++ b/debian/libbluetooth-frwk-0.install.in @@ -0,0 +1 @@ +/usr/lib/lib* diff --git a/debian/libbluetooth-frwk-0.postinst b/debian/libbluetooth-frwk-0.postinst new file mode 100644 index 0000000..63072c3 --- /dev/null +++ b/debian/libbluetooth-frwk-0.postinst @@ -0,0 +1,14 @@ +#!/bin/sh + +# root case +if [ ${USER} == "root" ] +then + # Set vconf values with -g/-u options + + # 6520 is vconf_bt + vconftool set -t int db/bluetooth/status "0" -g 6520 + vconftool set -t int file/private/bt-service/flight_mode_deactivated "0" -g 6520 + vconftool set -t int memory/private/libbluetooth-frwk-0/obex_no_agent "0" -g 6520 -i + vconftool set -t string memory/private/libbluetooth-frwk-0/uuid "" -g 6520 -i + vconftool set -t string memory/bluetooth/sco_headset_name "" -g 6520 -i +fi \ No newline at end of file diff --git a/debian/libbluetooth-frwk-dev.install.in b/debian/libbluetooth-frwk-dev.install.in new file mode 100644 index 0000000..ceab20e --- /dev/null +++ b/debian/libbluetooth-frwk-dev.install.in @@ -0,0 +1,2 @@ +/usr/include/* +/usr/lib/pkgconfig/* diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..3315059 --- /dev/null +++ b/debian/rules @@ -0,0 +1,155 @@ +#!/usr/bin/make -f + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +CFLAGS ?= -Wall -g +LDFLAGS ?= +PREFIX ?= /usr +DATADIR ?= /opt + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif + +LDFLAGS += -Wl,--rpath=$(PREFIX)/lib -Wl,--as-needed -Wl,--unresolved-symbols=ignore-in-shared-libs + +configure: configure-stamp +configure-stamp: + dh_testdir + # Add here commands to configure the package. + CFLAGS="$(CFLAGS) -fpie" LDFLAGS="$(LDFLAGS) -pie" \ + cmake . -DCMAKE_INSTALL_PREFIX=$(PREFIX) + + touch configure-stamp + +build: build-stamp + +build-stamp: configure-stamp + dh_testdir + + # Add here commands to compile the package. + $(MAKE) + + for f in `find $(CURDIR)/debian/ -name "*.in"`; do \ + cat $$f > $${f%.in}; \ + sed -i -e "s#@PREFIX@#$(PREFIX)#g" $${f%.in}; \ + sed -i -e "s#@DATADIR@#$(DATADIR)#g" $${f%.in}; \ + done + + touch $@ + +clean: + dh_testdir + dh_testroot + rm -f build-stamp configure-stamp + + # Add here commands to clean up after the build process. + -$(MAKE) clean + + for f in `find $(CURDIR)/ -name "CMakeCache.txt"`; do \ + rm -f $${f}; \ + done + for f in `find $(CURDIR)/ -name "CMakeFiles"`; do \ + rm -rf $${f}; \ + done + for f in `find $(CURDIR)/ -name "cmake_install.cmake"`; do \ + rm -f $${f}; \ + done +# for f in `find $(CURDIR)/ -name "Makefile"`; do \ + rm -f $${f}; \ + done + for f in `find $(CURDIR)/ -name "install_manifest.txt"`; do \ + rm -f $${f}; \ + done + for f in `find $(CURDIR)/ -name "*.edj"`; do \ + rm -f $${f}; \ + done + for f in `find $(CURDIR)/debian/ -name "*.in"`; do \ + rm -f $${f%.in}; \ + done + + rm -f Makefile + rm -f lib/Makefile + rm -f bluetooth-frwk-agent/Makefile + rm -f bluetooth-pb-agent/Makefile + rm -f bluetooth-map-agent/Makefile + rm -f bluetooth-frwk-agent/po/Makefile + rm -f lib/test/Makefile + + rm -f lib/*.pc + rm -f lib/marshal.c + rm -f lib/marshal.h + rm -f lib/obex-agent-glue.h + + rm -f bluetooth-frwk-agent/marshal.c + rm -f bluetooth-frwk-agent/marshal.h + rm -f bluetooth-telephony/marshal.c + rm -f bluetooth-telephony/marshal.h + + rm -f bluetooth-frwk-agent/sc_core_agent_glue.h + rm -f bluetooth-frwk-agent/bluetooth_obex_agent_glue.h + rm -f bluetooth-pb-agent/bluetooth_pb_agent_glue.h + rm -f bluetooth-map-agent/bluetooth_map_agent_glue.h + rm -f bluetooth-telephony/bluetooth-telephony-glue.h + + rm -f bluetooth-media-control/Makefile + rm -f bluetooth-media-control/bluetooth-media-control.pc + rm -f bluetooth-media-control/test/Makefile + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/wavplayer. + $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install + + # Booting script + mkdir -p $(CURDIR)/debian/tmp/etc/rc.d/rc3.d/ + mkdir -p $(CURDIR)/debian/tmp/etc/rc.d/rc5.d/ + ln -s ../init.d/bluetooth-frwk-agent $(CURDIR)/debian/tmp/etc/rc.d/rc3.d/S80bluetooth-frwk-agent + ln -s ../init.d/bluetooth-frwk-agent $(CURDIR)/debian/tmp/etc/rc.d/rc5.d/S80bluetooth-frwk-agent + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs + dh_installdocs + dh_installexamples + dh_install --sourcedir=debian/tmp +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_python +# dh_installinit +# dh_installcron +# dh_installinfo + dh_installman + dh_link + dh_strip --dbg-package=bluetooth-frwk-dbg + dh_compress + dh_fixperms +# dh_perl + dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/include/bluetooth-api.h b/include/bluetooth-api.h new file mode 100644 index 0000000..b790c53 --- /dev/null +++ b/include/bluetooth-api.h @@ -0,0 +1,3270 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 _BLUETOOTH_API_H_ +#define _BLUETOOTH_API_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup BLUETOOTHFW BluetoothFW + * + * A base library for bluetooth framework + * + * @addtogroup BLUETOOTHFW + * @{ + */ + +#define BLUETOOTH_ADDRESS_LENGTH 6 /**< This specifies bluetooth device address length */ +#define BLUETOOTH_INTERFACE_NAME_LENGTH 16 +#define BLUETOOTH_DEVICE_NAME_LENGTH_MAX 248 /**< This specifies maximum device name 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_OOB_DATA_LENGTH 16 +/** + * This is Bluetooth Connected event role + */ +#define RFCOMM_ROLE_SERVER 1 +#define RFCOMM_ROLE_CLIENT 2 + +/** + * This is Bluetooth error code + */ +#define BLUETOOTH_ERROR_BASE ((int)0) /**< Error code base */ + +#define BLUETOOTH_ERROR_NONE ((int)0) /**< No error #0 */ +#define BLUETOOTH_ERROR_CANCEL ((int)BLUETOOTH_ERROR_BASE - 0x01) + /**< cancelled */ +#define BLUETOOTH_ERROR_INVALID_CALLBACK ((int)BLUETOOTH_ERROR_BASE - 0x02) + /**< Callback error */ +#define BLUETOOTH_ERROR_INVALID_PARAM ((int)BLUETOOTH_ERROR_BASE - 0x03) + /**< invalid paramerror */ +#define BLUETOOTH_ERROR_INVALID_DATA ((int)BLUETOOTH_ERROR_BASE - 0x04) + /**< invalid data error */ +#define BLUETOOTH_ERROR_MEMORY_ALLOCATION ((int)BLUETOOTH_ERROR_BASE - 0x05) + /**< Memory allocation error */ +#define BLUETOOTH_ERROR_OUT_OF_MEMORY ((int)BLUETOOTH_ERROR_BASE - 0x06) + /**< out of memory error */ +#define BLUETOOTH_ERROR_TIMEOUT ((int)BLUETOOTH_ERROR_BASE - 0x07) + /**< timeout error */ +#define BLUETOOTH_ERROR_NO_RESOURCES ((int)BLUETOOTH_ERROR_BASE - 0x08) + /**< No resource error */ +#define BLUETOOTH_ERROR_INTERNAL ((int)BLUETOOTH_ERROR_BASE - 0x09) + /**< internal error */ +#define BLUETOOTH_ERROR_NOT_SUPPORT ((int)BLUETOOTH_ERROR_BASE - 0x0a) + /**< Not supported error */ +#define BLUETOOTH_ERROR_DEVICE_NOT_ENABLED ((int)BLUETOOTH_ERROR_BASE - 0x0b) + /**< Operation is failed because + of not enabled BT Adapter */ +#define BLUETOOTH_ERROR_DEVICE_ALREADY_ENABLED ((int)BLUETOOTH_ERROR_BASE - 0x0c) + /**< Enabling is failed because of + already enabled BT Adapter */ +#define BLUETOOTH_ERROR_DEVICE_BUSY ((int)BLUETOOTH_ERROR_BASE - 0x0d) + /**< Operation is failed because of + other on going operation */ +#define BLUETOOTH_ERROR_ACCESS_DENIED ((int)BLUETOOTH_ERROR_BASE - 0x0e) + /**< access denied error */ +#define BLUETOOTH_ERROR_MAX_CLIENT ((int)BLUETOOTH_ERROR_BASE - 0x0f) + /**< max client error */ +#define BLUETOOTH_ERROR_NOT_FOUND ((int)BLUETOOTH_ERROR_BASE - 0x10) + /**< not found error */ +#define BLUETOOTH_ERROR_SERVICE_SEARCH_ERROR ((int)BLUETOOTH_ERROR_BASE - 0x11) + /**< service search fail */ +#define BLUETOOTH_ERROR_PARING_FAILED ((int)BLUETOOTH_ERROR_BASE - 0x12) + /**< pairing failed error */ +#define BLUETOOTH_ERROR_NOT_PAIRED ((int)BLUETOOTH_ERROR_BASE - 0x13) + /**< Not paired error */ +#define BLUETOOTH_ERROR_SERVICE_NOT_FOUND ((int)BLUETOOTH_ERROR_BASE - 0x14) + /**< no service error */ +#define BLUETOOTH_ERROR_NOT_CONNECTED ((int)BLUETOOTH_ERROR_BASE - 0x15) + /**< no connection error */ +#define BLUETOOTH_ERROR_ALREADY_CONNECT ((int)BLUETOOTH_ERROR_BASE - 0x16) + /**< alread connected error */ +#define BLUETOOTH_ERROR_CONNECTION_BUSY ((int)BLUETOOTH_ERROR_BASE - 0x17) + /**< connection busy error */ +#define BLUETOOTH_ERROR_CONNECTION_ERROR ((int)BLUETOOTH_ERROR_BASE - 0x18) + /**< connection error */ +#define BLUETOOTH_ERROR_MAX_CONNECTION ((int)BLUETOOTH_ERROR_BASE - 0x19) + /**< max connection error*/ +#define BLUETOOTH_ERROR_NOT_IN_OPERATION ((int)BLUETOOTH_ERROR_BASE - 0x1a) + /**< Not in operation */ +#define BLUETOOTH_ERROR_CANCEL_BY_USER ((int)BLUETOOTH_ERROR_BASE - 0x1b) + /**< Cancelled by user */ +#define BLUETOOTH_ERROR_REGISTRATION_FAILED ((int)BLUETOOTH_ERROR_BASE - 0x1c) + /**< Service record registration failed */ +#define BLUETOOTH_ERROR_IN_PROGRESS ((int)BLUETOOTH_ERROR_BASE - 0x1d) + /**< Operation in progress */ +#define BLUETOOTH_ERROR_AUTHENTICATION_FAILED ((int)BLUETOOTH_ERROR_BASE - 0x1e) + /**< authentication failed error when paring*/ +#define BLUETOOTH_ERROR_HOST_DOWN ((int)BLUETOOTH_ERROR_BASE - 0x1f) + /**< Remote host is down */ +#define BLUETOOTH_ERROR_END_OF_DEVICE_LIST ((int)BLUETOOTH_ERROR_BASE - 0x20) + /**< End of device list */ + +#define BLUETOOTH_ERROR_AGENT_ALREADY_EXIST ((int)BLUETOOTH_ERROR_BASE - 0x21) + /**< Obex agent already exists */ +#define BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST ((int)BLUETOOTH_ERROR_BASE - 0x22) + /**< Obex agent does not exist */ + +#define BLUETOOTH_ERROR_ALREADY_INITIALIZED ((int)BLUETOOTH_ERROR_BASE - 0x23) + /**< Already initialized */ + + +/** + * This is Bluetooth device address type, fixed to 6 bytes ##:##:##:##:##:## + */ +typedef struct { + unsigned char addr[BLUETOOTH_ADDRESS_LENGTH]; +} bluetooth_device_address_t; + +/** + * This is Bluetooth device name type, maximum size of Bluetooth device name is 248 bytes + */ +typedef struct { + char name[BLUETOOTH_DEVICE_NAME_LENGTH_MAX + 1]; +} bluetooth_device_name_t; + +/** + * Adapter state + */ +typedef enum { + BLUETOOTH_ADAPTER_DISABLED, /**< Bluetooth adapter is disabled */ + BLUETOOTH_ADAPTER_ENABLED, /**< Bluetooth adapter is enabled */ + BLUETOOTH_ADAPTER_CHANGING_ENABLE, /**< Bluetooth adapter is currently enabling */ + BLUETOOTH_ADAPTER_CHANGING_DISABLE, /**< Bluetooth adapter is currently disabling */ +} bluetooth_adapter_state_t; + +/** + * Discoverable mode + */ +typedef enum { + BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE, /**< Non discoverable mode */ + /*Changed the order to make it compatable with old method */ + BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE,/**< Discoverable mode */ + BLUETOOTH_DISCOVERABLE_MODE_TIME_LIMITED_DISCOVERABLE, + /**< Discoverable mode with time limit + After specific timeout, it is changed + to non discoverable mode */ +} bluetooth_discoverable_mode_t; + +/** + * Network connect mode + */ +typedef enum { + BLUETOOTH_NETWORK_PANU_ROLE, + /**< PAN user */ + BLUETOOTH_NETWORK_NAP_ROLE,/**< Network Access Point */ + BLUETOOTH_NETWORK_GN_ROLE, /**< Group ad-hoc Network */ + BLUETOOTH_NETWORK_CUSTOM_UUID, /**< Custom role */ +} bluetooth_network_role_t; + +/** + * Service type + */ +typedef enum { + BLUETOOTH_RFCOMM_SERVICE = 0x01, + BLUETOOTH_A2DP_SERVICE = 0x02, + BLUETOOTH_HSP_SERVICE = 0x04, + BLUETOOTH_HID_SERVICE = 0x08, +} bluetooth_service_type_t; + +#define BLUETOOTH_EVENT_BASE ((int)(0x0000)) /**< No event */ +#define BLUETOOTH_EVENT_GAP_BASE ((int)(BLUETOOTH_EVENT_BASE + 0x0010)) + /**< Base ID for GAP Event */ +#define BLUETOOTH_EVENT_SDP_BASE ((int)(BLUETOOTH_EVENT_GAP_BASE + 0x0020)) + /**< Base ID for SDP events */ +#define BLUETOOTH_EVENT_RFCOMM_BASE ((int)(BLUETOOTH_EVENT_SDP_BASE + 0x0020)) + /**< Base ID for RFCOMM events */ +#define BLUETOOTH_EVENT_NETWORK_BASE ((int)(BLUETOOTH_EVENT_RFCOMM_BASE + 0x0020)) + /**< Base ID for NETWORK events */ +#define BLUETOOTH_EVENT_HDP_BASE ((int)(BLUETOOTH_EVENT_NETWORK_BASE + 0x0020)) + /**< Base ID for HDP events */ +#define BLUETOOTH_EVENT_OPC_BASE ((int)(BLUETOOTH_EVENT_HDP_BASE + 0x0020)) + /**< Base ID for OPC events */ +#define BLUETOOTH_EVENT_OBEX_SERVER_BASE ((int)(BLUETOOTH_EVENT_OPC_BASE + 0x0020)) + /**< Base ID for Obex Server events */ +#define BLUETOOTH_EVENT_GATT_BASE ((int)(BLUETOOTH_EVENT_OBEX_SERVER_BASE + 0x0020)) + /**< Base ID for GATT events */ + +#define BLUETOOTH_EVENT_AUDIO_BASE ((int)(BLUETOOTH_EVENT_GATT_BASE + 0x0020)) + /**< Base ID for Audio events */ +#define BLUETOOTH_EVENT_HID_BASE ((int)(BLUETOOTH_EVENT_AUDIO_BASE + 0x0020)) + /**< Base ID for HID events */ + +/** + * Bluetooth event type + */ +typedef enum { + BLUETOOTH_EVENT_NONE = BLUETOOTH_EVENT_BASE,/**< No event */ + + BLUETOOTH_EVENT_ENABLED, /**< Bluetooth event adpater enabled */ + BLUETOOTH_EVENT_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*/ + BLUETOOTH_EVENT_DISCOVERABLE_MODE_CHANGED, /**< Bluetooth event mode changed */ + 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_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 */ + BLUETOOTH_EVENT_BONDED_DEVICE_FOUND, /**< Bluetooth event paired device found */ + BLUETOOTH_EVENT_REMOTE_DEVICE_READ, /**< Bluetooth event read remote device */ + 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_SERVICE_SEARCHED = BLUETOOTH_EVENT_SDP_BASE, + /**< Bluetooth event serice search base id */ + BLUETOOTH_EVENT_SERVICE_SEARCH_CANCELLED, /**< Bluetooth event service search cancelled */ + BLUETOOTH_EVENT_RFCOMM_DATA_RECEIVED = BLUETOOTH_EVENT_RFCOMM_BASE, + /**< RFCOMM data receive event */ + BLUETOOTH_EVENT_RFCOMM_CONNECTED, /**< Rfcomm server incomming connection */ + BLUETOOTH_EVENT_RFCOMM_DISCONNECTED, /**< Rfcomm server/client disconnect */ + + BLUETOOTH_EVENT_RFCOMM_AUTHORIZE, + + BLUETOOTH_EVENT_DEVICE_CONNECTED, /**< Bluetooth event device connected */ + BLUETOOTH_EVENT_DEVICE_DISCONNECTED, /**< Bluetooth event device disconnected */ + + BLUETOOTH_EVENT_RFCOMM_SERVER_REMOVED, + + BLUETOOTH_EVENT_NETWORK_SERVER_ACTIVATED = BLUETOOTH_EVENT_NETWORK_BASE, + /**< Bluetooth Network event */ + BLUETOOTH_EVENT_NETWORK_SERVER_DEACTIVATED, /**< Network server deactivated */ + BLUETOOTH_EVENT_NETWORK_SERVER_CONNECTED, /**< Network connected event in server */ + BLUETOOTH_EVENT_NETWORK_SERVER_DISCONNECTED, + /**< Network disconnected evnet in server */ + + BLUETOOTH_EVENT_NETWORK_CONNECTED, /**< Network connected event in client*/ + BLUETOOTH_EVENT_NETWORK_DISCONNECTED, /**< Network disconnected evnet in client*/ + + BLUETOOTH_EVENT_HDP_CONNECTED + = BLUETOOTH_EVENT_HDP_BASE, /***/ + BLUETOOTH_EVENT_HDP_DISCONNECTED, /***/ + BLUETOOTH_EVENT_HDP_DATA_RECEIVED, /***/ + + BLUETOOTH_EVENT_OPC_CONNECTED = BLUETOOTH_EVENT_OPC_BASE, + /* OPC Connected event */ + BLUETOOTH_EVENT_OPC_DISCONNECTED, /* OPC Disonnected event */ + BLUETOOTH_EVENT_OPC_TRANSFER_STARTED, /* OPC Transfer started event */ + BLUETOOTH_EVENT_OPC_TRANSFER_PROGRESS, /* OPC Transfer progress event */ + BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE, /* OPC Transfer Complete event */ + + BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_AUTHORIZE = BLUETOOTH_EVENT_OBEX_SERVER_BASE, + /* Obex server authorize event*/ + BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_STARTED, /* Obex Server transfer started event*/ + 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_GATT_SVC_CHAR_DISCOVERED = BLUETOOTH_EVENT_GATT_BASE, + /**= BLUETOOTH_ERROR_NONE) + { + // bluetooth_register_callback returned Success + } + else + { + // bluetooth_register_callback returned failiure + } + g_main_loop_run(main_loop); +} +@endcode + */ +int bluetooth_register_callback(bluetooth_cb_func_ptr callback_ptr, void *user_data); + +/** + * @fn int bluetooth_deregister_callback(bluetooth_cb_func_ptr callback_ptr) + * @brief Set the callback function pointer for bluetooth event + * + * + * This API will register the callback function, when any response and event are received from + * bluetooth framework. @n + * this registered callback function will be get called with appropriate event and data structures. + * This function is a synchronous call. An application developer can call + * bluetooth_register_callback() function to register a callback function of bluetooth_cb_func_ptr + * type. This registered function will receive events of bluetooth_event_type_t type along with + * data any. + * + * + * @param[in] none + * @return BLUETOOTH_ERROR_NONE - Success + * @remark None + * @see None +@code +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: + g_main_loop_quit(main_loop); + break; + } +} + +int main() +{ + GMainLoop *main_loop = NULL; + int ret = 0; + g_type_init(); + main_loop = g_main_loop_new(NULL, FALSE); + ret = bluetooth_register_callback(bt_event_callback, (void*)main_loop); + if (ret >= BLUETOOTH_ERROR_NONE) + { + // bluetooth_register_callback returned Success + } + else + { + // bluetooth_register_callback returned failiure + } + ret = bluetooth_deregister_callback(void); + g_main_loop_run(main_loop); +} +@endcode + */ +int bluetooth_unregister_callback(void); + +/** + * @fn int bluetooth_enable_adapter(void) + * @brief Enable the Bluetooth H/W + * + * + * This API can be used to activate Bluetooth. It initializes Bluetooth protocol stack for use and + * send request to bluetooth chip for activation. + * This function is typically called at startup or when Bluetooth services are required. This + * function must be called before calling any other API of Bluetooth operations. + * + * Before performing any operations like Device discover, service search etc.., the adapter must be + * enabled. + * + * This function is a asynchronous call. + * If the call is success then the application will receive BLUETOOTH_EVENT_ENABLED event + * through registered callback function with appropriate result code + * BLUETOOTH_CHANGE_STATUS_TIMEOUT - Timeout has happen \n + * BLUETOOTH_ERROR_NONE - Success \n + * + * If the adpter is not enabled with in 30 seconds then BLUETOOTH_EVENT_ENABLED with result code + * BLUETOOTH_CHANGE_STATUS_TIMEOUT will come + * + * @return BLUETOOTH_ERROR_NONE - Success\n + * BLUETOOTH_ERROR_DEVICE_ALREADY_ENABLED - Adapter already enabled\n + * BLUETOOTH_ERROR_ACCESS_DENIED - Enabling adapter is not allowed by MDM policy\n + * BLUETOOTH_ERROR_IN_PROGRESS - Adapter is activating or deactivating\n + * @exception BLUETOOTH_ERROR_INTERNAL - Dbus proxy call is fail + * @remark None + * @see bluetooth_check_adapter, bluetooth_disable_adapter +@code +void bt_event_callback(int event, bluetooth_event_param_t *param) +{ + switch(event) + { + case BLUETOOTH_EVENT_ENABLED: + if (param->result == BLUETOOTH_ERROR_NONE) + { + // Successfully Enabled + } + else + { + // Failed + } + break; + } +} + +... + +int ret = 0; +ret = bluetooth_enable_adapter(); + +@endcode + */ +int bluetooth_enable_adapter(void); + +/** + * @fn int bluetooth_disable_adapter(void) + * @brief Disable the Bluetooth H/W + * + * + * This function disables Bluetooth protocol stack and hardware. This function is called when + * Bluetooth is no longer used. It will internally free all resources and power off the RF radio. + * + * Bluetooth adapter should be disabled to switch off Bluetooth chip (and thereby saving power). + * bluetooth_disable_adapter() API will do that job for you. After switching off Bluetooth, + * BLUETOOTH_EVENT_DISABLED will be sent by SDK to application for confirmation with appropriate + * error code. + * The various error codes are BLUETOOTH_ERROR_NONE for success and BLUETOOTH_ERROR_INTERNAL for + * internal error. + * + * This function is a asynchronous call. + * If this call is success then the applications will receive BLUETOOTH_EVENT_DISABLED event + * through registered callback function. + * + * + * @return BLUETOOTH_ERROR_NONE - Success\n + * BLUETOOTH_ERROR_IN_PROGRESS - Adapter is activating or deactivating\n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Bluetooth adapter is not enabled\n + * @exception BLUETOOTH_ERROR_INTERNAL - Dbus proxy call is fail + * @remark None + * @see bluetooth_check_adapter, bluetooth_enable_adapter +@code +void bt_event_callback(int event, bluetooth_event_param_t *param) +{ + switch(event) + { + case BLUETOOTH_EVENT_DISABLED: + if (param->result == BLUETOOTH_ERROR_NONE) + { + // Successfully disabled + } + else + { + // Failed + } + break; + } +} + +... + +int ret = 0; +ret = bluetooth_disable_adapter(); +@endcode + */ +int bluetooth_disable_adapter(void); + + +/** + * @fn int bluetooth_is_supported(void) + * @brief Check if the bluetooth is supported or not by the current target + * + * This API checks whether the bluetooth is supported or not. + * This API only run by root permission. + * This API was made for the MDM service. + * + * This function is a synchronous call. + * + * @return 0 - if bluetooth is not supported\n + * 1 - if bluetooth is supported\n + * BLUETOOTH_ERROR_INTERNAL - Error in API internal + * @remark None +@code + +int ret = 0; +ret = bluetooth_is_supported(); +@endcode + */ +int bluetooth_is_supported(void); + + +/** + * @fn int bluetooth_check_adapter(void) + * @brief Check the current status of the Bluetooth adapter + * + * + * This API checks whether the Bluetooth adapter is enabled or not. Before performing any operations + * the bluetooth adapter should be enabled. This API helps to find out the current state of the + * bluetooth adapter. + * This API get the adapter internal data structure and check current adapter status. + * + * This function is a synchronous call. + * + * + * @return BLUETOOTH_ADAPTER_DISABLED - if bluetooth adapter is disabled\n + * BLUETOOTH_ADAPTER_ENABLED - if bluetooth adapter is enabled\n + * @remark None + * @see bluetooth_enable_adapter, bluetooth_disable_adapter +@code + +int ret = 0; +ret = bluetooth_check_adapter(); +@endcode + */ +int bluetooth_check_adapter(void); + +/** + * @fn int bluetooth_get_local_address(bluetooth_device_address_t *local_address) + * @brief Get the local adapter bluetooth address + * + * + * This API is used, get the device address of the local bluetooth adapter. Before calling this API, + * the adapter should be enabled. + * In its output parameter, you can receive bluetooth_device_address_t type of pointer which will + * contain Bluetooth address. + * Since its inconvenient for user to remember the address, Bluetooth provides a method to have a + * friendly name for each device. + * There is no event callback for this API. + * + * This function is a synchronous call. + * + * + * @return BLUETOOTH_ERROR_NONE - Succeess \n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid parameter (NULL buffer) \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is disabled \n + * @param[out] local_address a device address of local bluetooth adapter + * @remark None + * @see None +@code + +bluetooth_device_address_t local_address={0,}; +int ret = 0; + +ret = bluetooth_get_local_address(&local_address); +@endcode + */ +int bluetooth_get_local_address(bluetooth_device_address_t *local_address); + +/** + * @fn int bluetooth_get_local_name(bluetooth_device_name_t* local_name) + * @brief Get the local device name + * + * + * This function is used, get the local device name. Since its difficult to remember the Adapter + * address, the friendly name can be assigned to the adapter and we can get it using this API. This + * friendly name is retrived by the remote device and displaying. + * Before calling this API, the adapter should be enabled. There is no event callback for this API. + * + * This function is a synchronous call. + * + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid parameter (NULL buffer)\n + * @param[out] local_name a local device name + * @remark None + * @see None +@code +bluetooth_device_name_t local_name={0,} +int ret = 0; +ret = bluetooth_get_local_name (&local_name); +@endcode + */ +int bluetooth_get_local_name(bluetooth_device_name_t *local_name); + +/** + * @fn int bluetooth_set_local_name(const bluetooth_device_name_t *local_name) + * @brief Set the local device name + * + * + * This function is used to set the local device name. This is a human friendly name whose + * length can be BLUETOOTH_DEVICE_NAME_LENGTH_MAX maximum + * + * This function is a synchronous call. + * + * @param[in] local_name bluetooth device name to set local device + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is not enabled \n + * BLUETOOTH_ERROR_INVALID_PARAM - Bluetooth name parameter is incorrect \n + * BLUETOOTH_ERROR_INVALID_DATA - Device address provided is incorrect \n + * BLUETOOTH_ERROR_NO_RESOURCES - Pre-allocated memory error \n + * BLUETOOTH_ERROR_INTERNAL - The dbus method call is fail \n + * + * @remark None + +@code +bluetooth_device_name_t local_name={0,} +int ret = 0; +ret = bluetooth_set_local_name (&local_name); +@endcode + */ +int bluetooth_set_local_name(const bluetooth_device_name_t *local_name); + + +/** + * @fn int bluetooth_is_service_used(const char *service_uuid, gboolean *used) + * @brief Check if the uuid is used or not + * + * This function is used to check if the uuid is used or not. + * + * This function is a synchronous call. + * + * @param[in] service_uuid service uuid (UUID 128 bit as string) + * @param[out] used if the uuid is used or not + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is not enabled \n + * BLUETOOTH_ERROR_INVALID_PARAM - Bluetooth name parameter is incorrect \n + * BLUETOOTH_ERROR_INTERNAL - The dbus method call is fail \n + * + * @remark None + * +@code +gboolean used = FALSE; +const char *uuid ="00001101-0000-1000-8000-00805F9B34FB"; +ret = bluetooth_is_service_used(uuid, &used); +@endcode + */ +int bluetooth_is_service_used(const char *service_uuid, gboolean *used); + +/** + * @fn int bluetooth_is_device_connected(const bluetooth_device_address_t *device_address, bluetooth_service_type_t type, gboolean *is_connected) + * @brief Check if the device is connected to the specific service + * + * This function is used to check if if the device is connected to the specific service. + * + * This function is a synchronous call. + * + * @param[in] local_address a device address of remote bluetooth device + * @param[in] type the service type + * @param[out] is_connected if the device is connected or not + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is not enabled \n + * BLUETOOTH_ERROR_INVALID_PARAM - Bluetooth name parameter is incorrect \n + * BLUETOOTH_ERROR_INTERNAL - The dbus method call is fail \n + * + * @remark None + * +@code +gboolean is_connected = FALSE; +bluetooth_device_address_t device_address={{0x00,0x0D,0xFD,0x24,0x5E,0xFF}}; +ret = bluetooth_is_device_connected(&device_address, BLUETOOTH_HSP_SERVICE, &used); +@endcode + */ +int bluetooth_is_device_connected(const bluetooth_device_address_t *device_address, + bluetooth_service_type_t type, + gboolean *is_connected); + +/** + * @fn int bluetooth_get_discoverable_mode(bluetooth_discoverable_mode_t *discoverable_mode_ptr) + * @brief Get the visibility mode + * + * + * This function is used to get the discoverable mode (Visibility option). Depending upon the + * visibity mode, the property of the device is determined whether it can be discoverable, non + * discoverable, connectable etc. Before calling this API make sure that the adapter is 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_DATA - Invalid data \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is not enabled \n + * BLUETOOTH_ERROR_INTERNAL - Internal IPC error \n + * @param[out] discoverable_mode current bluetooth discoverable mode + * @remark None + * @see bluetooth_set_discoverable_mode + @code + bluetooth_discoverable_mode_t discoverable_mode_ptr; + int ret = 0; + ret = bluetooth_get_discoverable_mode (&discoverable_mode_ptr); + @endcode + */ +int bluetooth_get_discoverable_mode(bluetooth_discoverable_mode_t *discoverable_mode_ptr); + +/** + * @fn int bluetooth_set_discoverable_mode(bluetooth_discoverable_mode_t discoverable_mode, + * int timeout) + * @brief Set the visibility mode + * + * + * This function is used to set the discoverable mode (Visibility option). + * + * Many times user may want to keep his device discoverable so that when peer device is performing + * device search, he/she can find user's device. Application programmer can keep the mode as + * BLUETOOTH_DISCOVERABLE_MODE_GENERAL_DISCOVERABLE or + * BLUETOOTH_DISCOVERABLE_MODE_TIME_LIMITED_DISCOVERABLE for the same purpose. However, all these + * modes cause bluetooth adapter to consume more battery. Hence developer should generally + * keep discoverable mode as BLUETOOTH_DISCOVERABLE_MODE_CONNECTABLE. + * + * This function is a synchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_NOT_SUPPORT - Requested mode is not supported \n + * + * @param[in] discoverable_mode the bluetooth discoverable mode to set + * @param[in] timeout discoverable time in only limited discoverable mode (second), default: 0 + * @remark None + * @see bluetooth_get_discoverable_mode + +@code + +bluetooth_discoverable_mode_t mode; +int ret = 0; +mode= BLUETOOTH_DISCOVERABLE_MODE_TIME_LIMITED_DISCOVERABLE; +ret = bluetooth_set_discoverable_mode (mode, 180); + +@endcode + */ +int bluetooth_set_discoverable_mode(bluetooth_discoverable_mode_t discoverable_mode, + int timeout); + + +/** + * @fn int bluetooth_get_timeout_value(int *timeout) + * @brief Get the visibility timeout value + * + * + * This function is used to get the visibility timeout + * Before calling this API make sure that the adapter is 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_DATA - Invalid data \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is not enabled \n + * BLUETOOTH_ERROR_INTERNAL - Internal IPC error \n + * @param[out] timeout remain visibility timeout value + * @remark None + * @see bluetooth_set_discoverable_mode + @code + int timeout; + int ret = 0; + ret = bluetooth_get_timeout_value (&timeout); + @endcode + */ +int bluetooth_get_timeout_value(int *timeout); + + +/** + * @fn int bluetooth_start_discovery(unsigned short max_response, unsigned short discovery_duration, + * unsigned int classOfDeviceMask) + * @brief Start the device discovery + * + * To connect connect to peer bluetooth device, you will need to know its bluetooth address and its + * name. You can search for Bluetooth devices in vicinity by bluetooth_start_discovery() API. It + * first performs an inquiry. For each device found from the inquiry it gets the remote name of the + * device. Bluetooth device address and name are given to Application via + * BLUETOOTH_EVENT_REMOTE_DEVICE_FOUND event. In param_data of bluetooth_event_param_t, you will + * receive a pointer to a structure of bluetooth_device_info_t type. you will receive device + * address, device name, device class, rssi (received signal strength indicator). please see + * bluetooth_device_info_t for more details. + * + * + * This API provides searching options like max responses, discovery duration in seconds and class + * of device mask to filter device search. some times there may be too many bluetooth devices in + * vicinity of your device.in such scenario, application can request to reduce number of responces + * (BLUETOOTH_EVENT_REMOTE_DEVICE_FOUND event) with help of max_response parameter. However if you + * pass zero, bluetooth adapter will not restrict number of responses. you can also specify duration + * of the seach in discovery_duration. bluetooth adapter will automatically stop device search after + * application defined time. please note that discovery_duration should be mentioned in seconds. + * Also note that search will end after 180 seconds automatically if you pass 0 in discovery + * duration. + * + * sometimes user may want to search for a perticular kind of device. for ex, mobile or pc. in such + * case, you can use classOfDeviceMask parameter. please see bluetooth_device_service_class_t, + * bluetooth_device_major_class_t and bluetooth_device_minor_class_t enums + * + * This function is a asynchronous call. + * If the call is success then the application will receive BLUETOOTH_EVENT_DISCOVERY_STARTED event + * through registered callback function. + * + * The discovery is responded by an BLUETOOTH_EVENT_REMOTE_DEVICE_FOUND event for each device it + * finds and an BLUETOOTH_EVENT_REMOTE_DEVICE_NAME_UPDATED event for each fount device its name + * finds. + * + * The completion or cancellation of the discovery is indicated by an + * BLUETOOTH_EVENT_DISCOVERY_FINISHED event. + * + * The device discovery can be cancelled by calling bluetooth_stop_discovery(). + * + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Bluetooth adapter is not enabled \n + * BLUETOOTH_ERROR_DEVICE_BUSY - Bluetooth adapter is busy doing some operation \n + * BLUETOOTH_ERROR_INTERNAL - System error like heap full has occured or bluetooth + agent is not running \n + * + * @param[in] max_response define the maximum response of the number of founded devices + (0 means unlimited) + * @param[in] discovery_duration define bluetooth discovery duration (0 means 180s ) + * @param[in] classOfDeviceMask define classes of the device mask which user wants + (refer to class of device) + * @remark None + * @see bluetooth_cancel_discovery, bluetooth_device_info_t + +@code +void bt_event_callback(int event, bluetooth_event_param_t *param) +{ + switch(event) + { + case BLUETOOTH_EVENT_REMOTE_DEVICE_FOUND: + { + bluetooth_device_info_t *device_info = NULL; + printf("BLUETOOTH_EVENT_REMOTE_DEVICE_FOUND, result [0x%04x]", + param->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_REMOTE_DEVICE_NAME_UPDATED: + { + bluetooth_device_info_t *device_info = NULL; + printf("BLUETOOTH_EVENT_REMOTE_DEVICE_NAME_UPDATED, result [0x%04x]", + param->result); + device_info = (bluetooth_device_info_t *)param->param_data; + memcpy(&searched_device, &device_info->device_address, + sizeof(bluetooth_device_address_t)); + printf("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: + printf("BLUETOOTH_EVENT_DISCOVERY_FINISHED, result[0x%04x]", param->result); + break; + } +} + +unsigned short max_response; +unsigned short discovery_duration; +unsigned classOfDeviceMask; +int ret = 0; + +max_response =0; +discovery_duration =0; +classOfDeviceMask =0; + +ret = bluetooth_start_discovery(max_response,discovery_duration,classOfDeviceMask); + +@endcode + * + */ + +int bluetooth_start_discovery(unsigned short max_response, + unsigned short discovery_duration, + unsigned int classOfDeviceMask); + +/** + * @fn int bluetooth_cancel_discovery (void) + * @brief Cancel the on-going device discovery operation + * + * + * This function stops the on-going device discovery operation. This API has to be called after the + * bluetooth_start_discovery API and before the BLUETOOTH_EVENT_DISCOVERY_FINISHED event comes of + * the bluetooth_start_discovery API + * + * Normally the device discovery takes a more time (~10.24 seconds) to get all the devices in its + * vicinity and it recevies as BLUETOOTH_EVENT_REMOTE_DEVICE_FOUND event. This API helps us to + * cancel the discover request once the user received the device to which he wish to connect. + * + * This function is a asynchronous call. + * If the call is success to cancel discovey then the application will receive + * BLUETOOTH_EVENT_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_DISCOVERY_FINISHED: + TC_PRT("BLUETOOTH_EVENT_DISCOVERY_FINISHED, result[0x%04x]", param->result); + break; + } +} + +.. + +int ret = 0; + +ret = bluetooth_cancel_discovery(); +@endcode + */ +int bluetooth_cancel_discovery(void); + +/** + * @fn int bluetooth_is_discovering(void) + * @brief Check for the device discovery is in-progress or not. + * + * This API is used to check the current status of the 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_DISCOVERY_FINISHED + * event before performing other operations. This API is used to get for the current discovery + * operation status and using bluetooth_cancel_discovery() + * we can cancell the ongoing 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 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_discovery, bluetooth_cancel_discovery + +@code +int ret = 0; +ret = bluetooth_is_discovering (); +@endcode + */ +int bluetooth_is_discovering(void); + +/** + * @fn int bluetooth_bond_device(const bluetooth_device_address_t *device_address) + * @brief Initiate a bonding process + * + * + * This function initiates a bonding procedure with a peer device. 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 the pairing + * should be initiated + * @remark None + * @see bluetooth_cancel_bonding + @code +void bt_event_callback(int event, bluetooth_event_param_t *param) +{ + switch(event) + { + case BLUETOOTH_EVENT_BONDING_FINISHED: + { + TC_PRT("BLUETOOTH_EVENT_BONDING_FINISHED, result [0x%04x]", param->result); + if (param->result >= BLUETOOTH_ERROR_NONE) + { + bluetooth_device_info_t *device_info = NULL; + device_info = (bluetooth_device_info_t *)param->param_data; + printf("dev [%s] [%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X] + mjr[%#x] min[%#x] srv[%#x]", + 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], + device_info->device_class.major_class, + device_info->device_class.minor_class, + device_info->device_class.service_class); + } + else + { + //bonding failed + } + break; + } + } +} + +... + +int ret = 0; +bluetooth_device_address_t device_address={{0}}; + +ret = bluetooth_bond_device(&device_address); + +@endcode + */ +int bluetooth_bond_device(const bluetooth_device_address_t *device_address); + +/** + * @fn int bluetooth_cancel_bonding(void) + * @brief Cancel the on-going bonding process + * + * This API is called to cancel the on-going bonding procedure. It should be called before the + * BLUETOOTH_EVENT_BONDING_FINISHED event comes. + * This API is useful when the remote device is not responding to the bond request or we wish to + * cancel the bonding request. In this case we need not wait for the timeout to happen. + * + * This function is a synchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_NOT_IN_OPERATION - No bonding request in progress \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Adapter is not enabled \n + * @exception None + * @remark None + * @see bluetooth_bond_device +@code +... + +int ret = 0; + +ret = bluetooth_cancel_bonding(); +@endcode + */ +int bluetooth_cancel_bonding(void); + +/** + * @fn int bluetooth_unbond_device(const bluetooth_device_address_t *device_address) + * @brief Remove bonding + * + * + * To communicate with remote device over bluetooth link, user should bond with peer device. + * After bonding is over, peer device is added to list of bonded devices. bluetooth_unbond_device() + * API is used to remove peer device from the list. Please note that after removing the device + * from bonded device list, you cannot communication with peer device until bonding happens again. + * + * User can call this function by passing bluetooth device address of any bonded device. Please note + * that after successful return of this function, any bluetooth application running on your device + * will not be able to communicate with unbonded device until bond operation happens again using + * bluetooth_bond_device() + * + * + * This function is a asynchronous call. The request to remove the specified device from the bonded + * list is responded by an BLUETOOTH_EVENT_BONDED_DEVICE_REMOVED event. if the operation is success, + * you will receive BLUETOOTH_ERROR_NONE. BLUETOOTH_ERROR_NOT_PAIRED may be received in result code + * in case if there is a problem in locating given bluetooth device address in bonded devices list + * + * + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INVALID_PARAM - Device address is not valid \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Bluetooth adapter is not enabled \n + * BLUETOOTH_ERROR_DEVICE_BUSY - Bluetooth adapter is busy doing some operation \n + * BLUETOOTH_ERROR_INVALID_DATA - Device address provided is incorrect \n + * BLUETOOTH_ERROR_INTERNAL - System error like heap full has occured or bluetooth + * agent is not running \n + * BLUETOOTH_ERROR_NOT_PAIRED - Device address mentioned in the argument is not a + * bonded device \n + * + * @param[in] device_address This indicates an address of the device to remove bonding + * + * @remark None + * + * @see bluetooth_bond_device, bluetooth_cancel_bonding + * +@code +void bt_event_callback(int event, bluetooth_event_param_t *param) +{ + switch(event) { + case BLUETOOTH_EVENT_BONDED_DEVICE_REMOVED: { + bluetooth_device_address_t *dev_addr = NULL; + + if (param->result == BLUETOOTH_ERROR_NONE) { + dev_addr = (bluetooth_device_address_t *)param->param_data; + //Unbound scuccess + printf("%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", + dev_addr->addr[0], dev_addr->addr[1] + dev_addr->addr[2], dev_addr->addr[3] + dev_addr->addr[4], dev_addr->addr[5] + } else { + //unbound failure + } + } + } +} + +... + +int ret = 0; +bluetooth_device_address_t *device_address; + +// copy valid device address in device_address + +ret = bluetooth_unbond_device(device_address); +@endcode + */ +int bluetooth_unbond_device(const bluetooth_device_address_t *device_address); + +/** + * @fn int bluetooth_get_bonded_device_list(GPtrArray **dev_list) + * @brief Get bonded(paired) device list + * + * + * This API gets all bonded device list. + * The devices in the bonded device list further can be used to perform the authorization by calling + * bluetooth_authorize_device API. + * + * This function is a synchronous call. + * Information for bonded devices can be obtained when result code is BLUETOOTH_ERROR_NONE. If not, + * there is no valid information in the dev_list. + * The len field in the dev_list represents the number of bonded devices. The data structure for + * bonded device information is bluetooth_device_info_t. + * + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_NOT_SUPPORT - Opreation not supported \n + * @remark None + * @see bluetooth_bond_device, bluetooth_unbond_device, bluetooth_authorize_device + @code +void bt_get_bonded_devices(void) +{ +... + int i; + GPtrArray *devinfo = NULL; + bluetooth_device_info_t *ptr; + + // allocate the g_pointer_array + devinfo = g_ptr_array_new(); + + ret = bluetooth_get_bonded_device_list(&devinfo); + if (ret != BLUETOOTH_ERROR_NONE) + { + printf("bluetooth_get_bonded_device_list failed with [%d]",ret); + } + else + { + printf("g pointer arrary count : [%d]", devinfo->len); + for (i=0; ilen; i++) + { + ptr = g_ptr_array_index(devinfo, i); + if (ptr != NULL) + { + printf("Name [%s]\n", ptr->device_name.name); + printf("Major Class [%d]\n", ptr->device_class.major_class); + printf("Minor Class [%d]\n", ptr->device_class.minor_class); + printf("Service Class [%d]\n", ptr->device_class.service_class); + printf("%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", + 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]); + + // handle + ... + } + } + } + // free g_pointer_array + g_ptr_array_free(devinfo, TRUE); +} + +@endcode + */ +int bluetooth_get_bonded_device_list(GPtrArray **dev_list); + +/** + * @fn int bluetooth_get_bonded_device(const bluetooth_device_address_t *device_address, + * bluetooth_device_info_t *dev_info) + * @brief Get a bonded(paired) device + * + * + * This API gets a bonded device. + * + * This function is a synchronous call. + * Information for bonded devices can be obtained when result code is BLUETOOTH_ERROR_NONE. If not, + * there is no valid information in the dev_info. + * The data structure for bonded device information is bluetooth_device_info_t. + * + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_NOT_SUPPORT - Opreation not supported \n + * @remark None + * @see bluetooth_bond_device, bluetooth_unbond_device, bluetooth_authorize_device + @code +void bt_get_bonded_device(void) +{ +... + int i; + bluetooth_device_info_t devinfo = {0}; + bluetooth_device_address_t device_address={{0x00,0x1C,0x43,0x2B,0x1A,0xE5}}; + + ret = bluetooth_get_bonded_device(&device_address, &devinfo); + if (ret != BLUETOOTH_ERROR_NONE) + { + printf("bluetooth_get_bonded_device failed with [%d]",ret); + } + else + { + printf("Name [%s]\n", devinfo.device_name.name); + printf("Major Class [%d]\n", devinfo.device_class.major_class); + printf("Minor Class [%d]\n", devinfo.device_class.minor_class); + printf("Service Class [%d]\n", devinfo.device_class.service_class); + printf("%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", devinfo.device_address.addr[0], + devinfo.device_address.addr[1], devinfo.device_address.addr[2], + devinfo.device_address.addr[3], devinfo.device_address.addr[4], + devinfo.device_address.addr[5]); + + // handle + ... + } +} + +@endcode + */ +int bluetooth_get_bonded_device(const bluetooth_device_address_t *device_address, + bluetooth_device_info_t *dev_info); + +/** + * @fn int bluetooth_set_alias(const bluetooth_device_address_t *device_address, const char *alias) + * @brief set alias for bonded device + * + * + * This function set alias for bonded device. + * + * This function is a synchronous call. + * + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid parameter \n + * @param[in] device_address This indicates an address of the remote device + * @param[in] alias This indicates an alias to set + * @remark None + * @see None +@code +int ret = 0; +ret = bluetooth_set_alias(&remote_address); +@endcode + */ +int bluetooth_set_alias(const bluetooth_device_address_t *device_address, + const char *alias); + +/** + * @fn int bluetooth_get_remote_device(const bluetooth_device_address_t *device_address) + * @brief Get remote deivice + * + * + * This function gets specific remote device. + * + * This function is a asynchronous call. + * This API is responded by an BLUETOOTH_EVENT_REMOTE_DEVICE_READ event. + * + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_NOT_SUPPORT - Operation not supported \n + * @param[in] device_address This indicates an address of the remote device + * @remark None + * @see None +@code +int ret = 0; +ret = bluetooth_get_remote_device(&remote_address); +@endcode + */ +int bluetooth_get_remote_device(const bluetooth_device_address_t *device_address); + +/** + * @fn int bluetooth_authorize_device(const bluetooth_device_address_t *device_address, + * gboolean authorized) + * @brief Authorize/Unauthorize a bonded device + * + * + * This function authorizes/unauthorize a bonded device. It decides the device to connect + * with/without user confirmation. + * + * If we select a paired device and make it authorized by calling this API with the authorized + * parameter to TRUE, then it will not ask for the user conformation before connecting. Similarly + * if we unauthorize the paired device by calling this API with the authorized parameter to FALSE, + * then it will ask for the user conformation before the connection. + * + * This API supposed to be called on the paired devices. Which means we have to use this API only + * after successful pairing. + * + * This function is a asynchronous call. + * Response will be received through BLUETOOTH_EVENT_DEVICE_AUTHORIZED event. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * @exception BLUETOOTH_ERROR_INTERNAL - Cannot get the interal DBUS proxy \n + * @param[in] device_address This indicates an address of the device to authorize \n + * @param[in] authorized TRUE : authorize FALSE: unauthorize + * @remark None + * @see bluetooth_get_bonded_device_list +@code +void bt_event_callback(int event, bluetooth_event_param_t *param) +{ + switch(event) + { + case BLUETOOTH_EVENT_DEVICE_AUTHORIZED : + { + if (param->result == BLUETOOTH_ERROR_NONE) + { + //Device authorized + } + //device authorization failed failure + } + } +} + +... + +int ret = 0; +bluetooth_device_address_t device_address={{0}}; +gboolean authorized; + +authorized =TRUE; + +ret = bluetooth_authorize_device(&device_address,authorized); +@endcode + */ +int bluetooth_authorize_device(const bluetooth_device_address_t *device_address, + gboolean authorized); + +/** + * @fn int bluetooth_search_service(const bluetooth_device_address_t *device_address) + * @brief Get all services supported by remote device + * + * + * This API call initiates the search for the services supported by the specified device. Normally + * the service search will take a couple of seconds to get it completed. Before calling this API + * make sure that the Adapter is enabled. We have to give the device address of the remote device to + * perform the service search. We can get the device address by doing a device discovery operation. + * + * + * This function is a asynchronous call. + * The service search request is responded by BLUETOOTH_EVENT_SERVICE_SEARCHED event. + * + * There is a timeout associated with the service search. The default time out is 40 seconds. If the + * remove device did not respond with in the time out period the BLUETOOTH_EVENT_SERVICE_SEARCHED + * event is generated with appropriate result code. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_SERVICE_SEARCH_ERROR - Service search error (NULL device address) \n + * BLUETOOTH_ERROR_INTERNAL - Internal IPC error \n + * @param[in] device_address This indicates an address of the device + * whose services need to be found + * @remark None + * @see bluetooth_cancel_service_search + */ +int bluetooth_search_service(const bluetooth_device_address_t *device_address); + +/** + * @fn int bluetooth_cancel_service_search(void) + * @brief Cancel the ongoing service search operation + * + * + * This function cancel the ongoing service search operation. This API is usually calling after the + * bluetooth_search_service API. + * Normally service search will take a more time (> 5 seconds) to complete. This API will be called + * if the user wish to cancel the Ongoing service search operation. + * + * This API should be called just after the bluetooth_search_service API and before the + * BLUETOOTH_EVENT_SERVICE_SEARCHED event + * + * This function is a synchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_CANCEL - Error in service search cancel operation \n + * BLUETOOTH_ERROR_NOT_PAIRED - Not paired device \n + * BLUETOOTH_ERROR_NOT_IN_OPERATION - Searching service is not in operation \n + * + * @remark None + * @see bluetooth_search_service +@code +... + +int ret = 0; +ret = bluetooth_cancel_service_search(); +@endcode +*/ +int bluetooth_cancel_service_search(void); + +/** + * @fn int bluetooth_rfcomm_create_socket(const char *uuid) + * @brief Register rfcomm socket with a specific uuid + * + * + * This API register rfcomm socket with the given UUID. The return value of this API is the socket + * descriptor of the server. + * This is the first API which is called to create the server. Once we created the server socket, + * we will listen on that return socket. + * So a bluetooth_rfcomm_listen_and_accept should follow this API call. This is a synchronous call. + * + * + * @return socket FD on Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Device is not enabled \n + * BLUETOOTH_ERROR_INTERNAL - Internal error\n + * BLUETOOTH_ERROR_MAX_CONNECTION - Maximum connection reached\n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid parameter \n + * @param[in] UUID (128 bits) + * + * @remark None + * @see bluetooth_rfcomm_listen_and_accept, bluetooth_rfcomm_remove_socket + * + @code + + const char *rfcomm_test_uuid="00001101-0000-1000-8000-00805F9B34FB"; + fd = bluetooth_rfcomm_create_socket(rfcomm_test_uuid); + + @endcode + */ +int bluetooth_rfcomm_create_socket(const char *uuid); + +/** + * @fn int bluetooth_rfcomm_remove_socket(int socket_fd, const char *uuid) + * @brief De-register the rfcomm socket + * + * + * This API deregister rfcomm socket with the given socket fd and UUID. If the remote device is + * already connected then we will receive the BLUETOOTH_EVENT_RFCOMM_DISCONNECTED with socket + * descriptor else no event will come. We will call this API only after the + * bluetooth_rfcomm_listen_and_accept. + * This is a synchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Device is not enabled \n + * BLUETOOTH_ERROR_NOT_FOUND - Cannot find the proxy\n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid parameter \n + * @param[in] int socket_fd + * + * @remark None + * @see bluetooth_rfcomm_create_socket, bluetooth_rfcomm_listen_and_accept + * + @code + void bt_event_callback(int event, bluetooth_event_param_t *param) + { + switch(event) + { + case BLUETOOTH_EVENT_RFCOMM_DISCONNECTED: + { + bluetooth_rfcomm_connection_t *discon_ind = + (bluetooth_rfcomm_connection_t *)param->param_data; + + printf("\nDisconnected from FD %d", discon_ind->socket_fd); + } + } + } + + ... + + int ret = 0; + fd = bluetooth_rfcomm_create_socket(rfcomm_test_uuid); + ret = bluetooth_rfcomm_listen_and_accept(fd, 1); + .... + ret = bluetooth_rfcomm_remove_socket(fd); + @endcode + */ +int bluetooth_rfcomm_remove_socket(int socket_fd); + +/** + * @fn int bluetooth_rfcomm_server_disconnect(int socket_fd) + * @brief Disconnect rfcomm connection + * + * + * Disconnect a specific(device node fd) RFCOMM connection. This is a Synchronous call and there + * is no cabbback events for this API. We have to provice the valid client fd to disconnect from the + * remote server. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid parameter \n + * BLUETOOTH_ERROR_NOT_CONNECTED - Not connected \n + * @param[in] int socket_fd the sending socket fd + * + * @remark None + * + @code + + ret = bluetooth_rfcomm_server_disconnect(g_ret_fd); + if (ret < 0) + printf("Disconnection failed"); + else + printf("Disconnection Success"); + + @endcode + */ +int bluetooth_rfcomm_server_disconnect(int socket_fd); + +/** + * @fn int bluetooth_rfcomm_listen_and_accept(int socket_fd,int max_pending_connection) + * @brief Rfcomm socket listen + * + * + * This API make rfcomm socket listen and accept with socket. We will call this API immediatly + * after the bluetooth_rfcomm_create_socket API. + * This API listen for the incomming connection and once it receives a connection, it will give + * BLUETOOTH_EVENT_RFCOMM_CONNECTED + * event to the application. This is an Asynchronous API call. + * + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid parameter \n + * BLUETOOTH_ERROR_CONNECTION_ERROR - Listen failed \n + + * @param[in] int socket_fd + * @param[in] max pending connection. + * + * @remark None + * @see bluetooth_rfcomm_create_socket + * + @code + void bt_event_callback(int event, bluetooth_event_param_t* param) + { + switch(event) + { + case BLUETOOTH_EVENT_RFCOMM_CONNECTED: + { + bluetooth_rfcomm_connection_t *conn_ind = + (bluetooth_rfcomm_connection_t *)param->param_data; + + printf("\nConnected from FD %d", conn_ind->socket_fd); + } + } + } + + ... + + int ret = 0; + fd = bluetooth_rfcomm_create_socket(rfcomm_test_uuid); + ret = bluetooth_rfcomm_listen_and_accept(fd, 1); + + @endcode + */ +int bluetooth_rfcomm_listen_and_accept(int socket_fd, int max_pending_connection); + +/** + * @fn int bluetooth_rfcomm_listen(int socket_fd,int max_pending_connection) + * @brief Rfcomm socket listen + * + * + * This API make rfcomm socket listen and accept with socket. We will call this API immediatly + * after the bluetooth_rfcomm_create_socket API. + * This API listen for the incomming connection and once it receives a connection, it will give + * BLUETOOTH_EVENT_RFCOMM_AUTHORIZE + * event to the application. This is an Asynchronous API call. + * + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid parameter \n + * BLUETOOTH_ERROR_CONNECTION_ERROR - Listen failed \n + + * @param[in] int socket_fd + * @param[in] max pending connection. + * + * @remark None + * @see bluetooth_rfcomm_create_socket + * + @code + void bt_event_callback(int event, bluetooth_event_param_t* param) + { + switch(event) + { + case BLUETOOTH_EVENT_RFCOMM_AUTHORIZE: + { + char *name = (char *)param->param_data; + + printf("\nConnected from %s", name); + + bluetooth_rfcomm_accept_connection(); + } + } + } + + ... + + int ret = 0; + fd = bluetooth_rfcomm_create_socket(rfcomm_test_uuid); + ret = bluetooth_rfcomm_listen(fd, 1); + + @endcode + */ +int bluetooth_rfcomm_listen(int socket_fd, int max_pending_connection); + +/** + * @fn int bluetooth_rfcomm_accept_connection() + * @brief Accepts the authorization request indicated by the event + * BLUETOOTH_EVENT_RFCOMM_AUTHORIZE. + * + * This function is a synchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INTERNAL - Internal error \n + * + * @param[in] the socket fd of the server + * @param[out] the socket fd of the client + * + * @exception None + * @remark None + * @see bluetooth_rfcomm_reject_connection + */ +int bluetooth_rfcomm_accept_connection(int server_fd, int *client_fd); + +/** + * @fn int bluetooth_rfcomm_reject_connection() + * @brief Rejects the authorization request indicated by the event + * BLUETOOTH_EVENT_RFCOMM_AUTHORIZE. + * + * This function is a synchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INTERNAL - Internal error \n + * + * @param[in] the socket fd of the server + * + * @exception None + * @remark None + * @see bluetooth_rfcomm_accept_connection + */ +int bluetooth_rfcomm_reject_connection(int server_fd); + +/** + * @fn gboolean bluetooth_rfcomm_is_server_uuid_available(const char *uuid) + * @brief Informs whether rfcomm server uuid is available or not. + * + * This function is a synchronous call. + * + * @return TRUE - RFCOMM uuid is available \n + * FALSE - RFCOMM uuid is not available \n + * + * @param[in] uuid UUID string + * + * @exception None + * + * @remark None + */ +gboolean bluetooth_rfcomm_is_server_uuid_available(const char *uuid); + +/** + * @fn int bluetooth_rfcomm_connect(const bluetooth_device_address_t *remote_bt_address, + * const char *remote_uuid) + * @brief Connect to the remote device rfcomm * + * + * Connect to a specific RFCOMM based service on a remote device UUID. This is a Async call. Once + * the connection is successful callback BLUETOOTH_EVENT_RFCOMM_CONNECTED events is generated, + * which contains the socket_fd, device role (RFCOMM_ROLE_SERVER/RFCOMM_ROLE_CLIENT), device addess + * etc. The socket_fd can be further used to send the data. It better to do a sevice search before + * initiating a connection. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Device is not enabled \n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid parameter \n + * BLUETOOTH_ERROR_CONNECTION_BUSY - Connection in progress \n + * BLUETOOTH_ERROR_INTERNAL - Internal Error\n + * @param[in] bluetooth_device_address_t remote bt_address + * @param[in] char remote uuid + * @remark None + * @see bluetooth_rfcomm_disconnect, bluetooth_rfcomm_write, bluetooth_search_service + * + @code + + void bt_event_callback(int event, bluetooth_event_param_t *param) + { + switch(event) + { + case BLUETOOTH_EVENT_SERVICE_SEARCHED: + { + if (param->result >= BLUETOOTH_ERROR_NONE) + { + bt_sdp_info_t *bt_sdp_info=param->param_data; + + printf("Dev add = %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", + bt_sdp_info->device_addr.addr[0], + bt_sdp_info->device_addr.addr[1], + bt_sdp_info->device_addr.addr[2], + bt_sdp_info->device_addr.addr[3], + bt_sdp_info->device_addr.addr[4], + bt_sdp_info->device_addr.addr[5]); + + printf("Supported service list:\n"); + for(i=0; iservice_index; i++) + printf("[%#x]\n", + bt_sdp_info->service_list_array[i]); + + //Alternate method + //ret = bluetooth_rfcomm_connect(bt_sdp_info->device_addr, + //rfcomm_test_uuid); + } + break; + } + case BLUETOOTH_EVENT_RFCOMM_CONNECTED: + { + bluetooth_rfcomm_connection_t *conn_ind = + (bluetooth_rfcomm_connection_t *)param->param_data; + + printf("\nConnected from FD %d, Role = %s", conn_ind->socket_fd, + (conn_ind->device_role == RFCOMM_ROLE_SERVER) ? + "SERVER" : "CLIENT"); + } + } + } + + bluetooth_device_address_t remote_address = {{0},}; + remote_address.addr[0] = 0x0; remote_address.addr[1] = 0x0A; remote_address.addr[2] = 0x3A; + remote_address.addr[3]= 0x54; remote_address.addr[4] = 0x19; remote_address.addr[5]= 0x36; + ret = bluetooth_search_service(&remote_address); + if (ret < 0) + printf("Seach failed, Reason = %d", ret); + else + printf("Search Success, Ret = %d", ret); + + ret = bluetooth_rfcomm_connect(&remote_address, rfcomm_test_uuid); + if (ret < 0) + printf("Connection failed, Reason = %d", ret); + else + printf("Connection Success, Ret = %d", ret); + + @endcode + */ +int bluetooth_rfcomm_connect(const bluetooth_device_address_t *remote_bt_address, + const char *remote_uuid); + +/** + * @fn int bluetooth_rfcomm_disconnect(int socket_fd) + * @brief Disconnect rfcomm connection + * + * + * Disconnect a specific(device node fd) RFCOMM connection. This is a Synchronous call and there + * is no cabbback events for this API. We have to provice the valid client fd to disconnect from the + * remote server. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid parameter \n + * BLUETOOTH_ERROR_NOT_CONNECTED - Not connected \n + * @param[in] char remote bt_address + * + * @remark None + * @see bluetooth_rfcomm_connect + * + @code + + ret = bluetooth_rfcomm_disconnect(g_ret_fd); + if (ret < 0) + printf("Disconnection failed"); + else + printf("Disconnection Success"); + + @endcode + */ + +int bluetooth_rfcomm_disconnect(int socket_fd); + +/** + * @fn int bluetooth_rfcomm_write (int fd, const char *buff, int length) + * @brief Write to rfcomm connection + * + * + * This API is used to send the data over the rfcomm connection. This is a synchronous API. The same + * API is used to send the data for server and the client. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid parameter \n + * BLUETOOTH_ERROR_NOT_IN_OPERATION - The Fd is currently not in operation\n + * @param[in] int fd + * @param[in] const char *buff Data buffer to send + * @param[in] int length Length of the data + * + * @remark None + * @see bluetooth_rfcomm_connect + * + @code + char *buff = "Test data 123456789" + ret = bluetooth_rfcomm_write(g_ret_fd, buff, 15); + if (ret < 0) + printf("Send failed"); + else + printf("Send success"); + + @endcode + */ +int bluetooth_rfcomm_write(int fd, const char *buf, int length); + +/** + * @fn gboolean bluetooth_rfcomm_is_client_connected(void) + * @brief Informs whether rfcomm client is connected. + * + * This function is a synchronous call. + * + * @return TRUE - RFCOMM client is connected \n + * FALSE - RFCOMM client is not connected \n + * + * @exception None + * + * @remark None + */ +gboolean bluetooth_rfcomm_is_client_connected(void); + +/** + * @fn int bluetooth_network_activate_server(void) + * @brief Activate the NAP (Network Access Point) service + * + * This function is a asynchronous call. + * The activate server request is responded by BLUETOOTH_EVENT_NETWORK_SERVER_ACTIVATED 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 + * + * @remark None + * @see bluetooth_network_deactivate_server + * + */ +int bluetooth_network_activate_server(void); + +/** + * @fn int bluetooth_network_deactivate_server(void) + * @brief Deactivate the NAP (Network Access Point) service + * + * This function is a asynchronous call. + * The deactivate server request is responded by BLUETOOTH_EVENT_NETWORK_SERVER_DEACTIVATED 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 + * + * @remark None + * @see bluetooth_network_activate_server + * + */ +int bluetooth_network_deactivate_server(void); + +/** + * @fn int bluetooth_network_connect(const bluetooth_device_address_t *device_address, + * bluetooth_network_role_t role, + * char custom_uuid) + * @brief Connect the network server in the peer + * + * This function is a asynchronous call. + * The network connect request is responded by BLUETOOTH_EVENT_NETWORK_CONNECTED 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 device with which the pairing + * should be initiated + * @param[in] role The role to connect. PANU / GN / NAP / CUSTOM. If use the CUSTOM value, + * need to use the third parameter. + * @param[in] custom_uuid If use the CUSTOM value in second parameter, use this parameter to + * connect. UUID string + * @remark None + * @see bluetooth_network_disconnect + */ +int bluetooth_network_connect(const bluetooth_device_address_t *device_address, + bluetooth_network_role_t role, char *custom_uuid); + +/** + * @fn int bluetooth_network_disconnect(const bluetooth_device_address_t *device_address, + * bluetooth_network_role_t role, + * char *custom_uuid) + * @brief Connect the network server in the peer + * + * This function is a asynchronous call. + * The network disconnect request is responded by BLUETOOTH_EVENT_NETWORK_CONNECTED 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 device with which the pairing + * should be initiated + * @remark None + * @see bluetooth_network_connect + */ +int bluetooth_network_disconnect(const bluetooth_device_address_t *device_address); + +/*HDP - API's*/ + +/** + * @fn int bluetooth_hdp_activate(unsigned short data_type, + * bt_hdp_role_type_t role, + * bt_hdp_qos_type_t channel_type, + * char **app_handle) + * @brief Activate the HDP service for a particular data type + * + * This function is a synchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid parameter \n + * BLUETOOTH_ERROR_INTERNAL - Internal Error \n + * BLUETOOTH_ERROR_NO_RESOURCES - Not resource available \n + * + * @exception None + * @param[in] data_type The data type against corresponding service + * @param[in] role The role of HDP. HDP_ROLE_SOURCE/HDP_ROLE_SINK. + * @param[in] channel_type The QOS type for the channel. + * HDP_QOS_RELIABLE/HDP_QOS_STREAMING/HDP_QOS_ANY. + * For role = HDP_ROLE_SINK, the channel_type + * should be HDP_QOS_ANY. + * @param[out] app_handle The application handler against corresponding service + * @remark None + * @see bluetooth_hdp_deactivate + */ +int bluetooth_hdp_activate(unsigned short data_type, + bt_hdp_role_type_t role, + bt_hdp_qos_type_t channel_type, + char **app_handle); +/** + * @fn int bluetooth_hdp_deactivate(const char *app_handle) + * @brief Deactivate the HDP service for a particular service using the handler + * + * This function is a synchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid parameter \n + * BLUETOOTH_ERROR_INTERNAL - Internal Error \n + * BLUETOOTH_ERROR_NO_RESOURCES - Not resource available \n + * + * @exception None + * @param[in] app_handle The application handler against corresponding service + * @remark None + * @see bluetooth_hdp_deactivate + */ +int bluetooth_hdp_deactivate(const char *app_handle); + +/** + * @fn int bluetooth_hdp_send_data(unsigned int channel_id, + * const char *buffer, unsigned int size) + * @brief Send data to the remote HDP device + * + * This function is a synchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid parameter \n + * BLUETOOTH_ERROR_INTERNAL - Internal Error \n + * BLUETOOTH_ERROR_NO_RESOURCES - Not resource available \n + * BLUETOOTH_ERROR_NOT_IN_OPERATION - FD is invalid \n + * + * @exception None + * @param[in] channel_id The channel id for the connection. + * @param[in] buffer The pdu buffer. + * @param[in] size Size of the buffer. + * @remark None + * @see bluetooth_hdp_connect + */ +int bluetooth_hdp_send_data(unsigned int channel_id, + const char *buffer, unsigned int size); +/** + * @fn int bluetooth_hdp_connect(const char *app_handle, + * bt_hdp_qos_type_t channel_type, + * const bluetooth_device_address_t *device_address) + * @brief Connect to the remote device(Mainly used by source) + * + * This function is a asynchronous call. + * The HDP activate is responded by BLUETOOTH_EVENT_HDP_CONNECTED event. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid parameter \n + * BLUETOOTH_ERROR_INTERNAL - Internal Error \n + * BLUETOOTH_ERROR_NO_RESOURCES - Not resource available \n + * BLUETOOTH_ERROR_MEMORY_ALLOCATION -Memory allocation failed \n + * + * @exception None + * @param[in] app_handle The application handler against corresponding service + * @param[in] channel_type The QOS type for the channel. + * HDP_QOS_RELIABLE/HDP_QOS_STREAMING. + * @param[in] device_address The remote device Bd address. + * + * @remark None + * @see bluetooth_hdp_disconnect + */ +int bluetooth_hdp_connect(const char *app_handle, + bt_hdp_qos_type_t channel_type, + const bluetooth_device_address_t *device_address); +/** + * @fn int bluetooth_hdp_disconnect(unsigned int channel_id, + * const bluetooth_device_address_t *device_address) + * @brief Disconnect from the remote device(Mainly used by source) + * + * This function is a asynchronous call. + * The HDP activate is responded by BLUETOOTH_EVENT_HDP_DISCONNECTED event. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid parameter \n + * BLUETOOTH_ERROR_INTERNAL - Internal Error \n + * BLUETOOTH_ERROR_NO_RESOURCES - Not resource available \n + * BLUETOOTH_ERROR_MEMORY_ALLOCATION -Memory allocation failed \n + * + * @exception None + * @param[in] channel_id The channel id for the connection. + * @param[in] device_address The remote device Bd address. + * + * @remark None + * @see bluetooth_hdp_connect + */ +int bluetooth_hdp_disconnect(unsigned int channel_id, + const bluetooth_device_address_t *device_address); + + +/** + * @fn int bluetooth_opc_init(void) + * @brief Initialize OPP client. + * + * This function is a synchronous call. + * No event corresponding to this api + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Device is not enabled \n + * BLUETOOTH_ERROR_INTERNAL - Internal Error \n + * BLUETOOTH_ERROR_NO_RESOURCES - Not resource available \n + * BLUETOOTH_ERROR_ACCESS_DENIED -Memory allocation failed \n + * + * @exception None + * + * @remark None + * @see bluetooth_opc_deinit + */ +int bluetooth_opc_init(void); + +/** + * @fn int bluetooth_opc_deinit(void) + * @brief Deinitialize OPP client. + * + * This function is a synchronous call. + * No event corresponding to this api + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Device is not enabled \n + * BLUETOOTH_ERROR_ACCESS_DENIED -Memory allocation failed \n + * + * @exception None + * + * @remark None + * @see bluetooth_opc_init + */ + + int bluetooth_opc_deinit(void); + +/** + * @fn int bluetooth_opc_push_files(bluetooth_device_address_t *remote_address, + char **file_name_array) + * @brief Send multiple files to a remote device. + * + * This function is a asynchronous call. + * This api is responded by BLUETOOTH_EVENT_OPC_CONNECTED event. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Device is not enabled \n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid parameter \n + * 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. + * @param[in] file_name_array Array of filepaths to be sent. + * + * @remark None + * @see bluetooth_opc_cancel_push + */ + +int bluetooth_opc_push_files(bluetooth_device_address_t *remote_address, + char **file_name_array); + +/** + * @fn int bluetooth_opc_cancel_push(void) + * @brief Cancels the ongoing file push. + * + * This function is a asynchronous call. + * This api is responded with either BLUETOOTH_EVENT_OPC_CONNECTED or + * BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETED event. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Device is not enabled \n + * BLUETOOTH_ERROR_ACCESS_DENIED - No push in progress \n + * + * @exception None + * + * @remark None + * @see bluetooth_opc_push_files + */ + +int bluetooth_opc_cancel_push(void); + +/** + * @fn gboolean bluetooth_opc_session_is_exist(void) + * @brief Informs whether opc session exists or not. + * + * This function is a synchronous call. + * + * @return TRUE - OPC session exists \n + * FALSE - OPC session does not exist \n + * + * @exception None + * + * @remark None + * @see None + */ + +gboolean bluetooth_opc_session_is_exist(void); + + +/** + * @fn int bluetooth_obex_server_init(const char *dst_path) + * @brief Initialize OPP and FTP server. + * + * This function is a synchronous call. + * No event corresponding to this api + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Device is not enabled \n + * BLUETOOTH_ERROR_NO_RESOURCES - Not resource available \n + * BLUETOOTH_ERROR_AGENT_ALREADY_EXIST - Obex agent already registered \n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid parameter \n + * + * @exception None + * @param[in] dst_path OPS destination file path. + * @remark None + * @see bluetooth_obex_server_deinit + */ +int bluetooth_obex_server_init(const char *dst_path); + + +/** + * @fn int bluetooth_obex_server_deinit(void) + * @brief Deinitialize OPP and FTP server. + * + * This function is a synchronous call. + * No event corresponding to this api + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Device is not enabled \n + * BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST -Obex agent not registered \n + * + * @exception None + * + * @remark None + * @see bluetooth_obex_server_init + */ +int bluetooth_obex_server_deinit(void); + + +/** + * @fn gboolean bluetooth_obex_server_is_activated(void) + * @brief Informs whether obex server is activated or not. + * + * This function is a synchronous call. + * + * @return TRUE - OBEX server is activated \n + * FALSE - OBEX server is not activated \n + * + * @exception None + * + * @remark None + */ + +gboolean bluetooth_obex_server_is_activated(void); + + +/** + * @fn int bluetooth_obex_server_init_without_agent(const char *dst_path) + * @brief Initialize OPP and FTP server without the conneciton authorization of the agent + * + * This function is a synchronous call. + * No event corresponding to this api + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Device is not enabled \n + * BLUETOOTH_ERROR_NO_RESOURCES - Not resource available \n + * BLUETOOTH_ERROR_AGENT_ALREADY_EXIST - Obex agent already registered \n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid parameter \n + * + * + * @exception None + * @param[in] dst_path OPS destination file path. + * @remark None + * @see bluetooth_obex_server_deinit_without_agent + */ +int bluetooth_obex_server_init_without_agent(const char *dst_path); + + +/** + * @fn int bluetooth_obex_server_deinit_without_agent(void) + * @brief Deinitialize OPP and FTP server without the conneciton authorization of the agent + * + * This function is a synchronous call. + * No event corresponding to this api + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Device is not enabled \n + * BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST -Obex agent not registered \n + * + * @exception None + * + * @remark None + * @see bluetooth_obex_server_init_without_agent + */ +int bluetooth_obex_server_deinit_without_agent(void); + + +/** + * @fn int bluetooth_obex_server_accept_connection(void) + * @brief Accepts the authorization request indicated by the event + * BLUETOOTH_EVENT_OBEX_SERVER_CONNECTION_AUTHORIZE. + * + * This function is a synchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_NO_RESOURCES - Not resource available \n + * BLUETOOTH_ERROR_INTERNAL - Internal error \n + * + * @exception None + * @remark None + * @see bluetooth_obex_server_reject_authorize + */ +int bluetooth_obex_server_accept_connection(void); + + +/** + * @fn int bluetooth_obex_server_reject_connection(void) + * @brief Rejects the authorization request indicated by the event + * BLUETOOTH_EVENT_OBEX_SERVER_CONNECTION_AUTHORIZE. + * + * This function is a synchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_NO_RESOURCES - Not resource available \n + * BLUETOOTH_ERROR_INTERNAL - Internal error \n + * + * @exception None + * @remark None + * @see bluetooth_obex_server_reject_authorize + */ +int bluetooth_obex_server_reject_connection(void); + + +/** + * @fn int bluetooth_obex_server_accept_authorize(const char *filename) + * @brief Accepts the authorization request indicated by the event + * BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_AUTHORIZE. + * + * This function is a asynchronous call. + * This api will be responded with the event BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_STARTED. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Device is not enabled \n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid parameter \n + * BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST -Obex agent not registered \n + * + * @exception None + * @param[in] filename Authorized filename. + + * @remark None + * @see bluetooth_obex_server_reject_authorize + */ + +int bluetooth_obex_server_accept_authorize(const char *filename); + +/** + * @fn int bluetooth_obex_server_reject_authorize(void) + * @brief Reject the authorization request indicated by the event + * BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_AUTHORIZE. + * + * This function is a asynchronous call. + * No event for this api.. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Device is not enabled \n + * BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST -Obex agent not registered \n + * + * @exception None + + * @remark None + * @see bluetooth_obex_server_accept_authorize + */ + +int bluetooth_obex_server_reject_authorize(void); + +/** + * @fn int bluetooth_obex_server_set_destination_path(const char *dst_path) + * @brief Set the OPS destination file path.. + * + * This function is a asynchronous call. + * No event for this api.. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_NO_RESOURCES - Not resource available \n + * BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST -Obex agent not registered \n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid Param \n + * + * @exception None + * @param[in] dst_path OPS destination file path. + + * @remark None + * @see None + */ + +int bluetooth_obex_server_set_destination_path(const char *dst_path); + +/** + * @fn int bluetooth_obex_server_set_root(const char *root) + * @brief Set the FTS root folder.. + * + * This function is a asynchronous call. + * No event for this api.. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_DEVICE_NOT_ENABLED - Device is not enabled \n + * BLUETOOTH_ERROR_NO_RESOURCES - Not resource available \n + * BLUETOOTH_ERROR_ACCESS_DENIED - Operation not allowed \n + * BLUETOOTH_ERROR_INVALID_PARAM - Invalid parameter \n + * BLUETOOTH_ERROR_INTERNAL - Internal Error \n + * + * @exception None + * @param[in] root FTS root folder. + + * @remark None + * @see None + */ + +int bluetooth_obex_server_set_root(const char *root); + +/** + * @fn int bluetooth_obex_server_cancel_transfer(int transfer_id) + * @brief Cancel the transfer on server + * + * This function is an asynchronous call. + * If the function call that cancels transfer is successful, the application would receive + * BLUETOOTH_EVENT_TRANSFER_COMPLETED 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 - Not enabled \n + * BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST -Obex agent not registered \n + * BLUETOOTH_ERROR_INTERNAL - internal error (proxy does not exist) \n + * BLUETOOTH_ERROR_NOT_FOUND - The transfer is not found \n + * + * @exception None + * @param[in] transfer_id transfer ID + + * @remark None + * @see None + */ +int bluetooth_obex_server_cancel_transfer(int transfer_id); + + +/** + * @fn int bluetooth_obex_server_cancel_all_transfers(void) + * @brief Cancel the transfer on server + * + * This function is an asynchronous call. + * If the function call that cancels transfer is successful, the application would receive + * BLUETOOTH_EVENT_TRANSFER_COMPLETED 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 - Not enabled \n + * BLUETOOTH_ERROR_AGENT_DOES_NOT_EXIST -Obex agent not registered \n + * BLUETOOTH_ERROR_INTERNAL - internal error (proxy does not exist) \n + * BLUETOOTH_ERROR_NOT_FOUND - The transfer is not found \n + * + * @exception None + * + * @remark None + * @see None + */ +int bluetooth_obex_server_cancel_all_transfers(void); + + +/** + * @fn int bluetooth_oob_read_local_data(bt_oob_data_t *local_oob_data) + * @brief Read the local Hash and Randmizer. + * + * This function is a synchronous call. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INTERNAL - Internal Error \n + * + * @exception None + * @param[in] None. + * @param[out] local_oob_data - Pointer to the local OOB data + * + * @remark None + * @see None + */ + +int bluetooth_oob_read_local_data(bt_oob_data_t *local_oob_data); + + +/** + * @fn int bluetooth_oob_add_remote_data( + * const bluetooth_device_address_t *remote_device_address, + * bt_oob_data_t *oob_data) + * @brief Add/updated the remote device Hash and Randmizer. + * + * This function is a synchronous call. + * No event for this api.. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INTERNAL - Internal Error \n + * + * @exception None + * @param[in] remote_device_address - Remote device address + * remote_oob_data - Ponter to Hash and Randomizer oob data structure + * + * @remark None + * @see None + */ + +int bluetooth_oob_add_remote_data( + const bluetooth_device_address_t *remote_device_address, + bt_oob_data_t *remote_oob_data); + + +/** + * @fn int bluetooth_oob_remove_remote_data( + * const bluetooth_device_address_t *remote_device_address) + * @brief Delete the Hash and Randomizer w.r.t the remote device address. + * + * This function is a synchronous call. + * No event for this api.. + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INTERNAL - Internal Error \n + * + * @exception None + * @param[in] remote_device_address - Remote device address + * + * @remark None + * @see None + */ + +int bluetooth_oob_remove_remote_data( + const bluetooth_device_address_t *remote_device_address); + +/** + * @fn int bluetooth_gatt_get_primary_services(const bluetooth_device_address_t *address, + * bt_gatt_handle_info_t *prim_svc); + * + * @brief Gets the GATT based primary services handle supported by remote device + * + * This function is a synchronous call. + * The output parameter needs to be freed by calling bluetooth_gatt_free_primary_services() + * + * @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 - Remote device address + * @param[out] prim_svc - Structure containing remote service count and handle list. + * + * @remark None + * @see bluetooth_gatt_free_primary_services() + */ +int bluetooth_gatt_get_primary_services(const bluetooth_device_address_t *address, + bt_gatt_handle_info_t *prim_svc); + +/** + * @fn int bluetooth_gatt_discover_service_characteristics(const char *service_handle) + * + * @brief Discovers the characteristics of GATT based service of remote device + * + * This function is an asynchronous call. + * This API is responded with BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED + * + * @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] service_handle - Handle for remote service. + * + * @remark None + * @see None + */ +int bluetooth_gatt_discover_service_characteristics(const char *service_handle); + +/** + * @fn int bluetooth_gatt_get_service_property(const char *service_handle, + * bt_gatt_service_property_t *service); + * + * @brief Gets the properties of GATT based service of remote device + * + * This function is a synchronous call. + * The output parameter needs to be freed by calling bluetooth_gatt_free_primary_services() + * + * @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] service_handle - Handle for remote service. + * @param[out] service - Structure containing remote service property. + * + * @remark None + * @see bluetooth_gatt_free_service_property() + */ +int bluetooth_gatt_get_service_property(const char *service_handle, + bt_gatt_service_property_t *service); + +/** + * @fn int bluetooth_gatt_watch_characteristics(const char *service_handle) + * + * @brief Register to GATT based service to receive value change notification/indication. + * + * This function is a synchronous call. + * No event for this api. + * + * @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] service_handle - Handle for remote service. + * + * @remark None + * @see None + */ +int bluetooth_gatt_watch_characteristics(const char *service_handle); + +/** + * @fn int bluetooth_gatt_unwatch_characteristics(const char *service_handle) + * + * @brief Unregister GATT based service to receive value change notification/indication. + * + * This function is a synchronous call. + * No event for this api. + * + * @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] service_handle - Handle for remote service. + * + * @remark None + * @see None + */ +int bluetooth_gatt_unwatch_characteristics(const char *service_handle); + +/** + * @fn int bluetooth_gatt_get_characteristics_property(const char *char_handle, + * bt_gatt_char_property_t *characteristic); + * + * @brief Provides characteristic value along with properties. + * + * This function is a synchronous call. + * The output parameter needs to be freed by calling bluetooth_gatt_free_char_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] char_handle - Handle for Characteristic property. + * @param[out] characteristic - Structure containing remote characteristic property. + * + * @remark None + * @see bluetooth_gatt_free_char_property() + */ +int bluetooth_gatt_get_characteristics_property(const char *char_handle, + bt_gatt_char_property_t *characteristic); + +/** + * @fn int bluetooth_gatt_set_characteristics_value(const char *char_handle, + * const guint8 *value, int length) + * + * @brief Set characteristic 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 + * @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(const char *char_handle, + const guint8 *value, int length); + +/** + * @fn int bluetooth_gatt_free_primary_services(bt_gatt_handle_info_t *prim_svc); + * + * @brief Releases the memory allocated by bluetooth_gatt_get_primary_services() + * + * This function is a synchronous call. + * The input parameter is obtained by calling bluetooth_gatt_get_primary_services() + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INVALID_PARAM -Invalid Parameters \n + * + * @exception None + * @param[in] prim_svc - GATT handle info structure + * + * @remark None + * @see bluetooth_gatt_get_primary_services() + */ +int bluetooth_gatt_free_primary_services(bt_gatt_handle_info_t *prim_svc); + +/** + * @fn int bluetooth_gatt_free_service_property(bt_gatt_service_property_t *svc_pty); + * + * @brief Releases the memory allocated by bluetooth_gatt_get_service_property() + * + * This function is a synchronous call. + * The input parameter is obtained by calling bluetooth_gatt_get_service_property() + * + * @return BLUETOOTH_ERROR_NONE - Success \n + * BLUETOOTH_ERROR_INVALID_PARAM -Invalid Parameters \n + * + * @exception None + * @param[in] svc_pty - GATT service property structure. + * + * @remark None + * @see bluetooth_gatt_get_service_property() + */ +int bluetooth_gatt_free_service_property(bt_gatt_service_property_t *svc_pty); + +/** + * @fn int bluetooth_gatt_free_char_property(bt_gatt_char_property_t *char_pty); + * + * @brief Provides characteristic value along with properties. + * + * This function is a synchronous call. + * 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] char_pty - GATT characteristics property structure. + * + * @remark None + * @see bluetooth_gatt_get_characteristics_property() + */ + int bluetooth_gatt_free_char_property(bt_gatt_char_property_t *char_pty); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* _BLUETOOTH_API_H_*/ diff --git a/include/bluetooth-audio-api.h b/include/bluetooth-audio-api.h new file mode 100644 index 0000000..88c318e --- /dev/null +++ b/include/bluetooth-audio-api.h @@ -0,0 +1,190 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 _BLUETOOTH_AUDIO_API_H_ +#define _BLUETOOTH_AUDIO_API_H_ + +#include +#include +#include +#include +#include + +#include "bluetooth-api.h" + +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus*/ + +#define BLUETOOTH_AUDIO_ERROR_BASE ((int)0) +#define BLUETOOTH_AUDIO_ERROR_NONE ((int)0) +#define BLUETOOTH_AUDIO_ERROR_INTERNAL \ + ((int)BLUETOOTH_AUDIO_ERROR_BASE - 0x01) +#define BLUETOOTH_AUDIO_ERROR_INVALID_PARAM \ + ((int)BLUETOOTH_AUDIO_ERROR_BASE - 0x02) +#define BLUETOOTH_AG_ERROR_CONNECTION_ERROR \ + ((int)BLUETOOTH_AUDIO_ERROR_BASE - 0x03) +#define BLUETOOTH_AV_ERROR_CONNECTION_ERROR \ + ((int)BLUETOOTH_AUDIO_ERROR_BASE - 0x04) + +typedef struct { + int event; + int result; + void *param_data; + void *user_data; +} bt_audio_event_param_t; + +typedef enum { + BLUETOOTH_AG_STATE_NONE, + BLUETOOTH_AG_STATE_CONNECTING, + BLUETOOTH_AG_STATE_CONNECTED, + BLUETOOTH_AG_STATE_DISCONNECTED, + BLUETOOTH_AG_STATE_PLAYING, +} bt_ag_conn_status_t; + +typedef enum { + BLUETOOTH_AV_STATE_NONE, + BLUETOOTH_AV_STATE_CONNECTING, + BLUETOOTH_AV_STATE_CONNECTED, + BLUETOOTH_AV_STATE_DISCONNECTED, +} bt_av_conn_status_t; + +typedef void (*bt_audio_func_ptr) (int, bt_audio_event_param_t *, void *); + +typedef struct { + bt_ag_conn_status_t ag_state; + bt_av_conn_status_t av_state; + unsigned int ag_audio_flag; + unsigned int ag_spkr_gain; + bluetooth_device_address_t local_address; + bluetooth_device_address_t remote_address; + bt_audio_func_ptr audio_cb; + void *user_data; +} bt_audio_info_t; + +typedef enum { + BLUETOOTH_STATE_NONE = 0x0000, + BLUETOOTH_STATE_HEADSET_CONNECTED = 0x0004, + BLUETOOTH_STATE_A2DP_HEADSET_CONNECTED = 0x0010, +} bluetooth_device_state_t; + +/** + * @brief The function bluetooth_audio_init called to initializes the Audio + * service to bluetoothD and Global data related to audio. + * @param[in] cb Callback function + * @param[in] user_data Data sent by application, which will be + * returned in event handler. + * @return int Zero on Success or reason for error if any. + * + */ +int bluetooth_audio_init(bt_audio_func_ptr cb, void *user_data); + +/** + * @brief The function bluetooth_audio_deinit is called to free the Audio + * related Global data. + * + * @return int Zero on Success or reason for error if any. + * + */ +int bluetooth_audio_deinit(void); + +/** + * @brief The function bluetooth_audio_connect is called to establish an + * AG 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_audio_connect(bluetooth_device_address_t *remote_address); + +/** + * @brief The function bluetooth_audio_disconnect is called to disconnect + * an existing AG 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_audio_disconnect(bluetooth_device_address_t *remote_address); + +/** + * @brief The function bluetooth_ag_connect is called to establish an AG + * 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_ag_connect(bluetooth_device_address_t *remote_address); + +/** + * @brief The function bluetooth_ag_disconnect is called to disconnect an + * existing AG 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_ag_disconnect(bluetooth_device_address_t *remote_address); + +/** + * @brief The function bluetooth_av_connect is called to establish an AV + * 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_av_connect(bluetooth_device_address_t *remote_address); + +/** + * @brief The function bluetooth_av_disconnect is called to disconnect an + * existing AV 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_av_disconnect(bluetooth_device_address_t *remote_address); + +/** + * @brief The function bluetooth_ag_get_headset_volume is called to get + * the changed Volume on AG. + * + * @param[in] speaker_gain Speaker gain/loss. + * @return int Zero on Success or reason for error if any. + * + */ +int bluetooth_ag_get_headset_volume(unsigned int *speaker_gain); + +/** + * @brief The function bluetooth_ag_set_speaker_gain is called to indicate + * that the Volume on AG is changed. + * + * @param[in] speaker_gain Speaker gain/loss. + * @return int Zero on Success or reason for error if any. + * + */ +int bluetooth_ag_set_speaker_gain(unsigned int speaker_gain); + +#ifdef __cplusplus +} +#endif /*__cplusplus*/ +#endif/*_BLUETOOTH_AUDIO_API_H_*/ diff --git a/include/bluetooth-hid-api.h b/include/bluetooth-hid-api.h new file mode 100644 index 0000000..3880d76 --- /dev/null +++ b/include/bluetooth-hid-api.h @@ -0,0 +1,136 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 __BLUETOOTH_HID_API_H +#define __BLUETOOTH_HID_API_H + +#ifdef __cplusplus +extern "C" { +#endif + + +#define HID_ADDRESS_LENGTH 6 + +#define HID_ERROR_NONE ((int)0) + +#define HID_ERROR_BASE ((int)0) +#define HID_ERROR_ALREADY_INITIALIZED ((int)HID_ERROR_BASE - 0x01) +#define HID_ERROR_NOT_INITIALIZED ((int)HID_ERROR_BASE - 0x01) +#define HID_ERROR_NOT_PAIRED ((int)HID_ERROR_BASE - 0x02) +#define HID_ERROR_INTERNAL ((int)HID_ERROR_BASE - 0x03) +#define HID_ERROR_INVALID_PARAM ((int)HID_ERROR_BASE - 0x04) +#define HID_ERROR_NOT_ENABLED ((int)HID_ERROR_BASE - 0x05) +#define HID_ERROR_CONNECTION_FAILED ((int)HID_ERROR_BASE - 0x06) + +typedef struct { + int event; + int result; + void *param_data; + void *user_data; +} hid_event_param_t; + +typedef void (*hid_cb_func_ptr)(int, hid_event_param_t *, void *); + +typedef struct { + unsigned char addr[HID_ADDRESS_LENGTH]; +} hid_device_address_t; + + +/** + * @fn int bluetooth_hid_init(hid_cb_func_ptr callback_ptr, void *user_data) + * @brief Initialize HID service and register the callback + * + * This function is a synchronous call. + * + * @return HID_ERROR_NONE - Success \n + * HID_ERROR_ALREADY_INITIALIZED - Aready Initialized \n + * HID_ERROR_INTERNAL - Internal Error \n + * HID_ERROR_NOT_ENABLED - Not enabled \n + * + * @remark None + * + */ +int bluetooth_hid_init(hid_cb_func_ptr callback_ptr, void *user_data); + +/** + * @fn int bluetooth_hid_deinit(void) + * @brief Initialize HID service and register the callback + * + * This function is a synchronous call. + * + * @return HID_ERROR_NONE - Success \n + * HID_ERROR_NOT_INITIALIZED - Not Initialiezed \n + * + * @remark None + * + */ +int bluetooth_hid_deinit(void); + + +/** + * @fn int bluetooth_hid_connect(hid_device_address_t *device_address) + * + * @brief Connect the HID device in the peer + * + * This function is a asynchronous call. + * The HID connect request is responded by BLUETOOTH_HID_CONNECTED event. + * + * @return HID_ERROR_NONE - Success \n + * HID_ERROR_INVALID_PARAM - Invalid parameter \n + * HID_ERROR_NOT_INITIALIZED - Internal Error \n + * HID_ERROR_NOT_ENABLED - Not enabled \n + * HID_ERROR_INTERNAL - Not enabled \n + * HID_ERROR_NOT_PAIRED - Not enabled \n + * HID_ERROR_CONNECTION_FAILED - Connection Fail \n + * + * @exception None + * @param[in] device_address This indicates an address of the device with which the pairing + * should be initiated + * @remark None + */ +int bluetooth_hid_connect(hid_device_address_t *device_address); + +/** + * @fn int bluetooth_hid_disconnect(hid_device_address_t *device_address) + * + * @brief Disconnect the HID device in the peer + * + * This function is a asynchronous call. + * The HID connect request is responded by BLUETOOTH_HID_DISCONNECTED event. + * + * @return HID_ERROR_NONE - Success \n + * HID_ERROR_INVALID_PARAM - Invalid parameter \n + * HID_ERROR_NOT_INITIALIZED - Internal Error \n + * HID_ERROR_NOT_ENABLED - Not enabled \n + * HID_ERROR_INTERNAL - Not enabled \n + * HID_ERROR_NOT_PAIRED - Not enabled \n + * HID_ERROR_CONNECTION_FAILED - Connection Fail \n + * + * @exception None + * @param[in] device_address This indicates an address of the device with which the pairing + * should be initiated + * @remark None + */ +int bluetooth_hid_disconnect(hid_device_address_t *device_address); + + +#ifdef __cplusplus +} +#endif +#endif /* __BLUETOOTH_HID_API_H */ diff --git a/include/bluetooth-media-control.h b/include/bluetooth-media-control.h new file mode 100644 index 0000000..48e04e0 --- /dev/null +++ b/include/bluetooth-media-control.h @@ -0,0 +1,206 @@ +/* + * bluetooth-frwk + * + *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 + * + * 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_MP_CONTROL_H_ +#define _BT_MP_CONTROL_H_ + +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus*/ + +#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) + +typedef enum { + EQUALIZER = 0x01, + REPEAT, + SHUFFLE, + SCAN, + STATUS, + POSITION +} media_player_property_type; + +typedef enum { + EQUALIZER_OFF = 0x01, + EQUALIZER_ON, + EQUALIZER_INVALID, +} media_player_equalizer_status; + +typedef enum { + REPEAT_MODE_OFF = 0x01, + REPEAT_SINGLE_TRACK, + REPEAT_ALL_TRACK, + REPEAT_GROUP, + REPEAT_INVALID, +} media_player_repeat_status; + +typedef enum { + SHUFFLE_MODE_OFF = 0x01, + SHUFFLE_ALL_TRACK, + SHUFFLE_GROUP, + SHUFFLE_INVALID, +} media_player_shuffle_status; + +typedef enum { + SCAN_MODE_OFF = 0x01, + SCAN_ALL_TRACK, + SCAN_GROUP, + 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 struct { + 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_player_settings_t; + +typedef struct { + const char *title; + const char *artist; + const char *album; + const char *genre; + unsigned int total_tracks; + unsigned int number; + unsigned int duration; +} media_metadata_attributes_t; + +typedef struct { + int event; + int result; + void *param_data; + void *user_data; +} media_event_param_t; + +typedef void (*media_cb_func_ptr)(int, media_event_param_t*, void*); + + +/** + * @fn int bluetooth_media_player_init(media_cb_func_ptr callback_ptr, void *user_data) + * @brief Initialize AVRCP service and register the callback + * + * This function is a synchronous call. + * + * @param[in] callback_ptr - Callback function (A2DP 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_player_init(media_cb_func_ptr callback_ptr, + void *user_data); + +/** + * @fn int bluetooth_media_player_deinit(void) + * @brief Deinitialize AVRCP service and register the 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_player_deinit(void); + +/** + * @fn int bluetooth_media_player_set_properties(media_player_settings_t *setting) + * @brief Notifies the remote bluetooth headset with change in music player 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 player properties + * + * @remark None + * @see None + */ +int bluetooth_media_player_set_properties( + media_player_settings_t *setting); + +/** + * @fn int bluetooth_media_player_change_property(media_player_property_type type, + * unsigned int value); + * @brief Notifies the remote bluetooth headset with change in music player 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] type - Type of the music player property + * value - Value of the property which is changed + * + * @remark None + * @see None + */ +int bluetooth_media_player_change_property( + media_player_property_type type, + unsigned int value); + +/** + * @fn int bluetooth_media_player_change_track(media_metadata_attributes_t metadata) + * @briefNotifies the remote bluetooth headset with change in media attributes of the track + * + * 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 -Meida attributes + * + * @remark None + * @see None + */ +int bluetooth_media_player_change_track( + media_metadata_attributes_t *metadata); + +#ifdef __cplusplus +} +#endif /*__cplusplus*/ + +#endif /*_BT_MP_CONTROL_H_*/ diff --git a/include/bluetooth-telephony-api.h b/include/bluetooth-telephony-api.h new file mode 100644 index 0000000..50582d1 --- /dev/null +++ b/include/bluetooth-telephony-api.h @@ -0,0 +1,345 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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 _BLUETOOTH_TELEPHONY_API_H_ +#define _BLUETOOTH_TELEPHONY_API_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus*/ + +typedef void (*bt_telephony_func_ptr)(int, void *, void *); + +#define BLUETOOTH_TELEPHONY_ERROR_NONE ((int)0) +#define BLUETOOTH_TELEPHONY_ERROR_INTERNAL \ + ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x01) +#define BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM \ + ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x02) +#define BLUETOOTH_TELEPHONY_ERROR_ALREADY_INITIALIZED \ + ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x03) +#define BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED \ + ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x04) +#define BLUETOOTH_TELEPHONY_ERROR_AUDIO_NOT_CONNECTED \ + ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x05) +#define BLUETOOTH_TELEPHONY_ERROR_NOT_ENABLED \ + ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x06) +#define BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE \ + ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x07) +#define BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED \ + ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x08) +#define BLUETOOTH_TELEPHONY_ERROR_BUSY \ + ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x09) +#define BLUETOOTH_TELEPHONY_ERROR_ALREADY_EXSIST \ + ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x0A) +#define BLUETOOTH_TELEPHONY_ERROR_NO_MEMORY \ + ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x0B) +#define BLUETOOTH_TELEPHONY_ERROR_I_O_ERROR \ + ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x0C) +#define BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED \ + ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x0D) +#define BLUETOOTH_TELEPHONY_ERROR_OPERATION_NOT_AVAILABLE \ + ((int)BLUETOOTH_TELEPHONY_ERROR_NONE - 0x0E) + +#define BT_ADDRESS_STR_LEN 18 +#define BT_ADAPTER_PATH_LEN 50 +#define BT_AUDIO_CALL_PATH_LEN 50 + +typedef struct { + int event; + int result; + void *param_data; +} telephony_event_param_t; + +typedef struct { + int callid; +} telephony_event_callid_t; + +typedef struct { + gchar *dtmf; +} telephony_event_dtmf_t; + +typedef enum { + BLUETOOTH_STATE_CONNECTED, + BLUETOOTH_STATE_PLAYING, + BLUETOOTH_STATE_DISCONNETED, +} bluetooth_headset_state_t; + +typedef enum { + BLUETOOTH_TELEPHONY_ERROR_INVALID_CHLD_INDEX, + BLUETOOTH_TELEPHONY_ERROR_BATTERY_STATUS, + BLUETOOTH_TELEPHONY_ERROR_SIGNAL_STATUS, + BLUETOOTH_TELEPHONY_ERROR_NOT_SUPPORTED, + BLUETOOTH_TELEPHONY_ERROR_APPLICATION, + BLUETOOTH_TELEPHONY_ERROR_INVALID_DTMF, +} bluetooth_telephony_error_t; + +typedef enum { + CSD_CALL_STATUS_IDLE, + CSD_CALL_STATUS_CREATE, + CSD_CALL_STATUS_COMING, + CSD_CALL_STATUS_PROCEEDING, + CSD_CALL_STATUS_MO_ALERTING, + CSD_CALL_STATUS_MT_ALERTING, + CSD_CALL_STATUS_WAITING, + CSD_CALL_STATUS_ANSWERED, + CSD_CALL_STATUS_ACTIVE, + CSD_CALL_STATUS_MO_RELEASE, + CSD_CALL_STATUS_MT_RELEASE, + CSD_CALL_STATUS_HOLD_INITIATED, + CSD_CALL_STATUS_HOLD, + CSD_CALL_STATUS_RETRIEVE_INITIATED, + CSD_CALL_STATUS_RECONNECT_PENDING, + CSD_CALL_STATUS_TERMINATED, + CSD_CALL_STATUS_SWAP_INITIATED, +} bt_telephony_call_status_t; + +#define BLUETOOTH_EVENT_TYPE_TELEPHONY_BASE (unsigned int)(0x00100) + +typedef enum { + BLUETOOTH_EVENT_TELEPHONY_ANSWER_CALL = BLUETOOTH_EVENT_TYPE_TELEPHONY_BASE, + BLUETOOTH_EVENT_TELEPHONY_RELEASE_CALL, + BLUETOOTH_EVENT_TELEPHONY_REJECT_CALL, + BLUETOOTH_EVENT_TELEPHONY_CHLD_0_RELEASE_ALL_HELD_CALL, + BLUETOOTH_EVENT_TELEPHONY_CHLD_1_RELEASE_ALL_ACTIVE_CALL, + BLUETOOTH_EVENT_TELEPHONY_CHLD_2_ACTIVE_HELD_CALL, + BLUETOOTH_EVENT_TELEPHONY_CHLD_3_MERGE_CALL, + BLUETOOTH_EVENT_TELEPHONY_CHLD_4_EXPLICIT_CALL_TRANSFER, + BLUETOOTH_EVENT_TELEPHONY_SEND_DTMF, + BLUETOOTH_EVENT_TELEPHONY_HFP_CONNECTED, + BLUETOOTH_EVENT_TELEPHONY_HFP_DISCONNECTED, + BLUETOOTH_EVENT_TELEPHONY_AUDIO_CONNECTED, + BLUETOOTH_EVENT_TELEPHONY_AUDIO_DISCONNECTED, + BLUETOOTH_EVENT_TELEPHONY_SET_SPEAKER_GAIN, + BLUETOOTH_EVENT_TELEPHONY_SET_MIC_GAIN, + BLUETOOTH_EVENT_TELEPHONY_NREC_CHANGED, +} bluetooth_telephony_event_type; + +typedef enum { + BLUETOOTH_CALL_STATE_NONE, + BLUETOOTH_CALL_STATE_CONNECTED, + BLUETOOTH_CALL_STATE_HELD, + BLUETOOTH_CALL_STATE_DIALLING, + BLUETOOTH_CALL_STATE_ALERTING, + BLUETOOTH_CALL_STATE_INCOMING, + BLUETOOTH_CALL_STATE_WAITING, + BLUETOOTH_CALL_STATE_ERROR, +} bt_telephony_call_state_t; + +typedef struct { + unsigned int call_id; + bt_telephony_call_state_t call_status; +} bt_telephony_call_status_info_t; + +/** + * @brief The function bluetooth_telephony_init is initialize telephony calls. + * + * @param[in] cb Callback function + * @param[in] user_data Data sent by application, which will be + * returned in event handler. + * @return int Zero on Success or reason for error if any. + * + */ +int bluetooth_telephony_init(bt_telephony_func_ptr cb, void *user_data); + +/** + * @brief The function bluetooth_telephony_deinit is deinitialize telephony calls. + * + * @return int Zero on Success or reason for error if any. + * + */ +int bluetooth_telephony_deinit(void); + +/** + * @brief The function bluetooth_telephony_audio_open is to open SCO channel + * + * @return int Zero on Success or reason for error if any. + * + */ +int bluetooth_telephony_audio_open(void); + +/** + * @brief The function bluetooth_telephony_audio_close is to close SCO channel. + * that the Volume on AG is changed. + * + * @return int Zero on Success or reason for error if any. + * + */ +int bluetooth_telephony_audio_close(void); + +/** + * @brief The function bluetooth_telephony_call_remote_ringing is send + * call status. + * + * @param[in] call_id Call Id. + * @return int Zero on Success or reason for error if any. + * + */ +int bluetooth_telephony_call_remote_ringing(unsigned int call_id); + +/** + * @brief The function bluetooth_telephony_call_answered is called to + * answer calls. + * + * @param[in] call_id Call Id. + * @param[in] bt_audio flag + * @return int Zero on Success or reason for error if any. + * + */ +int bluetooth_telephony_call_answered(unsigned int call_id, + unsigned int bt_audio); + +/** + * @brief The function bluetooth_telephony_call_end to end call + * + * @param[in] call_id Call Id. + * @return int Zero on Success or reason for error if any. + * + */ +int bluetooth_telephony_call_end(unsigned int call_id); + +/** + * @brief The function bluetooth_telephony_call_held to hold call + * + * @param[in] call_id Call Id. + * @return int Zero on Success or reason for error if any. + * + */ +int bluetooth_telephony_call_held(unsigned int call_id); + +/** + * @brief The function bluetooth_telephony_call_retrieved to retrieve call + * + * @param[in] call_id Call Id. + * @return int Zero on Success or reason for error if any. + * + */ +int bluetooth_telephony_call_retrieved(unsigned int call_id); + +/** + * @brief The function bluetooth_telephony_call_swapped to swap call + * + * @param[in] call_list Call info such as id and status. + * @param[in] call_count Call count. + * @return int Zero on Success or reason for error if any. + * + */ +int bluetooth_telephony_call_swapped(void *call_list, + unsigned int call_count); + +/** + * @brief The function bluetooth_telephony_set_call_status to set call status + * + * @param[in] call_list Call info such as id and status. + * @param[in] call_count Call count. + * @return int Zero on Success or reason for error if any. + * + */ +int bluetooth_telephony_set_call_status(void *call_list, + unsigned int call_count); + +/** + * @brief The function bluetooth_telephony_indicate_outgoing_call toindicate + * outgoing call. + * + * @param[in] ph_number Phone number of the outgoing call. + * @param[in] call_id Call ID. + * @param[in] bt_audio Flag. + * @return int Zero on Success or reason for error if any. + * + */ +int bluetooth_telephony_indicate_outgoing_call( + const char *ph_number, unsigned int call_id, + unsigned int bt_audio); + +/** + * @brief The function bluetooth_telephony_indicate_incoming_call to indicate + * incoming call. + * + * @param[in] call_info Call info such as id and status. + * @param[in] call_count Call count. + * @return int Zero on Success or reason for error if any. + * + */ +int bluetooth_telephony_indicate_incoming_call( + const char *ph_number, unsigned int call_id); + +/** + * @brief The function bluetooth_telephony_is_sco_connected to check + * if SCO channel is connected. + * + * @return gboolean TRUE if headset playing else FALSE. + * + */ +gboolean bluetooth_telephony_is_sco_connected(void); + +/** + * @brief The function bluetooth_telephony_is_nrec_enabled to check + * for noise reduction and echo cancelation(nrec) status + * + * @return int Zero on Success or reason for error if any. + * + */ + int bluetooth_telephony_is_nrec_enabled(gboolean *status); + +/** + * @brief This function sends request to enable voice recognition feature + * + * @return int Zero on Success or reason for error if any. + */ + int bluetooth_telephony_start_voice_recognition(void); + +/** + * @brief This function sends request to disable voice recognition feature + * + * @return int Zero on Success or reason for error if any. + */ + int bluetooth_telephony_stop_voice_recognition(void); + + +/** + * @brief The function bluetooth_telephony_get_headset_volume is called to get + * the changed Volume on AG. + * + * @param[out] speaker_gain Speaker gain. + * @return int Zero on Success or reason for error if any. + * + */ +int bluetooth_telephony_get_headset_volume(unsigned int *speaker_gain); + +/** + * @brief The function bluetooth_telephony_set_speaker_gain is called to indicate + * that the Volume on AG is changed. + * + * @param[in] speaker_gain Speaker gain. + * @return int Zero on Success or reason for error if any. + * + */ +int bluetooth_telephony_set_speaker_gain(unsigned short speaker_gain); + + +#ifdef __cplusplus +} +#endif /*__cplusplus*/ +#endif/*_BLUETOOTH_TELEPHONY_API_H_*/ diff --git a/include/bt-internal-types.h b/include/bt-internal-types.h new file mode 100644 index 0000000..2ee0568 --- /dev/null +++ b/include/bt-internal-types.h @@ -0,0 +1,264 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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_INTERNAL_TYPES_H_ +#define _BT_INTERNAL_TYPES_H_ + +#include +#include + +#include + +#include "bluetooth-api.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef enum { + BT_NO_SERVER, + BT_NATIVE_SERVER, + BT_CUSTOM_SERVER, + BT_FTP_SERVER, +} bt_server_type_t; + +typedef enum { + BT_SYNC_REQ, + BT_ASYNC_REQ +} bt_req_type_t; + +typedef enum { + BT_MANAGER_EVENT = 0x01, + BT_ADAPTER_EVENT, + BT_DEVICE_EVENT, + BT_HID_EVENT, + BT_NETWORK_EVENT, + BT_HEADSET_EVENT, + BT_AVRCP_EVENT, + BT_OPP_CLIENT_EVENT, + BT_OPP_SERVER_EVENT, + BT_RFCOMM_CLIENT_EVENT, + BT_RFCOMM_SERVER_EVENT, + BT_AGENT_EVENT, + /* Will be added */ +} bt_event_type_t; + +typedef enum { + BT_BLUEZ_SERVICE = 0x00, + BT_OBEX_SERVICE, + BT_AGENT_SERVICE, +} bt_service_type_t; + +typedef enum { + BT_RFCOMM_UUID = 0x00, + BT_RFCOMM_CHANNEL, +} bt_rfcomm_connect_type_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_HFP_AUDIO_GATEWAY_UUID "0000111f-0000-1000-8000-00805f9b34fb" +#define BT_A2DP_UUID "0000110D-0000-1000-8000-00805F9B34FB" +#define BT_AVRCP_TARGET_UUID "0000110c-0000-1000-8000-00805f9b34fb" +#define BT_OPP_UUID "00001105-0000-1000-8000-00805f9b34fb" +#define BT_FTP_UUID "00001106-0000-1000-8000-00805f9b34fb" +#define BT_SPP_UUID "00001101-0000-1000-8000-00805f9b34fb" +#define BT_HID_UUID "00001124-0000-1000-8000-00805f9b34fb" +#define BT_PAN_PANU_UUID "00001115-0000-1000-8000-00805f9b34fb" +#define BT_PAN_NAP_UUID "00001116-0000-1000-8000-00805f9b34fb" +#define BT_PAN_GN_UUID "00001117-0000-1000-8000-00805f9b34fb" + +#define BT_FUNC_BASE ((int)(0x0000)) +#define BT_FUNC_DEVICE_BASE ((int)(BT_FUNC_BASE + 0x0050)) +#define BT_FUNC_HID_BASE ((int)(BT_FUNC_DEVICE_BASE + 0x0020)) +#define BT_FUNC_NETWORK_BASE ((int)(BT_FUNC_HID_BASE + 0x0020)) +#define BT_FUNC_AUDIO_BASE ((int)(BT_FUNC_NETWORK_BASE + 0x0020)) +#define BT_FUNC_OOB_BASE ((int)(BT_FUNC_AUDIO_BASE + 0x0020)) +#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)) + +typedef enum { + BT_CHECK_ADAPTER = BT_FUNC_BASE, + BT_ENABLE_ADAPTER, + BT_DISABLE_ADAPTER, + BT_SET_DISCOVERABLE_TIME, + BT_GET_DISCOVERABLE_TIME, + BT_IGNORE_AUTO_PAIRING, + BT_GET_LOCAL_ADDRESS, + BT_GET_LOCAL_NAME, + BT_SET_LOCAL_NAME, + BT_IS_SERVICE_USED, + BT_GET_DISCOVERABLE_MODE, + BT_SET_DISCOVERABLE_MODE, + BT_START_DISCOVERY, + BT_CANCEL_DISCOVERY, + BT_IS_DISCOVERYING, + BT_GET_BONDED_DEVICES, + BT_RESET_ADAPTER, + BT_BOND_DEVICE = BT_FUNC_DEVICE_BASE, + BT_CANCEL_BONDING, + BT_UNBOND_DEVICE, + BT_SEARCH_SERVICE, + BT_CANCEL_SEARCH_SERVICE, + BT_GET_BONDED_DEVICE, + BT_SET_ALIAS, + BT_SET_AUTHORIZATION, + BT_IS_DEVICE_CONNECTED, + BT_HID_CONNECT = BT_FUNC_HID_BASE, + BT_HID_DISCONNECT, + BT_NETWORK_ACTIVATE = BT_FUNC_NETWORK_BASE, + BT_NETWORK_DEACTIVATE, + BT_NETWORK_CONNECT, + BT_NETWORK_DISCONNECT, + BT_AUDIO_CONNECT = BT_FUNC_AUDIO_BASE, + BT_AUDIO_DISCONNECT, + BT_AG_CONNECT, + BT_AG_DISCONNECT, + BT_AV_CONNECT, + BT_AV_DISCONNECT, + BT_GET_SPEAKER_GAIN, + BT_SET_SPEAKER_GAIN, + 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_OPP_PUSH_FILES = BT_FUNC_OPP_BASE, + BT_OPP_CANCEL_PUSH, + BT_OPP_IS_PUSHING_FILES, + BT_OBEX_SERVER_ALLOCATE, + BT_OBEX_SERVER_DEALLOCATE, + BT_OBEX_SERVER_IS_ACTIVATED, + BT_OBEX_SERVER_ACCEPT_CONNECTION, + BT_OBEX_SERVER_REJECT_CONNECTION, + BT_OBEX_SERVER_ACCEPT_FILE, + BT_OBEX_SERVER_REJECT_FILE, + BT_OBEX_SERVER_SET_PATH, + BT_OBEX_SERVER_SET_ROOT, + BT_OBEX_SERVER_CANCEL_TRANSFER, + BT_OBEX_SERVER_CANCEL_ALL_TRANSFERS, + BT_RFCOMM_CLIENT_CONNECT = BT_FUNC_RFCOMM_BASE, + BT_RFCOMM_CLIENT_CANCEL_CONNECT, + BT_RFCOMM_CLIENT_IS_CONNECTED, + BT_RFCOMM_SOCKET_DISCONNECT, + BT_RFCOMM_SOCKET_WRITE, + BT_RFCOMM_CREATE_SOCKET, + BT_RFCOMM_REMOVE_SOCKET, + BT_RFCOMM_LISTEN, + BT_RFCOMM_IS_UUID_AVAILABLE, + BT_RFCOMM_ACCEPT_CONNECTION, + BT_RFCOMM_REJECT_CONNECTION, + +} 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]; + unsigned int total_tracks; + unsigned int number; + unsigned int duration; +} media_metadata_t; + +#define BT_COMMON_PKG "ug-setting-bluetooth-efl" + +/* Need to convert the design ID */ +#define BT_STR_NOT_SUPPORT "Not support" + +#ifndef __TIZEN_OPEN__ +#define BT_MDM_LIMITED_VISIBLE_TIMEOUT 120 + +#define BT_STR_DISABLED_RESTRICTS \ + dgettext(BT_COMMON_PKG, "IDS_BT_BODY_SECURITY_POLICY_RESTRICTS_USE_OF_BLUETOOTH_CONNECTION") + +#define BT_STR_HANDS_FREE_RESTRICTS \ + dgettext(BT_COMMON_PKG, "IDS_BT_BODY_SECURITY_POLICY_RESTRICTS_USE_OF_BLUETOOTH_CONNECTION_TO_HANDS_FREE_FEATURES_ONLY") +#endif + +#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" + +#define BT_EVENT_SERVICE "org.projectx.bt_event" + +#define BT_ADAPTER_PATH "/org/projectx/bt/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" +#define BT_AVRCP_PATH "/org/projectx/bt/avrcp" +#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_RFCOMM_CLIENT_PATH "/org/projectx/bt/rfcomm_client" +#define BT_RFCOMM_SERVER_PATH "/org/projectx/bt/rfcomm_server" + + +#define BT_ENABLED "Enabled" +#define BT_DISABLED "Disabled" +#define BT_DISCOVERABLE_MODE_CHANGED "DiscoverableModeChanged" +#define BT_DISCOVERABLE_TIMEOUT_CHANGED "DiscoverableTimeoutChanged" +#define BT_ADAPTER_NAME_CHANGED "AdapterNameChanged" +#define BT_DISCOVERY_STARTED "DiscoveryStarted" +#define BT_DISCOVERY_FINISHED "DiscoveryFinished" +#define BT_DEVICE_FOUND "DeviceFound" +#define BT_DEVICE_CONNECTED "DeviceConnected" +#define BT_DEVICE_DISCONNECTED "DeviceDisconnected" +#define BT_BOND_CREATED "BondCreated" +#define BT_BOND_DESTROYED "BondDestroyed" +#define BT_SERVICE_SEARCHED "ServiceSearched" +#define BT_INPUT_CONNECTED "InputConnected" +#define BT_INPUT_DISCONNECTED "InputDisconnected" +#define BT_HEADSET_CONNECTED "HeadsetConnected" +#define BT_HEADSET_DISCONNECTED "HeadsetDisconnected" +#define BT_STEREO_HEADSET_CONNECTED "StereoHeadsetConnected" +#define BT_STEREO_HEADSET_DISCONNECTED "StereoHeadsetDisconnected" +#define BT_SCO_CONNECTED "ScoConnected" +#define BT_SCO_DISCONNECTED "ScoDisconnected" +#define BT_SPEAKER_GAIN "SpeakerGain" +#define BT_MICROPHONE_GAIN "MicrophoneGain" +#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_STARTED "TransferStarted" +#define BT_TRANSFER_PROGRESS "TransferProgress" +#define BT_TRANSFER_COMPLETED "TransferCompleted" +#define BT_TRANSFER_AUTHORIZED "TransferAuthorized" +#define BT_CONNECTION_AUTHORIZED "ConnectionAuthorized" +#define BT_RFCOMM_SERVER_REMOVED "RfcommServerRemoved" +#define BT_RFCOMM_DATA_RECEIVED "RfcommDataReceived" +#define BT_RFCOMM_CONNECTED "RfcommConnected" +#define BT_RFCOMM_DISCONNECTED "RfcommDisconnected" +#define BT_MEDIA_SHUFFLE_STATUS "MediaShuffleStatus" +#define BT_MEDIA_EQUALIZER_STATUS "MediaEqualizerStatus" +#define BT_MEDIA_REPEAT_STATUS "MediaRepeatStatus" +#define BT_MEDIA_SCAN_STATUS "MediaScanStatus" + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /*_BT_INTERNAL_TYPES_H_*/ + diff --git a/packaging/bluetooth-frwk.spec b/packaging/bluetooth-frwk.spec new file mode 100644 index 0000000..e71d816 --- /dev/null +++ b/packaging/bluetooth-frwk.spec @@ -0,0 +1,118 @@ +Name: bluetooth-frwk +Summary: Bluetooth framework for BlueZ and Obexd. This package is Bluetooth framework based on BlueZ and Obexd stack. +Version: 0.2.55 +Release: 2 +Group: TO_BE/FILLED_IN +License: Apache License, Version 2.0 +Source0: %{name}-%{version}.tar.gz + +BuildRequires: pkgconfig(aul) +BuildRequires: pkgconfig(dbus-glib-1) +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(syspopup-caller) +BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(libxml-2.0) +BuildRequires: pkgconfig(dbus-1) +BuildRequires: pkgconfig(utilX) +BuildRequires: pkgconfig(libprivilege-control) +BuildRequires: pkgconfig(status) +BuildRequires: cmake + +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig + +%description +Bluetooth framework for BlueZ and Obexd. This package is Bluetooth framework based on BlueZ and Obexd stack. + This package contains API set for BT GAP, BT SDP, and BT RFCOMM. + + +%package devel +Summary: Bluetooth framework for BlueZ and Obexd +Group: TO_BE/FILLED +Requires: %{name} = %{version}-%{release} + +%description devel +This package is development files for Bluetooth framework based on BlueZ and Obexd stack. +This package contains API set for BT GAP, BT SDP, and BT RFCOMM. + +%package service +Summary: Bluetooth Service daemon +Group: TO_BE/FILLED +Requires: %{name} = %{version}-%{release} + +%description service +This package is Bluetooth Service daemon to manage BT services. + +%package core +Summary: Bluetooth Core daemon +Group: TO_BE/FILLED +Requires: %{name} = %{version}-%{release} + +%description core +This package is Bluetooth core daemon to manage activation / deactivation. + +%prep +%setup -q + + +%build +export CFLAGS+=" -fpie" +export LDFLAGS+=" -Wl,--rpath=/usr/lib -Wl,--as-needed -Wl,--unresolved-symbols=ignore-in-shared-libs -pie" + +cmake . -DCMAKE_INSTALL_PREFIX=/usr + +make + +%install +rm -rf %{buildroot} +%make_install + +mkdir -p %{buildroot}%{_sysconfdir}/rc.d/rc3.d/ +mkdir -p %{buildroot}%{_sysconfdir}/rc.d/rc5.d/ +ln -s %{_sysconfdir}/rc.d/init.d/bluetooth-frwk-service %{buildroot}%{_sysconfdir}/rc.d/rc3.d/S80bluetooth-frwk-service +ln -s %{_sysconfdir}/rc.d/init.d/bluetooth-frwk-service %{buildroot}%{_sysconfdir}/rc.d/rc5.d/S80bluetooth-frwk-service + +mkdir -p %{buildroot}%{_libdir}/systemd/system/multi-user.target.wants +install -m 0644 bt-service/bluetooth-frwk-service.service %{buildroot}%{_libdir}/systemd/system/ +ln -s ../bluetooth-frwk-service.service %{buildroot}%{_libdir}/systemd/system/multi-user.target.wants/bluetooth-frwk-service.service + + +%post +vconftool set -tf int db/bluetooth/status "0" -g 6520 +vconftool set -tf int file/private/bt-service/flight_mode_deactivated "0" -g 6520 -i +vconftool set -tf string memory/bluetooth/sco_headset_name "" -g 6520 -i +vconftool set -tf int memory/bluetooth/device "0" -g 6520 -i +vconftool set -tf int memory/bluetooth/btsco "0" -g 6520 -i + +%postun -p /sbin/ldconfig + +%files +%defattr(-, root, root) +%{_libdir}/libbluetooth-api.so.* + +%files devel +%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 +%{_libdir}/pkgconfig/bluetooth-api.pc +%{_libdir}/libbluetooth-api.so + +%files service +%defattr(-, root, root) +%{_sysconfdir}/rc.d/init.d/bluetooth-frwk-service +%{_sysconfdir}/rc.d/rc3.d/S80bluetooth-frwk-service +%{_sysconfdir}/rc.d/rc5.d/S80bluetooth-frwk-service +%{_datadir}/dbus-1/services/org.projectx.bt.service +%{_bindir}/bt-service +%{_libdir}/systemd/system/multi-user.target.wants/bluetooth-frwk-service.service +%{_libdir}/systemd/system/bluetooth-frwk-service.service +%attr(0666,-,-) /opt/var/lib/bluetooth/auto-pair-blacklist + +%files core +%defattr(-, root, root) +%{_datadir}/dbus-1/services/org.projectx.bt_core.service +%{_bindir}/bt-core diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..8c7b767 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,38 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(bluetooth-frwk-test C) + +SET(SRCS bluetooth-frwk-test.c) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) + +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) + +#ADD_SUBDIRECTORY(media-control) +#ADD_SUBDIRECTORY(telephony) diff --git a/test/bluetooth-frwk-test.c b/test/bluetooth-frwk-test.c new file mode 100644 index 0000000..0fbe95c --- /dev/null +++ b/test/bluetooth-frwk-test.c @@ -0,0 +1,1634 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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-frwk-test.c + * @brief This is the source file for bluetooth framework test suite. + */ + +#include +#include +#include +#include +#include + +#include "bluetooth-api.h" +#include "bluetooth-hid-api.h" +#include "bluetooth-audio-api.h" + + +bluetooth_device_address_t searched_device = {{0}}; + +#define TC_TIMEOUT 30000 + +#define BT_DEFAULT_DEV_NAME "SLP-BT-TEST-TARGET" +#define DISCOVER_TIMEOUT 20 +#define DISCOVER_CANCEL_INTERVAL 3 + +#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 +int client_fd = 0; +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; +int selection; +int hdp_manual_mode = 1; +const char * rfcomm_test_uuid_spp ="00001101-0000-1000-8000-00805F9B34FB"; +const char * rfcomm_test_uuid_dun = "00001103-0000-1000-8000-00805F9B34FB"; +const char * rfcomm_test_uuid_custom ="26b2831b-2c2d-4f9c-914a-c0ab142351b7"; + + +GMainLoop *main_loop = NULL; +static int timeout_status = 0; + +int current_transfer_id = 0; + +typedef struct { + bluetooth_device_address_t address; + bt_oob_data_t oob_data; +} oob_data_t; + +oob_data_t g_local_oob_data; +oob_data_t g_remote_oob_data; + + +typedef struct +{ + const char *tc_name; + int tc_code; +} tc_table_t; + +void bt_event_callback(int event, bluetooth_event_param_t* param, void *user_data); +void bt_hid_event_callback(int event, hid_event_param_t* param, void *user_data); +void bt_audio_event_callback(int event, bt_audio_event_param_t* param, void *user_data); + + +tc_table_t tc_table[] = +{ + {"bluetooth_register_callback" , 1}, + {"bluetooth_unregister_callback" , 2}, + {"bluetooth_enable_adapter" , 3}, + {"bluetooth_disable_adapter" , 4}, + {"bluetooth_check_adapter" , 5}, + {"bluetooth_get_local_address" , 6}, + {"bluetooth_get_local_name" , 7}, + {"bluetooth_set_local_name" , 8}, + {"bluetooth_is_service_used" , 9}, + {"bluetooth_get_discoverable_mode" , 10}, + {"bluetooth_set_discoverable_mode(CONNECTABLE)" , 11}, + {"bluetooth_set_discoverable_mode(GENERAL_DISCOVERABLE)" , 12}, + {"bluetooth_set_discoverable_mode(TIME_LIMITED_DISCOVERABLE)" , 13}, + {"bluetooth_start_discovery" , 14}, + {"bluetooth_cancel_discovery" , 15}, + {"bluetooth_is_discovering" , 16}, + {"bluetooth_get_bonded_device_list" , 17}, + {"bluetooth_bond_device" , 18}, + {"bluetooth_cancel_bonding" , 19}, + {"bluetooth_unbond_device" , 20}, + {"bluetooth_get_bonded_device" , 21}, + {"bluetooth_set_alias" , 22}, + {"bluetooth_authorize_device (TRUE)" , 23}, + {"bluetooth_authorize_device (FALSE)" , 24}, + {"bluetooth_search_service" , 25}, + {"bluetooth_cancel_service_search" , 26}, + {"bluetooth_is_device_connected" , 27}, + + {"bluetooth_audio_init" , 29}, + {"bluetooth_audio_deinit" , 30}, + {"bluetooth_audio_connect" , 31}, + {"bluetooth_audio_disconnect" , 32}, + {"bluetooth_ag_connect" , 33}, + {"bluetooth_ag_disconnect" , 34}, + {"bluetooth_av_connect" , 35}, + {"bluetooth_av_disconnect" , 36}, + {"bluetooth_ag_get_headset_volume" , 37}, + {"bluetooth_ag_set_speaker_gain" , 38}, + + {"bluetooth_oob_read_local_data" , 39}, + {"bluetooth_oob_add_remote_data" , 40}, + {"bluetooth_oob_remove_remote_data" , 41}, + + {"bluetooth_opc_init" , 42}, + {"bluetooth_opc_deinit" , 43}, + {"bluetooth_opc_push_files" , 44}, + {"bluetooth_opc_cancel_push" , 45}, + {"bluetooth_opc_session_is_exist" , 46}, + + {"bluetooth_network_activate_server" , 47}, + {"bluetooth_network_deactivate_server" , 48}, + {"bluetooth_network_connect" , 49}, + {"bluetooth_network_disconnect" , 50}, + + {"bluetooth_obex_server_init" , 51}, + {"bluetooth_obex_server_deinit" , 52}, + {"bluetooth_obex_server_init_without_agent" , 53}, + {"bluetooth_obex_server_deinit_without_agent" , 54}, + {"bluetooth_obex_server_is_activated" , 55}, + {"bluetooth_obex_server_accept_connection" , 56}, + {"bluetooth_obex_server_reject_connection" , 57}, + {"bluetooth_obex_server_accept_authorize" , 58}, + {"bluetooth_obex_server_reject_authorize" , 59}, + {"bluetooth_obex_server_set_destination_path" , 60}, + {"bluetooth_obex_server_set_root" , 61}, + {"bluetooth_obex_server_cancel_transfer" , 62}, + {"bluetooth_obex_server_cancel_all_transfers" , 63}, + + {"bluetooth_hid_init" , 65}, + {"bluetooth_hid_deinit" , 66}, + {"bluetooth_hid_connect" , 67}, + {"bluetooth_hid_disconnect" , 68}, + + {"bluetooth_rfcomm_connect" , 70}, + {"bluetooth_rfcomm_disconnect (cancel)" , 71}, + {"bluetooth_rfcomm_disconnect" , 72}, + {"bluetooth_rfcomm_write" , 73}, + {"bluetooth_rfcomm_is_client_connected" , 74}, + + {"bluetooth_rfcomm_create_socket" , 80}, + {"bluetooth_rfcomm_create_socket (Custom UUID)" , 81}, + {"bluetooth_rfcomm_remove_socket" , 82}, + {"bluetooth_rfcomm_listen_and_accept" , 83}, + {"bluetooth_rfcomm_listen (OSP)" , 84}, + {"bluetooth_rfcomm_server_disconnect" , 85}, + {"bluetooth_rfcomm_is_server_uuid_available" , 86}, + {"bluetooth_rfcomm_accept_connection" , 87}, + {"bluetooth_rfcomm_reject_connection" , 88}, + + +#if 0 + {"bluetooth_rfcomm_is_server_uuid_available" , 26}, + + {"bluetooth_hdp_activate" , 30}, + {"bluetooth_hdp_deactivate" , 31}, + {"bluetooth_hdp_connect" , 32}, + {"bluetooth_hdp_disconnect" , 33}, + {"bluetooth_hdp_send_data" , 34}, + + {"bluetooth_opc_init" , 35}, + {"bluetooth_opc_push_file" , 36}, + {"bluetooth_opc_cancel_push" , 37}, + {"bluetooth_opc_deinit" , 38}, + {"bluetooth_obex_server_init" , 39}, + {"bluetooth_obex_server_deinit" , 40}, + {"bluetooth_obex_server_accept_authorize" , 41}, + {"bluetooth_obex_server_reject_authorize" , 42}, + {"bluetooth_is_supported" , 43}, + {"bluetooth_opc_session_is_exist" , 46}, + {"bluetooth_obex_server_is_activated" , 47}, + {"bluetooth_obex_server_cancel_transfer" , 48}, + + {"bluetooth_oob_read_local_data" , 50}, + {"bluetooth_oob_add_remote_data" , 51}, + {"bluetooth_oob_remove_remote_data" , 52}, + + {"bluetooth_network_activate_server" , 60}, + {"bluetooth_network_deactivate_server" , 61}, + {"bluetooth_network_connect" , 62}, + {"bluetooth_network_disconnect" , 63}, + + {"bluetooth_gatt_discover_primary_services", 64}, + {"bluetooth_gatt_discover_service_characteristics", 65}, + {"bluetooth_gatt_get_service_property", 66}, + {"bluetooth_gatt_get_characteristics_value", 67}, + {"bluetooth_gatt_set_characteristics_value", 68}, +#endif + /* -----------------------------------------*/ + {"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")); + +bluetooth_device_info_t bond_dev; +int is_bond_device = FALSE; + +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; + + switch (test_id) + { + case 0x00ff: + TC_PRT("Finished"); + g_main_loop_quit(main_loop); + break; + + case 1: + TC_PRT("TC : %s", tc_table[0].tc_name); + bluetooth_register_callback(bt_event_callback, NULL); + if (ret < 0) + { + TC_PRT("%s failed with [0x%04x]", tc_table[0].tc_name, ret); + tc_result(TC_FAIL, 1); + } + break; + + case 2: + TC_PRT("TC : %s", tc_table[1].tc_name); + bluetooth_unregister_callback(); + if (ret < 0) + { + TC_PRT("%s failed with [0x%04x]", tc_table[1].tc_name, ret); + tc_result(TC_FAIL, 1); + } + break; + + case 3: + TC_PRT("TC : %s", tc_table[2].tc_name); + ret = bluetooth_enable_adapter(); + if (ret < 0) + { + TC_PRT("%s failed with [0x%04x]", tc_table[2].tc_name, ret); + tc_result(TC_FAIL, 1); + } + break; + + case 4: + TC_PRT("TC : %s", tc_table[3].tc_name); + ret = bluetooth_disable_adapter(); + if (ret < 0) + { + TC_PRT("%s failed with [0x%04x]", tc_table[3].tc_name, ret); + tc_result(TC_FAIL, 2); + } + break; + + case 5: + { + TC_PRT("TC : %s", tc_table[4].tc_name); + ret = bluetooth_check_adapter(); + TC_PRT("state: %d", ret); + break; + } + + 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) + { + TC_PRT("%s failed with [0x%04x]", tc_table[5].tc_name, ret); + } else { + TC_PRT("dev [%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]); + } + break; + } + + case 7: + { + 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) + { + TC_PRT("%s failed with [0x%04x]", tc_table[6].tc_name, ret); + } else { + TC_PRT("name: %s", local_name.name); + } + break; + } + + case 8: + { + bluetooth_device_name_t local_name = {{0}}; + 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) + { + TC_PRT("%s failed with [0x%04x]", tc_table[7].tc_name, ret); + } + break; + } + + case 9: + { + 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) + { + TC_PRT("%s failed with [0x%04x]", tc_table[8].tc_name, ret); + } else { + TC_PRT("used: %d", used); + } + break; + } + + 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) + { + TC_PRT("%s failed with [0x%04x]", tc_table[9].tc_name, ret); + } + else + { + TC_PRT("BT Get Discoverable mode [%d]", mode); + } + break; + } + + 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) + { + TC_PRT("%s failed with [0x%04x]", tc_table[10].tc_name, ret); + } + else + { + TC_PRT("BT Set Discoverable mode [%d]", mode); + } + break; + } + + 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) + { + TC_PRT("%s failed with [0x%04x]", tc_table[11].tc_name, ret); + } + else + { + TC_PRT("BT Set Discoverable mode [%d]", mode); + } + break; + } + + 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) + { + TC_PRT("%s failed with [0x%04x]", tc_table[12].tc_name, ret); + } + else + { + TC_PRT("BT Set Discoverable mode [%d]", mode); + } + break; + } + + case 14: + TC_PRT("TC : %s", tc_table[13].tc_name); + ret = bluetooth_start_discovery(0,0,0); + if (ret < 0) + { + TC_PRT("%s failed with [0x%04x]", tc_table[13].tc_name, ret); + } + break; + + case 15: + TC_PRT("TC : %s", tc_table[14].tc_name); + ret = bluetooth_cancel_discovery(); + if (ret < 0) + { + TC_PRT("%s failed with [0x%04x]", tc_table[14].tc_name, ret); + } + break; + + case 16: + { + TC_PRT("TC : %s", tc_table[15].tc_name); + ret = bluetooth_is_discovering(); + if (ret < 0) + { + TC_PRT("%s failed with [0x%04x]", tc_table[15].tc_name, ret); + } + else + { + TC_PRT("Discovering [%d]", ret); + } + break; + } + + 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); + + ret = bluetooth_get_bonded_device_list(&devinfo); + if (ret < 0) + { + TC_PRT("%s failed with [0x%04x]", tc_table[16].tc_name, ret); + } + else + { + int i; + bluetooth_device_info_t *ptr; + TC_PRT("g pointer arrary count : [%d]", devinfo->len); + + for(i=0; ilen;i++) + { + ptr = g_ptr_array_index(devinfo, i); + if(ptr != NULL) + { + TC_PRT("Name [%s]", ptr->device_name.name); + TC_PRT("Major Class [%d]", ptr->device_class.major_class); + TC_PRT("Minor Class [%d]", ptr->device_class.minor_class); + TC_PRT("Service Class [%d]", ptr->device_class.service_class); + TC_PRT("%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", 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]); + TC_PRT("\n"); + } + } + } + g_ptr_array_free(devinfo, TRUE); + + break; + } + + case 18: + { + /* Apple wireless keyboard */ + //bluetooth_device_address_t device_address={{0xE8,0x06,0x88,0x3B,0x18,0xBA}}; + //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}}; /* DO-DH79-PYUN03 */ + //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]); + + ret = bluetooth_bond_device(&device_address); + if (ret < 0) + { + TC_PRT("%s failed with [0x%04x]", tc_table[17].tc_name, ret); + } + break; + } + + + case 19: /*Cancel bonding */ + { + + TC_PRT("TC : %s", tc_table[18].tc_name); + ret = bluetooth_cancel_bonding(); + if (ret < 0) + { + TC_PRT("%s failed with [0x%04x]", tc_table[18].tc_name, ret); + } + + break; + } + + case 20: /*unbonding */ + { + 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) + { + TC_PRT("%s failed with [0x%04x]", tc_table[19].tc_name, ret); + } + + break; + } + + case 21: /*Get paired device */ + { + bluetooth_device_info_t devinfo; + bluetooth_device_address_t device_address={{0x00,0x16,0x38,0xC3,0x1F,0xD2}}; + + memset(&devinfo, 0x00, sizeof(bluetooth_device_info_t)); + + ret = bluetooth_get_bonded_device(&device_address, &devinfo); + if (ret != BLUETOOTH_ERROR_NONE) + { + TC_PRT("bluetooth_get_bonded_device failed with [%d]",ret); + } + else + { + TC_PRT("Name [%s]", devinfo.device_name.name); + TC_PRT("Major Class [%d]", devinfo.device_class.major_class); + TC_PRT("Minor Class [%d]", devinfo.device_class.minor_class); + TC_PRT("Service Class [%d]", devinfo.device_class.service_class); + TC_PRT("%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", devinfo.device_address.addr[0], devinfo.device_address.addr[1], devinfo.device_address.addr[2], devinfo.device_address.addr[3], devinfo.device_address.addr[4], devinfo.device_address.addr[5]); + } + + break; + } + + case 22: /*set alias for bonded device */ + { + 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); + break; + } + + case 23: + { + 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); + break; + } + case 24: + { + 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); + break; + } + case 25: + { + 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); + break; + } + 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); + break; + } + case 27: + { + 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); + + TC_PRT("connected : %d", connected); + 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); + break; + } + 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); + break; + } + case 31: + { + /* MW600 */ + //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); + break; + } + case 32: + { + /* MW600 */ + //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); + break; + } + case 33: + { + /* 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); + break; + } + case 34: + { + /* 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); + break; + } + case 35: + { + /* 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); + break; + } + case 36: + { + /* 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); + break; + } + case 37: + { + unsigned int volume = 0; + + ret = bluetooth_ag_get_headset_volume(&volume); + if (ret < 0) + TC_PRT("failed with [0x%04x]", ret); + + TC_PRT("volume: %d", volume); + break; + } + case 38: + { + ret = bluetooth_ag_set_speaker_gain(10); + if (ret < 0) + TC_PRT("failed with [0x%04x]", ret); + break; + } + + case 39: + { + if (bluetooth_oob_read_local_data(&g_local_oob_data.oob_data)) + TC_PRT("ERROR in bluetooth_oob_read_local_data\n"); + else { + TC_PRT("SUCESS in bluetooth_oob_read_local_data\n"); + TC_PRT("hash = [%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X" + "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X]\n", + g_local_oob_data.oob_data.hash[0], + g_local_oob_data.oob_data.hash[1], + g_local_oob_data.oob_data.hash[2], + g_local_oob_data.oob_data.hash[3], + g_local_oob_data.oob_data.hash[4], + g_local_oob_data.oob_data.hash[5], + g_local_oob_data.oob_data.hash[6], + g_local_oob_data.oob_data.hash[7], + g_local_oob_data.oob_data.hash[8], + g_local_oob_data.oob_data.hash[9], + g_local_oob_data.oob_data.hash[10], + g_local_oob_data.oob_data.hash[11], + g_local_oob_data.oob_data.hash[12], + g_local_oob_data.oob_data.hash[13], + g_local_oob_data.oob_data.hash[14], + g_local_oob_data.oob_data.hash[15]); + + TC_PRT("randomizer = [%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X" + "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X]\n", + g_local_oob_data.oob_data.randomizer[0], + g_local_oob_data.oob_data.randomizer[1], + g_local_oob_data.oob_data.randomizer[2], + g_local_oob_data.oob_data.randomizer[3], + g_local_oob_data.oob_data.randomizer[4], + g_local_oob_data.oob_data.randomizer[5], + g_local_oob_data.oob_data.randomizer[6], + g_local_oob_data.oob_data.randomizer[7], + g_local_oob_data.oob_data.randomizer[8], + g_local_oob_data.oob_data.randomizer[9], + g_local_oob_data.oob_data.randomizer[10], + g_local_oob_data.oob_data.randomizer[11], + g_local_oob_data.oob_data.randomizer[12], + g_local_oob_data.oob_data.randomizer[13], + g_local_oob_data.oob_data.randomizer[14], + g_local_oob_data.oob_data.randomizer[15]); + + 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); + } + break; + } + case 40: + { + 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); + + if (bluetooth_oob_add_remote_data(&g_local_oob_data.address, + &g_local_oob_data.oob_data)) + TC_PRT("ERROR in bluetooth_oob_add_remote_data\n"); + else + TC_PRT(" bluetooth_oob_add_remote_data SUCCESS\n"); + break; + } + + case 41: + { + if (bluetooth_oob_remove_remote_data(&g_local_oob_data.address)) + TC_PRT("ERROR in bluetooth_oob_remove_remote_data\n"); + else + TC_PRT(" bluetooth_oob_remove_remote_data SUCCESS\n"); + break; + } + case 42: + { + bluetooth_opc_init(); + break; + } + case 43: + { + bluetooth_opc_deinit(); + break; + } + case 44: + { + bluetooth_device_address_t remote_address = {{0}}; + + /* Grey dongle */ + remote_address.addr[0] = 0x00; remote_address.addr[1] = 0x02; remote_address.addr[2] = 0x70; + remote_address.addr[3] = 0x2B; remote_address.addr[4] = 0xD3; remote_address.addr[5]= 0xAF; + + char *files[5] = {NULL}; + + files[0] = "/opt/media/Images/image1.jpg"; +// files[1] = "/opt/media/Images/image2.jpg"; +// files[2] = "/opt/media/Images/image3.jpg"; + bluetooth_opc_push_files(&remote_address, files); + break; + } + case 45: + { + bluetooth_opc_cancel_push(); + break; + } + case 46: + { + gboolean exist; + exist = bluetooth_opc_session_is_exist(); + TC_PRT("exist: %d", exist); + break; + } + case 47: + { + bluetooth_network_activate_server(); + break; + } + case 48: + { + bluetooth_network_deactivate_server(); + break; + } + case 49: + { + bluetooth_device_address_t device_address = {{0x00, 0x02, 0xA2, 0x14, 0x40, 0x51}}; + bluetooth_network_connect(&device_address, BLUETOOTH_NETWORK_NAP_ROLE, NULL); + break; + } + case 50: + { + bluetooth_device_address_t device_address = {{0x00, 0x02, 0xA2, 0x14, 0x40, 0x51}}; + bluetooth_network_disconnect(&device_address); + break; + } + case 51: + { + bluetooth_obex_server_init("/opt/media/Downloads"); + break; + } + case 52: + { + bluetooth_obex_server_deinit(); + break; + } + case 53: + { + bluetooth_obex_server_init_without_agent("/opt/media/Downloads"); + break; + } + case 54: + { + bluetooth_obex_server_deinit_without_agent(); + break; + } + case 55: + { + bluetooth_obex_server_is_activated(); + break; + } + case 56: + { + bluetooth_obex_server_accept_connection(); + TC_PRT(" bluetooth_obex_server_accept_connection SUCCESS\n"); + break; + } + case 57: + { + bluetooth_obex_server_reject_connection(); + break; + } + case 58: + { + bluetooth_obex_server_accept_authorize("abc"); + break; + } + case 59: + { + bluetooth_obex_server_reject_authorize(); + break; + } + case 60: + { + bluetooth_obex_server_set_destination_path("/opt/media"); + break; + } + case 61: + { + bluetooth_obex_server_set_root("/opt/media"); + break; + } + case 62: + { + bluetooth_obex_server_cancel_transfer(0); + break; + } + case 63: + { + bluetooth_obex_server_cancel_all_transfers(); + break; + } + + case 65: + { + ret = bluetooth_hid_init(bt_hid_event_callback, NULL); + if (ret < 0) + TC_PRT("Failed with [0x%04x]", ret); + break; + } + case 66: + { + ret = bluetooth_hid_deinit(); + if (ret < 0) + TC_PRT("Failed with [0x%04x]", ret); + break; + } + case 67: + { + /* Apple wireless keyboard */ + hid_device_address_t device_address={{0xE8,0x06,0x88,0x3B,0x18,0xBA}}; + + ret = bluetooth_hid_connect(&device_address); + if (ret < 0) + TC_PRT("Failed with [0x%04x]", ret); + break; + } + case 68: + { + /* Apple wireless keyboard */ + hid_device_address_t device_address={{0xE8,0x06,0x88,0x3B,0x18,0xBA}}; + + ret = bluetooth_hid_disconnect(&device_address); + if (ret < 0) + TC_PRT("Failed with [0x%04x]", ret); + break; + } + + case 70: + { + bluetooth_device_address_t device_address = {{0x00, 0x02, 0x2F, 0x92, 0x7B, 0xF5}}; + + ret = bluetooth_rfcomm_connect(&device_address, rfcomm_test_uuid_spp); + //ret = bluetooth_rfcomm_connect(&device_address, "1"); + + if (ret < 0) + TC_PRT("Failed with [0x%04x]", ret); + break; + } + case 71: + { + ret = bluetooth_rfcomm_disconnect(-1); + + if (ret < 0) + TC_PRT("Failed with [0x%04x]", ret); + break; + } + case 72: + { + ret = bluetooth_rfcomm_disconnect(g_ret_client_fd1); + + if (ret < 0) + TC_PRT("Failed with [0x%04x]", ret); + break; + } + case 73: + { + ret = bluetooth_rfcomm_write(g_ret_client_fd1, "123456789 12345", 20); + + if (ret < 0) + TC_PRT("Failed with [0x%04x]", ret); + break; + } + case 74: + { + gboolean is_connected; + + is_connected = bluetooth_rfcomm_is_client_connected(); + + TC_PRT("Connected: %d", is_connected); + break; + } + case 80: + { + ret = bluetooth_rfcomm_create_socket(rfcomm_test_uuid_spp); + if (ret < 0) + TC_PRT("Failed with [0x%04x]", ret); + + TC_PRT("Returned FD = %d", ret); + server_fd = ret; + break; + } + case 81: + { + ret = bluetooth_rfcomm_create_socket(rfcomm_test_uuid_custom); + if (ret < 0) + TC_PRT("Failed with [0x%04x]", ret); + + TC_PRT("Returned FD = %d", ret); + server_fd = ret; + break; + } + case 82: + { + ret = bluetooth_rfcomm_remove_socket(server_fd); + if (ret < 0) + TC_PRT("Failed with [0x%04x]", ret); + break; + } + case 83: /*Listen and accept */ + { + + ret = bluetooth_rfcomm_listen_and_accept(server_fd, 1); + if (ret < 0) + TC_PRT("Failed with [0x%04x]", ret); + + TC_PRT("result = %d", ret); + break; + } + case 84: /*Listen */ + { + + ret = bluetooth_rfcomm_listen(server_fd, 1); + if (ret < 0) + TC_PRT("Failed with [0x%04x]", ret); + + TC_PRT("result = %d", ret); + break; + } + case 85: + { + ret = bluetooth_rfcomm_server_disconnect(client_fd); + if (ret < 0) + TC_PRT("Failed with [0x%04x]", ret); + break; + } + case 86: + { + gboolean available; + + available = bluetooth_rfcomm_is_server_uuid_available(rfcomm_test_uuid_spp); + + TC_PRT("available: %d", available); + break; + } + case 87: + { + ret = bluetooth_rfcomm_accept_connection(server_fd, &client_fd); + if (ret < 0) + TC_PRT("Failed with [0x%04x]", ret); + TC_PRT("client fd: %d", client_fd); + break; + } + case 88: + { + ret = bluetooth_rfcomm_reject_connection(server_fd); + if (ret < 0) + TC_PRT("Failed with [0x%04x]", ret); + 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); + } +} + +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(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); + TC_PRT("bt event callback 0x%04x", event); + + + +} + +void bt_audio_event_callback(int event, bt_audio_event_param_t* param, void *user_data) +{ + TC_PRT(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); + TC_PRT("bt event callback 0x%04x", event); + + + +} + +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_ENABLED: + TC_PRT("BLUETOOTH_EVENT_ENABLED, result [0x%04x]", param->result); + break; + + case BLUETOOTH_EVENT_DISABLED: + TC_PRT("BLUETOOTH_EVENT_DISABLED, result [0x%04x]", param->result); + break; + + case BLUETOOTH_EVENT_LOCAL_NAME_CHANGED: + TC_PRT("BLUETOOTH_EVENT_LOCAL_NAME_CHANGED, result [0x%04x]", param->result); + if (param->result == BLUETOOTH_ERROR_NONE) + { + bluetooth_device_name_t *local_name = (bluetooth_device_name_t *)param->param_data; + tc_result(TC_PASS, 6); + TC_PRT("Changed Name : [%s]", local_name->name); + } + else + { + tc_result(TC_FAIL, 6); + } + break; + + + case BLUETOOTH_EVENT_DISCOVERY_STARTED: + TC_PRT("BLUETOOTH_EVENT_DISCOVERY_STARTED, result [0x%04x]", param->result); + 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; + memcpy(&searched_device, &device_info->device_address, sizeof(bluetooth_device_address_t)); + 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; + memcpy(&searched_device, &device_info->device_address, sizeof(bluetooth_device_address_t)); + 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_DISCOVERABLE_MODE_CHANGED: + { + int *mode = (int *)param->param_data; + TC_PRT("BT_DISCOVERABLE_MODE_CHANGED, result [0x%04x]", param->result); + TC_PRT("mode [%d]", *mode); + break; + } + case BLUETOOTH_EVENT_DISCOVERABLE_TIMEOUT_CHANGED: + { + int *timeout = (int *)param->param_data; + TC_PRT("BLUETOOTH_EVENT_DISCOVERABLE_TIMEOUT_CHANGED, result [0x%04x]", param->result); + TC_PRT("timeout [%d]", *timeout); + break; + } + case BLUETOOTH_EVENT_BONDING_FINISHED: + { + TC_PRT("BLUETOOTH_EVENT_BONDING_FINISHED, result [0x%04x]", param->result); + if (param->result >= BLUETOOTH_ERROR_NONE) + { + bluetooth_device_info_t *device_info = NULL; + tc_result(TC_PASS, 12); + device_info = (bluetooth_device_info_t *)param->param_data; + if (device_info == NULL) + break; + + TC_PRT("dev [%s] [%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X] mjr[%#x] min[%#x] srv[%#x]", 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], \ + device_info->device_class.major_class, device_info->device_class.minor_class, device_info->device_class.service_class); + } + else + { + tc_result(TC_FAIL, 12); + } + break; + } + + case BLUETOOTH_EVENT_BONDED_DEVICE_FOUND: + { + // bluetooth_get_bonded_device_list is changed as synchronous API. This event is not used any more. + // 2011.01.06 +#if 0 +// int i = 0; + TC_PRT("BLUETOOTH_EVENT_BONDED_DEVICE_FOUND, result [0x%04x]", param->result); + if (param->result >= BLUETOOTH_ERROR_NONE) + { + ///tc_result(TC_PASS, 15); + bluetooth_device_info_t * bt_dev_info= (bluetooth_device_info_t*)param->param_data; + + TC_PRT("Dev Name = %s, Dev add = %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X, COD (major,minor,service)= 0x%x:%x:%x\n", bt_dev_info->device_name.name, + bt_dev_info->device_address.addr[0], bt_dev_info->device_address.addr[1], bt_dev_info->device_address.addr[2], \ + bt_dev_info->device_address.addr[3], bt_dev_info->device_address.addr[4], bt_dev_info->device_address.addr[5], \ + bt_dev_info->device_class.major_class, bt_dev_info->device_class.minor_class, bt_dev_info->device_class.service_class); + + } + else + if(param->result == BLUETOOTH_ERROR_END_OF_DEVICE_LIST) /*End of the Device found indication*/ + { + tc_result(TC_PASS, 15); + TC_PRT("*****<>***** "); + } + else + { + tc_result(TC_FAIL, 15); + TC_PRT("*****API failed ***** "); + } + break; +#endif + } + case BLUETOOTH_EVENT_SERVICE_SEARCHED: + { + int i = 0; + TC_PRT("BLUETOOTH_EVENT_SERVICE_SEARCHED, result [0x%04x]", param->result); + if (param->result >= BLUETOOTH_ERROR_NONE) + { + tc_result(TC_PASS, 18); + bt_sdp_info_t * bt_sdp_info=param->param_data; + + TC_PRT("Dev add = %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", + bt_sdp_info->device_addr.addr[0], bt_sdp_info->device_addr.addr[1], bt_sdp_info->device_addr.addr[2], \ + bt_sdp_info->device_addr.addr[3], bt_sdp_info->device_addr.addr[4], bt_sdp_info->device_addr.addr[5]); + + TC_PRT("Supported service list:\n"); + for(i=0; iservice_index; i++) + TC_PRT("[%#x]\n", bt_sdp_info->service_list_array[i]); + + } + else + { + tc_result(TC_FAIL, 18); + } + break; + } + case BLUETOOTH_EVENT_RFCOMM_DATA_RECEIVED: + { + TC_PRT("BLUETOOTH_EVENT_RFCOMM_DATA_RECEIVED, result [0x%04x]", param->result); + bluetooth_rfcomm_received_data_t *rx_data = param->param_data; + printf("\n FD = %d \nBuffer len = %d ", rx_data->socket_fd, rx_data->buffer_size); + if (rx_data->buffer_size < sizeof(oob_data_t)) + TC_PRT("Complete oob data is not recivedn"); + else + memcpy(&g_remote_oob_data,rx_data->buffer, sizeof(oob_data_t)); + //tc_result(TC_PASS, 21); + break; + } + case BLUETOOTH_EVENT_RFCOMM_CONNECTED: + { + bluetooth_rfcomm_connection_t *con_ind = (bluetooth_rfcomm_connection_t *)param->param_data; + TC_PRT("BLUETOOTH_EVENT_RFCOMM_CONNECTED, result [0x%04x], fd = %d, device add = 0x%X:%X:%X:%X:%X:%X, Role = %s", param->result, + con_ind->socket_fd, + con_ind->device_addr.addr[0], con_ind->device_addr.addr[1], con_ind->device_addr.addr[2], + con_ind->device_addr.addr[3], con_ind->device_addr.addr[4], con_ind->device_addr.addr[5], + (con_ind->device_role == RFCOMM_ROLE_SERVER)? "SERVER":"CLIENT"); + //tc_result(TC_PASS, 22); + if((con_ind->device_role == RFCOMM_ROLE_CLIENT) && (con_ind->socket_fd > 0)) + { + g_ret_client_fd1 = con_ind->socket_fd; + } + + if((con_ind->device_role == RFCOMM_ROLE_SERVER) && (con_ind->socket_fd > 0)) + { + client_fd = con_ind->socket_fd; + } + + break; + } + case BLUETOOTH_EVENT_RFCOMM_DISCONNECTED: + { + bluetooth_rfcomm_disconnection_t *disconnection_ind = (bluetooth_rfcomm_disconnection_t *)param->param_data;; + TC_PRT("BLUETOOTH_EVENT_RFCOMM_DISCONNECTED, result [0x%04x] Fd = %d, device add = 0x%X:%X:%X:%X:%X:%X\n", param->result, disconnection_ind->socket_fd, + disconnection_ind->device_addr.addr[0], disconnection_ind->device_addr.addr[1], disconnection_ind->device_addr.addr[2], + disconnection_ind->device_addr.addr[3], disconnection_ind->device_addr.addr[4], disconnection_ind->device_addr.addr[5] ); + //tc_result(TC_PASS, 22); + break; + } + case BLUETOOTH_EVENT_NETWORK_SERVER_CONNECTED: + { + bluetooth_network_device_info_t *dev_info = (bluetooth_network_device_info_t *)param->param_data; + + TC_PRT("BLUETOOTH_EVENT_RFCOMM_DISCONNECTED, result [0x%04x]", param->result); + TC_PRT("interface name: %s", dev_info->interface_name); + + TC_PRT("device add = %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", + dev_info->device_address.addr[0], dev_info->device_address.addr[1], dev_info->device_address.addr[2], + dev_info->device_address.addr[3], dev_info->device_address.addr[4], dev_info->device_address.addr[5] ); + break; + } + case BLUETOOTH_EVENT_NETWORK_SERVER_DISCONNECTED: + { + bluetooth_network_device_info_t *dev_info = (bluetooth_network_device_info_t *)param->param_data; + + TC_PRT("BLUETOOTH_EVENT_RFCOMM_DISCONNECTED, result [0x%04x]", param->result); + TC_PRT("interface name: %s", dev_info->interface_name); + + TC_PRT("device add = %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", + dev_info->device_address.addr[0], dev_info->device_address.addr[1], dev_info->device_address.addr[2], + dev_info->device_address.addr[3], dev_info->device_address.addr[4], dev_info->device_address.addr[5] ); + break; + } + + case BLUETOOTH_EVENT_HDP_CONNECTED: + { + bt_hdp_connected_t *conn_ind = (bt_hdp_connected_t *)param->param_data; + + TC_PRT("BLUETOOTH_EVENT_HDP_CONNECTED, Result = %s\n", (param->result == 0)? "BLUETOOTH_ERROR_NONE": "BLUETOOTH_ERROR_XXXX"); + TC_PRT("App handler = %s, channel id = %d, type = %s", conn_ind->app_handle, conn_ind->channel_id, (conn_ind->type == HDP_QOS_RELIABLE)? "Reliable":"Streaming"); + TC_PRT("device add = %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", + conn_ind->device_address.addr[0], conn_ind->device_address.addr[1], conn_ind->device_address.addr[2], + conn_ind->device_address.addr[3], conn_ind->device_address.addr[4], conn_ind->device_address.addr[5] ); + + g_ret_client_fd1 = conn_ind->channel_id; + break; + } + + case BLUETOOTH_EVENT_HDP_DISCONNECTED: + { + bt_hdp_disconnected_t *dis_ind = (bt_hdp_disconnected_t *)param->param_data; + + TC_PRT("BLUETOOTH_EVENT_HDP_DISCONNECTED, Result = %s\n", (param->result == 0)? "BLUETOOTH_ERROR_NONE": "BLUETOOTH_ERROR_XXXX"); + TC_PRT("Channel = %d, Add = device add = %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", dis_ind->channel_id, + dis_ind->device_address.addr[0], dis_ind->device_address.addr[1], dis_ind->device_address.addr[2], + dis_ind->device_address.addr[3], dis_ind->device_address.addr[4], dis_ind->device_address.addr[5]); + break; + } + + case BLUETOOTH_EVENT_HDP_DATA_RECEIVED: + { + bt_hdp_data_ind_t *data_ind = (bt_hdp_data_ind_t *)param->param_data; + + TC_PRT("BLUETOOTH_EVENT_HDP_DATA_RECEIVED, Result = %s\n", (param->result == 0)? "BLUETOOTH_ERROR_NONE": "BLUETOOTH_ERROR_XXXX"); + TC_PRT("Data received from channel id = %d and size =%d, buff =[%s]\n", data_ind->channel_id, data_ind->size, data_ind->buffer); + + break; + } + + case BLUETOOTH_EVENT_OPC_CONNECTED: + TC_PRT("BLUETOOTH_EVENT_OPC_CONNECTED"); + break; + + case BLUETOOTH_EVENT_OPC_DISCONNECTED: + TC_PRT("BLUETOOTH_EVENT_OPC_DISCONNECTED"); + break; + case BLUETOOTH_EVENT_OPC_TRANSFER_STARTED: + { + TC_PRT("BLUETOOTH_EVENT_OPC_TRANSFER_STARTED"); + if (param->param_data) { + bt_opc_transfer_info_t *info = param->param_data; + TC_PRT("file %s", info->filename); + TC_PRT("size %ld", info->size); + } + break; + } + case BLUETOOTH_EVENT_OPC_TRANSFER_PROGRESS: + { + TC_PRT("BLUETOOTH_EVENT_OPC_TRANSFER_PROGRESS"); + break; + } + case BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE: + { + TC_PRT("BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE"); + bt_opc_transfer_info_t *info = param->param_data; + TC_PRT("file %s", info->filename); + TC_PRT("size %ld", info->size); + break; + } + + case BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_AUTHORIZE: + TC_PRT("BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_AUTHORIZE"); + break; + + case BLUETOOTH_EVENT_OBEX_SERVER_CONNECTION_AUTHORIZE: + TC_PRT("BLUETOOTH_EVENT_OBEX_SERVER_CONNECTION_AUTHORIZE"); + break; + + case BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_STARTED: + TC_PRT("BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_STARTED"); + bt_obex_server_transfer_info_t *info = param->param_data; + current_transfer_id = info->transfer_id; + break; + + case BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_PROGRESS: + TC_PRT("BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_PROGRESS"); + break; + + case BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_COMPLETED: + TC_PRT("BLUETOOTH_EVENT_OBEX_SERVER_TRANSFER_COMPLETED"); + break; + +#if 0 + case BLUETOOTH_EVENT_GATT_PRIM_SVC_DISCOVERED: + { + TC_PRT("BLUETOOTH_EVENT_GATT_PRIM_SVC_DISCOVERED"); + bt_gatt_handle_info_t *prim_svc = param->param_data; + int i; + + if (prim_svc == NULL) { + TC_PRT("prim_svc is NULL"); + break; + } + + for (i = 0; i < prim_svc->count; i++) { + TC_PRT("prim_svc[%d] = %s\n", i, prim_svc->handle[i]); + } + + break; + } + + case BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED: + { + TC_PRT("BLUETOOTH_EVENT_GATT_SVC_CHAR_DISCOVERED"); + bt_gatt_discovered_char_t *svc_char = param->param_data; + int i = 0; + + if (svc_char == NULL) { + TC_PRT("svc_char is NULL"); + break; + } + + if (svc_char->service_handle != NULL) { + TC_PRT("svc_char->service_handle %s \n", svc_char->service_handle); + } + + for (i = 0; i < svc_char->handle_info.count; i++) { + TC_PRT("svc_char.handle_info.handle[%d] = %s\n", i, svc_char->handle_info.handle[i]); + } + + break; + } + + case BLUETOOTH_EVENT_GATT_SVC_PROP_RECEIVED: + { + TC_PRT("BLUETOOTH_EVENT_GATT_SVC_PROP_RECEIVED"); + bt_gatt_service_property_t *svc_pty = param->param_data; + int i; + + if (svc_pty == NULL) { + TC_PRT("char_pty is NULL \n"); + break; + } + + if (svc_pty->service_handle != NULL) { + TC_PRT("svc_pty->service_handle %s \n", svc_pty->service_handle); + } + + if (svc_pty->uuid != NULL) { + TC_PRT("svc_pty->uuid %s \n", svc_pty->uuid); + } + + for (i = 0; i < svc_pty->handle_info.count; i++) { + TC_PRT("svc_char[%d] = %s\n", i, svc_pty->handle_info.handle[i]); + } + + break; + } + + case BLUETOOTH_EVENT_GATT_CHAR_PROP_RECEIVED: + { + TC_PRT("BLUETOOTH_EVENT_GATT_CHAR_PROP_RECEIVED"); + bt_gatt_char_property_t *char_pty = param->param_data; + int i = 0; + + if (char_pty->char_handle != NULL) { + TC_PRT("char_pty->char_handle %s \n", char_pty->char_handle); + } + + if (char_pty->uuid != NULL) { + TC_PRT("char_pty->uuid %s \n", char_pty->uuid); + } + + if (char_pty == NULL) { + TC_PRT("char_pty is NULL \n"); + break; + } + + if (char_pty->name != NULL) { + TC_PRT("char_pty->name %s \n", char_pty->name); + } + + if (char_pty->description != NULL) { + TC_PRT("char_pty->description %s \n", char_pty->description); + } + + if (char_pty->val != NULL) { + TC_PRT("char_pty->val_len %d \n", char_pty->val_len); + + for (i = 0; i < char_pty->val_len; i ++) + TC_PRT("char_pty->val %02x \n", char_pty->val[i]); + } + + break; + } +#endif + 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; + memset(buf, 0, sizeof(buf)); + + if(g_io_channel_read_chars(chan, buf, sizeof(buf), + &len, NULL) == G_IO_STATUS_ERROR) { + TC_PRT("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(void) +{ + startup(); + + GIOChannel *key_io; + key_io=g_io_channel_unix_new(fileno(stdin)); + + g_io_channel_set_encoding(key_io, NULL, NULL); + g_io_channel_set_flags(key_io, G_IO_FLAG_NONBLOCK, NULL); + + 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 new file mode 100644 index 0000000..657f5c2 --- /dev/null +++ b/test/media-control/CMakeLists.txt @@ -0,0 +1,32 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(bluetooth-media-control-test C) + +SET(SRCS bluetooth-media-control-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/media-control/bluetooth-media-control-test.c b/test/media-control/bluetooth-media-control-test.c new file mode 100644 index 0000000..8456323 --- /dev/null +++ b/test/media-control/bluetooth-media-control-test.c @@ -0,0 +1,233 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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-media-control.h" + +#include +#include +#include + +#define MEDIA_ATRRIBUTE_LENGTH 256 + +media_player_settings_t player_settings = {0x00, 0x00, 0x00, 0x00, 0x01, 1111}; +media_metadata_attributes_t metadata = {"Test Track", "Chethan", "TNC", "Tumkur", 1, 1, 14400}; + +void static __choose_metadata_settings(void) +{ + int cmd; + media_metadata_attributes_t metadata = {0,}; + + while (1) { + printf("\nPlease enter\n"); + printf("\t0: return to main menu\n"); + printf("\t1: Meta data settings\n"); + printf("\tEnter your choice [ ]\b\b"); + + scanf("%d", &cmd); + + switch (cmd) { + case 0: + return; + case 1: /* Title */ + + metadata.title = calloc(1, MEDIA_ATRRIBUTE_LENGTH); + metadata.artist = calloc(1, MEDIA_ATRRIBUTE_LENGTH); + metadata.album = calloc(1, MEDIA_ATRRIBUTE_LENGTH); + metadata.genre = calloc(1, MEDIA_ATRRIBUTE_LENGTH); + + printf("Enter the \"Track\" name\n"); + scanf("%s", (char *)metadata.title); + + printf(" Enter the \"Artist\" name\n"); + scanf("%s", (char *)metadata.artist); + + printf(" Enter the \"Album\" name\n"); + scanf("%s", (char *)metadata.album); + + printf(" Enter the \"Genre\" \n"); + scanf("%s", (char *)metadata.genre); + + printf(" Enter the \" Totol NumberOfTracks\" \n"); + scanf("%d", &metadata.total_tracks); + + printf(" Enter the \" Track Number\" \n"); + scanf("%d", &metadata.number); + + printf(" Enter the \"Duration\" \n"); + scanf("%d", &metadata.duration); + break; + default: + break; + } + bluetooth_media_player_change_track(&metadata); + + if (NULL != metadata.title) { + free((void *)metadata.title); + metadata.title = NULL; + } + if (NULL != metadata.artist) { + free((void *)metadata.artist); + metadata.artist = NULL; + } + if (NULL != metadata.album) { + free((void *)metadata.album); + metadata.album = NULL; + } + if (NULL != metadata.genre) { + free((void *)metadata.genre); + metadata.genre = NULL; + } + } +} + +void static __choose_player_settings(void) +{ + int cmd; + media_player_property_type type; + + while (1) { + printf("\nPlease choose player settings\n"); + printf("\t0: return to main menu\n"); + printf("\t1. Equalizer\n"); + printf("\t2. Repeat\n"); + printf("\t3. Shuffle\n"); + printf("\t4. Scan \n"); + printf("\t5. Status \n"); + printf("\t6. Position \n"); + printf("\tEnter your choice [ ]\b\b"); + + scanf("%d", &cmd); + + switch (cmd) { + case 0: + return; + case 1: /* Equalizer */ + { + printf("Possible Values - EQUALIZER_OFF = 0x00 and EQUALIZER_ON = 0x01,\n"); + scanf("%d", &player_settings.equalizer); + type = EQUALIZER; + + bluetooth_media_player_change_property(type, + (unsigned int)player_settings.equalizer); + + break; + } + case 2: /*Repeat */ + { + printf(" Possible Values - REPEAT_MODE_OFF = 0x00, REPEAT_SINGLE_TRACK = 0x01 , \ + REPEAT_ALL_TRACK = 0x02, REPEAT_GROUP = 0x03\n"); + scanf("%d", &player_settings.repeat); + type = REPEAT; + + bluetooth_media_player_change_property(type, + (unsigned int)player_settings.repeat); + break; + } + case 3: /* Shuffle */ + { + printf(" Possible Values - SHUFFLE_MODE_OFF = 0x00, SHUFFLE_ALL_TRACK = 0x01 , \ + SHUFFLE_GROUP = 0x02\n"); + scanf("%d", &player_settings.shuffle); + type = SHUFFLE; + + bluetooth_media_player_change_property(type, + (unsigned int)player_settings.shuffle); + break; + } + case 4: /* Scan */ + { + printf(" Possible Values - SCAN_MODE_OFF = 0x00, SCAN_ALL_TRACK = 0x01 , \ + SCAN_GROUP = 0x02\n"); + scanf("%d", &player_settings.scan); + type = SCAN; + + bluetooth_media_player_change_property(type, + (unsigned int)player_settings.scan); + break; + } + case 5: /* Status */ + { + printf(" Possible Values - STATUS_PLAYING = 0x00, STATUS_STOPPED = 0x01 , \ + STATUS_PAUSED = 0x02,STATUS_FORWARD_SEEK = 0x03 \ + STATUS_REVERSE_SEEK = 0x04 STATUS_ERROR = 0x05\n"); + scanf("%d", &player_settings.status); + type = STATUS; + + bluetooth_media_player_change_property(type, + (unsigned int)player_settings.status); + break; + } + case 6: /* Position */ + { + printf("Enter the possible value: "); + scanf("%d", &player_settings.position); + type = POSITION; + + bluetooth_media_player_change_property(type, + player_settings.position); + break; + } + default: + break; + } + } +} + +int main() +{ + GMainLoop *agent_loop; + int cmd; + + g_type_init(); + agent_loop = g_main_loop_new(NULL, FALSE); + + printf("MP-AV test application started\n"); + while (1) { + printf("\n\n\t0. Exit\n"); + printf("\t1. bluetooth_media_player_property_changed\n"); + printf("\t2. bluetooth_media_player_track_changed\n"); + printf("\tEnter your choice [ ]\b\b"); + + scanf("%d", &cmd); + + switch (cmd) { + case 0: /* exit the application */ + { + exit(0); + break; + } + case 1: + { + __choose_player_settings(); + break; + } + case 2: + { + __choose_metadata_settings(); + break; + } + } + } + printf("gmain loop enter\n"); + g_main_loop_run(agent_loop); + printf("gmain loop leave\n"); + return 0; +} diff --git a/test/telephony/CMakeLists.txt b/test/telephony/CMakeLists.txt new file mode 100644 index 0000000..9b2b225 --- /dev/null +++ b/test/telephony/CMakeLists.txt @@ -0,0 +1,32 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(bluetooth-telephony-test C) + +SET(SRCS bluetooth-telephony-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/telephony/bluetooth-telephony-test.c b/test/telephony/bluetooth-telephony-test.c new file mode 100644 index 0000000..33ac589 --- /dev/null +++ b/test/telephony/bluetooth-telephony-test.c @@ -0,0 +1,337 @@ +/* + * bluetooth-frwk + * + * 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 + * + * 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-telephony-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 "9986008917" + +typedef struct { + const char *tc_name; + int tc_code; +} tc_table_t; + +tc_table_t tc_table[] = { + /*Telephony Application*/ + {"bluetooth_telephony_init", 70}, + {"bluetooth_telephony_deinit", 71}, + {"Indicate Outgoing call", 72}, + {"Indicate Incoming call", 73}, + {"Speaker to Headphone", 74}, + {"Headphone to Speaker ", 75}, + {"Call End/Release", 76}, + {"Call Hold", 77}, + {"bluetooth_telephony_call_remote_ringing", 78}, + {"Call Swap", 79}, + {"Call Reject", 80}, + {"Call Answer", 81}, + {"Is SCO channel connected", 82}, + {"Voice Recognition Start", 83}, + {"Voice Recognition Stop", 84}, + {"NREC Status", 85}, + /* -----------------------------------------*/ + {"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 telephony_event_handler(int event, void *data, void *user_data) +{ + telephony_event_param_t *bt_event; + + if (data == NULL) + return; + bt_event = data; + + TC_PRT("AG event : [0x%04x]", event); + + switch (event) { + case BLUETOOTH_EVENT_TELEPHONY_ANSWER_CALL: + TC_PRT("BLUETOOTH_EVENT_TELEPHONY_ANSWER_CALL"); + bluetooth_telephony_call_answered(DEFAULT_CALL_ID, TRUE); + break; + + case BLUETOOTH_EVENT_TELEPHONY_RELEASE_CALL: + TC_PRT("BLUETOOTH_EVENT_TELEPHONY_RELEASE_CALL"); + bluetooth_telephony_call_end(DEFAULT_CALL_ID); + break; + + case BLUETOOTH_EVENT_TELEPHONY_REJECT_CALL: + bluetooth_telephony_call_end(DEFAULT_CALL_ID); + break; + + case BLUETOOTH_EVENT_TELEPHONY_CHLD_0_RELEASE_ALL_HELD_CALL: + TC_PRT("BLUETOOTH_EVENT_TELEPHONY_CHLD_0_RELEASE_ALL_HELD_CALL"); + break; + + case BLUETOOTH_EVENT_TELEPHONY_CHLD_1_RELEASE_ALL_ACTIVE_CALL: + TC_PRT("BLUETOOTH_EVENT_TELEPHONY_CHLD_1_RELEASE_ALL_ACTIVE_CALL"); + break; + + case BLUETOOTH_EVENT_TELEPHONY_CHLD_3_MERGE_CALL: + TC_PRT("BLUETOOTH_EVENT_TELEPHONY_CHLD_3_MERGE_CALL"); + break; + + case BLUETOOTH_EVENT_TELEPHONY_CHLD_2_ACTIVE_HELD_CALL: + TC_PRT("BLUETOOTH_EVENT_TELEPHONY_CHLD_2_ACTIVE_HELD_CALL"); + break; + + case BLUETOOTH_EVENT_TELEPHONY_SEND_DTMF: + TC_PRT("BLUETOOTH_EVENT_TELEPHONY_SEND_DTMF"); + break; + + case BLUETOOTH_EVENT_TELEPHONY_CHLD_4_EXPLICIT_CALL_TRANSFER: + TC_PRT("BLUETOOTH_EVENT_TELEPHONY_CHLD_4_EXPLICIT_CALL_TRANSFER"); + break; + + case BLUETOOTH_EVENT_TELEPHONY_NREC_CHANGED: { + gboolean *nrec; + TC_PRT("BLUETOOTH_EVENT_TELEPHONY_NREC_CHANGED"); + nrec = bt_event->param_data; + TC_PRT("NREC status = [%d]", *nrec); + break; + } + + default: + break; + } +} + +int test_input_callback(void *data) +{ + int test_id = (int)data; + + switch (test_id) { + case 0x00ff: + TC_PRT("Finished"); + g_main_loop_quit(main_loop); + break; + + case 70: + bluetooth_telephony_init(telephony_event_handler, NULL); + break; + case 71: + bluetooth_telephony_deinit(); + break; + + case 72: + bluetooth_telephony_indicate_outgoing_call( + TEST_NUMBER, DEFAULT_CALL_ID, TRUE); + break; + case 73: + bluetooth_telephony_indicate_incoming_call( + TEST_NUMBER, TRUE); + break; + case 74: + bluetooth_telephony_audio_open(); + break; + case 75: + bluetooth_telephony_audio_close(); + break; + case 76: + bluetooth_telephony_call_end(DEFAULT_CALL_ID); + break; + case 77: + bluetooth_telephony_call_held(DEFAULT_CALL_ID); + break; + case 78: + bluetooth_telephony_call_remote_ringing( + DEFAULT_CALL_ID); + break; + case 79: + TC_PRT("bluetooth_telephony_call_swapped \n"); + break; + case 80: + bluetooth_telephony_call_answered( + DEFAULT_CALL_ID, FALSE); + break; + case 81: + bluetooth_telephony_call_answered( + DEFAULT_CALL_ID, TRUE); + break; + + case 82: { + int state; + + state = bluetooth_telephony_is_sco_connected(); + + TC_PRT("State = %d \n", state); + break; + } + + case 83: { + int ret = 0; + + TC_PRT("**********************\n"); + TC_PRT(" PLEASE SPEAK \n"); + TC_PRT("**********************\n"); + + ret = bluetooth_telephony_start_voice_recognition(); + + if (ret == BLUETOOTH_TELEPHONY_ERROR_NONE) { + TC_PRT("No error\n"); + bluetooth_telephony_audio_open(); + } + break; + } + + case 84: { + TC_PRT("Rcognition finished \n"); + bluetooth_telephony_audio_close(); + bluetooth_telephony_stop_voice_recognition(); + break; + } + + case 85: { + int ret; + gboolean status = FALSE; + + ret = bluetooth_telephony_is_nrec_enabled(&status); + + if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) + TC_PRT("Error getting NREC Status\n"); + + TC_PRT("NREC status = %d\n", status); + 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); + } +} + +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) +{ + 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; +} -- 2.7.4