initial commit
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
// ****************************************************************************
|
||||
//
|
||||
// amdtp_api.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Ambiq Micro's demonstration of AMDTP client.
|
||||
//!
|
||||
//! @{
|
||||
//
|
||||
// ****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifndef AMDTP_API_H
|
||||
#define AMDTP_API_H
|
||||
|
||||
#include "wsf_os.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**************************************************************************************************
|
||||
Function Declarations
|
||||
**************************************************************************************************/
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AmdtpcStart
|
||||
*
|
||||
* \brief Start the application.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AmdtpcStart(void);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AmdtpcHandlerInit
|
||||
*
|
||||
* \brief Application handler init function called during system initialization.
|
||||
*
|
||||
* \param handlerID WSF handler ID for App.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AmdtpcHandlerInit(wsfHandlerId_t handlerId);
|
||||
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AmdtpcHandler
|
||||
*
|
||||
* \brief WSF event handler for the application.
|
||||
*
|
||||
* \param event WSF event mask.
|
||||
* \param pMsg WSF message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AmdtpcHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg);
|
||||
|
||||
void AmdtpcScanStart(void);
|
||||
void AmdtpcScanStop(void);
|
||||
void AmdtpcConnOpen(uint8_t idx);
|
||||
void AmdtpcSendTestData(void);
|
||||
void AmdtpcSendTestDataStop(void);
|
||||
void AmdtpcRequestServerSend(void);
|
||||
void AmdtpcRequestServerSendStop(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* AMDTP_API_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,113 @@
|
||||
// ****************************************************************************
|
||||
//
|
||||
// amdtp_api.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Ambiq Micro's demonstration of AMDTP service.
|
||||
//!
|
||||
//! @{
|
||||
//
|
||||
// ****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifndef AMDTP_API_H
|
||||
#define AMDTP_API_H
|
||||
|
||||
#include "wsf_os.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**************************************************************************************************
|
||||
Macros
|
||||
**************************************************************************************************/
|
||||
|
||||
#ifndef AMDTP_CONN_MAX
|
||||
#define AMDTP_CONN_MAX 1
|
||||
#endif
|
||||
|
||||
/**************************************************************************************************
|
||||
Function Declarations
|
||||
**************************************************************************************************/
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AmdtpStart
|
||||
*
|
||||
* \brief Start the application.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AmdtpStart(void);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AmdtpHandlerInit
|
||||
*
|
||||
* \brief Application handler init function called during system initialization.
|
||||
*
|
||||
* \param handlerID WSF handler ID for App.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AmdtpHandlerInit(wsfHandlerId_t handlerId);
|
||||
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AmdtpHandler
|
||||
*
|
||||
* \brief WSF event handler for the application.
|
||||
*
|
||||
* \param event WSF event mask.
|
||||
* \param pMsg WSF message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AmdtpHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* AMDTP_API_H */
|
||||
@@ -0,0 +1,845 @@
|
||||
// ****************************************************************************
|
||||
//
|
||||
// amdtp_main.c
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Ambiq Micro's demonstration of AMDTP service.
|
||||
//!
|
||||
//! @{
|
||||
//
|
||||
// ****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#include <string.h>
|
||||
#include "wsf_types.h"
|
||||
#include "bstream.h"
|
||||
#include "wsf_msg.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "hci_api.h"
|
||||
#include "dm_api.h"
|
||||
#include "att_api.h"
|
||||
#include "smp_api.h"
|
||||
#include "app_api.h"
|
||||
#include "app_db.h"
|
||||
#include "app_ui.h"
|
||||
#include "app_hw.h"
|
||||
#include "svc_ch.h"
|
||||
#include "svc_core.h"
|
||||
#include "svc_dis.h"
|
||||
#include "amdtp_api.h"
|
||||
#include "amdtps_api.h"
|
||||
#include "svc_amdtp.h"
|
||||
|
||||
#include "am_util.h"
|
||||
#include "gatt_api.h"
|
||||
|
||||
/**************************************************************************************************
|
||||
Macros
|
||||
**************************************************************************************************/
|
||||
#define MEASURE_THROUGHPUT
|
||||
|
||||
/*! WSF message event starting value */
|
||||
#define AMDTP_MSG_START 0xA0
|
||||
|
||||
/*! WSF message event enumeration */
|
||||
enum
|
||||
{
|
||||
AMDTP_TIMER_IND = AMDTP_MSG_START, /*! AMDTP tx timeout timer expired */
|
||||
#ifdef MEASURE_THROUGHPUT
|
||||
AMDTP_MEAS_TP_TIMER_IND,
|
||||
#endif
|
||||
};
|
||||
|
||||
/**************************************************************************************************
|
||||
Data Types
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! Application message type */
|
||||
typedef union
|
||||
{
|
||||
wsfMsgHdr_t hdr;
|
||||
dmEvt_t dm;
|
||||
attsCccEvt_t ccc;
|
||||
attEvt_t att;
|
||||
} amdtpMsg_t;
|
||||
|
||||
static void amdtpClose(amdtpMsg_t *pMsg);
|
||||
/**************************************************************************************************
|
||||
Configurable Parameters
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! configurable parameters for advertising */
|
||||
static const appAdvCfg_t amdtpAdvCfg =
|
||||
{
|
||||
{60000, 0, 0}, /*! Advertising durations in ms */
|
||||
{ 800, 800, 0} /*! Advertising intervals in 0.625 ms units */
|
||||
};
|
||||
|
||||
/*! configurable parameters for slave */
|
||||
static const appSlaveCfg_t amdtpSlaveCfg =
|
||||
{
|
||||
AMDTP_CONN_MAX, /*! Maximum connections */
|
||||
};
|
||||
|
||||
/*! configurable parameters for security */
|
||||
static const appSecCfg_t amdtpSecCfg =
|
||||
{
|
||||
DM_AUTH_BOND_FLAG | DM_AUTH_SC_FLAG, /*! Authentication and bonding flags */
|
||||
0, /*! Initiator key distribution flags */
|
||||
DM_KEY_DIST_LTK, /*! Responder key distribution flags */
|
||||
FALSE, /*! TRUE if Out-of-band pairing data is present */
|
||||
FALSE /*! TRUE to initiate security upon connection */
|
||||
};
|
||||
|
||||
/*! configurable parameters for AMDTP connection parameter update */
|
||||
static const appUpdateCfg_t amdtpUpdateCfg =
|
||||
{
|
||||
3000, /*! Connection idle period in ms before attempting
|
||||
connection parameter update; set to zero to disable */
|
||||
/* W/A: Apollo2-Blue has issues with interval 7.5ms */
|
||||
#if defined(AM_PART_APOLLO3) || defined(AM_PART_APOLLO3P)
|
||||
6, /*! 7.5ms */
|
||||
15, /*! 18.75ms */
|
||||
#else
|
||||
8,
|
||||
18,
|
||||
#endif
|
||||
0, /*! Connection latency */
|
||||
600, /*! Supervision timeout in 10ms units */
|
||||
5 /*! Number of update attempts before giving up */
|
||||
};
|
||||
|
||||
/*! SMP security parameter configuration */
|
||||
static const smpCfg_t amdtpSmpCfg =
|
||||
{
|
||||
3000, /*! 'Repeated attempts' timeout in msec */
|
||||
SMP_IO_NO_IN_NO_OUT, /*! I/O Capability */
|
||||
7, /*! Minimum encryption key length */
|
||||
16, /*! Maximum encryption key length */
|
||||
3, /*! Attempts to trigger 'repeated attempts' timeout */
|
||||
0, /*! Device authentication requirements */
|
||||
};
|
||||
|
||||
/*! AMDTPS configuration */
|
||||
static const AmdtpsCfg_t amdtpAmdtpsCfg =
|
||||
{
|
||||
0
|
||||
};
|
||||
/**************************************************************************************************
|
||||
Advertising Data
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! advertising data, discoverable mode */
|
||||
static const uint8_t amdtpAdvDataDisc[] =
|
||||
{
|
||||
/*! flags */
|
||||
2, /*! length */
|
||||
DM_ADV_TYPE_FLAGS, /*! AD type */
|
||||
DM_FLAG_LE_GENERAL_DISC | /*! flags */
|
||||
DM_FLAG_LE_BREDR_NOT_SUP,
|
||||
|
||||
/*! tx power */
|
||||
2, /*! length */
|
||||
DM_ADV_TYPE_TX_POWER, /*! AD type */
|
||||
0, /*! tx power */
|
||||
|
||||
/*! service UUID list */
|
||||
3, /*! length */
|
||||
DM_ADV_TYPE_16_UUID, /*! AD type */
|
||||
UINT16_TO_BYTES(ATT_UUID_DEVICE_INFO_SERVICE),
|
||||
|
||||
17, /*! length */
|
||||
DM_ADV_TYPE_128_UUID, /*! AD type */
|
||||
ATT_UUID_AMDTP_SERVICE
|
||||
};
|
||||
|
||||
/*! scan data, discoverable mode */
|
||||
static const uint8_t amdtpScanDataDisc[] =
|
||||
{
|
||||
/*! device name */
|
||||
6, /*! length */
|
||||
DM_ADV_TYPE_LOCAL_NAME, /*! AD type */
|
||||
'A',
|
||||
'm',
|
||||
'd',
|
||||
't',
|
||||
'p'
|
||||
};
|
||||
|
||||
/**************************************************************************************************
|
||||
Client Characteristic Configuration Descriptors
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! enumeration of client characteristic configuration descriptors */
|
||||
enum
|
||||
{
|
||||
AMDTP_GATT_SC_CCC_IDX, /*! GATT service, service changed characteristic */
|
||||
AMDTP_AMDTPS_TX_CCC_IDX, /*! AMDTP service, tx characteristic */
|
||||
AMDTP_AMDTPS_RX_ACK_CCC_IDX, /*! AMDTP service, rx ack characteristic */
|
||||
AMDTP_NUM_CCC_IDX
|
||||
};
|
||||
|
||||
/*! client characteristic configuration descriptors settings, indexed by above enumeration */
|
||||
static const attsCccSet_t amdtpCccSet[AMDTP_NUM_CCC_IDX] =
|
||||
{
|
||||
/* cccd handle value range security level */
|
||||
{GATT_SC_CH_CCC_HDL, ATT_CLIENT_CFG_INDICATE, DM_SEC_LEVEL_NONE}, /* AMDTP_GATT_SC_CCC_IDX */
|
||||
{AMDTPS_TX_CH_CCC_HDL, ATT_CLIENT_CFG_NOTIFY, DM_SEC_LEVEL_NONE}, /* AMDTP_AMDTPS_TX_CCC_IDX */
|
||||
{AMDTPS_ACK_CH_CCC_HDL, ATT_CLIENT_CFG_NOTIFY, DM_SEC_LEVEL_NONE} /* AMDTP_AMDTPS_RX_ACK_CCC_IDX */
|
||||
};
|
||||
|
||||
/**************************************************************************************************
|
||||
Global Variables
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! WSF handler ID */
|
||||
wsfHandlerId_t amdtpHandlerId;
|
||||
|
||||
#ifdef MEASURE_THROUGHPUT
|
||||
wsfTimer_t measTpTimer;
|
||||
int gTotalDataBytesRecev = 0;
|
||||
#endif
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amdtpDmCback
|
||||
*
|
||||
* \brief Application DM callback.
|
||||
*
|
||||
* \param pDmEvt DM callback event
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void amdtpDmCback(dmEvt_t *pDmEvt)
|
||||
{
|
||||
dmEvt_t *pMsg;
|
||||
uint16_t len;
|
||||
|
||||
len = DmSizeOfEvt(pDmEvt);
|
||||
|
||||
if ((pMsg = WsfMsgAlloc(len)) != NULL)
|
||||
{
|
||||
memcpy(pMsg, pDmEvt, len);
|
||||
WsfMsgSend(amdtpHandlerId, pMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amdtpAttCback
|
||||
*
|
||||
* \brief Application ATT callback.
|
||||
*
|
||||
* \param pEvt ATT callback event
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void amdtpAttCback(attEvt_t *pEvt)
|
||||
{
|
||||
attEvt_t *pMsg;
|
||||
|
||||
if ((pMsg = WsfMsgAlloc(sizeof(attEvt_t) + pEvt->valueLen)) != NULL)
|
||||
{
|
||||
memcpy(pMsg, pEvt, sizeof(attEvt_t));
|
||||
pMsg->pValue = (uint8_t *) (pMsg + 1);
|
||||
memcpy(pMsg->pValue, pEvt->pValue, pEvt->valueLen);
|
||||
WsfMsgSend(amdtpHandlerId, pMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amdtpCccCback
|
||||
*
|
||||
* \brief Application ATTS client characteristic configuration callback.
|
||||
*
|
||||
* \param pDmEvt DM callback event
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void amdtpCccCback(attsCccEvt_t *pEvt)
|
||||
{
|
||||
attsCccEvt_t *pMsg;
|
||||
appDbHdl_t dbHdl;
|
||||
|
||||
/* if CCC not set from initialization and there's a device record */
|
||||
if ((pEvt->handle != ATT_HANDLE_NONE) &&
|
||||
((dbHdl = AppDbGetHdl((dmConnId_t) pEvt->hdr.param)) != APP_DB_HDL_NONE))
|
||||
{
|
||||
/* store value in device database */
|
||||
AppDbSetCccTblValue(dbHdl, pEvt->idx, pEvt->value);
|
||||
}
|
||||
|
||||
if ((pMsg = WsfMsgAlloc(sizeof(attsCccEvt_t))) != NULL)
|
||||
{
|
||||
memcpy(pMsg, pEvt, sizeof(attsCccEvt_t));
|
||||
WsfMsgSend(amdtpHandlerId, pMsg);
|
||||
}
|
||||
}
|
||||
|
||||
static bool sendDataContinuously = false;
|
||||
static uint32_t counter = 0;
|
||||
|
||||
static void AmdtpsSendTestData(void)
|
||||
{
|
||||
uint8_t data[1024] = {0};
|
||||
eAmdtpStatus_t status;
|
||||
|
||||
sendDataContinuously = true;
|
||||
*((uint32_t*)&(data[0])) = counter;
|
||||
|
||||
// status = AmdtpsSendPacket(AMDTP_PKT_TYPE_DATA, false, true, data, sizeof(data));
|
||||
status = AmdtpsSendPacket(AMDTP_PKT_TYPE_DATA, false, false, data, AttGetMtu(1) - 11); //fixme
|
||||
if (status != AMDTP_STATUS_SUCCESS)
|
||||
{
|
||||
APP_TRACE_INFO1("AmdtpsSendTestData() failed, status = %d\n", status);
|
||||
}
|
||||
else
|
||||
{
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amdtpProcCccState
|
||||
*
|
||||
* \brief Process CCC state change.
|
||||
*
|
||||
* \param pMsg Pointer to message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
bool bPairingCompleted = false;
|
||||
static void amdtpProcCccState(amdtpMsg_t *pMsg)
|
||||
{
|
||||
APP_TRACE_INFO3("ccc state ind value:%d handle:%d idx:%d", pMsg->ccc.value, pMsg->ccc.handle, pMsg->ccc.idx);
|
||||
|
||||
/* AMDTPS TX CCC */
|
||||
if (pMsg->ccc.idx == AMDTP_AMDTPS_TX_CCC_IDX)
|
||||
{
|
||||
if (pMsg->ccc.value == ATT_CLIENT_CFG_NOTIFY)
|
||||
{
|
||||
// notify enabled
|
||||
amdtps_start((dmConnId_t)pMsg->ccc.hdr.param, AMDTP_TIMER_IND, AMDTP_AMDTPS_TX_CCC_IDX);
|
||||
// AppSlaveSecurityeq(1);
|
||||
// if(bPairingCompleted == true)
|
||||
{
|
||||
#if defined(AMDTPS_TXTEST)
|
||||
counter = 0;
|
||||
AmdtpsSendTestData(); //fixme
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// notify disabled
|
||||
amdtpClose(pMsg);
|
||||
amdtps_stop((dmConnId_t)pMsg->ccc.hdr.param);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amdtpClose
|
||||
*
|
||||
* \brief Perform UI actions on connection close.
|
||||
*
|
||||
* \param pMsg Pointer to message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void amdtpClose(amdtpMsg_t *pMsg)
|
||||
{
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amdtpSetup
|
||||
*
|
||||
* \brief Set up advertising and other procedures that need to be performed after
|
||||
* device reset.
|
||||
*
|
||||
* \param pMsg Pointer to message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void amdtpSetup(amdtpMsg_t *pMsg)
|
||||
{
|
||||
/* set advertising and scan response data for discoverable mode */
|
||||
AppAdvSetData(APP_ADV_DATA_DISCOVERABLE, sizeof(amdtpAdvDataDisc), (uint8_t *) amdtpAdvDataDisc);
|
||||
AppAdvSetData(APP_SCAN_DATA_DISCOVERABLE, sizeof(amdtpScanDataDisc), (uint8_t *) amdtpScanDataDisc);
|
||||
|
||||
/* set advertising and scan response data for connectable mode */
|
||||
AppAdvSetData(APP_ADV_DATA_CONNECTABLE, sizeof(amdtpAdvDataDisc), (uint8_t *) amdtpAdvDataDisc);
|
||||
AppAdvSetData(APP_SCAN_DATA_CONNECTABLE, sizeof(amdtpScanDataDisc), (uint8_t *) amdtpScanDataDisc);
|
||||
|
||||
/* start advertising; automatically set connectable/discoverable mode and bondable mode */
|
||||
AppAdvStart(APP_MODE_AUTO_INIT);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amdtpBtnCback
|
||||
*
|
||||
* \brief Button press callback.
|
||||
*
|
||||
* \param btn Button press.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void amdtpBtnCback(uint8_t btn)
|
||||
{
|
||||
dmConnId_t connId;
|
||||
|
||||
/* button actions when connected */
|
||||
if ((connId = AppConnIsOpen()) != DM_CONN_ID_NONE)
|
||||
{
|
||||
switch (btn)
|
||||
{
|
||||
case APP_UI_BTN_1_SHORT:
|
||||
break;
|
||||
|
||||
case APP_UI_BTN_1_MED:
|
||||
break;
|
||||
|
||||
case APP_UI_BTN_1_LONG:
|
||||
AppConnClose(connId);
|
||||
break;
|
||||
|
||||
case APP_UI_BTN_2_SHORT:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* button actions when not connected */
|
||||
else
|
||||
{
|
||||
switch (btn)
|
||||
{
|
||||
case APP_UI_BTN_1_SHORT:
|
||||
/* start or restart advertising */
|
||||
AppAdvStart(APP_MODE_AUTO_INIT);
|
||||
break;
|
||||
|
||||
case APP_UI_BTN_1_MED:
|
||||
/* enter discoverable and bondable mode mode */
|
||||
AppSetBondable(TRUE);
|
||||
AppAdvStart(APP_MODE_DISCOVERABLE);
|
||||
break;
|
||||
|
||||
case APP_UI_BTN_1_LONG:
|
||||
/* clear bonded device info and restart advertising */
|
||||
AppDbDeleteAllRecords();
|
||||
AppAdvStart(APP_MODE_AUTO_INIT);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MEASURE_THROUGHPUT
|
||||
static void showThroughput(void)
|
||||
{
|
||||
APP_TRACE_INFO1("throughput : %d Bytes/s\n", gTotalDataBytesRecev);
|
||||
gTotalDataBytesRecev = 0;
|
||||
WsfTimerStartSec(&measTpTimer, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amdtpProcMsg
|
||||
*
|
||||
* \brief Process messages from the event handler.
|
||||
*
|
||||
* \param pMsg Pointer to message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void amdtpProcMsg(amdtpMsg_t *pMsg)
|
||||
{
|
||||
uint8_t uiEvent = APP_UI_NONE;
|
||||
|
||||
switch(pMsg->hdr.event)
|
||||
{
|
||||
case AMDTP_TIMER_IND:
|
||||
amdtps_proc_msg(&pMsg->hdr);
|
||||
break;
|
||||
|
||||
#ifdef MEASURE_THROUGHPUT
|
||||
case AMDTP_MEAS_TP_TIMER_IND:
|
||||
showThroughput();
|
||||
break;
|
||||
#endif
|
||||
|
||||
case ATTS_HANDLE_VALUE_CNF:
|
||||
//APP_TRACE_INFO1("ATTS_HANDLE_VALUE_CNF, status = %d", pMsg->att.hdr.status);
|
||||
|
||||
amdtps_proc_msg(&pMsg->hdr);
|
||||
break;
|
||||
|
||||
case ATTS_CCC_STATE_IND:
|
||||
amdtpProcCccState(pMsg);
|
||||
break;
|
||||
|
||||
case ATT_MTU_UPDATE_IND:
|
||||
APP_TRACE_INFO1("Negotiated MTU %d", ((attEvt_t *)pMsg)->mtu);
|
||||
break;
|
||||
|
||||
case DM_CONN_DATA_LEN_CHANGE_IND:
|
||||
APP_TRACE_INFO2("DM_CONN_DATA_LEN_CHANGE_IND, Tx=%d, Rx=%d", ((hciLeDataLenChangeEvt_t*)pMsg)->maxTxOctets, ((hciLeDataLenChangeEvt_t*)pMsg)->maxRxOctets);
|
||||
//AttcMtuReq((dmConnId_t)(pMsg->hdr.param), 480);//ATT_MAX_MTU);//83); //fixme
|
||||
break;
|
||||
case DM_RESET_CMPL_IND:
|
||||
AttsCalculateDbHash();
|
||||
DmSecGenerateEccKeyReq();
|
||||
amdtpSetup(pMsg);
|
||||
uiEvent = APP_UI_RESET_CMPL;
|
||||
break;
|
||||
|
||||
case DM_ADV_START_IND:
|
||||
uiEvent = APP_UI_ADV_START;
|
||||
break;
|
||||
|
||||
case DM_ADV_STOP_IND:
|
||||
uiEvent = APP_UI_ADV_STOP;
|
||||
break;
|
||||
|
||||
case DM_CONN_OPEN_IND:
|
||||
amdtps_proc_msg(&pMsg->hdr);
|
||||
// AttcMtuReq((dmConnId_t)(pMsg->hdr.param), ATT_MAX_MTU);//83); //fixme
|
||||
|
||||
// hciConnSpec_t connSpec;
|
||||
// connSpec.connIntervalMin = (7.5/1.25);
|
||||
// connSpec.connIntervalMax = (15/1.25);
|
||||
// connSpec.connLatency = 0;
|
||||
// connSpec.supTimeout = 200;
|
||||
// connSpec.minCeLen = 4;//0;
|
||||
// connSpec.maxCeLen = 8;//0xffff; //fixme
|
||||
// DmConnUpdate(1, &connSpec);
|
||||
|
||||
// PDU length, TX interval (0x148 ~ 0x848)
|
||||
//DmConnSetDataLen(1, 27, 0x148);
|
||||
DmConnSetDataLen(1, 251, 0x848);
|
||||
|
||||
// AppSlaveSecurityReq(1);
|
||||
uiEvent = APP_UI_CONN_OPEN;
|
||||
break;
|
||||
|
||||
case DM_CONN_CLOSE_IND:
|
||||
amdtpClose(pMsg);
|
||||
amdtps_proc_msg(&pMsg->hdr);
|
||||
|
||||
APP_TRACE_INFO1("DM_CONN_CLOSE_IND, reason = 0x%x", pMsg->dm.connClose.reason);
|
||||
|
||||
uiEvent = APP_UI_CONN_CLOSE;
|
||||
break;
|
||||
|
||||
case DM_CONN_UPDATE_IND:
|
||||
amdtps_proc_msg(&pMsg->hdr);
|
||||
break;
|
||||
|
||||
case DM_SEC_PAIR_CMPL_IND:
|
||||
DmSecGenerateEccKeyReq();
|
||||
|
||||
uiEvent = APP_UI_SEC_PAIR_CMPL;
|
||||
|
||||
bPairingCompleted = true;
|
||||
|
||||
break;
|
||||
|
||||
case DM_SEC_PAIR_FAIL_IND:
|
||||
DmSecGenerateEccKeyReq();
|
||||
|
||||
APP_TRACE_INFO1("DM_SEC_PAIR_FAIL_IND, status = 0x%x", pMsg->dm.pairCmpl.hdr.status);
|
||||
bPairingCompleted = false;
|
||||
|
||||
uiEvent = APP_UI_SEC_PAIR_FAIL;
|
||||
break;
|
||||
|
||||
case DM_SEC_ENCRYPT_IND:
|
||||
uiEvent = APP_UI_SEC_ENCRYPT;
|
||||
break;
|
||||
|
||||
case DM_SEC_ENCRYPT_FAIL_IND:
|
||||
uiEvent = APP_UI_SEC_ENCRYPT_FAIL;
|
||||
break;
|
||||
|
||||
case DM_SEC_AUTH_REQ_IND:
|
||||
AppHandlePasskey(&pMsg->dm.authReq);
|
||||
break;
|
||||
|
||||
case DM_SEC_ECC_KEY_IND:
|
||||
DmSecSetEccKey(&pMsg->dm.eccMsg.data.key);
|
||||
break;
|
||||
|
||||
case DM_SEC_COMPARE_IND:
|
||||
AppHandleNumericComparison(&pMsg->dm.cnfInd);
|
||||
break;
|
||||
|
||||
case DM_HW_ERROR_IND:
|
||||
uiEvent = APP_UI_HW_ERROR;
|
||||
break;
|
||||
case DM_VENDOR_SPEC_CMD_CMPL_IND:
|
||||
{
|
||||
#if defined(AM_PART_APOLLO) || defined(AM_PART_APOLLO2)
|
||||
|
||||
uint8_t *param_ptr = &pMsg->dm.vendorSpecCmdCmpl.param[0];
|
||||
|
||||
switch (pMsg->dm.vendorSpecCmdCmpl.opcode)
|
||||
{
|
||||
case 0xFC20: //read at address
|
||||
{
|
||||
uint32_t read_value;
|
||||
|
||||
BSTREAM_TO_UINT32(read_value, param_ptr);
|
||||
|
||||
APP_TRACE_INFO3("VSC 0x%0x complete status %x param %x",
|
||||
pMsg->dm.vendorSpecCmdCmpl.opcode,
|
||||
pMsg->hdr.status,
|
||||
read_value);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
APP_TRACE_INFO2("VSC 0x%0x complete status %x",
|
||||
pMsg->dm.vendorSpecCmdCmpl.opcode,
|
||||
pMsg->hdr.status);
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (uiEvent != APP_UI_NONE)
|
||||
{
|
||||
AppUiAction(uiEvent);
|
||||
}
|
||||
}
|
||||
//
|
||||
//static void AmdtpsSendTestData(void)
|
||||
//{
|
||||
// static uint8_t counter = 0;
|
||||
// uint8_t data[236] = {0};
|
||||
// eAmdtpStatus_t status;
|
||||
//
|
||||
// sendDataContinuously = true;
|
||||
// data[1] = counter;
|
||||
// status = AmdtpsSendPacket(AMDTP_PKT_TYPE_DATA, false, true, data, sizeof(data));
|
||||
// if (status != AMDTP_STATUS_SUCCESS)
|
||||
// {
|
||||
// APP_TRACE_INFO1("AmdtpsSendTestData() failed, status = %d\n", status);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// counter++;
|
||||
// }
|
||||
//}
|
||||
|
||||
void amdtpDtpRecvCback(uint8_t * buf, uint16_t len)
|
||||
{
|
||||
#ifdef MEASURE_THROUGHPUT
|
||||
static bool measTpStarted = false;
|
||||
#endif
|
||||
#if 0
|
||||
// reception callback
|
||||
// print the received data
|
||||
APP_TRACE_INFO0("-----------AMDTP Received data--------------\n");
|
||||
APP_TRACE_INFO3("len = %d, buf[0] = %d, buf[1] = %d\n", len, buf[0], buf[1]);
|
||||
#endif
|
||||
if (buf[0] == 1)
|
||||
{
|
||||
APP_TRACE_INFO0("send test data\n");
|
||||
AmdtpsSendTestData();
|
||||
}
|
||||
else if (buf[0] == 2)
|
||||
{
|
||||
APP_TRACE_INFO0("send test data stop\n");
|
||||
sendDataContinuously = false;
|
||||
}
|
||||
#ifdef MEASURE_THROUGHPUT
|
||||
gTotalDataBytesRecev += len;
|
||||
if (!measTpStarted)
|
||||
{
|
||||
measTpStarted = true;
|
||||
WsfTimerStartSec(&measTpTimer, 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void amdtpDtpTransCback(eAmdtpStatus_t status)
|
||||
{
|
||||
// APP_TRACE_INFO1("amdtpDtpTransCback status = %d\n", status);
|
||||
if (status == AMDTP_STATUS_SUCCESS && sendDataContinuously)
|
||||
{
|
||||
AmdtpsSendTestData();
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AmdtpHandlerInit
|
||||
*
|
||||
* \brief Application handler init function called during system initialization.
|
||||
*
|
||||
* \param handlerID WSF handler ID.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AmdtpHandlerInit(wsfHandlerId_t handlerId)
|
||||
{
|
||||
APP_TRACE_INFO0("AmdtpHandlerInit");
|
||||
|
||||
/* store handler ID */
|
||||
amdtpHandlerId = handlerId;
|
||||
|
||||
/* Set configuration pointers */
|
||||
pAppAdvCfg = (appAdvCfg_t *) &amdtpAdvCfg;
|
||||
pAppSlaveCfg = (appSlaveCfg_t *) &amdtpSlaveCfg;
|
||||
pAppSecCfg = (appSecCfg_t *) &amdtpSecCfg;
|
||||
pAppUpdateCfg = (appUpdateCfg_t *) &amdtpUpdateCfg;
|
||||
|
||||
/* Initialize application framework */
|
||||
AppSlaveInit();
|
||||
AppServerInit();
|
||||
/* Set stack configuration pointers */
|
||||
pSmpCfg = (smpCfg_t *) &amdtpSmpCfg;
|
||||
|
||||
/* initialize amdtp service server */
|
||||
amdtps_init(handlerId, (AmdtpsCfg_t *) &amdtpAmdtpsCfg, amdtpDtpRecvCback, amdtpDtpTransCback);
|
||||
|
||||
#ifdef MEASURE_THROUGHPUT
|
||||
measTpTimer.handlerId = handlerId;
|
||||
measTpTimer.msg.event = AMDTP_MEAS_TP_TIMER_IND;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AmdtpHandler
|
||||
*
|
||||
* \brief WSF event handler for application.
|
||||
*
|
||||
* \param event WSF event mask.
|
||||
* \param pMsg WSF message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AmdtpHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg)
|
||||
{
|
||||
if (pMsg != NULL)
|
||||
{
|
||||
// APP_TRACE_INFO1("Amdtp got evt %d", pMsg->event);
|
||||
|
||||
/* process ATT messages */
|
||||
if (pMsg->event >= ATT_CBACK_START && pMsg->event <= ATT_CBACK_END)
|
||||
{
|
||||
/* process server-related ATT messages */
|
||||
AppServerProcAttMsg(pMsg);
|
||||
}
|
||||
/* process DM messages */
|
||||
else if (pMsg->event >= DM_CBACK_START && pMsg->event <= DM_CBACK_END)
|
||||
{
|
||||
/* process advertising and connection-related messages */
|
||||
AppSlaveProcDmMsg((dmEvt_t *) pMsg);
|
||||
|
||||
/* process security-related messages */
|
||||
AppSlaveSecProcDmMsg((dmEvt_t *) pMsg);
|
||||
}
|
||||
|
||||
/* perform profile and user interface-related operations */
|
||||
amdtpProcMsg((amdtpMsg_t *) pMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AmdtpStart
|
||||
*
|
||||
* \brief Start the application.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AmdtpStart(void)
|
||||
{
|
||||
/* Register for stack callbacks */
|
||||
DmRegister(amdtpDmCback);
|
||||
DmConnRegister(DM_CLIENT_ID_APP, amdtpDmCback);
|
||||
AttRegister(amdtpAttCback);
|
||||
AttConnRegister(AppServerConnCback);
|
||||
AttsCccRegister(AMDTP_NUM_CCC_IDX, (attsCccSet_t *) amdtpCccSet, amdtpCccCback);
|
||||
|
||||
/* Register for app framework callbacks */
|
||||
AppUiBtnRegister(amdtpBtnCback);
|
||||
|
||||
/* Initialize attribute server database */
|
||||
SvcCoreGattCbackRegister(GattReadCback, GattWriteCback);
|
||||
SvcCoreAddGroup();
|
||||
SvcDisAddGroup();
|
||||
SvcAmdtpsCbackRegister(NULL, amdtps_write_cback);
|
||||
SvcAmdtpsAddGroup();
|
||||
|
||||
/* Set Service Changed CCCD index. */
|
||||
GattSetSvcChangedIdx(AMDTP_GATT_SC_CCC_IDX);
|
||||
/* Reset the device */
|
||||
DmDevReset();
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
// ****************************************************************************
|
||||
//
|
||||
// amota_api.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Ambiq Micro's demonstration of AMOTA service.
|
||||
//!
|
||||
//! @{
|
||||
//
|
||||
// ****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifndef AMOTA_API_H
|
||||
#define AMOTA_API_H
|
||||
|
||||
#include "wsf_os.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**************************************************************************************************
|
||||
Macros
|
||||
**************************************************************************************************/
|
||||
|
||||
#ifndef AMOTA_CONN_MAX
|
||||
#define AMOTA_CONN_MAX 1
|
||||
#endif
|
||||
|
||||
/**************************************************************************************************
|
||||
Function Declarations
|
||||
**************************************************************************************************/
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AmotaStart
|
||||
*
|
||||
* \brief Start the application.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AmotaStart(void);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AmotaHandlerInit
|
||||
*
|
||||
* \brief Application handler init function called during system initialization.
|
||||
*
|
||||
* \param handlerID WSF handler ID for App.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AmotaHandlerInit(wsfHandlerId_t handlerId);
|
||||
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AmotaHandler
|
||||
*
|
||||
* \brief WSF event handler for the application.
|
||||
*
|
||||
* \param event WSF event mask.
|
||||
* \param pMsg WSF message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AmotaHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* AMOTA_API_H */
|
||||
@@ -0,0 +1,693 @@
|
||||
// ****************************************************************************
|
||||
//
|
||||
// amota_main.c
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Ambiq Micro's demonstration of AMOTA service.
|
||||
//!
|
||||
//! @{
|
||||
//
|
||||
// ****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include "wsf_types.h"
|
||||
#include "bstream.h"
|
||||
#include "wsf_msg.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "hci_api.h"
|
||||
#include "dm_api.h"
|
||||
#include "att_api.h"
|
||||
#include "app_api.h"
|
||||
#include "app_db.h"
|
||||
#include "app_ui.h"
|
||||
#include "app_hw.h"
|
||||
#include "svc_ch.h"
|
||||
#include "svc_core.h"
|
||||
#include "svc_dis.h"
|
||||
#include "amota_api.h"
|
||||
#include "amotas_api.h"
|
||||
#include "svc_amotas.h"
|
||||
#include "gatt_api.h"
|
||||
|
||||
/**************************************************************************************************
|
||||
Macros
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! WSF message event starting value */
|
||||
#define AMOTA_MSG_START 0xA0
|
||||
|
||||
/*! WSF message event enumeration */
|
||||
enum
|
||||
{
|
||||
AMOTA_RESET_TIMER_IND = AMOTA_MSG_START, /*! AMOTA reset timer expired */
|
||||
AMOTA_DISCONNECT_TIMER_IND, /*! AMOTA disconnect timer expired */
|
||||
};
|
||||
|
||||
/**************************************************************************************************
|
||||
Data Types
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! Application message type */
|
||||
typedef union
|
||||
{
|
||||
wsfMsgHdr_t hdr;
|
||||
dmEvt_t dm;
|
||||
attsCccEvt_t ccc;
|
||||
attEvt_t att;
|
||||
} amotaMsg_t;
|
||||
|
||||
/**************************************************************************************************
|
||||
Configurable Parameters
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! configurable parameters for advertising */
|
||||
static const appAdvCfg_t amotaAdvCfg =
|
||||
{
|
||||
{ 0, 0, 0}, /*! Advertising durations in ms */
|
||||
{ 800, 800, 0} /*! Advertising intervals in 0.625 ms units */
|
||||
};
|
||||
|
||||
/*! configurable parameters for slave */
|
||||
static const appSlaveCfg_t amotaSlaveCfg =
|
||||
{
|
||||
AMOTA_CONN_MAX, /*! Maximum connections */
|
||||
};
|
||||
|
||||
/*! configurable parameters for security */
|
||||
static const appSecCfg_t amotaSecCfg =
|
||||
{
|
||||
DM_AUTH_BOND_FLAG, /*! Authentication and bonding flags */
|
||||
0, /*! Initiator key distribution flags */
|
||||
DM_KEY_DIST_LTK, /*! Responder key distribution flags */
|
||||
FALSE, /*! TRUE if Out-of-band pairing data is present */
|
||||
FALSE /*! TRUE to initiate security upon connection */
|
||||
};
|
||||
|
||||
/*! configurable parameters for AMOTA connection parameter update */
|
||||
static appUpdateCfg_t otaUpdateCfg =
|
||||
{
|
||||
0, /*! Connection idle period in ms before attempting
|
||||
connection parameter update; set to zero to disable */
|
||||
(15 / 1.25), /*! 15 ms */
|
||||
(30 / 1.25), /*! 30 ms */
|
||||
0, /*! Connection latency */
|
||||
(6000 / 10), /*! Supervision timeout in 10ms units */
|
||||
5 /*! Number of update attempts before giving up */
|
||||
};
|
||||
|
||||
/*! AMOTAS configuration */
|
||||
static const AmotasCfg_t amotasCfg =
|
||||
{
|
||||
0
|
||||
};
|
||||
|
||||
/**************************************************************************************************
|
||||
Advertising Data
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! advertising data, discoverable mode */
|
||||
static const uint8_t amotaAdvDataDisc[] =
|
||||
{
|
||||
/*! flags */
|
||||
2, /*! length */
|
||||
DM_ADV_TYPE_FLAGS, /*! AD type */
|
||||
DM_FLAG_LE_GENERAL_DISC | /*! flags */
|
||||
DM_FLAG_LE_BREDR_NOT_SUP,
|
||||
|
||||
/*! tx power */
|
||||
2, /*! length */
|
||||
DM_ADV_TYPE_TX_POWER, /*! AD type */
|
||||
0, /*! tx power */
|
||||
|
||||
/*! service UUID list */
|
||||
3, /*! length */
|
||||
DM_ADV_TYPE_16_UUID, /*! AD type */
|
||||
UINT16_TO_BYTES(ATT_UUID_DEVICE_INFO_SERVICE)
|
||||
};
|
||||
|
||||
/*! scan data, discoverable mode */
|
||||
static const uint8_t amotaScanDataDisc[] =
|
||||
{
|
||||
/*! device name */
|
||||
15, /*! length */
|
||||
DM_ADV_TYPE_LOCAL_NAME, /*! AD type */
|
||||
'a',
|
||||
'm',
|
||||
'b',
|
||||
'i',
|
||||
'q',
|
||||
'm',
|
||||
'i',
|
||||
'c',
|
||||
'r',
|
||||
'o',
|
||||
' ',
|
||||
'o',
|
||||
't',
|
||||
'a'
|
||||
};
|
||||
|
||||
/**************************************************************************************************
|
||||
Client Characteristic Configuration Descriptors
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! enumeration of client characteristic configuration descriptors */
|
||||
enum
|
||||
{
|
||||
AMOTA_GATT_SC_CCC_IDX, /*! GATT service, service changed characteristic */
|
||||
AMOTA_AMOTAS_TX_CCC_IDX, /*! AMOTA service, tx characteristic */
|
||||
AMOTA_NUM_CCC_IDX
|
||||
};
|
||||
|
||||
/*! client characteristic configuration descriptors settings, indexed by above enumeration */
|
||||
static const attsCccSet_t amotaCccSet[AMOTA_NUM_CCC_IDX] =
|
||||
{
|
||||
/* cccd handle value range security level */
|
||||
{GATT_SC_CH_CCC_HDL, ATT_CLIENT_CFG_INDICATE, DM_SEC_LEVEL_NONE}, /* AMOTA_GATT_SC_CCC_IDX */
|
||||
{AMOTAS_TX_CH_CCC_HDL, ATT_CLIENT_CFG_NOTIFY, DM_SEC_LEVEL_NONE} /* AMOTA_AMOTAS_TX_CCC_IDX */
|
||||
};
|
||||
|
||||
/**************************************************************************************************
|
||||
Global Variables
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! WSF handler ID */
|
||||
wsfHandlerId_t amotaHandlerId;
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amotaDmCback
|
||||
*
|
||||
* \brief Application DM callback.
|
||||
*
|
||||
* \param pDmEvt DM callback event
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void amotaDmCback(dmEvt_t *pDmEvt)
|
||||
{
|
||||
dmEvt_t *pMsg;
|
||||
|
||||
if ((pMsg = WsfMsgAlloc(sizeof(dmEvt_t))) != NULL)
|
||||
{
|
||||
memcpy(pMsg, pDmEvt, sizeof(dmEvt_t));
|
||||
WsfMsgSend(amotaHandlerId, pMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amotaAttCback
|
||||
*
|
||||
* \brief Application ATT callback.
|
||||
*
|
||||
* \param pEvt ATT callback event
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void amotaAttCback(attEvt_t *pEvt)
|
||||
{
|
||||
attEvt_t *pMsg;
|
||||
|
||||
if ((pMsg = WsfMsgAlloc(sizeof(attEvt_t) + pEvt->valueLen)) != NULL)
|
||||
{
|
||||
memcpy(pMsg, pEvt, sizeof(attEvt_t));
|
||||
pMsg->pValue = (uint8_t *) (pMsg + 1);
|
||||
memcpy(pMsg->pValue, pEvt->pValue, pEvt->valueLen);
|
||||
WsfMsgSend(amotaHandlerId, pMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amotaCccCback
|
||||
*
|
||||
* \brief Application ATTS client characteristic configuration callback.
|
||||
*
|
||||
* \param pDmEvt DM callback event
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void amotaCccCback(attsCccEvt_t *pEvt)
|
||||
{
|
||||
attsCccEvt_t *pMsg;
|
||||
appDbHdl_t dbHdl;
|
||||
|
||||
/* if CCC not set from initialization and there's a device record */
|
||||
if ((pEvt->handle != ATT_HANDLE_NONE) &&
|
||||
((dbHdl = AppDbGetHdl((dmConnId_t) pEvt->hdr.param)) != APP_DB_HDL_NONE))
|
||||
{
|
||||
/* store value in device database */
|
||||
AppDbSetCccTblValue(dbHdl, pEvt->idx, pEvt->value);
|
||||
}
|
||||
|
||||
if ((pMsg = WsfMsgAlloc(sizeof(attsCccEvt_t))) != NULL)
|
||||
{
|
||||
memcpy(pMsg, pEvt, sizeof(attsCccEvt_t));
|
||||
WsfMsgSend(amotaHandlerId, pMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amotaProcCccState
|
||||
*
|
||||
* \brief Process CCC state change.
|
||||
*
|
||||
* \param pMsg Pointer to message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void amotaProcCccState(amotaMsg_t *pMsg)
|
||||
{
|
||||
APP_TRACE_INFO3("ccc state ind value:%d handle:%d idx:%d", pMsg->ccc.value, pMsg->ccc.handle, pMsg->ccc.idx);
|
||||
|
||||
/* handle heart rate measurement CCC */
|
||||
/* AMOTAS TX CCC */
|
||||
if (pMsg->ccc.idx == AMOTA_AMOTAS_TX_CCC_IDX)
|
||||
{
|
||||
if (pMsg->ccc.value == ATT_CLIENT_CFG_NOTIFY)
|
||||
{
|
||||
// notify enabled
|
||||
amotas_start((dmConnId_t) pMsg->ccc.hdr.param,
|
||||
AMOTA_RESET_TIMER_IND, AMOTA_DISCONNECT_TIMER_IND,
|
||||
AMOTA_AMOTAS_TX_CCC_IDX);
|
||||
}
|
||||
else
|
||||
{
|
||||
// notify disabled
|
||||
amotas_stop((dmConnId_t) pMsg->ccc.hdr.param);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amotaClose
|
||||
*
|
||||
* \brief Perform UI actions on connection close.
|
||||
*
|
||||
* \param pMsg Pointer to message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void amotaClose(amotaMsg_t *pMsg)
|
||||
{
|
||||
/* stop amotas */
|
||||
amotas_conn_close((dmConnId_t) pMsg->hdr.param);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amotaSetup
|
||||
*
|
||||
* \brief Set up advertising and other procedures that need to be performed after
|
||||
* device reset.
|
||||
*
|
||||
* \param pMsg Pointer to message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void amotaSetup(amotaMsg_t *pMsg)
|
||||
{
|
||||
/* set advertising and scan response data for discoverable mode */
|
||||
AppAdvSetData(APP_ADV_DATA_DISCOVERABLE, sizeof(amotaAdvDataDisc), (uint8_t *) amotaAdvDataDisc);
|
||||
AppAdvSetData(APP_SCAN_DATA_DISCOVERABLE, sizeof(amotaScanDataDisc), (uint8_t *) amotaScanDataDisc);
|
||||
|
||||
/* set advertising and scan response data for connectable mode */
|
||||
AppAdvSetData(APP_ADV_DATA_CONNECTABLE, 0, NULL);
|
||||
AppAdvSetData(APP_SCAN_DATA_CONNECTABLE, 0, NULL);
|
||||
|
||||
/* start advertising; automatically set connectable/discoverable mode and bondable mode */
|
||||
AppAdvStart(APP_MODE_AUTO_INIT);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amotaBtnCback
|
||||
*
|
||||
* \brief Button press callback.
|
||||
*
|
||||
* \param btn Button press.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void amotaBtnCback(uint8_t btn)
|
||||
{
|
||||
dmConnId_t connId;
|
||||
|
||||
/* button actions when connected */
|
||||
if ((connId = AppConnIsOpen()) != DM_CONN_ID_NONE)
|
||||
{
|
||||
switch (btn)
|
||||
{
|
||||
case APP_UI_BTN_1_SHORT:
|
||||
break;
|
||||
|
||||
case APP_UI_BTN_1_MED:
|
||||
break;
|
||||
|
||||
case APP_UI_BTN_1_LONG:
|
||||
AppConnClose(connId);
|
||||
break;
|
||||
|
||||
case APP_UI_BTN_2_SHORT:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* button actions when not connected */
|
||||
else
|
||||
{
|
||||
switch (btn)
|
||||
{
|
||||
case APP_UI_BTN_1_SHORT:
|
||||
/* start or restart advertising */
|
||||
AppAdvStart(APP_MODE_AUTO_INIT);
|
||||
break;
|
||||
|
||||
case APP_UI_BTN_1_MED:
|
||||
/* enter discoverable and bondable mode mode */
|
||||
AppSetBondable(TRUE);
|
||||
AppAdvStart(APP_MODE_DISCOVERABLE);
|
||||
break;
|
||||
|
||||
case APP_UI_BTN_1_LONG:
|
||||
/* clear bonded device info and restart advertising */
|
||||
AppDbDeleteAllRecords();
|
||||
AppAdvStart(APP_MODE_AUTO_INIT);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amotaProcMsg
|
||||
*
|
||||
* \brief Process messages from the event handler.
|
||||
*
|
||||
* \param pMsg Pointer to message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void amotaProcMsg(amotaMsg_t *pMsg)
|
||||
{
|
||||
uint8_t uiEvent = APP_UI_NONE;
|
||||
|
||||
switch(pMsg->hdr.event)
|
||||
{
|
||||
case AMOTA_RESET_TIMER_IND:
|
||||
case AMOTA_DISCONNECT_TIMER_IND:
|
||||
amotas_proc_msg(&pMsg->hdr);
|
||||
break;
|
||||
|
||||
case ATTS_HANDLE_VALUE_CNF:
|
||||
break;
|
||||
|
||||
case ATTS_CCC_STATE_IND:
|
||||
amotaProcCccState(pMsg);
|
||||
break;
|
||||
|
||||
case ATT_MTU_UPDATE_IND:
|
||||
APP_TRACE_INFO1("Negotiated MTU %d", ((attEvt_t *)pMsg)->mtu);
|
||||
break;
|
||||
|
||||
case DM_RESET_CMPL_IND:
|
||||
AttsCalculateDbHash();
|
||||
DmSecGenerateEccKeyReq();
|
||||
amotaSetup(pMsg);
|
||||
uiEvent = APP_UI_RESET_CMPL;
|
||||
break;
|
||||
|
||||
case DM_ADV_SET_START_IND:
|
||||
uiEvent = APP_UI_ADV_SET_START_IND;
|
||||
break;
|
||||
|
||||
case DM_ADV_SET_STOP_IND:
|
||||
uiEvent = APP_UI_ADV_SET_STOP_IND;
|
||||
break;
|
||||
|
||||
case DM_ADV_START_IND:
|
||||
uiEvent = APP_UI_ADV_START;
|
||||
break;
|
||||
|
||||
case DM_ADV_STOP_IND:
|
||||
uiEvent = APP_UI_ADV_STOP;
|
||||
break;
|
||||
|
||||
case DM_CONN_OPEN_IND:
|
||||
amotas_proc_msg(&pMsg->hdr);
|
||||
uiEvent = APP_UI_CONN_OPEN;
|
||||
break;
|
||||
|
||||
case DM_CONN_CLOSE_IND:
|
||||
{
|
||||
hciDisconnectCmplEvt_t *evt = (hciDisconnectCmplEvt_t*) pMsg;
|
||||
// uiEvent = APP_UI_CONN_CLOSE;
|
||||
APP_TRACE_INFO1(">>> Connection closed reason 0x%x <<<",
|
||||
evt->reason);
|
||||
amotaClose(pMsg);
|
||||
}
|
||||
break;
|
||||
|
||||
case DM_CONN_UPDATE_IND:
|
||||
amotas_proc_msg(&pMsg->hdr);
|
||||
break;
|
||||
|
||||
case DM_SEC_PAIR_CMPL_IND:
|
||||
DmSecGenerateEccKeyReq();
|
||||
uiEvent = APP_UI_SEC_PAIR_CMPL;
|
||||
break;
|
||||
|
||||
case DM_SEC_PAIR_FAIL_IND:
|
||||
DmSecGenerateEccKeyReq();
|
||||
uiEvent = APP_UI_SEC_PAIR_FAIL;
|
||||
break;
|
||||
|
||||
case DM_SEC_ENCRYPT_IND:
|
||||
uiEvent = APP_UI_SEC_ENCRYPT;
|
||||
break;
|
||||
|
||||
case DM_SEC_ENCRYPT_FAIL_IND:
|
||||
uiEvent = APP_UI_SEC_ENCRYPT_FAIL;
|
||||
break;
|
||||
|
||||
case DM_SEC_AUTH_REQ_IND:
|
||||
AppHandlePasskey(&pMsg->dm.authReq);
|
||||
break;
|
||||
|
||||
case DM_SEC_ECC_KEY_IND:
|
||||
DmSecSetEccKey(&pMsg->dm.eccMsg.data.key);
|
||||
break;
|
||||
|
||||
case DM_SEC_COMPARE_IND:
|
||||
AppHandleNumericComparison(&pMsg->dm.cnfInd);
|
||||
break;
|
||||
|
||||
case DM_PRIV_CLEAR_RES_LIST_IND:
|
||||
APP_TRACE_INFO1("Clear resolving list status 0x%02x", pMsg->hdr.status);
|
||||
break;
|
||||
|
||||
case DM_HW_ERROR_IND:
|
||||
uiEvent = APP_UI_HW_ERROR;
|
||||
break;
|
||||
case DM_VENDOR_SPEC_CMD_CMPL_IND:
|
||||
{
|
||||
#if defined(AM_PART_APOLLO) || defined(AM_PART_APOLLO2)
|
||||
|
||||
uint8_t *param_ptr = &pMsg->dm.vendorSpecCmdCmpl.param[0];
|
||||
|
||||
switch (pMsg->dm.vendorSpecCmdCmpl.opcode)
|
||||
{
|
||||
case 0xFC20: //read at address
|
||||
{
|
||||
uint32_t read_value;
|
||||
|
||||
BSTREAM_TO_UINT32(read_value, param_ptr);
|
||||
|
||||
APP_TRACE_INFO3("VSC 0x%0x complete status %x param %x",
|
||||
pMsg->dm.vendorSpecCmdCmpl.opcode,
|
||||
pMsg->hdr.status,
|
||||
read_value);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
APP_TRACE_INFO2("VSC 0x%0x complete status %x",
|
||||
pMsg->dm.vendorSpecCmdCmpl.opcode,
|
||||
pMsg->hdr.status);
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (uiEvent != APP_UI_NONE)
|
||||
{
|
||||
AppUiAction(uiEvent);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AmotaHandlerInit
|
||||
*
|
||||
* \brief Application handler init function called during system initialization.
|
||||
*
|
||||
* \param handlerID WSF handler ID.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AmotaHandlerInit(wsfHandlerId_t handlerId)
|
||||
{
|
||||
APP_TRACE_INFO0("AmotaHandlerInit");
|
||||
|
||||
/* store handler ID */
|
||||
amotaHandlerId = handlerId;
|
||||
|
||||
/* Set configuration pointers */
|
||||
pAppAdvCfg = (appAdvCfg_t *) &amotaAdvCfg;
|
||||
pAppSlaveCfg = (appSlaveCfg_t *) &amotaSlaveCfg;
|
||||
pAppSecCfg = (appSecCfg_t *) &amotaSecCfg;
|
||||
pAppUpdateCfg = (appUpdateCfg_t *) &otaUpdateCfg;
|
||||
|
||||
/* Initialize application framework */
|
||||
AppSlaveInit();
|
||||
AppServerInit();
|
||||
|
||||
/* initialize amota service server */
|
||||
amotas_init(handlerId, (AmotasCfg_t *) &amotasCfg);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AmotaHandler
|
||||
*
|
||||
* \brief WSF event handler for application.
|
||||
*
|
||||
* \param event WSF event mask.
|
||||
* \param pMsg WSF message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AmotaHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg)
|
||||
{
|
||||
if (pMsg != NULL)
|
||||
{
|
||||
// APP_TRACE_INFO1("Amota got evt %d", pMsg->event);
|
||||
|
||||
/* process ATT messages */
|
||||
if (pMsg->event >= ATT_CBACK_START && pMsg->event <= ATT_CBACK_END)
|
||||
{
|
||||
/* process server-related ATT messages */
|
||||
AppServerProcAttMsg(pMsg);
|
||||
}
|
||||
/* process DM messages */
|
||||
else if (pMsg->event >= DM_CBACK_START && pMsg->event <= DM_CBACK_END)
|
||||
{
|
||||
/* process advertising and connection-related messages */
|
||||
AppSlaveProcDmMsg((dmEvt_t *) pMsg);
|
||||
|
||||
/* process security-related messages */
|
||||
AppSlaveSecProcDmMsg((dmEvt_t *) pMsg);
|
||||
}
|
||||
|
||||
/* perform profile and user interface-related operations */
|
||||
amotaProcMsg((amotaMsg_t *) pMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AmotaStart
|
||||
*
|
||||
* \brief Start the application.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AmotaStart(void)
|
||||
{
|
||||
/* Register for stack callbacks */
|
||||
DmRegister(amotaDmCback);
|
||||
DmConnRegister(DM_CLIENT_ID_APP, amotaDmCback);
|
||||
AttRegister(amotaAttCback);
|
||||
AttConnRegister(AppServerConnCback);
|
||||
AttsCccRegister(AMOTA_NUM_CCC_IDX, (attsCccSet_t *) amotaCccSet, amotaCccCback);
|
||||
|
||||
/* Register for app framework callbacks */
|
||||
AppUiBtnRegister(amotaBtnCback);
|
||||
|
||||
/* Initialize attribute server database */
|
||||
SvcCoreGattCbackRegister(GattReadCback, GattWriteCback);
|
||||
SvcCoreAddGroup();
|
||||
SvcDisAddGroup();
|
||||
SvcAmotasCbackRegister(NULL, amotas_write_cback);
|
||||
SvcAmotasAddGroup();
|
||||
|
||||
/* Set Service Changed CCCD index. */
|
||||
GattSetSvcChangedIdx(AMOTA_GATT_SC_CCC_IDX);
|
||||
|
||||
/* Reset the device */
|
||||
DmDevReset();
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
// ****************************************************************************
|
||||
//
|
||||
// ancs_api.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Ambiq Micro's demonstration of ANCSC.
|
||||
//!
|
||||
//! @{
|
||||
//
|
||||
// ****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifndef ANCS_API_H
|
||||
#define ANCS_API_H
|
||||
|
||||
#include "wsf_os.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**************************************************************************************************
|
||||
Macros
|
||||
**************************************************************************************************/
|
||||
|
||||
#ifndef ANCS_CONN_MAX
|
||||
#define ANCS_CONN_MAX 1
|
||||
#endif
|
||||
|
||||
/**************************************************************************************************
|
||||
Function Declarations
|
||||
**************************************************************************************************/
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AncsStart
|
||||
*
|
||||
* \brief Start the application.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AncsStart(void);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AncsHandlerInit
|
||||
*
|
||||
* \brief Application handler init function called during system initialization.
|
||||
*
|
||||
* \param handlerID WSF handler ID for App.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AncsHandlerInit(wsfHandlerId_t handlerId);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AncsHandler
|
||||
*
|
||||
* \brief WSF event handler for the application.
|
||||
*
|
||||
* \param event WSF event mask.
|
||||
* \param pMsg WSF message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AncsHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* ANCS_API_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,106 @@
|
||||
// ****************************************************************************
|
||||
//
|
||||
// beaconscanner_api.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Beacon Scanner sample application interface
|
||||
//!
|
||||
//! @{
|
||||
//
|
||||
// ****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
|
||||
#ifndef BEACONSCANNER_API_H
|
||||
#define BEACONSCANNER_API_H
|
||||
|
||||
#include "wsf_os.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**************************************************************************************************
|
||||
Function Declarations
|
||||
**************************************************************************************************/
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn BeaconScannerStart
|
||||
*
|
||||
* \brief Start Beacon Scan application.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void BeaconScannerStart(void);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn BeaconScannerHandlerInit
|
||||
*
|
||||
* \brief Beacon Scan handler init function called during system initialization.
|
||||
*
|
||||
* \param handlerID WSF handler ID for App.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void BeaconScannerHandlerInit(wsfHandlerId_t handlerId);
|
||||
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn BeaconScannerHandler
|
||||
*
|
||||
* \brief WSF event handler for Beacon Scan application.
|
||||
*
|
||||
* \param event WSF event mask.
|
||||
* \param pMsg WSF message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void BeaconScannerHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* BEACONSCANNER_API_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,109 @@
|
||||
// ****************************************************************************
|
||||
//
|
||||
// ibeacon_api.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Ambiq Micro iBeacon example
|
||||
//!
|
||||
//! @{
|
||||
//
|
||||
// ****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifndef IBEACON_API_H
|
||||
#define IBEACON_API_H
|
||||
|
||||
#include "wsf_os.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**************************************************************************************************
|
||||
Macros
|
||||
**************************************************************************************************/
|
||||
|
||||
/**************************************************************************************************
|
||||
Function Declarations
|
||||
**************************************************************************************************/
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn iBeaconStart
|
||||
*
|
||||
* \brief Start the application.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void iBeaconStart(void);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn iBeaconHandlerInit
|
||||
*
|
||||
* \brief Application handler init function called during system initialization.
|
||||
*
|
||||
* \param handlerID WSF handler ID for App.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void iBeaconHandlerInit(wsfHandlerId_t handlerId);
|
||||
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn iBeaconHandler
|
||||
*
|
||||
* \brief WSF event handler for the application.
|
||||
*
|
||||
* \param event WSF event mask.
|
||||
* \param pMsg WSF message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void iBeaconHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* IBEACON_API_H */
|
||||
@@ -0,0 +1,331 @@
|
||||
// ****************************************************************************
|
||||
//
|
||||
// ibeacon_main.c
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Ambiq Micro's demonstration of iBeacon.
|
||||
//!
|
||||
//! @{
|
||||
//
|
||||
// ****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#include <string.h>
|
||||
#include "wsf_types.h"
|
||||
#include "bstream.h"
|
||||
#include "wsf_msg.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "hci_api.h"
|
||||
#include "dm_api.h"
|
||||
#include "att_api.h"
|
||||
#include "app_api.h"
|
||||
#include "app_db.h"
|
||||
#include "app_ui.h"
|
||||
#include "app_hw.h"
|
||||
#include "svc_ch.h"
|
||||
#include "svc_core.h"
|
||||
#include "svc_dis.h"
|
||||
#include "ibeacon_api.h"
|
||||
#include "gatt_api.h"
|
||||
/**************************************************************************************************
|
||||
Macros
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! WSF message event starting value */
|
||||
#define IBEACON_MSG_START 0xA0
|
||||
|
||||
/*! WSF message event enumeration */
|
||||
enum
|
||||
{
|
||||
IBEACON_TIMER_IND = IBEACON_MSG_START, /*! iBeacon reset timer expired */
|
||||
};
|
||||
|
||||
/**************************************************************************************************
|
||||
Data Types
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! Application message type */
|
||||
typedef union
|
||||
{
|
||||
wsfMsgHdr_t hdr;
|
||||
dmEvt_t dm;
|
||||
} ibeaconMsg_t;
|
||||
|
||||
/**************************************************************************************************
|
||||
Configurable Parameters
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! configurable parameters for advertising */
|
||||
static const appAdvCfg_t ibeaconAdvCfg =
|
||||
{
|
||||
{60000, 0, 0}, /*! Advertising durations in ms */
|
||||
{ 800, 800, 0} /*! Advertising intervals in 0.625 ms units */
|
||||
};
|
||||
|
||||
/*! configurable parameters for slave */
|
||||
static const appSlaveCfg_t ibeaconSlaveCfg =
|
||||
{
|
||||
1, /*! Maximum connections */
|
||||
};
|
||||
|
||||
/*! configurable parameters for security */
|
||||
static const appSecCfg_t ibeaconSecCfg =
|
||||
{
|
||||
DM_AUTH_BOND_FLAG, /*! Authentication and bonding flags */
|
||||
0, /*! Initiator key distribution flags */
|
||||
DM_KEY_DIST_LTK, /*! Responder key distribution flags */
|
||||
FALSE, /*! TRUE if Out-of-band pairing data is present */
|
||||
FALSE /*! TRUE to initiate security upon connection */
|
||||
};
|
||||
|
||||
/**************************************************************************************************
|
||||
Advertising Data
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! advertising data, discoverable mode */
|
||||
static const uint8_t ibeaconAdvDataDisc[] =
|
||||
{
|
||||
/*! flags */
|
||||
2, /*! length */
|
||||
DM_ADV_TYPE_FLAGS, /*! AD type */
|
||||
DM_FLAG_LE_GENERAL_DISC | /*! flags */
|
||||
DM_FLAG_LE_BREDR_NOT_SUP,
|
||||
|
||||
/*! Manufacturer specific data AD type */
|
||||
0x1A, /*! length */
|
||||
DM_ADV_TYPE_MANUFACTURER, /*! AD type */
|
||||
|
||||
0x4C, /*! Company ID[0] */
|
||||
0x00, /*! Company ID[1] */
|
||||
|
||||
0x02, /*! Device type, this has to be 0x02*/
|
||||
0x15, /*! Length of vendor advertising data. */
|
||||
|
||||
/*! Proximity UUID 16 bytes */
|
||||
0xe2, 0xc5, 0x6d, 0xb5,
|
||||
0xdf, 0xfb, 0x48, 0xd2,
|
||||
0xb0, 0x60, 0xd0, 0xf5,
|
||||
0xa7, 0x10, 0x96, 0xe0,
|
||||
|
||||
/*! Major 0xnnnn */
|
||||
0x00, 0x00,
|
||||
/*! Minor 0xnnnn */
|
||||
0x00, 0x00,
|
||||
|
||||
/*! Measured Power */
|
||||
0xc5
|
||||
};
|
||||
|
||||
/**************************************************************************************************
|
||||
Global Variables
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! WSF handler ID */
|
||||
wsfHandlerId_t iBeaconHandlerId;
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn iBeaconDmCback
|
||||
*
|
||||
* \brief Application DM callback.
|
||||
*
|
||||
* \param pDmEvt DM callback event
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void iBeaconDmCback(dmEvt_t *pDmEvt)
|
||||
{
|
||||
dmEvt_t *pMsg;
|
||||
|
||||
if ((pMsg = WsfMsgAlloc(sizeof(dmEvt_t))) != NULL)
|
||||
{
|
||||
memcpy(pMsg, pDmEvt, sizeof(dmEvt_t));
|
||||
WsfMsgSend(iBeaconHandlerId, pMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn iBeacon Setup
|
||||
*
|
||||
* \brief Set up advertising and other procedures that need to be performed after
|
||||
* device reset.
|
||||
*
|
||||
* \param pMsg Pointer to message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void iBeaconSetup(ibeaconMsg_t *pMsg)
|
||||
{
|
||||
|
||||
/* set advertising and scan response data for discoverable mode */
|
||||
AppAdvSetData(APP_ADV_DATA_DISCOVERABLE, sizeof(ibeaconAdvDataDisc), (uint8_t *) ibeaconAdvDataDisc);
|
||||
|
||||
/* set advertising and scan response data for connectable mode */
|
||||
AppAdvSetData(APP_ADV_DATA_CONNECTABLE, 0, NULL);
|
||||
|
||||
// non-connectable advertising
|
||||
AppSetAdvType(DM_ADV_NONCONN_UNDIRECT);
|
||||
|
||||
/* start advertising; automatically set connectable/discoverable mode and bondable mode */
|
||||
AppAdvStart(APP_MODE_DISCOVERABLE);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn iBeaconProcMsg
|
||||
*
|
||||
* \brief Process messages from the event handler.
|
||||
*
|
||||
* \param pMsg Pointer to message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void iBeaconProcMsg(ibeaconMsg_t *pMsg)
|
||||
{
|
||||
uint8_t uiEvent = APP_UI_NONE;
|
||||
|
||||
switch(pMsg->hdr.event)
|
||||
{
|
||||
case DM_RESET_CMPL_IND:
|
||||
AttsCalculateDbHash();
|
||||
DmSecGenerateEccKeyReq();
|
||||
iBeaconSetup(pMsg);
|
||||
uiEvent = APP_UI_RESET_CMPL;
|
||||
break;
|
||||
|
||||
case DM_ADV_START_IND:
|
||||
uiEvent = APP_UI_ADV_START;
|
||||
break;
|
||||
|
||||
case DM_ADV_STOP_IND:
|
||||
uiEvent = APP_UI_ADV_STOP;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (uiEvent != APP_UI_NONE)
|
||||
{
|
||||
AppUiAction(uiEvent);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn iBeaconHandlerInit
|
||||
*
|
||||
* \brief Application handler init function called during system initialization.
|
||||
*
|
||||
* \param handlerID WSF handler ID.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void iBeaconHandlerInit(wsfHandlerId_t handlerId)
|
||||
{
|
||||
APP_TRACE_INFO0("iBeaconHandlerInit");
|
||||
|
||||
/* store handler ID */
|
||||
iBeaconHandlerId = handlerId;
|
||||
|
||||
/* Set configuration pointers */
|
||||
pAppAdvCfg = (appAdvCfg_t *) &ibeaconAdvCfg;
|
||||
pAppSlaveCfg = (appSlaveCfg_t *) &ibeaconSlaveCfg;
|
||||
pAppSecCfg = (appSecCfg_t *) &ibeaconSecCfg;
|
||||
|
||||
/* Initialize application framework */
|
||||
AppSlaveInit();
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn iBeaconHandler
|
||||
*
|
||||
* \brief WSF event handler for application.
|
||||
*
|
||||
* \param event WSF event mask.
|
||||
* \param pMsg WSF message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void iBeaconHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg)
|
||||
{
|
||||
if (pMsg != NULL)
|
||||
{
|
||||
APP_TRACE_INFO1("iBeacon got evt %d", pMsg->event);
|
||||
|
||||
if (pMsg->event >= DM_CBACK_START && pMsg->event <= DM_CBACK_END)
|
||||
{
|
||||
/* process advertising and connection-related messages */
|
||||
AppSlaveProcDmMsg((dmEvt_t *) pMsg);
|
||||
|
||||
/* process security-related messages */
|
||||
AppSlaveSecProcDmMsg((dmEvt_t *) pMsg);
|
||||
}
|
||||
|
||||
/* perform profile and user interface-related operations */
|
||||
iBeaconProcMsg((ibeaconMsg_t *) pMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn iBeaconStart
|
||||
*
|
||||
* \brief Start the application.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void iBeaconStart(void)
|
||||
{
|
||||
/* Register for stack callbacks */
|
||||
DmRegister(iBeaconDmCback);
|
||||
DmConnRegister(DM_CLIENT_ID_APP, iBeaconDmCback);
|
||||
|
||||
/* Reset the device */
|
||||
DmDevReset();
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
// ****************************************************************************
|
||||
//
|
||||
// prodtest_datc_api.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Proprietary data transfer client sample application.
|
||||
//!
|
||||
//! @{
|
||||
//
|
||||
// ****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \file prodtest_datc_api.h
|
||||
*
|
||||
* \brief Proprietary data transfer client sample application.
|
||||
*
|
||||
* $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $
|
||||
* $Revision: 10805 $
|
||||
*
|
||||
* Copyright (c) 2012-2017 ARM Ltd., all rights reserved.
|
||||
* ARM Ltd. confidential and proprietary.
|
||||
*
|
||||
* IMPORTANT. Your use of this file is governed by a Software License Agreement
|
||||
* ("Agreement") that must be accepted in order to download or otherwise receive a
|
||||
* copy of this file. You may not use or copy this file for any purpose other than
|
||||
* as described in the Agreement. If you do not agree to all of the terms of the
|
||||
* Agreement do not use this file and delete all copies in your possession or control;
|
||||
* if you do not have a copy of the Agreement, you must contact ARM Ltd. prior
|
||||
* to any use, copying or further distribution of this software.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
#ifndef DATC_API_H
|
||||
#define DATC_API_H
|
||||
|
||||
#include "wsf_os.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**************************************************************************************************
|
||||
Function Declarations
|
||||
**************************************************************************************************/
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn DatcStart
|
||||
*
|
||||
* \brief Start the application.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void DatcStart(void);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn DatcHandlerInit
|
||||
*
|
||||
* \brief Application handler init function called during system initialization.
|
||||
*
|
||||
* \param handlerID WSF handler ID for App.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void DatcHandlerInit(wsfHandlerId_t handlerId);
|
||||
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn DatcHandler
|
||||
*
|
||||
* \brief WSF event handler for the application.
|
||||
*
|
||||
* \param event WSF event mask.
|
||||
* \param pMsg WSF message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void DatcHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* DATC_API_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,130 @@
|
||||
// ****************************************************************************
|
||||
//
|
||||
// prodtest_dats_api.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Proprietary data transfer server sample application.
|
||||
//!
|
||||
//! @{
|
||||
//
|
||||
// ****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* file prodtest_dats_api.h
|
||||
*
|
||||
* brief Proprietary data transfer server sample application.
|
||||
*
|
||||
* $Date: 2016-12-28 16:12:14 -0600 (Wed, 28 Dec 2016) $
|
||||
* $Revision: 10805 $
|
||||
*
|
||||
* Copyright (c) 2012-2017 ARM Ltd., all rights reserved.
|
||||
* ARM Ltd. confidential and proprietary.
|
||||
*
|
||||
* IMPORTANT. Your use of this file is governed by a Software License Agreement
|
||||
* ("Agreement") that must be accepted in order to download or otherwise receive a
|
||||
* copy of this file. You may not use or copy this file for any purpose other than
|
||||
* as described in the Agreement. If you do not agree to all of the terms of the
|
||||
* Agreement do not use this file and delete all copies in your possession or control;
|
||||
* if you do not have a copy of the Agreement, you must contact ARM Ltd. prior
|
||||
* to any use, copying or further distribution of this software.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
#ifndef DATS_API_H
|
||||
#define DATS_API_H
|
||||
|
||||
#include "wsf_os.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef WDXS_INCLUDED
|
||||
#define WDXS_INCLUDED FALSE
|
||||
#endif
|
||||
|
||||
/**************************************************************************************************
|
||||
Function Declarations
|
||||
**************************************************************************************************/
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn DatsStart
|
||||
*
|
||||
* \brief Start the application.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void DatsStart(void);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn DatsHandlerInit
|
||||
*
|
||||
* \brief Application handler init function called during system initialization.
|
||||
*
|
||||
* \param handlerID WSF handler ID for App.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void DatsHandlerInit(wsfHandlerId_t handlerId);
|
||||
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn DatsHandler
|
||||
*
|
||||
* \brief WSF event handler for the application.
|
||||
*
|
||||
* \param event WSF event mask.
|
||||
* \param pMsg WSF message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void DatsHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* DATS_API_H */
|
||||
@@ -0,0 +1,802 @@
|
||||
// ****************************************************************************
|
||||
//
|
||||
// prodtest_dats_main.c
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Data transmitter sample application.
|
||||
//!
|
||||
//! @{
|
||||
//
|
||||
// ****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* file dats_main.c
|
||||
*
|
||||
* brief Data transmitter sample application.
|
||||
*
|
||||
* $Date: 2017-03-09 12:18:38 -0600 (Thu, 09 Mar 2017) $
|
||||
* $Revision: 11460 $
|
||||
*
|
||||
* Copyright (c) 2012-2017 ARM Ltd., all rights reserved.
|
||||
* ARM Ltd. confidential and proprietary.
|
||||
*
|
||||
* IMPORTANT. Your use of this file is governed by a Software License Agreement
|
||||
* ("Agreement") that must be accepted in order to download or otherwise receive a
|
||||
* copy of this file. You may not use or copy this file for any purpose other than
|
||||
* as described in the Agreement. If you do not agree to all of the terms of the
|
||||
* Agreement do not use this file and delete all copies in your possession or control;
|
||||
* if you do not have a copy of the Agreement, you must contact ARM Ltd. prior
|
||||
* to any use, copying or further distribution of this software.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "wsf_types.h"
|
||||
#include "bstream.h"
|
||||
#include "wsf_msg.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "wsf_buf.h"
|
||||
#include "hci_api.h"
|
||||
#include "sec_api.h"
|
||||
#include "dm_api.h"
|
||||
#include "smp_api.h"
|
||||
#include "att_api.h"
|
||||
#include "app_api.h"
|
||||
#include "app_db.h"
|
||||
#include "app_ui.h"
|
||||
#include "svc_ch.h"
|
||||
#include "svc_core.h"
|
||||
#include "svc_wp.h"
|
||||
#include "calc128.h"
|
||||
#include "prodtest_dats_api.h"
|
||||
#if WDXS_INCLUDED == TRUE
|
||||
#include "wsf_efs.h"
|
||||
#include "svc_wdxs.h"
|
||||
#include "wdxs_api.h"
|
||||
#include "wdxs_main.h"
|
||||
#include "wdxs_stream.h"
|
||||
#endif
|
||||
|
||||
#include "hci_apollo_config.h"
|
||||
#include "hci_drv_em9304.h"
|
||||
#include "gatt_api.h"
|
||||
|
||||
/**************************************************************************************************
|
||||
Macros
|
||||
**************************************************************************************************/
|
||||
#if CS50_INCLUDED == TRUE
|
||||
|
||||
/* PHY Test Modes */
|
||||
#define DATS_PHY_1M 1
|
||||
#define DATS_PHY_2M 2
|
||||
#define DATS_PHY_CODED 3
|
||||
|
||||
#endif /* CS50_INCLUDED */
|
||||
|
||||
/*! Enumeration of client characteristic configuration descriptors */
|
||||
enum
|
||||
{
|
||||
#if WDXS_INCLUDED == TRUE
|
||||
WDXS_DC_CH_CCC_IDX, /*! WDXS DC service, service changed characteristic */
|
||||
WDXS_FTC_CH_CCC_IDX, /*! WDXS FTC service, service changed characteristic */
|
||||
WDXS_FTD_CH_CCC_IDX, /*! WDXS FTD service, service changed characteristic */
|
||||
WDXS_AU_CH_CCC_IDX, /*! WDXS AU service, service changed characteristic */
|
||||
#endif /* WDXS_INCLUDED */
|
||||
DATS_GATT_SC_CCC_IDX, /*! GATT service, service changed characteristic */
|
||||
DATS_WP_DAT_CCC_IDX, /*! ARM Ltd. proprietary service, data transfer characteristic */
|
||||
DATS_NUM_CCC_IDX
|
||||
};
|
||||
|
||||
/**************************************************************************************************
|
||||
Configurable Parameters
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! configurable parameters for advertising */
|
||||
static const appAdvCfg_t datsAdvCfg =
|
||||
{
|
||||
{30000, 0, 0}, /*! Advertising durations in ms */
|
||||
{ 32, 32, 0} /*! Advertising intervals in 0.625 ms units */
|
||||
};
|
||||
|
||||
/*! configurable parameters for slave */
|
||||
static const appSlaveCfg_t datsSlaveCfg =
|
||||
{
|
||||
1, /*! Maximum connections */
|
||||
};
|
||||
|
||||
/*! configurable parameters for security */
|
||||
static const appSecCfg_t datsSecCfg =
|
||||
{
|
||||
0, /*! Authentication and bonding flags */
|
||||
DM_KEY_DIST_IRK, /*! Initiator key distribution flags */
|
||||
DM_KEY_DIST_LTK | DM_KEY_DIST_IRK, /*! Responder key distribution flags */
|
||||
FALSE, /*! TRUE if Out-of-band pairing data is present */
|
||||
FALSE /*! TRUE to initiate security upon connection */
|
||||
};
|
||||
|
||||
/*! SMP security parameter configuration */
|
||||
static const smpCfg_t datsSmpCfg =
|
||||
{
|
||||
3000, /*! 'Repeated attempts' timeout in msec */
|
||||
SMP_IO_NO_IN_NO_OUT, /*! I/O Capability */
|
||||
7, /*! Minimum encryption key length */
|
||||
16, /*! Maximum encryption key length */
|
||||
1, /*! Attempts to trigger 'repeated attempts' timeout */
|
||||
0, /*! Device authentication requirements */
|
||||
64000, /*! Maximum repeated attempts timeout in msec */
|
||||
64000, /*! Time msec before attemptExp decreases */
|
||||
2 /*! Repeated attempts multiplier exponent */
|
||||
};
|
||||
|
||||
/*! configurable parameters for connection parameter update */
|
||||
static const appUpdateCfg_t datsUpdateCfg =
|
||||
{
|
||||
0, /*! Connection idle period in ms before attempting
|
||||
connection parameter update; set to zero to disable */
|
||||
640, /*! Minimum connection interval in 1.25ms units */
|
||||
800, /*! Maximum connection interval in 1.25ms units */
|
||||
3, /*! Connection latency */
|
||||
600, /*! Supervision timeout in 10ms units */
|
||||
5 /*! Number of update attempts before giving up */
|
||||
};
|
||||
|
||||
/*! ATT configurable parameters (increase MTU) */
|
||||
static const attCfg_t datsAttCfg =
|
||||
{
|
||||
15, /* ATT server service discovery connection idle timeout in seconds */
|
||||
241, /* desired ATT MTU */
|
||||
ATT_MAX_TRANS_TIMEOUT, /* transcation timeout in seconds */
|
||||
4 /* number of queued prepare writes supported by server */
|
||||
};
|
||||
|
||||
/*! local IRK */
|
||||
static uint8_t localIrk[] =
|
||||
{
|
||||
0x95, 0xC8, 0xEE, 0x6F, 0xC5, 0x0D, 0xEF, 0x93, 0x35, 0x4E, 0x7C, 0x57, 0x08, 0xE2, 0xA3, 0x85
|
||||
};
|
||||
|
||||
/**************************************************************************************************
|
||||
Advertising Data
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! advertising data, discoverable mode */
|
||||
static const uint8_t datsAdvDataDisc[] =
|
||||
{
|
||||
/*! flags */
|
||||
2, /*! length */
|
||||
DM_ADV_TYPE_FLAGS, /*! AD type */
|
||||
DM_FLAG_LE_GENERAL_DISC | /*! flags */
|
||||
DM_FLAG_LE_BREDR_NOT_SUP,
|
||||
|
||||
/*! manufacturer specific data */
|
||||
3, /*! length */
|
||||
DM_ADV_TYPE_MANUFACTURER, /*! AD type */
|
||||
UINT16_TO_BYTES(HCI_ID_ARM) /*! company ID */
|
||||
};
|
||||
|
||||
/*! scan data, discoverable mode */
|
||||
static const uint8_t datsScanDataDisc[] =
|
||||
{
|
||||
/*! device name */
|
||||
8, /*! length */
|
||||
DM_ADV_TYPE_LOCAL_NAME, /*! AD type */
|
||||
'D',
|
||||
'a',
|
||||
't',
|
||||
'a',
|
||||
' ',
|
||||
'T',
|
||||
'X'
|
||||
};
|
||||
|
||||
/**************************************************************************************************
|
||||
Client Characteristic Configuration Descriptors
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! client characteristic configuration descriptors settings, indexed by above enumeration */
|
||||
static const attsCccSet_t datsCccSet[DATS_NUM_CCC_IDX] =
|
||||
{
|
||||
/* cccd handle value range security level */
|
||||
#if WDXS_INCLUDED == TRUE
|
||||
{WDXS_DC_CH_CCC_HDL, ATT_CLIENT_CFG_NOTIFY, DM_SEC_LEVEL_NONE}, /* WDXS_DC_CH_CCC_IDX */
|
||||
{WDXS_FTC_CH_CCC_HDL, ATT_CLIENT_CFG_NOTIFY, DM_SEC_LEVEL_NONE}, /* WDXS_FTC_CH_CCC_IDX */
|
||||
{WDXS_FTD_CH_CCC_HDL, ATT_CLIENT_CFG_NOTIFY, DM_SEC_LEVEL_NONE}, /* WDXS_FTD_CH_CCC_IDX */
|
||||
{WDXS_AU_CH_CCC_HDL, ATT_CLIENT_CFG_NOTIFY, DM_SEC_LEVEL_NONE}, /* WDXS_AU_CH_CCC_IDX */
|
||||
#endif /* WDXS_INCLUDED */
|
||||
{GATT_SC_CH_CCC_HDL, ATT_CLIENT_CFG_INDICATE, DM_SEC_LEVEL_NONE}, /* DATS_GATT_SC_CCC_IDX */
|
||||
{WP_DAT_CH_CCC_HDL, ATT_CLIENT_CFG_NOTIFY, DM_SEC_LEVEL_NONE} /* DATS_WP_DAT_CCC_IDX */
|
||||
};
|
||||
|
||||
/**************************************************************************************************
|
||||
Local Variables
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! application control block */
|
||||
static struct
|
||||
{
|
||||
wsfHandlerId_t handlerId; /* WSF handler ID */
|
||||
#if CS50_INCLUDED == TRUE
|
||||
uint8_t phyMode; /*! PHY Test Mode */
|
||||
#endif /* CS50_INCLUDED */
|
||||
} datsCb;
|
||||
|
||||
/* LESC OOB configuration */
|
||||
static dmSecLescOobCfg_t *datsOobCfg;
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn datsSendData
|
||||
*
|
||||
* \brief Send notification containing data.
|
||||
*
|
||||
* \param connId DM connection ID.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void datsSendData(dmConnId_t connId)
|
||||
{
|
||||
uint8_t str[] = "hello.....from dats";
|
||||
|
||||
if (AttsCccEnabled(connId, DATS_WP_DAT_CCC_IDX))
|
||||
{
|
||||
/* send notification */
|
||||
AttsHandleValueNtf(connId, WP_DAT_HDL, sizeof(str), str);
|
||||
AttsHandleValueNtf(connId, WP_DAT_HDL, sizeof(str), str);
|
||||
AttsHandleValueNtf(connId, WP_DAT_HDL, sizeof(str), str);
|
||||
AttsHandleValueNtf(connId, WP_DAT_HDL, sizeof(str), str);
|
||||
AttsHandleValueNtf(connId, WP_DAT_HDL, sizeof(str), str);
|
||||
}
|
||||
}
|
||||
|
||||
static void datsSetup(dmEvt_t *pMsg);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn datsDmCback
|
||||
*
|
||||
* \brief Application DM callback.
|
||||
*
|
||||
* \param pDmEvt DM callback event
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void datsDmCback(dmEvt_t *pDmEvt)
|
||||
{
|
||||
dmEvt_t *pMsg;
|
||||
uint16_t len;
|
||||
|
||||
if (pDmEvt->hdr.event == DM_SEC_ECC_KEY_IND)
|
||||
{
|
||||
DmSecSetEccKey(&pDmEvt->eccMsg.data.key);
|
||||
|
||||
/* If the local device sends OOB data. */
|
||||
if (datsSecCfg.oob)
|
||||
{
|
||||
uint8_t oobLocalRandom[SMP_RAND_LEN];
|
||||
SecRand(oobLocalRandom, SMP_RAND_LEN);
|
||||
DmSecCalcOobReq(oobLocalRandom, pDmEvt->eccMsg.data.key.pubKey_x);
|
||||
}
|
||||
}
|
||||
else if (pDmEvt->hdr.event == DM_SEC_CALC_OOB_IND)
|
||||
{
|
||||
if (datsOobCfg == NULL)
|
||||
{
|
||||
datsOobCfg = WsfBufAlloc(sizeof(dmSecLescOobCfg_t));
|
||||
}
|
||||
|
||||
if (datsOobCfg)
|
||||
{
|
||||
Calc128Cpy(datsOobCfg->localConfirm, pDmEvt->oobCalcInd.confirm);
|
||||
Calc128Cpy(datsOobCfg->localRandom, pDmEvt->oobCalcInd.random);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
len = DmSizeOfEvt(pDmEvt);
|
||||
|
||||
if ((pMsg = WsfMsgAlloc(len)) != NULL)
|
||||
{
|
||||
memcpy(pMsg, pDmEvt, len);
|
||||
WsfMsgSend(datsCb.handlerId, pMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn datsAttCback
|
||||
*
|
||||
* \brief Application ATT callback.
|
||||
*
|
||||
* \param pEvt ATT callback event
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void datsAttCback(attEvt_t *pEvt)
|
||||
{
|
||||
#if WDXS_INCLUDED == TRUE
|
||||
WdxsAttCback(pEvt);
|
||||
#endif /* WDXS_INCLUDED */
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn datsCccCback
|
||||
*
|
||||
* \brief Application ATTS client characteristic configuration callback.
|
||||
*
|
||||
* \param pDmEvt DM callback event
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void datsCccCback(attsCccEvt_t *pEvt)
|
||||
{
|
||||
appDbHdl_t dbHdl;
|
||||
|
||||
/* If CCC not set from initialization and there's a device record and currently bonded */
|
||||
if ((pEvt->handle != ATT_HANDLE_NONE) &&
|
||||
((dbHdl = AppDbGetHdl((dmConnId_t) pEvt->hdr.param)) != APP_DB_HDL_NONE) &&
|
||||
AppCheckBonded((dmConnId_t)pEvt->hdr.param))
|
||||
{
|
||||
/* Store value in device database. */
|
||||
AppDbSetCccTblValue(dbHdl, pEvt->idx, pEvt->value);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn datsWpWriteCback
|
||||
*
|
||||
* \brief ATTS write callback for proprietary data service.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t datsWpWriteCback(dmConnId_t connId, uint16_t handle, uint8_t operation,
|
||||
uint16_t offset, uint16_t len, uint8_t *pValue, attsAttr_t *pAttr)
|
||||
{
|
||||
/* print received data */
|
||||
APP_TRACE_INFO0((const char*) pValue);
|
||||
|
||||
/* send back some data */
|
||||
datsSendData(connId);
|
||||
|
||||
return ATT_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn datsSetup
|
||||
*
|
||||
* \brief Set up advertising and other procedures that need to be performed after
|
||||
* device reset.
|
||||
*
|
||||
* \param pMsg Pointer to message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void datsSetup(dmEvt_t *pMsg)
|
||||
{
|
||||
/* set advertising and scan response data for discoverable mode */
|
||||
AppAdvSetData(APP_ADV_DATA_DISCOVERABLE, sizeof(datsAdvDataDisc), (uint8_t *) datsAdvDataDisc);
|
||||
AppAdvSetData(APP_SCAN_DATA_DISCOVERABLE, sizeof(datsScanDataDisc), (uint8_t *) datsScanDataDisc);
|
||||
|
||||
/* set advertising and scan response data for connectable mode */
|
||||
AppAdvSetData(APP_ADV_DATA_CONNECTABLE, sizeof(datsAdvDataDisc), (uint8_t *) datsAdvDataDisc);
|
||||
AppAdvSetData(APP_SCAN_DATA_CONNECTABLE, sizeof(datsScanDataDisc), (uint8_t *) datsScanDataDisc);
|
||||
|
||||
/* start advertising; automatically set connectable/discoverable mode and bondable mode */
|
||||
AppAdvStart(APP_MODE_AUTO_INIT);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn datsProcMsg
|
||||
*
|
||||
* \brief Process messages from the event handler.
|
||||
*
|
||||
* \param pMsg Pointer to message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void datsProcMsg(dmEvt_t *pMsg)
|
||||
{
|
||||
uint8_t uiEvent = APP_UI_NONE;
|
||||
|
||||
switch(pMsg->hdr.event)
|
||||
{
|
||||
case ATT_MTU_UPDATE_IND:
|
||||
APP_TRACE_INFO1("Negotiated MTU %d", ((attEvt_t *)pMsg)->mtu);
|
||||
break;
|
||||
|
||||
case DM_RESET_CMPL_IND:
|
||||
AttsCalculateDbHash();
|
||||
DmSecGenerateEccKeyReq();
|
||||
datsSetup(NULL);
|
||||
uiEvent = APP_UI_RESET_CMPL;
|
||||
HciVsEM_SetRfPowerLevelEx(TX_POWER_LEVEL_PLUS_0P4_dBm);
|
||||
break;
|
||||
|
||||
|
||||
case DM_ADV_SET_START_IND:
|
||||
uiEvent = APP_UI_ADV_SET_START_IND;
|
||||
break;
|
||||
|
||||
case DM_ADV_SET_STOP_IND:
|
||||
uiEvent = APP_UI_ADV_SET_STOP_IND;
|
||||
break;
|
||||
|
||||
case DM_ADV_START_IND:
|
||||
uiEvent = APP_UI_ADV_START;
|
||||
break;
|
||||
|
||||
case DM_ADV_STOP_IND:
|
||||
uiEvent = APP_UI_ADV_STOP;
|
||||
break;
|
||||
|
||||
case DM_CONN_OPEN_IND:
|
||||
uiEvent = APP_UI_CONN_OPEN;
|
||||
#if CS50_INCLUDED == TRUE
|
||||
datsCb.phyMode = DATS_PHY_1M;
|
||||
#endif /* CS50_INCLUDED */
|
||||
break;
|
||||
|
||||
case DM_CONN_CLOSE_IND:
|
||||
uiEvent = APP_UI_CONN_CLOSE;
|
||||
break;
|
||||
|
||||
case DM_SEC_PAIR_CMPL_IND:
|
||||
DmSecGenerateEccKeyReq();
|
||||
uiEvent = APP_UI_SEC_PAIR_CMPL;
|
||||
break;
|
||||
|
||||
case DM_SEC_PAIR_FAIL_IND:
|
||||
DmSecGenerateEccKeyReq();
|
||||
uiEvent = APP_UI_SEC_PAIR_FAIL;
|
||||
break;
|
||||
|
||||
case DM_SEC_ENCRYPT_IND:
|
||||
uiEvent = APP_UI_SEC_ENCRYPT;
|
||||
break;
|
||||
|
||||
case DM_SEC_ENCRYPT_FAIL_IND:
|
||||
uiEvent = APP_UI_SEC_ENCRYPT_FAIL;
|
||||
break;
|
||||
|
||||
case DM_SEC_AUTH_REQ_IND:
|
||||
|
||||
if (pMsg->authReq.oob)
|
||||
{
|
||||
dmConnId_t connId = (dmConnId_t) pMsg->hdr.param;
|
||||
|
||||
/* TODO: Perform OOB Exchange with the peer. */
|
||||
|
||||
|
||||
/* TODO: Fill datsOobCfg peerConfirm and peerRandom with value passed out of band */
|
||||
|
||||
if (datsOobCfg != NULL)
|
||||
{
|
||||
DmSecSetOob(connId, datsOobCfg);
|
||||
}
|
||||
|
||||
DmSecAuthRsp(connId, 0, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
AppHandlePasskey(&pMsg->authReq);
|
||||
}
|
||||
break;
|
||||
case DM_SEC_ECC_KEY_IND:
|
||||
DmSecSetEccKey(&pMsg->eccMsg.data.key);
|
||||
break;
|
||||
case DM_SEC_COMPARE_IND:
|
||||
AppHandleNumericComparison(&pMsg->cnfInd);
|
||||
break;
|
||||
|
||||
case DM_PRIV_CLEAR_RES_LIST_IND:
|
||||
APP_TRACE_INFO1("Clear resolving list status 0x%02x", pMsg->hdr.status);
|
||||
break;
|
||||
|
||||
case DM_HW_ERROR_IND:
|
||||
uiEvent = APP_UI_HW_ERROR;
|
||||
break;
|
||||
case DM_VENDOR_SPEC_CMD_CMPL_IND:
|
||||
{
|
||||
#if defined(AM_PART_APOLLO) || defined(AM_PART_APOLLO2)
|
||||
|
||||
uint8_t *param_ptr = &pMsg->vendorSpecCmdCmpl.param[0];
|
||||
|
||||
switch (pMsg->vendorSpecCmdCmpl.opcode)
|
||||
{
|
||||
case 0xFC20: //read at address
|
||||
{
|
||||
uint32_t read_value;
|
||||
|
||||
BSTREAM_TO_UINT32(read_value, param_ptr);
|
||||
|
||||
APP_TRACE_INFO3("VSC 0x%0x complete status %x param %x",
|
||||
pMsg->vendorSpecCmdCmpl.opcode,
|
||||
pMsg->hdr.status,
|
||||
read_value);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
APP_TRACE_INFO2("VSC 0x%0x complete status %x",
|
||||
pMsg->vendorSpecCmdCmpl.opcode,
|
||||
pMsg->hdr.status);
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (uiEvent != APP_UI_NONE)
|
||||
{
|
||||
AppUiAction(uiEvent);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn DatsHandlerInit
|
||||
*
|
||||
* \brief Application handler init function called during system initialization.
|
||||
*
|
||||
* \param handlerID WSF handler ID.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void DatsHandlerInit(wsfHandlerId_t handlerId)
|
||||
{
|
||||
APP_TRACE_INFO0("DatsHandlerInit");
|
||||
|
||||
/* store handler ID */
|
||||
datsCb.handlerId = handlerId;
|
||||
|
||||
/* Set configuration pointers */
|
||||
pAppSlaveCfg = (appSlaveCfg_t *) &datsSlaveCfg;
|
||||
pAppAdvCfg = (appAdvCfg_t *) &datsAdvCfg;
|
||||
pAppSecCfg = (appSecCfg_t *) &datsSecCfg;
|
||||
pAppUpdateCfg = (appUpdateCfg_t *) &datsUpdateCfg;
|
||||
pSmpCfg = (smpCfg_t *) &datsSmpCfg;
|
||||
|
||||
/* Initialize application framework */
|
||||
AppSlaveInit();
|
||||
|
||||
/* Set IRK for the local device */
|
||||
DmSecSetLocalIrk(localIrk);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn datsBtnCback
|
||||
*
|
||||
* \brief Button press callback.
|
||||
*
|
||||
* \param btn Button press.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void datsBtnCback(uint8_t btn)
|
||||
{
|
||||
#if WDXS_INCLUDED == TRUE
|
||||
static uint8_t waveform = WDXS_STREAM_WAVEFORM_SINE;
|
||||
#endif /* WDXS_INCLUDED */
|
||||
|
||||
#if CS50_INCLUDED == TRUE
|
||||
dmConnId_t connId;
|
||||
if ((connId = AppConnIsOpen()) != DM_CONN_ID_NONE)
|
||||
#else
|
||||
if (AppConnIsOpen() != DM_CONN_ID_NONE)
|
||||
#endif /* CS50_INCLUDED */
|
||||
{
|
||||
switch (btn)
|
||||
{
|
||||
#if CS50_INCLUDED == TRUE
|
||||
case APP_UI_BTN_2_SHORT:
|
||||
|
||||
/* Toggle PHY Test Mode */
|
||||
if (datsCb.phyMode == DATS_PHY_1M)
|
||||
{
|
||||
APP_TRACE_INFO0("2 MBit TX and RX PHY Requested");
|
||||
DmSetPhy(connId, HCI_ALL_PHY_ALL_PREFERENCES, HCI_PHY_LE_2M_BIT, HCI_PHY_LE_2M_BIT, HCI_PHY_OPTIONS_NONE);
|
||||
}
|
||||
else if (datsCb.phyMode == DATS_PHY_2M)
|
||||
{
|
||||
APP_TRACE_INFO0("LE Coded TX and RX PHY Requested");
|
||||
DmSetPhy(connId, HCI_ALL_PHY_ALL_PREFERENCES, HCI_PHY_LE_CODED_BIT, HCI_PHY_LE_CODED_BIT, HCI_PHY_OPTIONS_NONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
APP_TRACE_INFO0("1 MBit TX and RX PHY Requested");
|
||||
DmSetPhy(connId, HCI_ALL_PHY_ALL_PREFERENCES, HCI_PHY_LE_1M_BIT, HCI_PHY_LE_1M_BIT, HCI_PHY_OPTIONS_NONE);
|
||||
}
|
||||
break;
|
||||
|
||||
#endif /* CS50_INCLUDED */
|
||||
|
||||
#if WDXS_INCLUDED == TRUE
|
||||
case APP_UI_BTN_1_SHORT:
|
||||
/* Change stream waveform */
|
||||
waveform++;
|
||||
|
||||
if ( waveform > WDXS_STREAM_WAVEFORM_SAWTOOTH )
|
||||
{
|
||||
waveform = WDXS_STREAM_WAVEFORM_SINE;
|
||||
}
|
||||
|
||||
wdxsSetStreamWaveform(waveform);
|
||||
break;
|
||||
#endif /* WDXS_INCLUDED */
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn datsWsfBufDiagnostics
|
||||
*
|
||||
* \brief Callback for WSF buffer diagnostic messages.
|
||||
*
|
||||
* \param pInfo Diagnostics message
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void datsWsfBufDiagnostics(WsfBufDiag_t *pInfo)
|
||||
{
|
||||
if (pInfo->type == WSF_BUF_ALLOC_FAILED)
|
||||
{
|
||||
APP_TRACE_INFO2("Dats got WSF Buffer Allocation Failure - Task: %d Len: %d",
|
||||
pInfo->param.alloc.taskId, pInfo->param.alloc.len);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn DatsHandler
|
||||
*
|
||||
* \brief WSF event handler for application.
|
||||
*
|
||||
* \param event WSF event mask.
|
||||
* \param pMsg WSF message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void DatsHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg)
|
||||
{
|
||||
if (pMsg != NULL)
|
||||
{
|
||||
APP_TRACE_INFO1("Dats got evt %d", pMsg->event);
|
||||
|
||||
/* process ATT messages */
|
||||
if (pMsg->event >= ATT_CBACK_START && pMsg->event <= ATT_CBACK_END)
|
||||
{
|
||||
/* process server-related ATT messages */
|
||||
AppServerProcAttMsg(pMsg);
|
||||
}
|
||||
/* process DM messages */
|
||||
else if (pMsg->event >= DM_CBACK_START && pMsg->event <= DM_CBACK_END)
|
||||
{
|
||||
/* process advertising and connection-related messages */
|
||||
AppSlaveProcDmMsg((dmEvt_t *) pMsg);
|
||||
|
||||
/* process security-related messages */
|
||||
AppSlaveSecProcDmMsg((dmEvt_t *) pMsg);
|
||||
|
||||
#if WDXS_INCLUDED == TRUE
|
||||
/* process WDXS-related messages */
|
||||
WdxsProcDmMsg((dmEvt_t*) pMsg);
|
||||
#endif /* WDXS_INCLUDED */
|
||||
}
|
||||
|
||||
/* perform profile and user interface-related operations */
|
||||
datsProcMsg((dmEvt_t *) pMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn DatsStart
|
||||
*
|
||||
* \brief Start the application.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void DatsStart(void)
|
||||
{
|
||||
/* Register for stack callbacks */
|
||||
DmRegister(datsDmCback);
|
||||
DmConnRegister(DM_CLIENT_ID_APP, datsDmCback);
|
||||
AttRegister(datsAttCback);
|
||||
AttConnRegister(AppServerConnCback);
|
||||
AttsCccRegister(DATS_NUM_CCC_IDX, (attsCccSet_t *) datsCccSet, datsCccCback);
|
||||
|
||||
/* Initialize attribute server database */
|
||||
SvcCoreGattCbackRegister(GattReadCback, GattWriteCback);
|
||||
SvcCoreAddGroup();
|
||||
SvcWpCbackRegister(NULL, datsWpWriteCback);
|
||||
SvcWpAddGroup();
|
||||
|
||||
/* Register for app framework button callbacks */
|
||||
AppUiBtnRegister(datsBtnCback);
|
||||
|
||||
#if WDXS_INCLUDED == TRUE
|
||||
|
||||
/* Initialize the OTA File Media */
|
||||
WdxsOtaMediaInit();
|
||||
|
||||
/* Initialize the WDXS Stream */
|
||||
wdxsStreamInit();
|
||||
|
||||
/* Set the WDXS CCC Identifiers */
|
||||
WdxsSetCccIdx(WDXS_DC_CH_CCC_IDX, WDXS_AU_CH_CCC_IDX, WDXS_FTC_CH_CCC_IDX, WDXS_FTD_CH_CCC_IDX);
|
||||
|
||||
#endif /* WDXS_INCLUDED */
|
||||
|
||||
WsfBufDiagRegister(datsWsfBufDiagnostics);
|
||||
|
||||
/* Set Service Changed CCCD index. */
|
||||
GattSetSvcChangedIdx(DATS_GATT_SC_CCC_IDX);
|
||||
|
||||
/* Reset the device */
|
||||
DmDevReset();
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,126 @@
|
||||
// ****************************************************************************
|
||||
//
|
||||
// vole_api.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Ambiq Micro's demonstration of AMDTP service.
|
||||
//!
|
||||
//! @{
|
||||
//
|
||||
// ****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2018, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 1.2.12 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifndef VOLE_API_H
|
||||
#define VOLE_API_H
|
||||
|
||||
#include "wsf_os.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**************************************************************************************************
|
||||
Macros
|
||||
**************************************************************************************************/
|
||||
|
||||
#ifndef VOLE_CONN_MAX
|
||||
#define VOLE_CONN_MAX 1
|
||||
#endif
|
||||
|
||||
/*! WSF message event starting value */
|
||||
#define VOLE_MSG_START 0xA0
|
||||
|
||||
/*! WSF message event enumeration */
|
||||
enum
|
||||
{
|
||||
AMOTA_TIMER_IND = VOLE_MSG_START,
|
||||
};
|
||||
|
||||
extern dmConnId_t g_AmaConnId;
|
||||
|
||||
|
||||
/**************************************************************************************************
|
||||
Function Declarations
|
||||
**************************************************************************************************/
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AmvosStart
|
||||
*
|
||||
* \brief Start the application.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void VoleStart(void);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn VoleHandlerInit
|
||||
*
|
||||
* \brief Application handler init function called during system initialization.
|
||||
*
|
||||
* \param handlerID WSF handler ID for App.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void VoleHandlerInit(wsfHandlerId_t handlerId);
|
||||
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn VoleHandler
|
||||
*
|
||||
* \brief WSF event handler for the application.
|
||||
*
|
||||
* \param event WSF event mask.
|
||||
* \param pMsg WSF message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void VoleHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg);
|
||||
void VoleBleSend(uint8_t * buf, uint32_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* VOLE_API_H */
|
||||
@@ -0,0 +1,867 @@
|
||||
// ****************************************************************************
|
||||
//
|
||||
// vole_main.c
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Ambiq Micro's demonstration of Voice Over LE service.
|
||||
//!
|
||||
//! @{
|
||||
//
|
||||
// ****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#include "usr_include.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "wsf_types.h"
|
||||
#include "bstream.h"
|
||||
#include "wsf_msg.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "hci_api.h"
|
||||
#include "dm_api.h"
|
||||
#include "att_api.h"
|
||||
#include "smp_api.h"
|
||||
#include "app_api.h"
|
||||
#include "app_db.h"
|
||||
#include "app_ui.h"
|
||||
#include "app_hw.h"
|
||||
#include "svc_ch.h"
|
||||
#include "svc_core.h"
|
||||
#include "svc_dis.h"
|
||||
|
||||
#include "vole_api.h"
|
||||
#include "svc_amvole.h"
|
||||
#include "vole_common.h"
|
||||
#include "vole_board_config.h"
|
||||
|
||||
#include "am_util.h"
|
||||
#include "crc32.h"
|
||||
#include "am_app_KWD_AMA.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "voles_api.h"
|
||||
#include "gatt_api.h"
|
||||
|
||||
|
||||
/**************************************************************************************************
|
||||
Macros
|
||||
**************************************************************************************************/
|
||||
|
||||
/**************************************************************************************************
|
||||
Data Types
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! Application message type */
|
||||
typedef union
|
||||
{
|
||||
wsfMsgHdr_t hdr;
|
||||
dmEvt_t dm;
|
||||
attsCccEvt_t ccc;
|
||||
attEvt_t att;
|
||||
} amvoleMsg_t;
|
||||
|
||||
|
||||
/**************************************************************************************************
|
||||
Configurable Parameters
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! configurable parameters for advertising */
|
||||
static const appAdvCfg_t amvoleAdvCfg =
|
||||
{
|
||||
{60000, 0, 0}, /*! Advertising durations in ms */
|
||||
{ 800, 800, 0} /*! Advertising intervals in 0.625 ms units */
|
||||
};
|
||||
|
||||
/*! configurable parameters for slave */
|
||||
static const appSlaveCfg_t amvoleSlaveCfg =
|
||||
{
|
||||
VOLE_CONN_MAX, /*! Maximum connections */
|
||||
};
|
||||
|
||||
/*! configurable parameters for security */
|
||||
static const appSecCfg_t amvoleSecCfg =
|
||||
{
|
||||
DM_AUTH_BOND_FLAG | DM_AUTH_SC_FLAG, /*! Authentication and bonding flags */
|
||||
0, /*! Initiator key distribution flags */
|
||||
DM_KEY_DIST_LTK, /*! Responder key distribution flags */
|
||||
FALSE, /*! TRUE if Out-of-band pairing data is present */
|
||||
FALSE /*! TRUE to initiate security upon connection */
|
||||
};
|
||||
|
||||
|
||||
static const appUpdateCfg_t amvoleUpdateCfg =
|
||||
{
|
||||
1000, //3000, /*! Connection idle period in ms before attempting
|
||||
//connection parameter update; set to zero to disable */
|
||||
6, //6, /*! 7.5ms */
|
||||
12, //15, /*! 30ms */
|
||||
0, /*! Connection latency */
|
||||
400, //2000, //600, /*! Supervision timeout in 10ms units */
|
||||
5 /*! Number of update attempts before giving up */
|
||||
};
|
||||
|
||||
/*! SMP security parameter configuration */
|
||||
static const smpCfg_t amvoleSmpCfg =
|
||||
{
|
||||
3000, /*! 'Repeated attempts' timeout in msec */
|
||||
SMP_IO_NO_IN_NO_OUT, /*! I/O Capability */
|
||||
7, /*! Minimum encryption key length */
|
||||
16, /*! Maximum encryption key length */
|
||||
3, /*! Attempts to trigger 'repeated attempts' timeout */
|
||||
0, /*! Device authentication requirements */
|
||||
};
|
||||
|
||||
/**************************************************************************************************
|
||||
Advertising Data
|
||||
**************************************************************************************************/
|
||||
|
||||
// RAM buffers to be used
|
||||
uint8_t amvoleAdvDataDisc[31];
|
||||
uint8_t amvoleScanDataDisc[31];
|
||||
|
||||
/*! advertising data, discoverable mode */
|
||||
static const uint8_t amvoleAdvDataDiscDefault[] =
|
||||
{
|
||||
/*! flags */
|
||||
2, /*! length */
|
||||
DM_ADV_TYPE_FLAGS, /*! AD type */
|
||||
DM_FLAG_LE_GENERAL_DISC | /*! flags */
|
||||
DM_FLAG_LE_BREDR_NOT_SUP,
|
||||
|
||||
/*! tx power */
|
||||
2, /*! length */
|
||||
DM_ADV_TYPE_TX_POWER, /*! AD type */
|
||||
0, /*! tx power */
|
||||
|
||||
/*! service UUID list */
|
||||
17, /*! length */
|
||||
DM_ADV_TYPE_128_UUID, /*! AD type */
|
||||
ATT_UUID_VOLES_SERVICE
|
||||
};
|
||||
|
||||
/*! scan data, discoverable mode */
|
||||
static const uint8_t amvoleScanDataDiscDefault[] =
|
||||
{
|
||||
/*! device name */
|
||||
5, /*! length */
|
||||
DM_ADV_TYPE_LOCAL_NAME, /*! AD type */
|
||||
'V',
|
||||
'o',
|
||||
'L',
|
||||
'E'
|
||||
};
|
||||
|
||||
dmConnId_t g_AmaConnId = DM_CONN_ID_NONE;
|
||||
|
||||
bool_t g_start_voice_send = FALSE;
|
||||
|
||||
extern bool am_app_KWD_AMA_tx_ver_exchange_send(void);
|
||||
|
||||
// index is the starting point of the local name, local name only in advData
|
||||
static bool amvoleSetLocalName(uint8_t* pAdvData, uint8_t* pLocalName, uint8_t len, uint8_t index)
|
||||
{
|
||||
if (index + len + 1 > 31)
|
||||
{
|
||||
// max adv data is 31 byte long
|
||||
return false;
|
||||
}
|
||||
|
||||
// set parameter length
|
||||
pAdvData[index] = len + 1;
|
||||
// set parameter type
|
||||
pAdvData[index + 1] = DM_ADV_TYPE_LOCAL_NAME;
|
||||
|
||||
// set local name
|
||||
for ( uint8_t i = 0; i < len; i++ )
|
||||
{
|
||||
pAdvData[i + 2 + index] = pLocalName[i];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void amvoleKwdSetDemoName(void)
|
||||
{
|
||||
uint8_t test_bdaddress[6];
|
||||
uint8_t ble_device_name[20] = "VOLES-"; //local name = device name
|
||||
uint8_t *pBda;
|
||||
uint8_t index = 6;
|
||||
|
||||
//fixme: read bd address and print out
|
||||
pBda = HciGetBdAddr();
|
||||
BdaCpy(test_bdaddress, pBda);
|
||||
|
||||
pBda = (uint8_t*)Bda2Str(test_bdaddress);
|
||||
APP_TRACE_INFO0("Local Device BD Address: ");
|
||||
APP_TRACE_INFO0(Bda2Str(test_bdaddress));
|
||||
APP_TRACE_INFO0("\n");
|
||||
|
||||
// build demo name here
|
||||
// 1st letter is board variant
|
||||
#if USE_MAYA
|
||||
ble_device_name[index++] = 'M';
|
||||
#elif USE_APOLLO2_QT
|
||||
ble_device_name[index++] = 'Q';
|
||||
#else
|
||||
ble_device_name[index++] = 'E';
|
||||
#endif
|
||||
|
||||
|
||||
// 3rd letter is wake-on-sound variant
|
||||
#if USE_WAKE_ON_SOUND
|
||||
ble_device_name[index++] = 'W';
|
||||
#else
|
||||
ble_device_name[index++] = 'A'; // A for always listening...
|
||||
#endif
|
||||
|
||||
|
||||
ble_device_name[index++] = '-';
|
||||
|
||||
ble_device_name[index++] = 'A';
|
||||
ble_device_name[index++] = 'M';
|
||||
ble_device_name[index++] = 'A';
|
||||
|
||||
// a hyphen...
|
||||
ble_device_name[index++] = '-';
|
||||
|
||||
// take the last 4 hex digit
|
||||
ble_device_name[index++] = pBda[8];
|
||||
ble_device_name[index++] = pBda[9];
|
||||
ble_device_name[index++] = pBda[10];
|
||||
ble_device_name[index++] = pBda[11];
|
||||
|
||||
// set local name here:
|
||||
amvoleSetLocalName(amvoleScanDataDisc, ble_device_name, index, 0);
|
||||
//SvcCoreSetDevName(ble_device_name, index);
|
||||
}
|
||||
|
||||
/**************************************************************************************************
|
||||
Client Characteristic Configuration Descriptors
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! enumeration of client characteristic configuration descriptors */
|
||||
enum
|
||||
{
|
||||
VOLES_GATT_SC_CCC_IDX, /*! GATT service, service changed characteristic */
|
||||
VOLES_TX_CCC_IDX, /*! AMDTP service, tx characteristic */
|
||||
VOLES_NUM_CCC_IDX
|
||||
};
|
||||
|
||||
/*! client characteristic configuration descriptors settings, indexed by above enumeration */
|
||||
static const attsCccSet_t amvoleCccSet[VOLES_NUM_CCC_IDX] =
|
||||
{
|
||||
/* cccd handle value range security level */
|
||||
{GATT_SC_CH_CCC_HDL, ATT_CLIENT_CFG_INDICATE, DM_SEC_LEVEL_NONE}, /* VOLES_GATT_SC_CCC_IDX */
|
||||
{VOLES_TX_CH_CCC_HDL, ATT_CLIENT_CFG_NOTIFY, DM_SEC_LEVEL_NONE}, /* VOLES_TX_CCC_IDX */
|
||||
};
|
||||
|
||||
/**************************************************************************************************
|
||||
Global Variables
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! WSF handler ID */
|
||||
wsfHandlerId_t amvoleHandlerId;
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amvoleDmCback
|
||||
*
|
||||
* \brief Application DM callback.
|
||||
*
|
||||
* \param pDmEvt DM callback event
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void amvoleDmCback(dmEvt_t *pDmEvt)
|
||||
{
|
||||
dmEvt_t *pMsg;
|
||||
uint16_t len;
|
||||
|
||||
len = DmSizeOfEvt(pDmEvt);
|
||||
|
||||
if ((pMsg = WsfMsgAlloc(len)) != NULL)
|
||||
{
|
||||
memcpy(pMsg, pDmEvt, len);
|
||||
WsfMsgSend(amvoleHandlerId, pMsg);
|
||||
}
|
||||
}
|
||||
|
||||
bool amvoleTxChannelIsAvailable(void)
|
||||
{
|
||||
return(DM_CONN_ID_NONE != AppConnIsOpen());
|
||||
}
|
||||
|
||||
void VoleBleSend(uint8_t * buf, uint32_t len)
|
||||
{
|
||||
if (amvoleTxChannelIsAvailable())
|
||||
{
|
||||
// simply tries to send notification
|
||||
AttsHandleValueNtf(g_AmaConnId, VOLES_TX_HDL, len, buf); // connId always group 0 since support only 1 connection.
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amvoleAttCback
|
||||
*
|
||||
* \brief Application ATT callback.
|
||||
*
|
||||
* \param pEvt ATT callback event
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void amvoleAttCback(attEvt_t *pEvt)
|
||||
{
|
||||
attEvt_t *pMsg;
|
||||
|
||||
if ((pMsg = WsfMsgAlloc(sizeof(attEvt_t) + pEvt->valueLen)) != NULL)
|
||||
{
|
||||
memcpy(pMsg, pEvt, sizeof(attEvt_t));
|
||||
pMsg->pValue = (uint8_t *) (pMsg + 1);
|
||||
memcpy(pMsg->pValue, pEvt->pValue, pEvt->valueLen);
|
||||
WsfMsgSend(amvoleHandlerId, pMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amvoleCccCback
|
||||
*
|
||||
* \brief Application ATTS client characteristic configuration callback.
|
||||
*
|
||||
* \param pDmEvt DM callback event
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void amvoleCccCback(attsCccEvt_t *pEvt)
|
||||
{
|
||||
attsCccEvt_t *pMsg;
|
||||
appDbHdl_t dbHdl;
|
||||
|
||||
/* if CCC not set from initialization and there's a device record */
|
||||
if ((pEvt->handle != ATT_HANDLE_NONE) &&
|
||||
((dbHdl = AppDbGetHdl((dmConnId_t) pEvt->hdr.param)) != APP_DB_HDL_NONE))
|
||||
{
|
||||
/* store value in device database */
|
||||
AppDbSetCccTblValue(dbHdl, pEvt->idx, pEvt->value);
|
||||
}
|
||||
|
||||
if ((pMsg = WsfMsgAlloc(sizeof(attsCccEvt_t))) != NULL)
|
||||
{
|
||||
memcpy(pMsg, pEvt, sizeof(attsCccEvt_t));
|
||||
WsfMsgSend(amvoleHandlerId, pMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amvoleProcCccState
|
||||
*
|
||||
* \brief Process CCC state change.
|
||||
*
|
||||
* \param pMsg Pointer to message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void amvoleProcCccState(amvoleMsg_t *pMsg)
|
||||
{
|
||||
APP_TRACE_INFO3("ccc state ind value:%d handle:%d idx:%d\n", pMsg->ccc.value, pMsg->ccc.handle, pMsg->ccc.idx);
|
||||
|
||||
/* VOLES TX CCC */
|
||||
if (pMsg->ccc.idx == VOLES_TX_CCC_IDX)
|
||||
{
|
||||
if (pMsg->ccc.value == ATT_CLIENT_CFG_NOTIFY)
|
||||
{
|
||||
// notify enabled
|
||||
g_AmaConnId = (dmConnId_t) pMsg->ccc.hdr.param;
|
||||
APP_TRACE_INFO1("connId : %d\r\n", pMsg->ccc.hdr.param);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_AmaConnId = DM_CONN_ID_NONE;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amvoleClose
|
||||
*
|
||||
* \brief Perform UI actions on connection close.
|
||||
*
|
||||
* \param pMsg Pointer to message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void amvoleClose(amvoleMsg_t *pMsg)
|
||||
{
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amvoleSetup
|
||||
*
|
||||
* \brief Set up advertising and other procedures that need to be performed after
|
||||
* device reset.
|
||||
*
|
||||
* \param pMsg Pointer to message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void amvoleSetup(amvoleMsg_t *pMsg)
|
||||
{
|
||||
/* set advertising and scan response data for discoverable mode */
|
||||
AppAdvSetData(APP_ADV_DATA_DISCOVERABLE, sizeof(amvoleAdvDataDisc), (uint8_t *) amvoleAdvDataDisc);
|
||||
AppAdvSetData(APP_SCAN_DATA_DISCOVERABLE, sizeof(amvoleScanDataDisc), (uint8_t *) amvoleScanDataDisc);
|
||||
|
||||
/* set advertising and scan response data for connectable mode */
|
||||
AppAdvSetData(APP_ADV_DATA_CONNECTABLE, sizeof(amvoleAdvDataDisc), (uint8_t *) amvoleAdvDataDisc);
|
||||
AppAdvSetData(APP_SCAN_DATA_CONNECTABLE, sizeof(amvoleScanDataDisc), (uint8_t *) amvoleScanDataDisc);
|
||||
|
||||
AppSetBondable(TRUE);
|
||||
/* start advertising; automatically set connectable/discoverable mode and bondable mode */
|
||||
AppAdvStart(APP_MODE_AUTO_INIT);
|
||||
}
|
||||
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// LED task to indicate external events, such as heart beat and key word detected.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
void am_app_led_on(void)
|
||||
{
|
||||
#if defined(AM_PART_APOLLO2)
|
||||
am_hal_gpio_out_bit_toggle(LED_D6);
|
||||
am_hal_gpio_out_bit_toggle(LED_D7);
|
||||
am_hal_gpio_out_bit_toggle(LED_D8);
|
||||
#endif // #if defined(AM_PART_APOLLO2)
|
||||
|
||||
#if defined(AM_PART_APOLLO3) || defined(AM_PART_APOLLO3P)
|
||||
#if USE_APOLLO3_BLUE_EVB
|
||||
am_hal_gpio_state_write(LED_D5, AM_HAL_GPIO_OUTPUT_TOGGLE);
|
||||
am_hal_gpio_state_write(LED_D6, AM_HAL_GPIO_OUTPUT_TOGGLE);
|
||||
am_hal_gpio_state_write(LED_D7, AM_HAL_GPIO_OUTPUT_TOGGLE);
|
||||
am_hal_gpio_state_write(LED_D8, AM_HAL_GPIO_OUTPUT_TOGGLE);
|
||||
|
||||
#endif // #if USE_APOLLO3_BLUE_EVB
|
||||
#endif //#if defined(AM_PART_APOLLO3)
|
||||
|
||||
}
|
||||
|
||||
void am_app_led_off(void)
|
||||
{
|
||||
#if defined(AM_PART_APOLLO2)
|
||||
am_hal_gpio_out_bit_clear(LED_D6);
|
||||
am_hal_gpio_out_bit_clear(LED_D7);
|
||||
am_hal_gpio_out_bit_clear(LED_D8);
|
||||
#endif
|
||||
|
||||
#if defined(AM_PART_APOLLO3) || defined(AM_PART_APOLLO3P)
|
||||
#if USE_APOLLO3_BLUE_EVB
|
||||
am_hal_gpio_state_write(LED_D5, AM_HAL_GPIO_OUTPUT_CLEAR);
|
||||
am_hal_gpio_state_write(LED_D6, AM_HAL_GPIO_OUTPUT_CLEAR);
|
||||
am_hal_gpio_state_write(LED_D7, AM_HAL_GPIO_OUTPUT_CLEAR);
|
||||
am_hal_gpio_state_write(LED_D8, AM_HAL_GPIO_OUTPUT_CLEAR);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amvoleBtnCback
|
||||
*
|
||||
* \brief Button press callback.
|
||||
*
|
||||
* \param btn Button press.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void amvoleBtnCback(uint8_t btn)
|
||||
{
|
||||
dmConnId_t connId = AppConnIsOpen();
|
||||
|
||||
APP_TRACE_INFO2("button %d pressed, connection open:%d", btn, connId);
|
||||
|
||||
/* button actions when connected */
|
||||
if (connId != DM_CONN_ID_NONE)
|
||||
{
|
||||
APP_TRACE_INFO1("btn:%d", btn);
|
||||
switch (btn)
|
||||
{
|
||||
// transmit voice data using mSBC encode
|
||||
case APP_UI_BTN_1_SHORT:
|
||||
APP_TRACE_INFO0("start speech data send...");
|
||||
voles_set_codec_type(MSBC_CODEC_IN_USE);
|
||||
voles_init(amvoleHandlerId, MSBC_CODEC_IN_USE);
|
||||
am_app_KWD_AMA_start_speech_send();
|
||||
break;
|
||||
|
||||
case APP_UI_BTN_2_SHORT:
|
||||
voles_set_codec_type(OPUS_CODEC_IN_USE);
|
||||
voles_init(amvoleHandlerId, OPUS_CODEC_IN_USE);
|
||||
am_app_KWD_AMA_start_speech_send();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
amvole_write_cback(dmConnId_t connId, uint16_t handle, uint8_t operation,
|
||||
uint16_t offset, uint16_t len, uint8_t *pValue, attsAttr_t *pAttr)
|
||||
{
|
||||
if (handle == VOLES_RX_HDL)
|
||||
{
|
||||
am_app_KWD_AMA_rx_handler(pValue, len);
|
||||
}
|
||||
return ATT_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amvoleProcMsg
|
||||
*
|
||||
* \brief Process messages from the event handler.
|
||||
*
|
||||
* \param pMsg Pointer to message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void amvoleProcMsg(amvoleMsg_t *pMsg)
|
||||
{
|
||||
uint8_t uiEvent = APP_UI_NONE;
|
||||
|
||||
static uint8_t retry_cnt = 0;
|
||||
|
||||
switch(pMsg->hdr.event)
|
||||
{
|
||||
case ATTS_HANDLE_VALUE_CNF:
|
||||
|
||||
voles_proc_msg(&pMsg->hdr);
|
||||
|
||||
break;
|
||||
|
||||
case ATTS_CCC_STATE_IND:
|
||||
amvoleProcCccState(pMsg);
|
||||
if (pMsg->ccc.handle == VOLES_TX_CH_CCC_HDL)
|
||||
{
|
||||
am_app_KWD_AMA_tx_ver_exchange_send();
|
||||
}
|
||||
break;
|
||||
|
||||
case DM_RESET_CMPL_IND:
|
||||
AttsCalculateDbHash();
|
||||
DmSecGenerateEccKeyReq();
|
||||
amvoleSetup(pMsg);
|
||||
|
||||
#if USE_BLE_TX_POWER_SET
|
||||
HciVsEM_SetRfPowerLevelEx(TX_POWER_LEVEL_PLUS_6P2_dBm);
|
||||
#endif
|
||||
|
||||
uiEvent = APP_UI_RESET_CMPL;
|
||||
break;
|
||||
|
||||
case DM_ADV_SET_START_IND:
|
||||
uiEvent = APP_UI_ADV_SET_START_IND;
|
||||
break;
|
||||
|
||||
case DM_ADV_SET_STOP_IND:
|
||||
uiEvent = APP_UI_ADV_SET_STOP_IND;
|
||||
break;
|
||||
|
||||
case DM_ADV_START_IND:
|
||||
uiEvent = APP_UI_ADV_START;
|
||||
break;
|
||||
|
||||
case DM_ADV_STOP_IND:
|
||||
uiEvent = APP_UI_ADV_STOP;
|
||||
break;
|
||||
|
||||
case DM_CONN_OPEN_IND:
|
||||
voles_proc_msg(&pMsg->hdr);
|
||||
DmConnSetDataLen(1, 251, 0x848);
|
||||
|
||||
uiEvent = APP_UI_CONN_OPEN;
|
||||
|
||||
retry_cnt = 0;
|
||||
|
||||
break;
|
||||
|
||||
case ATT_MTU_UPDATE_IND:
|
||||
if ( AttGetMtu(1) < BLE_MSBC_DATA_BUFFER_SIZE )
|
||||
{
|
||||
if (retry_cnt < 5)
|
||||
{
|
||||
retry_cnt++;
|
||||
AttcMtuReq(1, 247);
|
||||
}
|
||||
}
|
||||
|
||||
APP_TRACE_INFO2("ATT_MTU_UPDATE_IND AttGetMtu(), return = %d pMsg->att.mtu = %d\n", AttGetMtu(1), pMsg->att.mtu);
|
||||
break;
|
||||
|
||||
case DM_CONN_DATA_LEN_CHANGE_IND:
|
||||
am_util_debug_printf("DM_CONN_DATA_LEN_CHANGE_IND: status = %d, max RX len = %d, max TX len = %d \n", pMsg->dm.dataLenChange.hdr.status, pMsg->dm.dataLenChange.maxRxOctets, pMsg->dm.dataLenChange.maxTxOctets);
|
||||
break;
|
||||
|
||||
case DM_CONN_CLOSE_IND:
|
||||
APP_TRACE_INFO1("DM_CONN_CLOSE_IND reason = 0x%02x\n", pMsg->dm.connClose.reason);
|
||||
|
||||
amvoleClose(pMsg);
|
||||
uiEvent = APP_UI_CONN_CLOSE;
|
||||
|
||||
// AppAdvStart(APP_MODE_DISCOVERABLE);
|
||||
|
||||
g_AmaConnId = DM_CONN_ID_NONE;
|
||||
//g_eAmaStatus = VOS_AMA_INIT;
|
||||
break;
|
||||
|
||||
case DM_CONN_UPDATE_IND:
|
||||
voles_proc_msg(&pMsg->hdr);
|
||||
break;
|
||||
|
||||
case DM_SEC_PAIR_CMPL_IND:
|
||||
DmSecGenerateEccKeyReq();
|
||||
uiEvent = APP_UI_SEC_PAIR_CMPL;
|
||||
break;
|
||||
|
||||
case DM_SEC_PAIR_FAIL_IND:
|
||||
DmSecGenerateEccKeyReq();
|
||||
uiEvent = APP_UI_SEC_PAIR_FAIL;
|
||||
break;
|
||||
|
||||
case DM_SEC_ENCRYPT_IND:
|
||||
uiEvent = APP_UI_SEC_ENCRYPT;
|
||||
break;
|
||||
|
||||
case DM_SEC_ENCRYPT_FAIL_IND:
|
||||
uiEvent = APP_UI_SEC_ENCRYPT_FAIL;
|
||||
break;
|
||||
|
||||
case DM_SEC_AUTH_REQ_IND:
|
||||
AppHandlePasskey(&pMsg->dm.authReq);
|
||||
break;
|
||||
|
||||
case DM_SEC_ECC_KEY_IND:
|
||||
DmSecSetEccKey(&pMsg->dm.eccMsg.data.key);
|
||||
break;
|
||||
|
||||
case DM_SEC_COMPARE_IND:
|
||||
AppHandleNumericComparison(&pMsg->dm.cnfInd);
|
||||
break;
|
||||
|
||||
case DM_PRIV_CLEAR_RES_LIST_IND:
|
||||
APP_TRACE_INFO1("Clear resolving list status 0x%02x", pMsg->hdr.status);
|
||||
break;
|
||||
|
||||
case DM_HW_ERROR_IND:
|
||||
uiEvent = APP_UI_HW_ERROR;
|
||||
break;
|
||||
|
||||
case DM_VENDOR_SPEC_CMD_CMPL_IND:
|
||||
{
|
||||
#if defined(AM_PART_APOLLO) || defined(AM_PART_APOLLO2)
|
||||
|
||||
uint8_t *param_ptr = &pMsg->dm.vendorSpecCmdCmpl.param[0];
|
||||
|
||||
switch (pMsg->dm.vendorSpecCmdCmpl.opcode)
|
||||
{
|
||||
case 0xFC20: //read at address
|
||||
{
|
||||
uint32_t read_value;
|
||||
|
||||
BSTREAM_TO_UINT32(read_value, param_ptr);
|
||||
|
||||
APP_TRACE_INFO3("VSC 0x%0x complete status %x param %x",
|
||||
pMsg->dm.vendorSpecCmdCmpl.opcode,
|
||||
pMsg->hdr.status,
|
||||
read_value);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
APP_TRACE_INFO2("VSC 0x%0x complete status %x",
|
||||
pMsg->dm.vendorSpecCmdCmpl.opcode,
|
||||
pMsg->hdr.status);
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (uiEvent != APP_UI_NONE)
|
||||
{
|
||||
AppUiAction(uiEvent);
|
||||
}
|
||||
}
|
||||
|
||||
void amvoleStartSendVoiceData()
|
||||
{
|
||||
g_start_voice_send = TRUE;
|
||||
am_app_led_on();
|
||||
voles_transmit_voice_data();
|
||||
}
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn VoleHandlerInit
|
||||
*
|
||||
* \brief Application handler init function called during system initialization.
|
||||
*
|
||||
* \param handlerID WSF handler ID.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void VoleHandlerInit(wsfHandlerId_t handlerId)
|
||||
{
|
||||
APP_TRACE_INFO0("VoleHandlerInit");
|
||||
|
||||
/* store handler ID */
|
||||
amvoleHandlerId = handlerId;
|
||||
|
||||
/* Set configuration pointers */
|
||||
pAppAdvCfg = (appAdvCfg_t *) &amvoleAdvCfg;
|
||||
pAppSlaveCfg = (appSlaveCfg_t *) &amvoleSlaveCfg;
|
||||
pAppSecCfg = (appSecCfg_t *) &amvoleSecCfg;
|
||||
pAppUpdateCfg = (appUpdateCfg_t *) &amvoleUpdateCfg;
|
||||
|
||||
/* Initialize application framework */
|
||||
AppSlaveInit();
|
||||
AppServerInit();
|
||||
|
||||
/* Set stack configuration pointers */
|
||||
pSmpCfg = (smpCfg_t *) &amvoleSmpCfg;
|
||||
//voles_init(handlerId);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn VoleHandler
|
||||
*
|
||||
* \brief WSF event handler for application.
|
||||
*
|
||||
* \param event WSF event mask.
|
||||
* \param pMsg WSF message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void VoleHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg)
|
||||
{
|
||||
if (pMsg != NULL)
|
||||
{
|
||||
APP_TRACE_INFO1("vole got evt 0x%x", pMsg->event);
|
||||
|
||||
/* process ATT messages */
|
||||
if (pMsg->event >= ATT_CBACK_START && pMsg->event <= ATT_CBACK_END)
|
||||
{
|
||||
/* process server-related ATT messages */
|
||||
AppServerProcAttMsg(pMsg);
|
||||
}
|
||||
/* process DM messages */
|
||||
else if (pMsg->event >= DM_CBACK_START && pMsg->event <= DM_CBACK_END)
|
||||
{
|
||||
/* process advertising and connection-related messages */
|
||||
AppSlaveProcDmMsg((dmEvt_t *) pMsg);
|
||||
|
||||
/* process security-related messages */
|
||||
AppSlaveSecProcDmMsg((dmEvt_t *) pMsg);
|
||||
}
|
||||
|
||||
/* perform profile and user interface-related operations */
|
||||
amvoleProcMsg((amvoleMsg_t *) pMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn VoleStart
|
||||
*
|
||||
* \brief Start the application.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void VoleStart(void)
|
||||
{
|
||||
/* Register for stack callbacks */
|
||||
DmRegister(amvoleDmCback);
|
||||
DmConnRegister(DM_CLIENT_ID_APP, amvoleDmCback);
|
||||
AttRegister(amvoleAttCback);
|
||||
AttConnRegister(AppServerConnCback);
|
||||
AttsCccRegister(VOLES_NUM_CCC_IDX, (attsCccSet_t *) amvoleCccSet, amvoleCccCback);
|
||||
|
||||
/* Register for app framework callbacks */
|
||||
AppUiBtnRegister(amvoleBtnCback);
|
||||
|
||||
// set up adv data
|
||||
memcpy(amvoleAdvDataDisc, amvoleAdvDataDiscDefault, sizeof(amvoleAdvDataDiscDefault));
|
||||
memcpy(amvoleScanDataDisc, amvoleScanDataDiscDefault, sizeof(amvoleScanDataDiscDefault));
|
||||
|
||||
/* Initialize attribute server database */
|
||||
SvcCoreGattCbackRegister(GattReadCback, GattWriteCback);
|
||||
SvcCoreAddGroup();
|
||||
SvcDisAddGroup();
|
||||
SvcVolesCbackRegister(NULL, amvole_write_cback);
|
||||
SvcVolesAddGroup();
|
||||
|
||||
/* Set Service Changed CCCD index. */
|
||||
GattSetSvcChangedIdx(VOLES_GATT_SC_CCC_IDX);
|
||||
/* Reset the device */
|
||||
DmDevReset();
|
||||
}
|
||||
@@ -0,0 +1,824 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file hci_drv.c
|
||||
//!
|
||||
//! @brief HCI driver interface.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "am_mcu_apollo.h"
|
||||
#include "am_util.h"
|
||||
#include "am_devices_em9304.h"
|
||||
#include "em9304_init.h"
|
||||
#include "em9304_patches.h"
|
||||
#include "hci_apollo_config.h"
|
||||
|
||||
#define INVALIDATE_UNKNOWN_PATCHES
|
||||
#define ENABLE_32K_CLK_FROM_APOLLO
|
||||
#define SLEEP_CLK_PATCH_CONTAINER_ID (0x16)
|
||||
|
||||
// if a product is designed with step-up DCDC mode for EM9304
|
||||
// and was programmed HCI v6 patch on OTP, it's required
|
||||
// to define INVALIDATE_HCI_V6_PATCH_ON_OTP to do a special
|
||||
// handling to invalidate the v6 patch on OTP and program
|
||||
// v8 or later HCI patch.
|
||||
#define INVALIDATE_HCI_V6_PATCH_ON_OTP
|
||||
|
||||
#ifdef INVALIDATE_HCI_V6_PATCH_ON_OTP
|
||||
#define HCI_V6_PATCH_CONTAINER_ID 53
|
||||
#endif
|
||||
// This should be defined as the currently included HCI code patch
|
||||
// e.g. currently v8 is latest, which has container ID 77.
|
||||
#define HCI_CURRENT_CODE_PATCH_CONTAINER_ID 77
|
||||
|
||||
// Define the HCI Command Type locally.
|
||||
#define HCI_CMD_TYPE 1
|
||||
|
||||
// EM_PatchQuery field offsets
|
||||
#define PATCH_INDEX_OFFSET 3
|
||||
|
||||
// EM_PatchQuery response field offsets
|
||||
#define CONTAINER_COUNT_INDEX 7
|
||||
#define CONTAINER_ADDR_INDEX 15
|
||||
#define CONTAINER_SIZE_INDEX 19
|
||||
#define BUILD_NUMBER_INDEX 27
|
||||
#define USER_BUILD_NUMBER_INDEX 29
|
||||
#define CONTAINER_VERSION_INDEX 32
|
||||
#define CONTAINER_TYPE_INDEX 33
|
||||
#define CONTAINER_ID_INDEX 34
|
||||
|
||||
// EM_PatchQuery response values
|
||||
#define CONTAINER_TYPE_CONFIG_DATA_WORD 1
|
||||
#define CONTAINER_TYPE_RANDOM_DATA_WORD 2
|
||||
#define CONTAINER_TYPE_RANDOM_DATA_BYTE 3
|
||||
#define CONTAINER_TYPE_CONFIG_DATA_BYTE 11
|
||||
|
||||
// EM_PatchWrite and EM_PatchContine field offsets
|
||||
#define PATCH_LENGTH_OFFSET 2
|
||||
|
||||
// EM_PatchWrite destination memory field offsets
|
||||
#define PATCH_DEST_MEMORY_OFFSET 3
|
||||
|
||||
// EM_PatchWrite and EM_PatchContinue response field offsets
|
||||
#define HCI_STATUS_OFFSET 6
|
||||
#define EM_PATCH_STATUS_OFFSET 7
|
||||
|
||||
// EM_PatchWrite and EM_PatchContinue Patch Status values
|
||||
#define EM_PATCH_APPLIED 1
|
||||
#define EM_PATCH_CONTINUE 2
|
||||
|
||||
// Maximum number of attempts to wait for a response from EM9304.
|
||||
#define EM9304_MAX_ATTEMPTS 100
|
||||
#define EM9304_ATTEMPT_DELAY_MS 1
|
||||
|
||||
#define EM9304_IRAM1_START_ADDRESS 0x20000
|
||||
|
||||
// Initialization function error return status.
|
||||
enum
|
||||
{
|
||||
EM9304_INIT_STATUS_SUCCESS,
|
||||
EM9304_INIT_STATUS_ERROR
|
||||
} e_em9304_init_status;
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// HCI Commands for EM9304
|
||||
//
|
||||
//*****************************************************************************
|
||||
uint8_t g_pui8EM_SleepDisable[] = {0x2D, 0xFC, 0x01, 0x00};
|
||||
uint8_t g_pui8EM_SetOTPOn[] = {0x2B, 0xFC, 0x01, 0x01};
|
||||
uint8_t g_pui8EM_SetOTPOff[] = {0x2B, 0xFC, 0x01, 0x00};
|
||||
uint8_t g_pui8EM_SetIRAMOn[] = {0x2B, 0xFC, 0x01, 0x07};
|
||||
uint8_t g_pui8EM_PatchQuery[] = {0x34, 0xFC, 0x02, 0x00, 0x00};
|
||||
uint8_t g_pui8EM_SleepEnable[] = {0x2D, 0xFC, 0x01, 0x01};
|
||||
uint8_t g_pui8EM_CpuReset[] = {0x32, 0xFC, 0x00};
|
||||
|
||||
uint32_t
|
||||
applyEM9304Patches(uint32_t target_memory, uint32_t containerID);
|
||||
//*****************************************************************************
|
||||
//
|
||||
// HCI RX packet buffer for EM9304 Driver.
|
||||
//
|
||||
//*****************************************************************************
|
||||
static uint32_t g_pui32HCIRXBuffer[64];
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Static record of the EM9304 patch errors
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
uint32_t g_EMPatchErrors = 0;
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @brief Patch Response helper functions for the EM9304 patches. This
|
||||
//! routine blocks on a response from the EM9304 and filters the
|
||||
//! vendor specific events.
|
||||
//!
|
||||
//! @return none.
|
||||
//
|
||||
//*****************************************************************************
|
||||
uint32_t
|
||||
waitEM9304Response(void)
|
||||
{
|
||||
uint32_t numBytesRx;
|
||||
|
||||
// HCI Respone should return in 1-2 messages at most, but driver returns
|
||||
// 0 bytes when nothing is available, so wait up to 10msec.
|
||||
for (uint32_t attempts = 0; attempts < EM9304_MAX_ATTEMPTS; attempts++)
|
||||
{
|
||||
numBytesRx = am_devices_em9304_block_read(&g_sEm9304, g_pui32HCIRXBuffer, 0);
|
||||
// Look for "no message" return while filtering out the EM9304 vendor specific events.
|
||||
if ((numBytesRx != 0) && (!((numBytesRx == 4) && (0x0000FF04 == (g_pui32HCIRXBuffer[0] & 0x0000FFFF)))))
|
||||
{
|
||||
return EM9304_INIT_STATUS_SUCCESS;
|
||||
}
|
||||
am_util_delay_ms(EM9304_ATTEMPT_DELAY_MS);
|
||||
}
|
||||
return EM9304_INIT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @brief Function to check for valid patches in the em9304_patches.* files.
|
||||
//! Invalid patches means that the scripts to generate the patch files
|
||||
//! were run without valid *.emp files as input.
|
||||
//!
|
||||
//! @return bool (TRUE = patches are valid).
|
||||
//
|
||||
//*****************************************************************************
|
||||
bool validEM9304Patches(void)
|
||||
{
|
||||
//
|
||||
// Check to see if we have valid patches.
|
||||
// NULL patch has a specific signature.
|
||||
//
|
||||
if ((1 == EM9304_PATCHES_NUM_PATCHES) &&
|
||||
(0xFFFF == g_pEm9304Patches[0].buildNumber) &&
|
||||
(0xFFFF == g_pEm9304Patches[0].userBuildNumber) &&
|
||||
(0xFF == g_pEm9304Patches[0].containerVersion) &&
|
||||
(0xFF == g_pEm9304Patches[0].containerType) &&
|
||||
(0xFF == g_pEm9304Patches[0].containerID) &&
|
||||
(0x00 == g_pEm9304Patches[0].applyPatch) &&
|
||||
(0x00 == g_pEm9304Patches[0].startingPatch) &&
|
||||
(0x00 == g_pEm9304Patches[0].endingPatch))
|
||||
{
|
||||
am_util_debug_printf("em9304_patches.c contains NULL patch only\n");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
am_util_debug_printf("Valid em9304_patches.c file found\n");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @brief Function to invalidate a patch at a given address. The size field
|
||||
//! is changed to corrupt the patch in OTP.
|
||||
//!
|
||||
//! @return status.
|
||||
//
|
||||
//*****************************************************************************
|
||||
#ifdef INVALIDATE_UNKNOWN_PATCHES
|
||||
static uint32_t invalidateEM9304Patch(uint32_t addr, uint32_t size)
|
||||
{
|
||||
uint8_t *bytePtr = (uint8_t *)&g_pui32HCIRXBuffer;
|
||||
|
||||
uint8_t payload[] =
|
||||
{
|
||||
0x22, 0xFC, //WriteAtAddr command
|
||||
0x0C, //HCI param length
|
||||
0, 0, 0, 0, // container address placeholder
|
||||
0x33, 0x39, 0x6D, 0x65, //signature
|
||||
0, 0, 0, 0 //size placeholder
|
||||
};
|
||||
|
||||
payload[3] = (uint8_t)(addr & 0xFF);
|
||||
payload[4] = (uint8_t)((addr & 0xFF00) >> 8);
|
||||
payload[5] = (uint8_t)((addr & 0xFF0000) >> 16);
|
||||
payload[6] = (uint8_t)((addr & 0xFF000000) >> 24);
|
||||
|
||||
size |= 0x36000000; // mask the size to change the patch (invalidate it).
|
||||
|
||||
payload[11] = (uint8_t)(size & 0xFF);
|
||||
payload[12] = (uint8_t)((size & 0xFF00) >> 8);
|
||||
payload[13] = (uint8_t)((size & 0xFF0000) >> 16);
|
||||
payload[14] = (uint8_t)((size & 0xFF000000) >> 24);
|
||||
|
||||
am_devices_em9304_block_write(&g_sEm9304, HCI_CMD_TYPE, payload, sizeof(payload));
|
||||
|
||||
if ((EM9304_INIT_STATUS_SUCCESS != waitEM9304Response()) || (bytePtr[HCI_STATUS_OFFSET] != 0))
|
||||
{
|
||||
am_util_debug_printf("Invalidating patch at %x status %d\n", addr, bytePtr[HCI_STATUS_OFFSET]);
|
||||
|
||||
return EM9304_INIT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
am_util_debug_printf("Invalidating patch at %x status OK\n", addr);
|
||||
|
||||
return EM9304_INIT_STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @brief Query the EM9304 patches. This routine uses the EM_PatchQuery HCI
|
||||
//! command to interogate the connected EM9304 about its current patch
|
||||
//! state and then update the patch Container Info data structure.
|
||||
//!
|
||||
//! @return status.
|
||||
//
|
||||
//*****************************************************************************
|
||||
uint32_t
|
||||
queryEM9304Patches(void)
|
||||
{
|
||||
uint32_t containerCount;
|
||||
uint32_t buildNumber, userBuildNumber, containerVersion, containerType, containerID;
|
||||
#ifdef INVALIDATE_UNKNOWN_PATCHES
|
||||
uint32_t containerAddr, containerSize;
|
||||
bool invalidatePatch = false;
|
||||
#endif
|
||||
|
||||
uint8_t *pBuf = (uint8_t *)g_pui32HCIRXBuffer;
|
||||
|
||||
// Initialize the container info patch status
|
||||
for (uint32_t patch = 0; patch < EM9304_PATCHES_NUM_PATCHES; patch++)
|
||||
{
|
||||
// Check patch for enabling 32Khz clck from Apollo MCU
|
||||
if ((g_pEm9304Patches[patch].userBuildNumber == 2) && (g_pEm9304Patches[patch].containerID == SLEEP_CLK_PATCH_CONTAINER_ID))
|
||||
{
|
||||
uint32_t ui32PN;
|
||||
|
||||
//
|
||||
// Device identification
|
||||
//
|
||||
ui32PN = AM_REG(MCUCTRL, CHIP_INFO) &
|
||||
AM_UTIL_MCUCTRL_CHIP_INFO_PARTNUM_PN_M;
|
||||
|
||||
#ifdef ENABLE_32K_CLK_FROM_APOLLO
|
||||
// Currently only enable this for Apollo2-Blue
|
||||
if (ui32PN == AM_UTIL_MCUCTRL_CHIP_INFO_PARTNUM_APOLLOBL)
|
||||
{
|
||||
g_pEm9304Patches[patch].applyPatch = true;
|
||||
|
||||
// GPIO 24 in Apollo2-blue connected to LFCLK in EM9304
|
||||
am_hal_gpio_pin_config(24, AM_HAL_PIN_24_CLKOUT);
|
||||
am_hal_clkgen_osc_start(AM_HAL_CLKGEN_OSC_XT);
|
||||
am_util_delay_ms(500);
|
||||
am_hal_clkgen_clkout_enable(AM_HAL_CLKGEN_CLKOUT_CKSEL_XT);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pEm9304Patches[patch].applyPatch = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Send the EM_SetSleepOptions command to disable sleep and check the response.
|
||||
am_devices_em9304_block_write(&g_sEm9304, HCI_CMD_TYPE, g_pui8EM_SleepDisable, sizeof(g_pui8EM_SleepDisable));
|
||||
|
||||
if (EM9304_INIT_STATUS_SUCCESS != waitEM9304Response())
|
||||
{
|
||||
am_util_debug_printf("No Response to EM9304 Sleep Disable\n");
|
||||
return EM9304_INIT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
// Check that the response is to the Sleep Disable.
|
||||
if ((0x01040E04 != g_pui32HCIRXBuffer[0]) || (0x0000FC2D != (g_pui32HCIRXBuffer[1] & 0x0000FFFF)))
|
||||
{
|
||||
am_util_debug_printf("Invalid Response to EM9304 Sleep Disable\n");
|
||||
return EM9304_INIT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
// Send the EM_SetMemoryMode command to turn on OTP and check the response.
|
||||
am_devices_em9304_block_write(&g_sEm9304, HCI_CMD_TYPE, g_pui8EM_SetOTPOn, sizeof(g_pui8EM_SetOTPOn));
|
||||
|
||||
if (EM9304_INIT_STATUS_SUCCESS != waitEM9304Response())
|
||||
{
|
||||
am_util_debug_printf("No Response to EM9304 OTP Enable\n");
|
||||
return EM9304_INIT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
// Check that the response is to the OTP enable.
|
||||
if ((0x01040E04 != g_pui32HCIRXBuffer[0]) || (0x0000FC2B != (g_pui32HCIRXBuffer[1] & 0x0000FFFF)))
|
||||
{
|
||||
am_util_debug_printf("Invalid Response to EM9304 OTP Enable\n");
|
||||
return EM9304_INIT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
// Query the EM9304 with the EM_PatchQuery and Patch Index = 0. This will return the Container Count.
|
||||
am_devices_em9304_block_write(&g_sEm9304, HCI_CMD_TYPE, g_pui8EM_PatchQuery, sizeof(g_pui8EM_PatchQuery));
|
||||
|
||||
if (EM9304_INIT_STATUS_SUCCESS != waitEM9304Response())
|
||||
{
|
||||
am_util_debug_printf("No Response to EM9304 Patch Query\n");
|
||||
return EM9304_INIT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
// Check that the response is to the Patch Query.
|
||||
if ((0x01200E04 != g_pui32HCIRXBuffer[0]) || (0x0000FC34 != (g_pui32HCIRXBuffer[1] & 0x0000FFFF)))
|
||||
{
|
||||
am_util_debug_printf("Invalid Response to EM9304 Patch Query\n");
|
||||
return EM9304_INIT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
// Extract the container information from the query response.
|
||||
containerCount = (uint32_t)pBuf[CONTAINER_COUNT_INDEX] +
|
||||
((uint32_t)pBuf[CONTAINER_COUNT_INDEX + 1] << 8);
|
||||
|
||||
// Assume the first patch is the manufacturing trim patch.
|
||||
// This is the only patch that never should be invalidated.
|
||||
am_util_debug_printf("Number of patch containers on EM9304 excluding Patch#0: %d\n", containerCount - 1);
|
||||
|
||||
#ifdef INVALIDATE_UNKNOWN_PATCHES
|
||||
#ifdef INVALIDATE_HCI_V6_PATCH_ON_OTP
|
||||
bool old_patch_invalidated = false;
|
||||
bool hci_v6_patch_present_on_otp = false;
|
||||
|
||||
// For each container in Container Count to see if HCI meta patch v6 patch
|
||||
// is present
|
||||
for (uint32_t container = 1; container < containerCount; container++)
|
||||
{
|
||||
// Send the EM_PatchQuery for the Container.
|
||||
g_pui8EM_PatchQuery[PATCH_INDEX_OFFSET] = container;
|
||||
|
||||
am_devices_em9304_block_write(&g_sEm9304, HCI_CMD_TYPE, g_pui8EM_PatchQuery, sizeof(g_pui8EM_PatchQuery));
|
||||
|
||||
if (EM9304_INIT_STATUS_SUCCESS != waitEM9304Response())
|
||||
{
|
||||
am_util_debug_printf("No Response to EM9304 Patch Query\n");
|
||||
return EM9304_INIT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
containerID = pBuf[CONTAINER_ID_INDEX];
|
||||
|
||||
// v6 patch's container ID is 53 in decimal.
|
||||
if (containerID == HCI_V6_PATCH_CONTAINER_ID)
|
||||
{
|
||||
|
||||
hci_v6_patch_present_on_otp = true;
|
||||
am_util_debug_printf("HCI v6 patch found in OTP\n");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hci_v6_patch_present_on_otp)
|
||||
{
|
||||
// here we have to do code-reset to EM9304
|
||||
am_hal_gpio_pin_config(HCI_APOLLO_RESET_PIN, AM_HAL_GPIO_OUTPUT);
|
||||
am_hal_gpio_out_bit_clear(HCI_APOLLO_RESET_PIN);
|
||||
|
||||
am_util_delay_ms(10);
|
||||
|
||||
am_hal_gpio_out_bit_set(HCI_APOLLO_RESET_PIN);
|
||||
|
||||
am_util_delay_ms(20);
|
||||
|
||||
// Apply the latest code patch into IRAM in order to invalidate v6 patch in otp
|
||||
// properly.
|
||||
|
||||
applyEM9304Patches(DEST_MEMORY_IRAM, HCI_CURRENT_CODE_PATCH_CONTAINER_ID);
|
||||
|
||||
// Send EM_CpuReset HCI command.
|
||||
am_devices_em9304_block_write(&g_sEm9304, HCI_CMD_TYPE, g_pui8EM_CpuReset, sizeof(g_pui8EM_CpuReset));
|
||||
|
||||
// HCI Respone should return in 1-2 messages at most, but driver returns
|
||||
// 0 bytes when nothing is available, so wait up to 10msec.
|
||||
for (uint32_t attempts = 0; attempts < EM9304_MAX_ATTEMPTS; attempts++)
|
||||
{
|
||||
uint32_t numBytesRx;
|
||||
|
||||
numBytesRx = am_devices_em9304_block_read(&g_sEm9304, g_pui32HCIRXBuffer, 0);
|
||||
if ((numBytesRx == 7) && (0x0000FC32 == (g_pui32HCIRXBuffer[1] & 0x0000FFFF)))
|
||||
{
|
||||
am_util_debug_printf("EM9304 CPU Reset Successfully\n");
|
||||
break;
|
||||
}
|
||||
am_util_delay_ms(EM9304_ATTEMPT_DELAY_MS);
|
||||
}
|
||||
|
||||
// Send the EM_SetSleepOptions command to disable sleep and check the response.
|
||||
am_devices_em9304_block_write(&g_sEm9304, HCI_CMD_TYPE, g_pui8EM_SleepDisable, sizeof(g_pui8EM_SleepDisable));
|
||||
|
||||
if (EM9304_INIT_STATUS_SUCCESS != waitEM9304Response())
|
||||
{
|
||||
am_util_debug_printf("No Response to EM9304 Sleep Disable\n");
|
||||
return EM9304_INIT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
// Check that the response is to the Sleep Disable.
|
||||
if ((0x01040E04 != g_pui32HCIRXBuffer[0]) || (0x0000FC2D != (g_pui32HCIRXBuffer[1] & 0x0000FFFF)))
|
||||
{
|
||||
am_util_debug_printf("Invalid Response to EM9304 Sleep Disable\n");
|
||||
return EM9304_INIT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
// Send the EM_SetMemoryMode command to turn on OTP and check the response.
|
||||
am_devices_em9304_block_write(&g_sEm9304, HCI_CMD_TYPE, g_pui8EM_SetOTPOn, sizeof(g_pui8EM_SetOTPOn));
|
||||
|
||||
if (EM9304_INIT_STATUS_SUCCESS != waitEM9304Response())
|
||||
{
|
||||
am_util_debug_printf("No Response to EM9304 OTP Enable\n");
|
||||
return EM9304_INIT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
// Check that the response is to the OTP enable.
|
||||
if ((0x01040E04 != g_pui32HCIRXBuffer[0]) || (0x0000FC2B != (g_pui32HCIRXBuffer[1] & 0x0000FFFF)))
|
||||
{
|
||||
am_util_debug_printf("Invalid Response to EM9304 OTP Enable\n");
|
||||
return EM9304_INIT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
// Query the EM9304 with the EM_PatchQuery and Patch Index = 0. This will return the Container Count.
|
||||
am_devices_em9304_block_write(&g_sEm9304, HCI_CMD_TYPE, g_pui8EM_PatchQuery, sizeof(g_pui8EM_PatchQuery));
|
||||
|
||||
if (EM9304_INIT_STATUS_SUCCESS != waitEM9304Response())
|
||||
{
|
||||
am_util_debug_printf("No Response to EM9304 Patch Query\n");
|
||||
return EM9304_INIT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
// Check that the response is to the Patch Query.
|
||||
if ((0x01200E04 != g_pui32HCIRXBuffer[0]) || (0x0000FC34 != (g_pui32HCIRXBuffer[1] & 0x0000FFFF)))
|
||||
{
|
||||
am_util_debug_printf("Invalid Response to EM9304 Patch Query\n");
|
||||
return EM9304_INIT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
// Extract the container information from the query response.
|
||||
containerCount = (uint32_t)pBuf[CONTAINER_COUNT_INDEX] +
|
||||
((uint32_t)pBuf[CONTAINER_COUNT_INDEX + 1] << 8);
|
||||
|
||||
// Assume the first patch is the manufacturing trim patch.
|
||||
// This is the only patch that never should be invalidated.
|
||||
am_util_debug_printf("Number of patch containers on EM9304 excluding Patch#0: %d\n", containerCount - 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// For each container in Container Count
|
||||
for (uint32_t container = 1; container < containerCount; container++)
|
||||
{
|
||||
// Send the EM_PatchQuery for the Container.
|
||||
g_pui8EM_PatchQuery[PATCH_INDEX_OFFSET] = container;
|
||||
am_devices_em9304_block_write(&g_sEm9304, HCI_CMD_TYPE, g_pui8EM_PatchQuery, sizeof(g_pui8EM_PatchQuery));
|
||||
|
||||
if (EM9304_INIT_STATUS_SUCCESS != waitEM9304Response())
|
||||
{
|
||||
am_util_debug_printf("No Response to EM9304 Patch Query\n");
|
||||
return EM9304_INIT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
// Extract the container information from the query response.
|
||||
containerCount = (uint32_t)pBuf[CONTAINER_COUNT_INDEX] +
|
||||
((uint32_t)pBuf[CONTAINER_COUNT_INDEX + 1] << 8);
|
||||
buildNumber = (uint32_t)pBuf[BUILD_NUMBER_INDEX] +
|
||||
((uint32_t)(pBuf[BUILD_NUMBER_INDEX + 1] << 8));
|
||||
userBuildNumber = (uint32_t)pBuf[USER_BUILD_NUMBER_INDEX] +
|
||||
((uint32_t)(pBuf[USER_BUILD_NUMBER_INDEX + 1] << 8));
|
||||
containerVersion = pBuf[CONTAINER_VERSION_INDEX];
|
||||
containerType = pBuf[CONTAINER_TYPE_INDEX];
|
||||
containerID = pBuf[CONTAINER_ID_INDEX];
|
||||
#ifdef INVALIDATE_UNKNOWN_PATCHES
|
||||
containerAddr = (uint32_t)((pBuf[CONTAINER_ADDR_INDEX + 3] << 24) +
|
||||
(pBuf[CONTAINER_ADDR_INDEX + 2] << 16) +
|
||||
(pBuf[CONTAINER_ADDR_INDEX + 1] << 8) +
|
||||
pBuf[CONTAINER_ADDR_INDEX]);
|
||||
containerSize = (uint32_t)((pBuf[CONTAINER_SIZE_INDEX + 3] << 24) +
|
||||
(pBuf[CONTAINER_SIZE_INDEX + 2] << 16) +
|
||||
(pBuf[CONTAINER_SIZE_INDEX + 1] << 8) +
|
||||
pBuf[CONTAINER_SIZE_INDEX]);
|
||||
|
||||
am_util_debug_printf("Patch #%d: Container Address = %8.8X Container Size = %4.4d Container Type=%d Container ID=%d Container Version=%d Build Number=%d User Build Number=%d\n",
|
||||
container, containerAddr, containerSize, containerType, containerID, containerVersion, buildNumber, userBuildNumber);
|
||||
|
||||
// if patch is on IRAM, we wont' do anything to it.
|
||||
if (containerAddr & EM9304_IRAM1_START_ADDRESS)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for patches that are likely not configuration managed by the customer.
|
||||
// Avoid invalidating these patches.
|
||||
if (((CONTAINER_TYPE_CONFIG_DATA_WORD == containerType) ||
|
||||
(CONTAINER_TYPE_RANDOM_DATA_WORD == containerType) ||
|
||||
(CONTAINER_TYPE_CONFIG_DATA_BYTE == containerType) ||
|
||||
(CONTAINER_TYPE_RANDOM_DATA_BYTE == containerType)) &&
|
||||
((0 == buildNumber) || (3089 == buildNumber)) &&
|
||||
(0 == userBuildNumber))
|
||||
{
|
||||
invalidatePatch = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Initialize the invalidate flag.
|
||||
invalidatePatch = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// For each local patch, compare the Container Version, Container Type, and Container ID to the container info.
|
||||
for (uint32_t patch = 0; patch < EM9304_PATCHES_NUM_PATCHES; patch++)
|
||||
{
|
||||
if ((g_pEm9304Patches[patch].buildNumber == buildNumber) &&
|
||||
(g_pEm9304Patches[patch].userBuildNumber == userBuildNumber) &&
|
||||
(g_pEm9304Patches[patch].containerVersion == containerVersion) &&
|
||||
(g_pEm9304Patches[patch].containerType == containerType) &&
|
||||
(g_pEm9304Patches[patch].containerID == containerID))
|
||||
{
|
||||
g_pEm9304Patches[patch].applyPatch = false; // Patch is already installed, so don't apply.
|
||||
#ifdef INVALIDATE_UNKNOWN_PATCHES
|
||||
// Note that we will "re-enable" patches here even if they met the criteria above (which can happen!)
|
||||
invalidatePatch = false;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef INVALIDATE_UNKNOWN_PATCHES
|
||||
// Check to see if we need to invalidate the patch.
|
||||
if (invalidatePatch)
|
||||
{
|
||||
invalidateEM9304Patch(containerAddr, containerSize);
|
||||
// if any old patch on OTP got invalidated, we need to hard-reset em9304
|
||||
// for the patch not to take effect so that subsequent patch applying can
|
||||
// work reliably.
|
||||
old_patch_invalidated = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef INVALIDATE_UNKNOWN_PATCHES
|
||||
#ifdef INVALIDATE_HCI_V6_PATCH_ON_OTP
|
||||
|
||||
if (hci_v6_patch_present_on_otp || old_patch_invalidated)
|
||||
{
|
||||
// If we has invalidate v6 or other unknown patch on OTP
|
||||
// we should do a cold reset to em9304 in order to clean
|
||||
// the previously programmed patch in IRAM.
|
||||
|
||||
// here we have to do code-reset to EM9304
|
||||
am_hal_gpio_pin_config(HCI_APOLLO_RESET_PIN, AM_HAL_GPIO_OUTPUT);
|
||||
am_hal_gpio_out_bit_clear(HCI_APOLLO_RESET_PIN);
|
||||
|
||||
am_util_delay_ms(10);
|
||||
|
||||
am_hal_gpio_out_bit_set(HCI_APOLLO_RESET_PIN);
|
||||
|
||||
am_util_delay_ms(20);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// if (DEST_MEMORY_IRAM == EM9304_PATCHES_DEST_MEMORY)
|
||||
// {
|
||||
// // Send the EM_SetMemoryMode command to turn off OTP and check the response.
|
||||
// am_devices_em9304_block_write(&g_sEm9304, HCI_CMD_TYPE, g_pui8EM_SetOTPOff, sizeof(g_pui8EM_SetOTPOff) );
|
||||
|
||||
// if (EM9304_INIT_STATUS_SUCCESS != waitEM9304Response())
|
||||
// {
|
||||
// am_util_debug_printf("No Response to EM9304 OTP Disable\n");
|
||||
// return EM9304_INIT_STATUS_ERROR;
|
||||
// }
|
||||
|
||||
// // Check that the response is to the OTP Disable.
|
||||
// if ((0x01040E04 != g_pui32HCIRXBuffer[0]) || (0x0000FC2B != (g_pui32HCIRXBuffer[1] & 0x0000FFFF)))
|
||||
// {
|
||||
// am_util_debug_printf("Invalid Response to EM9304 OTP Disable\n");
|
||||
// return EM9304_INIT_STATUS_ERROR;
|
||||
// }
|
||||
// }
|
||||
|
||||
// Send the EM_SetSleepOptions command to disable sleep and check the response.
|
||||
am_devices_em9304_block_write(&g_sEm9304, HCI_CMD_TYPE, g_pui8EM_SleepEnable, sizeof(g_pui8EM_SleepEnable));
|
||||
|
||||
if (EM9304_INIT_STATUS_SUCCESS != waitEM9304Response())
|
||||
{
|
||||
am_util_debug_printf("No Response to EM9304 Sleep Enable\n");
|
||||
return EM9304_INIT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
// Check that the response is to the Sleep Enable.
|
||||
if ((0x01040E04 != g_pui32HCIRXBuffer[0]) || (0x0000FC2D != (g_pui32HCIRXBuffer[1] & 0x0000FFFF)))
|
||||
{
|
||||
am_util_debug_printf("Invalid Response to EM9304 Sleep Enable\n");
|
||||
return EM9304_INIT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return EM9304_INIT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @brief Apply the EM9304 patches. This routine uses the EM_PatchQuery HCI
|
||||
//! command to interogate the connected EM9304 about its current patch
|
||||
//! state and then update the patch Container Info data structure.
|
||||
//!
|
||||
//!
|
||||
//! @return Returns the status of the patch application (< 0 is an error).
|
||||
//
|
||||
//*****************************************************************************
|
||||
uint32_t
|
||||
applyEM9304Patches(uint32_t target_memory, uint32_t containerID)
|
||||
{
|
||||
uint8_t *bytePtr = (uint8_t *)&g_pui32HCIRXBuffer;
|
||||
uint32_t ui32PN;
|
||||
|
||||
g_EMPatchErrors = 0;
|
||||
|
||||
//
|
||||
// Device identification
|
||||
//
|
||||
ui32PN = AM_REG(MCUCTRL, CHIP_INFO) &
|
||||
AM_UTIL_MCUCTRL_CHIP_INFO_PARTNUM_PN_M;
|
||||
|
||||
// only enable clock for Apollo2-blue (maybe later Apollo3 as well)
|
||||
if (ui32PN == AM_UTIL_MCUCTRL_CHIP_INFO_PARTNUM_APOLLOBL)
|
||||
{
|
||||
}
|
||||
|
||||
if (DEST_MEMORY_IRAM == target_memory)
|
||||
{
|
||||
// Send the EM_SetMemoryMode command to turn on IRAM and check the response.
|
||||
am_devices_em9304_block_write(&g_sEm9304, HCI_CMD_TYPE, g_pui8EM_SetIRAMOn, sizeof(g_pui8EM_SetIRAMOn));
|
||||
|
||||
if (EM9304_INIT_STATUS_SUCCESS != waitEM9304Response())
|
||||
{
|
||||
am_util_debug_printf("No Response to EM9304 IRAM Enable\n");
|
||||
return EM9304_INIT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
// Check that the response is to the IRAM enable.
|
||||
if ((0x01040E04 != g_pui32HCIRXBuffer[0]) || (0x0000FC2B != (g_pui32HCIRXBuffer[1] & 0x0000FFFF)))
|
||||
{
|
||||
am_util_debug_printf("Invalid Response to EM9304 IRAM Enable\n");
|
||||
return EM9304_INIT_STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// Loop through the patches and apply those that are not already there.
|
||||
// For each local patch, compare the Container Version, Container Type, and Container ID to the container info.
|
||||
for (uint32_t patch = 0; patch < EM9304_PATCHES_NUM_PATCHES; patch++)
|
||||
{
|
||||
if ((containerID != 0) && (containerID != (uint32_t)g_pEm9304Patches[patch].containerID))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (g_pEm9304Patches[patch].applyPatch)
|
||||
{
|
||||
am_util_debug_printf("Applying Patch #%d: Container Type=%d Container ID=%d Container Version=%d Build Number=%d User Build Number=%d\n",
|
||||
patch, g_pEm9304Patches[patch].containerType, g_pEm9304Patches[patch].containerID, g_pEm9304Patches[patch].containerVersion,
|
||||
g_pEm9304Patches[patch].buildNumber, g_pEm9304Patches[patch].userBuildNumber);
|
||||
|
||||
for (uint32_t index = g_pEm9304Patches[patch].startingPatch; index < g_pEm9304Patches[patch].endingPatch; index++)
|
||||
{
|
||||
if ((index == g_pEm9304Patches[patch].startingPatch) &&
|
||||
(target_memory != g_pEm9304PatchesHCICmd[index][PATCH_DEST_MEMORY_OFFSET]))
|
||||
{
|
||||
// max payload is 64 bytes for patch writing
|
||||
uint8_t g_pEm9304PatchesHCICmd_temp[80];
|
||||
|
||||
memcpy(g_pEm9304PatchesHCICmd_temp, g_pEm9304PatchesHCICmd[index],
|
||||
g_pEm9304PatchesHCICmd[index][PATCH_LENGTH_OFFSET] + 3);
|
||||
|
||||
// change destination memory type
|
||||
g_pEm9304PatchesHCICmd_temp[PATCH_DEST_MEMORY_OFFSET] = target_memory;
|
||||
|
||||
am_devices_em9304_block_write(&g_sEm9304, HCI_CMD_TYPE, (uint8_t *)g_pEm9304PatchesHCICmd_temp,
|
||||
g_pEm9304PatchesHCICmd_temp[PATCH_LENGTH_OFFSET] + 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
am_devices_em9304_block_write(&g_sEm9304, HCI_CMD_TYPE, (uint8_t *)g_pEm9304PatchesHCICmd[index],
|
||||
g_pEm9304PatchesHCICmd[index][PATCH_LENGTH_OFFSET] + 3);
|
||||
}
|
||||
|
||||
if (EM9304_INIT_STATUS_SUCCESS != waitEM9304Response())
|
||||
{
|
||||
am_util_debug_printf("No Response to EM9304 Patch Write\n");
|
||||
return EM9304_INIT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
if ((g_pEm9304PatchesHCICmd[index][0] == 0x27) &&
|
||||
((bytePtr[EM_PATCH_STATUS_OFFSET] != EM_PATCH_CONTINUE) &&
|
||||
(bytePtr[EM_PATCH_STATUS_OFFSET] != EM_PATCH_APPLIED)))
|
||||
{
|
||||
am_util_debug_printf("Error Response (%d)to EM9304 Patch Write\n", bytePtr[EM_PATCH_STATUS_OFFSET]);
|
||||
return EM9304_INIT_STATUS_ERROR;
|
||||
}
|
||||
else if (g_pEm9304PatchesHCICmd[index][0] == 0x28)
|
||||
{
|
||||
if (((index + 1) == g_pEm9304Patches[patch].endingPatch) && (bytePtr[EM_PATCH_STATUS_OFFSET] != EM_PATCH_APPLIED))
|
||||
{
|
||||
am_util_debug_printf("Error Response to EM9304 Patch Continue (next to last patch segment)\n");
|
||||
return EM9304_INIT_STATUS_ERROR;
|
||||
}
|
||||
else if (((index + 1) < g_pEm9304Patches[patch].endingPatch) && (bytePtr[EM_PATCH_STATUS_OFFSET] != EM_PATCH_CONTINUE))
|
||||
{
|
||||
am_util_debug_printf("Error Response to EM9304 Patch Continue (last patch segment)\n");
|
||||
return EM9304_INIT_STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EM9304_INIT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Configure the necessary pins and start the EM9304 radio.
|
||||
//
|
||||
//*****************************************************************************
|
||||
uint32_t
|
||||
initEM9304(void)
|
||||
{
|
||||
|
||||
if (validEM9304Patches())
|
||||
{
|
||||
//
|
||||
// Query the EM9304 for patches
|
||||
//
|
||||
if (EM9304_INIT_STATUS_SUCCESS == queryEM9304Patches())
|
||||
{
|
||||
//
|
||||
// Apply the patches not already in the EM9304
|
||||
//
|
||||
if (EM9304_INIT_STATUS_SUCCESS != applyEM9304Patches(EM9304_PATCHES_DEST_MEMORY, 0))
|
||||
{
|
||||
am_util_debug_printf("EM9304 Patch Application Failed\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
am_util_debug_printf("EM9304 Patching Query Failed. Patch update not applied\n");
|
||||
}
|
||||
}
|
||||
// Send EM_CpuReset HCI command.
|
||||
am_devices_em9304_block_write(&g_sEm9304, HCI_CMD_TYPE, g_pui8EM_CpuReset, sizeof(g_pui8EM_CpuReset));
|
||||
|
||||
// HCI Respone should return in 1-2 messages at most, but driver returns
|
||||
// 0 bytes when nothing is available, so wait up to 10msec.
|
||||
for (uint32_t attempts = 0; attempts < EM9304_MAX_ATTEMPTS; attempts++)
|
||||
{
|
||||
uint32_t numBytesRx;
|
||||
|
||||
numBytesRx = am_devices_em9304_block_read(&g_sEm9304, g_pui32HCIRXBuffer, 0);
|
||||
if ((numBytesRx == 7) && (0x0000FC32 == (g_pui32HCIRXBuffer[1] & 0x0000FFFF)))
|
||||
{
|
||||
am_util_debug_printf("EM9304 CPU Reset Successfully\n");
|
||||
break;
|
||||
}
|
||||
am_util_delay_ms(EM9304_ATTEMPT_DELAY_MS);
|
||||
}
|
||||
|
||||
return EM9304_PATCHES_DEST_MEMORY;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file em9304_init.h
|
||||
//!
|
||||
//! @brief Initialization functions for the EM Micro EM9304 BLE radio.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
#ifndef EM9304_INIT_H
|
||||
#define EM9304_INIT_H
|
||||
|
||||
uint32_t initEM9304(void);
|
||||
|
||||
#endif // EM9304_INIT_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,95 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file em9304_patches.h
|
||||
//!
|
||||
//! @brief This is a generated file.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef EM9304_PATCHES_H
|
||||
#define EM9304_PATCHES_H
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Length of the binary array in bytes.
|
||||
//
|
||||
//*****************************************************************************
|
||||
#define EM9304_PATCHES_NUM_PATCHES 8
|
||||
|
||||
// EM patch destination memory:
|
||||
// 1 means EM patch will be programmed into OTP if emp file
|
||||
// was not programmed before.
|
||||
// 0 means EM patch will be programmed into IRAM each time when
|
||||
// EM9304 is cold boot.
|
||||
|
||||
#define DEST_MEMORY_IRAM 0
|
||||
#define DEST_MEMORY_OTP 1
|
||||
#define EM9304_PATCHES_DEST_MEMORY 0
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// EM9304 Container Info type
|
||||
//
|
||||
//*****************************************************************************
|
||||
typedef struct
|
||||
{
|
||||
uint16_t buildNumber; // Firmware Build Number
|
||||
uint16_t userBuildNumber; // User defined Build Number (determines patch precedence)
|
||||
uint8_t containerVersion; // Container Version
|
||||
uint8_t containerType; // Container Type
|
||||
uint8_t containerID; // Container ID
|
||||
bool applyPatch; // Flag to apply this patch.
|
||||
uint8_t startingPatch; // Starting patch index.
|
||||
uint8_t endingPatch; // Ending patch index + 1.
|
||||
} em9304_container_info_t;
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Extracted binary array.
|
||||
//
|
||||
//*****************************************************************************
|
||||
extern em9304_container_info_t g_pEm9304Patches[8];
|
||||
extern const uint8_t g_pEm9304PatchesHCICmd[131][68];
|
||||
|
||||
#endif // EM9304_PATCHES_H
|
||||
@@ -0,0 +1,321 @@
|
||||
// ****************************************************************************
|
||||
//
|
||||
// ble_menu.c
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Functions for BLE control menu.
|
||||
//!
|
||||
//! @{
|
||||
//
|
||||
// ****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#include "ble_menu.h"
|
||||
#include "wsf_types.h"
|
||||
#include "amdtp_api.h"
|
||||
#include "app_api.h"
|
||||
|
||||
char menuRxData[20];
|
||||
uint32_t menuRxDataLen = 0;
|
||||
|
||||
sBleMenuCb bleMenuCb;
|
||||
|
||||
char mainMenuContent[BLE_MENU_ID_MAX][32] = {
|
||||
"1. BLE_MENU_ID_GAP",
|
||||
"2. BLE_MENU_ID_GATT",
|
||||
"3. BLE_MENU_ID_AMDTP",
|
||||
};
|
||||
|
||||
char gapMenuContent[GAP_MENU_ID_MAX][32] = {
|
||||
"1. Start Scan",
|
||||
"2. Stop Scan",
|
||||
"3. Show Scan Results",
|
||||
"4. Create Connection"
|
||||
};
|
||||
|
||||
char gattMenuContent[GATT_MENU_ID_MAX][32] = {
|
||||
"1. TBD",
|
||||
};
|
||||
|
||||
char amdtpMenuContent[AMDTP_MENU_ID_MAX][64] = {
|
||||
"1. Send test data continuously",
|
||||
"2. Stop sending test data",
|
||||
"3. Request Server to send",
|
||||
"4. Request Server to stop sending"
|
||||
};
|
||||
|
||||
static void BleMenuShowMenu(void);
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Transmit delay waits for busy bit to clear to allow
|
||||
// for a transmission to fully complete before proceeding.
|
||||
//
|
||||
//*****************************************************************************
|
||||
void
|
||||
uart_transmit_delay(uint32_t ui32Module)
|
||||
{
|
||||
//
|
||||
// Wait until busy bit clears to make sure UART fully transmitted last byte
|
||||
//
|
||||
//while ( am_hal_uart_flags_get(ui32Module) & AM_HAL_UART_FR_BUSY );
|
||||
}
|
||||
|
||||
|
||||
static bool isSelectionHome(void)
|
||||
{
|
||||
if (menuRxData[0] == 'h')
|
||||
{
|
||||
bleMenuCb.menuId = BLE_MENU_ID_MAIN;
|
||||
bleMenuCb.prevMenuId = BLE_MENU_ID_MAIN;
|
||||
bleMenuCb.gapMenuSelected = GAP_MENU_ID_NONE;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void showScanResults(void)
|
||||
{
|
||||
appDevInfo_t *devInfo;
|
||||
uint8_t num = AppScanGetNumResults();
|
||||
|
||||
am_menu_printf("--------------------Scan Results--------------------\r\n");
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
devInfo = AppScanGetResult(i);
|
||||
if (devInfo)
|
||||
{
|
||||
am_menu_printf("%d : %d %02x%02x%02x%02x%02x%02x \r\n", i, devInfo->addrType,
|
||||
devInfo->addr[0], devInfo->addr[1], devInfo->addr[2], devInfo->addr[3], devInfo->addr[4], devInfo->addr[5]);
|
||||
}
|
||||
}
|
||||
am_menu_printf("-----------------------------------------------------\r\n");
|
||||
}
|
||||
|
||||
static void handleGAPSlection(void)
|
||||
{
|
||||
eGapMenuId id;
|
||||
if (bleMenuCb.gapMenuSelected == GAP_MENU_ID_NONE)
|
||||
{
|
||||
id = (eGapMenuId)(menuRxData[0] - '0');
|
||||
}
|
||||
else
|
||||
{
|
||||
id = bleMenuCb.gapMenuSelected;
|
||||
}
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case GAP_MENU_ID_SCAN_START:
|
||||
am_menu_printf("scan start\r\n");
|
||||
AmdtpcScanStart();
|
||||
break;
|
||||
case GAP_MENU_ID_SCAN_STOP:
|
||||
AmdtpcScanStop();
|
||||
break;
|
||||
case GAP_MENU_ID_SCAN_RESULTS:
|
||||
showScanResults();
|
||||
break;
|
||||
case GAP_MENU_ID_CONNECT:
|
||||
if (bleMenuCb.gapMenuSelected == GAP_MENU_ID_NONE)
|
||||
{
|
||||
am_menu_printf("choose an idx from scan results to connect:\r\n");
|
||||
showScanResults();
|
||||
bleMenuCb.gapMenuSelected = GAP_MENU_ID_CONNECT;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t idx = menuRxData[0] - '0';
|
||||
bleMenuCb.gapMenuSelected = GAP_MENU_ID_NONE;
|
||||
AmdtpcConnOpen(idx);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void handleAMDTPSlection(void)
|
||||
{
|
||||
eAmdtpMenuId id;
|
||||
id = (eAmdtpMenuId)(menuRxData[0] - '0');
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case AMDTP_MENU_ID_SEND:
|
||||
am_menu_printf("send data to server\r\n");
|
||||
AmdtpcSendTestData();
|
||||
break;
|
||||
case AMDTP_MENU_ID_SEND_STOP:
|
||||
am_menu_printf("send data to server stop\r\n");
|
||||
AmdtpcSendTestDataStop();
|
||||
break;
|
||||
case AMDTP_MENU_ID_SERVER_SEND:
|
||||
am_menu_printf("request server to send\r\n");
|
||||
AmdtpcRequestServerSend();
|
||||
break;
|
||||
case AMDTP_MENU_ID_SERVER_SEND_STOP:
|
||||
am_menu_printf("request server to stop\r\n");
|
||||
AmdtpcRequestServerSendStop();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void handleSelection(void)
|
||||
{
|
||||
if (isSelectionHome())
|
||||
{
|
||||
BleMenuShowMenu();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (bleMenuCb.menuId)
|
||||
{
|
||||
case BLE_MENU_ID_MAIN:
|
||||
bleMenuCb.menuId = (eBleMenuId)(menuRxData[0] - '0');
|
||||
BleMenuShowMenu();
|
||||
break;
|
||||
case BLE_MENU_ID_GAP:
|
||||
handleGAPSlection();
|
||||
break;
|
||||
case BLE_MENU_ID_GATT:
|
||||
break;
|
||||
case BLE_MENU_ID_AMDTP:
|
||||
handleAMDTPSlection();
|
||||
break;
|
||||
default:
|
||||
am_util_debug_printf("handleSelection() unknown input\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BleMenuRx(void)
|
||||
{
|
||||
if (menuRxDataLen == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
menuRxData[menuRxDataLen] = '\0';
|
||||
am_util_debug_printf("BleMenuRx data = %s\n", menuRxData);
|
||||
|
||||
handleSelection();
|
||||
// clear UART rx buffer
|
||||
memset(menuRxData, 0, sizeof(menuRxData));
|
||||
menuRxDataLen = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
BLEMenuShowMainMenu(void)
|
||||
{
|
||||
am_menu_printf("--------------------BLE main menu--------------------\r\n");
|
||||
for (int i = 0; i < BLE_MENU_ID_MAX; i++)
|
||||
{
|
||||
am_menu_printf("%s\r\n", mainMenuContent[i]);
|
||||
uart_transmit_delay(AM_BSP_UART_PRINT_INST);
|
||||
}
|
||||
am_menu_printf("hint: use 'h' to do main menu\r\n");
|
||||
am_menu_printf("-----------------------------------------------------\r\n");
|
||||
}
|
||||
|
||||
static void
|
||||
BLEMenuShowGAPMenu(void)
|
||||
{
|
||||
for (int i = 0; i < GAP_MENU_ID_MAX; i++)
|
||||
{
|
||||
am_menu_printf("%s\r\n", gapMenuContent[i]);
|
||||
uart_transmit_delay(AM_BSP_UART_PRINT_INST);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
BLEMenuShowGATTMenu(void)
|
||||
{
|
||||
for (int i = 0; i < GATT_MENU_ID_MAX; i++)
|
||||
{
|
||||
am_menu_printf("%s\r\n", gattMenuContent[i]);
|
||||
uart_transmit_delay(AM_BSP_UART_PRINT_INST);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
BLEMenuShowAMDTPMenu(void)
|
||||
{
|
||||
for (int i = 0; i < AMDTP_MENU_ID_MAX; i++)
|
||||
{
|
||||
am_menu_printf("%s\r\n", amdtpMenuContent[i]);
|
||||
uart_transmit_delay(AM_BSP_UART_PRINT_INST);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
BleMenuShowMenu(void)
|
||||
{
|
||||
switch (bleMenuCb.menuId)
|
||||
{
|
||||
case BLE_MENU_ID_MAIN:
|
||||
BLEMenuShowMainMenu();
|
||||
break;
|
||||
case BLE_MENU_ID_GAP:
|
||||
BLEMenuShowGAPMenu();
|
||||
break;
|
||||
case BLE_MENU_ID_GATT:
|
||||
BLEMenuShowGATTMenu();
|
||||
break;
|
||||
case BLE_MENU_ID_AMDTP:
|
||||
BLEMenuShowAMDTPMenu();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BleMenuInit(void)
|
||||
{
|
||||
bleMenuCb.prevMenuId = BLE_MENU_ID_MAIN;
|
||||
bleMenuCb.menuId = BLE_MENU_ID_MAIN;
|
||||
bleMenuCb.gapMenuSelected = GAP_MENU_ID_NONE;
|
||||
bleMenuCb.gattMenuSelected = GATT_MENU_ID_NONE;
|
||||
BleMenuShowMenu();
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
// ****************************************************************************
|
||||
//
|
||||
// ble_menu.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Functions for BLE control menu.
|
||||
//!
|
||||
//! @{
|
||||
//
|
||||
// ****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifndef BLE_MENU_H
|
||||
#define BLE_MENU_H
|
||||
|
||||
#include "am_util.h"
|
||||
#include "am_util_stdio.h"
|
||||
#include "am_bsp.h"
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BLE_MENU_ID_MAIN = 0,
|
||||
BLE_MENU_ID_GAP,
|
||||
BLE_MENU_ID_GATT,
|
||||
BLE_MENU_ID_AMDTP,
|
||||
BLE_MENU_ID_MAX
|
||||
}eBleMenuId;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GAP_MENU_ID_NONE = 0,
|
||||
GAP_MENU_ID_SCAN_START,
|
||||
GAP_MENU_ID_SCAN_STOP,
|
||||
GAP_MENU_ID_SCAN_RESULTS,
|
||||
GAP_MENU_ID_CONNECT,
|
||||
GAP_MENU_ID_MAX
|
||||
}eGapMenuId;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GATT_MENU_ID_NONE = 0,
|
||||
GATT_MENU_ID_TBD,
|
||||
GATT_MENU_ID_MAX
|
||||
}eGattMenuId;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AMDTP_MENU_ID_NONE = 0,
|
||||
AMDTP_MENU_ID_SEND,
|
||||
AMDTP_MENU_ID_SEND_STOP,
|
||||
AMDTP_MENU_ID_SERVER_SEND,
|
||||
AMDTP_MENU_ID_SERVER_SEND_STOP,
|
||||
AMDTP_MENU_ID_MAX
|
||||
}eAmdtpMenuId;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
eBleMenuId prevMenuId;
|
||||
eBleMenuId menuId;
|
||||
eGapMenuId gapMenuSelected;
|
||||
eGattMenuId gattMenuSelected;
|
||||
}sBleMenuCb;
|
||||
|
||||
extern char menuRxData[20];
|
||||
extern uint32_t menuRxDataLen;
|
||||
|
||||
extern uint32_t am_menu_printf(const char *pcFmt, ...);
|
||||
|
||||
void
|
||||
BleMenuRx(void);
|
||||
|
||||
void
|
||||
BleMenuInit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // BLE_MENU_H
|
||||
@@ -0,0 +1,423 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file amdtp_common.c
|
||||
//!
|
||||
//! @brief This file provides the shared functions for the AMDTP service.
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "amdtp_common.h"
|
||||
#include "amota_crc32.h"
|
||||
#include "am_util.h"
|
||||
|
||||
extern void amdtps_timeout_timer_expired(void *data, UINT16 datalen);
|
||||
|
||||
void
|
||||
resetPkt(amdtpPacket_t *pkt)
|
||||
{
|
||||
pkt->offset = 0;
|
||||
pkt->header.pktType = AMDTP_PKT_TYPE_UNKNOWN;
|
||||
pkt->len = 0;
|
||||
}
|
||||
|
||||
eAmdtpStatus_t
|
||||
AmdtpReceivePkt(amdtpCb_t *amdtpCb, amdtpPacket_t *pkt, uint16_t len, uint8_t *pValue)
|
||||
{
|
||||
uint8_t dataIdx = 0;
|
||||
uint32_t calDataCrc = 0;
|
||||
uint16_t header = 0;
|
||||
|
||||
if (pkt->offset == 0 && len < AMDTP_PREFIX_SIZE_IN_PKT)
|
||||
{
|
||||
AMDTP_TRC("Invalid packet!!!\n");
|
||||
AmdtpSendReply(amdtpCb, AMDTP_STATUS_INVALID_PKT_LENGTH, NULL, 0);
|
||||
return AMDTP_STATUS_INVALID_PKT_LENGTH;
|
||||
}
|
||||
|
||||
// new packet
|
||||
if (pkt->offset == 0)
|
||||
{
|
||||
BT_UNPACK_LE_2_BYTE(&pkt->len, pValue);
|
||||
BT_UNPACK_LE_2_BYTE(&header, &pValue[2]);
|
||||
pkt->header.pktType = (header & PACKET_TYPE_BIT_MASK) >> PACKET_TYPE_BIT_OFFSET;
|
||||
pkt->header.pktSn = (header & PACKET_SN_BIT_MASK) >> PACKET_SN_BIT_OFFSET;
|
||||
pkt->header.encrypted = (header & PACKET_ENCRYPTION_BIT_MASK) >> PACKET_ENCRYPTION_BIT_OFFSET;
|
||||
pkt->header.ackEnabled = (header & PACKET_ACK_BIT_MASK) >> PACKET_ACK_BIT_OFFSET;
|
||||
dataIdx = AMDTP_PREFIX_SIZE_IN_PKT;
|
||||
if (pkt->header.pktType == AMDTP_PKT_TYPE_DATA)
|
||||
{
|
||||
amdtpCb->rxState = AMDTP_STATE_GETTING_DATA;
|
||||
}
|
||||
#ifdef AMDTP_DEBUG_ON
|
||||
AMDTP_TRC("pkt len = 0x%x\n", pkt->len);
|
||||
AMDTP_TRC("pkt header = 0x%x\n", header);
|
||||
#endif
|
||||
AMDTP_TRC("type = %d, sn = %d\n", pkt->header.pktType, pkt->header.pktSn);
|
||||
AMDTP_TRC("enc = %d, ackEnabled = %d\n", pkt->header.encrypted, pkt->header.ackEnabled);
|
||||
}
|
||||
|
||||
// make sure we have enough space for new data
|
||||
if (pkt->offset + len - dataIdx > AMDTP_PACKET_SIZE)
|
||||
{
|
||||
AMDTP_TRC("not enough buffer size!!!\n");
|
||||
if (pkt->header.pktType == AMDTP_PKT_TYPE_DATA)
|
||||
{
|
||||
amdtpCb->rxState = AMDTP_STATE_RX_IDLE;
|
||||
}
|
||||
|
||||
// reset pkt
|
||||
resetPkt(pkt);
|
||||
AmdtpSendReply(amdtpCb, AMDTP_STATUS_INSUFFICIENT_BUFFER, NULL, 0);
|
||||
return AMDTP_STATUS_INSUFFICIENT_BUFFER;
|
||||
}
|
||||
|
||||
// copy new data into buffer and also save crc into it if it's the last frame in a packet
|
||||
// 4 bytes crc is included in pkt length
|
||||
memcpy(pkt->data + pkt->offset, pValue + dataIdx, len - dataIdx);
|
||||
pkt->offset += (len - dataIdx);
|
||||
|
||||
// whole packet received
|
||||
if (pkt->offset >= pkt->len)
|
||||
{
|
||||
uint32_t peerCrc = 0;
|
||||
//
|
||||
// check CRC
|
||||
//
|
||||
BT_UNPACK_LE_4_BYTE(&peerCrc, pkt->data + pkt->len - AMDTP_CRC_SIZE_IN_PKT);
|
||||
calDataCrc = AmotaCrc32(0xFFFFFFFFU, pkt->len - AMDTP_CRC_SIZE_IN_PKT, pkt->data);
|
||||
#ifdef AMDTP_DEBUG_ON
|
||||
AMDTP_TRC("calDataCrc = 0x%x\n", calDataCrc);
|
||||
AMDTP_TRC("peerCrc = 0x%x\n", peerCrc);
|
||||
AMDTP_TRC("len: %d\n", pkt->len);
|
||||
#endif
|
||||
|
||||
if (peerCrc != calDataCrc)
|
||||
{
|
||||
AMDTP_TRC("crc error\n");
|
||||
|
||||
if (pkt->header.pktType == AMDTP_PKT_TYPE_DATA)
|
||||
{
|
||||
amdtpCb->rxState = AMDTP_STATE_RX_IDLE;
|
||||
}
|
||||
// reset pkt
|
||||
resetPkt(pkt);
|
||||
|
||||
AmdtpSendReply(amdtpCb, AMDTP_STATUS_CRC_ERROR, NULL, 0);
|
||||
|
||||
return AMDTP_STATUS_CRC_ERROR;
|
||||
}
|
||||
|
||||
return AMDTP_STATUS_RECEIVE_DONE;
|
||||
}
|
||||
|
||||
return AMDTP_STATUS_RECEIVE_CONTINUE;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// AMDTP packet handler
|
||||
//
|
||||
//*****************************************************************************
|
||||
void
|
||||
AmdtpPacketHandler(amdtpCb_t *amdtpCb, eAmdtpPktType_t type, uint16_t len, uint8_t *buf)
|
||||
{
|
||||
#ifdef AMDTP_DEBUG_ON
|
||||
AMDTP_TRC("received packet type = %d, len = %d\n", type, len);
|
||||
#endif
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case AMDTP_PKT_TYPE_DATA:
|
||||
//
|
||||
// data package recevied
|
||||
//
|
||||
// record packet serial number
|
||||
amdtpCb->lastRxPktSn = amdtpCb->rxPkt.header.pktSn;
|
||||
AmdtpSendReply(amdtpCb, AMDTP_STATUS_SUCCESS, NULL, 0);
|
||||
if (amdtpCb->recvCback)
|
||||
{
|
||||
amdtpCb->recvCback(buf, len);
|
||||
}
|
||||
|
||||
amdtpCb->rxState = AMDTP_STATE_RX_IDLE;
|
||||
resetPkt(&amdtpCb->rxPkt);
|
||||
break;
|
||||
|
||||
case AMDTP_PKT_TYPE_ACK:
|
||||
{
|
||||
eAmdtpStatus_t status = (eAmdtpStatus_t)buf[0];
|
||||
// stop tx timeout timer
|
||||
if (BT_TIMER_HANDLE_INIT_VAL != amdtpCb->timeoutTimer)
|
||||
{
|
||||
#ifdef AMDTP_DEBUG_ON
|
||||
API_RESULT retval = API_SUCCESS;
|
||||
retval = BT_stop_timer (amdtpCb->timeoutTimer);
|
||||
AMDTP_TRC (
|
||||
"[AMDTP]: Stopping Timer with result 0x%04X, timer handle %p\n",
|
||||
retval, amdtpCb->timeoutTimer);
|
||||
#else
|
||||
BT_stop_timer (amdtpCb->timeoutTimer);
|
||||
#endif
|
||||
amdtpCb->timeoutTimer = BT_TIMER_HANDLE_INIT_VAL;
|
||||
}
|
||||
|
||||
if (amdtpCb->txState != AMDTP_STATE_TX_IDLE)
|
||||
{
|
||||
#ifdef AMDTP_DEBUG_ON
|
||||
AMDTP_TRC("set txState back to idle, state = %d\n", amdtpCb->txState);
|
||||
#endif
|
||||
amdtpCb->txState = AMDTP_STATE_TX_IDLE;
|
||||
}
|
||||
|
||||
if (status == AMDTP_STATUS_CRC_ERROR || status == AMDTP_STATUS_RESEND_REPLY)
|
||||
{
|
||||
// resend packet
|
||||
AmdtpSendPacketHandler(amdtpCb);
|
||||
}
|
||||
else
|
||||
{
|
||||
// increase packet serial number if send successfully
|
||||
if (status == AMDTP_STATUS_SUCCESS)
|
||||
{
|
||||
amdtpCb->txPktSn++;
|
||||
if (amdtpCb->txPktSn == 16)
|
||||
{
|
||||
amdtpCb->txPktSn = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// packet transfer successful or other error
|
||||
// reset packet
|
||||
resetPkt(&amdtpCb->txPkt);
|
||||
|
||||
// notify application layer
|
||||
if (amdtpCb->transCback)
|
||||
{
|
||||
amdtpCb->transCback(status);
|
||||
}
|
||||
}
|
||||
resetPkt(&amdtpCb->ackPkt);
|
||||
}
|
||||
break;
|
||||
|
||||
case AMDTP_PKT_TYPE_CONTROL:
|
||||
{
|
||||
eAmdtpControl_t control = (eAmdtpControl_t)buf[0];
|
||||
uint8_t resendPktSn = buf[1];
|
||||
if (control == AMDTP_CONTROL_RESEND_REQ)
|
||||
{
|
||||
AMDTP_TRC("resendPktSn = %d, lastRxPktSn = %d\n", resendPktSn, amdtpCb->lastRxPktSn);
|
||||
amdtpCb->rxState = AMDTP_STATE_RX_IDLE;
|
||||
resetPkt(&amdtpCb->rxPkt);
|
||||
if (resendPktSn > amdtpCb->lastRxPktSn)
|
||||
{
|
||||
AmdtpSendReply(amdtpCb, AMDTP_STATUS_RESEND_REPLY, NULL, 0);
|
||||
}
|
||||
else if (resendPktSn == amdtpCb->lastRxPktSn)
|
||||
{
|
||||
AmdtpSendReply(amdtpCb, AMDTP_STATUS_SUCCESS, NULL, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
AMDTP_ERR("resendPktSn = %d, lastRxPktSn = %d\n", resendPktSn, amdtpCb->lastRxPktSn);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AMDTP_TRC("unexpected contrl = %d\n", control);
|
||||
}
|
||||
resetPkt(&amdtpCb->ackPkt);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AmdtpBuildPkt(amdtpCb_t *amdtpCb, eAmdtpPktType_t type, BOOLEAN encrypted, BOOLEAN enableACK, uint8_t *buf, uint16_t len)
|
||||
{
|
||||
uint16_t header = 0;
|
||||
uint32_t calDataCrc;
|
||||
amdtpPacket_t *pkt;
|
||||
|
||||
if (type == AMDTP_PKT_TYPE_DATA)
|
||||
{
|
||||
pkt = &amdtpCb->txPkt;
|
||||
header = amdtpCb->txPktSn << PACKET_SN_BIT_OFFSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
pkt = &amdtpCb->ackPkt;
|
||||
}
|
||||
|
||||
//
|
||||
// Prepare header frame to be sent first
|
||||
//
|
||||
// length
|
||||
pkt->len = len + AMDTP_PREFIX_SIZE_IN_PKT + AMDTP_CRC_SIZE_IN_PKT;
|
||||
pkt->data[0] = (len + AMDTP_CRC_SIZE_IN_PKT) & 0xff;
|
||||
pkt->data[1] = ((len + AMDTP_CRC_SIZE_IN_PKT) >> 8) & 0xff;
|
||||
|
||||
// header
|
||||
header = header | (type << PACKET_TYPE_BIT_OFFSET);
|
||||
if (encrypted)
|
||||
{
|
||||
header = header | (1 << PACKET_ENCRYPTION_BIT_OFFSET);
|
||||
}
|
||||
if (enableACK)
|
||||
{
|
||||
header = header | (1 << PACKET_ACK_BIT_OFFSET);
|
||||
}
|
||||
pkt->data[2] = (header & 0xff);
|
||||
pkt->data[3] = (header >> 8);
|
||||
|
||||
// copy data
|
||||
memcpy(&(pkt->data[AMDTP_PREFIX_SIZE_IN_PKT]), buf, len);
|
||||
calDataCrc = AmotaCrc32(0xFFFFFFFFU, len, buf);
|
||||
|
||||
// add checksum
|
||||
pkt->data[AMDTP_PREFIX_SIZE_IN_PKT + len] = (calDataCrc & 0xff);
|
||||
pkt->data[AMDTP_PREFIX_SIZE_IN_PKT + len + 1] = ((calDataCrc >> 8) & 0xff);
|
||||
pkt->data[AMDTP_PREFIX_SIZE_IN_PKT + len + 2] = ((calDataCrc >> 16) & 0xff);
|
||||
pkt->data[AMDTP_PREFIX_SIZE_IN_PKT + len + 3] = ((calDataCrc >> 24) & 0xff);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Send Reply to Sender
|
||||
//
|
||||
//*****************************************************************************
|
||||
void
|
||||
AmdtpSendReply(amdtpCb_t *amdtpCb, eAmdtpStatus_t status, uint8_t *data, uint16_t len)
|
||||
{
|
||||
uint8_t buf[ATT_DEFAULT_PAYLOAD_LEN] = {0};
|
||||
eAmdtpStatus_t st;
|
||||
|
||||
buf[0] = status;
|
||||
if (len > 0)
|
||||
{
|
||||
memcpy(buf + 1, data, len);
|
||||
}
|
||||
st = amdtpCb->ack_sender_func(AMDTP_PKT_TYPE_ACK, false, false, buf, len + 1);
|
||||
if (st != AMDTP_STATUS_SUCCESS)
|
||||
{
|
||||
AMDTP_ERR("AmdtpSendReply status = %d\n", status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Send control message to Receiver
|
||||
//
|
||||
//*****************************************************************************
|
||||
void
|
||||
AmdtpSendControl(amdtpCb_t *amdtpCb, eAmdtpControl_t control, uint8_t *data, uint16_t len)
|
||||
{
|
||||
uint8_t buf[ATT_DEFAULT_PAYLOAD_LEN] = {0};
|
||||
eAmdtpStatus_t st;
|
||||
|
||||
buf[0] = control;
|
||||
if (len > 0)
|
||||
{
|
||||
memcpy(buf + 1, data, len);
|
||||
}
|
||||
st = amdtpCb->ack_sender_func(AMDTP_PKT_TYPE_CONTROL, false, false, buf, len + 1);
|
||||
if (st != AMDTP_STATUS_SUCCESS)
|
||||
{
|
||||
AMDTP_ERR("AmdtpSendControl status = %d\n", st);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AmdtpSendPacketHandler(amdtpCb_t *amdtpCb)
|
||||
{
|
||||
uint16_t transferSize = 0;
|
||||
uint16_t remainingBytes = 0;
|
||||
amdtpPacket_t *txPkt = &amdtpCb->txPkt;
|
||||
API_RESULT retval = API_SUCCESS;
|
||||
|
||||
if ( amdtpCb->txState == AMDTP_STATE_TX_IDLE )
|
||||
{
|
||||
txPkt->offset = 0;
|
||||
amdtpCb->txState = AMDTP_STATE_SENDING;
|
||||
}
|
||||
|
||||
if ( txPkt->offset >= txPkt->len )
|
||||
{
|
||||
// done sent packet
|
||||
amdtpCb->txState = AMDTP_STATE_WAITING_ACK;
|
||||
// start tx timeout timer
|
||||
if (BT_TIMER_HANDLE_INIT_VAL != amdtpCb->timeoutTimer)
|
||||
{
|
||||
retval = BT_stop_timer (amdtpCb->timeoutTimer);
|
||||
AMDTP_TRC (
|
||||
"[AMDTP]: Stopping Timer with result 0x%04X, timer handle %p\n",
|
||||
retval, amdtpCb->timeoutTimer);
|
||||
amdtpCb->timeoutTimer = BT_TIMER_HANDLE_INIT_VAL;
|
||||
}
|
||||
|
||||
retval = BT_start_timer
|
||||
(
|
||||
&amdtpCb->timeoutTimer,
|
||||
amdtpCb->txTimeout,
|
||||
amdtps_timeout_timer_expired,
|
||||
NULL,
|
||||
0
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
remainingBytes = txPkt->len - txPkt->offset;
|
||||
transferSize = ((amdtpCb->attMtuSize - 3) > remainingBytes)
|
||||
? remainingBytes
|
||||
: (amdtpCb->attMtuSize - 3);
|
||||
// send packet
|
||||
amdtpCb->data_sender_func(&txPkt->data[txPkt->offset], transferSize);
|
||||
txPkt->offset += transferSize;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file amdtp_common.h
|
||||
//!
|
||||
//! @brief This file provides the shared functions for the AMDTP service.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifndef AMDTP_COMMON_H
|
||||
#define AMDTP_COMMON_H
|
||||
|
||||
#include "BT_api.h"
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Macro definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
#define BT_MODULE_BIT_MASK_AMDTPS 0x00020000
|
||||
#define BT_MODULE_ID_AMDTPS (BT_MODULE_PAGE_2 | BT_MODULE_BIT_MASK_AMDTPS)
|
||||
#define AMDTP_ERR(...) BT_debug_error(BT_MODULE_ID_AMDTPS, __VA_ARGS__)
|
||||
#define AMDTP_TRC(...) BT_debug_trace(BT_MODULE_ID_AMDTPS, __VA_ARGS__)
|
||||
|
||||
#define AMDTP_MAX_PAYLOAD_SIZE 2048 //512
|
||||
#define AMDTP_PACKET_SIZE (AMDTP_MAX_PAYLOAD_SIZE + AMDTP_PREFIX_SIZE_IN_PKT + AMDTP_CRC_SIZE_IN_PKT) // Bytes
|
||||
#define AMDTP_LENGTH_SIZE_IN_PKT 2
|
||||
#define AMDTP_HEADER_SIZE_IN_PKT 2
|
||||
#define AMDTP_CRC_SIZE_IN_PKT 4
|
||||
#define AMDTP_PREFIX_SIZE_IN_PKT AMDTP_LENGTH_SIZE_IN_PKT + AMDTP_HEADER_SIZE_IN_PKT
|
||||
|
||||
#define PACKET_TYPE_BIT_OFFSET 12
|
||||
#define PACKET_TYPE_BIT_MASK (0xf << PACKET_TYPE_BIT_OFFSET)
|
||||
#define PACKET_SN_BIT_OFFSET 8
|
||||
#define PACKET_SN_BIT_MASK (0xf << PACKET_SN_BIT_OFFSET)
|
||||
#define PACKET_ENCRYPTION_BIT_OFFSET 7
|
||||
#define PACKET_ENCRYPTION_BIT_MASK (0x1 << PACKET_ENCRYPTION_BIT_OFFSET)
|
||||
#define PACKET_ACK_BIT_OFFSET 6
|
||||
#define PACKET_ACK_BIT_MASK (0x1 << PACKET_ACK_BIT_OFFSET)
|
||||
|
||||
#define TX_TIMEOUT_DEFAULT 1 // 1 second
|
||||
#define ATT_DEFAULT_PAYLOAD_LEN 20
|
||||
|
||||
//
|
||||
// amdtp states
|
||||
//
|
||||
typedef enum eAmdtpState
|
||||
{
|
||||
AMDTP_STATE_INIT,
|
||||
AMDTP_STATE_TX_IDLE,
|
||||
AMDTP_STATE_RX_IDLE,
|
||||
AMDTP_STATE_SENDING,
|
||||
AMDTP_STATE_GETTING_DATA,
|
||||
AMDTP_STATE_WAITING_ACK,
|
||||
AMDTP_STATE_MAX
|
||||
}eAmdtpState_t;
|
||||
|
||||
//
|
||||
// amdtp packet type
|
||||
//
|
||||
typedef enum eAmdtpPktType
|
||||
{
|
||||
AMDTP_PKT_TYPE_UNKNOWN,
|
||||
AMDTP_PKT_TYPE_DATA,
|
||||
AMDTP_PKT_TYPE_ACK,
|
||||
AMDTP_PKT_TYPE_CONTROL,
|
||||
AMDTP_PKT_TYPE_MAX
|
||||
}eAmdtpPktType_t;
|
||||
|
||||
typedef enum eAmdtpControl
|
||||
{
|
||||
AMDTP_CONTROL_RESEND_REQ,
|
||||
AMDTP_CONTROL_MAX
|
||||
}eAmdtpControl_t;
|
||||
|
||||
//
|
||||
// amdtp status
|
||||
//
|
||||
typedef enum eAmdtpStatus
|
||||
{
|
||||
AMDTP_STATUS_SUCCESS,
|
||||
AMDTP_STATUS_CRC_ERROR,
|
||||
AMDTP_STATUS_INVALID_METADATA_INFO,
|
||||
AMDTP_STATUS_INVALID_PKT_LENGTH,
|
||||
AMDTP_STATUS_INSUFFICIENT_BUFFER,
|
||||
AMDTP_STATUS_UNKNOWN_ERROR,
|
||||
AMDTP_STATUS_BUSY,
|
||||
AMDTP_STATUS_TX_NOT_READY, // no connection or tx busy
|
||||
AMDTP_STATUS_RESEND_REPLY,
|
||||
AMDTP_STATUS_RECEIVE_CONTINUE,
|
||||
AMDTP_STATUS_RECEIVE_DONE,
|
||||
AMDTP_STATUS_MAX
|
||||
}eAmdtpStatus_t;
|
||||
|
||||
//
|
||||
// packet prefix structure
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
uint8_t pktType : 4;
|
||||
uint8_t pktSn : 4;
|
||||
uint8_t encrypted : 1;
|
||||
uint32_t ackEnabled : 1;
|
||||
uint32_t reserved : 6; // Reserved for future usage
|
||||
}
|
||||
amdtpPktHeader_t;
|
||||
|
||||
//
|
||||
// packet
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
uint16_t offset;
|
||||
uint16_t len; // data plus checksum
|
||||
amdtpPktHeader_t header;
|
||||
uint8_t *data;
|
||||
}
|
||||
amdtpPacket_t;
|
||||
|
||||
/*! Application data reception callback */
|
||||
typedef void (*amdtpRecvCback_t)(uint8_t *buf, uint16_t len);
|
||||
|
||||
/*! Application data transmission result callback */
|
||||
typedef void (*amdtpTransCback_t)(eAmdtpStatus_t status);
|
||||
|
||||
typedef void (*amdtp_reply_func_t)(eAmdtpStatus_t status, uint8_t *data, uint16_t len);
|
||||
|
||||
typedef void (*amdtp_packet_handler_func_t)(eAmdtpPktType_t type, uint16_t len, uint8_t *buf);
|
||||
|
||||
typedef eAmdtpStatus_t (*amdtp_ack_sender_func_t)(eAmdtpPktType_t type, BOOLEAN encrypted, BOOLEAN enableACK, uint8_t *buf, uint16_t len);
|
||||
|
||||
typedef void (*amdtp_data_sender_func_t)(uint8_t *buf, uint16_t len);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
eAmdtpState_t txState;
|
||||
eAmdtpState_t rxState;
|
||||
amdtpPacket_t rxPkt;
|
||||
amdtpPacket_t txPkt;
|
||||
amdtpPacket_t ackPkt;
|
||||
uint8_t txPktSn; // data packet serial number for Tx
|
||||
uint8_t lastRxPktSn; // last received data packet serial number
|
||||
uint16_t attMtuSize;
|
||||
BT_timer_handle timeoutTimer; // timeout timer after DTP update done
|
||||
uint8_t txTimeout; // timeout in second unit
|
||||
amdtpRecvCback_t recvCback; // application callback for data reception
|
||||
amdtpTransCback_t transCback; // application callback for tx complete status
|
||||
amdtp_data_sender_func_t data_sender_func;
|
||||
amdtp_ack_sender_func_t ack_sender_func;
|
||||
}
|
||||
amdtpCb_t;
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// function definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
void
|
||||
AmdtpBuildPkt(amdtpCb_t *amdtpCb, eAmdtpPktType_t type, BOOLEAN encrypted, BOOLEAN enableACK, uint8_t *buf, uint16_t len);
|
||||
|
||||
eAmdtpStatus_t
|
||||
AmdtpReceivePkt(amdtpCb_t *amdtpCb, amdtpPacket_t *pkt, uint16_t len, uint8_t *pValue);
|
||||
|
||||
void
|
||||
AmdtpSendReply(amdtpCb_t *amdtpCb, eAmdtpStatus_t status, uint8_t *data, uint16_t len);
|
||||
|
||||
void
|
||||
AmdtpSendControl(amdtpCb_t *amdtpCb, eAmdtpControl_t control, uint8_t *data, uint16_t len);
|
||||
|
||||
void
|
||||
AmdtpSendPacketHandler(amdtpCb_t *amdtpCb);
|
||||
|
||||
void
|
||||
AmdtpPacketHandler(amdtpCb_t *amdtpCb, eAmdtpPktType_t type, uint16_t len, uint8_t *buf);
|
||||
|
||||
void
|
||||
resetPkt(amdtpPacket_t *pkt);
|
||||
|
||||
#endif // AMDTP_COMMON_H
|
||||
@@ -0,0 +1,554 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// appl_amdtps.c
|
||||
//! @file
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
/**
|
||||
* \file appl_amdtps.c
|
||||
*
|
||||
* This file contains the AMDTP application.
|
||||
* Sample applications detailed below:
|
||||
* a. The Sensor, as defined by the Sepcification plays the GAP Peripheral
|
||||
* role.
|
||||
* b. The Sensor application has following sevice records:
|
||||
* - GAP
|
||||
* - GATT
|
||||
* - Battery
|
||||
* - Device Information and
|
||||
* - AMDTP
|
||||
* [NOTE]: Please see gatt_db.c for more details of the record.
|
||||
* c. appl_manage_transfer routine takes care of handling peer
|
||||
* configuration. This handling would be needed:
|
||||
* - When Peer Configures Measurement Transfer by writting to the
|
||||
* Characteristic Client Configuration of AMOTA Tx.
|
||||
* - Subsequent reconnection with bonded device that had already
|
||||
* configured the device for transfer. Please note it is mandatory
|
||||
* for GATT Servers to remember the configurations of bonded GATT
|
||||
* clients.
|
||||
* In order to ensure the above mentioned configurations are correctly
|
||||
* handled, the routine, appl_manage_transfer, is therefore called from:
|
||||
* - gatt_db_amotas_handler and
|
||||
* - appl_amdtps_connect
|
||||
* [NOTE]: If link does not have the needed secruity for the service,
|
||||
* transfer will not be initiated.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* --------------------------------------------- Header File Inclusion */
|
||||
#include "appl.h"
|
||||
|
||||
#include "am_mcu_apollo.h"
|
||||
#include "am_bsp.h"
|
||||
#include "am_util.h"
|
||||
|
||||
#ifdef AMDTPS
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Global variables
|
||||
//
|
||||
//*****************************************************************************
|
||||
uint8_t rxPktBuf[AMDTP_PACKET_SIZE];
|
||||
uint8_t txPktBuf[AMDTP_PACKET_SIZE];
|
||||
uint8_t ackPktBuf[20];
|
||||
|
||||
#if defined(AMDTPS_RXONLY) || defined(AMDTPS_RX2TX)
|
||||
static int totalLen = 0;
|
||||
#endif
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Macro definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
/* Control block */
|
||||
static struct
|
||||
{
|
||||
BOOLEAN txReady; // TRUE if ready to send notifications
|
||||
AmdtpsCfg_t cfg; // configurable parameters
|
||||
amdtpCb_t core;
|
||||
}
|
||||
amdtpsCb;
|
||||
|
||||
/* --------------------------------------------- Static Global Variables */
|
||||
static GATT_DB_HANDLE appl_amdtps_handle;
|
||||
static ATT_ATTR_HANDLE appl_tx_hndl;
|
||||
static ATT_ATTR_HANDLE appl_ack_hndl;
|
||||
|
||||
/* --------------------------------------------- Functions */
|
||||
|
||||
static bool sendDataContinuously = false;
|
||||
static uint32_t counter = 0;
|
||||
|
||||
static void AmdtpsSendTestData(void)
|
||||
{
|
||||
uint8_t data[236] = {0};
|
||||
eAmdtpStatus_t status;
|
||||
|
||||
sendDataContinuously = true;
|
||||
*((uint32_t*)&(data[0])) = counter;
|
||||
|
||||
status = AmdtpsSendPacket(AMDTP_PKT_TYPE_DATA, false, true, data, sizeof(data));
|
||||
if (status != AMDTP_STATUS_SUCCESS)
|
||||
{
|
||||
AMDTP_TRC("[AMDTP]: AmdtpsSendTestData() failed, status = %d\n", status);
|
||||
}
|
||||
else
|
||||
{
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
void amdtpsDtpRecvCback(uint8_t * buf, uint16_t len)
|
||||
{
|
||||
if (buf[0] == 1)
|
||||
{
|
||||
AMDTP_TRC("[AMDTP]: send test data\n");
|
||||
AmdtpsSendTestData();
|
||||
}
|
||||
else if (buf[0] == 2)
|
||||
{
|
||||
AMDTP_TRC("[AMDTP]: send test data stop\n");
|
||||
sendDataContinuously = false;
|
||||
}
|
||||
}
|
||||
|
||||
void amdtpsDtpTransCback(eAmdtpStatus_t status)
|
||||
{
|
||||
#ifdef AMDTP_DEBUG_ON
|
||||
AMDTP_TRC("[AMDTP]: amdtpDtpTransCback =%d\n", status);
|
||||
#endif
|
||||
if (status == AMDTP_STATUS_SUCCESS && sendDataContinuously)
|
||||
{
|
||||
AmdtpsSendTestData();
|
||||
}
|
||||
}
|
||||
|
||||
void appl_amdtps_init(void)
|
||||
{
|
||||
appl_amdtp_server_reinitialize();
|
||||
}
|
||||
|
||||
void appl_amdtps_connect(APPL_HANDLE * appl_handle)
|
||||
{
|
||||
ATT_VALUE value;
|
||||
UINT16 cli_cnfg;
|
||||
|
||||
cli_cnfg = 0;
|
||||
|
||||
appl_amdtps_handle.device_id = APPL_GET_DEVICE_HANDLE((*appl_handle));
|
||||
appl_amdtps_handle.char_id = GATT_CHAR_AMDTP_TX;
|
||||
appl_amdtps_handle.service_id = GATT_SER_AMDTP_INST;
|
||||
|
||||
BT_gatt_db_get_char_val_hndl(&appl_amdtps_handle, &appl_tx_hndl);
|
||||
BT_gatt_db_get_char_cli_cnfg(&appl_amdtps_handle, &value);
|
||||
BT_UNPACK_LE_2_BYTE (&cli_cnfg, value.val);
|
||||
|
||||
|
||||
appl_amdtps_handle.char_id = GATT_CHAR_AMDTP_ACK;
|
||||
BT_gatt_db_get_char_val_hndl(&appl_amdtps_handle, &appl_ack_hndl);
|
||||
BT_gatt_db_get_char_cli_cnfg(&appl_amdtps_handle, &value);
|
||||
BT_UNPACK_LE_2_BYTE (&cli_cnfg, value.val);
|
||||
|
||||
AMDTP_TRC (
|
||||
"[APPL]: Fetched Client Configuration (0x%04X) for Device (0x%02X)\n",
|
||||
cli_cnfg, APPL_GET_DEVICE_HANDLE((*appl_handle)));
|
||||
appl_manage_trasnfer(appl_amdtps_handle, cli_cnfg);
|
||||
}
|
||||
|
||||
void appl_manage_trasnfer(GATT_DB_HANDLE handle, UINT16 config)
|
||||
{
|
||||
APPL_HANDLE appl_handle;
|
||||
API_RESULT retval;
|
||||
|
||||
UCHAR security, ekey_size;
|
||||
|
||||
AMDTP_TRC("[AMDTP]: appl_manage_trasnfer+ \n");
|
||||
/* Get required security for service */
|
||||
/* Get required security level */
|
||||
BT_gatt_db_get_service_security (&handle, &security);
|
||||
/* Get required encryption key size */
|
||||
BT_gatt_db_get_service_enc_key_size (&handle, &ekey_size);
|
||||
|
||||
/* Verify if security requirements are available with the link */
|
||||
retval = appl_smp_assert_security
|
||||
(
|
||||
&handle.device_id,
|
||||
security,
|
||||
ekey_size
|
||||
);
|
||||
|
||||
/* Security requirements satisfied? */
|
||||
if (API_SUCCESS != retval)
|
||||
{
|
||||
/* No. Return */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Security requirements satisfied, go ahead with data transfer */
|
||||
|
||||
retval = appl_get_handle_from_device_handle(handle.device_id, &appl_handle);
|
||||
|
||||
if (API_SUCCESS != retval)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (GATT_CLI_CNFG_NOTIFICATION == config)
|
||||
{
|
||||
amdtpsCb.txReady = true;
|
||||
amdtpsCb.core.txState = AMDTP_STATE_TX_IDLE;
|
||||
AMDTP_TRC("[AMDTP]: notify registered \n");
|
||||
#if defined(AMDTPS_TXTEST)
|
||||
counter = 0;
|
||||
AmdtpsSendTestData(); //fixme
|
||||
#endif
|
||||
}
|
||||
else if (GATT_CLI_CNFG_DEFAULT == config)
|
||||
{
|
||||
amdtpsCb.txReady = false;
|
||||
AMDTP_TRC("[AMDTP]: notify unregistered \n");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Incorrect Configuration */
|
||||
}
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Send Notification to Client
|
||||
//
|
||||
//*****************************************************************************
|
||||
static void amdtpsSendData(uint8_t *buf, uint16_t len)
|
||||
{
|
||||
ATT_HANDLE_VALUE_PAIR hndl_val_param;
|
||||
API_RESULT retval;
|
||||
APPL_HANDLE appl_handle;
|
||||
|
||||
#ifdef AMDTP_DEBUG_ON
|
||||
AMDTP_TRC("Sending Tx On Handle 0x%04X\n", appl_tx_hndl);
|
||||
#endif
|
||||
|
||||
appl_get_handle_from_device_handle (appl_amdtps_handle.device_id, &appl_handle);
|
||||
hndl_val_param.handle = appl_tx_hndl;
|
||||
hndl_val_param.value.val = buf;
|
||||
hndl_val_param.value.len = len;
|
||||
|
||||
retval = BT_att_send_hndl_val_ntf
|
||||
(
|
||||
&APPL_GET_ATT_INSTANCE(appl_handle),
|
||||
&hndl_val_param
|
||||
);
|
||||
|
||||
if (API_SUCCESS != retval)
|
||||
{
|
||||
AMDTP_ERR( "[** ERR **]: Failed to send, reason 0x%04X", retval);
|
||||
}
|
||||
}
|
||||
|
||||
static eAmdtpStatus_t
|
||||
amdtpsSendAck(eAmdtpPktType_t type, BOOLEAN encrypted, BOOLEAN enableACK, uint8_t *buf, uint16_t len)
|
||||
{
|
||||
ATT_HANDLE_VALUE_PAIR hndl_val_param;
|
||||
API_RESULT retval;
|
||||
APPL_HANDLE appl_handle;
|
||||
|
||||
AmdtpBuildPkt(&amdtpsCb.core, type, encrypted, enableACK, buf, len);
|
||||
|
||||
#ifdef AMDTP_DEBUG_ON
|
||||
AMDTP_TRC("Sending Ack On Handle 0x%04X\n", appl_ack_hndl);
|
||||
#endif
|
||||
/* send notification */
|
||||
appl_get_handle_from_device_handle (appl_amdtps_handle.device_id, &appl_handle);
|
||||
hndl_val_param.handle = appl_ack_hndl;
|
||||
hndl_val_param.value.val = amdtpsCb.core.ackPkt.data;
|
||||
hndl_val_param.value.len = amdtpsCb.core.ackPkt.len;
|
||||
|
||||
retval = BT_att_send_hndl_val_ntf
|
||||
(
|
||||
&APPL_GET_ATT_INSTANCE(appl_handle),
|
||||
&hndl_val_param
|
||||
);
|
||||
|
||||
if (API_SUCCESS != retval)
|
||||
{
|
||||
AMDTP_ERR( "[** ERR **]: Failed to send measurement, reason 0x%04X", retval);
|
||||
return AMDTP_STATUS_TX_NOT_READY;
|
||||
}
|
||||
|
||||
return AMDTP_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Timer Expiration handler
|
||||
//
|
||||
//*****************************************************************************
|
||||
void amdtps_timeout_timer_expired(void *data, UINT16 datalen)
|
||||
{
|
||||
API_RESULT retval = API_SUCCESS;
|
||||
uint8_t ack[1];
|
||||
ack[0] = amdtpsCb.core.txPktSn;
|
||||
AMDTP_TRC("amdtps tx timeout, txPktSn = %d\n", amdtpsCb.core.txPktSn);
|
||||
AmdtpSendControl(&amdtpsCb.core, AMDTP_CONTROL_RESEND_REQ, ack, 1);
|
||||
// fire a timer for receiving an AMDTP_STATUS_RESEND_REPLY ACK
|
||||
if (BT_TIMER_HANDLE_INIT_VAL != amdtpsCb.core.timeoutTimer)
|
||||
{
|
||||
retval = BT_stop_timer (amdtpsCb.core.timeoutTimer);
|
||||
AMDTP_TRC (
|
||||
"[AMDTP]: Stopping Timer with result 0x%04X, timer handle %p\n",
|
||||
retval, amdtpsCb.core.timeoutTimer);
|
||||
amdtpsCb.core.timeoutTimer = BT_TIMER_HANDLE_INIT_VAL;
|
||||
}
|
||||
|
||||
retval = BT_start_timer
|
||||
(
|
||||
&amdtpsCb.core.timeoutTimer,
|
||||
amdtpsCb.core.txTimeout,
|
||||
amdtps_timeout_timer_expired,
|
||||
NULL,
|
||||
0
|
||||
);
|
||||
AMDTP_TRC (
|
||||
"[AMDTP]: Started Timer with result 0x%04X, timer handle %p\n",
|
||||
retval, amdtpsCb.core.timeoutTimer);
|
||||
}
|
||||
|
||||
void amdtpsHandleValueCnf(
|
||||
APPL_HANDLE * appl_handle,
|
||||
UCHAR * event_data,
|
||||
UINT16 event_datalen
|
||||
)
|
||||
{
|
||||
ATT_ATTR_HANDLE attr_handle;
|
||||
|
||||
BT_UNPACK_LE_2_BYTE(&attr_handle, event_data);
|
||||
|
||||
#ifdef AMDTP_DEBUG_ON
|
||||
AMDTP_TRC("appl_handle 0x%x attr_handle = 0x%x\n", *appl_handle, attr_handle);
|
||||
#endif
|
||||
|
||||
#if !defined(AMDTPS_RXONLY) && !defined(AMDTPS_RX2TX)
|
||||
if ( attr_handle == appl_tx_hndl )
|
||||
{
|
||||
amdtpsCb.txReady = true;
|
||||
// process next data
|
||||
AmdtpSendPacketHandler(&amdtpsCb.core);
|
||||
#ifdef AMDTPS_TXTEST
|
||||
// fixme when last packet, continue to send next one.
|
||||
if (amdtpsCb.core.txState == AMDTP_STATE_WAITING_ACK)
|
||||
{
|
||||
uint8_t temp[3];
|
||||
temp[0] = AMDTP_STATUS_SUCCESS;
|
||||
AmdtpPacketHandler(&amdtpsCb.core, AMDTP_PKT_TYPE_ACK, 3, temp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void amdtps_mtu_update(APPL_HANDLE * appl_handle, UINT16 t_mtu)
|
||||
{
|
||||
UINT16 mtu = 0;
|
||||
|
||||
BT_att_access_mtu(&APPL_GET_ATT_INSTANCE(*appl_handle),
|
||||
&mtu);
|
||||
|
||||
AMDTP_TRC("appl_handle 0x%x t_mtu = %d %d\n", *appl_handle, t_mtu, mtu);
|
||||
}
|
||||
|
||||
void appl_amdtp_server_reinitialize(void)
|
||||
{
|
||||
API_RESULT retval = API_SUCCESS;
|
||||
|
||||
memset(&amdtpsCb, 0, sizeof(amdtpsCb));
|
||||
amdtpsCb.txReady = false;
|
||||
amdtpsCb.core.txState = AMDTP_STATE_INIT;
|
||||
amdtpsCb.core.rxState = AMDTP_STATE_RX_IDLE;
|
||||
|
||||
amdtpsCb.core.lastRxPktSn = 0;
|
||||
amdtpsCb.core.txPktSn = 0;
|
||||
|
||||
resetPkt(&amdtpsCb.core.rxPkt);
|
||||
amdtpsCb.core.rxPkt.data = rxPktBuf;
|
||||
|
||||
resetPkt(&amdtpsCb.core.txPkt);
|
||||
amdtpsCb.core.txPkt.data = txPktBuf;
|
||||
|
||||
resetPkt(&amdtpsCb.core.ackPkt);
|
||||
amdtpsCb.core.ackPkt.data = ackPktBuf;
|
||||
|
||||
amdtpsCb.core.recvCback = amdtpsDtpRecvCback;
|
||||
amdtpsCb.core.transCback = amdtpsDtpTransCback;
|
||||
|
||||
amdtpsCb.core.data_sender_func = amdtpsSendData;
|
||||
amdtpsCb.core.ack_sender_func = amdtpsSendAck;
|
||||
|
||||
amdtpsCb.core.txTimeout = TX_TIMEOUT_DEFAULT;
|
||||
|
||||
if (BT_TIMER_HANDLE_INIT_VAL != amdtpsCb.core.timeoutTimer)
|
||||
{
|
||||
retval = BT_stop_timer (amdtpsCb.core.timeoutTimer);
|
||||
AMDTP_TRC (
|
||||
"[AMDTP]: Stopping Timer with result 0x%04X, timer handle %p\n",
|
||||
retval, amdtpsCb.core.timeoutTimer);
|
||||
amdtpsCb.core.timeoutTimer = BT_TIMER_HANDLE_INIT_VAL;
|
||||
}
|
||||
|
||||
#if defined(AMDTPS_RXONLY) || defined(AMDTPS_RX2TX)
|
||||
AMDTP_TRC("*** RECEIVED TOTAL %d ***\n", totalLen);
|
||||
totalLen = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
API_RESULT appl_amdtps_write_cback
|
||||
(
|
||||
GATT_DB_HANDLE * handle,
|
||||
ATT_VALUE * value
|
||||
)
|
||||
{
|
||||
API_RESULT retval = API_SUCCESS;
|
||||
eAmdtpStatus_t status = AMDTP_STATUS_UNKNOWN_ERROR;
|
||||
amdtpPacket_t *pkt = NULL;
|
||||
|
||||
#if 0
|
||||
uint16_t i = 0;
|
||||
AMDTP_TRC("============= data arrived start ===============\n");
|
||||
for (i = 0; i < value->len; i++)
|
||||
{
|
||||
AMDTP_TRC("%x\t", value->val[i]);
|
||||
}
|
||||
AMDTP_TRC("============= data arrived end ===============\n");
|
||||
#endif
|
||||
|
||||
if (GATT_CHAR_AMDTP_RX == handle->char_id)
|
||||
{
|
||||
#if defined(AMDTPS_RX2TX)
|
||||
amdtpsSendData(value->val, value->len);
|
||||
#endif
|
||||
#if defined(AMDTPS_RXONLY) || defined(AMDTPS_RX2TX)
|
||||
totalLen += value->len;
|
||||
AMDTP_TRC("received data len %d, total %d\n", value->len, totalLen);
|
||||
return API_SUCCESS;
|
||||
#else /* RXONLY && RX2TX */
|
||||
status = AmdtpReceivePkt(&amdtpsCb.core, &amdtpsCb.core.rxPkt, value->len, value->val);
|
||||
#endif
|
||||
}
|
||||
else if (GATT_CHAR_AMDTP_ACK == handle->char_id)
|
||||
{
|
||||
status = AmdtpReceivePkt(&amdtpsCb.core, &amdtpsCb.core.ackPkt, value->len, value->val);
|
||||
}
|
||||
|
||||
if (status == AMDTP_STATUS_RECEIVE_DONE)
|
||||
{
|
||||
if (GATT_CHAR_AMDTP_RX == handle->char_id)
|
||||
{
|
||||
pkt = &amdtpsCb.core.rxPkt;
|
||||
}
|
||||
else if (GATT_CHAR_AMDTP_ACK == handle->char_id)
|
||||
{
|
||||
pkt = &amdtpsCb.core.ackPkt;
|
||||
}
|
||||
|
||||
AmdtpPacketHandler(&amdtpsCb.core, (eAmdtpPktType_t)pkt->header.pktType, pkt->len - AMDTP_CRC_SIZE_IN_PKT, pkt->data);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @brief Send data to Client via notification
|
||||
//!
|
||||
//! @param type - packet type
|
||||
//! @param encrypted - is packet encrypted
|
||||
//! @param enableACK - does client need to response
|
||||
//! @param buf - data
|
||||
//! @param len - data length
|
||||
//!
|
||||
//! @return status
|
||||
//
|
||||
//*****************************************************************************
|
||||
eAmdtpStatus_t
|
||||
AmdtpsSendPacket(eAmdtpPktType_t type, BOOLEAN encrypted, BOOLEAN enableACK, uint8_t *buf, uint16_t len)
|
||||
{
|
||||
//
|
||||
// Check if ready to send notification
|
||||
//
|
||||
if ( !amdtpsCb.txReady )
|
||||
{
|
||||
//set in callback amdtpsHandleValueCnf
|
||||
AMDTP_TRC("data sending failed, not ready for notification.\n", NULL);
|
||||
return AMDTP_STATUS_TX_NOT_READY;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if the service is idle to send
|
||||
//
|
||||
if ( amdtpsCb.core.txState != AMDTP_STATE_TX_IDLE )
|
||||
{
|
||||
AMDTP_TRC("data sending failed, tx state = %d\n", amdtpsCb.core.txState);
|
||||
return AMDTP_STATUS_BUSY;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if data length is valid
|
||||
//
|
||||
if ( len > AMDTP_MAX_PAYLOAD_SIZE )
|
||||
{
|
||||
AMDTP_TRC("data sending failed, exceed maximum payload, len = %d.\n", len);
|
||||
return AMDTP_STATUS_INVALID_PKT_LENGTH;
|
||||
}
|
||||
|
||||
AmdtpBuildPkt(&amdtpsCb.core, type, encrypted, enableACK, buf, len);
|
||||
|
||||
// send packet
|
||||
AmdtpSendPacketHandler(&amdtpsCb.core);
|
||||
|
||||
return AMDTP_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#endif /* AMDTPS */
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// appl_amdtps.h
|
||||
//! @file
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
/**
|
||||
* \file appl_amdtps.h
|
||||
*
|
||||
* Application Header File for AMDTPS.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _H_APPL_AMDTPS_
|
||||
#define _H_APPL_AMDTPS_
|
||||
|
||||
/* ----------------------------------------- Header File Inclusion */
|
||||
#include "BT_api.h"
|
||||
#include "BT_gatt_db_api.h"
|
||||
#include "gatt_db.h"
|
||||
#include "appl.h"
|
||||
#include "amdtp_common.h"
|
||||
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Macro definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
/*! Configurable parameters */
|
||||
typedef struct
|
||||
{
|
||||
//! Short description of each member should go here.
|
||||
uint32_t reserved;
|
||||
}
|
||||
AmdtpsCfg_t;
|
||||
|
||||
/* --------------------------------------------- Functions */
|
||||
void appl_amdtps_init(void);
|
||||
void appl_manage_trasnfer(GATT_DB_HANDLE handle, UINT16 config);
|
||||
void appl_amdtps_connect(DEVICE_HANDLE * dq_handle);
|
||||
void appl_amdtp_server_reinitialize(void);
|
||||
API_RESULT appl_amdtps_write_cback(GATT_DB_HANDLE *handle, ATT_VALUE *value);
|
||||
eAmdtpStatus_t AmdtpsSendPacket(eAmdtpPktType_t type, BOOLEAN encrypted, BOOLEAN enableACK, uint8_t *buf, uint16_t len);
|
||||
void amdtpsHandleValueCnf( APPL_HANDLE * appl_handle, UCHAR * event_data, UINT16 event_datalen);
|
||||
void amdtps_mtu_update(APPL_HANDLE * appl_handle, UINT16 t_mtu);
|
||||
|
||||
/* Profile handling */
|
||||
#define APPL_PROFILE_INIT(...) appl_amdtps_init()
|
||||
#define APPL_PROFILE_CONNECT(x) appl_amdtps_connect(x)
|
||||
#define APPL_SEND_MEASUREMENT(x)
|
||||
#define APPL_PROFILE_DISCONNECT_HANDLER(x) appl_amdtp_server_reinitialize()
|
||||
#define GATT_DB_PROFILE_HANDLER gatt_db_amdtps_handler
|
||||
#define APPL_PROFILE_HVN_NTF_COMPLETE_HANDLER(x, y, z) amdtpsHandleValueCnf(x, y, z)
|
||||
#define APPL_PROFILE_HVN_IND_COMPLETE_HANDLER(x, y, z) amdtpsHandleValueCnf(x, y, z)
|
||||
#define APPL_PROFILE_MTU_UPDT_COMPLETE_HANDLER(x, y) amdtps_mtu_update(x, y)
|
||||
|
||||
#define APPL_USE_IDLE_TIMER
|
||||
#define APPL_IDLE_TIMEOUT 30
|
||||
|
||||
#endif /* _H_APPL_AMDTPS_ */
|
||||
|
||||
|
||||
+221
@@ -0,0 +1,221 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// appl_gap_config_params.c
|
||||
//! @file
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
/**
|
||||
* \file appl_gap_config_params.c
|
||||
*
|
||||
* This file contains GAP Configuration Parameters used by the application.
|
||||
*/
|
||||
|
||||
|
||||
/* --------------------------------------------- Header File Inclusion */
|
||||
#include "appl_gap.h"
|
||||
|
||||
#ifdef AMDTPS
|
||||
|
||||
/* --------------------------------------------- External Global Variables */
|
||||
|
||||
/* --------------------------------------------- Exported Global Variables */
|
||||
|
||||
/* --------------------------------------------- Static Global Variables */
|
||||
|
||||
#if ((defined APPL_GAP_BROADCASTER_SUPPORT) || (defined APPL_GAP_PERIPHERAL_SUPPORT))
|
||||
/** Advertisement Data Options */
|
||||
const APPL_GAP_ADV_DATA appl_gap_adv_data[APPL_GAP_MAX_ADV_DATA_OPTIONS] =
|
||||
{
|
||||
/* GAP Advertisement Parameters */
|
||||
{
|
||||
{
|
||||
/**
|
||||
* Flags:
|
||||
* 0x01: LE Limited Discoverable Mode
|
||||
* 0x02: LE General Discoverable Mode
|
||||
* 0x04: BR/EDR Not Supported
|
||||
* 0x08: Simultaneous LE and BR/EDR to Same Device
|
||||
* Capable (Controller)
|
||||
* 0x10: Simultaneous LE and BR/EDR to Same Device
|
||||
* Capable (Host)
|
||||
*/
|
||||
0x02, 0x01,
|
||||
(BT_AD_FLAGS_LE_GENERAL_DISC_MODE | BT_AD_FLAGS_LE_BR_EDR_SUPPORT),
|
||||
|
||||
/**
|
||||
* Service UUID List:
|
||||
* Battery Service (0x180F)
|
||||
* DeviceInformation Service (0x180A)
|
||||
* Heart Rate Service (0x180D)
|
||||
*/
|
||||
0x07, 0x03, 0x0F, 0x18, 0x0A, 0x18, 0x0D, 0x18,
|
||||
|
||||
/**
|
||||
* Shortened Device Name: Mindtree
|
||||
*/
|
||||
0x09, 0x08, 0x4D, 0x69, 0x6E, 0x64, 0x74, 0x72, 0x65, 0x65
|
||||
},
|
||||
|
||||
21
|
||||
}
|
||||
};
|
||||
|
||||
/* Advertisement parameters options */
|
||||
const APPL_GAP_ADV_PARAM appl_gap_adv_param[APPL_GAP_MAX_ADV_PARAM_OPTIONS] =
|
||||
{
|
||||
/* 0 - Normal Advertising Params */
|
||||
{
|
||||
32,
|
||||
|
||||
32,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
},
|
||||
/* 1 - Fast Connection Advertising Params */
|
||||
{
|
||||
32,
|
||||
|
||||
48,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
},
|
||||
/* 2 - Low Power Advertising Params */
|
||||
{
|
||||
1600,
|
||||
|
||||
4000,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
}
|
||||
};
|
||||
|
||||
/* Advertisement Table */
|
||||
APPL_GAP_ADV_INFO appl_gap_adv_table =
|
||||
{
|
||||
appl_gap_adv_data,
|
||||
|
||||
appl_gap_adv_param,
|
||||
|
||||
APPL_GAP_ADV_IDLE
|
||||
};
|
||||
#endif /* APPL_GAP_BROADCASTER || APPL_GAP_PERIPHERAL_SUPPORT */
|
||||
|
||||
#if ((defined APPL_GAP_OBSERVER_SUPPORT) || (defined APPL_GAP_CENTRAL_SUPPORT))
|
||||
/* Scan Parameters Option */
|
||||
const APPL_GAP_SCAN_PARAM appl_gap_scan_param[APPL_GAP_MAX_SCAN_PARAM_OPTIONS] =
|
||||
{
|
||||
/* Normal Scan Params */
|
||||
{
|
||||
32,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
},
|
||||
/* Fast Connection Scan Params */
|
||||
{
|
||||
48,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
},
|
||||
/* Low Power Scan Params */
|
||||
{
|
||||
4000,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
}
|
||||
};
|
||||
|
||||
/* Scan Table */
|
||||
APPL_GAP_SCAN_INFO appl_gap_scan_table =
|
||||
{
|
||||
appl_gap_scan_param,
|
||||
|
||||
APPL_GAP_SCAN_IDLE
|
||||
};
|
||||
#endif /* APPL_GAP_OBSERVER_SUPPORT || APPL_GAP_CENTRAL_SUPPORT */
|
||||
|
||||
#ifdef APPL_GAP_CENTRAL_SUPPORT
|
||||
/* Connection Parameters Options */
|
||||
const APPL_GAP_CONN_PARAM appl_gap_conn_param[APPL_GAP_MAX_CONN_PARAM_OPTIONS] =
|
||||
{
|
||||
{
|
||||
4,
|
||||
|
||||
4,
|
||||
|
||||
0,
|
||||
|
||||
40,
|
||||
|
||||
56,
|
||||
|
||||
0,
|
||||
|
||||
955,
|
||||
|
||||
32,
|
||||
|
||||
32
|
||||
}
|
||||
};
|
||||
|
||||
/* GAP Connection Table */
|
||||
APPL_GAP_CONN_INFO appl_gap_conn_table =
|
||||
{
|
||||
appl_gap_conn_param,
|
||||
|
||||
APPL_GAP_CONN_IDLE
|
||||
};
|
||||
#endif /* APPL_GAP_CENTRAL_SUPPORT */
|
||||
#endif /* AMDTPS */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,161 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// gatt_db.h
|
||||
//! @file
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
/**
|
||||
* \file gatt_db.h
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _H_GATT_DB_
|
||||
#define _H_GATT_DB_
|
||||
|
||||
/**
|
||||
* addgroup gatt_db_module
|
||||
*/
|
||||
|
||||
/**
|
||||
* defgroup gatt_db_tuneable_param Tuneable Parameters
|
||||
* {
|
||||
* This section defines the Tuneable Constants of Data Base Module.
|
||||
*/
|
||||
|
||||
/** Number of Characteristics in the data base */
|
||||
#define GATT_CHARACTERISTIC_COUNT 16
|
||||
|
||||
/** Number of Services in the data base */
|
||||
#define GATT_SERVICE_COUNT 5
|
||||
|
||||
/** Number of Characteristics that are configurable by the client */
|
||||
#define GATT_DB_MAX_CONFIGUREABLE_CHAR 4
|
||||
|
||||
/** Maximum Length of any Characteristic Value/Descriptor */
|
||||
#define GATT_DB_MAX_VAL_LENGTH 32
|
||||
|
||||
#define GATT_VALUE_ARRAY_SIZE 1
|
||||
|
||||
#define GATT_CONST_VALUE_ARRAY_SIZE 245
|
||||
|
||||
#define GATT_DB_PEER_VALUE_ARRAY_SIZE 8
|
||||
|
||||
#define GATT_DB_MAX_ATTRIBUTES 43
|
||||
|
||||
#define GATT_UUID_ARRAY_SIZE 118
|
||||
|
||||
#define GATT_DB_MAX_TYPE_COUNT 25
|
||||
|
||||
#define GATT_DB_MAX_PEER_CONFIGURATION \
|
||||
(GATT_DB_PEER_VALUE_ARRAY_SIZE * BT_MAX_DEVICE_QUEUE_SIZE)
|
||||
|
||||
/** \} */
|
||||
|
||||
/** Service Instance Reference */
|
||||
|
||||
/** GAP Service */
|
||||
#define GATT_SER_GAP_INST 0
|
||||
|
||||
/** GATT Service */
|
||||
#define GATT_SER_GATT_INST 1
|
||||
|
||||
/** Battery Service */
|
||||
#define GATT_SER_BATTERY_INST 2
|
||||
|
||||
/** DeviceInformation Service */
|
||||
#define GATT_SER_DEV_INFO_INST 3
|
||||
|
||||
/** AMDTP Service */
|
||||
#define GATT_SER_AMDTP_INST 4
|
||||
|
||||
/** Characteristic Instance Reference */
|
||||
|
||||
/** DeviceName */
|
||||
#define GATT_CHAR_DEV_NAME_INST 0
|
||||
|
||||
/** Appearance */
|
||||
#define GATT_CHAR_APPEARANCE_INST 1
|
||||
|
||||
/** Service Changed */
|
||||
#define GATT_CHAR_SER_CHNGD_INST 2
|
||||
|
||||
/** BatteryLevel */
|
||||
#define GATT_CHAR_BATTERY_LVL_INST 3
|
||||
|
||||
/** ManufacturerName */
|
||||
#define GATT_CHAR_MAN_NAME_INST 4
|
||||
|
||||
/** ModelNumber */
|
||||
#define GATT_CHAR_MODEL_NO_INST 5
|
||||
|
||||
/** SerialNumber */
|
||||
#define GATT_CHAR_SL_NO_INST 6
|
||||
|
||||
/** FirmwareRevision */
|
||||
#define GATT_CHAR_FW_REV_INST 7
|
||||
|
||||
/** HardwareRevision */
|
||||
#define GATT_CHAR_HW_REV_INST 8
|
||||
|
||||
/** SoftwareRevision */
|
||||
#define GATT_CHAR_SW_REV_INST 9
|
||||
|
||||
/** SystemId */
|
||||
#define GATT_CHAR_SYS_ID_INST 10
|
||||
|
||||
/** RegCertDataList */
|
||||
#define GATT_CHAR_REG_CERT_DATA_INST 11
|
||||
|
||||
/** PnPID */
|
||||
#define GATT_CHAR_PNP_ID_INST 12
|
||||
|
||||
/** AMDTP Rx */
|
||||
#define GATT_CHAR_AMDTP_RX 13
|
||||
|
||||
/** AMDTP Tx */
|
||||
#define GATT_CHAR_AMDTP_TX 14
|
||||
|
||||
/** AMDTP Ack */
|
||||
#define GATT_CHAR_AMDTP_ACK 15
|
||||
|
||||
#endif /* _H_GATT_DB_ */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,113 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// appl_amota.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Application Header File for AMOTA.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
/**
|
||||
* \file appl_amota.h
|
||||
*
|
||||
* Application Header File for AMOTA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _H_APPL_AMOTA_
|
||||
#define _H_APPL_AMOTA_
|
||||
|
||||
/* ----------------------------------------- Header File Inclusion */
|
||||
#include "BT_api.h"
|
||||
#include "BT_gatt_db_api.h"
|
||||
#include "gatt_db.h"
|
||||
#include "appl.h"
|
||||
|
||||
// enable debug print for AMOTA profile
|
||||
// #define AMOTA_DEBUG_ON
|
||||
|
||||
/* --------------------------------------------- Global Definitions */
|
||||
#define AMOTA_PACKET_SIZE (512 + 16) // Bytes
|
||||
#define AMOTA_LENGTH_SIZE_IN_PKT 2
|
||||
#define AMOTA_CMD_SIZE_IN_PKT 1
|
||||
#define AMOTA_CRC_SIZE_IN_PKT 4
|
||||
#define AMOTA_HEADER_SIZE_IN_PKT AMOTA_LENGTH_SIZE_IN_PKT + AMOTA_CMD_SIZE_IN_PKT
|
||||
|
||||
#define AMOTA_FW_HEADER_SIZE 44
|
||||
|
||||
#define AMOTA_FW_STORAGE_INTERNAL 0
|
||||
#define AMOTA_FW_STORAGE_EXTERNAL 1
|
||||
|
||||
/* ----------------------------------------- Data Types/ Structures */
|
||||
/*! Configurable parameters */
|
||||
typedef struct
|
||||
{
|
||||
//! Short description of each member should go here.
|
||||
uint32_t reserved;
|
||||
}
|
||||
AmotasCfg_t;
|
||||
|
||||
/* --------------------------------------------- Functions */
|
||||
void appl_amotas_init(void);
|
||||
void appl_manage_trasnfer(GATT_DB_HANDLE handle, UINT16 config);
|
||||
void appl_amotas_connect(DEVICE_HANDLE * dq_handle);
|
||||
void appl_amotas_send_data(UCHAR *data, UINT16 len);
|
||||
void appl_amotas_disconnect(void);
|
||||
|
||||
API_RESULT appl_amotas_write_cback(GATT_DB_HANDLE *handle, ATT_VALUE *value);
|
||||
|
||||
void amota_mtu_update(APPL_HANDLE * appl_handle, UINT16 t_mtu);
|
||||
|
||||
/* Profile handling */
|
||||
#define APPL_PROFILE_INIT(...) appl_amotas_init()
|
||||
#define APPL_PROFILE_CONNECT(x) appl_amotas_connect(x)
|
||||
#define APPL_SEND_MEASUREMENT(x) //appl_send_amotas_measurement(x)
|
||||
#define APPL_PROFILE_DISCONNECT_HANDLER(x) appl_amotas_disconnect()
|
||||
#define GATT_DB_PROFILE_HANDLER gatt_db_amotas_handler
|
||||
#define APPL_PROFILE_HVN_NTF_COMPLETE_HANDLER(x, y, z)
|
||||
#define APPL_PROFILE_HVN_IND_COMPLETE_HANDLER(x, y, z)
|
||||
#define APPL_PROFILE_MTU_UPDT_COMPLETE_HANDLER(x, y) amota_mtu_update(x, y)
|
||||
|
||||
#define APPL_USE_IDLE_TIMER
|
||||
#define APPL_IDLE_TIMEOUT 30
|
||||
#endif /* _H_APPL_AMOTA_ */
|
||||
|
||||
|
||||
+223
@@ -0,0 +1,223 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// appl_gap_config_params.c
|
||||
//! @file
|
||||
//!
|
||||
//! @brief This file contains GAP Configuration Parameters used by the application.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
/**
|
||||
* \file appl_gap_config_params.c
|
||||
*
|
||||
* This file contains GAP Configuration Parameters used by the application.
|
||||
*/
|
||||
|
||||
|
||||
/* --------------------------------------------- Header File Inclusion */
|
||||
#include "appl_gap.h"
|
||||
|
||||
#ifdef AMOTAS
|
||||
|
||||
/* --------------------------------------------- External Global Variables */
|
||||
|
||||
/* --------------------------------------------- Exported Global Variables */
|
||||
|
||||
/* --------------------------------------------- Static Global Variables */
|
||||
|
||||
#if ((defined APPL_GAP_BROADCASTER_SUPPORT) || (defined APPL_GAP_PERIPHERAL_SUPPORT))
|
||||
/** Advertisement Data Options */
|
||||
const APPL_GAP_ADV_DATA appl_gap_adv_data[APPL_GAP_MAX_ADV_DATA_OPTIONS] =
|
||||
{
|
||||
/* GAP Advertisement Parameters */
|
||||
{
|
||||
{
|
||||
/**
|
||||
* Flags:
|
||||
* 0x01: LE Limited Discoverable Mode
|
||||
* 0x02: LE General Discoverable Mode
|
||||
* 0x04: BR/EDR Not Supported
|
||||
* 0x08: Simultaneous LE and BR/EDR to Same Device
|
||||
* Capable (Controller)
|
||||
* 0x10: Simultaneous LE and BR/EDR to Same Device
|
||||
* Capable (Host)
|
||||
*/
|
||||
0x02, 0x01,
|
||||
(BT_AD_FLAGS_LE_GENERAL_DISC_MODE | BT_AD_FLAGS_LE_BR_EDR_SUPPORT),
|
||||
|
||||
/**
|
||||
* Service UUID List:
|
||||
* Battery Service (0x180F)
|
||||
* DeviceInformation Service (0x180A)
|
||||
* Heart Rate Service (0x180D)
|
||||
*/
|
||||
0x07, 0x03, 0x0F, 0x18, 0x0A, 0x18, 0x0D, 0x18,
|
||||
|
||||
/**
|
||||
* Shortened Device Name: Mindtree
|
||||
*/
|
||||
0x09, 0x08, 0x4D, 0x69, 0x6E, 0x64, 0x74, 0x72, 0x65, 0x65
|
||||
},
|
||||
|
||||
21
|
||||
}
|
||||
};
|
||||
|
||||
/* Advertisement parameters options */
|
||||
const APPL_GAP_ADV_PARAM appl_gap_adv_param[APPL_GAP_MAX_ADV_PARAM_OPTIONS] =
|
||||
{
|
||||
/* 0 - Normal Advertising Params */
|
||||
{
|
||||
32,
|
||||
|
||||
32,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
},
|
||||
/* 1 - Fast Connection Advertising Params */
|
||||
{
|
||||
32,
|
||||
|
||||
48,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
},
|
||||
/* 2 - Low Power Advertising Params */
|
||||
{
|
||||
32,
|
||||
|
||||
32,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
}
|
||||
};
|
||||
|
||||
/* Advertisement Table */
|
||||
APPL_GAP_ADV_INFO appl_gap_adv_table =
|
||||
{
|
||||
appl_gap_adv_data,
|
||||
|
||||
appl_gap_adv_param,
|
||||
|
||||
APPL_GAP_ADV_IDLE
|
||||
};
|
||||
#endif /* APPL_GAP_BROADCASTER || APPL_GAP_PERIPHERAL_SUPPORT */
|
||||
|
||||
#if ((defined APPL_GAP_OBSERVER_SUPPORT) || (defined APPL_GAP_CENTRAL_SUPPORT))
|
||||
/* Scan Parameters Option */
|
||||
const APPL_GAP_SCAN_PARAM appl_gap_scan_param[APPL_GAP_MAX_SCAN_PARAM_OPTIONS] =
|
||||
{
|
||||
/* Normal Scan Params */
|
||||
{
|
||||
32,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
},
|
||||
/* Fast Connection Scan Params */
|
||||
{
|
||||
48,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
},
|
||||
/* Low Power Scan Params */
|
||||
{
|
||||
4000,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
}
|
||||
};
|
||||
|
||||
/* Scan Table */
|
||||
APPL_GAP_SCAN_INFO appl_gap_scan_table =
|
||||
{
|
||||
appl_gap_scan_param,
|
||||
|
||||
APPL_GAP_SCAN_IDLE
|
||||
};
|
||||
#endif /* APPL_GAP_OBSERVER_SUPPORT || APPL_GAP_CENTRAL_SUPPORT */
|
||||
|
||||
#ifdef APPL_GAP_CENTRAL_SUPPORT
|
||||
/* Connection Parameters Options */
|
||||
const APPL_GAP_CONN_PARAM appl_gap_conn_param[APPL_GAP_MAX_CONN_PARAM_OPTIONS] =
|
||||
{
|
||||
{
|
||||
4,
|
||||
|
||||
4,
|
||||
|
||||
0,
|
||||
|
||||
40,
|
||||
|
||||
56,
|
||||
|
||||
0,
|
||||
|
||||
955,
|
||||
|
||||
32,
|
||||
|
||||
32
|
||||
}
|
||||
};
|
||||
|
||||
/* GAP Connection Table */
|
||||
APPL_GAP_CONN_INFO appl_gap_conn_table =
|
||||
{
|
||||
appl_gap_conn_param,
|
||||
|
||||
APPL_GAP_CONN_IDLE
|
||||
};
|
||||
#endif /* APPL_GAP_CENTRAL_SUPPORT */
|
||||
#endif /* AMOTAS */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,161 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// gatt_db.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief This section defines the Tuneable Constants of Data Base Module.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
|
||||
/**
|
||||
* \file gatt_db.h
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _H_GATT_DB_
|
||||
#define _H_GATT_DB_
|
||||
|
||||
/**
|
||||
* addgroup gatt_db_module
|
||||
*/
|
||||
|
||||
/**
|
||||
* defgroup gatt_db_tuneable_param Tuneable Parameters
|
||||
* {
|
||||
* This section defines the Tuneable Constants of Data Base Module.
|
||||
*/
|
||||
|
||||
/** Number of Characteristics in the data base */
|
||||
#define GATT_CHARACTERISTIC_COUNT 15
|
||||
|
||||
/** Number of Services in the data base */
|
||||
#define GATT_SERVICE_COUNT 5
|
||||
|
||||
/** Number of Characteristics that are configurable by the client */
|
||||
#define GATT_DB_MAX_CONFIGUREABLE_CHAR 3
|
||||
|
||||
/** Maximum Length of any Characteristic Value/Descriptor */
|
||||
#define GATT_DB_MAX_VAL_LENGTH 32
|
||||
|
||||
#define GATT_VALUE_ARRAY_SIZE 1
|
||||
|
||||
#define GATT_CONST_VALUE_ARRAY_SIZE 226
|
||||
|
||||
#define GATT_DB_PEER_VALUE_ARRAY_SIZE 6
|
||||
|
||||
#define GATT_DB_MAX_ATTRIBUTES 40
|
||||
|
||||
#define GATT_UUID_ARRAY_SIZE 102
|
||||
|
||||
#define GATT_DB_MAX_TYPE_COUNT 24
|
||||
|
||||
#define GATT_DB_MAX_PEER_CONFIGURATION \
|
||||
(GATT_DB_PEER_VALUE_ARRAY_SIZE * BT_MAX_DEVICE_QUEUE_SIZE)
|
||||
|
||||
/** \} */
|
||||
|
||||
/** Service Instance Reference */
|
||||
|
||||
/** GAP Service */
|
||||
#define GATT_SER_GAP_INST 0
|
||||
|
||||
/** GATT Service */
|
||||
#define GATT_SER_GATT_INST 1
|
||||
|
||||
/** Battery Service */
|
||||
#define GATT_SER_BATTERY_INST 2
|
||||
|
||||
/** DeviceInformation Service */
|
||||
#define GATT_SER_DEV_INFO_INST 3
|
||||
|
||||
/** AMOTA Service */
|
||||
#define GATT_SER_AMOTA_INST 4
|
||||
|
||||
/** Characteristic Instance Reference */
|
||||
|
||||
/** DeviceName */
|
||||
#define GATT_CHAR_DEV_NAME_INST 0
|
||||
|
||||
/** Appearance */
|
||||
#define GATT_CHAR_APPEARANCE_INST 1
|
||||
|
||||
/** Service Changed */
|
||||
#define GATT_CHAR_SER_CHNGD_INST 2
|
||||
|
||||
/** BatteryLevel */
|
||||
#define GATT_CHAR_BATTERY_LVL_INST 3
|
||||
|
||||
/** ManufacturerName */
|
||||
#define GATT_CHAR_MAN_NAME_INST 4
|
||||
|
||||
/** ModelNumber */
|
||||
#define GATT_CHAR_MODEL_NO_INST 5
|
||||
|
||||
/** SerialNumber */
|
||||
#define GATT_CHAR_SL_NO_INST 6
|
||||
|
||||
/** FirmwareRevision */
|
||||
#define GATT_CHAR_FW_REV_INST 7
|
||||
|
||||
/** HardwareRevision */
|
||||
#define GATT_CHAR_HW_REV_INST 8
|
||||
|
||||
/** SoftwareRevision */
|
||||
#define GATT_CHAR_SW_REV_INST 9
|
||||
|
||||
/** SystemId */
|
||||
#define GATT_CHAR_SYS_ID_INST 10
|
||||
|
||||
/** RegCertDataList */
|
||||
#define GATT_CHAR_REG_CERT_DATA_INST 11
|
||||
|
||||
/** PnPID */
|
||||
#define GATT_CHAR_PNP_ID_INST 12
|
||||
|
||||
/** AMOTA Rx */
|
||||
#define GATT_CHAR_AMOTA_RX 13
|
||||
|
||||
/** AMOTA Tx */
|
||||
#define GATT_CHAR_AMOTA_TX 14
|
||||
|
||||
#endif /* _H_GATT_DB_ */
|
||||
|
||||
@@ -0,0 +1,604 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file appl_ams.c
|
||||
//!
|
||||
//! @brief Provides functions for the AMS service.
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
/**
|
||||
* \file appl_ams.c
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* --------------------------------------------- Header File Inclusion */
|
||||
#ifdef AMS
|
||||
#include "appl.h"
|
||||
#include "BT_common.h"
|
||||
#include "BT_hci_api.h"
|
||||
#include "BT_att_api.h"
|
||||
#include "BT_smp_api.h"
|
||||
#include "smp_pl.h"
|
||||
#include "l2cap.h"
|
||||
#include "fsm_defines.h"
|
||||
#include "task.h"
|
||||
|
||||
/* ----------------------------------------- Configuration Defines */
|
||||
extern uint32_t am_util_stdio_printf(const char *pcFmt, ...);
|
||||
#undef APPL_TRC
|
||||
#undef APPL_ERR
|
||||
#define APPL_TRC am_util_stdio_printf
|
||||
#define APPL_ERR am_util_stdio_printf
|
||||
|
||||
|
||||
/* ----------------------------------------- Macro Defines */
|
||||
/**@brief Entity IDs */
|
||||
typedef enum
|
||||
{
|
||||
AMS_ENTITY_ID_PLAYER, /** The currently active media app. Attributes for this entity include values such as its name, playback state, and playback volume. */
|
||||
AMS_ENTITY_ID_QUEUE, /** The currently loaded playback queue. Attributes for this entity include values such as its size and its shuffle and repeat modes. */
|
||||
AMS_ENTITY_ID_TRACK, /** The currently loaded track. Attributes for this entity include values such as its artist, title, and duration. */
|
||||
} ams_entity_id_values_t;
|
||||
|
||||
/**@brief Player AttributeID */
|
||||
typedef enum
|
||||
{
|
||||
AMS_PLAYER_ATTRID_NAME, /** A string containing the localized name of the app */
|
||||
AMS_PLAYER_ATTRID_PLAYBACKINFO, /** PlaybackState, PlaybackRate, ElapsedTime */
|
||||
AMS_PLAYER_ATTRID_VOLUME, /** A string that represents the floating point value of the volume, ranging from 0 (silent) to 1 (full volume). */
|
||||
} ams_player_attribute_id_values_t;
|
||||
|
||||
/**@brief Queue AttributeID */
|
||||
typedef enum
|
||||
{
|
||||
AMS_QUEUE_ATTRID_INDEX, /** A string containing the integer value of the queue index, zero-based. */
|
||||
AMS_QUEUE_ATTRID_COUNT, /** A string containing the integer value of the total number of items in the queue. */
|
||||
AMS_QUEUE_ATTRID_SHUFFLE, /** A string containing the integer value of the shuffle mode. */
|
||||
AMS_QUEUE_ATTRID_REPEAT, /** A string containing the integer value value of the repeat mode. */
|
||||
} ams_queue_attribute_id_values_t;
|
||||
|
||||
/**@brief Track AttributeID */
|
||||
typedef enum
|
||||
{
|
||||
AMS_TRACK_ATTRID_ARTIST, /** A string containing the name of the artist. */
|
||||
AMS_TRACK_ATTRID_ALBUM, /** A string containing the name of the album. */
|
||||
AMS_TRACK_ATTRID_TITLE, /** A string containing the title of the track. */
|
||||
AMS_TRACK_ATTRID_DURATION, /** A string containing the floating point value of the total duration of the track in seconds. */
|
||||
} ams_track_attribute_id_values_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AMS_DISCONNECTED,
|
||||
AMS_CONNECTED,
|
||||
AMS_BONDED,
|
||||
AMS_DISCOVERED,
|
||||
} ams_appl_state_t;
|
||||
|
||||
/* ----------------------------------------- External Global Variables */
|
||||
void appl_profile_operations (void);
|
||||
void appl_bond_with_peer(void);
|
||||
void appl_discover_AMS(void);
|
||||
extern BT_DEVICE_ADDR g_bd_addr;
|
||||
|
||||
/* ----------------------------------------- Exported Global Variables */
|
||||
|
||||
|
||||
/* ----------------------------------------- Static Global Variables */
|
||||
DECL_STATIC UCHAR write_response = 0;
|
||||
DECL_STATIC API_RESULT gResult = 0;
|
||||
DECL_STATIC ams_appl_state_t appl_ams_state = AMS_DISCONNECTED;
|
||||
DECL_STATIC ATT_UUID ams_service_uuid128 = {.uuid_128.value = {0xDC, 0xF8, 0x55, 0xAD, 0x02, 0xC5, 0xF4, 0x8E, 0x3A, 0x43, 0x36, 0x0F, 0x2B, 0x50, 0xD3, 0x89}};
|
||||
DECL_STATIC ATT_UUID AMS_RemoteCommand_UUID = {.uuid_128.value = {0xC2, 0x51, 0xCA, 0xF7, 0x56, 0x0E, 0xDF, 0xB8, 0x8A, 0x4A, 0xB1, 0x57, 0xD8, 0x81, 0x3C, 0x9B}};
|
||||
DECL_STATIC ATT_UUID AMS_EntityUpdate_UUID = {.uuid_128.value = {0x02, 0xC1, 0x96, 0xBA, 0x92, 0xBB, 0x0C, 0x9A, 0x1F, 0x41, 0x8D, 0x80, 0xCE, 0xAB, 0x7C, 0x2F}};
|
||||
DECL_STATIC ATT_UUID AMS_EntityAttribute_UUID = {.uuid_128.value = {0xD7, 0xD5, 0xBB, 0x70, 0xA8, 0xA3, 0xAB, 0xA6, 0xD8, 0x46, 0xAB, 0x23, 0x8C, 0xF3, 0xB2, 0xC6}};
|
||||
/* BLE Connection Handle */
|
||||
//DECL_STATIC UINT16 appl_ble_connection_handle;
|
||||
|
||||
/** AMS Characteristic related information */
|
||||
typedef struct
|
||||
{
|
||||
/* AMS Service */
|
||||
|
||||
/* Remote Command */
|
||||
ATT_ATTR_HANDLE ams_remote_command_hdl;
|
||||
|
||||
/* Remote Command - CCC */
|
||||
ATT_ATTR_HANDLE ams_remote_command_ccc_hdl;
|
||||
|
||||
/* Entity Update */
|
||||
ATT_ATTR_HANDLE ams_entity_update_hdl;
|
||||
|
||||
/* Entity Update - CCC */
|
||||
ATT_ATTR_HANDLE ams_entity_update_ccc_hdl;
|
||||
|
||||
/* Entity Attribute */
|
||||
ATT_ATTR_HANDLE ams_entity_attribute_hdl;
|
||||
|
||||
} AMS_CHAR_INFO;
|
||||
|
||||
#define APPL_CLI_CNFG_VAL_LENGTH 2
|
||||
DECL_STATIC AMS_CHAR_INFO ams_char_info;
|
||||
#ifdef APPL_MENU_OPS
|
||||
BT_DEVICE_ADDR g_peer_bd_addr;
|
||||
|
||||
static UCHAR ams_client_menu[] =
|
||||
"\n\
|
||||
\r\n\
|
||||
1. Bond with peer \r\n\
|
||||
\r\n\
|
||||
2. Discover AMS \r\n\
|
||||
\r\n\
|
||||
3. Subscribe to Entity Update \r\n\
|
||||
\r\n\
|
||||
4. Write to Entity Update \r\n\
|
||||
\r\n\
|
||||
5. Write to Remote Command \r\n\
|
||||
\r\n\
|
||||
6. Write to Entity Attribute \r\n\
|
||||
\r\n\
|
||||
7. Read Entity Attribute \r\n\
|
||||
\r\n\
|
||||
Your Option? \0";
|
||||
#endif /* APPL_MENU_OPS */
|
||||
|
||||
/* --------------------------------------------- Constants */
|
||||
|
||||
|
||||
/* --------------------------------------------- Static Global Variables */
|
||||
|
||||
|
||||
/* --------------------------------------------- Functions */
|
||||
|
||||
void appl_bond_with_peer(void)
|
||||
{
|
||||
API_RESULT retval;
|
||||
/* If connection is successful, initiate bonding [Step 2(c)] */
|
||||
|
||||
SMP_AUTH_INFO auth;
|
||||
SMP_BD_ADDR smp_peer_bd_addr;
|
||||
SMP_BD_HANDLE smp_bd_handle;
|
||||
|
||||
APPL_TRC("\n<<appl_bond_with_peer>>\n");
|
||||
|
||||
auth.param = 1;
|
||||
auth.bonding = 1;
|
||||
auth.ekey_size = 12;
|
||||
auth.security = SMP_SEC_LEVEL_1;
|
||||
|
||||
BT_COPY_BD_ADDR(smp_peer_bd_addr.addr, g_bd_addr.addr);
|
||||
BT_COPY_TYPE(smp_peer_bd_addr.type, g_bd_addr.type);
|
||||
|
||||
retval = BT_smp_get_bd_handle
|
||||
(
|
||||
&smp_peer_bd_addr,
|
||||
&smp_bd_handle
|
||||
);
|
||||
|
||||
if (API_SUCCESS == retval)
|
||||
{
|
||||
retval = BT_smp_authenticate (&smp_bd_handle, &auth);
|
||||
}
|
||||
|
||||
if (API_SUCCESS != retval)
|
||||
{
|
||||
APPL_TRC (
|
||||
"Initiation of Authentication Failed. Reason 0x%04X\n",
|
||||
retval);
|
||||
}
|
||||
|
||||
/**
|
||||
* Application will receive authentication complete event,
|
||||
* in SMP Callback.
|
||||
*
|
||||
* Look for 'SMP_AUTHENTICATION_COMPLETE' event handling in
|
||||
* 'appl_smp_callback'.
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void appl_ams_init(void)
|
||||
{
|
||||
appl_ams_state = AMS_DISCONNECTED;
|
||||
APPL_TRC("\n\n<<appl_ams_init>>\n\n");
|
||||
}
|
||||
|
||||
void appl_ams_connect(APPL_HANDLE * appl_handle)
|
||||
{
|
||||
APPL_STATE_T state = GET_APPL_STATE(*appl_handle);
|
||||
|
||||
if ( state == SL_0_TRANSPORT_OPERATING && appl_ams_state == AMS_DISCONNECTED )
|
||||
{
|
||||
appl_ams_state = AMS_CONNECTED;
|
||||
APPL_TRC("\n\n<<CONNECTED>>\n\n");
|
||||
}
|
||||
else if ( state == SL_0_TRANSPORT_OPERATING && appl_ams_state == AMS_DISCOVERED)
|
||||
{
|
||||
appl_ams_state = AMS_BONDED;
|
||||
APPL_TRC("\n\n<<BONDED>>\n\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
appl_ams_state = AMS_DISCONNECTED;
|
||||
APPL_TRC("\n\n<<DISCONNECTED>>\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
void appl_search_complete(void)
|
||||
{
|
||||
appl_ams_state = AMS_DISCOVERED;
|
||||
APPL_TRC("\n\n<<DISCOVERED>>\n\n");
|
||||
}
|
||||
|
||||
void appl_recvice_att_event(UCHAR att_event, API_RESULT event_result)
|
||||
{
|
||||
if ( att_event == ATT_WRITE_RSP )
|
||||
{
|
||||
write_response = 1;
|
||||
gResult = 0;
|
||||
}
|
||||
else if ( att_event == ATT_ERROR_RSP )
|
||||
{
|
||||
gResult = event_result;
|
||||
}
|
||||
}
|
||||
|
||||
void appl_manage_trasnfer (GATT_DB_HANDLE handle, UINT16 config)
|
||||
{
|
||||
APPL_TRC("\n\n<<appl_manage_trasnfer>>\n\n");
|
||||
}
|
||||
|
||||
void appl_send_ams_measurement (APPL_HANDLE * handle)
|
||||
{
|
||||
APPL_TRC("\n\n<<appl_send_ams_measurement>>\n\n");
|
||||
}
|
||||
|
||||
|
||||
void appl_timer_expiry_handler (void *data, UINT16 datalen)
|
||||
{
|
||||
APPL_TRC("\n\n<<appl_timer_expiry_handler>>\n\n");
|
||||
}
|
||||
|
||||
void appl_ams_server_reinitialize (void)
|
||||
{
|
||||
appl_ams_state = AMS_DISCONNECTED;
|
||||
APPL_TRC("\n\n<<appl_ams_server_reinitialize>>\n\n");
|
||||
}
|
||||
|
||||
void ams_mtu_update(APPL_HANDLE * appl_handle, UINT16 t_mtu)
|
||||
{
|
||||
UINT16 mtu = 0;
|
||||
|
||||
BT_att_access_mtu(&APPL_GET_ATT_INSTANCE(*appl_handle),
|
||||
&mtu);
|
||||
|
||||
APPL_TRC("appl_handle 0x%x t_mtu = %d %d\n", *appl_handle, t_mtu, mtu);
|
||||
}
|
||||
|
||||
/* ------------------------------- ATT related Functions */
|
||||
void appl_rcv_service_desc (UINT16 config, ATT_UUID uuid, UINT16 value_handle)
|
||||
{
|
||||
/* Populate Needed CCCDs here */
|
||||
if (GATT_CLIENT_CONFIG == config)
|
||||
{
|
||||
if ( memcmp(&uuid, &AMS_RemoteCommand_UUID, ATT_128_BIT_UUID_SIZE) == 0 )
|
||||
{
|
||||
ams_char_info.ams_remote_command_ccc_hdl = value_handle;
|
||||
}
|
||||
else if ( memcmp(&uuid, &AMS_EntityUpdate_UUID, ATT_128_BIT_UUID_SIZE) == 0 )
|
||||
{
|
||||
ams_char_info.ams_entity_update_ccc_hdl = value_handle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void appl_rcv_service_char (ATT_UUID uuid, UINT16 value_handle)
|
||||
{
|
||||
if ( memcmp(&uuid, &AMS_RemoteCommand_UUID, ATT_128_BIT_UUID_SIZE) == 0 )
|
||||
{
|
||||
ams_char_info.ams_remote_command_hdl = value_handle;
|
||||
}
|
||||
else if ( memcmp(&uuid, &AMS_EntityUpdate_UUID, ATT_128_BIT_UUID_SIZE) == 0 )
|
||||
{
|
||||
ams_char_info.ams_entity_update_hdl = value_handle;
|
||||
}
|
||||
else if ( memcmp(&uuid, &AMS_EntityAttribute_UUID, ATT_128_BIT_UUID_SIZE) == 0 )
|
||||
{
|
||||
ams_char_info.ams_entity_attribute_hdl = value_handle;
|
||||
}
|
||||
}
|
||||
|
||||
void Wait4WrtRsp(void)
|
||||
{
|
||||
const TickType_t xDelay = 10 / portTICK_PERIOD_MS;
|
||||
UCHAR i = 0;
|
||||
|
||||
while ( !write_response )
|
||||
{
|
||||
vTaskDelay( xDelay );
|
||||
if (i++ > 10 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
write_response = 0;
|
||||
}
|
||||
|
||||
void appl_discover_AMS(void)
|
||||
{
|
||||
APPL_TRC("\n<<appl discover AMS>>\n");
|
||||
appl_discover_service
|
||||
(
|
||||
ams_service_uuid128,
|
||||
ATT_128_BIT_UUID_FORMAT
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void AmsWrite2EnityUpdate(uint8_t entityID)
|
||||
{
|
||||
ATT_VALUE att_value;
|
||||
uint8_t buf[5];
|
||||
|
||||
APPL_TRC("\n++<<AmsWrite2EnityUpdate %d>>\n", entityID);
|
||||
|
||||
if ( entityID == AMS_ENTITY_ID_PLAYER )
|
||||
{
|
||||
buf[0] = AMS_ENTITY_ID_PLAYER;
|
||||
buf[1] = AMS_PLAYER_ATTRID_NAME;
|
||||
buf[2] = AMS_PLAYER_ATTRID_PLAYBACKINFO;
|
||||
buf[3] = AMS_PLAYER_ATTRID_VOLUME;
|
||||
att_value.len = 4;
|
||||
}
|
||||
else if ( entityID == AMS_ENTITY_ID_QUEUE )
|
||||
{
|
||||
buf[0] = AMS_ENTITY_ID_QUEUE;
|
||||
buf[1] = AMS_QUEUE_ATTRID_INDEX;
|
||||
buf[2] = AMS_QUEUE_ATTRID_COUNT;
|
||||
buf[3] = AMS_QUEUE_ATTRID_SHUFFLE;
|
||||
buf[4] = AMS_QUEUE_ATTRID_REPEAT;
|
||||
att_value.len = 5;
|
||||
}
|
||||
else if ( entityID == AMS_ENTITY_ID_TRACK )
|
||||
{
|
||||
buf[0] = AMS_ENTITY_ID_TRACK;
|
||||
buf[1] = AMS_TRACK_ATTRID_ARTIST;
|
||||
buf[2] = AMS_TRACK_ATTRID_ALBUM;
|
||||
buf[3] = AMS_TRACK_ATTRID_TITLE;
|
||||
buf[4] = AMS_TRACK_ATTRID_DURATION;
|
||||
att_value.len = 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
att_value.val = buf;
|
||||
appl_write_req (ams_char_info.ams_entity_update_hdl, &att_value);
|
||||
|
||||
Wait4WrtRsp();
|
||||
APPL_TRC("\n--<<AmsWrite2EnityUpdate %d>>\n", entityID);
|
||||
|
||||
}
|
||||
|
||||
void AmsWrite2RemoteCommand(uint8_t cmd)
|
||||
{
|
||||
ATT_VALUE att_value;
|
||||
uint8_t buf[1]; // retrieve the complete attribute list
|
||||
|
||||
buf[0] = cmd;
|
||||
|
||||
att_value.len = 1;
|
||||
att_value.val = buf;
|
||||
appl_write_req (ams_char_info.ams_remote_command_hdl, &att_value);
|
||||
|
||||
}
|
||||
|
||||
void AmsWrite2EntityAttribute(uint8_t entityID, uint8_t attrID)
|
||||
{
|
||||
ATT_VALUE att_value;
|
||||
uint8_t buf[2]; // retrieve the complete attribute list
|
||||
|
||||
buf[0] = entityID;
|
||||
buf[1] = attrID;
|
||||
|
||||
att_value.len = 2;
|
||||
att_value.val = buf;
|
||||
appl_write_req (ams_char_info.ams_entity_attribute_hdl, &att_value);
|
||||
|
||||
}
|
||||
|
||||
void AmsSubscribe2EnityUpdate(void)
|
||||
{
|
||||
ATT_VALUE att_value;
|
||||
UINT16 cli_cfg;
|
||||
UCHAR cfg_val[APPL_CLI_CNFG_VAL_LENGTH];
|
||||
|
||||
APPL_TRC("\n++<<AmsSubscribe2EnityUpdate>>\n");
|
||||
|
||||
cli_cfg = GATT_CLI_CNFG_NOTIFICATION;
|
||||
BT_PACK_LE_2_BYTE(cfg_val, &cli_cfg);
|
||||
att_value.len = APPL_CLI_CNFG_VAL_LENGTH;
|
||||
att_value.val = cfg_val;
|
||||
appl_write_req (ams_char_info.ams_entity_update_ccc_hdl, &att_value);
|
||||
|
||||
Wait4WrtRsp();
|
||||
|
||||
APPL_TRC("\n--<<AmsSubscribe2EnityUpdate(0x%04X)>>\n", gResult);
|
||||
}
|
||||
|
||||
void appl_profile_operations (void)
|
||||
{
|
||||
|
||||
const TickType_t xDelay = 100 / portTICK_PERIOD_MS;
|
||||
write_response = 0;
|
||||
|
||||
fsm_post_event
|
||||
(
|
||||
APPL_FSM_ID,
|
||||
ev_appl_device_init_req,
|
||||
NULL
|
||||
);
|
||||
|
||||
while ( appl_ams_state != AMS_CONNECTED )
|
||||
{
|
||||
vTaskDelay( xDelay );
|
||||
}
|
||||
|
||||
appl_discover_AMS();
|
||||
|
||||
while ( appl_ams_state != AMS_DISCOVERED )
|
||||
{
|
||||
vTaskDelay( xDelay );
|
||||
}
|
||||
|
||||
AmsSubscribe2EnityUpdate();
|
||||
|
||||
if (gResult == 0x0305 /* insufficient authentication */ ||
|
||||
gResult == 0x030F /* insufficient Encryption */ )
|
||||
{
|
||||
appl_bond_with_peer();
|
||||
while ( appl_ams_state != AMS_BONDED )
|
||||
{
|
||||
vTaskDelay( xDelay );
|
||||
}
|
||||
AmsSubscribe2EnityUpdate();
|
||||
}
|
||||
else
|
||||
{
|
||||
appl_ams_state = AMS_BONDED;
|
||||
}
|
||||
|
||||
AmsWrite2EnityUpdate(AMS_ENTITY_ID_PLAYER);
|
||||
|
||||
AmsWrite2EnityUpdate(AMS_ENTITY_ID_QUEUE);
|
||||
|
||||
AmsWrite2EnityUpdate(AMS_ENTITY_ID_TRACK);
|
||||
|
||||
while ( appl_ams_state != AMS_DISCONNECTED )
|
||||
{
|
||||
vTaskDelay( xDelay );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void AmsDumpBytes (UCHAR *buffer, UINT16 length)
|
||||
{
|
||||
char hex_stream[49];
|
||||
char char_stream[17];
|
||||
UINT32 i;
|
||||
UINT16 offset, count;
|
||||
UCHAR c;
|
||||
|
||||
APPL_TRC("\n");
|
||||
|
||||
APPL_TRC (
|
||||
"-------------------------------------------------------------------\n");
|
||||
|
||||
count = 0;
|
||||
offset = 0;
|
||||
for (i = 0; i < length; i ++ )
|
||||
{
|
||||
c = buffer[i];
|
||||
sprintf(hex_stream + offset, "%02X ", c);
|
||||
|
||||
if ( (c >= 0x20) && (c <= 0x7E) )
|
||||
{
|
||||
char_stream[count] = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
char_stream[count] = '.';
|
||||
}
|
||||
|
||||
count ++;
|
||||
offset += 3;
|
||||
|
||||
if ( 16 == count )
|
||||
{
|
||||
char_stream[count] = '\0';
|
||||
count = 0;
|
||||
offset = 0;
|
||||
|
||||
APPL_TRC ("%s %s\n",
|
||||
hex_stream, char_stream);
|
||||
|
||||
BT_mem_set(hex_stream, 0, 49);
|
||||
BT_mem_set(char_stream, 0, 17);
|
||||
}
|
||||
}
|
||||
|
||||
if ( offset != 0 )
|
||||
{
|
||||
char_stream[count] = '\0';
|
||||
|
||||
/* Maintain the alignment */
|
||||
APPL_TRC ("%-48s %s\n",
|
||||
hex_stream, char_stream);
|
||||
}
|
||||
|
||||
APPL_TRC (
|
||||
"-------------------------------------------------------------------\n");
|
||||
|
||||
APPL_TRC ("\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void AmsNotificationCb(UCHAR *event_data, UINT16 event_datalen)
|
||||
{
|
||||
AmsDumpBytes(event_data + 2, (event_datalen - 2));
|
||||
}
|
||||
|
||||
void AmsReadRSPCb(UCHAR *event_data, UINT16 event_datalen)
|
||||
{
|
||||
ATT_ATTR_HANDLE attr_handle;
|
||||
|
||||
BT_UNPACK_LE_2_BYTE(&attr_handle, event_data);
|
||||
|
||||
AmsDumpBytes(event_data + 2, (event_datalen - 2));
|
||||
}
|
||||
#endif /* AMS */
|
||||
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file appl_ams.c
|
||||
//!
|
||||
//! @brief Application Header File for AMS.
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
/**
|
||||
* \file appl_ams.h
|
||||
*
|
||||
* Application Header File for AMS.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _H_APPL_AMS_
|
||||
#define _H_APPL_AMS_
|
||||
|
||||
/* ----------------------------------------- Header File Inclusion */
|
||||
#include "BT_api.h"
|
||||
#include "BT_gatt_db_api.h"
|
||||
#include "gatt_db.h"
|
||||
#include "appl.h"
|
||||
#include "appl_ams_att_server.h"
|
||||
|
||||
/* ----------------------------------------- Data Types/ Structures */
|
||||
typedef struct
|
||||
{
|
||||
UCHAR index;
|
||||
|
||||
UCHAR length;
|
||||
|
||||
}APPL_HRS_OBS_DATA_INFO;
|
||||
|
||||
/* --------------------------------------------- Global Definitions */
|
||||
/** LSB of error code has to be spec defined */
|
||||
#define APPL_HR_CNTRL_PNT_NOT_SUPPORTED (APPL_ERR_ID | 0x80)
|
||||
|
||||
/* --------------------------------------------- Functions */
|
||||
void appl_ams_init(void);
|
||||
void appl_manage_trasnfer (GATT_DB_HANDLE handle, UINT16 config);
|
||||
void appl_timer_expiry_handler (void *data, UINT16 datalen);
|
||||
void appl_ams_connect(DEVICE_HANDLE * dq_handle);
|
||||
void appl_send_ams_measurement (APPL_HANDLE * handle);
|
||||
void appl_ams_server_reinitialize (void);
|
||||
void appl_rcv_service_desc (UINT16 config, ATT_UUID uuid, UINT16 value_handle);
|
||||
void appl_rcv_service_char (ATT_UUID uuid, UINT16 value_handle);
|
||||
API_RESULT appl_hr_control_point_handler
|
||||
(
|
||||
GATT_DB_HANDLE * handle,
|
||||
ATT_VALUE * value
|
||||
);
|
||||
API_RESULT appl_att_callback
|
||||
(
|
||||
ATT_HANDLE * handle,
|
||||
UCHAR event_type,
|
||||
API_RESULT event_result,
|
||||
UCHAR * event_data,
|
||||
UINT16 event_datalen
|
||||
);
|
||||
|
||||
void ams_mtu_update(APPL_HANDLE * appl_handle, UINT16 t_mtu);
|
||||
|
||||
/* Profile handling */
|
||||
#define APPL_PROFILE_INIT(...) appl_ams_init()
|
||||
#define APPL_PROFILE_CONNECT(x) appl_ams_connect(x)
|
||||
#define APPL_SEND_MEASUREMENT(x)appl_send_ams_measurement(x)
|
||||
#define APPL_PROFILE_DISCONNECT_HANDLER(x) appl_ams_server_reinitialize()
|
||||
#define GATT_DB_PROFILE_HANDLER gatt_db_ams_handler
|
||||
#define APPL_PROFILE_HVN_NTF_COMPLETE_HANDLER(x, y, z)
|
||||
#define APPL_PROFILE_HVN_IND_COMPLETE_HANDLER(x, y, z)
|
||||
#define APPL_PROFILE_MTU_UPDT_COMPLETE_HANDLER(x, y) ams_mtu_update(x, y)
|
||||
|
||||
#define APPL_USE_IDLE_TIMER
|
||||
#define APPL_IDLE_TIMEOUT 30
|
||||
#endif /* _H_APPL_AMS_ */
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,158 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file appl_ams_att_server.h
|
||||
//!
|
||||
//! @brief ATT Server Application Header File
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
/**
|
||||
* \file appl_ams_att_server.h
|
||||
*
|
||||
* ATT Server Application Header File
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013. Mindtree Ltd.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _H_APPL_AMS_ATT_SERVER_
|
||||
#define _H_APPL_AMS_ATT_SERVER_
|
||||
|
||||
/* ----------------------------------------- Header File Inclusion */
|
||||
#include "BT_api.h"
|
||||
#include "BT_gatt_db_api.h"
|
||||
|
||||
#define APPL_ATT_WRITE_QUEUE_SIZE 10
|
||||
#define APPL_ATT_MAX_WRITE_BUFFER_SIZE 256 /* 255 */
|
||||
#define APPL_ATT_MTU ATT_MAX_MTU
|
||||
|
||||
#define APPL_SERVER_BUFFER_SIZE 256 /* 256 */
|
||||
|
||||
#define APPL_MAX_GROUP_TYPE_QUERIED 5
|
||||
#define APPL_MAX_HNDL_UUID_LIST_SIZE 5
|
||||
#define APPL_MAX_HNDL_LIST_SIZE 11
|
||||
#define APPL_MAX_HNDL_VALUE_SIZE 5
|
||||
|
||||
/* ATT PDU Request Length */
|
||||
#define APPL_ATT_XCNHG_MTU_REQ_LEN 2
|
||||
#define APPL_ATT_XCNHG_MTU_RSP_LEN 2
|
||||
#define APPL_ATT_FIND_INFO_REQ_LEN 4
|
||||
#define APPL_ATT_FIND_INFO_RSP_LEN_1 5
|
||||
#define APPL_ATT_FIND_INFO_RSP_LEN_2 22
|
||||
#define ATT_FIND_BY_TYPE_VAL_RSP_LEN1 4
|
||||
#define ATT_FIND_BY_TYPE_VAL_RSP_LEN2 21
|
||||
#define APPL_ATT_READ_BY_TYPE_REQ_LEN_1 6
|
||||
#define APPL_ATT_READ_BY_TYPE_REQ_LEN_2 20
|
||||
#define ATT_READ_BY_TYPE_RSP_LEN_1 3
|
||||
#define ATT_READ_BY_TYPE_RSP_LEN_2 22
|
||||
#define APPL_ATT_READ_REQ_LEN 2
|
||||
#define APPL_ATT_READ_RSP_LEN_1 0
|
||||
#define APPL_ATT_READ_RSP_LEN_2 22
|
||||
#define APPL_ATT_READ_BLOB_REQ_LEN 4
|
||||
#define APPL_ATT_READ_BLOB_RSP_LEN_1 0
|
||||
#define APPL_ATT_READ_BLOB_RSP_LEN_2 22
|
||||
#define APPL_ATT_READ_BY_GROUP_REQ_LEN_1 6
|
||||
#define APPL_ATT_READ_BY_GROUP_REQ_LEN_2 20
|
||||
#define APPL_ATT_READ_BY_GROUP_RSP_LEN_1 5
|
||||
#define APPL_ATT_READ_BY_GROUP_RSP_LEN_2 22
|
||||
#define APPL_ATT_EXECUTE_WRITE_REQ_LEN 1
|
||||
|
||||
#define APPL_ATT_INVALID_LEN 0xFF
|
||||
#define APPL_MAX_VALID_ATT_PDU_LEN_CHK 7
|
||||
|
||||
/** Application Defined error */
|
||||
#define APPL_ATT_INVALID_OFFSET 0xFFFF
|
||||
#define ATT_INVALID_ATTR_HANDLE_VAL 0x0000
|
||||
|
||||
#define APPL_MAX_MULTIPLE_READ_COUNT 11
|
||||
|
||||
#define APPL_CHECK_IF_ATT_REQUEST(type)\
|
||||
((((((type) > 0x13) && ((type) < 0x16)) ||\
|
||||
(((type) > 0x1E) && (((type) != ATT_SIGNED_WRITE_CMD) &&\
|
||||
((type) != ATT_WRITE_CMD)))) || (0x01 == ((type) & 0x01)))? BT_FALSE : BT_TRUE)
|
||||
|
||||
#define APPL_ATT_PREPARE_QUEUE_INIT(i)\
|
||||
appl_att_write_queue[(i)].handle_value.handle = 0;\
|
||||
appl_att_write_queue[(i)].offset = 0xFFFF;\
|
||||
appl_att_write_queue[(i)].handle_value.value.len = 0;\
|
||||
appl_att_write_queue[(i)].handle_value.value.val = NULL;
|
||||
|
||||
API_RESULT appl_discover_service
|
||||
(
|
||||
/* IN */ ATT_UUID uuid,
|
||||
/* IN */ UCHAR uuid_frmt
|
||||
);
|
||||
|
||||
API_RESULT appl_write_req
|
||||
(
|
||||
/* IN */ ATT_ATTR_HANDLE handle,
|
||||
/* IN */ ATT_VALUE * value
|
||||
);
|
||||
|
||||
API_RESULT appl_read_req
|
||||
(
|
||||
/* IN */ ATT_ATTR_HANDLE handle
|
||||
);
|
||||
|
||||
API_RESULT appl_att_server_init(void);
|
||||
|
||||
API_RESULT appl_handle_unsupported_op_code (ATT_HANDLE *handle, UCHAR op_code);
|
||||
API_RESULT appl_validate_att_pdu_req_len
|
||||
(
|
||||
UCHAR att_event,
|
||||
UINT16 event_datalen
|
||||
);
|
||||
|
||||
#ifdef SMP_DATA_SIGNING
|
||||
void appl_gatt_signing_complete (API_RESULT status, UCHAR * data, UINT16 datalen);
|
||||
|
||||
void appl_gatt_signing_verification_complete
|
||||
(
|
||||
API_RESULT status,
|
||||
UCHAR * data,
|
||||
UINT16 datalen
|
||||
);
|
||||
#endif /* SMP_DATA_SIGNING */
|
||||
#endif /* _H_APPL_AMS_ATT_SERVER_ */
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file appl_gap_config_params.c
|
||||
//!
|
||||
//! @brief This file contains GAP Configuration Parameters used by the application.
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
/**
|
||||
* \file appl_gap_config_params.c
|
||||
*
|
||||
* This file contains GAP Configuration Parameters used by the application.
|
||||
*/
|
||||
|
||||
|
||||
/* --------------------------------------------- Header File Inclusion */
|
||||
#include "appl_gap.h"
|
||||
|
||||
#ifdef AMS
|
||||
|
||||
/* --------------------------------------------- External Global Variables */
|
||||
|
||||
/* --------------------------------------------- Exported Global Variables */
|
||||
|
||||
/* --------------------------------------------- Static Global Variables */
|
||||
|
||||
#if ((defined APPL_GAP_BROADCASTER_SUPPORT) || (defined APPL_GAP_PERIPHERAL_SUPPORT))
|
||||
/** Advertisement Data Options */
|
||||
const APPL_GAP_ADV_DATA appl_gap_adv_data[APPL_GAP_MAX_ADV_DATA_OPTIONS] =
|
||||
{
|
||||
/* GAP Advertisement Parameters */
|
||||
{
|
||||
{
|
||||
/**
|
||||
* Flags:
|
||||
* 0x01: LE Limited Discoverable Mode
|
||||
* 0x02: LE General Discoverable Mode
|
||||
* 0x04: BR/EDR Not Supported
|
||||
* 0x08: Simultaneous LE and BR/EDR to Same Device
|
||||
* Capable (Controller)
|
||||
* 0x10: Simultaneous LE and BR/EDR to Same Device
|
||||
* Capable (Host)
|
||||
*/
|
||||
0x02, 0x01,
|
||||
(BT_AD_FLAGS_LE_GENERAL_DISC_MODE | BT_AD_FLAGS_LE_BR_EDR_SUPPORT),
|
||||
|
||||
/**
|
||||
* Service UUID List:
|
||||
* Battery Service (0x180F)
|
||||
* DeviceInformation Service (0x180A)
|
||||
*/
|
||||
0x05, 0x03, 0x0F, 0x18, 0x0A, 0x18,
|
||||
|
||||
/**
|
||||
* Shortened Device Name: AM
|
||||
*/
|
||||
0x03, 0x08, 0x41, 0x4d,
|
||||
|
||||
/**
|
||||
* List of 16-bit Service Solicitation UUIDs(AMS UUID)
|
||||
*/
|
||||
0x11, 0x15, 0xDC, 0xF8, 0x55, 0xAD, 0x02, 0xC5, 0xF4, 0x8E, 0x3A, 0x43, 0x36, 0x0F, 0x2B, 0x50, 0xD3, 0x89
|
||||
},
|
||||
|
||||
31
|
||||
}
|
||||
};
|
||||
|
||||
/* Advertisement parameters options */
|
||||
const APPL_GAP_ADV_PARAM appl_gap_adv_param[APPL_GAP_MAX_ADV_PARAM_OPTIONS] =
|
||||
{
|
||||
/* 0 - Normal Advertising Params */
|
||||
{
|
||||
32,
|
||||
|
||||
32,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
},
|
||||
/* 1 - Fast Connection Advertising Params */
|
||||
{
|
||||
32,
|
||||
|
||||
48,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
},
|
||||
/* 2 - Low Power Advertising Params */
|
||||
{
|
||||
1600,
|
||||
|
||||
4000,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
}
|
||||
};
|
||||
|
||||
/* Advertisement Table */
|
||||
APPL_GAP_ADV_INFO appl_gap_adv_table =
|
||||
{
|
||||
appl_gap_adv_data,
|
||||
|
||||
appl_gap_adv_param,
|
||||
|
||||
APPL_GAP_ADV_IDLE
|
||||
};
|
||||
#endif /* APPL_GAP_BROADCASTER || APPL_GAP_PERIPHERAL_SUPPORT */
|
||||
|
||||
#if ((defined APPL_GAP_OBSERVER_SUPPORT) || (defined APPL_GAP_CENTRAL_SUPPORT))
|
||||
/* Scan Parameters Option */
|
||||
const APPL_GAP_SCAN_PARAM appl_gap_scan_param[APPL_GAP_MAX_SCAN_PARAM_OPTIONS] =
|
||||
{
|
||||
/* Normal Scan Params */
|
||||
{
|
||||
32,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
},
|
||||
/* Fast Connection Scan Params */
|
||||
{
|
||||
48,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
},
|
||||
/* Low Power Scan Params */
|
||||
{
|
||||
4000,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
}
|
||||
};
|
||||
|
||||
/* Scan Table */
|
||||
APPL_GAP_SCAN_INFO appl_gap_scan_table =
|
||||
{
|
||||
appl_gap_scan_param,
|
||||
|
||||
APPL_GAP_SCAN_IDLE
|
||||
};
|
||||
#endif /* APPL_GAP_OBSERVER_SUPPORT || APPL_GAP_CENTRAL_SUPPORT */
|
||||
|
||||
#ifdef APPL_GAP_CENTRAL_SUPPORT
|
||||
/* Connection Parameters Options */
|
||||
const APPL_GAP_CONN_PARAM appl_gap_conn_param[APPL_GAP_MAX_CONN_PARAM_OPTIONS] =
|
||||
{
|
||||
{
|
||||
4,
|
||||
|
||||
4,
|
||||
|
||||
0,
|
||||
|
||||
40,
|
||||
|
||||
56,
|
||||
|
||||
0,
|
||||
|
||||
955,
|
||||
|
||||
32,
|
||||
|
||||
32
|
||||
}
|
||||
};
|
||||
|
||||
/* GAP Connection Table */
|
||||
APPL_GAP_CONN_INFO appl_gap_conn_table =
|
||||
{
|
||||
appl_gap_conn_param,
|
||||
|
||||
APPL_GAP_CONN_IDLE
|
||||
};
|
||||
#endif /* APPL_GAP_CENTRAL_SUPPORT */
|
||||
#endif /* AMS */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,157 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file gatt_db.h
|
||||
//!
|
||||
//! @brief GATT Databse.
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
|
||||
/**
|
||||
* \file gatt_db.h
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013. Mindtree Ltd.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _H_GATT_DB_
|
||||
#define _H_GATT_DB_
|
||||
|
||||
/**
|
||||
* addgroup gatt_db_module
|
||||
*/
|
||||
|
||||
/**
|
||||
* defgroup gatt_db_tuneable_param Tuneable Parameters
|
||||
* {
|
||||
* This section defines the Tuneable Constants of Data Base Module.
|
||||
*/
|
||||
|
||||
/** Number of Characteristics in the data base */
|
||||
#define GATT_CHARACTERISTIC_COUNT 13
|
||||
|
||||
/** Number of Services in the data base */
|
||||
#define GATT_SERVICE_COUNT 4
|
||||
|
||||
/** Number of Characteristics that are configurable by the client */
|
||||
#define GATT_DB_MAX_CONFIGUREABLE_CHAR 3
|
||||
|
||||
/** Maximum Length of any Characteristic Value/Descriptor */
|
||||
#define GATT_DB_MAX_VAL_LENGTH 32
|
||||
|
||||
#define GATT_VALUE_ARRAY_SIZE 1
|
||||
|
||||
#define GATT_CONST_VALUE_ARRAY_SIZE 180
|
||||
|
||||
#define GATT_DB_PEER_VALUE_ARRAY_SIZE 4
|
||||
|
||||
#define GATT_DB_MAX_ATTRIBUTES 34
|
||||
|
||||
#define GATT_UUID_ARRAY_SIZE 54
|
||||
|
||||
#define GATT_DB_MAX_TYPE_COUNT 21
|
||||
|
||||
#define GATT_DB_MAX_PEER_CONFIGURATION \
|
||||
(GATT_DB_PEER_VALUE_ARRAY_SIZE * BT_MAX_DEVICE_QUEUE_SIZE)
|
||||
|
||||
/** \} */
|
||||
|
||||
/** Service Instance Reference */
|
||||
|
||||
/** GAP Service */
|
||||
#define GATT_SER_GAP_INST 0
|
||||
|
||||
/** GATT Service */
|
||||
#define GATT_SER_GATT_INST 1
|
||||
|
||||
/** Battery Service */
|
||||
#define GATT_SER_BATTERY_INST 2
|
||||
|
||||
/** DeviceInformation Service */
|
||||
#define GATT_SER_DEV_INFO_INST 3
|
||||
|
||||
|
||||
/** Characteristic Instance Reference */
|
||||
|
||||
/** DeviceName */
|
||||
#define GATT_CHAR_DEV_NAME_INST 0
|
||||
|
||||
/** Appearance */
|
||||
#define GATT_CHAR_APPEARANCE_INST 1
|
||||
|
||||
/** Service Changed */
|
||||
#define GATT_CHAR_SER_CHNGD_INST 2
|
||||
|
||||
/** BatteryLevel */
|
||||
#define GATT_CHAR_BATTERY_LVL_INST 3
|
||||
|
||||
/** ManufacturerName */
|
||||
#define GATT_CHAR_MAN_NAME_INST 4
|
||||
|
||||
/** ModelNumber */
|
||||
#define GATT_CHAR_MODEL_NO_INST 5
|
||||
|
||||
/** SerialNumber */
|
||||
#define GATT_CHAR_SL_NO_INST 6
|
||||
|
||||
/** FirmwareRevision */
|
||||
#define GATT_CHAR_FW_REV_INST 7
|
||||
|
||||
/** HardwareRevision */
|
||||
#define GATT_CHAR_HW_REV_INST 8
|
||||
|
||||
/** SoftwareRevision */
|
||||
#define GATT_CHAR_SW_REV_INST 9
|
||||
|
||||
/** SystemId */
|
||||
#define GATT_CHAR_SYS_ID_INST 10
|
||||
|
||||
/** RegCertDataList */
|
||||
#define GATT_CHAR_REG_CERT_DATA_INST 11
|
||||
|
||||
/** PnPID */
|
||||
#define GATT_CHAR_PNP_ID_INST 12
|
||||
|
||||
#endif /* _H_GATT_DB_ */
|
||||
|
||||
@@ -0,0 +1,666 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file appl_ancs.c
|
||||
//!
|
||||
//! @brief ANCS service.
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
/**
|
||||
* \file appl_ancs.c
|
||||
*
|
||||
*/
|
||||
|
||||
/* --------------------------------------------- Header File Inclusion */
|
||||
#ifdef ANCS
|
||||
#include "appl.h"
|
||||
#include "BT_common.h"
|
||||
#include "BT_hci_api.h"
|
||||
#include "BT_att_api.h"
|
||||
#include "BT_smp_api.h"
|
||||
#include "smp_pl.h"
|
||||
#include "l2cap.h"
|
||||
#include "fsm_defines.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
|
||||
/* ----------------------------------------- Configuration Defines */
|
||||
extern uint32_t am_util_stdio_printf(const char *pcFmt, ...);
|
||||
#undef APPL_TRC
|
||||
#undef APPL_ERR
|
||||
#define APPL_TRC am_util_stdio_printf
|
||||
#define APPL_ERR am_util_stdio_printf
|
||||
|
||||
|
||||
/* ----------------------------------------- Macro Defines */
|
||||
/**@brief Category IDs for iOS notifications. */
|
||||
typedef enum
|
||||
{
|
||||
BLE_ANCS_CATEGORY_ID_OTHER, /**< The iOS notification belongs to the "other" category. */
|
||||
BLE_ANCS_CATEGORY_ID_INCOMING_CALL, /**< The iOS notification belongs to the "Incoming Call" category. */
|
||||
BLE_ANCS_CATEGORY_ID_MISSED_CALL, /**< The iOS notification belongs to the "Missed Call" category. */
|
||||
BLE_ANCS_CATEGORY_ID_VOICE_MAIL, /**< The iOS notification belongs to the "Voice Mail" category. */
|
||||
BLE_ANCS_CATEGORY_ID_SOCIAL, /**< The iOS notification belongs to the "Social" category. */
|
||||
BLE_ANCS_CATEGORY_ID_SCHEDULE, /**< The iOS notification belongs to the "Schedule" category. */
|
||||
BLE_ANCS_CATEGORY_ID_EMAIL, /**< The iOS notification belongs to the "E-mail" category. */
|
||||
BLE_ANCS_CATEGORY_ID_NEWS, /**< The iOS notification belongs to the "News" category. */
|
||||
BLE_ANCS_CATEGORY_ID_HEALTH_AND_FITNESS, /**< The iOS notification belongs to the "Health and Fitness" category. */
|
||||
BLE_ANCS_CATEGORY_ID_BUSINESS_AND_FINANCE, /**< The iOS notification belongs to the "Buisness and Finance" category. */
|
||||
BLE_ANCS_CATEGORY_ID_LOCATION, /**< The iOS notification belongs to the "Location" category. */
|
||||
BLE_ANCS_CATEGORY_ID_ENTERTAINMENT /**< The iOS notification belongs to the "Entertainment" category. */
|
||||
} ancc_category_id_values_t;
|
||||
|
||||
/**@brief Event IDs for iOS notifications. */
|
||||
typedef enum
|
||||
{
|
||||
BLE_ANCS_EVENT_ID_NOTIFICATION_ADDED, /**< The iOS notification was added. */
|
||||
BLE_ANCS_EVENT_ID_NOTIFICATION_MODIFIED, /**< The iOS notification was modified. */
|
||||
BLE_ANCS_EVENT_ID_NOTIFICATION_REMOVED /**< The iOS notification was removed. */
|
||||
} ancc_evt_id_values_t;
|
||||
|
||||
/**@brief Control point command IDs that the Notification Consumer can send to the Notification Provider. */
|
||||
typedef enum
|
||||
{
|
||||
BLE_ANCS_COMMAND_ID_GET_NOTIF_ATTRIBUTES, /**< Requests attributes to be sent from the NP to the NC for a given notification. */
|
||||
BLE_ANCS_COMMAND_ID_GET_APP_ATTRIBUTES, /**< Requests attributes to be sent from the NP to the NC for a given iOS App. */
|
||||
BLE_ANCS_COMMAND_ID_GET_PERFORM_NOTIF_ACTION, /**< Requests an action to be performed on a given notification, for example dismiss an alarm. */
|
||||
} ancc_command_id_values_t;
|
||||
|
||||
/**@brief IDs for iOS notification attributes. */
|
||||
typedef enum
|
||||
{
|
||||
BLE_ANCS_NOTIF_ATTR_ID_APP_IDENTIFIER, /**< Identifies that the attribute data is of an "App Identifier" type. */
|
||||
BLE_ANCS_NOTIF_ATTR_ID_TITLE, /**< Identifies that the attribute data is a "Title". Needs to be followed by a 2-bytes max length parameter*/
|
||||
BLE_ANCS_NOTIF_ATTR_ID_SUBTITLE, /**< Identifies that the attribute data is a "Subtitle". Needs to be followed by a 2-bytes max length parameter*/
|
||||
BLE_ANCS_NOTIF_ATTR_ID_MESSAGE, /**< Identifies that the attribute data is a "Message". Needs to be followed by a 2-bytes max length parameter*/
|
||||
BLE_ANCS_NOTIF_ATTR_ID_MESSAGE_SIZE, /**< Identifies that the attribute data is a "Message Size". */
|
||||
BLE_ANCS_NOTIF_ATTR_ID_DATE, /**< Identifies that the attribute data is a "Date". */
|
||||
BLE_ANCS_NOTIF_ATTR_ID_POSITIVE_ACTION_LABEL, /**< The notification has a "Positive action" that can be executed associated with it. */
|
||||
BLE_ANCS_NOTIF_ATTR_ID_NEGATIVE_ACTION_LABEL, /**< The notification has a "Negative action" that can be executed associated with it. */
|
||||
} ancc_notif_attr_id_values_t;
|
||||
|
||||
/**@brief Typedef for iOS notifications. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t event_id; /**< This field informs the accessory whether the given iOS notification was added, modified, or removed. The enumerated values for this field are defined in EventID Values.. */
|
||||
uint8_t event_flags; /**< A bitmask whose set bits inform an NC of specificities with the iOS notification. */
|
||||
uint8_t category_id; /**< A numerical value providing a category in which the iOS notification can be classified. */
|
||||
uint8_t category_count; /**< The current number of active iOS notifications in the given category. */
|
||||
uint32_t notification_uid; /**< A 32-bit numerical value that is the unique identifier (UID) for the iOS notification. */
|
||||
} ancc_notif_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ANCS_DISCONNECTED,
|
||||
ANCS_CONNECTED,
|
||||
ANCS_BONDED,
|
||||
ANCS_DISCOVERED,
|
||||
} ancs_appl_state_t;
|
||||
|
||||
/* ----------------------------------------- External Global Variables */
|
||||
void appl_profile_operations (void);
|
||||
void AncsGetNotificationAttribute(uint32_t notiUid);
|
||||
extern BT_DEVICE_ADDR g_bd_addr;
|
||||
|
||||
/* ----------------------------------------- Exported Global Variables */
|
||||
QueueHandle_t xNtfUIDQueue;
|
||||
|
||||
/* ----------------------------------------- Static Global Variables */
|
||||
DECL_STATIC UCHAR write_response = 0;
|
||||
DECL_STATIC API_RESULT gResult = 0;
|
||||
DECL_STATIC ancs_appl_state_t appl_ancs_state = ANCS_DISCONNECTED;
|
||||
DECL_STATIC ATT_UUID ancs_service_uuid128 = {.uuid_128.value = {0xD0, 0x00, 0x2D, 0x12, 0x1E, 0x4B, 0x0F, 0xA4, 0x99, 0x4E, 0xCE, 0xB5, 0x31, 0xF4, 0x05, 0x79}};
|
||||
DECL_STATIC ATT_UUID ANCS_ControlPoint_UUID = {.uuid_128.value = {0xD9, 0xD9, 0xAA, 0xFD, 0xBD, 0x9B, 0x21, 0x98, 0xA8, 0x49, 0xE1, 0x45, 0xF3, 0xD8, 0xD1, 0x69}};
|
||||
DECL_STATIC ATT_UUID ANCS_NotificationSource_UUID = {.uuid_128.value = {0xBD, 0x1D, 0xA2, 0x99, 0xE6, 0x25, 0x58, 0x8C, 0xD9, 0x42, 0x01, 0x63, 0x0D, 0x12, 0xBF, 0x9F}};
|
||||
DECL_STATIC ATT_UUID ANCS_DataSource_UUID = {.uuid_128.value = {0xFB, 0x7B, 0x7C, 0xCE, 0x6A, 0xB3, 0x44, 0xBE, 0xB5, 0x4B, 0xD6, 0x24, 0xE9, 0xC6, 0xEA, 0x22}};
|
||||
|
||||
/* BLE Connection Handle */
|
||||
//DECL_STATIC UINT16 appl_ble_connection_handle;
|
||||
|
||||
/** ANCS Characteristic related information */
|
||||
typedef struct
|
||||
{
|
||||
/* ANCS Service */
|
||||
|
||||
/* Notification Source */
|
||||
ATT_ATTR_HANDLE ancs_notification_source_hdl;
|
||||
|
||||
/* Notification Source - CCC */
|
||||
ATT_ATTR_HANDLE ancs_notification_source_ccc_hdl;
|
||||
|
||||
/* Control Point */
|
||||
ATT_ATTR_HANDLE ancs_control_point_hdl;
|
||||
|
||||
/* Data Source */
|
||||
ATT_ATTR_HANDLE ancs_data_source_hdl;
|
||||
|
||||
/* Data Source - CCC */
|
||||
ATT_ATTR_HANDLE ancs_data_source_ccc_hdl;
|
||||
|
||||
} ANCS_CHAR_INFO;
|
||||
|
||||
#define APPL_CLI_CNFG_VAL_LENGTH 2
|
||||
DECL_STATIC ANCS_CHAR_INFO ancs_char_info;
|
||||
|
||||
#ifdef APPL_MENU_OPS
|
||||
BT_DEVICE_ADDR g_peer_bd_addr;
|
||||
|
||||
static UCHAR ancs_client_menu[] =
|
||||
"\n\
|
||||
\r\n\
|
||||
1. Bond with peer \r\n\
|
||||
\r\n\
|
||||
2. Discover ANCS \r\n\
|
||||
\r\n\
|
||||
3. Set Data Source CCCD \r\n\
|
||||
\r\n\
|
||||
4. Set Notification Source CCCD \r\n\
|
||||
\r\n\
|
||||
5. Get Notification Attribute by UID \r\n\
|
||||
\r\n\
|
||||
Your Option? \0";
|
||||
#endif /* APPL_MENU_OPS */
|
||||
|
||||
/* --------------------------------------------- Constants */
|
||||
|
||||
|
||||
/* --------------------------------------------- Static Global Variables */
|
||||
|
||||
|
||||
/* --------------------------------------------- Functions */
|
||||
|
||||
void appl_bond_with_peer(void)
|
||||
{
|
||||
API_RESULT retval;
|
||||
/* If connection is successful, initiate bonding [Step 2(c)] */
|
||||
|
||||
SMP_AUTH_INFO auth;
|
||||
SMP_BD_ADDR smp_peer_bd_addr;
|
||||
SMP_BD_HANDLE smp_bd_handle;
|
||||
|
||||
APPL_TRC("\n<<appl_bond_with_peer>>\n");
|
||||
|
||||
auth.param = 1;
|
||||
auth.bonding = 1;
|
||||
auth.ekey_size = 12;
|
||||
auth.security = SMP_SEC_LEVEL_1;
|
||||
|
||||
BT_COPY_BD_ADDR(smp_peer_bd_addr.addr, g_bd_addr.addr);
|
||||
BT_COPY_TYPE(smp_peer_bd_addr.type, g_bd_addr.type);
|
||||
|
||||
retval = BT_smp_get_bd_handle
|
||||
(
|
||||
&smp_peer_bd_addr,
|
||||
&smp_bd_handle
|
||||
);
|
||||
|
||||
if (API_SUCCESS == retval)
|
||||
{
|
||||
retval = BT_smp_authenticate (&smp_bd_handle, &auth);
|
||||
}
|
||||
|
||||
if (API_SUCCESS != retval)
|
||||
{
|
||||
APPL_TRC (
|
||||
"Initiation of Authentication Failed. Reason 0x%04X\n",
|
||||
retval);
|
||||
}
|
||||
|
||||
/**
|
||||
* Application will receive authentication complete event,
|
||||
* in SMP Callback.
|
||||
*
|
||||
* Look for 'SMP_AUTHENTICATION_COMPLETE' event handling in
|
||||
* 'appl_smp_callback'.
|
||||
*/
|
||||
}
|
||||
|
||||
void appl_ancs_init(void)
|
||||
{
|
||||
appl_ancs_state = ANCS_DISCONNECTED;
|
||||
APPL_TRC("\n\n<<appl_ancs_init>>\n\n");
|
||||
}
|
||||
|
||||
void appl_ancs_connect(APPL_HANDLE * appl_handle)
|
||||
{
|
||||
APPL_STATE_T state = GET_APPL_STATE(*appl_handle);
|
||||
|
||||
if ( state == SL_0_TRANSPORT_OPERATING && appl_ancs_state == ANCS_DISCONNECTED )
|
||||
{
|
||||
appl_ancs_state = ANCS_CONNECTED;
|
||||
APPL_TRC("\n\n<<CONNECTED>>\n\n");
|
||||
}
|
||||
else if ( state == SL_0_TRANSPORT_OPERATING && appl_ancs_state == ANCS_DISCOVERED )
|
||||
{
|
||||
appl_ancs_state = ANCS_BONDED;
|
||||
APPL_TRC("\n\n<<BONDED>>\n\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
appl_ancs_state = ANCS_DISCONNECTED;
|
||||
APPL_TRC("\n\n<<DISCONNECTED>>\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
void appl_search_complete(void)
|
||||
{
|
||||
appl_ancs_state = ANCS_DISCOVERED;
|
||||
APPL_TRC("\n\n<<DISCOVERED>>\n\n");
|
||||
}
|
||||
|
||||
void appl_recvice_att_event(UCHAR att_event, API_RESULT event_result)
|
||||
{
|
||||
if ( att_event == ATT_WRITE_RSP )
|
||||
{
|
||||
write_response = 1;
|
||||
gResult = 0;
|
||||
}
|
||||
else if ( att_event == ATT_ERROR_RSP )
|
||||
{
|
||||
gResult = event_result;
|
||||
}
|
||||
}
|
||||
|
||||
void appl_manage_trasnfer (GATT_DB_HANDLE handle, UINT16 config)
|
||||
{
|
||||
APPL_TRC("\n\n<<appl_manage_trasnfer>>\n\n");
|
||||
}
|
||||
|
||||
void appl_send_ancs_measurement (APPL_HANDLE * handle)
|
||||
{
|
||||
APPL_TRC("\n\n<<appl_send_ancs_measurement>>\n\n");
|
||||
}
|
||||
|
||||
|
||||
void appl_timer_expiry_handler (void *data, UINT16 datalen)
|
||||
{
|
||||
APPL_TRC("\n\n<<appl_timer_expiry_handler>>\n\n");
|
||||
}
|
||||
|
||||
void appl_ancs_server_reinitialize (void)
|
||||
{
|
||||
appl_ancs_state = ANCS_DISCONNECTED;
|
||||
APPL_TRC("\n\n<<appl_ancs_server_reinitialize>>\n\n");
|
||||
}
|
||||
|
||||
|
||||
void ancs_mtu_update(APPL_HANDLE * appl_handle, UINT16 t_mtu)
|
||||
{
|
||||
UINT16 mtu = 0;
|
||||
|
||||
BT_att_access_mtu(&APPL_GET_ATT_INSTANCE(*appl_handle),
|
||||
&mtu);
|
||||
|
||||
APPL_TRC("appl_handle 0x%x t_mtu = %d %d\n", *appl_handle, t_mtu, mtu);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------- ATT related Functions */
|
||||
void appl_rcv_service_desc (UINT16 config, ATT_UUID uuid, UINT16 value_handle)
|
||||
{
|
||||
/* Populate Needed CCCDs here */
|
||||
if (GATT_CLIENT_CONFIG == config)
|
||||
{
|
||||
if ( memcmp(&uuid, &ANCS_NotificationSource_UUID, ATT_128_BIT_UUID_SIZE) == 0 )
|
||||
{
|
||||
ancs_char_info.ancs_notification_source_ccc_hdl = value_handle;
|
||||
}
|
||||
else if ( memcmp(&uuid, &ANCS_DataSource_UUID, ATT_128_BIT_UUID_SIZE) == 0 )
|
||||
{
|
||||
ancs_char_info.ancs_data_source_ccc_hdl = value_handle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void appl_rcv_service_char (ATT_UUID uuid, UINT16 value_handle)
|
||||
{
|
||||
if ( memcmp(&uuid, &ANCS_NotificationSource_UUID, ATT_128_BIT_UUID_SIZE) == 0 )
|
||||
{
|
||||
ancs_char_info.ancs_notification_source_hdl = value_handle;
|
||||
}
|
||||
else if ( memcmp(&uuid, &ANCS_ControlPoint_UUID, ATT_128_BIT_UUID_SIZE) == 0 )
|
||||
{
|
||||
ancs_char_info.ancs_control_point_hdl = value_handle;
|
||||
}
|
||||
else if ( memcmp(&uuid, &ANCS_DataSource_UUID, ATT_128_BIT_UUID_SIZE) == 0 )
|
||||
{
|
||||
ancs_char_info.ancs_data_source_hdl = value_handle;
|
||||
}
|
||||
}
|
||||
|
||||
void Wait4WrtRsp(void)
|
||||
{
|
||||
const TickType_t xDelay = 10 / portTICK_PERIOD_MS;
|
||||
UCHAR i = 0;
|
||||
|
||||
while ( !write_response )
|
||||
{
|
||||
vTaskDelay( xDelay );
|
||||
if (i++ > 10 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
write_response = 0;
|
||||
}
|
||||
|
||||
void appl_discover_ANCS(void)
|
||||
{
|
||||
APPL_TRC("\n<<appl_discover_ANCS>>\n");
|
||||
appl_discover_service
|
||||
(
|
||||
ancs_service_uuid128,
|
||||
ATT_128_BIT_UUID_FORMAT
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void AncsSubscribeNotifications(void)
|
||||
{
|
||||
ATT_VALUE att_value;
|
||||
UINT16 cli_cfg;
|
||||
UCHAR cfg_val[APPL_CLI_CNFG_VAL_LENGTH];
|
||||
|
||||
APPL_TRC("\n++<<AncsSubscribeNotifications>>\n");
|
||||
|
||||
cli_cfg = GATT_CLI_CNFG_NOTIFICATION;
|
||||
BT_PACK_LE_2_BYTE(cfg_val, &cli_cfg);
|
||||
att_value.len = APPL_CLI_CNFG_VAL_LENGTH;
|
||||
att_value.val = cfg_val;
|
||||
appl_write_req(ancs_char_info.ancs_data_source_ccc_hdl, &att_value);
|
||||
|
||||
Wait4WrtRsp();
|
||||
|
||||
cli_cfg = GATT_CLI_CNFG_NOTIFICATION;
|
||||
BT_PACK_LE_2_BYTE(cfg_val, &cli_cfg);
|
||||
att_value.len = APPL_CLI_CNFG_VAL_LENGTH;
|
||||
att_value.val = cfg_val;
|
||||
appl_write_req(ancs_char_info.ancs_notification_source_ccc_hdl, &att_value);
|
||||
|
||||
Wait4WrtRsp();
|
||||
|
||||
APPL_TRC("\n--<<AncsSubscribeNotifications(0x%04X)>>\n", gResult);
|
||||
}
|
||||
|
||||
void appl_profile_operations (void)
|
||||
{
|
||||
|
||||
const TickType_t xDelay = 100 / portTICK_PERIOD_MS;
|
||||
UINT32 NtfUID;
|
||||
write_response = 0;
|
||||
xNtfUIDQueue = 0;
|
||||
xNtfUIDQueue = xQueueCreate( 10, sizeof(UINT32) );
|
||||
|
||||
fsm_post_event
|
||||
(
|
||||
APPL_FSM_ID,
|
||||
ev_appl_device_init_req,
|
||||
NULL
|
||||
);
|
||||
|
||||
while ( appl_ancs_state != ANCS_CONNECTED)
|
||||
{
|
||||
vTaskDelay( xDelay );
|
||||
}
|
||||
|
||||
appl_discover_ANCS();
|
||||
|
||||
while ( appl_ancs_state != ANCS_DISCOVERED )
|
||||
{
|
||||
vTaskDelay( xDelay );
|
||||
}
|
||||
|
||||
AncsSubscribeNotifications();
|
||||
|
||||
if ( gResult == 0x0305 /* insufficient authentication */ ||
|
||||
gResult == 0x030F /* insufficient Encryption */ )
|
||||
{
|
||||
appl_bond_with_peer();
|
||||
while ( appl_ancs_state != ANCS_BONDED )
|
||||
{
|
||||
vTaskDelay( xDelay );
|
||||
}
|
||||
AncsSubscribeNotifications();
|
||||
}
|
||||
else
|
||||
{
|
||||
appl_ancs_state = ANCS_BONDED;
|
||||
}
|
||||
|
||||
while ( appl_ancs_state != ANCS_DISCONNECTED )
|
||||
{
|
||||
if ( xQueueReceive( xNtfUIDQueue, &( NtfUID ), ( TickType_t ) 10 ) )
|
||||
{
|
||||
AncsGetNotificationAttribute(NtfUID);
|
||||
}
|
||||
}
|
||||
|
||||
if ( xNtfUIDQueue != 0 )
|
||||
{
|
||||
vQueueDelete( xNtfUIDQueue);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void AncsDumpBytes (UCHAR *buffer, UINT16 length)
|
||||
{
|
||||
char hex_stream[49];
|
||||
char char_stream[17];
|
||||
UINT32 i;
|
||||
UINT16 offset, count;
|
||||
UCHAR c;
|
||||
|
||||
APPL_TRC (
|
||||
"-------------------------------------------------------------------\n");
|
||||
|
||||
count = 0;
|
||||
offset = 0;
|
||||
for ( i = 0; i < length; i++ )
|
||||
{
|
||||
c = buffer[i];
|
||||
sprintf(hex_stream + offset, "%02X ", c);
|
||||
|
||||
if ( (c >= 0x20) && (c <= 0x7E) )
|
||||
{
|
||||
char_stream[count] = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
char_stream[count] = '.';
|
||||
}
|
||||
|
||||
count ++;
|
||||
offset += 3;
|
||||
|
||||
if ( 16 == count )
|
||||
{
|
||||
char_stream[count] = '\0';
|
||||
count = 0;
|
||||
offset = 0;
|
||||
|
||||
APPL_TRC ("%s %s\n",
|
||||
hex_stream, char_stream);
|
||||
|
||||
BT_mem_set(hex_stream, 0, 49);
|
||||
BT_mem_set(char_stream, 0, 17);
|
||||
}
|
||||
}
|
||||
|
||||
if ( offset != 0 )
|
||||
{
|
||||
char_stream[count] = '\0';
|
||||
|
||||
/* Maintain the alignment */
|
||||
APPL_TRC ("%-48s %s\n",
|
||||
hex_stream, char_stream);
|
||||
}
|
||||
|
||||
APPL_TRC (
|
||||
"-------------------------------------------------------------------\n\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void AncsGetNotificationAttribute(uint32_t notiUid)
|
||||
{
|
||||
API_RESULT retval;
|
||||
ATT_VALUE att_value;
|
||||
// An example to get notification attributes
|
||||
uint16_t max_len = 256;
|
||||
uint8_t buf[19]; // retrieve the complete attribute list
|
||||
|
||||
APPL_TRC("++<<GetNtfUID:%X>>\n", notiUid);
|
||||
|
||||
buf[0] = BLE_ANCS_COMMAND_ID_GET_NOTIF_ATTRIBUTES; // put command
|
||||
uint8_t *p = &buf[1];
|
||||
BT_UNPACK_LE_4_BYTE(p, (uint8_t*)(¬iUid)); // encode notification uid
|
||||
|
||||
// encode attribute IDs
|
||||
buf[5] = BLE_ANCS_NOTIF_ATTR_ID_APP_IDENTIFIER;
|
||||
buf[6] = BLE_ANCS_NOTIF_ATTR_ID_TITLE;
|
||||
// 2 byte length
|
||||
buf[7] = max_len;
|
||||
buf[8] = max_len >> 8;
|
||||
buf[9] = BLE_ANCS_NOTIF_ATTR_ID_SUBTITLE;
|
||||
buf[10] = max_len;
|
||||
buf[11] = max_len >> 8;
|
||||
buf[12] = BLE_ANCS_NOTIF_ATTR_ID_MESSAGE;
|
||||
buf[13] = max_len;
|
||||
buf[14] = max_len >> 8;
|
||||
buf[15] = BLE_ANCS_NOTIF_ATTR_ID_MESSAGE_SIZE;
|
||||
buf[16] = BLE_ANCS_NOTIF_ATTR_ID_DATE;
|
||||
buf[17] = BLE_ANCS_NOTIF_ATTR_ID_POSITIVE_ACTION_LABEL;
|
||||
buf[18] = BLE_ANCS_NOTIF_ATTR_ID_NEGATIVE_ACTION_LABEL;
|
||||
|
||||
att_value.len = 19;
|
||||
att_value.val = buf;
|
||||
retval = appl_write_req(ancs_char_info.ancs_control_point_hdl, &att_value);
|
||||
|
||||
//APPL_TRC ("retval 0x%04X\n", retval);
|
||||
if ( retval == API_SUCCESS )
|
||||
{
|
||||
Wait4WrtRsp();
|
||||
}
|
||||
APPL_TRC("--<<GetNtfUID:%X>>\n", notiUid);
|
||||
|
||||
}
|
||||
|
||||
void AncsNotificationCb(UCHAR *event_data, UINT16 event_datalen)
|
||||
{
|
||||
ATT_ATTR_HANDLE attr_handle;
|
||||
ancc_notif_t *NotificationSource;
|
||||
|
||||
BT_UNPACK_LE_2_BYTE(&attr_handle, event_data);
|
||||
|
||||
if ( attr_handle == ancs_char_info.ancs_notification_source_hdl )
|
||||
{
|
||||
NotificationSource = (ancc_notif_t *)(event_data + 2);
|
||||
|
||||
switch(NotificationSource->category_id)
|
||||
{
|
||||
case(BLE_ANCS_CATEGORY_ID_OTHER):
|
||||
APPL_TRC("OTHER(%X)\n", NotificationSource->notification_uid);
|
||||
break;
|
||||
|
||||
case(BLE_ANCS_CATEGORY_ID_INCOMING_CALL):
|
||||
APPL_TRC("INCOMING_CALL(%X)\n", NotificationSource->notification_uid);
|
||||
break;
|
||||
|
||||
case(BLE_ANCS_CATEGORY_ID_MISSED_CALL):
|
||||
APPL_TRC("MISSED_CALL(%X)\n", NotificationSource->notification_uid);
|
||||
break;
|
||||
|
||||
case(BLE_ANCS_CATEGORY_ID_VOICE_MAIL):
|
||||
APPL_TRC("VOICE_MAIL(%X)\n", NotificationSource->notification_uid);
|
||||
break;
|
||||
|
||||
case(BLE_ANCS_CATEGORY_ID_SOCIAL):
|
||||
APPL_TRC("SOCIAL(%X)\n", NotificationSource->notification_uid);
|
||||
break;
|
||||
|
||||
case(BLE_ANCS_CATEGORY_ID_SCHEDULE):
|
||||
APPL_TRC("SCHEDULE(%X)\n", NotificationSource->notification_uid);
|
||||
break;
|
||||
|
||||
case(BLE_ANCS_CATEGORY_ID_EMAIL):
|
||||
APPL_TRC("EMAIL(%X)\n", NotificationSource->notification_uid);
|
||||
break;
|
||||
|
||||
case(BLE_ANCS_CATEGORY_ID_NEWS):
|
||||
APPL_TRC("NEWS(%X)\n", NotificationSource->notification_uid);
|
||||
break;
|
||||
|
||||
case(BLE_ANCS_CATEGORY_ID_HEALTH_AND_FITNESS):
|
||||
APPL_TRC("HEALTH_AND_FITNESS(%X)\n", NotificationSource->notification_uid);
|
||||
break;
|
||||
|
||||
case(BLE_ANCS_CATEGORY_ID_BUSINESS_AND_FINANCE):
|
||||
APPL_TRC("BUSINESS_AND_FINANCE(%X)\n", NotificationSource->notification_uid);
|
||||
break;
|
||||
|
||||
case(BLE_ANCS_CATEGORY_ID_LOCATION):
|
||||
APPL_TRC("LOCATION(%X)\n", NotificationSource->notification_uid);
|
||||
break;
|
||||
|
||||
case(BLE_ANCS_CATEGORY_ID_ENTERTAINMENT):
|
||||
APPL_TRC("ENTERTAINMENT(%X)\n", NotificationSource->notification_uid);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//APPL_TRC("Spaces %d\n", uxQueueSpacesAvailable(xNtfUIDQueue));
|
||||
xQueueSend( xNtfUIDQueue, ( void * ) &(NotificationSource->notification_uid), ( TickType_t ) 0 );
|
||||
}
|
||||
#if 0
|
||||
else if ( attr_handle == ancs_char_info.ancs_data_source_hdl )
|
||||
{
|
||||
APPL_TRC("data source\n");
|
||||
}
|
||||
#endif
|
||||
AncsDumpBytes(event_data + 2, (event_datalen-2));
|
||||
|
||||
}
|
||||
#endif /* ANCS */
|
||||
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file appl_ancs.h
|
||||
//!
|
||||
//! @brief Application Header File for ANCS.
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
|
||||
/**
|
||||
* \file appl_ancs.h
|
||||
*
|
||||
* Application Header File for ANCS.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013. Mindtree Ltd.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _H_APPL_ANCS_
|
||||
#define _H_APPL_ANCS_
|
||||
|
||||
/* ----------------------------------------- Header File Inclusion */
|
||||
#include "BT_api.h"
|
||||
#include "BT_gatt_db_api.h"
|
||||
#include "gatt_db.h"
|
||||
#include "appl.h"
|
||||
#include "appl_ancs_att_server.h"
|
||||
|
||||
/* ----------------------------------------- Data Types/ Structures */
|
||||
typedef struct
|
||||
{
|
||||
UCHAR index;
|
||||
|
||||
UCHAR length;
|
||||
|
||||
}APPL_HRS_OBS_DATA_INFO;
|
||||
|
||||
/* --------------------------------------------- Global Definitions */
|
||||
/** LSB of error code has to be spec defined */
|
||||
#define APPL_HR_CNTRL_PNT_NOT_SUPPORTED (APPL_ERR_ID | 0x80)
|
||||
|
||||
/* --------------------------------------------- Functions */
|
||||
void appl_ancs_init(void);
|
||||
void appl_manage_trasnfer (GATT_DB_HANDLE handle, UINT16 config);
|
||||
void appl_timer_expiry_handler (void *data, UINT16 datalen);
|
||||
void appl_ancs_connect(DEVICE_HANDLE * dq_handle);
|
||||
void appl_send_ancs_measurement (APPL_HANDLE * handle);
|
||||
void appl_ancs_server_reinitialize (void);
|
||||
void appl_rcv_service_desc (UINT16 config, ATT_UUID uuid, UINT16 value_handle);
|
||||
void appl_rcv_service_char (ATT_UUID uuid, UINT16 value_handle);
|
||||
API_RESULT appl_hr_control_point_handler
|
||||
(
|
||||
GATT_DB_HANDLE * handle,
|
||||
ATT_VALUE * value
|
||||
);
|
||||
API_RESULT appl_att_callback
|
||||
(
|
||||
ATT_HANDLE * handle,
|
||||
UCHAR event_type,
|
||||
API_RESULT event_result,
|
||||
UCHAR * event_data,
|
||||
UINT16 event_datalen
|
||||
);
|
||||
|
||||
void ancs_mtu_update(APPL_HANDLE * appl_handle, UINT16 t_mtu);
|
||||
|
||||
/* Profile handling */
|
||||
#define APPL_PROFILE_INIT(...) appl_ancs_init()
|
||||
#define APPL_PROFILE_CONNECT(x) appl_ancs_connect(x)
|
||||
#define APPL_SEND_MEASUREMENT(x)appl_send_ancs_measurement(x)
|
||||
#define APPL_PROFILE_DISCONNECT_HANDLER(x) appl_ancs_server_reinitialize()
|
||||
#define GATT_DB_PROFILE_HANDLER gatt_db_ancs_handler
|
||||
#define APPL_PROFILE_HVN_NTF_COMPLETE_HANDLER(x, y, z)
|
||||
#define APPL_PROFILE_HVN_IND_COMPLETE_HANDLER(x, y, z)
|
||||
#define APPL_PROFILE_MTU_UPDT_COMPLETE_HANDLER(x, y) ancs_mtu_update(x, y)
|
||||
|
||||
#define APPL_USE_IDLE_TIMER
|
||||
#define APPL_IDLE_TIMEOUT 30
|
||||
#endif /* _H_APPL_ANCS_ */
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,158 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file appl_ancs_att_server.h
|
||||
//!
|
||||
//! @brief ATT Server Application Header File
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
/**
|
||||
* \file appl_ancs_att_server.h
|
||||
*
|
||||
* ATT Server Application Header File
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013. Mindtree Ltd.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _H_APPL_ANCS_ATT_SERVER_
|
||||
#define _H_APPL_ANCS_ATT_SERVER_
|
||||
|
||||
/* ----------------------------------------- Header File Inclusion */
|
||||
#include "BT_api.h"
|
||||
#include "BT_gatt_db_api.h"
|
||||
|
||||
#define APPL_ATT_WRITE_QUEUE_SIZE 10
|
||||
#define APPL_ATT_MAX_WRITE_BUFFER_SIZE 256 /* 255 */
|
||||
#define APPL_ATT_MTU ATT_MAX_MTU
|
||||
|
||||
#define APPL_SERVER_BUFFER_SIZE 256 /* 256 */
|
||||
|
||||
#define APPL_MAX_GROUP_TYPE_QUERIED 5
|
||||
#define APPL_MAX_HNDL_UUID_LIST_SIZE 5
|
||||
#define APPL_MAX_HNDL_LIST_SIZE 11
|
||||
#define APPL_MAX_HNDL_VALUE_SIZE 5
|
||||
|
||||
/* ATT PDU Request Length */
|
||||
#define APPL_ATT_XCNHG_MTU_REQ_LEN 2
|
||||
#define APPL_ATT_XCNHG_MTU_RSP_LEN 2
|
||||
#define APPL_ATT_FIND_INFO_REQ_LEN 4
|
||||
#define APPL_ATT_FIND_INFO_RSP_LEN_1 5
|
||||
#define APPL_ATT_FIND_INFO_RSP_LEN_2 22
|
||||
#define ATT_FIND_BY_TYPE_VAL_RSP_LEN1 4
|
||||
#define ATT_FIND_BY_TYPE_VAL_RSP_LEN2 21
|
||||
#define APPL_ATT_READ_BY_TYPE_REQ_LEN_1 6
|
||||
#define APPL_ATT_READ_BY_TYPE_REQ_LEN_2 20
|
||||
#define ATT_READ_BY_TYPE_RSP_LEN_1 3
|
||||
#define ATT_READ_BY_TYPE_RSP_LEN_2 22
|
||||
#define APPL_ATT_READ_REQ_LEN 2
|
||||
#define APPL_ATT_READ_RSP_LEN_1 0
|
||||
#define APPL_ATT_READ_RSP_LEN_2 22
|
||||
#define APPL_ATT_READ_BLOB_REQ_LEN 4
|
||||
#define APPL_ATT_READ_BLOB_RSP_LEN_1 0
|
||||
#define APPL_ATT_READ_BLOB_RSP_LEN_2 22
|
||||
#define APPL_ATT_READ_BY_GROUP_REQ_LEN_1 6
|
||||
#define APPL_ATT_READ_BY_GROUP_REQ_LEN_2 20
|
||||
#define APPL_ATT_READ_BY_GROUP_RSP_LEN_1 5
|
||||
#define APPL_ATT_READ_BY_GROUP_RSP_LEN_2 22
|
||||
#define APPL_ATT_EXECUTE_WRITE_REQ_LEN 1
|
||||
|
||||
#define APPL_ATT_INVALID_LEN 0xFF
|
||||
#define APPL_MAX_VALID_ATT_PDU_LEN_CHK 7
|
||||
|
||||
/** Application Defined error */
|
||||
#define APPL_ATT_INVALID_OFFSET 0xFFFF
|
||||
#define ATT_INVALID_ATTR_HANDLE_VAL 0x0000
|
||||
|
||||
#define APPL_MAX_MULTIPLE_READ_COUNT 11
|
||||
|
||||
#define APPL_CHECK_IF_ATT_REQUEST(type)\
|
||||
((((((type) > 0x13) && ((type) < 0x16)) ||\
|
||||
(((type) > 0x1E) && (((type) != ATT_SIGNED_WRITE_CMD) &&\
|
||||
((type) != ATT_WRITE_CMD)))) || (0x01 == ((type) & 0x01)))? BT_FALSE : BT_TRUE)
|
||||
|
||||
#define APPL_ATT_PREPARE_QUEUE_INIT(i)\
|
||||
appl_att_write_queue[(i)].handle_value.handle = 0;\
|
||||
appl_att_write_queue[(i)].offset = 0xFFFF;\
|
||||
appl_att_write_queue[(i)].handle_value.value.len = 0;\
|
||||
appl_att_write_queue[(i)].handle_value.value.val = NULL;
|
||||
|
||||
API_RESULT appl_discover_service
|
||||
(
|
||||
/* IN */ ATT_UUID uuid,
|
||||
/* IN */ UCHAR uuid_frmt
|
||||
);
|
||||
|
||||
API_RESULT appl_write_req
|
||||
(
|
||||
/* IN */ ATT_ATTR_HANDLE handle,
|
||||
/* IN */ ATT_VALUE * value
|
||||
);
|
||||
|
||||
API_RESULT appl_read_req
|
||||
(
|
||||
/* IN */ ATT_ATTR_HANDLE handle
|
||||
);
|
||||
|
||||
API_RESULT appl_att_server_init(void);
|
||||
|
||||
API_RESULT appl_handle_unsupported_op_code (ATT_HANDLE *handle, UCHAR op_code);
|
||||
API_RESULT appl_validate_att_pdu_req_len
|
||||
(
|
||||
UCHAR att_event,
|
||||
UINT16 event_datalen
|
||||
);
|
||||
|
||||
#ifdef SMP_DATA_SIGNING
|
||||
void appl_gatt_signing_complete (API_RESULT status, UCHAR * data, UINT16 datalen);
|
||||
|
||||
void appl_gatt_signing_verification_complete
|
||||
(
|
||||
API_RESULT status,
|
||||
UCHAR * data,
|
||||
UINT16 datalen
|
||||
);
|
||||
#endif /* SMP_DATA_SIGNING */
|
||||
#endif /* _H_APPL_ANCS_ATT_SERVER_ */
|
||||
|
||||
+231
@@ -0,0 +1,231 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file appl_gap_config_params.c
|
||||
//!
|
||||
//! @brief This file contains GAP Configuration Parameters used by the application.
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
/**
|
||||
* \file appl_gap_config_params.c
|
||||
*
|
||||
* This file contains GAP Configuration Parameters used by the application.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013. Mindtree Ltd.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/* --------------------------------------------- Header File Inclusion */
|
||||
#include "appl_gap.h"
|
||||
|
||||
#ifdef ANCS
|
||||
|
||||
/* --------------------------------------------- External Global Variables */
|
||||
|
||||
/* --------------------------------------------- Exported Global Variables */
|
||||
|
||||
/* --------------------------------------------- Static Global Variables */
|
||||
|
||||
#if ((defined APPL_GAP_BROADCASTER_SUPPORT) || (defined APPL_GAP_PERIPHERAL_SUPPORT))
|
||||
/** Advertisement Data Options */
|
||||
const APPL_GAP_ADV_DATA appl_gap_adv_data[APPL_GAP_MAX_ADV_DATA_OPTIONS] =
|
||||
{
|
||||
/* GAP Advertisement Parameters */
|
||||
{
|
||||
{
|
||||
/**
|
||||
* Flags:
|
||||
* 0x01: LE Limited Discoverable Mode
|
||||
* 0x02: LE General Discoverable Mode
|
||||
* 0x04: BR/EDR Not Supported
|
||||
* 0x08: Simultaneous LE and BR/EDR to Same Device
|
||||
* Capable (Controller)
|
||||
* 0x10: Simultaneous LE and BR/EDR to Same Device
|
||||
* Capable (Host)
|
||||
*/
|
||||
0x02, 0x01,
|
||||
(BT_AD_FLAGS_LE_GENERAL_DISC_MODE | BT_AD_FLAGS_LE_BR_EDR_SUPPORT),
|
||||
|
||||
/**
|
||||
* Service UUID List:
|
||||
* Battery Service (0x180F)
|
||||
* DeviceInformation Service (0x180A)
|
||||
*/
|
||||
0x05, 0x03, 0x0F, 0x18, 0x0A, 0x18,
|
||||
|
||||
/**
|
||||
* Shortened Device Name: AM
|
||||
*/
|
||||
0x03, 0x08, 0x41, 0x4d,
|
||||
|
||||
/**
|
||||
* List of 16-bit Service Solicitation UUIDs(ANCS UUID)
|
||||
*/
|
||||
0x11, 0x15, 0xD0, 0x00, 0x2D, 0x12, 0x1E, 0x4B, 0x0F, 0xA4, 0x99, 0x4E, 0xCE, 0xB5, 0x31, 0xF4, 0x05, 0x79
|
||||
},
|
||||
|
||||
31
|
||||
}
|
||||
};
|
||||
|
||||
/* Advertisement parameters options */
|
||||
const APPL_GAP_ADV_PARAM appl_gap_adv_param[APPL_GAP_MAX_ADV_PARAM_OPTIONS] =
|
||||
{
|
||||
/* 0 - Normal Advertising Params */
|
||||
{
|
||||
32,
|
||||
|
||||
32,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
},
|
||||
/* 1 - Fast Connection Advertising Params */
|
||||
{
|
||||
32,
|
||||
|
||||
48,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
},
|
||||
/* 2 - Low Power Advertising Params */
|
||||
{
|
||||
1600,
|
||||
|
||||
4000,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
}
|
||||
};
|
||||
|
||||
/* Advertisement Table */
|
||||
APPL_GAP_ADV_INFO appl_gap_adv_table =
|
||||
{
|
||||
appl_gap_adv_data,
|
||||
|
||||
appl_gap_adv_param,
|
||||
|
||||
APPL_GAP_ADV_IDLE
|
||||
};
|
||||
#endif /* APPL_GAP_BROADCASTER || APPL_GAP_PERIPHERAL_SUPPORT */
|
||||
|
||||
#if ((defined APPL_GAP_OBSERVER_SUPPORT) || (defined APPL_GAP_CENTRAL_SUPPORT))
|
||||
/* Scan Parameters Option */
|
||||
const APPL_GAP_SCAN_PARAM appl_gap_scan_param[APPL_GAP_MAX_SCAN_PARAM_OPTIONS] =
|
||||
{
|
||||
/* Normal Scan Params */
|
||||
{
|
||||
32,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
},
|
||||
/* Fast Connection Scan Params */
|
||||
{
|
||||
48,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
},
|
||||
/* Low Power Scan Params */
|
||||
{
|
||||
4000,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
}
|
||||
};
|
||||
|
||||
/* Scan Table */
|
||||
APPL_GAP_SCAN_INFO appl_gap_scan_table =
|
||||
{
|
||||
appl_gap_scan_param,
|
||||
|
||||
APPL_GAP_SCAN_IDLE
|
||||
};
|
||||
#endif /* APPL_GAP_OBSERVER_SUPPORT || APPL_GAP_CENTRAL_SUPPORT */
|
||||
|
||||
#ifdef APPL_GAP_CENTRAL_SUPPORT
|
||||
/* Connection Parameters Options */
|
||||
const APPL_GAP_CONN_PARAM appl_gap_conn_param[APPL_GAP_MAX_CONN_PARAM_OPTIONS] =
|
||||
{
|
||||
{
|
||||
4,
|
||||
|
||||
4,
|
||||
|
||||
0,
|
||||
|
||||
40,
|
||||
|
||||
56,
|
||||
|
||||
0,
|
||||
|
||||
955,
|
||||
|
||||
32,
|
||||
|
||||
32
|
||||
}
|
||||
};
|
||||
|
||||
/* GAP Connection Table */
|
||||
APPL_GAP_CONN_INFO appl_gap_conn_table =
|
||||
{
|
||||
appl_gap_conn_param,
|
||||
|
||||
APPL_GAP_CONN_IDLE
|
||||
};
|
||||
#endif /* APPL_GAP_CENTRAL_SUPPORT */
|
||||
#endif /* ANCS */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,157 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file gatt_db.h
|
||||
//!
|
||||
//! @brief GATT Databse.
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
|
||||
/**
|
||||
* \file gatt_db.h
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013. Mindtree Ltd.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _H_GATT_DB_
|
||||
#define _H_GATT_DB_
|
||||
|
||||
/**
|
||||
* addgroup gatt_db_module
|
||||
*/
|
||||
|
||||
/**
|
||||
* defgroup gatt_db_tuneable_param Tuneable Parameters
|
||||
* {
|
||||
* This section defines the Tuneable Constants of Data Base Module.
|
||||
*/
|
||||
|
||||
/** Number of Characteristics in the data base */
|
||||
#define GATT_CHARACTERISTIC_COUNT 13
|
||||
|
||||
/** Number of Services in the data base */
|
||||
#define GATT_SERVICE_COUNT 4
|
||||
|
||||
/** Number of Characteristics that are configurable by the client */
|
||||
#define GATT_DB_MAX_CONFIGUREABLE_CHAR 3
|
||||
|
||||
/** Maximum Length of any Characteristic Value/Descriptor */
|
||||
#define GATT_DB_MAX_VAL_LENGTH 32
|
||||
|
||||
#define GATT_VALUE_ARRAY_SIZE 1
|
||||
|
||||
#define GATT_CONST_VALUE_ARRAY_SIZE 182
|
||||
|
||||
#define GATT_DB_PEER_VALUE_ARRAY_SIZE 4
|
||||
|
||||
#define GATT_DB_MAX_ATTRIBUTES 34
|
||||
|
||||
#define GATT_UUID_ARRAY_SIZE 54
|
||||
|
||||
#define GATT_DB_MAX_TYPE_COUNT 21
|
||||
|
||||
#define GATT_DB_MAX_PEER_CONFIGURATION \
|
||||
(GATT_DB_PEER_VALUE_ARRAY_SIZE * BT_MAX_DEVICE_QUEUE_SIZE)
|
||||
|
||||
/** \} */
|
||||
|
||||
/** Service Instance Reference */
|
||||
|
||||
/** GAP Service */
|
||||
#define GATT_SER_GAP_INST 0
|
||||
|
||||
/** GATT Service */
|
||||
#define GATT_SER_GATT_INST 1
|
||||
|
||||
/** Battery Service */
|
||||
#define GATT_SER_BATTERY_INST 2
|
||||
|
||||
/** DeviceInformation Service */
|
||||
#define GATT_SER_DEV_INFO_INST 3
|
||||
|
||||
|
||||
/** Characteristic Instance Reference */
|
||||
|
||||
/** DeviceName */
|
||||
#define GATT_CHAR_DEV_NAME_INST 0
|
||||
|
||||
/** Appearance */
|
||||
#define GATT_CHAR_APPEARANCE_INST 1
|
||||
|
||||
/** Service Changed */
|
||||
#define GATT_CHAR_SER_CHNGD_INST 2
|
||||
|
||||
/** BatteryLevel */
|
||||
#define GATT_CHAR_BATTERY_LVL_INST 3
|
||||
|
||||
/** ManufacturerName */
|
||||
#define GATT_CHAR_MAN_NAME_INST 4
|
||||
|
||||
/** ModelNumber */
|
||||
#define GATT_CHAR_MODEL_NO_INST 5
|
||||
|
||||
/** SerialNumber */
|
||||
#define GATT_CHAR_SL_NO_INST 6
|
||||
|
||||
/** FirmwareRevision */
|
||||
#define GATT_CHAR_FW_REV_INST 7
|
||||
|
||||
/** HardwareRevision */
|
||||
#define GATT_CHAR_HW_REV_INST 8
|
||||
|
||||
/** SoftwareRevision */
|
||||
#define GATT_CHAR_SW_REV_INST 9
|
||||
|
||||
/** SystemId */
|
||||
#define GATT_CHAR_SYS_ID_INST 10
|
||||
|
||||
/** RegCertDataList */
|
||||
#define GATT_CHAR_REG_CERT_DATA_INST 11
|
||||
|
||||
/** PnPID */
|
||||
#define GATT_CHAR_PNP_ID_INST 12
|
||||
|
||||
#endif /* _H_GATT_DB_ */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+234
@@ -0,0 +1,234 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file appl_gap_config_params.c
|
||||
//!
|
||||
//! @brief This file contains GAP Configuration Parameters used by the application.
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
/**
|
||||
* \file appl_gap_config_params.c
|
||||
*
|
||||
* This file contains GAP Configuration Parameters used by the application.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013. Mindtree Ltd.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/* --------------------------------------------- Header File Inclusion */
|
||||
#include "appl_gap.h"
|
||||
|
||||
/* --------------------------------------------- External Global Variables */
|
||||
|
||||
/* --------------------------------------------- Exported Global Variables */
|
||||
|
||||
/* --------------------------------------------- Static Global Variables */
|
||||
|
||||
#if ((defined APPL_GAP_BROADCASTER_SUPPORT) || (defined APPL_GAP_PERIPHERAL_SUPPORT))
|
||||
/** Advertisement Data Options */
|
||||
const APPL_GAP_ADV_DATA appl_gap_adv_data[APPL_GAP_MAX_ADV_DATA_OPTIONS] =
|
||||
{
|
||||
/* GAP Advertisement Parameters */
|
||||
{
|
||||
{
|
||||
/**
|
||||
* Flags:
|
||||
* 0x01: LE Limited Discoverable Mode
|
||||
* 0x02: LE General Discoverable Mode
|
||||
* 0x04: BR/EDR Not Supported
|
||||
* 0x08: Simultaneous LE and BR/EDR to Same Device
|
||||
* Capable (Controller)
|
||||
* 0x10: Simultaneous LE and BR/EDR to Same Device
|
||||
* Capable (Host)
|
||||
*/
|
||||
0x02, 0x01,
|
||||
(BT_AD_FLAGS_LE_GENERAL_DISC_MODE | BT_AD_FLAGS_LE_BR_EDR_SUPPORT),
|
||||
|
||||
/*! Manufacturer specific data AD type */
|
||||
0x1A, /*! length */
|
||||
HCI_AD_TYPE_MANUFACTURER_SPECIFIC_DATA, /*! AD type */
|
||||
|
||||
0x4C, /*! Company ID[0] */
|
||||
0x00, /*! Company ID[1] */
|
||||
|
||||
0x02, /*! Device type, this has to be 0x02*/
|
||||
0x15, /*! Length of vendor advertising data. */
|
||||
|
||||
/*! Proximity UUID 16 bytes */
|
||||
0xe2, 0xc5, 0x6d, 0xb5,
|
||||
0xdf, 0xfb, 0x48, 0xd2,
|
||||
0xb0, 0x60, 0xd0, 0xf5,
|
||||
0xa7, 0x10, 0x96, 0xe0,
|
||||
|
||||
/*! Major 0xnnnn */
|
||||
0x00, 0x00,
|
||||
/*! Minor 0xnnnn */
|
||||
0x00, 0x00,
|
||||
|
||||
/*! Measured Power */
|
||||
0xc5
|
||||
},
|
||||
30
|
||||
}
|
||||
};
|
||||
|
||||
/* Advertisement parameters options */
|
||||
const APPL_GAP_ADV_PARAM appl_gap_adv_param[APPL_GAP_MAX_ADV_PARAM_OPTIONS] =
|
||||
{
|
||||
/* 0 - Normal Advertising Params */
|
||||
{
|
||||
32,
|
||||
|
||||
32,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
},
|
||||
/* 1 - Fast Connection Advertising Params */
|
||||
{
|
||||
32,
|
||||
|
||||
48,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
},
|
||||
/* 2 - Low Power Advertising Params */
|
||||
{
|
||||
1600,
|
||||
|
||||
4000,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
}
|
||||
};
|
||||
|
||||
/* Advertisement Table */
|
||||
APPL_GAP_ADV_INFO appl_gap_adv_table =
|
||||
{
|
||||
appl_gap_adv_data,
|
||||
|
||||
appl_gap_adv_param,
|
||||
|
||||
APPL_GAP_ADV_IDLE
|
||||
};
|
||||
#endif /* APPL_GAP_BROADCASTER || APPL_GAP_PERIPHERAL_SUPPORT */
|
||||
|
||||
#if ((defined APPL_GAP_OBSERVER_SUPPORT) || (defined APPL_GAP_CENTRAL_SUPPORT))
|
||||
/* Scan Parameters Option */
|
||||
const APPL_GAP_SCAN_PARAM appl_gap_scan_param[APPL_GAP_MAX_SCAN_PARAM_OPTIONS] =
|
||||
{
|
||||
/* Normal Scan Params */
|
||||
{
|
||||
32,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
},
|
||||
/* Fast Connection Scan Params */
|
||||
{
|
||||
48,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
},
|
||||
/* Low Power Scan Params */
|
||||
{
|
||||
4000,
|
||||
|
||||
7,
|
||||
|
||||
0
|
||||
}
|
||||
};
|
||||
|
||||
/* Scan Table */
|
||||
APPL_GAP_SCAN_INFO appl_gap_scan_table =
|
||||
{
|
||||
appl_gap_scan_param,
|
||||
|
||||
APPL_GAP_SCAN_IDLE
|
||||
};
|
||||
#endif /* APPL_GAP_OBSERVER_SUPPORT || APPL_GAP_CENTRAL_SUPPORT */
|
||||
|
||||
#ifdef APPL_GAP_CENTRAL_SUPPORT
|
||||
/* Connection Parameters Options */
|
||||
const APPL_GAP_CONN_PARAM appl_gap_conn_param[APPL_GAP_MAX_CONN_PARAM_OPTIONS] =
|
||||
{
|
||||
{
|
||||
4,
|
||||
|
||||
4,
|
||||
|
||||
0,
|
||||
|
||||
40,
|
||||
|
||||
56,
|
||||
|
||||
0,
|
||||
|
||||
955,
|
||||
|
||||
32,
|
||||
|
||||
32
|
||||
}
|
||||
};
|
||||
|
||||
/* GAP Connection Table */
|
||||
APPL_GAP_CONN_INFO appl_gap_conn_table =
|
||||
{
|
||||
appl_gap_conn_param,
|
||||
|
||||
APPL_GAP_CONN_IDLE
|
||||
};
|
||||
#endif /* APPL_GAP_CENTRAL_SUPPORT */
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
/**
|
||||
* \file appl_ibeacon.c
|
||||
*
|
||||
* This file contains ibeacon example
|
||||
*
|
||||
* Copyright (C) 2013. Mindtree Ltd.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/* --------------------------------------------- Header File Inclusion */
|
||||
#include "appl.h"
|
||||
|
||||
/* --------------------------------------------- Constants */
|
||||
|
||||
/* --------------------------------------------- Static Global Variables */
|
||||
|
||||
|
||||
/* --------------------------------------------- Functions */
|
||||
|
||||
void appl_ibeacon_init(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file appl_ibeacon.h
|
||||
//!
|
||||
//! @brief Application Header File for iBeacon example.
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
/**
|
||||
* \file appl_ibeacon.h
|
||||
*
|
||||
* Application Header File for iBeacon example.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013. Mindtree Ltd.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _H_APPL_HRS_
|
||||
#define _H_APPL_HRS_
|
||||
|
||||
/* ----------------------------------------- Header File Inclusion */
|
||||
#include "BT_api.h"
|
||||
#include "BT_gatt_db_api.h"
|
||||
#include "gatt_db.h"
|
||||
#include "appl.h"
|
||||
|
||||
/* ----------------------------------------- Data Types/ Structures */
|
||||
|
||||
/* --------------------------------------------- Functions */
|
||||
void appl_ibeacon_init(void);
|
||||
|
||||
/* Profile handling */
|
||||
#define APPL_PROFILE_INIT(...) appl_ibeacon_init()
|
||||
#define APPL_PROFILE_CONNECT(x)
|
||||
#define APPL_SEND_MEASUREMENT(x)
|
||||
#define APPL_PROFILE_DISCONNECT_HANDLER(x)
|
||||
#define GATT_DB_PROFILE_HANDLER
|
||||
#define APPL_PROFILE_HVN_NTF_COMPLETE_HANDLER(x, y, z)
|
||||
#define APPL_PROFILE_HVN_IND_COMPLETE_HANDLER(x, y, z)
|
||||
#define APPL_PROFILE_MTU_UPDT_COMPLETE_HANDLER(x, y)
|
||||
|
||||
#define APPL_USE_IDLE_TIMER
|
||||
#define APPL_IDLE_TIMEOUT 30
|
||||
#endif /* _H_APPL_HRS_ */
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,167 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file gatt_db.h
|
||||
//!
|
||||
//! @brief GATT Databse.
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
/**
|
||||
* \file gatt_db.h
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013. Mindtree Ltd.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _H_GATT_DB_
|
||||
#define _H_GATT_DB_
|
||||
|
||||
/**
|
||||
* addgroup gatt_db_module
|
||||
*/
|
||||
|
||||
/**
|
||||
* defgroup gatt_db_tuneable_param Tuneable Parameters
|
||||
* {
|
||||
* This section defines the Tuneable Constants of Data Base Module.
|
||||
*/
|
||||
|
||||
/** Number of Characteristics in the data base */
|
||||
#define GATT_CHARACTERISTIC_COUNT 16
|
||||
|
||||
/** Number of Services in the data base */
|
||||
#define GATT_SERVICE_COUNT 5
|
||||
|
||||
/** Number of Characteristics that are configurable by the client */
|
||||
#define GATT_DB_MAX_CONFIGUREABLE_CHAR 3
|
||||
|
||||
/** Maximum Length of any Characteristic Value/Descriptor */
|
||||
#define GATT_DB_MAX_VAL_LENGTH 32
|
||||
|
||||
#define GATT_VALUE_ARRAY_SIZE 3
|
||||
|
||||
#define GATT_CONST_VALUE_ARRAY_SIZE 203
|
||||
|
||||
#define GATT_DB_PEER_VALUE_ARRAY_SIZE 6
|
||||
|
||||
#define GATT_DB_MAX_ATTRIBUTES 42
|
||||
|
||||
#define GATT_UUID_ARRAY_SIZE 62
|
||||
|
||||
#define GATT_DB_MAX_TYPE_COUNT 25
|
||||
|
||||
#define GATT_DB_MAX_PEER_CONFIGURATION \
|
||||
(GATT_DB_PEER_VALUE_ARRAY_SIZE * BT_MAX_DEVICE_QUEUE_SIZE)
|
||||
|
||||
/** \} */
|
||||
|
||||
/** Service Instance Reference */
|
||||
|
||||
/** GAP Service */
|
||||
#define GATT_SER_GAP_INST 0
|
||||
|
||||
/** GATT Service */
|
||||
#define GATT_SER_GATT_INST 1
|
||||
|
||||
/** Battery Service */
|
||||
#define GATT_SER_BATTERY_INST 2
|
||||
|
||||
/** DeviceInformation Service */
|
||||
#define GATT_SER_DEV_INFO_INST 3
|
||||
|
||||
/** Heart Rate Service */
|
||||
#define GATT_SER_HEART_RATE_INST 4
|
||||
|
||||
/** Characteristic Instance Reference */
|
||||
|
||||
/** DeviceName */
|
||||
#define GATT_CHAR_DEV_NAME_INST 0
|
||||
|
||||
/** Appearance */
|
||||
#define GATT_CHAR_APPEARANCE_INST 1
|
||||
|
||||
/** Service Changed */
|
||||
#define GATT_CHAR_SER_CHNGD_INST 2
|
||||
|
||||
/** BatteryLevel */
|
||||
#define GATT_CHAR_BATTERY_LVL_INST 3
|
||||
|
||||
/** ManufacturerName */
|
||||
#define GATT_CHAR_MAN_NAME_INST 4
|
||||
|
||||
/** ModelNumber */
|
||||
#define GATT_CHAR_MODEL_NO_INST 5
|
||||
|
||||
/** SerialNumber */
|
||||
#define GATT_CHAR_SL_NO_INST 6
|
||||
|
||||
/** FirmwareRevision */
|
||||
#define GATT_CHAR_FW_REV_INST 7
|
||||
|
||||
/** HardwareRevision */
|
||||
#define GATT_CHAR_HW_REV_INST 8
|
||||
|
||||
/** SoftwareRevision */
|
||||
#define GATT_CHAR_SW_REV_INST 9
|
||||
|
||||
/** SystemId */
|
||||
#define GATT_CHAR_SYS_ID_INST 10
|
||||
|
||||
/** RegCertDataList */
|
||||
#define GATT_CHAR_REG_CERT_DATA_INST 11
|
||||
|
||||
/** PnPID */
|
||||
#define GATT_CHAR_PNP_ID_INST 12
|
||||
|
||||
/** HeartRateMeasurement */
|
||||
#define GATT_CHAR_HR_MSRMNT 13
|
||||
|
||||
/** BodySensorLocation */
|
||||
#define GATT_CHAR_BODY_SNSR_LOC_INST 14
|
||||
|
||||
/** HeartRateControlPoint */
|
||||
#define GATT_CHAR_HR_CNTRL_PNT_INST 15
|
||||
|
||||
#endif /* _H_GATT_DB_ */
|
||||
|
||||
+1293
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,111 @@
|
||||
// ****************************************************************************
|
||||
//
|
||||
// amdtpc_api.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Ambiq Micro AMDTP client.
|
||||
//!
|
||||
//! @{
|
||||
//
|
||||
// ****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifndef AMDTPC_API_H
|
||||
#define AMDTPC_API_H
|
||||
|
||||
#include "att_api.h"
|
||||
#include "amdtp_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**************************************************************************************************
|
||||
Macros
|
||||
**************************************************************************************************/
|
||||
|
||||
enum
|
||||
{
|
||||
AMDTP_RX_HDL_IDX, /*! Rx data */
|
||||
AMDTP_TX_DATA_HDL_IDX, /*! Tx data */
|
||||
AMDTP_TX_DATA_CCC_HDL_IDX, /*! Tx data client characteristic configuration descriptor */
|
||||
AMDTP_ACK_HDL_IDX, /*! Ack */
|
||||
AMDTP_ACK_CCC_HDL_IDX, /*! Ack client characteristic configuration descriptor */
|
||||
AMDTP_HDL_LIST_LEN /*! Handle list length */
|
||||
};
|
||||
|
||||
/**************************************************************************************************
|
||||
Function Declarations
|
||||
**************************************************************************************************/
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AmdtpcDiscover
|
||||
*
|
||||
* \brief Perform service and characteristic discovery for AMDTP service.
|
||||
* Parameter pHdlList must point to an array of length AMDTP_HDL_LIST_LEN.
|
||||
* If discovery is successful the handles of discovered characteristics and
|
||||
* descriptors will be set in pHdlList.
|
||||
*
|
||||
* \param connId Connection identifier.
|
||||
* \param pHdlList Characteristic handle list.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AmdtpcDiscover(dmConnId_t connId, uint16_t *pHdlList);
|
||||
|
||||
void
|
||||
amdtpc_init(wsfHandlerId_t handlerId, amdtpRecvCback_t recvCback, amdtpTransCback_t transCback);
|
||||
|
||||
void
|
||||
amdtpc_start(uint16_t rxHdl, uint16_t ackHdl, uint8_t timerEvt);
|
||||
|
||||
void
|
||||
amdtpc_proc_msg(wsfMsgHdr_t *pMsg);
|
||||
|
||||
eAmdtpStatus_t
|
||||
AmdtpcSendPacket(eAmdtpPktType_t type, bool_t encrypted, bool_t enableACK, uint8_t *buf, uint16_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* AMDTPC_API_H */
|
||||
@@ -0,0 +1,438 @@
|
||||
// ****************************************************************************
|
||||
//
|
||||
// amdtpc_main.c
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Ambiq Micro AMDTP client.
|
||||
//!
|
||||
//! @{
|
||||
//
|
||||
// ****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include "wsf_types.h"
|
||||
#include "wsf_assert.h"
|
||||
#include "bstream.h"
|
||||
#include "app_api.h"
|
||||
#include "amdtpc_api.h"
|
||||
#include "svc_amdtp.h"
|
||||
#include "wsf_trace.h"
|
||||
|
||||
static void amdtpcHandleWriteResponse(attEvt_t *pMsg);
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Global variables
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
uint8_t rxPktBuf[AMDTP_PACKET_SIZE];
|
||||
uint8_t txPktBuf[AMDTP_PACKET_SIZE];
|
||||
uint8_t ackPktBuf[20];
|
||||
|
||||
|
||||
/**************************************************************************************************
|
||||
Local Variables
|
||||
**************************************************************************************************/
|
||||
|
||||
/* UUIDs */
|
||||
static const uint8_t amdtpSvcUuid[] = {ATT_UUID_AMDTP_SERVICE}; /*! AMDTP service */
|
||||
static const uint8_t amdtpRxChUuid[] = {ATT_UUID_AMDTP_RX}; /*! AMDTP Rx */
|
||||
static const uint8_t amdtpTxChUuid[] = {ATT_UUID_AMDTP_TX}; /*! AMDTP Tx */
|
||||
static const uint8_t amdtpAckChUuid[] = {ATT_UUID_AMDTP_ACK}; /*! AMDTP Ack */
|
||||
|
||||
/* Characteristics for discovery */
|
||||
|
||||
/*! Proprietary data */
|
||||
static const attcDiscChar_t amdtpRx =
|
||||
{
|
||||
amdtpRxChUuid,
|
||||
ATTC_SET_REQUIRED | ATTC_SET_UUID_128
|
||||
};
|
||||
|
||||
static const attcDiscChar_t amdtpTx =
|
||||
{
|
||||
amdtpTxChUuid,
|
||||
ATTC_SET_REQUIRED | ATTC_SET_UUID_128
|
||||
};
|
||||
|
||||
/*! AMDTP Tx CCC descriptor */
|
||||
static const attcDiscChar_t amdtpTxCcc =
|
||||
{
|
||||
attCliChCfgUuid,
|
||||
ATTC_SET_REQUIRED | ATTC_SET_DESCRIPTOR
|
||||
};
|
||||
|
||||
static const attcDiscChar_t amdtpAck =
|
||||
{
|
||||
amdtpAckChUuid,
|
||||
ATTC_SET_REQUIRED | ATTC_SET_UUID_128
|
||||
};
|
||||
|
||||
/*! AMDTP Tx CCC descriptor */
|
||||
static const attcDiscChar_t amdtpAckCcc =
|
||||
{
|
||||
attCliChCfgUuid,
|
||||
ATTC_SET_REQUIRED | ATTC_SET_DESCRIPTOR
|
||||
};
|
||||
|
||||
/*! List of characteristics to be discovered; order matches handle index enumeration */
|
||||
static const attcDiscChar_t *amdtpDiscCharList[] =
|
||||
{
|
||||
&amdtpRx, /*! Rx */
|
||||
&amdtpTx, /*! Tx */
|
||||
&amdtpTxCcc, /*! Tx CCC descriptor */
|
||||
&amdtpAck, /*! Ack */
|
||||
&amdtpAckCcc /*! Ack CCC descriptor */
|
||||
};
|
||||
|
||||
/* sanity check: make sure handle list length matches characteristic list length */
|
||||
//WSF_ASSERT(AMDTP_HDL_LIST_LEN == ((sizeof(amdtpDiscCharList) / sizeof(attcDiscChar_t *))));
|
||||
|
||||
|
||||
/* Control block */
|
||||
static struct
|
||||
{
|
||||
bool_t txReady; // TRUE if ready to send notifications
|
||||
uint16_t attRxHdl;
|
||||
uint16_t attAckHdl;
|
||||
amdtpCb_t core;
|
||||
}
|
||||
amdtpcCb;
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AmdtpDiscover
|
||||
*
|
||||
* \brief Perform service and characteristic discovery for AMDTP service.
|
||||
* Parameter pHdlList must point to an array of length AMDTP_HDL_LIST_LEN.
|
||||
* If discovery is successful the handles of discovered characteristics and
|
||||
* descriptors will be set in pHdlList.
|
||||
*
|
||||
* \param connId Connection identifier.
|
||||
* \param pHdlList Characteristic handle list.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void
|
||||
AmdtpcDiscover(dmConnId_t connId, uint16_t *pHdlList)
|
||||
{
|
||||
AppDiscFindService(connId, ATT_128_UUID_LEN, (uint8_t *) amdtpSvcUuid,
|
||||
AMDTP_HDL_LIST_LEN, (attcDiscChar_t **) amdtpDiscCharList, pHdlList);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Send data to Server
|
||||
//
|
||||
//*****************************************************************************
|
||||
static void
|
||||
amdtpcSendData(uint8_t *buf, uint16_t len)
|
||||
{
|
||||
dmConnId_t connId;
|
||||
|
||||
if ((connId = AppConnIsOpen()) == DM_CONN_ID_NONE)
|
||||
{
|
||||
APP_TRACE_INFO0("AmdtpcSendData() no connection\n");
|
||||
return;
|
||||
}
|
||||
if (amdtpcCb.attRxHdl != ATT_HANDLE_NONE)
|
||||
{
|
||||
AttcWriteCmd(connId, amdtpcCb.attRxHdl, len, buf);
|
||||
amdtpcCb.txReady = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
APP_TRACE_WARN1("Invalid attRxHdl = 0x%x\n", amdtpcCb.attRxHdl);
|
||||
}
|
||||
}
|
||||
|
||||
static eAmdtpStatus_t
|
||||
amdtpcSendAck(eAmdtpPktType_t type, bool_t encrypted, bool_t enableACK, uint8_t *buf, uint16_t len)
|
||||
{
|
||||
dmConnId_t connId;
|
||||
|
||||
AmdtpBuildPkt(&amdtpcCb.core, type, encrypted, enableACK, buf, len);
|
||||
|
||||
if ((connId = AppConnIsOpen()) == DM_CONN_ID_NONE)
|
||||
{
|
||||
APP_TRACE_INFO0("AmdtpcSendAck() no connection\n");
|
||||
return AMDTP_STATUS_TX_NOT_READY;
|
||||
}
|
||||
|
||||
if (amdtpcCb.attAckHdl != ATT_HANDLE_NONE)
|
||||
{
|
||||
//APP_TRACE_INFO2("rxHdl = 0x%x, ackHdl = 0x%x\n", amdtpcCb.attRxHdl, amdtpcCb.attAckHdl);
|
||||
AttcWriteCmd(connId, amdtpcCb.attAckHdl, amdtpcCb.core.ackPkt.len, amdtpcCb.core.ackPkt.data);
|
||||
}
|
||||
else
|
||||
{
|
||||
APP_TRACE_INFO1("Invalid attAckHdl = 0x%x\n", amdtpcCb.attAckHdl);
|
||||
return AMDTP_STATUS_TX_NOT_READY;
|
||||
}
|
||||
return AMDTP_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
amdtpc_init(wsfHandlerId_t handlerId, amdtpRecvCback_t recvCback, amdtpTransCback_t transCback)
|
||||
{
|
||||
memset(&amdtpcCb, 0, sizeof(amdtpcCb));
|
||||
amdtpcCb.txReady = false;
|
||||
amdtpcCb.core.txState = AMDTP_STATE_TX_IDLE;
|
||||
amdtpcCb.core.rxState = AMDTP_STATE_INIT;
|
||||
amdtpcCb.core.timeoutTimer.handlerId = handlerId;
|
||||
|
||||
amdtpcCb.core.lastRxPktSn = 0;
|
||||
amdtpcCb.core.txPktSn = 0;
|
||||
|
||||
resetPkt(&amdtpcCb.core.rxPkt);
|
||||
amdtpcCb.core.rxPkt.data = rxPktBuf;
|
||||
|
||||
resetPkt(&amdtpcCb.core.txPkt);
|
||||
amdtpcCb.core.txPkt.data = txPktBuf;
|
||||
|
||||
resetPkt(&amdtpcCb.core.ackPkt);
|
||||
amdtpcCb.core.ackPkt.data = ackPktBuf;
|
||||
|
||||
amdtpcCb.core.recvCback = recvCback;
|
||||
amdtpcCb.core.transCback = transCback;
|
||||
|
||||
amdtpcCb.core.txTimeoutMs = TX_TIMEOUT_DEFAULT;
|
||||
|
||||
amdtpcCb.core.data_sender_func = amdtpcSendData;
|
||||
amdtpcCb.core.ack_sender_func = amdtpcSendAck;
|
||||
}
|
||||
|
||||
static void
|
||||
amdtpc_conn_close(dmEvt_t *pMsg)
|
||||
{
|
||||
/* clear connection */
|
||||
WsfTimerStop(&amdtpcCb.core.timeoutTimer);
|
||||
amdtpcCb.txReady = false;
|
||||
amdtpcCb.core.txState = AMDTP_STATE_TX_IDLE;
|
||||
amdtpcCb.core.rxState = AMDTP_STATE_INIT;
|
||||
amdtpcCb.core.lastRxPktSn = 0;
|
||||
amdtpcCb.core.txPktSn = 0;
|
||||
resetPkt(&amdtpcCb.core.rxPkt);
|
||||
resetPkt(&amdtpcCb.core.txPkt);
|
||||
resetPkt(&amdtpcCb.core.ackPkt);
|
||||
}
|
||||
|
||||
void
|
||||
amdtpc_start(uint16_t rxHdl, uint16_t ackHdl, uint8_t timerEvt)
|
||||
{
|
||||
amdtpcCb.txReady = true;
|
||||
amdtpcCb.attRxHdl = rxHdl;
|
||||
amdtpcCb.attAckHdl = ackHdl;
|
||||
amdtpcCb.core.timeoutTimer.msg.event = timerEvt;
|
||||
|
||||
dmConnId_t connId;
|
||||
|
||||
if ((connId = AppConnIsOpen()) == DM_CONN_ID_NONE)
|
||||
{
|
||||
APP_TRACE_INFO0("amdtpc_start() no connection\n");
|
||||
return;
|
||||
}
|
||||
|
||||
amdtpcCb.core.attMtuSize = AttGetMtu(connId);
|
||||
APP_TRACE_INFO1("MTU size = %d bytes", amdtpcCb.core.attMtuSize);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Timer Expiration handler
|
||||
//
|
||||
//*****************************************************************************
|
||||
void
|
||||
amdtpc_timeout_timer_expired(wsfMsgHdr_t *pMsg)
|
||||
{
|
||||
uint8_t data[1];
|
||||
data[0] = amdtpcCb.core.txPktSn;
|
||||
APP_TRACE_INFO1("amdtpc tx timeout, txPktSn = %d", amdtpcCb.core.txPktSn);
|
||||
AmdtpSendControl(&amdtpcCb.core, AMDTP_CONTROL_RESEND_REQ, data, 1);
|
||||
// fire a timer for receiving an AMDTP_STATUS_RESEND_REPLY ACK
|
||||
WsfTimerStartMs(&amdtpcCb.core.timeoutTimer, amdtpcCb.core.txTimeoutMs);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amdtpcValueNtf
|
||||
*
|
||||
* \brief Process a received ATT notification.
|
||||
*
|
||||
* \param pMsg Pointer to ATT callback event message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t
|
||||
amdtpcValueNtf(attEvt_t *pMsg)
|
||||
{
|
||||
eAmdtpStatus_t status = AMDTP_STATUS_UNKNOWN_ERROR;
|
||||
amdtpPacket_t *pkt = NULL;
|
||||
#if 0
|
||||
APP_TRACE_INFO0("receive ntf data\n");
|
||||
APP_TRACE_INFO1("handle = 0x%x\n", pMsg->handle);
|
||||
for (int i = 0; i < pMsg->valueLen; i++)
|
||||
{
|
||||
APP_TRACE_INFO1("%02x ", pMsg->pValue[i]);
|
||||
}
|
||||
APP_TRACE_INFO0("\n");
|
||||
#endif
|
||||
|
||||
if (pMsg->handle == amdtpcCb.attRxHdl)
|
||||
{
|
||||
status = AmdtpReceivePkt(&amdtpcCb.core, &amdtpcCb.core.rxPkt, pMsg->valueLen, pMsg->pValue);
|
||||
}
|
||||
else if ( pMsg->handle == amdtpcCb.attAckHdl )
|
||||
{
|
||||
status = AmdtpReceivePkt(&amdtpcCb.core, &amdtpcCb.core.ackPkt, pMsg->valueLen, pMsg->pValue);
|
||||
}
|
||||
|
||||
if (status == AMDTP_STATUS_RECEIVE_DONE)
|
||||
{
|
||||
if (pMsg->handle == amdtpcCb.attRxHdl)
|
||||
{
|
||||
pkt = &amdtpcCb.core.rxPkt;
|
||||
}
|
||||
else if (pMsg->handle == amdtpcCb.attAckHdl)
|
||||
{
|
||||
pkt = &amdtpcCb.core.ackPkt;
|
||||
}
|
||||
|
||||
AmdtpPacketHandler(&amdtpcCb.core, (eAmdtpPktType_t)pkt->header.pktType, pkt->len - AMDTP_CRC_SIZE_IN_PKT, pkt->data);
|
||||
}
|
||||
|
||||
return ATT_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
amdtpcHandleWriteResponse(attEvt_t *pMsg)
|
||||
{
|
||||
//APP_TRACE_INFO2("amdtpcHandleWriteResponse, status = %d, hdl = 0x%x\n", pMsg->hdr.status, pMsg->handle);
|
||||
if (pMsg->hdr.status == ATT_SUCCESS && pMsg->handle == amdtpcCb.attRxHdl)
|
||||
{
|
||||
amdtpcCb.txReady = true;
|
||||
// process next data
|
||||
AmdtpSendPacketHandler(&amdtpcCb.core);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
amdtpc_proc_msg(wsfMsgHdr_t *pMsg)
|
||||
{
|
||||
if (pMsg->event == DM_CONN_OPEN_IND)
|
||||
{
|
||||
}
|
||||
else if (pMsg->event == DM_CONN_CLOSE_IND)
|
||||
{
|
||||
amdtpc_conn_close((dmEvt_t *) pMsg);
|
||||
}
|
||||
else if (pMsg->event == DM_CONN_UPDATE_IND)
|
||||
{
|
||||
}
|
||||
else if (pMsg->event == amdtpcCb.core.timeoutTimer.msg.event)
|
||||
{
|
||||
amdtpc_timeout_timer_expired(pMsg);
|
||||
}
|
||||
else if (pMsg->event == ATTC_WRITE_CMD_RSP)
|
||||
{
|
||||
amdtpcHandleWriteResponse((attEvt_t *) pMsg);
|
||||
}
|
||||
else if (pMsg->event == ATTC_HANDLE_VALUE_NTF)
|
||||
{
|
||||
amdtpcValueNtf((attEvt_t *) pMsg);
|
||||
}
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @brief Send data to Server via write command
|
||||
//!
|
||||
//! @param type - packet type
|
||||
//! @param encrypted - is packet encrypted
|
||||
//! @param enableACK - does client need to response
|
||||
//! @param buf - data
|
||||
//! @param len - data length
|
||||
//!
|
||||
//! @return status
|
||||
//
|
||||
//*****************************************************************************
|
||||
eAmdtpStatus_t
|
||||
AmdtpcSendPacket(eAmdtpPktType_t type, bool_t encrypted, bool_t enableACK, uint8_t *buf, uint16_t len)
|
||||
{
|
||||
//
|
||||
// Check if the service is idle to send
|
||||
//
|
||||
if ( amdtpcCb.core.txState != AMDTP_STATE_TX_IDLE )
|
||||
{
|
||||
APP_TRACE_INFO1("data sending failed, tx state = %d", amdtpcCb.core.txState);
|
||||
return AMDTP_STATUS_BUSY;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if data length is valid
|
||||
//
|
||||
if ( len > AMDTP_MAX_PAYLOAD_SIZE )
|
||||
{
|
||||
APP_TRACE_INFO1("data sending failed, exceed maximum payload, len = %d.", len);
|
||||
return AMDTP_STATUS_INVALID_PKT_LENGTH;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if ready to send notification
|
||||
//
|
||||
if ( !amdtpcCb.txReady )
|
||||
{
|
||||
//set in callback amdtpsHandleValueCnf
|
||||
APP_TRACE_INFO1("data sending failed, not ready for notification.", NULL);
|
||||
return AMDTP_STATUS_TX_NOT_READY;
|
||||
}
|
||||
|
||||
AmdtpBuildPkt(&amdtpcCb.core, type, encrypted, enableACK, buf, len);
|
||||
|
||||
// send packet
|
||||
AmdtpSendPacketHandler(&amdtpcCb.core);
|
||||
|
||||
return AMDTP_STATUS_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,399 @@
|
||||
// ****************************************************************************
|
||||
//
|
||||
// amdtp_common.c
|
||||
//! @file
|
||||
//!
|
||||
//! @brief This file provides the shared functions for the AMDTP service.
|
||||
//!
|
||||
//! @{
|
||||
//
|
||||
// ****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include "amdtp_common.h"
|
||||
#include "wsf_assert.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "bstream.h"
|
||||
#include "att_api.h"
|
||||
#include "am_util_debug.h"
|
||||
#include "crc32.h"
|
||||
#include "am_util.h"
|
||||
|
||||
void
|
||||
resetPkt(amdtpPacket_t *pkt)
|
||||
{
|
||||
pkt->offset = 0;
|
||||
pkt->header.pktType = AMDTP_PKT_TYPE_UNKNOWN;
|
||||
pkt->len = 0;
|
||||
}
|
||||
|
||||
eAmdtpStatus_t
|
||||
AmdtpReceivePkt(amdtpCb_t *amdtpCb, amdtpPacket_t *pkt, uint16_t len, uint8_t *pValue)
|
||||
{
|
||||
uint8_t dataIdx = 0;
|
||||
uint32_t calDataCrc = 0;
|
||||
uint16_t header = 0;
|
||||
|
||||
if (pkt->offset == 0 && len < AMDTP_PREFIX_SIZE_IN_PKT)
|
||||
{
|
||||
APP_TRACE_INFO0("Invalid packet!!!");
|
||||
AmdtpSendReply(amdtpCb, AMDTP_STATUS_INVALID_PKT_LENGTH, NULL, 0);
|
||||
return AMDTP_STATUS_INVALID_PKT_LENGTH;
|
||||
}
|
||||
|
||||
// new packet
|
||||
if (pkt->offset == 0)
|
||||
{
|
||||
BYTES_TO_UINT16(pkt->len, pValue);
|
||||
BYTES_TO_UINT16(header, &pValue[2]);
|
||||
pkt->header.pktType = (header & PACKET_TYPE_BIT_MASK) >> PACKET_TYPE_BIT_OFFSET;
|
||||
pkt->header.pktSn = (header & PACKET_SN_BIT_MASK) >> PACKET_SN_BIT_OFFSET;
|
||||
pkt->header.encrypted = (header & PACKET_ENCRYPTION_BIT_MASK) >> PACKET_ENCRYPTION_BIT_OFFSET;
|
||||
pkt->header.ackEnabled = (header & PACKET_ACK_BIT_MASK) >> PACKET_ACK_BIT_OFFSET;
|
||||
dataIdx = AMDTP_PREFIX_SIZE_IN_PKT;
|
||||
if (pkt->header.pktType == AMDTP_PKT_TYPE_DATA)
|
||||
{
|
||||
amdtpCb->rxState = AMDTP_STATE_GETTING_DATA;
|
||||
}
|
||||
#ifdef AMDTP_DEBUG_ON
|
||||
APP_TRACE_INFO1("pkt len = 0x%x", pkt->len);
|
||||
APP_TRACE_INFO1("pkt header = 0x%x", header);
|
||||
#endif
|
||||
APP_TRACE_INFO2("type = %d, sn = %d", pkt->header.pktType, pkt->header.pktSn);
|
||||
APP_TRACE_INFO2("enc = %d, ackEnabled = %d", pkt->header.encrypted, pkt->header.ackEnabled);
|
||||
}
|
||||
|
||||
// make sure we have enough space for new data
|
||||
if (pkt->offset + len - dataIdx > AMDTP_PACKET_SIZE)
|
||||
{
|
||||
APP_TRACE_INFO0("not enough buffer size!!!");
|
||||
if (pkt->header.pktType == AMDTP_PKT_TYPE_DATA)
|
||||
{
|
||||
amdtpCb->rxState = AMDTP_STATE_RX_IDLE;
|
||||
}
|
||||
// reset pkt
|
||||
resetPkt(pkt);
|
||||
AmdtpSendReply(amdtpCb, AMDTP_STATUS_INSUFFICIENT_BUFFER, NULL, 0);
|
||||
return AMDTP_STATUS_INSUFFICIENT_BUFFER;
|
||||
}
|
||||
|
||||
// copy new data into buffer and also save crc into it if it's the last frame in a packet
|
||||
// 4 bytes crc is included in pkt length
|
||||
memcpy(pkt->data + pkt->offset, pValue + dataIdx, len - dataIdx);
|
||||
pkt->offset += (len - dataIdx);
|
||||
|
||||
// whole packet received
|
||||
if (pkt->offset >= pkt->len)
|
||||
{
|
||||
uint32_t peerCrc = 0;
|
||||
//
|
||||
// check CRC
|
||||
//
|
||||
BYTES_TO_UINT32(peerCrc, pkt->data + pkt->len - AMDTP_CRC_SIZE_IN_PKT);
|
||||
calDataCrc = CalcCrc32(0xFFFFFFFFU, pkt->len - AMDTP_CRC_SIZE_IN_PKT, pkt->data);
|
||||
#ifdef AMDTP_DEBUG_ON
|
||||
APP_TRACE_INFO1("calDataCrc = 0x%x ", calDataCrc);
|
||||
APP_TRACE_INFO1("peerCrc = 0x%x", peerCrc);
|
||||
APP_TRACE_INFO1("len: %d", pkt->len);
|
||||
#endif
|
||||
|
||||
if (peerCrc != calDataCrc)
|
||||
{
|
||||
APP_TRACE_INFO0("crc error\n");
|
||||
|
||||
if (pkt->header.pktType == AMDTP_PKT_TYPE_DATA)
|
||||
{
|
||||
amdtpCb->rxState = AMDTP_STATE_RX_IDLE;
|
||||
}
|
||||
// reset pkt
|
||||
resetPkt(pkt);
|
||||
|
||||
AmdtpSendReply(amdtpCb, AMDTP_STATUS_CRC_ERROR, NULL, 0);
|
||||
|
||||
return AMDTP_STATUS_CRC_ERROR;
|
||||
}
|
||||
|
||||
return AMDTP_STATUS_RECEIVE_DONE;
|
||||
}
|
||||
|
||||
return AMDTP_STATUS_RECEIVE_CONTINUE;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// AMDTP packet handler
|
||||
//
|
||||
//*****************************************************************************
|
||||
void
|
||||
AmdtpPacketHandler(amdtpCb_t *amdtpCb, eAmdtpPktType_t type, uint16_t len, uint8_t *buf)
|
||||
{
|
||||
// APP_TRACE_INFO2("received packet type = %d, len = %d\n", type, len);
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case AMDTP_PKT_TYPE_DATA:
|
||||
//
|
||||
// data package recevied
|
||||
//
|
||||
// record packet serial number
|
||||
amdtpCb->lastRxPktSn = amdtpCb->rxPkt.header.pktSn;
|
||||
AmdtpSendReply(amdtpCb, AMDTP_STATUS_SUCCESS, NULL, 0);
|
||||
if (amdtpCb->recvCback)
|
||||
{
|
||||
amdtpCb->recvCback(buf, len);
|
||||
}
|
||||
|
||||
amdtpCb->rxState = AMDTP_STATE_RX_IDLE;
|
||||
resetPkt(&amdtpCb->rxPkt);
|
||||
break;
|
||||
|
||||
case AMDTP_PKT_TYPE_ACK:
|
||||
{
|
||||
eAmdtpStatus_t status = (eAmdtpStatus_t)buf[0];
|
||||
// stop tx timeout timer
|
||||
WsfTimerStop(&amdtpCb->timeoutTimer);
|
||||
|
||||
if (amdtpCb->txState != AMDTP_STATE_TX_IDLE)
|
||||
{
|
||||
// APP_TRACE_INFO1("set txState back to idle, state = %d\n", amdtpCb->txState);
|
||||
amdtpCb->txState = AMDTP_STATE_TX_IDLE;
|
||||
}
|
||||
|
||||
if (status == AMDTP_STATUS_CRC_ERROR || status == AMDTP_STATUS_RESEND_REPLY)
|
||||
{
|
||||
// resend packet
|
||||
AmdtpSendPacketHandler(amdtpCb);
|
||||
}
|
||||
else
|
||||
{
|
||||
// increase packet serial number if send successfully
|
||||
if (status == AMDTP_STATUS_SUCCESS)
|
||||
{
|
||||
amdtpCb->txPktSn++;
|
||||
if (amdtpCb->txPktSn == 16)
|
||||
{
|
||||
amdtpCb->txPktSn = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// packet transfer successful or other error
|
||||
// reset packet
|
||||
resetPkt(&amdtpCb->txPkt);
|
||||
|
||||
// notify application layer
|
||||
if (amdtpCb->transCback)
|
||||
{
|
||||
amdtpCb->transCback(status);
|
||||
}
|
||||
}
|
||||
resetPkt(&amdtpCb->ackPkt);
|
||||
}
|
||||
break;
|
||||
|
||||
case AMDTP_PKT_TYPE_CONTROL:
|
||||
{
|
||||
eAmdtpControl_t control = (eAmdtpControl_t)buf[0];
|
||||
uint8_t resendPktSn = buf[1];
|
||||
if (control == AMDTP_CONTROL_RESEND_REQ)
|
||||
{
|
||||
APP_TRACE_INFO2("resendPktSn = %d, lastRxPktSn = %d", resendPktSn, amdtpCb->lastRxPktSn);
|
||||
amdtpCb->rxState = AMDTP_STATE_RX_IDLE;
|
||||
resetPkt(&amdtpCb->rxPkt);
|
||||
if (resendPktSn > amdtpCb->lastRxPktSn)
|
||||
{
|
||||
AmdtpSendReply(amdtpCb, AMDTP_STATUS_RESEND_REPLY, NULL, 0);
|
||||
}
|
||||
else if (resendPktSn == amdtpCb->lastRxPktSn)
|
||||
{
|
||||
AmdtpSendReply(amdtpCb, AMDTP_STATUS_SUCCESS, NULL, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
APP_TRACE_WARN2("resendPktSn = %d, lastRxPktSn = %d", resendPktSn, amdtpCb->lastRxPktSn);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
APP_TRACE_WARN1("unexpected contrl = %d\n", control);
|
||||
}
|
||||
resetPkt(&amdtpCb->ackPkt);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AmdtpBuildPkt(amdtpCb_t *amdtpCb, eAmdtpPktType_t type, bool_t encrypted, bool_t enableACK, uint8_t *buf, uint16_t len)
|
||||
{
|
||||
uint16_t header = 0;
|
||||
uint32_t calDataCrc;
|
||||
amdtpPacket_t *pkt;
|
||||
|
||||
if (type == AMDTP_PKT_TYPE_DATA)
|
||||
{
|
||||
pkt = &amdtpCb->txPkt;
|
||||
header = amdtpCb->txPktSn << PACKET_SN_BIT_OFFSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
pkt = &amdtpCb->ackPkt;
|
||||
}
|
||||
|
||||
//
|
||||
// Prepare header frame to be sent first
|
||||
//
|
||||
// length
|
||||
pkt->len = len + AMDTP_PREFIX_SIZE_IN_PKT + AMDTP_CRC_SIZE_IN_PKT;
|
||||
pkt->data[0] = (len + AMDTP_CRC_SIZE_IN_PKT) & 0xff;
|
||||
pkt->data[1] = ((len + AMDTP_CRC_SIZE_IN_PKT) >> 8) & 0xff;
|
||||
|
||||
// header
|
||||
header = header | (type << PACKET_TYPE_BIT_OFFSET);
|
||||
if (encrypted)
|
||||
{
|
||||
header = header | (1 << PACKET_ENCRYPTION_BIT_OFFSET);
|
||||
}
|
||||
if (enableACK)
|
||||
{
|
||||
header = header | (1 << PACKET_ACK_BIT_OFFSET);
|
||||
}
|
||||
pkt->data[2] = (header & 0xff);
|
||||
pkt->data[3] = (header >> 8);
|
||||
|
||||
// copy data
|
||||
memcpy(&(pkt->data[AMDTP_PREFIX_SIZE_IN_PKT]), buf, len);
|
||||
calDataCrc = CalcCrc32(0xFFFFFFFFU, len, buf);
|
||||
|
||||
// add checksum
|
||||
pkt->data[AMDTP_PREFIX_SIZE_IN_PKT + len] = (calDataCrc & 0xff);
|
||||
pkt->data[AMDTP_PREFIX_SIZE_IN_PKT + len + 1] = ((calDataCrc >> 8) & 0xff);
|
||||
pkt->data[AMDTP_PREFIX_SIZE_IN_PKT + len + 2] = ((calDataCrc >> 16) & 0xff);
|
||||
pkt->data[AMDTP_PREFIX_SIZE_IN_PKT + len + 3] = ((calDataCrc >> 24) & 0xff);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Send Reply to Sender
|
||||
//
|
||||
//*****************************************************************************
|
||||
void
|
||||
AmdtpSendReply(amdtpCb_t *amdtpCb, eAmdtpStatus_t status, uint8_t *data, uint16_t len)
|
||||
{
|
||||
uint8_t buf[ATT_DEFAULT_PAYLOAD_LEN] = {0};
|
||||
eAmdtpStatus_t st;
|
||||
|
||||
WSF_ASSERT(len < ATT_DEFAULT_PAYLOAD_LEN);
|
||||
|
||||
buf[0] = status;
|
||||
if (len > 0)
|
||||
{
|
||||
memcpy(buf + 1, data, len);
|
||||
}
|
||||
st = amdtpCb->ack_sender_func(AMDTP_PKT_TYPE_ACK, false, false, buf, len + 1);
|
||||
if (st != AMDTP_STATUS_SUCCESS)
|
||||
{
|
||||
APP_TRACE_WARN1("AmdtpSendReply status = %d\n", status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Send control message to Receiver
|
||||
//
|
||||
//*****************************************************************************
|
||||
void
|
||||
AmdtpSendControl(amdtpCb_t *amdtpCb, eAmdtpControl_t control, uint8_t *data, uint16_t len)
|
||||
{
|
||||
uint8_t buf[ATT_DEFAULT_PAYLOAD_LEN] = {0};
|
||||
eAmdtpStatus_t st;
|
||||
|
||||
WSF_ASSERT(len < ATT_DEFAULT_PAYLOAD_LEN);
|
||||
|
||||
buf[0] = control;
|
||||
if (len > 0)
|
||||
{
|
||||
memcpy(buf + 1, data, len);
|
||||
}
|
||||
st = amdtpCb->ack_sender_func(AMDTP_PKT_TYPE_CONTROL, false, false, buf, len + 1);
|
||||
if (st != AMDTP_STATUS_SUCCESS)
|
||||
{
|
||||
APP_TRACE_WARN1("AmdtpSendControl status = %d\n", st);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AmdtpSendPacketHandler(amdtpCb_t *amdtpCb)
|
||||
{
|
||||
uint16_t transferSize = 0;
|
||||
uint16_t remainingBytes = 0;
|
||||
amdtpPacket_t *txPkt = &amdtpCb->txPkt;
|
||||
|
||||
if ( amdtpCb->txState == AMDTP_STATE_TX_IDLE )
|
||||
{
|
||||
txPkt->offset = 0;
|
||||
amdtpCb->txState = AMDTP_STATE_SENDING;
|
||||
}
|
||||
|
||||
if ( txPkt->offset >= txPkt->len )
|
||||
{
|
||||
// done sent packet
|
||||
amdtpCb->txState = AMDTP_STATE_WAITING_ACK;
|
||||
// start tx timeout timer
|
||||
WsfTimerStartMs(&amdtpCb->timeoutTimer, amdtpCb->txTimeoutMs);
|
||||
}
|
||||
else
|
||||
{
|
||||
remainingBytes = txPkt->len - txPkt->offset;
|
||||
transferSize = ((amdtpCb->attMtuSize - 3) > remainingBytes)
|
||||
? remainingBytes
|
||||
: (amdtpCb->attMtuSize - 3);
|
||||
// send packet
|
||||
amdtpCb->data_sender_func(&txPkt->data[txPkt->offset], transferSize);
|
||||
txPkt->offset += transferSize;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
// ****************************************************************************
|
||||
//
|
||||
// amdtp_common.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief This file provides the shared functions for the AMDTP service.
|
||||
//!
|
||||
//! @{
|
||||
//
|
||||
// ****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifndef AMDTP_COMMON_H
|
||||
#define AMDTP_COMMON_H
|
||||
|
||||
#include "wsf_types.h"
|
||||
#include "wsf_timer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Macro definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
#define AMDTP_MAX_PAYLOAD_SIZE 2048//512
|
||||
#define AMDTP_PACKET_SIZE (AMDTP_MAX_PAYLOAD_SIZE + AMDTP_PREFIX_SIZE_IN_PKT + AMDTP_CRC_SIZE_IN_PKT) // Bytes
|
||||
#define AMDTP_LENGTH_SIZE_IN_PKT 2
|
||||
#define AMDTP_HEADER_SIZE_IN_PKT 2
|
||||
#define AMDTP_CRC_SIZE_IN_PKT 4
|
||||
#define AMDTP_PREFIX_SIZE_IN_PKT AMDTP_LENGTH_SIZE_IN_PKT + AMDTP_HEADER_SIZE_IN_PKT
|
||||
|
||||
#define PACKET_TYPE_BIT_OFFSET 12
|
||||
#define PACKET_TYPE_BIT_MASK (0xf << PACKET_TYPE_BIT_OFFSET)
|
||||
#define PACKET_SN_BIT_OFFSET 8
|
||||
#define PACKET_SN_BIT_MASK (0xf << PACKET_SN_BIT_OFFSET)
|
||||
#define PACKET_ENCRYPTION_BIT_OFFSET 7
|
||||
#define PACKET_ENCRYPTION_BIT_MASK (0x1 << PACKET_ENCRYPTION_BIT_OFFSET)
|
||||
#define PACKET_ACK_BIT_OFFSET 6
|
||||
#define PACKET_ACK_BIT_MASK (0x1 << PACKET_ACK_BIT_OFFSET)
|
||||
|
||||
#define TX_TIMEOUT_DEFAULT 1000
|
||||
|
||||
//
|
||||
// amdtp states
|
||||
//
|
||||
typedef enum eAmdtpState
|
||||
{
|
||||
AMDTP_STATE_INIT,
|
||||
AMDTP_STATE_TX_IDLE,
|
||||
AMDTP_STATE_RX_IDLE,
|
||||
AMDTP_STATE_SENDING,
|
||||
AMDTP_STATE_GETTING_DATA,
|
||||
AMDTP_STATE_WAITING_ACK,
|
||||
AMDTP_STATE_MAX
|
||||
}eAmdtpState_t;
|
||||
|
||||
//
|
||||
// amdtp packet type
|
||||
//
|
||||
typedef enum eAmdtpPktType
|
||||
{
|
||||
AMDTP_PKT_TYPE_UNKNOWN,
|
||||
AMDTP_PKT_TYPE_DATA,
|
||||
AMDTP_PKT_TYPE_ACK,
|
||||
AMDTP_PKT_TYPE_CONTROL,
|
||||
AMDTP_PKT_TYPE_MAX
|
||||
}eAmdtpPktType_t;
|
||||
|
||||
typedef enum eAmdtpControl
|
||||
{
|
||||
AMDTP_CONTROL_RESEND_REQ,
|
||||
AMDTP_CONTROL_MAX
|
||||
}eAmdtpControl_t;
|
||||
|
||||
//
|
||||
// amdtp status
|
||||
//
|
||||
typedef enum eAmdtpStatus
|
||||
{
|
||||
AMDTP_STATUS_SUCCESS,
|
||||
AMDTP_STATUS_CRC_ERROR,
|
||||
AMDTP_STATUS_INVALID_METADATA_INFO,
|
||||
AMDTP_STATUS_INVALID_PKT_LENGTH,
|
||||
AMDTP_STATUS_INSUFFICIENT_BUFFER,
|
||||
AMDTP_STATUS_UNKNOWN_ERROR,
|
||||
AMDTP_STATUS_BUSY,
|
||||
AMDTP_STATUS_TX_NOT_READY, // no connection or tx busy
|
||||
AMDTP_STATUS_RESEND_REPLY,
|
||||
AMDTP_STATUS_RECEIVE_CONTINUE,
|
||||
AMDTP_STATUS_RECEIVE_DONE,
|
||||
AMDTP_STATUS_MAX
|
||||
}eAmdtpStatus_t;
|
||||
|
||||
//
|
||||
// packet prefix structure
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
uint8_t pktType : 4;
|
||||
uint8_t pktSn : 4;
|
||||
uint8_t encrypted : 1;
|
||||
uint32_t ackEnabled : 1;
|
||||
uint32_t reserved : 6; // Reserved for future usage
|
||||
}
|
||||
amdtpPktHeader_t;
|
||||
|
||||
//
|
||||
// packet
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
uint16_t offset;
|
||||
uint16_t len; // data plus checksum
|
||||
amdtpPktHeader_t header;
|
||||
uint8_t *data;
|
||||
}
|
||||
amdtpPacket_t;
|
||||
|
||||
/*! Application data reception callback */
|
||||
typedef void (*amdtpRecvCback_t)(uint8_t *buf, uint16_t len);
|
||||
|
||||
/*! Application data transmission result callback */
|
||||
typedef void (*amdtpTransCback_t)(eAmdtpStatus_t status);
|
||||
|
||||
typedef void (*amdtp_reply_func_t)(eAmdtpStatus_t status, uint8_t *data, uint16_t len);
|
||||
|
||||
typedef void (*amdtp_packet_handler_func_t)(eAmdtpPktType_t type, uint16_t len, uint8_t *buf);
|
||||
|
||||
typedef eAmdtpStatus_t (*amdtp_ack_sender_func_t)(eAmdtpPktType_t type, bool_t encrypted, bool_t enableACK, uint8_t *buf, uint16_t len);
|
||||
|
||||
typedef void (*amdtp_data_sender_func_t)(uint8_t *buf, uint16_t len);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
eAmdtpState_t txState;
|
||||
eAmdtpState_t rxState;
|
||||
amdtpPacket_t rxPkt;
|
||||
amdtpPacket_t txPkt;
|
||||
amdtpPacket_t ackPkt;
|
||||
uint8_t txPktSn; // data packet serial number for Tx
|
||||
uint8_t lastRxPktSn; // last received data packet serial number
|
||||
uint16_t attMtuSize;
|
||||
wsfTimer_t timeoutTimer; // timeout timer after DTP update done
|
||||
wsfTimerTicks_t txTimeoutMs;
|
||||
amdtpRecvCback_t recvCback; // application callback for data reception
|
||||
amdtpTransCback_t transCback; // application callback for tx complete status
|
||||
amdtp_data_sender_func_t data_sender_func;
|
||||
amdtp_ack_sender_func_t ack_sender_func;
|
||||
}
|
||||
amdtpCb_t;
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// function definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
void
|
||||
AmdtpBuildPkt(amdtpCb_t *amdtpCb, eAmdtpPktType_t type, bool_t encrypted, bool_t enableACK, uint8_t *buf, uint16_t len);
|
||||
|
||||
eAmdtpStatus_t
|
||||
AmdtpReceivePkt(amdtpCb_t *amdtpCb, amdtpPacket_t *pkt, uint16_t len, uint8_t *pValue);
|
||||
|
||||
void
|
||||
AmdtpSendReply(amdtpCb_t *amdtpCb, eAmdtpStatus_t status, uint8_t *data, uint16_t len);
|
||||
|
||||
void
|
||||
AmdtpSendControl(amdtpCb_t *amdtpCb, eAmdtpControl_t control, uint8_t *data, uint16_t len);
|
||||
|
||||
void
|
||||
AmdtpSendPacketHandler(amdtpCb_t *amdtpCb);
|
||||
|
||||
void
|
||||
AmdtpPacketHandler(amdtpCb_t *amdtpCb, eAmdtpPktType_t type, uint16_t len, uint8_t *buf);
|
||||
|
||||
void
|
||||
resetPkt(amdtpPacket_t *pkt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // AMDTP_COMMON_H
|
||||
@@ -0,0 +1,109 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// amdtps_api.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Brief description of the header. No need to get fancy here.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifndef AMDTPS_API_H
|
||||
#define AMDTPS_API_H
|
||||
|
||||
#include "wsf_timer.h"
|
||||
#include "att_api.h"
|
||||
#include "amdtp_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Macro definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
|
||||
//
|
||||
// Connection control block
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
dmConnId_t connId; // Connection ID
|
||||
bool_t amdtpToSend; // AMDTP notify ready to be sent on this channel
|
||||
}
|
||||
amdtpsConn_t;
|
||||
|
||||
/*! Configurable parameters */
|
||||
typedef struct
|
||||
{
|
||||
//! Short description of each member should go here.
|
||||
uint32_t reserved;
|
||||
}
|
||||
AmdtpsCfg_t;
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// function definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
void amdtps_init(wsfHandlerId_t handlerId, AmdtpsCfg_t *pCfg, amdtpRecvCback_t recvCback, amdtpTransCback_t transCback);
|
||||
|
||||
void amdtps_proc_msg(wsfMsgHdr_t *pMsg);
|
||||
|
||||
uint8_t amdtps_write_cback(dmConnId_t connId, uint16_t handle, uint8_t operation,
|
||||
uint16_t offset, uint16_t len, uint8_t *pValue, attsAttr_t *pAttr);
|
||||
|
||||
void amdtps_start(dmConnId_t connId, uint8_t timerEvt, uint8_t amdtpCccIdx);
|
||||
|
||||
void amdtps_stop(dmConnId_t connId);
|
||||
|
||||
eAmdtpStatus_t
|
||||
AmdtpsSendPacket(eAmdtpPktType_t type, bool_t encrypted, bool_t enableACK, uint8_t *buf, uint16_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // AMDTPS_API_H
|
||||
@@ -0,0 +1,524 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// amdtps_main.c
|
||||
//! @file
|
||||
//!
|
||||
//! @brief This file provides the main application for the AMDTP service.
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include "wsf_types.h"
|
||||
#include "wsf_assert.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "wsf_buf.h" //for WsfBufAlloc and WsfBufFree
|
||||
#include "bstream.h"
|
||||
#include "att_api.h"
|
||||
#include "svc_ch.h"
|
||||
#include "svc_amdtp.h"
|
||||
#include "app_api.h"
|
||||
#include "app_hw.h"
|
||||
#include "amdtps_api.h"
|
||||
#include "am_util_debug.h"
|
||||
#include "crc32.h"
|
||||
|
||||
#include "am_mcu_apollo.h"
|
||||
#include "am_bsp.h"
|
||||
#include "am_util.h"
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Global variables
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
uint8_t rxPktBuf[AMDTP_PACKET_SIZE];
|
||||
uint8_t txPktBuf[AMDTP_PACKET_SIZE];
|
||||
uint8_t ackPktBuf[20];
|
||||
|
||||
#if defined(AMDTPS_RXONLY) || defined(AMDTPS_RX2TX)
|
||||
static int totalLen = 0;
|
||||
#endif
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Macro definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
/* Control block */
|
||||
static struct
|
||||
{
|
||||
amdtpsConn_t conn[DM_CONN_MAX]; // connection control block
|
||||
bool_t txReady; // TRUE if ready to send notifications
|
||||
wsfHandlerId_t appHandlerId;
|
||||
AmdtpsCfg_t cfg; // configurable parameters
|
||||
amdtpCb_t core;
|
||||
}
|
||||
amdtpsCb;
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Connection Open event
|
||||
//
|
||||
//*****************************************************************************
|
||||
static void
|
||||
amdtps_conn_open(dmEvt_t *pMsg)
|
||||
{
|
||||
hciLeConnCmplEvt_t *evt = (hciLeConnCmplEvt_t*) pMsg;
|
||||
|
||||
APP_TRACE_INFO0("connection opened\n");
|
||||
APP_TRACE_INFO1("handle = 0x%x\n", evt->handle);
|
||||
APP_TRACE_INFO1("role = 0x%x\n", evt->role);
|
||||
APP_TRACE_INFO3("addrMSB = %02x%02x%02x%02x%02x%02x\n", evt->peerAddr[0], evt->peerAddr[1], evt->peerAddr[2]);
|
||||
APP_TRACE_INFO3("addrLSB = %02x%02x%02x%02x%02x%02x\n", evt->peerAddr[3], evt->peerAddr[4], evt->peerAddr[5]);
|
||||
APP_TRACE_INFO1("connInterval = 0x%x\n", evt->connInterval);
|
||||
APP_TRACE_INFO1("connLatency = 0x%x\n", evt->connLatency);
|
||||
APP_TRACE_INFO1("supTimeout = 0x%x\n", evt->supTimeout);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Connection Update event
|
||||
//
|
||||
//*****************************************************************************
|
||||
static void
|
||||
amdtps_conn_update(dmEvt_t *pMsg)
|
||||
{
|
||||
hciLeConnUpdateCmplEvt_t *evt = (hciLeConnUpdateCmplEvt_t*) pMsg;
|
||||
|
||||
APP_TRACE_INFO1("connection update status = 0x%x", evt->status);
|
||||
APP_TRACE_INFO1("handle = 0x%x", evt->handle);
|
||||
APP_TRACE_INFO1("connInterval = 0x%x", evt->connInterval);
|
||||
APP_TRACE_INFO1("connLatency = 0x%x", evt->connLatency);
|
||||
APP_TRACE_INFO1("supTimeout = 0x%x", evt->supTimeout);
|
||||
}
|
||||
|
||||
static void amdtpsSetupToSend(void)
|
||||
{
|
||||
amdtpsConn_t *pConn = amdtpsCb.conn;
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < DM_CONN_MAX; i++, pConn++)
|
||||
{
|
||||
if (pConn->connId != DM_CONN_ID_NONE)
|
||||
{
|
||||
pConn->amdtpToSend = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Find Next Connection to Send on
|
||||
//
|
||||
//*****************************************************************************
|
||||
static amdtpsConn_t*
|
||||
amdtps_find_next2send(void)
|
||||
{
|
||||
amdtpsConn_t *pConn = amdtpsCb.conn;
|
||||
return pConn;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Send Notification to Client
|
||||
//
|
||||
//*****************************************************************************
|
||||
static void
|
||||
amdtpsSendData(uint8_t *buf, uint16_t len)
|
||||
{
|
||||
amdtpsSetupToSend();
|
||||
amdtpsConn_t *pConn = amdtps_find_next2send();
|
||||
/* send notification */
|
||||
if (pConn)
|
||||
{
|
||||
#ifdef AMDTP_DEBUG_ON
|
||||
APP_TRACE_INFO1("amdtpsSendData(), Send to connId = %d\n", pConn->connId);
|
||||
#endif
|
||||
AttsHandleValueNtf(pConn->connId, AMDTPS_TX_HDL, len, buf);
|
||||
|
||||
pConn->amdtpToSend = false;
|
||||
amdtpsCb.txReady = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
APP_TRACE_WARN1("Invalid Conn = %d\n", pConn->connId);
|
||||
}
|
||||
}
|
||||
|
||||
static eAmdtpStatus_t
|
||||
amdtpsSendAck(eAmdtpPktType_t type, bool_t encrypted, bool_t enableACK, uint8_t *buf, uint16_t len)
|
||||
{
|
||||
AmdtpBuildPkt(&amdtpsCb.core, type, encrypted, enableACK, buf, len);
|
||||
// send packet
|
||||
amdtpsSetupToSend();
|
||||
amdtpsConn_t *pConn = amdtps_find_next2send();
|
||||
/* send notification */
|
||||
if (pConn)
|
||||
{
|
||||
#ifdef AMDTP_DEBUG_ON
|
||||
APP_TRACE_INFO1("amdtpsSendAck(), Send to connId = %d\n", pConn->connId);
|
||||
#endif
|
||||
AttsHandleValueNtf(pConn->connId, AMDTPS_ACK_HDL, amdtpsCb.core.ackPkt.len, amdtpsCb.core.ackPkt.data);
|
||||
|
||||
pConn->amdtpToSend = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
APP_TRACE_WARN1("Invalid Conn = %d\n", pConn->connId);
|
||||
return AMDTP_STATUS_TX_NOT_READY;
|
||||
}
|
||||
|
||||
return AMDTP_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Timer Expiration handler
|
||||
//
|
||||
//*****************************************************************************
|
||||
static void
|
||||
amdtps_timeout_timer_expired(wsfMsgHdr_t *pMsg)
|
||||
{
|
||||
uint8_t data[1];
|
||||
data[0] = amdtpsCb.core.txPktSn;
|
||||
APP_TRACE_INFO1("amdtps tx timeout, txPktSn = %d", amdtpsCb.core.txPktSn);
|
||||
AmdtpSendControl(&amdtpsCb.core, AMDTP_CONTROL_RESEND_REQ, data, 1);
|
||||
// fire a timer for receiving an AMDTP_STATUS_RESEND_REPLY ACK
|
||||
WsfTimerStartMs(&amdtpsCb.core.timeoutTimer, amdtpsCb.core.txTimeoutMs);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn amdtpsHandleValueCnf
|
||||
*
|
||||
* \brief Handle a received ATT handle value confirm.
|
||||
*
|
||||
* \param pMsg Event message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void
|
||||
amdtpsHandleValueCnf(attEvt_t *pMsg)
|
||||
{
|
||||
//APP_TRACE_INFO2("Cnf status = %d, handle = 0x%x\n", pMsg->hdr.status, pMsg->handle);
|
||||
if (pMsg->hdr.status == ATT_SUCCESS)
|
||||
{
|
||||
#if !defined(AMDTPS_RXONLY) && !defined(AMDTPS_RX2TX)
|
||||
if (pMsg->handle == AMDTPS_TX_HDL)
|
||||
{
|
||||
amdtpsCb.txReady = true;
|
||||
// process next data
|
||||
AmdtpSendPacketHandler(&amdtpsCb.core);
|
||||
#ifdef AMDTPS_TXTEST
|
||||
// fixme when last packet, continue to send next one.
|
||||
if (amdtpsCb.core.txState == AMDTP_STATE_WAITING_ACK)
|
||||
{
|
||||
uint8_t temp[3];
|
||||
temp[0] = AMDTP_STATUS_SUCCESS;
|
||||
AmdtpPacketHandler(&amdtpsCb.core, AMDTP_PKT_TYPE_ACK, 3, temp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0 //def AMDTPS_TXTEST
|
||||
// workround for ATT timeout issue
|
||||
/* Connection control block */
|
||||
typedef struct
|
||||
{
|
||||
|
||||
wsfQueue_t prepWriteQueue; /* prepare write queue */
|
||||
wsfTimer_t idleTimer; /* service discovery idle timer */
|
||||
uint16_t handle; /* connection handle */
|
||||
uint16_t mtu; /* connection mtu */
|
||||
dmConnId_t connId; /* DM connection ID */
|
||||
bool_t mtuSent; /* MTU req or rsp sent */
|
||||
bool_t flowDisabled; /* Data flow disabled */
|
||||
bool_t transTimedOut; /* ATT transaction timed out */
|
||||
} attCcb_t;
|
||||
extern attCcb_t *attCcbByConnId(dmConnId_t connId);
|
||||
if (pMsg->hdr.status == 0x71)
|
||||
{
|
||||
attCcb_t *ccb = attCcbByConnId(1);
|
||||
ccb->transTimedOut = FALSE;
|
||||
}
|
||||
#endif
|
||||
APP_TRACE_WARN2("cnf status = %d, hdl = 0x%x\n", pMsg->hdr.status, pMsg->handle);
|
||||
}
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @brief initialize amdtp service
|
||||
//!
|
||||
//! @param handlerId - connection handle
|
||||
//! @param pCfg - configuration parameters
|
||||
//!
|
||||
//! @return None
|
||||
//
|
||||
//*****************************************************************************
|
||||
void
|
||||
amdtps_init(wsfHandlerId_t handlerId, AmdtpsCfg_t *pCfg, amdtpRecvCback_t recvCback, amdtpTransCback_t transCback)
|
||||
{
|
||||
memset(&amdtpsCb, 0, sizeof(amdtpsCb));
|
||||
amdtpsCb.appHandlerId = handlerId;
|
||||
amdtpsCb.txReady = false;
|
||||
amdtpsCb.core.txState = AMDTP_STATE_INIT;
|
||||
amdtpsCb.core.rxState = AMDTP_STATE_RX_IDLE;
|
||||
amdtpsCb.core.timeoutTimer.handlerId = handlerId;
|
||||
for (int i = 0; i < DM_CONN_MAX; i++)
|
||||
{
|
||||
amdtpsCb.conn[i].connId = DM_CONN_ID_NONE;
|
||||
}
|
||||
|
||||
amdtpsCb.core.lastRxPktSn = 0;
|
||||
amdtpsCb.core.txPktSn = 0;
|
||||
|
||||
resetPkt(&amdtpsCb.core.rxPkt);
|
||||
amdtpsCb.core.rxPkt.data = rxPktBuf;
|
||||
|
||||
resetPkt(&amdtpsCb.core.txPkt);
|
||||
amdtpsCb.core.txPkt.data = txPktBuf;
|
||||
|
||||
resetPkt(&amdtpsCb.core.ackPkt);
|
||||
amdtpsCb.core.ackPkt.data = ackPktBuf;
|
||||
|
||||
amdtpsCb.core.recvCback = recvCback;
|
||||
amdtpsCb.core.transCback = transCback;
|
||||
|
||||
amdtpsCb.core.txTimeoutMs = TX_TIMEOUT_DEFAULT;
|
||||
|
||||
amdtpsCb.core.data_sender_func = amdtpsSendData;
|
||||
amdtpsCb.core.ack_sender_func = amdtpsSendAck;
|
||||
}
|
||||
|
||||
static void
|
||||
amdtps_conn_close(dmEvt_t *pMsg)
|
||||
{
|
||||
hciDisconnectCmplEvt_t *evt = (hciDisconnectCmplEvt_t*) pMsg;
|
||||
dmConnId_t connId = evt->hdr.param;
|
||||
/* clear connection */
|
||||
amdtpsCb.conn[connId - 1].connId = DM_CONN_ID_NONE;
|
||||
amdtpsCb.conn[connId - 1].amdtpToSend = FALSE;
|
||||
|
||||
WsfTimerStop(&amdtpsCb.core.timeoutTimer);
|
||||
amdtpsCb.core.txState = AMDTP_STATE_INIT;
|
||||
amdtpsCb.core.rxState = AMDTP_STATE_RX_IDLE;
|
||||
amdtpsCb.core.lastRxPktSn = 0;
|
||||
amdtpsCb.core.txPktSn = 0;
|
||||
resetPkt(&amdtpsCb.core.rxPkt);
|
||||
resetPkt(&amdtpsCb.core.txPkt);
|
||||
resetPkt(&amdtpsCb.core.ackPkt);
|
||||
|
||||
#if defined(AMDTPS_RXONLY) || defined(AMDTPS_RX2TX)
|
||||
APP_TRACE_INFO1("*** RECEIVED TOTAL %d ***", totalLen);
|
||||
totalLen = 0;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
uint8_t
|
||||
amdtps_write_cback(dmConnId_t connId, uint16_t handle, uint8_t operation,
|
||||
uint16_t offset, uint16_t len, uint8_t *pValue, attsAttr_t *pAttr)
|
||||
{
|
||||
eAmdtpStatus_t status = AMDTP_STATUS_UNKNOWN_ERROR;
|
||||
amdtpPacket_t *pkt = NULL;
|
||||
#if 0
|
||||
uint16_t i = 0;
|
||||
APP_TRACE_INFO0("============= data arrived start ===============");
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
APP_TRACE_INFO1("%x\t", pValue[i]);
|
||||
}
|
||||
APP_TRACE_INFO0("");
|
||||
APP_TRACE_INFO0("============= data arrived end ===============");
|
||||
#endif
|
||||
if (handle == AMDTPS_RX_HDL)
|
||||
{
|
||||
#if defined(AMDTPS_RX2TX)
|
||||
amdtpsSendData(pValue, len);
|
||||
#endif
|
||||
#if defined(AMDTPS_RXONLY) || defined(AMDTPS_RX2TX)
|
||||
totalLen += len;
|
||||
APP_TRACE_INFO2("received data len %d, total %d", len, totalLen);
|
||||
return ATT_SUCCESS;
|
||||
#else /* RXONLY && RX2TX */
|
||||
status = AmdtpReceivePkt(&amdtpsCb.core, &amdtpsCb.core.rxPkt, len, pValue);
|
||||
#endif /* RXONLY && RX2TX */
|
||||
}
|
||||
else if (handle == AMDTPS_ACK_HDL)
|
||||
{
|
||||
status = AmdtpReceivePkt(&amdtpsCb.core, &amdtpsCb.core.ackPkt, len, pValue);
|
||||
}
|
||||
|
||||
if (status == AMDTP_STATUS_RECEIVE_DONE)
|
||||
{
|
||||
if (handle == AMDTPS_RX_HDL)
|
||||
{
|
||||
pkt = &amdtpsCb.core.rxPkt;
|
||||
}
|
||||
else if (handle == AMDTPS_ACK_HDL)
|
||||
{
|
||||
pkt = &amdtpsCb.core.ackPkt;
|
||||
}
|
||||
|
||||
AmdtpPacketHandler(&amdtpsCb.core, (eAmdtpPktType_t)pkt->header.pktType, pkt->len - AMDTP_CRC_SIZE_IN_PKT, pkt->data);
|
||||
}
|
||||
|
||||
return ATT_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
amdtps_start(dmConnId_t connId, uint8_t timerEvt, uint8_t amdtpCccIdx)
|
||||
{
|
||||
//
|
||||
// set conn id
|
||||
//
|
||||
amdtpsCb.conn[connId - 1].connId = connId;
|
||||
amdtpsCb.conn[connId - 1].amdtpToSend = TRUE;
|
||||
|
||||
amdtpsCb.core.timeoutTimer.msg.event = timerEvt;
|
||||
amdtpsCb.core.txState = AMDTP_STATE_TX_IDLE;
|
||||
amdtpsCb.txReady = true;
|
||||
|
||||
amdtpsCb.core.attMtuSize = AttGetMtu(connId);
|
||||
APP_TRACE_INFO1("MTU size = %d bytes", amdtpsCb.core.attMtuSize);
|
||||
}
|
||||
|
||||
void
|
||||
amdtps_stop(dmConnId_t connId)
|
||||
{
|
||||
//
|
||||
// clear connection
|
||||
//
|
||||
amdtpsCb.conn[connId - 1].connId = DM_CONN_ID_NONE;
|
||||
amdtpsCb.conn[connId - 1].amdtpToSend = FALSE;
|
||||
|
||||
amdtpsCb.core.txState = AMDTP_STATE_INIT;
|
||||
amdtpsCb.txReady = false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
amdtps_proc_msg(wsfMsgHdr_t *pMsg)
|
||||
{
|
||||
if (pMsg->event == DM_CONN_OPEN_IND)
|
||||
{
|
||||
amdtps_conn_open((dmEvt_t *) pMsg);
|
||||
}
|
||||
else if (pMsg->event == DM_CONN_CLOSE_IND)
|
||||
{
|
||||
amdtps_conn_close((dmEvt_t *) pMsg);
|
||||
}
|
||||
else if (pMsg->event == DM_CONN_UPDATE_IND)
|
||||
{
|
||||
amdtps_conn_update((dmEvt_t *) pMsg);
|
||||
}
|
||||
else if (pMsg->event == amdtpsCb.core.timeoutTimer.msg.event)
|
||||
{
|
||||
amdtps_timeout_timer_expired(pMsg);
|
||||
}
|
||||
else if (pMsg->event == ATTS_HANDLE_VALUE_CNF)
|
||||
{
|
||||
amdtpsHandleValueCnf((attEvt_t *) pMsg);
|
||||
}
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @brief Send data to Client via notification
|
||||
//!
|
||||
//! @param type - packet type
|
||||
//! @param encrypted - is packet encrypted
|
||||
//! @param enableACK - does client need to response
|
||||
//! @param buf - data
|
||||
//! @param len - data length
|
||||
//!
|
||||
//! @return status
|
||||
//
|
||||
//*****************************************************************************
|
||||
eAmdtpStatus_t
|
||||
AmdtpsSendPacket(eAmdtpPktType_t type, bool_t encrypted, bool_t enableACK, uint8_t *buf, uint16_t len)
|
||||
{
|
||||
//
|
||||
// Check if ready to send notification
|
||||
//
|
||||
if ( !amdtpsCb.txReady )
|
||||
{
|
||||
//set in callback amdtpsHandleValueCnf
|
||||
APP_TRACE_INFO1("data sending failed, not ready for notification.", NULL);
|
||||
return AMDTP_STATUS_TX_NOT_READY;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if the service is idle to send
|
||||
//
|
||||
if ( amdtpsCb.core.txState != AMDTP_STATE_TX_IDLE )
|
||||
{
|
||||
APP_TRACE_INFO1("data sending failed, tx state = %d", amdtpsCb.core.txState);
|
||||
return AMDTP_STATUS_BUSY;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if data length is valid
|
||||
//
|
||||
if ( len > AMDTP_MAX_PAYLOAD_SIZE )
|
||||
{
|
||||
APP_TRACE_INFO1("data sending failed, exceed maximum payload, len = %d.", len);
|
||||
return AMDTP_STATUS_INVALID_PKT_LENGTH;
|
||||
}
|
||||
|
||||
AmdtpBuildPkt(&amdtpsCb.core, type, encrypted, enableACK, buf, len);
|
||||
|
||||
// send packet
|
||||
AmdtpSendPacketHandler(&amdtpsCb.core);
|
||||
|
||||
return AMDTP_STATUS_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// amotas_api.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Brief description of the header. No need to get fancy here.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
#ifndef AMOTAS_API_H
|
||||
#define AMOTAS_API_H
|
||||
|
||||
#include "wsf_timer.h"
|
||||
#include "att_api.h"
|
||||
|
||||
// enable debug print for AMOTA profile
|
||||
// #define AMOTA_DEBUG_ON
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Macro definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
#define AMOTA_PACKET_SIZE (512 + 16) // Bytes
|
||||
#define AMOTA_LENGTH_SIZE_IN_PKT 2
|
||||
#define AMOTA_CMD_SIZE_IN_PKT 1
|
||||
#define AMOTA_CRC_SIZE_IN_PKT 4
|
||||
#define AMOTA_HEADER_SIZE_IN_PKT AMOTA_LENGTH_SIZE_IN_PKT + AMOTA_CMD_SIZE_IN_PKT
|
||||
|
||||
#define AMOTA_FW_HEADER_SIZE 44
|
||||
|
||||
#define AMOTA_FW_STORAGE_INTERNAL 0
|
||||
#define AMOTA_FW_STORAGE_EXTERNAL 1
|
||||
|
||||
/*! Configurable parameters */
|
||||
typedef struct
|
||||
{
|
||||
//! Short description of each member should go here.
|
||||
uint32_t reserved;
|
||||
}
|
||||
AmotasCfg_t;
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// External variable definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// External function definitions.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// function definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
void amotas_init(wsfHandlerId_t handlerId, AmotasCfg_t *pCfg);
|
||||
|
||||
void amotas_proc_msg(wsfMsgHdr_t *pMsg);
|
||||
|
||||
uint8_t amotas_write_cback(dmConnId_t connId, uint16_t handle, uint8_t operation,
|
||||
uint16_t offset, uint16_t len, uint8_t *pValue, attsAttr_t *pAttr);
|
||||
|
||||
void amotas_start(dmConnId_t connId, uint8_t resetTimerEvt, uint8_t disconnectTimerEvt, uint8_t amotaCccIdx);
|
||||
|
||||
void amotas_stop(dmConnId_t connId);
|
||||
|
||||
extern void amotas_conn_close(dmConnId_t connId);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // AMOTAS_API_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,232 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// ancc_api.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief apple notification center service client.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifndef ANCC_API_H
|
||||
#define ANCC_API_H
|
||||
|
||||
#include "att_api.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**************************************************************************************************
|
||||
Macros
|
||||
**************************************************************************************************/
|
||||
/* ANCS Service */ // 7905F431-B5CE-4E99-A40F-4B1E122D00D0
|
||||
#define ATT_UUID_ANCS_SERVICE 0xd0, 0x00, 0x2d, 0x12, 0x1e, 0x4b, 0x0f, 0xa4,\
|
||||
0x99, 0x4e, 0xce, 0xb5, 0x31, 0xf4, 0x05, 0x79
|
||||
/* ANCS characteristics */
|
||||
// 9FBF120D-6301-42D9-8C58-25E699A21DBD
|
||||
#define ATT_UUID_NOTIFICATION_SOURCE 0xbd, 0x1d, 0xa2, 0x99, 0xe6, 0x25, 0x58, 0x8c, \
|
||||
0xd9, 0x42, 0x01, 0x63, 0x0d, 0x12, 0xbf, 0x9f
|
||||
|
||||
//69D1D8F3-45E1-49A8-9821-9BBDFDAAD9D9
|
||||
#define ATT_UUID_CTRL_POINT 0xd9, 0xd9, 0xaa, 0xfd, 0xbd, 0x9b, 0x21, 0x98,\
|
||||
0xa8, 0x49, 0xe1, 0x45, 0xf3, 0xd8, 0xd1, 0x69
|
||||
|
||||
// 22EAC6E9-24D6-4BB5-BE44-B36ACE7C7BFB
|
||||
#define ATT_UUID_DATA_SOURCE 0xfb, 0x7b, 0x7c, 0xce, 0x6a, 0xb3, 0x44, 0xbe,\
|
||||
0xb5, 0x4b, 0xd6, 0x24, 0xe9, 0xc6, 0xea, 0x22
|
||||
|
||||
#define ANCC_LIST_ELEMENTS 64
|
||||
#define ANCC_APP_IDENTIFIER_SIZE_BYTES 64
|
||||
#define ANCC_ATTRI_BUFFER_SIZE_BYTES 512
|
||||
|
||||
/**@brief Category IDs for iOS notifications. */
|
||||
typedef enum
|
||||
{
|
||||
BLE_ANCS_CATEGORY_ID_OTHER, /**< The iOS notification belongs to the "other" category. */
|
||||
BLE_ANCS_CATEGORY_ID_INCOMING_CALL, /**< The iOS notification belongs to the "Incoming Call" category. */
|
||||
BLE_ANCS_CATEGORY_ID_MISSED_CALL, /**< The iOS notification belongs to the "Missed Call" category. */
|
||||
BLE_ANCS_CATEGORY_ID_VOICE_MAIL, /**< The iOS notification belongs to the "Voice Mail" category. */
|
||||
BLE_ANCS_CATEGORY_ID_SOCIAL, /**< The iOS notification belongs to the "Social" category. */
|
||||
BLE_ANCS_CATEGORY_ID_SCHEDULE, /**< The iOS notification belongs to the "Schedule" category. */
|
||||
BLE_ANCS_CATEGORY_ID_EMAIL, /**< The iOS notification belongs to the "E-mail" category. */
|
||||
BLE_ANCS_CATEGORY_ID_NEWS, /**< The iOS notification belongs to the "News" category. */
|
||||
BLE_ANCS_CATEGORY_ID_HEALTH_AND_FITNESS, /**< The iOS notification belongs to the "Health and Fitness" category. */
|
||||
BLE_ANCS_CATEGORY_ID_BUSINESS_AND_FINANCE, /**< The iOS notification belongs to the "Buisness and Finance" category. */
|
||||
BLE_ANCS_CATEGORY_ID_LOCATION, /**< The iOS notification belongs to the "Location" category. */
|
||||
BLE_ANCS_CATEGORY_ID_ENTERTAINMENT /**< The iOS notification belongs to the "Entertainment" category. */
|
||||
} ancc_category_id_values_t;
|
||||
|
||||
/**@brief Event IDs for iOS notifications. */
|
||||
typedef enum
|
||||
{
|
||||
BLE_ANCS_EVENT_ID_NOTIFICATION_ADDED, /**< The iOS notification was added. */
|
||||
BLE_ANCS_EVENT_ID_NOTIFICATION_MODIFIED, /**< The iOS notification was modified. */
|
||||
BLE_ANCS_EVENT_ID_NOTIFICATION_REMOVED /**< The iOS notification was removed. */
|
||||
} ancc_evt_id_values_t;
|
||||
|
||||
/**@brief Control point command IDs that the Notification Consumer can send to the Notification Provider. */
|
||||
typedef enum
|
||||
{
|
||||
BLE_ANCS_COMMAND_ID_GET_NOTIF_ATTRIBUTES, /**< Requests attributes to be sent from the NP to the NC for a given notification. */
|
||||
BLE_ANCS_COMMAND_ID_GET_APP_ATTRIBUTES, /**< Requests attributes to be sent from the NP to the NC for a given iOS App. */
|
||||
BLE_ANCS_COMMAND_ID_GET_PERFORM_NOTIF_ACTION, /**< Requests an action to be performed on a given notification, for example dismiss an alarm. */
|
||||
} ancc_command_id_values_t;
|
||||
|
||||
/**@brief IDs for iOS notification attributes. */
|
||||
typedef enum
|
||||
{
|
||||
BLE_ANCS_NOTIF_ATTR_ID_APP_IDENTIFIER, /**< Identifies that the attribute data is of an "App Identifier" type. */
|
||||
BLE_ANCS_NOTIF_ATTR_ID_TITLE, /**< Identifies that the attribute data is a "Title". Needs to be followed by a 2-bytes max length parameter*/
|
||||
BLE_ANCS_NOTIF_ATTR_ID_SUBTITLE, /**< Identifies that the attribute data is a "Subtitle". Needs to be followed by a 2-bytes max length parameter*/
|
||||
BLE_ANCS_NOTIF_ATTR_ID_MESSAGE, /**< Identifies that the attribute data is a "Message". Needs to be followed by a 2-bytes max length parameter*/
|
||||
BLE_ANCS_NOTIF_ATTR_ID_MESSAGE_SIZE, /**< Identifies that the attribute data is a "Message Size". */
|
||||
BLE_ANCS_NOTIF_ATTR_ID_DATE, /**< Identifies that the attribute data is a "Date". */
|
||||
BLE_ANCS_NOTIF_ATTR_ID_POSITIVE_ACTION_LABEL, /**< The notification has a "Positive action" that can be executed associated with it. */
|
||||
BLE_ANCS_NOTIF_ATTR_ID_NEGATIVE_ACTION_LABEL, /**< The notification has a "Negative action" that can be executed associated with it. */
|
||||
} ancc_notif_attr_id_values_t;
|
||||
|
||||
/**@brief ActionID values. */
|
||||
typedef enum
|
||||
{
|
||||
BLE_ANCS_NOTIF_ACTION_ID_POSITIVE,
|
||||
BLE_ANCS_NOTIF_ACTION_ID_NEGATIVE,
|
||||
} ancc_notif_action_id_values_t;
|
||||
|
||||
|
||||
/**@brief Typedef for iOS notifications. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t event_id; /**< This field informs the accessory whether the given iOS notification was added, modified, or removed. The enumerated values for this field are defined in EventID Values.. */
|
||||
uint8_t event_flags; /**< A bitmask whose set bits inform an NC of specificities with the iOS notification. */
|
||||
uint8_t category_id; /**< A numerical value providing a category in which the iOS notification can be classified. */
|
||||
uint8_t category_count; /**< The current number of active iOS notifications in the given category. */
|
||||
uint32_t notification_uid; /**< A 32-bit numerical value that is the unique identifier (UID) for the iOS notification. */
|
||||
bool_t noti_valid; /**< A flag to indicate whether the notification is still valid in the list. */
|
||||
} ancc_notif_t;
|
||||
|
||||
/*! ancs client enumeration of handle indexes of characteristics to be discovered */
|
||||
enum
|
||||
{
|
||||
ANCC_NOTIFICATION_SOURCE_HDL_IDX, // ANCC Notification Source Handle
|
||||
ANCC_NOTIFICATION_SOURCE_CCC_HDL_IDX, // ANCC Notification Source CCC Handle
|
||||
ANCC_CONTROL_POINT_HDL_IDX, // ANCC Control Point Handle
|
||||
ANCC_DATA_SOURCE_HDL_IDX, // ANCC Data Source Handle
|
||||
ANCC_DATA_SOURCE_CCC_HDL_IDX, // ANCC Data Source CCC Handle
|
||||
ANCC_HDL_LIST_LEN /*! Handle list length */
|
||||
};
|
||||
|
||||
/*! Configurable parameters */
|
||||
typedef struct
|
||||
{
|
||||
wsfTimerTicks_t period; /*! action timer expiration period in ms */
|
||||
} anccCfg_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NOTI_ATTR_NEW_NOTIFICATION = 0,
|
||||
NOTI_ATTR_NEW_ATTRIBUTE,
|
||||
NOTI_ATTR_RECEIVING_ATTRIBUTE
|
||||
} enum_active_state_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t handle; // handle to indicate the current active notification in the list
|
||||
enum_active_state_t attrState;
|
||||
uint16_t bufIndex;
|
||||
uint16_t parseIndex;
|
||||
uint16_t attrLength;
|
||||
uint8_t attrId;
|
||||
uint16_t attrCount;
|
||||
uint8_t commandId;
|
||||
uint32_t notiUid;
|
||||
uint8_t appId[ANCC_APP_IDENTIFIER_SIZE_BYTES];
|
||||
uint8_t attrDataBuf[ANCC_ATTRI_BUFFER_SIZE_BYTES];
|
||||
} active_notif_t;
|
||||
|
||||
/*! Application data reception callback */
|
||||
typedef void (*anccAttrRecvCback_t)(active_notif_t* pAttr);
|
||||
typedef void (*anccNotiCmplCback_t)(active_notif_t* pAttr, uint32_t notiUid);
|
||||
|
||||
/*! Application notify remove callback */
|
||||
typedef void (*anccNotiRemoveCback_t)(ancc_notif_t* pAttr);
|
||||
typedef struct
|
||||
{
|
||||
dmConnId_t connId;
|
||||
uint16_t* hdlList;
|
||||
anccCfg_t cfg;
|
||||
wsfTimer_t actionTimer; // perform actions with proper delay
|
||||
wsfTimer_t discoverTimer; // perform service discovery delay
|
||||
ancc_notif_t anccList[ANCC_LIST_ELEMENTS]; // buffer size = MAX_LIST_ELEMENTS*sizeof(ancc_notif_t)
|
||||
active_notif_t active;
|
||||
anccAttrRecvCback_t attrCback;
|
||||
anccNotiCmplCback_t notiCback;
|
||||
anccNotiRemoveCback_t rmvCback;
|
||||
} anccCb_t;
|
||||
|
||||
/**************************************************************************************************
|
||||
Function Prototypes
|
||||
**************************************************************************************************/
|
||||
// operation interfaces
|
||||
void AncsPerformNotiAction(uint16_t *pHdlList, uint32_t notiUid, ancc_notif_action_id_values_t actionId);
|
||||
void AncsGetAppAttribute(uint16_t *pHdlList, uint8_t* appId);
|
||||
void AnccGetNotificationAttribute(uint16_t *pHdlList, uint32_t notiUid);
|
||||
|
||||
// initialization interfaces
|
||||
void AnccInit(wsfHandlerId_t handlerId, anccCfg_t* cfg, uint8_t disctimer_event);
|
||||
void AnccCbackRegister(anccAttrRecvCback_t attrCback, anccNotiCmplCback_t notiCback, anccNotiRemoveCback_t rmvCback);
|
||||
|
||||
// app routines
|
||||
void AnccNtfValueUpdate(uint16_t *pHdlList, attEvt_t * pMsg, uint8_t actionTimerEvt);
|
||||
void AnccActionHandler(uint8_t actionTimerEvt);
|
||||
void AnccActionStop(void);
|
||||
void AnccActionStart(uint8_t timerEvt);
|
||||
void AnccConnClose(void);
|
||||
void AnccConnOpen(dmConnId_t connId, uint16_t* hdlList);
|
||||
void AnccSvcDiscover(dmConnId_t connId, uint16_t *pHdlList);
|
||||
bool_t AnccStartServiceDiscovery(void);
|
||||
|
||||
/* Global variable */
|
||||
extern anccCb_t anccCb;
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* ANCC_API_H */
|
||||
@@ -0,0 +1,709 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// ancc_main.c
|
||||
//! @file
|
||||
//!
|
||||
//! @brief apple notification center service client.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#include <string.h>
|
||||
#include "wsf_types.h"
|
||||
#include "wsf_assert.h"
|
||||
#include "bstream.h"
|
||||
#include "app_api.h"
|
||||
#include "ancc_api.h"
|
||||
|
||||
#include "am_util.h"
|
||||
|
||||
/**************************************************************************************************
|
||||
Local Variables
|
||||
**************************************************************************************************/
|
||||
|
||||
/*!
|
||||
* Apple Notification Center Service Client (ANCC)
|
||||
*/
|
||||
|
||||
/* UUIDs */
|
||||
static const uint8_t anccAncsSvcUuid[] = {ATT_UUID_ANCS_SERVICE}; /*! ANCS Service UUID */
|
||||
static const uint8_t anccNSChUuid[] = {ATT_UUID_NOTIFICATION_SOURCE}; /*! Notification Source UUID */
|
||||
static const uint8_t anccCPChUuid[] = {ATT_UUID_CTRL_POINT}; /*! control point UUID*/
|
||||
static const uint8_t anccDSChUuid[] = {ATT_UUID_DATA_SOURCE}; /*! data source UUID*/
|
||||
/* Characteristics for discovery */
|
||||
|
||||
#define DISCOVER_TIMER_DELAY (3000) // ms
|
||||
|
||||
/*! Proprietary data */
|
||||
static const attcDiscChar_t anccNSDat =
|
||||
{
|
||||
anccNSChUuid,
|
||||
ATTC_SET_REQUIRED | ATTC_SET_UUID_128
|
||||
};
|
||||
|
||||
/*! Proprietary data descriptor */ //notification source
|
||||
static const attcDiscChar_t anccNSdatCcc =
|
||||
{
|
||||
attCliChCfgUuid,
|
||||
ATTC_SET_REQUIRED | ATTC_SET_DESCRIPTOR
|
||||
};
|
||||
// control point
|
||||
static const attcDiscChar_t anccCtrlPoint =
|
||||
{
|
||||
anccCPChUuid,
|
||||
ATTC_SET_REQUIRED | ATTC_SET_UUID_128
|
||||
};
|
||||
|
||||
// data source
|
||||
static const attcDiscChar_t anccDataSrc =
|
||||
{
|
||||
anccDSChUuid,
|
||||
ATTC_SET_REQUIRED | ATTC_SET_UUID_128
|
||||
};
|
||||
/*! Proprietary data descriptor */ //data source
|
||||
static const attcDiscChar_t anccDataSrcCcc =
|
||||
{
|
||||
attCliChCfgUuid,
|
||||
ATTC_SET_REQUIRED | ATTC_SET_DESCRIPTOR
|
||||
};
|
||||
|
||||
/*! List of characteristics to be discovered; order matches handle index enumeration */
|
||||
static const attcDiscChar_t *anccSvcDiscCharList[] =
|
||||
{
|
||||
&anccNSDat, /*! Proprietary data */
|
||||
&anccNSdatCcc, /*! Proprietary data descriptor */
|
||||
&anccCtrlPoint, /*! Control point */
|
||||
&anccDataSrc, /*! data source */
|
||||
&anccDataSrcCcc /*! data source descriptor */
|
||||
};
|
||||
|
||||
/* sanity check: make sure handle list length matches characteristic list length */
|
||||
WSF_CT_ASSERT(ANCC_HDL_LIST_LEN == ((sizeof(anccSvcDiscCharList) / sizeof(attcDiscChar_t *))));
|
||||
|
||||
/* Global variable */
|
||||
anccCb_t anccCb;
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AnccSvcDiscover
|
||||
*
|
||||
* \brief Perform service and characteristic discovery for ancs service.
|
||||
* Parameter pHdlList must point to an array of length ANCC_HDL_LIST_LEN.
|
||||
* If discovery is successful the handles of discovered characteristics and
|
||||
* descriptors will be set in pHdlList.
|
||||
*
|
||||
* \param connId Connection identifier.
|
||||
* \param pHdlList Characteristic handle list.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AnccSvcDiscover(dmConnId_t connId, uint16_t *pHdlList)
|
||||
{
|
||||
AppDiscFindService(connId, ATT_128_UUID_LEN, (uint8_t *) anccAncsSvcUuid,
|
||||
ANCC_HDL_LIST_LEN, (attcDiscChar_t **) anccSvcDiscCharList, pHdlList);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AnccInit
|
||||
*
|
||||
* \brief Initialize the control variables of ancs client
|
||||
*
|
||||
* \param handlerId App handler id for timer operation.
|
||||
* \param cfg config variable.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AnccInit(wsfHandlerId_t handlerId, anccCfg_t* cfg, uint8_t disctimer_event)
|
||||
{
|
||||
memset(anccCb.anccList, 0, ANCC_LIST_ELEMENTS * sizeof(ancc_notif_t));
|
||||
anccCb.cfg.period = cfg->period;
|
||||
anccCb.actionTimer.handlerId = handlerId;
|
||||
anccCb.discoverTimer.handlerId = handlerId;
|
||||
anccCb.discoverTimer.msg.event = disctimer_event;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AnccConnOpen
|
||||
*
|
||||
* \brief Update the key parameters for control variables when connection open.
|
||||
*
|
||||
* \param connId Connection identifier.
|
||||
* \param hdlList Characteristic handle list.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AnccConnOpen(dmConnId_t connId, uint16_t* hdlList)
|
||||
{
|
||||
anccCb.connId = connId;
|
||||
anccCb.hdlList = hdlList;
|
||||
|
||||
WsfTimerStop(&anccCb.discoverTimer);
|
||||
WsfTimerStartMs(&anccCb.discoverTimer, DISCOVER_TIMER_DELAY);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AnccConnClose
|
||||
*
|
||||
* \brief Clear the key parameters for control variables when connection close.
|
||||
*
|
||||
* \param None.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AnccConnClose(void)
|
||||
{
|
||||
WsfTimerStop(&anccCb.discoverTimer);
|
||||
anccCb.connId = DM_CONN_ID_NONE;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn anccNoConnActive
|
||||
*
|
||||
* \brief Return TRUE if no connections with active measurements.
|
||||
*
|
||||
* \return TRUE if no connections active.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static bool_t anccNoConnActive(void)
|
||||
{
|
||||
if (anccCb.connId != DM_CONN_ID_NONE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn anccActionListPush
|
||||
*
|
||||
* \brief Return TRUE if element is added/updated to the list.
|
||||
*
|
||||
* \return TRUE if element is added/updated to the list.
|
||||
* FALSE if list is full.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static bool_t anccActionListPush(ancc_notif_t* pElement)
|
||||
{
|
||||
uint16_t i;
|
||||
for ( i = 0; i < ANCC_LIST_ELEMENTS; i++ )
|
||||
{
|
||||
if ( (anccCb.anccList[i].notification_uid == pElement->notification_uid ) && (anccCb.anccList[i].noti_valid == true) )
|
||||
{
|
||||
// same notification uid received, update the element
|
||||
anccCb.anccList[i].notification_uid = pElement->notification_uid;
|
||||
anccCb.anccList[i].event_id = pElement->event_id;
|
||||
anccCb.anccList[i].event_flags = pElement->event_flags;
|
||||
anccCb.anccList[i].category_id = pElement->category_id;
|
||||
anccCb.anccList[i].category_count = pElement->category_count;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for ( i = 0; i < ANCC_LIST_ELEMENTS; i++ )
|
||||
{
|
||||
if ( anccCb.anccList[i].noti_valid == false )
|
||||
{
|
||||
// found an empty slot
|
||||
anccCb.anccList[i].notification_uid = pElement->notification_uid;
|
||||
anccCb.anccList[i].event_id = pElement->event_id;
|
||||
anccCb.anccList[i].event_flags = pElement->event_flags;
|
||||
anccCb.anccList[i].category_id = pElement->category_id;
|
||||
anccCb.anccList[i].category_count = pElement->category_count;
|
||||
anccCb.anccList[i].noti_valid = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false; //no empty slot left
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn anccActionListPop
|
||||
*
|
||||
* \brief Return TRUE if element is popped out and removed from the list.
|
||||
*
|
||||
* \return TRUE if element is popped out and removed from the list.
|
||||
* FALSE if list is already empty.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static bool_t anccActionListPop(void)
|
||||
{
|
||||
uint16_t i;
|
||||
for ( i = 0; i < ANCC_LIST_ELEMENTS; i++ )
|
||||
{
|
||||
if ( anccCb.anccList[ANCC_LIST_ELEMENTS - i - 1].noti_valid == true )
|
||||
{
|
||||
// found a valid element in the list
|
||||
anccCb.anccList[ANCC_LIST_ELEMENTS - i - 1].noti_valid = false;
|
||||
anccCb.active.handle = ANCC_LIST_ELEMENTS - i - 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false; //no element left in the list
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AnccActionStart
|
||||
*
|
||||
* \brief Start periodic ancc operation. This function starts a timer to perform
|
||||
* periodic actions.
|
||||
*
|
||||
* \param timerEvt WSF event designated by the application for the timer.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AnccActionStart(uint8_t timerEvt)
|
||||
{
|
||||
/* if this is first connection */
|
||||
if (anccNoConnActive() == FALSE)
|
||||
{
|
||||
/* initialize control block */
|
||||
anccCb.actionTimer.msg.event = timerEvt;
|
||||
|
||||
/* (re-)start timer */
|
||||
WsfTimerStop(&anccCb.actionTimer);
|
||||
WsfTimerStartMs(&anccCb.actionTimer, anccCb.cfg.period);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AnccActionStop
|
||||
*
|
||||
* \brief Stop periodic ancc action.
|
||||
*
|
||||
* \param connId DM connection identifier.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AnccActionStop(void)
|
||||
{
|
||||
/* stop timer */
|
||||
WsfTimerStop(&anccCb.actionTimer);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AnccGetNotificationAttribute
|
||||
*
|
||||
* \brief Send a command to the apple notification center service control point.
|
||||
*
|
||||
* \param pHdlList Characteristic handle list.
|
||||
* \param notiUid NotificationUid.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AnccGetNotificationAttribute(uint16_t *pHdlList, uint32_t notiUid)
|
||||
{
|
||||
// An example to get notification attributes
|
||||
uint16_t max_len = 256;
|
||||
uint8_t buf[19]; // retrieve the complete attribute list
|
||||
if (pHdlList[ANCC_CONTROL_POINT_HDL_IDX] != ATT_HANDLE_NONE)
|
||||
{
|
||||
buf[0] = BLE_ANCS_COMMAND_ID_GET_NOTIF_ATTRIBUTES; // put command
|
||||
uint8_t * p = &buf[1];
|
||||
UINT32_TO_BSTREAM(p, notiUid); // encode notification uid
|
||||
|
||||
// encode attribute IDs
|
||||
buf[5] = BLE_ANCS_NOTIF_ATTR_ID_APP_IDENTIFIER;
|
||||
buf[6] = BLE_ANCS_NOTIF_ATTR_ID_TITLE;
|
||||
// 2 byte length
|
||||
buf[7] = max_len;
|
||||
buf[8] = max_len >> 8;
|
||||
buf[9] = BLE_ANCS_NOTIF_ATTR_ID_SUBTITLE;
|
||||
buf[10] = max_len;
|
||||
buf[11] = max_len >> 8;
|
||||
buf[12] = BLE_ANCS_NOTIF_ATTR_ID_MESSAGE;
|
||||
buf[13] = max_len;
|
||||
buf[14] = max_len >> 8;
|
||||
buf[15] = BLE_ANCS_NOTIF_ATTR_ID_MESSAGE_SIZE;
|
||||
buf[16] = BLE_ANCS_NOTIF_ATTR_ID_DATE;
|
||||
buf[17] = BLE_ANCS_NOTIF_ATTR_ID_POSITIVE_ACTION_LABEL;
|
||||
buf[18] = BLE_ANCS_NOTIF_ATTR_ID_NEGATIVE_ACTION_LABEL;
|
||||
AttcWriteReq(anccCb.connId, pHdlList[ANCC_CONTROL_POINT_HDL_IDX], sizeof(buf), buf);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AncsGetAppAttribute
|
||||
*
|
||||
* \brief Send a command to the apple notification center service control point.
|
||||
*
|
||||
* \param pHdlList Connection identifier.
|
||||
* \param pAppId Attribute handle.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AncsGetAppAttribute(uint16_t *pHdlList, uint8_t *pAppId)
|
||||
{
|
||||
// An example to get app attributes
|
||||
uint8_t buf[64]; // to hold the command, size of app identifier is unknown
|
||||
uint8_t count = 0;
|
||||
if (pHdlList[ANCC_CONTROL_POINT_HDL_IDX] != ATT_HANDLE_NONE)
|
||||
{
|
||||
buf[0] = BLE_ANCS_COMMAND_ID_GET_APP_ATTRIBUTES; // put command
|
||||
|
||||
while (pAppId[count++] != 0); // NULL terminated string
|
||||
if ( count > (64 - 2) )
|
||||
{
|
||||
// app identifier is too long
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&buf[1], pAppId, count);
|
||||
}
|
||||
|
||||
buf[count + 1] = 0; // app attribute id
|
||||
AttcWriteReq(anccCb.connId, pHdlList[ANCC_CONTROL_POINT_HDL_IDX], (count + 2), buf);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AncsPerformNotiAction
|
||||
*
|
||||
* \brief Send a command to the apple notification center service control point.
|
||||
*
|
||||
* \param pHdlList Characteristic handle list.
|
||||
* \param actionId Notification action identifier.
|
||||
* \param notiUid NotificationUid.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AncsPerformNotiAction(uint16_t *pHdlList, uint32_t notiUid, ancc_notif_action_id_values_t actionId)
|
||||
{
|
||||
// An example to performs notification action
|
||||
uint8_t buf[6]; //to hold the command, size of app identifier is unknown
|
||||
if (pHdlList[ANCC_CONTROL_POINT_HDL_IDX] != ATT_HANDLE_NONE)
|
||||
{
|
||||
buf[0] = BLE_ANCS_COMMAND_ID_GET_PERFORM_NOTIF_ACTION; // put command
|
||||
uint8_t * p = &buf[1];
|
||||
UINT32_TO_BSTREAM(p, notiUid); // encode notification uid
|
||||
buf[5] = actionId; //action id
|
||||
AttcWriteReq(anccCb.connId, pHdlList[ANCC_CONTROL_POINT_HDL_IDX], sizeof(buf), buf);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AnccActionHandler
|
||||
*
|
||||
* \brief Routine to handle ancc related actions.
|
||||
*
|
||||
* \param actionTimerEvt WsfTimer event indication.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AnccActionHandler(uint8_t actionTimerEvt)
|
||||
{
|
||||
// perform action
|
||||
if ( anccActionListPop() )
|
||||
{
|
||||
AnccGetNotificationAttribute(anccCb.hdlList, anccCb.anccList[anccCb.active.handle].notification_uid);
|
||||
AnccActionStart(actionTimerEvt);
|
||||
}
|
||||
else
|
||||
{
|
||||
//list empty
|
||||
AnccActionStop();
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn anccAttrHandler
|
||||
*
|
||||
* \brief Static routine to handle attribute receiving and processing.
|
||||
*
|
||||
* \param pMsg pointer to ATT message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static bool anccAttrHandler(attEvt_t * pMsg)
|
||||
{
|
||||
uint8_t count = 0;
|
||||
uint16_t bytesRemaining = 0;
|
||||
|
||||
switch(anccCb.active.attrState)
|
||||
{
|
||||
case NOTI_ATTR_NEW_NOTIFICATION:
|
||||
// new notification
|
||||
anccCb.active.commandId = pMsg->pValue[0];
|
||||
if ( anccCb.active.commandId == BLE_ANCS_COMMAND_ID_GET_NOTIF_ATTRIBUTES )
|
||||
{
|
||||
BYTES_TO_UINT32(anccCb.active.notiUid, &(pMsg->pValue[1]));
|
||||
count = 4;
|
||||
}
|
||||
else if ( anccCb.active.commandId == BLE_ANCS_COMMAND_ID_GET_APP_ATTRIBUTES )
|
||||
{
|
||||
while(pMsg->pValue[count + 1] != 0) // NULL terminated string
|
||||
{
|
||||
anccCb.active.appId[count] = pMsg->pValue[count + 1];
|
||||
count++;
|
||||
}
|
||||
anccCb.active.appId[count + 1] = 0; // NULL terminated string
|
||||
}
|
||||
else
|
||||
{
|
||||
// BLE_ANCS_COMMAND_ID_GET_PERFORM_NOTIF_ACTION
|
||||
return false;
|
||||
}
|
||||
anccCb.active.parseIndex += count + 1;
|
||||
anccCb.active.attrState = NOTI_ATTR_NEW_ATTRIBUTE;
|
||||
anccCb.active.attrId = 0;
|
||||
anccCb.active.attrCount = 0;
|
||||
|
||||
if ( pMsg->valueLen > ANCC_ATTRI_BUFFER_SIZE_BYTES )
|
||||
{
|
||||
// notification size overflow
|
||||
}
|
||||
else
|
||||
{
|
||||
bytesRemaining = pMsg->valueLen;
|
||||
}
|
||||
// copy data
|
||||
memset(anccCb.active.attrDataBuf, 0, ANCC_ATTRI_BUFFER_SIZE_BYTES);
|
||||
anccCb.active.bufIndex = 0;
|
||||
for (uint16_t i = 0; i < bytesRemaining; i++)
|
||||
{
|
||||
anccCb.active.attrDataBuf[anccCb.active.bufIndex++] = pMsg->pValue[i];
|
||||
}
|
||||
// no break here by intention
|
||||
case NOTI_ATTR_NEW_ATTRIBUTE:
|
||||
// new attribute
|
||||
// check consistency of the attribute
|
||||
if ( anccCb.active.bufIndex - anccCb.active.parseIndex < 3 ) // 1 byte attribute id + 2 bytes attribute length
|
||||
{
|
||||
// attribute header not received completely
|
||||
anccCb.active.attrState = NOTI_ATTR_RECEIVING_ATTRIBUTE;
|
||||
return false;
|
||||
}
|
||||
|
||||
anccCb.active.attrId = anccCb.active.attrDataBuf[anccCb.active.parseIndex];
|
||||
BYTES_TO_UINT16(anccCb.active.attrLength, &(anccCb.active.attrDataBuf[anccCb.active.parseIndex + 1]));
|
||||
|
||||
if ( anccCb.active.attrLength > (anccCb.active.bufIndex - anccCb.active.parseIndex - 3) ) // 1 byte attribute id + 2 bytes attribute length
|
||||
{
|
||||
// attribute body not received completely
|
||||
anccCb.active.attrState = NOTI_ATTR_RECEIVING_ATTRIBUTE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// parse attribute
|
||||
anccCb.active.attrCount++;
|
||||
anccCb.active.parseIndex += 3; // 1 byte attribute id + 2 bytes attribute length
|
||||
|
||||
if ( anccCb.active.attrId == BLE_ANCS_NOTIF_ATTR_ID_APP_IDENTIFIER )
|
||||
{
|
||||
uint8_t temp = 0;
|
||||
while(anccCb.active.attrDataBuf[anccCb.active.parseIndex + temp] != 0) // NULL terminated string
|
||||
{
|
||||
anccCb.active.appId[temp] = anccCb.active.attrDataBuf[anccCb.active.parseIndex + temp];
|
||||
temp++;
|
||||
}
|
||||
anccCb.active.appId[temp] = 0; // NULL terminated string
|
||||
}
|
||||
|
||||
//
|
||||
// attribute received
|
||||
// execute callback function
|
||||
//
|
||||
(*anccCb.attrCback)(&anccCb.active);
|
||||
|
||||
anccCb.active.parseIndex += anccCb.active.attrLength;
|
||||
|
||||
if ( anccCb.active.attrCount >= 8 ) //custom criteria
|
||||
{
|
||||
//notification reception done
|
||||
anccCb.active.attrState = NOTI_ATTR_NEW_NOTIFICATION;
|
||||
anccCb.active.parseIndex = 0;
|
||||
anccCb.active.bufIndex = 0;
|
||||
|
||||
//
|
||||
// notification received
|
||||
// execute callback function
|
||||
//
|
||||
(*anccCb.notiCback)(&anccCb.active, anccCb.active.notiUid);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true; // continue parsing
|
||||
// no need to break;
|
||||
case NOTI_ATTR_RECEIVING_ATTRIBUTE:
|
||||
// notification continuing
|
||||
bytesRemaining = 0;
|
||||
if ( anccCb.active.bufIndex + pMsg->valueLen > ANCC_ATTRI_BUFFER_SIZE_BYTES )
|
||||
{
|
||||
// notification size overflow
|
||||
anccCb.active.attrState = NOTI_ATTR_NEW_NOTIFICATION;
|
||||
anccCb.active.parseIndex = 0;
|
||||
anccCb.active.bufIndex = 0;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
bytesRemaining = pMsg->valueLen;
|
||||
}
|
||||
// copy data
|
||||
for (uint16_t i = 0; i < bytesRemaining; i++)
|
||||
{
|
||||
anccCb.active.attrDataBuf[anccCb.active.bufIndex++] = pMsg->pValue[i];
|
||||
}
|
||||
anccCb.active.attrState = NOTI_ATTR_NEW_ATTRIBUTE;
|
||||
return true;
|
||||
// no need to break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AnccNtfValueUpdate
|
||||
*
|
||||
* \brief Routine to handle any ancc related notify.
|
||||
*
|
||||
* \param pHdlList Characteristic handle list.
|
||||
* \param actionTimerEvt WsfTimer event indication.
|
||||
* \param pMsg pointer to ATT message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AnccNtfValueUpdate(uint16_t *pHdlList, attEvt_t * pMsg, uint8_t actionTimerEvt)
|
||||
{
|
||||
ancc_notif_t ancs_notif;
|
||||
uint8_t *p;
|
||||
|
||||
//notification received
|
||||
if (pMsg->handle == pHdlList[ANCC_NOTIFICATION_SOURCE_HDL_IDX])
|
||||
{
|
||||
// process notificiation source (brief)
|
||||
p = pMsg->pValue;
|
||||
ancs_notif.event_id = p[0];
|
||||
ancs_notif.event_flags = p[1];
|
||||
ancs_notif.category_id = p[2];
|
||||
ancs_notif.category_count = p[3];
|
||||
BYTES_TO_UINT32(ancs_notif.notification_uid, &p[4]);
|
||||
|
||||
if (BLE_ANCS_EVENT_ID_NOTIFICATION_REMOVED == ancs_notif.event_id)
|
||||
{
|
||||
if (NULL != anccCb.rmvCback)
|
||||
{
|
||||
anccCb.rmvCback(&ancs_notif);
|
||||
}
|
||||
}
|
||||
else if ( !anccActionListPush(&ancs_notif) )
|
||||
{
|
||||
// list full
|
||||
// APP_TRACE_INFO0("action list full...");
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// actions to be done with timer delays to avoid generating heavy traffic
|
||||
//
|
||||
AnccActionStart(actionTimerEvt);
|
||||
// APP_TRACE_INFO0("added to action list");
|
||||
}
|
||||
}
|
||||
else if ( pMsg->handle == pHdlList[ANCC_DATA_SOURCE_HDL_IDX] )
|
||||
{
|
||||
// process notificiation/app attributes
|
||||
while(anccAttrHandler(pMsg));
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AnccCbackRegister
|
||||
*
|
||||
* \brief Register the attribute received callback and notification completed callback.
|
||||
*
|
||||
* \param attrCback Pointer to attribute received callback function.
|
||||
* \param notiCback Pointer to notification completed callback function.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void AnccCbackRegister(anccAttrRecvCback_t attrCback, anccNotiCmplCback_t notiCback, anccNotiRemoveCback_t rmvCback)
|
||||
{
|
||||
anccCb.attrCback = attrCback;
|
||||
anccCb.notiCback = notiCback;
|
||||
anccCb.rmvCback = rmvCback;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn AnccStartServiceDiscovery
|
||||
*
|
||||
* \brief Do service discovery on connected connection.
|
||||
*
|
||||
* \return Return TRUE if service discovery is initiated successfully.
|
||||
*
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
bool_t AnccStartServiceDiscovery(void)
|
||||
{
|
||||
if (anccCb.connId != DM_CONN_ID_NONE)
|
||||
{
|
||||
appDiscStart(anccCb.connId);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// voles_api.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Brief description of the header. No need to get fancy here.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifndef VOLES_API_H
|
||||
#define VOLES_API_H
|
||||
|
||||
#include "wsf_timer.h"
|
||||
#include "att_api.h"
|
||||
#include "vole_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Macro definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
|
||||
//
|
||||
// Connection control block
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
dmConnId_t connId; // Connection ID
|
||||
bool_t voleToSend; // VOLE notify ready to be sent on this channel
|
||||
}
|
||||
volesConn_t;
|
||||
|
||||
/*! Configurable parameters */
|
||||
typedef struct
|
||||
{
|
||||
//! Short description of each member should go here.
|
||||
uint32_t reserved;
|
||||
}
|
||||
VolesCfg_t;
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// function definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
void voles_init(wsfHandlerId_t handlerId, eVoleCodecType codec_type);
|
||||
void voles_proc_msg(wsfMsgHdr_t *pMsg);
|
||||
void voles_transmit_voice_data(void);
|
||||
|
||||
int voles_set_codec_type(eVoleCodecType codec_type);
|
||||
|
||||
uint8_t voles_write_cback(dmConnId_t connId, uint16_t handle, uint8_t operation,
|
||||
uint16_t offset, uint16_t len, uint8_t *pValue, attsAttr_t *pAttr);
|
||||
|
||||
void voles_start(dmConnId_t connId, uint8_t timerEvt, uint8_t voleCccIdx);
|
||||
|
||||
void voles_stop(dmConnId_t connId);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // VOLES_API_H
|
||||
@@ -0,0 +1,465 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// voles_main.c
|
||||
//! @file
|
||||
//!
|
||||
//! @brief This file provides the main application for the VOLE service.
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include "wsf_types.h"
|
||||
#include "wsf_assert.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "wsf_buf.h" //for WsfBufAlloc and WsfBufFree
|
||||
#include "bstream.h"
|
||||
#include "att_api.h"
|
||||
#include "svc_ch.h"
|
||||
#include "svc_amvole.h"
|
||||
#include "app_api.h"
|
||||
#include "app_hw.h"
|
||||
#include "voles_api.h"
|
||||
#include "am_util_debug.h"
|
||||
#include "crc32.h"
|
||||
|
||||
#include "am_mcu_apollo.h"
|
||||
#include "am_bsp.h"
|
||||
#include "am_util.h"
|
||||
#include "sbc.h"
|
||||
#include "vole_common.h"
|
||||
#include "att_defs.h"
|
||||
#include "vole_board_config.h"
|
||||
#include "voice_data.h"
|
||||
|
||||
#include "ae_api.h"
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Global variables
|
||||
//
|
||||
//*****************************************************************************
|
||||
eVoleCodecType g_vole_codec_type;
|
||||
uint8_t g_ble_data_buffer[ATT_MAX_MTU];
|
||||
|
||||
extern bool_t g_start_voice_send;
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Macro definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
static sbc_t g_SBCInstance;
|
||||
int g_opusErr;
|
||||
uint32_t g_audioSampleRate = 16000;
|
||||
int32_t g_audioChannel = 1;
|
||||
|
||||
/* Control block */
|
||||
static struct
|
||||
{
|
||||
volesConn_t conn[DM_CONN_MAX]; // connection control block
|
||||
bool_t txReady; // TRUE if ready to send notifications
|
||||
wsfHandlerId_t appHandlerId;
|
||||
VolesCfg_t cfg; // configurable parameters
|
||||
voleCb_t core;
|
||||
}
|
||||
volesCb;
|
||||
|
||||
extern bool am_app_KWD_AMA_tx_ver_exchange_send(void);
|
||||
extern uint16_t am_app_KWD_AMA_stream_send(uint8_t* buf, uint32_t len);
|
||||
extern void am_app_led_off(void);
|
||||
|
||||
static void voles_conn_parameter_req(void)
|
||||
{
|
||||
hciConnSpec_t connSpec;
|
||||
connSpec.connIntervalMin = 6; //(15/1.25);//(30/1.25);
|
||||
connSpec.connIntervalMax = 12; //(15/1.25);//(30/1.25);
|
||||
connSpec.connLatency = 0; //0;
|
||||
connSpec.supTimeout = 400;
|
||||
connSpec.minCeLen = 0;
|
||||
connSpec.maxCeLen = 0xffff; //fixme
|
||||
DmConnUpdate(1, &connSpec);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Connection Open event
|
||||
//
|
||||
//*****************************************************************************
|
||||
static void
|
||||
voles_conn_open(dmEvt_t *pMsg)
|
||||
{
|
||||
hciLeConnCmplEvt_t *evt = (hciLeConnCmplEvt_t*) pMsg;
|
||||
|
||||
APP_TRACE_INFO0("connection opened\n");
|
||||
APP_TRACE_INFO1("handle = 0x%x\n", evt->handle);
|
||||
APP_TRACE_INFO1("role = 0x%x\n", evt->role);
|
||||
APP_TRACE_INFO3("addrMSB = %02x%02x%02x%02x%02x%02x\n", evt->peerAddr[0], evt->peerAddr[1], evt->peerAddr[2]);
|
||||
APP_TRACE_INFO3("addrLSB = %02x%02x%02x%02x%02x%02x\n", evt->peerAddr[3], evt->peerAddr[4], evt->peerAddr[5]);
|
||||
APP_TRACE_INFO1("connInterval = %d x 1.25 ms\n", evt->connInterval);
|
||||
APP_TRACE_INFO1("connLatency = %d\n", evt->connLatency);
|
||||
APP_TRACE_INFO1("supTimeout = %d ms\n", evt->supTimeout * 10);
|
||||
|
||||
if ( evt->connInterval > 12 )
|
||||
{
|
||||
voles_conn_parameter_req();
|
||||
}
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Connection Update event
|
||||
//
|
||||
//*****************************************************************************
|
||||
static void
|
||||
voles_conn_update(dmEvt_t *pMsg)
|
||||
{
|
||||
hciLeConnUpdateCmplEvt_t *evt = (hciLeConnUpdateCmplEvt_t*) pMsg;
|
||||
|
||||
APP_TRACE_INFO1("connection update status = 0x%x", evt->status);
|
||||
APP_TRACE_INFO1("handle = 0x%x", evt->handle);
|
||||
APP_TRACE_INFO1("connInterval = 0x%x", evt->connInterval);
|
||||
APP_TRACE_INFO1("connLatency = 0x%x", evt->connLatency);
|
||||
APP_TRACE_INFO1("supTimeout = 0x%x", evt->supTimeout);
|
||||
|
||||
|
||||
if ( evt->connInterval > (15 / 1.25) )
|
||||
{
|
||||
// retry
|
||||
voles_conn_parameter_req();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int32_t voles_msbc_encode_voice_data(uint8_t *input, uint8_t *output, uint16_t len)
|
||||
{
|
||||
int32_t i32CompressedLen = 0;
|
||||
|
||||
if ((input == NULL) || (output == NULL))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
sbc_encoder_encode(&g_SBCInstance, input, len,
|
||||
output, CODEC_MSBC_OUTPUT_SIZE, (int *)&i32CompressedLen);
|
||||
|
||||
APP_TRACE_INFO2("voles encode, input len:%d, compressedLen:%d", len, i32CompressedLen);
|
||||
|
||||
return i32CompressedLen;
|
||||
}
|
||||
|
||||
int voles_set_codec_type(eVoleCodecType codec_type)
|
||||
{
|
||||
APP_TRACE_INFO1("set codec type:%s", ((codec_type == 0) ? "MSBC code" : "OPUS codec"));
|
||||
|
||||
if (codec_type != VOLE_CODEC_TYPE_INVALID)
|
||||
{
|
||||
g_vole_codec_type = codec_type;
|
||||
return codec_type;
|
||||
}
|
||||
else
|
||||
{
|
||||
return VOLE_CODEC_TYPE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
eVoleCodecType voles_get_codec_type(void)
|
||||
{
|
||||
return g_vole_codec_type;
|
||||
}
|
||||
|
||||
// get the size for each sending packet
|
||||
int voles_ble_buffer_size(void)
|
||||
{
|
||||
eVoleCodecType codec_type = voles_get_codec_type();
|
||||
int buffer_size = 0;
|
||||
|
||||
switch(codec_type)
|
||||
{
|
||||
case MSBC_CODEC_IN_USE:
|
||||
buffer_size = BLE_MSBC_DATA_BUFFER_SIZE;
|
||||
break;
|
||||
|
||||
case OPUS_CODEC_IN_USE:
|
||||
buffer_size = BLE_OPUS_DATA_BUFFER_SIZE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return buffer_size;
|
||||
}
|
||||
|
||||
void voles_transmit_voice_data(void)
|
||||
{
|
||||
volePacket_t *txPkt = &volesCb.core.txPkt;
|
||||
uint32_t offset = txPkt->offset;
|
||||
int remain_data_len = 0;
|
||||
int enc_data_len = 0;
|
||||
uint8_t output_data[100] = {0};
|
||||
int output_len = 0;
|
||||
static int index = 0;
|
||||
eVoleCodecType codec_type = voles_get_codec_type();
|
||||
|
||||
txPkt->len = sizeof(voice_data);
|
||||
remain_data_len = txPkt->len - offset;
|
||||
|
||||
if (codec_type == MSBC_CODEC_IN_USE)
|
||||
{
|
||||
enc_data_len = (remain_data_len>CODEC_MSBC_INPUT_SIZE)?CODEC_MSBC_INPUT_SIZE:remain_data_len;
|
||||
}
|
||||
else if (codec_type == OPUS_CODEC_IN_USE)
|
||||
{
|
||||
enc_data_len = (remain_data_len>CODEC_OPUS_INPUT_SIZE)?CODEC_OPUS_INPUT_SIZE:remain_data_len;
|
||||
}
|
||||
|
||||
APP_TRACE_INFO3("send %s encode data, total len:%d, offset:%d", (codec_type == MSBC_CODEC_IN_USE) ? "mSBC" : "Opus",
|
||||
txPkt->len, offset);
|
||||
|
||||
if (offset >= txPkt->len)
|
||||
{
|
||||
am_app_led_off();
|
||||
g_start_voice_send = FALSE;
|
||||
memset(output_data, 0x0, sizeof(output_data));
|
||||
txPkt->offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (codec_type == MSBC_CODEC_IN_USE)
|
||||
{
|
||||
output_len = voles_msbc_encode_voice_data(&voice_data[offset + AUD_HEADER_LEN], output_data, enc_data_len);
|
||||
txPkt->offset += enc_data_len;
|
||||
}
|
||||
else if (codec_type == OPUS_CODEC_IN_USE)
|
||||
{
|
||||
output_len = audio_enc_encode_frame((short *)&voice_data[offset + AUD_HEADER_LEN], enc_data_len, output_data);
|
||||
APP_TRACE_INFO1("opus encode, output_len:%d", output_len);
|
||||
if (output_len == (CODEC_OPUS_OUTPUT_SIZE))
|
||||
{
|
||||
txPkt->offset += (2*CODEC_OPUS_INPUT_SIZE);
|
||||
//APP_TRACE_INFO1("opus_encode: ret:%d", output_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
txPkt->offset += enc_data_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( output_len > 0 )
|
||||
{
|
||||
memcpy(&g_ble_data_buffer[index], output_data, output_len);
|
||||
index += output_len;
|
||||
}
|
||||
|
||||
if ( index >= voles_ble_buffer_size() || output_len <= 0 )
|
||||
{
|
||||
if (index >0)
|
||||
{
|
||||
am_app_KWD_AMA_stream_send(g_ble_data_buffer, index);
|
||||
index = 0;
|
||||
memset(g_ble_data_buffer, 0x0, sizeof(g_ble_data_buffer));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t output_size = ((voles_get_codec_type() == MSBC_CODEC_IN_USE) ? CODEC_MSBC_OUTPUT_SIZE : (CODEC_OPUS_OUTPUT_SIZE));
|
||||
|
||||
if (output_len == output_size)
|
||||
{
|
||||
voles_transmit_voice_data();
|
||||
}
|
||||
else if (output_len>0 && output_len<output_size)
|
||||
{
|
||||
am_app_KWD_AMA_stream_send(output_data, output_len);
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//extern opus_encoder_t* octopus_encoder_create(int option);
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn volesHandleValueCnf
|
||||
*
|
||||
* \brief Handle a received ATT handle value confirm.
|
||||
*
|
||||
* \param pMsg Event message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void
|
||||
volesHandleValueCnf(attEvt_t *pMsg)
|
||||
{
|
||||
if (pMsg->hdr.status == ATT_SUCCESS)
|
||||
{
|
||||
if (g_start_voice_send)
|
||||
{
|
||||
voles_transmit_voice_data();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
APP_TRACE_WARN2("cnf status = %d, hdl = 0x%x\n", pMsg->hdr.status, pMsg->handle);
|
||||
}
|
||||
}
|
||||
|
||||
void voles_opus_encoder_init(void)
|
||||
{
|
||||
//
|
||||
// Opus codec init
|
||||
//
|
||||
audio_enc_init(0);
|
||||
|
||||
APP_TRACE_INFO0("Opus encoder initialization is finished!\r\n\n");
|
||||
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//6
|
||||
//! @brief initialize vole service
|
||||
//!
|
||||
//! @param handlerId - connection handle
|
||||
//! @param pCfg - configuration parameters
|
||||
//!
|
||||
//! @return None
|
||||
//
|
||||
//*****************************************************************************
|
||||
void voles_init(wsfHandlerId_t handlerId, eVoleCodecType codec_type)
|
||||
{
|
||||
memset(&volesCb, 0, sizeof(volesCb));
|
||||
volesCb.appHandlerId = handlerId;
|
||||
|
||||
volesCb.core.txPkt.data = voice_data;
|
||||
|
||||
if (codec_type == MSBC_CODEC_IN_USE)
|
||||
{
|
||||
sbc_encode_init(&g_SBCInstance, 1); //0: SBC
|
||||
}
|
||||
else if (codec_type == OPUS_CODEC_IN_USE)
|
||||
{
|
||||
voles_opus_encoder_init();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
voles_conn_close(dmEvt_t *pMsg)
|
||||
{
|
||||
hciDisconnectCmplEvt_t *evt = (hciDisconnectCmplEvt_t*) pMsg;
|
||||
dmConnId_t connId = evt->hdr.param;
|
||||
/* clear connection */
|
||||
volesCb.conn[connId - 1].connId = DM_CONN_ID_NONE;
|
||||
volesCb.conn[connId - 1].voleToSend = FALSE;
|
||||
|
||||
WsfTimerStop(&volesCb.core.timeoutTimer);
|
||||
volesCb.core.txState = VOLE_STATE_INIT;
|
||||
volesCb.core.rxState = VOLE_STATE_RX_IDLE;
|
||||
volesCb.core.lastRxPktSn = 0;
|
||||
volesCb.core.txPktSn = 0;
|
||||
VoleResetPkt(&volesCb.core.rxPkt);
|
||||
VoleResetPkt(&volesCb.core.txPkt);
|
||||
VoleResetPkt(&volesCb.core.ackPkt);
|
||||
}
|
||||
|
||||
uint8_t
|
||||
voles_write_cback(dmConnId_t connId, uint16_t handle, uint8_t operation,
|
||||
uint16_t offset, uint16_t len, uint8_t *pValue, attsAttr_t *pAttr)
|
||||
{
|
||||
APP_TRACE_INFO3("write cb, len:%d, value %x %x", len, pValue[0], pValue[1]);
|
||||
|
||||
return ATT_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
voles_start(dmConnId_t connId, uint8_t timerEvt, uint8_t voleCccIdx)
|
||||
{
|
||||
//
|
||||
// set conn id
|
||||
//
|
||||
volesCb.conn[connId - 1].connId = connId;
|
||||
volesCb.conn[connId - 1].voleToSend = TRUE;
|
||||
|
||||
volesCb.core.timeoutTimer.msg.event = timerEvt;
|
||||
volesCb.core.txState = VOLE_STATE_TX_IDLE;
|
||||
volesCb.txReady = true;
|
||||
|
||||
volesCb.core.attMtuSize = AttGetMtu(connId);
|
||||
APP_TRACE_INFO1("MTU size = %d bytes", volesCb.core.attMtuSize);
|
||||
}
|
||||
|
||||
void
|
||||
voles_stop(dmConnId_t connId)
|
||||
{
|
||||
//
|
||||
// clear connection
|
||||
//
|
||||
volesCb.conn[connId - 1].connId = DM_CONN_ID_NONE;
|
||||
volesCb.conn[connId - 1].voleToSend = FALSE;
|
||||
|
||||
volesCb.core.txState = VOLE_STATE_INIT;
|
||||
volesCb.txReady = false;
|
||||
}
|
||||
|
||||
|
||||
void voles_proc_msg(wsfMsgHdr_t *pMsg)
|
||||
{
|
||||
if (pMsg->event == DM_CONN_OPEN_IND)
|
||||
{
|
||||
voles_conn_open((dmEvt_t *) pMsg);
|
||||
}
|
||||
else if (pMsg->event == DM_CONN_CLOSE_IND)
|
||||
{
|
||||
voles_conn_close((dmEvt_t *) pMsg);
|
||||
}
|
||||
else if (pMsg->event == DM_CONN_UPDATE_IND)
|
||||
{
|
||||
voles_conn_update((dmEvt_t *) pMsg);
|
||||
}
|
||||
else if (pMsg->event == ATTS_HANDLE_VALUE_CNF)
|
||||
{
|
||||
volesHandleValueCnf((attEvt_t *) pMsg);
|
||||
}
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file am_app_KWD_AMA.h
|
||||
//!
|
||||
//! @brief header file of AMA protocol handler
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2017, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision v1.2.11 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifndef AM_APP_KWD_AMA_H
|
||||
#define AM_APP_KWD_AMA_H
|
||||
|
||||
#include "accessories.pb.h"
|
||||
|
||||
#define AMA_TRANSPORT_HEADER_VERSION_MASK 0xF000
|
||||
#define AMA_TRANSPORT_HEADER_STEAM_ID_MASK 0x0F80
|
||||
#define AMA_TRANSPORT_HEADER_LENGTH_TYPE_MASK 0x01
|
||||
|
||||
typedef struct
|
||||
{
|
||||
#if USE_OUTPUT_AMVOS_AMA
|
||||
uint8_t ama_buf[AMA_BUFFER_SIZE + 3];
|
||||
#else
|
||||
uint8_t* buf;
|
||||
#endif
|
||||
uint32_t len;
|
||||
uint32_t reserved;
|
||||
} sRadioQueue_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VOS_AMA_INIT = 0, // New state for disconnected time
|
||||
VOS_AMA_IDLE,
|
||||
VOS_AMA_LISTENING,
|
||||
VOS_AMA_PROCESSING,
|
||||
VOS_AMA_SPEAKING
|
||||
} eVosAmaStatus_t;
|
||||
|
||||
//*****************************************************************************
|
||||
// External function declaration
|
||||
//*****************************************************************************
|
||||
|
||||
extern bool am_app_KWD_AMA_start_speech_send(void);
|
||||
extern int am_app_KWD_AMA_rx_handler(uint8_t *data, uint16_t len);
|
||||
extern bool am_app_KWD_AMA_keep_alive_send(void);
|
||||
|
||||
extern uint32_t g_ui32AmaDialogID;
|
||||
extern eVosAmaStatus_t g_eAmaStatus;
|
||||
|
||||
#endif // #ifndef AM_APP_KWD_AMA_H
|
||||
BIN
Binary file not shown.
+239
@@ -0,0 +1,239 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// accessories.pb.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Auto-generated (see below).
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.3.9.1 at Fri Nov 09 16:58:28 2018. */
|
||||
|
||||
#ifndef PB_ACCESSORIES_PB_H_INCLUDED
|
||||
#define PB_ACCESSORIES_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
|
||||
#include "common.pb.h"
|
||||
|
||||
#include "system.pb.h"
|
||||
|
||||
#include "transport.pb.h"
|
||||
|
||||
#include "speech.pb.h"
|
||||
|
||||
#include "calling.pb.h"
|
||||
|
||||
#include "central.pb.h"
|
||||
|
||||
#include "device.pb.h"
|
||||
|
||||
#include "media.pb.h"
|
||||
|
||||
#include "state.pb.h"
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Enum definitions */
|
||||
typedef enum _Command
|
||||
{
|
||||
Command_NONE = 0,
|
||||
Command_RESET_CONNECTION = 51,
|
||||
Command_SYNCHRONIZE_SETTINGS = 50,
|
||||
Command_KEEP_ALIVE = 55,
|
||||
Command_REMOVE_DEVICE = 56,
|
||||
Command_UPGRADE_TRANSPORT = 30,
|
||||
Command_SWITCH_TRANSPORT = 31,
|
||||
Command_START_SPEECH = 11,
|
||||
Command_PROVIDE_SPEECH = 10,
|
||||
Command_STOP_SPEECH = 12,
|
||||
Command_ENDPOINT_SPEECH = 13,
|
||||
Command_NOTIFY_SPEECH_STATE = 14,
|
||||
Command_FORWARD_AT_COMMAND = 40,
|
||||
Command_INCOMING_CALL = 41,
|
||||
Command_GET_CENTRAL_INFORMATION = 103,
|
||||
Command_GET_DEVICE_INFORMATION = 20,
|
||||
Command_GET_DEVICE_CONFIGURATION = 21,
|
||||
Command_OVERRIDE_ASSISTANT = 22,
|
||||
Command_START_SETUP = 23,
|
||||
Command_COMPLETE_SETUP = 24,
|
||||
Command_NOTIFY_DEVICE_CONFIGURATION = 25,
|
||||
Command_UPDATE_DEVICE_INFORMATION = 26,
|
||||
Command_NOTIFY_DEVICE_INFORMATION = 27,
|
||||
Command_ISSUE_MEDIA_CONTROL = 60,
|
||||
Command_GET_STATE = 100,
|
||||
Command_SET_STATE = 101,
|
||||
Command_SYNCHRONIZE_STATE = 102
|
||||
} Command;
|
||||
#define _Command_MIN Command_NONE
|
||||
#define _Command_MAX Command_SYNCHRONIZE_STATE
|
||||
#define _Command_ARRAYSIZE ((Command)(Command_SYNCHRONIZE_STATE + 1))
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _Response
|
||||
{
|
||||
ErrorCode error_code;
|
||||
pb_size_t which_payload;
|
||||
union
|
||||
{
|
||||
DeviceInformation device_information;
|
||||
State state;
|
||||
ConnectionDetails connection_details;
|
||||
DeviceConfiguration device_configuration;
|
||||
CentralInformation central_information;
|
||||
Dialog dialog;
|
||||
SpeechProvider speech_provider;
|
||||
} payload;
|
||||
/* @@protoc_insertion_point(struct:Response) */
|
||||
} Response;
|
||||
|
||||
typedef struct _ControlEnvelope
|
||||
{
|
||||
Command command;
|
||||
pb_size_t which_payload;
|
||||
union
|
||||
{
|
||||
Response response;
|
||||
ProvideSpeech provide_speech;
|
||||
StartSpeech start_speech;
|
||||
StopSpeech stop_speech;
|
||||
EndpointSpeech endpoint_speech;
|
||||
NotifySpeechState notify_speech_state;
|
||||
GetDeviceInformation get_device_information;
|
||||
GetDeviceConfiguration get_device_configuration;
|
||||
OverrideAssistant override_assistant;
|
||||
StartSetup start_setup;
|
||||
CompleteSetup complete_setup;
|
||||
NotifyDeviceConfiguration notify_device_configuration;
|
||||
UpdateDeviceInformation update_device_information;
|
||||
NotifyDeviceInformation notify_device_information;
|
||||
UpgradeTransport upgrade_transport;
|
||||
SwitchTransport switch_transport;
|
||||
ForwardATCommand forward_at_command;
|
||||
IncomingCall incoming_call;
|
||||
SynchronizeSettings synchronize_settings;
|
||||
ResetConnection reset_connection;
|
||||
KeepAlive keep_alive;
|
||||
RemoveDevice remove_device;
|
||||
IssueMediaControl issue_media_control;
|
||||
GetState get_state;
|
||||
SetState set_state;
|
||||
SynchronizeState synchronize_state;
|
||||
GetCentralInformation get_central_information;
|
||||
} payload;
|
||||
/* @@protoc_insertion_point(struct:ControlEnvelope) */
|
||||
} ControlEnvelope;
|
||||
|
||||
/* Default values for struct fields */
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define Response_init_default {_ErrorCode_MIN, 0, {DeviceInformation_init_default}}
|
||||
#define ControlEnvelope_init_default {_Command_MIN, 0, {Response_init_default}}
|
||||
#define Response_init_zero {_ErrorCode_MIN, 0, {DeviceInformation_init_zero}}
|
||||
#define ControlEnvelope_init_zero {_Command_MIN, 0, {Response_init_zero}}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define Response_device_information_tag 3
|
||||
#define Response_state_tag 7
|
||||
#define Response_connection_details_tag 8
|
||||
#define Response_device_configuration_tag 10
|
||||
#define Response_central_information_tag 13
|
||||
#define Response_dialog_tag 14
|
||||
#define Response_speech_provider_tag 15
|
||||
#define Response_error_code_tag 1
|
||||
#define ControlEnvelope_response_tag 9
|
||||
#define ControlEnvelope_provide_speech_tag 10
|
||||
#define ControlEnvelope_start_speech_tag 11
|
||||
#define ControlEnvelope_stop_speech_tag 12
|
||||
#define ControlEnvelope_endpoint_speech_tag 13
|
||||
#define ControlEnvelope_notify_speech_state_tag 14
|
||||
#define ControlEnvelope_get_device_information_tag 20
|
||||
#define ControlEnvelope_get_device_configuration_tag 21
|
||||
#define ControlEnvelope_override_assistant_tag 22
|
||||
#define ControlEnvelope_start_setup_tag 23
|
||||
#define ControlEnvelope_complete_setup_tag 24
|
||||
#define ControlEnvelope_notify_device_configuration_tag 25
|
||||
#define ControlEnvelope_update_device_information_tag 26
|
||||
#define ControlEnvelope_notify_device_information_tag 27
|
||||
#define ControlEnvelope_upgrade_transport_tag 30
|
||||
#define ControlEnvelope_switch_transport_tag 31
|
||||
#define ControlEnvelope_forward_at_command_tag 40
|
||||
#define ControlEnvelope_incoming_call_tag 41
|
||||
#define ControlEnvelope_synchronize_settings_tag 50
|
||||
#define ControlEnvelope_reset_connection_tag 51
|
||||
#define ControlEnvelope_keep_alive_tag 55
|
||||
#define ControlEnvelope_remove_device_tag 56
|
||||
#define ControlEnvelope_issue_media_control_tag 60
|
||||
#define ControlEnvelope_get_state_tag 100
|
||||
#define ControlEnvelope_set_state_tag 101
|
||||
#define ControlEnvelope_synchronize_state_tag 102
|
||||
#define ControlEnvelope_get_central_information_tag 103
|
||||
#define ControlEnvelope_command_tag 1
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
extern const pb_field_t Response_fields[9];
|
||||
extern const pb_field_t ControlEnvelope_fields[29];
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define Response_size 104
|
||||
#define ControlEnvelope_size (2 + (UpdateDeviceInformation_size > 302 ? UpdateDeviceInformation_size : 302))
|
||||
|
||||
/* Message IDs (where set with "msgid" option) */
|
||||
#ifdef PB_MSGID
|
||||
|
||||
#define ACCESSORIES_MESSAGES \
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
|
||||
#endif
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// calling.pb.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Auto-generated (see below).
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.3.9.1 at Fri Nov 09 16:58:28 2018. */
|
||||
|
||||
#ifndef PB_CALLING_PB_H_INCLUDED
|
||||
#define PB_CALLING_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _ForwardATCommand
|
||||
{
|
||||
char command[34];
|
||||
/* @@protoc_insertion_point(struct:ForwardATCommand) */
|
||||
} ForwardATCommand;
|
||||
|
||||
typedef struct _IncomingCall
|
||||
{
|
||||
char caller_number[34];
|
||||
/* @@protoc_insertion_point(struct:IncomingCall) */
|
||||
} IncomingCall;
|
||||
|
||||
/* Default values for struct fields */
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define ForwardATCommand_init_default {""}
|
||||
#define IncomingCall_init_default {""}
|
||||
#define ForwardATCommand_init_zero {""}
|
||||
#define IncomingCall_init_zero {""}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define ForwardATCommand_command_tag 1
|
||||
#define IncomingCall_caller_number_tag 1
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
extern const pb_field_t ForwardATCommand_fields[2];
|
||||
extern const pb_field_t IncomingCall_fields[2];
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define ForwardATCommand_size 36
|
||||
#define IncomingCall_size 36
|
||||
|
||||
/* Message IDs (where set with "msgid" option) */
|
||||
#ifdef PB_MSGID
|
||||
|
||||
#define CALLING_MESSAGES \
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
|
||||
#endif
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// central.pb.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Auto-generated (see below).
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.3.9.1 at Fri Nov 09 16:58:28 2018. */
|
||||
|
||||
#ifndef PB_CENTRAL_PB_H_INCLUDED
|
||||
#define PB_CENTRAL_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Enum definitions */
|
||||
typedef enum _Platform
|
||||
{
|
||||
Platform_UNDEFINED = 0,
|
||||
Platform_IOS = 1,
|
||||
Platform_ANDROID = 2
|
||||
} Platform;
|
||||
#define _Platform_MIN Platform_UNDEFINED
|
||||
#define _Platform_MAX Platform_ANDROID
|
||||
#define _Platform_ARRAYSIZE ((Platform)(Platform_ANDROID + 1))
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _GetCentralInformation
|
||||
{
|
||||
char dummy_field;
|
||||
/* @@protoc_insertion_point(struct:GetCentralInformation) */
|
||||
} GetCentralInformation;
|
||||
|
||||
typedef struct _CentralInformation
|
||||
{
|
||||
char name[32];
|
||||
Platform platform;
|
||||
/* @@protoc_insertion_point(struct:CentralInformation) */
|
||||
} CentralInformation;
|
||||
|
||||
/* Default values for struct fields */
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define CentralInformation_init_default {"", _Platform_MIN}
|
||||
#define GetCentralInformation_init_default {0}
|
||||
#define CentralInformation_init_zero {"", _Platform_MIN}
|
||||
#define GetCentralInformation_init_zero {0}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define CentralInformation_name_tag 1
|
||||
#define CentralInformation_platform_tag 2
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
extern const pb_field_t CentralInformation_fields[3];
|
||||
extern const pb_field_t GetCentralInformation_fields[1];
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define CentralInformation_size 36
|
||||
#define GetCentralInformation_size 0
|
||||
|
||||
/* Message IDs (where set with "msgid" option) */
|
||||
#ifdef PB_MSGID
|
||||
|
||||
#define CENTRAL_MESSAGES \
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
|
||||
#endif
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// common.pb.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Auto-generated (see below).
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.3.9.1 at Fri Nov 09 16:58:28 2018. */
|
||||
|
||||
#ifndef PB_COMMON_PB_H_INCLUDED
|
||||
#define PB_COMMON_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Enum definitions */
|
||||
typedef enum _Transport
|
||||
{
|
||||
Transport_BLUETOOTH_LOW_ENERGY = 0,
|
||||
Transport_BLUETOOTH_RFCOMM = 1,
|
||||
Transport_BLUETOOTH_IAP = 2
|
||||
} Transport;
|
||||
#define _Transport_MIN Transport_BLUETOOTH_LOW_ENERGY
|
||||
#define _Transport_MAX Transport_BLUETOOTH_IAP
|
||||
#define _Transport_ARRAYSIZE ((Transport)(Transport_BLUETOOTH_IAP + 1))
|
||||
|
||||
typedef enum _ErrorCode
|
||||
{
|
||||
ErrorCode_SUCCESS = 0,
|
||||
ErrorCode_UNKNOWN = 1,
|
||||
ErrorCode_INTERNAL = 2,
|
||||
ErrorCode_UNSUPPORTED = 3,
|
||||
ErrorCode_USER_CANCELLED = 4,
|
||||
ErrorCode_NOT_FOUND = 5,
|
||||
ErrorCode_INVALID = 6,
|
||||
ErrorCode_BUSY = 7
|
||||
} ErrorCode;
|
||||
#define _ErrorCode_MIN ErrorCode_SUCCESS
|
||||
#define _ErrorCode_MAX ErrorCode_BUSY
|
||||
#define _ErrorCode_ARRAYSIZE ((ErrorCode)(ErrorCode_BUSY + 1))
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
|
||||
#endif
|
||||
+278
@@ -0,0 +1,278 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// device.pb.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Auto-generated (see below).
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.3.9.1 at Fri Nov 09 16:58:28 2018. */
|
||||
|
||||
#ifndef PB_DEVICE_PB_H_INCLUDED
|
||||
#define PB_DEVICE_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
|
||||
#include "common.pb.h"
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Enum definitions */
|
||||
typedef enum _ConnectionStatus
|
||||
{
|
||||
ConnectionStatus_CONNECTION_STATUS_UNKNOWN = 0,
|
||||
ConnectionStatus_CONNECTION_STATUS_CONNECTED = 1,
|
||||
ConnectionStatus_CONNECTION_STATUS_DISCONNECTED = 2
|
||||
} ConnectionStatus;
|
||||
#define _ConnectionStatus_MIN ConnectionStatus_CONNECTION_STATUS_UNKNOWN
|
||||
#define _ConnectionStatus_MAX ConnectionStatus_CONNECTION_STATUS_DISCONNECTED
|
||||
#define _ConnectionStatus_ARRAYSIZE ((ConnectionStatus)(ConnectionStatus_CONNECTION_STATUS_DISCONNECTED + 1))
|
||||
|
||||
typedef enum _DevicePresence
|
||||
{
|
||||
DevicePresence_DEVICE_PRESENCE_UNKNOWN = 0,
|
||||
DevicePresence_DEVICE_PRESENCE_ACTIVE = 1,
|
||||
DevicePresence_DEVICE_PRESENCE_INACTIVE = 2,
|
||||
DevicePresence_DEVICE_PRESENCE_ACCESSIBLE = 3
|
||||
} DevicePresence;
|
||||
#define _DevicePresence_MIN DevicePresence_DEVICE_PRESENCE_UNKNOWN
|
||||
#define _DevicePresence_MAX DevicePresence_DEVICE_PRESENCE_ACCESSIBLE
|
||||
#define _DevicePresence_ARRAYSIZE ((DevicePresence)(DevicePresence_DEVICE_PRESENCE_ACCESSIBLE + 1))
|
||||
|
||||
typedef enum _DeviceBattery_Status
|
||||
{
|
||||
DeviceBattery_Status_UNKNOWN = 0,
|
||||
DeviceBattery_Status_CHARGING = 1,
|
||||
DeviceBattery_Status_DISCHARGING = 2,
|
||||
DeviceBattery_Status_FULL = 3
|
||||
} DeviceBattery_Status;
|
||||
#define _DeviceBattery_Status_MIN DeviceBattery_Status_UNKNOWN
|
||||
#define _DeviceBattery_Status_MAX DeviceBattery_Status_FULL
|
||||
#define _DeviceBattery_Status_ARRAYSIZE ((DeviceBattery_Status)(DeviceBattery_Status_FULL + 1))
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _GetDeviceConfiguration
|
||||
{
|
||||
char dummy_field;
|
||||
/* @@protoc_insertion_point(struct:GetDeviceConfiguration) */
|
||||
} GetDeviceConfiguration;
|
||||
|
||||
typedef struct _StartSetup
|
||||
{
|
||||
char dummy_field;
|
||||
/* @@protoc_insertion_point(struct:StartSetup) */
|
||||
} StartSetup;
|
||||
|
||||
typedef struct _UpdateDeviceInformation
|
||||
{
|
||||
pb_callback_t name;
|
||||
/* @@protoc_insertion_point(struct:UpdateDeviceInformation) */
|
||||
} UpdateDeviceInformation;
|
||||
|
||||
typedef struct _CompleteSetup
|
||||
{
|
||||
ErrorCode error_code;
|
||||
/* @@protoc_insertion_point(struct:CompleteSetup) */
|
||||
} CompleteSetup;
|
||||
|
||||
typedef struct _DeviceBattery
|
||||
{
|
||||
uint32_t level;
|
||||
uint32_t scale;
|
||||
DeviceBattery_Status status;
|
||||
/* @@protoc_insertion_point(struct:DeviceBattery) */
|
||||
} DeviceBattery;
|
||||
|
||||
typedef struct _DeviceConfiguration
|
||||
{
|
||||
bool needs_assistant_override;
|
||||
bool needs_setup;
|
||||
/* @@protoc_insertion_point(struct:DeviceConfiguration) */
|
||||
} DeviceConfiguration;
|
||||
|
||||
typedef struct _DeviceStatus
|
||||
{
|
||||
ConnectionStatus link;
|
||||
ConnectionStatus nfmi;
|
||||
DevicePresence presence;
|
||||
/* @@protoc_insertion_point(struct:DeviceStatus) */
|
||||
} DeviceStatus;
|
||||
|
||||
typedef struct _GetDeviceInformation
|
||||
{
|
||||
uint32_t device_id;
|
||||
/* @@protoc_insertion_point(struct:GetDeviceInformation) */
|
||||
} GetDeviceInformation;
|
||||
|
||||
typedef struct _OverrideAssistant
|
||||
{
|
||||
ErrorCode error_code;
|
||||
/* @@protoc_insertion_point(struct:OverrideAssistant) */
|
||||
} OverrideAssistant;
|
||||
|
||||
typedef struct _DeviceInformation
|
||||
{
|
||||
char serial_number[20];
|
||||
char name[16];
|
||||
pb_size_t supported_transports_count;
|
||||
Transport supported_transports[4];
|
||||
char device_type[14];
|
||||
uint32_t device_id;
|
||||
DeviceBattery battery;
|
||||
DeviceStatus status;
|
||||
uint32_t product_color;
|
||||
/* @@protoc_insertion_point(struct:DeviceInformation) */
|
||||
} DeviceInformation;
|
||||
|
||||
typedef struct _NotifyDeviceConfiguration
|
||||
{
|
||||
DeviceConfiguration device_configuration;
|
||||
/* @@protoc_insertion_point(struct:NotifyDeviceConfiguration) */
|
||||
} NotifyDeviceConfiguration;
|
||||
|
||||
typedef struct _NotifyDeviceInformation
|
||||
{
|
||||
DeviceInformation device_information;
|
||||
/* @@protoc_insertion_point(struct:NotifyDeviceInformation) */
|
||||
} NotifyDeviceInformation;
|
||||
|
||||
/* Default values for struct fields */
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define DeviceBattery_init_default {0, 0, _DeviceBattery_Status_MIN}
|
||||
#define DeviceStatus_init_default {_ConnectionStatus_MIN, _ConnectionStatus_MIN, _DevicePresence_MIN}
|
||||
#define DeviceInformation_init_default {"", "", 0, {_Transport_MIN, _Transport_MIN, _Transport_MIN, _Transport_MIN}, "", 0, DeviceBattery_init_default, DeviceStatus_init_default, 0}
|
||||
#define GetDeviceInformation_init_default {0}
|
||||
#define DeviceConfiguration_init_default {0, 0}
|
||||
#define GetDeviceConfiguration_init_default {0}
|
||||
#define OverrideAssistant_init_default {_ErrorCode_MIN}
|
||||
#define StartSetup_init_default {0}
|
||||
#define CompleteSetup_init_default {_ErrorCode_MIN}
|
||||
#define NotifyDeviceConfiguration_init_default {DeviceConfiguration_init_default}
|
||||
#define UpdateDeviceInformation_init_default {{{NULL}, NULL}}
|
||||
#define NotifyDeviceInformation_init_default {DeviceInformation_init_default}
|
||||
#define DeviceBattery_init_zero {0, 0, _DeviceBattery_Status_MIN}
|
||||
#define DeviceStatus_init_zero {_ConnectionStatus_MIN, _ConnectionStatus_MIN, _DevicePresence_MIN}
|
||||
#define DeviceInformation_init_zero {"", "", 0, {_Transport_MIN, _Transport_MIN, _Transport_MIN, _Transport_MIN}, "", 0, DeviceBattery_init_zero, DeviceStatus_init_zero, 0}
|
||||
#define GetDeviceInformation_init_zero {0}
|
||||
#define DeviceConfiguration_init_zero {0, 0}
|
||||
#define GetDeviceConfiguration_init_zero {0}
|
||||
#define OverrideAssistant_init_zero {_ErrorCode_MIN}
|
||||
#define StartSetup_init_zero {0}
|
||||
#define CompleteSetup_init_zero {_ErrorCode_MIN}
|
||||
#define NotifyDeviceConfiguration_init_zero {DeviceConfiguration_init_zero}
|
||||
#define UpdateDeviceInformation_init_zero {{{NULL}, NULL}}
|
||||
#define NotifyDeviceInformation_init_zero {DeviceInformation_init_zero}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define UpdateDeviceInformation_name_tag 1
|
||||
#define CompleteSetup_error_code_tag 1
|
||||
#define DeviceBattery_level_tag 1
|
||||
#define DeviceBattery_scale_tag 2
|
||||
#define DeviceBattery_status_tag 3
|
||||
#define DeviceConfiguration_needs_assistant_override_tag 1
|
||||
#define DeviceConfiguration_needs_setup_tag 2
|
||||
#define DeviceStatus_link_tag 1
|
||||
#define DeviceStatus_nfmi_tag 2
|
||||
#define DeviceStatus_presence_tag 3
|
||||
#define GetDeviceInformation_device_id_tag 1
|
||||
#define OverrideAssistant_error_code_tag 1
|
||||
#define DeviceInformation_serial_number_tag 1
|
||||
#define DeviceInformation_name_tag 2
|
||||
#define DeviceInformation_supported_transports_tag 3
|
||||
#define DeviceInformation_device_type_tag 4
|
||||
#define DeviceInformation_device_id_tag 5
|
||||
#define DeviceInformation_battery_tag 6
|
||||
#define DeviceInformation_status_tag 7
|
||||
#define DeviceInformation_product_color_tag 8
|
||||
#define NotifyDeviceConfiguration_device_configuration_tag 1
|
||||
#define NotifyDeviceInformation_device_information_tag 1
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
extern const pb_field_t DeviceBattery_fields[4];
|
||||
extern const pb_field_t DeviceStatus_fields[4];
|
||||
extern const pb_field_t DeviceInformation_fields[9];
|
||||
extern const pb_field_t GetDeviceInformation_fields[2];
|
||||
extern const pb_field_t DeviceConfiguration_fields[3];
|
||||
extern const pb_field_t GetDeviceConfiguration_fields[1];
|
||||
extern const pb_field_t OverrideAssistant_fields[2];
|
||||
extern const pb_field_t StartSetup_fields[1];
|
||||
extern const pb_field_t CompleteSetup_fields[2];
|
||||
extern const pb_field_t NotifyDeviceConfiguration_fields[2];
|
||||
extern const pb_field_t UpdateDeviceInformation_fields[2];
|
||||
extern const pb_field_t NotifyDeviceInformation_fields[2];
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define DeviceBattery_size 14
|
||||
#define DeviceStatus_size 6
|
||||
#define DeviceInformation_size 100
|
||||
#define GetDeviceInformation_size 6
|
||||
#define DeviceConfiguration_size 4
|
||||
#define GetDeviceConfiguration_size 0
|
||||
#define OverrideAssistant_size 2
|
||||
#define StartSetup_size 0
|
||||
#define CompleteSetup_size 2
|
||||
#define NotifyDeviceConfiguration_size 6
|
||||
/* UpdateDeviceInformation_size depends on runtime parameters */
|
||||
#define NotifyDeviceInformation_size 102
|
||||
|
||||
/* Message IDs (where set with "msgid" option) */
|
||||
#ifdef PB_MSGID
|
||||
|
||||
#define DEVICE_MESSAGES \
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
|
||||
#endif
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// media.pb.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Auto-generated (see below).
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.3.9.1 at Fri Nov 09 16:58:28 2018. */
|
||||
|
||||
#ifndef PB_MEDIA_PB_H_INCLUDED
|
||||
#define PB_MEDIA_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Enum definitions */
|
||||
typedef enum _MediaControl
|
||||
{
|
||||
MediaControl_PLAY = 0,
|
||||
MediaControl_PAUSE = 1,
|
||||
MediaControl_NEXT = 2,
|
||||
MediaControl_PREVIOUS = 3,
|
||||
MediaControl_PLAY_PAUSE = 4
|
||||
} MediaControl;
|
||||
#define _MediaControl_MIN MediaControl_PLAY
|
||||
#define _MediaControl_MAX MediaControl_PLAY_PAUSE
|
||||
#define _MediaControl_ARRAYSIZE ((MediaControl)(MediaControl_PLAY_PAUSE + 1))
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _IssueMediaControl
|
||||
{
|
||||
MediaControl control;
|
||||
/* @@protoc_insertion_point(struct:IssueMediaControl) */
|
||||
} IssueMediaControl;
|
||||
|
||||
/* Default values for struct fields */
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define IssueMediaControl_init_default {_MediaControl_MIN}
|
||||
#define IssueMediaControl_init_zero {_MediaControl_MIN}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define IssueMediaControl_control_tag 1
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
extern const pb_field_t IssueMediaControl_fields[2];
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define IssueMediaControl_size 2
|
||||
|
||||
/* Message IDs (where set with "msgid" option) */
|
||||
#ifdef PB_MSGID
|
||||
|
||||
#define MEDIA_MESSAGES \
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,649 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// pb.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Auto-generated (see below).
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
/* Common parts of the nanopb library. Most of these are quite low-level
|
||||
* stuff. For the high-level interface, see pb_encode.h and pb_decode.h.
|
||||
*/
|
||||
|
||||
#ifndef PB_H_INCLUDED
|
||||
#define PB_H_INCLUDED
|
||||
|
||||
/*****************************************************************
|
||||
* Nanopb compilation time options. You can change these here by *
|
||||
* uncommenting the lines, or on the compiler command line. *
|
||||
*****************************************************************/
|
||||
|
||||
/* Enable support for dynamically allocated fields */
|
||||
/* #define PB_ENABLE_MALLOC 1 */
|
||||
|
||||
/* Define this if your CPU / compiler combination does not support
|
||||
* unaligned memory access to packed structures. */
|
||||
/* #define PB_NO_PACKED_STRUCTS 1 */
|
||||
|
||||
/* Increase the number of required fields that are tracked.
|
||||
* A compiler warning will tell if you need this. */
|
||||
/* #define PB_MAX_REQUIRED_FIELDS 256 */
|
||||
|
||||
/* Add support for tag numbers > 255 and fields larger than 255 bytes. */
|
||||
/* #define PB_FIELD_16BIT 1 */
|
||||
#define PB_FIELD_16BIT 1
|
||||
|
||||
/* Add support for tag numbers > 65536 and fields larger than 65536 bytes. */
|
||||
/* #define PB_FIELD_32BIT 1 */
|
||||
|
||||
/* Disable support for error messages in order to save some code space. */
|
||||
/* #define PB_NO_ERRMSG 1 */
|
||||
|
||||
/* Disable support for custom streams (support only memory buffers). */
|
||||
/* #define PB_BUFFER_ONLY 1 */
|
||||
|
||||
/* Switch back to the old-style callback function signature.
|
||||
* This was the default until nanopb-0.2.1. */
|
||||
/* #define PB_OLD_CALLBACK_STYLE */
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* You usually don't need to change anything below this line. *
|
||||
* Feel free to look around and use the defined macros, though. *
|
||||
******************************************************************/
|
||||
|
||||
|
||||
/* Version of the nanopb library. Just in case you want to check it in
|
||||
* your own program. */
|
||||
#define NANOPB_VERSION nanopb-0.3.9.1
|
||||
|
||||
/* Include all the system headers needed by nanopb. You will need the
|
||||
* definitions of the following:
|
||||
* - strlen, memcpy, memset functions
|
||||
* - [u]int_least8_t, uint_fast8_t, [u]int_least16_t, [u]int32_t, [u]int64_t
|
||||
* - size_t
|
||||
* - bool
|
||||
*
|
||||
* If you don't have the standard header files, you can instead provide
|
||||
* a custom header that defines or includes all this. In that case,
|
||||
* define PB_SYSTEM_HEADER to the path of this file.
|
||||
*/
|
||||
#ifdef PB_SYSTEM_HEADER
|
||||
#include PB_SYSTEM_HEADER
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef PB_ENABLE_MALLOC
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Macro for defining packed structures (compiler dependent).
|
||||
* This just reduces memory requirements, but is not required.
|
||||
*/
|
||||
#if defined(PB_NO_PACKED_STRUCTS)
|
||||
/* Disable struct packing */
|
||||
# define PB_PACKED_STRUCT_START
|
||||
# define PB_PACKED_STRUCT_END
|
||||
# define pb_packed
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
/* For GCC and clang */
|
||||
# define PB_PACKED_STRUCT_START
|
||||
# define PB_PACKED_STRUCT_END
|
||||
# define pb_packed __attribute__((packed))
|
||||
#elif defined(__ICCARM__) || defined(__CC_ARM)
|
||||
/* For IAR ARM and Keil MDK-ARM compilers */
|
||||
# define PB_PACKED_STRUCT_START _Pragma("pack(push, 1)")
|
||||
# define PB_PACKED_STRUCT_END _Pragma("pack(pop)")
|
||||
# define pb_packed
|
||||
#elif defined(_MSC_VER) && (_MSC_VER >= 1500)
|
||||
/* For Microsoft Visual C++ */
|
||||
# define PB_PACKED_STRUCT_START __pragma(pack(push, 1))
|
||||
# define PB_PACKED_STRUCT_END __pragma(pack(pop))
|
||||
# define pb_packed
|
||||
#else
|
||||
/* Unknown compiler */
|
||||
# define PB_PACKED_STRUCT_START
|
||||
# define PB_PACKED_STRUCT_END
|
||||
# define pb_packed
|
||||
#endif
|
||||
|
||||
/* Handly macro for suppressing unreferenced-parameter compiler warnings. */
|
||||
#ifndef PB_UNUSED
|
||||
#define PB_UNUSED(x) (void)(x)
|
||||
#endif
|
||||
|
||||
/* Compile-time assertion, used for checking compatible compilation options.
|
||||
* If this does not work properly on your compiler, use
|
||||
* #define PB_NO_STATIC_ASSERT to disable it.
|
||||
*
|
||||
* But before doing that, check carefully the error message / place where it
|
||||
* comes from to see if the error has a real cause. Unfortunately the error
|
||||
* message is not always very clear to read, but you can see the reason better
|
||||
* in the place where the PB_STATIC_ASSERT macro was called.
|
||||
*/
|
||||
#ifndef PB_NO_STATIC_ASSERT
|
||||
#ifndef PB_STATIC_ASSERT
|
||||
#define PB_STATIC_ASSERT(COND, MSG) typedef char PB_STATIC_ASSERT_MSG(MSG, __LINE__, __COUNTER__)[(COND) ? 1 : -1];
|
||||
#define PB_STATIC_ASSERT_MSG(MSG, LINE, COUNTER) PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER)
|
||||
#define PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) pb_static_assertion_##MSG##LINE##COUNTER
|
||||
#endif
|
||||
#else
|
||||
#define PB_STATIC_ASSERT(COND, MSG)
|
||||
#endif
|
||||
|
||||
/* Number of required fields to keep track of. */
|
||||
#ifndef PB_MAX_REQUIRED_FIELDS
|
||||
#define PB_MAX_REQUIRED_FIELDS 64
|
||||
#endif
|
||||
|
||||
#if PB_MAX_REQUIRED_FIELDS < 64
|
||||
#error You should not lower PB_MAX_REQUIRED_FIELDS from the default value (64).
|
||||
#endif
|
||||
|
||||
/* List of possible field types. These are used in the autogenerated code.
|
||||
* Least-significant 4 bits tell the scalar type
|
||||
* Most-significant 4 bits specify repeated/required/packed etc.
|
||||
*/
|
||||
|
||||
typedef uint_least8_t pb_type_t;
|
||||
|
||||
/**** Field data types ****/
|
||||
|
||||
/* Numeric types */
|
||||
#define PB_LTYPE_VARINT 0x00 /* int32, int64, enum, bool */
|
||||
#define PB_LTYPE_UVARINT 0x01 /* uint32, uint64 */
|
||||
#define PB_LTYPE_SVARINT 0x02 /* sint32, sint64 */
|
||||
#define PB_LTYPE_FIXED32 0x03 /* fixed32, sfixed32, float */
|
||||
#define PB_LTYPE_FIXED64 0x04 /* fixed64, sfixed64, double */
|
||||
|
||||
/* Marker for last packable field type. */
|
||||
#define PB_LTYPE_LAST_PACKABLE 0x04
|
||||
|
||||
/* Byte array with pre-allocated buffer.
|
||||
* data_size is the length of the allocated PB_BYTES_ARRAY structure. */
|
||||
#define PB_LTYPE_BYTES 0x05
|
||||
|
||||
/* String with pre-allocated buffer.
|
||||
* data_size is the maximum length. */
|
||||
#define PB_LTYPE_STRING 0x06
|
||||
|
||||
/* Submessage
|
||||
* submsg_fields is pointer to field descriptions */
|
||||
#define PB_LTYPE_SUBMESSAGE 0x07
|
||||
|
||||
/* Extension pseudo-field
|
||||
* The field contains a pointer to pb_extension_t */
|
||||
#define PB_LTYPE_EXTENSION 0x08
|
||||
|
||||
/* Byte array with inline, pre-allocated byffer.
|
||||
* data_size is the length of the inline, allocated buffer.
|
||||
* This differs from PB_LTYPE_BYTES by defining the element as
|
||||
* pb_byte_t[data_size] rather than pb_bytes_array_t. */
|
||||
#define PB_LTYPE_FIXED_LENGTH_BYTES 0x09
|
||||
|
||||
/* Number of declared LTYPES */
|
||||
#define PB_LTYPES_COUNT 0x0A
|
||||
#define PB_LTYPE_MASK 0x0F
|
||||
|
||||
/**** Field repetition rules ****/
|
||||
|
||||
#define PB_HTYPE_REQUIRED 0x00
|
||||
#define PB_HTYPE_OPTIONAL 0x10
|
||||
#define PB_HTYPE_REPEATED 0x20
|
||||
#define PB_HTYPE_ONEOF 0x30
|
||||
#define PB_HTYPE_MASK 0x30
|
||||
|
||||
/**** Field allocation types ****/
|
||||
|
||||
#define PB_ATYPE_STATIC 0x00
|
||||
#define PB_ATYPE_POINTER 0x80
|
||||
#define PB_ATYPE_CALLBACK 0x40
|
||||
#define PB_ATYPE_MASK 0xC0
|
||||
|
||||
#define PB_ATYPE(x) ((x) & PB_ATYPE_MASK)
|
||||
#define PB_HTYPE(x) ((x) & PB_HTYPE_MASK)
|
||||
#define PB_LTYPE(x) ((x) & PB_LTYPE_MASK)
|
||||
|
||||
/* Data type used for storing sizes of struct fields
|
||||
* and array counts.
|
||||
*/
|
||||
#if defined(PB_FIELD_32BIT)
|
||||
typedef uint32_t pb_size_t;
|
||||
typedef int32_t pb_ssize_t;
|
||||
#elif defined(PB_FIELD_16BIT)
|
||||
typedef uint_least16_t pb_size_t;
|
||||
typedef int_least16_t pb_ssize_t;
|
||||
#else
|
||||
typedef uint_least8_t pb_size_t;
|
||||
typedef int_least8_t pb_ssize_t;
|
||||
#endif
|
||||
#define PB_SIZE_MAX ((pb_size_t)-1)
|
||||
|
||||
/* Data type for storing encoded data and other byte streams.
|
||||
* This typedef exists to support platforms where uint8_t does not exist.
|
||||
* You can regard it as equivalent on uint8_t on other platforms.
|
||||
*/
|
||||
typedef uint_least8_t pb_byte_t;
|
||||
|
||||
/* This structure is used in auto-generated constants
|
||||
* to specify struct fields.
|
||||
* You can change field sizes if you need structures
|
||||
* larger than 256 bytes or field tags larger than 256.
|
||||
* The compiler should complain if your .proto has such
|
||||
* structures. Fix that by defining PB_FIELD_16BIT or
|
||||
* PB_FIELD_32BIT.
|
||||
*/
|
||||
PB_PACKED_STRUCT_START
|
||||
typedef struct pb_field_s pb_field_t;
|
||||
struct pb_field_s
|
||||
{
|
||||
pb_size_t tag;
|
||||
pb_type_t type;
|
||||
pb_size_t data_offset; /* Offset of field data, relative to previous field. */
|
||||
pb_ssize_t size_offset; /* Offset of array size or has-boolean, relative to data */
|
||||
pb_size_t data_size; /* Data size in bytes for a single item */
|
||||
pb_size_t array_size; /* Maximum number of entries in array */
|
||||
|
||||
/* Field definitions for submessage
|
||||
* OR default value for all other non-array, non-callback types
|
||||
* If null, then field will zeroed. */
|
||||
const void *ptr;
|
||||
} pb_packed;
|
||||
PB_PACKED_STRUCT_END
|
||||
|
||||
/* Make sure that the standard integer types are of the expected sizes.
|
||||
* Otherwise fixed32/fixed64 fields can break.
|
||||
*
|
||||
* If you get errors here, it probably means that your stdint.h is not
|
||||
* correct for your platform.
|
||||
*/
|
||||
#ifndef PB_WITHOUT_64BIT
|
||||
PB_STATIC_ASSERT(sizeof(int64_t) == 2 * sizeof(int32_t), INT64_T_WRONG_SIZE)
|
||||
PB_STATIC_ASSERT(sizeof(uint64_t) == 2 * sizeof(uint32_t), UINT64_T_WRONG_SIZE)
|
||||
#endif
|
||||
|
||||
/* This structure is used for 'bytes' arrays.
|
||||
* It has the number of bytes in the beginning, and after that an array.
|
||||
* Note that actual structs used will have a different length of bytes array.
|
||||
*/
|
||||
#define PB_BYTES_ARRAY_T(n) struct { pb_size_t size; pb_byte_t bytes[n]; }
|
||||
#define PB_BYTES_ARRAY_T_ALLOCSIZE(n) ((size_t)n + offsetof(pb_bytes_array_t, bytes))
|
||||
|
||||
struct pb_bytes_array_s
|
||||
{
|
||||
pb_size_t size;
|
||||
pb_byte_t bytes[1];
|
||||
};
|
||||
typedef struct pb_bytes_array_s pb_bytes_array_t;
|
||||
|
||||
/* This structure is used for giving the callback function.
|
||||
* It is stored in the message structure and filled in by the method that
|
||||
* calls pb_decode.
|
||||
*
|
||||
* The decoding callback will be given a limited-length stream
|
||||
* If the wire type was string, the length is the length of the string.
|
||||
* If the wire type was a varint/fixed32/fixed64, the length is the length
|
||||
* of the actual value.
|
||||
* The function may be called multiple times (especially for repeated types,
|
||||
* but also otherwise if the message happens to contain the field multiple
|
||||
* times.)
|
||||
*
|
||||
* The encoding callback will receive the actual output stream.
|
||||
* It should write all the data in one call, including the field tag and
|
||||
* wire type. It can write multiple fields.
|
||||
*
|
||||
* The callback can be null if you want to skip a field.
|
||||
*/
|
||||
typedef struct pb_istream_s pb_istream_t;
|
||||
typedef struct pb_ostream_s pb_ostream_t;
|
||||
typedef struct pb_callback_s pb_callback_t;
|
||||
struct pb_callback_s
|
||||
{
|
||||
#ifdef PB_OLD_CALLBACK_STYLE
|
||||
/* Deprecated since nanopb-0.2.1 */
|
||||
union
|
||||
{
|
||||
bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void *arg);
|
||||
bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, const void *arg);
|
||||
} funcs;
|
||||
#else
|
||||
/* New function signature, which allows modifying arg contents in callback. */
|
||||
union
|
||||
{
|
||||
bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void **arg);
|
||||
bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, void * const *arg);
|
||||
} funcs;
|
||||
#endif
|
||||
|
||||
/* Free arg for use by callback */
|
||||
void *arg;
|
||||
};
|
||||
|
||||
/* Wire types. Library user needs these only in encoder callbacks. */
|
||||
typedef enum
|
||||
{
|
||||
PB_WT_VARINT = 0,
|
||||
PB_WT_64BIT = 1,
|
||||
PB_WT_STRING = 2,
|
||||
PB_WT_32BIT = 5
|
||||
} pb_wire_type_t;
|
||||
|
||||
/* Structure for defining the handling of unknown/extension fields.
|
||||
* Usually the pb_extension_type_t structure is automatically generated,
|
||||
* while the pb_extension_t structure is created by the user. However,
|
||||
* if you want to catch all unknown fields, you can also create a custom
|
||||
* pb_extension_type_t with your own callback.
|
||||
*/
|
||||
typedef struct pb_extension_type_s pb_extension_type_t;
|
||||
typedef struct pb_extension_s pb_extension_t;
|
||||
struct pb_extension_type_s
|
||||
{
|
||||
/* Called for each unknown field in the message.
|
||||
* If you handle the field, read off all of its data and return true.
|
||||
* If you do not handle the field, do not read anything and return true.
|
||||
* If you run into an error, return false.
|
||||
* Set to NULL for default handler.
|
||||
*/
|
||||
bool (*decode)(pb_istream_t *stream, pb_extension_t *extension,
|
||||
uint32_t tag, pb_wire_type_t wire_type);
|
||||
|
||||
/* Called once after all regular fields have been encoded.
|
||||
* If you have something to write, do so and return true.
|
||||
* If you do not have anything to write, just return true.
|
||||
* If you run into an error, return false.
|
||||
* Set to NULL for default handler.
|
||||
*/
|
||||
bool (*encode)(pb_ostream_t *stream, const pb_extension_t *extension);
|
||||
|
||||
/* Free field for use by the callback. */
|
||||
const void *arg;
|
||||
};
|
||||
|
||||
struct pb_extension_s
|
||||
{
|
||||
/* Type describing the extension field. Usually you'll initialize
|
||||
* this to a pointer to the automatically generated structure. */
|
||||
const pb_extension_type_t *type;
|
||||
|
||||
/* Destination for the decoded data. This must match the datatype
|
||||
* of the extension field. */
|
||||
void *dest;
|
||||
|
||||
/* Pointer to the next extension handler, or NULL.
|
||||
* If this extension does not match a field, the next handler is
|
||||
* automatically called. */
|
||||
pb_extension_t *next;
|
||||
|
||||
/* The decoder sets this to true if the extension was found.
|
||||
* Ignored for encoding. */
|
||||
bool found;
|
||||
};
|
||||
|
||||
/* Memory allocation functions to use. You can define pb_realloc and
|
||||
* pb_free to custom functions if you want. */
|
||||
#ifdef PB_ENABLE_MALLOC
|
||||
# ifndef pb_realloc
|
||||
# define pb_realloc(ptr, size) realloc(ptr, size)
|
||||
# endif
|
||||
# ifndef pb_free
|
||||
# define pb_free(ptr) free(ptr)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* This is used to inform about need to regenerate .pb.h/.pb.c files. */
|
||||
#define PB_PROTO_HEADER_VERSION 30
|
||||
|
||||
/* These macros are used to declare pb_field_t's in the constant array. */
|
||||
/* Size of a structure member, in bytes. */
|
||||
#define pb_membersize(st, m) (sizeof ((st*)0)->m)
|
||||
/* Number of entries in an array. */
|
||||
#define pb_arraysize(st, m) (pb_membersize(st, m) / pb_membersize(st, m[0]))
|
||||
/* Delta from start of one member to the start of another member. */
|
||||
#define pb_delta(st, m1, m2) ((int)offsetof(st, m1) - (int)offsetof(st, m2))
|
||||
/* Marks the end of the field list */
|
||||
#define PB_LAST_FIELD {0, (pb_type_t)0, 0, 0, 0, 0, 0}
|
||||
|
||||
/* Macros for filling in the data_offset field */
|
||||
/* data_offset for first field in a message */
|
||||
#define PB_DATAOFFSET_FIRST(st, m1, m2) (offsetof(st, m1))
|
||||
/* data_offset for subsequent fields */
|
||||
#define PB_DATAOFFSET_OTHER(st, m1, m2) (offsetof(st, m1) - offsetof(st, m2) - pb_membersize(st, m2))
|
||||
/* data offset for subsequent fields inside an union (oneof) */
|
||||
#define PB_DATAOFFSET_UNION(st, m1, m2) (PB_SIZE_MAX)
|
||||
/* Choose first/other based on m1 == m2 (deprecated, remains for backwards compatibility) */
|
||||
#define PB_DATAOFFSET_CHOOSE(st, m1, m2) (int)(offsetof(st, m1) == offsetof(st, m2) \
|
||||
? PB_DATAOFFSET_FIRST(st, m1, m2) \
|
||||
: PB_DATAOFFSET_OTHER(st, m1, m2))
|
||||
|
||||
/* Required fields are the simplest. They just have delta (padding) from
|
||||
* previous field end, and the size of the field. Pointer is used for
|
||||
* submessages and default values.
|
||||
*/
|
||||
#define PB_REQUIRED_STATIC(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_STATIC | PB_HTYPE_REQUIRED | ltype, \
|
||||
fd, 0, pb_membersize(st, m), 0, ptr}
|
||||
|
||||
/* Optional fields add the delta to the has_ variable. */
|
||||
#define PB_OPTIONAL_STATIC(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_STATIC | PB_HTYPE_OPTIONAL | ltype, \
|
||||
fd, \
|
||||
pb_delta(st, has_ ## m, m), \
|
||||
pb_membersize(st, m), 0, ptr}
|
||||
|
||||
#define PB_SINGULAR_STATIC(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_STATIC | PB_HTYPE_OPTIONAL | ltype, \
|
||||
fd, 0, pb_membersize(st, m), 0, ptr}
|
||||
|
||||
/* Repeated fields have a _count field and also the maximum number of entries. */
|
||||
#define PB_REPEATED_STATIC(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_STATIC | PB_HTYPE_REPEATED | ltype, \
|
||||
fd, \
|
||||
pb_delta(st, m ## _count, m), \
|
||||
pb_membersize(st, m[0]), \
|
||||
pb_arraysize(st, m), ptr}
|
||||
|
||||
/* Allocated fields carry the size of the actual data, not the pointer */
|
||||
#define PB_REQUIRED_POINTER(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_POINTER | PB_HTYPE_REQUIRED | ltype, \
|
||||
fd, 0, pb_membersize(st, m[0]), 0, ptr}
|
||||
|
||||
/* Optional fields don't need a has_ variable, as information would be redundant */
|
||||
#define PB_OPTIONAL_POINTER(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_POINTER | PB_HTYPE_OPTIONAL | ltype, \
|
||||
fd, 0, pb_membersize(st, m[0]), 0, ptr}
|
||||
|
||||
/* Same as optional fields*/
|
||||
#define PB_SINGULAR_POINTER(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_POINTER | PB_HTYPE_OPTIONAL | ltype, \
|
||||
fd, 0, pb_membersize(st, m[0]), 0, ptr}
|
||||
|
||||
/* Repeated fields have a _count field and a pointer to array of pointers */
|
||||
#define PB_REPEATED_POINTER(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_POINTER | PB_HTYPE_REPEATED | ltype, \
|
||||
fd, pb_delta(st, m ## _count, m), \
|
||||
pb_membersize(st, m[0]), 0, ptr}
|
||||
|
||||
/* Callbacks are much like required fields except with special datatype. */
|
||||
#define PB_REQUIRED_CALLBACK(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_CALLBACK | PB_HTYPE_REQUIRED | ltype, \
|
||||
fd, 0, pb_membersize(st, m), 0, ptr}
|
||||
|
||||
#define PB_OPTIONAL_CALLBACK(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_CALLBACK | PB_HTYPE_OPTIONAL | ltype, \
|
||||
fd, 0, pb_membersize(st, m), 0, ptr}
|
||||
|
||||
#define PB_SINGULAR_CALLBACK(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_CALLBACK | PB_HTYPE_OPTIONAL | ltype, \
|
||||
fd, 0, pb_membersize(st, m), 0, ptr}
|
||||
|
||||
#define PB_REPEATED_CALLBACK(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_CALLBACK | PB_HTYPE_REPEATED | ltype, \
|
||||
fd, 0, pb_membersize(st, m), 0, ptr}
|
||||
|
||||
/* Optional extensions don't have the has_ field, as that would be redundant.
|
||||
* Furthermore, the combination of OPTIONAL without has_ field is used
|
||||
* for indicating proto3 style fields. Extensions exist in proto2 mode only,
|
||||
* so they should be encoded according to proto2 rules. To avoid the conflict,
|
||||
* extensions are marked as REQUIRED instead.
|
||||
*/
|
||||
#define PB_OPTEXT_STATIC(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_STATIC | PB_HTYPE_REQUIRED | ltype, \
|
||||
0, \
|
||||
0, \
|
||||
pb_membersize(st, m), 0, ptr}
|
||||
|
||||
#define PB_OPTEXT_POINTER(tag, st, m, fd, ltype, ptr) \
|
||||
PB_OPTIONAL_POINTER(tag, st, m, fd, ltype, ptr)
|
||||
|
||||
#define PB_OPTEXT_CALLBACK(tag, st, m, fd, ltype, ptr) \
|
||||
PB_OPTIONAL_CALLBACK(tag, st, m, fd, ltype, ptr)
|
||||
|
||||
/* The mapping from protobuf types to LTYPEs is done using these macros. */
|
||||
#define PB_LTYPE_MAP_BOOL PB_LTYPE_VARINT
|
||||
#define PB_LTYPE_MAP_BYTES PB_LTYPE_BYTES
|
||||
#define PB_LTYPE_MAP_DOUBLE PB_LTYPE_FIXED64
|
||||
#define PB_LTYPE_MAP_ENUM PB_LTYPE_VARINT
|
||||
#define PB_LTYPE_MAP_UENUM PB_LTYPE_UVARINT
|
||||
#define PB_LTYPE_MAP_FIXED32 PB_LTYPE_FIXED32
|
||||
#define PB_LTYPE_MAP_FIXED64 PB_LTYPE_FIXED64
|
||||
#define PB_LTYPE_MAP_FLOAT PB_LTYPE_FIXED32
|
||||
#define PB_LTYPE_MAP_INT32 PB_LTYPE_VARINT
|
||||
#define PB_LTYPE_MAP_INT64 PB_LTYPE_VARINT
|
||||
#define PB_LTYPE_MAP_MESSAGE PB_LTYPE_SUBMESSAGE
|
||||
#define PB_LTYPE_MAP_SFIXED32 PB_LTYPE_FIXED32
|
||||
#define PB_LTYPE_MAP_SFIXED64 PB_LTYPE_FIXED64
|
||||
#define PB_LTYPE_MAP_SINT32 PB_LTYPE_SVARINT
|
||||
#define PB_LTYPE_MAP_SINT64 PB_LTYPE_SVARINT
|
||||
#define PB_LTYPE_MAP_STRING PB_LTYPE_STRING
|
||||
#define PB_LTYPE_MAP_UINT32 PB_LTYPE_UVARINT
|
||||
#define PB_LTYPE_MAP_UINT64 PB_LTYPE_UVARINT
|
||||
#define PB_LTYPE_MAP_EXTENSION PB_LTYPE_EXTENSION
|
||||
#define PB_LTYPE_MAP_FIXED_LENGTH_BYTES PB_LTYPE_FIXED_LENGTH_BYTES
|
||||
|
||||
/* This is the actual macro used in field descriptions.
|
||||
* It takes these arguments:
|
||||
* - Field tag number
|
||||
* - Field type: BOOL, BYTES, DOUBLE, ENUM, UENUM, FIXED32, FIXED64,
|
||||
* FLOAT, INT32, INT64, MESSAGE, SFIXED32, SFIXED64
|
||||
* SINT32, SINT64, STRING, UINT32, UINT64 or EXTENSION
|
||||
* - Field rules: REQUIRED, OPTIONAL or REPEATED
|
||||
* - Allocation: STATIC, CALLBACK or POINTER
|
||||
* - Placement: FIRST or OTHER, depending on if this is the first field in structure.
|
||||
* - Message name
|
||||
* - Field name
|
||||
* - Previous field name (or field name again for first field)
|
||||
* - Pointer to default value or submsg fields.
|
||||
*/
|
||||
|
||||
#define PB_FIELD(tag, type, rules, allocation, placement, message, field, prevfield, ptr) \
|
||||
PB_ ## rules ## _ ## allocation(tag, message, field, \
|
||||
PB_DATAOFFSET_ ## placement(message, field, prevfield), \
|
||||
PB_LTYPE_MAP_ ## type, ptr)
|
||||
|
||||
/* Field description for repeated static fixed count fields.*/
|
||||
#define PB_REPEATED_FIXED_COUNT(tag, type, placement, message, field, prevfield, ptr) \
|
||||
{tag, PB_ATYPE_STATIC | PB_HTYPE_REPEATED | PB_LTYPE_MAP_ ## type, \
|
||||
PB_DATAOFFSET_ ## placement(message, field, prevfield), \
|
||||
0, \
|
||||
pb_membersize(message, field[0]), \
|
||||
pb_arraysize(message, field), ptr}
|
||||
|
||||
/* Field description for oneof fields. This requires taking into account the
|
||||
* union name also, that's why a separate set of macros is needed.
|
||||
*/
|
||||
#define PB_ONEOF_STATIC(u, tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_STATIC | PB_HTYPE_ONEOF | ltype, \
|
||||
fd, pb_delta(st, which_ ## u, u.m), \
|
||||
pb_membersize(st, u.m), 0, ptr}
|
||||
|
||||
#define PB_ONEOF_POINTER(u, tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_POINTER | PB_HTYPE_ONEOF | ltype, \
|
||||
fd, pb_delta(st, which_ ## u, u.m), \
|
||||
pb_membersize(st, u.m[0]), 0, ptr}
|
||||
|
||||
#define PB_ONEOF_FIELD(union_name, tag, type, rules, allocation, placement, message, field, prevfield, ptr) \
|
||||
PB_ONEOF_ ## allocation(union_name, tag, message, field, \
|
||||
PB_DATAOFFSET_ ## placement(message, union_name.field, prevfield), \
|
||||
PB_LTYPE_MAP_ ## type, ptr)
|
||||
|
||||
#define PB_ANONYMOUS_ONEOF_STATIC(u, tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_STATIC | PB_HTYPE_ONEOF | ltype, \
|
||||
fd, pb_delta(st, which_ ## u, m), \
|
||||
pb_membersize(st, m), 0, ptr}
|
||||
|
||||
#define PB_ANONYMOUS_ONEOF_POINTER(u, tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_POINTER | PB_HTYPE_ONEOF | ltype, \
|
||||
fd, pb_delta(st, which_ ## u, m), \
|
||||
pb_membersize(st, m[0]), 0, ptr}
|
||||
|
||||
#define PB_ANONYMOUS_ONEOF_FIELD(union_name, tag, type, rules, allocation, placement, message, field, prevfield, ptr) \
|
||||
PB_ANONYMOUS_ONEOF_ ## allocation(union_name, tag, message, field, \
|
||||
PB_DATAOFFSET_ ## placement(message, field, prevfield), \
|
||||
PB_LTYPE_MAP_ ## type, ptr)
|
||||
|
||||
/* These macros are used for giving out error messages.
|
||||
* They are mostly a debugging aid; the main error information
|
||||
* is the true/false return value from functions.
|
||||
* Some code space can be saved by disabling the error
|
||||
* messages if not used.
|
||||
*
|
||||
* PB_SET_ERROR() sets the error message if none has been set yet.
|
||||
* msg must be a constant string literal.
|
||||
* PB_GET_ERROR() always returns a pointer to a string.
|
||||
* PB_RETURN_ERROR() sets the error and returns false from current
|
||||
* function.
|
||||
*/
|
||||
#ifdef PB_NO_ERRMSG
|
||||
#define PB_SET_ERROR(stream, msg) PB_UNUSED(stream)
|
||||
#define PB_GET_ERROR(stream) "(errmsg disabled)"
|
||||
#else
|
||||
#define PB_SET_ERROR(stream, msg) (stream->errmsg = (stream)->errmsg ? (stream)->errmsg : (msg))
|
||||
#define PB_GET_ERROR(stream) ((stream)->errmsg ? (stream)->errmsg : "(none)")
|
||||
#endif
|
||||
|
||||
#define PB_RETURN_ERROR(stream, msg) return PB_SET_ERROR(stream, msg), false
|
||||
|
||||
#endif
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// bp_common.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Auto-generated (see below).
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
/* pb_common.h: Common support functions for pb_encode.c and pb_decode.c.
|
||||
* These functions are rarely needed by applications directly.
|
||||
*/
|
||||
|
||||
#ifndef PB_COMMON_H_INCLUDED
|
||||
#define PB_COMMON_H_INCLUDED
|
||||
|
||||
#include "pb.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Iterator for pb_field_t list */
|
||||
struct pb_field_iter_s
|
||||
{
|
||||
const pb_field_t *start; /* Start of the pb_field_t array */
|
||||
const pb_field_t *pos; /* Current position of the iterator */
|
||||
unsigned required_field_index; /* Zero-based index that counts only the required fields */
|
||||
void *dest_struct; /* Pointer to start of the structure */
|
||||
void *pData; /* Pointer to current field value */
|
||||
void *pSize; /* Pointer to count/has field */
|
||||
};
|
||||
typedef struct pb_field_iter_s pb_field_iter_t;
|
||||
|
||||
/* Initialize the field iterator structure to beginning.
|
||||
* Returns false if the message type is empty. */
|
||||
bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_field_t *fields, void *dest_struct);
|
||||
|
||||
/* Advance the iterator to the next field.
|
||||
* Returns false when the iterator wraps back to the first field. */
|
||||
bool pb_field_iter_next(pb_field_iter_t *iter);
|
||||
|
||||
/* Advance the iterator until it points at a field with the given tag.
|
||||
* Returns false if no such field exists. */
|
||||
bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
+222
@@ -0,0 +1,222 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// pb_decode.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Auto-generated (see below).
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
/* pb_decode.h: Functions to decode protocol buffers. Depends on pb_decode.c.
|
||||
* The main function is pb_decode. You also need an input stream, and the
|
||||
* field descriptions created by nanopb_generator.py.
|
||||
*/
|
||||
|
||||
#ifndef PB_DECODE_H_INCLUDED
|
||||
#define PB_DECODE_H_INCLUDED
|
||||
|
||||
#include "pb.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Structure for defining custom input streams. You will need to provide
|
||||
* a callback function to read the bytes from your storage, which can be
|
||||
* for example a file or a network socket.
|
||||
*
|
||||
* The callback must conform to these rules:
|
||||
*
|
||||
* 1) Return false on IO errors. This will cause decoding to abort.
|
||||
* 2) You can use state to store your own data (e.g. buffer pointer),
|
||||
* and rely on pb_read to verify that no-body reads past bytes_left.
|
||||
* 3) Your callback may be used with substreams, in which case bytes_left
|
||||
* is different than from the main stream. Don't use bytes_left to compute
|
||||
* any pointers.
|
||||
*/
|
||||
struct pb_istream_s
|
||||
{
|
||||
#ifdef PB_BUFFER_ONLY
|
||||
/* Callback pointer is not used in buffer-only configuration.
|
||||
* Having an int pointer here allows binary compatibility but
|
||||
* gives an error if someone tries to assign callback function.
|
||||
*/
|
||||
int *callback;
|
||||
#else
|
||||
bool (*callback)(pb_istream_t *stream, pb_byte_t *buf, size_t count);
|
||||
#endif
|
||||
|
||||
void *state; /* Free field for use by callback implementation */
|
||||
size_t bytes_left;
|
||||
|
||||
#ifndef PB_NO_ERRMSG
|
||||
const char *errmsg;
|
||||
#endif
|
||||
};
|
||||
|
||||
/***************************
|
||||
* Main decoding functions *
|
||||
***************************/
|
||||
|
||||
/* Decode a single protocol buffers message from input stream into a C structure.
|
||||
* Returns true on success, false on any failure.
|
||||
* The actual struct pointed to by dest must match the description in fields.
|
||||
* Callback fields of the destination structure must be initialized by caller.
|
||||
* All other fields will be initialized by this function.
|
||||
*
|
||||
* Example usage:
|
||||
* MyMessage msg = {};
|
||||
* uint8_t buffer[64];
|
||||
* pb_istream_t stream;
|
||||
*
|
||||
* // ... read some data into buffer ...
|
||||
*
|
||||
* stream = pb_istream_from_buffer(buffer, count);
|
||||
* pb_decode(&stream, MyMessage_fields, &msg);
|
||||
*/
|
||||
bool pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct);
|
||||
|
||||
/* Same as pb_decode, except does not initialize the destination structure
|
||||
* to default values. This is slightly faster if you need no default values
|
||||
* and just do memset(struct, 0, sizeof(struct)) yourself.
|
||||
*
|
||||
* This can also be used for 'merging' two messages, i.e. update only the
|
||||
* fields that exist in the new message.
|
||||
*
|
||||
* Note: If this function returns with an error, it will not release any
|
||||
* dynamically allocated fields. You will need to call pb_release() yourself.
|
||||
*/
|
||||
bool pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct);
|
||||
|
||||
/* Same as pb_decode, except expects the stream to start with the message size
|
||||
* encoded as varint. Corresponds to parseDelimitedFrom() in Google's
|
||||
* protobuf API.
|
||||
*/
|
||||
bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct);
|
||||
|
||||
/* Same as pb_decode_delimited, except that it does not initialize the destination structure.
|
||||
* See pb_decode_noinit
|
||||
*/
|
||||
bool pb_decode_delimited_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct);
|
||||
|
||||
/* Same as pb_decode, except allows the message to be terminated with a null byte.
|
||||
* NOTE: Until nanopb-0.4.0, pb_decode() also allows null-termination. This behaviour
|
||||
* is not supported in most other protobuf implementations, so pb_decode_delimited()
|
||||
* is a better option for compatibility.
|
||||
*/
|
||||
bool pb_decode_nullterminated(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct);
|
||||
|
||||
#ifdef PB_ENABLE_MALLOC
|
||||
/* Release any allocated pointer fields. If you use dynamic allocation, you should
|
||||
* call this for any successfully decoded message when you are done with it. If
|
||||
* pb_decode() returns with an error, the message is already released.
|
||||
*/
|
||||
void pb_release(const pb_field_t fields[], void *dest_struct);
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************
|
||||
* Functions for manipulating streams *
|
||||
**************************************/
|
||||
|
||||
/* Create an input stream for reading from a memory buffer.
|
||||
*
|
||||
* Alternatively, you can use a custom stream that reads directly from e.g.
|
||||
* a file or a network socket.
|
||||
*/
|
||||
pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize);
|
||||
|
||||
/* Function to read from a pb_istream_t. You can use this if you need to
|
||||
* read some custom header data, or to read data in field callbacks.
|
||||
*/
|
||||
bool pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count);
|
||||
|
||||
|
||||
/************************************************
|
||||
* Helper functions for writing field callbacks *
|
||||
************************************************/
|
||||
|
||||
/* Decode the tag for the next field in the stream. Gives the wire type and
|
||||
* field tag. At end of the message, returns false and sets eof to true. */
|
||||
bool pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof);
|
||||
|
||||
/* Skip the field payload data, given the wire type. */
|
||||
bool pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type);
|
||||
|
||||
/* Decode an integer in the varint format. This works for bool, enum, int32,
|
||||
* int64, uint32 and uint64 field types. */
|
||||
#ifndef PB_WITHOUT_64BIT
|
||||
bool pb_decode_varint(pb_istream_t *stream, uint64_t *dest);
|
||||
#else
|
||||
#define pb_decode_varint pb_decode_varint32
|
||||
#endif
|
||||
|
||||
/* Decode an integer in the varint format. This works for bool, enum, int32,
|
||||
* and uint32 field types. */
|
||||
bool pb_decode_varint32(pb_istream_t *stream, uint32_t *dest);
|
||||
|
||||
/* Decode an integer in the zig-zagged svarint format. This works for sint32
|
||||
* and sint64. */
|
||||
#ifndef PB_WITHOUT_64BIT
|
||||
bool pb_decode_svarint(pb_istream_t *stream, int64_t *dest);
|
||||
#else
|
||||
bool pb_decode_svarint(pb_istream_t *stream, int32_t *dest);
|
||||
#endif
|
||||
|
||||
/* Decode a fixed32, sfixed32 or float value. You need to pass a pointer to
|
||||
* a 4-byte wide C variable. */
|
||||
bool pb_decode_fixed32(pb_istream_t *stream, void *dest);
|
||||
|
||||
#ifndef PB_WITHOUT_64BIT
|
||||
/* Decode a fixed64, sfixed64 or double value. You need to pass a pointer to
|
||||
* a 8-byte wide C variable. */
|
||||
bool pb_decode_fixed64(pb_istream_t *stream, void *dest);
|
||||
#endif
|
||||
|
||||
/* Make a limited-length substream for reading a PB_WT_STRING field. */
|
||||
bool pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream);
|
||||
bool pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+217
@@ -0,0 +1,217 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// pb_encode.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Auto-generated (see below).
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
/* pb_encode.h: Functions to encode protocol buffers. Depends on pb_encode.c.
|
||||
* The main function is pb_encode. You also need an output stream, and the
|
||||
* field descriptions created by nanopb_generator.py.
|
||||
*/
|
||||
|
||||
#ifndef PB_ENCODE_H_INCLUDED
|
||||
#define PB_ENCODE_H_INCLUDED
|
||||
|
||||
#include "pb.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Structure for defining custom output streams. You will need to provide
|
||||
* a callback function to write the bytes to your storage, which can be
|
||||
* for example a file or a network socket.
|
||||
*
|
||||
* The callback must conform to these rules:
|
||||
*
|
||||
* 1) Return false on IO errors. This will cause encoding to abort.
|
||||
* 2) You can use state to store your own data (e.g. buffer pointer).
|
||||
* 3) pb_write will update bytes_written after your callback runs.
|
||||
* 4) Substreams will modify max_size and bytes_written. Don't use them
|
||||
* to calculate any pointers.
|
||||
*/
|
||||
struct pb_ostream_s
|
||||
{
|
||||
#ifdef PB_BUFFER_ONLY
|
||||
/* Callback pointer is not used in buffer-only configuration.
|
||||
* Having an int pointer here allows binary compatibility but
|
||||
* gives an error if someone tries to assign callback function.
|
||||
* Also, NULL pointer marks a 'sizing stream' that does not
|
||||
* write anything.
|
||||
*/
|
||||
int *callback;
|
||||
#else
|
||||
bool (*callback)(pb_ostream_t *stream, const pb_byte_t *buf, size_t count);
|
||||
#endif
|
||||
void *state; /* Free field for use by callback implementation. */
|
||||
size_t max_size; /* Limit number of output bytes written (or use SIZE_MAX). */
|
||||
size_t bytes_written; /* Number of bytes written so far. */
|
||||
|
||||
#ifndef PB_NO_ERRMSG
|
||||
const char *errmsg;
|
||||
#endif
|
||||
};
|
||||
|
||||
/***************************
|
||||
* Main encoding functions *
|
||||
***************************/
|
||||
|
||||
/* Encode a single protocol buffers message from C structure into a stream.
|
||||
* Returns true on success, false on any failure.
|
||||
* The actual struct pointed to by src_struct must match the description in fields.
|
||||
* All required fields in the struct are assumed to have been filled in.
|
||||
*
|
||||
* Example usage:
|
||||
* MyMessage msg = {};
|
||||
* uint8_t buffer[64];
|
||||
* pb_ostream_t stream;
|
||||
*
|
||||
* msg.field1 = 42;
|
||||
* stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
|
||||
* pb_encode(&stream, MyMessage_fields, &msg);
|
||||
*/
|
||||
bool pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct);
|
||||
|
||||
/* Same as pb_encode, but prepends the length of the message as a varint.
|
||||
* Corresponds to writeDelimitedTo() in Google's protobuf API.
|
||||
*/
|
||||
bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct);
|
||||
|
||||
/* Same as pb_encode, but appends a null byte to the message for termination.
|
||||
* NOTE: This behaviour is not supported in most other protobuf implementations, so pb_encode_delimited()
|
||||
* is a better option for compatibility.
|
||||
*/
|
||||
bool pb_encode_nullterminated(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct);
|
||||
|
||||
/* Encode the message to get the size of the encoded data, but do not store
|
||||
* the data. */
|
||||
bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct);
|
||||
|
||||
/**************************************
|
||||
* Functions for manipulating streams *
|
||||
**************************************/
|
||||
|
||||
/* Create an output stream for writing into a memory buffer.
|
||||
* The number of bytes written can be found in stream.bytes_written after
|
||||
* encoding the message.
|
||||
*
|
||||
* Alternatively, you can use a custom stream that writes directly to e.g.
|
||||
* a file or a network socket.
|
||||
*/
|
||||
pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize);
|
||||
|
||||
/* Pseudo-stream for measuring the size of a message without actually storing
|
||||
* the encoded data.
|
||||
*
|
||||
* Example usage:
|
||||
* MyMessage msg = {};
|
||||
* pb_ostream_t stream = PB_OSTREAM_SIZING;
|
||||
* pb_encode(&stream, MyMessage_fields, &msg);
|
||||
* printf("Message size is %d\n", stream.bytes_written);
|
||||
*/
|
||||
#ifndef PB_NO_ERRMSG
|
||||
#define PB_OSTREAM_SIZING {0, 0, 0, 0, 0}
|
||||
#else
|
||||
#define PB_OSTREAM_SIZING {0, 0, 0, 0}
|
||||
#endif
|
||||
|
||||
/* Function to write into a pb_ostream_t stream. You can use this if you need
|
||||
* to append or prepend some custom headers to the message.
|
||||
*/
|
||||
bool pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count);
|
||||
|
||||
|
||||
/************************************************
|
||||
* Helper functions for writing field callbacks *
|
||||
************************************************/
|
||||
|
||||
/* Encode field header based on type and field number defined in the field
|
||||
* structure. Call this from the callback before writing out field contents. */
|
||||
bool pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field);
|
||||
|
||||
/* Encode field header by manually specifing wire type. You need to use this
|
||||
* if you want to write out packed arrays from a callback field. */
|
||||
bool pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number);
|
||||
|
||||
/* Encode an integer in the varint format.
|
||||
* This works for bool, enum, int32, int64, uint32 and uint64 field types. */
|
||||
#ifndef PB_WITHOUT_64BIT
|
||||
bool pb_encode_varint(pb_ostream_t *stream, uint64_t value);
|
||||
#else
|
||||
bool pb_encode_varint(pb_ostream_t *stream, uint32_t value);
|
||||
#endif
|
||||
|
||||
/* Encode an integer in the zig-zagged svarint format.
|
||||
* This works for sint32 and sint64. */
|
||||
#ifndef PB_WITHOUT_64BIT
|
||||
bool pb_encode_svarint(pb_ostream_t *stream, int64_t value);
|
||||
#else
|
||||
bool pb_encode_svarint(pb_ostream_t *stream, int32_t value);
|
||||
#endif
|
||||
|
||||
/* Encode a string or bytes type field. For strings, pass strlen(s) as size. */
|
||||
bool pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size);
|
||||
|
||||
/* Encode a fixed32, sfixed32 or float value.
|
||||
* You need to pass a pointer to a 4-byte wide C variable. */
|
||||
bool pb_encode_fixed32(pb_ostream_t *stream, const void *value);
|
||||
|
||||
#ifndef PB_WITHOUT_64BIT
|
||||
/* Encode a fixed64, sfixed64 or double value.
|
||||
* You need to pass a pointer to a 8-byte wide C variable. */
|
||||
bool pb_encode_fixed64(pb_ostream_t *stream, const void *value);
|
||||
#endif
|
||||
|
||||
/* Encode a submessage field.
|
||||
* You need to pass the pb_field_t array and pointer to struct, just like
|
||||
* with pb_encode(). This internally encodes the submessage twice, first to
|
||||
* calculate message size and then to actually write it out.
|
||||
*/
|
||||
bool pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+276
@@ -0,0 +1,276 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// speech.pb.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Auto-generated (see below).
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.3.9.1 at Fri Nov 09 16:58:28 2018. */
|
||||
|
||||
#ifndef PB_SPEECH_PB_H_INCLUDED
|
||||
#define PB_SPEECH_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
|
||||
#include "common.pb.h"
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Enum definitions */
|
||||
typedef enum _AudioProfile
|
||||
{
|
||||
AudioProfile_CLOSE_TALK = 0,
|
||||
AudioProfile_NEAR_FIELD = 1,
|
||||
AudioProfile_FAR_FIELD = 2
|
||||
} AudioProfile;
|
||||
#define _AudioProfile_MIN AudioProfile_CLOSE_TALK
|
||||
#define _AudioProfile_MAX AudioProfile_FAR_FIELD
|
||||
#define _AudioProfile_ARRAYSIZE ((AudioProfile)(AudioProfile_FAR_FIELD + 1))
|
||||
|
||||
typedef enum _AudioFormat
|
||||
{
|
||||
AudioFormat_PCM_L16_16KHZ_MONO = 0,
|
||||
AudioFormat_OPUS_16KHZ_32KBPS_CBR_0_20MS = 1,
|
||||
AudioFormat_OPUS_16KHZ_16KBPS_CBR_0_20MS = 2,
|
||||
AudioFormat_MSBC = 3
|
||||
} AudioFormat;
|
||||
#define _AudioFormat_MIN AudioFormat_PCM_L16_16KHZ_MONO
|
||||
#define _AudioFormat_MAX AudioFormat_MSBC
|
||||
#define _AudioFormat_ARRAYSIZE ((AudioFormat)(AudioFormat_MSBC + 1))
|
||||
|
||||
typedef enum _AudioSource
|
||||
{
|
||||
AudioSource_STREAM = 0,
|
||||
AudioSource_BLUETOOTH_SCO = 1
|
||||
} AudioSource;
|
||||
#define _AudioSource_MIN AudioSource_STREAM
|
||||
#define _AudioSource_MAX AudioSource_BLUETOOTH_SCO
|
||||
#define _AudioSource_ARRAYSIZE ((AudioSource)(AudioSource_BLUETOOTH_SCO + 1))
|
||||
|
||||
typedef enum _SpeechState
|
||||
{
|
||||
SpeechState_IDLE = 0,
|
||||
SpeechState_LISTENING = 1,
|
||||
SpeechState_PROCESSING = 2,
|
||||
SpeechState_SPEAKING = 3
|
||||
} SpeechState;
|
||||
#define _SpeechState_MIN SpeechState_IDLE
|
||||
#define _SpeechState_MAX SpeechState_SPEAKING
|
||||
#define _SpeechState_ARRAYSIZE ((SpeechState)(SpeechState_SPEAKING + 1))
|
||||
|
||||
typedef enum _SpeechInitiator_Type
|
||||
{
|
||||
SpeechInitiator_Type_NONE = 0,
|
||||
SpeechInitiator_Type_PRESS_AND_HOLD = 1,
|
||||
SpeechInitiator_Type_TAP = 3,
|
||||
SpeechInitiator_Type_WAKEWORD = 4
|
||||
} SpeechInitiator_Type;
|
||||
#define _SpeechInitiator_Type_MIN SpeechInitiator_Type_NONE
|
||||
#define _SpeechInitiator_Type_MAX SpeechInitiator_Type_WAKEWORD
|
||||
#define _SpeechInitiator_Type_ARRAYSIZE ((SpeechInitiator_Type)(SpeechInitiator_Type_WAKEWORD + 1))
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _Dialog
|
||||
{
|
||||
uint32_t id;
|
||||
/* @@protoc_insertion_point(struct:Dialog) */
|
||||
} Dialog;
|
||||
|
||||
typedef struct _NotifySpeechState
|
||||
{
|
||||
SpeechState state;
|
||||
/* @@protoc_insertion_point(struct:NotifySpeechState) */
|
||||
} NotifySpeechState;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(256) SpeechInitiator_WakeWord_metadata_t;
|
||||
typedef struct _SpeechInitiator_WakeWord
|
||||
{
|
||||
uint32_t start_index_in_samples;
|
||||
uint32_t end_index_in_samples;
|
||||
bool near_miss;
|
||||
SpeechInitiator_WakeWord_metadata_t metadata;
|
||||
/* @@protoc_insertion_point(struct:SpeechInitiator_WakeWord) */
|
||||
} SpeechInitiator_WakeWord;
|
||||
|
||||
typedef struct _SpeechSettings
|
||||
{
|
||||
AudioProfile audio_profile;
|
||||
AudioFormat audio_format;
|
||||
AudioSource audio_source;
|
||||
/* @@protoc_insertion_point(struct:SpeechSettings) */
|
||||
} SpeechSettings;
|
||||
|
||||
typedef struct _EndpointSpeech
|
||||
{
|
||||
Dialog dialog;
|
||||
/* @@protoc_insertion_point(struct:EndpointSpeech) */
|
||||
} EndpointSpeech;
|
||||
|
||||
typedef struct _ProvideSpeech
|
||||
{
|
||||
Dialog dialog;
|
||||
/* @@protoc_insertion_point(struct:ProvideSpeech) */
|
||||
} ProvideSpeech;
|
||||
|
||||
typedef struct _SpeechInitiator
|
||||
{
|
||||
SpeechInitiator_Type type;
|
||||
SpeechInitiator_WakeWord wake_word;
|
||||
/* @@protoc_insertion_point(struct:SpeechInitiator) */
|
||||
} SpeechInitiator;
|
||||
|
||||
typedef struct _SpeechProvider
|
||||
{
|
||||
SpeechSettings speech_settings;
|
||||
Dialog dialog;
|
||||
/* @@protoc_insertion_point(struct:SpeechProvider) */
|
||||
} SpeechProvider;
|
||||
|
||||
typedef struct _StopSpeech
|
||||
{
|
||||
ErrorCode error_code;
|
||||
Dialog dialog;
|
||||
/* @@protoc_insertion_point(struct:StopSpeech) */
|
||||
} StopSpeech;
|
||||
|
||||
typedef struct _StartSpeech
|
||||
{
|
||||
SpeechSettings settings;
|
||||
SpeechInitiator initiator;
|
||||
Dialog dialog;
|
||||
bool suppressEarcon;
|
||||
/* @@protoc_insertion_point(struct:StartSpeech) */
|
||||
} StartSpeech;
|
||||
|
||||
/* Default values for struct fields */
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define Dialog_init_default {0}
|
||||
#define SpeechSettings_init_default {_AudioProfile_MIN, _AudioFormat_MIN, _AudioSource_MIN}
|
||||
#define SpeechInitiator_init_default {_SpeechInitiator_Type_MIN, SpeechInitiator_WakeWord_init_default}
|
||||
#define SpeechInitiator_WakeWord_init_default {0, 0, 0, {0, {0}}}
|
||||
#define StartSpeech_init_default {SpeechSettings_init_default, SpeechInitiator_init_default, Dialog_init_default, 0}
|
||||
#define SpeechProvider_init_default {SpeechSettings_init_default, Dialog_init_default}
|
||||
#define ProvideSpeech_init_default {Dialog_init_default}
|
||||
#define StopSpeech_init_default {_ErrorCode_MIN, Dialog_init_default}
|
||||
#define EndpointSpeech_init_default {Dialog_init_default}
|
||||
#define NotifySpeechState_init_default {_SpeechState_MIN}
|
||||
#define Dialog_init_zero {0}
|
||||
#define SpeechSettings_init_zero {_AudioProfile_MIN, _AudioFormat_MIN, _AudioSource_MIN}
|
||||
#define SpeechInitiator_init_zero {_SpeechInitiator_Type_MIN, SpeechInitiator_WakeWord_init_zero}
|
||||
#define SpeechInitiator_WakeWord_init_zero {0, 0, 0, {0, {0}}}
|
||||
#define StartSpeech_init_zero {SpeechSettings_init_zero, SpeechInitiator_init_zero, Dialog_init_zero, 0}
|
||||
#define SpeechProvider_init_zero {SpeechSettings_init_zero, Dialog_init_zero}
|
||||
#define ProvideSpeech_init_zero {Dialog_init_zero}
|
||||
#define StopSpeech_init_zero {_ErrorCode_MIN, Dialog_init_zero}
|
||||
#define EndpointSpeech_init_zero {Dialog_init_zero}
|
||||
#define NotifySpeechState_init_zero {_SpeechState_MIN}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define Dialog_id_tag 1
|
||||
#define NotifySpeechState_state_tag 1
|
||||
#define SpeechInitiator_WakeWord_start_index_in_samples_tag 1
|
||||
#define SpeechInitiator_WakeWord_end_index_in_samples_tag 2
|
||||
#define SpeechInitiator_WakeWord_near_miss_tag 3
|
||||
#define SpeechInitiator_WakeWord_metadata_tag 4
|
||||
#define SpeechSettings_audio_profile_tag 1
|
||||
#define SpeechSettings_audio_format_tag 2
|
||||
#define SpeechSettings_audio_source_tag 3
|
||||
#define EndpointSpeech_dialog_tag 1
|
||||
#define ProvideSpeech_dialog_tag 1
|
||||
#define SpeechInitiator_type_tag 1
|
||||
#define SpeechInitiator_wake_word_tag 2
|
||||
#define SpeechProvider_speech_settings_tag 1
|
||||
#define SpeechProvider_dialog_tag 2
|
||||
#define StopSpeech_error_code_tag 1
|
||||
#define StopSpeech_dialog_tag 2
|
||||
#define StartSpeech_settings_tag 1
|
||||
#define StartSpeech_initiator_tag 2
|
||||
#define StartSpeech_dialog_tag 3
|
||||
#define StartSpeech_suppressEarcon_tag 4
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
extern const pb_field_t Dialog_fields[2];
|
||||
extern const pb_field_t SpeechSettings_fields[4];
|
||||
extern const pb_field_t SpeechInitiator_fields[3];
|
||||
extern const pb_field_t SpeechInitiator_WakeWord_fields[5];
|
||||
extern const pb_field_t StartSpeech_fields[5];
|
||||
extern const pb_field_t SpeechProvider_fields[3];
|
||||
extern const pb_field_t ProvideSpeech_fields[2];
|
||||
extern const pb_field_t StopSpeech_fields[3];
|
||||
extern const pb_field_t EndpointSpeech_fields[2];
|
||||
extern const pb_field_t NotifySpeechState_fields[2];
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define Dialog_size 6
|
||||
#define SpeechSettings_size 6
|
||||
#define SpeechInitiator_size 278
|
||||
#define SpeechInitiator_WakeWord_size 273
|
||||
#define StartSpeech_size 299
|
||||
#define SpeechProvider_size 16
|
||||
#define ProvideSpeech_size 8
|
||||
#define StopSpeech_size 10
|
||||
#define EndpointSpeech_size 8
|
||||
#define NotifySpeechState_size 2
|
||||
|
||||
/* Message IDs (where set with "msgid" option) */
|
||||
#ifdef PB_MSGID
|
||||
|
||||
#define SPEECH_MESSAGES \
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
|
||||
#endif
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// state.pb.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Auto-generated (see below).
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.3.9.1 at Fri Nov 09 16:58:28 2018. */
|
||||
|
||||
#ifndef PB_STATE_PB_H_INCLUDED
|
||||
#define PB_STATE_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _GetState
|
||||
{
|
||||
uint32_t feature;
|
||||
/* @@protoc_insertion_point(struct:GetState) */
|
||||
} GetState;
|
||||
|
||||
typedef struct _State
|
||||
{
|
||||
uint32_t feature;
|
||||
pb_size_t which_value;
|
||||
union
|
||||
{
|
||||
bool boolean;
|
||||
uint32_t integer;
|
||||
} value;
|
||||
/* @@protoc_insertion_point(struct:State) */
|
||||
} State;
|
||||
|
||||
typedef struct _SetState
|
||||
{
|
||||
State state;
|
||||
/* @@protoc_insertion_point(struct:SetState) */
|
||||
} SetState;
|
||||
|
||||
typedef struct _SynchronizeState
|
||||
{
|
||||
State state;
|
||||
/* @@protoc_insertion_point(struct:SynchronizeState) */
|
||||
} SynchronizeState;
|
||||
|
||||
/* Default values for struct fields */
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define State_init_default {0, 0, {0}}
|
||||
#define GetState_init_default {0}
|
||||
#define SetState_init_default {State_init_default}
|
||||
#define SynchronizeState_init_default {State_init_default}
|
||||
#define State_init_zero {0, 0, {0}}
|
||||
#define GetState_init_zero {0}
|
||||
#define SetState_init_zero {State_init_zero}
|
||||
#define SynchronizeState_init_zero {State_init_zero}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define GetState_feature_tag 1
|
||||
#define State_boolean_tag 2
|
||||
#define State_integer_tag 3
|
||||
#define State_feature_tag 1
|
||||
#define SetState_state_tag 1
|
||||
#define SynchronizeState_state_tag 1
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
extern const pb_field_t State_fields[4];
|
||||
extern const pb_field_t GetState_fields[2];
|
||||
extern const pb_field_t SetState_fields[2];
|
||||
extern const pb_field_t SynchronizeState_fields[2];
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define State_size 12
|
||||
#define GetState_size 6
|
||||
#define SetState_size 14
|
||||
#define SynchronizeState_size 14
|
||||
|
||||
/* Message IDs (where set with "msgid" option) */
|
||||
#ifdef PB_MSGID
|
||||
|
||||
#define STATE_MESSAGES \
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
|
||||
#endif
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// system.pb.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Auto-generated (see below).
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.3.9.1 at Fri Nov 09 16:58:28 2018. */
|
||||
|
||||
#ifndef PB_SYSTEM_PB_H_INCLUDED
|
||||
#define PB_SYSTEM_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _KeepAlive
|
||||
{
|
||||
char dummy_field;
|
||||
/* @@protoc_insertion_point(struct:KeepAlive) */
|
||||
} KeepAlive;
|
||||
|
||||
typedef struct _RemoveDevice
|
||||
{
|
||||
char dummy_field;
|
||||
/* @@protoc_insertion_point(struct:RemoveDevice) */
|
||||
} RemoveDevice;
|
||||
|
||||
typedef struct _ResetConnection
|
||||
{
|
||||
uint32_t timeout;
|
||||
bool force_disconnect;
|
||||
/* @@protoc_insertion_point(struct:ResetConnection) */
|
||||
} ResetConnection;
|
||||
|
||||
typedef struct _SynchronizeSettings
|
||||
{
|
||||
uint32_t timestamp_hi;
|
||||
uint32_t timestamp_lo;
|
||||
/* @@protoc_insertion_point(struct:SynchronizeSettings) */
|
||||
} SynchronizeSettings;
|
||||
|
||||
/* Default values for struct fields */
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define ResetConnection_init_default {0, 0}
|
||||
#define SynchronizeSettings_init_default {0, 0}
|
||||
#define KeepAlive_init_default {0}
|
||||
#define RemoveDevice_init_default {0}
|
||||
#define ResetConnection_init_zero {0, 0}
|
||||
#define SynchronizeSettings_init_zero {0, 0}
|
||||
#define KeepAlive_init_zero {0}
|
||||
#define RemoveDevice_init_zero {0}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define ResetConnection_timeout_tag 1
|
||||
#define ResetConnection_force_disconnect_tag 2
|
||||
#define SynchronizeSettings_timestamp_hi_tag 1
|
||||
#define SynchronizeSettings_timestamp_lo_tag 2
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
extern const pb_field_t ResetConnection_fields[3];
|
||||
extern const pb_field_t SynchronizeSettings_fields[3];
|
||||
extern const pb_field_t KeepAlive_fields[1];
|
||||
extern const pb_field_t RemoveDevice_fields[1];
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define ResetConnection_size 8
|
||||
#define SynchronizeSettings_size 12
|
||||
#define KeepAlive_size 0
|
||||
#define RemoveDevice_size 0
|
||||
|
||||
/* Message IDs (where set with "msgid" option) */
|
||||
#ifdef PB_MSGID
|
||||
|
||||
#define SYSTEM_MESSAGES \
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
|
||||
#endif
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// transport.pb.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Auto-generated (see below).
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.3.9.1 at Fri Nov 09 16:58:28 2018. */
|
||||
|
||||
#ifndef PB_TRANSPORT_PB_H_INCLUDED
|
||||
#define PB_TRANSPORT_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
|
||||
#include "common.pb.h"
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Struct definitions */
|
||||
typedef PB_BYTES_ARRAY_T(64) ConnectionDetails_identifier_t;
|
||||
typedef struct _ConnectionDetails
|
||||
{
|
||||
ConnectionDetails_identifier_t identifier;
|
||||
/* @@protoc_insertion_point(struct:ConnectionDetails) */
|
||||
} ConnectionDetails;
|
||||
|
||||
typedef struct _SwitchTransport
|
||||
{
|
||||
Transport new_transport;
|
||||
/* @@protoc_insertion_point(struct:SwitchTransport) */
|
||||
} SwitchTransport;
|
||||
|
||||
typedef struct _UpgradeTransport
|
||||
{
|
||||
Transport transport;
|
||||
/* @@protoc_insertion_point(struct:UpgradeTransport) */
|
||||
} UpgradeTransport;
|
||||
|
||||
/* Default values for struct fields */
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define ConnectionDetails_init_default {{0, {0}}}
|
||||
#define UpgradeTransport_init_default {_Transport_MIN}
|
||||
#define SwitchTransport_init_default {_Transport_MIN}
|
||||
#define ConnectionDetails_init_zero {{0, {0}}}
|
||||
#define UpgradeTransport_init_zero {_Transport_MIN}
|
||||
#define SwitchTransport_init_zero {_Transport_MIN}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define ConnectionDetails_identifier_tag 1
|
||||
#define SwitchTransport_new_transport_tag 1
|
||||
#define UpgradeTransport_transport_tag 1
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
extern const pb_field_t ConnectionDetails_fields[2];
|
||||
extern const pb_field_t UpgradeTransport_fields[2];
|
||||
extern const pb_field_t SwitchTransport_fields[2];
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define ConnectionDetails_size 66
|
||||
#define UpgradeTransport_size 2
|
||||
#define SwitchTransport_size 2
|
||||
|
||||
/* Message IDs (where set with "msgid" option) */
|
||||
#ifdef PB_MSGID
|
||||
|
||||
#define TRANSPORT_MESSAGES \
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,124 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
// ae.api.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Functions for interfacing with the encoder library
|
||||
//!
|
||||
//! @addtogroup
|
||||
//! @ingroup
|
||||
//! @{
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifndef AE_API__H
|
||||
#define AE_API__H
|
||||
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// External Function Calls
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @brief Initialization of the library
|
||||
//!
|
||||
//! Run the initialization function before any operation with the encoder.
|
||||
//! @param option - option to select whether to include 8-byte header into output.
|
||||
//! 0 for no header.
|
||||
//! other value for with header.
|
||||
//! @return numBytes - number of bytes of the data output, including header length.
|
||||
//!
|
||||
//! @{
|
||||
//
|
||||
//*****************************************************************************
|
||||
int audio_enc_init(int option);
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @brief Encodes a frame of audio
|
||||
//!
|
||||
//! @param p_pcm_buffer - pointer to the input buffer.
|
||||
//! @param n_pcm_samples - input length in samples.
|
||||
//! @param p_encoded_buffer - pointer to the output buffer.
|
||||
//!
|
||||
//! This is the major function of the encoder, the encoder encodes a fixed length
|
||||
//! of audio (20ms) in a fixed input format (16KHz, 16bit, mono, 640 bytes in length),
|
||||
//! with a fixed output format: CBR, 32000bps output rate (8:1 compression),
|
||||
//! complexity 4.
|
||||
//! When output header is selected, each output frame will have a 8 byte header in
|
||||
//! the beginning of the output data: 4 bytes of length (fixed to 80) followed by
|
||||
//! 4 bytes of range code.
|
||||
//!
|
||||
//! @return numBytes - number of bytes of the data output, including header length.
|
||||
//!
|
||||
//! @{
|
||||
//
|
||||
//*****************************************************************************
|
||||
int audio_enc_encode_frame(short *p_pcm_buffer, int n_pcm_samples, unsigned char *p_encoded_buffer);
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @brief Get version information of the libary
|
||||
//!
|
||||
//! @return version_string - pointer to the libary version string.
|
||||
//!
|
||||
//! @{
|
||||
//
|
||||
//*****************************************************************************
|
||||
char* audio_get_lib_version(void);
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @brief Get version information of the base package
|
||||
//!
|
||||
//! @return version_string - pointer to the base package version string.
|
||||
//! version information is 7 byte long without line break
|
||||
//! @{
|
||||
//
|
||||
//*****************************************************************************
|
||||
char* audio_get_package_version(void);
|
||||
|
||||
#endif // AE_API__H
|
||||
|
||||
|
||||
BIN
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,848 @@
|
||||
/*
|
||||
*
|
||||
* Bluetooth low-complexity, subband codec (SBC) library
|
||||
*
|
||||
* Copyright (C) 2008-2010 Nokia Corporation
|
||||
* Copyright (C) 2012-2014 Intel Corporation
|
||||
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
|
||||
* Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch>
|
||||
* Copyright (C) 2005-2006 Brad Midgley <bmidgley@xmission.com>
|
||||
*
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SBC_H
|
||||
#define __SBC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
//#include <sys/types.h>
|
||||
#include <limits.h>
|
||||
|
||||
/* sampling frequency */
|
||||
#define SBC_FREQ_16000 0x00
|
||||
#define SBC_FREQ_32000 0x01
|
||||
#define SBC_FREQ_44100 0x02
|
||||
#define SBC_FREQ_48000 0x03
|
||||
|
||||
/* blocks */
|
||||
#define SBC_BLK_4 0x00
|
||||
#define SBC_BLK_8 0x01
|
||||
#define SBC_BLK_12 0x02
|
||||
#define SBC_BLK_16 0x03
|
||||
|
||||
/* channel mode */
|
||||
#define SBC_MODE_MONO 0x00
|
||||
#define SBC_MODE_DUAL_CHANNEL 0x01
|
||||
#define SBC_MODE_STEREO 0x02
|
||||
#define SBC_MODE_JOINT_STEREO 0x03
|
||||
|
||||
/* allocation method */
|
||||
#define SBC_AM_LOUDNESS 0x00
|
||||
#define SBC_AM_SNR 0x01
|
||||
|
||||
/* subbands */
|
||||
#define SBC_SB_4 0x00
|
||||
#define SBC_SB_8 0x01
|
||||
|
||||
/* data endianess */
|
||||
#define SBC_LE 0x00
|
||||
#define SBC_BE 0x01
|
||||
|
||||
#ifndef _SSIZE_T_DEFINED
|
||||
#ifdef _WIN64
|
||||
typedef __int64 ssize_t;
|
||||
#else
|
||||
typedef int ssize_t;
|
||||
#endif
|
||||
#define _SSIZE_T_DEFINED
|
||||
#endif
|
||||
#define SBC_EXPORT
|
||||
#define SBC_X_BUFFER_SIZE 328
|
||||
#define SCALE_OUT_BITS 15
|
||||
|
||||
//#define SBC_ALIGNED
|
||||
#define SBC_ALWAYS_INLINE inline
|
||||
#define SBCDEC_FIXED_EXTRA_BITS 2
|
||||
#define SBC_ALIGN_BITS 4
|
||||
#define SBC_ALIGN_MASK ((1 << (SBC_ALIGN_BITS)) - 1)
|
||||
|
||||
#define fabs(x) ((x) < 0 ? -(x) : (x))
|
||||
/* C does not provide an explicit arithmetic shift right but this will
|
||||
always be correct and every compiler *should* generate optimal code */
|
||||
#define ASR(val, bits) ((-2 >> 1 == -1) ? \
|
||||
((int32_t)(val)) >> (bits) : ((int32_t) (val)) / (1 << (bits)))
|
||||
|
||||
#define SCALE_SPROTO4_TBL 12
|
||||
#define SCALE_SPROTO8_TBL 14
|
||||
#define SCALE_NPROTO4_TBL 11
|
||||
#define SCALE_NPROTO8_TBL 11
|
||||
#define SCALE4_STAGED1_BITS 15
|
||||
#define SCALE4_STAGED2_BITS 16
|
||||
#define SCALE8_STAGED1_BITS 15
|
||||
#define SCALE8_STAGED2_BITS 16
|
||||
|
||||
typedef int32_t sbc_fixed_t;
|
||||
|
||||
#define SCALE4_STAGED1(src) ASR(src, SCALE4_STAGED1_BITS)
|
||||
#define SCALE4_STAGED2(src) ASR(src, SCALE4_STAGED2_BITS)
|
||||
#define SCALE8_STAGED1(src) ASR(src, SCALE8_STAGED1_BITS)
|
||||
#define SCALE8_STAGED2(src) ASR(src, SCALE8_STAGED2_BITS)
|
||||
|
||||
|
||||
#define MULA(a, b, res) ((a) * (b) + (res))
|
||||
#define MUL(a, b) ((a) * (b))
|
||||
#define SBC_FIXED_0(val) { val = 0; }
|
||||
|
||||
#define FIXED_A int32_t /* data type for fixed point accumulator */
|
||||
#define FIXED_T int16_t /* data type for fixed point constants */
|
||||
#define SBC_FIXED_EXTRA_BITS 0
|
||||
|
||||
#define SS4(val) ASR(val, SCALE_SPROTO4_TBL)
|
||||
#define SS8(val) ASR(val, SCALE_SPROTO8_TBL)
|
||||
#define SN4(val) ASR(val, SCALE_NPROTO4_TBL + 1 + SBCDEC_FIXED_EXTRA_BITS)
|
||||
#define SN8(val) ASR(val, SCALE_NPROTO8_TBL + 1 + SBCDEC_FIXED_EXTRA_BITS)
|
||||
|
||||
#define SBC_PROTO_FIXED4_SCALE \
|
||||
((sizeof(FIXED_T) * CHAR_BIT - 1) - SBC_FIXED_EXTRA_BITS + 1)
|
||||
#define F_PROTO4(x) (FIXED_A) ((x * 2) * \
|
||||
((FIXED_A) 1 << (sizeof(FIXED_T) * CHAR_BIT - 1)) + 0.5)
|
||||
#define F(x) F_PROTO4(x)
|
||||
static const FIXED_T _sbc_proto_fixed4[40] =
|
||||
{
|
||||
F(0.00000000E+00), F(5.36548976E-04),
|
||||
-F(1.49188357E-03), F(2.73370904E-03),
|
||||
F(3.83720193E-03), F(3.89205149E-03),
|
||||
F(1.86581691E-03), F(3.06012286E-03),
|
||||
|
||||
F(1.09137620E-02), F(2.04385087E-02),
|
||||
-F(2.88757392E-02), F(3.21939290E-02),
|
||||
F(2.58767811E-02), F(6.13245186E-03),
|
||||
-F(2.88217274E-02), F(7.76463494E-02),
|
||||
|
||||
F(1.35593274E-01), F(1.94987841E-01),
|
||||
-F(2.46636662E-01), F(2.81828203E-01),
|
||||
F(2.94315332E-01), F(2.81828203E-01),
|
||||
F(2.46636662E-01), -F(1.94987841E-01),
|
||||
|
||||
-F(1.35593274E-01), -F(7.76463494E-02),
|
||||
F(2.88217274E-02), F(6.13245186E-03),
|
||||
F(2.58767811E-02), F(3.21939290E-02),
|
||||
F(2.88757392E-02), -F(2.04385087E-02),
|
||||
|
||||
-F(1.09137620E-02), -F(3.06012286E-03),
|
||||
-F(1.86581691E-03), F(3.89205149E-03),
|
||||
F(3.83720193E-03), F(2.73370904E-03),
|
||||
F(1.49188357E-03), -F(5.36548976E-04),
|
||||
};
|
||||
#undef F
|
||||
|
||||
/*
|
||||
* To produce this cosine matrix in Octave:
|
||||
*
|
||||
* b = zeros(4, 8);
|
||||
* for i = 0:3
|
||||
* for j = 0:7 b(i+1, j+1) = cos((i + 0.5) * (j - 2) * (pi/4))
|
||||
* endfor
|
||||
* endfor;
|
||||
* printf("%.10f, ", b');
|
||||
*
|
||||
* Note: in each block of 8 numbers sign was changed for elements 2 and 7
|
||||
*
|
||||
* Change of sign for element 2 allows to replace constant 1.0 (not
|
||||
* representable in Q15 format) with -1.0 (fine with Q15).
|
||||
* Changed sign for element 7 allows to have more similar constants
|
||||
* and simplify subband filter function code.
|
||||
*/
|
||||
#define SBC_COS_TABLE_FIXED4_SCALE \
|
||||
((sizeof(FIXED_T) * CHAR_BIT - 1) + SBC_FIXED_EXTRA_BITS)
|
||||
#define F_COS4(x) (FIXED_A) ((x) * \
|
||||
((FIXED_A) 1 << (sizeof(FIXED_T) * CHAR_BIT - 1)) + 0.5)
|
||||
#define F(x) F_COS4(x)
|
||||
static const FIXED_T cos_table_fixed_4[32] =
|
||||
{
|
||||
F(0.7071067812), F(0.9238795325), -F(1.0000000000), F(0.9238795325),
|
||||
F(0.7071067812), F(0.3826834324), F(0.0000000000), F(0.3826834324),
|
||||
|
||||
-F(0.7071067812), F(0.3826834324), -F(1.0000000000), F(0.3826834324),
|
||||
-F(0.7071067812), -F(0.9238795325), -F(0.0000000000), -F(0.9238795325),
|
||||
|
||||
-F(0.7071067812), -F(0.3826834324), -F(1.0000000000), -F(0.3826834324),
|
||||
-F(0.7071067812), F(0.9238795325), F(0.0000000000), F(0.9238795325),
|
||||
|
||||
F(0.7071067812), -F(0.9238795325), -F(1.0000000000), -F(0.9238795325),
|
||||
F(0.7071067812), -F(0.3826834324), -F(0.0000000000), -F(0.3826834324),
|
||||
};
|
||||
#undef F
|
||||
|
||||
/* A2DP specification: Section 12.8 Tables
|
||||
*
|
||||
* Original values are premultiplied by 4 for better precision (that is the
|
||||
* maximum which is possible without overflows)
|
||||
*
|
||||
* Note: in each block of 16 numbers sign was changed for elements 4, 13, 14, 15
|
||||
* in order to compensate the same change applied to cos_table_fixed_8
|
||||
*/
|
||||
#define SBC_PROTO_FIXED8_SCALE \
|
||||
((sizeof(FIXED_T) * CHAR_BIT - 1) - SBC_FIXED_EXTRA_BITS + 1)
|
||||
#define F_PROTO8(x) (FIXED_A) ((x * 2) * \
|
||||
((FIXED_A) 1 << (sizeof(FIXED_T) * CHAR_BIT - 1)) + 0.5)
|
||||
#define F(x) F_PROTO8(x)
|
||||
static const FIXED_T _sbc_proto_fixed8[80] =
|
||||
{
|
||||
F(0.00000000E+00), F(1.56575398E-04),
|
||||
F(3.43256425E-04), F(5.54620202E-04),
|
||||
-F(8.23919506E-04), F(1.13992507E-03),
|
||||
F(1.47640169E-03), F(1.78371725E-03),
|
||||
F(2.01182542E-03), F(2.10371989E-03),
|
||||
F(1.99454554E-03), F(1.61656283E-03),
|
||||
F(9.02154502E-04), F(1.78805361E-04),
|
||||
F(1.64973098E-03), F(3.49717454E-03),
|
||||
|
||||
F(5.65949473E-03), F(8.02941163E-03),
|
||||
F(1.04584443E-02), F(1.27472335E-02),
|
||||
-F(1.46525263E-02), F(1.59045603E-02),
|
||||
F(1.62208471E-02), F(1.53184106E-02),
|
||||
F(1.29371806E-02), F(8.85757540E-03),
|
||||
F(2.92408442E-03), -F(4.91578024E-03),
|
||||
-F(1.46404076E-02), F(2.61098752E-02),
|
||||
F(3.90751381E-02), F(5.31873032E-02),
|
||||
|
||||
F(6.79989431E-02), F(8.29847578E-02),
|
||||
F(9.75753918E-02), F(1.11196689E-01),
|
||||
-F(1.23264548E-01), F(1.33264415E-01),
|
||||
F(1.40753505E-01), F(1.45389847E-01),
|
||||
F(1.46955068E-01), F(1.45389847E-01),
|
||||
F(1.40753505E-01), F(1.33264415E-01),
|
||||
F(1.23264548E-01), -F(1.11196689E-01),
|
||||
-F(9.75753918E-02), -F(8.29847578E-02),
|
||||
|
||||
-F(6.79989431E-02), -F(5.31873032E-02),
|
||||
-F(3.90751381E-02), -F(2.61098752E-02),
|
||||
F(1.46404076E-02), -F(4.91578024E-03),
|
||||
F(2.92408442E-03), F(8.85757540E-03),
|
||||
F(1.29371806E-02), F(1.53184106E-02),
|
||||
F(1.62208471E-02), F(1.59045603E-02),
|
||||
F(1.46525263E-02), -F(1.27472335E-02),
|
||||
-F(1.04584443E-02), -F(8.02941163E-03),
|
||||
|
||||
-F(5.65949473E-03), -F(3.49717454E-03),
|
||||
-F(1.64973098E-03), -F(1.78805361E-04),
|
||||
-F(9.02154502E-04), F(1.61656283E-03),
|
||||
F(1.99454554E-03), F(2.10371989E-03),
|
||||
F(2.01182542E-03), F(1.78371725E-03),
|
||||
F(1.47640169E-03), F(1.13992507E-03),
|
||||
F(8.23919506E-04), -F(5.54620202E-04),
|
||||
-F(3.43256425E-04), -F(1.56575398E-04),
|
||||
};
|
||||
#undef F
|
||||
|
||||
/*
|
||||
* To produce this cosine matrix in Octave:
|
||||
*
|
||||
* b = zeros(8, 16);
|
||||
* for i = 0:7
|
||||
* for j = 0:15 b(i+1, j+1) = cos((i + 0.5) * (j - 4) * (pi/8))
|
||||
* endfor endfor;
|
||||
* printf("%.10f, ", b');
|
||||
*
|
||||
* Note: in each block of 16 numbers sign was changed for elements 4, 13, 14, 15
|
||||
*
|
||||
* Change of sign for element 4 allows to replace constant 1.0 (not
|
||||
* representable in Q15 format) with -1.0 (fine with Q15).
|
||||
* Changed signs for elements 13, 14, 15 allow to have more similar constants
|
||||
* and simplify subband filter function code.
|
||||
*/
|
||||
#define SBC_COS_TABLE_FIXED8_SCALE \
|
||||
((sizeof(FIXED_T) * CHAR_BIT - 1) + SBC_FIXED_EXTRA_BITS)
|
||||
#define F_COS8(x) (FIXED_A) ((x) * \
|
||||
((FIXED_A) 1 << (sizeof(FIXED_T) * CHAR_BIT - 1)) + 0.5)
|
||||
#define F(x) F_COS8(x)
|
||||
static const FIXED_T cos_table_fixed_8[128] =
|
||||
{
|
||||
F(0.7071067812), F(0.8314696123), F(0.9238795325), F(0.9807852804),
|
||||
-F(1.0000000000), F(0.9807852804), F(0.9238795325), F(0.8314696123),
|
||||
F(0.7071067812), F(0.5555702330), F(0.3826834324), F(0.1950903220),
|
||||
F(0.0000000000), F(0.1950903220), F(0.3826834324), F(0.5555702330),
|
||||
|
||||
-F(0.7071067812), -F(0.1950903220), F(0.3826834324), F(0.8314696123),
|
||||
-F(1.0000000000), F(0.8314696123), F(0.3826834324), -F(0.1950903220),
|
||||
-F(0.7071067812), -F(0.9807852804), -F(0.9238795325), -F(0.5555702330),
|
||||
-F(0.0000000000), -F(0.5555702330), -F(0.9238795325), -F(0.9807852804),
|
||||
|
||||
-F(0.7071067812), -F(0.9807852804), -F(0.3826834324), F(0.5555702330),
|
||||
-F(1.0000000000), F(0.5555702330), -F(0.3826834324), -F(0.9807852804),
|
||||
-F(0.7071067812), F(0.1950903220), F(0.9238795325), F(0.8314696123),
|
||||
F(0.0000000000), F(0.8314696123), F(0.9238795325), F(0.1950903220),
|
||||
|
||||
F(0.7071067812), -F(0.5555702330), -F(0.9238795325), F(0.1950903220),
|
||||
-F(1.0000000000), F(0.1950903220), -F(0.9238795325), -F(0.5555702330),
|
||||
F(0.7071067812), F(0.8314696123), -F(0.3826834324), -F(0.9807852804),
|
||||
-F(0.0000000000), -F(0.9807852804), -F(0.3826834324), F(0.8314696123),
|
||||
|
||||
F(0.7071067812), F(0.5555702330), -F(0.9238795325), -F(0.1950903220),
|
||||
-F(1.0000000000), -F(0.1950903220), -F(0.9238795325), F(0.5555702330),
|
||||
F(0.7071067812), -F(0.8314696123), -F(0.3826834324), F(0.9807852804),
|
||||
F(0.0000000000), F(0.9807852804), -F(0.3826834324), -F(0.8314696123),
|
||||
|
||||
-F(0.7071067812), F(0.9807852804), -F(0.3826834324), -F(0.5555702330),
|
||||
-F(1.0000000000), -F(0.5555702330), -F(0.3826834324), F(0.9807852804),
|
||||
-F(0.7071067812), -F(0.1950903220), F(0.9238795325), -F(0.8314696123),
|
||||
-F(0.0000000000), -F(0.8314696123), F(0.9238795325), -F(0.1950903220),
|
||||
|
||||
-F(0.7071067812), F(0.1950903220), F(0.3826834324), -F(0.8314696123),
|
||||
-F(1.0000000000), -F(0.8314696123), F(0.3826834324), F(0.1950903220),
|
||||
-F(0.7071067812), F(0.9807852804), -F(0.9238795325), F(0.5555702330),
|
||||
-F(0.0000000000), F(0.5555702330), -F(0.9238795325), F(0.9807852804),
|
||||
|
||||
F(0.7071067812), -F(0.8314696123), F(0.9238795325), -F(0.9807852804),
|
||||
-F(1.0000000000), -F(0.9807852804), F(0.9238795325), -F(0.8314696123),
|
||||
F(0.7071067812), -F(0.5555702330), F(0.3826834324), -F(0.1950903220),
|
||||
-F(0.0000000000), -F(0.1950903220), F(0.3826834324), -F(0.5555702330),
|
||||
};
|
||||
#undef F
|
||||
|
||||
/*
|
||||
* Enforce 16 byte alignment for the data, which is supposed to be used
|
||||
* with SIMD optimized code.
|
||||
*/
|
||||
|
||||
#define SBC_ALIGN_BITS 4
|
||||
#define SBC_ALIGN_MASK ((1 << (SBC_ALIGN_BITS)) - 1)
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define SBC_ALIGNED __attribute__((aligned(1 << (SBC_ALIGN_BITS))))
|
||||
#else
|
||||
#define SBC_ALIGNED
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Constant tables for the use in SIMD optimized analysis filters
|
||||
* Each table consists of two parts:
|
||||
* 1. reordered "proto" table
|
||||
* 2. reordered "cos" table
|
||||
*
|
||||
* Due to non-symmetrical reordering, separate tables for "even"
|
||||
* and "odd" cases are needed
|
||||
*/
|
||||
|
||||
static const FIXED_T SBC_ALIGNED analysis_consts_fixed4_simd_even[40 + 16] =
|
||||
{
|
||||
#define C0 1.0932568993
|
||||
#define C1 1.3056875580
|
||||
#define C2 1.3056875580
|
||||
#define C3 1.6772280856
|
||||
|
||||
#define F(x) F_PROTO4(x)
|
||||
F(0.00000000E+00 * C0), F(3.83720193E-03 * C0),
|
||||
F(5.36548976E-04 * C1), F(2.73370904E-03 * C1),
|
||||
F(3.06012286E-03 * C2), F(3.89205149E-03 * C2),
|
||||
F(0.00000000E+00 * C3), -F(1.49188357E-03 * C3),
|
||||
F(1.09137620E-02 * C0), F(2.58767811E-02 * C0),
|
||||
F(2.04385087E-02 * C1), F(3.21939290E-02 * C1),
|
||||
F(7.76463494E-02 * C2), F(6.13245186E-03 * C2),
|
||||
F(0.00000000E+00 * C3), -F(2.88757392E-02 * C3),
|
||||
F(1.35593274E-01 * C0), F(2.94315332E-01 * C0),
|
||||
F(1.94987841E-01 * C1), F(2.81828203E-01 * C1),
|
||||
-F(1.94987841E-01 * C2), F(2.81828203E-01 * C2),
|
||||
F(0.00000000E+00 * C3), -F(2.46636662E-01 * C3),
|
||||
-F(1.35593274E-01 * C0), F(2.58767811E-02 * C0),
|
||||
-F(7.76463494E-02 * C1), F(6.13245186E-03 * C1),
|
||||
-F(2.04385087E-02 * C2), F(3.21939290E-02 * C2),
|
||||
F(0.00000000E+00 * C3), F(2.88217274E-02 * C3),
|
||||
-F(1.09137620E-02 * C0), F(3.83720193E-03 * C0),
|
||||
-F(3.06012286E-03 * C1), F(3.89205149E-03 * C1),
|
||||
-F(5.36548976E-04 * C2), F(2.73370904E-03 * C2),
|
||||
F(0.00000000E+00 * C3), -F(1.86581691E-03 * C3),
|
||||
#undef F
|
||||
#define F(x) F_COS4(x)
|
||||
F(0.7071067812 / C0), F(0.9238795325 / C1),
|
||||
-F(0.7071067812 / C0), F(0.3826834324 / C1),
|
||||
-F(0.7071067812 / C0), -F(0.3826834324 / C1),
|
||||
F(0.7071067812 / C0), -F(0.9238795325 / C1),
|
||||
F(0.3826834324 / C2), -F(1.0000000000 / C3),
|
||||
-F(0.9238795325 / C2), -F(1.0000000000 / C3),
|
||||
F(0.9238795325 / C2), -F(1.0000000000 / C3),
|
||||
-F(0.3826834324 / C2), -F(1.0000000000 / C3),
|
||||
#undef F
|
||||
|
||||
#undef C0
|
||||
#undef C1
|
||||
#undef C2
|
||||
#undef C3
|
||||
};
|
||||
|
||||
static const FIXED_T SBC_ALIGNED analysis_consts_fixed4_simd_odd[40 + 16] =
|
||||
{
|
||||
#define C0 1.3056875580
|
||||
#define C1 1.6772280856
|
||||
#define C2 1.0932568993
|
||||
#define C3 1.3056875580
|
||||
|
||||
#define F(x) F_PROTO4(x)
|
||||
F(2.73370904E-03 * C0), F(5.36548976E-04 * C0),
|
||||
-F(1.49188357E-03 * C1), F(0.00000000E+00 * C1),
|
||||
F(3.83720193E-03 * C2), F(1.09137620E-02 * C2),
|
||||
F(3.89205149E-03 * C3), F(3.06012286E-03 * C3),
|
||||
F(3.21939290E-02 * C0), F(2.04385087E-02 * C0),
|
||||
-F(2.88757392E-02 * C1), F(0.00000000E+00 * C1),
|
||||
F(2.58767811E-02 * C2), F(1.35593274E-01 * C2),
|
||||
F(6.13245186E-03 * C3), F(7.76463494E-02 * C3),
|
||||
F(2.81828203E-01 * C0), F(1.94987841E-01 * C0),
|
||||
-F(2.46636662E-01 * C1), F(0.00000000E+00 * C1),
|
||||
F(2.94315332E-01 * C2), -F(1.35593274E-01 * C2),
|
||||
F(2.81828203E-01 * C3), -F(1.94987841E-01 * C3),
|
||||
F(6.13245186E-03 * C0), -F(7.76463494E-02 * C0),
|
||||
F(2.88217274E-02 * C1), F(0.00000000E+00 * C1),
|
||||
F(2.58767811E-02 * C2), -F(1.09137620E-02 * C2),
|
||||
F(3.21939290E-02 * C3), -F(2.04385087E-02 * C3),
|
||||
F(3.89205149E-03 * C0), -F(3.06012286E-03 * C0),
|
||||
-F(1.86581691E-03 * C1), F(0.00000000E+00 * C1),
|
||||
F(3.83720193E-03 * C2), F(0.00000000E+00 * C2),
|
||||
F(2.73370904E-03 * C3), -F(5.36548976E-04 * C3),
|
||||
#undef F
|
||||
#define F(x) F_COS4(x)
|
||||
F(0.9238795325 / C0), -F(1.0000000000 / C1),
|
||||
F(0.3826834324 / C0), -F(1.0000000000 / C1),
|
||||
-F(0.3826834324 / C0), -F(1.0000000000 / C1),
|
||||
-F(0.9238795325 / C0), -F(1.0000000000 / C1),
|
||||
F(0.7071067812 / C2), F(0.3826834324 / C3),
|
||||
-F(0.7071067812 / C2), -F(0.9238795325 / C3),
|
||||
-F(0.7071067812 / C2), F(0.9238795325 / C3),
|
||||
F(0.7071067812 / C2), -F(0.3826834324 / C3),
|
||||
#undef F
|
||||
|
||||
#undef C0
|
||||
#undef C1
|
||||
#undef C2
|
||||
#undef C3
|
||||
};
|
||||
|
||||
static const FIXED_T SBC_ALIGNED analysis_consts_fixed8_simd_even[80 + 64] =
|
||||
{
|
||||
#define C0 2.7906148894
|
||||
#define C1 2.4270044280
|
||||
#define C2 2.8015616024
|
||||
#define C3 3.1710363741
|
||||
#define C4 2.5377944043
|
||||
#define C5 2.4270044280
|
||||
#define C6 2.8015616024
|
||||
#define C7 3.1710363741
|
||||
|
||||
#define F(x) F_PROTO8(x)
|
||||
F(0.00000000E+00 * C0), F(2.01182542E-03 * C0),
|
||||
F(1.56575398E-04 * C1), F(1.78371725E-03 * C1),
|
||||
F(3.43256425E-04 * C2), F(1.47640169E-03 * C2),
|
||||
F(5.54620202E-04 * C3), F(1.13992507E-03 * C3),
|
||||
-F(8.23919506E-04 * C4), F(0.00000000E+00 * C4),
|
||||
F(2.10371989E-03 * C5), F(3.49717454E-03 * C5),
|
||||
F(1.99454554E-03 * C6), F(1.64973098E-03 * C6),
|
||||
F(1.61656283E-03 * C7), F(1.78805361E-04 * C7),
|
||||
F(5.65949473E-03 * C0), F(1.29371806E-02 * C0),
|
||||
F(8.02941163E-03 * C1), F(1.53184106E-02 * C1),
|
||||
F(1.04584443E-02 * C2), F(1.62208471E-02 * C2),
|
||||
F(1.27472335E-02 * C3), F(1.59045603E-02 * C3),
|
||||
-F(1.46525263E-02 * C4), F(0.00000000E+00 * C4),
|
||||
F(8.85757540E-03 * C5), F(5.31873032E-02 * C5),
|
||||
F(2.92408442E-03 * C6), F(3.90751381E-02 * C6),
|
||||
-F(4.91578024E-03 * C7), F(2.61098752E-02 * C7),
|
||||
F(6.79989431E-02 * C0), F(1.46955068E-01 * C0),
|
||||
F(8.29847578E-02 * C1), F(1.45389847E-01 * C1),
|
||||
F(9.75753918E-02 * C2), F(1.40753505E-01 * C2),
|
||||
F(1.11196689E-01 * C3), F(1.33264415E-01 * C3),
|
||||
-F(1.23264548E-01 * C4), F(0.00000000E+00 * C4),
|
||||
F(1.45389847E-01 * C5), -F(8.29847578E-02 * C5),
|
||||
F(1.40753505E-01 * C6), -F(9.75753918E-02 * C6),
|
||||
F(1.33264415E-01 * C7), -F(1.11196689E-01 * C7),
|
||||
-F(6.79989431E-02 * C0), F(1.29371806E-02 * C0),
|
||||
-F(5.31873032E-02 * C1), F(8.85757540E-03 * C1),
|
||||
-F(3.90751381E-02 * C2), F(2.92408442E-03 * C2),
|
||||
-F(2.61098752E-02 * C3), -F(4.91578024E-03 * C3),
|
||||
F(1.46404076E-02 * C4), F(0.00000000E+00 * C4),
|
||||
F(1.53184106E-02 * C5), -F(8.02941163E-03 * C5),
|
||||
F(1.62208471E-02 * C6), -F(1.04584443E-02 * C6),
|
||||
F(1.59045603E-02 * C7), -F(1.27472335E-02 * C7),
|
||||
-F(5.65949473E-03 * C0), F(2.01182542E-03 * C0),
|
||||
-F(3.49717454E-03 * C1), F(2.10371989E-03 * C1),
|
||||
-F(1.64973098E-03 * C2), F(1.99454554E-03 * C2),
|
||||
-F(1.78805361E-04 * C3), F(1.61656283E-03 * C3),
|
||||
-F(9.02154502E-04 * C4), F(0.00000000E+00 * C4),
|
||||
F(1.78371725E-03 * C5), -F(1.56575398E-04 * C5),
|
||||
F(1.47640169E-03 * C6), -F(3.43256425E-04 * C6),
|
||||
F(1.13992507E-03 * C7), -F(5.54620202E-04 * C7),
|
||||
#undef F
|
||||
#define F(x) F_COS8(x)
|
||||
F(0.7071067812 / C0), F(0.8314696123 / C1),
|
||||
-F(0.7071067812 / C0), -F(0.1950903220 / C1),
|
||||
-F(0.7071067812 / C0), -F(0.9807852804 / C1),
|
||||
F(0.7071067812 / C0), -F(0.5555702330 / C1),
|
||||
F(0.7071067812 / C0), F(0.5555702330 / C1),
|
||||
-F(0.7071067812 / C0), F(0.9807852804 / C1),
|
||||
-F(0.7071067812 / C0), F(0.1950903220 / C1),
|
||||
F(0.7071067812 / C0), -F(0.8314696123 / C1),
|
||||
F(0.9238795325 / C2), F(0.9807852804 / C3),
|
||||
F(0.3826834324 / C2), F(0.8314696123 / C3),
|
||||
-F(0.3826834324 / C2), F(0.5555702330 / C3),
|
||||
-F(0.9238795325 / C2), F(0.1950903220 / C3),
|
||||
-F(0.9238795325 / C2), -F(0.1950903220 / C3),
|
||||
-F(0.3826834324 / C2), -F(0.5555702330 / C3),
|
||||
F(0.3826834324 / C2), -F(0.8314696123 / C3),
|
||||
F(0.9238795325 / C2), -F(0.9807852804 / C3),
|
||||
-F(1.0000000000 / C4), F(0.5555702330 / C5),
|
||||
-F(1.0000000000 / C4), -F(0.9807852804 / C5),
|
||||
-F(1.0000000000 / C4), F(0.1950903220 / C5),
|
||||
-F(1.0000000000 / C4), F(0.8314696123 / C5),
|
||||
-F(1.0000000000 / C4), -F(0.8314696123 / C5),
|
||||
-F(1.0000000000 / C4), -F(0.1950903220 / C5),
|
||||
-F(1.0000000000 / C4), F(0.9807852804 / C5),
|
||||
-F(1.0000000000 / C4), -F(0.5555702330 / C5),
|
||||
F(0.3826834324 / C6), F(0.1950903220 / C7),
|
||||
-F(0.9238795325 / C6), -F(0.5555702330 / C7),
|
||||
F(0.9238795325 / C6), F(0.8314696123 / C7),
|
||||
-F(0.3826834324 / C6), -F(0.9807852804 / C7),
|
||||
-F(0.3826834324 / C6), F(0.9807852804 / C7),
|
||||
F(0.9238795325 / C6), -F(0.8314696123 / C7),
|
||||
-F(0.9238795325 / C6), F(0.5555702330 / C7),
|
||||
F(0.3826834324 / C6), -F(0.1950903220 / C7),
|
||||
#undef F
|
||||
|
||||
#undef C0
|
||||
#undef C1
|
||||
#undef C2
|
||||
#undef C3
|
||||
#undef C4
|
||||
#undef C5
|
||||
#undef C6
|
||||
#undef C7
|
||||
};
|
||||
|
||||
static const FIXED_T SBC_ALIGNED analysis_consts_fixed8_simd_odd[80 + 64] =
|
||||
{
|
||||
#define C0 2.5377944043
|
||||
#define C1 2.4270044280
|
||||
#define C2 2.8015616024
|
||||
#define C3 3.1710363741
|
||||
#define C4 2.7906148894
|
||||
#define C5 2.4270044280
|
||||
#define C6 2.8015616024
|
||||
#define C7 3.1710363741
|
||||
|
||||
#define F(x) F_PROTO8(x)
|
||||
F(0.00000000E+00 * C0), -F(8.23919506E-04 * C0),
|
||||
F(1.56575398E-04 * C1), F(1.78371725E-03 * C1),
|
||||
F(3.43256425E-04 * C2), F(1.47640169E-03 * C2),
|
||||
F(5.54620202E-04 * C3), F(1.13992507E-03 * C3),
|
||||
F(2.01182542E-03 * C4), F(5.65949473E-03 * C4),
|
||||
F(2.10371989E-03 * C5), F(3.49717454E-03 * C5),
|
||||
F(1.99454554E-03 * C6), F(1.64973098E-03 * C6),
|
||||
F(1.61656283E-03 * C7), F(1.78805361E-04 * C7),
|
||||
F(0.00000000E+00 * C0), -F(1.46525263E-02 * C0),
|
||||
F(8.02941163E-03 * C1), F(1.53184106E-02 * C1),
|
||||
F(1.04584443E-02 * C2), F(1.62208471E-02 * C2),
|
||||
F(1.27472335E-02 * C3), F(1.59045603E-02 * C3),
|
||||
F(1.29371806E-02 * C4), F(6.79989431E-02 * C4),
|
||||
F(8.85757540E-03 * C5), F(5.31873032E-02 * C5),
|
||||
F(2.92408442E-03 * C6), F(3.90751381E-02 * C6),
|
||||
-F(4.91578024E-03 * C7), F(2.61098752E-02 * C7),
|
||||
F(0.00000000E+00 * C0), -F(1.23264548E-01 * C0),
|
||||
F(8.29847578E-02 * C1), F(1.45389847E-01 * C1),
|
||||
F(9.75753918E-02 * C2), F(1.40753505E-01 * C2),
|
||||
F(1.11196689E-01 * C3), F(1.33264415E-01 * C3),
|
||||
F(1.46955068E-01 * C4), -F(6.79989431E-02 * C4),
|
||||
F(1.45389847E-01 * C5), -F(8.29847578E-02 * C5),
|
||||
F(1.40753505E-01 * C6), -F(9.75753918E-02 * C6),
|
||||
F(1.33264415E-01 * C7), -F(1.11196689E-01 * C7),
|
||||
F(0.00000000E+00 * C0), F(1.46404076E-02 * C0),
|
||||
-F(5.31873032E-02 * C1), F(8.85757540E-03 * C1),
|
||||
-F(3.90751381E-02 * C2), F(2.92408442E-03 * C2),
|
||||
-F(2.61098752E-02 * C3), -F(4.91578024E-03 * C3),
|
||||
F(1.29371806E-02 * C4), -F(5.65949473E-03 * C4),
|
||||
F(1.53184106E-02 * C5), -F(8.02941163E-03 * C5),
|
||||
F(1.62208471E-02 * C6), -F(1.04584443E-02 * C6),
|
||||
F(1.59045603E-02 * C7), -F(1.27472335E-02 * C7),
|
||||
F(0.00000000E+00 * C0), -F(9.02154502E-04 * C0),
|
||||
-F(3.49717454E-03 * C1), F(2.10371989E-03 * C1),
|
||||
-F(1.64973098E-03 * C2), F(1.99454554E-03 * C2),
|
||||
-F(1.78805361E-04 * C3), F(1.61656283E-03 * C3),
|
||||
F(2.01182542E-03 * C4), F(0.00000000E+00 * C4),
|
||||
F(1.78371725E-03 * C5), -F(1.56575398E-04 * C5),
|
||||
F(1.47640169E-03 * C6), -F(3.43256425E-04 * C6),
|
||||
F(1.13992507E-03 * C7), -F(5.54620202E-04 * C7),
|
||||
#undef F
|
||||
#define F(x) F_COS8(x)
|
||||
-F(1.0000000000 / C0), F(0.8314696123 / C1),
|
||||
-F(1.0000000000 / C0), -F(0.1950903220 / C1),
|
||||
-F(1.0000000000 / C0), -F(0.9807852804 / C1),
|
||||
-F(1.0000000000 / C0), -F(0.5555702330 / C1),
|
||||
-F(1.0000000000 / C0), F(0.5555702330 / C1),
|
||||
-F(1.0000000000 / C0), F(0.9807852804 / C1),
|
||||
-F(1.0000000000 / C0), F(0.1950903220 / C1),
|
||||
-F(1.0000000000 / C0), -F(0.8314696123 / C1),
|
||||
F(0.9238795325 / C2), F(0.9807852804 / C3),
|
||||
F(0.3826834324 / C2), F(0.8314696123 / C3),
|
||||
-F(0.3826834324 / C2), F(0.5555702330 / C3),
|
||||
-F(0.9238795325 / C2), F(0.1950903220 / C3),
|
||||
-F(0.9238795325 / C2), -F(0.1950903220 / C3),
|
||||
-F(0.3826834324 / C2), -F(0.5555702330 / C3),
|
||||
F(0.3826834324 / C2), -F(0.8314696123 / C3),
|
||||
F(0.9238795325 / C2), -F(0.9807852804 / C3),
|
||||
F(0.7071067812 / C4), F(0.5555702330 / C5),
|
||||
-F(0.7071067812 / C4), -F(0.9807852804 / C5),
|
||||
-F(0.7071067812 / C4), F(0.1950903220 / C5),
|
||||
F(0.7071067812 / C4), F(0.8314696123 / C5),
|
||||
F(0.7071067812 / C4), -F(0.8314696123 / C5),
|
||||
-F(0.7071067812 / C4), -F(0.1950903220 / C5),
|
||||
-F(0.7071067812 / C4), F(0.9807852804 / C5),
|
||||
F(0.7071067812 / C4), -F(0.5555702330 / C5),
|
||||
F(0.3826834324 / C6), F(0.1950903220 / C7),
|
||||
-F(0.9238795325 / C6), -F(0.5555702330 / C7),
|
||||
F(0.9238795325 / C6), F(0.8314696123 / C7),
|
||||
-F(0.3826834324 / C6), -F(0.9807852804 / C7),
|
||||
-F(0.3826834324 / C6), F(0.9807852804 / C7),
|
||||
F(0.9238795325 / C6), -F(0.8314696123 / C7),
|
||||
-F(0.9238795325 / C6), F(0.5555702330 / C7),
|
||||
F(0.3826834324 / C6), -F(0.1950903220 / C7),
|
||||
#undef F
|
||||
|
||||
#undef C0
|
||||
#undef C1
|
||||
#undef C2
|
||||
#undef C3
|
||||
#undef C4
|
||||
#undef C5
|
||||
#undef C6
|
||||
#undef C7
|
||||
};
|
||||
|
||||
static const int32_t sbc_proto_4_40m0[] =
|
||||
{
|
||||
SS4(0x00000000), SS4(0xffa6982f), SS4(0xfba93848), SS4(0x0456c7b8),
|
||||
SS4(0x005967d1), SS4(0xfffb9ac7), SS4(0xff589157), SS4(0xf9c2a8d8),
|
||||
SS4(0x027c1434), SS4(0x0019118b), SS4(0xfff3c74c), SS4(0xff137330),
|
||||
SS4(0xf81b8d70), SS4(0x00ec1b8b), SS4(0xfff0b71a), SS4(0xffe99b00),
|
||||
SS4(0xfef84470), SS4(0xf6fb4370), SS4(0xffcdc351), SS4(0xffe01dc7)
|
||||
};
|
||||
|
||||
static const int32_t sbc_proto_4_40m1[] =
|
||||
{
|
||||
SS4(0xffe090ce), SS4(0xff2c0475), SS4(0xf694f800), SS4(0xff2c0475),
|
||||
SS4(0xffe090ce), SS4(0xffe01dc7), SS4(0xffcdc351), SS4(0xf6fb4370),
|
||||
SS4(0xfef84470), SS4(0xffe99b00), SS4(0xfff0b71a), SS4(0x00ec1b8b),
|
||||
SS4(0xf81b8d70), SS4(0xff137330), SS4(0xfff3c74c), SS4(0x0019118b),
|
||||
SS4(0x027c1434), SS4(0xf9c2a8d8), SS4(0xff589157), SS4(0xfffb9ac7)
|
||||
};
|
||||
|
||||
static const int32_t sbc_proto_8_80m0[] =
|
||||
{
|
||||
SS8(0x00000000), SS8(0xfe8d1970), SS8(0xee979f00), SS8(0x11686100),
|
||||
SS8(0x0172e690), SS8(0xfff5bd1a), SS8(0xfdf1c8d4), SS8(0xeac182c0),
|
||||
SS8(0x0d9daee0), SS8(0x00e530da), SS8(0xffe9811d), SS8(0xfd52986c),
|
||||
SS8(0xe7054ca0), SS8(0x0a00d410), SS8(0x006c1de4), SS8(0xffdba705),
|
||||
SS8(0xfcbc98e8), SS8(0xe3889d20), SS8(0x06af2308), SS8(0x000bb7db),
|
||||
SS8(0xffca00ed), SS8(0xfc3fbb68), SS8(0xe071bc00), SS8(0x03bf7948),
|
||||
SS8(0xffc4e05c), SS8(0xffb54b3b), SS8(0xfbedadc0), SS8(0xdde26200),
|
||||
SS8(0x0142291c), SS8(0xff960e94), SS8(0xff9f3e17), SS8(0xfbd8f358),
|
||||
SS8(0xdbf79400), SS8(0xff405e01), SS8(0xff7d4914), SS8(0xff8b1a31),
|
||||
SS8(0xfc1417b8), SS8(0xdac7bb40), SS8(0xfdbb828c), SS8(0xff762170)
|
||||
};
|
||||
|
||||
static const int32_t sbc_proto_8_80m1[] =
|
||||
{
|
||||
SS8(0xff7c272c), SS8(0xfcb02620), SS8(0xda612700), SS8(0xfcb02620),
|
||||
SS8(0xff7c272c), SS8(0xff762170), SS8(0xfdbb828c), SS8(0xdac7bb40),
|
||||
SS8(0xfc1417b8), SS8(0xff8b1a31), SS8(0xff7d4914), SS8(0xff405e01),
|
||||
SS8(0xdbf79400), SS8(0xfbd8f358), SS8(0xff9f3e17), SS8(0xff960e94),
|
||||
SS8(0x0142291c), SS8(0xdde26200), SS8(0xfbedadc0), SS8(0xffb54b3b),
|
||||
SS8(0xffc4e05c), SS8(0x03bf7948), SS8(0xe071bc00), SS8(0xfc3fbb68),
|
||||
SS8(0xffca00ed), SS8(0x000bb7db), SS8(0x06af2308), SS8(0xe3889d20),
|
||||
SS8(0xfcbc98e8), SS8(0xffdba705), SS8(0x006c1de4), SS8(0x0a00d410),
|
||||
SS8(0xe7054ca0), SS8(0xfd52986c), SS8(0xffe9811d), SS8(0x00e530da),
|
||||
SS8(0x0d9daee0), SS8(0xeac182c0), SS8(0xfdf1c8d4), SS8(0xfff5bd1a)
|
||||
};
|
||||
|
||||
static const int32_t synmatrix4[8][4] =
|
||||
{
|
||||
{ SN4(0x05a82798), SN4(0xfa57d868), SN4(0xfa57d868), SN4(0x05a82798) },
|
||||
{ SN4(0x030fbc54), SN4(0xf89be510), SN4(0x07641af0), SN4(0xfcf043ac) },
|
||||
{ SN4(0x00000000), SN4(0x00000000), SN4(0x00000000), SN4(0x00000000) },
|
||||
{ SN4(0xfcf043ac), SN4(0x07641af0), SN4(0xf89be510), SN4(0x030fbc54) },
|
||||
{ SN4(0xfa57d868), SN4(0x05a82798), SN4(0x05a82798), SN4(0xfa57d868) },
|
||||
{ SN4(0xf89be510), SN4(0xfcf043ac), SN4(0x030fbc54), SN4(0x07641af0) },
|
||||
{ SN4(0xf8000000), SN4(0xf8000000), SN4(0xf8000000), SN4(0xf8000000) },
|
||||
{ SN4(0xf89be510), SN4(0xfcf043ac), SN4(0x030fbc54), SN4(0x07641af0) }
|
||||
};
|
||||
|
||||
static const int32_t synmatrix8[16][8] =
|
||||
{
|
||||
{ SN8(0x05a82798), SN8(0xfa57d868), SN8(0xfa57d868), SN8(0x05a82798),
|
||||
SN8(0x05a82798), SN8(0xfa57d868), SN8(0xfa57d868), SN8(0x05a82798) },
|
||||
{ SN8(0x0471ced0), SN8(0xf8275a10), SN8(0x018f8b84), SN8(0x06a6d988),
|
||||
SN8(0xf9592678), SN8(0xfe70747c), SN8(0x07d8a5f0), SN8(0xfb8e3130) },
|
||||
{ SN8(0x030fbc54), SN8(0xf89be510), SN8(0x07641af0), SN8(0xfcf043ac),
|
||||
SN8(0xfcf043ac), SN8(0x07641af0), SN8(0xf89be510), SN8(0x030fbc54) },
|
||||
{ SN8(0x018f8b84), SN8(0xfb8e3130), SN8(0x06a6d988), SN8(0xf8275a10),
|
||||
SN8(0x07d8a5f0), SN8(0xf9592678), SN8(0x0471ced0), SN8(0xfe70747c) },
|
||||
{ SN8(0x00000000), SN8(0x00000000), SN8(0x00000000), SN8(0x00000000),
|
||||
SN8(0x00000000), SN8(0x00000000), SN8(0x00000000), SN8(0x00000000) },
|
||||
{ SN8(0xfe70747c), SN8(0x0471ced0), SN8(0xf9592678), SN8(0x07d8a5f0),
|
||||
SN8(0xf8275a10), SN8(0x06a6d988), SN8(0xfb8e3130), SN8(0x018f8b84) },
|
||||
{ SN8(0xfcf043ac), SN8(0x07641af0), SN8(0xf89be510), SN8(0x030fbc54),
|
||||
SN8(0x030fbc54), SN8(0xf89be510), SN8(0x07641af0), SN8(0xfcf043ac) },
|
||||
{ SN8(0xfb8e3130), SN8(0x07d8a5f0), SN8(0xfe70747c), SN8(0xf9592678),
|
||||
SN8(0x06a6d988), SN8(0x018f8b84), SN8(0xf8275a10), SN8(0x0471ced0) },
|
||||
{ SN8(0xfa57d868), SN8(0x05a82798), SN8(0x05a82798), SN8(0xfa57d868),
|
||||
SN8(0xfa57d868), SN8(0x05a82798), SN8(0x05a82798), SN8(0xfa57d868) },
|
||||
{ SN8(0xf9592678), SN8(0x018f8b84), SN8(0x07d8a5f0), SN8(0x0471ced0),
|
||||
SN8(0xfb8e3130), SN8(0xf8275a10), SN8(0xfe70747c), SN8(0x06a6d988) },
|
||||
{ SN8(0xf89be510), SN8(0xfcf043ac), SN8(0x030fbc54), SN8(0x07641af0),
|
||||
SN8(0x07641af0), SN8(0x030fbc54), SN8(0xfcf043ac), SN8(0xf89be510) },
|
||||
{ SN8(0xf8275a10), SN8(0xf9592678), SN8(0xfb8e3130), SN8(0xfe70747c),
|
||||
SN8(0x018f8b84), SN8(0x0471ced0), SN8(0x06a6d988), SN8(0x07d8a5f0) },
|
||||
{ SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000),
|
||||
SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000) },
|
||||
{ SN8(0xf8275a10), SN8(0xf9592678), SN8(0xfb8e3130), SN8(0xfe70747c),
|
||||
SN8(0x018f8b84), SN8(0x0471ced0), SN8(0x06a6d988), SN8(0x07d8a5f0) },
|
||||
{ SN8(0xf89be510), SN8(0xfcf043ac), SN8(0x030fbc54), SN8(0x07641af0),
|
||||
SN8(0x07641af0), SN8(0x030fbc54), SN8(0xfcf043ac), SN8(0xf89be510) },
|
||||
{ SN8(0xf9592678), SN8(0x018f8b84), SN8(0x07d8a5f0), SN8(0x0471ced0),
|
||||
SN8(0xfb8e3130), SN8(0xf8275a10), SN8(0xfe70747c), SN8(0x06a6d988) }
|
||||
};
|
||||
|
||||
struct sbc_encoder_state
|
||||
{
|
||||
int position;
|
||||
/* Number of consecutive blocks handled by the encoder */
|
||||
uint8_t increment;
|
||||
int16_t SBC_ALIGNED X[2][SBC_X_BUFFER_SIZE];
|
||||
/* Polyphase analysis filter for 4 subbands configuration,
|
||||
* it handles "increment" blocks at once */
|
||||
void (*sbc_analyze_4s)(struct sbc_encoder_state *state,
|
||||
int16_t *x, int32_t *out, int out_stride);
|
||||
/* Polyphase analysis filter for 8 subbands configuration,
|
||||
* it handles "increment" blocks at once */
|
||||
void (*sbc_analyze_8s)(struct sbc_encoder_state *state,
|
||||
int16_t *x, int32_t *out, int out_stride);
|
||||
/* Process input data (deinterleave, endian conversion, reordering),
|
||||
* depending on the number of subbands and input data byte order */
|
||||
int (*sbc_enc_process_input_4s_le)(int position,
|
||||
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
|
||||
int nsamples, int nchannels);
|
||||
int (*sbc_enc_process_input_4s_be)(int position,
|
||||
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
|
||||
int nsamples, int nchannels);
|
||||
int (*sbc_enc_process_input_8s_le)(int position,
|
||||
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
|
||||
int nsamples, int nchannels);
|
||||
int (*sbc_enc_process_input_8s_be)(int position,
|
||||
const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
|
||||
int nsamples, int nchannels);
|
||||
/* Scale factors calculation */
|
||||
void (*sbc_calc_scalefactors)(int32_t sb_sample_f[16][2][8],
|
||||
uint32_t scale_factor[2][8],
|
||||
int blocks, int channels, int subbands);
|
||||
/* Scale factors calculation with joint stereo support */
|
||||
int (*sbc_calc_scalefactors_j)(int32_t sb_sample_f[16][2][8],
|
||||
uint32_t scale_factor[2][8],
|
||||
int blocks, int subbands);
|
||||
const char *implementation_info;
|
||||
};
|
||||
|
||||
/* A2DP specification: Appendix B, page 69 */
|
||||
static const int sbc_offset4[4][4] =
|
||||
{
|
||||
{ -1, 0, 0, 0 },
|
||||
{ -2, 0, 0, 1 },
|
||||
{ -2, 0, 0, 1 },
|
||||
{ -2, 0, 0, 1 }
|
||||
};
|
||||
|
||||
/* A2DP specification: Appendix B, page 69 */
|
||||
static const int sbc_offset8[4][8] =
|
||||
{
|
||||
{ -2, 0, 0, 0, 0, 0, 0, 1 },
|
||||
{ -3, 0, 0, 0, 0, 0, 1, 2 },
|
||||
{ -4, 0, 0, 0, 0, 0, 1, 2 },
|
||||
{ -4, 0, 0, 0, 0, 0, 1, 2 }
|
||||
};
|
||||
|
||||
struct sbc_struct
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
uint8_t frequency;
|
||||
uint8_t blocks;
|
||||
uint8_t subbands;
|
||||
uint8_t mode;
|
||||
uint8_t allocation;
|
||||
uint8_t bitpool;
|
||||
uint8_t endian;
|
||||
|
||||
void *priv;
|
||||
void *priv_alloc_base;
|
||||
};
|
||||
|
||||
typedef struct sbc_struct sbc_t;
|
||||
|
||||
int sbc_init(sbc_t *sbc, unsigned long flags);
|
||||
int sbc_reinit(sbc_t *sbc, unsigned long flags);
|
||||
int sbc_init_msbc(sbc_t *sbc, unsigned long flags);
|
||||
int sbc_init_a2dp(sbc_t *sbc, unsigned long flags,
|
||||
const void *conf, size_t conf_len);
|
||||
int sbc_reinit_a2dp(sbc_t *sbc, unsigned long flags,
|
||||
const void *conf, size_t conf_len);
|
||||
|
||||
ssize_t sbc_parse(sbc_t *sbc, const void *input, size_t input_len);
|
||||
|
||||
/* Decodes ONE input block into ONE output block */
|
||||
ssize_t sbc_decode(sbc_t *sbc, const void *input, size_t input_len,
|
||||
void *output, size_t output_len, size_t *written);
|
||||
|
||||
/* Encodes ONE input block into ONE output block */
|
||||
ssize_t sbc_encode(sbc_t *sbc, const void *input, size_t input_len,
|
||||
void *output, size_t output_len, ssize_t *written);
|
||||
|
||||
/* Returns the output block size in bytes */
|
||||
size_t sbc_get_frame_length(sbc_t *sbc);
|
||||
|
||||
/* Returns the time one input/output block takes to play in msec*/
|
||||
unsigned sbc_get_frame_duration(sbc_t *sbc);
|
||||
|
||||
/* Returns the input block size in bytes */
|
||||
size_t sbc_get_codesize(sbc_t *sbc);
|
||||
|
||||
const char *sbc_get_implementation_info(sbc_t *sbc);
|
||||
void sbc_finish(sbc_t *sbc);
|
||||
void pcm_to_sbc(char *filename, char *output, int msbc);
|
||||
void sbc_to_pcm(char *filename, char *output, int msbc);
|
||||
void sbc_init_primitives(struct sbc_encoder_state *state);
|
||||
void sbc_decode_init(sbc_t *sbc, int msbc);
|
||||
ssize_t sbc_decoder_decode(sbc_t *sbc, const void *input, size_t input_len,
|
||||
void *output, size_t output_len, size_t *written);
|
||||
void sbc_decoder_uninit(sbc_t *sbc);
|
||||
void sbc_encode_init(sbc_t *sbc, int msbc);
|
||||
ssize_t sbc_encoder_encode(sbc_t *sbc, const void *input, size_t input_len,
|
||||
void *output, size_t output_len, ssize_t *written);
|
||||
void sbc_encoder_uninit(sbc_t *sbc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SBC_H */
|
||||
@@ -0,0 +1,400 @@
|
||||
// ****************************************************************************
|
||||
//
|
||||
// vole_common.c
|
||||
//! @file
|
||||
//!
|
||||
//! @brief This file provides the shared functions for the Vole service.
|
||||
//!
|
||||
//! @{
|
||||
//
|
||||
// ****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include "vole_common.h"
|
||||
#include "wsf_assert.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "bstream.h"
|
||||
#include "att_api.h"
|
||||
#include "am_util_debug.h"
|
||||
#include "crc32.h"
|
||||
#include "am_util.h"
|
||||
|
||||
void
|
||||
VoleResetPkt(volePacket_t *pkt)
|
||||
{
|
||||
// pkt->offset = 0;
|
||||
// pkt->header.pktType = VOLE_PKT_TYPE_UNKNOWN;
|
||||
// pkt->len = 0;
|
||||
}
|
||||
|
||||
eVoleStatus_t
|
||||
VoleReceivePkt(voleCb_t *voleCb, volePacket_t *pkt, uint16_t len, uint8_t *pValue)
|
||||
{
|
||||
uint8_t dataIdx = 0;
|
||||
uint32_t calDataCrc = 0;
|
||||
uint16_t header = 0;
|
||||
|
||||
if (pkt->offset == 0 && len < VOLE_PREFIX_SIZE_IN_PKT)
|
||||
{
|
||||
APP_TRACE_INFO0("Invalid packet!!!");
|
||||
VoleSendReply(voleCb, VOLE_STATUS_INVALID_PKT_LENGTH, NULL, 0);
|
||||
return VOLE_STATUS_INVALID_PKT_LENGTH;
|
||||
}
|
||||
|
||||
// new packet
|
||||
if (pkt->offset == 0)
|
||||
{
|
||||
BYTES_TO_UINT16(pkt->len, pValue);
|
||||
BYTES_TO_UINT16(header, &pValue[2]);
|
||||
pkt->header.pktType = (header & PACKET_TYPE_BIT_MASK) >> PACKET_TYPE_BIT_OFFSET;
|
||||
pkt->header.pktSn = (header & PACKET_SN_BIT_MASK) >> PACKET_SN_BIT_OFFSET;
|
||||
pkt->header.encrypted = (header & PACKET_ENCRYPTION_BIT_MASK) >> PACKET_ENCRYPTION_BIT_OFFSET;
|
||||
pkt->header.ackEnabled = (header & PACKET_ACK_BIT_MASK) >> PACKET_ACK_BIT_OFFSET;
|
||||
dataIdx = VOLE_PREFIX_SIZE_IN_PKT;
|
||||
if (pkt->header.pktType == VOLE_PKT_TYPE_DATA)
|
||||
{
|
||||
voleCb->rxState = VOLE_STATE_GETTING_DATA;
|
||||
}
|
||||
#ifdef VOLE_DEBUG_ON
|
||||
APP_TRACE_INFO1("pkt len = 0x%x", pkt->len);
|
||||
APP_TRACE_INFO1("pkt header = 0x%x", header);
|
||||
#endif
|
||||
APP_TRACE_INFO2("type = %d, sn = %d", pkt->header.pktType, pkt->header.pktSn);
|
||||
APP_TRACE_INFO2("enc = %d, ackEnabled = %d", pkt->header.encrypted, pkt->header.ackEnabled);
|
||||
}
|
||||
|
||||
// make sure we have enough space for new data
|
||||
if (pkt->offset + len - dataIdx > VOLE_PACKET_SIZE)
|
||||
{
|
||||
APP_TRACE_INFO0("not enough buffer size!!!");
|
||||
if (pkt->header.pktType == VOLE_PKT_TYPE_DATA)
|
||||
{
|
||||
voleCb->rxState = VOLE_STATE_RX_IDLE;
|
||||
}
|
||||
// reset pkt
|
||||
VoleResetPkt(pkt);
|
||||
VoleSendReply(voleCb, VOLE_STATUS_INSUFFICIENT_BUFFER, NULL, 0);
|
||||
return VOLE_STATUS_INSUFFICIENT_BUFFER;
|
||||
}
|
||||
|
||||
// copy new data into buffer and also save crc into it if it's the last frame in a packet
|
||||
// 4 bytes crc is included in pkt length
|
||||
memcpy(pkt->data + pkt->offset, pValue + dataIdx, len - dataIdx);
|
||||
pkt->offset += (len - dataIdx);
|
||||
|
||||
// whole packet received
|
||||
if (pkt->offset >= pkt->len)
|
||||
{
|
||||
uint32_t peerCrc = 0;
|
||||
//
|
||||
// check CRC
|
||||
//
|
||||
BYTES_TO_UINT32(peerCrc, pkt->data + pkt->len - VOLE_CRC_SIZE_IN_PKT);
|
||||
calDataCrc = CalcCrc32(0xFFFFFFFFU, pkt->len - VOLE_CRC_SIZE_IN_PKT, pkt->data);
|
||||
#ifdef VOLE_DEBUG_ON
|
||||
APP_TRACE_INFO1("calDataCrc = 0x%x ", calDataCrc);
|
||||
APP_TRACE_INFO1("peerCrc = 0x%x", peerCrc);
|
||||
APP_TRACE_INFO1("len: %d", pkt->len);
|
||||
#endif
|
||||
|
||||
if (peerCrc != calDataCrc)
|
||||
{
|
||||
APP_TRACE_INFO0("crc error\n");
|
||||
|
||||
if (pkt->header.pktType == VOLE_PKT_TYPE_DATA)
|
||||
{
|
||||
voleCb->rxState = VOLE_STATE_RX_IDLE;
|
||||
}
|
||||
// reset pkt
|
||||
VoleResetPkt(pkt);
|
||||
|
||||
VoleSendReply(voleCb, VOLE_STATUS_CRC_ERROR, NULL, 0);
|
||||
|
||||
return VOLE_STATUS_CRC_ERROR;
|
||||
}
|
||||
|
||||
return VOLE_STATUS_RECEIVE_DONE;
|
||||
}
|
||||
|
||||
return VOLE_STATUS_RECEIVE_CONTINUE;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Vole packet handler
|
||||
//
|
||||
//*****************************************************************************
|
||||
void
|
||||
VolePacketHandler(voleCb_t *voleCb, eVolePktType_t type, uint16_t len, uint8_t *buf)
|
||||
{
|
||||
// APP_TRACE_INFO2("received packet type = %d, len = %d\n", type, len);
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case VOLE_PKT_TYPE_DATA:
|
||||
//
|
||||
// data package recevied
|
||||
//
|
||||
// record packet serial number
|
||||
voleCb->lastRxPktSn = voleCb->rxPkt.header.pktSn;
|
||||
VoleSendReply(voleCb, VOLE_STATUS_SUCCESS, NULL, 0);
|
||||
if (voleCb->recvCback)
|
||||
{
|
||||
voleCb->recvCback(buf, len);
|
||||
}
|
||||
|
||||
voleCb->rxState = VOLE_STATE_RX_IDLE;
|
||||
VoleResetPkt(&voleCb->rxPkt);
|
||||
break;
|
||||
|
||||
case VOLE_PKT_TYPE_ACK:
|
||||
{
|
||||
eVoleStatus_t status = (eVoleStatus_t)buf[0];
|
||||
// stop tx timeout timer
|
||||
WsfTimerStop(&voleCb->timeoutTimer);
|
||||
|
||||
if (voleCb->txState != VOLE_STATE_TX_IDLE)
|
||||
{
|
||||
// APP_TRACE_INFO1("set txState back to idle, state = %d\n", voleCb->txState);
|
||||
voleCb->txState = VOLE_STATE_TX_IDLE;
|
||||
}
|
||||
|
||||
if (status == VOLE_STATUS_CRC_ERROR || status == VOLE_STATUS_RESEND_REPLY)
|
||||
{
|
||||
// resend packet
|
||||
VoleSendPacketHandler(voleCb);
|
||||
}
|
||||
else
|
||||
{
|
||||
// increase packet serial number if send successfully
|
||||
if (status == VOLE_STATUS_SUCCESS)
|
||||
{
|
||||
voleCb->txPktSn++;
|
||||
if (voleCb->txPktSn == 16)
|
||||
{
|
||||
voleCb->txPktSn = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// packet transfer successful or other error
|
||||
// reset packet
|
||||
VoleResetPkt(&voleCb->txPkt);
|
||||
|
||||
// notify application layer
|
||||
if (voleCb->transCback)
|
||||
{
|
||||
voleCb->transCback(status);
|
||||
}
|
||||
}
|
||||
VoleResetPkt(&voleCb->ackPkt);
|
||||
}
|
||||
break;
|
||||
|
||||
case VOLE_PKT_TYPE_CONTROL:
|
||||
{
|
||||
eVoleControl_t control = (eVoleControl_t)buf[0];
|
||||
uint8_t resendPktSn = buf[1];
|
||||
if (control == VOLE_CONTROL_RESEND_REQ)
|
||||
{
|
||||
APP_TRACE_INFO2("resendPktSn = %d, lastRxPktSn = %d", resendPktSn, voleCb->lastRxPktSn);
|
||||
voleCb->rxState = VOLE_STATE_RX_IDLE;
|
||||
VoleResetPkt(&voleCb->rxPkt);
|
||||
if (resendPktSn > voleCb->lastRxPktSn)
|
||||
{
|
||||
VoleSendReply(voleCb, VOLE_STATUS_RESEND_REPLY, NULL, 0);
|
||||
}
|
||||
else if (resendPktSn == voleCb->lastRxPktSn)
|
||||
{
|
||||
VoleSendReply(voleCb, VOLE_STATUS_SUCCESS, NULL, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
APP_TRACE_WARN2("resendPktSn = %d, lastRxPktSn = %d", resendPktSn, voleCb->lastRxPktSn);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
APP_TRACE_WARN1("unexpected contrl = %d\n", control);
|
||||
}
|
||||
VoleResetPkt(&voleCb->ackPkt);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VoleBuildPkt(voleCb_t *voleCb, eVolePktType_t type, bool_t encrypted, bool_t enableACK, uint8_t *buf, uint16_t len)
|
||||
{
|
||||
uint16_t header = 0;
|
||||
uint32_t calDataCrc;
|
||||
volePacket_t *pkt;
|
||||
|
||||
if (type == VOLE_PKT_TYPE_DATA)
|
||||
{
|
||||
pkt = &voleCb->txPkt;
|
||||
header = voleCb->txPktSn << PACKET_SN_BIT_OFFSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
pkt = &voleCb->ackPkt;
|
||||
}
|
||||
|
||||
//
|
||||
// Prepare header frame to be sent first
|
||||
//
|
||||
// length
|
||||
pkt->len = len + VOLE_PREFIX_SIZE_IN_PKT + VOLE_CRC_SIZE_IN_PKT;
|
||||
pkt->data[0] = (len + VOLE_CRC_SIZE_IN_PKT) & 0xff;
|
||||
pkt->data[1] = ((len + VOLE_CRC_SIZE_IN_PKT) >> 8) & 0xff;
|
||||
|
||||
// header
|
||||
header = header | (type << PACKET_TYPE_BIT_OFFSET);
|
||||
if (encrypted)
|
||||
{
|
||||
header = header | (1 << PACKET_ENCRYPTION_BIT_OFFSET);
|
||||
}
|
||||
if (enableACK)
|
||||
{
|
||||
header = header | (1 << PACKET_ACK_BIT_OFFSET);
|
||||
}
|
||||
pkt->data[2] = (header & 0xff);
|
||||
pkt->data[3] = (header >> 8);
|
||||
|
||||
// copy data
|
||||
memcpy(&(pkt->data[VOLE_PREFIX_SIZE_IN_PKT]), buf, len);
|
||||
calDataCrc = CalcCrc32(0xFFFFFFFFU, len, buf);
|
||||
|
||||
// add checksum
|
||||
pkt->data[VOLE_PREFIX_SIZE_IN_PKT + len] = (calDataCrc & 0xff);
|
||||
pkt->data[VOLE_PREFIX_SIZE_IN_PKT + len + 1] = ((calDataCrc >> 8) & 0xff);
|
||||
pkt->data[VOLE_PREFIX_SIZE_IN_PKT + len + 2] = ((calDataCrc >> 16) & 0xff);
|
||||
pkt->data[VOLE_PREFIX_SIZE_IN_PKT + len + 3] = ((calDataCrc >> 24) & 0xff);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Send Reply to Sender
|
||||
//
|
||||
//*****************************************************************************
|
||||
void
|
||||
VoleSendReply(voleCb_t *voleCb, eVoleStatus_t status, uint8_t *data, uint16_t len)
|
||||
{
|
||||
uint8_t buf[ATT_DEFAULT_PAYLOAD_LEN] = {0};
|
||||
eVoleStatus_t st;
|
||||
|
||||
WSF_ASSERT(len < ATT_DEFAULT_PAYLOAD_LEN);
|
||||
|
||||
buf[0] = status;
|
||||
if (len > 0)
|
||||
{
|
||||
memcpy(buf + 1, data, len);
|
||||
}
|
||||
st = voleCb->ack_sender_func(VOLE_PKT_TYPE_ACK, false, false, buf, len + 1);
|
||||
if (st != VOLE_STATUS_SUCCESS)
|
||||
{
|
||||
APP_TRACE_WARN1("VoleSendReply status = %d\n", status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Send control message to Receiver
|
||||
//
|
||||
//*****************************************************************************
|
||||
void
|
||||
VoleSendControl(voleCb_t *voleCb, eVoleControl_t control, uint8_t *data, uint16_t len)
|
||||
{
|
||||
uint8_t buf[ATT_DEFAULT_PAYLOAD_LEN] = {0};
|
||||
eVoleStatus_t st;
|
||||
|
||||
WSF_ASSERT(len < ATT_DEFAULT_PAYLOAD_LEN);
|
||||
|
||||
buf[0] = control;
|
||||
if (len > 0)
|
||||
{
|
||||
memcpy(buf + 1, data, len);
|
||||
}
|
||||
st = voleCb->ack_sender_func(VOLE_PKT_TYPE_CONTROL, false, false, buf, len + 1);
|
||||
if (st != VOLE_STATUS_SUCCESS)
|
||||
{
|
||||
APP_TRACE_WARN1("VoleSendControl status = %d\n", st);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VoleSendPacketHandler(voleCb_t *voleCb)
|
||||
{
|
||||
uint16_t transferSize = 0;
|
||||
uint16_t remainingBytes = 0;
|
||||
volePacket_t *txPkt = &voleCb->txPkt;
|
||||
|
||||
if ( voleCb->txState == VOLE_STATE_TX_IDLE )
|
||||
{
|
||||
txPkt->offset = 0;
|
||||
voleCb->txState = VOLE_STATE_SENDING;
|
||||
}
|
||||
|
||||
if ( txPkt->offset >= txPkt->len )
|
||||
{
|
||||
// done sent packet
|
||||
voleCb->txState = VOLE_STATE_WAITING_ACK;
|
||||
// start tx timeout timer
|
||||
WsfTimerStartMs(&voleCb->timeoutTimer, voleCb->txTimeoutMs);
|
||||
}
|
||||
else
|
||||
{
|
||||
remainingBytes = txPkt->len - txPkt->offset;
|
||||
transferSize = ((voleCb->attMtuSize - 3) > remainingBytes)
|
||||
? remainingBytes
|
||||
: (voleCb->attMtuSize - 3);
|
||||
// send packet
|
||||
APP_TRACE_INFO1("VoleSendPacketHandler, send len:%d", transferSize);
|
||||
voleCb->data_sender_func(&txPkt->data[txPkt->offset], transferSize);
|
||||
txPkt->offset += transferSize;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
// ****************************************************************************
|
||||
//
|
||||
// vole_common.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief This file provides the shared functions for the Vole service.
|
||||
//!
|
||||
//! @{
|
||||
//
|
||||
// ****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifndef VOLE_COMMON_H
|
||||
#define VOLE_COMMON_H
|
||||
|
||||
#include "wsf_types.h"
|
||||
#include "wsf_timer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Macro definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
#define VOLE_MAX_PAYLOAD_SIZE 10//2048//512
|
||||
#define VOLE_PACKET_SIZE (VOLE_MAX_PAYLOAD_SIZE + VOLE_PREFIX_SIZE_IN_PKT + VOLE_CRC_SIZE_IN_PKT) // Bytes
|
||||
#define VOLE_LENGTH_SIZE_IN_PKT 2
|
||||
#define VOLE_HEADER_SIZE_IN_PKT 2
|
||||
#define VOLE_CRC_SIZE_IN_PKT 4
|
||||
#define VOLE_PREFIX_SIZE_IN_PKT VOLE_LENGTH_SIZE_IN_PKT + VOLE_HEADER_SIZE_IN_PKT
|
||||
|
||||
#define PACKET_TYPE_BIT_OFFSET 12
|
||||
#define PACKET_TYPE_BIT_MASK (0xf << PACKET_TYPE_BIT_OFFSET)
|
||||
#define PACKET_SN_BIT_OFFSET 8
|
||||
#define PACKET_SN_BIT_MASK (0xf << PACKET_SN_BIT_OFFSET)
|
||||
#define PACKET_ENCRYPTION_BIT_OFFSET 7
|
||||
#define PACKET_ENCRYPTION_BIT_MASK (0x1 << PACKET_ENCRYPTION_BIT_OFFSET)
|
||||
#define PACKET_ACK_BIT_OFFSET 6
|
||||
#define PACKET_ACK_BIT_MASK (0x1 << PACKET_ACK_BIT_OFFSET)
|
||||
|
||||
#define TX_TIMEOUT_DEFAULT 1000
|
||||
|
||||
#define MANUFACT_ADV 0x1234
|
||||
#define AUD_HEADER_LEN 44
|
||||
|
||||
|
||||
struct au_header
|
||||
{
|
||||
uint32_t magic; /* '.snd' */
|
||||
uint32_t hdr_size; /* size of header (min 24) */
|
||||
uint32_t data_size; /* size of data */
|
||||
uint32_t encoding; /* see to AU_FMT_XXXX */
|
||||
uint32_t sample_rate; /* sample rate */
|
||||
uint32_t channels; /* number of channels (voices) */
|
||||
};
|
||||
|
||||
typedef enum codecType
|
||||
{
|
||||
MSBC_CODEC_IN_USE = 0,
|
||||
OPUS_CODEC_IN_USE = 1,
|
||||
|
||||
VOLE_CODEC_TYPE_INVALID = 0xFF
|
||||
}eVoleCodecType;
|
||||
|
||||
//
|
||||
// Vole states
|
||||
//
|
||||
typedef enum eVoleState
|
||||
{
|
||||
VOLE_STATE_INIT,
|
||||
VOLE_STATE_TX_IDLE,
|
||||
VOLE_STATE_RX_IDLE,
|
||||
VOLE_STATE_SENDING,
|
||||
VOLE_STATE_GETTING_DATA,
|
||||
VOLE_STATE_WAITING_ACK,
|
||||
VOLE_STATE_MAX
|
||||
}eVoleState_t;
|
||||
|
||||
//
|
||||
// Vole packet type
|
||||
//
|
||||
typedef enum eVolePktType
|
||||
{
|
||||
VOLE_PKT_TYPE_UNKNOWN,
|
||||
VOLE_PKT_TYPE_DATA,
|
||||
VOLE_PKT_TYPE_ACK,
|
||||
VOLE_PKT_TYPE_CONTROL,
|
||||
VOLE_PKT_TYPE_MAX
|
||||
}eVolePktType_t;
|
||||
|
||||
typedef enum eVoleControl
|
||||
{
|
||||
VOLE_CONTROL_RESEND_REQ,
|
||||
VOLE_CONTROL_MAX
|
||||
}eVoleControl_t;
|
||||
|
||||
//
|
||||
// Vole status
|
||||
//
|
||||
typedef enum eVoleStatus
|
||||
{
|
||||
VOLE_STATUS_SUCCESS,
|
||||
VOLE_STATUS_CRC_ERROR,
|
||||
VOLE_STATUS_INVALID_METADATA_INFO,
|
||||
VOLE_STATUS_INVALID_PKT_LENGTH,
|
||||
VOLE_STATUS_INSUFFICIENT_BUFFER,
|
||||
VOLE_STATUS_UNKNOWN_ERROR,
|
||||
VOLE_STATUS_BUSY,
|
||||
VOLE_STATUS_TX_NOT_READY, // no connection or tx busy
|
||||
VOLE_STATUS_RESEND_REPLY,
|
||||
VOLE_STATUS_RECEIVE_CONTINUE,
|
||||
VOLE_STATUS_RECEIVE_DONE,
|
||||
VOLE_STATUS_MAX
|
||||
}eVoleStatus_t;
|
||||
|
||||
//
|
||||
// packet prefix structure
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
uint8_t pktType : 4;
|
||||
uint8_t pktSn : 4;
|
||||
uint8_t encrypted : 1;
|
||||
uint32_t ackEnabled : 1;
|
||||
uint32_t reserved : 6; // Reserved for future usage
|
||||
}
|
||||
volePktHeader_t;
|
||||
|
||||
//
|
||||
// packet
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
uint32_t offset;
|
||||
uint32_t len; // data plus checksum
|
||||
volePktHeader_t header;
|
||||
uint8_t *data;
|
||||
}
|
||||
volePacket_t;
|
||||
|
||||
/*! Application data reception callback */
|
||||
typedef void (*voleRecvCback_t)(uint8_t *buf, uint16_t len);
|
||||
|
||||
/*! Application data transmission result callback */
|
||||
typedef void (*voleTransCback_t)(eVoleStatus_t status);
|
||||
|
||||
typedef void (*vole_reply_func_t)(eVoleStatus_t status, uint8_t *data, uint16_t len);
|
||||
|
||||
typedef void (*vole_packet_handler_func_t)(eVolePktType_t type, uint16_t len, uint8_t *buf);
|
||||
|
||||
typedef eVoleStatus_t (*vole_ack_sender_func_t)(eVolePktType_t type, bool_t encrypted, bool_t enableACK, uint8_t *buf, uint16_t len);
|
||||
|
||||
typedef void (*vole_data_sender_func_t)(uint8_t *buf, uint16_t len);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
eVoleState_t txState;
|
||||
eVoleState_t rxState;
|
||||
volePacket_t rxPkt;
|
||||
volePacket_t txPkt;
|
||||
volePacket_t ackPkt;
|
||||
uint8_t txPktSn; // data packet serial number for Tx
|
||||
uint8_t lastRxPktSn; // last received data packet serial number
|
||||
uint16_t attMtuSize;
|
||||
// int total_tx_len;
|
||||
wsfTimer_t timeoutTimer; // timeout timer after DTP update done
|
||||
wsfTimerTicks_t txTimeoutMs;
|
||||
voleRecvCback_t recvCback; // application callback for data reception
|
||||
voleTransCback_t transCback; // application callback for tx complete status
|
||||
vole_data_sender_func_t data_sender_func;
|
||||
vole_ack_sender_func_t ack_sender_func;
|
||||
}
|
||||
voleCb_t;
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// function definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
void
|
||||
VoleBuildPkt(voleCb_t *voleCb, eVolePktType_t type, bool_t encrypted, bool_t enableACK, uint8_t *buf, uint16_t len);
|
||||
|
||||
eVoleStatus_t
|
||||
VoleReceivePkt(voleCb_t *voleCb, volePacket_t *pkt, uint16_t len, uint8_t *pValue);
|
||||
|
||||
void
|
||||
VoleSendReply(voleCb_t *voleCb, eVoleStatus_t status, uint8_t *data, uint16_t len);
|
||||
|
||||
void
|
||||
VoleSendControl(voleCb_t *voleCb, eVoleControl_t control, uint8_t *data, uint16_t len);
|
||||
|
||||
void
|
||||
VoleSendPacketHandler(voleCb_t *voleCb);
|
||||
|
||||
void
|
||||
VolePacketHandler(voleCb_t *voleCb, eVolePktType_t type, uint16_t len, uint8_t *buf);
|
||||
|
||||
void
|
||||
VoleResetPkt(volePacket_t *pkt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // VOLE_COMMON_H
|
||||
@@ -0,0 +1,253 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file svc_amdtp.c
|
||||
//!
|
||||
//! @brief AM data transfer protocol service implementation
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
#include "wsf_types.h"
|
||||
#include "att_api.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "bstream.h"
|
||||
#include "svc_ch.h"
|
||||
#include "svc_amdtp.h"
|
||||
#include "svc_cfg.h"
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Macro definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
//#define SOME_MACRO 42 //!< This is the answer
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Global Variables
|
||||
//
|
||||
//*****************************************************************************
|
||||
//uint32_t g_ui32Stuff;
|
||||
|
||||
/**************************************************************************************************
|
||||
Static Variables
|
||||
**************************************************************************************************/
|
||||
/* UUIDs */
|
||||
static const uint8_t svcRxUuid[] = {ATT_UUID_AMDTP_RX};
|
||||
static const uint8_t svcTxUuid[] = {ATT_UUID_AMDTP_TX};
|
||||
static const uint8_t svcAckUuid[] = {ATT_UUID_AMDTP_ACK};
|
||||
|
||||
/**************************************************************************************************
|
||||
Service variables
|
||||
**************************************************************************************************/
|
||||
|
||||
/* AMDTP service declaration */
|
||||
static const uint8_t amdtpSvc[] = {ATT_UUID_AMDTP_SERVICE};
|
||||
static const uint16_t amdtpLenSvc = sizeof(amdtpSvc);
|
||||
|
||||
/* AMDTP RX characteristic */
|
||||
static const uint8_t amdtpRxCh[] = {ATT_PROP_WRITE_NO_RSP, UINT16_TO_BYTES(AMDTPS_RX_HDL), ATT_UUID_AMDTP_RX};
|
||||
static const uint16_t amdtpLenRxCh = sizeof(amdtpRxCh);
|
||||
|
||||
/* AMDTP TX characteristic */
|
||||
static const uint8_t amdtpTxCh[] = {ATT_PROP_NOTIFY, UINT16_TO_BYTES(AMDTPS_TX_HDL), ATT_UUID_AMDTP_TX};
|
||||
static const uint16_t amdtpLenTxCh = sizeof(amdtpTxCh);
|
||||
|
||||
/* AMDTP RX ack characteristic */
|
||||
static const uint8_t amdtpAckCh[] = {(ATT_PROP_WRITE_NO_RSP | ATT_PROP_NOTIFY), UINT16_TO_BYTES(AMDTPS_ACK_HDL), ATT_UUID_AMDTP_ACK};
|
||||
static const uint16_t amdtpLenAckCh = sizeof(amdtpAckCh);
|
||||
|
||||
/* AMDTP RX data */
|
||||
/* Note these are dummy values */
|
||||
static const uint8_t amdtpRx[] = {0};
|
||||
static const uint16_t amdtpLenRx = sizeof(amdtpRx);
|
||||
|
||||
/* AMDTP TX data */
|
||||
/* Note these are dummy values */
|
||||
static const uint8_t amdtpTx[] = {0};
|
||||
static const uint16_t amdtpLenTx = sizeof(amdtpTx);
|
||||
|
||||
/* Proprietary data client characteristic configuration */
|
||||
static uint8_t amdtpTxChCcc[] = {UINT16_TO_BYTES(0x0000)};
|
||||
static const uint16_t amdtpLenTxChCcc = sizeof(amdtpTxChCcc);
|
||||
|
||||
/* AMDTP RX ack data */
|
||||
/* Note these are dummy values */
|
||||
static const uint8_t amdtpAck[] = {0};
|
||||
static const uint16_t amdtpLenAck = sizeof(amdtpAck);
|
||||
|
||||
/* Proprietary data client characteristic configuration */
|
||||
static uint8_t amdtpAckChCcc[] = {UINT16_TO_BYTES(0x0000)};
|
||||
static const uint16_t amdtpLenAckChCcc = sizeof(amdtpAckChCcc);
|
||||
|
||||
|
||||
/* Attribute list for AMDTP group */
|
||||
static const attsAttr_t amdtpList[] =
|
||||
{
|
||||
{
|
||||
attPrimSvcUuid,
|
||||
(uint8_t *) amdtpSvc,
|
||||
(uint16_t *) &amdtpLenSvc,
|
||||
sizeof(amdtpSvc),
|
||||
0,
|
||||
ATTS_PERMIT_READ
|
||||
},
|
||||
{
|
||||
attChUuid,
|
||||
(uint8_t *) amdtpRxCh,
|
||||
(uint16_t *) &amdtpLenRxCh,
|
||||
sizeof(amdtpRxCh),
|
||||
0,
|
||||
ATTS_PERMIT_READ
|
||||
},
|
||||
{
|
||||
svcRxUuid,
|
||||
(uint8_t *) amdtpRx,
|
||||
(uint16_t *) &amdtpLenRx,
|
||||
ATT_VALUE_MAX_LEN,
|
||||
(ATTS_SET_UUID_128 | ATTS_SET_VARIABLE_LEN | ATTS_SET_WRITE_CBACK),
|
||||
ATTS_PERMIT_WRITE
|
||||
},
|
||||
{
|
||||
attChUuid,
|
||||
(uint8_t *) amdtpTxCh,
|
||||
(uint16_t *) &amdtpLenTxCh,
|
||||
sizeof(amdtpTxCh),
|
||||
0,
|
||||
ATTS_PERMIT_READ
|
||||
},
|
||||
{
|
||||
svcTxUuid,
|
||||
(uint8_t *) amdtpTx,
|
||||
(uint16_t *) &amdtpLenTx,
|
||||
sizeof(amdtpTx), //ATT_VALUE_MAX_LEN,
|
||||
0, //(ATTS_SET_UUID_128 | ATTS_SET_VARIABLE_LEN),
|
||||
0, //ATTS_PERMIT_READ
|
||||
},
|
||||
{
|
||||
attCliChCfgUuid,
|
||||
(uint8_t *) amdtpTxChCcc,
|
||||
(uint16_t *) &amdtpLenTxChCcc,
|
||||
sizeof(amdtpTxChCcc),
|
||||
ATTS_SET_CCC,
|
||||
(ATTS_PERMIT_READ | ATTS_PERMIT_WRITE)
|
||||
},
|
||||
{
|
||||
attChUuid,
|
||||
(uint8_t *) amdtpAckCh,
|
||||
(uint16_t *) &amdtpLenAckCh,
|
||||
sizeof(amdtpAckCh),
|
||||
0,
|
||||
ATTS_PERMIT_READ
|
||||
},
|
||||
{
|
||||
svcAckUuid,
|
||||
(uint8_t *) amdtpAck,
|
||||
(uint16_t *) &amdtpLenAck,
|
||||
ATT_VALUE_MAX_LEN,
|
||||
(ATTS_SET_UUID_128 | ATTS_SET_VARIABLE_LEN | ATTS_SET_WRITE_CBACK),
|
||||
ATTS_PERMIT_WRITE,
|
||||
},
|
||||
{
|
||||
attCliChCfgUuid,
|
||||
(uint8_t *) amdtpAckChCcc,
|
||||
(uint16_t *) &amdtpLenAckChCcc,
|
||||
sizeof(amdtpAckChCcc),
|
||||
ATTS_SET_CCC,
|
||||
(ATTS_PERMIT_READ | ATTS_PERMIT_WRITE)
|
||||
}
|
||||
};
|
||||
|
||||
/* AMDTP group structure */
|
||||
static attsGroup_t svcAmdtpGroup =
|
||||
{
|
||||
NULL,
|
||||
(attsAttr_t *) amdtpList,
|
||||
NULL,
|
||||
NULL,
|
||||
AMDTPS_START_HDL,
|
||||
AMDTPS_END_HDL
|
||||
};
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn SvcAmdtpsAddGroup
|
||||
*
|
||||
* \brief Add the services to the attribute server.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SvcAmdtpsAddGroup(void)
|
||||
{
|
||||
AttsAddGroup(&svcAmdtpGroup);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn SvcAmdtpRemoveGroup
|
||||
*
|
||||
* \brief Remove the services from the attribute server.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SvcAmdtpsRemoveGroup(void)
|
||||
{
|
||||
AttsRemoveGroup(AMDTPS_START_HDL);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn SvcAmdtpsCbackRegister
|
||||
*
|
||||
* \brief Register callbacks for the service.
|
||||
*
|
||||
* \param readCback Read callback function.
|
||||
* \param writeCback Write callback function.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SvcAmdtpsCbackRegister(attsReadCback_t readCback, attsWriteCback_t writeCback)
|
||||
{
|
||||
svcAmdtpGroup.readCback = readCback;
|
||||
svcAmdtpGroup.writeCback = writeCback;
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file svc_amdtps.h
|
||||
//!
|
||||
//! @brief AmbiqMicro Data Transfer Protocol service definition
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
#ifndef SVC_AMDTPS_H
|
||||
#define SVC_AMDTPS_H
|
||||
|
||||
//
|
||||
// Put additional includes here if necessary.
|
||||
//
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Macro definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
/*! Base UUID: 00002760-08C2-11E1-9073-0E8AC72EXXXX */
|
||||
#define ATT_UUID_AMBIQ_BASE 0x2E, 0xC7, 0x8A, 0x0E, 0x73, 0x90, \
|
||||
0xE1, 0x11, 0xC2, 0x08, 0x60, 0x27, 0x00, 0x00
|
||||
|
||||
/*! Macro for building Ambiq UUIDs */
|
||||
#define ATT_UUID_AMBIQ_BUILD(part) UINT16_TO_BYTES(part), ATT_UUID_AMBIQ_BASE
|
||||
|
||||
/*! Partial amdtp service UUIDs */
|
||||
#define ATT_UUID_AMDTP_SERVICE_PART 0x1011
|
||||
|
||||
/*! Partial amdtp rx characteristic UUIDs */
|
||||
#define ATT_UUID_AMDTP_RX_PART 0x0011
|
||||
|
||||
/*! Partial amdtp tx characteristic UUIDs */
|
||||
#define ATT_UUID_AMDTP_TX_PART 0x0012
|
||||
|
||||
/*! Partial amdtp ack characteristic UUIDs */
|
||||
#define ATT_UUID_AMDTP_ACK_PART 0x0013
|
||||
|
||||
/* Amdtp services */
|
||||
#define ATT_UUID_AMDTP_SERVICE ATT_UUID_AMBIQ_BUILD(ATT_UUID_AMDTP_SERVICE_PART)
|
||||
|
||||
/* Amdtp characteristics */
|
||||
#define ATT_UUID_AMDTP_RX ATT_UUID_AMBIQ_BUILD(ATT_UUID_AMDTP_RX_PART)
|
||||
#define ATT_UUID_AMDTP_TX ATT_UUID_AMBIQ_BUILD(ATT_UUID_AMDTP_TX_PART)
|
||||
#define ATT_UUID_AMDTP_ACK ATT_UUID_AMBIQ_BUILD(ATT_UUID_AMDTP_ACK_PART)
|
||||
|
||||
// AM DTP Service
|
||||
#define AMDTPS_START_HDL 0x0800//0x300
|
||||
#define AMDTPS_END_HDL (AMDTPS_MAX_HDL - 1)
|
||||
|
||||
|
||||
/* AMDTP Service Handles */
|
||||
enum
|
||||
{
|
||||
AMDTP_SVC_HDL = AMDTPS_START_HDL, /* AMDTP service declaration */
|
||||
AMDTPS_RX_CH_HDL, /* AMDTP write command characteristic */
|
||||
AMDTPS_RX_HDL, /* AMDTP write command data */
|
||||
AMDTPS_TX_CH_HDL, /* AMDTP notify characteristic */
|
||||
AMDTPS_TX_HDL, /* AMDTP notify data */
|
||||
AMDTPS_TX_CH_CCC_HDL, /* AMDTP notify client characteristic configuration */
|
||||
AMDTPS_ACK_CH_HDL, /* AMDTP rx ack characteristic */
|
||||
AMDTPS_ACK_HDL, /* AMDTP rx ack data */
|
||||
AMDTPS_ACK_CH_CCC_HDL, /* AMDTP rx ack client characteristic configuration */
|
||||
AMDTPS_MAX_HDL
|
||||
};
|
||||
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// External variable definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
//extern uint32_t g_ui32Stuff;
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Function definitions.
|
||||
//
|
||||
//*****************************************************************************
|
||||
void SvcAmdtpsAddGroup(void);
|
||||
void SvcAmdtpsRemoveGroup(void);
|
||||
void SvcAmdtpsCbackRegister(attsReadCback_t readCback, attsWriteCback_t writeCback);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // SVC_AMDTPS_H
|
||||
@@ -0,0 +1,215 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file svc_amotas.c
|
||||
//!
|
||||
//! @brief AM OTA service implementation
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
#include "wsf_types.h"
|
||||
#include "att_api.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "bstream.h"
|
||||
#include "svc_ch.h"
|
||||
#include "svc_amotas.h"
|
||||
#include "svc_cfg.h"
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Macro definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
//#define SOME_MACRO 42 //!< This is the answer
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Global Variables
|
||||
//
|
||||
//*****************************************************************************
|
||||
//uint32_t g_ui32Stuff;
|
||||
|
||||
/**************************************************************************************************
|
||||
Static Variables
|
||||
**************************************************************************************************/
|
||||
/* UUIDs */
|
||||
static const uint8_t svcRxUuid[] = {ATT_UUID_AMOTA_RX};
|
||||
static const uint8_t svcTxUuid[] = {ATT_UUID_AMOTA_TX};
|
||||
|
||||
/**************************************************************************************************
|
||||
Service variables
|
||||
**************************************************************************************************/
|
||||
|
||||
/* AMOTA service declaration */
|
||||
static const uint8_t amotaSvc[] = {ATT_UUID_AMOTA_SERVICE};
|
||||
static const uint16_t amotaLenSvc = sizeof(amotaSvc);
|
||||
|
||||
/* AMOTA RX characteristic */
|
||||
static const uint8_t amotaRxCh[] = {ATT_PROP_WRITE_NO_RSP, UINT16_TO_BYTES(AMOTAS_RX_HDL), ATT_UUID_AMOTA_RX};
|
||||
static const uint16_t amotaLenRxCh = sizeof(amotaRxCh);
|
||||
|
||||
/* AMOTA TX characteristic */
|
||||
static const uint8_t amotaTxCh[] = {ATT_PROP_NOTIFY, UINT16_TO_BYTES(AMOTAS_TX_HDL), ATT_UUID_AMOTA_TX};
|
||||
static const uint16_t amotaLenTxCh = sizeof(amotaTxCh);
|
||||
|
||||
/* AMOTA RX data */
|
||||
/* Note these are dummy values */
|
||||
static const uint8_t amotaRx[] = {0};
|
||||
static const uint16_t amotaLenRx = sizeof(amotaRx);
|
||||
|
||||
/* AMOTA TX data */
|
||||
/* Note these are dummy values */
|
||||
static const uint8_t amotaTx[] = {0};
|
||||
static const uint16_t amotaLenTx = sizeof(amotaTx);
|
||||
|
||||
/* Proprietary data client characteristic configuration */
|
||||
static uint8_t amotaTxChCcc[] = {UINT16_TO_BYTES(0x0000)};
|
||||
static const uint16_t amotaLenTxChCcc = sizeof(amotaTxChCcc);
|
||||
|
||||
|
||||
/* Attribute list for AMOTA group */
|
||||
static const attsAttr_t amotaList[] =
|
||||
{
|
||||
{
|
||||
attPrimSvcUuid,
|
||||
(uint8_t *) amotaSvc,
|
||||
(uint16_t *) &amotaLenSvc,
|
||||
sizeof(amotaSvc),
|
||||
0,
|
||||
ATTS_PERMIT_READ
|
||||
},
|
||||
{
|
||||
attChUuid,
|
||||
(uint8_t *) amotaRxCh,
|
||||
(uint16_t *) &amotaLenRxCh,
|
||||
sizeof(amotaRxCh),
|
||||
0,
|
||||
ATTS_PERMIT_READ
|
||||
},
|
||||
{
|
||||
svcRxUuid,
|
||||
(uint8_t *) amotaRx,
|
||||
(uint16_t *) &amotaLenRx,
|
||||
ATT_VALUE_MAX_LEN,
|
||||
(ATTS_SET_UUID_128 | ATTS_SET_VARIABLE_LEN | ATTS_SET_WRITE_CBACK),
|
||||
ATTS_PERMIT_WRITE
|
||||
},
|
||||
{
|
||||
attChUuid,
|
||||
(uint8_t *) amotaTxCh,
|
||||
(uint16_t *) &amotaLenTxCh,
|
||||
sizeof(amotaTxCh),
|
||||
0,
|
||||
ATTS_PERMIT_READ
|
||||
},
|
||||
{
|
||||
svcTxUuid,
|
||||
(uint8_t *) amotaTx,
|
||||
(uint16_t *) &amotaLenTx,
|
||||
ATT_VALUE_MAX_LEN,
|
||||
(ATTS_SET_UUID_128 | ATTS_SET_VARIABLE_LEN),
|
||||
ATTS_PERMIT_READ
|
||||
},
|
||||
{
|
||||
attCliChCfgUuid,
|
||||
(uint8_t *) amotaTxChCcc,
|
||||
(uint16_t *) &amotaLenTxChCcc,
|
||||
sizeof(amotaTxChCcc),
|
||||
ATTS_SET_CCC,
|
||||
(ATTS_PERMIT_READ | ATTS_PERMIT_WRITE)
|
||||
}
|
||||
};
|
||||
|
||||
/* AMOTA group structure */
|
||||
static attsGroup_t svcAmotaGroup =
|
||||
{
|
||||
NULL,
|
||||
(attsAttr_t *) amotaList,
|
||||
NULL,
|
||||
NULL,
|
||||
AMOTAS_START_HDL,
|
||||
AMOTAS_END_HDL
|
||||
};
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn SvcAmotasAddGroup
|
||||
*
|
||||
* \brief Add the services to the attribute server.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SvcAmotasAddGroup(void)
|
||||
{
|
||||
AttsAddGroup(&svcAmotaGroup);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn SvcAmotaRemoveGroup
|
||||
*
|
||||
* \brief Remove the services from the attribute server.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SvcAmotasRemoveGroup(void)
|
||||
{
|
||||
AttsRemoveGroup(AMOTAS_START_HDL);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn SvcAmotasCbackRegister
|
||||
*
|
||||
* \brief Register callbacks for the service.
|
||||
*
|
||||
* \param readCback Read callback function.
|
||||
* \param writeCback Write callback function.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SvcAmotasCbackRegister(attsReadCback_t readCback, attsWriteCback_t writeCback)
|
||||
{
|
||||
svcAmotaGroup.readCback = readCback;
|
||||
svcAmotaGroup.writeCback = writeCback;
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file svc_amotas.h
|
||||
//!
|
||||
//! @brief AmbiqMicro OTA service definition
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
#ifndef SVC_AMOTAS_H
|
||||
#define SVC_AMOTAS_H
|
||||
|
||||
//
|
||||
// Put additional includes here if necessary.
|
||||
//
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Macro definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
/*! Base UUID: 00002760-08C2-11E1-9073-0E8AC72EXXXX */
|
||||
#define ATT_UUID_AMBIQ_BASE 0x2E, 0xC7, 0x8A, 0x0E, 0x73, 0x90, \
|
||||
0xE1, 0x11, 0xC2, 0x08, 0x60, 0x27, 0x00, 0x00
|
||||
|
||||
/*! Macro for building Ambiq UUIDs */
|
||||
#define ATT_UUID_AMBIQ_BUILD(part) UINT16_TO_BYTES(part), ATT_UUID_AMBIQ_BASE
|
||||
|
||||
/*! Partial amota service UUIDs */
|
||||
#define ATT_UUID_AMOTA_SERVICE_PART 0x1001
|
||||
|
||||
/*! Partial amota rx characteristic UUIDs */
|
||||
#define ATT_UUID_AMOTA_RX_PART 0x0001
|
||||
|
||||
/*! Partial amota tx characteristic UUIDs */
|
||||
#define ATT_UUID_AMOTA_TX_PART 0x0002
|
||||
|
||||
/* Amota services */
|
||||
#define ATT_UUID_AMOTA_SERVICE ATT_UUID_AMBIQ_BUILD(ATT_UUID_AMOTA_SERVICE_PART)
|
||||
|
||||
/* Amota characteristics */
|
||||
#define ATT_UUID_AMOTA_RX ATT_UUID_AMBIQ_BUILD(ATT_UUID_AMOTA_RX_PART)
|
||||
#define ATT_UUID_AMOTA_TX ATT_UUID_AMBIQ_BUILD(ATT_UUID_AMOTA_TX_PART)
|
||||
|
||||
// AM OTA Service
|
||||
#define AMOTAS_START_HDL 0x300
|
||||
#define AMOTAS_END_HDL (AMOTAS_MAX_HDL - 1)
|
||||
|
||||
|
||||
/* AMOTA Service Handles */
|
||||
enum
|
||||
{
|
||||
AMOTA_SVC_HDL = AMOTAS_START_HDL, /* AMOTA service declaration */
|
||||
AMOTAS_RX_CH_HDL, /* AMOTA write command characteristic */
|
||||
AMOTAS_RX_HDL, /* AMOTA write command data */
|
||||
AMOTAS_TX_CH_HDL, /* AMOTA notify characteristic */
|
||||
AMOTAS_TX_HDL, /* AMOTA notify data */
|
||||
AMOTAS_TX_CH_CCC_HDL, /* AMOTA notify client characteristic configuration */
|
||||
AMOTAS_MAX_HDL
|
||||
};
|
||||
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// External variable definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
//extern uint32_t g_ui32Stuff;
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Function definitions.
|
||||
//
|
||||
//*****************************************************************************
|
||||
void SvcAmotasAddGroup(void);
|
||||
void SvcAmotasRemoveGroup(void);
|
||||
void SvcAmotasCbackRegister(attsReadCback_t readCback, attsWriteCback_t writeCback);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // SVC_AMOTAS_H
|
||||
@@ -0,0 +1,224 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file svc_amvole.c
|
||||
//!
|
||||
//! @brief AM Voice Over LE service implementation
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2018, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 1.2.12 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
#include "wsf_types.h"
|
||||
#include "att_api.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "bstream.h"
|
||||
#include "svc_ch.h"
|
||||
#include "svc_amvole.h"
|
||||
#include "svc_cfg.h"
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Macro definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
//#define SOME_MACRO 42 //!< This is the answer
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Global Variables
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
/**************************************************************************************************
|
||||
Static Variables
|
||||
**************************************************************************************************/
|
||||
/* UUIDs */
|
||||
static const uint8_t svcRxUuid[] = {ATT_UUID_VOLES_RX};
|
||||
static const uint8_t svcTxUuid[] = {ATT_UUID_VOLES_TX};
|
||||
|
||||
/**************************************************************************************************
|
||||
Service variables
|
||||
**************************************************************************************************/
|
||||
|
||||
/* VOLES service declaration */
|
||||
static const uint8_t amvoleSvc[] = {ATT_UUID_VOLES_SERVICE};
|
||||
static const uint16_t amvoleLenSvc = sizeof(amvoleSvc);
|
||||
|
||||
/* VOLES RX characteristic */
|
||||
static const uint8_t amvoleRxCh[] = {ATT_PROP_WRITE, UINT16_TO_BYTES(VOLES_RX_HDL), ATT_UUID_VOLES_RX};
|
||||
static const uint16_t amvoleLenRxCh = sizeof(amvoleRxCh);
|
||||
|
||||
/* VOLES TX characteristic */
|
||||
static const uint8_t amvoleTxCh[] = {ATT_PROP_NOTIFY | ATT_PROP_READ, UINT16_TO_BYTES(VOLES_TX_HDL), ATT_UUID_VOLES_TX};
|
||||
static const uint16_t amvoleLenTxCh = sizeof(amvoleTxCh);
|
||||
|
||||
/* VOLES RX data */
|
||||
/* Note these are dummy values */
|
||||
static const uint8_t amvoleRx[] = {0};
|
||||
static const uint16_t amvoleLenRx = sizeof(amvoleRx);
|
||||
|
||||
/* VOLES TX data */
|
||||
/* Note these are dummy values */
|
||||
static const uint8_t amvoleTx[] = {0};
|
||||
static const uint16_t amvoleLenTx = sizeof(amvoleTx);
|
||||
|
||||
/* Proprietary data client characteristic configuration */
|
||||
static uint8_t amvoleTxChCcc[] = {UINT16_TO_BYTES(0x0000)};
|
||||
static const uint16_t amvoleLenTxChCcc = sizeof(amvoleTxChCcc);
|
||||
|
||||
/* Attribute list for VOLES group */
|
||||
static const attsAttr_t amvoleList[] =
|
||||
{
|
||||
{
|
||||
attPrimSvcUuid,
|
||||
(uint8_t *) amvoleSvc,
|
||||
(uint16_t *) &amvoleLenSvc,
|
||||
sizeof(amvoleSvc),
|
||||
0,
|
||||
ATTS_PERMIT_READ
|
||||
},
|
||||
{
|
||||
attChUuid,
|
||||
(uint8_t *) amvoleRxCh,
|
||||
(uint16_t *) &amvoleLenRxCh,
|
||||
sizeof(amvoleRxCh),
|
||||
0,
|
||||
ATTS_PERMIT_READ
|
||||
},
|
||||
{
|
||||
svcRxUuid,
|
||||
(uint8_t *) amvoleRx,
|
||||
(uint16_t *) &amvoleLenRx,
|
||||
ATT_VALUE_MAX_LEN,
|
||||
(ATTS_SET_UUID_128 | ATTS_SET_VARIABLE_LEN | ATTS_SET_WRITE_CBACK),
|
||||
ATTS_PERMIT_WRITE
|
||||
//ATTS_PERMIT_WRITE_ENC
|
||||
},
|
||||
{
|
||||
attChUuid,
|
||||
(uint8_t *) amvoleTxCh,
|
||||
(uint16_t *) &amvoleLenTxCh,
|
||||
sizeof(amvoleTxCh),
|
||||
0,
|
||||
ATTS_PERMIT_READ
|
||||
},
|
||||
{
|
||||
svcTxUuid,
|
||||
(uint8_t *) amvoleTx,
|
||||
(uint16_t *) &amvoleLenTx,
|
||||
sizeof(amvoleTx), //ATT_VALUE_MAX_LEN,
|
||||
#if 0
|
||||
#if USE_OUTPUT_VOLES_AMA
|
||||
(ATTS_SET_UUID_128 | ATTS_SET_VARIABLE_LEN),
|
||||
ATTS_PERMIT_READ
|
||||
#else
|
||||
0, //(ATTS_SET_UUID_128 | ATTS_SET_VARIABLE_LEN),
|
||||
0 //ATTS_PERMIT_READ
|
||||
#endif
|
||||
#endif
|
||||
(ATTS_SET_UUID_128),
|
||||
ATTS_PERMIT_READ
|
||||
|
||||
},
|
||||
{
|
||||
attCliChCfgUuid,
|
||||
(uint8_t *) amvoleTxChCcc,
|
||||
(uint16_t *) &amvoleLenTxChCcc,
|
||||
sizeof(amvoleTxChCcc),
|
||||
ATTS_SET_CCC,
|
||||
(ATTS_PERMIT_READ | ATTS_PERMIT_WRITE)
|
||||
}
|
||||
};
|
||||
|
||||
/* VOLES group structure */
|
||||
static attsGroup_t svcVolesGroup =
|
||||
{
|
||||
NULL,
|
||||
(attsAttr_t *) amvoleList,
|
||||
NULL,
|
||||
NULL,
|
||||
VOLES_START_HDL,
|
||||
VOLES_END_HDL
|
||||
};
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn SvcVolesAddGroup
|
||||
*
|
||||
* \brief Add the services to the attribute server.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SvcVolesAddGroup(void)
|
||||
{
|
||||
AttsAddGroup(&svcVolesGroup);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn SvcVolesRemoveGroup
|
||||
*
|
||||
* \brief Remove the services from the attribute server.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SvcVolesRemoveGroup(void)
|
||||
{
|
||||
AttsRemoveGroup(VOLES_START_HDL);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn SvcVolesCbackRegister
|
||||
*
|
||||
* \brief Register callbacks for the service.
|
||||
*
|
||||
* \param readCback Read callback function.
|
||||
* \param writeCback Write callback function.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void SvcVolesCbackRegister(attsReadCback_t readCback, attsWriteCback_t writeCback)
|
||||
{
|
||||
svcVolesGroup.readCback = readCback;
|
||||
svcVolesGroup.writeCback = writeCback;
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file svc_amvole.h
|
||||
//!
|
||||
//! @brief AmbiqMicro Voice Over LE service definition
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2018, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 1.2.12 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
#ifndef SVC_VOLES_H
|
||||
#define SVC_VOLES_H
|
||||
|
||||
//
|
||||
// Put additional includes here if necessary.
|
||||
//
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Macro definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
/* AMA services */
|
||||
#define ATT_UUID_VOLES_SERVICE 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00
|
||||
|
||||
/* VOLE characteristics */
|
||||
#define ATT_UUID_VOLES_RX 0x76, 0x30, 0xF8, 0xDD, 0x90, 0xA3, 0x61, 0xAC, 0xA7, 0x43, 0x05, 0x30, 0x77, 0xB1, 0x4E, 0xF0
|
||||
#define ATT_UUID_VOLES_TX 0x0B, 0x42, 0x82, 0x1F, 0x64, 0x72, 0x2F, 0x8A, 0xB4, 0x4B, 0x79, 0x18, 0x5B, 0xA0, 0xEE, 0x2B
|
||||
|
||||
#define VOLES_START_HDL 0x0800//0x300
|
||||
#define VOLES_END_HDL (VOLES_MAX_HDL - 1)
|
||||
|
||||
|
||||
/* VOLE Service Handles */
|
||||
enum
|
||||
{
|
||||
VOLES_SVC_HDL = VOLES_START_HDL, /* VOLE service declaration */
|
||||
VOLES_RX_CH_HDL, /* VOLE write command characteristic */
|
||||
VOLES_RX_HDL, /* VOLE write command data */
|
||||
VOLES_TX_CH_HDL, /* VOLE notify characteristic */
|
||||
VOLES_TX_HDL, /* VOLE notify data */
|
||||
VOLES_TX_CH_CCC_HDL, /* VOLE notify client characteristic configuration */
|
||||
VOLES_MAX_HDL
|
||||
};
|
||||
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// External variable definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Function definitions.
|
||||
//
|
||||
//*****************************************************************************
|
||||
void SvcVolesAddGroup(void);
|
||||
void SvcVolesRemoveGroup(void);
|
||||
void SvcVolesCbackRegister(attsReadCback_t readCback, attsWriteCback_t writeCback);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // SVC_VOLES_H
|
||||
Reference in New Issue
Block a user