Merge pull request #2 from rohan-martin/master
Android_System_Package_2-0-0
This commit is contained in:
		
							
								
								
									
										21
									
								
								Android.mk
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								Android.mk
									
									
									
									
									
								
							@@ -16,6 +16,8 @@
 | 
			
		||||
 | 
			
		||||
ifneq ($(BOARD_ANT_WIRELESS_DEVICE),)
 | 
			
		||||
 | 
			
		||||
LOCAL_PATH := $(call my-dir)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# ANT native library
 | 
			
		||||
#
 | 
			
		||||
@@ -24,15 +26,19 @@ include $(CLEAR_VARS)
 | 
			
		||||
 | 
			
		||||
ifeq ($(BOARD_ANT_WIRELESS_DEVICE),"wl12xx")
 | 
			
		||||
 | 
			
		||||
include $(LOCAL_PATH)/hal/bluez_hci/Android.mk
 | 
			
		||||
ANT_DIR := src/bluez_hci
 | 
			
		||||
 | 
			
		||||
else ifeq ($(BOARD_ANT_WIRELESS_DEVICE),"chip-B")
 | 
			
		||||
else ifeq ($(BOARD_ANT_WIRELESS_DEVICE),"bcm433x")
 | 
			
		||||
 | 
			
		||||
include $(LOCAL_PATH)/hal/chip-B/Android.mk
 | 
			
		||||
ANT_DIR := src/bluez_hci
 | 
			
		||||
 | 
			
		||||
else ifeq ($(BOARD_ANT_WIRELESS_DEVICE),"chip-C")
 | 
			
		||||
else ifeq ($(BOARD_ANT_WIRELESS_DEVICE),"cg29xx")
 | 
			
		||||
 | 
			
		||||
include $(LOCAL_PATH)/hal/chip-C/Android.mk
 | 
			
		||||
ANT_DIR := src/vfs
 | 
			
		||||
 | 
			
		||||
else ifeq ($(BOARD_ANT_WIRELESS_DEVICE),"vfs-prerelease")
 | 
			
		||||
 | 
			
		||||
ANT_DIR := src/vfs
 | 
			
		||||
 | 
			
		||||
else
 | 
			
		||||
 | 
			
		||||
@@ -40,6 +46,9 @@ $(error Unsupported BOARD_ANT_WIRELESS_DEVICE := $(BOARD_ANT_WIRELESS_DEVICE))
 | 
			
		||||
 | 
			
		||||
endif # BOARD_ANT_WIRELESS_DEVICE type
 | 
			
		||||
 | 
			
		||||
COMMON_DIR := src/common
 | 
			
		||||
 | 
			
		||||
include $(LOCAL_PATH)/$(ANT_DIR)/Android.mk
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# ANT Application
 | 
			
		||||
@@ -54,7 +63,7 @@ LOCAL_C_INCLUDES:= \
 | 
			
		||||
LOCAL_CFLAGS:= -g -c -W -Wall -O2
 | 
			
		||||
 | 
			
		||||
LOCAL_SRC_FILES:= \
 | 
			
		||||
	$(LOCAL_PATH)/app/ant_app.c
 | 
			
		||||
	app/ant_app.c
 | 
			
		||||
 | 
			
		||||
LOCAL_SHARED_LIBRARIES := \
 | 
			
		||||
	libantradio \
 | 
			
		||||
 
 | 
			
		||||
@@ -14,39 +14,41 @@
 | 
			
		||||
# 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_CFLAGS += -DBOARD_ANT_DEVICE_WL12XX
 | 
			
		||||
else ifeq ($(BOARD_ANT_WIRELESS_DEVICE),"bcm433x")
 | 
			
		||||
LOCAL_CFLAGS += -DBOARD_ANT_DEVICE_BCM433X
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
LOCAL_C_INCLUDES := \
 | 
			
		||||
   $(LOCAL_PATH)/../common/inc \
 | 
			
		||||
   $(LOCAL_PATH)/inc \
 | 
			
		||||
   $(LOCAL_PATH)/src/common/inc \
 | 
			
		||||
   $(LOCAL_PATH)/$(ANT_DIR)/inc \
 | 
			
		||||
   system/bluetooth/bluez-clean-headers \
 | 
			
		||||
 | 
			
		||||
ifeq ($(BOARD_ANT_WIRELESS_POWER),"bluedroid")
 | 
			
		||||
LOCAL_CFLAGS += -DBOARD_HAVE_ANT_WIRELESS
 | 
			
		||||
LOCAL_CFLAGS += \
 | 
			
		||||
   -DBOARD_HAVE_ANT_WIRELESS \
 | 
			
		||||
   -DUSE_EXTERNAL_POWER_LIBRARY \
 | 
			
		||||
 | 
			
		||||
LOCAL_C_INCLUDES += system/bluetooth/bluedroid/include/bluedroid
 | 
			
		||||
endif # BOARD_ANT_WIRELESS_POWER = bluedroid
 | 
			
		||||
 | 
			
		||||
LOCAL_SRC_FILES := \
 | 
			
		||||
   $(COMMON_DIR)/JAntNative.cpp \
 | 
			
		||||
   $(COMMON_DIR)/ant_utils.c \
 | 
			
		||||
   $(ANT_DIR)/ant_native_hci.c \
 | 
			
		||||
   $(ANT_DIR)/ant_rx.c \
 | 
			
		||||
   $(ANT_DIR)/ant_tx.c \
 | 
			
		||||
 | 
			
		||||
# JNI
 | 
			
		||||
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 +=  \
 | 
			
		||||
LOCAL_SHARED_LIBRARIES += \
 | 
			
		||||
   libnativehelper \
 | 
			
		||||
 | 
			
		||||
# chip power
 | 
			
		||||
@@ -63,5 +65,3 @@ LOCAL_MODULE := libantradio
 | 
			
		||||
 | 
			
		||||
include $(BUILD_SHARED_LIBRARY)
 | 
			
		||||
 | 
			
		||||
endif # BOARD_ANT_WIRELESS_DEVICE = "wl12xx"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,26 +1,26 @@
 | 
			
		||||
/*
 | 
			
		||||
* 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.
 | 
			
		||||
*/
 | 
			
		||||
 * 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
 | 
			
		||||
*      This file provides the BlueZ HCI implementation of ant_native.h
 | 
			
		||||
*
 | 
			
		||||
*
 | 
			
		||||
\******************************************************************************/
 | 
			
		||||
@@ -29,13 +29,15 @@
 | 
			
		||||
#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"
 | 
			
		||||
 | 
			
		||||
#if USE_EXTERNAL_POWER_LIBRARY
 | 
			
		||||
#include "antradio_power.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "ant_rx.h"
 | 
			
		||||
#include "ant_tx.h"
 | 
			
		||||
#include "ant_hciutils.h"
 | 
			
		||||
@@ -44,7 +46,7 @@
 | 
			
		||||
static pthread_mutex_t         txLock;
 | 
			
		||||
pthread_mutex_t                enableLock;
 | 
			
		||||
 | 
			
		||||
static ANTRadioEnabledStatus radio_status = RADIO_STATUS_DISABLED;
 | 
			
		||||
ANTRadioEnabledStatus radio_status = RADIO_STATUS_DISABLED;
 | 
			
		||||
