aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRohan Martin <rohan.martin@thisisant.com>2012-11-01 15:20:17 -0600
committerRohan Martin <rohan.martin@thisisant.com>2012-11-01 15:20:17 -0600
commit95c4bdb20e2823f28df739902947c98b11ddc03e (patch)
treee0ef46bac8dfddec9df9009880bdce503b6389ba
parent6baccbbe08b8b5174fb1e49b8511f522b551f463 (diff)
downloadandroid_external_ant-wireless_ant_native-95c4bdb20e2823f28df739902947c98b11ddc03e.tar.gz
android_external_ant-wireless_ant_native-95c4bdb20e2823f28df739902947c98b11ddc03e.tar.bz2
android_external_ant-wireless_ant_native-95c4bdb20e2823f28df739902947c98b11ddc03e.zip
Broke Android_System_package in to individual repositories
-rw-r--r--Android.mk70
-rw-r--r--JAntNative.cpp366
-rw-r--r--LICENSE202
-rw-r--r--NOTICE5
-rw-r--r--README.md2
-rw-r--r--app/ant_app.c326
-rw-r--r--app/ant_app.h25
-rw-r--r--src/bluez_hci/Android.mk67
-rw-r--r--src/bluez_hci/ant_native_hci.c823
-rw-r--r--src/bluez_hci/ant_rx.c275
-rw-r--r--src/bluez_hci/ant_tx.c358
-rw-r--r--src/bluez_hci/inc/ant_framing.h50
-rw-r--r--src/bluez_hci/inc/ant_hciutils.h121
-rw-r--r--src/bluez_hci/inc/ant_rx.h54
-rw-r--r--src/bluez_hci/inc/ant_tx.h42
-rw-r--r--src/chip-B/Android.mk50
-rw-r--r--src/chip-B/ant_native_chardev.c424
-rw-r--r--src/chip-B/ant_rx_chardev.c213
-rw-r--r--src/chip-B/inc/ant_native_chardev.h48
-rw-r--r--src/chip-B/inc/ant_rx_chardev.h73
-rw-r--r--src/chip-C/Android.mk50
-rw-r--r--src/chip-C/ant_native_chardev.c389
-rw-r--r--src/chip-C/ant_rx_chardev.c213
-rw-r--r--src/chip-C/inc/ant_native_chardev.h48
-rw-r--r--src/chip-C/inc/ant_rx_chardev.h73
-rw-r--r--src/common/ant_utils.c57
-rw-r--r--src/common/inc/ant_log.h174
-rw-r--r--src/common/inc/ant_native.h142
-rw-r--r--src/common/inc/ant_types.h125
-rw-r--r--src/common/inc/ant_utils.h139
-rw-r--r--src/common/inc/ant_version.h27
31 files changed, 5030 insertions, 1 deletions
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..801a40c
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,70 @@
+#
+# Copyright (C) 2009 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.
+#
+
+ifneq ($(BOARD_ANT_WIRELESS_DEVICE),)
+
+#
+# ANT native library
+#
+
+include $(CLEAR_VARS)
+
+ifeq ($(BOARD_ANT_WIRELESS_DEVICE),"wl12xx")
+
+include $(LOCAL_PATH)/hal/bluez_hci/Android.mk
+
+else ifeq ($(BOARD_ANT_WIRELESS_DEVICE),"chip-B")
+
+include $(LOCAL_PATH)/hal/chip-B/Android.mk
+
+else ifeq ($(BOARD_ANT_WIRELESS_DEVICE),"chip-C")
+
+include $(LOCAL_PATH)/hal/chip-C/Android.mk
+
+else
+
+$(error Unsupported BOARD_ANT_WIRELESS_DEVICE := $(BOARD_ANT_WIRELESS_DEVICE))
+
+endif # BOARD_ANT_WIRELESS_DEVICE type
+
+
+#
+# ANT Application
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_C_INCLUDES:= \
+ $(LOCAL_PATH)/src/common/inc \
+ $(LOCAL_PATH)/app
+
+LOCAL_CFLAGS:= -g -c -W -Wall -O2
+
+LOCAL_SRC_FILES:= \
+ $(LOCAL_PATH)/app/ant_app.c
+
+LOCAL_SHARED_LIBRARIES := \
+ libantradio \
+ libcutils
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
+LOCAL_MODULE_TAGS := debug
+LOCAL_MODULE:=antradio_app
+
+include $(BUILD_EXECUTABLE)
+
+
+endif # BOARD_ANT_WIRELESS_DEVICE defined
diff --git a/JAntNative.cpp b/JAntNative.cpp
new file mode 100644
index 0000000..2e3beb0
--- /dev/null
+++ b/JAntNative.cpp
@@ -0,0 +1,366 @@
+/*
+ * ANT Stack
+ *
+ * Copyright 2009 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: JAntNative.cpp
+*
+* BRIEF:
+* This file provides the implementation of the native interface functions for ANT
+*
+*
+\*******************************************************************************/
+
+#include "android_runtime/AndroidRuntime.h"
+#include "jni.h"
+#include "nativehelper/JNIHelp.h"
+
+static JNIEnv *g_jEnv = NULL;
+static JavaVM *g_jVM = NULL;
+static jclass g_sJClazz;
+static jmethodID g_sMethodId_nativeCb_AntRxMessage;
+static jmethodID g_sMethodId_nativeCb_AntStateChange;
+
+extern "C"
+{
+ #include "ant_native.h"
+ #include "ant_log.h"
+ #undef LOG_TAG
+ #define LOG_TAG "JAntNative"
+
+ void nativeJAnt_RxCallback(ANT_U8 ucLen, ANT_U8* pucData);
+ void nativeJAnt_StateCallback(ANTRadioEnabledStatus uiNewState);
+}
+
+static jint nativeJAnt_Create(JNIEnv *env, jobject obj)
+{
+ ANTStatus antStatus = ANT_STATUS_FAILED;
+ (void)env; //unused warning
+ (void)obj; //unused warning
+
+ ANT_FUNC_START();
+
+ antStatus = ant_init();
+ if (antStatus)
+ {
+ ANT_DEBUG_D("failed to init ANT stack");
+ goto CLEANUP;
+ }
+
+ antStatus = set_ant_rx_callback(nativeJAnt_RxCallback);
+ if (antStatus)
+ {
+ ANT_DEBUG_D("failed to set ANT rx callback");
+ goto CLEANUP;
+ }
+
+ antStatus = set_ant_state_callback(nativeJAnt_StateCallback);
+ if (antStatus)
+ {
+ ANT_DEBUG_D("failed to set ANT state callback");
+ goto CLEANUP;
+ }
+
+CLEANUP:
+ ANT_FUNC_END();
+ return antStatus;
+}
+
+static jint nativeJAnt_Destroy(JNIEnv *env, jobject obj)
+{
+ (void)env; //unused warning
+ (void)obj; //unused warning
+ ANTStatus status;
+ ANT_FUNC_START();
+
+ ANT_DEBUG_D("nativeJAnt_Destroy(): calling ant_deinit");
+ status = ant_deinit();
+ if (status)
+ {
+ ANT_DEBUG_D("failed to deinit ANT stack returned %d",(int)status);
+ return status;
+ }
+ else
+ {
+ ANT_DEBUG_D("deinit ANT stack Success");
+ }
+
+ ANT_FUNC_END();
+ return status;
+}
+
+static jint nativeJAnt_Enable(JNIEnv *env, jobject obj)
+{
+ (void)env; //unused warning
+ (void)obj; //unused warning
+ ANT_FUNC_START();
+
+ ANTStatus status = ant_enable_radio();
+
+ ANT_FUNC_END();
+ return status;
+}
+
+static jint nativeJAnt_Disable(JNIEnv *env, jobject obj)
+{
+ (void)env; //unused warning
+ (void)obj; //unused warning
+ ANT_FUNC_START();
+
+ ANTStatus status = ant_disable_radio();
+
+ ANT_FUNC_END();
+ return status;
+}
+
+static jint nativeJAnt_GetRadioEnabledStatus(JNIEnv *env, jobject obj)
+{
+ (void)env; //unused warning
+ (void)obj; //unused warning
+ ANT_FUNC_START();
+
+ jint status = ant_radio_enabled_status();
+
+ ANT_FUNC_END();
+ return status;
+}
+
+static jint nativeJAnt_TxMessage(JNIEnv *env, jobject obj, jbyteArray msg)
+{
+ (void)obj; //unused warning
+ ANT_FUNC_START();
+
+ if (msg == NULL)
+ {
+ if (jniThrowException(env, "java/lang/NullPointerException", NULL))
+ {
+ ANT_ERROR("Unable to throw NullPointerException");
+ }
+ return -1;
+ }
+
+ jbyte* msgBytes = env->GetByteArrayElements(msg, NULL);
+ jint msgLength = env->GetArrayLength(msg);
+
+ ANTStatus status = ant_tx_message((ANT_U8) msgLength, (ANT_U8 *)msgBytes);
+ ANT_DEBUG_D("nativeJAnt_TxMessage: ant_tx_message() returned %d", (int)status);
+
+ env->ReleaseByteArrayElements(msg, msgBytes, JNI_ABORT);
+
+ ANT_FUNC_END();
+ return status;
+}
+
+static jint nativeJAnt_HardReset(JNIEnv *env, jobject obj)
+{
+ (void)env; //unused warning
+ (void)obj; //unused warning
+ ANT_FUNC_START();
+
+ ANTStatus status = ant_radio_hard_reset();
+
+ ANT_FUNC_END();
+ return status;
+}
+
+extern "C"
+{
+
+ /**********************************************************************
+ * Callback registration
+ ***********************************************************************/
+ void nativeJAnt_RxCallback(ANT_U8 ucLen, ANT_U8* pucData)
+ {
+ JNIEnv* env = NULL;
+ jbyteArray jAntRxMsg = NULL;
+ ANT_FUNC_START();
+
+ ANT_DEBUG_D( "got message %d bytes", ucLen);
+
+ g_jVM->AttachCurrentThread((&env), NULL);
+
+ if (env == NULL)
+ {
+ ANT_DEBUG_D("nativeJAnt_RxCallback: Entered, env is null");
+ return; // log error? cleanup?
+ }
+ else
+ {
+ ANT_DEBUG_D("nativeJAnt_RxCallback: jEnv %p", env);
+ }
+
+ jAntRxMsg = env->NewByteArray(ucLen);
+
+ if (jAntRxMsg == NULL)
+ {
+ ANT_ERROR("nativeJAnt_RxCallback: Failed creating java byte[]");
+ goto CLEANUP;
+ }
+
+ env->SetByteArrayRegion(jAntRxMsg,0,ucLen,(jbyte*)pucData);
+
+ if (env->ExceptionOccurred())
+ {
+ ANT_ERROR("nativeJAnt_RxCallback: ExceptionOccurred during byte[] copy");
+ goto CLEANUP;
+ }
+ ANT_DEBUG_V("nativeJAnt_RxCallback: Calling java rx callback");
+ env->CallStaticVoidMethod(g_sJClazz, g_sMethodId_nativeCb_AntRxMessage, jAntRxMsg);
+ ANT_DEBUG_V("nativeJAnt_RxCallback: Called java rx callback");
+
+ if (env->ExceptionOccurred())
+ {
+ ANT_ERROR("nativeJAnt_RxCallback: Calling Java nativeCb_AntRxMessage failed");
+ goto CLEANUP;
+ }
+
+ //Delete the local references
+ if (jAntRxMsg != NULL)
+ {
+ env->DeleteLocalRef(jAntRxMsg);
+ }
+
+ ANT_DEBUG_D("nativeJAnt_RxCallback: Exiting, Calling DetachCurrentThread at the END");
+
+ g_jVM->DetachCurrentThread();
+
+ ANT_FUNC_END();
+ return;
+
+ CLEANUP:
+ ANT_ERROR("nativeJAnt_RxCallback: Exiting due to failure");
+ if (jAntRxMsg != NULL)
+ {
+ env->DeleteLocalRef(jAntRxMsg);
+ }
+
+ if (env->ExceptionOccurred())
+ {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+
+ g_jVM->DetachCurrentThread();
+
+ return;
+ }
+
+ void nativeJAnt_StateCallback(ANTRadioEnabledStatus uiNewState)
+ {
+ JNIEnv* env = NULL;
+ jint jNewState = uiNewState;
+ ANT_BOOL iShouldDetach = ANT_FALSE;
+ ANT_FUNC_START();
+
+ g_jVM->GetEnv((void**) &env, JNI_VERSION_1_4);
+ if (env == NULL)
+ {
+ ANT_DEBUG_D("nativeJAnt_StateCallback: called from rx thread, attaching to VM");
+ g_jVM->AttachCurrentThread((&env), NULL);
+ if (env == NULL)
+ {
+ ANT_DEBUG_E("nativeJAnt_StateCallback: failed to attach rx thread to VM");
+ return;
+ }
+ iShouldDetach = ANT_TRUE;
+ }
+ else
+ {
+ ANT_DEBUG_D("nativeJAnt_StateCallback: called from java enable/disable"
+ ", already attached, don't detach");
+ }
+
+ ANT_DEBUG_V("nativeJAnt_StateCallback: Calling java state callback");
+ env->CallStaticVoidMethod(g_sJClazz, g_sMethodId_nativeCb_AntStateChange, jNewState);
+ ANT_DEBUG_V("nativeJAnt_StateCallback: Called java state callback");
+
+ if (env->ExceptionOccurred())
+ {
+ ANT_ERROR("nativeJAnt_StateCallback: Calling Java nativeCb_AntStateChange failed");
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+
+ if (iShouldDetach)
+ {
+ ANT_DEBUG_D("nativeJAnt_StateCallback: env was attached, detaching");
+ g_jVM->DetachCurrentThread();
+ }
+
+ ANT_FUNC_END();
+ return;
+ }
+}
+
+static JNINativeMethod g_sMethods[] =
+{
+ /* name, signature, funcPtr */
+ {"nativeJAnt_Create", "()I", (void*)nativeJAnt_Create},
+ {"nativeJAnt_Destroy", "()I", (void*)nativeJAnt_Destroy},
+ {"nativeJAnt_Enable", "()I", (void*)nativeJAnt_Enable},
+ {"nativeJAnt_Disable", "()I", (void*)nativeJAnt_Disable},
+ {"nativeJAnt_GetRadioEnabledStatus", "()I", (void*)nativeJAnt_GetRadioEnabledStatus},
+ {"nativeJAnt_TxMessage","([B)I", (void*)nativeJAnt_TxMessage},
+ {"nativeJAnt_HardReset", "()I", (void *)nativeJAnt_HardReset}
+};
+
+jint JNI_OnLoad(JavaVM* vm, void* reserved) {
+ ANT_FUNC_START();
+ (void)reserved; //unused warning
+
+ g_jVM = vm;
+ if (g_jVM->GetEnv((void**) &g_jEnv, JNI_VERSION_1_4) != JNI_OK) {
+ ANT_ERROR("GetEnv failed");
+ return -1;
+ }
+ if (NULL == g_jEnv) {
+ ANT_ERROR("env is null");
+ return -1;
+ }
+
+ g_sJClazz = g_jEnv->FindClass("com/dsi/ant/core/JAntJava");
+ if (NULL == g_sJClazz) {
+ ANT_ERROR("could not find class \"com/dsi/ant/core/JAntJava\"");
+ return -1;
+ }
+
+ /* Save class information in global reference to prevent class unloading */
+ g_sJClazz = (jclass)g_jEnv->NewGlobalRef(g_sJClazz);
+
+ if (g_jEnv->RegisterNatives(g_sJClazz, g_sMethods, NELEM(g_sMethods)) != JNI_OK) {
+ ANT_ERROR("failed to register methods");
+ return -1;
+ }
+
+ g_sMethodId_nativeCb_AntRxMessage = g_jEnv->GetStaticMethodID(g_sJClazz,
+ "nativeCb_AntRxMessage", "([B)V");
+ if (NULL == g_sMethodId_nativeCb_AntRxMessage) {
+ ANT_ERROR("VerifyMethodId: Failed getting method id of \"void nativeCb_AntRxMessage(byte[])\"");
+ return -1;
+ }
+
+ g_sMethodId_nativeCb_AntStateChange = g_jEnv->GetStaticMethodID(g_sJClazz,
+ "nativeCb_AntStateChange", "(I)V");
+ if (NULL == g_sMethodId_nativeCb_AntStateChange) {
+ ANT_ERROR("VerifyMethodId: Failed getting method id of \"void nativeCb_AntStateChange(int)\"");
+ return -1;
+ }
+
+ ANT_FUNC_END();
+ return JNI_VERSION_1_4;
+}
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..0dafa6b
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,5 @@
+ANT Android System Package
+Copyright 2009-2012 Dynastream Innovations
+
+This product includes software developed at
+Dynastream Innovations (http://www.dynastream.com/). \ No newline at end of file
diff --git a/README.md b/README.md
index 5d4d917..2d7f30d 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,2 @@
-Linux_commandline-app
+Linux ANT HAL library
===================== \ No newline at end of file
diff --git a/app/ant_app.c b/app/ant_app.c
new file mode 100644
index 0000000..b0090ba
--- /dev/null
+++ b/app/ant_app.c
@@ -0,0 +1,326 @@
+/*
+ * ANT Stack testing appication
+ *
+ * Copyright 2009 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.
+ */
+
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <pthread.h>
+#include <string.h>
+#include <errno.h>
+#include <math.h>
+#include <signal.h>
+
+#include "ant_native.h"
+#include "ant_types.h"
+#include "ant_log.h"
+#undef LOG_TAG
+#define LOG_TAG "antradio_app"
+
+/* transient stage */
+typedef ANTStatus ant_status;
+
+void app_ANT_rx_callback(ANT_U8 ucLen, ANT_U8* pucData);
+void app_ANT_state_callback(ANTRadioEnabledStatus uiNewState);
+
+static int Ant_Create(void)
+{
+ ANTStatus antStatus;
+
+ //register_antsig_handlers();
+
+ antStatus = ant_init();
+ if (antStatus)
+ {
+ printf("failed to init ANT rx stacki\n");
+ goto CLEANUP;
+ }
+
+ antStatus = set_ant_rx_callback(app_ANT_rx_callback);
+ if (antStatus)
+ {
+ printf("failed to set ANT rx callback");
+ goto CLEANUP;
+ }
+
+ antStatus = set_ant_state_callback(app_ANT_state_callback);
+ if (antStatus)
+ {
+ printf("failed to set ANT rx callback");
+ goto CLEANUP;
+ }
+ return antStatus;
+
+CLEANUP:
+ return ANT_STATUS_FAILED;
+}
+
+void ProcessCommand(char cCmd)
+{
+ ANT_U8 TxMessage[256];
+ switch (cCmd)
+ {
+ case 'V':
+ TxMessage[0] = 0x02; //Size
+ TxMessage[1] = 0x4D; //MESG_REQUEST_ID
+ TxMessage[2] = 0x00; //Ch0
+ TxMessage[3] = 0x3E;
+ ant_tx_message(4,TxMessage);
+ break;
+ case 'R':
+ TxMessage[0] = 0x01; //Size
+ TxMessage[1] = 0x4A; //MESG_RESET_ID
+ TxMessage[2] = 0x00; //Ch0
+ ant_tx_message(3,TxMessage);
+ break;
+ case 'K':
+ printf("Hard Reset returned: %d\n", ant_radio_hard_reset());
+ break;
+
+ case 'H':
+ //Normally we will not blindly send commands like this and actually check for responses before sending the next command, but this is just for a quick test.
+ ProcessCommand('R'); //Reset chip
+ ProcessCommand('A'); //Assign channel
+ ProcessCommand('F'); //Set RF Freq
+ ProcessCommand('I'); //Set Channel ID
+ ProcessCommand('P'); //Set Channel Period
+ ProcessCommand('O'); //Open Channel
+ break;
+
+ case 'A':
+ TxMessage[0] = 0x03; //Size
+ TxMessage[1] = 0x42; //MESG_ASSIGN_ID
+ TxMessage[2] = 0x00; //Ch0
+ TxMessage[3] = 0x00; //Assignment Params (Rx channel)
+ TxMessage[4] = 0x01; //Network 1 (ANT+)
+ ant_tx_message(5,TxMessage);
+ break;
+
+ case 'F':
+ TxMessage[0] = 0x02; //Size
+ TxMessage[1] = 0x45; //MESG_CHANNEL_RADIO_FREQ_ID
+ TxMessage[2] = 0x00; //Ch0
+ TxMessage[3] = 57; //2.457GHz
+ ant_tx_message(4,TxMessage);
+ break;
+
+ case 'I':
+ TxMessage[0] = 0x05; //Size
+ TxMessage[1] = 0x51; //MESG_CHANNEL_ID_ID
+ TxMessage[2] = 0x00; //Ch0
+ TxMessage[3] = 0x00; //Wildcard Device Number
+ TxMessage[4] = 0x00; //Wildcard Device Number
+ TxMessage[5] = 0x78; //Set HRM Device Type
+ TxMessage[6] = 0x00; //Wildcard Transmission Type
+ ant_tx_message(7,TxMessage);
+ break;
+
+ case 'P':
+ TxMessage[0] = 0x03; //Size
+ TxMessage[1] = 0x43; //MESG_CHANNEL_MESG_PERIOD_ID
+ TxMessage[2] = 0x00; //Ch0
+ TxMessage[3] = 0x86; //
+ TxMessage[4] = 0x1F; // HRM MESG Peroid 0x1F86 (8070)
+ ant_tx_message(5,TxMessage);
+ break;
+
+ case 'O':
+ TxMessage[0] = 0x01; //Size
+ TxMessage[1] = 0x4B; //MESG_OPEN_CHANNEL__ID
+ TxMessage[2] = 0x00; //Ch0
+ ant_tx_message(3,TxMessage);
+ break;
+ case 'E':
+ printf("Enable returned: %d\n", ant_enable_radio());
+ break;
+ case 'D':
+ printf("Disable returned: %d\n", ant_disable_radio());
+ break;
+ case 'S':
+ printf("State is: %d\n", ant_radio_enabled_status());
+ break;
+ case '1':
+ TxMessage[0] = 0x0A; //Size
+ TxMessage[1] = 0x01; //Enable
+ TxMessage[2] = 0x00; //Code upload
+ TxMessage[3] = 0x00;
+ TxMessage[4] = 0x00;
+ TxMessage[5] = 0x00;
+ TxMessage[6] = 0x00;
+ TxMessage[7] = 0x00;
+ TxMessage[8] = 0x00;
+ TxMessage[9] = 0x00;
+ TxMessage[10] = 0x00;
+ //ANT_CORE_Send_VS_Command(0xFDD0, 11, TxMessage);
+ printf("Not Implemented\n");
+ break;
+
+ case '2':
+ TxMessage[0] = 0x00; //Size
+ //ANT_CORE_Send_VS_Command(0xFF22, 1, TxMessage);
+ printf("Not Implemented\n");
+ break;
+
+
+ case 'X':
+ printf("Exiting\n");
+ break;
+
+ default:
+ printf("Invalid command: %#02x\n", cCmd);
+ break;
+ }
+}
+
+
+void app_ANT_rx_callback(ANT_U8 ucLen, ANT_U8* pucData)
+{
+ ANT_U8 i;
+
+ for(i=0; i <ucLen; i++)
+ printf("[%02X]",pucData[i]);
+ switch (pucData[1])
+ {
+ case 0x3E:
+ printf(" ANT FW Version:%s\n", &(pucData[2]));
+ break;
+ case 0x6F:
+ printf(" Chip Reset\n");
+ break;
+ case 0x40:
+ if (pucData[3] != 0x01)
+ {
+ printf(" Response (Ch:%d Mesg:%02X) ", pucData[2], pucData[3]);
+ if (pucData[4] == 0)
+ printf("Success\n");
+ else
+ printf("Error - %02X\n", pucData[4]);
+ }
+ else
+ {
+ printf(" Event (Ch:%d) %02X\n", pucData[2], pucData[4]);
+ }
+ break;
+ case 0x4E:
+ if (pucData[2] == 0) //we are using channel 0 for HRM
+ {
+ // We are just assuming this is a HRM message and pulling the BPM out, refer to the ANT+ HRM profile documentation for proper/complete decoding instructions.
+ printf(" BPM: %u\n", pucData[10]);
+ }
+ break;
+
+ default:
+
+ break;
+ }
+ return;
+}
+
+void app_ANT_state_callback(ANTRadioEnabledStatus uiNewState)
+{
+ const char *pcState;
+ switch (uiNewState) {
+ case RADIO_STATUS_UNKNOWN:
+ pcState = "UNKNOWN";
+ break;
+ case RADIO_STATUS_ENABLING:
+ pcState = "ENABLING";
+ break;
+ case RADIO_STATUS_ENABLED:
+ pcState = "ENABLED";
+ break;
+ case RADIO_STATUS_DISABLING:
+ pcState = "DISABLING";
+ break;
+ case RADIO_STATUS_DISABLED:
+ pcState = "DISABLED";
+ break;
+ case RADIO_STATUS_NOT_SUPPORTED:
+ pcState = "NOT SUPPORTED";
+ break;
+ case RADIO_STATUS_SERVICE_NOT_INSTALLED:
+ pcState = "SERVICE NOT INSTALLED";
+ break;
+ case RADIO_STATUS_SERVICE_NOT_CONNECTED:
+ pcState = "SERVICE NOT CONNECTED";
+ break;
+ case RADIO_STATUS_RESETTING:
+ pcState = "RESETTING";
+ break;
+ case RADIO_STATUS_RESET:
+ pcState = "RESET";
+ break;
+ default:
+ printf("State change to: %d is an undefined state\n", uiNewState);
+ return;
+ }
+ printf("State change to: %s\n", pcState);
+}
+
+int main(void)
+{
+ char buffer[1024];
+ int ret = 0;
+
+ if (Ant_Create())
+ {
+ printf("failed to init ANT\n");
+ goto out;
+ }
+
+ printf("===ANT Test===\n");
+ printf("Using libantradio version:\n");
+ printf("%s\n", ant_get_lib_version());
+ printf("\n");
+ printf("Press V to get Version\n");
+ printf("Press R to Reset\n");
+ printf("Press K to hard reset\n");
+ printf("Press H to setup an ANT+ HRM rx channel\n");
+ printf("\n");
+ printf("Press A to Assign channel\n");
+ printf("Press F to set radio Frequency\n");
+ printf("Press I to set channel Id\n");
+ printf("Press P to set channel Peroid\n");
+ printf("Press O to Open channel\n");
+ printf("\n");
+ printf("Press E to Enable ANT\n");
+ printf("Press D to Disable ANT\n");
+ printf("Press S to get State\n");
+ printf("\n");
+ printf("Press X to eXit\n");
+
+ while (1)
+ {
+ memset(&buffer,0,sizeof(buffer));
+ fgets(buffer, sizeof(buffer), stdin);
+ ProcessCommand(buffer[0]);
+ if (buffer[0] == 'X')
+ goto done;
+ }
+
+done:
+ ProcessCommand('R');
+ sleep(1);
+ ProcessCommand('D');
+ ant_deinit();
+
+
+out:
+ return ret;
+}
+
diff --git a/app/ant_app.h b/app/ant_app.h
new file mode 100644
index 0000000..1806975
--- /dev/null
+++ b/app/ant_app.h
@@ -0,0 +1,25 @@
+/*
+ * ANT Stack
+ *
+ * Copyright 2009 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.
+ */
+
+
+#ifndef __ANT_APP_H
+#define __ANT_APP_H
+
+
+
+#endif
diff --git a/src/bluez_hci/Android.mk b/src/bluez_hci/Android.mk
new file mode 100644
index 0000000..0320a39
--- /dev/null
+++ b/src/bluez_hci/Android.mk
@@ -0,0 +1,67 @@
+#
+# Copyright (C) 2009 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.
+#
+
+ifeq ($(BOARD_ANT_WIRELESS_DEVICE),"wl12xx")
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_CFLAGS := -g -c -W -Wall -O2
+
+# Check which chip is used so correct values in messages
+ifeq ($(BOARD_ANT_WIRELESS_DEVICE),"wl12xx")
+LOCAL_CFLAGS += -DBOARD_ANT_DEVICE_WILINK
+endif # BOARD_ANT_WIRELESS_DEVICE = wl12xx
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/../common/inc \
+ $(LOCAL_PATH)/inc \
+ system/bluetooth/bluez-clean-headers \
+
+ifeq ($(BOARD_ANT_WIRELESS_POWER),"bluedroid")
+LOCAL_CFLAGS += -DBOARD_HAVE_ANT_WIRELESS
+LOCAL_C_INCLUDES += system/bluetooth/bluedroid/include/bluedroid
+endif # BOARD_ANT_WIRELESS_POWER = bluedroid
+
+LOCAL_C_INCLUDE += $(JNI_H_INCLUDE)
+
+LOCAL_SRC_FILES := \
+ ../../JAntNative.cpp \
+ ../common/ant_utils.c \
+ ant_native_hci.c \
+ ant_rx.c \
+ ant_tx.c \
+
+# jni
+LOCAL_SHARED_LIBRARIES += \
+ libnativehelper \
+
+# chip power
+LOCAL_SHARED_LIBRARIES += \
+ libbluedroid \
+
+# logging
+LOCAL_SHARED_LIBRARIES += \
+ libcutils \
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE := libantradio
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif # BOARD_ANT_WIRELESS_DEVICE = "wl12xx"
+
diff --git a/src/bluez_hci/ant_native_hci.c b/src/bluez_hci/ant_native_hci.c
new file mode 100644
index 0000000..4650f62
--- /dev/null
+++ b/src/bluez_hci/ant_native_hci.c
@@ -0,0 +1,823 @@
+/*
+* ANT Stack
+*
+* Copyright 2009 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_hci.c
+*
+* BRIEF:
+* This file provides the HCI implementation of ant_native.h
+*
+*
+\******************************************************************************/
+
+#include <pthread.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "antradio_power.h"
+
+#include "ant_types.h"
+#include "ant_native.h"
+#include "ant_utils.h"
+#include "ant_version.h"
+
+#include "ant_rx.h"
+#include "ant_tx.h"
+#include "ant_hciutils.h"
+#include "ant_log.h"
+
+static pthread_mutex_t txLock;
+pthread_mutex_t enableLock;
+
+static ANTRadioEnabledStatus radio_status = RADIO_STATUS_DISABLED;
+ANTRadioEnabledStatus get_and_set_radio_status(void);
+
+////////////////////////////////////////////////////////////////////
+// ant_init
+//
+// Initialises the native environment.
+//
+// Parameters:
+// -
+//
+// Returns:
+// Success:
+// ANT_STATUS_SUCCESS
+// Failures:
+// ANT_STATUS_FAILED if could not initialize mutex
+//
+// Psuedocode:
+/*
+LOCK antdevice_LOCK
+ CREATE mutex for locking Tx attempt
+ IF could not create mutex
+ RESULT = ANT_STATUS_FAILED
+ ELSE
+ CREATE mutex for locking enable/disable
+ IF could not create mutex
+ RESULT = ANT_STATUS_FAILED
+ ELSE
+ RESULT = ANT_STATUS_SUCCESS
+ ENDIF
+ ENDIF
+UNLOCK
+*/
+////////////////////////////////////////////////////////////////////
+ANTStatus ant_init(void)
+{
+ int mutexResult;
+ ANTStatus status = ANT_STATUS_FAILED;
+ ANT_FUNC_START();
+
+ mutexResult = pthread_mutex_init(&txLock, NULL); //use default attr
+ if (mutexResult)
+ {
+ ANT_ERROR("Tx Lock mutex initialization failed: %s", strerror(mutexResult));
+ }
+ else
+ {
+ mutexResult = pthread_mutex_init(&enableLock, NULL);
+ if (mutexResult)
+ {
+ ANT_ERROR("Enable Lock mutex init failed %s", strerror(mutexResult));
+ }
+ else
+ {
+ status = ANT_STATUS_SUCCESS;
+ }
+ }
+
+ ANT_FUNC_END();
+ return status;
+}
+
+
+////////////////////////////////////////////////////////////////////
+// ant_deinit
+//
+// De-initialises the native environment.
+//
+// Parameters:
+// -
+//
+// Returns:
+// Success:
+// ANT_STATUS_SUCCESS
+// Failures:
+// ANT_STATUS_FAILED if could not de-initialize mutex
+//
+// Psuedocode:
+/*
+LOCK antdevice_LOCK (also Init and Tx)
+ DESTROY mutex for locking Tx attempt
+ IF could not destroy mutex
+ RESULT = ANT_STATUS_FAILED
+ ELSE
+ DESTROY mutex for locking enable/disable
+ IF coult not destroy mutex
+ RESULT = ANT_STATUS_FAILED
+ ELSE
+ RESULT = ANT_STATUS_SUCCESS
+ ENDIF
+ ENDIF
+UNLOCK
+*/
+////////////////////////////////////////////////////////////////////
+ANTStatus ant_deinit(void)
+{
+ int mutexResult;
+ ANTStatus result_status = ANT_STATUS_FAILED;
+ ANT_FUNC_START();
+
+ mutexResult = pthread_mutex_destroy(&txLock);
+ if (mutexResult)
+ {
+ ANT_ERROR("Tx Lock mutex destroy failed: %s", strerror(mutexResult));
+ }
+ else
+ {
+ mutexResult = pthread_mutex_destroy(&enableLock);
+ if (mutexResult)
+ {
+ ANT_ERROR("Enable Lock mutex destroy failed: %s", strerror(mutexResult));
+ }
+ 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
+// On Android this is in the Bluedroid module.
+// On Linux this is device specific
+//
+// 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
+ LOCK tx_LOCK
+ IF state is not enabled
+ STATE = ENABLING
+ ENDIF
+ ant enable
+ IF ant_enable success
+ IF rx thread is running
+ STATE = ENABLED
+ RESULT = SUCCESS
+ ELSE
+ start rx thread
+ IF starting rx thread fails
+ ant disable
+ get state
+ IF state is enabled
+ log a serious error
+ ENDIF
+ RESULT = FAILED
+ ELSE
+ STATE = ENABLED
+ RESULT = SUCCESS
+ ENDIF
+ ENDIF
+ ELSE
+ get state
+ IF state is enabled
+ log a serious error
+ ENDIF
+ RESULT = FAILURE
+ ENDIF
+ UNLOCK
+UNLOCK
+*/
+////////////////////////////////////////////////////////////////////
+ANTStatus ant_enable_radio(void)
+{
+ int result;
+ int lockResult;
+ ANTStatus result_status = ANT_STATUS_FAILED;
+ ANT_FUNC_START();
+
+ ANT_DEBUG_V("getting enableLock in %s", __FUNCTION__);
+ lockResult = pthread_mutex_lock(&enableLock);
+ if(lockResult)
+ {
+ ANT_ERROR("Enable failed to get enableLock mutex: %s", strerror(lockResult));
+ return ANT_STATUS_FAILED;
+ }
+ ANT_DEBUG_V("got enableLock in %s", __FUNCTION__);
+
+ ANT_DEBUG_V("getting txLock in %s", __FUNCTION__);
+ lockResult = pthread_mutex_lock(&txLock);
+ if (lockResult)
+ {
+ ANT_ERROR("Enable txLock failed: %s", strerror(lockResult));
+ pthread_mutex_unlock(&enableLock);
+ return ANT_STATUS_FAILED;
+ }
+ ANT_DEBUG_V("got txLock in %s", __FUNCTION__);
+
+ if (get_and_set_radio_status() != RADIO_STATUS_ENABLED)
+ {
+ if (RxParams.thread)
+ {
+ ANT_WARN("in enable call: rx thread still exists but radio crashed. trying to recover");
+ ANT_DEBUG_V("radio crashed, letting rx thread join");
+ pthread_join(RxParams.thread, NULL);
+ RxParams.thread = 0;
+ ANT_DEBUG_V("recovered. joined by rx thread");
+ }
+ ANT_DEBUG_I("radio_status (%d -> %d)", radio_status, RADIO_STATUS_ENABLING);
+ radio_status = RADIO_STATUS_ENABLING;
+
+ if (RxParams.pfStateCallback)
+ RxParams.pfStateCallback(radio_status);
+ }
+
+ result = ant_enable();
+ ANT_DEBUG_D("ant_enable() result is %d", result);
+ if (result == 0)
+ {
+ if (RxParams.thread)
+ {
+ result_status = ANT_STATUS_SUCCESS;
+ radio_status = RADIO_STATUS_ENABLED; // sanity assign, cant be enabling
+ ANT_DEBUG_D("ANT radio re-enabled");
+ }
+ else
+ {
+ result = pthread_create(&RxParams.thread, NULL, ANTHCIRxThread, NULL);
+ if (result)
+ {
+ ANT_ERROR("Thread initialization failed: %s", strerror(result));
+ result_status = ANT_STATUS_FAILED;
+ }
+ else
+ {
+ result_status = ANT_STATUS_SUCCESS;
+ if (radio_status == RADIO_STATUS_ENABLING)
+ {
+ ANT_DEBUG_I("radio_status (%d -> %d)", radio_status, RADIO_STATUS_ENABLED);
+ radio_status = RADIO_STATUS_ENABLED;
+
+ if (RxParams.pfStateCallback)
+ RxParams.pfStateCallback(radio_status);
+ }
+ else
+ {
+ ANT_WARN("radio was already enabled but rx thread was not running");
+ }
+ }
+ }
+ }
+ else
+ {
+ result_status = ANT_STATUS_TRANSPORT_INIT_ERR;
+ }
+
+ if (result_status != ANT_STATUS_SUCCESS)
+ {
+ ant_disable();
+
+ switch (get_and_set_radio_status())
+ {
+ case RADIO_STATUS_ENABLED:
+ ANT_ERROR("SERIOUS: enable failed, but ANT is enabled without a rx thread");
+ break;
+ default:
+ ANT_DEBUG_D("Enable failed, after cleanup chip is not enabled");
+ break;
+ }
+ }
+
+ ANT_DEBUG_V("releasing txLock in %s", __FUNCTION__);
+ pthread_mutex_unlock(&txLock);
+ ANT_DEBUG_V("released txLock in %s", __FUNCTION__);
+
+ ANT_DEBUG_V("releasing enableLock in %s", __FUNCTION__);
+ pthread_mutex_unlock(&enableLock);
+ ANT_DEBUG_V("released enableLock in %s", __FUNCTION__);
+
+ ANT_FUNC_END();
+ return result_status;
+}
+
+ANTStatus ant_radio_hard_reset(void)
+{
+ ANTStatus result_status = ANT_STATUS_NOT_SUPPORTED;
+ ANT_FUNC_START();
+ ANT_FUNC_END();
+ return result_status;
+}
+
+////////////////////////////////////////////////////////////////////
+// ant_disable_radio
+//
+// Disables the HCI transport and powers off the ANT part.
+//
+// Parameters:
+// -
+//
+// Returns:
+// Success:
+// ANT_STATUS_SUCCESS
+// Failures:
+// ANT_STATUS_FAILED if could not get mutex
+// ANT_STATUS_NOT_DE_INITIALIZED if ant_disable failed
+//
+// Psuedocode:
+/*
+LOCK enable_LOCK
+ LOCK tx_LOCK
+ IF not disabled
+ STATE = DISABLING
+ ENDIF
+ ant disable
+ IF rx thread is running
+ wait for rx thread to terminate
+ ENDIF
+ get radio status
+ IF radio is disabled
+ RESULT = SUCCESS
+ ELSE IF radio is enabled
+ log a serious error
+ RESULT = FAILURE
+ ELSE
+ RESULT = FAILURE
+ ENDIF
+ UNLOCK
+UNLOCK
+*/
+////////////////////////////////////////////////////////////////////
+ANTStatus ant_disable_radio(void)
+{
+ int result;
+ int lockResult;
+ ANTStatus ret = ANT_STATUS_FAILED;
+ ANT_FUNC_START();
+
+ ANT_DEBUG_V("getting enableLock in %s", __FUNCTION__);
+ lockResult = pthread_mutex_lock(&enableLock);
+ if(lockResult)
+ {
+ ANT_ERROR("Disable failed to get enableLock mutex: %s", strerror(lockResult));
+ return ANT_STATUS_FAILED;
+ }
+ ANT_DEBUG_V("got enableLock in %s", __FUNCTION__);
+
+ ANT_DEBUG_V("getting txLock in %s", __FUNCTION__);
+ lockResult = pthread_mutex_lock(&txLock);
+ if (lockResult)
+ {
+ ANT_ERROR("Disable txLock failed: %s", strerror(lockResult));
+ pthread_mutex_unlock(&enableLock);
+ return ANT_STATUS_FAILED;
+ }
+ ANT_DEBUG_V("got txLock in %s", __FUNCTION__);
+
+ if (get_and_set_radio_status() != RADIO_STATUS_DISABLED)
+ {
+ ANT_DEBUG_I("radio_status (%d -> %d)", radio_status, RADIO_STATUS_DISABLING);
+ radio_status = RADIO_STATUS_DISABLING;
+
+ if (RxParams.pfStateCallback)
+ RxParams.pfStateCallback(radio_status);
+ }
+
+ result = ant_disable();
+ ANT_DEBUG_D("ant_disable() result is %d", result);
+
+ // If rx thread exists ( != 0)
+ if (RxParams.thread)
+ {
+ ANT_DEBUG_V("quit rx thread, joining");
+ pthread_join(RxParams.thread, NULL);
+ RxParams.thread = 0;
+ ANT_DEBUG_V("joined by rx thread");
+ }
+ else
+ {
+ ANT_DEBUG_W("rx thread is 0 (not created?)");
+ }
+
+ switch (get_and_set_radio_status())
+ {
+ case RADIO_STATUS_DISABLED:
+ ret = ANT_STATUS_SUCCESS;
+ break;
+ case RADIO_STATUS_ENABLED:
+ ANT_ERROR("SERIOUS: ANT was disabled, rx thread quit, but ANT is enabled");
+ ret = ANT_STATUS_FAILED;
+ break;
+ default:
+ ret = ANT_STATUS_NOT_DE_INITIALIZED;
+ break;
+ }
+
+ ANT_DEBUG_V("releasing txLock in %s", __FUNCTION__);
+ pthread_mutex_unlock(&txLock);
+ ANT_DEBUG_V("released txLock in %s", __FUNCTION__);
+
+ ANT_DEBUG_V("releasing enableLock in %s", __FUNCTION__);
+ pthread_mutex_unlock(&enableLock);
+ ANT_DEBUG_V("released enableLock in %s", __FUNCTION__);
+
+ ANT_FUNC_END();
+ return ret;
+}
+
+
+////////////////////////////////////////////////////////////////////
+// ant_radio_enabled_status
+//
+// Returns if the chip/transport is disabled/disabling/enabling/enabled. This
+// function will NOT overwrite internal state variable enabling or disabling.
+// It will call get_and_set_radio_status() if not enabling/disabling which can
+// change internal state on errors.
+//
+// Parameters:
+// -
+//
+// Returns:
+// The current radio status (ANTRadioEnabledStatus)
+//
+// Psuedocode:
+/*
+IF Enabling
+ RESULT = Enabling
+ELSE IF Disabling
+ RESULT = Disabling
+ELSE
+ IF ant_is_enabled
+ Enabled
+ RESULT = Enabled
+ ELSE
+ Disabled
+ RESULT = Disabled
+ ENDIF
+ENDIF
+*/
+////////////////////////////////////////////////////////////////////
+ANTRadioEnabledStatus ant_radio_enabled_status(void)
+{
+ ANT_FUNC_START();
+
+ if ((RADIO_STATUS_ENABLING != radio_status) &&
+ (RADIO_STATUS_DISABLING != radio_status))
+ {
+ get_and_set_radio_status();
+ }
+
+ ANT_FUNC_END();
+ return radio_status;
+}
+
+////////////////////////////////////////////////////////////////////
+// get_and_set_radio_status
+//
+// Returns if the chip/transport is disabled/enabled/unknown This function WILL
+// overwrite what it thinks the state is with what the BlueZ core (kernel)
+// thinks it is. It will overwrite enabling or disabling states, and might
+// change internal state from enabled, disabled, or unknown to any of these
+// three on errors.
+//
+// Paramerters:
+// -
+//
+// Returns:
+// The current radio status (ANTRadioEnabledStatus)
+//
+////////////////////////////////////////////////////////////////////
+ANTRadioEnabledStatus get_and_set_radio_status(void)
+{
+ ANTRadioEnabledStatus orig_status = radio_status;
+ ANT_FUNC_START();
+
+ switch (ant_is_enabled())
+ {
+ case 0:
+ radio_status = RADIO_STATUS_DISABLED;
+ break;
+ case 1:
+ radio_status = RADIO_STATUS_ENABLED;
+ break;
+ default:
+ ANT_ERROR("getting chip state returned an error");
+ radio_status = RADIO_STATUS_UNKNOWN;
+ break;
+ }
+ if (orig_status != radio_status)
+ {
+ ANT_DEBUG_I("radio_status (%d -> %d)", orig_status, radio_status);
+
+ if (RxParams.pfStateCallback)
+ RxParams.pfStateCallback(radio_status);
+ }
+
+ ANT_FUNC_END();
+ return radio_status;
+}
+
+////////////////////////////////////////////////////////////////////
+// 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 recieved messages.
+//
+// Returns:
+// ANT_STATUS_SUCCESS
+//
+// Psuedocode:
+/*
+ Rx Callback = rx_callback_func
+*/
+////////////////////////////////////////////////////////////////////
+ANTStatus set_ant_rx_callback(ANTNativeANTEventCb rx_callback_func)
+{
+ ANTStatus status = ANT_STATUS_SUCCESS;
+
+ ANT_FUNC_START();
+
+ RxParams.pfRxCallback = rx_callback_func;
+
+ 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 recieved 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();
+
+ RxParams.pfStateCallback = state_callback_func;
+
+ ANT_FUNC_END();
+
+ return status;
+}
+
+////////////////////////////////////////////////////////////////////
+// ant_tx_message
+//
+// Sends an 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 = NOT ENABLED
+ELSE
+ Lock
+ IF Lock failed
+ RESULT = FAILED
+ ELSE
+ STORE length (little endian) in send buffer
+ STORE data in send buffer
+ ENDIF
+ENDIF
+*/
+////////////////////////////////////////////////////////////////////
+ANTStatus ant_tx_message(ANT_U8 ucLen, ANT_U8 *pucMesg)
+{
+ ANTStatus status;
+
+ /* Socket for sending HCI commands */
+ int tx_socket = -1;
+
+ int lockResult;
+
+ ANT_FUNC_START();
+
+ ANT_DEBUG_V("getting txLock in %s", __FUNCTION__);
+ lockResult = pthread_mutex_lock(&txLock);
+ if (lockResult)
+ {
+ ANT_ERROR("ant_tx_message, could not get txLock: %s", strerror(lockResult));
+ return ANT_STATUS_FAILED;
+ }
+
+ ANT_DEBUG_V("got txLock in %s", __FUNCTION__);
+
+ if(RADIO_STATUS_ENABLED != get_and_set_radio_status())
+ {
+ ANT_DEBUG_E("ant_tx_message, ANT not enabled - ABORTING. Radio status = %d",
+ radio_status);
+ ANT_DEBUG_V("releasing txLock in %s", __FUNCTION__);
+ pthread_mutex_unlock(&txLock);
+ ANT_DEBUG_V("released txLock in %s", __FUNCTION__);
+ return ANT_STATUS_FAILED_BT_NOT_INITIALIZED;
+ }
+
+ // Open socket
+ tx_socket = ant_open_tx_transport();
+
+ if(tx_socket < 0)
+ {
+ ANT_ERROR("Could not open Tx socket");
+ ANT_DEBUG_V("releasing txLock in %s", __FUNCTION__);
+ pthread_mutex_unlock(&txLock);
+ ANT_DEBUG_V("released txLock in %s", __FUNCTION__);
+ return ANT_STATUS_FAILED;
+ }
+
+ // Send HCI packet
+ ANT_BOOL retryRx;
+ ANT_BOOL retryTx;
+ status = ANT_STATUS_FAILED;
+
+ int MAX_RETRIES_WRITE_FAIL = 10;
+ int MAX_RETRY_TIME_SECS = 10;
+ int commandWriteFailRetries = 0;
+
+ // Start New timed retry code:
+ time_t startTime = time(NULL);
+ time_t endTime = 0;
+ if((time_t)-1 != startTime)
+ {
+ endTime = startTime + MAX_RETRY_TIME_SECS;
+ }
+ else
+ {
+ ANT_ERROR("failed to get current time");
+ }
+
+ do // while (retryTx)
+ {
+ retryTx = ANT_FALSE;
+
+ if(ANT_STATUS_SUCCESS == write_data(pucMesg, ucLen))
+ {
+ do // while (retryRx)
+ {
+ retryRx = ANT_FALSE;
+
+ if(ANT_TRUE == wait_for_message(tx_socket))
+ {
+ ANT_DEBUG_D("New HCI data available, reading...");
+
+ status = get_command_complete_result(tx_socket);
+ switch (status)
+ {
+ case ANT_STATUS_NO_VALUE_AVAILABLE:
+ {
+ ANT_WARN("Did not get an expected response for write, trying again");
+ retryRx = ANT_TRUE;
+ break;
+ }
+ case ANT_STATUS_FAILED:
+ {
+ ANT_ERROR("Command Complete: ANT_STATUS_FAILED");
+ break;
+ }
+ case ANT_STATUS_COMMAND_WRITE_FAILED:
+ {
+ ANT_ERROR("Command Complete: ANT_STATUS_WRITE_FAILED");
+
+ if(++commandWriteFailRetries < MAX_RETRIES_WRITE_FAIL)
+ {
+ ANT_DEBUG_D("Retrying. Retry count = %d",
+ commandWriteFailRetries);
+
+ retryTx = ANT_TRUE;
+ }
+ else
+ {
+ ANT_ERROR("Aborting. Retry count = %d. Max retries = %d",
+ commandWriteFailRetries, MAX_RETRIES_WRITE_FAIL);
+ }
+ break;
+ }
+ case ANT_STATUS_TRANSPORT_UNSPECIFIED_ERROR:
+ {
+ ANT_DEBUG_D("Command Complete: ANT_STATUS_UNSPECIFIED_ERROR");
+
+ time_t currentTime = time(NULL);
+
+ if((time_t)-1 != currentTime)
+ {
+ if(currentTime < endTime)
+ {
+ ANT_DEBUG_V("Retrying. Current time = %d. "
+ "End time = %d", (int)currentTime, (int)endTime);
+
+ retryTx = ANT_TRUE;
+ }
+ else
+ {
+ ANT_ERROR("Command Complete: ANT_STATUS_UNSPECIFIED_ERROR");
+ ANT_ERROR("Aborting. Current time = %d. End Time = %d",
+ (int)currentTime, (int)endTime);
+ }
+ }
+ else
+ {
+ ANT_ERROR("Command Complete: failed to get current time");
+ }
+
+ break;
+ }
+ case ANT_STATUS_SUCCESS:
+ {
+ break;
+ }
+ default:
+ {
+ ANT_ERROR("Unhandled command complete status");
+ break;
+ }
+ }
+ }
+ else
+ {
+ ANT_WARN("Command Complete: wait for message failed");
+ }
+ } while (retryRx);
+ }
+ else
+ {
+ ANT_ERROR("write failed");
+ retryRx = ANT_FALSE;
+
+ status = ANT_STATUS_FAILED;
+ }
+ } while(retryTx);
+
+ ant_close_tx_transport(tx_socket);
+
+ ANT_DEBUG_V("releasing txLock in %s", __FUNCTION__);
+ pthread_mutex_unlock(&txLock);
+ ANT_DEBUG_V("released txLock in %s", __FUNCTION__);
+
+ ANT_FUNC_END();
+
+ return status;
+}
+
+const char *ant_get_lib_version()
+{
+ return "libantradio.so Bluez HCI Transport Version "
+ LIBANT_STACK_MAJOR "." LIBANT_STACK_MINOR "." LIBANT_STACK_INCRE;
+}
+
diff --git a/src/bluez_hci/ant_rx.c b/src/bluez_hci/ant_rx.c
new file mode 100644
index 0000000..76d29ff
--- /dev/null
+++ b/src/bluez_hci/ant_rx.c
@@ -0,0 +1,275 @@
+/*
+ * ANT Stack
+ *
+ * Copyright 2009 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.c
+*
+* BRIEF:
+* This file Implements the receive thread for an HCI implementation
+* using Vendor Specific messages.
+*
+*
+\******************************************************************************/
+
+
+#define _GNU_SOURCE /* needed for PTHREAD_MUTEX_RECURSIVE */
+
+#include <errno.h>
+#include <poll.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <sys/resource.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/un.h>
+
+#include "antradio_power.h"
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+
+#include "ant_rx.h"
+#include "ant_hciutils.h"
+#include "ant_types.h"
+#include "ant_framing.h"
+#include "ant_log.h"
+#undef LOG_TAG
+#define LOG_TAG "antradio_rx"
+
+static char EVT_PKT_VENDOR_FILTER[] = {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x80,0x00,0x05,0x00,0x00};
+
+/* Global Options */
+ANTHCIRxParams RxParams = {
+ .pfRxCallback = NULL,
+ .pfStateCallback = NULL,
+ .thread = 0
+};
+
+extern pthread_mutex_t enableLock;
+extern ANTRadioEnabledStatus get_and_set_radio_status(void);
+/*
+ * This thread opens a Bluez HCI socket and waits for ANT messages.
+ */
+void *ANTHCIRxThread(void *pvHCIDevice)
+{
+ int ret = ANT_STATUS_SUCCESS;
+ int rxSocket;
+ int len;
+ unsigned char buf[HCI_MAX_EVENT_SIZE];
+ int result;
+ ANT_FUNC_START();
+
+ (void)pvHCIDevice; //unused waring
+
+ ANT_DEBUG_D("Entering ANTHCIRxThread");
+
+ rxSocket = create_hci_sock();
+ if (rxSocket < 0)
+ {
+ ANT_DEBUG_E("can't open HCI socket in rx thread: %s", strerror(errno));
+
+ ret = ANT_STATUS_FAILED;
+ goto out;
+ }
+
+ if (setsockopt(rxSocket, SOL_HCI, HCI_FILTER, &EVT_PKT_VENDOR_FILTER,
+ sizeof(EVT_PKT_VENDOR_FILTER)) < 0)
+ {
+ ANT_ERROR("failed to set socket options: %s", strerror(errno));
+
+ ret = ANT_STATUS_FAILED;
+ goto close;
+ }
+
+ /* continue running as long as not terminated */
+ while (get_and_set_radio_status() == RADIO_STATUS_ENABLED)
+ {
+ struct pollfd p;
+ int n;
+
+ p.fd = rxSocket;
+ p.events = POLLIN;
+
+ ANT_DEBUG_V(" RX: Polling HCI for data...");
+
+ /* poll socket, wait for ANT messages */
+ while ((n = poll(&p, 1, 2500)) == -1)
+ {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+
+ ANT_ERROR("failed to poll socket: %s", strerror(errno));
+
+ ret = ANT_STATUS_FAILED;
+ goto close;
+ }
+
+ /* we timeout once in a while */
+ /* this let's us the chance to check if we were terminated */
+ if (0 == n)
+ {
+ ANT_DEBUG_V(" RX: Timeout");
+ continue;
+ }
+
+ ANT_DEBUG_D("New HCI data available, reading...");
+
+ /* read newly arrived data */
+ /* TBD: rethink assumption about single arrival */
+ while ((len = read(rxSocket, buf, sizeof(buf))) < 0)
+ {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+
+ ANT_ERROR("failed to read socket: %s", strerror(errno));
+
+ ret = ANT_STATUS_FAILED;
+ goto close;
+ }
+
+ // 0 = packet type eg. HCI_EVENT_PKT
+ // FOR EVENT:
+ // 1 = event code eg. EVT_VENDOR, EVT_CMD_COMPLETE
+ // 2 = Parameter total length
+ // 3... parameters
+ // FOR CC
+ // 3 = Num HCI Command packets allowed to be sent
+ // 4+5 = ANT Opcode
+ // 6 = Result ??
+ // FOR VS
+ // 3+4 = ANT Opcode
+ // 5 = length
+ // 6 ? MSB of length ?
+ // 7... ant message
+
+ if (len >= 7)
+ {
+ ANT_DEBUG_V("HCI Data: [%02X][%02X][%02X][%02X][%02X][%02X][%02X]...",
+ buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+ }
+ else
+ {
+ ANT_ERROR("Failed to read full header off socket. len = %d", len);
+ continue;
+ }
+
+ if (len != (buf[2] + 3))
+ {
+ ANT_WARN("HCI packet length(%d) and bytes read(%d) dont match", buf[2] + 3, len);
+ }
+
+ if(HCI_EVENT_PKT == buf[0])
+ {
+ ANT_DEBUG_D("Received Event Packet");
+
+ if (EVT_VENDOR == buf[1])
+ {
+ if ((HCI_VSOP_ANT_LSB == buf[3]) && (HCI_VSOP_ANT_MSB == buf[4]))
+ {
+ ANT_DEBUG_D("Received ANT VS Message");
+
+ if (len < 9)
+ {
+ ANT_ERROR("Malformed ANT header");
+ ret = ANT_STATUS_FAILED;
+ goto close;
+ }
+
+ ANT_DEBUG_V("ANT Mesg: ANTMesgSize:%d ANTMesgID:0x%02X ...",
+ buf[7], buf[8]);
+
+ ANT_SERIAL(&(buf[7]), buf[5], 'R');
+
+ if(RxParams.pfRxCallback != NULL)
+ {
+ RxParams.pfRxCallback(buf[5], &(buf[7]));
+ }
+ else
+ {
+ ANT_ERROR("Can't send rx message - no callback registered");
+ }
+
+ continue;
+ }
+ else
+ {
+ ANT_DEBUG_W("Vendor Specific message for another vendor. "
+ "Should filter out");
+ }
+ }
+ else
+ {
+ ANT_DEBUG_V("Other Event Packet, Ignoring");
+ }
+ }
+ else
+ {
+ ANT_DEBUG_V("Non-Event Packet, Ignoring");
+ }
+ }
+
+close:
+ result = pthread_mutex_trylock(&enableLock);
+ ANT_DEBUG_D("rx thread close: trylock enableLock returned %d", result);
+
+ if (result == 0)
+ {
+ ANT_DEBUG_W("rx thread socket has unexpectedly crashed");
+ if (RxParams.pfStateCallback)
+ RxParams.pfStateCallback(RADIO_STATUS_DISABLING);
+ ant_disable();
+ get_and_set_radio_status();
+ RxParams.thread = 0;
+ pthread_mutex_unlock(&enableLock);
+ }
+ else if (result == EBUSY)
+ {
+ ANT_DEBUG_V("rx thread socket was closed");
+ }
+ else
+ {
+ ANT_ERROR("rx thread close: trylock failed: %s", strerror(result));
+ }
+
+ if (-1 == close(rxSocket))
+ {
+ ANT_ERROR("failed to close hci device (socket handle=%#x): %s", rxSocket, strerror(errno));
+ }
+ else
+ {
+ ANT_DEBUG_D("closed hci device (socket handle=%#x)", rxSocket);
+ }
+
+out:
+ ANT_FUNC_END();
+
+ pthread_exit((void *)ret);
+
+#if defined(ANDROID)
+ return 0;
+#endif
+}
+
diff --git a/src/bluez_hci/ant_tx.c b/src/bluez_hci/ant_tx.c
new file mode 100644
index 0000000..2757a3b
--- /dev/null
+++ b/src/bluez_hci/ant_tx.c
@@ -0,0 +1,358 @@
+/*
+ * ANT Stack
+ *
+ * Copyright 2009 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_tx.c
+*
+* BRIEF:
+* This file Implements the transmit functionality for an HCI implementation
+* using Vendor Specific messages.
+*
+*
+\******************************************************************************/
+
+#include <errno.h>
+#include <poll.h>
+#include <sys/uio.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+
+#include "ant_types.h"
+#include "ant_hciutils.h"
+#include "ant_framing.h"
+#include "ant_utils.h"
+#include "ant_log.h"
+#undef LOG_TAG
+#define LOG_TAG "antradio_tx"
+
+static char EVT_PKT_CMD_COMPLETE_FILTER[] = {0x10,0x00,0x00,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xD1,0xFD,0x00,0x00};
+
+int g_ant_cmd_socket = -1;
+
+int ant_open_tx_transport(void)
+{
+ int socket = -1;
+ ANT_FUNC_START();
+
+ socket = create_hci_sock();
+
+ if (socket < 0)
+ {
+ ANT_DEBUG_E("failed to open HCI socket for tx: %s", strerror(errno));
+ }
+ else
+ {
+ g_ant_cmd_socket = socket;
+ ANT_DEBUG_D("socket handle %#x", g_ant_cmd_socket);
+ if (setsockopt(g_ant_cmd_socket, SOL_HCI, HCI_FILTER,
+ &EVT_PKT_CMD_COMPLETE_FILTER, sizeof(EVT_PKT_CMD_COMPLETE_FILTER)) < 0)
+ {
+ ANT_ERROR("failed to set socket options: %s", strerror(errno));
+ close(socket);
+ socket = -1;
+ }
+ }
+
+ ANT_FUNC_END();
+ return socket;
+}
+
+void ant_close_tx_transport(int socket)
+{
+ ANT_FUNC_START();
+
+ if(0 < socket)
+ {
+ if (0 == close(socket))
+ {
+ ANT_DEBUG_D("closed hci device (socket handle=%#x)", socket);
+ }
+ else
+ {
+ ANT_ERROR("failed to close hci device (socket handle=%#x): %s", socket, strerror(errno));
+ }
+ }
+ else
+ {
+ ANT_DEBUG_E("requested close on socket %#x. invalid param", socket);
+ }
+
+ ANT_FUNC_END();
+}
+
+/*
+Format of an HCI WRITE command to ANT chip:
+
+HCI Header:
+----------
+- HCI Packet Type: 1 byte
+
+- HCI Opcode: 2 bytes
+ (LSB, MSB - LE)
+- HCI Parameters Total Len (total length of all subsequent fields): 1 byte
+
+HCI Parameters:
+--------------
+- VS Parameters Len (total length of ANT Mesg inculding Len/ID) 2 bytes
+ (LSB, MSB - LE)
+- ANT Mesg Len (N = number of bytes in ANT Mesg Data): 1 byte
+- ANT Mesg ID: 1 byte
+- ANT Mesg Data: N bytes
+*/
+
+ANT_BOOL wait_for_message(int socket)
+{
+ struct pollfd p;
+ int n;
+
+ ANT_BOOL bReturn = ANT_FALSE;
+ ANT_BOOL bRetry = ANT_FALSE;
+
+ ANT_FUNC_START();
+
+ p.fd = socket;
+ p.events = POLLIN;
+
+ do
+ {
+ bRetry = ANT_FALSE;
+
+ ANT_DEBUG_V(" CC: Polling HCI for data...");
+
+ /* poll socket, wait for ANT messages */
+ n = poll(&p, 1, 2500);
+ if (0 > n)
+ {
+ if (errno == EAGAIN || errno == EINTR)
+ {
+ ANT_DEBUG_W(" CC: error: %s", strerror(errno));
+ bRetry = ANT_TRUE;
+ }
+ else
+ {
+ ANT_ERROR("failed to poll socket. error: %s", strerror(errno));
+ }
+ }
+
+ /* timeout */
+ else if (0 == n)
+ {
+ ANT_ERROR("SERIOUS: Timeouted getting Command Complete");
+ }
+ else if(0 < n)
+ {
+ // There is data to read.
+ bReturn = ANT_TRUE;
+ }
+
+ } while(ANT_TRUE == bRetry);
+
+ ANT_FUNC_END();
+
+ return bReturn;
+}
+
+ANTStatus write_data(ANT_U8 ant_message[], int ant_message_len)
+{
+ ANTStatus ret = ANT_STATUS_FAILED;
+ ANT_BOOL retry = ANT_FALSE;
+ int bytes_written;
+ struct iovec iov[2];
+ hci_vendor_cmd_packet_t hci_header;
+ ANT_U16 hci_opcode;
+
+ ANT_FUNC_START();
+
+ hci_opcode = cmd_opcode_pack(OGF_VENDOR_CMD, HCI_CMD_ANT_MESSAGE_WRITE);
+
+ hci_header.packet_type = HCI_COMMAND_PKT;
+ ANT_UTILS_StoreLE16(hci_header.cmd_header.opcode, hci_opcode);
+ hci_header.cmd_header.plen = ((ant_message_len + HCI_VENDOR_HEADER_SIZE) & 0xFF);
+ ANT_UTILS_StoreLE16(hci_header.vendor_header.hcilen, ant_message_len);
+
+ iov[0].iov_base = &hci_header;
+ iov[0].iov_len = sizeof(hci_header);
+ iov[1].iov_base = ant_message;
+ iov[1].iov_len = ant_message_len;
+
+ do //while retry
+ {
+ retry = ANT_FALSE;
+
+ if (g_ant_cmd_socket < 0)
+ {
+ ANT_DEBUG_E("bad socket handle %#x", g_ant_cmd_socket);
+ return ANT_STATUS_INTERNAL_ERROR;
+ }
+
+ ANT_SERIAL(ant_message, ant_message_len, 'T');
+
+ bytes_written = writev(g_ant_cmd_socket, iov, 2);
+
+ ANT_DEBUG_D("writing to socket %#x returned %d", g_ant_cmd_socket,
+ bytes_written);
+
+// bytes_written < 0 = error (check errno)
+// bytes_written = 0 = No data written
+// bytes_written < sizeof(hci_message) = not all data written
+// bytes_written = sizeof(hci_message) = all data written
+
+ if(bytes_written < 0)
+ {
+ ANT_ERROR("write to HCI failed: %s", strerror(errno));
+
+ if (errno == EAGAIN || errno == EINTR)
+ {
+ ANT_DEBUG_D("Retrying write to HCI");
+ retry = ANT_TRUE;
+ }
+ else
+ {
+ ret = ANT_STATUS_FAILED;
+ }
+ }
+ else if(bytes_written < ((int)sizeof(hci_header) + ant_message_len))
+ {
+ ANT_DEBUG_D("Only %d bytes written to HCI.", bytes_written);
+ ret = ANT_STATUS_FAILED;
+ }
+ else
+ {
+ ANT_DEBUG_V("writev successful");
+ ret = ANT_STATUS_SUCCESS;
+ }
+ } while(retry);
+
+ ANT_FUNC_END();
+
+ return ret;
+}
+
+// Returns:
+// ANT_STATUS_NO_VALUE_AVAILABLE if not a CC packet
+// ANT_STATUS_FAILED if could not read socket or not a
+// valid length CC packet
+// ANT_STATUS_TRANSPORT_UNSPECIFIED_ERROR if CC indicates an unspecified error
+// ANT_STATUS_COMMAND_WRITE_FAILED if CC indicates a failure
+// ANT_STATUS_SUCCESS if CC indicates message was received
+ANTStatus get_command_complete_result(int socket)
+{
+ ANTStatus status = ANT_STATUS_NO_VALUE_AVAILABLE;
+ int len;
+ ANTStatus ret = ANT_STATUS_SUCCESS;
+ ANT_U8 ucResult = -1;
+ ANT_U8 buf[ANT_NATIVE_MAX_PARMS_LEN];
+
+ ANT_FUNC_START();
+ ANT_DEBUG_V("reading off socket %#x", socket);
+
+ /* read newly arrived data */
+ while ((len = read(socket, buf, sizeof(buf))) < 0)
+ {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+
+ ANT_ERROR("failed to read socket. error: %s", strerror(errno));
+
+ ret = ANT_STATUS_FAILED;
+ goto close;
+ }
+
+ ANT_SERIAL(buf, len, 'C');
+
+ ANT_DEBUG_V("HCI Data: [%02X][%02X][%02X][%02X][%02X][%02X][%02X]...",
+ buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+
+ // 0 = packet type eg. HCI_EVENT_PKT
+ // FOR EVENT:
+ // 1 = event code eg. EVT_VENDOR, EVT_CMD_COMPLETE
+ // 2 = Parameter total length
+ // 3... parameters
+ // FOR CC
+ // 3 = Num HCI Vommand packets (allowed to be sent)
+ // 4+5 = ANT Opcode
+ // 6 = Result ??
+ // FOR VS
+ // 3+4 = ANT Opcode
+ // 5 = length
+ // 6 ? MSB of length ?
+ // 7... ant message
+
+ if(HCI_EVENT_PKT == buf[0])
+ {
+ ANT_DEBUG_D("Received Event Packet");
+
+ if(EVT_CMD_COMPLETE == buf[1])
+ {
+ if(len < HCI_EVENT_OVERHEAD_SIZE)
+ {
+ status = ANT_STATUS_FAILED;
+ }
+ else
+ {
+ if((HCI_CMD_OPCODE_ANT_LSB == buf[4]) &&
+ (HCI_CMD_OPCODE_ANT_MSB == buf[5]))
+ {
+ ucResult = buf[6];
+
+ ANT_DEBUG_V("Received COMMAND COMPLETE");
+ }
+ else
+ {
+ ANT_DEBUG_V("Command complete has wrong opcode");
+ }
+ }
+
+ /*
+ * if got a status byte, pass it forward, otherwise pass a failure
+ * status
+ */
+ if(status != ANT_STATUS_FAILED)
+ {
+ if(ucResult == 0)
+ {
+ ANT_DEBUG_D("Command Complete = SUCCESS");
+ status = ANT_STATUS_SUCCESS;
+ }
+ else if(ucResult == HCI_UNSPECIFIED_ERROR)
+ {
+ ANT_DEBUG_D("Command Complete = UNSPECIFIED_ERROR");
+
+ status = ANT_STATUS_TRANSPORT_UNSPECIFIED_ERROR;
+ }
+ else
+ {
+ status = ANT_STATUS_COMMAND_WRITE_FAILED;
+ ANT_DEBUG_D("Command Complete = WRITE_FAILED");
+ }
+ }
+ }
+ else
+ {
+ ANT_DEBUG_W("Other Event Packet, Should filter out");
+ }
+ }
+
+close:
+ ANT_FUNC_END();
+ return status;
+}
+
diff --git a/src/bluez_hci/inc/ant_framing.h b/src/bluez_hci/inc/ant_framing.h
new file mode 100644
index 0000000..7d01844
--- /dev/null
+++ b/src/bluez_hci/inc/ant_framing.h
@@ -0,0 +1,50 @@
+/*
+ * ANT Stack
+ *
+ * Copyright 2009 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_Framing.h
+*
+* BRIEF:
+* This file defines ANT specific HCI values used by the ANT chip.
+*
+*
+\******************************************************************************/
+
+#ifndef __ANT_HCIFRAMING_H
+#define __ANT_HCIFRAMING_H
+
+#ifdef BOARD_ANT_DEVICE_WILINK
+
+/* Number to used by the VS Parameters Len field */
+#define ANT_NATIVE_HCI_VS_PARMS_LEN_FIELD_LEN (2)
+
+#define HCI_CMD_ANT_MESSAGE_WRITE ((ANT_U16)0x01D1)
+
+#define HCI_CMD_OPCODE_ANT_LSB 0xD1
+#define HCI_CMD_OPCODE_ANT_MSB 0xFD
+
+#define HCI_VSOP_ANT_LSB 0x00
+#define HCI_VSOP_ANT_MSB 0x05
+
+#else
+
+#error "Board ANT Device Type not recognised"
+
+#endif
+
+#endif /* __ANT_HCIFRAMING_H */
diff --git a/src/bluez_hci/inc/ant_hciutils.h b/src/bluez_hci/inc/ant_hciutils.h
new file mode 100644
index 0000000..f8cf579
--- /dev/null
+++ b/src/bluez_hci/inc/ant_hciutils.h
@@ -0,0 +1,121 @@
+/*
+ * ANT Stack
+ *
+ * Copyright 2009 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_hciuntils.h
+*
+* BRIEF:
+* This file defines the utility functions for an HCI implementation
+*
+*
+\******************************************************************************/
+
+#ifndef __ANT_HCIUTILS_H
+#define __ANT_HCIUTILS_H
+
+#include <errno.h>
+#include <sys/socket.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+
+#include "ant_types.h"
+#include "ant_native.h"
+#include "ant_log.h"
+// -------------------------------------------------
+
+#define HCI_COMMAND_HEADER_SIZE 3
+typedef struct {
+ ANT_U8 opcode[2]; // 0xFDD1 for ANT
+ ANT_U8 plen;
+} __attribute__ ((packed)) hci_command_header_t;
+
+#define HCI_VENDOR_HEADER_SIZE 2
+typedef struct {
+ ANT_U8 hcilen[2];
+} __attribute__ ((packed)) hci_vendor_header_t;
+
+#define HCI_COMMAND_OVERHEAD_SIZE ( HCI_COMMAND_HEADER_SIZE + \
+ HCI_VENDOR_HEADER_SIZE + 1)
+typedef struct {
+ ANT_U8 packet_type; // 0x01 for HCI_COMMAND_PKT
+ hci_command_header_t cmd_header;
+ hci_vendor_header_t vendor_header;
+} __attribute__ ((packed)) hci_vendor_cmd_packet_t;
+
+#define HCI_EVENT_HEADER_SIZE 2
+typedef struct {
+ ANT_U8 event_c; // 0xFF for Vendor Specific,
+ // 0x0E for EVNT_CMD_COMPLETE
+ ANT_U8 plen; // data/parameter length
+} __attribute__ ((packed)) hci_event_header_t;
+
+#define HCI_EVENT_OVERHEAD_SIZE (HCI_EVENT_HEADER_SIZE + 5)
+typedef struct {
+ ANT_U8 packet_type; // HCI_EVENT_PKT
+ hci_event_header_t header;
+ union {
+ struct {
+ ANT_U8 vendor_c[2]; // 0x0500 for ANT
+ ANT_U8 hcilen[2];
+ } vendor;
+ struct {
+ ANT_U8 num_token;
+ ANT_U8 opcode[2]; // 0xFDD1 for ANT
+ ANT_U8 resp;
+ } cmd_cmplt;
+ };
+ ANT_U8 data[ANT_NATIVE_MAX_PARMS_LEN]; // Should be 255
+} __attribute__ ((packed)) hci_event_packet_t;
+
+typedef struct {
+ union {
+ hci_event_packet_t hci_event_packet;
+ ANT_U8 raw_packet[sizeof(hci_event_packet_t)];
+ };
+} rx_data_t; // Use this is for vendor specific and command complete events
+
+
+// -------------------------------------------------
+
+static inline int create_hci_sock() {
+ struct sockaddr_hci sa;
+ int sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+ if (sk < 0)
+ {
+ ANT_ERROR("Failed to create bluetooth hci socket: %s", strerror(errno));
+ }
+ else
+ {
+ memset(&sa, 0, sizeof(sa));
+ // sockaddr_hci changed from kernel 2.6.37 to 2.6.38 adding member hci_channel
+ // In order to be backwards compatible set it to 0 if it exists (HCI_CHANNEL_RAW)
+ sa.hci_family = AF_BLUETOOTH;
+ sa.hci_dev = 0;
+ if (bind(sk, (struct sockaddr *) &sa, sizeof(sa)) < 0)
+ {
+ ANT_ERROR("Failed to bind socket %#x to hci0: %s", sk, strerror(errno));
+ close(sk);
+ sk = -1;
+ }
+ }
+ return sk;
+}
+
+#endif /* __ANT_HCIUTILS_H */
+
+
diff --git a/src/bluez_hci/inc/ant_rx.h b/src/bluez_hci/inc/ant_rx.h
new file mode 100644
index 0000000..c914bb6
--- /dev/null
+++ b/src/bluez_hci/inc/ant_rx.h
@@ -0,0 +1,54 @@
+/*
+ * ANT Stack
+ *
+ * Copyright 2009 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.h
+*
+* BRIEF:
+* This file defines the receive thread function
+*
+*
+\******************************************************************************/
+
+#ifndef __ANT_OS_H
+#define __ANT_OS_H
+
+#include <pthread.h>
+#include "ant_types.h"
+#include "ant_native.h"
+
+typedef struct
+{
+ //The function to call back with received data
+ ANTNativeANTEventCb pfRxCallback;
+
+ //The function to call back with state changes
+ ANTNativeANTStateCb pfStateCallback;
+
+ //The thread object itself
+ pthread_t thread;
+
+} ANTHCIRxParams;
+
+extern ANTHCIRxParams RxParams;
+
+//The message receive thread
+void* ANTHCIRxThread(void* pvHCIDevice);
+
+#endif /* __ANT_OS_H */
+
diff --git a/src/bluez_hci/inc/ant_tx.h b/src/bluez_hci/inc/ant_tx.h
new file mode 100644
index 0000000..5057011
--- /dev/null
+++ b/src/bluez_hci/inc/ant_tx.h
@@ -0,0 +1,42 @@
+/*
+ * ANT Stack
+ *
+ * Copyright 2009 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_tx.h
+*
+* BRIEF:
+* This file defines the transmit function
+*
+*
+\******************************************************************************/
+
+#ifndef __ANT_TX_H
+#define __ANT_TX_H
+
+#include "ant_types.h"
+#include "ant_hciutils.h"
+
+int ant_open_tx_transport(void);
+void ant_close_tx_transport(int socket);
+ANT_BOOL wait_for_message(int socket);
+ANTStatus write_data(ANT_U8 ant_message[], int ant_message_len);
+
+ANTStatus get_command_complete_result(int socket);
+
+#endif /* __ANT_TX_H */
+
diff --git a/src/chip-B/Android.mk b/src/chip-B/Android.mk
new file mode 100644
index 0000000..5b030ff
--- /dev/null
+++ b/src/chip-B/Android.mk
@@ -0,0 +1,50 @@
+#
+# 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.
+#
+
+ifeq ($(BOARD_ANT_WIRELESS_DEVICE),"chip-B")
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_CFLAGS := -g -c -W -Wall -O2
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/../common/inc \
+ $(LOCAL_PATH)/inc \
+
+LOCAL_SRC_FILES:= \
+ ../../JAntNative.cpp \
+ ../common/ant_utils.c \
+ ant_native_chardev.c \
+ ant_rx_chardev.c \
+
+#JNI
+LOCAL_C_INCLUDE += $(JNI_H_INCLUDE)
+
+LOCAL_SHARED_LIBRARIES += \
+ libnativehelper
+
+# logging
+LOCAL_SHARED_LIBRARIES += \
+ libcutils
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE := libantradio
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif # BOARD_ANT_WIRELESS_DEVICE = "chip-B"
diff --git a/src/chip-B/ant_native_chardev.c b/src/chip-B/ant_native_chardev.c
new file mode 100644
index 0000000..39e61d7
--- /dev/null
+++ b/src/chip-B/ant_native_chardev.c
@@ -0,0 +1,424 @@
+/*
+ * 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 character device implementation of ant_native.h
+*
+*
+\*******************************************************************************/
+
+#include <errno.h>
+#include <fcntl.h> /* for open() */
+#include <linux/ioctl.h>
+#include <pthread.h>
+
+#include "ant_native.h"
+#include "ant_types.h"
+#include "ant_log.h"
+#include "ant_version.h"
+
+#include "ant_native_chardev.h"
+#include "ant_rx_chardev.h"
+
+#define CHIP_B_CHAR_DEV_IOCTL_RESET _IO('H', 160)
+
+#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)
+
+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 void ant_channel_init(ant_channel_info_t *pstChnlInfo, const char *pcCharDevName)
+{
+ pstChnlInfo->pcDevicePath = pcCharDevName;
+ pstChnlInfo->iFd = -1;
+ pstChnlInfo->fnRxCallback = NULL;
+ pstChnlInfo->ucFlowControlResp = FLOW_GO;
+ pstChnlInfo->pstFlowControlCond = &stFlowControlCond;
+ pstChnlInfo->pstFlowControlLock = &stFlowControlLock;
+}
+
+ANTStatus ant_init(void)
+{
+ ANTStatus uiRet = ANT_STATUS_FAILED;
+ ANT_FUNC_START();
+ stRxThreadInfo.stRxThread = 0;
+ stRxThreadInfo.ucRunThread = 0;
+ stRxThreadInfo.ucChipResetting = 0;
+ stRxThreadInfo.pstEnabledStatusLock = &stEnabledStatusLock;
+ g_fnStateCallback = 0;
+ ant_channel_init(&stRxThreadInfo.astChannels[COMMAND_CHANNEL], ANT_COMMANDS_DEVICE_NAME);
+ ant_channel_init(&stRxThreadInfo.astChannels[DATA_CHANNEL], ANT_DATA_DEVICE_NAME);
+ uiRet = ANT_STATUS_SUCCESS;
+ ANT_FUNC_END();
+ return uiRet;
+}
+
+ANTStatus ant_deinit(void)
+{
+ ANTStatus uiRet = ANT_STATUS_FAILED;
+ ANT_FUNC_START();
+ uiRet = ANT_STATUS_SUCCESS;
+ ANT_FUNC_END();
+ return uiRet;
+}
+
+ANTStatus set_ant_rx_callback(ANTNativeANTEventCb rx_callback_func)
+{
+ ANT_FUNC_START();
+ stRxThreadInfo.astChannels[COMMAND_CHANNEL].fnRxCallback = rx_callback_func;
+ stRxThreadInfo.astChannels[DATA_CHANNEL].fnRxCallback = rx_callback_func;
+ ANT_FUNC_END();
+ return ANT_STATUS_SUCCESS;
+}
+
+ANTStatus set_ant_state_callback(ANTNativeANTStateCb state_callback_func)
+{
+ ANT_FUNC_START();
+ g_fnStateCallback = state_callback_func;
+ ANT_FUNC_END();
+ return ANT_STATUS_SUCCESS;
+}
+
+ANTStatus ant_tx_message(ANT_U8 ucLen, ANT_U8 *pucMesg)
+{
+ ANTStatus uiRet = ANT_STATUS_FAILED;
+ int iMutexResult;
+ int iResult;
+ struct timespec stTimeout;
+ int iCondWaitResult;
+ ANT_U8 txBuffer[ANT_HCI_MAX_MSG_SIZE];
+ ANT_FUNC_START();
+ if (ant_radio_enabled_status() != RADIO_STATUS_ENABLED) {
+ uiRet = ANT_STATUS_FAILED_BT_NOT_INITIALIZED;
+ goto out;
+ }
+ txBuffer[CHIP_B_HCI_SIZE_OFFSET] = ucLen;
+ memcpy(txBuffer + CHIP_B_HCI_HEADER_SIZE, pucMesg, ucLen);
+ ANT_SERIAL(txBuffer, ucLen + CHIP_B_HCI_HEADER_SIZE, 'T');
+ switch (txBuffer[CHIP_B_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:
+ 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[COMMAND_CHANNEL].ucFlowControlResp = FLOW_STOP;
+ iResult = write(stRxThreadInfo.astChannels[DATA_CHANNEL].iFd, txBuffer, ucLen + CHIP_B_HCI_HEADER_SIZE);
+ if (iResult < 0) {
+ ANT_ERROR("failed to write data message to device: %s", strerror(errno));
+ } else if (iResult != ucLen + CHIP_B_HCI_HEADER_SIZE) {
+ ANT_ERROR("bytes written and message size dont match up");
+ } else {
+ stTimeout.tv_sec = time(0) + CHIP_B_FLOW_GO_WAIT_TIMEOUT_SEC;
+ stTimeout.tv_nsec = 0;
+
+ while (stRxThreadInfo.astChannels[COMMAND_CHANNEL].ucFlowControlResp != 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)
+ uiRet = ANT_STATUS_HARDWARE_ERR;
+ goto wait_error;
+ }
+ }
+ uiRet = 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__);
+ break;
+ default:
+ iResult = write(stRxThreadInfo.astChannels[COMMAND_CHANNEL].iFd, txBuffer, ucLen + CHIP_B_HCI_HEADER_SIZE);
+ if (iResult < 0) {
+ ANT_ERROR("failed to write message to device: %s", strerror(errno));
+ } else if (iResult != ucLen + CHIP_B_HCI_HEADER_SIZE) {
+ ANT_ERROR("bytes written and message size dont match up");
+ } else {
+ uiRet = ANT_STATUS_SUCCESS;
+ }
+ }
+out:
+ ANT_FUNC_END();
+ return uiRet;
+}
+
+ANTStatus ant_radio_hard_reset(void)
+{
+ enum ant_channel_type eChannel;
+ int iLockResult;
+ ANTStatus uiRet = 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__);
+
+ stRxThreadInfo.ucChipResetting = 1;
+ if (g_fnStateCallback)
+ g_fnStateCallback(RADIO_STATUS_RESETTING);
+
+ for (eChannel = 0; eChannel < NUM_ANT_CHANNELS; eChannel++)
+ ioctl(stRxThreadInfo.astChannels[eChannel].iFd, CHIP_B_CHAR_DEV_IOCTL_RESET); //TODO only one?
+
+ ant_do_disable();
+
+ if (ant_do_enable()) { /* failed */
+ if (g_fnStateCallback)
+ g_fnStateCallback(RADIO_STATUS_DISABLED);
+ } else { /* success */
+ if (g_fnStateCallback)
+ g_fnStateCallback(RADIO_STATUS_RESET);
+ uiRet = 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:
+ ANT_FUNC_END();
+ return uiRet;
+}
+
+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;
+ }
+ if (pstChnlInfo->iFd != -1) {
+ if (close(pstChnlInfo->iFd) < 0) {
+ ANT_ERROR("failed to close channel %s(%#x): %s", pstChnlInfo->pcDevicePath, pstChnlInfo->iFd, strerror(errno));
+ }
+ pstChnlInfo->iFd = -1; //TODO can this overwrite a still valid fd?
+ } else {
+ ANT_DEBUG_D("%s file is already closed", pstChnlInfo->pcDevicePath);
+ }
+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;
+ }
+ if (pstChnlInfo->iFd == -1) {
+ pstChnlInfo->iFd = open(pstChnlInfo->pcDevicePath, O_RDWR);
+ if (pstChnlInfo->iFd < 0) {
+ ANT_ERROR("failed to open dev %s: %s", pstChnlInfo->pcDevicePath, strerror(errno));
+ goto out;
+ }
+ } else {
+ ANT_DEBUG_D("%s is already enabled", pstChnlInfo->pcDevicePath);
+ }
+ iRet = 0;
+out:
+ ANT_FUNC_END();
+ return iRet;
+}
+
+int ant_do_enable(void)
+{
+ int iRet = -1;
+ enum 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;
+}
+
+void ant_do_disable(void)
+{
+ enum ant_channel_type eChannel;
+ ANT_FUNC_START();
+ stRxThreadInfo.ucRunThread = 0;
+ for (eChannel = 0; eChannel < NUM_ANT_CHANNELS; eChannel++)
+ ant_disable_channel(&stRxThreadInfo.astChannels[eChannel]);
+ if (stRxThreadInfo.stRxThread != 0) {
+ if (pthread_join(stRxThreadInfo.stRxThread, NULL) < 0) {
+ ANT_ERROR("failed to join rx thread: %s", strerror(errno));
+ }
+ stRxThreadInfo.stRxThread = 0;
+ } else {
+ ANT_DEBUG_D("rx thread is not running");
+ }
+ ANT_FUNC_END();
+}
+
+ANTStatus ant_enable_radio(void)
+{
+ int iLockResult;
+ ANTStatus uiRet = 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_do_enable() < 0) {
+ ANT_ERROR("ant enable failed: %s", strerror(errno));
+
+ ant_do_disable();
+
+ if (g_fnStateCallback)
+ g_fnStateCallback(ant_radio_enabled_status());
+ } else {
+ if (g_fnStateCallback)
+ g_fnStateCallback(RADIO_STATUS_ENABLED);
+ uiRet = 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 uiRet;
+}
+
+ANTStatus ant_disable_radio(void)
+{
+ int iLockResult;
+ ANTStatus uiRet = 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_do_disable();
+
+ if (g_fnStateCallback)
+ g_fnStateCallback(ant_radio_enabled_status());
+ uiRet = 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 uiRet;
+}
+
+ANTRadioEnabledStatus ant_radio_enabled_status(void)
+{
+ enum 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;
+ }
+ for (eChannel = 0; eChannel < NUM_ANT_CHANNELS; eChannel++)
+ if (stRxThreadInfo.astChannels[eChannel].iFd != -1)
+ iOpenFiles++;
+ iOpenThread = (stRxThreadInfo.stRxThread) ? 1 : 0;
+
+ if (!stRxThreadInfo.ucRunThread) {
+ if (iOpenFiles || iOpenThread) {
+ uiRet = RADIO_STATUS_DISABLING;
+ } else {
+ uiRet = RADIO_STATUS_DISABLED;
+ }
+ } else {
+ if ((iOpenFiles == NUM_ANT_CHANNELS) && iOpenThread) {
+ uiRet = RADIO_STATUS_ENABLED;
+ } else if (!iOpenFiles && iOpenThread) {
+ uiRet = RADIO_STATUS_UNKNOWN;
+ } else {
+ uiRet = RADIO_STATUS_ENABLING;
+ }
+ }
+out:
+ ANT_DEBUG_D("get radio enabled status returned %d", uiRet);
+ ANT_FUNC_END();
+ return uiRet;
+}
+
+const char *ant_get_lib_version()
+{
+ return "libantradio.so: CHIP_B Character Device Transport. Version "
+ LIBANT_STACK_MAJOR"."LIBANT_STACK_MINOR"."LIBANT_STACK_INCRE;
+}
+
diff --git a/src/chip-B/ant_rx_chardev.c b/src/chip-B/ant_rx_chardev.c
new file mode 100644
index 0000000..c4aedac
--- /dev/null
+++ b/src/chip-B/ant_rx_chardev.c
@@ -0,0 +1,213 @@
+/*
+ * 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 provides the rx function which will loop reading ANT messages
+* until told to exit.
+*
+*
+\*******************************************************************************/
+
+#include <errno.h>
+#include <poll.h>
+#include <pthread.h>
+
+#include "ant_rx_chardev.h"
+#include "ant_native_chardev.h"
+
+#include "ant_native.h"
+#include "ant_types.h"
+#include "ant_log.h"
+#undef LOG_TAG
+#define LOG_TAG "antradio_rx"
+
+#define ANT_POLL_TIMEOUT ((int)30000)
+
+int readChannelMsg(ant_channel_info_t *pstChnlInfo)
+{
+ int iRet = -1;
+ ANT_U8 aucRxBuffer[ANT_HCI_MAX_MSG_SIZE];
+ int iRxLenRead;
+ int iMutexResult;
+ ANT_FUNC_START();
+
+ while (((iRxLenRead = read(pstChnlInfo->iFd, aucRxBuffer, sizeof(aucRxBuffer))) < 0)
+ && errno == EAGAIN)
+ ;
+
+ if (iRxLenRead < 0) {
+ if (errno == ENODEV) {
+ ANT_ERROR("%s not enabled, exiting rx thread",
+ pstChnlInfo->pcDevicePath);
+ goto out;
+ } else if (errno == ENXIO) {
+ ANT_ERROR("%s there is no physical ANT device connected",
+ pstChnlInfo->pcDevicePath);
+ goto out;
+ } else {
+ ANT_ERROR("%s read thread exiting, unhandled error: %s",
+ pstChnlInfo->pcDevicePath, strerror(errno));
+ goto out;
+ }
+ } else {
+ ANT_SERIAL(aucRxBuffer, iRxLenRead, 'R');
+ if (aucRxBuffer[CHIP_B_HCI_DATA_OFFSET + ANT_MSG_ID_OFFSET] == ANT_MESG_FLOW_CONTROL) {
+ 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));
+ goto out;
+ }
+ ANT_DEBUG_V("got stFlowControlLock in %s", __FUNCTION__);
+
+ pstChnlInfo->ucFlowControlResp = aucRxBuffer[CHIP_B_HCI_DATA_OFFSET + ANT_MSG_DATA_OFFSET];
+
+ 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);
+ } else {
+ if (pstChnlInfo->fnRxCallback != NULL) {
+ pstChnlInfo->fnRxCallback(aucRxBuffer[CHIP_B_HCI_SIZE_OFFSET], &aucRxBuffer[CHIP_B_HCI_DATA_OFFSET]);
+ } else {
+ ANT_WARN("%s rx callback is null", pstChnlInfo->pcDevicePath);
+ }
+ }
+ iRet = 0;
+ }
+out:
+ ANT_FUNC_END();
+ return iRet;
+}
+
+void *fnRxThread(void *ant_rx_thread_info)
+{
+ int iMutexLockResult;
+ int iPollRet;
+ ant_rx_thread_info_t *stRxThreadInfo;
+ struct pollfd astPollFd[NUM_ANT_CHANNELS];
+ enum ant_channel_type eChannel;
+ ANT_FUNC_START();
+
+ stRxThreadInfo = (ant_rx_thread_info_t *)ant_rx_thread_info;
+ for (eChannel = 0; eChannel < NUM_ANT_CHANNELS; eChannel++) {
+ astPollFd[eChannel].fd = stRxThreadInfo->astChannels[eChannel].iFd;
+ astPollFd[eChannel].events = POLLIN | POLLRDNORM;
+ }
+
+ while (stRxThreadInfo->ucRunThread) {
+ iPollRet = poll(astPollFd, NUM_ANT_CHANNELS, ANT_POLL_TIMEOUT);
+ if (!iPollRet) {
+ ANT_DEBUG_V("poll timed out, checking exit cond");
+ } else if (iPollRet < 0) {
+ ANT_ERROR("read thread exiting, unhandled error: %s", strerror(errno));
+ } else {
+ for (eChannel = 0; eChannel < NUM_ANT_CHANNELS; eChannel++) {
+ if (astPollFd[eChannel].revents & (POLLERR | POLLPRI | POLLRDHUP)) {
+ ANT_ERROR("poll error from %s. exiting rx thread",
+ stRxThreadInfo->astChannels[eChannel].pcDevicePath);
+ /* 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);
+ goto reset;
+
+ } else if (astPollFd[eChannel].revents & (POLLIN | POLLRDNORM)) {
+ ANT_DEBUG_D("data on %s. reading it",
+ stRxThreadInfo->astChannels[eChannel].pcDevicePath);
+ if (readChannelMsg(&stRxThreadInfo->astChannels[eChannel]) < 0)
+ goto out;
+ } else if (astPollFd[eChannel].revents) {
+ ANT_DEBUG_W("unhandled poll result %#x from %s",
+ astPollFd[eChannel].revents,
+ stRxThreadInfo->astChannels[eChannel].pcDevicePath);
+ }
+ }
+ }
+ }
+out:
+ stRxThreadInfo->ucRunThread = 0;
+ /* Try to get stEnabledStatusLock.
+ * if you get it then noone 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");
+ stRxThreadInfo->stRxThread = 0; /* spoof our handle as closed so we don't
+ * try to join ourselves in disable */
+
+ if (g_fnStateCallback)
+ g_fnStateCallback(RADIO_STATUS_DISABLING);
+
+ ant_do_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");
+ }
+ ANT_FUNC_END();
+#ifdef ANDROID
+ return NULL;
+#endif
+
+reset:
+ 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;
+ } 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_do_disable();
+
+ if (ant_do_enable()) { /* 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__);
+ }
+ stRxThreadInfo->ucChipResetting = 0;
+ ANT_FUNC_END();
+#ifdef ANDROID
+ return NULL;
+#endif
+}
+
diff --git a/src/chip-B/inc/ant_native_chardev.h b/src/chip-B/inc/ant_native_chardev.h
new file mode 100644
index 0000000..1173f08
--- /dev/null
+++ b/src/chip-B/inc/ant_native_chardev.h
@@ -0,0 +1,48 @@
+/*
+ * 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.h
+*
+* BRIEF:
+* This file defines constants for the char dev implementation
+*
+*
+\*******************************************************************************/
+
+#ifndef __ANT_NATIVE_CHARDEV_H
+#define __ANT_NATIVE_CHARDEV_H
+
+#define ANT_COMMANDS_DEVICE_NAME "/dev/antradio_cmd"
+#define ANT_DATA_DEVICE_NAME "/dev/antradio_data"
+
+#define CHIP_B_HCI_SIZE_OFFSET 0
+#define CHIP_B_HCI_DATA_OFFSET 1
+#define CHIP_B_HCI_HEADER_SIZE 1
+
+#define ANT_MESG_FLOW_CONTROL ((ANT_U8)0xC9)
+#define FLOW_GO ((ANT_U8)0x00)
+#define FLOW_STOP ((ANT_U8)0x80)
+#define CHIP_B_FLOW_GO_WAIT_TIMEOUT_SEC 10
+
+int ant_do_enable(void);
+void ant_do_disable(void);
+extern ANTNativeANTStateCb g_fnStateCallback;
+
+#endif /* ifndef __ANT_NATIVE_CHARDEV_H */
+
diff --git a/src/chip-B/inc/ant_rx_chardev.h b/src/chip-B/inc/ant_rx_chardev.h
new file mode 100644
index 0000000..6721222
--- /dev/null
+++ b/src/chip-B/inc/ant_rx_chardev.h
@@ -0,0 +1,73 @@
+/*
+ * 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 public members in ant_rx_chardev.c
+*
+*
+\*******************************************************************************/
+
+#ifndef __ANT_RX_NATIVE_H
+#define __ANT_RX_NATIVE_H
+
+#include "ant_native.h"
+
+/* 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;
+} ant_channel_info_t;
+
+enum ant_channel_type {
+ DATA_CHANNEL,
+ COMMAND_CHANNEL,
+ NUM_ANT_CHANNELS
+};
+
+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];
+} 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/chip-C/Android.mk b/src/chip-C/Android.mk
new file mode 100644
index 0000000..1f75535
--- /dev/null
+++ b/src/chip-C/Android.mk
@@ -0,0 +1,50 @@
+#
+# 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.
+#
+
+ifeq ($(BOARD_ANT_WIRELESS_DEVICE),"chip-C")
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_CFLAGS := -g -c -W -Wall -O2
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/../common/inc \
+ $(LOCAL_PATH)/inc \
+
+LOCAL_SRC_FILES:= \
+ ../../JAntNative.cpp \
+ ../common/ant_utils.c \
+ ant_native_chardev.c \
+ ant_rx_chardev.c \
+
+#JNI
+LOCAL_C_INCLUDE += $(JNI_H_INCLUDE)
+
+LOCAL_SHARED_LIBRARIES += \
+ libnativehelper
+
+# logging
+LOCAL_SHARED_LIBRARIES += \
+ libcutils
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE := libantradio
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif # BOARD_ANT_WIRELESS_DEVICE = "chip-C"
diff --git a/src/chip-C/ant_native_chardev.c b/src/chip-C/ant_native_chardev.c
new file mode 100644
index 0000000..fe10382
--- /dev/null
+++ b/src/chip-C/ant_native_chardev.c
@@ -0,0 +1,389 @@
+/*
+ * 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 character device implementation of ant_native.h
+*
+*
+\*******************************************************************************/
+
+#include <errno.h>
+#include <fcntl.h> /* for open() */
+#include <linux/ioctl.h>
+#include <pthread.h>
+
+#include "ant_native.h"
+#include "ant_types.h"
+#include "ant_log.h"
+#include "ant_version.h"
+
+#include "ant_native_chardev.h"
+#include "ant_rx_chardev.h"
+
+#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)
+
+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 void ant_channel_init(ant_channel_info_t *pstChnlInfo, const char *pcCharDevName)
+{
+ pstChnlInfo->pcDevicePath = pcCharDevName;
+ pstChnlInfo->iFd = -1;
+ pstChnlInfo->fnRxCallback = NULL;
+ pstChnlInfo->ucFlowControlResp = FLOW_GO;
+ pstChnlInfo->pstFlowControlCond = &stFlowControlCond;
+ pstChnlInfo->pstFlowControlLock = &stFlowControlLock;
+}
+
+ANTStatus ant_init(void)
+{
+ ANTStatus uiRet = ANT_STATUS_FAILED;
+ ANT_FUNC_START();
+ stRxThreadInfo.stRxThread = 0;
+ stRxThreadInfo.ucRunThread = 0;
+ stRxThreadInfo.ucChipResetting = 0;
+ stRxThreadInfo.pstEnabledStatusLock = &stEnabledStatusLock;
+ g_fnStateCallback = 0;
+ ant_channel_init(&stRxThreadInfo.astChannels[COMMAND_CHANNEL], ANT_COMMANDS_DEVICE_NAME);
+ ant_channel_init(&stRxThreadInfo.astChannels[DATA_CHANNEL], ANT_DATA_DEVICE_NAME);
+ uiRet = ANT_STATUS_SUCCESS;
+ ANT_FUNC_END();
+ return uiRet;
+}
+
+ANTStatus ant_deinit(void)
+{
+ ANTStatus uiRet = ANT_STATUS_FAILED;
+ ANT_FUNC_START();
+ uiRet = ANT_STATUS_SUCCESS;
+ ANT_FUNC_END();
+ return uiRet;
+}
+
+ANTStatus set_ant_rx_callback(ANTNativeANTEventCb rx_callback_func)
+{
+ ANT_FUNC_START();
+ stRxThreadInfo.astChannels[COMMAND_CHANNEL].fnRxCallback = rx_callback_func;
+ stRxThreadInfo.astChannels[DATA_CHANNEL].fnRxCallback = rx_callback_func;
+ ANT_FUNC_END();
+ return ANT_STATUS_SUCCESS;
+}
+
+ANTStatus set_ant_state_callback(ANTNativeANTStateCb state_callback_func)
+{
+ ANT_FUNC_START();
+ g_fnStateCallback = state_callback_func;
+ ANT_FUNC_END();
+ return ANT_STATUS_SUCCESS;
+}
+
+ANTStatus ant_tx_message(ANT_U8 ucLen, ANT_U8 *pucMesg)
+{
+ ANTStatus uiRet = ANT_STATUS_FAILED;
+ int iMutexResult;
+ int iResult;
+ struct timespec stTimeout;
+ int iCondWaitResult;
+ ANT_U8 txBuffer[ANT_HCI_MAX_MSG_SIZE];
+ ANT_FUNC_START();
+ if (ant_radio_enabled_status() != RADIO_STATUS_ENABLED) {
+ uiRet = ANT_STATUS_FAILED_BT_NOT_INITIALIZED;
+ goto out;
+ }
+ txBuffer[CHIP_C_HCI_SIZE_OFFSET] = ucLen;
+ memcpy(txBuffer + CHIP_C_HCI_HEADER_SIZE, pucMesg, ucLen);
+ ANT_SERIAL(txBuffer, ucLen + CHIP_C_HCI_HEADER_SIZE, 'T');
+ switch (txBuffer[CHIP_C_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:
+ 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[COMMAND_CHANNEL].ucFlowControlResp = FLOW_STOP;
+ iResult = write(stRxThreadInfo.astChannels[DATA_CHANNEL].iFd, txBuffer, ucLen + CHIP_C_HCI_HEADER_SIZE);
+ if (iResult < 0) {
+ ANT_ERROR("failed to write data message to device: %s", strerror(errno));
+ } else if (iResult != ucLen + CHIP_C_HCI_HEADER_SIZE) {
+ ANT_ERROR("bytes written and message size dont match up");
+ } else {
+ stTimeout.tv_sec = time(0) + CHIP_C_FLOW_GO_WAIT_TIMEOUT_SEC;
+ stTimeout.tv_nsec = 0;
+
+ while (stRxThreadInfo.astChannels[COMMAND_CHANNEL].ucFlowControlResp != 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)
+ uiRet = ANT_STATUS_HARDWARE_ERR;
+ goto wait_error;
+ }
+ }
+ uiRet = 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__);
+ break;
+ default:
+ iResult = write(stRxThreadInfo.astChannels[COMMAND_CHANNEL].iFd, txBuffer, ucLen + CHIP_C_HCI_HEADER_SIZE);
+ if (iResult < 0) {
+ ANT_ERROR("failed to write message to device: %s", strerror(errno));
+ } else if (iResult != ucLen + CHIP_C_HCI_HEADER_SIZE) {
+ ANT_ERROR("bytes written and message size dont match up");
+ } else {
+ uiRet = ANT_STATUS_SUCCESS;
+ }
+ }
+out:
+ ANT_FUNC_END();
+ return uiRet;
+}
+
+ANTStatus ant_radio_hard_reset(void)
+{
+ ANTStatus result_status = ANT_STATUS_NOT_SUPPORTED;
+ ANT_FUNC_START();
+ ANT_FUNC_END();
+ return result_status;
+}
+
+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;
+ }
+ if (pstChnlInfo->iFd != -1) {
+ if (close(pstChnlInfo->iFd) < 0) {
+ ANT_ERROR("failed to close channel %s(%#x): %s", pstChnlInfo->pcDevicePath, pstChnlInfo->iFd, strerror(errno));
+ }
+ pstChnlInfo->iFd = -1; //TODO can this overwrite a still valid fd?
+ } else {
+ ANT_DEBUG_D("%s file is already closed", pstChnlInfo->pcDevicePath);
+ }
+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;
+ }
+ if (pstChnlInfo->iFd == -1) {
+ pstChnlInfo->iFd = open(pstChnlInfo->pcDevicePath, O_RDWR);
+ if (pstChnlInfo->iFd < 0) {
+ ANT_ERROR("failed to open dev %s: %s", pstChnlInfo->pcDevicePath, strerror(errno));
+ goto out;
+ }
+ } else {
+ ANT_DEBUG_D("%s is already enabled", pstChnlInfo->pcDevicePath);
+ }
+ iRet = 0;
+out:
+ ANT_FUNC_END();
+ return iRet;
+}
+
+int ant_do_enable(void)
+{
+ int iRet = -1;
+ enum 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;
+}
+
+void ant_do_disable(void)
+{
+ enum ant_channel_type eChannel;
+ ANT_FUNC_START();
+ stRxThreadInfo.ucRunThread = 0;
+ for (eChannel = 0; eChannel < NUM_ANT_CHANNELS; eChannel++)
+ ant_disable_channel(&stRxThreadInfo.astChannels[eChannel]);
+ if (stRxThreadInfo.stRxThread != 0) {
+ if (pthread_join(stRxThreadInfo.stRxThread, NULL) < 0) {
+ ANT_ERROR("failed to join rx thread: %s", strerror(errno));
+ }
+ stRxThreadInfo.stRxThread = 0;
+ } else {
+ ANT_DEBUG_D("rx thread is not running");
+ }
+ ANT_FUNC_END();
+}
+
+ANTStatus ant_enable_radio(void)
+{
+ int iLockResult;
+ ANTStatus uiRet = 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_do_enable() < 0) {
+ ANT_ERROR("ant enable failed: %s", strerror(errno));
+
+ ant_do_disable();
+
+ if (g_fnStateCallback)
+ g_fnStateCallback(ant_radio_enabled_status());
+ } else {
+ if (g_fnStateCallback)
+ g_fnStateCallback(RADIO_STATUS_ENABLED);
+ uiRet = 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 uiRet;
+}
+
+ANTStatus ant_disable_radio(void)
+{
+ int iLockResult;
+ ANTStatus uiRet = 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_do_disable();
+
+ if (g_fnStateCallback)
+ g_fnStateCallback(ant_radio_enabled_status());
+ uiRet = 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 uiRet;
+}
+
+ANTRadioEnabledStatus ant_radio_enabled_status(void)
+{
+ enum 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;
+ }
+ for (eChannel = 0; eChannel < NUM_ANT_CHANNELS; eChannel++)
+ if (stRxThreadInfo.astChannels[eChannel].iFd != -1)
+ iOpenFiles++;
+ iOpenThread = (stRxThreadInfo.stRxThread) ? 1 : 0;
+
+ if (!stRxThreadInfo.ucRunThread) {
+ if (iOpenFiles || iOpenThread) {
+ uiRet = RADIO_STATUS_DISABLING;
+ } else {
+ uiRet = RADIO_STATUS_DISABLED;
+ }
+ } else {
+ if ((iOpenFiles == NUM_ANT_CHANNELS) && iOpenThread) {
+ uiRet = RADIO_STATUS_ENABLED;
+ } else if (!iOpenFiles && iOpenThread) {
+ uiRet = RADIO_STATUS_UNKNOWN;
+ } else {
+ uiRet = RADIO_STATUS_ENABLING;
+ }
+ }
+out:
+ ANT_DEBUG_D("get radio enabled status returned %d", uiRet);
+ ANT_FUNC_END();
+ return uiRet;
+}
+
+const char *ant_get_lib_version()
+{
+ return "libantradio.so: CHIP_C TTY Transport. Version "
+ LIBANT_STACK_MAJOR"."LIBANT_STACK_MINOR"."LIBANT_STACK_INCRE;
+}
+
diff --git a/src/chip-C/ant_rx_chardev.c b/src/chip-C/ant_rx_chardev.c
new file mode 100644
index 0000000..2c0c6bd
--- /dev/null
+++ b/src/chip-C/ant_rx_chardev.c
@@ -0,0 +1,213 @@
+/*
+ * 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 provides the rx function which will loop reading ANT messages
+* until told to exit.
+*
+*
+\*******************************************************************************/
+
+#include <errno.h>
+#include <poll.h>
+#include <pthread.h>
+
+#include "ant_rx_chardev.h"
+#include "ant_native_chardev.h"
+
+#include "ant_native.h"
+#include "ant_types.h"
+#include "ant_log.h"
+#undef LOG_TAG
+#define LOG_TAG "antradio_rx"
+
+#define ANT_POLL_TIMEOUT ((int)30000)
+
+int readChannelMsg(ant_channel_info_t *pstChnlInfo)
+{
+ int iRet = -1;
+ ANT_U8 aucRxBuffer[ANT_HCI_MAX_MSG_SIZE];
+ int iRxLenRead;
+ int iMutexResult;
+ ANT_FUNC_START();
+
+ while (((iRxLenRead = read(pstChnlInfo->iFd, aucRxBuffer, sizeof(aucRxBuffer))) < 0)
+ && errno == EAGAIN)
+ ;
+
+ if (iRxLenRead < 0) {
+ if (errno == ENODEV) {
+ ANT_ERROR("%s not enabled, exiting rx thread",
+ pstChnlInfo->pcDevicePath);
+ goto out;
+ } else if (errno == ENXIO) {
+ ANT_ERROR("%s there is no physical ANT device connected",
+ pstChnlInfo->pcDevicePath);
+ goto out;
+ } else {
+ ANT_ERROR("%s read thread exiting, unhandled error: %s",
+ pstChnlInfo->pcDevicePath, strerror(errno));
+ goto out;
+ }
+ } else {
+ ANT_SERIAL(aucRxBuffer, iRxLenRead, 'R');
+ if (aucRxBuffer[CHIP_C_HCI_DATA_OFFSET + ANT_MSG_ID_OFFSET] == ANT_MESG_FLOW_CONTROL) {
+ 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));
+ goto out;
+ }
+ ANT_DEBUG_V("got stFlowControlLock in %s", __FUNCTION__);
+
+ pstChnlInfo->ucFlowControlResp = aucRxBuffer[CHIP_C_HCI_DATA_OFFSET + ANT_MSG_DATA_OFFSET];
+
+ 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);
+ } else {
+ if (pstChnlInfo->fnRxCallback != NULL) {
+ pstChnlInfo->fnRxCallback(aucRxBuffer[CHIP_C_HCI_SIZE_OFFSET], &aucRxBuffer[CHIP_C_HCI_DATA_OFFSET]);
+ } else {
+ ANT_WARN("%s rx callback is null", pstChnlInfo->pcDevicePath);
+ }
+ }
+ iRet = 0;
+ }
+out:
+ ANT_FUNC_END();
+ return iRet;
+}
+
+void *fnRxThread(void *ant_rx_thread_info)
+{
+ int iMutexLockResult;
+ int iPollRet;
+ ant_rx_thread_info_t *stRxThreadInfo;
+ struct pollfd astPollFd[NUM_ANT_CHANNELS];
+ enum ant_channel_type eChannel;
+ ANT_FUNC_START();
+
+ stRxThreadInfo = (ant_rx_thread_info_t *)ant_rx_thread_info;
+ for (eChannel = 0; eChannel < NUM_ANT_CHANNELS; eChannel++) {
+ astPollFd[eChannel].fd = stRxThreadInfo->astChannels[eChannel].iFd;
+ astPollFd[eChannel].events = POLLIN | POLLRDNORM;
+ }
+
+ while (stRxThreadInfo->ucRunThread) {
+ iPollRet = poll(astPollFd, NUM_ANT_CHANNELS, ANT_POLL_TIMEOUT);
+ if (!iPollRet) {
+ ANT_DEBUG_V("poll timed out, checking exit cond");
+ } else if (iPollRet < 0) {
+ ANT_ERROR("read thread exiting, unhandled error: %s", strerror(errno));
+ } else {
+ for (eChannel = 0; eChannel < NUM_ANT_CHANNELS; eChannel++) {
+ if (astPollFd[eChannel].revents & (POLLERR | POLLPRI | POLLRDHUP)) {
+ ANT_ERROR("poll error from %s. exiting rx thread",
+ stRxThreadInfo->astChannels[eChannel].pcDevicePath);
+ /* 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);
+ goto reset;
+
+ } else if (astPollFd[eChannel].revents & (POLLIN | POLLRDNORM)) {
+ ANT_DEBUG_D("data on %s. reading it",
+ stRxThreadInfo->astChannels[eChannel].pcDevicePath);
+ if (readChannelMsg(&stRxThreadInfo->astChannels[eChannel]) < 0)
+ goto out;
+ } else if (astPollFd[eChannel].revents) {
+ ANT_DEBUG_W("unhandled poll result %#x from %s",
+ astPollFd[eChannel].revents,
+ stRxThreadInfo->astChannels[eChannel].pcDevicePath);
+ }
+ }
+ }
+ }
+out:
+ stRxThreadInfo->ucRunThread = 0;
+ /* Try to get stEnabledStatusLock.
+ * if you get it then noone 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");
+ stRxThreadInfo->stRxThread = 0; /* spoof our handle as closed so we don't
+ * try to join ourselves in disable */
+
+ if (g_fnStateCallback)
+ g_fnStateCallback(RADIO_STATUS_DISABLING);
+
+ ant_do_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");
+ }
+ ANT_FUNC_END();
+#ifdef ANDROID
+ return NULL;
+#endif
+
+reset:
+ 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;
+ } 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_do_disable();
+
+ if (ant_do_enable()) { /* 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__);
+ }
+ stRxThreadInfo->ucChipResetting = 0;
+ ANT_FUNC_END();
+#ifdef ANDROID
+ return NULL;
+#endif
+}
+
diff --git a/src/chip-C/inc/ant_native_chardev.h b/src/chip-C/inc/ant_native_chardev.h
new file mode 100644
index 0000000..c72ac0e
--- /dev/null
+++ b/src/chip-C/inc/ant_native_chardev.h
@@ -0,0 +1,48 @@
+/*
+ * 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.h
+*
+* BRIEF:
+* This file defines constants for the char dev implementation
+*
+*
+\*******************************************************************************/
+
+#ifndef __ANT_NATIVE_CHARDEV_H
+#define __ANT_NATIVE_CHARDEV_H
+
+#define ANT_COMMANDS_DEVICE_NAME "/dev/smd5"
+#define ANT_DATA_DEVICE_NAME "/dev/smd6"
+
+#define CHIP_C_HCI_SIZE_OFFSET 0
+#define CHIP_C_HCI_DATA_OFFSET 1
+#define CHIP_C_HCI_HEADER_SIZE 1
+
+#define ANT_MESG_FLOW_CONTROL ((ANT_U8)0xC9)
+#define FLOW_GO ((ANT_U8)0x00)
+#define FLOW_STOP ((ANT_U8)0x80)
+#define CHIP_C_FLOW_GO_WAIT_TIMEOUT_SEC 10
+
+int ant_do_enable(void);
+void ant_do_disable(void);
+extern ANTNativeANTStateCb g_fnStateCallback;
+
+#endif /* ifndef __ANT_NATIVE_CHARDEV_H */
+
diff --git a/src/chip-C/inc/ant_rx_chardev.h b/src/chip-C/inc/ant_rx_chardev.h
new file mode 100644
index 0000000..6721222
--- /dev/null
+++ b/src/chip-C/inc/ant_rx_chardev.h
@@ -0,0 +1,73 @@
+/*
+ * 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 public members in ant_rx_chardev.c
+*
+*
+\*******************************************************************************/
+
+#ifndef __ANT_RX_NATIVE_H
+#define __ANT_RX_NATIVE_H
+
+#include "ant_native.h"
+
+/* 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;
+} ant_channel_info_t;
+
+enum ant_channel_type {
+ DATA_CHANNEL,
+ COMMAND_CHANNEL,
+ NUM_ANT_CHANNELS
+};
+
+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];
+} 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/common/ant_utils.c b/src/common/ant_utils.c
new file mode 100644
index 0000000..65b35de
--- /dev/null
+++ b/src/common/ant_utils.c
@@ -0,0 +1,57 @@
+/*
+ * ANT Stack
+ *
+ * Copyright 2009 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_utils.c
+*
+* BRIEF:
+* This file contains utility functions
+*
+*
+\******************************************************************************/
+
+#include "ant_types.h"
+#include "ant_utils.h"
+
+
+ANT_U16 ANT_UTILS_BEtoHost16(ANT_U8 * num)
+{
+ return (ANT_U16)(((ANT_U16) *(num) << 8) | ((ANT_U16) *(num+1)));
+}
+ANT_U16 ANT_UTILS_LEtoHost16(ANT_U8 * num)
+{
+ return (ANT_U16)(((ANT_U16) *(num+1) << 8) | ((ANT_U16) *(num)));
+}
+void ANT_UTILS_StoreBE16(ANT_U8 *buff, ANT_U16 be_value)
+{
+ buff[0] = (ANT_U8)(be_value>>8);
+ buff[1] = (ANT_U8)be_value;
+}
+void ANT_UTILS_StoreLE16(ANT_U8 *buff, ANT_U16 le_value)
+{
+ buff[1] = (ANT_U8)(le_value>>8);
+ buff[0] = (ANT_U8)le_value;
+}
+
+void ANT_UTILS_StoreBE32(ANT_U8 *buff, ANT_U32 be_value)
+{
+ buff[0] = (ANT_U8)(be_value>>24);
+ buff[1] = (ANT_U8)(be_value>>16);
+ buff[2] = (ANT_U8)(be_value>>8);
+ buff[3] = (ANT_U8)be_value;
+}
diff --git a/src/common/inc/ant_log.h b/src/common/inc/ant_log.h
new file mode 100644
index 0000000..f2d09b5
--- /dev/null
+++ b/src/common/inc/ant_log.h
@@ -0,0 +1,174 @@
+/*
+ * ANT Stack
+ *
+ * Copyright 2009 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_log.h
+*
+* BRIEF:
+* This file defines logging functions
+*
+*
+\******************************************************************************/
+
+#ifndef __ANT_LOG_H
+#define __ANT_LOG_H
+
+#include <unistd.h>
+#include "ant_types.h"
+
+#define LEVEL_NONE 0
+#define LEVEL_ERROR 1
+#define LEVEL_WARNING 2
+#define LEVEL_INFO 3
+#define LEVEL_DEBUG 4
+#define LEVEL_VERBOSE 5
+
+#define STREAM_STDOUT 16
+#define STREAM_LOGCAT 17
+
+/* Define what stream output should go to depending on platform */
+#if defined(__ANDROID__) || defined(ANDROID)
+ #define ANT_OUTPUT_STREAM STREAM_LOGCAT
+#elif defined(__linux__) || defined(__linux) || defined(linux)
+ #define ANT_OUTPUT_STREAM STREAM_STDOUT
+#endif
+
+/* If no debug level defined, set default as none */
+#if !defined(ANT_DEBUG)
+ #define ANT_DEBUG LEVEL_NONE
+#endif
+
+/* Define to show function entry and exit */
+//#define ANT_STACK_TRACE
+
+/* Define to show message in byte form */
+//#define ANT_LOG_SERIAL
+
+/* Define to write serial log to file instead of logcat */
+//#define ANT_LOG_SERIAL_FILE "/data/system/antseriallog.txt"
+
+#undef LOG_TAG
+#define LOG_TAG "antradio"
+
+#if ANT_DEBUG == LEVEL_NONE
+ #undef ANT_STACK_TRACE
+ #undef ANT_LOG_SERIAL
+#endif
+
+#if ANT_DEBUG >= LEVEL_ERROR
+ #define OUTPUT_LEVEL_ERROR(...) OUTPUT_ERROR(__VA_ARGS__)
+#else
+ #define OUTPUT_LEVEL_ERROR(...) ((void)0)
+#endif
+#if ANT_DEBUG >= LEVEL_WARNING
+ #define OUTPUT_LEVEL_WARNING(...) OUTPUT_WARNING(__VA_ARGS__)
+#else
+ #define OUTPUT_LEVEL_WARNING(...) ((void)0)
+#endif
+#if ANT_DEBUG >= LEVEL_INFO
+ #define OUTPUT_LEVEL_INFO(...) OUTPUT_INFO(__VA_ARGS__)
+#else
+ #define OUTPUT_LEVEL_INFO(...) ((void)0)
+#endif
+#if ANT_DEBUG >= LEVEL_DEBUG
+ #define OUTPUT_LEVEL_DEBUG(...) OUTPUT_DEBUG(__VA_ARGS__)
+#else
+ #define OUTPUT_LEVEL_DEBUG(...) ((void)0)
+#endif
+#if ANT_DEBUG >= LEVEL_VERBOSE
+ #define OUTPUT_LEVEL_VERBOSE(...) OUTPUT_VERBOSE(__VA_ARGS__)
+#else
+ #define OUTPUT_LEVEL_VERBOSE(...) ((void)0)
+#endif
+
+#if ANT_OUTPUT_STREAM == STREAM_STDOUT
+ #include <stdio.h>
+ #define OUTPUT_VERBOSE(fmt, ...) fprintf(stdout, LOG_TAG "<V>: " fmt "\n", ##__VA_ARGS__)
+ #define OUTPUT_DEBUG(fmt, ...) fprintf(stdout, LOG_TAG "<D>: " fmt "\n", ##__VA_ARGS__)
+ #define OUTPUT_INFO(fmt, ...) fprintf(stdout, LOG_TAG "<I>: " fmt "\n", ##__VA_ARGS__)
+ #define OUTPUT_WARNING(fmt, ...) fprintf(stdout, LOG_TAG "<W>: " fmt "\n", ##__VA_ARGS__)
+ #define OUTPUT_ERROR(fmt, ...) fprintf(stdout, LOG_TAG "<E>: " fmt "\n", ##__VA_ARGS__)
+#elif ANT_OUTPUT_STREAM == STREAM_LOGCAT
+ #if (ANT_DEBUG >= LEVEL_VERBOSE) || (defined(ANT_LOG_SERIAL) && !defined(ANT_LOG_SERIAL_FILE))
+ #undef NDEBUG /* Define verbose logging for logcat if required */
+ #endif
+ #include <cutils/log.h>
+ #define OUTPUT_VERBOSE(...) LOGV(__VA_ARGS__)
+ #define OUTPUT_DEBUG(...) LOGD(__VA_ARGS__)
+ #define OUTPUT_INFO(...) LOGI(__VA_ARGS__)
+ #define OUTPUT_WARNING(...) LOGW(__VA_ARGS__)
+ #define OUTPUT_ERROR(...) LOGE(__VA_ARGS__)
+#endif
+
+#define ANT_WARN(...) OUTPUT_WARNING(__VA_ARGS__)
+#define ANT_ERROR(...) OUTPUT_ERROR(__VA_ARGS__)
+
+#define ANT_DEBUG_V(...) OUTPUT_LEVEL_VERBOSE(__VA_ARGS__)
+#define ANT_DEBUG_D(...) OUTPUT_LEVEL_DEBUG(__VA_ARGS__)
+#define ANT_DEBUG_I(...) OUTPUT_LEVEL_INFO(__VA_ARGS__)
+#define ANT_DEBUG_W(...) OUTPUT_LEVEL_WARNING(__VA_ARGS__)
+#define ANT_DEBUG_E(...) OUTPUT_LEVEL_ERROR(__VA_ARGS__)
+
+#if defined(ANT_STACK_TRACE)
+ #define ANT_FUNC_START() OUTPUT_DEBUG("-> FUNC start %s", __FUNCTION__)
+ #define ANT_FUNC_END() OUTPUT_DEBUG("<- FUNC end %s", __FUNCTION__)
+#else
+ #define ANT_FUNC_START() ((void)0)
+ #define ANT_FUNC_END() ((void)0)
+#endif
+
+#if defined(ANT_LOG_SERIAL)
+static inline void ANT_SERIAL(ANT_U8 *buf, ANT_U8 len, char dir)
+{
+ static const char hexToChar[] = {'0','1','2','3','4','5','6','7',
+ '8','9','A','B','C','D','E','F'};
+ int i;
+ static char log[1024];
+ char *ptr = log;
+
+ *(ptr++) = dir;
+ *(ptr++) = 'x';
+ *(ptr++) = ' ';
+ for (i = 0; i < len; i++) {
+ *(ptr++) = '[';
+ *(ptr++) = hexToChar[(buf[i] & 0xF0) >> 4];
+ *(ptr++) = hexToChar[(buf[i] & 0x0F) >> 0];
+ *(ptr++) = ']';
+ }
+#if defined(ANT_LOG_SERIAL_FILE)
+ *(ptr++) = '\n';
+ FILE *fd = NULL;
+ fd = fopen(ANT_LOG_SERIAL_FILE, "a");
+ if (NULL == fd) {
+ LOGW("Could not open %s for serial output. %s", ANT_LOG_SERIAL_FILE, strerror(errno));
+ } else {
+ fwrite(log, 1, (ptr - log), fd);
+ if (fclose(fd)) {
+ LOGW("Could not close file for serial output. %s", strerror(errno));
+ }
+ }
+#else
+ *(ptr++) = '\0';
+ OUTPUT_VERBOSE("%s", log);
+#endif
+}
+#else
+ #define ANT_SERIAL(...) ((void)0)
+#endif
+
+#endif /* __ANT_LOG_H */
diff --git a/src/common/inc/ant_native.h b/src/common/inc/ant_native.h
new file mode 100644
index 0000000..eedec50
--- /dev/null
+++ b/src/common/inc/ant_native.h
@@ -0,0 +1,142 @@
+/*
+ * ANT Stack
+ *
+ * Copyright 2009 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.h
+*
+* BRIEF:
+* This file defines the interface to the ANT transport layer
+*
+*
+\******************************************************************************/
+
+#ifndef __ANT_NATIVE_H
+#define __ANT_NATIVE_H
+
+/*******************************************************************************
+ *
+ * Include files
+ *
+ ******************************************************************************/
+#include "ant_types.h"
+
+/*******************************************************************************
+ *
+ * Constants
+ *
+ ******************************************************************************/
+#define ANT_NATIVE_MAX_PARMS_LEN 255
+#define ANT_NATIVE_MESSAGE_OVERHEAD_SIZE 2
+#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)
+
+/*******************************************************************************
+ *
+ * Types
+ *
+ ******************************************************************************/
+typedef void (*ANTNativeANTEventCb)(ANT_U8 ucLen, ANT_U8* pucData);
+typedef void (*ANTNativeANTStateCb)(ANTRadioEnabledStatus uiNewState);
+
+/*******************************************************************************
+ *
+ * Data Structures
+ *
+ ******************************************************************************/
+
+/*******************************************************************************
+ *
+ * Function declarations
+ *
+ ******************************************************************************/
+
+/*------------------------------------------------------------------------------
+ * ant_init()
+ *
+ * Called to initialize the ANT stack
+ */
+ANTStatus ant_init(void);
+
+/*------------------------------------------------------------------------------
+ * ant_deinit()
+ *
+ * Called to de-initialize the ANT stack
+ */
+ANTStatus ant_deinit(void);
+
+/*------------------------------------------------------------------------------
+ * ant_enable_radio()
+ *
+ * Power on the chip and set it to a state which can read / write to it
+ */
+ANTStatus ant_enable_radio(void);
+
+/*------------------------------------------------------------------------------
+ * ant_disable_radio()
+ *
+ * Kill power to the ANT chip and set state which doesnt allow read / write
+ */
+ANTStatus ant_disable_radio(void);
+
+/*------------------------------------------------------------------------------
+ * ant_radio_enabled_status()
+ *
+ * Gets if the chip/transport is disabled/disabling/enabling/enabled
+ */
+ANTRadioEnabledStatus ant_radio_enabled_status(void);
+
+/*------------------------------------------------------------------------------
+ * set_ant_rx_callback()
+ *
+ * Sets the callback function for receiving ANT messages
+ */
+ANTStatus set_ant_rx_callback(ANTNativeANTEventCb rx_callback_func);
+
+/*------------------------------------------------------------------------------
+ * set_ant_state_callback()
+ *
+ * Sets the callback function for any ANT radio enabled status state changes
+ */
+ANTStatus set_ant_state_callback(ANTNativeANTStateCb state_callback_func);
+
+/*------------------------------------------------------------------------------
+ * ant_tx_message()
+ *
+ * Sends an ANT message command to the chip.
+ */
+ANTStatus ant_tx_message(ANT_U8 ucLen, ANT_U8 *pucMesg);
+
+/*------------------------------------------------------------------------------
+ * ant_radio_hard_reset()
+ *
+ * If supported, forces the chip to do a power cycle reset
+ */
+ANTStatus ant_radio_hard_reset(void);
+
+/*------------------------------------------------------------------------------
+ * ant_get_lib_version()
+ *
+ * Gets the current version and transport type of libantradio.so
+ */
+const char *ant_get_lib_version(void);
+
+#endif /* ifndef __ANT_NATIVE_H */
+
diff --git a/src/common/inc/ant_types.h b/src/common/inc/ant_types.h
new file mode 100644
index 0000000..bc896b6
--- /dev/null
+++ b/src/common/inc/ant_types.h
@@ -0,0 +1,125 @@
+/*
+ * ANT Stack
+ *
+ * Copyright 2009 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_types.h
+*
+* BRIEF:
+* This file defines types used in the ANT stack
+*
+*
+\******************************************************************************/
+
+#ifndef __ANT_TYPES_H
+#define __ANT_TYPES_H
+
+#include <stdint.h>
+
+/* -------------------------------------------------------------
+ * 8 Bits Types
+ */
+typedef uint8_t ANT_U8;
+typedef int8_t ANT_S8;
+
+/* -------------------------------------------------------------
+ * 16 Bits Types
+ */
+typedef uint16_t ANT_U16;
+typedef int8_t ANT_S16;
+
+/* -------------------------------------------------------------
+ * 32 Bits Types
+ */
+typedef uint32_t ANT_U32;
+typedef int32_t ANT_S32;
+
+
+/* -------------------------------------------------------------
+ * Native Integer Types (# of bits irrelevant)
+ */
+typedef int ANT_INT;
+typedef unsigned int ANT_UINT;
+
+
+/* --------------------------------------------------------------
+ * Boolean Definitions
+ */
+typedef ANT_INT ANT_BOOL;
+
+#define ANT_TRUE (1 == 1)
+#define ANT_FALSE (1 == 0)
+
+/*
+*/
+#define ANT_NO_VALUE ((ANT_U32)0xFFFFFFFFUL)
+
+
+/* -------------------------------------------------------------
+ * ANTRadioEnabledStatus Type
+ */
+typedef ANT_UINT ANTRadioEnabledStatus;
+
+#define RADIO_STATUS_UNKNOWN ((ANTRadioEnabledStatus)0)
+#define RADIO_STATUS_ENABLING ((ANTRadioEnabledStatus)1)
+#define RADIO_STATUS_ENABLED ((ANTRadioEnabledStatus)2)
+#define RADIO_STATUS_DISABLING ((ANTRadioEnabledStatus)3)
+#define RADIO_STATUS_DISABLED ((ANTRadioEnabledStatus)4)
+#define RADIO_STATUS_NOT_SUPPORTED ((ANTRadioEnabledStatus)5)
+#define RADIO_STATUS_SERVICE_NOT_INSTALLED ((ANTRadioEnabledStatus)6)
+#define RADIO_STATUS_SERVICE_NOT_CONNECTED ((ANTRadioEnabledStatus)7)
+#define RADIO_STATUS_RESETTING ((ANTRadioEnabledStatus)8)
+#define RADIO_STATUS_RESET ((ANTRadioEnabledStatus)9)
+
+/*------------------------------------------------------------------------------
+ * ANTStatus Type
+ *
+ */
+typedef ANT_UINT ANTStatus;
+
+#define ANT_STATUS_SUCCESS ((ANTStatus)0)
+#define ANT_STATUS_FAILED ((ANTStatus)1)
+#define ANT_STATUS_PENDING ((ANTStatus)2)
+#define ANT_STATUS_INVALID_PARM ((ANTStatus)3)
+#define ANT_STATUS_IN_PROGRESS ((ANTStatus)4)
+#define ANT_STATUS_NOT_APPLICABLE ((ANTStatus)5)
+#define ANT_STATUS_NOT_SUPPORTED ((ANTStatus)6)
+#define ANT_STATUS_INTERNAL_ERROR ((ANTStatus)7)
+#define ANT_STATUS_TRANSPORT_INIT_ERR ((ANTStatus)8)
+#define ANT_STATUS_HARDWARE_ERR ((ANTStatus)9)
+#define ANT_STATUS_NO_VALUE_AVAILABLE ((ANTStatus)10)
+#define ANT_STATUS_CONTEXT_DOESNT_EXIST ((ANTStatus)11)
+#define ANT_STATUS_CONTEXT_NOT_DESTROYED ((ANTStatus)12)
+#define ANT_STATUS_CONTEXT_NOT_ENABLED ((ANTStatus)13)
+#define ANT_STATUS_CONTEXT_NOT_DISABLED ((ANTStatus)14)
+#define ANT_STATUS_NOT_DE_INITIALIZED ((ANTStatus)15)
+#define ANT_STATUS_NOT_INITIALIZED ((ANTStatus)16)
+#define ANT_STATUS_TOO_MANY_PENDING_CMDS ((ANTStatus)17)
+#define ANT_STATUS_DISABLING_IN_PROGRESS ((ANTStatus)18)
+
+#define ANT_STATUS_COMMAND_WRITE_FAILED ((ANTStatus)20)
+#define ANT_STATUS_SCRIPT_EXEC_FAILED ((ANTStatus)21)
+
+#define ANT_STATUS_FAILED_BT_NOT_INITIALIZED ((ANTStatus)23)
+#define ANT_STATUS_AUDIO_OPERATION_UNAVAILIBLE_RESOURCES ((ANTStatus)24)
+
+#define ANT_STATUS_TRANSPORT_UNSPECIFIED_ERROR ((ANTStatus)30)
+
+#define ANT_STATUS_NO_VALUE ((ANTStatus)100)
+
+#endif /* __ANT_TYPES_H */
+
diff --git a/src/common/inc/ant_utils.h b/src/common/inc/ant_utils.h
new file mode 100644
index 0000000..60abe8c
--- /dev/null
+++ b/src/common/inc/ant_utils.h
@@ -0,0 +1,139 @@
+/*
+ * ANT Stack
+ *
+ * Copyright 2009 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_utils.h
+*
+* BRIEF:
+* This file defines utility functions
+*
+*
+\******************************************************************************/
+#ifndef __ANT_UTILS_H
+#define __ANT_UTILS_H
+
+#include "ant_types.h"
+
+/****************************************************************************
+ *
+ * Type Definitions
+ *
+ ****************************************************************************/
+
+
+
+/*------------------------------------------------------------------------------
+ * ANT_xxx()
+ *
+ * Brief:
+ * xxx
+ *
+ * Description:
+ * xxx
+ *
+ * Type:
+ * Syxxx/As
+ *
+ * Parameters:
+ * xxx [in] -
+ *
+ * Returns:
+ * xxx
+ */
+ANT_U16 ANT_UTILS_BEtoHost16(ANT_U8 * num);
+/*------------------------------------------------------------------------------
+ * ANT_xxx()
+ *
+ * Brief:
+ * xxx
+ *
+ * Description:
+ * xxx
+ *
+ * Type:
+ * Syxxx/As
+ *
+ * Parameters:
+ * xxx [in] -
+ *
+ * Returns:
+ * xxx
+ */
+ANT_U16 ANT_UTILS_LEtoHost16(ANT_U8 * num);
+/*------------------------------------------------------------------------------
+ * ANT_xxx()
+ *
+ * Brief:
+ * xxx
+ *
+ * Description:
+ * xxx
+ *
+ * Type:
+ * Syxxx/As
+ *
+ * Parameters:
+ * xxx [in] -
+ *
+ * Returns:
+ * xxx
+ */
+void ANT_UTILS_StoreBE16(ANT_U8 *buff, ANT_U16 be_value) ;
+/*------------------------------------------------------------------------------
+ * ANT_xxx()
+ *
+ * Brief:
+ * xxx
+ *
+ * Description:
+ * xxx
+ *
+ * Type:
+ * Syxxx/As
+ *
+ * Parameters:
+ * xxx [in] -
+ *
+ * Returns:
+ * xxx
+ */
+void ANT_UTILS_StoreLE16(ANT_U8 *buff, ANT_U16 le_value) ;
+/*------------------------------------------------------------------------------
+ * ANT_xxx()
+ *
+ * Brief:
+ * xxx
+ *
+ * Description:
+ * xxx
+ *
+ * Type:
+ * Syxxx/As
+ *
+ * Parameters:
+ * xxx [in] -
+ *
+ * Returns:
+ * xxx
+ */
+void ANT_UTILS_StoreBE32(ANT_U8 *buff, ANT_U32 be_value) ;
+
+
+
+#endif /* __ANT_UTILS_H */
+
diff --git a/src/common/inc/ant_version.h b/src/common/inc/ant_version.h
new file mode 100644
index 0000000..bc1f239
--- /dev/null
+++ b/src/common/inc/ant_version.h
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+#ifndef __ANT_VERSION_H
+#define __ANT_VERSION_H
+
+#define LIBANT_STACK_MAJOR "0"
+#define LIBANT_STACK_MINOR "7"
+#define LIBANT_STACK_INCRE "0"
+
+#endif // __ANT_VERSION_H
+