diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index 773ef76..b63aa13 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
#include <glib.h>
#include "lib/bluetooth.h"
+#include "lib/sdp.h"
+#include "lib/sdp_lib.h"
+#include "src/sdp-client.h"
#include "ipc.h"
#include "ipc-common.h"
#include "src/log.h"
#include "utils.h"
+#include "bluetooth.h"
#include "hal-msg.h"
#include "handsfree-client.h"
+#define HFP_HF_CHANNEL 7
+
+#define HFP_HF_FEAT_ECNR 0x00000001
+#define HFP_HF_FEAT_3WAY 0x00000002
+#define HFP_HF_FEAT_CLI 0x00000004
+#define HFP_HF_FEAT_VR 0x00000008
+#define HFP_HF_FEAT_RVC 0x00000010
+#define HFP_HF_FEAT_ECS 0x00000020
+#define HFP_HF_FEAT_ECC 0x00000040
+#define HFP_HF_FEAT_CODEC 0x00000080
+#define HFP_HF_FEAT_HF_IND 0x00000100
+#define HFP_HF_FEAT_ESCO_S4_T2 0x00000200
+
+
+#define HFP_HF_FEATURES (HFP_HF_FEAT_ECNR | HFP_HF_FEAT_3WAY |\
+ HFP_HF_FEAT_CLI | HFP_HF_FEAT_VR |\
+ HFP_HF_FEAT_RVC | HFP_HF_FEAT_ECS |\
+ HFP_HF_FEAT_ECC)
+
static bdaddr_t adapter_addr;
static struct ipc *hal_ipc = NULL;
+static uint32_t hfp_hf_features = 0;
+static uint32_t hfp_hf_record_id = 0;
+
static void handle_connect(const void *buf, uint16_t len)
{
DBG("Not Implemented");
{ handle_get_last_vc_tag_num, false, 0 },
};
+static sdp_record_t *hfp_hf_record(void)
+{
+ sdp_list_t *svclass_id, *pfseq, *apseq, *root;
+ uuid_t root_uuid, svclass_uuid, ga_svclass_uuid;
+ uuid_t l2cap_uuid, rfcomm_uuid;
+ sdp_profile_desc_t profile;
+ sdp_list_t *aproto, *proto[2];
+ sdp_record_t *record;
+ sdp_data_t *channel, *features;
+ uint16_t sdpfeat;
+ uint8_t ch = HFP_HF_CHANNEL;
+
+ record = sdp_record_alloc();
+ if (!record)
+ return NULL;
+
+ sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
+ root = sdp_list_append(NULL, &root_uuid);
+ sdp_set_browse_groups(record, root);
+
+ sdp_uuid16_create(&svclass_uuid, HANDSFREE_SVCLASS_ID);
+ svclass_id = sdp_list_append(NULL, &svclass_uuid);
+ sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
+ svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
+ sdp_set_service_classes(record, svclass_id);
+
+ sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID);
+ profile.version = 0x0106;
+ pfseq = sdp_list_append(NULL, &profile);
+ sdp_set_profile_descs(record, pfseq);
+
+ sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
+ proto[0] = sdp_list_append(NULL, &l2cap_uuid);
+ apseq = sdp_list_append(NULL, proto[0]);
+
+ sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
+ proto[1] = sdp_list_append(NULL, &rfcomm_uuid);
+ channel = sdp_data_alloc(SDP_UINT8, &ch);
+ proto[1] = sdp_list_append(proto[1], channel);
+ apseq = sdp_list_append(apseq, proto[1]);
+
+ /* Codec Negotiation bit in SDP feature is different then in BRSF */
+ sdpfeat = hfp_hf_features & 0x0000003F;
+ if (hfp_hf_features & HFP_HF_FEAT_CODEC)
+ sdpfeat |= 0x00000020;
+ else
+ sdpfeat &= ~0x00000020;
+
+ features = sdp_data_alloc(SDP_UINT16, &sdpfeat);
+ sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features);
+
+ aproto = sdp_list_append(NULL, apseq);
+ sdp_set_access_protos(record, aproto);
+
+ sdp_set_info_attr(record, "Hands-Free unit", NULL, NULL);
+
+ sdp_data_free(channel);
+ sdp_list_free(proto[0], NULL);
+ sdp_list_free(proto[1], NULL);
+ sdp_list_free(apseq, NULL);
+ sdp_list_free(pfseq, NULL);
+ sdp_list_free(aproto, NULL);
+ sdp_list_free(root, NULL);
+ sdp_list_free(svclass_id, NULL);
+
+ return record;
+}
+
+static bool enable_hf_client(void)
+{
+ sdp_record_t *rec;
+
+ hfp_hf_features = HFP_HF_FEATURES;
+
+ rec = hfp_hf_record();
+ if (!rec) {
+ error("hf-client: Could not create service record");
+ return false;
+ }
+
+ if (bt_adapter_add_record(rec, 0) < 0) {
+ error("hf-client: Failed to register service record");
+ sdp_record_free(rec);
+ return false;
+ }
+
+ hfp_hf_record_id = rec->handle;
+
+ return true;
+}
+
+static void cleanup_hfp_hf(void)
+{
+ if (hfp_hf_record_id > 0) {
+ bt_adapter_remove_record(hfp_hf_record_id);
+ hfp_hf_record_id = 0;
+ }
+}
+
bool bt_hf_client_register(struct ipc *ipc, const bdaddr_t *addr)
{
DBG("");
bacpy(&adapter_addr, addr);
+ if (!enable_hf_client())
+ return false;
+
hal_ipc = ipc;
ipc_register(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT, cmd_handlers,
G_N_ELEMENTS(cmd_handlers));
{
DBG("");
+ cleanup_hfp_hf();
+
ipc_unregister(hal_ipc, HAL_SERVICE_ID_HANDSFREE);
hal_ipc = NULL;
}