ANTRadioEnabledStatus get_and_set_radio_status(void);
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
@@ -238,6 +240,11 @@ ANTStatus ant_enable_radio(void)
 | 
			
		||||
   }
 | 
			
		||||
   ANT_DEBUG_V("got enableLock in %s", __FUNCTION__);
 | 
			
		||||
 | 
			
		||||
   if(RADIO_STATUS_DISABLED == radio_status)
 | 
			
		||||
   {
 | 
			
		||||
      radio_status = RADIO_STATUS_ENABLING;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   ANT_DEBUG_V("getting txLock in %s", __FUNCTION__);
 | 
			
		||||
   lockResult = pthread_mutex_lock(&txLock);
 | 
			
		||||
   if (lockResult)
 | 
			
		||||
@@ -258,15 +265,23 @@ ANTStatus ant_enable_radio(void)
 | 
			
		||||
         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 USE_EXTERNAL_POWER_LIBRARY
 | 
			
		||||
      if (RxParams.pfStateCallback)
 | 
			
		||||
         RxParams.pfStateCallback(radio_status);
 | 
			
		||||
#endif
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
#if USE_EXTERNAL_POWER_LIBRARY
 | 
			
		||||
   result = ant_enable();
 | 
			
		||||
 | 
			
		||||
   ANT_DEBUG_D("ant_enable() result is %d", result);
 | 
			
		||||
#else
 | 
			
		||||
   result = 0;
 | 
			
		||||
#endif
 | 
			
		||||
   if (result == 0)
 | 
			
		||||
   {
 | 
			
		||||
      if (RxParams.thread)
 | 
			
		||||
@@ -286,6 +301,7 @@ ANTStatus ant_enable_radio(void)
 | 
			
		||||
         else
 | 
			
		||||
         {
 | 
			
		||||
            result_status = ANT_STATUS_SUCCESS;
 | 
			
		||||
#if USE_EXTERNAL_POWER_LIBRARY
 | 
			
		||||
            if (radio_status == RADIO_STATUS_ENABLING)
 | 
			
		||||
            {
 | 
			
		||||
               ANT_DEBUG_I("radio_status (%d -> %d)", radio_status, RADIO_STATUS_ENABLED);
 | 
			
		||||
@@ -298,6 +314,9 @@ ANTStatus ant_enable_radio(void)
 | 
			
		||||
            {
 | 
			
		||||
               ANT_WARN("radio was already enabled but rx thread was not running");
 | 
			
		||||
            }
 | 
			
		||||
#else
 | 
			
		||||
            radio_status = RADIO_STATUS_ENABLED;
 | 
			
		||||
#endif
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
@@ -306,9 +325,11 @@ ANTStatus ant_enable_radio(void)
 | 
			
		||||
      result_status = ANT_STATUS_TRANSPORT_INIT_ERR;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   if (result_status != ANT_STATUS_SUCCESS)
 | 
			
		||||
   if (result_status != ANT_STATUS_SUCCESS) // ant_enable() or rx thread creating failed
 | 
			
		||||
   {
 | 
			
		||||
#if USE_EXTERNAL_POWER_LIBRARY
 | 
			
		||||
      ant_disable();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
      switch (get_and_set_radio_status())
 | 
			
		||||
      {
 | 
			
		||||
@@ -333,6 +354,22 @@ ANTStatus ant_enable_radio(void)
 | 
			
		||||
   return result_status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
//  ant_radio_hard_reset
 | 
			
		||||
//
 | 
			
		||||
//  Does nothing as Hard Reset is not supported.
 | 
			
		||||
//
 | 
			
		||||
//  Parameters:
 | 
			
		||||
//      -
 | 
			
		||||
//
 | 
			
		||||
//  Returns:
 | 
			
		||||
//      ANT_NOT_SUPPORTED
 | 
			
		||||
//
 | 
			
		||||
//  Psuedocode:
 | 
			
		||||
/*
 | 
			
		||||
RESULT = NOT SUPPORTED
 | 
			
		||||
*/
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
ANTStatus ant_radio_hard_reset(void)
 | 
			
		||||
{
 | 
			
		||||
   ANTStatus result_status = ANT_STATUS_NOT_SUPPORTED;
 | 
			
		||||
@@ -406,6 +443,7 @@ ANTStatus ant_disable_radio(void)
 | 
			
		||||
   }
 | 
			
		||||
   ANT_DEBUG_V("got txLock in %s", __FUNCTION__);
 | 
			
		||||
 | 
			
		||||
#if USE_EXTERNAL_POWER_LIBRARY
 | 
			
		||||
   if (get_and_set_radio_status() != RADIO_STATUS_DISABLED)
 | 
			
		||||
   {
 | 
			
		||||
      ANT_DEBUG_I("radio_status (%d -> %d)", radio_status, RADIO_STATUS_DISABLING);
 | 
			
		||||
@@ -416,7 +454,11 @@ ANTStatus ant_disable_radio(void)
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   result = ant_disable();
 | 
			
		||||
 | 
			
		||||
   ANT_DEBUG_D("ant_disable() result is %d", result);
 | 
			
		||||
#else
 | 
			
		||||
   radio_status = RADIO_STATUS_DISABLED;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
   // If rx thread exists ( != 0)
 | 
			
		||||
   if (RxParams.thread)
 | 
			
		||||
@@ -512,7 +554,7 @@ ANTRadioEnabledStatus ant_radio_enabled_status(void)
 | 
			
		||||
//  change internal state from enabled, disabled, or unknown to any of these
 | 
			
		||||
//  three on errors.
 | 
			
		||||
//
 | 
			
		||||
//  Paramerters:
 | 
			
		||||
//  Parameters:
 | 
			
		||||
//      -
 | 
			
		||||
//
 | 
			
		||||
//  Returns:
 | 
			
		||||
@@ -521,9 +563,9 @@ ANTRadioEnabledStatus ant_radio_enabled_status(void)
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
ANTRadioEnabledStatus get_and_set_radio_status(void)
 | 
			
		||||
{
 | 
			
		||||
   ANTRadioEnabledStatus orig_status = radio_status;
 | 
			
		||||
   ANT_FUNC_START();
 | 
			
		||||
 | 
			
		||||
#if USE_EXTERNAL_POWER_LIBRARY
 | 
			
		||||
   ANTRadioEnabledStatus orig_status = radio_status;
 | 
			
		||||
   switch (ant_is_enabled())
 | 
			
		||||
   {
 | 
			
		||||
      case 0:
 | 
			
		||||
@@ -544,7 +586,7 @@ ANTRadioEnabledStatus get_and_set_radio_status(void)
 | 
			
		||||
      if (RxParams.pfStateCallback)
 | 
			
		||||
         RxParams.pfStateCallback(radio_status);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
   ANT_FUNC_END();
 | 
			
		||||
   return radio_status;
 | 
			
		||||
}
 | 
			
		||||
@@ -556,7 +598,7 @@ ANTRadioEnabledStatus get_and_set_radio_status(void)
 | 
			
		||||
//
 | 
			
		||||
//  Parameters:
 | 
			
		||||
//      rx_callback_func   the ANTNativeANTEventCb function to be used
 | 
			
		||||
//                         for recieved messages.
 | 
			
		||||
//                         for received messages.
 | 
			
		||||
//
 | 
			
		||||
//  Returns:
 | 
			
		||||
//          ANT_STATUS_SUCCESS
 | 
			
		||||
@@ -569,13 +611,11 @@ ANTRadioEnabledStatus get_and_set_radio_status(void)
 | 
			
		||||
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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -586,7 +626,7 @@ ANTStatus set_ant_rx_callback(ANTNativeANTEventCb rx_callback_func)
 | 
			
		||||
//
 | 
			
		||||
//  Parameters:
 | 
			
		||||
//      state_callback_func   the ANTNativeANTStateCb function to be used
 | 
			
		||||
//                            for recieved state changes.
 | 
			
		||||
//                            for received state changes.
 | 
			
		||||
//
 | 
			
		||||
//  Returns:
 | 
			
		||||
//          ANT_STATUS_SUCCESS
 | 
			
		||||
@@ -599,7 +639,6 @@ ANTStatus set_ant_rx_callback(ANTNativeANTEventCb rx_callback_func)
 | 
			
		||||
ANTStatus set_ant_state_callback(ANTNativeANTStateCb state_callback_func)
 | 
			
		||||
{
 | 
			
		||||
   ANTStatus status = ANT_STATUS_SUCCESS;
 | 
			
		||||
 | 
			
		||||
   ANT_FUNC_START();
 | 
			
		||||
 | 
			
		||||
   RxParams.pfStateCallback = state_callback_func;
 | 
			
		||||
 
 | 
			
		||||
@@ -20,13 +20,12 @@
 | 
			
		||||
*   FILE NAME:      ant_rx.c
 | 
			
		||||
*
 | 
			
		||||
*   BRIEF:
 | 
			
		||||
*      This file Implements the receive thread for an HCI implementation
 | 
			
		||||
*      This file implements the receive thread for a BlueZ HCI implementation
 | 
			
		||||
*      using Vendor Specific messages.
 | 
			
		||||
*
 | 
			
		||||
*
 | 
			
		||||
\******************************************************************************/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define _GNU_SOURCE /* needed for PTHREAD_MUTEX_RECURSIVE */
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
@@ -44,23 +43,24 @@
 | 
			
		||||
#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_types.h"
 | 
			
		||||
 | 
			
		||||
#if USE_EXTERNAL_POWER_LIBRARY
 | 
			
		||||
#include "antradio_power.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#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,
 | 
			
		||||
@@ -70,6 +70,10 @@ ANTHCIRxParams RxParams = {
 | 
			
		||||
 | 
			
		||||
extern pthread_mutex_t enableLock;
 | 
			
		||||
extern ANTRadioEnabledStatus get_and_set_radio_status(void);
 | 
			
		||||
#ifndef USE_EXTERNAL_POWER_LIBRARY
 | 
			
		||||
extern ANTRadioEnabledStatus radio_status;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This thread opens a Bluez HCI socket and waits for ANT messages.
 | 
			
		||||
 */
 | 
			
		||||
@@ -80,6 +84,7 @@ void *ANTHCIRxThread(void *pvHCIDevice)
 | 
			
		||||
   int len;
 | 
			
		||||
   unsigned char buf[HCI_MAX_EVENT_SIZE];
 | 
			
		||||
   int result;
 | 
			
		||||
   struct hci_filter eventVendorFilter;
 | 
			
		||||
   ANT_FUNC_START();
 | 
			
		||||
 | 
			
		||||
   (void)pvHCIDevice; //unused waring
 | 
			
		||||
@@ -95,8 +100,12 @@ void *ANTHCIRxThread(void *pvHCIDevice)
 | 
			
		||||
      goto out;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   if (setsockopt(rxSocket, SOL_HCI, HCI_FILTER, &EVT_PKT_VENDOR_FILTER,
 | 
			
		||||
                                             sizeof(EVT_PKT_VENDOR_FILTER)) < 0)
 | 
			
		||||
   eventVendorFilter.type_mask = TYPE_MASK_EVENT_PACKET;
 | 
			
		||||
   eventVendorFilter.event_mask[0] = 0;
 | 
			
		||||
   eventVendorFilter.event_mask[1] = EVENT_MASK_1_EVENT_VENDOR;
 | 
			
		||||
   eventVendorFilter.opcode = htobs(ANT_EVENT_VENDOR_CODE);
 | 
			
		||||
 | 
			
		||||
   if (setsockopt(rxSocket, SOL_HCI, HCI_FILTER, &eventVendorFilter, sizeof(eventVendorFilter)) < 0)
 | 
			
		||||
   {
 | 
			
		||||
      ANT_ERROR("failed to set socket options: %s", strerror(errno));
 | 
			
		||||
 | 
			
		||||
@@ -150,84 +159,23 @@ void *ANTHCIRxThread(void *pvHCIDevice)
 | 
			
		||||
         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)
 | 
			
		||||
      hci_event_packet_t *event_packet = (hci_event_packet_t *)buf;
 | 
			
		||||
      int hci_payload_len = validate_hci_event_packet(event_packet, len);
 | 
			
		||||
      if (hci_payload_len == -1)
 | 
			
		||||
      {
 | 
			
		||||
          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);
 | 
			
		||||
         // part of the message is incorrect, ignore it. validate_event_packet will log error
 | 
			
		||||
         continue;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (len != (buf[2] + 3))
 | 
			
		||||
      ANT_SERIAL(event_packet->hci_payload, hci_payload_len, 'R');
 | 
			
		||||
 | 
			
		||||
      if(RxParams.pfRxCallback != NULL)
 | 
			
		||||
      {
 | 
			
		||||
         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");
 | 
			
		||||
         }
 | 
			
		||||
         RxParams.pfRxCallback(hci_payload_len, event_packet->hci_payload);
 | 
			
		||||
      }
 | 
			
		||||
      else
 | 
			
		||||
      {
 | 
			
		||||
         ANT_DEBUG_V("Non-Event Packet, Ignoring");
 | 
			
		||||
         ANT_ERROR("Can't send rx message - no callback registered");
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
@@ -238,10 +186,14 @@ close:
 | 
			
		||||
   if (result == 0)
 | 
			
		||||
   {
 | 
			
		||||
      ANT_DEBUG_W("rx thread socket has unexpectedly crashed");
 | 
			
		||||
#if USE_EXTERNAL_POWER_LIBRARY
 | 
			
		||||
      if (RxParams.pfStateCallback)
 | 
			
		||||
         RxParams.pfStateCallback(RADIO_STATUS_DISABLING);
 | 
			
		||||
      ant_disable();
 | 
			
		||||
      get_and_set_radio_status();
 | 
			
		||||
#else
 | 
			
		||||
      radio_status = RADIO_STATUS_DISABLED;
 | 
			
		||||
#endif
 | 
			
		||||
      RxParams.thread = 0;
 | 
			
		||||
      pthread_mutex_unlock(&enableLock);
 | 
			
		||||
   }
 | 
			
		||||
 
 | 
			
		||||
@@ -20,8 +20,8 @@
 | 
			
		||||
*   FILE NAME:      ant_tx.c
 | 
			
		||||
*
 | 
			
		||||
*   BRIEF:
 | 
			
		||||
*      This file Implements the transmit functionality for an HCI implementation
 | 
			
		||||
*      using Vendor Specific messages.
 | 
			
		||||
*      This file Implements the transmit functionality for a BlueZ HCI
 | 
			
		||||
*      implementation using Vendor Specific messages.
 | 
			
		||||
*
 | 
			
		||||
*
 | 
			
		||||
\******************************************************************************/
 | 
			
		||||
@@ -39,31 +39,35 @@
 | 
			
		||||
#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;
 | 
			
		||||
   struct hci_filter commandCompleteFilter;
 | 
			
		||||
   ANT_FUNC_START();
 | 
			
		||||
 | 
			
		||||
   socket = create_hci_sock();
 | 
			
		||||
   
 | 
			
		||||
   if (socket < 0) 
 | 
			
		||||
 | 
			
		||||
   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_DEBUG_D("socket handle %#x", socket);
 | 
			
		||||
 | 
			
		||||
      commandCompleteFilter.type_mask = TYPE_MASK_EVENT_PACKET;
 | 
			
		||||
      commandCompleteFilter.event_mask[0] = EVENT_MASK_0_COMMAND_COMPLETE;
 | 
			
		||||
      commandCompleteFilter.event_mask[1] = 0;
 | 
			
		||||
      commandCompleteFilter.opcode = htobs(ANT_COMMAND_OPCODE);
 | 
			
		||||
 | 
			
		||||
      if (setsockopt(socket, SOL_HCI, HCI_FILTER, &commandCompleteFilter, sizeof(commandCompleteFilter)) < 0)
 | 
			
		||||
      {
 | 
			
		||||
         ANT_ERROR("failed to set socket options: %s", strerror(errno));
 | 
			
		||||
         close(socket);
 | 
			
		||||
@@ -81,7 +85,7 @@ void ant_close_tx_transport(int socket)
 | 
			
		||||
 | 
			
		||||
   if(0 < socket)
 | 
			
		||||
   {
 | 
			
		||||
      if (0 == close(socket)) 
 | 
			
		||||
      if (0 == close(socket))
 | 
			
		||||
      {
 | 
			
		||||
         ANT_DEBUG_D("closed hci device (socket handle=%#x)", socket);
 | 
			
		||||
      }
 | 
			
		||||
@@ -176,17 +180,11 @@ ANTStatus write_data(ANT_U8 ant_message[], int ant_message_len)
 | 
			
		||||
   ANT_BOOL retry = ANT_FALSE;
 | 
			
		||||
   int bytes_written;
 | 
			
		||||
   struct iovec iov[2];
 | 
			
		||||
   hci_vendor_cmd_packet_t hci_header;
 | 
			
		||||
   ANT_U16 hci_opcode;
 | 
			
		||||
   hci_command_vendor_header_t hci_header;
 | 
			
		||||
 | 
			
		||||
   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);
 | 
			
		||||
   create_command_header(&hci_header, ant_message_len);
 | 
			
		||||
 | 
			
		||||
   iov[0].iov_base = &hci_header;
 | 
			
		||||
   iov[0].iov_len = sizeof(hci_header);
 | 
			
		||||
@@ -257,9 +255,8 @@ 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_U8 buf[HCI_MAX_EVENT_SIZE];
 | 
			
		||||
 | 
			
		||||
   ANT_FUNC_START();
 | 
			
		||||
   ANT_DEBUG_V("reading off socket %#x", socket);
 | 
			
		||||
@@ -272,82 +269,62 @@ ANTStatus get_command_complete_result(int socket)
 | 
			
		||||
 | 
			
		||||
      ANT_ERROR("failed to read socket. error: %s", strerror(errno));
 | 
			
		||||
 | 
			
		||||
      ret = ANT_STATUS_FAILED;
 | 
			
		||||
      status = 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])
 | 
			
		||||
   // validate that we have a single command complete packet
 | 
			
		||||
   if (len != sizeof(hci_command_complete_packet_t))
 | 
			
		||||
   {
 | 
			
		||||
      ANT_DEBUG_D("Received Event Packet");
 | 
			
		||||
       status = ANT_STATUS_FAILED;
 | 
			
		||||
   }
 | 
			
		||||
   else
 | 
			
		||||
   {
 | 
			
		||||
      hci_command_complete_packet_t *command_complete = (hci_command_complete_packet_t *)buf;
 | 
			
		||||
 | 
			
		||||
      if(EVT_CMD_COMPLETE == buf[1])
 | 
			
		||||
      if(command_complete->packet_type == HCI_EVENT_PKT)
 | 
			
		||||
      {
 | 
			
		||||
         if(len < HCI_EVENT_OVERHEAD_SIZE) 
 | 
			
		||||
         ANT_DEBUG_D("Received Event Packet");
 | 
			
		||||
 | 
			
		||||
         if(command_complete->event_header.evt == EVT_CMD_COMPLETE)
 | 
			
		||||
         {
 | 
			
		||||
            status = ANT_STATUS_FAILED;
 | 
			
		||||
            ANT_U16 opcode = ANT_UTILS_LEtoHost16((ANT_U8 *)&command_complete->command_complete_hdr.opcode);
 | 
			
		||||
            if(opcode == ANT_COMMAND_OPCODE)
 | 
			
		||||
            {
 | 
			
		||||
               ANT_DEBUG_V("Received COMMAND COMPLETE");
 | 
			
		||||
               ucResult = command_complete->response;
 | 
			
		||||
 | 
			
		||||
               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("Command complete has wrong opcode, this should have been filtered out");
 | 
			
		||||
            }
 | 
			
		||||
         }
 | 
			
		||||
         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");
 | 
			
		||||
            }
 | 
			
		||||
            ANT_DEBUG_W("Event is not a command complete, this should have been filtered out");
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
      else
 | 
			
		||||
      {
 | 
			
		||||
         ANT_DEBUG_W("Other Event Packet, Should filter out");
 | 
			
		||||
         ANT_DEBUG_W("Other Event Packet, this should have been filtered out");
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,25 +2,26 @@
 | 
			
		||||
 * 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  
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
/******************************************************************************\
 | 
			
		||||
*
 | 
			
		||||
*   FILE NAME:      ANT_Framing.h
 | 
			
		||||
*   FILE NAME:      ant_framing.h
 | 
			
		||||
*
 | 
			
		||||
*   BRIEF:          
 | 
			
		||||
*		This file defines ANT specific HCI values used by the ANT chip.
 | 
			
		||||
*   BRIEF:
 | 
			
		||||
*      This file defines ANT specific HCI values used by the ANT chip with a
 | 
			
		||||
*      shared BlueZ HCI transport.
 | 
			
		||||
*
 | 
			
		||||
*
 | 
			
		||||
\******************************************************************************/
 | 
			
		||||
@@ -28,23 +29,167 @@
 | 
			
		||||
#ifndef __ANT_HCIFRAMING_H
 | 
			
		||||
#define __ANT_HCIFRAMING_H
 | 
			
		||||
 | 
			
		||||
#ifdef BOARD_ANT_DEVICE_WILINK
 | 
			
		||||
#if defined(BOARD_ANT_DEVICE_WL12XX)
 | 
			
		||||
 | 
			
		||||
/* Number to used by the VS Parameters Len field */
 | 
			
		||||
#define ANT_NATIVE_HCI_VS_PARMS_LEN_FIELD_LEN    (2)
 | 
			
		||||
#define ANT_COMMAND_OPCODE                         0xFDD1
 | 
			
		||||
#define ANT_EVENT_VENDOR_CODE                      0x0500
 | 
			
		||||
 | 
			
		||||
#define HCI_CMD_ANT_MESSAGE_WRITE                ((ANT_U16)0x01D1)
 | 
			
		||||
typedef struct {
 | 
			
		||||
   ANT_U16                    vendor_msg_len;
 | 
			
		||||
} __attribute__ ((packed)) hci_cmd_vendor_hdr_t;
 | 
			
		||||
#define HCI_COMMAND_VENDOR_HDR_SIZE                2
 | 
			
		||||
 | 
			
		||||
#define HCI_CMD_OPCODE_ANT_LSB                   0xD1
 | 
			
		||||
#define HCI_CMD_OPCODE_ANT_MSB                   0xFD
 | 
			
		||||
typedef struct {
 | 
			
		||||
   ANT_U16                    vendor_code;
 | 
			
		||||
   ANT_U16                    vendor_msg_len;
 | 
			
		||||
} __attribute__ ((packed)) hci_evt_vendor_hdr_t;
 | 
			
		||||
#define HCI_EVENT_VENDOR_HDR_SIZE                  4
 | 
			
		||||
 | 
			
		||||
#define HCI_VSOP_ANT_LSB                         0x00
 | 
			
		||||
#define HCI_VSOP_ANT_MSB                         0x05
 | 
			
		||||
#elif defined(BOARD_ANT_DEVICE_BCM433X)
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
#define ANT_COMMAND_OPCODE                         0xFCEC
 | 
			
		||||
#define ANT_EVENT_VENDOR_CODE                      0x2D
 | 
			
		||||
 | 
			
		||||
#error "Board ANT Device Type not recognised"
 | 
			
		||||
typedef struct {
 | 
			
		||||
   ANT_U8                     command_id_padding;
 | 
			
		||||
} __attribute__ ((packed)) hci_cmd_vendor_hdr_t;
 | 
			
		||||
#define HCI_COMMAND_VENDOR_HDR_SIZE                1
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
   ANT_U8                     vendor_code;
 | 
			
		||||
   ANT_U8                     status;
 | 
			
		||||
} __attribute__ ((packed)) hci_evt_vendor_hdr_t;
 | 
			
		||||
#define HCI_EVENT_VENDOR_HDR_SIZE                  2
 | 
			
		||||
 | 
			
		||||
#define  COMMAND_ID_PADDING                        0xFF
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <bluetooth/bluetooth.h>
 | 
			
		||||
#include <bluetooth/hci.h>
 | 
			
		||||
 | 
			
		||||
#include "ant_native.h"
 | 
			
		||||
#include "ant_types.h"
 | 
			
		||||
#include "ant_utils.h"
 | 
			
		||||
 | 
			
		||||
#define HCI_EVENT_HEADER_OVERHEAD (HCI_TYPE_LEN + HCI_EVENT_HDR_SIZE)
 | 
			
		||||
#define HCI_EVENT_TOTAL_OVERHEAD (HCI_EVENT_HEADER_OVERHEAD + HCI_EVENT_VENDOR_HDR_SIZE)
 | 
			
		||||
 | 
			
		||||
#define TYPE_MASK_EVENT_PACKET                     0x00000010
 | 
			
		||||
#define EVENT_MASK_0_COMMAND_COMPLETE              0x00004000
 | 
			
		||||
#define EVENT_MASK_1_EVENT_VENDOR                  0x80000000
 | 
			
		||||
 | 
			
		||||
// -------------------------------------------------
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
   ANT_U8                     packet_type;         // HCI_COMMAND_PKT
 | 
			
		||||
   hci_command_hdr            command_header;      // from hci.h
 | 
			
		||||
   hci_cmd_vendor_hdr_t       vendor_header;
 | 
			
		||||
} __attribute__ ((packed)) hci_command_vendor_header_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
   ANT_U8                     packet_type;         // HCI_EVENT_PKT
 | 
			
		||||
   hci_event_hdr              event_header;        // from hci.h
 | 
			
		||||
   hci_evt_vendor_hdr_t       vendor_header;
 | 
			
		||||
   ANT_U8                     hci_payload[HCI_MAX_EVENT_SIZE];
 | 
			
		||||
} __attribute__ ((packed)) hci_event_packet_t;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
   ANT_U8                     packet_type;         // HCI_EVENT_PKT
 | 
			
		||||
   hci_event_hdr              event_header;        // from hci.h
 | 
			
		||||
   evt_cmd_complete           command_complete_hdr;// from hci.h
 | 
			
		||||
   ANT_U8                     response;
 | 
			
		||||
} __attribute__ ((packed)) hci_command_complete_packet_t;
 | 
			
		||||
 | 
			
		||||
// -------------------------------------------------
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @param header the struct to fill with chip specific hci header
 | 
			
		||||
 * @param ant_message_len total ant length, size, id, and data
 | 
			
		||||
 */
 | 
			
		||||
static inline void create_command_header(hci_command_vendor_header_t *header, ANT_U8 ant_message_len)
 | 
			
		||||
{
 | 
			
		||||
   header->packet_type = HCI_COMMAND_PKT;
 | 
			
		||||
   header->command_header.opcode = htobs(ANT_COMMAND_OPCODE);
 | 
			
		||||
   header->command_header.plen = ant_message_len + HCI_COMMAND_VENDOR_HDR_SIZE;
 | 
			
		||||
#if defined(BOARD_ANT_DEVICE_WL12XX)
 | 
			
		||||
   header->vendor_header.vendor_msg_len = htobs(ant_message_len);
 | 
			
		||||
#elif defined(BOARD_ANT_DEVICE_BCM433X)
 | 
			
		||||
   header->vendor_header.command_id_padding = COMMAND_ID_PADDING;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @param packet the struct to check if is an ANT hci payload
 | 
			
		||||
 * @param packet_len the total length of the packet
 | 
			
		||||
 * @return 0 if valid, -1 if not valid
 | 
			
		||||
 */
 | 
			
		||||
static inline int validate_hci_event_vendor(hci_event_packet_t *packet, int packet_len)
 | 
			
		||||
{
 | 
			
		||||
#if defined(BOARD_ANT_DEVICE_WL12XX)
 | 
			
		||||
   ANT_U16 vendor_code = ANT_UTILS_LEtoHost16((ANT_U8 *)&packet->vendor_header.vendor_code);
 | 
			
		||||
#elif defined(BOARD_ANT_DEVICE_BCM433X)
 | 
			
		||||
   ANT_U8 vendor_code = packet->vendor_header.vendor_code;
 | 
			
		||||
#endif
 | 
			
		||||
   if (vendor_code != ANT_EVENT_VENDOR_CODE) {
 | 
			
		||||
      ANT_ERROR("HCI packet vendor event code is not ANT");
 | 
			
		||||
      return -1;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
#if defined(BOARD_ANT_DEVICE_WL12XX)
 | 
			
		||||
   ANT_U16 vendor_msg_len = ANT_UTILS_LEtoHost16((ANT_U8 *)&packet->vendor_header.vendor_msg_len);
 | 
			
		||||
   if (packet_len != vendor_msg_len + HCI_EVENT_TOTAL_OVERHEAD) {
 | 
			
		||||
      ANT_ERROR("HCI packet length (%d) should be %d bytes more than HCI payload length (%d)",
 | 
			
		||||
              packet_len, HCI_EVENT_TOTAL_OVERHEAD, vendor_msg_len);
 | 
			
		||||
      return -1;
 | 
			
		||||
   }
 | 
			
		||||
#elif defined(BOARD_ANT_DEVICE_BCM433X)
 | 
			
		||||
   (void)packet_len; // unused warning
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
   return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @param packet the struct to validate
 | 
			
		||||
 * @param packet_len the total length of the packet
 | 
			
		||||
 * @return -1 if not valid, or length of the ANT hci payload
 | 
			
		||||
 */
 | 
			
		||||
static inline int validate_hci_event_packet(hci_event_packet_t *packet, int packet_len)
 | 
			
		||||
{
 | 
			
		||||
   // Make sure we have at the minimum the hci header, vendor header, and ANT size/id bytes
 | 
			
		||||
   if (packet_len < HCI_EVENT_TOTAL_OVERHEAD) {
 | 
			
		||||
      ANT_ERROR("HCI packet length (%d) is less than minimum (%d)",
 | 
			
		||||
              packet_len, HCI_EVENT_TOTAL_OVERHEAD);
 | 
			
		||||
      return -1;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   if (packet->packet_type != HCI_EVENT_PKT) {
 | 
			
		||||
      ANT_ERROR("HCI packet is not an event packet");
 | 
			
		||||
      return -1;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   if (packet->event_header.evt != EVT_VENDOR) {
 | 
			
		||||
      ANT_ERROR("HCI packet is not a vendor event");
 | 
			
		||||
      return -1;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   if (packet_len != packet->event_header.plen + HCI_EVENT_HEADER_OVERHEAD) {
 | 
			
		||||
      ANT_ERROR("HCI packet length (%d) should be %d bytes more than HCI event length (%d)",
 | 
			
		||||
              packet_len, HCI_EVENT_HDR_SIZE, packet->event_header.plen);
 | 
			
		||||
      return -1;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   if (validate_hci_event_vendor(packet, packet_len) == -1)
 | 
			
		||||
   {
 | 
			
		||||
      return -1;
 | 
			
		||||
   }
 | 
			
		||||
   else
 | 
			
		||||
   {
 | 
			
		||||
      // return HCI payload len
 | 
			
		||||
      return packet_len - HCI_EVENT_TOTAL_OVERHEAD;
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* __ANT_HCIFRAMING_H */
 | 
			
		||||
 
 | 
			
		||||
@@ -17,10 +17,10 @@
 | 
			
		||||
 */
 | 
			
		||||
/******************************************************************************\
 | 
			
		||||
*
 | 
			
		||||
*   FILE NAME:      ant_hciuntils.h
 | 
			
		||||
*   FILE NAME:      ant_hciutils.h
 | 
			
		||||
*
 | 
			
		||||
*   BRIEF:
 | 
			
		||||
*		This file defines the utility functions for an HCI implementation
 | 
			
		||||
*      This file defines the utility functions for a Bluetooth HCI implementation
 | 
			
		||||
*
 | 
			
		||||
*
 | 
			
		||||
\******************************************************************************/
 | 
			
		||||
@@ -33,65 +33,9 @@
 | 
			
		||||
#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);
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,8 @@
 | 
			
		||||
*   FILE NAME:      ant_rx.h
 | 
			
		||||
*
 | 
			
		||||
*   BRIEF:
 | 
			
		||||
*		This file defines the receive thread function
 | 
			
		||||
*      This file defines the receive thread function and the ANTHCIRxParams
 | 
			
		||||
*      type for storing the configuration of the receive thread.
 | 
			
		||||
*
 | 
			
		||||
*
 | 
			
		||||
\******************************************************************************/
 | 
			
		||||
@@ -32,6 +33,7 @@
 | 
			
		||||
#include "ant_types.h"
 | 
			
		||||
#include "ant_native.h"
 | 
			
		||||
 | 
			
		||||
// The configuration of a receive thread
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
   //The function to call back with received data
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@
 | 
			
		||||
*   FILE NAME:      ant_tx.h
 | 
			
		||||
*
 | 
			
		||||
*   BRIEF:
 | 
			
		||||
*		This file defines the transmit function
 | 
			
		||||
*      This file defines the utility functions used by the transmit function.
 | 
			
		||||
*
 | 
			
		||||
*
 | 
			
		||||
\******************************************************************************/
 | 
			
		||||
 
 | 
			
		||||
@@ -1,424 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1,48 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 */
 | 
			
		||||
 | 
			
		||||
@@ -1,50 +0,0 @@
 | 
			
		||||
#
 | 
			
		||||
# 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"
 | 
			
		||||
@@ -1,389 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1,213 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1,48 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 */
 | 
			
		||||
 | 
			
		||||
@@ -1,73 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 */
 | 
			
		||||
 | 
			
		||||
@@ -1,26 +1,26 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
* 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
 | 
			
		||||
* FILE NAME: ANT_log.h
 | 
			
		||||
*
 | 
			
		||||
*   BRIEF:          
 | 
			
		||||
*		This file defines logging functions
 | 
			
		||||
* BRIEF:
 | 
			
		||||
* This file defines logging functions
 | 
			
		||||
*
 | 
			
		||||
*
 | 
			
		||||
\******************************************************************************/
 | 
			
		||||
@@ -108,11 +108,11 @@
 | 
			
		||||
      #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__)
 | 
			
		||||
   #define OUTPUT_VERBOSE(...)         ALOGV(__VA_ARGS__)
 | 
			
		||||
   #define OUTPUT_DEBUG(...)           ALOGD(__VA_ARGS__)
 | 
			
		||||
   #define OUTPUT_INFO(...)            ALOGI(__VA_ARGS__)
 | 
			
		||||
   #define OUTPUT_WARNING(...)         ALOGW(__VA_ARGS__)
 | 
			
		||||
   #define OUTPUT_ERROR(...)           ALOGE(__VA_ARGS__)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define ANT_WARN(...)                  OUTPUT_WARNING(__VA_ARGS__)
 | 
			
		||||
 
 | 
			
		||||
@@ -40,13 +40,6 @@
 | 
			
		||||
 * 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)
 | 
			
		||||
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 
 | 
			
		||||
@@ -19,8 +19,8 @@
 | 
			
		||||
#ifndef __ANT_VERSION_H
 | 
			
		||||
#define __ANT_VERSION_H
 | 
			
		||||
 | 
			
		||||
#define LIBANT_STACK_MAJOR "0"
 | 
			
		||||
#define LIBANT_STACK_MINOR "7"
 | 
			
		||||
#define LIBANT_STACK_MAJOR "1"
 | 
			
		||||
#define LIBANT_STACK_MINOR "3"
 | 
			
		||||
#define LIBANT_STACK_INCRE "0"
 | 
			
		||||
 | 
			
		||||
#endif // __ANT_VERSION_H
 | 
			
		||||
 
 | 
			
		||||
@@ -14,37 +14,42 @@
 | 
			
		||||
# 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_PATH)/src/common/inc \
 | 
			
		||||
   $(LOCAL_PATH)/$(ANT_DIR)/inc \
 | 
			
		||||
 | 
			
		||||
LOCAL_SRC_FILES:= \
 | 
			
		||||
    ../../JAntNative.cpp \
 | 
			
		||||
    ../common/ant_utils.c \
 | 
			
		||||
    ant_native_chardev.c \
 | 
			
		||||
    ant_rx_chardev.c \
 | 
			
		||||
ifeq ($(BOARD_ANT_WIRELESS_DEVICE),"cg29xx")
 | 
			
		||||
LOCAL_C_INCLUDES += \
 | 
			
		||||
   $(ANT_DIR)/ste/cg29xx \
 | 
			
		||||
 | 
			
		||||
#JNI
 | 
			
		||||
else ifeq ($(BOARD_ANT_WIRELESS_DEVICE),"vfs-prerelease")
 | 
			
		||||
LOCAL_C_INCLUDES += \
 | 
			
		||||
   $(ANT_DIR)/prerelease \
 | 
			
		||||
 | 
			
		||||
endif # BOARD_ANT_WIRELESS_DEVICE = "vfs-prerelease"
 | 
			
		||||
 | 
			
		||||
LOCAL_SRC_FILES := \
 | 
			
		||||
   $(COMMON_DIR)/JAntNative.cpp \
 | 
			
		||||
   $(COMMON_DIR)/ant_utils.c \
 | 
			
		||||
   $(ANT_DIR)/ant_native_chardev.c \
 | 
			
		||||
   $(ANT_DIR)/ant_rx_chardev.c \
 | 
			
		||||
 | 
			
		||||
# JNI
 | 
			
		||||
LOCAL_C_INCLUDE += $(JNI_H_INCLUDE)
 | 
			
		||||
 | 
			
		||||
LOCAL_SHARED_LIBRARIES += \
 | 
			
		||||
    libnativehelper
 | 
			
		||||
   libnativehelper \
 | 
			
		||||
 | 
			
		||||
# logging
 | 
			
		||||
LOCAL_SHARED_LIBRARIES += \
 | 
			
		||||
    libcutils
 | 
			
		||||
   libcutils \
 | 
			
		||||
 | 
			
		||||
LOCAL_MODULE_TAGS := optional
 | 
			
		||||
LOCAL_PRELINK_MODULE := false
 | 
			
		||||
LOCAL_MODULE := libantradio
 | 
			
		||||
 | 
			
		||||
include $(BUILD_SHARED_LIBRARY)
 | 
			
		||||
 | 
			
		||||
endif # BOARD_ANT_WIRELESS_DEVICE = "chip-B"
 | 
			
		||||
							
								
								
									
										905
									
								
								src/vfs/ant_native_chardev.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										905
									
								
								src/vfs/ant_native_chardev.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,905 @@
 | 
			
		||||
/*
 | 
			
		||||
 * ANT Stack
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2011 Dynastream Innovations
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
/******************************************************************************\
 | 
			
		||||
*
 | 
			
		||||
*   FILE NAME:      ant_native_chardev.c
 | 
			
		||||
*
 | 
			
		||||
*   BRIEF:
 | 
			
		||||
*      This file provides the VFS implementation of ant_native.h
 | 
			
		||||
*      VFS could be Character Device, TTY, etc.
 | 
			
		||||
*
 | 
			
		||||
*
 | 
			
		||||
\******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fcntl.h> /* for open() */
 | 
			
		||||
#include <linux/ioctl.h> /* For hard reset */
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
 | 
			
		||||
#include "ant_types.h"
 | 
			
		||||
#include "ant_native.h"
 | 
			
		||||
#include "ant_version.h"
 | 
			
		||||
 | 
			
		||||
#include "antradio_power.h"
 | 
			
		||||
#include "ant_rx_chardev.h"
 | 
			
		||||
#include "ant_driver_defines.h"
 | 
			
		||||
#include "ant_log.h"
 | 
			
		||||
 | 
			
		||||
#if ANT_HCI_SIZE_SIZE > 1
 | 
			
		||||
#include "ant_utils.h"  // Put HCI Size value across multiple bytes
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define MESG_BROADCAST_DATA_ID               ((ANT_U8)0x4E)
 | 
			
		||||
#define MESG_ACKNOWLEDGED_DATA_ID            ((ANT_U8)0x4F)
 | 
			
		||||
#define MESG_BURST_DATA_ID                   ((ANT_U8)0x50)
 | 
			
		||||
#define MESG_EXT_BROADCAST_DATA_ID           ((ANT_U8)0x5D)
 | 
			
		||||
#define MESG_EXT_ACKNOWLEDGED_DATA_ID        ((ANT_U8)0x5E)
 | 
			
		||||
#define MESG_EXT_BURST_DATA_ID               ((ANT_U8)0x5F)
 | 
			
		||||
#define MESG_ADV_BURST_DATA_ID               ((ANT_U8)0x72)
 | 
			
		||||
 | 
			
		||||
static ant_rx_thread_info_t stRxThreadInfo;
 | 
			
		||||
static pthread_mutex_t stEnabledStatusLock = PTHREAD_MUTEX_INITIALIZER;
 | 
			
		||||
static pthread_mutex_t stFlowControlLock = PTHREAD_MUTEX_INITIALIZER;
 | 
			
		||||
static pthread_cond_t stFlowControlCond = PTHREAD_COND_INITIALIZER;
 | 
			
		||||
ANTNativeANTStateCb g_fnStateCallback;
 | 
			
		||||
 | 
			
		||||
static void ant_channel_init(ant_channel_info_t *pstChnlInfo, const char *pcCharDevName);
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
//  ant_init
 | 
			
		||||
//
 | 
			
		||||
//  Initialises the native environment.
 | 
			
		||||
//
 | 
			
		||||
//  Parameters:
 | 
			
		||||
//      -
 | 
			
		||||
//
 | 
			
		||||
//  Returns:
 | 
			
		||||
//      ANT_STATUS_SUCCESS
 | 
			
		||||
//
 | 
			
		||||
//  Psuedocode:
 | 
			
		||||
/*
 | 
			
		||||
Set variables to defaults
 | 
			
		||||
Initialise each supported path to chip
 | 
			
		||||
RESULT = ANT_STATUS_SUCCESS
 | 
			
		||||
*/
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
ANTStatus ant_init(void)
 | 
			
		||||
{
 | 
			
		||||
   ANTStatus status = ANT_STATUS_FAILED;
 | 
			
		||||
   ANT_FUNC_START();
 | 
			
		||||
 | 
			
		||||
   stRxThreadInfo.stRxThread = 0;
 | 
			
		||||
   stRxThreadInfo.ucRunThread = 0;
 | 
			
		||||
   stRxThreadInfo.ucChipResetting = 0;
 | 
			
		||||
   stRxThreadInfo.pstEnabledStatusLock = &stEnabledStatusLock;
 | 
			
		||||
   g_fnStateCallback = 0;
 | 
			
		||||
 | 
			
		||||
#ifdef ANT_DEVICE_NAME // Single transport path
 | 
			
		||||
   ant_channel_init(&stRxThreadInfo.astChannels[SINGLE_CHANNEL], ANT_DEVICE_NAME);
 | 
			
		||||
#else // Separate data/command paths
 | 
			
		||||
   ant_channel_init(&stRxThreadInfo.astChannels[COMMAND_CHANNEL], ANT_COMMANDS_DEVICE_NAME);
 | 
			
		||||
   ant_channel_init(&stRxThreadInfo.astChannels[DATA_CHANNEL], ANT_DATA_DEVICE_NAME);
 | 
			
		||||
#endif // Separate data/command paths
 | 
			
		||||
 | 
			
		||||
   status = ANT_STATUS_SUCCESS;
 | 
			
		||||
 | 
			
		||||
   ANT_FUNC_END();
 | 
			
		||||
   return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
//  ant_deinit
 | 
			
		||||
//
 | 
			
		||||
//  Doesn't actually do anything.
 | 
			
		||||
//
 | 
			
		||||
//  Parameters:
 | 
			
		||||
//      -
 | 
			
		||||
//
 | 
			
		||||
//  Returns:
 | 
			
		||||
//      ANT_STATUS_SUCCESS
 | 
			
		||||
//
 | 
			
		||||
//  Psuedocode:
 | 
			
		||||
/*
 | 
			
		||||
RESULT = SUCCESS
 | 
			
		||||
*/
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
ANTStatus ant_deinit(void)
 | 
			
		||||
{
 | 
			
		||||
   ANTStatus result_status = ANT_STATUS_FAILED;
 | 
			
		||||
   ANT_FUNC_START();
 | 
			
		||||
 | 
			
		||||
   result_status = ANT_STATUS_SUCCESS;
 | 
			
		||||
 | 
			
		||||
   ANT_FUNC_END();
 | 
			
		||||
   return result_status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
//  ant_enable_radio
 | 
			
		||||
//
 | 
			
		||||
//  Powers on the ANT part and initialises the transport to the chip.
 | 
			
		||||
//  Changes occur in part implementing ant_enable() call
 | 
			
		||||
//
 | 
			
		||||
//  Parameters:
 | 
			
		||||
//      -
 | 
			
		||||
//
 | 
			
		||||
//  Returns:
 | 
			
		||||
//      Success:
 | 
			
		||||
//          ANT_STATUS_SUCCESS
 | 
			
		||||
//      Failures:
 | 
			
		||||
//          ANT_STATUS_TRANSPORT_INIT_ERR if could not enable
 | 
			
		||||
//          ANT_STATUS_FAILED if failed to get mutex or init rx thread
 | 
			
		||||
//
 | 
			
		||||
//  Psuedocode:
 | 
			
		||||
/*
 | 
			
		||||
LOCK enable_LOCK
 | 
			
		||||
    State callback: STATE = ENABLING
 | 
			
		||||
    ant enable
 | 
			
		||||
    IF ant_enable success
 | 
			
		||||
        State callback: STATE = ENABLED
 | 
			
		||||
        RESULT = SUCCESS
 | 
			
		||||
    ELSE
 | 
			
		||||
        ant disable
 | 
			
		||||
        State callback: STATE = Current state
 | 
			
		||||
        RESULT = FAILURE
 | 
			
		||||
    ENDIF
 | 
			
		||||
UNLOCK
 | 
			
		||||
*/
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
ANTStatus ant_enable_radio(void)
 | 
			
		||||
{
 | 
			
		||||
   int iLockResult;
 | 
			
		||||
   ANTStatus result_status = ANT_STATUS_FAILED;
 | 
			
		||||
   ANT_FUNC_START();
 | 
			
		||||
 | 
			
		||||
   ANT_DEBUG_V("getting stEnabledStatusLock in %s", __FUNCTION__);
 | 
			
		||||
   iLockResult = pthread_mutex_lock(&stEnabledStatusLock);
 | 
			
		||||
   if(iLockResult) {
 | 
			
		||||
      ANT_ERROR("enable failed to get state lock: %s", strerror(iLockResult));
 | 
			
		||||
      goto out;
 | 
			
		||||
   }
 | 
			
		||||
   ANT_DEBUG_V("got stEnabledStatusLock in %s", __FUNCTION__);
 | 
			
		||||
 | 
			
		||||
   if (g_fnStateCallback) {
 | 
			
		||||
      g_fnStateCallback(RADIO_STATUS_ENABLING);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   if (ant_enable() < 0) {
 | 
			
		||||
      ANT_ERROR("ant enable failed: %s", strerror(errno));
 | 
			
		||||
 | 
			
		||||
      ant_disable();
 | 
			
		||||
 | 
			
		||||
      if (g_fnStateCallback) {
 | 
			
		||||
         g_fnStateCallback(ant_radio_enabled_status());
 | 
			
		||||
      }
 | 
			
		||||
   } else {
 | 
			
		||||
      if (g_fnStateCallback) {
 | 
			
		||||
         g_fnStateCallback(RADIO_STATUS_ENABLED);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      result_status = ANT_STATUS_SUCCESS;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   ANT_DEBUG_V("releasing stEnabledStatusLock in %s", __FUNCTION__);
 | 
			
		||||
   pthread_mutex_unlock(&stEnabledStatusLock);
 | 
			
		||||
   ANT_DEBUG_V("released stEnabledStatusLock in %s", __FUNCTION__);
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
   ANT_FUNC_END();
 | 
			
		||||
   return result_status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
//  ant_radio_hard_reset
 | 
			
		||||
//
 | 
			
		||||
//  IF SUPPORTED triggers a hard reset of the chip providing ANT functionality.
 | 
			
		||||
//
 | 
			
		||||
//  Parameters:
 | 
			
		||||
//      -
 | 
			
		||||
//
 | 
			
		||||
//  Returns:
 | 
			
		||||
//      Success:
 | 
			
		||||
//          ANT_STATUS_SUCCESS
 | 
			
		||||
//      Failures:
 | 
			
		||||
//          ANT_STATUS_NOT_SUPPORTED if the chip can't hard reset
 | 
			
		||||
//          ANT_STATUS_FAILED if failed to get mutex or enable
 | 
			
		||||
//
 | 
			
		||||
//  Psuedocode:
 | 
			
		||||
/*
 | 
			
		||||
IF Hard Reset not supported
 | 
			
		||||
    RESULT = NOT SUPPORTED
 | 
			
		||||
ELSE
 | 
			
		||||
  LOCK enable_LOCK
 | 
			
		||||
  IF Lock failed
 | 
			
		||||
        RESULT = FAILED
 | 
			
		||||
  ELSE
 | 
			
		||||
    Set Flag Rx thread that chip is resetting
 | 
			
		||||
    FOR each path to chip
 | 
			
		||||
        Send Reset IOCTL to path
 | 
			
		||||
    ENDFOR
 | 
			
		||||
    ant disable
 | 
			
		||||
    ant enable
 | 
			
		||||
    IF ant_enable success
 | 
			
		||||
        State callback: STATE = RESET
 | 
			
		||||
        RESULT = SUCCESS
 | 
			
		||||
    ELSE
 | 
			
		||||
        State callback: STATE = DISABLED
 | 
			
		||||
        RESULT = FAILURE
 | 
			
		||||
    ENDIF
 | 
			
		||||
    Clear Flag Rx thread that chip is resetting
 | 
			
		||||
  UNLOCK
 | 
			
		||||
ENDIF
 | 
			
		||||
*/
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
ANTStatus ant_radio_hard_reset(void)
 | 
			
		||||
{
 | 
			
		||||
   ANTStatus result_status = ANT_STATUS_NOT_SUPPORTED;
 | 
			
		||||
   ANT_FUNC_START();
 | 
			
		||||
 | 
			
		||||
#ifdef ANT_IOCTL_RESET
 | 
			
		||||
   ant_channel_type eChannel;
 | 
			
		||||
   int iLockResult;
 | 
			
		||||
 | 
			
		||||
   result_status = ANT_STATUS_FAILED;
 | 
			
		||||
 | 
			
		||||
   ANT_DEBUG_V("getting stEnabledStatusLock in %s", __FUNCTION__);
 | 
			
		||||
   iLockResult = pthread_mutex_lock(&stEnabledStatusLock);
 | 
			
		||||
   if(iLockResult) {
 | 
			
		||||
      ANT_ERROR("enable failed to get state lock: %s", strerror(iLockResult));
 | 
			
		||||
      goto out;
 | 
			
		||||
   }
 | 
			
		||||
   ANT_DEBUG_V("got stEnabledStatusLock in %s", __FUNCTION__);
 | 
			
		||||
 | 
			
		||||
   stRxThreadInfo.ucChipResetting = 1;
 | 
			
		||||
   if (g_fnStateCallback)
 | 
			
		||||
      g_fnStateCallback(RADIO_STATUS_RESETTING);
 | 
			
		||||
 | 
			
		||||
   for (eChannel = 0; eChannel < NUM_ANT_CHANNELS; eChannel++)
 | 
			
		||||
      ioctl(stRxThreadInfo.astChannels[eChannel].iFd, ANT_IOCTL_RESET); //TODO only one?
 | 
			
		||||
 | 
			
		||||
   ant_disable();
 | 
			
		||||
 | 
			
		||||
   if (ant_enable()) { /* failed */
 | 
			
		||||
      if (g_fnStateCallback)
 | 
			
		||||
         g_fnStateCallback(RADIO_STATUS_DISABLED);
 | 
			
		||||
   } else { /* success */
 | 
			
		||||
      if (g_fnStateCallback)
 | 
			
		||||
         g_fnStateCallback(RADIO_STATUS_RESET);
 | 
			
		||||
      result_status = ANT_STATUS_SUCCESS;
 | 
			
		||||
   }
 | 
			
		||||
   stRxThreadInfo.ucChipResetting = 0;
 | 
			
		||||
 | 
			
		||||
   ANT_DEBUG_V("releasing stEnabledStatusLock in %s", __FUNCTION__);
 | 
			
		||||
   pthread_mutex_unlock(&stEnabledStatusLock);
 | 
			
		||||
   ANT_DEBUG_V("released stEnabledStatusLock in %s", __FUNCTION__);
 | 
			
		||||
out:
 | 
			
		||||
#endif // ANT_IOCTL_RESET
 | 
			
		||||
 | 
			
		||||
   ANT_FUNC_END();
 | 
			
		||||
   return result_status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
//  ant_disable_radio
 | 
			
		||||
//
 | 
			
		||||
//  Powers off the ANT part and closes the transport to the chip.
 | 
			
		||||
//
 | 
			
		||||
//  Parameters:
 | 
			
		||||
//      -
 | 
			
		||||
//
 | 
			
		||||
//  Returns:
 | 
			
		||||
//      Success:
 | 
			
		||||
//          ANT_STATUS_SUCCESS
 | 
			
		||||
//      Failures:
 | 
			
		||||
//          ANT_STATUS_FAILED if failed to get mutex
 | 
			
		||||
//
 | 
			
		||||
//  Psuedocode:
 | 
			
		||||
/*
 | 
			
		||||
LOCK enable_LOCK
 | 
			
		||||
    State callback: STATE = DISABLING
 | 
			
		||||
    ant disable
 | 
			
		||||
    State callback: STATE = Current state
 | 
			
		||||
    RESULT = SUCCESS
 | 
			
		||||
UNLOCK
 | 
			
		||||
*/
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
ANTStatus ant_disable_radio(void)
 | 
			
		||||
{
 | 
			
		||||
   int iLockResult;
 | 
			
		||||
   ANTStatus ret = ANT_STATUS_FAILED;
 | 
			
		||||
   ANT_FUNC_START();
 | 
			
		||||
 | 
			
		||||
   ANT_DEBUG_V("getting stEnabledStatusLock in %s", __FUNCTION__);
 | 
			
		||||
   iLockResult = pthread_mutex_lock(&stEnabledStatusLock);
 | 
			
		||||
   if(iLockResult) {
 | 
			
		||||
      ANT_ERROR("disable failed to get state lock: %s", strerror(iLockResult));
 | 
			
		||||
      goto out;
 | 
			
		||||
   }
 | 
			
		||||
   ANT_DEBUG_V("got stEnabledStatusLock in %s", __FUNCTION__);
 | 
			
		||||
 | 
			
		||||
   if (g_fnStateCallback) {
 | 
			
		||||
      g_fnStateCallback(RADIO_STATUS_DISABLING);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   ant_disable();
 | 
			
		||||
 | 
			
		||||
   if (g_fnStateCallback) {
 | 
			
		||||
      g_fnStateCallback(ant_radio_enabled_status());
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   ret = ANT_STATUS_SUCCESS;
 | 
			
		||||
 | 
			
		||||
   ANT_DEBUG_V("releasing stEnabledStatusLock in %s", __FUNCTION__);
 | 
			
		||||
   pthread_mutex_unlock(&stEnabledStatusLock);
 | 
			
		||||
   ANT_DEBUG_V("released stEnabledStatusLock in %s", __FUNCTION__);
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
   ANT_FUNC_END();
 | 
			
		||||
   return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
//  ant_radio_enabled_status
 | 
			
		||||
//
 | 
			
		||||
//  Gets the current chip/transport state; either disabled, disabling,
 | 
			
		||||
//  enabling, enabled, or resetting.  Determines this on the fly by checking
 | 
			
		||||
//  if Rx thread is running and how many of the paths for the ANT chip have
 | 
			
		||||
//  open VFS files.
 | 
			
		||||
//
 | 
			
		||||
//  Parameters:
 | 
			
		||||
//      -
 | 
			
		||||
//
 | 
			
		||||
//  Returns:
 | 
			
		||||
//      The current radio status (ANTRadioEnabledStatus)
 | 
			
		||||
//
 | 
			
		||||
//  Psuedocode:
 | 
			
		||||
/*
 | 
			
		||||
IF Thread Resetting Flag is set
 | 
			
		||||
    RESULT = Resetting
 | 
			
		||||
ELSE
 | 
			
		||||
    COUNT the number of open files
 | 
			
		||||
    IF Thread Run Flag is Not Set
 | 
			
		||||
        IF there are open files OR Rx thread exists
 | 
			
		||||
            RESULT = Disabling
 | 
			
		||||
        ELSE
 | 
			
		||||
            RESULT = Disabled
 | 
			
		||||
        ENDIF
 | 
			
		||||
    ELSE
 | 
			
		||||
        IF All files are open (all paths) AND Rx thread exists
 | 
			
		||||
            RESULT = ENABLED
 | 
			
		||||
        ELSE IF there are open files (Not 0 open files) AND Rx thread exists
 | 
			
		||||
            RESULT = UNKNOWN
 | 
			
		||||
        ELSE (0 open files or Rx thread does not exist [while Thread Run set])
 | 
			
		||||
            RESULT = ENABLING
 | 
			
		||||
        ENDIF
 | 
			
		||||
    ENDIF
 | 
			
		||||
ENDIF
 | 
			
		||||
*/
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
ANTRadioEnabledStatus ant_radio_enabled_status(void)
 | 
			
		||||
{
 | 
			
		||||
   ant_channel_type eChannel;
 | 
			
		||||
   int iOpenFiles = 0;
 | 
			
		||||
   int iOpenThread;
 | 
			
		||||
   ANTRadioEnabledStatus uiRet = RADIO_STATUS_UNKNOWN;
 | 
			
		||||
   ANT_FUNC_START();
 | 
			
		||||
 | 
			
		||||
   if (stRxThreadInfo.ucChipResetting) {
 | 
			
		||||
      uiRet = RADIO_STATUS_RESETTING;
 | 
			
		||||
      goto out;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
//  set_ant_rx_callback
 | 
			
		||||
//
 | 
			
		||||
//  Sets which function to call when an ANT message is received.
 | 
			
		||||
//
 | 
			
		||||
//  Parameters:
 | 
			
		||||
//      rx_callback_func   the ANTNativeANTEventCb function to be used for
 | 
			
		||||
//                         received messages (from all transport paths).
 | 
			
		||||
//
 | 
			
		||||
//  Returns:
 | 
			
		||||
//          ANT_STATUS_SUCCESS
 | 
			
		||||
//
 | 
			
		||||
//  Psuedocode:
 | 
			
		||||
/*
 | 
			
		||||
FOR each transport path
 | 
			
		||||
    Path Rx Callback = rx_callback_func
 | 
			
		||||
ENDFOR
 | 
			
		||||
*/
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
ANTStatus set_ant_rx_callback(ANTNativeANTEventCb rx_callback_func)
 | 
			
		||||
{
 | 
			
		||||
   ANTStatus status = ANT_STATUS_SUCCESS;
 | 
			
		||||
   ANT_FUNC_START();
 | 
			
		||||
 | 
			
		||||
#ifdef ANT_DEVICE_NAME // Single transport path
 | 
			
		||||
   stRxThreadInfo.astChannels[SINGLE_CHANNEL].fnRxCallback = rx_callback_func;
 | 
			
		||||
#else // Separate data/command paths
 | 
			
		||||
   stRxThreadInfo.astChannels[COMMAND_CHANNEL].fnRxCallback = rx_callback_func;
 | 
			
		||||
   stRxThreadInfo.astChannels[DATA_CHANNEL].fnRxCallback = rx_callback_func;
 | 
			
		||||
#endif // Separate data/command paths
 | 
			
		||||
 | 
			
		||||
   ANT_FUNC_END();
 | 
			
		||||
   return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
//  set_ant_state_callback
 | 
			
		||||
//
 | 
			
		||||
//  Sets which function to call when an ANT state change occurs.
 | 
			
		||||
//
 | 
			
		||||
//  Parameters:
 | 
			
		||||
//      state_callback_func   the ANTNativeANTStateCb function to be used
 | 
			
		||||
//                            for received state changes.
 | 
			
		||||
//
 | 
			
		||||
//  Returns:
 | 
			
		||||
//          ANT_STATUS_SUCCESS
 | 
			
		||||
//
 | 
			
		||||
//  Psuedocode:
 | 
			
		||||
/*
 | 
			
		||||
    State Callback = state_callback_func
 | 
			
		||||
*/
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
ANTStatus set_ant_state_callback(ANTNativeANTStateCb state_callback_func)
 | 
			
		||||
{
 | 
			
		||||
   ANTStatus status = ANT_STATUS_SUCCESS;
 | 
			
		||||
   ANT_FUNC_START();
 | 
			
		||||
 | 
			
		||||
   g_fnStateCallback = state_callback_func;
 | 
			
		||||
 | 
			
		||||
   ANT_FUNC_END();
 | 
			
		||||
   return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
//  ant_tx_message_flowcontrol_wait
 | 
			
		||||
//
 | 
			
		||||
//  Sends an ANT message to the chip and waits for a CTS signal
 | 
			
		||||
//
 | 
			
		||||
//  Parameters:
 | 
			
		||||
//      eTxPath          device to transmit message on
 | 
			
		||||
//      eFlowMessagePath device that receives CTS
 | 
			
		||||
//      ucMessageLength  the length of the message
 | 
			
		||||
//      pucMesg          pointer to the message data
 | 
			
		||||
//
 | 
			
		||||
//  Returns:
 | 
			
		||||
//      Success:
 | 
			
		||||
//          ANT_STATUS_SUCCESS
 | 
			
		||||
//      Failure:
 | 
			
		||||
//          ANT_STATUS_NOT_ENABLED
 | 
			
		||||
//
 | 
			
		||||
//  Psuedocode:
 | 
			
		||||
/*
 | 
			
		||||
        LOCK flow control
 | 
			
		||||
        IF Lock failed
 | 
			
		||||
            RESULT = FAILED
 | 
			
		||||
        ELSE
 | 
			
		||||
            SET flowMessagePath Flow Control response as FLOW_STOP
 | 
			
		||||
            WRITE txBuffer to txPath (only length of packet part)
 | 
			
		||||
            IF Wrote less then 0 bytes
 | 
			
		||||
                Log error
 | 
			
		||||
                RESULT = FAILED
 | 
			
		||||
            ELSE IF Didn't write 'length of packet' bytes
 | 
			
		||||
                Log error
 | 
			
		||||
                RESULT = FAILED
 | 
			
		||||
            ELSE
 | 
			
		||||
                IF flowMessagePath Flow Control response is not FLOW_GO
 | 
			
		||||
                    WAIT until flowMessagePath Flow Control response is FLOW_GO, UNTIL FLOW_GO Wait Timeout seconds (10) from Now
 | 
			
		||||
                    IF error Waiting
 | 
			
		||||
                        IF error is Timeout
 | 
			
		||||
                            RESULT = HARDWARE ERROR
 | 
			
		||||
                        ELSE
 | 
			
		||||
                            RESULT = FAILED
 | 
			
		||||
                        ENDIF
 | 
			
		||||
                    ELSE
 | 
			
		||||
                        RESULT = SUCCESS
 | 
			
		||||
                    ENDIF
 | 
			
		||||
                ELSE
 | 
			
		||||
                    RESULT = SUCCESS;
 | 
			
		||||
                ENDIF
 | 
			
		||||
            ENDIF
 | 
			
		||||
            UNLOCK flow control
 | 
			
		||||
        ENDIF
 | 
			
		||||
*/
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
ANTStatus ant_tx_message_flowcontrol_wait(ant_channel_type eTxPath, ant_channel_type eFlowMessagePath, ANT_U8 ucMessageLength, ANT_U8 *pucTxMessage)
 | 
			
		||||
{
 | 
			
		||||
   int iMutexResult;
 | 
			
		||||
   int iResult;
 | 
			
		||||
   struct timespec stTimeout;
 | 
			
		||||
   int iCondWaitResult;
 | 
			
		||||
   ANTStatus status = ANT_STATUS_FAILED;
 | 
			
		||||
   ANT_FUNC_START();
 | 
			
		||||
 | 
			
		||||
   ANT_DEBUG_V("getting stFlowControlLock in %s", __FUNCTION__);
 | 
			
		||||
   iMutexResult = pthread_mutex_lock(&stFlowControlLock);
 | 
			
		||||
   if (iMutexResult) {
 | 
			
		||||
      ANT_ERROR("failed to lock flow control mutex during tx: %s", strerror(iMutexResult));
 | 
			
		||||
      goto out;
 | 
			
		||||
   }
 | 
			
		||||
   ANT_DEBUG_V("got stFlowControlLock in %s", __FUNCTION__);
 | 
			
		||||
 | 
			
		||||
   stRxThreadInfo.astChannels[eFlowMessagePath].ucFlowControlResp = ANT_FLOW_STOP;
 | 
			
		||||
 | 
			
		||||
#ifdef ANT_FLOW_RESEND
 | 
			
		||||
   // Store Tx message so can resend it from Rx thread
 | 
			
		||||
   stRxThreadInfo.astChannels[eFlowMessagePath].ucResendMessageLength = ucMessageLength;
 | 
			
		||||
   stRxThreadInfo.astChannels[eFlowMessagePath].pucResendMessage = pucTxMessage;
 | 
			
		||||
#endif // ANT_FLOW_RESEND
 | 
			
		||||
 | 
			
		||||
   iResult = write(stRxThreadInfo.astChannels[eTxPath].iFd, pucTxMessage, ucMessageLength);
 | 
			
		||||
   if (iResult < 0) {
 | 
			
		||||
      ANT_ERROR("failed to write data message to device: %s", strerror(errno));
 | 
			
		||||
   } else if (iResult != ucMessageLength) {
 | 
			
		||||
      ANT_ERROR("bytes written and message size don't match up");
 | 
			
		||||
   } else {
 | 
			
		||||
      stTimeout.tv_sec = time(0) + ANT_FLOW_GO_WAIT_TIMEOUT_SEC;
 | 
			
		||||
      stTimeout.tv_nsec = 0;
 | 
			
		||||
 | 
			
		||||
      while (stRxThreadInfo.astChannels[eFlowMessagePath].ucFlowControlResp != ANT_FLOW_GO) {
 | 
			
		||||
         iCondWaitResult = pthread_cond_timedwait(&stFlowControlCond, &stFlowControlLock, &stTimeout);
 | 
			
		||||
         if (iCondWaitResult) {
 | 
			
		||||
            ANT_ERROR("failed to wait for flow control response: %s", strerror(iCondWaitResult));
 | 
			
		||||
 | 
			
		||||
            if (iCondWaitResult == ETIMEDOUT) {
 | 
			
		||||
               status = ANT_STATUS_HARDWARE_ERR;
 | 
			
		||||
 | 
			
		||||
#ifdef ANT_FLOW_RESEND
 | 
			
		||||
               // Clear Tx message so will stop resending it from Rx thread
 | 
			
		||||
               stRxThreadInfo.astChannels[eFlowMessagePath].ucResendMessageLength = 0;
 | 
			
		||||
               stRxThreadInfo.astChannels[eFlowMessagePath].pucResendMessage = NULL;
 | 
			
		||||
#endif // ANT_FLOW_RESEND
 | 
			
		||||
            }
 | 
			
		||||
            goto wait_error;
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      status = ANT_STATUS_SUCCESS;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
wait_error:
 | 
			
		||||
   ANT_DEBUG_V("releasing stFlowControlLock in %s", __FUNCTION__);
 | 
			
		||||
   pthread_mutex_unlock(&stFlowControlLock);
 | 
			
		||||
   ANT_DEBUG_V("released stFlowControlLock in %s", __FUNCTION__);
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
   ANT_FUNC_END();
 | 
			
		||||
   return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
//  ant_tx_message_flowcontrol_none
 | 
			
		||||
//
 | 
			
		||||
//  Sends an ANT message to the chip without waiting for flow control
 | 
			
		||||
//
 | 
			
		||||
//  Parameters:
 | 
			
		||||
//      eTxPath         device to transmit on
 | 
			
		||||
//      ucMessageLength the length of the message
 | 
			
		||||
//      pucMesg         pointer to the message data
 | 
			
		||||
//
 | 
			
		||||
//  Returns:
 | 
			
		||||
//      Success:
 | 
			
		||||
//          ANT_STATUS_SUCCESS
 | 
			
		||||
//      Failure:
 | 
			
		||||
//          ANT_STATUS_NOT_ENABLED
 | 
			
		||||
//
 | 
			
		||||
//  Psuedocode:
 | 
			
		||||
/*
 | 
			
		||||
        WRITE txBuffer to Tx Path (only length of packet part)
 | 
			
		||||
        IF Wrote less then 0 bytes
 | 
			
		||||
            Log error
 | 
			
		||||
            RESULT = FAILED
 | 
			
		||||
        ELSE IF Didn't write 'length of packet' bytes
 | 
			
		||||
            Log error
 | 
			
		||||
            RESULT = FAILED
 | 
			
		||||
        ELSE
 | 
			
		||||
            RESULT = SUCCESS
 | 
			
		||||
        ENDIF
 | 
			
		||||
*/
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
ANTStatus ant_tx_message_flowcontrol_none(ant_channel_type eTxPath, ANT_U8 ucMessageLength, ANT_U8 *pucTxMessage)
 | 
			
		||||
{
 | 
			
		||||
   int iResult;
 | 
			
		||||
   ANTStatus status = ANT_STATUS_FAILED;\
 | 
			
		||||
   ANT_FUNC_START();
 | 
			
		||||
 | 
			
		||||
   iResult = write(stRxThreadInfo.astChannels[eTxPath].iFd, pucTxMessage, ucMessageLength);
 | 
			
		||||
   if (iResult < 0) {
 | 
			
		||||
      ANT_ERROR("failed to write message to device: %s", strerror(errno));
 | 
			
		||||
   }  else if (iResult != ucMessageLength) {
 | 
			
		||||
      ANT_ERROR("bytes written and message size don't match up");
 | 
			
		||||
   } else {
 | 
			
		||||
      status = ANT_STATUS_SUCCESS;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   ANT_FUNC_END();
 | 
			
		||||
   return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
//  ant_tx_message
 | 
			
		||||
//
 | 
			
		||||
//  Frames ANT data and decides which flow control method to use for sending the
 | 
			
		||||
//  ANT message to the chip
 | 
			
		||||
//
 | 
			
		||||
//  Parameters:
 | 
			
		||||
//      ucLen   the length of the message
 | 
			
		||||
//      pucMesg pointer to the message data
 | 
			
		||||
//
 | 
			
		||||
//  Returns:
 | 
			
		||||
//      Success:
 | 
			
		||||
//          ANT_STATUS_SUCCESS
 | 
			
		||||
//      Failure:
 | 
			
		||||
//          ANT_STATUS_NOT_ENABLED
 | 
			
		||||
//
 | 
			
		||||
//  Psuedocode:
 | 
			
		||||
/*
 | 
			
		||||
IF not enabled
 | 
			
		||||
    RESULT = BT NOT INITIALIZED
 | 
			
		||||
ELSE
 | 
			
		||||
    Create txBuffer, MAX HCI Message Size large
 | 
			
		||||
    PUT ucLen in txBuffer AT ANT HCI Size Offset (0)
 | 
			
		||||
    COPY pucMesg to txBuffer AT ANT HCI Header Size (1)     <- ? Not at offset?
 | 
			
		||||
    LOG txBuffer as a serial Tx (only length of packet part)
 | 
			
		||||
    IF is a data message
 | 
			
		||||
        Tx message on Data Path with FLOW_GO/FLOW_STOP flow control (ant_tx_message_flowcontrol_go_stop())
 | 
			
		||||
    ELSE
 | 
			
		||||
        Tx message on Command Path with no flow control (ant_tx_message_flowcontrol_none())
 | 
			
		||||
    ENDIF
 | 
			
		||||
ENDIF
 | 
			
		||||
*/
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
ANTStatus ant_tx_message(ANT_U8 ucLen, ANT_U8 *pucMesg)
 | 
			
		||||
{
 | 
			
		||||
   ANTStatus status = ANT_STATUS_FAILED;
 | 
			
		||||
   // TODO ANT_HCI_MAX_MSG_SIZE is transport (driver) dependent.
 | 
			
		||||
   ANT_U8 txBuffer[ANT_HCI_MAX_MSG_SIZE];
 | 
			
		||||
   // TODO Message length can be greater than ANT_U8 can hold.
 | 
			
		||||
   // Not changed as ANT_SERIAL takes length as ANT_U8.
 | 
			
		||||
   ANT_U8 txMessageLength = ucLen + ANT_HCI_HEADER_SIZE;
 | 
			
		||||
   ANT_FUNC_START();
 | 
			
		||||
 | 
			
		||||
   if (ant_radio_enabled_status() != RADIO_STATUS_ENABLED) {
 | 
			
		||||
      status = ANT_STATUS_FAILED_BT_NOT_INITIALIZED;
 | 
			
		||||
      goto out;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
#if ANT_HCI_OPCODE_SIZE == 1
 | 
			
		||||
   txBuffer[ANT_HCI_OPCODE_OFFSET] = ANT_HCI_OPCODE_TX;
 | 
			
		||||
#elif ANT_HCI_OPCODE_SIZE > 1
 | 
			
		||||
#error "Specified ANT_HCI_OPCODE_SIZE not currently supported"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if ANT_HCI_SIZE_SIZE == 1
 | 
			
		||||
   txBuffer[ANT_HCI_SIZE_OFFSET] = ucLen;
 | 
			
		||||
#elif ANT_HCI_SIZE_SIZE == 2
 | 
			
		||||
   ANT_UTILS_StoreLE16(txBuffer + ANT_HCI_SIZE_OFFSET, (ANT_U16)ucLen);
 | 
			
		||||
#else
 | 
			
		||||
#error "Specified ANT_HCI_SIZE_SIZE not currently supported"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
   memcpy(txBuffer + ANT_HCI_HEADER_SIZE, pucMesg, ucLen);
 | 
			
		||||
 | 
			
		||||
   ANT_SERIAL(txBuffer, txMessageLength, 'T');
 | 
			
		||||
 | 
			
		||||
#ifdef ANT_DEVICE_NAME // Single transport path
 | 
			
		||||
   status = ant_tx_message_flowcontrol_wait(SINGLE_CHANNEL, SINGLE_CHANNEL, txMessageLength, txBuffer);
 | 
			
		||||
#else // Separate data/command paths
 | 
			
		||||
   switch (txBuffer[ANT_HCI_DATA_OFFSET + ANT_MSG_ID_OFFSET]) {
 | 
			
		||||
   case MESG_BROADCAST_DATA_ID:
 | 
			
		||||
   case MESG_ACKNOWLEDGED_DATA_ID:
 | 
			
		||||
   case MESG_BURST_DATA_ID:
 | 
			
		||||
   case MESG_EXT_BROADCAST_DATA_ID:
 | 
			
		||||
   case MESG_EXT_ACKNOWLEDGED_DATA_ID:
 | 
			
		||||
   case MESG_EXT_BURST_DATA_ID:
 | 
			
		||||
   case MESG_ADV_BURST_DATA_ID:
 | 
			
		||||
      status = ant_tx_message_flowcontrol_wait(DATA_CHANNEL, COMMAND_CHANNEL, txMessageLength, txBuffer);
 | 
			
		||||
      break;
 | 
			
		||||
   default:
 | 
			
		||||
      status = ant_tx_message_flowcontrol_none(COMMAND_CHANNEL, txMessageLength, txBuffer);
 | 
			
		||||
   }
 | 
			
		||||
#endif // Separate data/command paths
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
   ANT_FUNC_END();
 | 
			
		||||
   return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//----------------- TODO Move these somewhere for multi transport path / dedicated channel support:
 | 
			
		||||
 | 
			
		||||
static void ant_channel_init(ant_channel_info_t *pstChnlInfo, const char *pcCharDevName)
 | 
			
		||||
{
 | 
			
		||||
   ANT_FUNC_START();
 | 
			
		||||
 | 
			
		||||
   // TODO Don't need to store, only accessed when trying to open:
 | 
			
		||||
   // Is however useful for logs.
 | 
			
		||||
   pstChnlInfo->pcDevicePath = pcCharDevName;
 | 
			
		||||
 | 
			
		||||
   // This is the only piece of info that needs to be stored per channel
 | 
			
		||||
   pstChnlInfo->iFd = -1;
 | 
			
		||||
 | 
			
		||||
   // TODO Only 1 of these (not per-channel) is actually ever used:
 | 
			
		||||
   pstChnlInfo->fnRxCallback = NULL;
 | 
			
		||||
   pstChnlInfo->ucFlowControlResp = ANT_FLOW_GO;
 | 
			
		||||
#ifdef ANT_FLOW_RESEND
 | 
			
		||||
   pstChnlInfo->ucResendMessageLength = 0;
 | 
			
		||||
   pstChnlInfo->pucResendMessage = NULL;
 | 
			
		||||
#endif // ANT_FLOW_RESEND
 | 
			
		||||
   // TODO Only used when Flow Control message received, so must only be Command path Rx thread
 | 
			
		||||
   pstChnlInfo->pstFlowControlCond = &stFlowControlCond;
 | 
			
		||||
   pstChnlInfo->pstFlowControlLock = &stFlowControlLock;
 | 
			
		||||
 | 
			
		||||
   ANT_FUNC_END();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ant_disable_channel(ant_channel_info_t *pstChnlInfo)
 | 
			
		||||
{
 | 
			
		||||
   ANT_FUNC_START();
 | 
			
		||||
 | 
			
		||||
   if (!pstChnlInfo) {
 | 
			
		||||
      ANT_ERROR("null channel info passed to channel disable function");
 | 
			
		||||
      goto out;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//----------------------------------------------------------------------- This is antradio_power.h:
 | 
			
		||||
 | 
			
		||||
int ant_enable(void)
 | 
			
		||||
{
 | 
			
		||||
   int iRet = -1;
 | 
			
		||||
   ant_channel_type eChannel;
 | 
			
		||||
   ANT_FUNC_START();
 | 
			
		||||
 | 
			
		||||
   stRxThreadInfo.ucRunThread = 1;
 | 
			
		||||
 | 
			
		||||
   for (eChannel = 0; eChannel < NUM_ANT_CHANNELS; eChannel++) {
 | 
			
		||||
      if (ant_enable_channel(&stRxThreadInfo.astChannels[eChannel]) < 0) {
 | 
			
		||||
         ANT_ERROR("failed to enable channel %s: %s",
 | 
			
		||||
                         stRxThreadInfo.astChannels[eChannel].pcDevicePath,
 | 
			
		||||
                         strerror(errno));
 | 
			
		||||
         goto out;
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   if (stRxThreadInfo.stRxThread == 0) {
 | 
			
		||||
      if (pthread_create(&stRxThreadInfo.stRxThread, NULL, fnRxThread, &stRxThreadInfo) < 0) {
 | 
			
		||||
         ANT_ERROR("failed to start rx thread: %s", strerror(errno));
 | 
			
		||||
         goto out;
 | 
			
		||||
      }
 | 
			
		||||
   } else {
 | 
			
		||||
      ANT_DEBUG_D("rx thread is already running");
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   if (!stRxThreadInfo.ucRunThread) {
 | 
			
		||||
      ANT_ERROR("rx thread crashed during init");
 | 
			
		||||
      goto out;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   iRet = 0;
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
   ANT_FUNC_END();
 | 
			
		||||
   return iRet;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ant_disable(void)
 | 
			
		||||
{
 | 
			
		||||
   int iRet = -1;
 | 
			
		||||
   ant_channel_type eChannel;
 | 
			
		||||
   ANT_FUNC_START();
 | 
			
		||||
 | 
			
		||||
   stRxThreadInfo.ucRunThread = 0;
 | 
			
		||||
 | 
			
		||||
   for (eChannel = 0; eChannel < NUM_ANT_CHANNELS; eChannel++) {
 | 
			
		||||
      ant_disable_channel(&stRxThreadInfo.astChannels[eChannel]);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   if (stRxThreadInfo.stRxThread != 0) {
 | 
			
		||||
      if (pthread_join(stRxThreadInfo.stRxThread, NULL) < 0) {
 | 
			
		||||
         ANT_ERROR("failed to join rx thread: %s", strerror(errno));
 | 
			
		||||
         goto out;
 | 
			
		||||
      }
 | 
			
		||||
   } else {
 | 
			
		||||
      ANT_DEBUG_D("rx thread is not running");
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   iRet = 0;
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
   stRxThreadInfo.stRxThread = 0;
 | 
			
		||||
   ANT_FUNC_END();
 | 
			
		||||
   return iRet;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//---------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
const char *ant_get_lib_version()
 | 
			
		||||
{
 | 
			
		||||
   return "libantradio.so: "ANT_CHIP_NAME". Version "
 | 
			
		||||
      LIBANT_STACK_MAJOR"."LIBANT_STACK_MINOR"."LIBANT_STACK_INCRE;
 | 
			
		||||
}
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
 * 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
 | 
			
		||||
 *     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,
 | 
			
		||||
@@ -15,96 +15,48 @@
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
/*******************************************************************************\
 | 
			
		||||
/******************************************************************************\
 | 
			
		||||
*
 | 
			
		||||
*   FILE NAME:     ant_rx_chardev.c
 | 
			
		||||
*   FILE NAME:      ant_rx_chardev.c
 | 
			
		||||
*
 | 
			
		||||
*   BRIEF:
 | 
			
		||||
*      This file provides the rx function which will loop reading ANT messages
 | 
			
		||||
*        until told to exit.
 | 
			
		||||
*      This file implements the receive thread function which will loop reading
 | 
			
		||||
*      ANT messages until told to exit.
 | 
			
		||||
*
 | 
			
		||||
*
 | 
			
		||||
\*******************************************************************************/
 | 
			
		||||
\******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <poll.h>
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
 | 
			
		||||
#include "ant_rx_chardev.h"
 | 
			
		||||
#include "ant_native_chardev.h"
 | 
			
		||||
 | 
			
		||||
#include "ant_native.h"
 | 
			
		||||
#include "ant_types.h"
 | 
			
		||||
#include "antradio_power.h"
 | 
			
		||||
#include "ant_rx_chardev.h"
 | 
			
		||||
#include "ant_driver_defines.h"
 | 
			
		||||
#include "ant_log.h"
 | 
			
		||||
#include "ant_native.h"  // ANT_HCI_MAX_MSG_SIZE, ANT_MSG_ID_OFFSET, ANT_MSG_DATA_OFFSET,
 | 
			
		||||
                         // ant_radio_enabled_status()
 | 
			
		||||
 | 
			
		||||
extern ANTStatus ant_tx_message_flowcontrol_none(ant_channel_type eTxPath, ANT_U8 ucMessageLength, ANT_U8 *pucTxMessage);
 | 
			
		||||
 | 
			
		||||
#undef LOG_TAG
 | 
			
		||||
#define LOG_TAG "antradio_rx"
 | 
			
		||||
 | 
			
		||||
#define ANT_POLL_TIMEOUT         ((int)30000)
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
}
 | 
			
		||||
int readChannelMsg(ant_channel_type eChannel, ant_channel_info_t *pstChnlInfo);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This thread waits for ANT messages from a VFS file.
 | 
			
		||||
 */
 | 
			
		||||
void *fnRxThread(void *ant_rx_thread_info)
 | 
			
		||||
{
 | 
			
		||||
   int iMutexLockResult;
 | 
			
		||||
   int iPollRet;
 | 
			
		||||
   ant_rx_thread_info_t *stRxThreadInfo;
 | 
			
		||||
   struct pollfd astPollFd[NUM_ANT_CHANNELS];
 | 
			
		||||
   enum ant_channel_type eChannel;
 | 
			
		||||
   ant_channel_type eChannel;
 | 
			
		||||
   ANT_FUNC_START();
 | 
			
		||||
 | 
			
		||||
   stRxThreadInfo = (ant_rx_thread_info_t *)ant_rx_thread_info;
 | 
			
		||||
@@ -113,7 +65,9 @@ void *fnRxThread(void *ant_rx_thread_info)
 | 
			
		||||
      astPollFd[eChannel].events = POLLIN | POLLRDNORM;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /* continue running as long as not terminated */
 | 
			
		||||
   while (stRxThreadInfo->ucRunThread) {
 | 
			
		||||
      /* Wait for data available on any file (transport path) */
 | 
			
		||||
      iPollRet = poll(astPollFd, NUM_ANT_CHANNELS, ANT_POLL_TIMEOUT);
 | 
			
		||||
      if (!iPollRet) {
 | 
			
		||||
         ANT_DEBUG_V("poll timed out, checking exit cond");
 | 
			
		||||
@@ -127,15 +81,19 @@ void *fnRxThread(void *ant_rx_thread_info)
 | 
			
		||||
               /* 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;
 | 
			
		||||
 | 
			
		||||
               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)
 | 
			
		||||
 | 
			
		||||
               if (readChannelMsg(eChannel, &stRxThreadInfo->astChannels[eChannel]) < 0) {
 | 
			
		||||
                  goto out;
 | 
			
		||||
               }
 | 
			
		||||
            } else if (astPollFd[eChannel].revents) {
 | 
			
		||||
               ANT_DEBUG_W("unhandled poll result %#x from %s",
 | 
			
		||||
                            astPollFd[eChannel].revents,
 | 
			
		||||
@@ -144,8 +102,10 @@ void *fnRxThread(void *ant_rx_thread_info)
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
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 */
 | 
			
		||||
@@ -157,13 +117,15 @@ out:
 | 
			
		||||
      stRxThreadInfo->stRxThread = 0; /* spoof our handle as closed so we don't
 | 
			
		||||
                                       * try to join ourselves in disable */
 | 
			
		||||
 | 
			
		||||
      if (g_fnStateCallback)
 | 
			
		||||
      if (g_fnStateCallback) {
 | 
			
		||||
         g_fnStateCallback(RADIO_STATUS_DISABLING);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      ant_do_disable();
 | 
			
		||||
      ant_disable();
 | 
			
		||||
 | 
			
		||||
      if (g_fnStateCallback)
 | 
			
		||||
      if (g_fnStateCallback) {
 | 
			
		||||
         g_fnStateCallback(ant_radio_enabled_status());
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      ANT_DEBUG_V("releasing stEnabledStatusLock in %s", __FUNCTION__);
 | 
			
		||||
      pthread_mutex_unlock(stRxThreadInfo->pstEnabledStatusLock);
 | 
			
		||||
@@ -174,6 +136,10 @@ out:
 | 
			
		||||
   } else {
 | 
			
		||||
      ANT_DEBUG_V("stEnabledStatusLock busy");
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   // FIXME This is not the end of the function
 | 
			
		||||
   // Probably because goto:reset is a bad implementation; can have a reset function.
 | 
			
		||||
   // Will only end here on Android.
 | 
			
		||||
   ANT_FUNC_END();
 | 
			
		||||
#ifdef ANDROID
 | 
			
		||||
   return NULL;
 | 
			
		||||
@@ -181,6 +147,7 @@ out:
 | 
			
		||||
 | 
			
		||||
reset:
 | 
			
		||||
   stRxThreadInfo->ucRunThread = 0;
 | 
			
		||||
 | 
			
		||||
   ANT_DEBUG_V("getting stEnabledStatusLock in %s", __FUNCTION__);
 | 
			
		||||
   iMutexLockResult = pthread_mutex_lock(stRxThreadInfo->pstEnabledStatusLock);
 | 
			
		||||
   if (iMutexLockResult < 0) {
 | 
			
		||||
@@ -189,25 +156,157 @@ reset:
 | 
			
		||||
      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)
 | 
			
		||||
      ant_disable();
 | 
			
		||||
 | 
			
		||||
      if (ant_enable()) { /* failed */
 | 
			
		||||
         if (g_fnStateCallback) {
 | 
			
		||||
            g_fnStateCallback(RADIO_STATUS_DISABLED);
 | 
			
		||||
         }
 | 
			
		||||
      } else { /* success */
 | 
			
		||||
         if (g_fnStateCallback)
 | 
			
		||||
         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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
//  setFlowControl
 | 
			
		||||
//
 | 
			
		||||
//  Sets the flow control "flag" to the value provided and signals the transmit
 | 
			
		||||
//  thread to check the value.
 | 
			
		||||
//
 | 
			
		||||
//  Parameters:
 | 
			
		||||
//      pstChnlInfo   the details of the channel being updated
 | 
			
		||||
//      ucFlowSetting the value to use
 | 
			
		||||
//
 | 
			
		||||
//  Returns:
 | 
			
		||||
//      Success:
 | 
			
		||||
//          0
 | 
			
		||||
//      Failure:
 | 
			
		||||
//          -1
 | 
			
		||||
////////////////////////////////////////////////////////////////////
 | 
			
		||||
int setFlowControl(ant_channel_info_t *pstChnlInfo, ANT_U8 ucFlowSetting)
 | 
			
		||||
{
 | 
			
		||||
   int iRet = -1;
 | 
			
		||||
   int iMutexResult;
 | 
			
		||||
   ANT_FUNC_START();
 | 
			
		||||
 | 
			
		||||
   ANT_DEBUG_V("getting stFlowControlLock in %s", __FUNCTION__);
 | 
			
		||||
   iMutexResult = pthread_mutex_lock(pstChnlInfo->pstFlowControlLock);
 | 
			
		||||
   if (iMutexResult) {
 | 
			
		||||
      ANT_ERROR("failed to lock flow control mutex during response: %s", strerror(iMutexResult));
 | 
			
		||||
   } else {
 | 
			
		||||
      ANT_DEBUG_V("got stFlowControlLock in %s", __FUNCTION__);
 | 
			
		||||
 | 
			
		||||
      pstChnlInfo->ucFlowControlResp = ucFlowSetting;
 | 
			
		||||
 | 
			
		||||
      ANT_DEBUG_V("releasing stFlowControlLock in %s", __FUNCTION__);
 | 
			
		||||
      pthread_mutex_unlock(pstChnlInfo->pstFlowControlLock);
 | 
			
		||||
      ANT_DEBUG_V("released stFlowControlLock in %s", __FUNCTION__);
 | 
			
		||||
 | 
			
		||||
      pthread_cond_signal(pstChnlInfo->pstFlowControlCond);
 | 
			
		||||
 | 
			
		||||
      iRet = 0;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   ANT_FUNC_END();
 | 
			
		||||
   return iRet;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int readChannelMsg(ant_channel_type eChannel, ant_channel_info_t *pstChnlInfo)
 | 
			
		||||
{
 | 
			
		||||
   int iRet = -1;
 | 
			
		||||
   ANT_U8 aucRxBuffer[ANT_HCI_MAX_MSG_SIZE];
 | 
			
		||||
   int iRxLenRead;
 | 
			
		||||
   ANT_FUNC_START();
 | 
			
		||||
 | 
			
		||||
   // Keep trying to read while there is an error, and that error is EAGAIN
 | 
			
		||||
   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 ANT_HCI_OPCODE_SIZE == 1  // Check the different message types by opcode
 | 
			
		||||
      ANT_U8 opcode = aucRxBuffer[ANT_HCI_OPCODE_OFFSET];
 | 
			
		||||
 | 
			
		||||
      if(ANT_HCI_OPCODE_COMMAND_COMPLETE == opcode) {
 | 
			
		||||
         // Command Complete, so signal a FLOW_GO
 | 
			
		||||
         if(setFlowControl(pstChnlInfo, ANT_FLOW_GO)) {
 | 
			
		||||
            goto out;
 | 
			
		||||
         }
 | 
			
		||||
      } else if(ANT_HCI_OPCODE_FLOW_ON == opcode) {
 | 
			
		||||
         // FLow On, so resend the last Tx
 | 
			
		||||
#ifdef ANT_FLOW_RESEND
 | 
			
		||||
         // Check if there is a message to resend
 | 
			
		||||
         if(pstChnlInfo->ucResendMessageLength > 0) {
 | 
			
		||||
            ant_tx_message_flowcontrol_none(eChannel, pstChnlInfo->ucResendMessageLength, pstChnlInfo->pucResendMessage);
 | 
			
		||||
         } else {
 | 
			
		||||
            ANT_DEBUG_D("Resend requested by chip, but tx request cancelled");
 | 
			
		||||
         }
 | 
			
		||||
#endif // ANT_FLOW_RESEND
 | 
			
		||||
      } else if(ANT_HCI_OPCODE_ANT_EVENT == opcode)
 | 
			
		||||
         // ANT Event, send ANT packet to Rx Callback
 | 
			
		||||
#endif // ANT_HCI_OPCODE_SIZE == 1
 | 
			
		||||
      {
 | 
			
		||||
      // Received an ANT packet
 | 
			
		||||
#ifdef ANT_MESG_FLOW_CONTROL
 | 
			
		||||
         if (aucRxBuffer[ANT_HCI_DATA_OFFSET + ANT_MSG_ID_OFFSET] == ANT_MESG_FLOW_CONTROL) {
 | 
			
		||||
            // This is a flow control packet, not a standard ANT message
 | 
			
		||||
            if(setFlowControl(pstChnlInfo, aucRxBuffer[ANT_HCI_DATA_OFFSET + ANT_MSG_DATA_OFFSET])) {
 | 
			
		||||
               goto out;
 | 
			
		||||
            }
 | 
			
		||||
         } else
 | 
			
		||||
#endif // ANT_MESG_FLOW_CONTROL
 | 
			
		||||
         {
 | 
			
		||||
            if (pstChnlInfo->fnRxCallback != NULL) {
 | 
			
		||||
               // TODO Allow HCI Size value to be larger than 1 byte
 | 
			
		||||
               // This currently works as no size value is greater than 255, and little endian
 | 
			
		||||
               pstChnlInfo->fnRxCallback(aucRxBuffer[ANT_HCI_SIZE_OFFSET], &aucRxBuffer[ANT_HCI_DATA_OFFSET]);
 | 
			
		||||
            } else {
 | 
			
		||||
               ANT_WARN("%s rx callback is null", pstChnlInfo->pcDevicePath);
 | 
			
		||||
            }
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      iRet = 0;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
   ANT_FUNC_END();
 | 
			
		||||
   return iRet;
 | 
			
		||||
}
 | 
			
		||||
@@ -20,7 +20,10 @@
 | 
			
		||||
*   FILE NAME:      ant_rx_chardev.h
 | 
			
		||||
*
 | 
			
		||||
*   BRIEF:
 | 
			
		||||
*       This file defines public members in ant_rx_chardev.c
 | 
			
		||||
*      This file defines the receive thread function, the ant_rx_thread_info_t
 | 
			
		||||
*      type for storing the -configuration- <state> of the receive thread, the
 | 
			
		||||
*      ant_channel_info_t type for storing a channel's (transport path)
 | 
			
		||||
*      configuration, and an enumeration of all ANT channels (transport paths).
 | 
			
		||||
*
 | 
			
		||||
*
 | 
			
		||||
\*******************************************************************************/
 | 
			
		||||
@@ -29,6 +32,14 @@
 | 
			
		||||
#define __ANT_RX_NATIVE_H
 | 
			
		||||
 | 
			
		||||
#include "ant_native.h"
 | 
			
		||||
#include "ant_driver_defines.h"
 | 
			
		||||
 | 
			
		||||
/* same as HCI_MAX_EVENT_SIZE from hci.h, but hci.h is not included for vfs */
 | 
			
		||||
#define ANT_HCI_MAX_MSG_SIZE 260
 | 
			
		||||
 | 
			
		||||
#define ANT_MSG_SIZE_OFFSET     ((ANT_U8)0)
 | 
			
		||||
#define ANT_MSG_ID_OFFSET       ((ANT_U8)1)
 | 
			
		||||
#define ANT_MSG_DATA_OFFSET     ((ANT_U8)2)
 | 
			
		||||
 | 
			
		||||
/* This struct defines the info passed to an rx thread */
 | 
			
		||||
typedef struct {
 | 
			
		||||
@@ -44,13 +55,23 @@ typedef struct {
 | 
			
		||||
   pthread_cond_t *pstFlowControlCond;
 | 
			
		||||
   /* Handle to flow control mutex */
 | 
			
		||||
   pthread_mutex_t *pstFlowControlLock;
 | 
			
		||||
#ifdef ANT_FLOW_RESEND
 | 
			
		||||
   /* Length of message to resend on request from chip */
 | 
			
		||||
   ANT_U8 ucResendMessageLength;
 | 
			
		||||
   /* The message to resend on request from chip */
 | 
			
		||||
   ANT_U8 *pucResendMessage;
 | 
			
		||||
#endif // ANT_FLOW_RESEND
 | 
			
		||||
} ant_channel_info_t;
 | 
			
		||||
 | 
			
		||||
enum ant_channel_type {
 | 
			
		||||
typedef enum {
 | 
			
		||||
#ifdef ANT_DEVICE_NAME // Single transport path
 | 
			
		||||
   SINGLE_CHANNEL,
 | 
			
		||||
#else // Separate data/command paths
 | 
			
		||||
   DATA_CHANNEL,
 | 
			
		||||
   COMMAND_CHANNEL,
 | 
			
		||||
#endif // Separate data/command paths
 | 
			
		||||
   NUM_ANT_CHANNELS
 | 
			
		||||
};
 | 
			
		||||
} ant_channel_type;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
   /* Thread handle */
 | 
			
		||||
@@ -65,6 +86,8 @@ typedef struct {
 | 
			
		||||
   ant_channel_info_t astChannels[NUM_ANT_CHANNELS];
 | 
			
		||||
} ant_rx_thread_info_t;
 | 
			
		||||
 | 
			
		||||
extern ANTNativeANTStateCb g_fnStateCallback;  // TODO State callback should be inside ant_rx_thread_info_t.
 | 
			
		||||
 | 
			
		||||
/* This is the rx thread function. It loops reading ANT packets until told to
 | 
			
		||||
 * exit */
 | 
			
		||||
void *fnRxThread(void *ant_rx_thread_info);
 | 
			
		||||
							
								
								
									
										48
									
								
								src/vfs/inc/antradio_power.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/vfs/inc/antradio_power.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __ANTRADIOPM_H
 | 
			
		||||
#define __ANTRADIOPM_H
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Enable the ANT radio interface.
 | 
			
		||||
 *
 | 
			
		||||
 * Responsible for power on, and bringing up HCI interface.
 | 
			
		||||
 * Will block until the HCI interface is ready to use.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns 0 on success, -ve on error */
 | 
			
		||||
int ant_enable();
 | 
			
		||||
 | 
			
		||||
/* Disable the ANT radio interface.
 | 
			
		||||
 *
 | 
			
		||||
 * Responsbile for pulling down the HCI interface, and powering down the chip.
 | 
			
		||||
 * Will block until power down is complete, and it is safe to immediately call 
 | 
			
		||||
 * enable().
 | 
			
		||||
 *
 | 
			
		||||
 * Returns 0 on success, -ve on error */
 | 
			
		||||
int ant_disable();
 | 
			
		||||
 | 
			
		||||
/* Returns 1 if enabled, 0 if disabled, and -ve on error */
 | 
			
		||||
int ant_is_enabled();
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										67
									
								
								src/vfs/prerelease/ant_driver_defines.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								src/vfs/prerelease/ant_driver_defines.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,67 @@
 | 
			
		||||
/*
 | 
			
		||||
 * ANT Stack
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2011 Dynastream Innovations
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
/*******************************************************************************\
 | 
			
		||||
*
 | 
			
		||||
*   FILE NAME:    ant_driver_defines.h
 | 
			
		||||
*
 | 
			
		||||
*   BRIEF:
 | 
			
		||||
*      This file defines ANT specific HCI values used by the ANT chip for a
 | 
			
		||||
*      sample TTY implementation.
 | 
			
		||||
*
 | 
			
		||||
*
 | 
			
		||||
\*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef __VFS_PRERELEASE_H
 | 
			
		||||
#define __VFS_PRERELEASE_H
 | 
			
		||||
 | 
			
		||||
#define ANT_CHIP_NAME                        "TTY"
 | 
			
		||||
 | 
			
		||||
#define ANT_COMMANDS_DEVICE_NAME             "/dev/smd5"
 | 
			
		||||
#define ANT_DATA_DEVICE_NAME                 "/dev/smd6"
 | 
			
		||||
 | 
			
		||||
// Hard reset not supported, don't define ANT_IOCTL_RESET
 | 
			
		||||
 | 
			
		||||
// -----------------------------------------
 | 
			
		||||
// |         Header       | Data |  Footer  |
 | 
			
		||||
// |----------------------|-----------------|
 | 
			
		||||
// |Optional| Data | Opt. | ...  | Optional |
 | 
			
		||||
// | Opcode | Size | Sync |      | Checksum |
 | 
			
		||||
 | 
			
		||||
#define ANT_HCI_OPCODE_SIZE                  0
 | 
			
		||||
#define ANT_HCI_SIZE_SIZE                    1
 | 
			
		||||
 | 
			
		||||
#define ANT_HCI_SYNC_SIZE                    0
 | 
			
		||||
#define ANT_HCI_CHECKSUM_SIZE                0
 | 
			
		||||
 | 
			
		||||
#define ANT_MESG_FLOW_CONTROL                ((ANT_U8)0xC9)
 | 
			
		||||
 | 
			
		||||
#define ANT_FLOW_GO                          ((ANT_U8)0x00)
 | 
			
		||||
 | 
			
		||||
// ---------------------- Not chip specific
 | 
			
		||||
 | 
			
		||||
#define ANT_HCI_HEADER_SIZE                  ((ANT_HCI_OPCODE_SIZE) + (ANT_HCI_SIZE_SIZE) + (ANT_HCI_SYNC_SIZE))
 | 
			
		||||
 | 
			
		||||
#define ANT_HCI_OPCODE_OFFSET                0
 | 
			
		||||
#define ANT_HCI_SIZE_OFFSET                  ((ANT_HCI_OPCODE_OFFSET) + (ANT_HCI_OPCODE_SIZE))
 | 
			
		||||
#define ANT_HCI_SYNC_OFFSET                  ((ANT_HCI_SIZE_OFFSET) + (ANT_HCI_SIZE_SIZE))
 | 
			
		||||
#define ANT_HCI_DATA_OFFSET                  (ANT_HCI_HEADER_SIZE)
 | 
			
		||||
 | 
			
		||||
#define ANT_FLOW_STOP                        ((ANT_U8)0x80)
 | 
			
		||||
#define ANT_FLOW_GO_WAIT_TIMEOUT_SEC         10
 | 
			
		||||
 | 
			
		||||
#endif /* ifndef __VFS_PRERELEASE_H */
 | 
			
		||||
							
								
								
									
										67
									
								
								src/vfs/ste/cg29xx/ant_driver_defines.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								src/vfs/ste/cg29xx/ant_driver_defines.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,67 @@
 | 
			
		||||
/*
 | 
			
		||||
 * ANT Stack
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2011 Dynastream Innovations
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
/*******************************************************************************\
 | 
			
		||||
*
 | 
			
		||||
*   FILE NAME:      ant_driver_defines.h
 | 
			
		||||
*
 | 
			
		||||
*   BRIEF:
 | 
			
		||||
*       This file defines constants for the ST-E CG29XX implementation
 | 
			
		||||
*
 | 
			
		||||
*
 | 
			
		||||
\*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef __VFS_PRERELEASE_H
 | 
			
		||||
#define __VFS_PRERELEASE_H
 | 
			
		||||
 | 
			
		||||
#define ANT_CHIP_NAME                        "ST-E CG29XX"
 | 
			
		||||
 | 
			
		||||
#define ANT_COMMANDS_DEVICE_NAME             "/dev/cg2900_antradio_cmd"
 | 
			
		||||
#define ANT_DATA_DEVICE_NAME                 "/dev/cg2900_antradio_data"
 | 
			
		||||
 | 
			
		||||
// TODO Must define ANT_IOCTL_RESET to value driver is expecting
 | 
			
		||||
#define ANT_IOCTL_RESET                      _IO('H', 160)
 | 
			
		||||
 | 
			
		||||
// -----------------------------------------
 | 
			
		||||
// |         Header       | Data |  Footer  |
 | 
			
		||||
// |----------------------|-----------------|
 | 
			
		||||
// |Optional| Data | Opt. | ...  | Optional |
 | 
			
		||||
// | Opcode | Size | Sync |      | Checksum |
 | 
			
		||||
 | 
			
		||||
#define ANT_HCI_OPCODE_SIZE                  0
 | 
			
		||||
#define ANT_HCI_SIZE_SIZE                    1
 | 
			
		||||
 | 
			
		||||
#define ANT_HCI_SYNC_SIZE                    0
 | 
			
		||||
#define ANT_HCI_CHECKSUM_SIZE                0
 | 
			
		||||
 | 
			
		||||
#define ANT_MESG_FLOW_CONTROL                ((ANT_U8)0xC9)
 | 
			
		||||
 | 
			
		||||
#define ANT_FLOW_GO                          ((ANT_U8)0x00)
 | 
			
		||||
 | 
			
		||||
// ---------------------- Not chip specific
 | 
			
		||||
 | 
			
		||||
#define ANT_HCI_HEADER_SIZE                  ((ANT_HCI_OPCODE_SIZE) + (ANT_HCI_SIZE_SIZE) + (ANT_HCI_SYNC_SIZE))
 | 
			
		||||
 | 
			
		||||
#define ANT_HCI_OPCODE_OFFSET                0
 | 
			
		||||
#define ANT_HCI_SIZE_OFFSET                  ((ANT_HCI_OPCODE_OFFSET) + (ANT_HCI_OPCODE_SIZE))
 | 
			
		||||
#define ANT_HCI_SYNC_OFFSET                  ((ANT_HCI_SIZE_OFFSET) + (ANT_HCI_SIZE_SIZE))
 | 
			
		||||
#define ANT_HCI_DATA_OFFSET                  (ANT_HCI_HEADER_SIZE)
 | 
			
		||||
 | 
			
		||||
#define ANT_FLOW_STOP                        ((ANT_U8)0x80)
 | 
			
		||||
#define ANT_FLOW_GO_WAIT_TIMEOUT_SEC         10
 | 
			
		||||
 | 
			
		||||
#endif /* ifndef __VFS_PRERELEASE_H */
 | 
			
		||||
		Reference in New Issue
	
	Block a user