am f88e742e: Correct the logic of UIPC thread id check
* commit 'f88e742ea5f95a529a1758cb00aea0e58fdb9863':
Correct the logic of UIPC thread id check
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..92b837b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+buildtools
+out
+third_party
diff --git a/.gn b/.gn
new file mode 100644
index 0000000..947ebac
--- /dev/null
+++ b/.gn
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2015 Google, Inc.
+#
+# 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.
+#
+
+# This file is used by the GN meta build system to find the root of the source
+# tree and to set startup options. For documentation on the values set in this
+# file, run "gn help dotfile" at the command line.
+
+buildconfig = "//build/config/BUILDCONFIG.gn"
+secondary_source = "//build/secondary/"
diff --git a/Android.mk b/Android.mk
index c5d3d16..36b5807 100644
--- a/Android.mk
+++ b/Android.mk
@@ -17,9 +17,11 @@
bdroid_CFLAGS += -DBLUEDROID_DEBUG
endif
+bdroid_CFLAGS += -DEXPORT_SYMBOL="__attribute__((visibility(\"default\")))"
+
bdroid_CFLAGS += \
+ -fvisibility=hidden \
-Wall \
- -Wno-unused-parameter \
-Wunused-but-set-variable \
-UNDEBUG \
-DLOG_NDEBUG=1
diff --git a/BUILD.gn b/BUILD.gn
new file mode 100644
index 0000000..10cefaa
--- /dev/null
+++ b/BUILD.gn
@@ -0,0 +1,28 @@
+#
+# Copyright (C) 2015 Google, Inc.
+#
+# 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.
+#
+
+# This is the root build file for GN. GN will start processing by loading this
+# file, and recursively load all dependencies until all dependencies are either
+# resolved or known not to exist (which will cause the build to fail). So if
+# you add a new build file, there must be some path of dependencies from this
+# file to your new one or GN won't know about it.
+
+# This pulls in main/BUILD.gn and all of its dependencies.
+group("bluetooth") {
+ deps = [
+ "//main:bluetooth.default",
+ ]
+}
diff --git a/audio_a2dp_hw/BUILD.gn b/audio_a2dp_hw/BUILD.gn
new file mode 100644
index 0000000..2c5024a
--- /dev/null
+++ b/audio_a2dp_hw/BUILD.gn
@@ -0,0 +1,27 @@
+#
+# Copyright (C) 2015 Google, Inc.
+#
+# 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.
+#
+
+shared_library("audio.a2dp.default") {
+ sources = [
+ "audio_a2dp_hw.c"
+ ]
+
+ include_dirs = [
+ "include",
+ "//",
+ "//utils/include",
+ ]
+}
diff --git a/audio_a2dp_hw/audio_a2dp_hw.c b/audio_a2dp_hw/audio_a2dp_hw.c
index bd153a3..53396cb 100644
--- a/audio_a2dp_hw/audio_a2dp_hw.c
+++ b/audio_a2dp_hw/audio_a2dp_hw.c
@@ -199,7 +199,6 @@
{
int ret;
int skt_fd;
- struct sockaddr_un remote;
int len;
INFO("connect to %s (sz %zu)", path, buffer_sz);
@@ -235,8 +234,6 @@
static int skt_read(int fd, void *p, size_t len)
{
int read;
- struct pollfd pfd;
- struct timespec ts;
FNLOG();
@@ -366,7 +363,6 @@
static int a2dp_read_audio_config(struct a2dp_stream_common *common)
{
- char cmd = A2DP_CTRL_GET_AUDIO_CONFIG;
uint32_t sample_rate;
uint8_t channel_count;
@@ -652,8 +648,8 @@
static int out_set_format(struct audio_stream *stream, audio_format_t format)
{
+ UNUSED(stream);
UNUSED(format);
- struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
DEBUG("setting format not yet supported (0x%x)", format);
return -ENOSYS;
}
@@ -678,8 +674,8 @@
static int out_dump(const struct audio_stream *stream, int fd)
{
+ UNUSED(stream);
UNUSED(fd);
- struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
FNLOG();
return 0;
}
@@ -741,9 +737,8 @@
static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
{
+ UNUSED(stream);
UNUSED(keys);
- struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
-
FNLOG();
/* add populating param here */
@@ -1014,7 +1009,6 @@
struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev;
struct a2dp_stream_out *out;
int ret = 0;
- int i;
UNUSED(address);
UNUSED(handle);
UNUSED(devices);
@@ -1138,8 +1132,7 @@
static int adev_init_check(const struct audio_hw_device *dev)
{
- struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device*)dev;
-
+ UNUSED(dev);
FNLOG();
return 0;
@@ -1320,7 +1313,6 @@
hw_device_t** device)
{
struct a2dp_audio_device *adev;
- int ret;
INFO(" adev_open in A2dp_hw module");
FNLOG();
diff --git a/bta/BUILD.gn b/bta/BUILD.gn
new file mode 100644
index 0000000..756a80d
--- /dev/null
+++ b/bta/BUILD.gn
@@ -0,0 +1,114 @@
+#
+# Copyright (C) 2015 Google, Inc.
+#
+# 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.
+#
+
+static_library("bta") {
+ sources = [
+ "ag/bta_ag_act.c",
+ "ag/bta_ag_api.c",
+ "ag/bta_ag_at.c",
+ "ag/bta_ag_cfg.c",
+ "ag/bta_ag_ci.c",
+ "ag/bta_ag_cmd.c",
+ "ag/bta_ag_main.c",
+ "ag/bta_ag_rfc.c",
+ "ag/bta_ag_sco.c",
+ "ag/bta_ag_sdp.c",
+ "ar/bta_ar.c",
+ "av/bta_av_aact.c",
+ "av/bta_av_act.c",
+ "av/bta_av_api.c",
+ "av/bta_av_cfg.c",
+ "av/bta_av_ci.c",
+ "av/bta_av_main.c",
+ "av/bta_av_sbc.c",
+ "av/bta_av_ssm.c",
+ "dm/bta_dm_act.c",
+ "dm/bta_dm_api.c",
+ "dm/bta_dm_cfg.c",
+ "dm/bta_dm_ci.c",
+ "dm/bta_dm_main.c",
+ "dm/bta_dm_pm.c",
+ "dm/bta_dm_sco.c",
+ "gatt/bta_gattc_act.c",
+ "gatt/bta_gattc_api.c",
+ "gatt/bta_gattc_cache.c",
+ "gatt/bta_gattc_ci.c",
+ "gatt/bta_gattc_main.c",
+ "gatt/bta_gattc_utils.c",
+ "gatt/bta_gatts_act.c",
+ "gatt/bta_gatts_api.c",
+ "gatt/bta_gatts_main.c",
+ "gatt/bta_gatts_utils.c",
+ "hf_client/bta_hf_client_act.c",
+ "hf_client/bta_hf_client_api.c",
+ "hf_client/bta_hf_client_at.c",
+ "hf_client/bta_hf_client_cmd.c",
+ "hf_client/bta_hf_client_main.c",
+ "hf_client/bta_hf_client_rfc.c",
+ "hf_client/bta_hf_client_sdp.c",
+ "hf_client/bta_hf_client_sco.c",
+ "hh/bta_hh_act.c",
+ "hh/bta_hh_api.c",
+ "hh/bta_hh_cfg.c",
+ "hh/bta_hh_le.c",
+ "hh/bta_hh_main.c",
+ "hh/bta_hh_utils.c",
+ "hl/bta_hl_act.c",
+ "hl/bta_hl_api.c",
+ "hl/bta_hl_ci.c",
+ "hl/bta_hl_main.c",
+ "hl/bta_hl_sdp.c",
+ "hl/bta_hl_utils.c",
+ "jv/bta_jv_act.c",
+ "jv/bta_jv_api.c",
+ "jv/bta_jv_cfg.c",
+ "jv/bta_jv_main.c",
+ "mce/bta_mce_act.c",
+ "mce/bta_mce_api.c",
+ "mce/bta_mce_cfg.c",
+ "mce/bta_mce_main.c",
+ "pan/bta_pan_act.c",
+ "pan/bta_pan_api.c",
+ "pan/bta_pan_ci.c",
+ "pan/bta_pan_main.c",
+ "sdp/bta_sdp.c",
+ "sdp/bta_sdp_act.c",
+ "sdp/bta_sdp_api.c",
+ "sdp/bta_sdp_cfg.c",
+ "sys/bta_sys_conn.c",
+ "sys/bta_sys_main.c",
+ "sys/utl.c",
+ ]
+
+ include_dirs = [
+ "dm",
+ "hh",
+ "include",
+ "sys",
+ "//",
+ "//btcore/include",
+ "//gki/common",
+ "//gki/ulinux",
+ "//hci/include",
+ "//include",
+ "//stack/include",
+ "//stack/btm",
+ "//osi/include",
+ "//udrv/include",
+ "//utils/include",
+ "//vnd/include",
+ ]
+}
diff --git a/bta/ag/bta_ag_main.c b/bta/ag/bta_ag_main.c
index b550191..a3c1784 100644
--- a/bta/ag/bta_ag_main.c
+++ b/bta/ag/bta_ag_main.c
@@ -321,7 +321,7 @@
p_scb->codec_updated = FALSE;
#endif
/* set up timers */
- p_scb->act_timer.param = (UINT32) p_scb;
+ p_scb->act_timer.param = p_scb;
p_scb->act_timer.p_cback = bta_ag_timer_cback;
#if (BTM_WBS_INCLUDED == TRUE)
/* set eSCO mSBC setting to T2 as the preferred */
@@ -650,7 +650,7 @@
/* Start timer to han */
p_scb->colli_timer.p_cback = (TIMER_CBACK*)&bta_ag_colli_timer_cback;
- p_scb->colli_timer.param = (INT32)p_scb;
+ p_scb->colli_timer.param = p_scb;
bta_sys_start_timer(&p_scb->colli_timer, 0, BTA_AG_COLLISION_TIMER);
p_scb->colli_tmr_on = TRUE;
}
diff --git a/bta/ag/bta_ag_sco.c b/bta/ag/bta_ag_sco.c
index af6c9bc..c7b3023 100644
--- a/bta/ag/bta_ag_sco.c
+++ b/bta/ag/bta_ag_sco.c
@@ -693,7 +693,7 @@
/* Start timer to handle timeout */
p_scb->cn_timer.p_cback = (TIMER_CBACK*)&bta_ag_cn_timer_cback;
- p_scb->cn_timer.param = (INT32)p_scb;
+ p_scb->cn_timer.param = p_scb;
bta_sys_start_timer(&p_scb->cn_timer, 0, BTA_AG_CODEC_NEGO_TIMEOUT);
}
else
diff --git a/bta/av/bta_av_act.c b/bta/av/bta_av_act.c
index 75e0900..5d7588e 100644
--- a/bta/av/bta_av_act.c
+++ b/bta/av/bta_av_act.c
@@ -33,6 +33,7 @@
#include "utl.h"
#include "l2c_api.h"
#include "osi/include/list.h"
+#include "osi/include/osi.h"
#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
#include "bta_ar_api.h"
#endif
@@ -1467,7 +1468,12 @@
/* Possible collision : need to avoid outgoing processing while the timer is running */
p_cb->p_scb[xx]->coll_mask = BTA_AV_COLL_INC_TMR;
- p_cb->acp_sig_tmr.param = (UINT32)xx;
+
+ // TODO(armansito): Why is this variable called "xx" and
+ // why is it a signed integer? The callback reinterprets
+ // it as a UINT8 and then reassigns it as param that
+ // way, so should this be unsigned?
+ p_cb->acp_sig_tmr.param = INT_TO_PTR(xx);
p_cb->acp_sig_tmr.p_cback = (TIMER_CBACK*)&bta_av_acp_sig_timer_cback;
bta_sys_start_timer(&p_cb->acp_sig_tmr, 0, BTA_AV_ACP_SIG_TIME_VAL);
}
@@ -1564,7 +1570,7 @@
*******************************************************************************/
static void bta_av_acp_sig_timer_cback (TIMER_LIST_ENT *p_tle)
{
- UINT8 inx = (UINT8)p_tle->param;
+ UINT8 inx = PTR_TO_UINT(p_tle->param);
tBTA_AV_CB *p_cb = &bta_av_cb;
tBTA_AV_SCB *p_scb = NULL;
tBTA_AV_API_OPEN *p_buf;
@@ -1587,7 +1593,7 @@
/* We are still doing SDP. Run the timer again. */
p_scb->coll_mask |= BTA_AV_COLL_INC_TMR;
- p_cb->acp_sig_tmr.param = (UINT32)inx;
+ p_cb->acp_sig_tmr.param = UINT_TO_PTR(inx);
p_cb->acp_sig_tmr.p_cback = (TIMER_CBACK *)&bta_av_acp_sig_timer_cback;
bta_sys_start_timer(&p_cb->acp_sig_tmr, 0, BTA_AV_ACP_SIG_TIME_VAL);
}
diff --git a/bta/av/bta_av_main.c b/bta/av/bta_av_main.c
index 9a40929..3552911 100644
--- a/bta/av/bta_av_main.c
+++ b/bta/av/bta_av_main.c
@@ -397,25 +397,6 @@
}
/*******************************************************************************
-**
-** Function bta_av_free_scb
-**
-** Description free stream control block,
-**
-**
-** Returns void
-**
-*******************************************************************************/
-static void bta_av_free_scb(tBTA_AV_SCB *p_scb)
-{
- // NOTE(google) This free currently is not called
- assert(p_scb != NULL);
-
- list_free(p_scb->a2d_list);
- GKI_freebuf(p_scb);
-}
-
-/*******************************************************************************
*******************************************************************************/
void bta_av_conn_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data)
{
diff --git a/bta/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c
index 5775296..abf2240 100644
--- a/bta/dm/bta_dm_act.c
+++ b/bta/dm/bta_dm_act.c
@@ -41,6 +41,7 @@
#define LOG_TAG "bt_bta_dm"
#include "osi/include/log.h"
+#include "osi/include/osi.h"
#if (GAP_INCLUDED == TRUE)
#include "gap_api.h"
@@ -451,7 +452,7 @@
else
{
bta_dm_cb.disable_timer.p_cback = (TIMER_CBACK*)&bta_dm_disable_timer_cback;
- bta_dm_cb.disable_timer.param = 0;
+ bta_dm_cb.disable_timer.param = INT_TO_PTR(0);
bta_sys_start_timer(&bta_dm_cb.disable_timer, 0, 5000);
}
@@ -479,7 +480,7 @@
APPL_TRACE_EVENT(" bta_dm_disable_timer_cback trial %d ", p_tle->param);
- if(BTM_GetNumAclLinks() && p_tle->param == 0)
+ if(BTM_GetNumAclLinks() && PTR_TO_INT(p_tle->param) == 0)
{
for(i=0; i<bta_dm_cb.device_list.count; i++)
{
@@ -495,7 +496,7 @@
if (trigger_disc)
{
bta_dm_cb.disable_timer.p_cback = (TIMER_CBACK*)&bta_dm_disable_timer_cback;
- bta_dm_cb.disable_timer.param = 1;
+ bta_dm_cb.disable_timer.param = INT_TO_PTR(1);
bta_sys_start_timer(&bta_dm_cb.disable_timer, 0, 1500);
}
}
@@ -2076,7 +2077,6 @@
{
tSDP_UUID uuid;
- UINT16 num_attrs = 1;
tBTA_DM_MSG *p_msg;
memset (&uuid, 0, sizeof(tSDP_UUID));
@@ -4367,8 +4367,6 @@
tBTM_STATUS status = BTM_SUCCESS;
tBTA_DM_SEC sec_event;
char *p_name = NULL;
- UINT8 i;
- tBT_DEVICE_TYPE dev_type;
if (!bta_dm_cb.p_sec_cback)
return BTM_NOT_AUTHORIZED;
diff --git a/bta/dm/bta_dm_pm.c b/bta/dm/bta_dm_pm.c
index 43c9a5a..d0615bc 100644
--- a/bta/dm/bta_dm_pm.c
+++ b/bta/dm/bta_dm_pm.c
@@ -154,7 +154,6 @@
{
UINT8 i,j;
- UINT16 policy_setting;
UINT8 *p = NULL;
#if (BTM_SSR_INCLUDED == TRUE)
int index = BTA_DM_PM_SSR0;
diff --git a/bta/hf_client/bta_hf_client_main.c b/bta/hf_client/bta_hf_client_main.c
index 27c00cb..e582963 100644
--- a/bta/hf_client/bta_hf_client_main.c
+++ b/bta/hf_client/bta_hf_client_main.c
@@ -19,7 +19,14 @@
#include <string.h>
#include <stdlib.h>
+
+// TODO(armansito): cutils/properties.h is only being used to pull-in runtime
+// settings on Android. Remove this conditional include once we have a generic
+// way to obtain system properties.
+#if !defined(OS_GENERIC)
#include <cutils/properties.h>
+#endif // !defined(OS_GENERIC)
+
#include "bt_utils.h"
#include "bta_api.h"
#include "bta_sys.h"
@@ -372,7 +379,12 @@
*******************************************************************************/
static void bta_hf_client_api_enable(tBTA_HF_CLIENT_DATA *p_data)
{
+ // TODO(armansito): For non-Android systems we need a common method of
+ // loading system properties. Remove the conditionally compiled code once we
+ // have that in place.
+#if !defined(OS_GENERIC)
char value[PROPERTY_VALUE_MAX];
+#endif // !defined(OS_GENERIC)
/* initialize control block */
memset(&bta_hf_client_cb, 0, sizeof(tBTA_HF_CLIENT_CB));
@@ -380,12 +392,17 @@
/* store callback function */
bta_hf_client_cb.p_cback = p_data->api_enable.p_cback;
+ // TODO(armansito): For non-Android systems we need a common method of
+ // loading system properties. Remove the conditionally compiled code once we
+ // have that in place.
+#if !defined(OS_GENERIC)
/* check if mSBC support enabled */
property_get("ro.bluetooth.hfp.ver", value, "0");
if (strcmp(value,"1.6") == 0)
{
bta_hf_client_cb.msbc_enabled = TRUE;
}
+#endif // !defined(OS_GENERIC)
bta_hf_client_cb.scb.negotiated_codec = BTM_SCO_CODEC_CVSD;
diff --git a/bta/hl/bta_hl_sdp.c b/bta/hl/bta_hl_sdp.c
index f5b3fd1..f6cb909 100644
--- a/bta/hl/bta_hl_sdp.c
+++ b/bta/hl/bta_hl_sdp.c
@@ -50,7 +50,7 @@
{
return(FALSE);
}
- SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
+
item_cnt=0;
for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr && (item_cnt < 4) ; p_sattr = p_sattr->p_next_attr)
diff --git a/bta/hl/bta_hl_utils.c b/bta/hl/bta_hl_utils.c
index 0a0f326..3fa142b 100644
--- a/bta/hl/bta_hl_utils.c
+++ b/bta/hl/bta_hl_utils.c
@@ -1170,8 +1170,6 @@
for (i=0; i < BTA_HL_NUM_MCLS ; i ++)
{
- BTA_HL_GET_MCL_CB_PTR(app_idx, i);
-
if (bta_hl_cb.acb[app_idx].mcb[i].in_use &&
(!memcmp (bta_hl_cb.acb[app_idx].mcb[i].bd_addr, p_bd_addr, BD_ADDR_LEN)))
{
diff --git a/bta/jv/bta_jv_act.c b/bta/jv/bta_jv_act.c
index b7ea751..ea14d6d 100644
--- a/bta/jv/bta_jv_act.c
+++ b/bta/jv/bta_jv_act.c
@@ -25,6 +25,7 @@
#include <arpa/inet.h>
#include <pthread.h>
#include <stdlib.h>
+#include <string.h>
#include "osi/include/allocator.h"
#include "bt_types.h"
@@ -40,13 +41,14 @@
#include "sdp_api.h"
#include "l2c_api.h"
#include "port_api.h"
-#include <string.h>
#include "rfcdefs.h"
#include "avct_api.h"
#include "avdt_api.h"
#include "gap_api.h"
#include "l2c_api.h"
+#include "osi/include/osi.h"
+
/* one of these exists for each client */
struct fc_client {
@@ -75,22 +77,6 @@
static struct fc_client *fc_clients;
static struct fc_channel *fc_channels;
static uint32_t fc_next_id;
-static pthread_once_t fc_init_once = PTHREAD_ONCE_INIT;
-
-
-static void fc_init_work(void)
-{
- fc_clients = NULL;
- fc_channels = NULL;
- fc_next_id = 0;
-
- //more init here if needed...
-}
-
-static void fc_init(void)
-{
- pthread_once(&fc_init_once, fc_init_work);
-}
static void fcchan_conn_chng_cbk(UINT16 chan, BD_ADDR bd_addr, BOOLEAN connected,
@@ -543,8 +529,6 @@
/* rfc handle bd addr retrieval requires core stack handle */
if (bRfcHandle)
{
- UINT32 hi = ((jv_handle & BTA_JV_RFC_HDL_MASK) & ~BTA_JV_RFCOMM_MASK) - 1;
- UINT32 si = BTA_JV_RFC_HDL_TO_SIDX(jv_handle);
for (j = 0; j < BTA_JV_MAX_RFC_CONN; j++)
{
if (jv_handle == bta_jv_cb.port_cb[j].handle)
@@ -869,7 +853,6 @@
static void bta_jv_start_discovery_cback(UINT16 result, void * user_data)
{
tBTA_JV_STATUS status;
- UINT8 old_sdp_act = bta_jv_cb.sdp_active;
APPL_TRACE_DEBUG("bta_jv_start_discovery_cback res: 0x%x", result);
@@ -1229,7 +1212,6 @@
tL2CAP_CFG_INFO cfg;
tBTA_JV_L2CAP_START evt_data;
tBTA_JV_API_L2CAP_SERVER *ls = &(p_data->l2cap_server);
- INT32 use_etm = FALSE;
UINT8 chan_mode_mask = GAP_FCR_CHAN_OPT_BASIC;
tL2CAP_ERTM_INFO *ertm_info = NULL;
@@ -1670,7 +1652,7 @@
return 1;
}
}
- APPL_TRACE_DEBUG("find_rfc_pcb: cannot find rfc_cb from user data:%d", (UINT32)user_data);
+ APPL_TRACE_DEBUG("find_rfc_pcb: cannot find rfc_cb from user data: %u", PTR_TO_UINT(user_data));
return 0;
}
@@ -1705,38 +1687,6 @@
/*******************************************************************************
**
-** Function bta_jv_get_num_rfc_listen
-**
-** Description when a RFCOMM connection goes down, make sure that there's only
-** one port stays listening on this scn.
-**
-** Returns
-**
-*******************************************************************************/
-static UINT8 bta_jv_get_num_rfc_listen(tBTA_JV_RFC_CB *p_cb)
-{
- UINT8 listen=1;
-
- if (p_cb->max_sess > 1)
- {
- listen = 0;
- for (UINT8 i=0; i<p_cb->max_sess; i++)
- {
- if (p_cb->rfc_hdl[i] != 0)
- {
- const tBTA_JV_PCB *p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[i] - 1];
- if (BTA_JV_ST_SR_LISTEN == p_pcb->state)
- {
- listen++;
- }
- }
- }
- }
- return listen;
-}
-
-/*******************************************************************************
-**
** Function bta_jv_port_mgmt_sr_cback
**
** Description callback for port mamangement function of rfcomm
@@ -2555,7 +2505,6 @@
static void fcchan_data_cbk(UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf)
{
tBTA_JV evt_data;
- tBTA_JV evt_open;
struct fc_channel *tc;
struct fc_client *t = NULL;
tBTA_JV_L2CAP_CBACK *sock_cback = NULL;
@@ -2686,7 +2635,6 @@
tBTA_JV_API_L2CAP_SERVER *ss = &(p_data->l2cap_server);
tBTA_JV_L2CAP_START evt_data;
struct fc_client *t;
- uint16_t handle;
evt_data.handle = GAP_INVALID_HANDLE;
evt_data.status = BTA_JV_FAILURE;
diff --git a/bta/sdp/bta_sdp_act.c b/bta/sdp/bta_sdp_act.c
index f3e6005..7755c04 100644
--- a/bta/sdp/bta_sdp_act.c
+++ b/bta/sdp/bta_sdp_act.c
@@ -94,11 +94,9 @@
static void bta_create_mns_sdp_record(bluetooth_sdp_record *record, tSDP_DISC_REC *p_rec)
{
- tSDP_DISCOVERY_DB *db = p_bta_sdp_cfg->p_sdp_db;
tSDP_DISC_ATTR *p_attr;
tSDP_PROTOCOL_ELEM pe;
UINT16 pversion = 0;
- UINT8 offset = 0;
record->mns.hdr.type = SDP_TYPE_MAP_MNS;
record->mns.hdr.service_name_length = 0;
record->mns.hdr.service_name = NULL;
@@ -136,7 +134,6 @@
static void bta_create_mas_sdp_record(bluetooth_sdp_record *record, tSDP_DISC_REC *p_rec)
{
- tSDP_DISCOVERY_DB *db = p_bta_sdp_cfg->p_sdp_db;
tSDP_DISC_ATTR *p_attr;
tSDP_PROTOCOL_ELEM pe;
UINT16 pversion = -1;
@@ -190,7 +187,6 @@
static void bta_create_pse_sdp_record(bluetooth_sdp_record *record, tSDP_DISC_REC *p_rec)
{
- tSDP_DISCOVERY_DB *db = p_bta_sdp_cfg->p_sdp_db;
tSDP_DISC_ATTR *p_attr;
UINT16 pversion;
tSDP_PROTOCOL_ELEM pe;
@@ -237,7 +233,6 @@
static void bta_create_ops_sdp_record(bluetooth_sdp_record *record, tSDP_DISC_REC *p_rec)
{
- tSDP_DISCOVERY_DB *db = p_bta_sdp_cfg->p_sdp_db;
tSDP_DISC_ATTR *p_attr, *p_sattr;
tSDP_PROTOCOL_ELEM pe;
UINT16 pversion = -1;
@@ -350,9 +345,7 @@
static void bta_create_raw_sdp_record(bluetooth_sdp_record *record, tSDP_DISC_REC *p_rec)
{
- tSDP_DISCOVERY_DB *db = p_bta_sdp_cfg->p_sdp_db;
tSDP_DISC_ATTR *p_attr;
- UINT16 pversion;
tSDP_PROTOCOL_ELEM pe;
record->hdr.type = SDP_TYPE_RAW;
@@ -393,7 +386,6 @@
tSDP_DISC_REC *p_rec = NULL;
tBTA_SDP_SEARCH_COMP evt_data = {0}; // We need to zero-initialize
tBTA_SDP_STATUS status = BTA_SDP_FAILURE;
- UINT16 uuid16 = 0;
int count = 0;
tBT_UUID su;
APPL_TRACE_DEBUG("%s() - res: 0x%x", __func__, result);
diff --git a/bta/sys/bta_sys_main.c b/bta/sys/bta_sys_main.c
index b03c2d1..f05ddac 100644
--- a/bta/sys/bta_sys_main.c
+++ b/bta/sys/bta_sys_main.c
@@ -24,6 +24,7 @@
#define LOG_TAG "bt_bta_sys_main"
#include <assert.h>
+#include <pthread.h>
#include <string.h>
#include "osi/include/alarm.h"
diff --git a/btcore/BUILD.gn b/btcore/BUILD.gn
new file mode 100644
index 0000000..56719ad
--- /dev/null
+++ b/btcore/BUILD.gn
@@ -0,0 +1,57 @@
+#
+# Copyright (C) 2015 Google, Inc.
+#
+# 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.
+#
+
+static_library("btcore") {
+ sources = [
+ "src/bdaddr.c",
+ "src/counter.c",
+ "src/device_class.c",
+ "src/module.c",
+ "src/property.c",
+ "src/uuid.c",
+ ]
+
+ include_dirs = [
+ "include",
+ "//osi/include",
+ "//",
+ ]
+}
+
+executable("net_test_btcore") {
+ testonly = true
+ sources = [
+ "test/bdaddr_test.cpp",
+ "test/counter_test.cpp",
+ "test/device_class_test.cpp",
+ "test/property_test.cpp",
+ "test/uuid_test.cpp",
+ "//osi/test/AllocationTestHarness.cpp",
+ ]
+
+ include_dirs = [
+ "include",
+ "//",
+ ]
+
+ deps = [
+ "//btcore",
+ "//osi",
+ "//third_party/gtest:gtest_main",
+ ]
+
+ libs = [ "-lpthread", "-lrt", "-ldl" ]
+}
diff --git a/btcore/src/counter.c b/btcore/src/counter.c
index 08aa518..89f967d 100644
--- a/btcore/src/counter.c
+++ b/btcore/src/counter.c
@@ -21,6 +21,8 @@
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
+#include <pthread.h>
+#include <stdarg.h>
#include <string.h>
#include <sys/eventfd.h>
@@ -142,7 +144,7 @@
return future_new_immediate(FUTURE_SUCCESS);
}
-module_t counter_module = {
+EXPORT_SYMBOL module_t counter_module = {
.name = COUNTER_MODULE,
.init = counter_init,
.start_up = NULL,
diff --git a/btif/BUILD.gn b/btif/BUILD.gn
new file mode 100644
index 0000000..cee6c03
--- /dev/null
+++ b/btif/BUILD.gn
@@ -0,0 +1,89 @@
+#
+# Copyright (C) 2015 Google, Inc.
+#
+# 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.
+#
+
+static_library("btif") {
+ sources = [
+ "src/btif_av.c",
+ "src/btif_config.c",
+ "src/btif_config_transcode.cpp",
+ "src/btif_core.c",
+ "src/btif_debug.c",
+ "src/btif_debug_btsnoop.c",
+ "src/btif_debug_conn.c",
+ "src/btif_dm.c",
+ "src/btif_gatt.c",
+ "src/btif_gatt_client.c",
+ "src/btif_gatt_multi_adv_util.c",
+ "src/btif_gatt_server.c",
+ "src/btif_gatt_test.c",
+ "src/btif_gatt_util.c",
+ "src/btif_hf.c",
+ "src/btif_hf_client.c",
+ "src/btif_hh.c",
+ "src/btif_hl.c",
+ "src/btif_mce.c",
+ "src/btif_media_task.c",
+ "src/btif_pan.c",
+ "src/btif_profile_queue.c",
+ "src/btif_rc.c",
+ "src/btif_sdp.c",
+ "src/btif_sdp_server.c",
+ "src/btif_sm.c",
+ "src/btif_sock.c",
+ "src/btif_sock_l2cap.c",
+ "src/btif_sock_rfc.c",
+ "src/btif_sock_sco.c",
+ "src/btif_sock_sdp.c",
+ "src/btif_sock_thread.c",
+ "src/btif_sock_util.c",
+ "src/btif_storage.c",
+ "src/btif_util.c",
+ "src/stack_manager.c",
+ ]
+
+ # BTIF callouts
+ sources += [
+ "co/bta_ag_co.c",
+ "co/bta_dm_co.c",
+ "co/bta_av_co.c",
+ "co/bta_hh_co.c",
+ "co/bta_hl_co.c",
+ "co/bta_pan_co.c",
+ "co/bta_gattc_co.c",
+ "co/bta_gatts_co.c",
+ ]
+
+ include_dirs = [
+ "include",
+ "//",
+ "//audio_a2dp_hw",
+ "//bta/include",
+ "//bta/sys",
+ "//btcore/include",
+ "//embdrv/sbc/encoder/include",
+ "//gki/common",
+ "//hci/include",
+ "//osi/include",
+ "//stack/a2dp",
+ "//stack/btm",
+ "//stack/include",
+ "//third_party/tinyxml2",
+ "//include",
+ "//udrv/include",
+ "//utils/include",
+ "//vnd/include",
+ ]
+}
diff --git a/btif/co/bta_hh_co.c b/btif/co/bta_hh_co.c
index b5c845a..bc4db01 100644
--- a/btif/co/bta_hh_co.c
+++ b/btif/co/bta_hh_co.c
@@ -518,8 +518,6 @@
{
UNUSED(app_id);
- unsigned idx = 0;
-
bdstr_t bdstr;
sprintf(bdstr, "%02x:%02x:%02x:%02x:%02x:%02x",
remote_bda[0], remote_bda[1], remote_bda[2],
diff --git a/btif/src/bluetooth.c b/btif/src/bluetooth.c
index f842e5c..e056061 100644
--- a/btif/src/bluetooth.c
+++ b/btif/src/bluetooth.c
@@ -486,7 +486,7 @@
.open = open_bluetooth_stack,
};
-struct hw_module_t HAL_MODULE_INFO_SYM = {
+EXPORT_SYMBOL struct hw_module_t HAL_MODULE_INFO_SYM = {
.tag = HARDWARE_MODULE_TAG,
.version_major = 1,
.version_minor = 0,
diff --git a/btif/src/btif_av.c b/btif/src/btif_av.c
index ee02ee6..3727d65 100644
--- a/btif/src/btif_av.c
+++ b/btif/src/btif_av.c
@@ -329,7 +329,7 @@
BTIF_TRACE_DEBUG("BTA_AV_RC_OPEN_EVT received w/o AV");
memset(&tle_av_open_on_rc, 0, sizeof(tle_av_open_on_rc));
- tle_av_open_on_rc.param = (UINT32)btif_initiate_av_open_tmr_hdlr;
+ tle_av_open_on_rc.param = btif_initiate_av_open_tmr_hdlr;
btu_start_timer(&tle_av_open_on_rc, BTU_TTYPE_USER_FUNC,
BTIF_TIMEOUT_AV_OPEN_ON_RC_SECS);
btif_rc_handler(event, p_data);
diff --git a/btif/src/btif_config.c b/btif/src/btif_config.c
index 3cbff50..f47b37f 100644
--- a/btif/src/btif_config.c
+++ b/btif/src/btif_config.c
@@ -23,6 +23,7 @@
#include <pthread.h>
#include <stdio.h>
#include <string.h>
+#include <unistd.h>
#include "osi/include/alarm.h"
#include "osi/include/allocator.h"
@@ -143,7 +144,7 @@
return future_new_immediate(FUTURE_SUCCESS);
}
-const module_t btif_config_module = {
+EXPORT_SYMBOL const module_t btif_config_module = {
.name = BTIF_CONFIG_MODULE,
.init = init,
.start_up = NULL,
diff --git a/btif/src/btif_core.c b/btif/src/btif_core.c
index d552e5c..82ce13d 100644
--- a/btif/src/btif_core.c
+++ b/btif/src/btif_core.c
@@ -27,7 +27,6 @@
***********************************************************************************/
#include <ctype.h>
-#include <cutils/properties.h>
#include <dirent.h>
#include <fcntl.h>
#include <hardware/bluetooth.h>
@@ -35,6 +34,16 @@
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <unistd.h>
+
+/**
+ * TODO(armansito): On OSs other than Android, the sys/properties.h system
+ * does not exist. Remove this conditional include once we have a generic way
+ * to obtain system properties.
+ */
+#if !defined(OS_GENERIC)
+#include <cutils/properties.h>
+#endif /* !defined(OS_GENERIC) */
#define LOG_TAG "bt_btif_core"
#include "btcore/include/bdaddr.h"
@@ -321,6 +330,13 @@
char val[256];
uint8_t valid_bda = FALSE;
int val_size = 0;
+
+ /**
+ * TODO(armansito): On OSs other than Android, the sys/properties.h system
+ * does not exist. Remove this conditional include once we have a generic way
+ * to obtain system properties.
+ */
+#if !defined(OS_GENERIC)
const uint8_t null_bdaddr[BD_ADDR_LEN] = {0,0,0,0,0,0};
/* Get local bdaddr storage path from property */
@@ -369,6 +385,7 @@
local_addr->address[0], local_addr->address[1], local_addr->address[2],
local_addr->address[3], local_addr->address[4], local_addr->address[5]);
}
+#endif /* !defined(OS_GENERIC) */
/* Generate new BDA if necessary */
if (!valid_bda)
@@ -391,8 +408,16 @@
BTIF_TRACE_DEBUG("No preset BDA. Generating BDA: %s for prop %s",
(char*)bdstr, PERSIST_BDADDR_PROPERTY);
+
+ /**
+ * TODO(armansito): On OSs other than Android, the sys/properties.h system
+ * does not exist. Remove this conditional include once we have a generic way
+ * to obtain system properties.
+ */
+#if !defined(OS_GENERIC)
if (property_set(PERSIST_BDADDR_PROPERTY, (char*)bdstr) < 0)
BTIF_TRACE_ERROR("Failed to set random BDA in prop %s",PERSIST_BDADDR_PROPERTY);
+#endif /* !defined(OS_GENERIC) */
}
//save the bd address to config file
@@ -849,9 +874,6 @@
local_le_features.version_supported = cmn_vsc_cb.version_supported;
local_le_features.total_trackable_advertisers =
cmn_vsc_cb.total_trackable_advertisers;
-
- local_le_features.extended_scan_support = cmn_vsc_cb.extended_scan_support > 0;
- local_le_features.debug_logging_supported = cmn_vsc_cb.debug_logging_supported > 0;
memcpy(prop.val, &local_le_features, prop.len);
#endif
}
diff --git a/btif/src/btif_dm.c b/btif/src/btif_dm.c
index 351a312..24aad27 100644
--- a/btif/src/btif_dm.c
+++ b/btif/src/btif_dm.c
@@ -37,7 +37,15 @@
#include <hardware/bluetooth.h>
+/**
+ * TODO(armansito): cutils/properties.h is only being used to pull-in runtime
+ * settings on Android. Remove this conditional include once we have a generic
+ * way to obtain system properties.
+ */
+#if !defined(OS_GENERIC)
#include <cutils/properties.h>
+#endif /* !defined(OS_GENERIC) */
+
#include "gki.h"
#include "btu.h"
#include "btcore/include/bdaddr.h"
@@ -2722,6 +2730,12 @@
#ifdef BTIF_DM_OOB_TEST
void btif_dm_load_local_oob(void)
{
+ /**
+ * TODO(armansito): On OSs other than Android, the sys/properties.h system
+ * does not exist. Remove this conditional include once we have a generic way
+ * to obtain system properties.
+ */
+#if !defined(OS_GENERIC)
char prop_oob[PROPERTY_VALUE_MAX];
property_get("service.brcm.bt.oob", prop_oob, "3");
BTIF_TRACE_DEBUG("btif_dm_load_local_oob prop_oob = %s",prop_oob);
@@ -2734,14 +2748,21 @@
BTIF_TRACE_DEBUG("btif_dm_load_local_oob: read OOB, call BTA_DmLocalOob()");
BTA_DmLocalOob();
}
-#else
+#else /* (BTM_OOB_INCLUDED != TRUE) */
BTIF_TRACE_ERROR("BTM_OOB_INCLUDED is FALSE!!(btif_dm_load_local_oob)");
-#endif
+#endif /* (BTM_OOB_INCLUDED == TRUE) */
}
+#endif /* !defined(OS_GENERIC) */
}
void btif_dm_proc_loc_oob(BOOLEAN valid, BT_OCTET16 c, BT_OCTET16 r)
{
+ /**
+ * TODO(armansito): On OSs other than Android, the sys/properties.h system
+ * does not exist. Remove this conditional include once we have a generic way
+ * to obtain system properties.
+ */
+#if !defined(OS_GENERIC)
FILE *fp;
char *path_a = "/data/misc/bluedroid/LOCAL/a.key";
char *path_b = "/data/misc/bluedroid/LOCAL/b.key";
@@ -2777,9 +2798,17 @@
}
}
}
+#endif /* !defined(OS_GENERIC) */
}
+
BOOLEAN btif_dm_proc_rmt_oob(BD_ADDR bd_addr, BT_OCTET16 p_c, BT_OCTET16 p_r)
{
+ /**
+ * TODO(armansito): On OSs other than Android, the sys/properties.h system
+ * does not exist. Remove this conditional include once we have a generic way
+ * to obtain system properties.
+ */
+#if !defined(OS_GENERIC)
char t[128];
FILE *fp;
char *path_a = "/data/misc/bluedroid/LOCAL/a.key";
@@ -2830,6 +2859,9 @@
}
BTIF_TRACE_DEBUG("btif_dm_proc_rmt_oob result=%d",result);
return result;
+#else /* defined(OS_GENERIC) */
+ return FALSE;
+#endif /* !defined(OS_GENERIC) */
}
#endif /* BTIF_DM_OOB_TEST */
#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
@@ -3229,6 +3261,12 @@
}
static char* btif_get_default_local_name() {
+ /**
+ * TODO(armansito): On OSs other than Android, the sys/properties.h system
+ * does not exist. Remove this conditional include once we have a generic way
+ * to obtain system properties.
+ */
+#if !defined(OS_GENERIC)
if (btif_default_local_name[0] == '\0')
{
int max_len = sizeof(btif_default_local_name) - 1;
@@ -3244,5 +3282,6 @@
}
btif_default_local_name[max_len] = '\0';
}
+#endif /* !defined(OS_GENERIC) */
return btif_default_local_name;
}
diff --git a/btif/src/btif_gatt_client.c b/btif/src/btif_gatt_client.c
index 295f74a..1c8f179 100644
--- a/btif/src/btif_gatt_client.c
+++ b/btif/src/btif_gatt_client.c
@@ -247,7 +247,7 @@
static bt_status_t btif_gattc_multi_adv_disable(int client_if);
static void btif_multi_adv_stop_cb(void *p_tle)
{
- int client_if = ((TIMER_LIST_ENT*)p_tle)->data;
+ int client_if = PTR_TO_INT(((TIMER_LIST_ENT*)p_tle)->data);
btif_gattc_multi_adv_disable(client_if); // Does context switch
}
diff --git a/btif/src/btif_gatt_multi_adv_util.c b/btif/src/btif_gatt_multi_adv_util.c
index 63bca08..692945d 100644
--- a/btif/src/btif_gatt_multi_adv_util.c
+++ b/btif/src/btif_gatt_multi_adv_util.c
@@ -633,8 +633,8 @@
btu_stop_timer_oneshot(&p_multi_adv_data_cb->inst_cb[cbindex].tle_limited_timer);
memset(&p_multi_adv_data_cb->inst_cb[cbindex].tle_limited_timer, 0, sizeof(TIMER_LIST_ENT));
- p_multi_adv_data_cb->inst_cb[cbindex].tle_limited_timer.param = (UINT32)cb;
- p_multi_adv_data_cb->inst_cb[cbindex].tle_limited_timer.data = (UINT32)client_if;
+ p_multi_adv_data_cb->inst_cb[cbindex].tle_limited_timer.param = cb;
+ p_multi_adv_data_cb->inst_cb[cbindex].tle_limited_timer.data = INT_TO_PTR(client_if);
btu_start_timer_oneshot(&p_multi_adv_data_cb->inst_cb[cbindex].tle_limited_timer,
BTU_TTYPE_USER_FUNC, p_multi_adv_data_cb->inst_cb[cbindex].timeout_s);
}
diff --git a/btif/src/btif_hf.c b/btif/src/btif_hf.c
index ede52a7..69b76a5 100644
--- a/btif/src/btif_hf.c
+++ b/btif/src/btif_hf.c
@@ -29,6 +29,7 @@
#include <hardware/bt_hf.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
#define LOG_TAG "bt_btif_hf"
#include "btif_common.h"
diff --git a/btif/src/btif_hf_client.c b/btif/src/btif_hf_client.c
index ee78a8a..0fe3699 100644
--- a/btif/src/btif_hf_client.c
+++ b/btif/src/btif_hf_client.c
@@ -30,7 +30,15 @@
#include <hardware/bt_hf_client.h>
#include <stdlib.h>
#include <string.h>
+
+/**
+ * TODO(armansito): On OSs other than Android, the sys/properties.h system
+ * does not exist. Remove this conditional include once we have a generic way
+ * to obtain system properties.
+ */
+#if !defined(OS_GENERIC)
#include <cutils/properties.h>
+#endif /* !defined(OS_GENERIC) */
#define LOG_TAG "bt_btif_hfc"
#include "btif_common.h"
@@ -71,9 +79,19 @@
** Static variables
************************************************************************************/
static bthf_client_callbacks_t *bt_hf_client_callbacks = NULL;
-char btif_hf_client_version[PROPERTY_VALUE_MAX];
static UINT32 btif_hf_client_features = 0;
+/**
+ * TODO(armansito): On OSs other than Android, the sys/properties.h system
+ * does not exist. Since that is how the HFP version is currently obtained, on
+ * systems other than Android, hardcode 1.5 as the profile version for now,
+ * until there is a generic way to obtain these configuration properties.
+ */
+#if defined(OS_GENERIC)
+const char btif_hf_client_version[] = "1.5";
+#else /* !defined(OS_GENERIC) */
+char btif_hf_client_version[PROPERTY_VALUE_MAX];
+#endif /* defined(OS_GENERIC) */
#define CHECK_BTHF_CLIENT_INIT() if (bt_hf_client_callbacks == NULL)\
{\
@@ -937,7 +955,14 @@
{
BTIF_TRACE_EVENT("%s enable:%d", __FUNCTION__, b_enable);
+/**
+ * TODO(armansito): On OSs other than Android, the sys/properties.h system
+ * does not exist. Since that is how the HFP version is currently obtained, on
+ * systems other than Android we're hardcoding the version to 1.5 above.
+ */
+#if !defined(OS_GENERIC)
property_get("ro.bluetooth.hfp.ver", btif_hf_client_version, "1.5");
+#endif /* !defined(OS_GENERIC) */
if (b_enable)
{
diff --git a/btif/src/btif_hh.c b/btif/src/btif_hh.c
index 3b9220a..26102e6 100644
--- a/btif/src/btif_hh.c
+++ b/btif/src/btif_hh.c
@@ -30,6 +30,7 @@
#include <stdlib.h>
#include <errno.h>
#include <string.h>
+#include <unistd.h>
#define LOG_TAG "bt_btif_hh"
@@ -433,7 +434,7 @@
{
BTIF_TRACE_DEBUG("Start VUP timer ");
memset(&p_dev->vup_timer, 0, sizeof(TIMER_LIST_ENT));
- p_dev->vup_timer.param = (UINT32)btif_hh_tmr_hdlr;
+ p_dev->vup_timer.param = btif_hh_tmr_hdlr;
btu_start_timer(&p_dev->vup_timer, BTU_TTYPE_USER_FUNC,
BTIF_TIMEOUT_VUP_SECS);
}
diff --git a/btif/src/btif_hl.c b/btif/src/btif_hl.c
index 9d0c0d7..2f370a5 100644
--- a/btif/src/btif_hl.c
+++ b/btif/src/btif_hl.c
@@ -358,7 +358,7 @@
{
BTIF_TRACE_DEBUG("Start CCH timer ");
memset(&p_mcb->cch_timer, 0, sizeof(TIMER_LIST_ENT));
- p_mcb->cch_timer.param = (UINT32)btif_hl_tmr_hdlr;
+ p_mcb->cch_timer.param = btif_hl_tmr_hdlr;
btu_start_timer(&p_mcb->cch_timer, BTU_TTYPE_USER_FUNC,
BTIF_TIMEOUT_CCH_NO_DCH_SECS);
}
@@ -1214,10 +1214,9 @@
if (btif_hl_find_app_idx(app_id, &app_idx) )
{
- BTIF_HL_GET_APP_CB_PTR(app_idx);
if (btif_hl_find_mcl_idx(app_idx, bd_addr, &mcl_idx))
{
- p_mcb =BTIF_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ p_mcb = BTIF_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
BTIF_TRACE_DEBUG("app_idx=%d mcl_idx=%d",app_idx, mcl_idx);
BTIF_TRACE_DEBUG("valid_spd_idx=%d sdp_idx=%d",p_mcb->valid_sdp_idx, p_mcb->sdp_idx);
@@ -1227,7 +1226,7 @@
num_mdeps = p_rec->num_mdeps;
BTIF_TRACE_DEBUG("num_mdeps=%d", num_mdeps);
- for (i=0; i< num_mdeps; i++)
+ for (i = 0; i < num_mdeps; i++)
{
BTIF_TRACE_DEBUG("p_rec->mdep_cfg[%d].mdep_role=%d",i, p_rec->mdep_cfg[i].mdep_role);
BTIF_TRACE_DEBUG("p_rec->mdep_cfg[%d].data_type =%d",i, p_rec->mdep_cfg[i].data_type );
@@ -2592,8 +2591,6 @@
BTIF_TRACE_DEBUG("app_idx=%d", app_idx);
if (btif_hl_find_mcl_idx(app_idx, p_data->cch_open_cfm.bd_addr, &mcl_idx))
{
- BTIF_HL_GET_APP_CB_PTR(app_idx);
-
p_mcb = BTIF_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
BTIF_TRACE_DEBUG("mcl_idx=%d, mcl_handle=%d", mcl_idx,p_data->cch_open_cfm.mcl_handle);
p_mcb->mcl_handle = p_data->cch_open_cfm.mcl_handle;
@@ -2779,9 +2776,6 @@
if (btif_hl_find_mcl_idx_using_app_idx(p_data->dch_open_ind.mcl_handle, orig_app_idx, &mcl_idx ))
{
- BTIF_HL_GET_APP_CB_PTR(orig_app_idx);
- BTIF_HL_GET_MCL_CB_PTR(orig_app_idx, mcl_idx);
-
if (btif_hl_find_avail_mdl_idx(orig_app_idx, mcl_idx, &mdl_idx))
{
p_dcb = BTIF_HL_GET_MDL_CB_PTR(orig_app_idx, mcl_idx, mdl_idx);
@@ -2858,8 +2852,6 @@
if (btif_hl_find_mcl_idx_using_app_idx(p_data->dch_open_cfm.mcl_handle, app_idx, &mcl_idx ))
{
- BTIF_HL_GET_APP_CB_PTR(app_idx);
- BTIF_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
p_pcb = BTIF_HL_GET_PCB_PTR(app_idx, mcl_idx);
if (btif_hl_find_avail_mdl_idx(app_idx, mcl_idx, &mdl_idx))
@@ -2932,8 +2924,6 @@
if (btif_hl_find_mcl_idx_using_app_idx(p_data->dch_reconnect_cfm.mcl_handle, app_idx, &mcl_idx ))
{
- BTIF_HL_GET_APP_CB_PTR(app_idx);
- BTIF_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
p_pcb = BTIF_HL_GET_PCB_PTR(app_idx, mcl_idx);
if (btif_hl_find_avail_mdl_idx(app_idx, mcl_idx, &mdl_idx))
@@ -3011,7 +3001,6 @@
p_acb = BTIF_HL_GET_APP_CB_PTR(app_idx);
BTIF_TRACE_DEBUG("btif_hl_proc_dch_reconnect_ind: app_idx = %d, mcl_idx = %d",
app_idx, mcl_idx);
- BTIF_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
if (btif_hl_find_avail_mdl_idx(app_idx, mcl_idx, &mdl_idx))
{
@@ -3280,9 +3269,6 @@
BOOLEAN send_chan_cb=TRUE;
tBTA_HL_REG_PARAM reg_param;
btif_hl_app_cb_t *p_acb;
- bthl_app_reg_state_t reg_state = BTHL_APP_REG_STATE_REG_FAILED;
- UINT8 preg_idx;
- bt_status_t bt_status;
BTIF_TRACE_DEBUG("%s event %d", __FUNCTION__, event);
btif_hl_display_calling_process_name();
@@ -4163,7 +4149,6 @@
if (btif_hl_find_app_idx(((UINT8)app_id), &app_idx))
{
evt_param.unreg.app_idx = app_idx;
- BTIF_HL_GET_APP_CB_PTR(app_idx);
reg_counter --;
len = sizeof(btif_hl_unreg_t);
status = btif_transfer_context (btif_hl_proc_cb_evt, BTIF_HL_UNREG_APP,
@@ -4393,9 +4378,6 @@
if(btif_hl_find_app_idx_using_mdepId(mdep_id,&app_idx))
{
-
- BTIF_HL_GET_APP_CB_PTR(app_idx);
-
p_mdl = BTIF_HL_GET_MDL_CFG_PTR(app_idx, item_idx);
if (p_mdl)
{
diff --git a/btif/src/btif_pan.c b/btif/src/btif_pan.c
index c3dec2a..256568c 100644
--- a/btif/src/btif_pan.c
+++ b/btif/src/btif_pan.c
@@ -46,6 +46,7 @@
#include <sys/prctl.h>
#include <linux/if_tun.h>
#include <linux/if_ether.h>
+#include <unistd.h>
#define LOG_TAG "bt_btif_pan"
#include "btif_common.h"
@@ -389,7 +390,7 @@
btpan_cb.flow = enable;
if (enable) {
btsock_thread_add_fd(pan_pth, btpan_cb.tap_fd, 0, SOCK_THREAD_FD_RD, 0);
- bta_dmexecutecallback(btu_exec_tap_fd_read, (void *)btpan_cb.tap_fd);
+ bta_dmexecutecallback(btu_exec_tap_fd_read, INT_TO_PTR(btpan_cb.tap_fd));
}
}
@@ -659,7 +660,7 @@
#define IS_EXCEPTION(e) ((e) & (POLLHUP | POLLRDHUP | POLLERR | POLLNVAL))
static void btu_exec_tap_fd_read(void *p_param) {
struct pollfd ufd;
- int fd = (int)p_param;
+ int fd = PTR_TO_INT(p_param);
if (fd == INVALID_FD || fd != btpan_cb.tap_fd)
return;
@@ -758,5 +759,5 @@
btpan_tap_close(fd);
btif_pan_close_all_conns();
} else if (flags & SOCK_THREAD_FD_RD)
- bta_dmexecutecallback(btu_exec_tap_fd_read, (void *)fd);
+ bta_dmexecutecallback(btu_exec_tap_fd_read, INT_TO_PTR(fd));
}
diff --git a/btif/src/btif_rc.c b/btif/src/btif_rc.c
index e4bf771..10b6738 100644
--- a/btif/src/btif_rc.c
+++ b/btif/src/btif_rc.c
@@ -26,7 +26,10 @@
*****************************************************************************/
#include <hardware/bluetooth.h>
#include <fcntl.h>
+#include <pthread.h>
#include <string.h>
+#include <unistd.h>
+
#include "bta_api.h"
#include "bta_av_api.h"
#include "avrc_defs.h"
diff --git a/btif/src/btif_sdp.c b/btif/src/btif_sdp.c
index f728605..b14d6cb 100644
--- a/btif/src/btif_sdp.c
+++ b/btif/src/btif_sdp.c
@@ -108,12 +108,12 @@
}
case BTA_SDP_CREATE_RECORD_USER_EVT:
{
- on_create_record_event((int)user_data);
+ on_create_record_event(PTR_TO_INT(user_data));
break;
}
case BTA_SDP_REMOVE_RECORD_USER_EVT:
{
- on_remove_record_event((int)user_data);
+ on_remove_record_event(PTR_TO_INT(user_data));
break;
}
default:
@@ -147,7 +147,6 @@
static bt_status_t search(bt_bdaddr_t *bd_addr, const uint8_t *uuid)
{
- bdstr_t bdstr;
tSDP_UUID sdp_uuid;
sdp_uuid.len = 16;
memcpy(sdp_uuid.uu.uuid128, uuid, sizeof(sdp_uuid.uu.uuid128));
diff --git a/btif/src/btif_sdp_server.c b/btif/src/btif_sdp_server.c
index 5be23f0..f22df99 100644
--- a/btif/src/btif_sdp_server.c
+++ b/btif/src/btif_sdp_server.c
@@ -32,13 +32,13 @@
#include <pthread.h>
#define LOG_TAG "BTIF_SDP_SERVER"
-#include "allocator.h"
#include "btif_common.h"
#include "btif_util.h"
#include "bta_sdp_api.h"
#include "bta_sys.h"
-#include "utl.h"
#include "btif_sock_util.h"
+#include "osi/include/allocator.h"
+#include "utl.h"
static pthread_mutex_t sdp_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
@@ -184,7 +184,6 @@
* user2_ptr. */
static int alloc_sdp_slot(bluetooth_sdp_record* in_record) {
int i;
- char* tmp_ptr = NULL;
int record_size = get_sdp_records_size(in_record, 1);
bluetooth_sdp_record* record = osi_malloc(record_size);
@@ -281,7 +280,7 @@
if(handle < 0)
return BT_STATUS_FAIL;
- BTA_SdpCreateRecordByUser((void*) handle);
+ BTA_SdpCreateRecordByUser(INT_TO_PTR(handle));
*record_handle = handle;
@@ -298,7 +297,7 @@
/* Pass the actual record handle */
if(handle > 0) {
- BTA_SdpRemoveRecordByUser((void*) handle);
+ BTA_SdpRemoveRecordByUser(INT_TO_PTR(handle));
return BT_STATUS_SUCCESS;
}
BTIF_TRACE_DEBUG("Sdp Server %s - record already removed - or never created", __FUNCTION__);
diff --git a/btif/src/btif_sock_l2cap.c b/btif/src/btif_sock_l2cap.c
index 04c5b67..f42c65a 100644
--- a/btif/src/btif_sock_l2cap.c
+++ b/btif/src/btif_sock_l2cap.c
@@ -53,9 +53,6 @@
#define asrt(s) if (!(s)) APPL_TRACE_ERROR("## %s assert %s failed at line:%d ##",__FUNCTION__, \
#s, __LINE__)
-static pthread_mutex_t slot_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
-
-
struct packet {
struct packet *next, *prev;
uint32_t len;
@@ -290,13 +287,6 @@
osi_free(sock);
}
-static void btsock_l2cap_free(l2cap_socket *sock)
-{
- pthread_mutex_lock(&state_lock);
- btsock_l2cap_free_l(sock);
- pthread_mutex_unlock(&state_lock);
-}
-
static l2cap_socket *btsock_l2cap_alloc_l(const char *name, const bt_bdaddr_t *addr,
char is_server, int flags)
{
@@ -369,18 +359,6 @@
return NULL;
}
-static l2cap_socket *btsock_l2cap_alloc(const char *name, const bt_bdaddr_t *addr,
- char is_server, int flags)
-{
- l2cap_socket *ret;
-
- pthread_mutex_lock(&state_lock);
- ret = btsock_l2cap_alloc_l(name, addr, is_server, flags);
- pthread_mutex_unlock(&state_lock);
-
- return ret;
-}
-
bt_status_t btsock_l2cap_init(int handle)
{
APPL_TRACE_DEBUG("btsock_l2cap_init...");
@@ -539,7 +517,7 @@
//if we do not set a callback, this socket will be dropped */
*(p_open->p_p_cback) = (void*)btsock_l2cap_cbk;
- *(p_open->p_user_data) = (void*)accept_rs->id;
+ *(p_open->p_user_data) = UINT_TO_PTR(accept_rs->id);
//start monitor the socket
btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP, SOCK_THREAD_FD_EXCEPTION, sock->id);
@@ -720,7 +698,6 @@
} else {
- tBTA_JV_DATA_IND *p_data_ind = &evt->data_ind;
UINT8 buffer[L2CAP_MAX_SDU_LENGTH];
UINT32 count;
@@ -744,29 +721,29 @@
static void btsock_l2cap_cbk(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_data)
{
- int rc;
+ uint32_t sock_id = PTR_TO_UINT(user_data);
switch (event) {
case BTA_JV_L2CAP_START_EVT:
- on_srv_l2cap_listen_started(&p_data->l2c_start, (uint32_t)user_data);
+ on_srv_l2cap_listen_started(&p_data->l2c_start, sock_id);
break;
case BTA_JV_L2CAP_CL_INIT_EVT:
- on_cl_l2cap_init(&p_data->l2c_cl_init, (uint32_t)user_data);
+ on_cl_l2cap_init(&p_data->l2c_cl_init, sock_id);
break;
case BTA_JV_L2CAP_OPEN_EVT:
- on_l2cap_connect(p_data, (uint32_t)user_data);
- BTA_JvSetPmProfile(p_data->l2c_open.handle,BTA_JV_PM_ID_1,BTA_JV_CONN_OPEN);
+ on_l2cap_connect(p_data, sock_id);
+ BTA_JvSetPmProfile(p_data->l2c_open.handle, BTA_JV_PM_ID_1,BTA_JV_CONN_OPEN);
break;
case BTA_JV_L2CAP_CLOSE_EVT:
- APPL_TRACE_DEBUG("BTA_JV_L2CAP_CLOSE_EVT: user_data:%d", (uint32_t)user_data);
- on_l2cap_close(&p_data->l2c_close, (uint32_t)user_data);
+ APPL_TRACE_DEBUG("BTA_JV_L2CAP_CLOSE_EVT: id: %u", sock_id);
+ on_l2cap_close(&p_data->l2c_close, sock_id);
break;
case BTA_JV_L2CAP_DATA_IND_EVT:
- on_l2cap_data_ind(p_data, (uint32_t)user_data);
+ on_l2cap_data_ind(p_data, sock_id);
APPL_TRACE_DEBUG("BTA_JV_L2CAP_DATA_IND_EVT");
break;
@@ -779,21 +756,21 @@
break;
case BTA_JV_L2CAP_WRITE_EVT:
- APPL_TRACE_DEBUG("BTA_JV_L2CAP_WRITE_EVT id: %d", (int)user_data);
- on_l2cap_write_done((void*)p_data->l2c_write.req_id, (uint32_t)user_data);
+ APPL_TRACE_DEBUG("BTA_JV_L2CAP_WRITE_EVT: id: %u", sock_id);
+ on_l2cap_write_done(UINT_TO_PTR(p_data->l2c_write.req_id), sock_id);
break;
case BTA_JV_L2CAP_WRITE_FIXED_EVT:
- APPL_TRACE_DEBUG("BTA_JV_L2CAP_WRITE_FIXED_EVT id: %d", (int)user_data);
- on_l2cap_write_fixed_done((void*)p_data->l2c_write_fixed.req_id, (uint32_t)user_data);
+ APPL_TRACE_DEBUG("BTA_JV_L2CAP_WRITE_FIXED_EVT: id: %u", sock_id);
+ on_l2cap_write_fixed_done(UINT_TO_PTR(p_data->l2c_write_fixed.req_id), sock_id);
break;
case BTA_JV_L2CAP_CONG_EVT:
- on_l2cap_outgoing_congest(&p_data->l2c_cong, (uint32_t)user_data);
+ on_l2cap_outgoing_congest(&p_data->l2c_cong, sock_id);
break;
default:
- APPL_TRACE_ERROR("unhandled event %d, slot id:%d", event, (uint32_t)user_data);
+ APPL_TRACE_ERROR("unhandled event %d, slot id: %u", event, sock_id);
break;
}
}
@@ -852,7 +829,7 @@
if (sock->fixed_chan) {
if (BTA_JvL2capStartServerLE(sock->security, 0, NULL, sock->channel,
- L2CAP_DEFAULT_MTU, NULL, btsock_l2cap_cbk, (void*)sock->id)
+ L2CAP_DEFAULT_MTU, NULL, btsock_l2cap_cbk, UINT_TO_PTR(sock->id))
!= BTA_JV_SUCCESS)
stat = BT_STATUS_FAIL;
@@ -860,12 +837,12 @@
/* If we have a channel specified in the request, just start the server,
* else we request a PSM and start the server after we receive a PSM. */
if(sock->channel < 0) {
- if(BTA_JvGetChannelId(BTA_JV_CONN_TYPE_L2CAP, (void*)sock->id, 0)
+ if(BTA_JvGetChannelId(BTA_JV_CONN_TYPE_L2CAP, UINT_TO_PTR(sock->id), 0)
!= BTA_JV_SUCCESS)
stat = BT_STATUS_FAIL;
} else {
if (BTA_JvL2capStartServer(sock->security, 0, &obex_l2c_etm_opt,
- sock->channel, L2CAP_MAX_SDU_LENGTH, &cfg, btsock_l2cap_cbk, (void*)sock->id)
+ sock->channel, L2CAP_MAX_SDU_LENGTH, &cfg, btsock_l2cap_cbk, UINT_TO_PTR(sock->id))
!= BTA_JV_SUCCESS)
stat = BT_STATUS_FAIL;
}
@@ -921,13 +898,13 @@
if (fixed_chan) {
if (BTA_JvL2capConnectLE(sock->security, 0, NULL, channel,
L2CAP_DEFAULT_MTU, NULL, sock->addr.address, btsock_l2cap_cbk,
- (void*)sock->id) != BTA_JV_SUCCESS)
+ UINT_TO_PTR(sock->id)) != BTA_JV_SUCCESS)
stat = BT_STATUS_FAIL;
} else {
if (BTA_JvL2capConnect(sock->security, 0, &obex_l2c_etm_opt,
channel, L2CAP_MAX_SDU_LENGTH, &cfg, sock->addr.address,
- btsock_l2cap_cbk, (void*)sock->id) != BTA_JV_SUCCESS)
+ btsock_l2cap_cbk, UINT_TO_PTR(sock->id)) != BTA_JV_SUCCESS)
stat = BT_STATUS_FAIL;
}
}
@@ -1027,21 +1004,28 @@
* be wrong
* UPDATE: Since we are responsible for freeing the buffer in the
* write_complete_ind, it is OK to use malloc. */
-
int count = recv(fd, buffer, L2CAP_MAX_SDU_LENGTH,
MSG_NOSIGNAL | MSG_DONTWAIT);
APPL_TRACE_DEBUG("btsock_l2cap_signaled - %d bytes received from socket",
count);
+
+ // TODO(armansito): |buffer|, which is created above via
+ // malloc, is being cast below to UINT32 to be used as
+ // the |req_id| parameter of BTA_JvL2capWriteFixed and
+ // BTA_JvL2capWrite. The "id" then gets freed in an
+ // obscure callback elsewhere. We need to watch out for
+ // this type of unsafe practice, as this is error prone
+ // and difficult to follow.
if (sock->fixed_chan) {
if(BTA_JvL2capWriteFixed(sock->channel, (BD_ADDR*)&sock->addr,
- (UINT32)buffer, btsock_l2cap_cbk, buffer, count,
- (void *)user_id) != BTA_JV_SUCCESS) {
+ PTR_TO_UINT(buffer), btsock_l2cap_cbk, buffer, count,
+ UINT_TO_PTR(user_id)) != BTA_JV_SUCCESS) {
// On fail, free the buffer
on_l2cap_write_fixed_done(buffer, user_id);
}
} else {
- if(BTA_JvL2capWrite(sock->handle, (UINT32)buffer, buffer, count,
- (void *)user_id) != BTA_JV_SUCCESS) {
+ if(BTA_JvL2capWrite(sock->handle, PTR_TO_UINT(buffer), buffer, count,
+ UINT_TO_PTR(user_id)) != BTA_JV_SUCCESS) {
// On fail, free the buffer
on_l2cap_write_done(buffer, user_id);
}
diff --git a/btif/src/btif_sock_rfc.c b/btif/src/btif_sock_rfc.c
index f80ed56..0637156 100644
--- a/btif/src/btif_sock_rfc.c
+++ b/btif/src/btif_sock_rfc.c
@@ -23,11 +23,12 @@
#include <features.h>
#include <hardware/bluetooth.h>
#include <hardware/bt_sock.h>
+#include <pthread.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
-#include <pthread.h>
+#include <unistd.h>
#include "bta_api.h"
#include "bt_target.h"
@@ -287,7 +288,7 @@
goto out;
}
APPL_TRACE_DEBUG("BTA_JvGetChannelId: service_name: %s - channel: %d", service_name, channel);
- BTA_JvGetChannelId(BTA_JV_CONN_TYPE_RFCOMM, (void*) slot->id, channel);
+ BTA_JvGetChannelId(BTA_JV_CONN_TYPE_RFCOMM, UINT_TO_PTR(slot->id), channel);
*sock_fd = slot->app_fd; // Transfer ownership of fd to caller.
/*TODO:
* We are leaking one of the app_fd's - either the listen socket, or the connection socket.
@@ -602,7 +603,7 @@
}
static void jv_dm_cback(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_data) {
- uint32_t id = (uintptr_t)user_data;
+ uint32_t id = PTR_TO_UINT(user_data);
switch(event) {
case BTA_JV_GET_SCN_EVT:
{
@@ -628,13 +629,13 @@
} else {
if(rs->is_service_uuid_valid == true) {
// We already have data for SDP record, create it (RFC-only profiles)
- BTA_JvCreateRecordByUser((void *)rs->id);
+ BTA_JvCreateRecordByUser(UINT_TO_PTR(rs->id));
} else {
APPL_TRACE_DEBUG("is_service_uuid_valid==false - don't set SDP-record, "
"just start the RFCOMM server", rs->id);
//now start the rfcomm server after sdp & channel # assigned
BTA_JvRfcommStartServer(rs->security, rs->role, rs->scn, MAX_RFC_SESSION,
- rfcomm_cback, (void*)rs->id);
+ rfcomm_cback, UINT_TO_PTR(rs->id));
}
}
} else if(rs) {
diff --git a/btif/src/btif_sock_sco.c b/btif/src/btif_sock_sco.c
index 9012527..e9bff91 100644
--- a/btif/src/btif_sock_sco.c
+++ b/btif/src/btif_sock_sco.c
@@ -22,15 +22,17 @@
#include <errno.h>
#include <hardware/bluetooth.h>
#include <hardware/bt_sock.h>
+#include <pthread.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
+#include <unistd.h>
#include "btif_common.h"
#include "osi/include/allocator.h"
#include "osi/include/list.h"
-#include "osi/include/osi.h"
#include "osi/include/log.h"
+#include "osi/include/osi.h"
#include "osi/include/socket.h"
#include "osi/include/thread.h"
diff --git a/btif/src/btif_sock_util.c b/btif/src/btif_sock_util.c
index baa3ed3..4ce5270 100644
--- a/btif/src/btif_sock_util.c
+++ b/btif/src/btif_sock_util.c
@@ -163,8 +163,14 @@
return ret_len;
}
-
+// TODO(armansito): I'm not sure why the osi log macros aren't being used here,
+// but for now just redefine PRINT for non-Android platforms.
+#if defined(OS_GENERIC)
+#define PRINT(s) fprintf(stderr, "%s\n", s)
+#else // !defined(OS_GENERIC)
#define PRINT(s) __android_log_write(ANDROID_LOG_DEBUG, NULL, s)
+#endif // defined(OS_GENERIC)
+
static const char* hex_table = "0123456789abcdef";
static inline void byte2hex(const char* data, char** str)
{
diff --git a/btif/src/btif_storage.c b/btif/src/btif_storage.c
index ff7e7aa..ca89077 100644
--- a/btif/src/btif_storage.c
+++ b/btif/src/btif_storage.c
@@ -1193,7 +1193,6 @@
{
int device_type;
int addr_type;
- UINT32 i;
bt_bdaddr_t bd_addr;
BD_ADDR bta_bd_addr;
bool device_added = false;
diff --git a/build/BUILD.gn b/build/BUILD.gn
new file mode 100644
index 0000000..5f55f57
--- /dev/null
+++ b/build/BUILD.gn
@@ -0,0 +1,72 @@
+#
+# Copyright (C) 2015 Google, Inc.
+#
+# 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.
+#
+
+declare_args() {
+ # Include path for hardware/bluetooth.h
+ libhw_include_path = ""
+ core_include_path = ""
+}
+
+config("default_include_dirs") {
+ # TODO(armansito): Remove "core_include_path" once the cutils includes have
+ # been removed.
+ assert(libhw_include_path != "", "libhardware_include_path build argument wasn't provided.")
+ assert(core_include_path != "", "core_include_path build argument wasn't provided.")
+ include_dirs = [
+ libhw_include_path,
+ core_include_path,
+ ]
+}
+
+config("linux") {
+ # TODO(keybuk): AndroidConfig.h or equivalent
+
+ cflags = [
+ "-Wall",
+ "-Werror",
+ "-g",
+ "-O0",
+ "-fpic",
+ "-fdata-sections",
+ "-ffunction-sections",
+ "-fvisibility=hidden",
+ ]
+
+ cflags_c = [
+ "-std=c99"
+ ]
+
+ defines = [
+ "_FORTIFY_SOURCE=2",
+ "_GNU_SOURCE",
+ "HAS_NO_BDROID_BUILDCFG",
+ "LOG_NDEBUG=1",
+ "EXPORT_SYMBOL=__attribute__((visibility(\"default\")))",
+
+ # This is a macro to that can be used by source code to detect if the
+ # current build is done by GN or via Android.mk. This is a temporary
+ # workaround until we can remove all Android-specific dependencies.
+ "OS_GENERIC",
+ ]
+}
+
+config("pic") {
+ cflags = [ "-fPIC" ]
+}
+
+config("gc") {
+ ldflags = [ "-Wl,--gc-sections" ]
+}
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
new file mode 100644
index 0000000..419d62f
--- /dev/null
+++ b/build/config/BUILDCONFIG.gn
@@ -0,0 +1,49 @@
+#
+# Copyright (C) 2015 Google, Inc.
+#
+# 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.
+#
+
+set_default_toolchain("//build/toolchain/gcc")
+
+set_defaults("executable") {
+ configs = [
+ "//build:linux",
+ "//build:gc",
+ "//build:default_include_dirs",
+ ]
+}
+
+set_defaults("shared_library") {
+ configs = [
+ "//build:linux",
+ "//build:gc",
+ "//build:default_include_dirs",
+ ]
+}
+
+set_defaults("source_set") {
+ configs = [
+ "//build:linux",
+ "//build:gc",
+ "//build:default_include_dirs",
+ ]
+}
+
+set_defaults("static_library") {
+ configs = [
+ "//build:linux",
+ "//build:gc",
+ "//build:default_include_dirs",
+ ]
+}
diff --git a/build/secondary/third_party/gtest/BUILD.gn b/build/secondary/third_party/gtest/BUILD.gn
new file mode 100644
index 0000000..c1112d9
--- /dev/null
+++ b/build/secondary/third_party/gtest/BUILD.gn
@@ -0,0 +1,77 @@
+#
+# Copyright (C) 2015 Google, Inc.
+#
+# 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.
+#
+
+config("gtest_config") {
+ # Gtest headers need to be able to find themselves.
+ include_dirs = [ "include" ]
+
+ defines = [ "GTEST_HAS_RTTI=0" ]
+}
+
+config("gtest_direct_config") {
+ visibility = [ ":*" ]
+ defines = [ "UNIT_TEST" ]
+}
+
+static_library("gtest") {
+ testonly = true
+ sources = [
+ "include/gtest/gtest-death-test.h",
+ "include/gtest/gtest-message.h",
+ "include/gtest/gtest-param-test.h",
+ "include/gtest/gtest-printers.h",
+ "include/gtest/gtest-spi.h",
+ "include/gtest/gtest-test-part.h",
+ "include/gtest/gtest-typed-test.h",
+ "include/gtest/gtest.h",
+ "include/gtest/gtest_pred_impl.h",
+ "include/gtest/internal/gtest-death-test-internal.h",
+ "include/gtest/internal/gtest-filepath.h",
+ "include/gtest/internal/gtest-internal.h",
+ "include/gtest/internal/gtest-linked_ptr.h",
+ "include/gtest/internal/gtest-param-util-generated.h",
+ "include/gtest/internal/gtest-param-util.h",
+ "include/gtest/internal/gtest-port.h",
+ "include/gtest/internal/gtest-string.h",
+ "include/gtest/internal/gtest-tuple.h",
+ "include/gtest/internal/gtest-type-util.h",
+
+ "src/gtest-all.cc",
+ "src/gtest-death-test.cc",
+ "src/gtest-filepath.cc",
+ "src/gtest-internal-inl.h",
+ "src/gtest-port.cc",
+ "src/gtest-printers.cc",
+ "src/gtest-test-part.cc",
+ "src/gtest-typed-test.cc",
+ "src/gtest.cc",
+ ]
+
+ include_dirs = [ "." ]
+
+ all_dependent_configs = [ ":gtest_config" ]
+ public_configs = [ ":gtest_direct_config" ]
+}
+
+source_set("gtest_main") {
+ testonly = true
+ sources = [
+ "src/gtest_main.cc",
+ ]
+ deps = [
+ ":gtest",
+ ]
+}
diff --git a/build/secondary/third_party/tinyxml2/BUILD.gn b/build/secondary/third_party/tinyxml2/BUILD.gn
new file mode 100644
index 0000000..335960b
--- /dev/null
+++ b/build/secondary/third_party/tinyxml2/BUILD.gn
@@ -0,0 +1,23 @@
+#
+# Copyright (C) 2015 Google, Inc.
+#
+# 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.
+#
+
+static_library("tinyxml2") {
+ sources = [
+ "tinyxml2.cpp"
+ ]
+
+ include_dirs = [ "." ]
+}
diff --git a/build/toolchain/gcc/BUILD.gn b/build/toolchain/gcc/BUILD.gn
new file mode 100644
index 0000000..ecf9057
--- /dev/null
+++ b/build/toolchain/gcc/BUILD.gn
@@ -0,0 +1,96 @@
+#
+# Copyright (C) 2015 Google, Inc.
+#
+# 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.
+#
+cc = "gcc"
+cxx = "g++"
+
+toolchain("gcc") {
+ tool("cc") {
+ depfile = "{{output}}.d"
+ command = "$cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}"
+ depsformat = "gcc"
+ description = "CC {{output}}"
+ outputs = [
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
+ ]
+ }
+
+ tool("cxx") {
+ depfile = "{{output}}.d"
+ command = "$cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}} -o {{output}}"
+ depsformat = "gcc"
+ description = "CXX {{output}}"
+ outputs = [
+ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
+ ]
+ }
+
+ tool("alink") {
+ rspfile = "{{output}}.rsp"
+ command = "rm -f {{output}} && ar rcs {{output}} @$rspfile"
+ description = "AR {{target_output_name}}{{output_extension}}"
+ rspfile_content = "{{inputs}}"
+ outputs = [
+ "{{target_out_dir}}/{{target_output_name}}{{output_extension}}",
+ ]
+ default_output_extension = ".a"
+
+ output_prefix = "lib"
+ }
+
+ tool("solink") {
+ soname = "{{target_output_name}}{{output_extension}}" # e.g. "libfoo.so".
+ rspfile = soname + ".rsp"
+
+ command = "$cxx -shared {{ldflags}} -o $soname -Wl,-soname=$soname @$rspfile"
+ rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whole-archive {{libs}}"
+
+ description = "SOLINK $soname"
+
+ # Use this for {{output_extension}} expansions unless a target manually
+ # overrides it (in which case {{output_extension}} will be what the target
+ # specifies).
+ default_output_extension = ".so"
+
+ outputs = [
+ soname,
+ ]
+ link_output = soname
+ depend_output = soname
+
+ output_prefix = "lib"
+ }
+
+ tool("link") {
+ outfile = "{{target_output_name}}{{output_extension}}"
+ rspfile = "$outfile.rsp"
+ command = "$cxx {{ldflags}} -o $outfile -Wl,--start-group @$rspfile {{solibs}} -Wl,--end-group {{libs}}"
+ description = "LINK $outfile"
+ rspfile_content = "{{inputs}}"
+ outputs = [
+ outfile,
+ ]
+ }
+
+ tool("stamp") {
+ command = "touch {{output}}"
+ description = "STAMP {{output}}"
+ }
+
+ tool("copy") {
+ command = "cp -af {{source}} {{output}}"
+ description = "COPY {{source}} {{output}}"
+ }
+}
diff --git a/device/BUILD.gn b/device/BUILD.gn
new file mode 100644
index 0000000..1ca0288
--- /dev/null
+++ b/device/BUILD.gn
@@ -0,0 +1,54 @@
+#
+# Copyright (C) 2015 Google, Inc.
+#
+# 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.
+#
+
+static_library("device") {
+ sources = [
+ "src/classic/peer.c",
+ "src/controller.c"
+ ]
+
+ include_dirs = [
+ "//",
+ "//btcore/include",
+ "//gki/common",
+ "//hci/include",
+ "//include",
+ "//osi/include",
+ "//stack/include",
+ ]
+}
+
+executable("net_test_device") {
+ testonly = true
+ sources = [
+ "//osi/test/AllocationTestHarness.cpp",
+ "test/classic/peer_test.cpp",
+ ]
+
+ include_dirs = [
+ "//",
+ "//osi/include",
+ ]
+
+ deps = [
+ "//device",
+ "//btcore",
+ "//osi",
+ "//third_party/gtest:gtest_main",
+ ]
+
+ libs = [ "-lpthread", "-lrt", "-ldl" ]
+}
diff --git a/device/src/classic/peer.c b/device/src/classic/peer.c
index 6d1a7b5..d2de679 100644
--- a/device/src/classic/peer.c
+++ b/device/src/classic/peer.c
@@ -68,7 +68,7 @@
return NULL;
}
-const module_t classic_peer_module = {
+EXPORT_SYMBOL const module_t classic_peer_module = {
.name = CLASSIC_PEER_MODULE,
.init = init,
.start_up = NULL,
diff --git a/device/src/controller.c b/device/src/controller.c
index 5101625..89c0133 100644
--- a/device/src/controller.c
+++ b/device/src/controller.c
@@ -250,7 +250,7 @@
return future_new_immediate(FUTURE_SUCCESS);
}
-const module_t controller_module = {
+EXPORT_SYMBOL const module_t controller_module = {
.name = CONTROLLER_MODULE,
.init = NULL,
.start_up = start_up,
diff --git a/embdrv/sbc/BUILD.gn b/embdrv/sbc/BUILD.gn
new file mode 100644
index 0000000..7c9387c
--- /dev/null
+++ b/embdrv/sbc/BUILD.gn
@@ -0,0 +1,64 @@
+#
+# Copyright (C) 2015 Google, Inc.
+#
+# 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.
+#
+
+source_set("sbc_decoder") {
+ sources = [
+ "decoder/srce/alloc.c",
+ "decoder/srce/bitalloc.c",
+ "decoder/srce/bitalloc-sbc.c",
+ "decoder/srce/bitstream-decode.c",
+ "decoder/srce/decoder-oina.c",
+ "decoder/srce/decoder-private.c",
+ "decoder/srce/decoder-sbc.c",
+ "decoder/srce/dequant.c",
+ "decoder/srce/framing.c",
+ "decoder/srce/framing-sbc.c",
+ "decoder/srce/oi_codec_version.c",
+ "decoder/srce/synthesis-8-generated.c",
+ "decoder/srce/synthesis-dct8.c",
+ "decoder/srce/synthesis-sbc.c",
+ ]
+
+ include_dirs = [
+ "decoder/include",
+ ]
+}
+
+source_set("sbc_encoder") {
+ sources = [
+ "encoder/srce/sbc_analysis.c",
+ "encoder/srce/sbc_dct.c",
+ "encoder/srce/sbc_dct_coeffs.c",
+ "encoder/srce/sbc_enc_bit_alloc_mono.c",
+ "encoder/srce/sbc_enc_bit_alloc_ste.c",
+ "encoder/srce/sbc_enc_coeffs.c",
+ "encoder/srce/sbc_encoder.c",
+ "encoder/srce/sbc_packing.c",
+ ]
+
+ include_dirs = [
+ "encoder/include",
+ "//include",
+ "//stack/include",
+ ]
+}
+
+static_library("sbc") {
+ deps = [
+ ":sbc_decoder",
+ ":sbc_encoder",
+ ]
+}
diff --git a/gki/BUILD.gn b/gki/BUILD.gn
new file mode 100644
index 0000000..95993ac
--- /dev/null
+++ b/gki/BUILD.gn
@@ -0,0 +1,30 @@
+#
+# Copyright (C) 2015 Google, Inc.
+#
+# 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.
+#
+
+static_library("gki") {
+ sources = [
+ "common/gki_buffer.c",
+ "ulinux/gki_ulinux.c",
+ ]
+
+ include_dirs = [
+ "common",
+ "ulinux",
+ "//",
+ "//include",
+ "//stack/include",
+ ]
+}
diff --git a/gki/common/gki.h b/gki/common/gki.h
index cf1c48c..f0df9e3 100644
--- a/gki/common/gki.h
+++ b/gki/common/gki.h
@@ -27,7 +27,7 @@
*/
typedef void (TIMER_CBACK)(void *p_tle);
#ifndef TIMER_PARAM_TYPE
-#define TIMER_PARAM_TYPE UINT32
+#define TIMER_PARAM_TYPE void*
#endif
/* Define a timer list entry
*/
diff --git a/gki/ulinux/gki_ulinux.c b/gki/ulinux/gki_ulinux.c
index 72ad479..c8e9953 100644
--- a/gki/ulinux/gki_ulinux.c
+++ b/gki/ulinux/gki_ulinux.c
@@ -51,7 +51,7 @@
}
// Temp module until GKI dies
-const module_t gki_module = {
+EXPORT_SYMBOL const module_t gki_module = {
.name = GKI_MODULE,
.init = init,
.start_up = NULL,
diff --git a/hci/Android.mk b/hci/Android.mk
index af87285..a36d6b7 100644
--- a/hci/Android.mk
+++ b/hci/Android.mk
@@ -44,6 +44,7 @@
include $(BUILD_STATIC_LIBRARY)
#####################################################
+ifeq (,$(strip $(SANITIZE_TARGET)))
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := \
@@ -78,3 +79,4 @@
LOCAL_STATIC_LIBRARIES := libbt-hci libosi libcutils libbtcore
include $(BUILD_NATIVE_TEST)
+endif # SANITIZE_TARGET
diff --git a/hci/BUILD.gn b/hci/BUILD.gn
new file mode 100644
index 0000000..c199ff0
--- /dev/null
+++ b/hci/BUILD.gn
@@ -0,0 +1,77 @@
+#
+# Copyright (C) 2015 Google, Inc.
+#
+# 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.
+#
+
+static_library("hci") {
+ sources = [
+ "src/btsnoop.c",
+ "src/btsnoop_mem.c",
+ "src/btsnoop_net.c",
+ "src/buffer_allocator.c",
+ "src/hci_audio.c",
+ "src/hci_hal.c",
+ "src/hci_hal_h4.c",
+ "src/hci_hal_mct.c",
+ "src/hci_inject.c",
+ "src/hci_layer.c",
+ "src/hci_packet_factory.c",
+ "src/hci_packet_parser.c",
+ "src/low_power_manager.c",
+ "src/packet_fragmenter.c",
+ "src/vendor.c",
+ ]
+
+ include_dirs = [
+ "include",
+ "//",
+ "//include",
+ "//btcore/include",
+ "//gki/common",
+ "//osi/include",
+ "//stack/include",
+ ]
+}
+
+executable("net_test_hci") {
+ testonly = true
+ sources = [
+ "//osi/test/AllocationTestHarness.cpp",
+ "//osi/test/AlarmTestHarness.cpp",
+ "test/hci_hal_h4_test.cpp",
+ "test/hci_hal_mct_test.cpp",
+ "test/hci_layer_test.cpp",
+ "test/low_power_manager_test.cpp",
+ "test/packet_fragmenter_test.cpp",
+ ]
+
+ include_dirs = [
+ "//",
+ "//include",
+ "//btcore/include",
+ "//hci/include",
+ "//osi/include",
+ "//osi/test",
+ "//stack/include",
+ ]
+
+ deps = [
+ "//hci",
+ "//osi",
+ "//btcore",
+ "//third_party/gtest:gtest_main",
+ ]
+
+ libs = [ "-lpthread", "-lrt", "-ldl" ]
+}
diff --git a/hci/src/btsnoop.c b/hci/src/btsnoop.c
index 990623e..b768f70 100644
--- a/hci/src/btsnoop.c
+++ b/hci/src/btsnoop.c
@@ -80,7 +80,7 @@
return NULL;
}
-const module_t btsnoop_module = {
+EXPORT_SYMBOL const module_t btsnoop_module = {
.name = BTSNOOP_MODULE,
.init = NULL,
.start_up = start_up,
diff --git a/hci/src/btsnoop_net.c b/hci/src/btsnoop_net.c
index c601da8..173638d 100644
--- a/hci/src/btsnoop_net.c
+++ b/hci/src/btsnoop_net.c
@@ -27,6 +27,7 @@
#include <sys/prctl.h>
#include <sys/socket.h>
#include <sys/types.h>
+#include <unistd.h>
#include "osi/include/osi.h"
#include "osi/include/log.h"
diff --git a/hci/src/hci_hal_h4.c b/hci/src/hci_hal_h4.c
index 836937d..fd3ad83 100644
--- a/hci/src/hci_hal_h4.c
+++ b/hci/src/hci_hal_h4.c
@@ -21,6 +21,7 @@
#include <assert.h>
#include <errno.h>
#include <string.h>
+#include <unistd.h>
#include "osi/include/eager_reader.h"
#include "hci_hal.h"
diff --git a/hci/src/hci_hal_mct.c b/hci/src/hci_hal_mct.c
index 9b3707c..25fa53a 100644
--- a/hci/src/hci_hal_mct.c
+++ b/hci/src/hci_hal_mct.c
@@ -21,6 +21,7 @@
#include <assert.h>
#include <errno.h>
#include <string.h>
+#include <unistd.h>
#include "bt_vendor_lib.h"
#include "osi/include/eager_reader.h"
diff --git a/hci/src/hci_layer.c b/hci/src/hci_layer.c
index 89d5cc9..62e3ad6 100644
--- a/hci/src/hci_layer.c
+++ b/hci/src/hci_layer.c
@@ -19,11 +19,19 @@
#define LOG_TAG "bt_hci"
#include <assert.h>
-#include <cutils/properties.h>
+#include <pthread.h>
#include <string.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
+#include <unistd.h>
+
+// TODO(armansito): cutils/properties.h is only being used to pull-in runtime
+// settings on Android. Remove this conditional include once we have a generic
+// way to obtain system properties.
+#if !defined(OS_GENERIC)
+#include <cutils/properties.h>
+#endif // !defined(OS_GENERIC)
#include "buffer_allocator.h"
#include "btsnoop.h"
@@ -175,12 +183,19 @@
pthread_mutex_init(&commands_pending_response_lock, NULL);
+ // TODO(armansito): cutils/properties.h is only being used to pull-in runtime
+ // settings on Android. Remove this conditional include once we have a generic
+ // way to obtain system properties. For now, always use the default timeout on
+ // non-Android builds.
+ period_ms_t startup_timeout_ms = DEFAULT_STARTUP_TIMEOUT_MS;
+
+#if !defined(OS_GENERIC)
// Grab the override startup timeout ms, if present.
- period_ms_t startup_timeout_ms;
char timeout_prop[PROPERTY_VALUE_MAX];
if (!property_get("bluetooth.enable_timeout_ms", timeout_prop, STRING_VALUE_OF(DEFAULT_STARTUP_TIMEOUT_MS))
|| (startup_timeout_ms = atoi(timeout_prop)) < 100)
startup_timeout_ms = DEFAULT_STARTUP_TIMEOUT_MS;
+#endif // !defined(OS_GENERIC)
startup_timer = non_repeating_timer_new(startup_timeout_ms, startup_timer_expired, NULL);
if (!startup_timer) {
@@ -317,7 +332,7 @@
return NULL;
}
-const module_t hci_module = {
+EXPORT_SYMBOL const module_t hci_module = {
.name = HCI_MODULE,
.init = NULL,
.start_up = start_up,
diff --git a/include/bt_target.h b/include/bt_target.h
index f712d2c..57ff43d 100644
--- a/include/bt_target.h
+++ b/include/bt_target.h
@@ -753,7 +753,7 @@
#ifndef TIMER_PARAM_TYPE
-#define TIMER_PARAM_TYPE UINT32
+#define TIMER_PARAM_TYPE void*
#endif
/******************************************************************************
diff --git a/main/BUILD.gn b/main/BUILD.gn
new file mode 100644
index 0000000..a80e31d
--- /dev/null
+++ b/main/BUILD.gn
@@ -0,0 +1,78 @@
+#
+# Copyright (C) 2015 Google, Inc.
+#
+# 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.
+#
+
+shared_library("bluetooth.default") {
+ # HAL layer
+ sources = [
+ "//btif/src/bluetooth.c",
+ ]
+
+ # platform specific
+ sources += [
+ "bte_main.c",
+ "bte_init.c",
+ "bte_logmsg.c",
+ "bte_conf.c",
+ "stack_config.c",
+ ]
+
+ include_dirs = [
+ "//",
+ "//bta/include",
+ "//bta/sys",
+ "//bta/dm",
+ "//btcore/include",
+ "//osi/include",
+ "//gki/common",
+ "//gki/ulinux",
+ "//include",
+ "//stack/include",
+ "//stack/l2cap",
+ "//stack/a2dp",
+ "//stack/btm",
+ "//stack/avdt",
+ "//hci",
+ "//hci/include",
+ "//udrv/include",
+ "//btif/include",
+ "//btif/co",
+ "//hci/includ",
+ "//vnd/include",
+ "//brcm/include",
+ "//embdrv/sbc/encoder/include",
+ "//embdrv/sbc/decoder/include",
+ "//audio_a2dp_hw",
+ "//utils/include",
+ ]
+
+ deps = [
+ "//audio_a2dp_hw:audio.a2dp.default",
+ "//bta",
+ "//btcore",
+ "//btif",
+ "//device",
+ "//embdrv/sbc",
+ "//gki",
+ "//hci",
+ "//osi",
+ "//stack",
+ "//third_party/tinyxml2",
+ "//udrv",
+ "//utils",
+ ]
+
+ libs = [ "-lpthread", "-lrt", "-ldl" ]
+}
diff --git a/main/bte_logmsg.c b/main/bte_logmsg.c
index 3258f47..e302cbe 100644
--- a/main/bte_logmsg.c
+++ b/main/bte_logmsg.c
@@ -59,10 +59,19 @@
#include "smp_api.h"
#endif
+// TODO(armansito): Work-around until we figure out a way to generate logs in a
+// platform-independent manner.
+#if defined(OS_GENERIC)
+#define LOGI0(t,s) fprintf(stderr, "%s\n", s)
+#define LOGD0(t,s) fprintf(stderr, "%s\n", s)
+#define LOGW0(t,s) fprintf(stderr, "%s\n", s)
+#define LOGE0(t,s) fprintf(stderr, "%s\n", s)
+#else // !defined(OS_GENERIC)
#define LOGI0(t,s) __android_log_write(ANDROID_LOG_INFO, t, s)
#define LOGD0(t,s) __android_log_write(ANDROID_LOG_DEBUG, t, s)
#define LOGW0(t,s) __android_log_write(ANDROID_LOG_WARN, t, s)
#define LOGE0(t,s) __android_log_write(ANDROID_LOG_ERROR, t, s)
+#endif // defined(OS_GENERIC)
#ifndef DEFAULT_CONF_TRACE_LEVEL
#define DEFAULT_CONF_TRACE_LEVEL BT_TRACE_LEVEL_WARNING
@@ -249,7 +258,7 @@
return NULL;
}
-const module_t bte_logmsg_module = {
+EXPORT_SYMBOL const module_t bte_logmsg_module = {
.name = BTE_LOGMSG_MODULE,
.init = init,
.start_up = NULL,
diff --git a/main/bte_main.c b/main/bte_main.c
index d08d6f6..4f6c1b0 100644
--- a/main/bte_main.c
+++ b/main/bte_main.c
@@ -27,7 +27,6 @@
#define LOG_TAG "bt_main"
#include <assert.h>
-#include <cutils/properties.h>
#include <fcntl.h>
#include <hardware/bluetooth.h>
#include <pthread.h>
diff --git a/main/stack_config.c b/main/stack_config.c
index 6e1431e..06e15d1 100644
--- a/main/stack_config.c
+++ b/main/stack_config.c
@@ -53,7 +53,7 @@
return future_new_immediate(FUTURE_SUCCESS);
}
-const module_t stack_config_module = {
+EXPORT_SYMBOL const module_t stack_config_module = {
.name = STACK_CONFIG_MODULE,
.init = init,
.start_up = NULL,
diff --git a/osi/Android.mk b/osi/Android.mk
index 52dc2cf..ee55c5c 100644
--- a/osi/Android.mk
+++ b/osi/Android.mk
@@ -48,7 +48,7 @@
./src/socket.c \
./src/thread.c
-LOCAL_CFLAGS := -std=c99 -Wall -Werror -UNDEBUG
+LOCAL_CFLAGS := -std=c99 -Wall -Werror -UNDEBUG -fvisibility=hidden
# Many .h files have redefined typedefs
LOCAL_CLANG_CFLAGS += -Wno-error=typedef-redefinition
LOCAL_MODULE := libosi
diff --git a/osi/BUILD.gn b/osi/BUILD.gn
new file mode 100644
index 0000000..3c12636
--- /dev/null
+++ b/osi/BUILD.gn
@@ -0,0 +1,76 @@
+#
+# Copyright (C) 2015 Google, Inc.
+#
+# 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.
+#
+
+static_library("osi") {
+ sources = [
+ "src/alarm.c",
+ "src/allocation_tracker.c",
+ "src/allocator.c",
+ "src/array.c",
+ "src/buffer.c",
+ "src/compat.c",
+ "src/config.c",
+ "src/data_dispatcher.c",
+ "src/eager_reader.c",
+ "src/fixed_queue.c",
+ "src/future.c",
+ "src/hash_functions.c",
+ "src/hash_map.c",
+ "src/list.c",
+ "src/non_repeating_timer.c",
+ "src/reactor.c",
+ "src/semaphore.c",
+ "src/socket.c",
+ "src/thread.c",
+ ]
+
+ include_dirs = [
+ "include",
+ "//"
+ ]
+}
+
+executable("net_test_osi") {
+ testonly = true
+ sources = [
+ "test/AlarmTestHarness.cpp",
+ "test/AllocationTestHarness.cpp",
+ "test/alarm_test.cpp",
+ "test/allocation_tracker_test.cpp",
+ "test/array_test.cpp",
+ "test/atomic_test.cpp",
+ "test/config_test.cpp",
+ "test/data_dispatcher_test.cpp",
+ "test/eager_reader_test.cpp",
+ "test/future_test.cpp",
+ "test/hash_map_test.cpp",
+ "test/list_test.cpp",
+ "test/reactor_test.cpp",
+ "test/thread_test.cpp",
+ ]
+
+ include_dirs = [
+ "include",
+ "//",
+ ]
+
+ deps = [
+ "//osi",
+ "//third_party/gtest:gtest_main",
+ ]
+
+ libs = [ "-lpthread", "-lrt" ]
+}
diff --git a/osi/include/log.h b/osi/include/log.h
index a5de1cf..4493ee9 100644
--- a/osi/include/log.h
+++ b/osi/include/log.h
@@ -18,6 +18,25 @@
#pragma once
+/*
+ * TODO(armansito): Work-around until we figure out a way to generate logs in a
+ * platform-independent manner.
+ */
+#if defined(OS_GENERIC)
+
+/* syslog didn't work well here since we would be redefining LOG_DEBUG. */
+#include <stdio.h>
+
+#define LOGWRAPPER(fmt, args...) fprintf(stderr, fmt "\n", ## args)
+
+#define LOG_VERBOSE(...) LOGWRAPPER(__VA_ARGS__)
+#define LOG_DEBUG(...) LOGWRAPPER(__VA_ARGS__)
+#define LOG_INFO(...) LOGWRAPPER(__VA_ARGS__)
+#define LOG_WARN(...) LOGWRAPPER(__VA_ARGS__)
+#define LOG_ERROR(...) LOGWRAPPER(__VA_ARGS__)
+
+#else /* !defined(OS_GENERIC) */
+
#include <cutils/log.h>
#define LOG_VERBOSE(...) ALOGV(__VA_ARGS__)
@@ -25,3 +44,6 @@
#define LOG_INFO(...) ALOGI(__VA_ARGS__)
#define LOG_WARN(...) ALOGW(__VA_ARGS__)
#define LOG_ERROR(...) ALOGE(__VA_ARGS__)
+
+
+#endif /* defined(OS_GENERIC) */
diff --git a/osi/include/osi.h b/osi/include/osi.h
index c035bf8..673f4e8 100644
--- a/osi/include/osi.h
+++ b/osi/include/osi.h
@@ -20,3 +20,14 @@
#define COMPILE_ASSERT(x) char * DUMMY_PTR = !(x)
typedef uint32_t timeout_t;
+
+// Macros for safe integer to pointer conversion. In the C language, data is
+// commonly cast to opaque pointer containers and back for generic parameter
+// passing in callbacks. These macros should be used sparingly in new code
+// (never in C++ code). Whenever integers need to be passed as a pointer, use
+// these macros.
+#define PTR_TO_UINT(p) ((unsigned int) ((uintptr_t) (p)))
+#define UINT_TO_PTR(u) ((void *) ((uintptr_t) (u)))
+
+#define PTR_TO_INT(p) ((int) ((intptr_t) (p)))
+#define INT_TO_PTR(i) ((void *) ((intptr_t) (i)))
diff --git a/osi/src/alarm.c b/osi/src/alarm.c
index a9cd4dd..5139167 100644
--- a/osi/src/alarm.c
+++ b/osi/src/alarm.c
@@ -26,6 +26,7 @@
#include <string.h>
#include <signal.h>
#include <time.h>
+#include <pthread.h>
#include "osi/include/alarm.h"
#include "osi/include/allocator.h"
@@ -42,7 +43,7 @@
// a guarantee to its caller that the callback will not be in progress when it
// returns.
pthread_mutex_t callback_lock;
- period_ms_t created;
+ period_ms_t creation_time;
period_ms_t period;
period_ms_t deadline;
bool is_periodic;
@@ -143,7 +144,7 @@
pthread_mutex_lock(&monitor);
- alarm->created = now();
+ alarm->creation_time = now();
alarm->is_periodic = is_periodic;
alarm->period = period;
alarm->callback = cb;
@@ -255,7 +256,7 @@
// Calculate the next deadline for this alarm
period_ms_t just_now = now();
- period_ms_t ms_into_period = alarm->is_periodic ? ((just_now - alarm->created) % alarm->period) : 0;
+ period_ms_t ms_into_period = alarm->is_periodic ? ((just_now - alarm->creation_time) % alarm->period) : 0;
alarm->deadline = just_now + (alarm->period - ms_into_period);
// Add it into the timer list sorted by deadline (earliest deadline first).
diff --git a/osi/src/config.c b/osi/src/config.c
index 11a5baf..46acab0 100644
--- a/osi/src/config.c
+++ b/osi/src/config.c
@@ -24,6 +24,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <sys/stat.h>
#include "osi/include/allocator.h"
diff --git a/osi/src/eager_reader.c b/osi/src/eager_reader.c
index 63b190e..6f6fe86 100644
--- a/osi/src/eager_reader.c
+++ b/osi/src/eager_reader.c
@@ -22,6 +22,7 @@
#include <errno.h>
#include <stddef.h>
#include <string.h>
+#include <unistd.h>
#include <sys/eventfd.h>
#include "osi/include/allocator.h"
diff --git a/osi/src/reactor.c b/osi/src/reactor.c
index 08b5098..68b0984 100644
--- a/osi/src/reactor.c
+++ b/osi/src/reactor.c
@@ -25,6 +25,7 @@
#include <string.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
+#include <unistd.h>
#include "osi/include/allocator.h"
#include "osi/include/list.h"
diff --git a/osi/src/semaphore.c b/osi/src/semaphore.c
index 5ee9926..c9b117d 100644
--- a/osi/src/semaphore.c
+++ b/osi/src/semaphore.c
@@ -24,6 +24,7 @@
#include <malloc.h>
#include <string.h>
#include <sys/eventfd.h>
+#include <unistd.h>
#include "osi/include/allocator.h"
#include "osi/include/osi.h"
diff --git a/profile/src/manager.c b/profile/src/manager.c
index 9e56b65..6e3d45c 100644
--- a/profile/src/manager.c
+++ b/profile/src/manager.c
@@ -57,7 +57,7 @@
return NULL;
}
-const module_t profile_manager_module = {
+EXPORT_SYMBOL const module_t profile_manager_module = {
.name = PROFILE_MANAGER_MODULE,
.init = init,
.start_up = NULL,
diff --git a/service/Android.mk b/service/Android.mk
new file mode 100644
index 0000000..f450840
--- /dev/null
+++ b/service/Android.mk
@@ -0,0 +1,59 @@
+#
+# Copyright (C) 2015 Google
+#
+# 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.
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+BASE_SRC := \
+ base/base64.cpp \
+ base/string_split.cpp \
+ base/string_number_conversions.cpp \
+ modp_b64/modp_b64.cpp
+
+CORE_SRC := \
+ a2dp_source.cpp \
+ logging_helpers.cpp \
+ core_stack.cpp \
+ uuid.cpp \
+ gatt_server.cpp
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := uuid_test.cpp uuid.cpp
+LOCAL_CFLAGS += -std=c++11
+LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE := uuid_test_bd
+include $(BUILD_HOST_NATIVE_TEST)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ $(BASE_SRC) \
+ $(CORE_SRC) \
+ host.cpp \
+ main.cpp
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/../
+
+LOCAL_CFLAGS += -std=c++11
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := bthost
+LOCAL_REQUIRED_MODULES = bluetooth.default
+LOCAL_SHARED_LIBRARIES += \
+ libhardware \
+ libcutils \
+ liblog
+
+include $(BUILD_EXECUTABLE)
diff --git a/service/a2dp_source.cpp b/service/a2dp_source.cpp
new file mode 100644
index 0000000..6cde92a
--- /dev/null
+++ b/service/a2dp_source.cpp
@@ -0,0 +1,82 @@
+//
+// Copyright (C) 2015 Google, Inc.
+//
+// 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 "a2dp_source.h"
+
+#define LOG_TAG "A2dpSource"
+#include "osi/include/log.h"
+
+#include "core_stack.h"
+#include "logging_helpers.h"
+#include "osi/include/osi.h"
+
+namespace {
+
+void ConnectionStateCallback(btav_connection_state_t state,
+ UNUSED_ATTR bt_bdaddr_t *bd_addr) {
+ LOG_INFO("%s: %s", __func__, BtAvConnectionStateText(state));
+}
+
+void AudioStateCallback(btav_audio_state_t state,
+ UNUSED_ATTR bt_bdaddr_t *bd_addr) {
+ LOG_INFO("%s: %s", __func__, BtAvAudioStateText(state));
+}
+
+void AudioConfigCallback(UNUSED_ATTR bt_bdaddr_t *bd_addr,
+ UNUSED_ATTR uint32_t sample_rate,
+ UNUSED_ATTR uint8_t channel_count) {
+ // I think these are used for audio sink only?
+ // TODO(icoolidge): revisit.
+}
+
+btav_callbacks_t av_callbacks = {
+ sizeof(btav_callbacks_t), ConnectionStateCallback, AudioStateCallback,
+ AudioConfigCallback,
+};
+
+} // namespace
+
+namespace bluetooth {
+
+A2dpSource::A2dpSource(CoreStack *bt) : av_(nullptr), bt_(bt) {
+ // TODO(icoolidge): DCHECK(bt);
+}
+
+int A2dpSource::Start() {
+ // Get the interface to the a2dp source profile.
+ const void *interface = bt_->GetInterface(BT_PROFILE_ADVANCED_AUDIO_ID);
+ if (!interface) {
+ LOG_ERROR("Error getting audio source interface");
+ return -1;
+ }
+
+ av_ = reinterpret_cast<const btav_interface_t *>(interface);
+
+ bt_status_t btstat = av_->init(&av_callbacks);
+ if (btstat != BT_STATUS_SUCCESS && btstat != BT_STATUS_DONE) {
+ LOG_ERROR("Failed to initialize audio source interface: %s %d",
+ BtStatusText(btstat), btstat);
+ return -1;
+ }
+ return 0;
+}
+
+int A2dpSource::Stop() {
+ // TODO(icoolidge): DCHECK(av_);
+ av_->cleanup();
+ return 0;
+}
+
+} // namespace bluetooth
diff --git a/service/a2dp_source.h b/service/a2dp_source.h
new file mode 100644
index 0000000..557b98f
--- /dev/null
+++ b/service/a2dp_source.h
@@ -0,0 +1,44 @@
+//
+// Copyright (C) 2015 Google, Inc.
+//
+// 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.
+//
+#pragma once
+
+#include "hardware/bluetooth.h"
+#include "hardware/bt_av.h"
+
+namespace bluetooth {
+
+class CoreStack;
+
+// This class is just experimental to test out BlueDroid A2DP
+// interface, capability, and functionality.
+class A2dpSource {
+ public:
+ explicit A2dpSource(CoreStack* bt);
+
+ // Enables the A2DP source profile in the stack.
+ // Creates audio Unix sockets. (see audio_a2dp_hw.h)
+ int Start();
+
+ // Disables the A2DP source profile in the stack.
+ int Stop();
+
+ private:
+ const btav_interface_t* av_;
+ // Weak reference.
+ CoreStack* bt_;
+};
+
+} // namespace bluetooth
diff --git a/service/base/base64.cpp b/service/base/base64.cpp
new file mode 100644
index 0000000..704d678
--- /dev/null
+++ b/service/base/base64.cpp
@@ -0,0 +1,37 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/base64.h"
+
+#include "modp_b64/modp_b64.h"
+
+namespace base {
+
+void Base64Encode(const std::string& input, std::string* output) {
+ std::string temp;
+ temp.resize(modp_b64_encode_len(input.size())); // makes room for null byte
+
+ // modp_b64_encode_len() returns at least 1, so temp[0] is safe to use.
+ size_t output_size = modp_b64_encode(&(temp[0]), input.data(), input.size());
+
+ temp.resize(output_size); // strips off null byte
+ output->swap(temp);
+}
+
+bool Base64Decode(const std::string& input, std::string* output) {
+ std::string temp;
+ temp.resize(modp_b64_decode_len(input.size()));
+
+ // does not null terminate result since result is binary data!
+ size_t input_size = input.size();
+ size_t output_size = modp_b64_decode(&(temp[0]), input.data(), input_size);
+ if (output_size == MODP_B64_ERROR)
+ return false;
+
+ temp.resize(output_size);
+ output->swap(temp);
+ return true;
+}
+
+} // namespace base
diff --git a/service/base/base64.h b/service/base/base64.h
new file mode 100644
index 0000000..38923af
--- /dev/null
+++ b/service/base/base64.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_BASE64_H__
+#define BASE_BASE64_H__
+
+#include <string>
+
+namespace base {
+
+// Encodes the input string in base64. The encoding can be done in-place.
+void Base64Encode(const std::string& input, std::string* output);
+
+// Decodes the base64 input string. Returns true if successful and false
+// otherwise. The output string is only modified if successful. The decoding can
+// be done in-place.
+bool Base64Decode(const std::string& input, std::string* output);
+
+} // namespace base
+
+#endif // BASE_BASE64_H__
diff --git a/service/base/string_number_conversions.cpp b/service/base/string_number_conversions.cpp
new file mode 100644
index 0000000..62c3d48
--- /dev/null
+++ b/service/base/string_number_conversions.cpp
@@ -0,0 +1,87 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/string_number_conversions.h"
+
+#include <stdlib.h>
+
+#include <limits>
+
+namespace base {
+
+// Utility to convert a character to a digit in a given base
+template<typename CHAR, int BASE, bool BASE_LTE_10> class BaseCharToDigit {
+};
+
+// Faster specialization for bases <= 10
+template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, true> {
+ public:
+ static bool Convert(CHAR c, uint8_t* digit) {
+ if (c >= '0' && c < '0' + BASE) {
+ *digit = static_cast<uint8_t>(c - '0');
+ return true;
+ }
+ return false;
+ }
+};
+
+// Specialization for bases where 10 < base <= 36
+template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, false> {
+ public:
+ static bool Convert(CHAR c, uint8_t* digit) {
+ if (c >= '0' && c <= '9') {
+ *digit = c - '0';
+ } else if (c >= 'a' && c < 'a' + BASE - 10) {
+ *digit = c - 'a' + 10;
+ } else if (c >= 'A' && c < 'A' + BASE - 10) {
+ *digit = c - 'A' + 10;
+ } else {
+ return false;
+ }
+ return true;
+ }
+};
+
+template<int BASE, typename CHAR> bool CharToDigit(CHAR c, uint8_t* digit) {
+ return BaseCharToDigit<CHAR, BASE, BASE <= 10>::Convert(c, digit);
+}
+
+template<typename STR>
+bool HexStringToBytesT(const STR& input, std::vector<uint8_t>* output) {
+ output->clear();
+ size_t count = input.size();
+ if (count == 0 || (count % 2) != 0)
+ return false;
+ for (uintptr_t i = 0; i < count / 2; ++i) {
+ uint8_t msb = 0; // most significant 4 bits
+ uint8_t lsb = 0; // least significant 4 bits
+ if (!CharToDigit<16>(input[i * 2], &msb) ||
+ !CharToDigit<16>(input[i * 2 + 1], &lsb))
+ return false;
+ output->push_back((msb << 4) | lsb);
+ }
+ return true;
+}
+
+
+std::string HexEncode(const void* bytes, size_t size) {
+ static const char kHexChars[] = "0123456789ABCDEF";
+
+ // Each input byte creates two output hex characters.
+ std::string ret(size * 2, '\0');
+
+ for (size_t i = 0; i < size; ++i) {
+ char b = reinterpret_cast<const char*>(bytes)[i];
+ ret[(i * 2)] = kHexChars[(b >> 4) & 0xf];
+ ret[(i * 2) + 1] = kHexChars[b & 0xf];
+ }
+ return ret;
+}
+
+
+bool HexStringToBytes(const std::string& input, std::vector<uint8_t>* output) {
+ return HexStringToBytesT(input, output);
+}
+
+} // namespace base
diff --git a/service/base/string_number_conversions.h b/service/base/string_number_conversions.h
new file mode 100644
index 0000000..7d1d737
--- /dev/null
+++ b/service/base/string_number_conversions.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_STRINGS_STRING_NUMBER_CONVERSIONS_H_
+#define BASE_STRINGS_STRING_NUMBER_CONVERSIONS_H_
+
+#include <string>
+#include <vector>
+
+namespace base {
+
+// Hex encoding ----------------------------------------------------------------
+
+// Returns a hex string representation of a binary buffer. The returned hex
+// string will be in upper case. This function does not check if |size| is
+// within reasonable limits since it's written with trusted data in mind. If
+// you suspect that the data you want to format might be large, the absolute
+// max size for |size| should be is
+// std::numeric_limits<size_t>::max() / 2
+std::string HexEncode(const void* bytes, size_t size);
+
+// Similar to the previous functions, except that output is a vector of bytes.
+// |*output| will contain as many bytes as were successfully parsed prior to the
+// error. There is no overflow, but input.size() must be evenly divisible by 2.
+// Leading 0x or +/- are not allowed.
+bool HexStringToBytes(const std::string& input,
+ std::vector<uint8_t>* output);
+
+} // namespace base
+
+#endif // BASE_STRINGS_STRING_NUMBER_CONVERSIONS_H_
diff --git a/service/base/string_split.cpp b/service/base/string_split.cpp
new file mode 100644
index 0000000..670f2e4
--- /dev/null
+++ b/service/base/string_split.cpp
@@ -0,0 +1,36 @@
+//
+// Copyright (C) 2015 Google, Inc.
+//
+// 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 "string_split.h"
+
+namespace base {
+
+std::vector<std::string> SplitString(const std::string& input, char delimiter) {
+ std::vector<std::string> output;
+ size_t token_start = 0;
+ for (size_t i = 0; i <= input.size(); ++i) {
+ // Token is the whole string if no delimiter found.
+ if (i == input.size() || input[i] == delimiter) {
+ size_t token_length = i - token_start;
+ // Qualified tokens: substring, end text after token, non-empty whole input.
+ if (i != input.size() || !output.empty() || token_length)
+ output.emplace_back(input, token_start, token_length);
+ token_start = i + 1;
+ }
+ }
+ return output;
+}
+
+} // namespace base
diff --git a/service/base/string_split.h b/service/base/string_split.h
new file mode 100644
index 0000000..ee1a13f
--- /dev/null
+++ b/service/base/string_split.h
@@ -0,0 +1,25 @@
+//
+// Copyright (C) 2015 Google, Inc.
+//
+// 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.
+//
+#pragma once
+
+#include <string>
+#include <vector>
+
+namespace base {
+
+std::vector<std::string> SplitString(const std::string& input, char delimiter);
+
+} // namespace base
diff --git a/service/core_stack.cpp b/service/core_stack.cpp
new file mode 100644
index 0000000..d40d64b
--- /dev/null
+++ b/service/core_stack.cpp
@@ -0,0 +1,287 @@
+//
+// Copyright (C) 2015 Google, Inc.
+//
+// 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 "core_stack.h"
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <condition_variable>
+#include <mutex>
+#include <string>
+
+#define LOG_TAG "BluetoothBase"
+#include "osi/include/log.h"
+
+#include "hardware/bluetooth.h"
+#include "hardware/hardware.h"
+#include "logging_helpers.h"
+#include "osi/include/osi.h"
+
+namespace {
+
+std::mutex mutex;
+std::condition_variable synchronize;
+bool instantiated = false;
+
+void AdapterStateChangedCallback(bt_state_t state) {
+ LOG_INFO("Bluetooth state:%s", BtStateText(state));
+ if (state == BT_STATE_ON)
+ synchronize.notify_one();
+}
+
+void CallbackThreadCallback(bt_cb_thread_evt evt) {
+ LOG_INFO("%s: %s", __func__, BtEventText(evt));
+}
+
+// TODO(icoolidge): Audit how these os callouts should be
+// implemented (or nulled) for systems w/out wakelocks.
+bool SetWakeAlarmCallback(uint64_t delay_millis,
+ UNUSED_ATTR bool should_wake,
+ alarm_cb cb,
+ void *data) {
+ static timer_t timer;
+ static bool timer_created;
+
+ if (!timer_created) {
+ struct sigevent sigevent;
+ memset(&sigevent, 0, sizeof(sigevent));
+ sigevent.sigev_notify = SIGEV_THREAD;
+ sigevent.sigev_notify_function = (void (*)(union sigval))cb;
+ sigevent.sigev_value.sival_ptr = data;
+ timer_create(CLOCK_MONOTONIC, &sigevent, &timer);
+ timer_created = true;
+ }
+
+ struct itimerspec new_value;
+ new_value.it_value.tv_sec = delay_millis / 1000;
+ new_value.it_value.tv_nsec = (delay_millis % 1000) * 1000 * 1000;
+ new_value.it_interval.tv_sec = 0;
+ new_value.it_interval.tv_nsec = 0;
+ timer_settime(timer, 0, &new_value, nullptr);
+
+ return true;
+}
+
+// Dummy implementation due to no wakelocks.
+int AcquireWakeLock(UNUSED_ATTR const char *lock_name) {
+ return BT_STATUS_SUCCESS;
+}
+
+// Dummy implementation due to no wakelocks.
+int ReleaseWakeLock(UNUSED_ATTR const char *lock_name) {
+ return BT_STATUS_SUCCESS;
+}
+
+void GenericDevicePropertiesCallback(bt_status_t status,
+ bt_bdaddr_t *remote_address,
+ int num_properties,
+ bt_property_t *properties) {
+ if (status != BT_STATUS_SUCCESS) {
+ LOG_ERROR("%s: %s", __func__, BtStatusText(status));
+ return;
+ }
+
+ if (!remote_address) {
+ LOG_INFO("Local adapter properties:");
+ }
+
+ for (int i = 0; i < num_properties; ++i) {
+ bt_property_t *prop = &properties[i];
+ switch (prop->type) {
+ case BT_PROPERTY_BDADDR: {
+ std::string text =
+ BtAddrString(reinterpret_cast<bt_bdaddr_t *>(prop->val));
+ LOG_INFO("%s: %s", BtPropertyText(prop->type), text.c_str());
+ break;
+ }
+ case BT_PROPERTY_ADAPTER_SCAN_MODE: {
+ bt_scan_mode_t *mode = reinterpret_cast<bt_scan_mode_t *>(prop->val);
+ LOG_INFO("%s: %s", BtPropertyText(prop->type), BtScanModeText(*mode));
+ std::lock_guard<std::mutex> lock(mutex);
+ synchronize.notify_one();
+ break;
+ }
+ case BT_PROPERTY_BDNAME: {
+ bt_bdname_t *name = reinterpret_cast<bt_bdname_t *>(prop->val);
+ LOG_INFO("%s: %s", BtPropertyText(prop->type),
+ reinterpret_cast<char *>(name->name));
+ std::lock_guard<std::mutex> lock(mutex);
+ synchronize.notify_one();
+ break;
+ }
+ default:
+ LOG_INFO("%s: %s", __func__, BtPropertyText(prop->type));
+ break;
+ }
+ }
+}
+
+void AclStateChangedCallback(bt_status_t status, bt_bdaddr_t *remote_bd_addr,
+ bt_acl_state_t state) {
+ if (status != BT_STATUS_SUCCESS) {
+ LOG_ERROR("%s: %s", __func__, BtStatusText(status));
+ return;
+ }
+
+ std::string text = BtAddrString(remote_bd_addr);
+ LOG_INFO("%s: %s: %s", __func__, text.c_str(), BtAclText(state));
+}
+
+void LocalAdapterPropertiesCallback(bt_status_t status, int num_properties,
+ bt_property_t *properties) {
+ GenericDevicePropertiesCallback(status, nullptr, num_properties, properties);
+}
+
+bt_callbacks_t bt_callbacks = {
+ sizeof(bt_callbacks_t),
+ AdapterStateChangedCallback,
+ LocalAdapterPropertiesCallback,
+ GenericDevicePropertiesCallback,
+ nullptr, /* device_found_cb */
+ nullptr, /* discovery_state_changed_cb */
+ nullptr, /* pin_request_cb */
+ nullptr, /* ssp_request_cb */
+ nullptr, /* bond_state_changed_cb */
+ AclStateChangedCallback,
+ CallbackThreadCallback,
+ nullptr, /* dut_mode_recv_cb */
+ nullptr, /* le_test_mode_cb */
+ nullptr /* energy_info_cb */
+};
+
+bt_os_callouts_t callouts = {
+ sizeof(bt_os_callouts_t),
+ SetWakeAlarmCallback,
+ AcquireWakeLock,
+ ReleaseWakeLock
+};
+
+} // namespace
+
+namespace bluetooth {
+
+CoreStack::CoreStack() : adapter_(nullptr), hal_(nullptr) {
+ std::lock_guard<std::mutex> lock(mutex);
+ // TODO(icoolidge): DCHECK(!instantiated);
+ instantiated = true;
+}
+
+bool CoreStack::Initialize() {
+ std::unique_lock<std::mutex> lock(mutex);
+
+ // Load the bluetooth module.
+ const hw_module_t *module;
+ int status = hw_get_module(BT_HARDWARE_MODULE_ID, &module);
+ if (status) {
+ LOG_ERROR("Error getting bluetooth module");
+ return false;
+ }
+
+ // Open the bluetooth device.
+ hw_device_t *device;
+ status = module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
+ if (status) {
+ LOG_ERROR("Error opening bluetooth module");
+ return false;
+ }
+
+ // TODO(icoolidge): Audit initialization and teardown.
+ adapter_ = reinterpret_cast<bluetooth_device_t *>(device);
+ hal_ = adapter_->get_bluetooth_interface();
+
+ // Bind module callbacks to local handlers.
+ status = hal_->init(&bt_callbacks);
+ if (status != BT_STATUS_SUCCESS) {
+ LOG_ERROR("Error binding callbacks");
+ return false;
+ }
+
+ status = hal_->set_os_callouts(&callouts);
+ if (status != BT_STATUS_SUCCESS) {
+ LOG_ERROR("Error binding OS callbacks");
+ return false;
+ }
+
+ status = hal_->enable();
+ if (status) {
+ LOG_ERROR("Enable failed: %d", status);
+ return false;
+ }
+
+ synchronize.wait(lock);
+ LOG_INFO("CoreStack::Initialize success");
+ return true;
+}
+
+bool CoreStack::SetAdapterName(const std::string &name) {
+ bt_bdname_t n;
+ snprintf(reinterpret_cast<char *>(n.name), sizeof(n.name), "%s",
+ name.c_str());
+ bt_property_t prop;
+ prop.len = sizeof(n);
+ prop.val = &n;
+ prop.type = BT_PROPERTY_BDNAME;
+
+ std::unique_lock<std::mutex> lock(mutex);
+
+ int status = hal_->set_adapter_property(&prop);
+ if (status) {
+ LOG_ERROR("%s: prop change failed: %d", __func__, status);
+ return false;
+ }
+
+ synchronize.wait(lock);
+ return true;
+}
+
+bool CoreStack::SetClassicDiscoverable() {
+ bt_scan_mode_t mode = BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
+ bt_property_t disc;
+ disc.len = sizeof(mode);
+ disc.val = &mode;
+ disc.type = BT_PROPERTY_ADAPTER_SCAN_MODE;
+
+ std::unique_lock<std::mutex> lock(mutex);
+
+ int status = hal_->set_adapter_property(&disc);
+ if (status) {
+ LOG_ERROR("Prop change failed: %d", status);
+ return false;
+ }
+
+ synchronize.wait(lock);
+ return true;
+}
+
+const void *CoreStack::GetInterface(const char *profile) {
+ std::unique_lock<std::mutex> lock(mutex);
+ // Get the interface to the GATT profile.
+ const void *interface = hal_->get_profile_interface(profile);
+ if (!interface) {
+ LOG_ERROR("Error getting %s interface", profile);
+ return nullptr;
+ }
+ return interface;
+}
+
+CoreStack::~CoreStack() {
+ // TODO(icoolidge): Disable bluetooth hardware, clean up library state.
+ std::lock_guard<std::mutex> lock(mutex);
+ instantiated = false;
+}
+
+} // namespace bluetooth
diff --git a/service/core_stack.h b/service/core_stack.h
new file mode 100644
index 0000000..8b5671a
--- /dev/null
+++ b/service/core_stack.h
@@ -0,0 +1,57 @@
+//
+// Copyright (C) 2015 Google, Inc.
+//
+// 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.
+//
+#pragma once
+
+#include <string>
+
+#include "hardware/bluetooth.h"
+
+namespace bluetooth {
+
+// This represents the core Bluetooth stack,
+// with high level operations that affect many profiles.
+// It is also used to access profile interfaces.
+class CoreStack {
+ public:
+ CoreStack();
+ ~CoreStack();
+
+ // Initialize the bluetooth stack and device.
+ bool Initialize();
+
+ // Set the device name.
+ // This can be referenced in BLE GAP advertisements.
+ bool SetAdapterName(const std::string& name);
+
+ // Allow activated classic profiles to be discovered.
+ bool SetClassicDiscoverable();
+
+ // Get an interface for a profile (BLE GATT, A2DP, etc).
+ const void *GetInterface(const char* profile);
+
+ private:
+ // Prevent copy and assignment.
+ CoreStack& operator=(const CoreStack& rhs) = delete;
+ CoreStack(const CoreStack& rhs) = delete;
+
+ // Our libhardware handle.
+ bluetooth_device_t *adapter_;
+
+ // Common bluetooth interface handle.
+ const bt_interface_t *hal_;
+};
+
+} // namespace bluetooth
diff --git a/service/gatt_server.cpp b/service/gatt_server.cpp
new file mode 100644
index 0000000..54e407e
--- /dev/null
+++ b/service/gatt_server.cpp
@@ -0,0 +1,704 @@
+//
+// Copyright (C) 2015 Google, Inc.
+//
+// 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 "gatt_server.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <array>
+#include <condition_variable>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <set>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#define LOG_TAG "GattServer"
+#include "osi/include/log.h"
+
+#include "core_stack.h"
+#include "hardware/bluetooth.h"
+#include "hardware/bt_gatt.h"
+#include "logging_helpers.h"
+#include "osi/include/osi.h"
+#include "uuid.h"
+
+namespace {
+
+const size_t kMaxGattAttributeSize = 512;
+// TODO(icoolidge): Difficult to generalize without knowing how many attributes.
+const int kNumBlueDroidHandles = 60;
+
+// TODO(icoolidge): Support multiple instances
+static bluetooth::gatt::ServerInternals *internal = nullptr;
+
+enum { kPipeReadEnd = 0, kPipeWriteEnd = 1, kPipeNumEnds = 2 };
+
+} // namespace
+
+namespace bluetooth {
+namespace gatt {
+
+struct Characteristic {
+ Uuid uuid;
+ int blob_section;
+ std::vector<uint8_t> blob;
+
+ // Support synchronized blob updates by latching under mutex.
+ std::vector<uint8_t> next_blob;
+ bool next_blob_pending;
+ bool notify;
+};
+
+struct ServerInternals {
+ ServerInternals();
+ ~ServerInternals();
+ int Initialize(CoreStack *bt);
+
+ // This maps API attribute UUIDs to BlueDroid handles.
+ std::map<Uuid, int> uuid_to_attribute;
+
+ // The attribute cache, indexed by BlueDroid handles.
+ std::unordered_map<int, Characteristic> characteristics;
+
+ // Associate a control attribute with its value attribute.
+ std::unordered_map<int, int> controlled_blobs;
+
+ ScanResults scan_results;
+
+ Uuid last_write;
+ const btgatt_interface_t *gatt;
+ int server_if;
+ int client_if;
+ int service_handle;
+ btgatt_srvc_id_t service_id;
+ std::set<int> connections;
+
+ std::mutex lock;
+ std::condition_variable api_synchronize;
+ int pipefd[kPipeNumEnds];
+};
+
+} // namespace gatt
+} // namespace bluetooth
+
+namespace {
+
+/** Callback invoked in response to register_server */
+void RegisterServerCallback(int status, int server_if, bt_uuid_t *app_uuid) {
+ LOG_INFO("%s: status:%d server_if:%d app_uuid:%p", __func__, status,
+ server_if, app_uuid);
+
+ internal->server_if = server_if;
+
+ btgatt_srvc_id_t service_id;
+ service_id.id.uuid = *app_uuid;
+ service_id.id.inst_id = 0;
+ service_id.is_primary = true;
+
+ bt_status_t btstat = internal->gatt->server->add_service(
+ server_if, &service_id, kNumBlueDroidHandles);
+}
+
+void ServiceAddedCallback(int status, int server_if, btgatt_srvc_id_t *srvc_id,
+ int srvc_handle) {
+ LOG_INFO("%s: status:%d server_if:%d gatt_srvc_id:%u srvc_handle:%d",
+ __func__, status, server_if, srvc_id->id.inst_id, srvc_handle);
+
+ std::lock_guard<std::mutex> lock(internal->lock);
+ internal->server_if = server_if;
+ internal->service_handle = srvc_handle;
+ internal->service_id = *srvc_id;
+ // This finishes the Initialize call.
+ internal->api_synchronize.notify_one();
+}
+
+void RequestReadCallback(int conn_id, int trans_id, bt_bdaddr_t *bda,
+ int attr_handle, int attribute_offset_octets,
+ bool is_long) {
+ std::lock_guard<std::mutex> lock(internal->lock);
+
+ bluetooth::gatt::Characteristic &ch = internal->characteristics[attr_handle];
+
+ // Latch next_blob to blob on a 'fresh' read.
+ if (ch.next_blob_pending && attribute_offset_octets == 0 &&
+ ch.blob_section == 0) {
+ std::swap(ch.blob, ch.next_blob);
+ ch.next_blob_pending = false;
+ }
+
+ const size_t blob_offset_octets =
+ std::min(ch.blob.size(), ch.blob_section * kMaxGattAttributeSize);
+ const size_t blob_remaining = ch.blob.size() - blob_offset_octets;
+ const size_t attribute_size = std::min(kMaxGattAttributeSize, blob_remaining);
+
+ std::string addr(BtAddrString(bda));
+ LOG_INFO(
+ "%s: connection:%d (%s) reading attr:%d attribute_offset_octets:%d "
+ "blob_section:%u (is_long:%u)",
+ __func__, conn_id, addr.c_str(), attr_handle, attribute_offset_octets,
+ ch.blob_section, is_long);
+
+ btgatt_response_t response;
+ response.attr_value.len = 0;
+
+ if (attribute_offset_octets < static_cast<int>(attribute_size)) {
+ std::copy(ch.blob.begin() + blob_offset_octets + attribute_offset_octets,
+ ch.blob.begin() + blob_offset_octets + attribute_size,
+ response.attr_value.value);
+ response.attr_value.len = attribute_size - attribute_offset_octets;
+ }
+
+ response.attr_value.handle = attr_handle;
+ response.attr_value.offset = attribute_offset_octets;
+ response.attr_value.auth_req = 0;
+ internal->gatt->server->send_response(conn_id, trans_id, 0, &response);
+}
+
+void RequestWriteCallback(int conn_id, int trans_id, bt_bdaddr_t *bda,
+ int attr_handle, int attribute_offset, int length,
+ bool need_rsp, bool is_prep, uint8_t *value) {
+ std::string addr(BtAddrString(bda));
+ LOG_INFO(
+ "%s: connection:%d (%s:trans:%d) write attr:%d attribute_offset:%d "
+ "length:%d "
+ "need_resp:%u is_prep:%u",
+ __func__, conn_id, addr.c_str(), trans_id, attr_handle, attribute_offset,
+ length, need_rsp, is_prep);
+
+ std::lock_guard<std::mutex> lock(internal->lock);
+
+ bluetooth::gatt::Characteristic &ch = internal->characteristics[attr_handle];
+
+ ch.blob.resize(attribute_offset + length);
+
+ std::copy(value, value + length, ch.blob.begin() + attribute_offset);
+
+ auto target_blob = internal->controlled_blobs.find(attr_handle);
+ // If this is a control attribute, adjust offset of the target blob.
+ if (target_blob != internal->controlled_blobs.end() && ch.blob.size() == 1u) {
+ internal->characteristics[target_blob->second].blob_section = ch.blob[0];
+ LOG_INFO("%s: updating attribute %d blob_section to %u", __func__,
+ target_blob->second, ch.blob[0]);
+ } else if (!is_prep) {
+ // This is a single frame characteristic write.
+ // Notify upwards because we're done now.
+ const bluetooth::Uuid::Uuid128Bit &attr_uuid = ch.uuid.GetFullBigEndian();
+ int status = write(internal->pipefd[kPipeWriteEnd], attr_uuid.data(),
+ attr_uuid.size());
+ if (-1 == status)
+ LOG_ERROR("%s: write failed: %s", __func__, strerror(errno));
+ } else {
+ // This is a multi-frame characteristic write.
+ // Wait for an 'RequestExecWriteCallback' to notify completion.
+ internal->last_write = ch.uuid;
+ }
+
+ // Respond only if needed.
+ if (!need_rsp) return;
+
+ btgatt_response_t response;
+ response.attr_value.handle = attr_handle;
+ response.attr_value.offset = attribute_offset;
+ response.attr_value.len = length;
+ response.attr_value.auth_req = 0;
+ internal->gatt->server->send_response(conn_id, trans_id, 0, &response);
+}
+
+void RequestExecWriteCallback(int conn_id, int trans_id, bt_bdaddr_t *bda,
+ int exec_write) {
+ std::string addr(BtAddrString(bda));
+ LOG_INFO("%s: connection:%d (%s:trans:%d) exec_write:%d", __func__, conn_id,
+ addr.c_str(), trans_id, exec_write);
+
+ if (!exec_write)
+ return;
+
+ std::lock_guard<std::mutex> lock(internal->lock);
+ // Communicate the attribute UUID as notification of a write update.
+ const bluetooth::Uuid::Uuid128Bit uuid =
+ internal->last_write.GetFullBigEndian();
+ int status = write(internal->pipefd[kPipeWriteEnd], uuid.data(), uuid.size());
+ if (-1 == status)
+ LOG_ERROR("%s: write failed: %s", __func__, strerror(errno));
+}
+
+void ConnectionCallback(int conn_id, int server_if, int connected,
+ bt_bdaddr_t *bda) {
+ std::string addr(BtAddrString(bda));
+ LOG_INFO("%s: connection:%d server_if:%d connected:%d addr:%s", __func__,
+ conn_id, server_if, connected, addr.c_str());
+ if (connected == 1) {
+ internal->connections.insert(conn_id);
+ } else if (connected == 0) {
+ internal->connections.erase(conn_id);
+ }
+}
+
+void CharacteristicAddedCallback(int status, int server_if, bt_uuid_t *uuid,
+ int srvc_handle, int char_handle) {
+ LOG_INFO("%s: status:%d server_if:%d service_handle:%d char_handle:%d",
+ __func__, status, server_if, srvc_handle, char_handle);
+
+ bluetooth::Uuid id(*uuid);
+
+ std::lock_guard<std::mutex> lock(internal->lock);
+
+ internal->uuid_to_attribute[id] = char_handle;
+ internal->characteristics[char_handle].uuid = id;
+ internal->characteristics[char_handle].blob_section = 0;
+
+ // This terminates an AddCharacteristic.
+ internal->api_synchronize.notify_one();
+}
+
+void DescriptorAddedCallback(int status, int server_if, bt_uuid_t *uuid,
+ int srvc_handle, int descr_handle) {
+ LOG_INFO(
+ "%s: status:%d server_if:%d service_handle:%d uuid[0]:%u "
+ "descr_handle:%d",
+ __func__, status, server_if, srvc_handle, uuid->uu[0], descr_handle);
+}
+
+void ServiceStartedCallback(int status, int server_if, int srvc_handle) {
+ LOG_INFO("%s: status:%d server_if:%d srvc_handle:%d", __func__, status,
+ server_if, srvc_handle);
+
+ // The UUID provided here is unimportant, and is only used to satisfy
+ // BlueDroid.
+ // It must be different than any other registered UUID.
+ bt_uuid_t client_id = internal->service_id.id.uuid;
+ ++client_id.uu[15];
+
+ bt_status_t btstat = internal->gatt->client->register_client(&client_id);
+ if (btstat != BT_STATUS_SUCCESS) {
+ LOG_ERROR("%s: Failed to register client", __func__);
+ }
+}
+
+void RegisterClientCallback(int status, int client_if, bt_uuid_t *app_uuid) {
+ LOG_INFO("%s: status:%d client_if:%d uuid[0]:%u", __func__, status,
+ client_if, app_uuid->uu[0]);
+ internal->client_if = client_if;
+
+ // Setup our advertisement. This has no callback.
+ bt_status_t btstat = internal->gatt->client->set_adv_data(
+ client_if, false, /* beacon, not scan response */
+ false, /* name */
+ false, /* no txpower */
+ 2, 2, /* interval */
+ 0, /* appearance */
+ 0, nullptr, /* no mfg data */
+ 0, nullptr, /* no service data */
+ 0, nullptr /* no service id yet */);
+ if (btstat != BT_STATUS_SUCCESS) {
+ LOG_ERROR("Failed to set advertising data");
+ return;
+ }
+
+ // TODO(icoolidge): Deprecated, use multi-adv interface.
+ // This calls back to ListenCallback.
+ btstat = internal->gatt->client->listen(client_if, true);
+ if (btstat != BT_STATUS_SUCCESS) {
+ LOG_ERROR("Failed to start listening");
+ }
+}
+
+void ListenCallback(int status, int client_if) {
+ LOG_INFO("%s: status:%d client_if:%d", __func__, status, client_if);
+ // This terminates a Start call.
+ std::lock_guard<std::mutex> lock(internal->lock);
+ internal->api_synchronize.notify_one();
+}
+
+void ServiceStoppedCallback(int status, int server_if, int srvc_handle) {
+ LOG_INFO("%s: status:%d server_if:%d srvc_handle:%d", __func__, status,
+ server_if, srvc_handle);
+ // This terminates a Stop call.
+ // TODO(icoolidge): make this symmetric with start
+ std::lock_guard<std::mutex> lock(internal->lock);
+ internal->api_synchronize.notify_one();
+}
+
+void ScanResultCallback(bt_bdaddr_t *bda, int rssi, uint8_t *adv_data) {
+ std::string addr(BtAddrString(bda));
+ (void)adv_data;
+ std::lock_guard<std::mutex> lock(internal->lock);
+ internal->scan_results[addr] = rssi;
+}
+
+void ClientConnectCallback(int conn_id, int status, int client_if,
+ bt_bdaddr_t *bda) {
+ std::string addr(BtAddrString(bda));
+ LOG_INFO("%s: conn_id:%d status:%d client_if:%d %s", __func__, conn_id,
+ status, client_if, addr.c_str());
+}
+
+void ClientDisconnectCallback(int conn_id, int status, int client_if,
+ bt_bdaddr_t *bda) {
+ std::string addr(BtAddrString(bda));
+ LOG_INFO("%s: conn_id:%d status:%d client_if:%d %s", __func__, conn_id,
+ status, client_if, addr.c_str());
+}
+
+void IndicationSentCallback(UNUSED_ATTR int conn_id,
+ UNUSED_ATTR int status) {
+ // TODO(icoolidge): what to do
+}
+
+void ResponseConfirmationCallback(UNUSED_ATTR int status,
+ UNUSED_ATTR int handle) {
+ // TODO(icoolidge): what to do
+}
+
+const btgatt_server_callbacks_t gatt_server_callbacks = {
+ RegisterServerCallback,
+ ConnectionCallback,
+ ServiceAddedCallback,
+ nullptr, /* included_service_added_cb */
+ CharacteristicAddedCallback,
+ DescriptorAddedCallback,
+ ServiceStartedCallback,
+ ServiceStoppedCallback,
+ nullptr, /* service_deleted_cb */
+ RequestReadCallback,
+ RequestWriteCallback,
+ RequestExecWriteCallback,
+ ResponseConfirmationCallback,
+ IndicationSentCallback,
+ nullptr, /* congestion_cb*/
+ nullptr, /* mtu_changed_cb */
+};
+
+// TODO(eisenbach): Refactor GATT interface to not require servers
+// to refer to the client interface.
+const btgatt_client_callbacks_t gatt_client_callbacks = {
+ RegisterClientCallback,
+ ScanResultCallback,
+ ClientConnectCallback,
+ ClientDisconnectCallback,
+ nullptr, /* search_complete_cb; */
+ nullptr, /* search_result_cb; */
+ nullptr, /* get_characteristic_cb; */
+ nullptr, /* get_descriptor_cb; */
+ nullptr, /* get_included_service_cb; */
+ nullptr, /* register_for_notification_cb; */
+ nullptr, /* notify_cb; */
+ nullptr, /* read_characteristic_cb; */
+ nullptr, /* write_characteristic_cb; */
+ nullptr, /* read_descriptor_cb; */
+ nullptr, /* write_descriptor_cb; */
+ nullptr, /* execute_write_cb; */
+ nullptr, /* read_remote_rssi_cb; */
+ ListenCallback,
+ nullptr, /* configure_mtu_cb; */
+ nullptr, /* scan_filter_cfg_cb; */
+ nullptr, /* scan_filter_param_cb; */
+ nullptr, /* scan_filter_status_cb; */
+ nullptr, /* multi_adv_enable_cb */
+ nullptr, /* multi_adv_update_cb; */
+ nullptr, /* multi_adv_data_cb*/
+ nullptr, /* multi_adv_disable_cb; */
+ nullptr, /* congestion_cb; */
+ nullptr, /* batchscan_cfg_storage_cb; */
+ nullptr, /* batchscan_enb_disable_cb; */
+ nullptr, /* batchscan_reports_cb; */
+ nullptr, /* batchscan_threshold_cb; */
+ nullptr, /* track_adv_event_cb; */
+};
+
+const btgatt_callbacks_t gatt_callbacks = {
+ /** Set to sizeof(btgatt_callbacks_t) */
+ sizeof(btgatt_callbacks_t),
+
+ /** GATT Client callbacks */
+ &gatt_client_callbacks,
+
+ /** GATT Server callbacks */
+ &gatt_server_callbacks};
+
+} // namespace
+
+namespace bluetooth {
+namespace gatt {
+
+int ServerInternals::Initialize(CoreStack *bt) {
+ // Get the interface to the GATT profile.
+ gatt = reinterpret_cast<const btgatt_interface_t *>(
+ bt->GetInterface(BT_PROFILE_GATT_ID));
+ if (!gatt) {
+ LOG_ERROR("Error getting GATT interface");
+ return -1;
+ }
+
+ bt_status_t btstat = gatt->init(&gatt_callbacks);
+ if (btstat != BT_STATUS_SUCCESS) {
+ LOG_ERROR("Failed to initialize gatt interface");
+ return -1;
+ }
+
+ int status = pipe(pipefd);
+ if (status == -1) {
+ LOG_ERROR("pipe creation failed: %s", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+ServerInternals::ServerInternals()
+ : gatt(nullptr),
+ server_if(0),
+ client_if(0),
+ service_handle(0),
+ pipefd{INVALID_FD, INVALID_FD} {}
+
+ServerInternals::~ServerInternals() {
+ if (pipefd[0] != INVALID_FD)
+ close(pipefd[0]);
+ if (pipefd[1] != INVALID_FD)
+ close(pipefd[1]);
+}
+
+Server::Server() : internal_(nullptr) {}
+
+Server::~Server() {}
+
+bool Server::Initialize(const Uuid &service_id, int *gatt_pipe, CoreStack *bt) {
+ internal_.reset(new ServerInternals);
+ if (!internal_) {
+ LOG_ERROR("Error creating internals");
+ return false;
+ }
+ internal = internal_.get();
+
+ std::unique_lock<std::mutex> lock(internal_->lock);
+ int status = internal_->Initialize(bt);
+ if (status) {
+ LOG_ERROR("Error initializing internals");
+ return false;
+ }
+
+ bt_uuid_t uuid = service_id.GetBlueDroid();
+
+ bt_status_t btstat = internal_->gatt->server->register_server(&uuid);
+ if (btstat != BT_STATUS_SUCCESS) {
+ LOG_ERROR("Failed to register server");
+ return false;
+ }
+
+ internal_->api_synchronize.wait(lock);
+ // TODO(icoolidge): Better error handling.
+ if (internal_->server_if == 0) {
+ LOG_ERROR("Initialization of server failed");
+ return false;
+ }
+
+ *gatt_pipe = internal_->pipefd[kPipeReadEnd];
+ LOG_INFO("Server Initialize succeeded");
+ return true;
+}
+
+bool Server::SetAdvertisement(const std::vector<Uuid> &ids,
+ const std::vector<uint8_t> &service_data,
+ bool transmit_name) {
+ std::vector<uint8_t> id_data;
+ auto mutable_service_data = service_data;
+
+ for (const Uuid &id : ids) {
+ const auto le_id = id.GetFullLittleEndian();
+ id_data.insert(id_data.end(), le_id.begin(), le_id.end());
+ }
+
+ std::lock_guard<std::mutex> lock(internal_->lock);
+
+ // Setup our advertisement. This has no callback.
+ bt_status_t btstat = internal->gatt->client->set_adv_data(
+ internal_->client_if, false, /* beacon, not scan response */
+ transmit_name, /* name */
+ false, /* no txpower */
+ 2, 2, /* interval */
+ 0, /* appearance */
+ 0, nullptr, /* no mfg data */
+ mutable_service_data.size(),
+ reinterpret_cast<char *>(mutable_service_data.data()), id_data.size(),
+ reinterpret_cast<char *>(id_data.data()));
+ if (btstat != BT_STATUS_SUCCESS) {
+ LOG_ERROR("Failed to set advertising data");
+ return false;
+ }
+ return true;
+}
+
+bool Server::SetScanResponse(const std::vector<Uuid> &ids,
+ const std::vector<uint8_t> &service_data,
+ bool transmit_name) {
+ std::vector<uint8_t> id_data;
+ auto mutable_service_data = service_data;
+
+ for (const Uuid &id : ids) {
+ const auto le_id = id.GetFullLittleEndian();
+ id_data.insert(id_data.end(), le_id.begin(), le_id.end());
+ }
+
+ std::lock_guard<std::mutex> lock(internal_->lock);
+
+ // Setup our advertisement. This has no callback.
+ bt_status_t btstat = internal->gatt->client->set_adv_data(
+ internal_->client_if, true, /* scan response */
+ transmit_name, /* name */
+ false, /* no txpower */
+ 2, 2, /* interval */
+ 0, /* appearance */
+ 0, nullptr, /* no mfg data */
+ mutable_service_data.size(),
+ reinterpret_cast<char *>(mutable_service_data.data()), id_data.size(),
+ reinterpret_cast<char *>(id_data.data()));
+ if (btstat != BT_STATUS_SUCCESS) {
+ LOG_ERROR("Failed to set scan response data");
+ return false;
+ }
+ return true;
+}
+
+bool Server::AddCharacteristic(const Uuid &id, int properties, int permissions) {
+ bt_uuid_t char_id = id.GetBlueDroid();
+
+ std::unique_lock<std::mutex> lock(internal->lock);
+ bt_status_t btstat = internal->gatt->server->add_characteristic(
+ internal->server_if, internal->service_handle, &char_id, properties,
+ permissions);
+ internal_->api_synchronize.wait(lock);
+ const int handle = internal->uuid_to_attribute[id];
+ internal->characteristics[handle].notify = properties & kPropertyNotify;
+ return true;
+}
+
+bool Server::AddBlob(const Uuid &id, const Uuid &control_id, int properties,
+ int permissions) {
+ bt_uuid_t char_id = id.GetBlueDroid();
+ bt_uuid_t ctrl_id = control_id.GetBlueDroid();
+
+ std::unique_lock<std::mutex> lock(internal->lock);
+
+ // First, add the primary attribute (characteristic value)
+ bt_status_t btstat = internal->gatt->server->add_characteristic(
+ internal->server_if, internal->service_handle, &char_id, properties,
+ permissions);
+ internal->api_synchronize.wait(lock);
+
+ // Next, add the secondary attribute (blob control).
+ // Control attributes have fixed permissions/properties.
+ const int kControlPermissions = kPermissionRead | kPermissionWrite;
+ const int kControlProperties = kPropertyRead | kPropertyWrite;
+
+ btstat = internal->gatt->server->add_characteristic(
+ internal->server_if, internal->service_handle, &ctrl_id,
+ kControlProperties, kControlPermissions);
+ internal->api_synchronize.wait(lock);
+
+ // Finally, associate the control attribute with the value attribute.
+ // Also, initialize the control attribute to a readable zero.
+ const int control_attribute = internal->uuid_to_attribute[control_id];
+ const int blob_attribute = internal->uuid_to_attribute[id];
+ internal->controlled_blobs[control_attribute] = blob_attribute;
+ internal->characteristics[blob_attribute].notify = properties & kPropertyNotify;
+
+ Characteristic &ctrl = internal->characteristics[control_attribute];
+ ctrl.next_blob.clear();
+ ctrl.next_blob.push_back(0);
+ ctrl.next_blob_pending = true;
+ ctrl.blob_section = 0;
+ ctrl.notify = false;
+ return true;
+}
+
+bool Server::Start() {
+ std::unique_lock<std::mutex> lock(internal_->lock);
+ bt_status_t btstat = internal_->gatt->server->start_service(
+ internal_->server_if, internal_->service_handle, GATT_TRANSPORT_LE);
+ internal_->api_synchronize.wait(lock);
+ return true;
+}
+
+bool Server::Stop() {
+ std::unique_lock<std::mutex> lock(internal_->lock);
+ bt_status_t btstat = internal_->gatt->server->stop_service(
+ internal_->server_if, internal_->service_handle);
+ internal_->api_synchronize.wait(lock);
+ return true;
+}
+
+bool Server::ScanEnable() {
+ bt_status_t btstat = internal_->gatt->client->scan(true);
+ if (btstat) {
+ LOG_ERROR("Enable scan failed: %d", btstat);
+ return false;
+ }
+ return true;
+}
+
+bool Server::ScanDisable() {
+ bt_status_t btstat = internal_->gatt->client->scan(false);
+ if (btstat) {
+ LOG_ERROR("Disable scan failed: %d", btstat);
+ return false;
+ }
+ return true;
+}
+
+bool Server::GetScanResults(ScanResults *results) {
+ std::lock_guard<std::mutex> lock(internal_->lock);
+ *results = internal_->scan_results;
+ return true;
+}
+
+bool Server::SetCharacteristicValue(const Uuid &id,
+ const std::vector<uint8_t> &value) {
+ std::lock_guard<std::mutex> lock(internal->lock);
+ const int attribute_id = internal->uuid_to_attribute[id];
+ Characteristic &ch = internal->characteristics[attribute_id];
+ ch.next_blob = value;
+ ch.next_blob_pending = true;
+
+ if (!ch.notify)
+ return true;
+
+ for (auto connection : internal->connections) {
+ char dummy = 0;
+ internal_->gatt->server->send_indication(internal->server_if,
+ attribute_id,
+ connection,
+ sizeof(dummy),
+ true,
+ &dummy);
+ }
+ return true;
+}
+
+bool Server::GetCharacteristicValue(const Uuid &id, std::vector<uint8_t> *value) {
+ std::lock_guard<std::mutex> lock(internal_->lock);
+ const int attribute_id = internal_->uuid_to_attribute[id];
+ *value = internal_->characteristics[attribute_id].blob;
+ return true;
+}
+
+} // namespace gatt
+} // namespace bluetooth
diff --git a/service/gatt_server.h b/service/gatt_server.h
new file mode 100644
index 0000000..2328395
--- /dev/null
+++ b/service/gatt_server.h
@@ -0,0 +1,117 @@
+//
+// Copyright (C) 2015 Google, Inc.
+//
+// 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.
+//
+#pragma once
+
+#include <array>
+#include <memory>
+#include <unordered_map>
+#include <vector>
+
+#include "hardware/bluetooth.h"
+#include "hardware/bt_gatt.h"
+#include "uuid.h"
+
+namespace bluetooth {
+
+class CoreStack;
+
+namespace gatt {
+
+// Attribute permission values
+const int kPermissionRead = 0x1;
+const int kPermissionReadEncrypted = 0x2;
+const int kPermissionReadEncryptedMitm = 0x4;
+const int kPermissionWrite = 0x10;
+const int kPermissionWriteEnecrypted = 0x20;
+const int KPermissionWriteEncryptedMitm = 0x40;
+const int kPermissionWriteSigned = 0x80;
+const int kPermissionWriteSignedMitm = 0x100;
+
+// GATT characteristic properties bit-field values
+const int kPropertyBroadcast = 0x1;
+const int kPropertyRead = 0x2;
+const int kPropertyWriteNoResponse = 0x4;
+const int kPropertyWrite = 0x8;
+const int kPropertyNotify = 0x10;
+const int kPropertyIndicate = 0x20;
+const int kPropertySignedWrite = 0x40;
+const int kPropertyExtendedProps = 0x80;
+
+// A mapping from string bluetooth addresses to RSSI measurements.
+typedef std::unordered_map<std::string, int> ScanResults;
+
+class ServerInternals;
+
+// Server is threadsafe and internally locked.
+// Asynchronous IO is identified via a gatt_pipe FD,
+// and synchronously read with 'GetCharacteristicValue'
+class Server {
+ public:
+ Server();
+ ~Server();
+
+ // Register GATT interface, initialize internal state,
+ // and open a pipe for characteristic write notification.
+ bool Initialize(const Uuid &service_id, int *gatt_pipe, CoreStack *bt);
+
+ // Control the content of service advertisement.
+ bool SetAdvertisement(const std::vector<Uuid> &ids,
+ const std::vector<uint8_t> &service_data,
+ bool transmit_name);
+
+ // Control the content of service scan response.
+ bool SetScanResponse(const std::vector<Uuid> &ids,
+ const std::vector<uint8_t> &service_data,
+ bool transmit_name);
+
+ // Add an ordinary characteristic for reading and/or writing.
+ bool AddCharacteristic(const Uuid &id, int properties, int permissions);
+
+ // Add a special 'blob' characteristic with a corresponding control
+ // attribute to manipulate which part of the blob the attribute represents.
+ bool AddBlob(const Uuid &id, const Uuid &control_id, int properties,
+ int permissions);
+
+ // Put a new value into a characeteristic.
+ // It will be read from a client starting at the next 0-offset read.
+ bool SetCharacteristicValue(const Uuid &id, const std::vector<uint8_t> &value);
+
+ // Get the current value of a characteristic.
+ bool GetCharacteristicValue(const Uuid &id, std::vector<uint8_t> *value);
+
+ // Start this service. Activate advertisements, allow connections.
+ // Characteristics should all be created before this.
+ bool Start();
+
+ // Cease advertisements and disallow connections.
+ bool Stop();
+
+ // Enable LE scan. Scan results will be cached internally.
+ bool ScanEnable();
+
+ // Disable LE scan.
+ bool ScanDisable();
+
+ // Copy out the cached scan results.
+ bool GetScanResults(ScanResults *results);
+
+ private:
+ // Internal data.
+ std::unique_ptr<ServerInternals> internal_;
+};
+
+} // namespace gatt
+} // namespace bluetooth
diff --git a/service/host.cpp b/service/host.cpp
new file mode 100644
index 0000000..fb38f18
--- /dev/null
+++ b/service/host.cpp
@@ -0,0 +1,313 @@
+//
+// Copyright (C) 2015 Google, Inc.
+//
+// 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 "host.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include <algorithm>
+
+#define LOG_TAG "BluetoothHost"
+#include "osi/include/log.h"
+
+#include "base/base64.h"
+#include "base/string_number_conversions.h"
+#include "base/string_split.h"
+#include "core_stack.h"
+#include "gatt_server.h"
+#include "uuid.h"
+
+namespace {
+
+// IPC API is according to:
+// https://docs.google.com/document/d/1eRnku-jAyVU1wGJsLT2CzWi0-8bs2g49s1b3FR_GApM
+const char kSetAdapterNameCommand[] = "set-device-name";
+const char kCreateServiceCommand[] = "create-service";
+const char kDestroyServiceCommand[] = "destroy-service";
+const char kAddCharacteristicCommand[] = "add-characteristic";
+const char kSetCharacteristicValueCommand[] = "set-characteristic-value";
+const char kSetAdvertisementCommand[] = "set-advertisement";
+const char kSetScanResponseCommand[] = "set-scan-response";
+const char kStartServiceCommand[] = "start-service";
+const char kStopServiceCommand[] = "stop-service";
+const char kWriteCharacteristicCommand[] = "write-characteristic";
+
+// Useful values for indexing Host::pfds_
+// Not super general considering that we should be able to support
+// many GATT FDs owned by one Host.
+enum {
+ kFdIpc = 0,
+ kFdGatt = 1,
+ kPossibleFds = 2,
+};
+
+bool TokenBool(const std::string& text) {
+ return text == "true";
+}
+
+} // namespace
+
+namespace bluetooth {
+
+Host::Host(int sockfd, CoreStack* bt)
+ : bt_(bt), pfds_(1, {sockfd, POLLIN, 0}) {}
+
+Host::~Host() {
+ close(pfds_[0].fd);
+}
+
+bool Host::EventLoop() {
+ while (true) {
+ int status =
+ TEMP_FAILURE_RETRY(ppoll(pfds_.data(), pfds_.size(), nullptr, nullptr));
+ if (status < 1) {
+ LOG_ERROR("ppoll error");
+ return false;
+ }
+
+ if (pfds_[kFdIpc].revents && !OnMessage()) {
+ return false;
+ }
+
+ if (pfds_.size() == kPossibleFds &&
+ pfds_[kFdGatt].revents &&
+ !OnGattWrite()) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool Host::OnSetAdapterName(const std::string& name) {
+ std::string decoded_data;
+ base::Base64Decode(name, &decoded_data);
+ return bt_->SetAdapterName(decoded_data);
+}
+
+bool Host::OnCreateService(const std::string& service_uuid) {
+ gatt_servers_[service_uuid] = std::unique_ptr<gatt::Server>(new gatt::Server);
+
+ int gattfd;
+ bool status =
+ gatt_servers_[service_uuid]->Initialize(Uuid(service_uuid), &gattfd, bt_);
+ if (!status) {
+ LOG_ERROR("Failed to initialize bluetooth");
+ return false;
+ }
+ pfds_.resize(kPossibleFds);
+ pfds_[kFdGatt] = {gattfd, POLLIN, 0};
+ return true;
+}
+
+bool Host::OnDestroyService(const std::string& service_uuid) {
+ gatt_servers_.erase(service_uuid);
+ close(pfds_[1].fd);
+ pfds_.resize(1);
+ return true;
+}
+
+bool Host::OnAddCharacteristic(const std::string& service_uuid,
+ const std::string& characteristic_uuid,
+ const std::string& control_uuid,
+ const std::string& options) {
+ const std::vector<std::string> option_tokens(
+ base::SplitString(options, '.'));
+
+ int properties_mask = 0;
+ int permissions_mask = 0;
+
+ if (std::find(option_tokens.begin(), option_tokens.end(), "notify") !=
+ option_tokens.end()) {
+ permissions_mask |= gatt::kPermissionRead;
+ properties_mask |= gatt::kPropertyRead;
+ properties_mask |= gatt::kPropertyNotify;
+ }
+ if (std::find(option_tokens.begin(), option_tokens.end(), "read") !=
+ option_tokens.end()) {
+ permissions_mask |= gatt::kPermissionRead;
+ properties_mask |= gatt::kPropertyRead;
+ }
+ if (std::find(option_tokens.begin(), option_tokens.end(), "write") !=
+ option_tokens.end()) {
+ permissions_mask |= gatt::kPermissionWrite;
+ properties_mask |= gatt::kPropertyWrite;
+ }
+
+ if (control_uuid.empty()) {
+ gatt_servers_[service_uuid]->AddCharacteristic(
+ Uuid(characteristic_uuid), properties_mask, permissions_mask);
+ } else {
+ gatt_servers_[service_uuid]->AddBlob(Uuid(characteristic_uuid),
+ Uuid(control_uuid), properties_mask,
+ permissions_mask);
+ }
+ return true;
+}
+
+bool Host::OnSetCharacteristicValue(const std::string& service_uuid,
+ const std::string& characteristic_uuid,
+ const std::string& value) {
+ std::string decoded_data;
+ base::Base64Decode(value, &decoded_data);
+ std::vector<uint8_t> blob_data(decoded_data.begin(), decoded_data.end());
+ gatt_servers_[service_uuid]->SetCharacteristicValue(Uuid(characteristic_uuid),
+ blob_data);
+ return true;
+}
+
+bool Host::OnSetAdvertisement(const std::string& service_uuid,
+ const std::string& advertise_uuids,
+ const std::string& advertise_data,
+ const std::string& transmit_name) {
+ LOG_INFO("%s: service:%s uuids:%s data:%s", __func__, service_uuid.c_str(),
+ advertise_uuids.c_str(), advertise_data.c_str());
+
+ const std::vector<std::string> advertise_uuid_tokens(
+ base::SplitString(advertise_uuids, '.'));
+
+ // string -> vector<Uuid>
+ std::vector<Uuid> ids;
+ for (const auto& uuid_token : advertise_uuid_tokens)
+ ids.emplace_back(uuid_token);
+
+ std::string decoded_data;
+ base::Base64Decode(advertise_data, &decoded_data);
+ std::vector<uint8_t> blob_data(decoded_data.begin(), decoded_data.end());
+ gatt_servers_[service_uuid]->SetAdvertisement(ids, blob_data,
+ TokenBool(transmit_name));
+ return true;
+}
+
+bool Host::OnSetScanResponse(const std::string& service_uuid,
+ const std::string& scan_response_uuids,
+ const std::string& scan_response_data,
+ const std::string& transmit_name) {
+ const std::vector<std::string> scan_response_uuid_tokens(
+ base::SplitString(scan_response_uuids, '.'));
+
+ // string -> vector<Uuid>
+ std::vector<Uuid> ids;
+ for (const auto& uuid_token : scan_response_uuid_tokens)
+ ids.emplace_back(uuid_token);
+
+ std::string decoded_data;
+ base::Base64Decode(scan_response_data, &decoded_data);
+ std::vector<uint8_t> blob_data(decoded_data.begin(), decoded_data.end());
+ gatt_servers_[service_uuid]->SetScanResponse(ids, blob_data,
+ TokenBool(transmit_name));
+ return true;
+}
+
+bool Host::OnStartService(const std::string& service_uuid) {
+ return gatt_servers_[service_uuid]->Start();
+}
+
+bool Host::OnStopService(const std::string& service_uuid) {
+ return gatt_servers_[service_uuid]->Stop();
+}
+
+bool Host::OnMessage() {
+ std::string ipc_msg;
+ int size = recv(pfds_[kFdIpc].fd, &ipc_msg[0], 0, MSG_PEEK | MSG_TRUNC);
+ if (-1 == size) {
+ LOG_ERROR("Error reading datagram size: %s", strerror(errno));
+ return false;
+ } else if (0 == size) {
+ LOG_INFO("%s:%d: Connection closed", __func__, __LINE__);
+ return false;
+ }
+
+ ipc_msg.resize(size);
+ size = read(pfds_[kFdIpc].fd, &ipc_msg[0], ipc_msg.size());
+ if (-1 == size) {
+ LOG_ERROR("Error reading IPC: %s", strerror(errno));
+ return false;
+ } else if (0 == size) {
+ LOG_INFO("%s:%d: Connection closed", __func__, __LINE__);
+ return false;
+ }
+
+ const std::vector<std::string> tokens(base::SplitString(ipc_msg, '|'));
+ switch (tokens.size()) {
+ case 2:
+ if (tokens[0] == kSetAdapterNameCommand)
+ return OnSetAdapterName(tokens[1]);
+ if (tokens[0] == kCreateServiceCommand)
+ return OnCreateService(tokens[1]);
+ if (tokens[0] == kDestroyServiceCommand)
+ return OnDestroyService(tokens[1]);
+ if (tokens[0] == kStartServiceCommand)
+ return OnStartService(tokens[1]);
+ if (tokens[0] == kStopServiceCommand)
+ return OnStopService(tokens[1]);
+ break;
+ case 4:
+ if (tokens[0] == kSetCharacteristicValueCommand)
+ return OnSetCharacteristicValue(tokens[1], tokens[2], tokens[3]);
+ break;
+ case 5:
+ if (tokens[0] == kSetAdvertisementCommand)
+ return OnSetAdvertisement(tokens[1], tokens[2], tokens[3], tokens[4]);
+ if (tokens[0] == kSetScanResponseCommand)
+ return OnSetScanResponse(tokens[1], tokens[2], tokens[3], tokens[4]);
+ if (tokens[0] == kAddCharacteristicCommand)
+ return OnAddCharacteristic(tokens[1], tokens[2], tokens[3], tokens[4]);
+ break;
+ default:
+ break;
+ }
+
+ LOG_ERROR("Malformed IPC message: %s", ipc_msg.c_str());
+ return false;
+}
+
+bool Host::OnGattWrite() {
+ Uuid::Uuid128Bit id;
+ int r = read(pfds_[kFdGatt].fd, id.data(), id.size());
+ if (r != id.size()) {
+ LOG_ERROR("Error reading GATT attribute ID");
+ return false;
+ }
+
+ std::vector<uint8_t> value;
+ // TODO(icoolidge): Generalize this for multiple clients.
+ auto server = gatt_servers_.begin();
+ server->second->GetCharacteristicValue(Uuid(id), &value);
+ const std::string value_string(value.begin(), value.end());
+ std::string encoded_value;
+ base::Base64Encode(value_string, &encoded_value);
+
+ std::string transmit(kWriteCharacteristicCommand);
+ transmit += "|" + server->first;
+ transmit += "|" + base::HexEncode(id.data(), id.size());
+ transmit += "|" + encoded_value;
+
+ r = write(pfds_[kFdIpc].fd, transmit.data(), transmit.size());
+ if (-1 == r) {
+ LOG_ERROR("Error replying to IPC: %s", strerror(errno));
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace bluetooth
diff --git a/service/host.h b/service/host.h
new file mode 100644
index 0000000..e695717
--- /dev/null
+++ b/service/host.h
@@ -0,0 +1,102 @@
+//
+// Copyright (C) 2015 Google, Inc.
+//
+// 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.
+//
+#pragma once
+
+#include <poll.h>
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+
+#include "gatt_server.h"
+#include "uuid.h"
+
+namespace bluetooth {
+
+class CoreStack;
+
+// This implements a single threaded event loop which dispatches
+// reads from a set of FDs (pfds_) to a set of handlers.
+// Reads from the GATT pipe read end will result in a write to
+// to the IPC socket, and vise versa.
+class Host {
+ public:
+ // Host owns the passed sockfd.
+ Host(int sockfd, CoreStack* bt);
+ ~Host();
+
+ // Synchronously handle all events on input FDs.
+ bool EventLoop();
+
+ private:
+ // Handler for IPC message receives.
+ // Decodes protocol and dispatches to another handler.
+ bool OnMessage();
+
+ // Handler for GATT characteristic writes.
+ // Encodes to protocol and transmits IPC.
+ bool OnGattWrite();
+
+ // Applies adapter name changes to stack.
+ bool OnSetAdapterName(const std::string& name);
+
+ // Handles service creation.
+ bool OnCreateService(const std::string& service_uuid);
+
+ // Handles service destruction.
+ bool OnDestroyService(const std::string& service_uuid);
+
+ // Creates a characteristic for a service.
+ bool OnAddCharacteristic(const std::string& service_uuid,
+ const std::string& characteristic_uuid,
+ const std::string& control_uuid,
+ const std::string& options);
+
+ // Sets the value of a characetistic.
+ bool OnSetCharacteristicValue(const std::string& service_uuid,
+ const std::string& characteristic_uuid,
+ const std::string& value);
+
+ // Applies settings to service advertisement.
+ bool OnSetAdvertisement(const std::string& service_uuid,
+ const std::string& advertise_uuids,
+ const std::string& advertise_data,
+ const std::string& transmit_name);
+
+ // Applies settings to scan response.
+ bool OnSetScanResponse(const std::string& service_uuid,
+ const std::string& advertise_uuids,
+ const std::string& advertise_data,
+ const std::string& transmit_name);
+
+ // Starts service (advertisement and connections)
+ bool OnStartService(const std::string& service_uuid);
+
+ // Stops service.
+ bool OnStopService(const std::string& service_uuid);
+
+ // weak reference.
+ CoreStack *bt_;
+
+ // File descripters that we will block against.
+ std::vector<struct pollfd> pfds_;
+
+ // Container for multiple GATT servers. Currently only one is supported.
+ // TODO(icoolidge): support many to one for real.
+ std::unordered_map<std::string, std::unique_ptr<gatt::Server>> gatt_servers_;
+};
+
+} // namespace bluetooth
diff --git a/service/logging_helpers.cpp b/service/logging_helpers.cpp
new file mode 100644
index 0000000..59cde12
--- /dev/null
+++ b/service/logging_helpers.cpp
@@ -0,0 +1,135 @@
+//
+// Copyright (C) 2015 Google, Inc.
+//
+// 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 "logging_helpers.h"
+
+#include <string.h>
+
+#include <string>
+
+#define CASE_RETURN_TEXT(code) \
+ case code: \
+ return #code
+
+const char *BtAvConnectionStateText(const btav_connection_state_t state) {
+ switch (state) {
+ CASE_RETURN_TEXT(BTAV_CONNECTION_STATE_DISCONNECTED);
+ CASE_RETURN_TEXT(BTAV_CONNECTION_STATE_CONNECTING);
+ CASE_RETURN_TEXT(BTAV_CONNECTION_STATE_CONNECTED);
+ CASE_RETURN_TEXT(BTAV_CONNECTION_STATE_DISCONNECTING);
+ default:
+ return "Invalid AV connection state";
+ }
+}
+
+const char *BtAvAudioStateText(const btav_audio_state_t state) {
+ switch (state) {
+ CASE_RETURN_TEXT(BTAV_AUDIO_STATE_REMOTE_SUSPEND);
+ CASE_RETURN_TEXT(BTAV_AUDIO_STATE_STOPPED);
+ CASE_RETURN_TEXT(BTAV_AUDIO_STATE_STARTED);
+ default:
+ return "Invalid audio state";
+ }
+}
+
+const char *BtTransportText(const btgatt_transport_t t) {
+ switch(t) {
+ CASE_RETURN_TEXT(GATT_TRANSPORT_AUTO);
+ CASE_RETURN_TEXT(GATT_TRANSPORT_BREDR);
+ CASE_RETURN_TEXT(GATT_TRANSPORT_LE);
+ default:
+ return "unknown transport";
+ }
+}
+
+const char *BtStateText(const bt_state_t state) {
+ switch (state) {
+ CASE_RETURN_TEXT(BT_STATE_OFF);
+ CASE_RETURN_TEXT(BT_STATE_ON);
+ default:
+ return "unknown state code";
+ }
+}
+
+const char *BtScanModeText(const bt_scan_mode_t mode) {
+ switch (mode) {
+ CASE_RETURN_TEXT(BT_SCAN_MODE_NONE);
+ CASE_RETURN_TEXT(BT_SCAN_MODE_CONNECTABLE);
+ CASE_RETURN_TEXT(BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+ default:
+ return "unknown scan mode";
+ }
+}
+
+const char *BtStatusText(const bt_status_t status) {
+ switch (status) {
+ CASE_RETURN_TEXT(BT_STATUS_SUCCESS);
+ CASE_RETURN_TEXT(BT_STATUS_FAIL);
+ CASE_RETURN_TEXT(BT_STATUS_NOT_READY);
+ CASE_RETURN_TEXT(BT_STATUS_NOMEM);
+ CASE_RETURN_TEXT(BT_STATUS_DONE);
+ CASE_RETURN_TEXT(BT_STATUS_BUSY);
+ CASE_RETURN_TEXT(BT_STATUS_UNSUPPORTED);
+ default:
+ return "unknown status code";
+ }
+}
+
+const char *BtPropertyText(const bt_property_type_t prop) {
+ switch (prop) {
+ CASE_RETURN_TEXT(BT_PROPERTY_BDNAME);
+ CASE_RETURN_TEXT(BT_PROPERTY_BDADDR);
+ CASE_RETURN_TEXT(BT_PROPERTY_UUIDS);
+ CASE_RETURN_TEXT(BT_PROPERTY_CLASS_OF_DEVICE);
+ CASE_RETURN_TEXT(BT_PROPERTY_TYPE_OF_DEVICE);
+ CASE_RETURN_TEXT(BT_PROPERTY_SERVICE_RECORD);
+ CASE_RETURN_TEXT(BT_PROPERTY_ADAPTER_SCAN_MODE);
+ CASE_RETURN_TEXT(BT_PROPERTY_ADAPTER_BONDED_DEVICES);
+ CASE_RETURN_TEXT(BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT);
+ CASE_RETURN_TEXT(BT_PROPERTY_REMOTE_FRIENDLY_NAME);
+ CASE_RETURN_TEXT(BT_PROPERTY_REMOTE_RSSI);
+ CASE_RETURN_TEXT(BT_PROPERTY_REMOTE_VERSION_INFO);
+ CASE_RETURN_TEXT(BT_PROPERTY_LOCAL_LE_FEATURES);
+ CASE_RETURN_TEXT(BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP);
+ default:
+ return "Invalid property";
+ }
+}
+
+const char *BtEventText(const bt_cb_thread_evt evt) {
+ switch (evt) {
+ CASE_RETURN_TEXT(ASSOCIATE_JVM);
+ CASE_RETURN_TEXT(DISASSOCIATE_JVM);
+ default:
+ return "unknown state code";
+ }
+}
+
+const char *BtAclText(const bt_acl_state_t code) {
+ switch (code) {
+ CASE_RETURN_TEXT(BT_ACL_STATE_CONNECTED);
+ CASE_RETURN_TEXT(BT_ACL_STATE_DISCONNECTED);
+ default:
+ return "unknown ACL code";
+ }
+}
+
+std::string BtAddrString(const bt_bdaddr_t *addr) {
+ char buffer[20];
+ snprintf(buffer, sizeof(buffer), "%02X:%02X:%02X:%02X:%02X:%02X",
+ addr->address[0], addr->address[1], addr->address[2],
+ addr->address[3], addr->address[4], addr->address[5]);
+ return std::string(buffer);
+}
diff --git a/service/logging_helpers.h b/service/logging_helpers.h
new file mode 100644
index 0000000..6baafa8
--- /dev/null
+++ b/service/logging_helpers.h
@@ -0,0 +1,45 @@
+//
+// Copyright (C) 2015 Google, Inc.
+//
+// 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.
+//
+#pragma once
+
+#include <string.h>
+
+#include <string>
+
+#include "hardware/bluetooth.h"
+#include "hardware/bt_av.h"
+#include "hardware/bt_gatt_types.h"
+
+const char *BtAvConnectionStateText(const btav_connection_state_t state);
+
+const char *BtAvAudioStateText(const btav_audio_state_t state);
+
+const char *BtTransportText(const btgatt_transport_t t);
+
+const char *BtStateText(const bt_state_t state);
+
+const char *BtScanModeText(const bt_scan_mode_t mode);
+
+const char *BtStatusText(const bt_status_t status);
+
+const char *BtPropertyText(const bt_property_type_t prop);
+
+const char *BtEventText(const bt_cb_thread_evt evt);
+
+const char *BtAclText(const bt_acl_state_t state);
+
+// TODO(icoolidge): Address object.
+std::string BtAddrString(const bt_bdaddr_t *addr);
diff --git a/service/main.cpp b/service/main.cpp
new file mode 100644
index 0000000..a818f74
--- /dev/null
+++ b/service/main.cpp
@@ -0,0 +1,77 @@
+//
+// Copyright (C) 2015 Google, Inc.
+//
+// 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 <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define LOG_TAG "BtHost"
+#include "osi/include/log.h"
+// For system properties
+// TODO(icoolidge): abstraction or non-cutils stub.
+#include <cutils/properties.h>
+// For init socket environment variable decode
+// TODO(icoolidge): abstraction or remove.
+#include <cutils/sockets.h>
+
+#include "core_stack.h"
+#include "host.h"
+
+namespace {
+
+const char kDisableProperty[] = "persist.bluetooth.disable";
+const char kSocketFromInit[] = "bluetooth";
+
+} // namespace
+
+int main() {
+ char disable_value[PROPERTY_VALUE_MAX];
+ int status = property_get(kDisableProperty, disable_value, nullptr);
+ if (status && !strcmp(disable_value, "1")) {
+ LOG_INFO("service disabled");
+ return EXIT_SUCCESS;
+ }
+
+ int server_socket = android_get_control_socket(kSocketFromInit);
+ if (server_socket == -1) {
+ LOG_ERROR("failed to get socket from init");
+ return EXIT_FAILURE;
+ }
+
+ status = listen(server_socket, SOMAXCONN);
+ if (status == -1) {
+ LOG_ERROR("listen failed: %s", strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ bluetooth::CoreStack bt;
+ bt.Initialize();
+
+ // TODO(icoolidge): accept simultaneous clients
+ while (true) {
+ int client_socket = accept4(server_socket, nullptr, nullptr, SOCK_NONBLOCK);
+ if (status == -1) {
+ LOG_ERROR("accept failed: %s", strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ LOG_INFO("client connected: %d", client_socket);
+ bluetooth::Host bluetooth_host(client_socket, &bt);
+ bluetooth_host.EventLoop();
+ }
+
+ close(server_socket);
+ return EXIT_SUCCESS;
+}
diff --git a/service/modp_b64/LICENSE b/service/modp_b64/LICENSE
new file mode 100644
index 0000000..55af76f
--- /dev/null
+++ b/service/modp_b64/LICENSE
@@ -0,0 +1,33 @@
+ * MODP_B64 - High performance base64 encoder/decoder
+ * Version 1.3 -- 17-Mar-2006
+ * http://modp.com/release/base64
+ *
+ * Copyright (c) 2005, 2006 Nick Galbreath -- nickg [at] modp [dot] com
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of the modp.com nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/service/modp_b64/README.chromium b/service/modp_b64/README.chromium
new file mode 100644
index 0000000..35b9e54
--- /dev/null
+++ b/service/modp_b64/README.chromium
@@ -0,0 +1,15 @@
+Name: modp base64 decoder
+Short Name: stringencoders
+URL: http://code.google.com/p/stringencoders/
+Version: unknown
+License: BSD
+Security Critical: yes
+
+Description:
+The modp_b64.c file was modified to remove the inclusion of modp's config.h
+and to fix compilation errors that occur under VC8. The file was renamed
+modp_b64.cc to force it to be compiled as C++ so that the inclusion of
+basictypes.h could be possible.
+
+The modp_b64.cc and modp_b64.h files were modified to make them safe on
+64-bit systems.
diff --git a/service/modp_b64/modp_b64.cpp b/service/modp_b64/modp_b64.cpp
new file mode 100644
index 0000000..e5f6cf1
--- /dev/null
+++ b/service/modp_b64/modp_b64.cpp
@@ -0,0 +1,265 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
+/* vi: set expandtab shiftwidth=4 tabstop=4: */
+/**
+ * \file
+ * <PRE>
+ * MODP_B64 - High performance base64 encoder/decoder
+ * Version 1.3 -- 17-Mar-2006
+ * http://modp.com/release/base64
+ *
+ * Copyright © 2005, 2006 Nick Galbreath -- nickg [at] modp [dot] com
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of the modp.com nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This is the standard "new" BSD license:
+ * http://www.opensource.org/licenses/bsd-license.php
+ * </PRE>
+ */
+
+/* public header */
+#include "modp_b64.h"
+
+/*
+ * If you are ripping this out of the library, comment out the next
+ * line and uncomment the next lines as approrpiate
+ */
+//#include "config.h"
+
+/* if on motoral, sun, ibm; uncomment this */
+/* #define WORDS_BIGENDIAN 1 */
+/* else for Intel, Amd; uncomment this */
+/* #undef WORDS_BIGENDIAN */
+
+#include "modp_b64_data.h"
+
+#define BADCHAR 0x01FFFFFF
+
+/**
+ * you can control if we use padding by commenting out this
+ * next line. However, I highly recommend you use padding and not
+ * using it should only be for compatability with a 3rd party.
+ * Also, 'no padding' is not tested!
+ */
+#define DOPAD 1
+
+/*
+ * if we aren't doing padding
+ * set the pad character to NULL
+ */
+#ifndef DOPAD
+#undef CHARPAD
+#define CHARPAD '\0'
+#endif
+
+size_t modp_b64_encode(char* dest, const char* str, size_t len)
+{
+ size_t i = 0;
+ uint8_t* p = (uint8_t*) dest;
+
+ /* unsigned here is important! */
+ uint8_t t1, t2, t3;
+
+ if (len > 2) {
+ for (; i < len - 2; i += 3) {
+ t1 = str[i]; t2 = str[i+1]; t3 = str[i+2];
+ *p++ = e0[t1];
+ *p++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
+ *p++ = e1[((t2 & 0x0F) << 2) | ((t3 >> 6) & 0x03)];
+ *p++ = e2[t3];
+ }
+ }
+
+ switch (len - i) {
+ case 0:
+ break;
+ case 1:
+ t1 = str[i];
+ *p++ = e0[t1];
+ *p++ = e1[(t1 & 0x03) << 4];
+ *p++ = CHARPAD;
+ *p++ = CHARPAD;
+ break;
+ default: /* case 2 */
+ t1 = str[i]; t2 = str[i+1];
+ *p++ = e0[t1];
+ *p++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
+ *p++ = e2[(t2 & 0x0F) << 2];
+ *p++ = CHARPAD;
+ }
+
+ *p = '\0';
+ return p - (uint8_t*)dest;
+}
+
+#ifdef WORDS_BIGENDIAN /* BIG ENDIAN -- SUN / IBM / MOTOROLA */
+int modp_b64_decode(char* dest, const char* src, int len)
+{
+ if (len == 0) return 0;
+
+#ifdef DOPAD
+ /* if padding is used, then the message must be at least
+ 4 chars and be a multiple of 4.
+ there can be at most 2 pad chars at the end */
+ if (len < 4 || (len % 4 != 0)) return MODP_B64_ERROR;
+ if (src[len-1] == CHARPAD) {
+ len--;
+ if (src[len -1] == CHARPAD) {
+ len--;
+ }
+ }
+#endif /* DOPAD */
+
+ size_t i;
+ int leftover = len % 4;
+ size_t chunks = (leftover == 0) ? len / 4 - 1 : len /4;
+
+ uint8_t* p = (uint8_t*) dest;
+ uint32_t x = 0;
+ uint32_t* destInt = (uint32_t*) p;
+ uint32_t* srcInt = (uint32_t*) src;
+ uint32_t y = *srcInt++;
+ for (i = 0; i < chunks; ++i) {
+ x = d0[y >> 24 & 0xff] | d1[y >> 16 & 0xff] |
+ d2[y >> 8 & 0xff] | d3[y & 0xff];
+
+ if (x >= BADCHAR) return MODP_B64_ERROR;
+ *destInt = x << 8;
+ p += 3;
+ destInt = (uint32_t*)p;
+ y = *srcInt++;
+ }
+
+ switch (leftover) {
+ case 0:
+ x = d0[y >> 24 & 0xff] | d1[y >> 16 & 0xff] |
+ d2[y >> 8 & 0xff] | d3[y & 0xff];
+ if (x >= BADCHAR) return MODP_B64_ERROR;
+ *p++ = ((uint8_t*)&x)[1];
+ *p++ = ((uint8_t*)&x)[2];
+ *p = ((uint8_t*)&x)[3];
+ return (chunks+1)*3;
+ case 1:
+ x = d3[y >> 24];
+ *p = (uint8_t)x;
+ break;
+ case 2:
+ x = d3[y >> 24] *64 + d3[(y >> 16) & 0xff];
+ *p = (uint8_t)(x >> 4);
+ break;
+ default: /* case 3 */
+ x = (d3[y >> 24] *64 + d3[(y >> 16) & 0xff])*64 +
+ d3[(y >> 8) & 0xff];
+ *p++ = (uint8_t) (x >> 10);
+ *p = (uint8_t) (x >> 2);
+ break;
+ }
+
+ if (x >= BADCHAR) return MODP_B64_ERROR;
+ return 3*chunks + (6*leftover)/8;
+}
+
+#else /* LITTLE ENDIAN -- INTEL AND FRIENDS */
+
+size_t modp_b64_decode(char* dest, const char* src, size_t len)
+{
+ if (len == 0) return 0;
+
+#ifdef DOPAD
+ /*
+ * if padding is used, then the message must be at least
+ * 4 chars and be a multiple of 4
+ */
+ if (len < 4 || (len % 4 != 0)) return MODP_B64_ERROR; /* error */
+ /* there can be at most 2 pad chars at the end */
+ if (src[len-1] == CHARPAD) {
+ len--;
+ if (src[len -1] == CHARPAD) {
+ len--;
+ }
+ }
+#endif
+
+ size_t i;
+ int leftover = len % 4;
+ size_t chunks = (leftover == 0) ? len / 4 - 1 : len /4;
+
+ uint8_t* p = (uint8_t*)dest;
+ uint32_t x = 0;
+ uint32_t* destInt = (uint32_t*) p;
+ uint32_t* srcInt = (uint32_t*) src;
+ uint32_t y = *srcInt++;
+ for (i = 0; i < chunks; ++i) {
+ x = d0[y & 0xff] |
+ d1[(y >> 8) & 0xff] |
+ d2[(y >> 16) & 0xff] |
+ d3[(y >> 24) & 0xff];
+
+ if (x >= BADCHAR) return MODP_B64_ERROR;
+ *destInt = x ;
+ p += 3;
+ destInt = (uint32_t*)p;
+ y = *srcInt++;}
+
+
+ switch (leftover) {
+ case 0:
+ x = d0[y & 0xff] |
+ d1[(y >> 8) & 0xff] |
+ d2[(y >> 16) & 0xff] |
+ d3[(y >> 24) & 0xff];
+
+ if (x >= BADCHAR) return MODP_B64_ERROR;
+ *p++ = ((uint8_t*)(&x))[0];
+ *p++ = ((uint8_t*)(&x))[1];
+ *p = ((uint8_t*)(&x))[2];
+ return (chunks+1)*3;
+ break;
+ case 1: /* with padding this is an impossible case */
+ x = d0[y & 0xff];
+ *p = *((uint8_t*)(&x)); // i.e. first char/byte in int
+ break;
+ case 2: // * case 2, 1 output byte */
+ x = d0[y & 0xff] | d1[y >> 8 & 0xff];
+ *p = *((uint8_t*)(&x)); // i.e. first char
+ break;
+ default: /* case 3, 2 output bytes */
+ x = d0[y & 0xff] |
+ d1[y >> 8 & 0xff ] |
+ d2[y >> 16 & 0xff]; /* 0x3c */
+ *p++ = ((uint8_t*)(&x))[0];
+ *p = ((uint8_t*)(&x))[1];
+ break;
+ }
+
+ if (x >= BADCHAR) return MODP_B64_ERROR;
+
+ return 3*chunks + (6*leftover)/8;
+}
+
+#endif /* if bigendian / else / endif */
diff --git a/service/modp_b64/modp_b64.h b/service/modp_b64/modp_b64.h
new file mode 100644
index 0000000..3270e5f
--- /dev/null
+++ b/service/modp_b64/modp_b64.h
@@ -0,0 +1,171 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
+/* vi: set expandtab shiftwidth=4 tabstop=4: */
+
+/**
+ * \file
+ * <PRE>
+ * High performance base64 encoder / decoder
+ * Version 1.3 -- 17-Mar-2006
+ *
+ * Copyright © 2005, 2006, Nick Galbreath -- nickg [at] modp [dot] com
+ * All rights reserved.
+ *
+ * http://modp.com/release/base64
+ *
+ * Released under bsd license. See modp_b64.c for details.
+ * </pre>
+ *
+ * The default implementation is the standard b64 encoding with padding.
+ * It's easy to change this to use "URL safe" characters and to remove
+ * padding. See the modp_b64.c source code for details.
+ *
+ */
+
+#ifndef MODP_B64
+#define MODP_B64
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Encode a raw binary string into base 64.
+ * src contains the bytes
+ * len contains the number of bytes in the src
+ * dest should be allocated by the caller to contain
+ * at least modp_b64_encode_len(len) bytes (see below)
+ * This will contain the null-terminated b64 encoded result
+ * returns length of the destination string plus the ending null byte
+ * i.e. the result will be equal to strlen(dest) + 1
+ *
+ * Example
+ *
+ * \code
+ * char* src = ...;
+ * int srclen = ...; //the length of number of bytes in src
+ * char* dest = (char*) malloc(modp_b64_encode_len);
+ * int len = modp_b64_encode(dest, src, sourcelen);
+ * if (len == -1) {
+ * printf("Error\n");
+ * } else {
+ * printf("b64 = %s\n", dest);
+ * }
+ * \endcode
+ *
+ */
+size_t modp_b64_encode(char* dest, const char* str, size_t len);
+
+/**
+ * Decode a base64 encoded string
+ *
+ * src should contain exactly len bytes of b64 characters.
+ * if src contains -any- non-base characters (such as white
+ * space, -1 is returned.
+ *
+ * dest should be allocated by the caller to contain at least
+ * len * 3 / 4 bytes.
+ *
+ * Returns the length (strlen) of the output, or -1 if unable to
+ * decode
+ *
+ * \code
+ * char* src = ...;
+ * int srclen = ...; // or if you don't know use strlen(src)
+ * char* dest = (char*) malloc(modp_b64_decode_len(srclen));
+ * int len = modp_b64_decode(dest, src, sourcelen);
+ * if (len == -1) { error }
+ * \endcode
+ */
+size_t modp_b64_decode(char* dest, const char* src, size_t len);
+
+/**
+ * Given a source string of length len, this returns the amount of
+ * memory the destination string should have.
+ *
+ * remember, this is integer math
+ * 3 bytes turn into 4 chars
+ * ceiling[len / 3] * 4 + 1
+ *
+ * +1 is for any extra null.
+ */
+#define modp_b64_encode_len(A) ((A+2)/3 * 4 + 1)
+
+/**
+ * Given a base64 string of length len,
+ * this returns the amount of memory required for output string
+ * It maybe be more than the actual number of bytes written.
+ * NOTE: remember this is integer math
+ * this allocates a bit more memory than traditional versions of b64
+ * decode 4 chars turn into 3 bytes
+ * floor[len * 3/4] + 2
+ */
+#define modp_b64_decode_len(A) (A / 4 * 3 + 2)
+
+/**
+ * Will return the strlen of the output from encoding.
+ * This may be less than the required number of bytes allocated.
+ *
+ * This allows you to 'deserialized' a struct
+ * \code
+ * char* b64encoded = "...";
+ * int len = strlen(b64encoded);
+ *
+ * struct datastuff foo;
+ * if (modp_b64_encode_strlen(sizeof(struct datastuff)) != len) {
+ * // wrong size
+ * return false;
+ * } else {
+ * // safe to do;
+ * if (modp_b64_decode((char*) &foo, b64encoded, len) == -1) {
+ * // bad characters
+ * return false;
+ * }
+ * }
+ * // foo is filled out now
+ * \endcode
+ */
+#define modp_b64_encode_strlen(A) ((A + 2)/ 3 * 4)
+
+#define MODP_B64_ERROR ((size_t)-1)
+
+#ifdef __cplusplus
+}
+
+#include <string>
+
+inline std::string& modp_b64_encode(std::string& s)
+{
+ std::string x(modp_b64_encode_len(s.size()), '\0');
+ size_t d = modp_b64_encode(const_cast<char*>(x.data()), s.data(), (int)s.size());
+ x.erase(d, std::string::npos);
+ s.swap(x);
+ return s;
+}
+
+/**
+ * base 64 decode a string (self-modifing)
+ * On failure, the string is empty.
+ *
+ * This function is for C++ only (duh)
+ *
+ * \param[in,out] s the string to be decoded
+ * \return a reference to the input string
+ */
+inline std::string& modp_b64_decode(std::string& s)
+{
+ std::string x(modp_b64_decode_len(s.size()), '\0');
+ size_t d = modp_b64_decode(const_cast<char*>(x.data()), s.data(), (int)s.size());
+ if (d == MODP_B64_ERROR) {
+ x.clear();
+ } else {
+ x.erase(d, std::string::npos);
+ }
+ s.swap(x);
+ return s;
+}
+
+#endif /* __cplusplus */
+
+#endif /* MODP_B64 */
diff --git a/service/modp_b64/modp_b64_data.h b/service/modp_b64/modp_b64_data.h
new file mode 100644
index 0000000..9a777b8
--- /dev/null
+++ b/service/modp_b64/modp_b64_data.h
@@ -0,0 +1,482 @@
+//#include "build/build_config.h"
+#include <stdint.h>
+
+#define CHAR62 '+'
+#define CHAR63 '/'
+#define CHARPAD '='
+static const char e0[256] = {
+ 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C',
+ 'C', 'C', 'D', 'D', 'D', 'D', 'E', 'E', 'E', 'E',
+ 'F', 'F', 'F', 'F', 'G', 'G', 'G', 'G', 'H', 'H',
+ 'H', 'H', 'I', 'I', 'I', 'I', 'J', 'J', 'J', 'J',
+ 'K', 'K', 'K', 'K', 'L', 'L', 'L', 'L', 'M', 'M',
+ 'M', 'M', 'N', 'N', 'N', 'N', 'O', 'O', 'O', 'O',
+ 'P', 'P', 'P', 'P', 'Q', 'Q', 'Q', 'Q', 'R', 'R',
+ 'R', 'R', 'S', 'S', 'S', 'S', 'T', 'T', 'T', 'T',
+ 'U', 'U', 'U', 'U', 'V', 'V', 'V', 'V', 'W', 'W',
+ 'W', 'W', 'X', 'X', 'X', 'X', 'Y', 'Y', 'Y', 'Y',
+ 'Z', 'Z', 'Z', 'Z', 'a', 'a', 'a', 'a', 'b', 'b',
+ 'b', 'b', 'c', 'c', 'c', 'c', 'd', 'd', 'd', 'd',
+ 'e', 'e', 'e', 'e', 'f', 'f', 'f', 'f', 'g', 'g',
+ 'g', 'g', 'h', 'h', 'h', 'h', 'i', 'i', 'i', 'i',
+ 'j', 'j', 'j', 'j', 'k', 'k', 'k', 'k', 'l', 'l',
+ 'l', 'l', 'm', 'm', 'm', 'm', 'n', 'n', 'n', 'n',
+ 'o', 'o', 'o', 'o', 'p', 'p', 'p', 'p', 'q', 'q',
+ 'q', 'q', 'r', 'r', 'r', 'r', 's', 's', 's', 's',
+ 't', 't', 't', 't', 'u', 'u', 'u', 'u', 'v', 'v',
+ 'v', 'v', 'w', 'w', 'w', 'w', 'x', 'x', 'x', 'x',
+ 'y', 'y', 'y', 'y', 'z', 'z', 'z', 'z', '0', '0',
+ '0', '0', '1', '1', '1', '1', '2', '2', '2', '2',
+ '3', '3', '3', '3', '4', '4', '4', '4', '5', '5',
+ '5', '5', '6', '6', '6', '6', '7', '7', '7', '7',
+ '8', '8', '8', '8', '9', '9', '9', '9', '+', '+',
+ '+', '+', '/', '/', '/', '/'
+};
+
+static const char e1[256] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+ 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
+ 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
+ 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', '+', '/', 'A', 'B', 'C', 'D', 'E', 'F',
+ 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
+ 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
+ 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
+ '4', '5', '6', '7', '8', '9', '+', '/', 'A', 'B',
+ 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
+ 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
+ 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
+ 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ '+', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
+ 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b',
+ 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
+ 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5',
+ '6', '7', '8', '9', '+', '/'
+};
+
+static const char e2[256] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+ 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
+ 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
+ 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', '+', '/', 'A', 'B', 'C', 'D', 'E', 'F',
+ 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
+ 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
+ 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
+ '4', '5', '6', '7', '8', '9', '+', '/', 'A', 'B',
+ 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
+ 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
+ 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
+ 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ '+', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
+ 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b',
+ 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
+ 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5',
+ '6', '7', '8', '9', '+', '/'
+};
+
+
+
+#ifdef WORDS_BIGENDIAN
+
+
+/* SPECIAL DECODE TABLES FOR BIG ENDIAN (IBM/MOTOROLA/SUN) CPUS */
+
+static const uint32_t d0[256] = {
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x00f80000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00fc0000,
+0x00d00000, 0x00d40000, 0x00d80000, 0x00dc0000, 0x00e00000, 0x00e40000,
+0x00e80000, 0x00ec0000, 0x00f00000, 0x00f40000, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
+0x00040000, 0x00080000, 0x000c0000, 0x00100000, 0x00140000, 0x00180000,
+0x001c0000, 0x00200000, 0x00240000, 0x00280000, 0x002c0000, 0x00300000,
+0x00340000, 0x00380000, 0x003c0000, 0x00400000, 0x00440000, 0x00480000,
+0x004c0000, 0x00500000, 0x00540000, 0x00580000, 0x005c0000, 0x00600000,
+0x00640000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x00680000, 0x006c0000, 0x00700000, 0x00740000, 0x00780000,
+0x007c0000, 0x00800000, 0x00840000, 0x00880000, 0x008c0000, 0x00900000,
+0x00940000, 0x00980000, 0x009c0000, 0x00a00000, 0x00a40000, 0x00a80000,
+0x00ac0000, 0x00b00000, 0x00b40000, 0x00b80000, 0x00bc0000, 0x00c00000,
+0x00c40000, 0x00c80000, 0x00cc0000, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff
+};
+
+
+static const uint32_t d1[256] = {
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x0003e000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x0003f000,
+0x00034000, 0x00035000, 0x00036000, 0x00037000, 0x00038000, 0x00039000,
+0x0003a000, 0x0003b000, 0x0003c000, 0x0003d000, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
+0x00001000, 0x00002000, 0x00003000, 0x00004000, 0x00005000, 0x00006000,
+0x00007000, 0x00008000, 0x00009000, 0x0000a000, 0x0000b000, 0x0000c000,
+0x0000d000, 0x0000e000, 0x0000f000, 0x00010000, 0x00011000, 0x00012000,
+0x00013000, 0x00014000, 0x00015000, 0x00016000, 0x00017000, 0x00018000,
+0x00019000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x0001a000, 0x0001b000, 0x0001c000, 0x0001d000, 0x0001e000,
+0x0001f000, 0x00020000, 0x00021000, 0x00022000, 0x00023000, 0x00024000,
+0x00025000, 0x00026000, 0x00027000, 0x00028000, 0x00029000, 0x0002a000,
+0x0002b000, 0x0002c000, 0x0002d000, 0x0002e000, 0x0002f000, 0x00030000,
+0x00031000, 0x00032000, 0x00033000, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff
+};
+
+
+static const uint32_t d2[256] = {
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x00000f80, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000fc0,
+0x00000d00, 0x00000d40, 0x00000d80, 0x00000dc0, 0x00000e00, 0x00000e40,
+0x00000e80, 0x00000ec0, 0x00000f00, 0x00000f40, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
+0x00000040, 0x00000080, 0x000000c0, 0x00000100, 0x00000140, 0x00000180,
+0x000001c0, 0x00000200, 0x00000240, 0x00000280, 0x000002c0, 0x00000300,
+0x00000340, 0x00000380, 0x000003c0, 0x00000400, 0x00000440, 0x00000480,
+0x000004c0, 0x00000500, 0x00000540, 0x00000580, 0x000005c0, 0x00000600,
+0x00000640, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x00000680, 0x000006c0, 0x00000700, 0x00000740, 0x00000780,
+0x000007c0, 0x00000800, 0x00000840, 0x00000880, 0x000008c0, 0x00000900,
+0x00000940, 0x00000980, 0x000009c0, 0x00000a00, 0x00000a40, 0x00000a80,
+0x00000ac0, 0x00000b00, 0x00000b40, 0x00000b80, 0x00000bc0, 0x00000c00,
+0x00000c40, 0x00000c80, 0x00000cc0, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff
+};
+
+
+static const uint32_t d3[256] = {
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x0000003e, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x0000003f,
+0x00000034, 0x00000035, 0x00000036, 0x00000037, 0x00000038, 0x00000039,
+0x0000003a, 0x0000003b, 0x0000003c, 0x0000003d, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
+0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006,
+0x00000007, 0x00000008, 0x00000009, 0x0000000a, 0x0000000b, 0x0000000c,
+0x0000000d, 0x0000000e, 0x0000000f, 0x00000010, 0x00000011, 0x00000012,
+0x00000013, 0x00000014, 0x00000015, 0x00000016, 0x00000017, 0x00000018,
+0x00000019, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x0000001a, 0x0000001b, 0x0000001c, 0x0000001d, 0x0000001e,
+0x0000001f, 0x00000020, 0x00000021, 0x00000022, 0x00000023, 0x00000024,
+0x00000025, 0x00000026, 0x00000027, 0x00000028, 0x00000029, 0x0000002a,
+0x0000002b, 0x0000002c, 0x0000002d, 0x0000002e, 0x0000002f, 0x00000030,
+0x00000031, 0x00000032, 0x00000033, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff
+};
+
+
+#else
+
+
+/* SPECIAL DECODE TABLES FOR LITTLE ENDIAN (INTEL) CPUS */
+
+static const uint32_t d0[256] = {
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x000000f8, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x000000fc,
+0x000000d0, 0x000000d4, 0x000000d8, 0x000000dc, 0x000000e0, 0x000000e4,
+0x000000e8, 0x000000ec, 0x000000f0, 0x000000f4, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
+0x00000004, 0x00000008, 0x0000000c, 0x00000010, 0x00000014, 0x00000018,
+0x0000001c, 0x00000020, 0x00000024, 0x00000028, 0x0000002c, 0x00000030,
+0x00000034, 0x00000038, 0x0000003c, 0x00000040, 0x00000044, 0x00000048,
+0x0000004c, 0x00000050, 0x00000054, 0x00000058, 0x0000005c, 0x00000060,
+0x00000064, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x00000068, 0x0000006c, 0x00000070, 0x00000074, 0x00000078,
+0x0000007c, 0x00000080, 0x00000084, 0x00000088, 0x0000008c, 0x00000090,
+0x00000094, 0x00000098, 0x0000009c, 0x000000a0, 0x000000a4, 0x000000a8,
+0x000000ac, 0x000000b0, 0x000000b4, 0x000000b8, 0x000000bc, 0x000000c0,
+0x000000c4, 0x000000c8, 0x000000cc, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff
+};
+
+
+static const uint32_t d1[256] = {
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x0000e003, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x0000f003,
+0x00004003, 0x00005003, 0x00006003, 0x00007003, 0x00008003, 0x00009003,
+0x0000a003, 0x0000b003, 0x0000c003, 0x0000d003, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
+0x00001000, 0x00002000, 0x00003000, 0x00004000, 0x00005000, 0x00006000,
+0x00007000, 0x00008000, 0x00009000, 0x0000a000, 0x0000b000, 0x0000c000,
+0x0000d000, 0x0000e000, 0x0000f000, 0x00000001, 0x00001001, 0x00002001,
+0x00003001, 0x00004001, 0x00005001, 0x00006001, 0x00007001, 0x00008001,
+0x00009001, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x0000a001, 0x0000b001, 0x0000c001, 0x0000d001, 0x0000e001,
+0x0000f001, 0x00000002, 0x00001002, 0x00002002, 0x00003002, 0x00004002,
+0x00005002, 0x00006002, 0x00007002, 0x00008002, 0x00009002, 0x0000a002,
+0x0000b002, 0x0000c002, 0x0000d002, 0x0000e002, 0x0000f002, 0x00000003,
+0x00001003, 0x00002003, 0x00003003, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff
+};
+
+
+static const uint32_t d2[256] = {
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x00800f00, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00c00f00,
+0x00000d00, 0x00400d00, 0x00800d00, 0x00c00d00, 0x00000e00, 0x00400e00,
+0x00800e00, 0x00c00e00, 0x00000f00, 0x00400f00, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
+0x00400000, 0x00800000, 0x00c00000, 0x00000100, 0x00400100, 0x00800100,
+0x00c00100, 0x00000200, 0x00400200, 0x00800200, 0x00c00200, 0x00000300,
+0x00400300, 0x00800300, 0x00c00300, 0x00000400, 0x00400400, 0x00800400,
+0x00c00400, 0x00000500, 0x00400500, 0x00800500, 0x00c00500, 0x00000600,
+0x00400600, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x00800600, 0x00c00600, 0x00000700, 0x00400700, 0x00800700,
+0x00c00700, 0x00000800, 0x00400800, 0x00800800, 0x00c00800, 0x00000900,
+0x00400900, 0x00800900, 0x00c00900, 0x00000a00, 0x00400a00, 0x00800a00,
+0x00c00a00, 0x00000b00, 0x00400b00, 0x00800b00, 0x00c00b00, 0x00000c00,
+0x00400c00, 0x00800c00, 0x00c00c00, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff
+};
+
+
+static const uint32_t d3[256] = {
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x003e0000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x003f0000,
+0x00340000, 0x00350000, 0x00360000, 0x00370000, 0x00380000, 0x00390000,
+0x003a0000, 0x003b0000, 0x003c0000, 0x003d0000, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
+0x00010000, 0x00020000, 0x00030000, 0x00040000, 0x00050000, 0x00060000,
+0x00070000, 0x00080000, 0x00090000, 0x000a0000, 0x000b0000, 0x000c0000,
+0x000d0000, 0x000e0000, 0x000f0000, 0x00100000, 0x00110000, 0x00120000,
+0x00130000, 0x00140000, 0x00150000, 0x00160000, 0x00170000, 0x00180000,
+0x00190000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x001a0000, 0x001b0000, 0x001c0000, 0x001d0000, 0x001e0000,
+0x001f0000, 0x00200000, 0x00210000, 0x00220000, 0x00230000, 0x00240000,
+0x00250000, 0x00260000, 0x00270000, 0x00280000, 0x00290000, 0x002a0000,
+0x002b0000, 0x002c0000, 0x002d0000, 0x002e0000, 0x002f0000, 0x00300000,
+0x00310000, 0x00320000, 0x00330000, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff
+};
+
+
+#endif
diff --git a/service/uuid.cpp b/service/uuid.cpp
new file mode 100644
index 0000000..13e21a1
--- /dev/null
+++ b/service/uuid.cpp
@@ -0,0 +1,86 @@
+//
+// Copyright (C) 2015 Google, Inc.
+//
+// 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 "uuid.h"
+
+#include <algorithm>
+#include <array>
+#include <stack>
+#include <string>
+
+namespace bluetooth {
+
+void Uuid::InitializeDefault() {
+ // Initialize to base bluetooth UUID.
+ id_ = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+}
+
+Uuid::Uuid() {
+ InitializeDefault();
+}
+
+Uuid::Uuid(const std::string& uuid) {
+ InitializeDefault();
+ const int start_index = uuid.size() == 4 ? 2 : 0;
+ const size_t copy_size = std::min(id_.size(), uuid.size() / 2);
+ for (size_t i = 0; i < copy_size; ++i) {
+ std::string octet_text(uuid, i * 2, 2);
+ id_[start_index + i] = std::stoul(octet_text, 0, 16);
+ }
+}
+
+Uuid::Uuid(const bt_uuid_t& uuid) {
+ std::reverse_copy(uuid.uu, uuid.uu + sizeof(uuid.uu), id_.begin());
+}
+
+Uuid::Uuid(const Uuid::Uuid16Bit& uuid) {
+ InitializeDefault();
+ std::copy(uuid.begin(), uuid.end(), id_.begin() + kUuid16Octets);
+}
+
+Uuid::Uuid(const Uuid::Uuid32Bit& uuid) {
+ InitializeDefault();
+ std::copy(uuid.begin(), uuid.end(), id_.begin());
+}
+
+Uuid::Uuid(const Uuid::Uuid128Bit& uuid) : id_(uuid) {}
+
+const Uuid::Uuid128Bit Uuid::GetFullBigEndian() const {
+ return id_;
+}
+
+const Uuid::Uuid128Bit Uuid::GetFullLittleEndian() const {
+ Uuid::Uuid128Bit ret;
+ std::reverse_copy(id_.begin(), id_.end(), ret.begin());
+ return ret;
+}
+
+const bt_uuid_t Uuid::GetBlueDroid() const {
+ bt_uuid_t ret;
+ std::reverse_copy(id_.begin(), id_.end(), ret.uu);
+ return ret;
+}
+
+bool Uuid::operator<(const Uuid& rhs) const {
+ return std::lexicographical_compare(id_.begin(), id_.end(), rhs.id_.begin(),
+ rhs.id_.end());
+}
+
+bool Uuid::operator==(const Uuid& rhs) const {
+ return std::equal(id_.begin(), id_.end(), rhs.id_.begin());
+}
+
+} // namespace bluetooth
diff --git a/service/uuid.h b/service/uuid.h
new file mode 100644
index 0000000..0226ef6
--- /dev/null
+++ b/service/uuid.h
@@ -0,0 +1,69 @@
+//
+// Copyright (C) 2015 Google, Inc.
+//
+// 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.
+//
+#pragma once
+
+#include <array>
+#include <string>
+
+#include "hardware/bluetooth.h"
+
+namespace bluetooth {
+
+class Uuid {
+ public:
+ enum Type {
+ kUuid128Octets = 16,
+ kUuid32Octets = 4,
+ kUuid16Octets = 2,
+ };
+
+ typedef std::array<uint8_t, Uuid::kUuid16Octets> Uuid16Bit;
+ typedef std::array<uint8_t, Uuid::kUuid32Octets> Uuid32Bit;
+ typedef std::array<uint8_t, Uuid::kUuid128Octets> Uuid128Bit;
+
+ // Construct a Bluetooth 'base' UUID.
+ Uuid();
+
+ // BlueDroid constructor.
+ explicit Uuid(const bt_uuid_t& uuid);
+
+ // String constructor. Only hex ASCII accepted.
+ explicit Uuid(const std::string& uuid);
+
+ // std::array variants constructors.
+ explicit Uuid(const Uuid::Uuid16Bit& uuid);
+ explicit Uuid(const Uuid::Uuid32Bit& uuid);
+ explicit Uuid(const Uuid::Uuid128Bit& uuid);
+
+ // Provide the full network-byte-ordered blob.
+ const Uuid128Bit GetFullBigEndian() const;
+
+ // Provide blob in Little endian (BlueDroid expects this).
+ const Uuid128Bit GetFullLittleEndian() const;
+
+ // Helper for bluedroid LE type.
+ const bt_uuid_t GetBlueDroid() const;
+
+ bool operator<(const Uuid& rhs) const;
+ bool operator==(const Uuid& rhs) const;
+
+ private:
+ void InitializeDefault();
+ // Network-byte-ordered ID.
+ Uuid128Bit id_;
+};
+
+} // namespace bluetooth
diff --git a/service/uuid_test.cpp b/service/uuid_test.cpp
new file mode 100644
index 0000000..a04c336
--- /dev/null
+++ b/service/uuid_test.cpp
@@ -0,0 +1,123 @@
+//
+// Copyright (C) 2015 Google, Inc.
+//
+// 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 <algorithm>
+#include <array>
+#include <stdint.h>
+
+#include <gtest/gtest.h>
+
+#include "uuid.h"
+
+using namespace bluetooth;
+
+namespace {
+
+const std::array<uint8_t, Uuid::kUuid128Octets> kBtSigBaseUuid = {
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb, }
+};
+
+} // namespace
+
+// Verify that an uninitialized Uuid is equal
+// To the BT SIG Base UUID.
+TEST(UuidTest, DefaultUuid) {
+ Uuid uuid;
+ ASSERT_TRUE(uuid.GetFullBigEndian() == kBtSigBaseUuid);
+}
+
+// Verify that we initialize a 16-bit UUID in a
+// way consistent with how we read it.
+TEST(UuidTest, Init16Bit) {
+ auto my_uuid_16 = kBtSigBaseUuid;
+ my_uuid_16[2] = 0xde;
+ my_uuid_16[3] = 0xad;
+ Uuid uuid(Uuid::Uuid16Bit({{ 0xde, 0xad }}));
+ ASSERT_TRUE(uuid.GetFullBigEndian() == my_uuid_16);
+}
+
+// Verify that we initialize a 16-bit UUID in a
+// way consistent with how we read it.
+TEST(UuidTest, Init16BitString) {
+ auto my_uuid_16 = kBtSigBaseUuid;
+ my_uuid_16[2] = 0xde;
+ my_uuid_16[3] = 0xad;
+ Uuid uuid("dead");
+ ASSERT_TRUE(uuid.GetFullBigEndian() == my_uuid_16);
+}
+
+
+// Verify that we initialize a 32-bit UUID in a
+// way consistent with how we read it.
+TEST(UuidTest, Init32Bit) {
+ auto my_uuid_32 = kBtSigBaseUuid;
+ my_uuid_32[0] = 0xde;
+ my_uuid_32[1] = 0xad;
+ my_uuid_32[2] = 0xbe;
+ my_uuid_32[3] = 0xef;
+ Uuid uuid(Uuid::Uuid32Bit({{ 0xde, 0xad, 0xbe, 0xef }}));
+ ASSERT_TRUE(uuid.GetFullBigEndian() == my_uuid_32);
+}
+
+// Verify correct reading of a 32-bit UUID initialized from string.
+TEST(UuidTest, Init32BitString) {
+ auto my_uuid_32 = kBtSigBaseUuid;
+ my_uuid_32[0] = 0xde;
+ my_uuid_32[1] = 0xad;
+ my_uuid_32[2] = 0xbe;
+ my_uuid_32[3] = 0xef;
+ Uuid uuid("deadbeef");
+ ASSERT_TRUE(uuid.GetFullBigEndian() == my_uuid_32);
+}
+
+// Verify that we initialize a 128-bit UUID in a
+// way consistent with how we read it.
+TEST(UuidTest, Init128Bit) {
+ auto my_uuid_128 = kBtSigBaseUuid;
+ for (int i = 0; i < static_cast<int>(my_uuid_128.size()); ++i) {
+ my_uuid_128[i] = i;
+ }
+
+ Uuid uuid(my_uuid_128);
+ ASSERT_TRUE(uuid.GetFullBigEndian() == my_uuid_128);
+}
+
+// Verify that we initialize a 128-bit UUID in a
+// way consistent with how we read it as LE.
+TEST(UuidTest, Init128BitLittleEndian) {
+ auto my_uuid_128 = kBtSigBaseUuid;
+ for (int i = 0; i < static_cast<int>(my_uuid_128.size()); ++i) {
+ my_uuid_128[i] = i;
+ }
+
+ Uuid uuid(my_uuid_128);
+ std::reverse(my_uuid_128.begin(), my_uuid_128.end());
+ ASSERT_TRUE(uuid.GetFullLittleEndian() == my_uuid_128);
+}
+
+// Verify that we initialize a 128-bit UUID in a
+// way consistent with how we read it.
+TEST(UuidTest, Init128BitString) {
+ auto my_uuid_128 = kBtSigBaseUuid;
+ for (int i = 0; i < static_cast<int>(my_uuid_128.size()); ++i) {
+ my_uuid_128[i] = i;
+ }
+
+ std::string uuid_text("000102030405060708090A0B0C0D0E0F");
+ ASSERT_TRUE(uuid_text.size() == (16 * 2));
+ Uuid uuid(uuid_text);
+ ASSERT_TRUE(uuid.GetFullBigEndian() == my_uuid_128);
+}
diff --git a/stack/BUILD.gn b/stack/BUILD.gn
new file mode 100644
index 0000000..f8ea514
--- /dev/null
+++ b/stack/BUILD.gn
@@ -0,0 +1,169 @@
+#
+# Copyright (C) 2015 Google, Inc.
+#
+# 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.
+#
+
+static_library("stack") {
+ sources = [
+ "a2dp/a2d_api.c",
+ "a2dp/a2d_sbc.c",
+ "avrc/avrc_api.c",
+ "avrc/avrc_sdp.c",
+ "avrc/avrc_opt.c",
+ "avrc/avrc_bld_tg.c",
+ "avrc/avrc_bld_ct.c",
+ "avrc/avrc_pars_tg.c",
+ "avrc/avrc_pars_ct.c",
+ "avrc/avrc_utils.c",
+ "hid/hidh_api.c",
+ "hid/hidh_conn.c",
+ "bnep/bnep_main.c",
+ "bnep/bnep_utils.c",
+ "bnep/bnep_api.c",
+ "hcic/hciblecmds.c",
+ "hcic/hcicmds.c",
+ "btm/btm_ble.c",
+ "btm/btm_sec.c",
+ "btm/btm_inq.c",
+ "btm/btm_ble_addr.c",
+ "btm/btm_ble_bgconn.c",
+ "btm/btm_main.c",
+ "btm/btm_dev.c",
+ "btm/btm_ble_gap.c",
+ "btm/btm_ble_adv_filter.c",
+ "btm/btm_ble_multi_adv.c",
+ "btm/btm_ble_batchscan.c",
+ "btm/btm_ble_cont_energy.c",
+ "btm/btm_ble_privacy.c",
+ "btm/btm_acl.c",
+ "btm/btm_sco.c",
+ "btm/btm_pm.c",
+ "btm/btm_devctl.c",
+ "rfcomm/rfc_utils.c",
+ "rfcomm/port_rfc.c",
+ "rfcomm/rfc_l2cap_if.c",
+ "rfcomm/rfc_mx_fsm.c",
+ "rfcomm/port_utils.c",
+ "rfcomm/rfc_port_fsm.c",
+ "rfcomm/rfc_port_if.c",
+ "rfcomm/port_api.c",
+ "rfcomm/rfc_ts_frames.c",
+ "mcap/mca_dact.c",
+ "mcap/mca_dsm.c",
+ "mcap/mca_l2c.c",
+ "mcap/mca_main.c",
+ "mcap/mca_csm.c",
+ "mcap/mca_cact.c",
+ "mcap/mca_api.c",
+ "gatt/gatt_sr.c",
+ "gatt/gatt_cl.c",
+ "gatt/gatt_api.c",
+ "gatt/gatt_auth.c",
+ "gatt/gatt_utils.c",
+ "gatt/gatt_main.c",
+ "gatt/att_protocol.c",
+ "gatt/gatt_attr.c",
+ "gatt/gatt_db.c",
+ "avct/avct_api.c",
+ "avct/avct_l2c.c",
+ "avct/avct_lcb.c",
+ "avct/avct_ccb.c",
+ "avct/avct_lcb_act.c",
+ "smp/smp_main.c",
+ "smp/smp_l2c.c",
+ "smp/smp_cmac.c",
+ "smp/smp_utils.c",
+ "smp/smp_act.c",
+ "smp/smp_keys.c",
+ "smp/smp_api.c",
+ "smp/aes.c",
+ "smp/smp_br_main.c",
+ "smp/p_256_curvepara.c",
+ "smp/p_256_ecc_pp.c",
+ "smp/p_256_multprecision.c",
+ "avdt/avdt_ccb.c",
+ "avdt/avdt_scb_act.c",
+ "avdt/avdt_msg.c",
+ "avdt/avdt_ccb_act.c",
+ "avdt/avdt_api.c",
+ "avdt/avdt_scb.c",
+ "avdt/avdt_ad.c",
+ "avdt/avdt_l2c.c",
+ "sdp/sdp_server.c",
+ "sdp/sdp_main.c",
+ "sdp/sdp_db.c",
+ "sdp/sdp_utils.c",
+ "sdp/sdp_api.c",
+ "sdp/sdp_discovery.c",
+ "pan/pan_main.c",
+ "srvc/srvc_battery.c",
+ "srvc/srvc_battery_int.h",
+ "srvc/srvc_dis.c",
+ "srvc/srvc_dis_int.h",
+ "srvc/srvc_eng.c",
+ "srvc/srvc_eng_int.h",
+ "pan/pan_api.c",
+ "pan/pan_utils.c",
+ "btu/btu_hcif.c",
+ "btu/btu_init.c",
+ "btu/btu_task.c",
+ "l2cap/l2c_fcr.c",
+ "l2cap/l2c_ucd.c",
+ "l2cap/l2c_main.c",
+ "l2cap/l2c_api.c",
+ "l2cap/l2c_utils.c",
+ "l2cap/l2c_csm.c",
+ "l2cap/l2c_link.c",
+ "l2cap/l2c_ble.c",
+ "l2cap/l2cap_client.c",
+ "gap/gap_api.c",
+ "gap/gap_ble.c",
+ "gap/gap_conn.c",
+ "gap/gap_utils.c",
+ ]
+
+ include_dirs = [
+ "include",
+ "avct",
+ "btm",
+ "avrc",
+ "l2cap",
+ "avdt",
+ "gatt",
+ "gap",
+ "pan",
+ "bnep",
+ "hid",
+ "sdp",
+ "smp",
+ "srvc",
+ "//btcore/include",
+ "//vnd/include",
+ "//vnd/ble",
+ "//btif/include",
+ "//hci/include",
+ "//include",
+ "//gki/common",
+ "//gki/ulinux",
+ "//osi/include",
+ "//udrv/include",
+ "//rpc/include",
+ "//hcis",
+ "//ctrlr/include",
+ "//bta/include",
+ "//bta/sys",
+ "//utils/include",
+ "//",
+ ]
+}
diff --git a/stack/a2dp/a2d_sbc.c b/stack/a2dp/a2d_sbc.c
index 4b786b4..fd7c816 100644
--- a/stack/a2dp/a2d_sbc.c
+++ b/stack/a2dp/a2d_sbc.c
@@ -284,8 +284,9 @@
status = A2D_INVALID_PARAMS;
else
{
- losc = *p_info++;
- *p_info++;
+ losc = *p_info;
+ *p_info += 2;
+
/* If the function is called for the wrong Media Type or Media Codec Type */
if(losc != A2D_SBC_INFO_LEN || *p_info != A2D_MEDIA_CT_SBC)
status = A2D_WRONG_CODEC;
diff --git a/stack/avdt/avdt_ccb.c b/stack/avdt/avdt_ccb.c
index 09ed39a..0cad57c 100644
--- a/stack/avdt/avdt_ccb.c
+++ b/stack/avdt/avdt_ccb.c
@@ -386,7 +386,7 @@
memcpy(p_ccb->peer_addr, bd_addr, BD_ADDR_LEN);
GKI_init_q(&p_ccb->cmd_q);
GKI_init_q(&p_ccb->rsp_q);
- p_ccb->timer_entry.param = (UINT32) p_ccb;
+ p_ccb->timer_entry.param = p_ccb;
AVDT_TRACE_DEBUG("avdt_ccb_alloc %d", i);
break;
}
diff --git a/stack/avdt/avdt_scb.c b/stack/avdt/avdt_scb.c
index 696fcca..2a2ab4a 100644
--- a/stack/avdt/avdt_scb.c
+++ b/stack/avdt/avdt_scb.c
@@ -620,7 +620,7 @@
#endif
}
#endif
- p_scb->timer_entry.param = (UINT32) p_scb;
+ p_scb->timer_entry.param = p_scb;
AVDT_TRACE_DEBUG("avdt_scb_alloc hdl=%d, psc_mask:0x%x", i+1, p_cs->cfg.psc_mask);
break;
}
diff --git a/stack/bnep/bnep_utils.c b/stack/bnep/bnep_utils.c
index 1db329d..0cf3b3f 100644
--- a/stack/bnep/bnep_utils.c
+++ b/stack/bnep/bnep_utils.c
@@ -120,7 +120,7 @@
{
memset ((UINT8 *)p_bcb, 0, sizeof (tBNEP_CONN));
- p_bcb->conn_tle.param = (UINT32) p_bcb;
+ p_bcb->conn_tle.param = p_bcb;
memcpy ((UINT8 *)(p_bcb->rem_bda), (UINT8 *)p_rem_bda, BD_ADDR_LEN);
p_bcb->handle = xx + 1;
diff --git a/stack/btm/btm_acl.c b/stack/btm/btm_acl.c
index 9337697..59a311f 100644
--- a/stack/btm/btm_acl.c
+++ b/stack/btm/btm_acl.c
@@ -795,7 +795,7 @@
btsnd_hcic_disconnect(p_dev_rec->hci_handle, HCI_ERR_PEER_USER);
}
BTM_TRACE_ERROR("btm_acl_encrypt_change: tBTM_SEC_DEV:0x%x rs_disc_pending=%d",
- (UINT32)p_dev_rec, p_dev_rec->rs_disc_pending);
+ PTR_TO_UINT(p_dev_rec), p_dev_rec->rs_disc_pending);
p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */
}
#endif
@@ -1528,7 +1528,7 @@
btsnd_hcic_disconnect(p_dev_rec->hci_handle, HCI_ERR_PEER_USER);
}
BTM_TRACE_ERROR("tBTM_SEC_DEV:0x%x rs_disc_pending=%d",
- (UINT32)p_dev_rec, p_dev_rec->rs_disc_pending);
+ PTR_TO_UINT(p_dev_rec), p_dev_rec->rs_disc_pending);
p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */
}
diff --git a/stack/btm/btm_ble.c b/stack/btm/btm_ble.c
index 5954898..0101b97 100644
--- a/stack/btm/btm_ble.c
+++ b/stack/btm/btm_ble.c
@@ -683,7 +683,6 @@
BOOLEAN BTM_ReadConnectedTransportAddress(BD_ADDR remote_bda, tBT_TRANSPORT transport)
{
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev(remote_bda);
- tACL_CONN *p = btm_bda_to_acl(remote_bda, transport);
/* if no device can be located, return */
if (p_dev_rec == NULL)
@@ -1467,61 +1466,6 @@
}
/*******************************************************************************
-** Function btm_enc_proc_ltk
-** Description send LTK reply when it's ready.
-*******************************************************************************/
-static void btm_enc_proc_ltk(tSMP_ENC *p)
-{
- UINT8 i;
- BTM_TRACE_DEBUG ("btm_enc_proc_ltk");
- if (p && p->param_len == BT_OCTET16_LEN)
- {
- for (i = 0; i < (BT_OCTET16_LEN - btm_cb.key_size); i ++)
- p->param_buf[BT_OCTET16_LEN - i - 1] = 0;
- btsnd_hcic_ble_ltk_req_reply(btm_cb.enc_handle, p->param_buf);
- }
-}
-
-/*******************************************************************************
-** Function btm_enc_proc_slave_y
-** Description calculate LTK when Y is ready
-*******************************************************************************/
-static void btm_enc_proc_slave_y(tSMP_ENC *p)
-{
- UINT16 div, y;
- UINT8 *pp = p->param_buf;
- tBTM_CB *p_cb = &btm_cb;
- tSMP_ENC output;
- tBTM_SEC_DEV_REC *p_dev_rec;
-
- BTM_TRACE_DEBUG ("btm_enc_proc_slave_y");
- if (p != NULL)
- {
- STREAM_TO_UINT16(y, pp);
-
- div = p_cb->ediv ^ y;
- p_dev_rec = btm_find_dev_by_handle (p_cb->enc_handle);
-
- if ( p_dev_rec &&
- p_dev_rec->ble.keys.div == div )
- {
- BTM_TRACE_DEBUG ("LTK request OK");
- /* calculating LTK , LTK = E er(div) */
- SMP_Encrypt(p_cb->devcb.ble_encryption_key_value, BT_OCTET16_LEN, (UINT8 *)&div, 2, &output);
- btm_enc_proc_ltk(&output);
- }
- else
- {
- BTM_TRACE_DEBUG ("LTK request failed - send negative reply");
- btsnd_hcic_ble_ltk_req_neg_reply(p_cb->enc_handle);
- if (p_dev_rec)
- btm_ble_link_encrypted(p_dev_rec->bd_addr, 0);
-
- }
- }
-}
-
-/*******************************************************************************
**
** Function btm_ble_ltk_request_reply
**
@@ -1535,7 +1479,6 @@
{
tBTM_SEC_DEV_REC *p_rec = btm_find_dev (bda);
tBTM_CB *p_cb = &btm_cb;
- tSMP_ENC output;
if (p_rec == NULL)
{
diff --git a/stack/btm/btm_ble_bgconn.c b/stack/btm/btm_ble_bgconn.c
index 116b8fc..f66ef9f 100644
--- a/stack/btm/btm_ble_bgconn.c
+++ b/stack/btm/btm_ble_bgconn.c
@@ -521,6 +521,7 @@
#endif
if (!btsnd_hcic_ble_set_scan_enable(TRUE, TRUE)) /* duplicate filtering enabled */
return FALSE;
+
/* mark up inquiry status flag */
p_cb->scan_activity |= BTM_LE_SELECT_CONN_ACTIVE;
p_cb->wl_state |= BTM_BLE_WL_SCAN;
diff --git a/stack/btm/btm_ble_gap.c b/stack/btm/btm_ble_gap.c
index 43d0f36..153b598 100644
--- a/stack/btm/btm_ble_gap.c
+++ b/stack/btm/btm_ble_gap.c
@@ -486,6 +486,7 @@
return status;
}
+#if BLE_VND_INCLUDED == TRUE
/*******************************************************************************
**
** Function btm_vsc_brcm_features_complete
@@ -497,7 +498,6 @@
*******************************************************************************/
static void btm_ble_vendor_capability_vsc_cmpl_cback (tBTM_VSC_CMPL *p_vcs_cplt_params)
{
-#if BLE_VND_INCLUDED == TRUE
UINT8 status = 0xFF;
UINT8 *p;
@@ -555,15 +555,15 @@
if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz > 0 &&
controller_get_interface()->get_ble_resolving_list_max_size() == 0)
btm_ble_resolving_list_init(btm_cb.cmn_ble_vsc_cb.max_irk_list_sz);
-#endif
+#endif /* (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE) */
if (btm_cb.cmn_ble_vsc_cb.tot_scan_results_strg > 0)
btm_ble_batchscan_init();
if (p_ctrl_le_feature_rd_cmpl_cback != NULL)
p_ctrl_le_feature_rd_cmpl_cback(status);
-#endif
}
+#endif /* BLE_VND_INCLUDED == TRUE */
/*******************************************************************************
**
diff --git a/stack/btm/btm_dev.c b/stack/btm/btm_dev.c
index c8265e4..9f57522 100644
--- a/stack/btm/btm_dev.c
+++ b/stack/btm/btm_dev.c
@@ -479,7 +479,6 @@
#if BLE_INCLUDED == TRUE
tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
tBTM_SEC_DEV_REC temp_rec = *p_target_rec;
- BD_ADDR dummy_bda = {0};
BTM_TRACE_DEBUG("%s", __func__);
diff --git a/stack/btm/btm_devctl.c b/stack/btm/btm_devctl.c
index 3a70788..896bef5 100644
--- a/stack/btm/btm_devctl.c
+++ b/stack/btm/btm_devctl.c
@@ -262,9 +262,6 @@
*******************************************************************************/
static void btm_decode_ext_features_page (UINT8 page_number, const UINT8 *p_features)
{
- UINT8 last;
- UINT8 first;
-
BTM_TRACE_DEBUG ("btm_decode_ext_features_page page: %d", page_number);
switch (page_number)
{
diff --git a/stack/btm/btm_sec.c b/stack/btm/btm_sec.c
index e735299..b8d0eaf 100644
--- a/stack/btm/btm_sec.c
+++ b/stack/btm/btm_sec.c
@@ -103,10 +103,8 @@
static BOOLEAN btm_sec_queue_encrypt_request (BD_ADDR bd_addr, tBT_TRANSPORT transport,
tBTM_SEC_CALLBACK *p_callback, void *p_ref_data);
-static void btm_sec_clean_pending_req_queue (BD_ADDR remote_bda, tBT_TRANSPORT transport) ;
static void btm_sec_check_pending_enc_req (tBTM_SEC_DEV_REC *p_dev_rec, tBT_TRANSPORT transport,
UINT8 encr_enable);
-static BOOLEAN btm_sec_acceptor_rejects_bonding (tBTM_SEC_DEV_REC *p_dev_rec);
static BOOLEAN btm_sec_use_smp_br_chnl(tBTM_SEC_DEV_REC *p_dev_rec);
static BOOLEAN btm_sec_is_master(tBTM_SEC_DEV_REC *p_dev_rec);
@@ -3996,7 +3994,7 @@
p_dev_rec->sec_state = 0;
btm_cb.p_collided_dev_rec = p_dev_rec;
- btm_cb.sec_collision_tle.param = (UINT32) btm_sec_collision_timeout;
+ btm_cb.sec_collision_tle.param = UINT_TO_PTR(btm_sec_collision_timeout);
btu_start_timer (&btm_cb.sec_collision_tle, BTU_TTYPE_USER_FUNC, BT_1SEC_TIMEOUT);
}
}
@@ -4491,7 +4489,7 @@
/* Start timer with 0 to initiate connection with new LCB */
/* because L2CAP will delete current LCB with this event */
btm_cb.p_collided_dev_rec = p_dev_rec;
- btm_cb.sec_collision_tle.param = (UINT32) btm_sec_connect_after_reject_timeout;
+ btm_cb.sec_collision_tle.param = UINT_TO_PTR(btm_sec_connect_after_reject_timeout);
btu_start_timer (&btm_cb.sec_collision_tle, BTU_TTYPE_USER_FUNC, 0);
}
else
@@ -4549,7 +4547,7 @@
/* Start timer with 0 to initiate connection with new LCB */
/* because L2CAP will delete current LCB with this event */
btm_cb.p_collided_dev_rec = p_dev_rec;
- btm_cb.sec_collision_tle.param = (UINT32) btm_sec_connect_after_reject_timeout;
+ btm_cb.sec_collision_tle.param = UINT_TO_PTR(btm_sec_connect_after_reject_timeout);
btu_start_timer (&btm_cb.sec_collision_tle, BTU_TTYPE_USER_FUNC, 0);
}
@@ -6218,38 +6216,6 @@
/*******************************************************************************
**
-** Function btm_sec_clean_pending_req_queue
-**
-** Description This function cleans up the pending security request when the
-** link to the target device dropped.
-**
-** Returns void
-**
-*******************************************************************************/
-static void btm_sec_clean_pending_req_queue (BD_ADDR remote_bda, tBT_TRANSPORT transport)
-{
- tBTM_SEC_QUEUE_ENTRY *p_e;
- BUFFER_Q *bq = &btm_cb.sec_pending_q;
-
- p_e = (tBTM_SEC_QUEUE_ENTRY *)GKI_getfirst(bq);
-
- if (p_e != NULL)
- {
- if (memcmp(p_e->bd_addr, remote_bda, BD_ADDR_LEN) == 0
-#if BLE_INCLUDED == TRUE
- && p_e->transport == transport
-#endif
- )
- {
- (*p_e->p_callback) (remote_bda, transport, p_e->p_ref_data, BTM_ERR_PROCESSING);
- GKI_remove_from_queue(bq, (void *)p_e);
- }
- p_e = (tBTM_SEC_QUEUE_ENTRY *) GKI_getnext ((void *)p_e);
- }
-}
-
-/*******************************************************************************
-**
** Function btm_sec_is_serv_level0
**
** Description This function is called to check if the service corresponding
diff --git a/stack/btu/btu_task.c b/stack/btu/btu_task.c
index e2b899e..41170f0 100644
--- a/stack/btu/btu_task.c
+++ b/stack/btu/btu_task.c
@@ -19,6 +19,7 @@
#define LOG_TAG "bt_btu_task"
#include <assert.h>
+#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
diff --git a/stack/gap/gap_conn.c b/stack/gap/gap_conn.c
index 67b8922..6c6c5e7 100644
--- a/stack/gap/gap_conn.c
+++ b/stack/gap/gap_conn.c
@@ -127,7 +127,6 @@
{
tGAP_CCB *p_ccb;
UINT16 cid;
- tBT_UUID bt_uuid = {2, {GAP_PROTOCOL_ID}};
GAP_TRACE_EVENT ("GAP_CONN - Open Request");
@@ -235,7 +234,7 @@
p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE;
/* Check if L2CAP started the connection process */
- if (p_rem_bda && ((cid = L2CA_CONNECT_REQ (p_ccb->psm, p_rem_bda, &p_ccb->ertm_info, &bt_uuid)) != 0))
+ if (p_rem_bda && ((cid = L2CA_CONNECT_REQ (p_ccb->psm, p_rem_bda, &p_ccb->ertm_info)) != 0))
{
p_ccb->connection_id = cid;
return (p_ccb->gap_handle);
@@ -739,7 +738,6 @@
{
UINT16 xx;
tGAP_CCB *p_ccb;
- tBT_UUID bt_uuid = {2, {GAP_PROTOCOL_ID}};
/* See if we have a CCB listening for the connection */
for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++)
@@ -770,7 +768,7 @@
p_ccb->connection_id = l2cap_cid;
/* Send response to the L2CAP layer. */
- L2CA_CONNECT_RSP (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK, &p_ccb->ertm_info, &bt_uuid);
+ L2CA_CONNECT_RSP (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK, &p_ccb->ertm_info);
GAP_TRACE_EVENT("GAP_CONN - Rcvd L2CAP conn ind, CID: 0x%x", p_ccb->connection_id);
diff --git a/stack/gatt/gatt_attr.c b/stack/gatt/gatt_attr.c
index a175129..659a864 100644
--- a/stack/gatt/gatt_attr.c
+++ b/stack/gatt/gatt_attr.c
@@ -485,7 +485,6 @@
*******************************************************************************/
void GATT_ConfigServiceChangeCCC (BD_ADDR remote_bda, BOOLEAN enable, tBT_TRANSPORT transport)
{
- UINT16 conn_id = GATT_INVALID_CONN_ID;
tGATT_PROFILE_CLCB *p_clcb = gatt_profile_find_clcb_by_bd_addr (remote_bda, transport);
if (p_clcb == NULL)
diff --git a/stack/hid/hidh_conn.c b/stack/hid/hidh_conn.c
index 0cc6976..7b3db4a 100644
--- a/stack/hid/hidh_conn.c
+++ b/stack/hid/hidh_conn.c
@@ -43,6 +43,8 @@
#include "hidh_int.h"
#include "bt_utils.h"
+#include "osi/include/osi.h"
+
static UINT8 find_conn_by_cid (UINT16 cid);
static void hidh_conn_retry (UINT8 dhandle);
@@ -301,10 +303,16 @@
*******************************************************************************/
void hidh_proc_repage_timeout (TIMER_LIST_ENT *p_tle)
{
- hidh_conn_initiate( (UINT8) p_tle->param ) ;
- hh_cb.devices[p_tle->param].conn_tries++;
- hh_cb.callback( (UINT8) p_tle->param, hh_cb.devices[p_tle->param].addr,
- HID_HDEV_EVT_RETRYING, hh_cb.devices[p_tle->param].conn_tries, NULL ) ;
+ tHID_HOST_DEV_CTB *device;
+ UINT8 dhandle = PTR_TO_UINT(p_tle->param);
+
+ hidh_conn_initiate(dhandle);
+
+ device = &hh_cb.devices[dhandle];
+ device->conn_tries++;
+
+ hh_cb.callback(dhandle, device->addr, HID_HDEV_EVT_RETRYING,
+ device->conn_tries, NULL ) ;
}
/*******************************************************************************
@@ -321,11 +329,12 @@
{
tHID_HOST_DEV_CTB *p_dev = (tHID_HOST_DEV_CTB *) p_ref_data;
UINT8 dhandle;
- UINT32 reason;
UNUSED(bd_addr);
UNUSED (transport);
- dhandle = ((UINT32)p_dev - (UINT32)&(hh_cb.devices[0]))/ sizeof(tHID_HOST_DEV_CTB);
+ // TODO(armansito): This kind of math to determine a device handle is way
+ // too dirty and unnecessary. Why can't |p_dev| store it's handle?
+ dhandle = (PTR_TO_UINT(p_dev) - PTR_TO_UINT(&(hh_cb.devices[0])))/ sizeof(tHID_HOST_DEV_CTB);
if( res == BTM_SUCCESS && p_dev->conn.conn_state == HID_CONN_STATE_SECURITY )
{
HIDH_TRACE_EVENT ("HID-Host Originator security pass.");
@@ -653,7 +662,7 @@
(hh_cb.devices[dhandle].attr_mask & HID_NORMALLY_CONNECTABLE))
{
hh_cb.devices[dhandle].conn_tries = 0;
- hh_cb.devices[dhandle].conn.timer_entry.param = (UINT32) dhandle;
+ hh_cb.devices[dhandle].conn.timer_entry.param = UINT_TO_PTR(dhandle);
btu_start_timer (&(hh_cb.devices[dhandle].conn.timer_entry), BTU_TTYPE_HID_HOST_REPAGE_TO, HID_HOST_REPAGE_WIN);
hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, disc_res, NULL);
}
@@ -1086,7 +1095,7 @@
tHID_HOST_DEV_CTB *p_dev = &hh_cb.devices[dhandle];
p_dev->conn.conn_state = HID_CONN_STATE_UNUSED;
- p_dev->conn.timer_entry.param = (UINT32) dhandle;
+ p_dev->conn.timer_entry.param = UINT_TO_PTR(dhandle);
#if (HID_HOST_REPAGE_WIN > 0)
btu_start_timer (&(p_dev->conn.timer_entry), BTU_TTYPE_HID_HOST_REPAGE_TO, HID_HOST_REPAGE_WIN);
#else
diff --git a/stack/include/l2c_api.h b/stack/include/l2c_api.h
index 837dbc8..b431d56 100644
--- a/stack/include/l2c_api.h
+++ b/stack/include/l2c_api.h
@@ -319,8 +319,8 @@
#define L2CA_REGISTER(a,b,c) L2CA_Register(a,(tL2CAP_APPL_INFO *)b)
#define L2CA_DEREGISTER(a) L2CA_Deregister(a)
-#define L2CA_CONNECT_REQ(a,b,c,d) L2CA_ErtmConnectReq(a,b,c)
-#define L2CA_CONNECT_RSP(a,b,c,d,e,f,g) L2CA_ErtmConnectRsp(a,b,c,d,e,f)
+#define L2CA_CONNECT_REQ(a,b,c) L2CA_ErtmConnectReq(a,b,c)
+#define L2CA_CONNECT_RSP(a,b,c,d,e,f) L2CA_ErtmConnectRsp(a,b,c,d,e,f)
#define L2CA_CONFIG_REQ(a,b) L2CA_ConfigReq(a,b)
#define L2CA_CONFIG_RSP(a,b) L2CA_ConfigRsp(a,b)
#define L2CA_DISCONNECT_REQ(a) L2CA_DisconnectReq(a)
diff --git a/stack/l2cap/l2c_ble.c b/stack/l2cap/l2c_ble.c
index 2460bd4..f7d65f0 100644
--- a/stack/l2cap/l2c_ble.c
+++ b/stack/l2cap/l2c_ble.c
@@ -263,7 +263,6 @@
void l2cble_scanner_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
{
- int i;
tL2C_LCB *p_lcb;
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (bda);
@@ -372,7 +371,6 @@
void l2cble_advertiser_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
{
- int i;
tL2C_LCB *p_lcb;
tBTM_SEC_DEV_REC *p_dev_rec;
UNUSED(type);
@@ -480,9 +478,13 @@
static void l2cble_start_conn_update (tL2C_LCB *p_lcb)
{
UINT16 min_conn_int, max_conn_int, slave_latency, supervision_tout;
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev(p_lcb->remote_bd_addr);
tACL_CONN *p_acl_cb = btm_bda_to_acl(p_lcb->remote_bd_addr, BT_TRANSPORT_LE);
+ // TODO(armansito): The return value of this call wasn't being used but the
+ // logic of this function might be depending on its side effects. We should
+ // verify if this call is needed at all and remove it otherwise.
+ btm_find_or_alloc_dev(p_lcb->remote_bd_addr);
+
if (p_lcb->conn_update_mask & L2C_BLE_UPDATE_PENDING) return;
if (p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE)
diff --git a/stack/rfcomm/rfc_utils.c b/stack/rfcomm/rfc_utils.c
index e2cff28..0014c9b 100644
--- a/stack/rfcomm/rfc_utils.c
+++ b/stack/rfcomm/rfc_utils.c
@@ -224,7 +224,7 @@
RFCOMM_TRACE_EVENT ("rfc_timer_start - timeout:%d", timeout);
- p_tle->param = (UINT32)p_mcb;
+ p_tle->param = p_mcb;
btu_start_timer (p_tle, BTU_TTYPE_RFCOMM_MFC, timeout);
}
@@ -258,7 +258,7 @@
RFCOMM_TRACE_EVENT ("rfc_port_timer_start - timeout:%d", timeout);
- p_tle->param = (UINT32)p_port;
+ p_tle->param = p_port;
btu_start_timer (p_tle, BTU_TTYPE_RFCOMM_PORT, timeout);
}
diff --git a/stack/sdp/sdp_api.c b/stack/sdp/sdp_api.c
index 6e84ded..5a69816 100644
--- a/stack/sdp/sdp_api.c
+++ b/stack/sdp/sdp_api.c
@@ -37,6 +37,8 @@
#include "sdpint.h"
#include "btu.h"
+#include "osi/include/osi.h"
+
/**********************************************************************
** C L I E N T F U N C T I O N P R O T O T Y P E S *
***********************************************************************/
@@ -73,7 +75,7 @@
num_attr > SDP_MAX_ATTR_FILTERS || num_uuid > SDP_MAX_UUID_FILTERS)
{
SDP_TRACE_ERROR("SDP_InitDiscoveryDb Illegal param: p_db 0x%x, len %d, num_uuid %d, num_attr %d",
- (UINT32)p_db, len, num_uuid, num_attr);
+ PTR_TO_UINT(p_db), len, num_uuid, num_attr);
return(FALSE);
}
diff --git a/stack/sdp/sdp_utils.c b/stack/sdp/sdp_utils.c
index 238896f..f18eb88 100644
--- a/stack/sdp/sdp_utils.c
+++ b/stack/sdp/sdp_utils.c
@@ -122,7 +122,7 @@
{
memset (p_ccb, 0, sizeof (tCONN_CB));
- p_ccb->timer_entry.param = (UINT32) p_ccb;
+ p_ccb->timer_entry.param = p_ccb;
return (p_ccb);
}
diff --git a/udrv/BUILD.gn b/udrv/BUILD.gn
new file mode 100644
index 0000000..6b94bfe
--- /dev/null
+++ b/udrv/BUILD.gn
@@ -0,0 +1,31 @@
+#
+# Copyright (C) 2015 Google, Inc.
+#
+# 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.
+#
+
+source_set("udrv") {
+ sources = [
+ "ulinux/uipc.c"
+ ]
+
+ include_dirs = [
+ "include",
+ "uipc",
+ "//audio_a2dp_hw",
+ "//include",
+ "//gki/common",
+ "//stack/include",
+ "//utils/include",
+ ]
+}
diff --git a/utils/BUILD.gn b/utils/BUILD.gn
new file mode 100644
index 0000000..2b7dc59
--- /dev/null
+++ b/utils/BUILD.gn
@@ -0,0 +1,27 @@
+#
+# Copyright (C) 2015 Google, Inc.
+#
+# 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.
+#
+
+static_library("utils") {
+ sources = [
+ "src/bt_utils.c"
+ ]
+
+ include_dirs = [
+ "include",
+ "//",
+ "//stack/include",
+ ]
+}
diff --git a/utils/src/bt_utils.c b/utils/src/bt_utils.c
index 53a53de..2420716 100644
--- a/utils/src/bt_utils.c
+++ b/utils/src/bt_utils.c
@@ -27,7 +27,13 @@
#define LOG_TAG "bt_utils"
+// TODO(armansito): cutils/properties.h is only being used to pull-in runtime
+// settings on Android. Remove this conditional include once we have a generic
+// way to obtain system properties.
+#if !defined(OS_GENERIC)
#include <cutils/properties.h>
+#endif // !defined(OS_GENERIC)
+
#include <cutils/sched_policy.h>
#include <errno.h>
#include <pthread.h>
@@ -73,7 +79,7 @@
return NULL;
}
-const module_t bt_utils_module = {
+EXPORT_SYMBOL const module_t bt_utils_module = {
.name = BT_UTILS_MODULE,
.init = init,
.start_up = NULL,
@@ -84,7 +90,10 @@
}
};
-
+// TODO(armansito): Remove this conditional code once there is a generic way
+// to obtain system properties. System properties are only available on
+// Android. Don't do the following check if this is a generic build.
+#if !defined(OS_GENERIC)
/*****************************************************************************
**
** Function check_do_scheduling_group
@@ -104,6 +113,7 @@
}
}
}
+#endif // !defined(OS_GENERIC)
/*****************************************************************************
**
@@ -122,11 +132,18 @@
pthread_mutex_lock(&gIdxLock);
g_TaskIdx = high_task;
+ // TODO(armansito): Remove this conditional check once we find a solution
+ // for system/core on non-Android platforms.
+#if defined(OS_GENERIC)
+ rc = -1;
+#else // !defined(OS_GENERIC)
pthread_once(&g_DoSchedulingGroupOnce[g_TaskIdx], check_do_scheduling_group);
if (g_DoSchedulingGroup[g_TaskIdx]) {
// set_sched_policy does not support tid == 0
rc = set_sched_policy(tid, SP_AUDIO_SYS);
}
+#endif // defined(OS_GENERIC)
+
g_TaskIDs[high_task] = tid;
pthread_mutex_unlock(&gIdxLock);