Version 1.9.0
- Add support for qualcomm HIDL interface in upcoming
android O release.
diff --git a/Android.mk b/Android.mk
index 94c3bb2..113b6ff 100644
--- a/Android.mk
+++ b/Android.mk
@@ -52,6 +52,10 @@
ANT_DIR := src/bt-vendor_vfs
+else ifeq ($(BOARD_ANT_WIRELESS_DEVICE),"qualcomm-hidl")
+
+ANT_DIR := src/qcomm-hidl
+
else ifeq ($(BOARD_ANT_WIRELESS_DEVICE),"vfs-prerelease")
ANT_DIR := src/vfs
diff --git a/src/common/inc/ant_version.h b/src/common/inc/ant_version.h
index 834603c..e7c3a97 100644
--- a/src/common/inc/ant_version.h
+++ b/src/common/inc/ant_version.h
@@ -20,7 +20,7 @@
#define __ANT_VERSION_H
#define LIBANT_STACK_MAJOR "1"
-#define LIBANT_STACK_MINOR "8"
+#define LIBANT_STACK_MINOR "9"
#define LIBANT_STACK_INCRE "0"
#endif // __ANT_VERSION_H
diff --git a/src/qcomm-hidl/Android.mk b/src/qcomm-hidl/Android.mk
new file mode 100644
index 0000000..55f8d3d
--- /dev/null
+++ b/src/qcomm-hidl/Android.mk
@@ -0,0 +1,72 @@
+#
+# Copyright (C) 2011 Dynastream Innovations
+#
+# 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 $(CLEAR_VARS)
+
+LOCAL_CFLAGS := -g -c -W -Wall -O2
+
+# needed to pull in the header file for libbt-vendor.so
+BDROID_DIR:= system/bt
+HWBINDER_DIR := system/hwbinder
+QCOM_DIR:= hardware/qcom/bt/libbt-vendor
+
+# Added hci/include to give access to the header for the libbt-vendorso interface.
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/src/common/inc \
+ $(LOCAL_PATH)/$(ANT_DIR)/inc \
+ $(BDROID_DIR)/hci/include \
+ $(QCOM_DIR)/include \
+ $(HWBINDER_DIR)/include
+
+
+ifeq ($(BOARD_ANT_WIRELESS_DEVICE),"qualcomm-hidl")
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/$(ANT_DIR)/qualcomm/hidl
+
+endif # BOARD_ANT_WIRELESS_DEVICE = "qualcomm-hidl"
+
+LOCAL_SRC_FILES := \
+ $(COMMON_DIR)/ant_utils.c \
+ $(ANT_DIR)/ant_native_chardev.c \
+ $(ANT_DIR)/ant_rx_chardev.c \
+ $(ANT_DIR)/AntHidlClient.cpp
+
+LOCAL_SRC_FILES += $(COMMON_DIR)/JAntNative.cpp
+
+
+# JNI
+LOCAL_C_INCLUDE += $(JNI_H_INCLUDE)
+
+LOCAL_SHARED_LIBRARIES += \
+ libnativehelper \
+ libbase \
+ libhidlbase \
+ libhidltransport \
+ libhwbinder \
+ libutils \
+ com.qualcomm.qti.ant@1.0 \
+ android.hardware.bluetooth@1.0 \
+
+# logging and dll loading
+LOCAL_SHARED_LIBRARIES += \
+ libcutils \
+ libdl \
+ liblog
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libantradio
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/src/qcomm-hidl/AntHidlClient.cpp b/src/qcomm-hidl/AntHidlClient.cpp
new file mode 100644
index 0000000..37aa540
--- /dev/null
+++ b/src/qcomm-hidl/AntHidlClient.cpp
@@ -0,0 +1,266 @@
+/*
+ *Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ *WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ *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.
+ */
+
+
+#include <iostream> // std::cin, std::cout
+#include <queue> // std::queue
+#include <mutex> // std::mutex, std::unique_lock
+#include <condition_variable> // std::condition_variable
+#include <cstdlib>
+#include <thread>
+
+#include <hwbinder/ProcessState.h>
+
+#include <com/qualcomm/qti/ant/1.0/IAntHci.h>
+#include <com/qualcomm/qti/ant/1.0/IAntHciCallbacks.h>
+#include <com/qualcomm/qti/ant/1.0/types.h>
+
+#include <utils/Log.h>
+
+
+#include <hidl/Status.h>
+#include <hwbinder/ProcessState.h>
+#include "ant_types.h"
+#include "AntHidlClient.h"
+
+using com::qualcomm::qti::ant::V1_0::IAntHci;
+using com::qualcomm::qti::ant::V1_0::IAntHciCallbacks;
+using com::qualcomm::qti::ant::V1_0::AntPacket;
+using com::qualcomm::qti::ant::V1_0::Status;
+
+using ::android::hardware::hidl_vec;
+
+
+using android::hardware::ProcessState;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+android::sp<IAntHci> anthci;
+typedef std::unique_lock<std::mutex> Lock;
+
+
+
+struct ant_hci_t {
+public:
+ std::condition_variable rx_cond;
+ std::condition_variable on_cond;
+ std::mutex on_mtx;
+ std::mutex rx_mtx;
+ ant_power_state_t state;
+ bool rx_processing;
+};
+
+static struct ant_hci_t ant_hci;
+
+Return<void> initialization_complete(bool is_hci_initialize)
+{
+ ALOGI("%s: is_hci_initialize: %d", __func__, is_hci_initialize);
+
+ Lock lk(ant_hci.on_mtx);
+ if (is_hci_initialize)
+ {
+ ant_hci.state = ANT_RADIO_ENABLED;
+ ALOGI("%s: is_hci_initialize: %d", __func__, is_hci_initialize);
+ }
+ else
+ {
+ ALOGE("%s:Ant hci init failed :%d", __func__, is_hci_initialize);
+ ant_hci.state = ANT_RADIO_DISABLED;
+ }
+ ant_hci.on_cond.notify_all();
+ ALOGI("%s: exit", __func__);
+ return Void();
+}
+
+
+class AntHciCallbacks : public IAntHciCallbacks {
+public:
+ AntHciCallbacks() {};
+ virtual ~AntHciCallbacks() = default;
+
+ Return<void> initializationComplete(Status status)
+ {
+ ALOGI("%s", __func__);
+ if(status == Status::SUCCESS)
+ {
+ initialization_complete(true);
+ } else {
+ initialization_complete(false);
+ }
+ ALOGI("%s: exit", __func__);
+ return Void();
+ }
+
+ Return<void> antControlReceived(const hidl_vec<uint8_t>& event)
+ {
+ ALOGI("%s: Start ", __func__);
+ Lock lk(ant_hci.rx_mtx);
+
+ // Make sure we don't overwrite a message still processing.
+ while(ant_hci.rx_processing)
+ {
+ ant_hci.rx_cond.wait(lk);
+ }
+ ant_hci.rx_processing = true;
+
+ memcpy(&aucRxBuffer[0][0], event.data(), event.size());
+ iRxBufferLength[0] = event.size();
+ ant_hci.rx_cond.notify_all();
+ ALOGI("%s: End", __func__);
+ return Void();
+ }
+
+ Return<void> antDataReceived(const hidl_vec<uint8_t>& event)
+ {
+ ALOGI("%s: ", __func__);
+ Lock lk(ant_hci.rx_mtx);
+
+ // Make sure we don't overwrite a message still processing.
+ while(ant_hci.rx_processing)
+ {
+ ant_hci.rx_cond.wait(lk);
+ }
+ ant_hci.rx_processing = true;
+
+ memcpy(&aucRxBuffer[0][0], event.data(), event.size());
+ iRxBufferLength[0] = event.size();
+ ant_hci.rx_cond.notify_all();
+ ALOGI("%s: exit", __func__);
+ return Void();
+ }
+};
+
+bool hci_initialize()
+{
+ ALOGI("%s", __func__);
+
+ anthci = IAntHci::getService();
+
+ if(anthci != nullptr)
+ {
+ ant_hci.state = ANT_RADIO_ENABLING;
+ ant_hci.rx_processing = false;
+ android::sp<IAntHciCallbacks> callbacks = new AntHciCallbacks();
+ anthci->initialize(callbacks);
+ ALOGI("%s: exit", __func__);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void hci_close() {
+ ALOGV("%s", __func__);
+
+ if(anthci != nullptr)
+ {
+ anthci->close();
+ }
+ ant_rx_clear();
+ anthci =nullptr;
+ ant_hci.state = ANT_RADIO_DISABLED;
+ ALOGI("%s: exit", __func__);
+}
+
+ANT_UINT ant_get_status()
+{
+ return ant_hci.state;
+}
+
+ANTStatus ant_tx_write(ANT_U8 *pucTxMessage,ANT_U8 ucMessageLength)
+{
+ AntPacket data;
+ ANT_U8 packet_type;
+ ALOGI("%s: start", __func__);
+ packet_type = *pucTxMessage;
+ ALOGV("%s: proto type :%d", __func__, packet_type);
+ if (anthci != nullptr)
+ {
+ data.setToExternal(pucTxMessage+1, ucMessageLength);
+ if (packet_type == ANT_DATA_TYPE_PACKET)
+ {
+ anthci->sendAntData(data);
+ } else {
+ anthci->sendAntControl(data);
+ }
+ } else {
+ ALOGE("%s: antHci is NULL", __func__);
+ return -1;
+ }
+ ALOGI("%s: exit", __func__);
+ return ucMessageLength;
+}
+
+ANTStatus ant_rx_check()
+{
+ ALOGI("%s: start", __func__);
+ Lock lk(ant_hci.rx_mtx);
+ ant_hci.rx_cond.wait(lk);
+ ALOGI("%s: exit", __func__);
+ if (ant_hci.rx_processing)
+ {
+ return ANT_STATUS_SUCCESS;
+ }
+ else
+ {
+ return ANT_STATUS_NO_VALUE_AVAILABLE;
+ }
+}
+
+void ant_rx_clear()
+{
+ ALOGI("%s: start", __func__);
+ Lock lk(ant_hci.rx_mtx);
+ ant_hci.rx_processing = false;
+ ant_hci.rx_cond.notify_all();
+ ALOGI("%s: exit", __func__);
+}
+
+void ant_interface_init()
+{
+ ALOGI("%s: start", __func__);
+ bool status;
+ status = hci_initialize();
+ if (status)
+ {
+ ALOGV("%s waiting for iniialization complete hci state: %d ", __func__, ant_hci.state);
+ Lock lk(ant_hci.on_mtx);
+ while(ant_hci.state == ANT_RADIO_ENABLING)
+ {
+ ant_hci.on_cond.wait(lk);
+ ALOGV(LOG_TAG,"%s:after on_cond wait ",__func__);
+ }
+ } else {
+ ALOGE(LOG_TAG,"%s:Failed ",__func__);
+ ant_hci.state = ANT_RADIO_DISABLED;
+ }
+ ALOGI(LOG_TAG,"%s:exit ",__func__);
+}
diff --git a/src/qcomm-hidl/ant_native_chardev.c b/src/qcomm-hidl/ant_native_chardev.c
new file mode 100644
index 0000000..072dbb7
--- /dev/null
+++ b/src/qcomm-hidl/ant_native_chardev.c
@@ -0,0 +1,918 @@
+/*
+ * ANT Stack
+ *
+ * Copyright 2011 Dynastream Innovations
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/******************************************************************************\
+*
+* FILE NAME: ant_native_chardev.c
+*
+* BRIEF:
+* This file provides the VFS implementation of ant_native.h
+* VFS could be Character Device, TTY, etc.
+*
+*
+\******************************************************************************/
+
+#include <errno.h>
+#include <fcntl.h> /* for open() */
+#include <linux/ioctl.h> /* For hard reset */
+#include <pthread.h>
+#include <dlfcn.h> /* needed for runtime dll loading. */
+#include <stdint.h> /* for uint64_t */
+#include <sys/eventfd.h> /* For eventfd() */
+#include <unistd.h> /* for read(), write(), and close() */
+#include <string.h>
+
+#include "ant_types.h"
+#include "ant_native.h"
+#include "ant_version.h"
+
+#include "AntHidlClient.h"
+#include "antradio_power.h"
+#include "ant_rx_chardev.h"
+#include "ant_hci_defines.h"
+#include "ant_log.h"
+#include <cutils/properties.h> /* used by qualcomms additions for logging. */
+
+
+#if ANT_HCI_SIZE_SIZE > 1
+#include "ant_utils.h" // Put HCI Size value across multiple bytes
+#endif
+
+#define MESG_BROADCAST_DATA_ID ((ANT_U8)0x4E)
+#define MESG_ACKNOWLEDGED_DATA_ID ((ANT_U8)0x4F)
+#define MESG_BURST_DATA_ID ((ANT_U8)0x50)
+#define MESG_EXT_BROADCAST_DATA_ID ((ANT_U8)0x5D)
+#define MESG_EXT_ACKNOWLEDGED_DATA_ID ((ANT_U8)0x5E)
+#define MESG_EXT_BURST_DATA_ID ((ANT_U8)0x5F)
+#define MESG_ADV_BURST_DATA_ID ((ANT_U8)0x72)
+
+static ant_rx_thread_info_t stRxThreadInfo;
+static pthread_mutex_t stEnabledStatusLock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t stFlowControlLock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t stFlowControlCond = PTHREAD_COND_INITIALIZER;
+ANTNativeANTStateCb g_fnStateCallback;
+
+static const uint64_t EVENT_FD_PLUS_ONE = 1L;
+
+static void ant_channel_init(ant_channel_info_t *pstChnlInfo, const char *pcCharDevName);
+
+////////////////////////////////////////////////////////////////////
+// ant_init
+//
+// Initialises the native environment.
+//
+// Parameters:
+// -
+//
+// Returns:
+// ANT_STATUS_SUCCESS if intialize completed, else ANT_STATUS_FAILED
+//
+// Psuedocode:
+/*
+Set variables to defaults
+Initialise each supported path to chip
+Setup eventfd object.
+RESULT = ANT_STATUS_SUCCESS if no problems else ANT_STATUS_FAILED
+*/
+////////////////////////////////////////////////////////////////////
+ANTStatus ant_init(void)
+{
+ ANTStatus status = ANT_STATUS_FAILED;
+ ANT_FUNC_START();
+
+ stRxThreadInfo.stRxThread = 0;
+ stRxThreadInfo.ucRunThread = 0;
+ stRxThreadInfo.ucChipResetting = 0;
+ stRxThreadInfo.pstEnabledStatusLock = &stEnabledStatusLock;
+ g_fnStateCallback = 0;
+
+#ifdef ANT_DEVICE_NAME // Single transport path
+ ant_channel_init(&stRxThreadInfo.astChannels[SINGLE_CHANNEL], ANT_DEVICE_NAME);
+#else // Separate data/command paths
+ ant_channel_init(&stRxThreadInfo.astChannels[COMMAND_CHANNEL], ANT_COMMANDS_DEVICE_NAME);
+ ant_channel_init(&stRxThreadInfo.astChannels[DATA_CHANNEL], ANT_DATA_DEVICE_NAME);
+#endif // Separate data/command paths
+
+ // Make the eventfd. Want it non blocking so that we can easily reset it by reading.
+ stRxThreadInfo.iRxShutdownEventFd = eventfd(0, EFD_NONBLOCK);
+
+ // Check for error case
+ if(stRxThreadInfo.iRxShutdownEventFd == -1)
+ {
+ ANT_ERROR("ANT init failed. Could not create event fd. Reason: %s", strerror(errno));
+ } else {
+ status = ANT_STATUS_SUCCESS;
+ }
+
+ ANT_FUNC_END();
+ return status;
+}
+
+////////////////////////////////////////////////////////////////////
+// ant_deinit
+//
+// clean up eventfd object
+//
+// Parameters:
+// -
+//
+// Returns:
+// ANT_STATUS_SUCCESS
+//
+// Psuedocode:
+/*
+RESULT = SUCCESS
+*/
+////////////////////////////////////////////////////////////////////
+ANTStatus ant_deinit(void)
+{
+ ANTStatus result_status = ANT_STATUS_FAILED;
+ ANT_FUNC_START();
+
+ if(close(stRxThreadInfo.iRxShutdownEventFd) < 0)
+ {
+ ANT_ERROR("Could not close eventfd in deinit. Reason: %s", strerror(errno));
+ } else {
+ result_status = ANT_STATUS_SUCCESS;
+ }
+
+ ANT_FUNC_END();
+ return result_status;
+}
+
+
+////////////////////////////////////////////////////////////////////
+// ant_enable_radio
+//
+// Powers on the ANT part and initialises the transport to the chip.
+// Changes occur in part implementing ant_enable() call
+//
+// Parameters:
+// -
+//
+// Returns:
+// Success:
+// ANT_STATUS_SUCCESS
+// Failures:
+// ANT_STATUS_TRANSPORT_INIT_ERR if could not enable
+// ANT_STATUS_FAILED if failed to get mutex or init rx thread
+//
+// Psuedocode:
+/*
+LOCK enable_LOCK
+ State callback: STATE = ENABLING
+ ant enable
+ IF ant_enable success
+ State callback: STATE = ENABLED
+ RESULT = SUCCESS
+ ELSE
+ ant disable
+ State callback: STATE = Current state
+ RESULT = FAILURE
+ ENDIF
+UNLOCK
+*/
+////////////////////////////////////////////////////////////////////
+ANTStatus ant_enable_radio(void)
+{
+ int iLockResult;
+ ANTStatus result_status = ANT_STATUS_FAILED;
+ ANT_FUNC_START();
+
+ ANT_DEBUG_V("getting stEnabledStatusLock in %s", __FUNCTION__);
+ iLockResult = pthread_mutex_lock(&stEnabledStatusLock);
+ if(iLockResult) {
+ ANT_ERROR("enable failed to get state lock: %s", strerror(iLockResult));
+ goto out;
+ }
+ ANT_DEBUG_V("got stEnabledStatusLock in %s", __FUNCTION__);
+
+ if (g_fnStateCallback) {
+ g_fnStateCallback(RADIO_STATUS_ENABLING);
+ }
+
+ if (ant_enable() < 0) {
+ ANT_ERROR("ant enable failed: %s", strerror(errno));
+
+ ant_disable();
+
+ if (g_fnStateCallback) {
+ g_fnStateCallback(ant_radio_enabled_status());
+ }
+ } else {
+ if (g_fnStateCallback) {
+ g_fnStateCallback(RADIO_STATUS_ENABLED);
+ }
+
+ result_status = ANT_STATUS_SUCCESS;
+ }
+
+ ANT_DEBUG_V("releasing stEnabledStatusLock in %s", __FUNCTION__);
+ pthread_mutex_unlock(&stEnabledStatusLock);
+ ANT_DEBUG_V("released stEnabledStatusLock in %s", __FUNCTION__);
+
+out:
+ ANT_FUNC_END();
+ return result_status;
+}
+
+////////////////////////////////////////////////////////////////////
+// ant_radio_hard_reset
+//
+// IF SUPPORTED triggers a hard reset of the chip providing ANT functionality.
+//
+// Parameters:
+// -
+//
+// Returns:
+// Success:
+// ANT_STATUS_SUCCESS
+// Failures:
+// ANT_STATUS_NOT_SUPPORTED if the chip can't hard reset
+// ANT_STATUS_FAILED if failed to get mutex or enable
+//
+// Psuedocode:
+/*
+IF Hard Reset not supported
+ RESULT = NOT SUPPORTED
+ELSE
+ LOCK enable_LOCK
+ IF Lock failed
+ RESULT = FAILED
+ ELSE
+ Set Flag Rx thread that chip is resetting
+ FOR each path to chip
+ Send Reset IOCTL to path
+ ENDFOR
+ ant disable
+ ant enable
+ IF ant_enable success
+ State callback: STATE = RESET
+ RESULT = SUCCESS
+ ELSE
+ State callback: STATE = DISABLED
+ RESULT = FAILURE
+ ENDIF
+ Clear Flag Rx thread that chip is resetting
+ UNLOCK
+ENDIF
+*/
+////////////////////////////////////////////////////////////////////
+ANTStatus ant_radio_hard_reset(void)
+{
+ ANTStatus result_status = ANT_STATUS_NOT_SUPPORTED;
+ ANT_FUNC_START();
+
+#ifdef ANT_IOCTL_RESET
+ ant_channel_type eChannel;
+ int iLockResult;
+
+ result_status = ANT_STATUS_FAILED;
+
+ ANT_DEBUG_V("getting stEnabledStatusLock in %s", __FUNCTION__);
+ iLockResult = pthread_mutex_lock(&stEnabledStatusLock);
+ if(iLockResult) {
+ ANT_ERROR("enable failed to get state lock: %s", strerror(iLockResult));
+ goto out;
+ }
+ ANT_DEBUG_V("got stEnabledStatusLock in %s", __FUNCTION__);
+
+ stRxThreadInfo.ucChipResetting = 1;
+ if (g_fnStateCallback)
+ g_fnStateCallback(RADIO_STATUS_RESETTING);
+
+#ifdef ANT_IOCTL_RESET_PARAMETER
+ ioctl(stRxThreadInfo.astChannels[0].iFd, ANT_IOCTL_RESET, ANT_IOCTL_RESET_PARAMETER);
+#else
+ ioctl(stRxThreadInfo.astChannels[0].iFd, ANT_IOCTL_RESET);
+#endif // ANT_IOCTL_RESET_PARAMETER
+
+ ant_disable();
+
+ if (ant_enable()) { /* failed */
+ if (g_fnStateCallback)
+ g_fnStateCallback(RADIO_STATUS_DISABLED);
+ } else { /* success */
+ if (g_fnStateCallback)
+ g_fnStateCallback(RADIO_STATUS_RESET);
+ result_status = ANT_STATUS_SUCCESS;
+ }
+ stRxThreadInfo.ucChipResetting = 0;
+
+ ANT_DEBUG_V("releasing stEnabledStatusLock in %s", __FUNCTION__);
+ pthread_mutex_unlock(&stEnabledStatusLock);
+ ANT_DEBUG_V("released stEnabledStatusLock in %s", __FUNCTION__);
+out:
+#endif // ANT_IOCTL_RESET
+
+ ANT_FUNC_END();
+ return result_status;
+}
+
+////////////////////////////////////////////////////////////////////
+// ant_disable_radio
+//
+// Powers off the ANT part and closes the transport to the chip.
+//
+// Parameters:
+// -
+//
+// Returns:
+// Success:
+// ANT_STATUS_SUCCESS
+// Failures:
+// ANT_STATUS_FAILED if failed to get mutex
+//
+// Psuedocode:
+/*
+LOCK enable_LOCK
+ State callback: STATE = DISABLING
+ ant disable
+ State callback: STATE = Current state
+ RESULT = SUCCESS
+UNLOCK
+*/
+////////////////////////////////////////////////////////////////////
+ANTStatus ant_disable_radio(void)
+{
+ int iLockResult;
+ ANTStatus ret = ANT_STATUS_FAILED;
+ ANT_FUNC_START();
+
+ ANT_DEBUG_V("getting stEnabledStatusLock in %s", __FUNCTION__);
+ iLockResult = pthread_mutex_lock(&stEnabledStatusLock);
+ if(iLockResult) {
+ ANT_ERROR("disable failed to get state lock: %s", strerror(iLockResult));
+ goto out;
+ }
+ ANT_DEBUG_V("got stEnabledStatusLock in %s", __FUNCTION__);
+
+ if (g_fnStateCallback) {
+ g_fnStateCallback(RADIO_STATUS_DISABLING);
+ }
+
+ ant_disable();
+
+ if (g_fnStateCallback) {
+ g_fnStateCallback(ant_radio_enabled_status());
+ }
+
+ ret = ANT_STATUS_SUCCESS;
+
+ ANT_DEBUG_V("releasing stEnabledStatusLock in %s", __FUNCTION__);
+ pthread_mutex_unlock(&stEnabledStatusLock);
+ ANT_DEBUG_V("released stEnabledStatusLock in %s", __FUNCTION__);
+
+out:
+ ANT_FUNC_END();
+ return ret;
+}
+
+////////////////////////////////////////////////////////////////////
+// ant_radio_enabled_status
+//
+// Gets the current chip/transport state; either disabled, disabling,
+// enabling, enabled, or resetting. Determines this on the fly by checking
+// if Rx thread is running and how many of the paths for the ANT chip have
+// open VFS files.
+//
+// Parameters:
+// -
+//
+// Returns:
+// The current radio status (ANTRadioEnabledStatus)
+//
+// Psuedocode:
+/*
+IF Thread Resetting Flag is set
+ RESULT = Resetting
+ELSE
+ COUNT the number of open files
+ IF Thread Run Flag is Not Set
+ IF there are open files OR Rx thread exists
+ RESULT = Disabling
+ ELSE
+ RESULT = Disabled
+ ENDIF
+ ELSE
+ IF All files are open (all paths) AND Rx thread exists
+ RESULT = ENABLED
+ ELSE IF there are open files (Not 0 open files) AND Rx thread exists
+ RESULT = UNKNOWN
+ ELSE (0 open files or Rx thread does not exist [while Thread Run set])
+ RESULT = ENABLING
+ ENDIF
+ ENDIF
+ENDIF
+*/
+////////////////////////////////////////////////////////////////////
+ANTRadioEnabledStatus ant_radio_enabled_status(void)
+{
+ ant_channel_type eChannel;
+ int iOpenFiles = 0;
+ int iOpenThread;
+ ANTRadioEnabledStatus uiRet = RADIO_STATUS_UNKNOWN;
+ ANT_FUNC_START();
+
+ if (stRxThreadInfo.ucChipResetting) {
+ uiRet = RADIO_STATUS_RESETTING;
+ goto out;
+ }
+
+ uiRet = ant_get_status();
+ ANT_ERROR("ANT radio status =%d",uiRet);
+
+out:
+ ANT_DEBUG_D("get radio enabled status returned %d", uiRet);
+
+ ANT_FUNC_END();
+ return uiRet;
+}
+
+////////////////////////////////////////////////////////////////////
+// set_ant_rx_callback
+//
+// Sets which function to call when an ANT message is received.
+//
+// Parameters:
+// rx_callback_func the ANTNativeANTEventCb function to be used for
+// received messages (from all transport paths).
+//
+// Returns:
+// ANT_STATUS_SUCCESS
+//
+// Psuedocode:
+/*
+FOR each transport path
+ Path Rx Callback = rx_callback_func
+ENDFOR
+*/
+////////////////////////////////////////////////////////////////////
+ANTStatus set_ant_rx_callback(ANTNativeANTEventCb rx_callback_func)
+{
+ ANTStatus status = ANT_STATUS_SUCCESS;
+ ANT_FUNC_START();
+
+#ifdef ANT_DEVICE_NAME // Single transport path
+ stRxThreadInfo.astChannels[SINGLE_CHANNEL].fnRxCallback = rx_callback_func;
+#else // Separate data/command paths
+ stRxThreadInfo.astChannels[COMMAND_CHANNEL].fnRxCallback = rx_callback_func;
+ stRxThreadInfo.astChannels[DATA_CHANNEL].fnRxCallback = rx_callback_func;
+#endif // Separate data/command paths
+
+ ANT_FUNC_END();
+ return status;
+}
+
+////////////////////////////////////////////////////////////////////
+// set_ant_state_callback
+//
+// Sets which function to call when an ANT state change occurs.
+//
+// Parameters:
+// state_callback_func the ANTNativeANTStateCb function to be used
+// for received state changes.
+//
+// Returns:
+// ANT_STATUS_SUCCESS
+//
+// Psuedocode:
+/*
+ State Callback = state_callback_func
+*/
+////////////////////////////////////////////////////////////////////
+ANTStatus set_ant_state_callback(ANTNativeANTStateCb state_callback_func)
+{
+ ANTStatus status = ANT_STATUS_SUCCESS;
+ ANT_FUNC_START();
+
+ g_fnStateCallback = state_callback_func;
+
+ ANT_FUNC_END();
+ return status;
+}
+
+////////////////////////////////////////////////////////////////////
+// ant_tx_message_flowcontrol_wait
+//
+// Sends an ANT message to the chip and waits for a CTS signal
+//
+// Parameters:
+// eTxPath device to transmit message on
+// eFlowMessagePath device that receives CTS
+// ucMessageLength the length of the message
+// pucMesg pointer to the message data
+//
+// Returns:
+// Success:
+// ANT_STATUS_SUCCESS
+// Failure:
+// ANT_STATUS_NOT_ENABLED
+//
+// Psuedocode:
+/*
+ LOCK flow control
+ IF Lock failed
+ RESULT = FAILED
+ ELSE
+ SET flowMessagePath Flow Control response as FLOW_STOP
+ WRITE txBuffer to txPath (only length of packet part)
+ IF Wrote less then 0 bytes
+ Log error
+ RESULT = FAILED
+ ELSE IF Didn't write 'length of packet' bytes
+ Log error
+ RESULT = FAILED
+ ELSE
+ IF flowMessagePath Flow Control response is not FLOW_GO
+ WAIT until flowMessagePath Flow Control response is FLOW_GO, UNTIL FLOW_GO Wait Timeout seconds (10) from Now
+ IF error Waiting
+ IF error is Timeout
+ RESULT = HARDWARE ERROR
+ ELSE
+ RESULT = FAILED
+ ENDIF
+ ELSE
+ RESULT = SUCCESS
+ ENDIF
+ ELSE
+ RESULT = SUCCESS;
+ ENDIF
+ ENDIF
+ UNLOCK flow control
+ ENDIF
+*/
+////////////////////////////////////////////////////////////////////
+ANTStatus ant_tx_message_flowcontrol_wait(ant_channel_type eTxPath, ant_channel_type eFlowMessagePath, ANT_U8 ucMessageLength, ANT_U8 *pucTxMessage)
+{
+ int iMutexResult;
+ int iResult;
+ struct timespec stTimeout;
+ int iCondWaitResult;
+ ANTStatus status = ANT_STATUS_FAILED;
+ ANT_FUNC_START();
+
+ ANT_DEBUG_V("getting stFlowControlLock in %s", __FUNCTION__);
+ iMutexResult = pthread_mutex_lock(&stFlowControlLock);
+ if (iMutexResult) {
+ ANT_ERROR("failed to lock flow control mutex during tx: %s", strerror(iMutexResult));
+ goto out;
+ }
+ ANT_DEBUG_V("got stFlowControlLock in %s", __FUNCTION__);
+
+ stRxThreadInfo.astChannels[eFlowMessagePath].ucFlowControlResp = ANT_FLOW_STOP;
+
+#ifdef ANT_FLOW_RESEND
+ // Store Tx message so can resend it from Rx thread
+ stRxThreadInfo.astChannels[eFlowMessagePath].ucResendMessageLength = ucMessageLength;
+ stRxThreadInfo.astChannels[eFlowMessagePath].pucResendMessage = pucTxMessage;
+#endif // ANT_FLOW_RESEND
+
+ iResult = ant_tx_write(pucTxMessage,ucMessageLength);
+ if (iResult < 0) {
+ ANT_ERROR("failed to write data message to device: %s", strerror(errno));
+ } else if (iResult != ucMessageLength) {
+ ANT_ERROR("bytes written and message size don't match up");
+ } else {
+ stTimeout.tv_sec = time(0) + ANT_FLOW_GO_WAIT_TIMEOUT_SEC;
+ stTimeout.tv_nsec = 0;
+
+ while (stRxThreadInfo.astChannels[eFlowMessagePath].ucFlowControlResp != ANT_FLOW_GO) {
+ iCondWaitResult = pthread_cond_timedwait(&stFlowControlCond, &stFlowControlLock, &stTimeout);
+ if (iCondWaitResult) {
+ ANT_ERROR("failed to wait for flow control response: %s", strerror(iCondWaitResult));
+
+ if (iCondWaitResult == ETIMEDOUT) {
+ status = ANT_STATUS_HARDWARE_ERR;
+
+#ifdef ANT_FLOW_RESEND
+ // Clear Tx message so will stop resending it from Rx thread
+ stRxThreadInfo.astChannels[eFlowMessagePath].ucResendMessageLength = 0;
+ stRxThreadInfo.astChannels[eFlowMessagePath].pucResendMessage = NULL;
+#endif // ANT_FLOW_RESEND
+ }
+ goto wait_error;
+ }
+ }
+
+ status = ANT_STATUS_SUCCESS;
+ }
+
+wait_error:
+ ANT_DEBUG_V("releasing stFlowControlLock in %s", __FUNCTION__);
+ pthread_mutex_unlock(&stFlowControlLock);
+ ANT_DEBUG_V("released stFlowControlLock in %s", __FUNCTION__);
+
+out:
+ ANT_FUNC_END();
+ return status;
+}
+
+////////////////////////////////////////////////////////////////////
+// ant_tx_message_flowcontrol_none
+//
+// Sends an ANT message to the chip without waiting for flow control
+//
+// Parameters:
+// eTxPath device to transmit on
+// ucMessageLength the length of the message
+// pucMesg pointer to the message data
+//
+// Returns:
+// Success:
+// ANT_STATUS_SUCCESS
+// Failure:
+// ANT_STATUS_NOT_ENABLED
+//
+// Psuedocode:
+/*
+ WRITE txBuffer to Tx Path (only length of packet part)
+ IF Wrote less then 0 bytes
+ Log error
+ RESULT = FAILED
+ ELSE IF Didn't write 'length of packet' bytes
+ Log error
+ RESULT = FAILED
+ ELSE
+ RESULT = SUCCESS
+ ENDIF
+*/
+////////////////////////////////////////////////////////////////////
+ANTStatus ant_tx_message_flowcontrol_none(ant_channel_type eTxPath, ANT_U8 ucMessageLength, ANT_U8 *pucTxMessage)
+{
+ int iResult;
+ ANTStatus status = ANT_STATUS_FAILED;\
+ ANT_FUNC_START();
+
+ iResult = ant_tx_write(pucTxMessage, ucMessageLength);
+ if (iResult < 0) {
+ ANT_ERROR("failed to write message to device: %s", strerror(errno));
+ } else if (iResult != ucMessageLength) {
+ ANT_ERROR("bytes written and message size don't match up");
+ } else {
+ status = ANT_STATUS_SUCCESS;
+ }
+
+ ANT_FUNC_END();
+ return status;
+}
+
+////////////////////////////////////////////////////////////////////
+// ant_tx_message
+//
+// Frames ANT data and decides which flow control method to use for sending the
+// ANT message to the chip
+//
+// Parameters:
+// ucLen the length of the message
+// pucMesg pointer to the message data
+//
+// Returns:
+// Success:
+// ANT_STATUS_SUCCESS
+// Failure:
+// ANT_STATUS_NOT_ENABLED
+//
+// Psuedocode:
+/*
+IF not enabled
+ RESULT = BT NOT INITIALIZED
+ELSE
+ Create txBuffer, MAX HCI Message Size large
+ PUT ucLen in txBuffer AT ANT HCI Size Offset (0)
+ COPY pucMesg to txBuffer AT ANT HCI Header Size (1) <- ? Not at offset?
+ LOG txBuffer as a serial Tx (only length of packet part)
+ IF is a data message
+ Tx message on Data Path with FLOW_GO/FLOW_STOP flow control (ant_tx_message_flowcontrol_go_stop())
+ ELSE
+ Tx message on Command Path with no flow control (ant_tx_message_flowcontrol_none())
+ ENDIF
+ENDIF
+*/
+////////////////////////////////////////////////////////////////////
+ANTStatus ant_tx_message(ANT_U8 ucLen, ANT_U8 *pucMesg)
+{
+ // During a tx we must prepend a packet type byte. Thus HCI_PACKET_TYPE_SIZE is added
+ // to all offsets when writing into the tx buffer.
+ ANTStatus status = ANT_STATUS_FAILED;
+ // TODO ANT_HCI_MAX_MSG_SIZE is transport (driver) dependent.
+ ANT_U8 txBuffer[HCI_PACKET_TYPE_SIZE + ANT_HCI_MAX_MSG_SIZE];
+ // TODO Message length can be greater than ANT_U8 can hold.
+ // Not changed as ANT_SERIAL takes length as ANT_U8.
+ ANT_U8 txMessageLength = HCI_PACKET_TYPE_SIZE + ucLen + ANT_HCI_HEADER_SIZE;
+ ANT_FUNC_START();
+
+ if (ant_radio_enabled_status() != RADIO_STATUS_ENABLED) {
+ status = ANT_STATUS_FAILED_BT_NOT_INITIALIZED;
+ goto out;
+ }
+
+#if ANT_HCI_OPCODE_SIZE == 1
+ txBuffer[HCI_PACKET_TYPE_SIZE + ANT_HCI_OPCODE_OFFSET] = ANT_HCI_OPCODE_TX;
+#elif ANT_HCI_OPCODE_SIZE > 1
+#error "Specified ANT_HCI_OPCODE_SIZE not currently supported"
+#endif
+
+#if ANT_HCI_SIZE_SIZE == 1
+ txBuffer[HCI_PACKET_TYPE_SIZE + ANT_HCI_SIZE_OFFSET] = ucLen;
+#elif ANT_HCI_SIZE_SIZE == 2
+ ANT_UTILS_StoreLE16(txBuffer + HCI_PACKET_TYPE_SIZE + ANT_HCI_SIZE_OFFSET, (ANT_U16)ucLen);
+#else
+#error "Specified ANT_HCI_SIZE_SIZE not currently supported"
+#endif
+
+ memcpy(txBuffer + HCI_PACKET_TYPE_SIZE + ANT_HCI_HEADER_SIZE, pucMesg, ucLen);
+
+// We no longer do the serial logging here because the packet type byte is not yet written.
+//ANT_SERIAL(txBuffer, txMessageLength, 'T');
+
+// We only do this if we are using single physical and logical channels.
+#if defined(ANT_DEVICE_NAME) && (HCI_PACKET_TYPE_SIZE == 0) // Single transport path
+ ANT_SERIAL(txBuffer, txMessageLength, 'T');
+ status = ant_tx_message_flowcontrol_wait(SINGLE_CHANNEL, SINGLE_CHANNEL, txMessageLength, txBuffer);
+#else // Separate data/command paths
+ // Each path follows this structure:
+ // write the packet type if needed.
+ // log the packet
+ // Send using the appropriate physical channel, waiting for flow control for data commands.
+ switch (txBuffer[HCI_PACKET_TYPE_SIZE + ANT_HCI_DATA_OFFSET + ANT_MSG_ID_OFFSET]) {
+ case MESG_BROADCAST_DATA_ID:
+ case MESG_ACKNOWLEDGED_DATA_ID:
+ case MESG_BURST_DATA_ID:
+ case MESG_EXT_BROADCAST_DATA_ID:
+ case MESG_EXT_ACKNOWLEDGED_DATA_ID:
+ case MESG_EXT_BURST_DATA_ID:
+ case MESG_ADV_BURST_DATA_ID:
+ ANT_DEBUG_V("Data Path");
+ #if HCI_PACKET_TYPE_SIZE == 1
+ txBuffer[0] = ANT_DATA_TYPE_PACKET;
+ #elif HCI_PACKET_TYPE_SIZE > 1
+ #error "Specified HCI_PACKET_TYPE_SIZE not supported"
+ #endif
+ ANT_SERIAL(txBuffer, txMessageLength, 'T');
+ #ifdef ANT_DEVICE_NAME
+ status = ant_tx_message_flowcontrol_wait(SINGLE_CHANNEL, SINGLE_CHANNEL, txMessageLength, txBuffer);
+ #else
+ status = ant_tx_message_flowcontrol_wait(DATA_CHANNEL, COMMAND_CHANNEL, txMessageLength, txBuffer);
+ #endif
+ break;
+ default:
+ ANT_DEBUG_V("Control Path");
+ #if HCI_PACKET_TYPE_SIZE == 1
+ txBuffer[0] = ANT_CMD_TYPE_PACKET;
+ #elif HCI_PACKET_TYPE_SIZE > 1
+ #error "Specified HCI_PACKET_TYPE_SIZE not supported"
+ #endif
+ ANT_SERIAL(txBuffer, txMessageLength, 'T');
+ #ifdef ANT_DEVICE_NAME
+ status = ant_tx_message_flowcontrol_none(SINGLE_CHANNEL, txMessageLength, txBuffer);
+ #else
+ status = ant_tx_message_flowcontrol_none(COMMAND_CHANNEL, txMessageLength, txBuffer);
+ #endif
+ }
+#endif // Separate data/command paths
+
+out:
+ ANT_FUNC_END();
+ return status;
+}
+
+//----------------- TODO Move these somewhere for multi transport path / dedicated channel support:
+
+static void ant_channel_init(ant_channel_info_t *pstChnlInfo, const char *pcCharDevName)
+{
+ ANT_FUNC_START();
+
+ // TODO Don't need to store, only accessed when trying to open:
+ // Is however useful for logs.
+ pstChnlInfo->pcDevicePath = pcCharDevName;
+
+ // This is the only piece of info that needs to be stored per channel
+ pstChnlInfo->iFd = -1;
+
+ // TODO Only 1 of these (not per-channel) is actually ever used:
+ pstChnlInfo->fnRxCallback = NULL;
+ pstChnlInfo->ucFlowControlResp = ANT_FLOW_GO;
+#ifdef ANT_FLOW_RESEND
+ pstChnlInfo->ucResendMessageLength = 0;
+ pstChnlInfo->pucResendMessage = NULL;
+#endif // ANT_FLOW_RESEND
+ // TODO Only used when Flow Control message received, so must only be Command path Rx thread
+ pstChnlInfo->pstFlowControlCond = &stFlowControlCond;
+ pstChnlInfo->pstFlowControlLock = &stFlowControlLock;
+
+ ANT_FUNC_END();
+}
+
+static void ant_disable_channel(ant_channel_info_t *pstChnlInfo)
+{
+ ANT_FUNC_START();
+ if (!pstChnlInfo) {
+ ANT_ERROR("null channel info passed to channel disable function");
+ goto out;
+ }
+
+ hci_close();
+
+out:
+ ANT_FUNC_END();
+}
+
+static int ant_enable_channel(ant_channel_info_t *pstChnlInfo)
+{
+ int iRet = -1;
+ ANT_FUNC_START();
+ if (!pstChnlInfo) {
+ ANT_ERROR("null channel info passed to channel enable function");
+ errno = EINVAL;
+ goto out;
+ }
+ ANT_DEBUG_V("call HIDL init");
+ ant_interface_init();
+ iRet = 0;
+out:
+ ANT_FUNC_END();
+ return iRet;
+}
+
+//----------------------------------------------------------------------- This is antradio_power.h:
+
+int ant_enable(void)
+{
+ int iRet = -1;
+ ant_channel_type eChannel;
+ ANT_FUNC_START();
+
+ stRxThreadInfo.ucRunThread = 1;
+
+ for (eChannel = 0; eChannel < NUM_ANT_CHANNELS; eChannel++) {
+ if (ant_enable_channel(&stRxThreadInfo.astChannels[eChannel]) < 0) {
+ ANT_ERROR("failed to enable channel %s: %s",
+ stRxThreadInfo.astChannels[eChannel].pcDevicePath,
+ strerror(errno));
+ goto out;
+ }
+ }
+
+ if (stRxThreadInfo.stRxThread == 0) {
+ if (pthread_create(&stRxThreadInfo.stRxThread, NULL, fnRxThread, &stRxThreadInfo) < 0) {
+ ANT_ERROR("failed to start rx thread: %s", strerror(errno));
+ goto out;
+ }
+ } else {
+ ANT_DEBUG_D("rx thread is already running");
+ }
+
+ if (!stRxThreadInfo.ucRunThread) {
+ ANT_ERROR("rx thread crashed during init");
+ goto out;
+ }
+
+ iRet = 0;
+
+out:
+ ANT_FUNC_END();
+ return iRet;
+}
+
+int ant_disable(void)
+{
+ int iRet = -1;
+ ant_channel_type eChannel;
+ ANT_FUNC_START();
+
+ stRxThreadInfo.ucRunThread = 0;
+
+ for (eChannel = 0; eChannel < NUM_ANT_CHANNELS; eChannel++) {
+ ant_disable_channel(&stRxThreadInfo.astChannels[eChannel]);
+ }
+
+ iRet = 0;
+
+out:
+ stRxThreadInfo.stRxThread = 0;
+ ANT_FUNC_END();
+ return iRet;
+}
+
+//---------------------------------------------------------
+
+const char *ant_get_lib_version()
+{
+ return "libantradio.so: "ANT_CHIP_NAME". Version "
+ LIBANT_STACK_MAJOR"."LIBANT_STACK_MINOR"."LIBANT_STACK_INCRE;
+}
diff --git a/src/qcomm-hidl/ant_rx_chardev.c b/src/qcomm-hidl/ant_rx_chardev.c
new file mode 100644
index 0000000..153660c
--- /dev/null
+++ b/src/qcomm-hidl/ant_rx_chardev.c
@@ -0,0 +1,346 @@
+/*
+ * ANT Stack
+ *
+ * Copyright 2011 Dynastream Innovations
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/******************************************************************************\
+*
+* FILE NAME: ant_rx_chardev.c
+*
+* BRIEF:
+* This file implements the receive thread function which will loop reading
+* ANT messages until told to exit.
+*
+*
+\******************************************************************************/
+
+#include <errno.h>
+#include <poll.h>
+#include <pthread.h>
+#include <stdint.h> /* for uint64_t */
+#include <string.h>
+
+#include "ant_types.h"
+#include "antradio_power.h"
+#include "ant_rx_chardev.h"
+#include "ant_hci_defines.h"
+#include "ant_log.h"
+#include "ant_native.h" // ANT_HCI_MAX_MSG_SIZE, ANT_MSG_ID_OFFSET, ANT_MSG_DATA_OFFSET,
+ // ant_radio_enabled_status()
+
+#include "AntHidlClient.h"
+extern ANTStatus ant_tx_message_flowcontrol_none(ant_channel_type eTxPath, ANT_U8 ucMessageLength, ANT_U8 *pucTxMessage);
+
+#undef LOG_TAG
+#define LOG_TAG "antradio_rx"
+
+#define ANT_POLL_TIMEOUT ((int)30000)
+#define KEEPALIVE_TIMEOUT ((int)5000)
+
+ANT_U8 aucRxBuffer[NUM_ANT_CHANNELS][ANT_HCI_MAX_MSG_SIZE];
+
+#ifdef ANT_DEVICE_NAME // Single transport path
+ int iRxBufferLength[NUM_ANT_CHANNELS] = {0};
+#else
+ int iRxBufferLength[NUM_ANT_CHANNELS] = {0, 0};
+#endif //
+
+// Plus one is for the eventfd shutdown signal.
+#define NUM_POLL_FDS (NUM_ANT_CHANNELS + 1)
+#define EVENTFD_IDX NUM_ANT_CHANNELS
+
+static ANT_U8 KEEPALIVE_MESG[] = {0x01, 0x00, 0x00};
+static ANT_U8 KEEPALIVE_RESP[] = {0x03, 0x40, 0x00, 0x00, 0x28};
+
+void doReset(ant_rx_thread_info_t *stRxThreadInfo);
+int readChannelMsg(ant_channel_type eChannel, ant_channel_info_t *pstChnlInfo);
+
+
+/*
+ * This thread is run occasionally as a detached thread in order to send a keepalive message to the
+ * chip.
+ */
+void *fnKeepAliveThread(void *unused)
+{
+ ANT_DEBUG_V("Sending dummy keepalive message.");
+ ant_tx_message(sizeof(KEEPALIVE_MESG)/sizeof(ANT_U8), KEEPALIVE_MESG);
+ return NULL;
+}
+
+/*
+ * This thread waits for ANT messages from a VFS file.
+ */
+void *fnRxThread(void *ant_rx_thread_info)
+{
+ int iMutexLockResult;
+ int iPollRet;
+ ant_rx_thread_info_t *stRxThreadInfo;
+ struct pollfd astPollFd[NUM_POLL_FDS];
+ ANT_FUNC_START();
+
+ stRxThreadInfo = (ant_rx_thread_info_t *)ant_rx_thread_info;
+ // Fill out poll request for the shutdown signaller.
+ astPollFd[EVENTFD_IDX].fd = stRxThreadInfo->iRxShutdownEventFd;
+ astPollFd[EVENTFD_IDX].events = POLL_IN;
+
+ // Reset the waiting for response, since we don't want a stale value if we were reset.
+ stRxThreadInfo->bWaitingForKeepaliveResponse = ANT_FALSE;
+
+ /* continue running as long as not terminated */
+ while (stRxThreadInfo->ucRunThread) {
+ iPollRet = ant_rx_check();
+ if(iPollRet == 0)
+ {
+ readChannelMsg(0, &stRxThreadInfo->astChannels[0]);
+ }
+ }
+
+ /* disable ANT radio if not already disabling */
+ // Try to get stEnabledStatusLock.
+ // if you get it then no one is enabling or disabling
+ // if you can't get it assume something made you exit
+ ANT_DEBUG_V("try getting stEnabledStatusLock in %s", __FUNCTION__);
+ iMutexLockResult = pthread_mutex_trylock(stRxThreadInfo->pstEnabledStatusLock);
+ if (!iMutexLockResult) {
+ ANT_DEBUG_V("got stEnabledStatusLock in %s", __FUNCTION__);
+ ANT_WARN("rx thread has unexpectedly crashed, cleaning up");
+
+ // spoof our handle as closed so we don't try to join ourselves in disable
+ stRxThreadInfo->stRxThread = 0;
+
+ if (g_fnStateCallback) {
+ g_fnStateCallback(RADIO_STATUS_DISABLING);
+ }
+
+ ant_disable();
+
+ if (g_fnStateCallback) {
+ g_fnStateCallback(ant_radio_enabled_status());
+ }
+
+ ANT_DEBUG_V("releasing stEnabledStatusLock in %s", __FUNCTION__);
+ pthread_mutex_unlock(stRxThreadInfo->pstEnabledStatusLock);
+ ANT_DEBUG_V("released stEnabledStatusLock in %s", __FUNCTION__);
+ } else if (iMutexLockResult != EBUSY) {
+ ANT_ERROR("rx thread closing code, trylock on state lock failed: %s",
+ strerror(iMutexLockResult));
+ } else {
+ ANT_DEBUG_V("stEnabledStatusLock busy");
+ }
+
+ out:
+ ANT_FUNC_END();
+#ifdef ANDROID
+ return NULL;
+#endif
+}
+
+void doReset(ant_rx_thread_info_t *stRxThreadInfo)
+{
+ int iMutexLockResult;
+
+ ANT_FUNC_START();
+ /* Chip was reset or other error, only way to recover is to
+ * close and open ANT chardev */
+ stRxThreadInfo->ucChipResetting = 1;
+
+ if (g_fnStateCallback) {
+ g_fnStateCallback(RADIO_STATUS_RESETTING);
+ }
+
+ stRxThreadInfo->ucRunThread = 0;
+
+ ANT_DEBUG_V("getting stEnabledStatusLock in %s", __FUNCTION__);
+ iMutexLockResult = pthread_mutex_lock(stRxThreadInfo->pstEnabledStatusLock);
+ if (iMutexLockResult < 0) {
+ ANT_ERROR("chip was reset, getting state mutex failed: %s",
+ strerror(iMutexLockResult));
+ stRxThreadInfo->stRxThread = 0;
+ stRxThreadInfo->ucChipResetting = 0;
+ } else {
+ ANT_DEBUG_V("got stEnabledStatusLock in %s", __FUNCTION__);
+
+ stRxThreadInfo->stRxThread = 0; /* spoof our handle as closed so we don't
+ * try to join ourselves in disable */
+
+ ant_disable();
+
+ int enableResult = ant_enable();
+
+ stRxThreadInfo->ucChipResetting = 0;
+ if (enableResult) { /* failed */
+ if (g_fnStateCallback) {
+ g_fnStateCallback(RADIO_STATUS_DISABLED);
+ }
+ } else { /* success */
+ if (g_fnStateCallback) {
+ g_fnStateCallback(RADIO_STATUS_RESET);
+ }
+ }
+
+ ANT_DEBUG_V("releasing stEnabledStatusLock in %s", __FUNCTION__);
+ pthread_mutex_unlock(stRxThreadInfo->pstEnabledStatusLock);
+ ANT_DEBUG_V("released stEnabledStatusLock in %s", __FUNCTION__);
+ }
+
+ ANT_FUNC_END();
+}
+
+////////////////////////////////////////////////////////////////////
+// setFlowControl
+//
+// Sets the flow control "flag" to the value provided and signals the transmit
+// thread to check the value.
+//
+// Parameters:
+// pstChnlInfo the details of the channel being updated
+// ucFlowSetting the value to use
+//
+// Returns:
+// Success:
+// 0
+// Failure:
+// -1
+////////////////////////////////////////////////////////////////////
+int setFlowControl(ant_channel_info_t *pstChnlInfo, ANT_U8 ucFlowSetting)
+{
+ int iRet = -1;
+ int iMutexResult;
+ ANT_FUNC_START();
+
+ ANT_DEBUG_V("getting stFlowControlLock in %s", __FUNCTION__);
+ iMutexResult = pthread_mutex_lock(pstChnlInfo->pstFlowControlLock);
+ if (iMutexResult) {
+ ANT_ERROR("failed to lock flow control mutex during response: %s", strerror(iMutexResult));
+ } else {
+ ANT_DEBUG_V("got stFlowControlLock in %s", __FUNCTION__);
+
+ pstChnlInfo->ucFlowControlResp = ucFlowSetting;
+
+ ANT_DEBUG_V("releasing stFlowControlLock in %s", __FUNCTION__);
+ pthread_mutex_unlock(pstChnlInfo->pstFlowControlLock);
+ ANT_DEBUG_V("released stFlowControlLock in %s", __FUNCTION__);
+
+ pthread_cond_signal(pstChnlInfo->pstFlowControlCond);
+
+ iRet = 0;
+ }
+
+ ANT_FUNC_END();
+ return iRet;
+}
+
+int readChannelMsg(ant_channel_type eChannel, ant_channel_info_t *pstChnlInfo)
+{
+ int iRet = -1;
+ int iRxLenRead = 0;
+ int iCurrentHciPacketOffset;
+ int iHciDataSize;
+ ANT_FUNC_START();
+
+ // Keep trying to read while there is an error, and that error is EAGAIN
+ {
+ iRxLenRead += iRxBufferLength[eChannel]; // add existing data on
+ ANT_DEBUG_D("iRxLenRead %d",iRxLenRead);
+ ANT_SERIAL(aucRxBuffer[eChannel], iRxLenRead, 'R');
+
+ // if we didn't get a full packet, then just exit
+ if (iRxLenRead < (aucRxBuffer[eChannel][ANT_HCI_SIZE_OFFSET] + ANT_HCI_HEADER_SIZE + ANT_HCI_FOOTER_SIZE)) {
+ iRxBufferLength[eChannel] = iRxLenRead;
+ iRet = 0;
+ goto out;
+ }
+
+ iRxBufferLength[eChannel] = 0; // reset buffer length here since we should have a full packet
+
+#if ANT_HCI_OPCODE_SIZE == 1 // Check the different message types by opcode
+ ANT_U8 opcode = aucRxBuffer[eChannel][ANT_HCI_OPCODE_OFFSET];
+
+ if(ANT_HCI_OPCODE_COMMAND_COMPLETE == opcode) {
+ // Command Complete, so signal a FLOW_GO
+ if(setFlowControl(pstChnlInfo, ANT_FLOW_GO)) {
+ goto out;
+ }
+ } else if(ANT_HCI_OPCODE_FLOW_ON == opcode) {
+ // FLow On, so resend the last Tx
+#ifdef ANT_FLOW_RESEND
+ // Check if there is a message to resend
+ if(pstChnlInfo->ucResendMessageLength > 0) {
+ ant_tx_message_flowcontrol_none(eChannel, pstChnlInfo->ucResendMessageLength, pstChnlInfo->pucResendMessage);
+ } else {
+ ANT_DEBUG_D("Resend requested by chip, but tx request cancelled");
+ }
+#endif // ANT_FLOW_RESEND
+ } else if(ANT_HCI_OPCODE_ANT_EVENT == opcode)
+ // ANT Event, send ANT packet to Rx Callback
+#endif // ANT_HCI_OPCODE_SIZE == 1
+ {
+ // Received an ANT packet
+ iCurrentHciPacketOffset = 0;
+
+ while(iCurrentHciPacketOffset < iRxLenRead) {
+ ANT_DEBUG_D("iRxLenRead = %d",iRxLenRead);
+
+ // TODO Allow HCI Packet Size value to be larger than 1 byte
+ // This currently works as no size value is greater than 255, and little endian
+ iHciDataSize = aucRxBuffer[eChannel][iCurrentHciPacketOffset + ANT_HCI_SIZE_OFFSET];
+
+ if ((iHciDataSize + ANT_HCI_HEADER_SIZE + ANT_HCI_FOOTER_SIZE + iCurrentHciPacketOffset) >
+ iRxLenRead) {
+ // we don't have a whole packet
+ iRxBufferLength[eChannel] = iRxLenRead - iCurrentHciPacketOffset;
+ memcpy(aucRxBuffer[eChannel], &aucRxBuffer[eChannel][iCurrentHciPacketOffset], iRxBufferLength[eChannel]);
+ // the increment at the end should push us out of the while loop
+ } else
+#ifdef ANT_MESG_FLOW_CONTROL
+ if (aucRxBuffer[eChannel][iCurrentHciPacketOffset + ANT_HCI_DATA_OFFSET + ANT_MSG_ID_OFFSET] ==
+ ANT_MESG_FLOW_CONTROL) {
+ // This is a flow control packet, not a standard ANT message
+ if(setFlowControl(pstChnlInfo, \
+ aucRxBuffer[eChannel][iCurrentHciPacketOffset + ANT_HCI_DATA_OFFSET + ANT_MSG_DATA_OFFSET])) {
+ goto out;
+ }
+ } else
+#endif // ANT_MESG_FLOW_CONTROL
+ {
+ ANT_U8 *msg = aucRxBuffer[eChannel] + iCurrentHciPacketOffset + ANT_HCI_DATA_OFFSET;
+ ANT_BOOL bIsKeepAliveResponse = memcmp(msg, KEEPALIVE_RESP, sizeof(KEEPALIVE_RESP)/sizeof(ANT_U8)) == 0;
+ if (bIsKeepAliveResponse) {
+ ANT_DEBUG_V("Filtered out keepalive response.");
+ } else if (pstChnlInfo->fnRxCallback != NULL) {
+ ANT_DEBUG_V("call rx callback hci data size = %d",iHciDataSize);
+
+ // Loop through read data until all HCI packets are written to callback
+ pstChnlInfo->fnRxCallback(iHciDataSize, \
+ msg);
+ } else {
+ ANT_WARN("%s rx callback is null", pstChnlInfo->pcDevicePath);
+ }
+ }
+
+ iCurrentHciPacketOffset = iCurrentHciPacketOffset + ANT_HCI_HEADER_SIZE + ANT_HCI_FOOTER_SIZE + iHciDataSize;
+ }
+ }
+
+ iRet = 0;
+ }
+
+out:
+ // Need to indicate that we are done handling the rx buffer and it can be
+ // overwritten again.
+ ant_rx_clear();
+ ANT_FUNC_END();
+ return iRet;
+}
diff --git a/src/qcomm-hidl/inc/AntHidlClient.h b/src/qcomm-hidl/inc/AntHidlClient.h
new file mode 100644
index 0000000..cbb81d8
--- /dev/null
+++ b/src/qcomm-hidl/inc/AntHidlClient.h
@@ -0,0 +1,56 @@
+/*
+ *Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ *WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ *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.
+ */
+
+
+#include "ant_driver_defines.h"
+#include "ant_rx_chardev.h"
+
+extern ANT_U8 aucRxBuffer[NUM_ANT_CHANNELS][ANT_HCI_MAX_MSG_SIZE];
+
+extern int iRxBufferLength[NUM_ANT_CHANNELS];
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void ant_interface_init();
+ void hci_close();
+
+ ANTStatus ant_tx_write(ANT_U8 *pucTxMessage,ANT_U8 ucMessageLength);
+ ANTStatus ant_rx_check();
+ void ant_rx_clear();
+
+ ANT_UINT ant_get_status();
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/qcomm-hidl/inc/ant_hci_defines.h b/src/qcomm-hidl/inc/ant_hci_defines.h
new file mode 100644
index 0000000..3ffe672
--- /dev/null
+++ b/src/qcomm-hidl/inc/ant_hci_defines.h
@@ -0,0 +1,53 @@
+/*
+ * ANT Stack
+ *
+ * Copyright 2013 Dynastream Innovations
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*******************************************************************************\
+*
+* FILE NAME: ant_hci_defines.h
+*
+* BRIEF:
+* This file defines ANT specific HCI values used by the ANT chip that are
+* not specific to the underlying chip. These should not need to be modified,
+* but should be verified they are correct.
+*
+\*******************************************************************************/
+
+#ifndef __VFS_INDEPENDENT_H
+#define __VFS_INDEPENDENT_H
+
+// ANT HCI Packet Structure
+// -----------------------------------------
+// | Header | Data | Footer |
+// |----------------------|-----------------|
+// |Optional| Data | Opt. | ... | Optional |
+// | Opcode | Size | Sync | | Checksum |
+// Data may include any number of ANT packets, with no sync byte or checksum.
+// A read from the driver may return any number of ANT HCI packets.
+
+#include "ant_driver_defines.h"
+
+#define ANT_HCI_HEADER_SIZE ((ANT_HCI_OPCODE_SIZE) + (ANT_HCI_SIZE_SIZE) + (ANT_HCI_SYNC_SIZE))
+#define ANT_HCI_FOOTER_SIZE (ANT_HCI_CHECKSUM_SIZE)
+
+#define ANT_HCI_OPCODE_OFFSET 0
+#define ANT_HCI_SIZE_OFFSET ((ANT_HCI_OPCODE_OFFSET) + (ANT_HCI_OPCODE_SIZE))
+#define ANT_HCI_SYNC_OFFSET ((ANT_HCI_SIZE_OFFSET) + (ANT_HCI_SIZE_SIZE))
+#define ANT_HCI_DATA_OFFSET (ANT_HCI_HEADER_SIZE)
+
+#define ANT_FLOW_GO_WAIT_TIMEOUT_SEC 10
+
+#endif /* ifndef __VFS_INDEPENDENT_H */
diff --git a/src/qcomm-hidl/inc/ant_rx_chardev.h b/src/qcomm-hidl/inc/ant_rx_chardev.h
new file mode 100644
index 0000000..12ba629
--- /dev/null
+++ b/src/qcomm-hidl/inc/ant_rx_chardev.h
@@ -0,0 +1,100 @@
+/*
+ * ANT Stack
+ *
+ * Copyright 2011 Dynastream Innovations
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*******************************************************************************\
+*
+* FILE NAME: ant_rx_chardev.h
+*
+* BRIEF:
+* This file defines the receive thread function, the ant_rx_thread_info_t
+* type for storing the -configuration- <state> of the receive thread, the
+* ant_channel_info_t type for storing a channel's (transport path)
+* configuration, and an enumeration of all ANT channels (transport paths).
+*
+*
+\*******************************************************************************/
+
+#ifndef __ANT_RX_NATIVE_H
+#define __ANT_RX_NATIVE_H
+
+#include "ant_native.h"
+#include "ant_hci_defines.h"
+
+/* same as HCI_MAX_EVENT_SIZE from hci.h, but hci.h is not included for vfs */
+#define ANT_HCI_MAX_MSG_SIZE 260
+
+#define ANT_MSG_SIZE_OFFSET ((ANT_U8)0)
+#define ANT_MSG_ID_OFFSET ((ANT_U8)1)
+#define ANT_MSG_DATA_OFFSET ((ANT_U8)2)
+
+/* This struct defines the info passed to an rx thread */
+typedef struct {
+ /* Device path */
+ const char *pcDevicePath;
+ /* File descriptor to read from */
+ int iFd;
+ /* Callback to call with ANT packet */
+ ANTNativeANTEventCb fnRxCallback;
+ /* Flow control response if channel supports it */
+ ANT_U8 ucFlowControlResp;
+ /* Handle to flow control condition */
+ pthread_cond_t *pstFlowControlCond;
+ /* Handle to flow control mutex */
+ pthread_mutex_t *pstFlowControlLock;
+#ifdef ANT_FLOW_RESEND
+ /* Length of message to resend on request from chip */
+ ANT_U8 ucResendMessageLength;
+ /* The message to resend on request from chip */
+ ANT_U8 *pucResendMessage;
+#endif // ANT_FLOW_RESEND
+} ant_channel_info_t;
+
+typedef enum {
+#ifdef ANT_DEVICE_NAME // Single transport path
+ SINGLE_CHANNEL,
+#else // Separate data/command paths
+ DATA_CHANNEL,
+ COMMAND_CHANNEL,
+#endif // Separate data/command paths
+ NUM_ANT_CHANNELS
+} ant_channel_type;
+
+typedef struct {
+ /* Thread handle */
+ pthread_t stRxThread;
+ /* Exit condition */
+ ANT_U8 ucRunThread;
+ /* Set state as resetting override */
+ ANT_U8 ucChipResetting;
+ /* Handle to state change lock for crash cleanup */
+ pthread_mutex_t *pstEnabledStatusLock;
+ /* ANT channels */
+ ant_channel_info_t astChannels[NUM_ANT_CHANNELS];
+ /* Event file descriptor used to interrupt the poll() loop in the rx thread. */
+ int iRxShutdownEventFd;
+ /* Indicates whether thread is waiting for a keepalive response. */
+ ANT_BOOL bWaitingForKeepaliveResponse;
+} ant_rx_thread_info_t;
+
+extern ANTNativeANTStateCb g_fnStateCallback; // TODO State callback should be inside ant_rx_thread_info_t.
+
+/* This is the rx thread function. It loops reading ANT packets until told to
+ * exit */
+void *fnRxThread(void *ant_rx_thread_info);
+
+#endif /* ifndef __ANT_RX_NATIVE_H */
+
diff --git a/src/qcomm-hidl/inc/antradio_power.h b/src/qcomm-hidl/inc/antradio_power.h
new file mode 100644
index 0000000..d0f8478
--- /dev/null
+++ b/src/qcomm-hidl/inc/antradio_power.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ANTRADIOPM_H
+#define __ANTRADIOPM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Enable the ANT radio interface.
+ *
+ * Responsible for power on, and bringing up HCI interface.
+ * Will block until the HCI interface is ready to use.
+ *
+ * Returns 0 on success, -ve on error */
+int ant_enable();
+
+/* Disable the ANT radio interface.
+ *
+ * Responsbile for pulling down the HCI interface, and powering down the chip.
+ * Will block until power down is complete, and it is safe to immediately call
+ * enable().
+ *
+ * Returns 0 on success, -ve on error */
+int ant_disable();
+
+/* Returns 1 if enabled, 0 if disabled, and -ve on error */
+int ant_is_enabled();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/qcomm-hidl/qualcomm/hidl/ant_driver_defines.h b/src/qcomm-hidl/qualcomm/hidl/ant_driver_defines.h
new file mode 100644
index 0000000..0f4ed7a
--- /dev/null
+++ b/src/qcomm-hidl/qualcomm/hidl/ant_driver_defines.h
@@ -0,0 +1,109 @@
+/*
+ * ANT Stack
+ *
+ * Copyright 2011 Dynastream Innovations
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*******************************************************************************\
+*
+* FILE NAME: ant_driver_defines.h
+*
+* BRIEF:
+* This file defines ANT specific HCI values used by the ANT chip for a
+* Qualcomm UART implementation.
+*
+*
+\*******************************************************************************/
+
+#ifndef __VFS_PRERELEASE_H
+#define __VFS_PRERELEASE_H
+
+// Packets may be prefixed with an optional packet type byte when being sent to
+// the chip. Will not be present in messages received.
+
+// -----------------------------------------
+// | Header | Data | Footer |
+// |----------------------|-----------------|
+// |Optional| Data | Opt. | ... | Optional |
+// | Opcode | Size | Sync | | Checksum |
+
+// Data may include any number of ANT packets, with no sync byte or checksum.
+// A read from the driver may return any number of ANT HCI packets.
+
+
+// ---------------------- REQUIRED
+
+// Which chip is this library being built for:
+#define ANT_CHIP_NAME "Qualcomm HIDL"
+
+// Set the file name the driver creates for the ANT device:
+// If chip uses separate command and data paths:
+// #define ANT_COMMANDS_DEVICE_NAME "/dev/X"
+// #define ANT_DATA_DEVICE_NAME "/dev/Y"
+// OR
+// If chip uses one path:
+
+#define ANT_DEVICE_NAME "/dev/ttyHS0"
+
+// Optional Packet prefix byte.
+#define HCI_PACKET_TYPE_SIZE 1
+
+// Set to the number of bytes of header is for Opcode:
+#define ANT_HCI_OPCODE_SIZE 0
+
+// Set to the number of bytes of header is for Data Size:
+#define ANT_HCI_SIZE_SIZE 1
+
+// Set to the number of bytes of header is for Sync:
+#define ANT_HCI_SYNC_SIZE 0
+
+// Set to the number of bytes of footer is for Checksum:
+#define ANT_HCI_CHECKSUM_SIZE 0
+
+// ---------------------- OPTIONAL
+
+// If hard reset is supported, define ANT_IOCTL_RESET
+// #define ANT_IOCTL_RESET _IOW('U', 210, int)
+// #define ANT_IOCTL_RESET_PARAMETER (0)
+
+// If the chip sends flow control messages:
+// Define the Opcode for a Flow Control message:
+#define ANT_MESG_FLOW_CONTROL ((ANT_U8)0xC9)
+// AND
+// define the message content:
+// That signals Flow Go:
+#define ANT_FLOW_GO ((ANT_U8)0x00)
+
+// That signals Flow Stop:
+#define ANT_FLOW_STOP ((ANT_U8)0x80)
+
+// Define protocol byte to be added
+// as multiple data will be sent/received over
+// same transport(BT, ANT ..etc)
+// needed for HCI_PACKET_TYPE_SIZE > 1.
+#define ANT_CMD_TYPE_PACKET ((ANT_U8)0x0C)
+#define ANT_DATA_TYPE_PACKET ((ANT_U8)0x0E)
+
+
+typedef enum {
+ ANT_RADIO_UNKNOWN,
+ ANT_RADIO_ENABLING,
+ ANT_RADIO_ENABLED,
+ ANT_RADIO_DISABLING,
+ ANT_RADIO_DISABLED
+} ant_power_state_t;
+
+
+
+#endif /* ifndef __VFS_PRERELEASE_H */