[Adapt Audio HAL] Add HFP Audio Gateway Role 86/88086/1
authorAnupam Roy <anupam.r@samsung.com>
Tue, 13 Sep 2016 08:39:26 +0000 (14:09 +0530)
committerAnupam Roy <anupam.r@samsung.com>
Tue, 13 Sep 2016 08:39:26 +0000 (14:09 +0530)
This patch primarily adds following:-
 a/ HFP (AG Role)) Android HAL interface
 b/ Implement Bluez based HF Init, Connect, Disconnect methods
 c/ Implemnt HF Connection event handlers

Change-Id: I71980f182e5ffd7888597b44769a121daa533325
Signed-off-by: Anupam Roy <anupam.r@samsung.com>
17 files changed:
bt-oal/bluez_hal/CMakeLists.txt
bt-oal/bluez_hal/hardware/bt_hf.h [new file with mode: 0644]
bt-oal/bluez_hal/hardware/src [new file with mode: 0644]
bt-oal/bluez_hal/inc/bt-hal-msg.h
bt-oal/bluez_hal/inc/bt-hal-utils.h
bt-oal/bluez_hal/inc/bt-hal.h
bt-oal/bluez_hal/src/bt-hal-agent.c
bt-oal/bluez_hal/src/bt-hal-bluetooth.c
bt-oal/bluez_hal/src/bt-hal-device-dbus-handler.c
bt-oal/bluez_hal/src/bt-hal-event-receiver.c
bt-oal/bluez_hal/src/bt-hal-event-receiver.h
bt-oal/bluez_hal/src/bt-hal-hf-dbus-handler.c [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-hf-dbus-handler.h [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-hf.c [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-hf.h [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-internal.h
bt-oal/bluez_hal/src/bt-hal-utils.c

index 8f25e7b..3b965da 100644 (file)
@@ -13,6 +13,8 @@ SET(SRCS
 ./src/bt-hal-hidhost.c
 ./src/bt-hal-av.c
 ./src/bt-hal-av-dbus-handler.c
+./src/bt-hal-hf.c
+./src/bt-hal-hf-dbus-handler.c
 ./src/bt-hal-hid-dbus-handler.c
 ./src/bt-hal-socket.c
 ./src/bt-hal-rfcomm-dbus-handler.c
diff --git a/bt-oal/bluez_hal/hardware/bt_hf.h b/bt-oal/bluez_hal/hardware/bt_hf.h
new file mode 100644 (file)
index 0000000..d4c3326
--- /dev/null
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * 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 ANDROID_INCLUDE_BT_HF_H
+#define ANDROID_INCLUDE_BT_HF_H
+
+__BEGIN_DECLS
+
+/* AT response code - OK/Error */
+typedef enum {
+    BTHF_AT_RESPONSE_ERROR = 0,
+    BTHF_AT_RESPONSE_OK
+} bthf_at_response_t;
+
+typedef enum {
+    BTHF_CONNECTION_STATE_DISCONNECTED = 0,
+    BTHF_CONNECTION_STATE_CONNECTING,
+    BTHF_CONNECTION_STATE_CONNECTED,
+    BTHF_CONNECTION_STATE_SLC_CONNECTED,
+    BTHF_CONNECTION_STATE_DISCONNECTING
+} bthf_connection_state_t;
+
+typedef enum {
+    BTHF_AUDIO_STATE_DISCONNECTED = 0,
+    BTHF_AUDIO_STATE_CONNECTING,
+    BTHF_AUDIO_STATE_CONNECTED,
+    BTHF_AUDIO_STATE_DISCONNECTING
+} bthf_audio_state_t;
+
+typedef enum {
+    BTHF_VR_STATE_STOPPED = 0,
+    BTHF_VR_STATE_STARTED
+} bthf_vr_state_t;
+
+typedef enum {
+    BTHF_VOLUME_TYPE_SPK = 0,
+    BTHF_VOLUME_TYPE_MIC
+} bthf_volume_type_t;
+
+/* Noise Reduction and Echo Cancellation */
+typedef enum
+{
+    BTHF_NREC_STOP,
+    BTHF_NREC_START
+} bthf_nrec_t;
+
+/* WBS codec setting */
+typedef enum
+{
+   BTHF_WBS_NONE,
+   BTHF_WBS_NO,
+   BTHF_WBS_YES
+}bthf_wbs_config_t;
+
+/* CHLD - Call held handling */
+typedef enum
+{
+    BTHF_CHLD_TYPE_RELEASEHELD,              // Terminate all held or set UDUB("busy") to a waiting call
+    BTHF_CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD, // Terminate all active calls and accepts a waiting/held call
+    BTHF_CHLD_TYPE_HOLDACTIVE_ACCEPTHELD,    // Hold all active calls and accepts a waiting/held call
+    BTHF_CHLD_TYPE_ADDHELDTOCONF,            // Add all held calls to a conference
+} bthf_chld_type_t;
+
+/** Callback for connection state change.
+ *  state will have one of the values from BtHfConnectionState
+ */
+typedef void (* bthf_connection_state_callback)(bthf_connection_state_t state, bt_bdaddr_t *bd_addr);
+
+/** Callback for audio connection state change.
+ *  state will have one of the values from BtHfAudioState
+ */
+typedef void (* bthf_audio_state_callback)(bthf_audio_state_t state, bt_bdaddr_t *bd_addr);
+
+/** Callback for VR connection state change.
+ *  state will have one of the values from BtHfVRState
+ */
+typedef void (* bthf_vr_cmd_callback)(bthf_vr_state_t state, bt_bdaddr_t *bd_addr);
+
+/** Callback for answer incoming call (ATA)
+ */
+typedef void (* bthf_answer_call_cmd_callback)(bt_bdaddr_t *bd_addr);
+
+/** Callback for disconnect call (AT+CHUP)
+ */
+typedef void (* bthf_hangup_call_cmd_callback)(bt_bdaddr_t *bd_addr);
+
+/** Callback for disconnect call (AT+CHUP)
+ *  type will denote Speaker/Mic gain (BtHfVolumeControl).
+ */
+typedef void (* bthf_volume_cmd_callback)(bthf_volume_type_t type, int volume, bt_bdaddr_t *bd_addr);
+
+/** Callback for dialing an outgoing call
+ *  If number is NULL, redial
+ */
+typedef void (* bthf_dial_call_cmd_callback)(char *number, bt_bdaddr_t *bd_addr);
+
+/** Callback for sending DTMF tones
+ *  tone contains the dtmf character to be sent
+ */
+typedef void (* bthf_dtmf_cmd_callback)(char tone, bt_bdaddr_t *bd_addr);
+
+/** Callback for enabling/disabling noise reduction/echo cancellation
+ *  value will be 1 to enable, 0 to disable
+ */
+typedef void (* bthf_nrec_cmd_callback)(bthf_nrec_t nrec, bt_bdaddr_t *bd_addr);
+
+/** Callback for AT+BCS and event from BAC
+ *  WBS enable, WBS disable
+ */
+typedef void (* bthf_wbs_callback)(bthf_wbs_config_t wbs, bt_bdaddr_t *bd_addr);
+
+/** Callback for call hold handling (AT+CHLD)
+ *  value will contain the call hold command (0, 1, 2, 3)
+ */
+typedef void (* bthf_chld_cmd_callback)(bthf_chld_type_t chld, bt_bdaddr_t *bd_addr);
+
+/** Callback for CNUM (subscriber number)
+ */
+typedef void (* bthf_cnum_cmd_callback)(bt_bdaddr_t *bd_addr);
+
+/** Callback for indicators (CIND)
+ */
+typedef void (* bthf_cind_cmd_callback)(bt_bdaddr_t *bd_addr);
+
+/** Callback for operator selection (COPS)
+ */
+typedef void (* bthf_cops_cmd_callback)(bt_bdaddr_t *bd_addr);
+
+/** Callback for call list (AT+CLCC)
+ */
+typedef void (* bthf_clcc_cmd_callback) (bt_bdaddr_t *bd_addr);
+
+/** Callback for unknown AT command recd from HF
+ *  at_string will contain the unparsed AT string
+ */
+typedef void (* bthf_unknown_at_cmd_callback)(char *at_string, bt_bdaddr_t *bd_addr);
+
+/** Callback for keypressed (HSP) event.
+ */
+typedef void (* bthf_key_pressed_cmd_callback)(bt_bdaddr_t *bd_addr);
+
+/** BT-HF callback structure. */
+typedef struct {
+    /** set to sizeof(BtHfCallbacks) */
+    size_t      size;
+    bthf_connection_state_callback  connection_state_cb;
+    bthf_audio_state_callback       audio_state_cb;
+    bthf_vr_cmd_callback            vr_cmd_cb;
+    bthf_answer_call_cmd_callback   answer_call_cmd_cb;
+    bthf_hangup_call_cmd_callback   hangup_call_cmd_cb;
+    bthf_volume_cmd_callback        volume_cmd_cb;
+    bthf_dial_call_cmd_callback     dial_call_cmd_cb;
+    bthf_dtmf_cmd_callback          dtmf_cmd_cb;
+    bthf_nrec_cmd_callback          nrec_cmd_cb;
+    bthf_wbs_callback               wbs_cb;
+    bthf_chld_cmd_callback          chld_cmd_cb;
+    bthf_cnum_cmd_callback          cnum_cmd_cb;
+    bthf_cind_cmd_callback          cind_cmd_cb;
+    bthf_cops_cmd_callback          cops_cmd_cb;
+    bthf_clcc_cmd_callback          clcc_cmd_cb;
+    bthf_unknown_at_cmd_callback    unknown_at_cmd_cb;
+    bthf_key_pressed_cmd_callback   key_pressed_cmd_cb;
+} bthf_callbacks_t;
+
+/** Network Status */
+typedef enum
+{
+    BTHF_NETWORK_STATE_NOT_AVAILABLE = 0,
+    BTHF_NETWORK_STATE_AVAILABLE
+} bthf_network_state_t;
+
+/** Service type */
+typedef enum
+{
+    BTHF_SERVICE_TYPE_HOME = 0,
+    BTHF_SERVICE_TYPE_ROAMING
+} bthf_service_type_t;
+
+typedef enum {
+    BTHF_CALL_STATE_ACTIVE = 0,
+    BTHF_CALL_STATE_HELD,
+    BTHF_CALL_STATE_DIALING,
+    BTHF_CALL_STATE_ALERTING,
+    BTHF_CALL_STATE_INCOMING,
+    BTHF_CALL_STATE_WAITING,
+    BTHF_CALL_STATE_IDLE
+} bthf_call_state_t;
+
+typedef enum {
+    BTHF_CALL_DIRECTION_OUTGOING = 0,
+    BTHF_CALL_DIRECTION_INCOMING
+} bthf_call_direction_t;
+
+typedef enum {
+    BTHF_CALL_TYPE_VOICE = 0,
+    BTHF_CALL_TYPE_DATA,
+    BTHF_CALL_TYPE_FAX
+} bthf_call_mode_t;
+
+typedef enum {
+    BTHF_CALL_MPTY_TYPE_SINGLE = 0,
+    BTHF_CALL_MPTY_TYPE_MULTI
+} bthf_call_mpty_type_t;
+
+typedef enum {
+    BTHF_CALL_ADDRTYPE_UNKNOWN = 0x81,
+    BTHF_CALL_ADDRTYPE_INTERNATIONAL = 0x91
+} bthf_call_addrtype_t;
+
+/** Represents the standard BT-HF interface. */
+typedef struct {
+
+    /** set to sizeof(BtHfInterface) */
+    size_t          size;
+    /**
+     * Register the BtHf callbacks
+     */
+    bt_status_t (*init)( bthf_callbacks_t* callbacks, int max_hf_clients);
+
+    /** connect to headset */
+    bt_status_t (*connect)( bt_bdaddr_t *bd_addr );
+
+    /** dis-connect from headset */
+    bt_status_t (*disconnect)( bt_bdaddr_t *bd_addr );
+
+    /** create an audio connection */
+    bt_status_t (*connect_audio)( bt_bdaddr_t *bd_addr );
+
+    /** close the audio connection */
+    bt_status_t (*disconnect_audio)( bt_bdaddr_t *bd_addr );
+
+    /** start voice recognition */
+    bt_status_t (*start_voice_recognition)( bt_bdaddr_t *bd_addr );
+
+    /** stop voice recognition */
+    bt_status_t (*stop_voice_recognition)( bt_bdaddr_t *bd_addr );
+
+    /** volume control */
+    bt_status_t (*volume_control) (bthf_volume_type_t type, int volume, bt_bdaddr_t *bd_addr );
+
+    /** Combined device status change notification */
+    bt_status_t (*device_status_notification)(bthf_network_state_t ntk_state, bthf_service_type_t svc_type, int signal,
+                           int batt_chg);
+
+    /** Response for COPS command */
+    bt_status_t (*cops_response)(const char *cops, bt_bdaddr_t *bd_addr );
+
+    /** Response for CIND command */
+    bt_status_t (*cind_response)(int svc, int num_active, int num_held, bthf_call_state_t call_setup_state,
+                                 int signal, int roam, int batt_chg, bt_bdaddr_t *bd_addr );
+
+    /** Pre-formatted AT response, typically in response to unknown AT cmd */
+    bt_status_t (*formatted_at_response)(const char *rsp, bt_bdaddr_t *bd_addr );
+
+    /** ok/error response
+     *  ERROR (0)
+     *  OK    (1)
+     */
+    bt_status_t (*at_response) (bthf_at_response_t response_code, int error_code, bt_bdaddr_t *bd_addr );
+
+    /** response for CLCC command
+     *  Can be iteratively called for each call index
+     *  Call index of 0 will be treated as NULL termination (Completes response)
+     */
+    bt_status_t (*clcc_response) (int index, bthf_call_direction_t dir,
+                                bthf_call_state_t state, bthf_call_mode_t mode,
+                                bthf_call_mpty_type_t mpty, const char *number,
+                                bthf_call_addrtype_t type, bt_bdaddr_t *bd_addr );
+
+    /** notify of a call state change
+     *  Each update notifies
+     *    1. Number of active/held/ringing calls
+     *    2. call_state: This denotes the state change that triggered this msg
+     *                  This will take one of the values from BtHfCallState
+     *    3. number & type: valid only for incoming & waiting call
+    */
+    bt_status_t (*phone_state_change) (int num_active, int num_held, bthf_call_state_t call_setup_state,
+                                       const char *number, bthf_call_addrtype_t type);
+
+    /** Closes the interface. */
+    void  (*cleanup)( void );
+
+    /** configureation for the SCO codec */
+    bt_status_t (*configure_wbs)( bt_bdaddr_t *bd_addr ,bthf_wbs_config_t config );
+} bthf_interface_t;
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_BT_HF_H */
diff --git a/bt-oal/bluez_hal/hardware/src b/bt-oal/bluez_hal/hardware/src
new file mode 100644 (file)
index 0000000..fd1103b
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:  Anupam Roy <anupam.r@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __BT_HAL_HF_SRC_H__
+#define __BT_HAL_HF_SRC_H__
+
+#include <stdint.h>
+#include <glib.h>
+#include <unistd.h>
+#include <dlog.h>
+#include <stdio.h>
+
+bthf_interface_t *bt_get_hf_interface(void);
+
+#endif //__BT_HAL_HF_SRC_H__
index ef35182..868e02e 100644 (file)
@@ -292,5 +292,29 @@ struct hal_ev_a2dp_audio_config {
         uint32_t sample_rate;
         uint8_t  channel_count;
 } __attribute__((packed));
+
+/* HandsFree Headers */
+#define HAL_EV_HANDSFREE_CONN_STATE_DISCONNECTED        0x00
+#define HAL_EV_HANDSFREE_CONN_STATE_CONNECTING          0x01
+#define HAL_EV_HANDSFREE_CONN_STATE_CONNECTED           0x02
+#define HAL_EV_HANDSFREE_CONN_STATE_SLC_CONNECTED       0x03
+#define HAL_EV_HANDSFREE_CONN_STATE_DISCONNECTING       0x04
+
+#define HAL_EV_HANDSFREE_CONN_STATE             0x91
+struct hal_ev_handsfree_conn_state {
+        uint8_t state;
+        uint8_t bdaddr[6];
+} __attribute__((packed));
+
+#define HAL_EV_HANDSFREE_AUDIO_STATE_DISCONNECTED       0x00
+#define HAL_EV_HANDSFREE_AUDIO_STATE_CONNECTING         0x01
+#define HAL_EV_HANDSFREE_AUDIO_STATE_CONNECTED          0x02
+#define HAL_EV_HANDSFREE_AUDIO_STATE_DISCONNECTING      0x04
+
+#define HAL_EV_HANDSFREE_AUDIO_STATE            0x92
+struct hal_ev_handsfree_audio_state {
+        uint8_t state;
+        uint8_t bdaddr[6];
+} __attribute__((packed));
 #endif //_BT_HAL_MSG_H_
 
index 9f8c423..35ae780 100644 (file)
@@ -34,6 +34,7 @@ static const char BT_BASE_UUID[] = {
 /** BT Profile Service UUID's */
 #define BT_HAL_HFP_AUDIO_GATEWAY_UUID "0000111f-0000-1000-8000-00805f9b34fb"
 #define BT_HAL_HSP_AUDIO_GATEWAY_UUID "00001112-0000-1000-8000-00805f9b34fb"
+#define BT_HAL_HFP_HF_UUID "0000111e-0000-1000-8000-00805f9b34fb"
 #define BT_HAL_A2DP_PROFILE_UUID "0000110d-0000-1000-8000-00805f9b34fb" /* This is A2DP Profile UUID */
 #define BT_HAL_A2DP_SOURCE_UUID "0000110a-0000-1000-8000-00805f9b34fb"  /* This is A2DP Profile Role(SRC) UUID */
 #define BT_HAL_A2DP_SINK_UUID "0000110b-0000-1000-8000-00805f9b34fb"   /* This is A2DP Profile Role(SNK) UUID */
index c1e46be..7df0d24 100644 (file)
@@ -25,6 +25,7 @@
 #include <hardware/bluetooth.h>
 #include <hardware/bt_hh.h>
 #include <hardware/bt_av.h>
+#include <hardware/bt_hf.h>
 #include <hardware/bt_sock.h>
 
 /*TODO: Profile interfaces headers and exposed methods of Android HAL framework to be included in next patches */
index d47b4cb..92b5cc5 100644 (file)
@@ -222,6 +222,9 @@ static void __bt_hal_send_authorize_request_event(const gchar *address, const ch
        DBG("Remote Device address [%s]", address);
 
        _bt_convert_addr_string_to_type(ev.bdaddr, address);
+
+       /* UUID received in authorization request (In case of HFP unit, UUID received from Bluez
+          would be of that of Audio Gateway UUID (0x111f) */
        ev.service_id = _bt_convert_uuid_string_to_service_id(uuid);
 
        handle_stack_msg event_cb = _bt_hal_get_stack_message_handler();
index b7eac19..1128779 100644 (file)
@@ -35,6 +35,7 @@
 #include <bt-hal-hidhost.h>
 #include <bt-hal-socket.h>
 #include <bt-hal-av.h>
+#include <bt-hal-hf.h>
 
 #define enum_prop_to_hal(prop, hal_prop, type) do { \
        static type e; \
@@ -226,7 +227,7 @@ static const void *get_profile_interface(const char *profile_id)
                return NULL;
 
        if (!strcmp(profile_id, BT_PROFILE_HANDSFREE_ID))
-               return NULL;
+               return bt_get_hf_interface();
 
        if (!strcmp(profile_id, BT_PROFILE_GATT_ID))
                return NULL;
index b2f4337..39b73fd 100644 (file)
@@ -1282,6 +1282,8 @@ int _bt_hal_device_get_service_connection_state(
 
        uuid = _bt_convert_service_id_to_uuid_string(rem_svc_id);
        DBG("uuid: %s", uuid);
+       if (!uuid)
+               return 0;
 
        result = g_dbus_proxy_call_sync(device_proxy, "IsConnectedProfile",
                        g_variant_new("(s)", uuid),
index d6f6fbd..3388a41 100644 (file)
@@ -51,6 +51,7 @@ static GDBusConnection *manager_conn;
 static handle_stack_msg event_cb = NULL;
 static handle_stack_msg hid_event_cb = NULL;
 static handle_stack_msg av_event_cb = NULL;
+static handle_stack_msg hf_event_cb = NULL;
 static guint event_id;
 
 /* Forward declarations */
@@ -81,6 +82,10 @@ static void __bt_hal_handle_input_event(GVariant *msg, const char *path);
 static void __bt_hal_send_av_connection_state_event(gboolean connected, const char *address);
 
 static void __bt_hal_send_device_trust_state_event(gboolean is_trusted, const char *address);
+static int __bt_hal_register_audio_subscribe_signal(GDBusConnection *conn, int subscribe);
+static void __bt_hal_handle_headset_events(GVariant *msg, const char *member,const char *path);
+static void __bt_hal_send_hf_audio_connection_state_event(gboolean connected, const char *address);
+static void __bt_hal_send_hf_connection_state_event(gboolean connected, const char *address);
 
 static gboolean __bt_hal_discovery_finished_cb(gpointer user_data)
 {
@@ -728,6 +733,7 @@ static  void __bt_hal_manager_event_filter(GDBusConnection *connection,
                DBG("Manager Event: Interface Name: BT_HAL_NETWORK_SERVER_INTERFACE");
        } else if (g_strcmp0(interface_name, BT_HAL_HEADSET_INTERFACE) == 0) {
                DBG("Manager Event: Interface Name: BT_HAL_HEADSET_INTERFACE");
+                __bt_hal_handle_headset_events(parameters, signal_name, object_path);
        } else if (g_strcmp0(interface_name, BT_HAL_SINK_INTERFACE) == 0) {
                /* TODO: Handle Sink interface events from stack */
                DBG("Manager Event: Interface Name:BT_HAL_SINK_INTERFACE");
@@ -742,6 +748,79 @@ static  void __bt_hal_manager_event_filter(GDBusConnection *connection,
        return;
 }
 
+static void __bt_hal_handle_headset_events(GVariant *msg, const char *member,const char *path)
+{
+       gboolean property_flag = FALSE;
+       char *property = NULL;
+       GVariant *value = NULL;
+       g_variant_get(msg, "(sv)", &property, &value);
+
+       if (property == NULL)
+               return;
+
+       DBG("Property = %s \n", property);
+       /* We allow only 1 headset connection (HSP or HFP)*/
+       if (strcasecmp(property, "Connected") == 0) {
+               char *address;
+               g_variant_get(value, "b", &property_flag);
+
+               address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE);
+
+               /* Fix : NULL_RETURNS */
+               if (address == NULL)
+                       return;
+
+               _bt_convert_device_path_to_address(path, address);
+               __bt_hal_send_hf_audio_connection_state_event(property_flag, address);
+               g_free(address);
+       } else if (strcasecmp(property, "State") == 0) {
+               char *state = NULL;
+
+               g_variant_get(value, "s", &state);
+
+               /* This code assumes we support only 1 headset connection */
+               /* Need to use the headset list, if we support multi-headsets */
+               if (strcasecmp(state, "Playing") == 0) {
+                       DBG("Playing: Sco Connected");
+               } else if (strcasecmp(state, "connected") == 0 ||
+                               strcasecmp(state, "disconnected") == 0) {
+                       if (strcasecmp(state, "connected") == 0)
+                               DBG("Sco Connected");
+                       else
+                               DBG("Sco Disconnected");
+               } else {
+                       ERR("Not handled state - %s", state);
+                       g_free(state);
+                       return;
+               }
+               g_free(state);
+       } else if (strcasecmp(property, "SpeakerGain") == 0) {
+               char *address;
+
+               address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE);
+
+               _bt_convert_device_path_to_address(path, address);
+               INFO("Speaker Gain for address [%s]", address);
+               /* TODO Handle event sending to HAL */
+
+               g_free(address);
+       } else if (strcasecmp(property, "MicrophoneGain") == 0) {
+               char *address;
+
+               address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE);
+
+               _bt_convert_device_path_to_address(path, address);
+               INFO("Microphone Gain for address [%s]", address);
+               /* TODO Handle event sending to HAL */
+
+               g_free(address);
+       }
+
+       if (property)
+               g_free(property);
+       g_variant_unref(value);
+}
+
 static int __bt_hal_register_manager_subscribe_signal(GDBusConnection *conn,
                int subscribe)
 {
@@ -900,6 +979,9 @@ static int __bt_hal_register_service_event(GDBusConnection *g_conn, int event_ty
        case BT_HAL_HID_EVENT:
                __bt_hal_register_input_subscribe_signal(g_conn, TRUE);
                break;
+       case BT_HAL_HEADSET_EVENT:
+                __bt_hal_register_audio_subscribe_signal(g_conn, TRUE);
+               break;
        default:
                INFO_C("Register Event: event_type [%d]", event_type);
                return BT_HAL_ERROR_NOT_SUPPORT;
@@ -908,6 +990,45 @@ static int __bt_hal_register_service_event(GDBusConnection *g_conn, int event_ty
        return BT_HAL_ERROR_NONE;
 }
 
+static int __bt_hal_register_audio_subscribe_signal(GDBusConnection *conn,
+                                int subscribe)
+{
+       if (conn == NULL)
+               return -1;
+
+       static int subs_headset_id = -1;
+       static int subs_sink_id = -1;
+
+       if (subscribe) {
+               if (subs_headset_id == -1) {
+                       subs_headset_id = g_dbus_connection_signal_subscribe(conn,
+                                       NULL, BT_HAL_HEADSET_INTERFACE,
+                                       NULL, NULL, NULL, 0,
+                                       __bt_hal_manager_event_filter,
+                                       NULL, NULL);
+               }
+               if (subs_sink_id == -1) {
+                       subs_sink_id = g_dbus_connection_signal_subscribe(conn,
+                                       NULL, BT_HAL_SINK_INTERFACE,
+                                       NULL, NULL, NULL, 0,
+                                       __bt_hal_manager_event_filter,
+                                       NULL, NULL);
+               }
+       } else {
+               if (subs_headset_id != -1) {
+                       g_dbus_connection_signal_unsubscribe(conn,
+                                       subs_headset_id);
+                       subs_headset_id = -1;
+               }
+               if (subs_sink_id != -1) {
+                       g_dbus_connection_signal_unsubscribe(conn,
+                                       subs_sink_id);
+                       subs_sink_id = -1;
+               }
+       }
+       return 0;
+}
+
 static int __bt_hal_initialize_manager_receiver(void)
 {
        DBG("+");
@@ -933,6 +1054,9 @@ static int __bt_hal_initialize_manager_receiver(void)
        if (__bt_hal_register_service_event(manager_conn,
                                BT_HAL_HID_EVENT) != BT_HAL_ERROR_NONE)
                goto fail;
+       if (__bt_hal_register_service_event(manager_conn,
+                               BT_HAL_HEADSET_EVENT) != BT_HAL_ERROR_NONE)
+               goto fail;
        return BT_HAL_ERROR_NONE;
 fail:
        if (manager_conn) {
@@ -1359,18 +1483,34 @@ static void __bt_hal_handle_device_specific_events(GVariant *msg, const char *me
                                DBG("Profile state: %d", state);
 
                } else if ((strncmp(profile_uuid, A2DP_SINK_UUID, strlen(A2DP_SINK_UUID)) == 0)) {
-                        if (state == BT_HAL_PROFILE_STATE_CONNECTED) {
-                                DBG("A2DP Profile state changed: BT_PROFILE_STATE_CONNECTED");
-                                __bt_hal_send_av_connection_state_event(TRUE, address);
-                        } else if (state == BT_HAL_PROFILE_STATE_DISCONNECTED) {
-                                DBG("A2DP Profile state changed: BT_PROFILE_STATE_DISCONNECTED");
-                                __bt_hal_send_av_connection_state_event(FALSE, address);
-                        } else if (state == BT_HAL_PROFILE_STATE_DISCONNECTING) {
-                                DBG("A2DP Profile state changed: BT_PROFILE_STATE_DISCONNECTING");
-                        } else if (state == BT_HAL_PROFILE_STATE_CONNECTING) {
-                                DBG("A2DP Profile state changed: BT_PROFILE_STATE_CONNECTING");
-                        }
-                } else {
+                       if (state == BT_HAL_PROFILE_STATE_CONNECTED) {
+                               DBG("A2DP Profile state changed: BT_PROFILE_STATE_CONNECTED");
+                               __bt_hal_send_av_connection_state_event(TRUE, address);
+                       } else if (state == BT_HAL_PROFILE_STATE_DISCONNECTED) {
+                               DBG("A2DP Profile state changed: BT_PROFILE_STATE_DISCONNECTED");
+                               __bt_hal_send_av_connection_state_event(FALSE, address);
+                       } else if (state == BT_HAL_PROFILE_STATE_DISCONNECTING) {
+                               DBG("A2DP Profile state changed: BT_PROFILE_STATE_DISCONNECTING");
+                       } else if (state == BT_HAL_PROFILE_STATE_CONNECTING) {
+                               DBG("A2DP Profile state changed: BT_PROFILE_STATE_CONNECTING");
+                       } else {
+                               ERR("A2DP Profile state: Invalid");
+                       }
+               } else if (strncmp(profile_uuid, HFP_HF_UUID, strlen(HFP_HF_UUID)) == 0) {
+                       if (state == BT_HAL_PROFILE_STATE_CONNECTING)
+                               DBG("HFP Profile state changed: BT_PROFILE_STATE_CONNECTING");
+                       else if (state == BT_HAL_PROFILE_STATE_CONNECTED) {
+                               DBG("HFP Profile state changed: BT_PROFILE_STATE_CONNECTED");
+                               __bt_hal_send_hf_connection_state_event(TRUE, address);
+                       } else if (state == BT_HAL_PROFILE_STATE_DISCONNECTED) {
+                               DBG("HFP Profile state changed: BT_PROFILE_STATE_DISCONNECTED");
+                               __bt_hal_send_hf_connection_state_event(FALSE, address);
+                       } else if (state == BT_HAL_PROFILE_STATE_DISCONNECTING) {
+                               DBG("HFP Profile state changed: BT_PROFILE_STATE_DISCONNECTING");
+                       } else {
+                               ERR("HFP Profile state: Invalid");
+                       }
+               } else {
                        DBG("Profile[%s] State changed status [%d] ", profile_uuid,state);
                }
                g_free(address);
@@ -1383,12 +1523,12 @@ static void __bt_hal_handle_device_specific_events(GVariant *msg, const char *me
 
 void _bt_hal_register_hid_event_handler_cb(handle_stack_msg cb)
 {
-               hid_event_cb = cb;
+       hid_event_cb = cb;
 }
 
 void _bt_hal_unregister_hid_event_handler_cb()
 {
-               hid_event_cb = NULL;
+       hid_event_cb = NULL;
 }
 
 /* A2DP Src Role(Remote:Sink) Events */
@@ -1402,6 +1542,17 @@ void _bt_hal_unregister_av_event_handler_cb()
        av_event_cb = NULL;
 }
 
+/* HF(AG Role) Events */
+void _bt_hal_register_hf_event_handler_cb(handle_stack_msg cb)
+{
+       hf_event_cb = cb;
+}
+
+void _bt_hal_unregister_hf_event_handler_cb()
+{
+       hf_event_cb = NULL;
+}
+
 static void __bt_hal_send_av_connection_state_event(gboolean connected, const char *address)
 {
        DBG("+");
@@ -1423,3 +1574,48 @@ static void __bt_hal_send_av_connection_state_event(gboolean connected, const ch
        else
                av_event_cb(HAL_EV_A2DP_CONN_STATE, &ev, sizeof(ev));
 }
+
+static void __bt_hal_send_hf_connection_state_event(gboolean connected, const char *address)
+{
+       DBG("+");
+       struct hal_ev_handsfree_conn_state ev;
+
+       if (connected == TRUE)
+               INFO("AG Profile Connected for address [%s]", address);
+       else
+               INFO("AG Profile DisConnected for address [%s]", address);
+
+       ev.state = (connected == TRUE) ?
+               HAL_EV_HANDSFREE_CONN_STATE_CONNECTED :
+               HAL_EV_HANDSFREE_CONN_STATE_DISCONNECTED;
+
+       _bt_convert_addr_string_to_type(ev.bdaddr, address);
+
+       if (!hf_event_cb)
+               ERR("HF event handler not registered");
+       else
+               hf_event_cb(HAL_EV_HANDSFREE_CONN_STATE, &ev, sizeof(ev));
+}
+
+static void __bt_hal_send_hf_audio_connection_state_event(gboolean connected,
+                                               const char *address)
+{
+       DBG("+");
+       struct hal_ev_handsfree_audio_state ev;
+
+       if (connected == TRUE)
+               INFO("AG Audio Connected for address [%s]", address);
+       else
+               INFO("AG Audio DisConnected for address [%s]", address);
+
+       ev.state = (connected == TRUE) ?
+               HAL_EV_HANDSFREE_AUDIO_STATE_CONNECTED :
+               HAL_EV_HANDSFREE_AUDIO_STATE_DISCONNECTED;
+
+       _bt_convert_addr_string_to_type(ev.bdaddr, address);
+
+       if (!hf_event_cb)
+               ERR("HF event handler not registered");
+       else
+               hf_event_cb(HAL_EV_HANDSFREE_AUDIO_STATE, &ev, sizeof(ev));
+}
index bef1c58..4c0b775 100644 (file)
@@ -49,6 +49,11 @@ void _bt_hal_register_av_event_handler_cb(handle_stack_msg cb);
 
 void _bt_hal_unregister_av_event_handler_cb();
 
+/* HF(AG Role) Events*/
+void _bt_hal_register_hf_event_handler_cb(handle_stack_msg cb);
+
+void _bt_hal_unregister_hf_event_handler_cb();
+
 handle_stack_msg _bt_hal_get_stack_message_handler(void);
 
 int __bt_insert_hal_properties(void *buf, uint8_t type, uint16_t len, const void *val);
diff --git a/bt-oal/bluez_hal/src/bt-hal-hf-dbus-handler.c b/bt-oal/bluez_hal/src/bt-hal-hf-dbus-handler.c
new file mode 100644 (file)
index 0000000..2d62b83
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * BLUETOOTH HAL
+ *
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Anupam Roy <anupam.r@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <dlog.h>
+#include <vconf.h>
+
+#include "bt-hal-hf-dbus-handler.h"
+#include "bt-hal-dbus-common-utils.h"
+#include "bt-hal-internal.h"
+
+static handle_stack_msg event_cb = NULL;
+
+/* To send stack event to hal-hf handler */
+void _bt_hal_register_hf_dbus_handler_cb(handle_stack_msg cb)
+{
+       event_cb = cb;
+}
+
+/* To send stack event to hal-hf handler */
+void _bt_hal_unregister_hf_dbus_handler_cb()
+{
+       event_cb = NULL;
+}
+
+static void __bt_hf_connect_cb(GDBusProxy *proxy, GAsyncResult *res,
+                                                       gpointer user_data)
+{
+       GError *g_error = NULL;
+       struct hal_ev_handsfree_conn_state ev;
+       GVariant *reply = NULL;
+       char *address = user_data;
+       int result = BT_STATUS_SUCCESS;
+
+       DBG("+");
+
+       reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
+       g_object_unref(proxy);
+       if (reply == NULL) {
+               ERR("HF Connect Dbus Call Error");
+               if (g_error) {
+                       ERR("Error: %s\n", g_error->message);
+                       g_clear_error(&g_error);
+               }
+               result = BT_STATUS_FAIL;
+       }
+       g_variant_unref(reply);
+
+       DBG("Address: %s", address);
+       /*
+        * If result is success, HF connected event will be triggered
+        * automatically from stack, so return from here.
+        */
+       if (result == BT_STATUS_SUCCESS)
+               goto done;
+
+
+       /* Prepare to send HF connection state event */
+       memset(&ev, 0, sizeof(ev));
+       _bt_convert_addr_string_to_type(ev.bdaddr, address);
+       ev.state = HAL_EV_HANDSFREE_CONN_STATE_DISCONNECTED;
+       if (!event_cb)
+               ERR("HF DBUS handler callback not registered");
+       else
+               event_cb(HAL_EV_HANDSFREE_CONN_STATE, (void *)&ev, sizeof(ev));
+
+done:
+       g_free(address);
+}
+
+bt_status_t _bt_hal_dbus_handler_hf_connect(bt_bdaddr_t *bd_addr)
+{
+       char *address;
+       struct hal_ev_handsfree_conn_state ev;
+       GDBusConnection *conn;
+       int ret;
+
+       if(!bd_addr) {
+               ERR("bd_addr is NULL, return");
+               return BT_STATUS_PARM_INVALID;
+       }
+
+       conn = _bt_get_system_gconn();
+       if(!conn) {
+               ERR("_bt_get_system_gconn returned NULL, return");
+               return BT_STATUS_FAIL;
+       }
+
+       address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE * sizeof(char));
+       if (!address) {
+               ERR("Memory allocation failed");
+               return BT_STATUS_NOMEM;
+       }
+       _bt_convert_addr_type_to_string(address, bd_addr->address);
+
+       ret = _bt_connect_profile(address, HFP_HF_UUID,
+                       __bt_hf_connect_cb, address);
+
+       if (ret != BT_HAL_ERROR_NONE) {
+               ERR("_bt_connect_profile(HF) Error");
+               return BT_STATUS_FAIL;
+       }
+
+       /* Prepare to send HID connecting event */
+       memset(&ev, 0, sizeof(ev));
+       ev.state = HAL_EV_HANDSFREE_CONN_STATE_CONNECTING;
+       memcpy(ev.bdaddr, bd_addr, sizeof(bt_bdaddr_t));
+       if (!event_cb)
+               ERR("HF dbus handler callback not registered");
+       else
+               event_cb(HAL_EV_HANDSFREE_CONN_STATE, (void *)&ev, sizeof(ev));
+
+       return BT_STATUS_SUCCESS;
+}
+
+static void __bt_hf_disconnect_cb(GDBusProxy *proxy, GAsyncResult *res,
+                                                       gpointer user_data)
+{
+       GError *g_error = NULL;
+       struct hal_ev_handsfree_conn_state ev;
+       GVariant *reply = NULL;
+       char *address = user_data;
+       int result = BT_STATUS_SUCCESS;
+
+       DBG("+");
+
+       reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
+       g_object_unref(proxy);
+       if (reply == NULL) {
+               ERR("HF Disconnect Dbus Call Error");
+               if (g_error) {
+                       ERR("Error: %s\n", g_error->message);
+                       g_clear_error(&g_error);
+               }
+               result = BT_STATUS_FAIL;
+       }
+       g_variant_unref(reply);
+
+       if (result != BT_STATUS_FAIL)
+               DBG("HF Disconnect successful for Device: %s", address);
+       else
+               DBG("HF Disconnect un-successful for Device: %s", address);
+
+       /* Prepare to send HF disconnection state event */
+       memset(&ev, 0, sizeof(ev));
+       _bt_convert_addr_string_to_type(ev.bdaddr, address);
+       ev.state = HAL_EV_HANDSFREE_CONN_STATE_DISCONNECTED;
+       if (!event_cb)
+               ERR("HF DBUS handler callback not registered");
+       else
+               event_cb(HAL_EV_HANDSFREE_CONN_STATE, (void *)&ev, sizeof(ev));
+
+       g_free(address);
+       DBG("-");
+}
+
+bt_status_t _bt_hal_dbus_handler_hf_disconnect(bt_bdaddr_t *bd_addr)
+{
+       char *address;
+       struct hal_ev_handsfree_conn_state ev;
+       GDBusConnection *conn;
+       int ret;
+
+       if(!bd_addr) {
+               ERR("bd_addr is NULL, return");
+               return BT_STATUS_PARM_INVALID;
+       }
+
+       conn = _bt_get_system_gconn();
+       if(!conn) {
+               ERR("_bt_get_system_gconn returned NULL, return");
+               return BT_STATUS_FAIL;
+       }
+
+       address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE * sizeof(char));
+       if (!address) {
+               ERR("Memory allocation failed");
+               return BT_STATUS_NOMEM;
+       }
+       _bt_convert_addr_type_to_string(address, bd_addr->address);
+
+       ret = _bt_disconnect_profile(address, HFP_HF_UUID,
+                       __bt_hf_disconnect_cb, address);
+
+       if (ret != BT_HAL_ERROR_NONE) {
+               ERR("_bt_connect_profile Error");
+               return BT_STATUS_FAIL;
+       }
+
+       /* Prepare to send HID connecting event */
+       memset(&ev, 0, sizeof(ev));
+       ev.state = HAL_EV_HANDSFREE_CONN_STATE_DISCONNECTING;
+       memcpy(ev.bdaddr, bd_addr, sizeof(bt_bdaddr_t));
+       if (!event_cb)
+               ERR("HID dbus handler callback not registered");
+       else
+               event_cb(HAL_EV_HANDSFREE_CONN_STATE, (void *)&ev, sizeof(ev));
+
+       return BT_STATUS_SUCCESS;
+}
diff --git a/bt-oal/bluez_hal/src/bt-hal-hf-dbus-handler.h b/bt-oal/bluez_hal/src/bt-hal-hf-dbus-handler.h
new file mode 100644 (file)
index 0000000..c927359
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * BLUETOOTH HAL
+ *
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Anupam Roy <anupam.r@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *              http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+#ifndef _BT_HAL_HF_DBUS_HANDLER_H_
+#define _BT_HAL_HF_DBUS_HANDLER_H_
+
+#include <glib.h>
+#include <sys/types.h>
+
+#include "bt-hal.h"
+#include "bt-hal-log.h"
+#include "bt-hal-msg.h"
+
+#include "bt-hal-event-receiver.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void _bt_hal_register_hf_dbus_handler_cb(handle_stack_msg cb);
+
+void _bt_hal_unregister_hf_dbus_handler_cb();
+
+bt_status_t _bt_hal_dbus_handler_hf_connect(bt_bdaddr_t *bd_addr);
+
+bt_status_t _bt_hal_dbus_handler_hf_disconnect(bt_bdaddr_t *bd_addr);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* _BT_HAL_HF_DBUS_HANDLER_H_*/
diff --git a/bt-oal/bluez_hal/src/bt-hal-hf.c b/bt-oal/bluez_hal/src/bt-hal-hf.c
new file mode 100644 (file)
index 0000000..7a2f3e9
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * BLUETOOTH HAL
+ *
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:  Anupam Roy <anupam.r@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdlib.h>
+#include <dlog.h>
+
+#include "bt-hal.h"
+#include "bt-hal-log.h"
+#include "bt-hal-msg.h"
+#include "bt-hal-utils.h"
+
+#include "bt-hal-hf-dbus-handler.h"
+#include "bt-hal-event-receiver.h"
+
+static const bthf_callbacks_t *bt_hal_hf_cbacks;
+
+static bool interface_ready(void)
+{
+       return bt_hal_hf_cbacks != NULL;
+}
+
+static bt_status_t hf_connect(bt_bdaddr_t *bd_addr)
+{
+       DBG("");
+       return _bt_hal_dbus_handler_hf_connect(bd_addr);
+}
+
+static bt_status_t hf_disconnect(bt_bdaddr_t *bd_addr)
+{
+       DBG("");
+       return _bt_hal_dbus_handler_hf_disconnect(bd_addr);
+}
+
+static bt_status_t hf_connect_audio(bt_bdaddr_t *bd_addr)
+{
+       DBG("");
+       return BT_STATUS_UNSUPPORTED;
+}
+
+static bt_status_t hf_disconnect_audio(bt_bdaddr_t *bd_addr)
+{
+       DBG("");
+       return BT_STATUS_UNSUPPORTED;
+}
+
+static bt_status_t hf_start_voice_recognition(bt_bdaddr_t *bd_addr)
+{
+       DBG("");
+       return BT_STATUS_UNSUPPORTED;
+}
+
+static bt_status_t hf_stop_voice_recognition(bt_bdaddr_t *bd_addr)
+{
+       DBG("");
+       return BT_STATUS_UNSUPPORTED;
+}
+
+static bt_status_t hf_voume_control(bthf_volume_type_t type, int volume,
+                                                       bt_bdaddr_t *bd_addr)
+{
+       DBG("");
+       return BT_STATUS_UNSUPPORTED;
+}
+
+static bt_status_t hf_device_status_notification(bthf_network_state_t ntk_state,
+                          bthf_service_type_t svc_type, int signal, int batt_chg)
+{
+       DBG("");
+       return BT_STATUS_UNSUPPORTED;
+}
+
+static bt_status_t hf_cops_response(const char *cops, bt_bdaddr_t *bd_addr)
+{
+       DBG("");
+       return BT_STATUS_UNSUPPORTED;
+}
+
+static bt_status_t hf_cind_response(int svc, int num_active, int num_held,
+                                     bthf_call_state_t call_setup_state,
+                                     int signal, int roam, int batt_chg,
+                                                    bt_bdaddr_t *bd_addr)
+{
+       DBG("");
+       return BT_STATUS_UNSUPPORTED;
+}
+
+static bt_status_t hf_formatted_at_response(const char *rsp, bt_bdaddr_t *bd_addr)
+{
+       DBG("");
+       return BT_STATUS_UNSUPPORTED;
+}
+
+static bt_status_t hf_at_response(bthf_at_response_t response_code,
+                                    int error_code, bt_bdaddr_t *bd_addr)
+{
+       DBG("");
+       return BT_STATUS_UNSUPPORTED;
+}
+
+static bt_status_t hf_clcc_response(int index, bthf_call_direction_t dir,
+                               bthf_call_state_t state, bthf_call_mode_t mode,
+                               bthf_call_mpty_type_t mpty, const char *number,
+                               bthf_call_addrtype_t type, bt_bdaddr_t *bd_addr)
+{
+       DBG("");
+       return BT_STATUS_UNSUPPORTED;
+}
+
+static bt_status_t hf_phone_state_change(int num_active, int num_held, bthf_call_state_t call_setup_state,
+                                            const char *number, bthf_call_addrtype_t type)
+{
+       DBG("");
+       return BT_STATUS_UNSUPPORTED;
+}
+
+static void __bt_hal_handle_hf_conn_state(void *buf, uint16_t len)
+{
+        struct hal_ev_handsfree_conn_state *ev = buf;
+
+        if (bt_hal_hf_cbacks->connection_state_cb)
+                bt_hal_hf_cbacks->connection_state_cb(ev->state, (bt_bdaddr_t *) ev->bdaddr);
+}
+
+static void __bt_hal_handle_hf_audio_conn_state(void *buf, uint16_t len)
+{
+        struct hal_ev_handsfree_audio_state *ev = buf;
+
+        if (bt_hal_hf_cbacks->audio_state_cb)
+                bt_hal_hf_cbacks->audio_state_cb(ev->state, (bt_bdaddr_t *) ev->bdaddr);
+}
+
+static void __bt_hal_handle_hf_events(int message, void *buf, uint16_t len)
+{
+       DBG("+");
+       if (!interface_ready())
+               return;
+       switch(message) {
+       case HAL_EV_HANDSFREE_CONN_STATE:
+               DBG("Event: HAL_EV_HANDSFREE_CONN_STATE");
+               __bt_hal_handle_hf_conn_state(buf, len);
+               break;
+       case HAL_EV_HANDSFREE_AUDIO_STATE:
+               DBG("Event: HAL_EV_HANDSFREE_AUDIO_STATE");
+               __bt_hal_handle_hf_audio_conn_state(buf, len);
+               break;
+       default:
+               DBG("Event Currently not handled!!");
+               break;
+       }
+       DBG("-");
+}
+
+static bt_status_t init(bthf_callbacks_t* callbacks, int max_hf_clients)
+{
+       DBG("");
+
+       if (interface_ready())
+               return BT_STATUS_DONE;
+
+       if (max_hf_clients > 1)
+               return BT_STATUS_UNSUPPORTED;
+       bt_hal_hf_cbacks = callbacks;
+       DBG("Register HF AG Role callback function");
+       _bt_hal_register_hf_dbus_handler_cb(__bt_hal_handle_hf_events);
+       _bt_hal_register_hf_event_handler_cb(__bt_hal_handle_hf_events);
+       return BT_STATUS_SUCCESS;
+}
+
+static void cleanup(void)
+{
+       DBG("");
+
+       if (!interface_ready())
+               return;
+
+       bt_hal_hf_cbacks = NULL;
+}
+
+static bthf_interface_t bthf_if = {
+    .size = sizeof(bthf_if),
+    .init = init,
+    .connect = hf_connect,
+    .disconnect = hf_disconnect,
+    .connect_audio = hf_connect_audio,
+    .disconnect_audio = hf_disconnect_audio,
+    .start_voice_recognition = hf_start_voice_recognition,
+    .stop_voice_recognition = hf_stop_voice_recognition,
+    .volume_control = hf_voume_control,
+    .device_status_notification = hf_device_status_notification,
+    .cops_response = hf_cops_response,
+    .cind_response = hf_cind_response,
+    .formatted_at_response = hf_formatted_at_response,
+    .at_response = hf_at_response,
+    .clcc_response = hf_clcc_response,
+    .phone_state_change = hf_phone_state_change,
+    .cleanup = cleanup
+};
+
+/*******************************************************************************
+**
+** Function         bt_get_hf_interface
+**
+** Description      Get the hf callback interface
+**
+** Returns          bthf_interface_t
+**
+*******************************************************************************/
+const bthf_interface_t *bt_get_hf_interface()
+{
+    return &bthf_if;
+}
diff --git a/bt-oal/bluez_hal/src/bt-hal-hf.h b/bt-oal/bluez_hal/src/bt-hal-hf.h
new file mode 100644 (file)
index 0000000..1d3e975
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * BLUETOOTH HAL
+ *
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:  Anupam Roy <anupam.r@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __BT_HAL_HF_SRC_H__
+#define __BT_HAL_HF_SRC_H__
+
+#include <stdint.h>
+#include <glib.h>
+#include <unistd.h>
+#include <dlog.h>
+#include <stdio.h>
+
+bthf_interface_t *bt_get_hf_interface(void);
+
+#endif //__BT_HAL_HF_SRC_H__
index de4f522..0745992 100644 (file)
@@ -65,6 +65,7 @@ typedef enum {
 /* UUIDs */
 #define HID_UUID                "00001124-0000-1000-8000-00805f9b34fb"
 #define A2DP_SINK_UUID          "0000110b-0000-1000-8000-00805f9b34fb"
+#define HFP_HF_UUID             "0000111e-0000-1000-8000-00805f9b34fb"
 
 /* TODO  More declarations to be added in subsequent patches */
 #ifdef __cplusplus
index 3bedd7e..796dc7f 100644 (file)
@@ -417,7 +417,7 @@ char *_bt_convert_service_id_to_uuid_string(bt_service_id_t service_id)
 
        switch (service_id) {
        case BT_HFP_SERVICE_ID:
-               return g_strdup(BT_HAL_HFP_AUDIO_GATEWAY_UUID);
+               return g_strdup(BT_HAL_HFP_HF_UUID);
        case BT_HSP_SERVICE_ID:
                return g_strdup(BT_HAL_HSP_AUDIO_GATEWAY_UUID);
        case BT_A2DP_SERVICE_ID: