initial commit
This commit is contained in:
Vendored
+163
@@ -0,0 +1,163 @@
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \brief Wireless Data Exchange profile application interface.
|
||||
*
|
||||
* Copyright (c) 2013-2018 Arm Ltd.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
|
||||
#ifndef WDXS_API_H
|
||||
#define WDXS_API_H
|
||||
|
||||
#include "att_api.h"
|
||||
#include "wdx_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*! \addtogroup WIRELESS_DATA_EXCHANGE_PROFILE
|
||||
* \{ */
|
||||
|
||||
/**************************************************************************************************
|
||||
Macros
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! \brief Size of RAM Media used by the application */
|
||||
#define WDXS_APP_RAM_MEDIA_SIZE 256
|
||||
|
||||
/*! \brief Device Model Name */
|
||||
#ifndef WDXS_DEVICE_MODEL
|
||||
#define WDXS_DEVICE_MODEL "WDXS App"
|
||||
#endif
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Called at startup to configure WDXS authentication.
|
||||
*
|
||||
* \param reqLevel Level of authentication that is required for a client to use WDXS
|
||||
* \param pKey Authentication key (set to NULL if no authentication is required)
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void WdxsAuthenticationCfg(bool_t reqLevel, uint8_t *pKey);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Handle WSF events for WDXS.
|
||||
*
|
||||
* \param event event
|
||||
* \param pMsg message assiciated with event
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void WdxsHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief WSF Task Initialization for WDXS task.
|
||||
*
|
||||
* \param handlerId ID of the WDXS task
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void WdxsHandlerInit(wsfHandlerId_t handlerId);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Called by application to notify the WDXS of ATT Events.
|
||||
*
|
||||
* \param pEvt Pointer to the ATT Event
|
||||
*
|
||||
* \return TRUE if the application should ignore the event, else FALSE.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t WdxsAttCback(attEvt_t *pEvt);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Called by application to notify the WDXS of DM Events.
|
||||
*
|
||||
* \param pEvt Pointer to the DM Event
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void WdxsProcDmMsg(dmEvt_t *pEvt);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Set the CCCD index used by the application for WDXS service characteristics.
|
||||
*
|
||||
* \param dcCccIdx Device Control CCCD index.
|
||||
* \param auCccIdx Authentication CCCD index.
|
||||
* \param ftcCccIdx File Transfer Control CCCD index.
|
||||
* \param ftdCccIdx File Transfer Data CCCD index.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void WdxsSetCccIdx(uint8_t dcCccIdx, uint8_t auCccIdx, uint8_t ftcCccIdx, uint8_t ftdCccIdx);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Registers the platform dependent Flash Media with the Embedded File System (EFS)
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void WdxsFlashMediaInit(void);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Registers the platform dependent OTA Media with the Embedded File System (EFS)
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void WdxsOtaMediaInit(void);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Resets the system.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void WdxsResetSystem(void);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Initialize WDXS Device Configuration PHY.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void WdxsPhyInit(void);
|
||||
|
||||
/*! \} */ /* WIRELESS_DATA_EXCHANGE_PROFILE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WDXS_API_H */
|
||||
Vendored
+218
@@ -0,0 +1,218 @@
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \brief Wireless Data Exchange profile implementation - Authentication.
|
||||
*
|
||||
* Copyright (c) 2013-2018 Arm Ltd.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "wsf_types.h"
|
||||
#include "util/bstream.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "wsf_assert.h"
|
||||
#include "wsf_efs.h"
|
||||
#include "wsf_os.h"
|
||||
#include "sec_api.h"
|
||||
#include "svc_wdxs.h"
|
||||
#include "wdxs_api.h"
|
||||
#include "wdxs_main.h"
|
||||
#include "dm_api.h"
|
||||
#include "att_api.h"
|
||||
#include "app_api.h"
|
||||
|
||||
#if WDXS_AU_ENABLED == TRUE
|
||||
|
||||
/* WDXS Authentication Control Block */
|
||||
wdxsAuCb_t wdxsAuCb;
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Transmit to authentication characteristic.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void wdxsAuSend(dmConnId_t connId)
|
||||
{
|
||||
APP_TRACE_INFO0("WDXS: AuSend");
|
||||
|
||||
/* if notification enabled */
|
||||
if (AttsCccEnabled(connId, wdxsCb.auCccIdx))
|
||||
{
|
||||
/* send notification */
|
||||
AttsHandleValueNtf(connId, WDXS_AU_HDL, wdxsAuCb.auMsgLen, wdxsAuCb.auMsgBuf);
|
||||
wdxsCb.txReadyMask &= ~(WDXS_TX_MASK_AU_BIT | WDXS_TX_MASK_READY_BIT);
|
||||
|
||||
wdxsAuCb.authState = WDXS_AU_STATE_WAIT_REPLY;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Called by WDXS event handler when the WSF Sec operation is complete.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void WdxsAuSecComplete(secAes_t *pAes)
|
||||
{
|
||||
uint8_t *p = wdxsAuCb.auMsgBuf;
|
||||
|
||||
/* Record the hash */
|
||||
memcpy(wdxsAuCb.auHash, pAes->pCiphertext, WDX_AU_HASH_LEN);
|
||||
|
||||
/* Build challenge message */
|
||||
UINT8_TO_BSTREAM(p, WDX_AU_OP_CHALLENGE);
|
||||
memcpy(p, wdxsAuCb.auRand, WDX_AU_RAND_LEN);
|
||||
wdxsAuCb.auMsgLen = WDX_AU_RAND_LEN + WDX_AU_HDR_LEN;
|
||||
|
||||
/* Update State */
|
||||
wdxsAuCb.authState = WDXS_AU_STATE_WAIT_REPLY;
|
||||
|
||||
/* Indicate TX Ready */
|
||||
wdxsCb.txReadyMask &= ~(WDXS_TX_MASK_AU_BIT | WDXS_TX_MASK_READY_BIT);
|
||||
WsfSetEvent(wdxsCb.handlerId, WDXS_EVT_TX_PATH);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a request to start authentication.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t wdxsAuProcStart(dmConnId_t connId, uint8_t len, uint8_t *pValue)
|
||||
{
|
||||
/* Verify parameter length */
|
||||
if (len != WDX_AU_PARAM_LEN_START)
|
||||
{
|
||||
return ATT_ERR_LENGTH;
|
||||
}
|
||||
|
||||
/* Parse parameters */
|
||||
BSTREAM_TO_UINT8(wdxsAuCb.authLevel, pValue);
|
||||
BSTREAM_TO_UINT8(wdxsAuCb.authMode, pValue);
|
||||
|
||||
/* Generate random number */
|
||||
SecRand(wdxsAuCb.auRand, WDX_AU_RAND_LEN);
|
||||
|
||||
/* Encrypt the random number to create the hash */
|
||||
SecAes(wdxsAuCb.sessionKey, wdxsAuCb.auRand, wdxsCb.handlerId, connId, WDXS_EVT_AU_SEC_COMPLETE);
|
||||
|
||||
/* Update State */
|
||||
wdxsAuCb.authState = WDXS_AU_STATE_WAIT_SEC;
|
||||
|
||||
return ATT_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a reply to the authentication challenge.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t wdxsAuProcReply(uint8_t len, uint8_t *pValue)
|
||||
{
|
||||
/* Verify parameter length */
|
||||
if (len != WDX_AU_PARAM_LEN_REPLY)
|
||||
{
|
||||
return ATT_ERR_LENGTH;
|
||||
}
|
||||
|
||||
if (wdxsAuCb.authState == WDXS_AU_STATE_WAIT_REPLY)
|
||||
{
|
||||
/* Verify [0-7] bytes of cipher text against what was sent by client */
|
||||
if (memcmp(wdxsAuCb.auHash, pValue, WDX_AU_HASH_LEN) == 0)
|
||||
{
|
||||
/* Successful challenge */
|
||||
wdxsAuCb.authState = WDXS_AU_STATE_AUTHORIZED;
|
||||
return ATT_SUCCESS;
|
||||
}
|
||||
|
||||
return WDX_AU_ST_AUTH_FAILED;
|
||||
}
|
||||
|
||||
return WDX_AU_ST_INVALID_STATE;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a write to the authentication characteristic.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t wdxsAuWrite(dmConnId_t connId, uint16_t len, uint8_t *pValue)
|
||||
{
|
||||
uint8_t op;
|
||||
uint8_t status;
|
||||
|
||||
/* Sanity check message length */
|
||||
if (len < WDX_AU_HDR_LEN)
|
||||
{
|
||||
return ATT_ERR_LENGTH;
|
||||
}
|
||||
|
||||
/* Get Operation ID */
|
||||
BSTREAM_TO_UINT8(op, pValue);
|
||||
len -= WDX_AU_HDR_LEN;
|
||||
|
||||
APP_TRACE_INFO1("WDXS: AuWrite: op=%d", op);
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case WDX_AU_OP_START:
|
||||
status = wdxsAuProcStart(connId, (uint8_t) len, pValue);
|
||||
break;
|
||||
|
||||
case WDX_AU_OP_REPLY:
|
||||
status = wdxsAuProcReply((uint8_t) len, pValue);
|
||||
break;
|
||||
|
||||
default:
|
||||
status = ATT_ERR_RANGE;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Called at startup to configure WDXS authentication.
|
||||
*
|
||||
* \param reqLevel Level of authentication that is required for a client to use WDXS
|
||||
* \param key Authentication key (set to NULL if no authentication is required)
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void WdxsAuthenticationCfg(bool_t reqLevel, uint8_t *pKey)
|
||||
{
|
||||
wdxsAuCb.reqAuthLevel = reqLevel;
|
||||
|
||||
if (pKey)
|
||||
{
|
||||
memcpy(wdxsAuCb.sessionKey, pKey, WDX_AU_KEY_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* WDXS_AU_ENABLED */
|
||||
Vendored
+608
@@ -0,0 +1,608 @@
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \brief Wireless Data Exchange profile implementation - Device Configuration.
|
||||
*
|
||||
* Copyright (c) 2013-2018 Arm Ltd.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "wsf_types.h"
|
||||
#include "util/wstr.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "wsf_assert.h"
|
||||
#include "wsf_efs.h"
|
||||
#include "util/bstream.h"
|
||||
#include "svc_wdxs.h"
|
||||
#include "wdxs_api.h"
|
||||
#include "wdxs_main.h"
|
||||
#include "dm_api.h"
|
||||
#include "app_api.h"
|
||||
#include "app_hw.h"
|
||||
|
||||
#if WDXS_DC_ENABLED == TRUE
|
||||
|
||||
/* WDXS Device Configuration Control Block */
|
||||
wdxsDcCb_t wdxsDcCb;
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Send device configuration notification
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void wdxsDcSend(dmConnId_t connId)
|
||||
{
|
||||
APP_TRACE_INFO0("WDXS: DcSend");
|
||||
|
||||
/* if notification enabled */
|
||||
if (AttsCccEnabled(connId, wdxsCb.dcCccIdx))
|
||||
{
|
||||
/* send notification */
|
||||
AttsHandleValueNtf(connId, WDXS_DC_HDL, wdxsDcCb.dcMsgLen, wdxsDcCb.dcMsgBuf);
|
||||
wdxsCb.txReadyMask &= ~(WDXS_TX_MASK_DC_BIT | WDXS_TX_MASK_READY_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Send update message for connection parameters.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t wdxsDcUpdateConnParam(dmConnId_t connId, uint8_t status)
|
||||
{
|
||||
uint8_t *p;
|
||||
|
||||
/* if update already waiting to be sent */
|
||||
if (wdxsCb.txReadyMask & WDXS_TX_MASK_DC_BIT)
|
||||
{
|
||||
return ATT_ERR_IN_PROGRESS;
|
||||
}
|
||||
|
||||
/* build update to global buffer */
|
||||
p = wdxsDcCb.dcMsgBuf;
|
||||
UINT8_TO_BSTREAM(p, WDX_DC_OP_UPDATE);
|
||||
UINT8_TO_BSTREAM(p, WDX_DC_ID_CONN_PARAM);
|
||||
UINT8_TO_BSTREAM(p, status);
|
||||
UINT16_TO_BSTREAM(p, wdxsCb.connInterval);
|
||||
UINT16_TO_BSTREAM(p, wdxsCb.connLatency);
|
||||
UINT16_TO_BSTREAM(p, wdxsCb.supTimeout);
|
||||
wdxsDcCb.dcMsgLen = WDX_DC_LEN_CONN_PARAM + WDX_DC_HDR_LEN;
|
||||
|
||||
/* Indicate TX Ready */
|
||||
wdxsCb.txReadyMask |= WDXS_TX_MASK_DC_BIT;
|
||||
WsfSetEvent(wdxsCb.handlerId, WDXS_EVT_TX_PATH);
|
||||
|
||||
return ATT_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Send update message for PHY.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t wdxsDcUpdatePhy(dmConnId_t connId, uint8_t status)
|
||||
{
|
||||
uint8_t *p;
|
||||
|
||||
/* if update already waiting to be sent */
|
||||
if (wdxsCb.txReadyMask & WDXS_TX_MASK_DC_BIT)
|
||||
{
|
||||
return ATT_ERR_IN_PROGRESS;
|
||||
}
|
||||
|
||||
/* build update to global buffer */
|
||||
p = wdxsDcCb.dcMsgBuf;
|
||||
UINT8_TO_BSTREAM(p, WDX_DC_OP_UPDATE);
|
||||
UINT8_TO_BSTREAM(p, WDX_DC_ID_PHY);
|
||||
UINT8_TO_BSTREAM(p, status);
|
||||
UINT8_TO_BSTREAM(p, wdxsCb.txPhy);
|
||||
UINT8_TO_BSTREAM(p, wdxsCb.rxPhy);
|
||||
wdxsDcCb.dcMsgLen = WDX_DC_LEN_PHY + WDX_DC_HDR_LEN;
|
||||
|
||||
/* Indicate TX Ready */
|
||||
wdxsCb.txReadyMask |= WDXS_TX_MASK_DC_BIT;
|
||||
WsfSetEvent(wdxsCb.handlerId, WDXS_EVT_TX_PATH);
|
||||
|
||||
return ATT_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process Update Diagnostics Complete.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t wdxsDcUpdateDiagnosticsComplete(dmConnId_t connId)
|
||||
{
|
||||
uint8_t *p;
|
||||
|
||||
/* if update already waiting to be sent */
|
||||
if (wdxsCb.txReadyMask & WDXS_TX_MASK_DC_BIT)
|
||||
{
|
||||
return ATT_ERR_IN_PROGRESS;
|
||||
}
|
||||
|
||||
/* build update to global buffer */
|
||||
p = wdxsDcCb.dcMsgBuf;
|
||||
UINT8_TO_BSTREAM(p, WDX_DC_OP_UPDATE);
|
||||
UINT8_TO_BSTREAM(p, WDX_DC_ID_DIAGNOSTICS_COMPLETE);
|
||||
wdxsDcCb.dcMsgLen = WDX_DC_LEN_DIAG_COMPLETE + WDX_DC_HDR_LEN;
|
||||
|
||||
/* Indicate TX Ready */
|
||||
wdxsCb.txReadyMask |= WDXS_TX_MASK_DC_BIT;
|
||||
WsfSetEvent(wdxsCb.handlerId, WDXS_EVT_TX_PATH);
|
||||
|
||||
return ATT_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process set connection paramter request.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t wdxsDcSetConnParamReq(dmConnId_t connId, uint16_t len, uint8_t *pValue)
|
||||
{
|
||||
hciConnSpec_t connSpec;
|
||||
|
||||
/* verify parameter length */
|
||||
if (len != WDX_DC_LEN_CONN_PARAM_REQ)
|
||||
{
|
||||
return ATT_ERR_LENGTH;
|
||||
}
|
||||
|
||||
/* parse parameters */
|
||||
BSTREAM_TO_UINT16(connSpec.connIntervalMin, pValue);
|
||||
BSTREAM_TO_UINT16(connSpec.connIntervalMax, pValue);
|
||||
BSTREAM_TO_UINT16(connSpec.connLatency, pValue);
|
||||
BSTREAM_TO_UINT16(connSpec.supTimeout, pValue);
|
||||
|
||||
/* request update to connection parameters */
|
||||
DmConnUpdate(connId, &connSpec);
|
||||
|
||||
return ATT_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process set diagnostics.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t wdxsDcSetEnterDiadnostics(dmConnId_t connId)
|
||||
{
|
||||
return wdxsDcUpdateDiagnosticsComplete(connId);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a Set Disconnect request.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t wdxsDcSetDisconnectReq(dmConnId_t connId, uint16_t len, uint8_t *pValue)
|
||||
{
|
||||
AppConnClose(connId);
|
||||
return ATT_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a Set Security request.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t wdxsDcSetSecurityReq(dmConnId_t connId, uint16_t len, uint8_t *pValue)
|
||||
{
|
||||
uint8_t secLevel;
|
||||
|
||||
/* verify parameter length */
|
||||
if (len != WDX_DC_LEN_SEC_LEVEL)
|
||||
{
|
||||
return ATT_ERR_LENGTH;
|
||||
}
|
||||
|
||||
/* parse parameters */
|
||||
BSTREAM_TO_UINT8(secLevel, pValue);
|
||||
|
||||
/* Enable Security */
|
||||
if (DmConnSecLevel(connId) != DM_SEC_LEVEL_NONE)
|
||||
{
|
||||
DmSecSlaveReq(connId, secLevel);
|
||||
}
|
||||
|
||||
return ATT_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a Set Service Changed request.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t wdxsDcSetServiceChanged(dmConnId_t connId, uint16_t len, uint8_t *pValue)
|
||||
{
|
||||
/* TBD */
|
||||
return ATT_ERR_NOT_SUP;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a Set Delete Bonds request.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t wdxsDcSetDeleteBonds(dmConnId_t connId, uint16_t len, uint8_t *pValue)
|
||||
{
|
||||
/* TBD */
|
||||
return ATT_ERR_NOT_SUP;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a Set Disconnect And Reset request.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t wdxsDcSetDisconnectAndReset(dmConnId_t connId, uint16_t len, uint8_t *pValue)
|
||||
{
|
||||
wdxsDcCb.doReset = TRUE;
|
||||
AppConnClose(connId);
|
||||
return ATT_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a Get Connection Parameter request.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t wdxsDcGetConnParam(dmConnId_t connId, uint16_t len, uint8_t *pValue)
|
||||
{
|
||||
return wdxsDcUpdateConnParam(connId, HCI_SUCCESS);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a Get Security Level request.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t wdxsDcGetSecurityLevel(dmConnId_t connId, uint16_t len, uint8_t *pValue)
|
||||
{
|
||||
uint8_t *p;
|
||||
|
||||
/* if update already waiting to be sent */
|
||||
if (wdxsCb.txReadyMask & WDXS_TX_MASK_DC_BIT)
|
||||
{
|
||||
return ATT_ERR_IN_PROGRESS;
|
||||
}
|
||||
|
||||
/* build update to global buffer */
|
||||
p = wdxsDcCb.dcMsgBuf;
|
||||
UINT8_TO_BSTREAM(p, WDX_DC_OP_UPDATE);
|
||||
UINT8_TO_BSTREAM(p, WDX_DC_ID_CONN_SEC_LEVEL);
|
||||
UINT8_TO_BSTREAM(p, DmConnSecLevel(connId));
|
||||
wdxsDcCb.dcMsgLen = WDX_DC_LEN_SEC_LEVEL + WDX_DC_HDR_LEN;
|
||||
|
||||
/* Indicate TX Ready */
|
||||
wdxsCb.txReadyMask |= WDXS_TX_MASK_DC_BIT;
|
||||
WsfSetEvent(wdxsCb.handlerId, WDXS_EVT_TX_PATH);
|
||||
|
||||
return ATT_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a Get Current ATT MTU request.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t wdxsDcGetAttMtu(dmConnId_t connId, uint16_t len, uint8_t *pValue)
|
||||
{
|
||||
uint8_t *p;
|
||||
|
||||
/* if update already waiting to be sent */
|
||||
if (wdxsCb.txReadyMask & WDXS_TX_MASK_DC_BIT)
|
||||
{
|
||||
return ATT_ERR_IN_PROGRESS;
|
||||
}
|
||||
|
||||
/* build update to global buffer */
|
||||
p = wdxsDcCb.dcMsgBuf;
|
||||
UINT8_TO_BSTREAM(p, WDX_DC_OP_UPDATE);
|
||||
UINT8_TO_BSTREAM(p, WDX_DC_ID_ATT_MTU);
|
||||
UINT16_TO_BSTREAM(p, AttGetMtu(connId));
|
||||
wdxsDcCb.dcMsgLen = WDX_DC_LEN_ATT_MTU + WDX_DC_HDR_LEN;
|
||||
|
||||
/* Indicate TX Ready */
|
||||
wdxsCb.txReadyMask |= WDXS_TX_MASK_DC_BIT;
|
||||
WsfSetEvent(wdxsCb.handlerId, WDXS_EVT_TX_PATH);
|
||||
|
||||
return ATT_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a Get Battery Level request.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t wdxsDcGetBatteryLevel(dmConnId_t connId, uint16_t len, uint8_t *pValue)
|
||||
{
|
||||
uint8_t *p;
|
||||
|
||||
/* if update already waiting to be sent */
|
||||
if (wdxsCb.txReadyMask & WDXS_TX_MASK_DC_BIT)
|
||||
{
|
||||
return ATT_ERR_IN_PROGRESS;
|
||||
}
|
||||
|
||||
/* build update to global buffer */
|
||||
p = wdxsDcCb.dcMsgBuf;
|
||||
UINT8_TO_BSTREAM(p, WDX_DC_OP_UPDATE);
|
||||
UINT8_TO_BSTREAM(p, WDX_DC_ID_BATTERY_LEVEL);
|
||||
|
||||
/* add battery level */
|
||||
AppHwBattRead(p);
|
||||
wdxsDcCb.dcMsgLen = WDX_DC_LEN_BATTERY_LEVEL + WDX_DC_HDR_LEN;
|
||||
|
||||
/* Indicate TX Ready */
|
||||
wdxsCb.txReadyMask |= WDXS_TX_MASK_DC_BIT;
|
||||
WsfSetEvent(wdxsCb.handlerId, WDXS_EVT_TX_PATH);
|
||||
|
||||
return ATT_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a Get Device Model Number request.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t wdxsDcGetDeviceModel(dmConnId_t connId, uint16_t len, uint8_t *pValue)
|
||||
{
|
||||
uint8_t *p;
|
||||
|
||||
/* TODO: Add Device Model */
|
||||
char *pModelTxt = WDXS_DEVICE_MODEL;
|
||||
|
||||
/* if update already waiting to be sent */
|
||||
if (wdxsCb.txReadyMask & WDXS_TX_MASK_DC_BIT)
|
||||
{
|
||||
return ATT_ERR_IN_PROGRESS;
|
||||
}
|
||||
|
||||
/* build update to global buffer */
|
||||
p = wdxsDcCb.dcMsgBuf;
|
||||
UINT8_TO_BSTREAM(p, WDX_DC_OP_UPDATE);
|
||||
UINT8_TO_BSTREAM(p, WDX_DC_ID_MODEL_NUMBER);
|
||||
/* Potential buffer overrun is intentional to zero out fixed length field */
|
||||
/* coverity[overrun-buffer-arg] */
|
||||
WstrnCpy((char *)p, pModelTxt, WDX_DC_LEN_DEVICE_MODEL);
|
||||
wdxsDcCb.dcMsgLen = WDX_DC_LEN_DEVICE_MODEL + WDX_DC_HDR_LEN;
|
||||
|
||||
/* Indicate TX Ready */
|
||||
wdxsCb.txReadyMask |= WDXS_TX_MASK_DC_BIT;
|
||||
WsfSetEvent(wdxsCb.handlerId, WDXS_EVT_TX_PATH);
|
||||
|
||||
return ATT_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a Get Firmware Revision request.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t wdxsDcGetFirmwareRev(dmConnId_t connId, uint16_t len, uint8_t *pValue)
|
||||
{
|
||||
uint8_t *p;
|
||||
|
||||
/* TODO: Add Firmware Revision */
|
||||
char *pFirmwareRev = "1.0";
|
||||
|
||||
/* if update already waiting to be sent */
|
||||
if (wdxsCb.txReadyMask & WDXS_TX_MASK_DC_BIT)
|
||||
{
|
||||
return ATT_ERR_IN_PROGRESS;
|
||||
}
|
||||
|
||||
/* build update to global buffer */
|
||||
p = wdxsDcCb.dcMsgBuf;
|
||||
UINT8_TO_BSTREAM(p, WDX_DC_OP_UPDATE);
|
||||
UINT8_TO_BSTREAM(p, WDX_DC_ID_FIRMWARE_REV);
|
||||
|
||||
/* Potential buffer overrun is intentional to zero out fixed length field */
|
||||
/* coverity[overrun-buffer-arg] */
|
||||
WstrnCpy((char *)p, pFirmwareRev, WDX_DC_LEN_FIRMWARE_REV);
|
||||
wdxsDcCb.dcMsgLen = WDX_DC_LEN_FIRMWARE_REV + WDX_DC_HDR_LEN;
|
||||
|
||||
/* Indicate TX Ready */
|
||||
wdxsCb.txReadyMask |= WDXS_TX_MASK_DC_BIT;
|
||||
WsfSetEvent(wdxsCb.handlerId, WDXS_EVT_TX_PATH);
|
||||
|
||||
return ATT_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a write to the device configuration characteristic.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t wdxsDcWrite(dmConnId_t connId, uint16_t len, uint8_t *pValue)
|
||||
{
|
||||
uint8_t op;
|
||||
uint8_t id;
|
||||
uint8_t status = ATT_SUCCESS;
|
||||
|
||||
/* sanity check on message length */
|
||||
if (len < WDX_DC_HDR_LEN)
|
||||
{
|
||||
return ATT_ERR_LENGTH;
|
||||
}
|
||||
|
||||
/* verify notifications are enabled */
|
||||
if (!AttsCccEnabled(connId, wdxsCb.dcCccIdx))
|
||||
{
|
||||
return ATT_ERR_CCCD;
|
||||
}
|
||||
|
||||
/* get operation and parameter ID */
|
||||
BSTREAM_TO_UINT8(op, pValue);
|
||||
BSTREAM_TO_UINT8(id, pValue);
|
||||
|
||||
/* skip over header (note pValue was incremented above) */
|
||||
len -= WDX_DC_HDR_LEN;
|
||||
|
||||
/* set operation */
|
||||
if (op == WDX_DC_OP_SET)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case WDX_DC_ID_CONN_UPDATE_REQ:
|
||||
status = wdxsDcSetConnParamReq(connId, len, pValue);
|
||||
break;
|
||||
|
||||
case WDX_DC_ID_DISCONNECT_REQ:
|
||||
status = wdxsDcSetDisconnectReq(connId, len, pValue);
|
||||
break;
|
||||
|
||||
case WDX_DC_ID_SECURITY_REQ:
|
||||
status = wdxsDcSetSecurityReq(connId, len, pValue);
|
||||
break;
|
||||
|
||||
case WDX_DC_ID_SERVICE_CHANGED:
|
||||
status = wdxsDcSetServiceChanged(connId, len, pValue);
|
||||
break;
|
||||
|
||||
case WDX_DC_ID_DELETE_BONDS:
|
||||
status = wdxsDcSetDeleteBonds(connId, len, pValue);
|
||||
break;
|
||||
|
||||
case WDX_DC_ID_ENTER_DIAGNOSTICS:
|
||||
status = wdxsDcSetEnterDiadnostics(connId);
|
||||
break;
|
||||
|
||||
case WDX_DC_ID_DISCONNECT_AND_RESET:
|
||||
status = wdxsDcSetDisconnectAndReset(connId, len, pValue);
|
||||
break;
|
||||
|
||||
case WDX_DC_ID_PHY_UPDATE_REQ:
|
||||
/* if device configuration phy callback registered */
|
||||
if (wdxsDcCb.phyWriteCback != NULL)
|
||||
{
|
||||
status = (*wdxsDcCb.phyWriteCback)(connId, op, id, len, pValue);
|
||||
break;
|
||||
}
|
||||
/* else fall through */
|
||||
|
||||
default:
|
||||
status = ATT_ERR_RANGE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* get operation */
|
||||
else if (op == WDX_DC_OP_GET)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case WDX_DC_ID_CONN_PARAM:
|
||||
status = wdxsDcGetConnParam(connId, len, pValue);
|
||||
break;
|
||||
|
||||
case WDX_DC_ID_CONN_SEC_LEVEL:
|
||||
status = wdxsDcGetSecurityLevel(connId, len, pValue);
|
||||
break;
|
||||
|
||||
case WDX_DC_ID_ATT_MTU:
|
||||
status = wdxsDcGetAttMtu(connId, len, pValue);
|
||||
break;
|
||||
|
||||
case WDX_DC_ID_BATTERY_LEVEL:
|
||||
status = wdxsDcGetBatteryLevel(connId, len, pValue);
|
||||
break;
|
||||
|
||||
case WDX_DC_ID_MODEL_NUMBER:
|
||||
status = wdxsDcGetDeviceModel(connId, len, pValue);
|
||||
break;
|
||||
|
||||
case WDX_DC_ID_FIRMWARE_REV:
|
||||
status = wdxsDcGetFirmwareRev(connId, len, pValue);
|
||||
break;
|
||||
|
||||
case WDX_DC_ID_PHY:
|
||||
/* if device configuration phy callback registered */
|
||||
if (wdxsDcCb.phyWriteCback != NULL)
|
||||
{
|
||||
status = (*wdxsDcCb.phyWriteCback)(connId, op, id, len, pValue);
|
||||
break;
|
||||
}
|
||||
/* else fall through */
|
||||
|
||||
default:
|
||||
status = ATT_ERR_RANGE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ATT_ERR_RANGE;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Register a PHY write callback for the device configuration characteristic.
|
||||
*
|
||||
* \param cback PHY callback function.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void wdxsDcPhyRegister(wdxsDcPhyWriteCback_t cback)
|
||||
{
|
||||
wdxsDcCb.phyWriteCback = cback;
|
||||
}
|
||||
|
||||
#endif /* WDXS_DC_ENABLED */
|
||||
Vendored
+518
@@ -0,0 +1,518 @@
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \brief Wireless Data Exchange profile implementation - File Transfer.
|
||||
*
|
||||
* Copyright (c) 2013-2018 Arm Ltd.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include "wsf_types.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "wsf_assert.h"
|
||||
#include "wsf_efs.h"
|
||||
#include "util/bstream.h"
|
||||
#include "svc_wdxs.h"
|
||||
#include "wdxs_api.h"
|
||||
#include "wdxs_main.h"
|
||||
#include "dm_api.h"
|
||||
#include "app_api.h"
|
||||
|
||||
/**************************************************************************************************
|
||||
Local Variables
|
||||
**************************************************************************************************/
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Read data from file.
|
||||
*
|
||||
* \return TRUE if EOF.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static bool_t wdxsFileRead(uint16_t handle, uint32_t offset, uint32_t *pReadLen, uint8_t *pData)
|
||||
{
|
||||
bool_t eof = FALSE;
|
||||
uint32_t fileSize = WsfEfsGetFileSize(handle);
|
||||
|
||||
if (fileSize && (offset + *pReadLen > fileSize))
|
||||
{
|
||||
*pReadLen = fileSize - offset;
|
||||
eof = TRUE;
|
||||
}
|
||||
|
||||
WsfEfsGet(handle, offset, pData, (uint16_t) *pReadLen);
|
||||
|
||||
return eof;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Prepare for FTD data.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t wdxsInitializeForPut(dmConnId_t connId, uint16_t handle)
|
||||
{
|
||||
uint32_t availableSize = WsfEfsGetFileMaxSize(handle);
|
||||
|
||||
/* verify file total length
|
||||
* verify offset+length is not more than total length
|
||||
*/
|
||||
if ((wdxsCb.ftTotalLen > availableSize) ||
|
||||
((wdxsCb.ftOffset + wdxsCb.ftLen) > wdxsCb.ftTotalLen))
|
||||
{
|
||||
return WDX_FTC_ST_INVALID_OP_DATA;
|
||||
}
|
||||
|
||||
/* Erase on offset of zero */
|
||||
if (wdxsCb.ftOffset == 0)
|
||||
{
|
||||
WsfEfsErase(handle);
|
||||
}
|
||||
|
||||
/* set up file put operation */
|
||||
wdxsCb.ftHandle = handle;
|
||||
wdxsCb.ftInProgress = WDX_FTC_OP_PUT_REQ;
|
||||
|
||||
return WDX_FTC_ST_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Send a file transfer control characteristic notification.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void wdxsFtcSend(dmConnId_t connId)
|
||||
{
|
||||
APP_TRACE_INFO0("WDXS: FTC Send");
|
||||
|
||||
/* if notification enabled */
|
||||
if (AttsCccEnabled(connId, wdxsCb.ftcCccIdx))
|
||||
{
|
||||
/* send notification */
|
||||
AttsHandleValueNtf(connId, WDXS_FTC_HDL, wdxsCb.ftcMsgLen, wdxsCb.ftcMsgBuf);
|
||||
wdxsCb.txReadyMask &= ~(WDXS_TX_MASK_FTC_BIT | WDXS_TX_MASK_READY_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Send a file transfer response message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void wdxsFtcSendRsp(dmConnId_t connId, uint8_t op, uint16_t handle, uint8_t status)
|
||||
{
|
||||
uint8_t *p;
|
||||
|
||||
/* there should not be another response message set up */
|
||||
if (wdxsCb.txReadyMask & WDXS_TX_MASK_FTC_BIT)
|
||||
{
|
||||
APP_TRACE_WARN0("WDXS: FTC message overflow");
|
||||
return;
|
||||
}
|
||||
|
||||
APP_TRACE_INFO3("WDXS: FTC SendRsp op=%d handle=%d status=%d", op, handle, status);
|
||||
|
||||
/* build message */
|
||||
p = wdxsCb.ftcMsgBuf;
|
||||
UINT8_TO_BSTREAM(p, op);
|
||||
UINT16_TO_BSTREAM(p, handle);
|
||||
|
||||
if (op != WDX_FTC_OP_ABORT && op != WDX_FTC_OP_EOF)
|
||||
{
|
||||
UINT8_TO_BSTREAM(p, status);
|
||||
}
|
||||
|
||||
if (op == WDX_FTC_OP_GET_RSP || op == WDX_FTC_OP_PUT_RSP)
|
||||
{
|
||||
UINT8_TO_BSTREAM(p, WDX_FTC_TRANSPORT_TYPE);
|
||||
UINT16_TO_BSTREAM(p, WDX_FTC_TRANSPORT_ID);
|
||||
}
|
||||
|
||||
wdxsCb.ftcMsgLen = (uint16_t) (p - wdxsCb.ftcMsgBuf);
|
||||
|
||||
/* Indicate TX Ready */
|
||||
wdxsCb.txReadyMask |= WDXS_TX_MASK_FTC_BIT;
|
||||
WsfSetEvent(wdxsCb.handlerId, WDXS_EVT_TX_PATH);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a file get request.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void wdxsFtcProcGetReq(dmConnId_t connId, uint16_t handle, uint16_t len, uint8_t *pValue)
|
||||
{
|
||||
uint8_t status;
|
||||
|
||||
APP_TRACE_INFO2("WDXS: FTC GetReq handle=%d len=%d", handle, len);
|
||||
|
||||
/* verify operation not already in progress */
|
||||
if (wdxsCb.ftInProgress != WDX_FTC_OP_NONE)
|
||||
{
|
||||
status = WDX_FTC_ST_IN_PROGRESS;
|
||||
}
|
||||
else if ((WsfEfsGetFilePermissions(handle) & WSF_EFS_REMOTE_GET_PERMITTED) == 0)
|
||||
{
|
||||
status = WDX_FTC_ST_INVALID_OP_FILE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (handle == WDX_FLIST_HANDLE)
|
||||
{
|
||||
WdxsUpdateListing();
|
||||
}
|
||||
|
||||
/* parse operation data */
|
||||
BSTREAM_TO_UINT32(wdxsCb.ftOffset, pValue);
|
||||
BSTREAM_TO_UINT32(wdxsCb.ftLen, pValue);
|
||||
BSTREAM_TO_UINT8(wdxsCb.ftPrefXferType, pValue);
|
||||
|
||||
/* set up file get operation */
|
||||
wdxsCb.ftHandle = handle;
|
||||
wdxsCb.ftInProgress = WDX_FTC_OP_GET_REQ;
|
||||
|
||||
wdxsCb.txReadyMask |= WDXS_TX_MASK_FTD_BIT;
|
||||
WsfSetEvent(wdxsCb.handlerId, WDXS_EVT_TX_PATH);
|
||||
|
||||
status = WDX_FTC_ST_SUCCESS;
|
||||
}
|
||||
|
||||
/* send response */
|
||||
wdxsFtcSendRsp(connId, WDX_FTC_OP_GET_RSP, handle, status);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a file put request.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void wdxsFtcProcPutReq(dmConnId_t connId, uint16_t handle, uint16_t len, uint8_t *pValue)
|
||||
{
|
||||
uint8_t status;
|
||||
|
||||
/* verify operation not already in progress */
|
||||
if (wdxsCb.ftInProgress != WDX_FTC_OP_NONE)
|
||||
{
|
||||
status = WDX_FTC_ST_IN_PROGRESS;
|
||||
}
|
||||
/* verify permissions */
|
||||
else if ((WsfEfsGetFilePermissions(handle) & WSF_EFS_REMOTE_PUT_PERMITTED) == 0)
|
||||
{
|
||||
status = WDX_FTC_ST_INVALID_HANDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* parse operation data */
|
||||
wdxsCb.ftHandle = handle;
|
||||
BSTREAM_TO_UINT32(wdxsCb.ftOffset, pValue);
|
||||
BSTREAM_TO_UINT32(wdxsCb.ftLen, pValue);
|
||||
BSTREAM_TO_UINT32(wdxsCb.ftTotalLen, pValue);
|
||||
BSTREAM_TO_UINT8(wdxsCb.ftPrefXferType, pValue);
|
||||
|
||||
APP_TRACE_INFO3("WDXS: FTC PutReq handle=%d offset=%d, len=%d", handle, wdxsCb.ftOffset, wdxsCb.ftLen);
|
||||
|
||||
/* Initialize transfer*/
|
||||
status = wdxsInitializeForPut(connId, handle);
|
||||
}
|
||||
|
||||
APP_TRACE_INFO2("WDXS: FTC PutReq handle=%d status=%d", handle, status);
|
||||
|
||||
/* send response */
|
||||
wdxsFtcSendRsp(connId, WDX_FTC_OP_PUT_RSP, handle, status);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a file verify request.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void wdxsFtcProcVerifyReq(dmConnId_t connId, uint16_t handle)
|
||||
{
|
||||
uint8_t status;
|
||||
|
||||
APP_TRACE_INFO1("WDXS: FTC VerifyReq: handle=%d", handle);
|
||||
|
||||
/* verify operation not already in progress */
|
||||
if (wdxsCb.ftInProgress != WDX_FTC_OP_NONE)
|
||||
{
|
||||
status = WDX_FTC_ST_IN_PROGRESS;
|
||||
}
|
||||
else if ((WsfEfsGetFilePermissions(handle) & WSF_EFS_REMOTE_VERIFY_PERMITTED) == 0)
|
||||
{
|
||||
status = WDX_FTC_ST_INVALID_HANDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Call the media specific validate command */
|
||||
status = WsfEfsMediaSpecificCommand(handle, WSF_EFS_VALIDATE_CMD, 0);
|
||||
}
|
||||
|
||||
/* send response */
|
||||
wdxsFtcSendRsp(connId, WDX_FTC_OP_VERIFY_RSP, handle, status);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a file erase request.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void wdxsFtcProcEraseReq(dmConnId_t connId, uint16_t handle)
|
||||
{
|
||||
uint8_t status = WDX_FTC_ST_SUCCESS;
|
||||
|
||||
APP_TRACE_INFO1("WDXS: FTC EraseReq: handle=%d", handle);
|
||||
|
||||
/* verify operation not already in progress */
|
||||
if (wdxsCb.ftInProgress != WDX_FTC_OP_NONE)
|
||||
{
|
||||
status = WDX_FTC_ST_IN_PROGRESS;
|
||||
}
|
||||
/* verify file handle */
|
||||
else if ((WsfEfsGetFilePermissions(handle) & WSF_EFS_REMOTE_ERASE_PERMITTED) == 0)
|
||||
{
|
||||
status = WDX_FTC_ST_INVALID_OP_FILE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* do file erase */
|
||||
WsfEfsErase(handle);
|
||||
}
|
||||
|
||||
/* send response */
|
||||
wdxsFtcSendRsp(connId, WDX_FTC_OP_ERASE_RSP, handle, status);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a file abort.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void wdxsFtcProcAbort(dmConnId_t connId, uint16_t handle)
|
||||
{
|
||||
APP_TRACE_INFO1("WDXS: FTC AbortReq: handle=%d", handle);
|
||||
|
||||
if (wdxsCb.ftInProgress != WDX_FTC_OP_NONE)
|
||||
{
|
||||
/* abort operation */
|
||||
if (WsfEfsGetFileType(handle) == WSF_EFS_FILE_TYPE_STREAM)
|
||||
{
|
||||
wdxsCb.ftInProgress = WDX_FTC_OP_ABORT;
|
||||
}
|
||||
else
|
||||
{
|
||||
wdxsCb.ftInProgress = WDX_FTC_OP_NONE;
|
||||
}
|
||||
|
||||
wdxsCb.ftLen = 0;
|
||||
wdxsCb.ftOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a write to the file transfer data characteristic.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t wdxsFtdWrite(dmConnId_t connId, uint16_t len, uint8_t *pValue)
|
||||
{
|
||||
/* verify put operation in progress */
|
||||
if (wdxsCb.ftInProgress != WDX_FTC_OP_PUT_REQ)
|
||||
{
|
||||
return ATT_ERR_UNLIKELY;
|
||||
}
|
||||
|
||||
/* verify data length */
|
||||
if (len <= WDX_FTD_HDR_LEN)
|
||||
{
|
||||
return ATT_ERR_LENGTH;
|
||||
}
|
||||
|
||||
/* verify more data is expected */
|
||||
if (wdxsCb.ftLen >= len)
|
||||
{
|
||||
WsfEfsPut(wdxsCb.ftHandle, wdxsCb.ftOffset, pValue, len);
|
||||
|
||||
/* update remaining length of put request */
|
||||
wdxsCb.ftOffset += len;
|
||||
wdxsCb.ftLen -= len;
|
||||
|
||||
/* if end of put req reached */
|
||||
if (wdxsCb.ftLen == 0)
|
||||
{
|
||||
if (wdxsCb.ftOffset == wdxsCb.ftTotalLen)
|
||||
{
|
||||
/* Call the media specific WDXS Put Complete command */
|
||||
WsfEfsMediaSpecificCommand(wdxsCb.ftHandle, WSF_EFS_WDXS_PUT_COMPLETE_CMD, wdxsCb.ftTotalLen);
|
||||
}
|
||||
|
||||
/* put req done */
|
||||
wdxsCb.ftInProgress = WDX_FTC_OP_NONE;
|
||||
|
||||
/* send eof */
|
||||
wdxsFtcSendRsp(connId, WDX_FTC_OP_EOF, wdxsCb.ftHandle, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return ATT_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a write to the file transfer control characteristic.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t wdxsFtcWrite(dmConnId_t connId, uint16_t len, uint8_t *pValue)
|
||||
{
|
||||
uint8_t op;
|
||||
uint16_t handle;
|
||||
|
||||
APP_TRACE_INFO1("WDXS: FTC Write: len=%d", len);
|
||||
|
||||
/* sanity check on message length */
|
||||
if (len < WDX_FTC_HDR_LEN + WDX_FTC_HANDLE_LEN)
|
||||
{
|
||||
return ATT_ERR_LENGTH;
|
||||
}
|
||||
|
||||
/* get operation and file handle */
|
||||
BSTREAM_TO_UINT8(op, pValue);
|
||||
BSTREAM_TO_UINT16(handle, pValue);
|
||||
|
||||
APP_TRACE_INFO2("WDXS: FTC Write: op=%d handle=%d", op, handle);
|
||||
|
||||
len -= WDX_FTC_HANDLE_LEN + WDX_FTC_HDR_LEN;
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case WDX_FTC_OP_GET_REQ:
|
||||
wdxsFtcProcGetReq(connId, handle, len, pValue);
|
||||
break;
|
||||
|
||||
case WDX_FTC_OP_PUT_REQ:
|
||||
wdxsFtcProcPutReq(connId, handle, len, pValue);
|
||||
break;
|
||||
|
||||
case WDX_FTC_OP_VERIFY_REQ:
|
||||
wdxsFtcProcVerifyReq(connId, handle);
|
||||
break;
|
||||
|
||||
case WDX_FTC_OP_ERASE_REQ:
|
||||
wdxsFtcProcEraseReq(connId, handle);
|
||||
break;
|
||||
|
||||
case WDX_FTC_OP_ABORT:
|
||||
wdxsFtcProcAbort(connId, handle);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ATT_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Send a file transfer data characteristic notification.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void wdxsFtdSend(dmConnId_t connId)
|
||||
{
|
||||
/* if notification enabled */
|
||||
if (AttsCccEnabled(connId, wdxsCb.ftdCccIdx))
|
||||
{
|
||||
uint8_t *pBuf;
|
||||
uint32_t readLen = AttGetMtu(connId) - ATT_VALUE_NTF_LEN;
|
||||
bool_t eof;
|
||||
uint8_t fileType = WsfEfsGetFileType(wdxsCb.ftHandle);
|
||||
|
||||
/* Check for abort when Streaming */
|
||||
if ((fileType == WSF_EFS_FILE_TYPE_STREAM) && (wdxsCb.ftInProgress == WDX_FTC_OP_ABORT))
|
||||
{
|
||||
eof = TRUE;
|
||||
readLen = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
eof = FALSE;
|
||||
}
|
||||
|
||||
readLen = (readLen < wdxsCb.ftLen) ? readLen : wdxsCb.ftLen;
|
||||
|
||||
if (readLen && (pBuf = AttMsgAlloc((uint16_t)readLen, ATT_PDU_VALUE_NTF)) != NULL)
|
||||
{
|
||||
/* read data from file */
|
||||
eof = wdxsFileRead(wdxsCb.ftHandle, wdxsCb.ftOffset, &readLen, pBuf);
|
||||
|
||||
if (readLen > 0)
|
||||
{
|
||||
/* update stored offset and length (non-streaming file) */
|
||||
if (fileType == WSF_EFS_FILE_TYPE_BULK)
|
||||
{
|
||||
wdxsCb.ftLen -= readLen;
|
||||
wdxsCb.ftOffset += readLen;
|
||||
}
|
||||
|
||||
/* send notification */
|
||||
AttsHandleValueNtfZeroCpy(connId, WDXS_FTD_HDL, (uint16_t)readLen, pBuf);
|
||||
wdxsCb.txReadyMask &= ~(WDXS_TX_MASK_READY_BIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
AttMsgFree(pBuf, ATT_PDU_VALUE_NTF);
|
||||
}
|
||||
}
|
||||
|
||||
/* check if end of transfer reached */
|
||||
if (wdxsCb.ftLen == 0 || readLen == 0 || eof || wdxsCb.ftInProgress == WDX_FTC_OP_ABORT)
|
||||
{
|
||||
wdxsCb.ftInProgress = WDX_FTC_OP_NONE;
|
||||
wdxsCb.txReadyMask &= ~(WDXS_TX_MASK_FTD_BIT);
|
||||
}
|
||||
|
||||
if (eof)
|
||||
{
|
||||
/* send EOF */
|
||||
wdxsFtcSendRsp(connId, WDX_FTC_OP_EOF, wdxsCb.ftHandle, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+539
@@ -0,0 +1,539 @@
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \brief Wireless Data Exchange profile implementation.
|
||||
*
|
||||
* Copyright (c) 2013-2018 Arm Ltd.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "wsf_types.h"
|
||||
#include "util/wstr.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "wsf_assert.h"
|
||||
#include "wsf_efs.h"
|
||||
#include "wsf_os.h"
|
||||
#include "sec_api.h"
|
||||
#include "util/bstream.h"
|
||||
#include "svc_wdxs.h"
|
||||
#include "wdxs_api.h"
|
||||
#include "wdxs_main.h"
|
||||
#include "dm_api.h"
|
||||
#include "att_api.h"
|
||||
#include "app_api.h"
|
||||
|
||||
/**************************************************************************************************
|
||||
Global Variables
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! application control block */
|
||||
wdxsCb_t wdxsCb;
|
||||
|
||||
/**************************************************************************************************
|
||||
Macros
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! RAM File Media Configuration */
|
||||
#define WDXS_RAM_LOCATION ((uint32_t)WdxsRamBlock)
|
||||
#define WDXS_RAM_SIZE (WDX_FLIST_MAX_LEN + WDXS_APP_RAM_MEDIA_SIZE)
|
||||
#define WDXS_RAM_END (WDXS_RAM_LOCATION + WDXS_RAM_SIZE)
|
||||
|
||||
/**************************************************************************************************
|
||||
Local Function Prototypes
|
||||
**************************************************************************************************/
|
||||
static uint8_t WdxsRamErase(uint32_t address, uint32_t size);
|
||||
static uint8_t WdxsRamRead(uint8_t *pBuf, uint32_t address, uint32_t size);
|
||||
static uint8_t WdxsRamWrite(const uint8_t *pBuf, uint32_t address, uint32_t size);
|
||||
|
||||
/**************************************************************************************************
|
||||
Function Prototypes
|
||||
**************************************************************************************************/
|
||||
void WdxsAuSecComplete(secAes_t *pAes);
|
||||
|
||||
/**************************************************************************************************
|
||||
Local Variables
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! Reserve RAM for use by the RAM EFS Media */
|
||||
static uint8_t WdxsRamBlock[WDXS_RAM_SIZE];
|
||||
|
||||
/*! EFS RAM Media Control Block */
|
||||
static const wsfEfsMedia_t WDXS_RamMediaCtrl =
|
||||
{
|
||||
WDXS_RAM_LOCATION,
|
||||
WDXS_RAM_LOCATION + WDXS_RAM_SIZE,
|
||||
1,
|
||||
NULL,
|
||||
WdxsRamErase,
|
||||
WdxsRamRead,
|
||||
WdxsRamWrite,
|
||||
NULL
|
||||
};
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Erase function for the EFS RAM media.
|
||||
*
|
||||
* \return none.
|
||||
*
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t WdxsRamErase(uint32_t address, uint32_t size)
|
||||
{
|
||||
uint8_t *pMem = (uint8_t *) address;
|
||||
memset(pMem, 0xFF, size);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Read function for the EFS RAM media.
|
||||
*
|
||||
* \return none.
|
||||
*
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t WdxsRamRead(uint8_t *pBuf, uint32_t address, uint32_t size)
|
||||
{
|
||||
uint8_t *pMem = (uint8_t *) address;
|
||||
memcpy(pBuf, pMem, size);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Write function for the EFS RAM media.
|
||||
*
|
||||
* \return none.
|
||||
*
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t WdxsRamWrite(const uint8_t *pBuf, uint32_t address, uint32_t size)
|
||||
{
|
||||
uint8_t *pMem = (uint8_t *) address;
|
||||
memcpy(pMem, pBuf, size);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Format file list information for the given file.
|
||||
*
|
||||
* \return none.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void wdxsFormatFileResource(uint8_t *pData, wsfEfsHandle_t handle)
|
||||
{
|
||||
UINT16_TO_BSTREAM(pData, handle);
|
||||
UINT8_TO_BSTREAM(pData, WsfEfsGetFileType(handle));
|
||||
UINT8_TO_BSTREAM(pData, WsfEfsGetFilePermissions(handle) & WSF_EFS_REMOTE_PERMISSIONS_MASK);
|
||||
UINT32_TO_BSTREAM(pData, WsfEfsGetFileSize(handle));
|
||||
WstrnCpy((char *)pData, WsfEfsGetFileName(handle), WSF_EFS_NAME_LEN);
|
||||
WstrnCpy((char *)pData+WSF_EFS_NAME_LEN, WsfEfsGetFileVersion(handle), WSF_EFS_VERSION_LEN);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Create the file list.
|
||||
*
|
||||
* \return none.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void WdxsUpdateListing(void)
|
||||
{
|
||||
uint8_t *pTmp;
|
||||
uint8_t header[WDX_FLIST_HDR_SIZE];
|
||||
uint8_t record[WDX_FLIST_RECORD_SIZE];
|
||||
uint32_t position = 0, totalSize = 0;
|
||||
uint32_t fileCount = 0;
|
||||
uint8_t i;
|
||||
|
||||
position = WDX_FLIST_HDR_SIZE;
|
||||
|
||||
for (i=0; i<WSF_EFS_MAX_FILES; i++)
|
||||
{
|
||||
if (WsfEfsGetFileByHandle(i) && (WsfEfsGetFilePermissions(i) & WSF_EFS_REMOTE_VISIBLE))
|
||||
{
|
||||
/* Update the total size and file count */
|
||||
totalSize += WsfEfsGetFileSize(i);
|
||||
fileCount++;
|
||||
|
||||
wdxsFormatFileResource(record, i);
|
||||
|
||||
/* Write the record */
|
||||
WsfEfsPut(WDX_FLIST_HANDLE, position, record, WDX_FLIST_RECORD_SIZE);
|
||||
position += WDX_FLIST_RECORD_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add the header after calculating the total_size and file_count */
|
||||
pTmp = header;
|
||||
UINT8_TO_BSTREAM(pTmp, WDX_FLIST_FORMAT_VER);
|
||||
UINT16_TO_BSTREAM(pTmp, fileCount);
|
||||
UINT32_TO_BSTREAM(pTmp, totalSize);
|
||||
|
||||
/* Write the header */
|
||||
WsfEfsPut(WDX_FLIST_HANDLE, 0, header, WDX_FLIST_HDR_SIZE);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Set the CCCD index used by the application for WDXS service characteristics.
|
||||
*
|
||||
* \param dcCccIdx Device Control CCCD index.
|
||||
* \param auCccIdx Authentication CCCD index.
|
||||
* \param ftcCccIdx File Transfer Control CCCD index.
|
||||
* \param ftdCccIdx File Transfer Data CCCD index.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void WdxsSetCccIdx(uint8_t dcCccIdx, uint8_t auCccIdx, uint8_t ftcCccIdx, uint8_t ftdCccIdx)
|
||||
{
|
||||
wdxsCb.dcCccIdx = dcCccIdx;
|
||||
wdxsCb.auCccIdx = auCccIdx;
|
||||
wdxsCb.ftcCccIdx = ftcCccIdx;
|
||||
wdxsCb.ftdCccIdx = ftdCccIdx;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief ATTS write callback for proprietary service.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t wdxsWriteCback(dmConnId_t connId, uint16_t handle, uint8_t operation,
|
||||
uint16_t offset, uint16_t len, uint8_t *pValue, attsAttr_t *pAttr)
|
||||
{
|
||||
uint8_t status;
|
||||
|
||||
#if WDXS_AU_ENABLED == TRUE
|
||||
|
||||
/* Require peer authentication before writing to any characteristic
|
||||
(except for the authentication characteristic) */
|
||||
if ((wdxsAuCb.reqAuthLevel != WDX_AU_LVL_NONE) && (handle != WDXS_AU_HDL))
|
||||
{
|
||||
if ((wdxsAuCb.authState != WDXS_AU_STATE_AUTHORIZED) || (wdxsAuCb.authLevel < wdxsAuCb.reqAuthLevel))
|
||||
{
|
||||
APP_TRACE_INFO1("WDXS: WriteCback unauthorized state=%d", wdxsAuCb.authState);
|
||||
return WDX_APP_AUTH_REQUIRED;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* WDXS_AU_ENABLED */
|
||||
|
||||
switch (handle)
|
||||
{
|
||||
#if WDXS_DC_ENABLED == TRUE
|
||||
/* Device configuration */
|
||||
case WDXS_DC_HDL:
|
||||
status = wdxsDcWrite(connId, len, pValue);
|
||||
break;
|
||||
#endif /* WDXS_DC_ENABLED */
|
||||
|
||||
/* File transfer control */
|
||||
case WDXS_FTC_HDL:
|
||||
status = wdxsFtcWrite(connId, len, pValue);
|
||||
break;
|
||||
|
||||
/* File transfer data */
|
||||
case WDXS_FTD_HDL:
|
||||
status = wdxsFtdWrite(connId, len, pValue);
|
||||
break;
|
||||
|
||||
#if WDXS_AU_ENABLED == TRUE
|
||||
/* Authentication */
|
||||
case WDXS_AU_HDL:
|
||||
status = wdxsAuWrite(connId, len, pValue);
|
||||
break;
|
||||
#endif /* WDXS_AU_ENABLED */
|
||||
|
||||
default:
|
||||
APP_TRACE_INFO1("WDXS: WriteCback unexpected handle=%d", handle);
|
||||
status = ATT_ERR_HANDLE;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process TX data path
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static void wdxsProcTxPath(void)
|
||||
{
|
||||
dmConnId_t connId;
|
||||
|
||||
/* Check for a connection */
|
||||
if ((connId = AppConnIsOpen()) != DM_CONN_ID_NONE)
|
||||
{
|
||||
/* Check if ready to transmit a message */
|
||||
if (wdxsCb.txReadyMask & WDXS_TX_MASK_READY_BIT)
|
||||
{
|
||||
|
||||
#if WDXS_DC_ENABLED == TRUE
|
||||
/* Device configuration */
|
||||
if (wdxsCb.txReadyMask & WDXS_TX_MASK_DC_BIT)
|
||||
{
|
||||
wdxsDcSend(connId);
|
||||
return;
|
||||
}
|
||||
#endif /* WDXS_DC_ENABLED */
|
||||
|
||||
/* File Transfer Control */
|
||||
if (wdxsCb.txReadyMask & WDXS_TX_MASK_FTC_BIT)
|
||||
{
|
||||
wdxsFtcSend(connId);
|
||||
return;
|
||||
}
|
||||
|
||||
#if WDXS_AU_ENABLED == TRUE
|
||||
/* Authentication */
|
||||
if (wdxsCb.txReadyMask & WDXS_TX_MASK_AU_BIT)
|
||||
{
|
||||
wdxsAuSend(connId);
|
||||
return;
|
||||
}
|
||||
#endif /* WDXS_AU_ENABLED */
|
||||
|
||||
/* File Transfer Data */
|
||||
if (wdxsCb.txReadyMask & WDXS_TX_MASK_FTD_BIT)
|
||||
{
|
||||
wdxsFtdSend(connId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief WSF event handler for application.
|
||||
*
|
||||
* \param event WSF event mask.
|
||||
* \param pMsg WSF message.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void WdxsHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg)
|
||||
{
|
||||
APP_TRACE_INFO1("WDXS: Task Handler Evt=%d", event);
|
||||
|
||||
if (event & WDXS_EVT_TX_PATH)
|
||||
{
|
||||
wdxsProcTxPath();
|
||||
}
|
||||
|
||||
#if WDXS_AU_ENABLED == TRUE
|
||||
|
||||
if (event & WDXS_EVT_AU_SEC_COMPLETE)
|
||||
{
|
||||
WdxsAuSecComplete((secAes_t*) pMsg);
|
||||
}
|
||||
|
||||
#endif /* WDXS_AU_ENABLED */
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Called by application to notify the WDXS of DM Events.
|
||||
*
|
||||
* \param pEvt Pointer to the DM Event
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void WdxsProcDmMsg(dmEvt_t *pEvt)
|
||||
{
|
||||
switch (pEvt->hdr.event)
|
||||
{
|
||||
case DM_CONN_CLOSE_IND:
|
||||
if (wdxsDcCb.doReset)
|
||||
{
|
||||
WdxsResetSystem();
|
||||
}
|
||||
break;
|
||||
|
||||
case DM_CONN_OPEN_IND:
|
||||
/* Initialize connection parameters */
|
||||
wdxsCb.txReadyMask = WDXS_TX_MASK_READY_BIT;
|
||||
wdxsCb.ftInProgress = WDX_FTC_OP_NONE;
|
||||
wdxsCb.ftLen = 0;
|
||||
wdxsCb.ftOffset = 0;
|
||||
#if WDXS_AU_ENABLED == TRUE
|
||||
wdxsAuCb.authLevel = WDX_AU_LVL_NONE;
|
||||
wdxsAuCb.authState = WDXS_AU_STATE_UNAUTHORIZED;
|
||||
#endif /* WDXS_AU_ENABLED */
|
||||
wdxsCb.connInterval = pEvt->connOpen.connInterval;
|
||||
wdxsCb.connLatency = pEvt->connOpen.connLatency;
|
||||
wdxsCb.supTimeout = pEvt->connOpen.supTimeout;
|
||||
wdxsCb.txPhy= HCI_PHY_LE_1M_BIT;
|
||||
wdxsCb.rxPhy = HCI_PHY_LE_1M_BIT;
|
||||
break;
|
||||
|
||||
case DM_CONN_UPDATE_IND:
|
||||
if (pEvt->hdr.status == HCI_SUCCESS)
|
||||
{
|
||||
wdxsCb.connInterval = pEvt->connUpdate.connInterval;
|
||||
wdxsCb.connLatency = pEvt->connUpdate.connLatency;
|
||||
wdxsCb.supTimeout = pEvt->connUpdate.supTimeout;
|
||||
}
|
||||
wdxsDcUpdateConnParam((dmConnId_t) pEvt->hdr.param, pEvt->hdr.status);
|
||||
break;
|
||||
|
||||
case DM_PHY_UPDATE_IND:
|
||||
if (pEvt->hdr.status == HCI_SUCCESS)
|
||||
{
|
||||
wdxsCb.txPhy = pEvt->phyUpdate.txPhy;
|
||||
wdxsCb.rxPhy = pEvt->phyUpdate.rxPhy;
|
||||
}
|
||||
wdxsDcUpdatePhy((dmConnId_t) pEvt->hdr.param, pEvt->hdr.status);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Called by application to notify the WDXS of ATT Events.
|
||||
*
|
||||
* \param pEvt Pointer to the ATT Event
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t WdxsAttCback(attEvt_t *pEvt)
|
||||
{
|
||||
if (pEvt->handle < WDXS_START_HDL || pEvt->handle > WDXS_END_HDL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
APP_TRACE_INFO2("WDXS: AttHook handle=%d event=%d", pEvt->handle, pEvt->hdr.event);
|
||||
|
||||
/* trigger tx data path on confirm */
|
||||
if (pEvt->hdr.event == ATTS_HANDLE_VALUE_CNF &&
|
||||
pEvt->hdr.status == ATT_SUCCESS)
|
||||
{
|
||||
wdxsCb.txReadyMask |= WDXS_TX_MASK_READY_BIT;
|
||||
WsfSetEvent(wdxsCb.handlerId, WDXS_EVT_TX_PATH);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Application handler init function called during system initialization.
|
||||
*
|
||||
* \param handlerID WSF handler ID.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void WdxsHandlerInit(wsfHandlerId_t handlerId)
|
||||
{
|
||||
wsfEsfAttributes_t attr;
|
||||
|
||||
APP_TRACE_INFO0("WDXS: WdxsHandlerInit");
|
||||
|
||||
/* Initialize the control block */
|
||||
memset(&wdxsCb, 0, sizeof(wdxsCb));
|
||||
wdxsCb.txReadyMask = WDXS_TX_MASK_READY_BIT;
|
||||
|
||||
/* Store Handler ID */
|
||||
wdxsCb.handlerId = handlerId;
|
||||
|
||||
/* Initialize the device configuration control block */
|
||||
memset(&wdxsDcCb, 0, sizeof(wdxsDcCb));
|
||||
|
||||
/* Register the WDXS Service */
|
||||
SvcWdxsRegister(wdxsWriteCback);
|
||||
SvcWdxsAddGroup();
|
||||
|
||||
/* Initialize the embedded file system */
|
||||
WsfEfsInit();
|
||||
|
||||
/* Register the RAM Media */
|
||||
memset(WdxsRamBlock, 0xFF, sizeof(WdxsRamBlock));
|
||||
WsfEfsRegisterMedia(&WDXS_RamMediaCtrl, WDX_RAM_MEDIA);
|
||||
|
||||
/* Set attributes for the WDXS File List */
|
||||
attr.type = WSF_EFS_FILE_TYPE_BULK;
|
||||
attr.permissions = WSF_EFS_LOCAL_PUT_PERMITTED | WSF_EFS_REMOTE_GET_PERMITTED;
|
||||
WstrnCpy(attr.name, "Listing", WSF_EFS_NAME_LEN);
|
||||
WstrnCpy(attr.version, "1.0", WSF_EFS_VERSION_LEN);
|
||||
|
||||
/* Create a file in RAM to contain the list WDXS File List */
|
||||
WsfEfsAddFile(WDX_FLIST_MAX_LEN, WDX_RAM_MEDIA, &attr, WSF_EFS_FILE_OFFSET_ANY);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn WdxsOtaMediaInit
|
||||
*
|
||||
* \brief Registers the platform dependent OTA Media with the Embedded File System (EFS)
|
||||
*
|
||||
* \param None
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void WdxsOtaMediaInit(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn WdxsResetSystem
|
||||
*
|
||||
* \brief Resets the system.
|
||||
*
|
||||
* \param None
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void WdxsResetSystem(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \fn WdxsFlashMediaInit
|
||||
*
|
||||
* \brief Registers the platform dependent Flash Media with the Embedded File System (EFS)
|
||||
*
|
||||
* \param None
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void WdxsFlashMediaInit(void)
|
||||
{
|
||||
}
|
||||
Vendored
+327
@@ -0,0 +1,327 @@
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \brief Wireless Data Exchange profile implementation.
|
||||
*
|
||||
* Copyright (c) 2013-2018 Arm Ltd.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
|
||||
#ifndef WDXS_MAIN_H
|
||||
#define WDXS_MAIN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*! \addtogroup WIRELESS_DATA_EXCHANGE_PROFILE
|
||||
* \{ */
|
||||
|
||||
/**************************************************************************************************
|
||||
Macros
|
||||
**************************************************************************************************/
|
||||
|
||||
/** \name WDXS Default Feature Set
|
||||
*
|
||||
*/
|
||||
/**@{*/
|
||||
#ifndef WDXS_DC_ENABLED
|
||||
#define WDXS_DC_ENABLED TRUE
|
||||
#endif
|
||||
|
||||
#ifndef WDXS_AU_ENABLED
|
||||
#define WDXS_AU_ENABLED TRUE
|
||||
#endif
|
||||
|
||||
#ifndef WDXS_OTA_ENABLED
|
||||
#define WDXS_OTA_ENABLED TRUE
|
||||
#endif
|
||||
/**@}*/
|
||||
|
||||
/*! \brief Special length for streaming file */
|
||||
#define WDXS_STREAM_FILE_LEN 0xFFFFFFFF
|
||||
|
||||
/** \name WSF event types for application event handler
|
||||
*
|
||||
*/
|
||||
/**@{*/
|
||||
#define WDXS_EVT_TX_PATH 0x01 /*!< \brief Trigger tx data path */
|
||||
#define WDXS_EVT_AU_SEC_COMPLETE 0x02 /*!< \brief AU encryption of challenge ready */
|
||||
/**@}*/
|
||||
|
||||
/** \name TX Ready Mask Bits
|
||||
*
|
||||
*/
|
||||
/**@{*/
|
||||
#define WDXS_TX_MASK_READY_BIT (1<<0) /*!< \brief Ready bit */
|
||||
#define WDXS_TX_MASK_DC_BIT (1<<1) /*!< \brief DC bit */
|
||||
#define WDXS_TX_MASK_FTC_BIT (1<<2) /*!< \brief FTC bit */
|
||||
#define WDXS_TX_MASK_FTD_BIT (1<<3) /*!< \brief FTD bit */
|
||||
#define WDXS_TX_MASK_AU_BIT (1<<4) /*!< \brief AU bit */
|
||||
/**@}*/
|
||||
|
||||
/** \name Authentication states
|
||||
*
|
||||
*/
|
||||
/**@{*/
|
||||
#define WDXS_AU_STATE_UNAUTHORIZED 0x00 /*!< \brief Authentication has not started */
|
||||
#define WDXS_AU_STATE_HASHING 0x01 /*!< \brief Authentication hash is being calculated */
|
||||
#define WDXS_AU_STATE_WAIT_SEC 0x02 /*!< \brief Authentication challenge sent */
|
||||
#define WDXS_AU_STATE_WAIT_REPLY 0x03 /*!< \brief Authentication waiting for challenge reply */
|
||||
#define WDXS_AU_STATE_AUTHORIZED 0x04 /*!< \brief Authentication completed successfully */
|
||||
/**@}*/
|
||||
|
||||
/**************************************************************************************************
|
||||
Data Types
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! \brief WDXS Device Configuration PHY Write Callback */
|
||||
typedef uint8_t (*wdxsDcPhyWriteCback_t)(dmConnId_t connId, uint8_t op, uint8_t id, uint16_t len,
|
||||
uint8_t *pValue);
|
||||
|
||||
/**************************************************************************************************
|
||||
Local Variables
|
||||
**************************************************************************************************/
|
||||
|
||||
/*! \brief WDXS profile control block */
|
||||
typedef struct
|
||||
{
|
||||
wsfHandlerId_t handlerId; /*!< \brief WSF handler ID */
|
||||
uint8_t txReadyMask; /*!< \brief Bits indicate DC, FTC, FTD, and/or AU wish to transmit */
|
||||
|
||||
/* connection parameters */
|
||||
uint16_t connInterval; /*!< \brief connection interval */
|
||||
uint16_t connLatency; /*!< \brief connection latency */
|
||||
uint16_t supTimeout; /*!< \brief supervision timeout */
|
||||
|
||||
/* Phy parameters */
|
||||
uint8_t txPhy; /*!< \brief transmitter PHY */
|
||||
uint8_t rxPhy; /*!< \brief receiver PHY */
|
||||
|
||||
/* for file transfer */
|
||||
uint32_t ftOffset; /*!< \brief file data offset */
|
||||
uint32_t ftLen; /*!< \brief remaining data length for current operation */
|
||||
uint32_t ftTotalLen; /*!< \brief file total length */
|
||||
uint16_t ftHandle; /*!< \brief file handle */
|
||||
uint16_t ftcMsgLen; /*!< \brief message length */
|
||||
uint8_t ftcMsgBuf[ATT_DEFAULT_PAYLOAD_LEN]; /*!< \brief message buffer */
|
||||
uint8_t ftInProgress; /*!< \brief operation in progress */
|
||||
uint8_t ftPrefXferType; /*!< \brief Preferred transport type */
|
||||
|
||||
/* ccc index */
|
||||
uint8_t dcCccIdx; /*!< \brief device configuration ccc index */
|
||||
uint8_t auCccIdx; /*!< \brief authentication ccc index */
|
||||
uint8_t ftcCccIdx; /*!< \brief file transfer control ccc index */
|
||||
uint8_t ftdCccIdx; /*!< \brief file transfer data ccc index */
|
||||
} wdxsCb_t;
|
||||
|
||||
/*! \brief WDXS Device Configuration Control Block */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t dcMsgLen; /*!< \brief message length */
|
||||
uint8_t dcMsgBuf[ATT_DEFAULT_PAYLOAD_LEN]; /*!< \brief message buffer */
|
||||
bool_t doReset; /*!< \brief Reset device after disconnect */
|
||||
wdxsDcPhyWriteCback_t phyWriteCback; /*!< \brief Device config PHY write callback */
|
||||
} wdxsDcCb_t;
|
||||
|
||||
/*! \brief WDXS Authentication Control Block */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t auMsgBuf[ATT_DEFAULT_PAYLOAD_LEN]; /*!< \brief message buffer */
|
||||
uint8_t auRand[WDX_AU_RAND_LEN]; /*!< \brief random challenge */
|
||||
uint8_t sessionKey[WDX_AU_KEY_LEN]; /*!< \brief session key */
|
||||
uint8_t auHash[WDX_AU_HASH_LEN]; /*!< \brief session key */
|
||||
uint16_t auMsgLen; /*!< \brief message length */
|
||||
uint8_t authLevel; /*!< \brief current authentication level */
|
||||
uint8_t authMode; /*!< \brief current authentication mode */
|
||||
uint8_t reqAuthLevel; /*!< \brief requested authentication level */
|
||||
uint8_t authState; /*!< \brief authentication protocol state */
|
||||
} wdxsAuCb_t;
|
||||
|
||||
/*! \brief WDXS event message union */
|
||||
typedef union
|
||||
{
|
||||
wsfMsgHdr_t hdr; /*!< header */
|
||||
dmEvt_t dm; /*!< DM event */
|
||||
attsCccEvt_t ccc; /*!< ATT CCC event */
|
||||
} wdxsMsg_t;
|
||||
|
||||
/**************************************************************************************************
|
||||
Global Variables
|
||||
**************************************************************************************************/
|
||||
|
||||
/** \name WDXS Control Block External Declaration
|
||||
*
|
||||
*/
|
||||
/**@{*/
|
||||
extern wdxsCb_t wdxsCb; /*!< \brief WDXS control block */
|
||||
extern wdxsAuCb_t wdxsAuCb; /*!< \brief WDXS AU control block */
|
||||
extern wdxsDcCb_t wdxsDcCb; /*!< \brief WDXS DC control block */
|
||||
/**@}*/
|
||||
|
||||
/**************************************************************************************************
|
||||
Global Function Prototypes
|
||||
**************************************************************************************************/
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Send device configuration notification
|
||||
*
|
||||
* \param connId DM connection identifier.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void wdxsDcSend(dmConnId_t connId);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Send a file transfer control characteristic notification.
|
||||
*
|
||||
* \param connId DM connection identifier.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void wdxsFtcSend(dmConnId_t connId);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Send a file transfer data characteristic notification.
|
||||
*
|
||||
* \param connId DM connection identifier.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void wdxsFtdSend(dmConnId_t connId);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Transmit to authentication characteristic.
|
||||
*
|
||||
* \param connId DM connection identifier.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void wdxsAuSend(dmConnId_t connId);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a write to the device configuration characteristic.
|
||||
*
|
||||
* \param connId DM connection identifier.
|
||||
* \param len Length to write.
|
||||
* \param pValue value to write.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t wdxsDcWrite(dmConnId_t connId, uint16_t len, uint8_t *pValue);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a write to the file transfer control characteristic.
|
||||
*
|
||||
* \param connId DM connection identifier.
|
||||
* \param len Length to write.
|
||||
* \param pValue Value to write.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t wdxsFtcWrite(dmConnId_t connId, uint16_t len, uint8_t *pValue);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a write to the file transfer data characteristic.
|
||||
*
|
||||
* \param connId DM connection identifier.
|
||||
* \param len Length to write.
|
||||
* \param pValue Value to write.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t wdxsFtdWrite(dmConnId_t connId, uint16_t len, uint8_t *pValue);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a write to the authentication characteristic.
|
||||
*
|
||||
* \param connId DM connection identifier.
|
||||
* \param len Length to write.
|
||||
* \param pValue Value to write
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t wdxsAuWrite(dmConnId_t connId, uint16_t len, uint8_t *pValue);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Send update message for connection parameters.
|
||||
*
|
||||
* \param connId DM connection identifier.
|
||||
* \param status Update status.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t wdxsDcUpdateConnParam(dmConnId_t connId, uint8_t status);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Send update message for PHY.
|
||||
*
|
||||
* \param connId DM connection identifier.
|
||||
* \param status Update status.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t wdxsDcUpdatePhy(dmConnId_t connId, uint8_t status);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Register a PHY write callback for the device configuration characteristic.
|
||||
*
|
||||
* \param cback PHY callback function.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void wdxsDcPhyRegister(wdxsDcPhyWriteCback_t cback);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Create the file list.
|
||||
*
|
||||
* \return none.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void WdxsUpdateListing(void);
|
||||
|
||||
/*! \} */ /* WIRELESS_DATA_EXCHANGE_PROFILE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WDXS_MAIN_H */
|
||||
Vendored
+147
@@ -0,0 +1,147 @@
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \brief Wireless Data Exchange profile implementation - Device PHY Configuration.
|
||||
*
|
||||
* Copyright (c) 2013-2018 Arm Ltd.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "wsf_types.h"
|
||||
#include "util/wstr.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "wsf_assert.h"
|
||||
#include "wsf_efs.h"
|
||||
#include "util/bstream.h"
|
||||
#include "svc_wdxs.h"
|
||||
#include "wdxs_api.h"
|
||||
#include "wdxs_main.h"
|
||||
#include "dm_api.h"
|
||||
#include "app_api.h"
|
||||
#include "app_hw.h"
|
||||
|
||||
#if WDXS_DC_ENABLED == TRUE
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process set PHY request.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t wdxsDcSetPhyReq(dmConnId_t connId, uint16_t len, uint8_t *pValue)
|
||||
{
|
||||
uint8_t allPhys;
|
||||
uint8_t txPhys;
|
||||
uint8_t rxPhys;
|
||||
uint16_t phyOptions;
|
||||
|
||||
/* verify parameter length */
|
||||
if (len != WDX_DC_LEN_PHY_UPDATE_REQ)
|
||||
{
|
||||
return ATT_ERR_LENGTH;
|
||||
}
|
||||
|
||||
/* parse parameters */
|
||||
BSTREAM_TO_UINT8(allPhys, pValue);
|
||||
BSTREAM_TO_UINT8(txPhys, pValue);
|
||||
BSTREAM_TO_UINT8(rxPhys, pValue);
|
||||
BSTREAM_TO_UINT16(phyOptions, pValue);
|
||||
|
||||
/* request update to PHY */
|
||||
DmSetPhy(connId, allPhys, txPhys, rxPhys, phyOptions);
|
||||
|
||||
return ATT_SUCCESS;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a Get PHY request.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t wdxsDcGetPhy(dmConnId_t connId, uint16_t len, uint8_t *pValue)
|
||||
{
|
||||
return wdxsDcUpdatePhy(connId, HCI_SUCCESS);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Process a PHY write to the device configuration characteristic.
|
||||
*
|
||||
* \return ATT status.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t wdxsDcPhyWrite(dmConnId_t connId, uint8_t op, uint8_t id, uint16_t len, uint8_t *pValue)
|
||||
{
|
||||
uint8_t status;
|
||||
|
||||
/* set operation */
|
||||
if (op == WDX_DC_OP_SET)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case WDX_DC_ID_PHY_UPDATE_REQ:
|
||||
status = wdxsDcSetPhyReq(connId, len, pValue);
|
||||
break;
|
||||
|
||||
default:
|
||||
status = ATT_ERR_RANGE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* get operation */
|
||||
else if (op == WDX_DC_OP_GET)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case WDX_DC_ID_PHY:
|
||||
status = wdxsDcGetPhy(connId, len, pValue);
|
||||
break;
|
||||
|
||||
default:
|
||||
status = ATT_ERR_RANGE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ATT_ERR_RANGE;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Initialize WDXS Device Configuration PHY.
|
||||
*
|
||||
* \param None
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void WdxsPhyInit(void)
|
||||
{
|
||||
/* register device configuration phy write callback */
|
||||
wdxsDcPhyRegister(wdxsDcPhyWrite);
|
||||
}
|
||||
|
||||
#endif /* WDXS_DC_ENABLED */
|
||||
+264
@@ -0,0 +1,264 @@
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \brief Wireless Data Exchange profile implementation - Stream Example.
|
||||
*
|
||||
* Copyright (c) 2013-2018 Arm Ltd.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "wsf_types.h"
|
||||
#include "util/wstr.h"
|
||||
#include "wsf_trace.h"
|
||||
#include "wsf_assert.h"
|
||||
#include "wsf_efs.h"
|
||||
#include "util/bstream.h"
|
||||
#include "svc_wdxs.h"
|
||||
#include "wdxs_api.h"
|
||||
#include "wdxs_main.h"
|
||||
#include "wdxs_stream.h"
|
||||
#include "dm_api.h"
|
||||
#include "att_api.h"
|
||||
#include "app_api.h"
|
||||
|
||||
/*! Type of waveform to output from the Example Stream */
|
||||
static uint8_t wdxsStreamWaveform = WDXS_STREAM_WAVEFORM_SINE;
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*
|
||||
* Note: This file contains an example of creating Wireless Data Exchange
|
||||
* (WDXS) Streams. WDXS Streams are implemented as virtual Physical Media in
|
||||
* the Embedded File System (EFS). A Stream can be created in three steps:
|
||||
*
|
||||
* Step 1: Create a FileMedia_t (EFS Media Control structure) for the stream
|
||||
* containing the read function created in step 2.
|
||||
*
|
||||
* Step 2: Implement a read function for the stream. The WDXS and EFS will
|
||||
* call the read function to get data from the stream.
|
||||
*
|
||||
* Step 3: Register the media with the EFS, and add a file to the embedded
|
||||
* file system that uses the media created in step 2.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
|
||||
/*************************************************************************************************/
|
||||
/* Step 1: Media Control Block */
|
||||
/*************************************************************************************************/
|
||||
|
||||
/* Prototype of stream read function */
|
||||
static uint8_t wdxsStreamRead(uint8_t *pBuf, uint32_t address, uint32_t len);
|
||||
|
||||
/* Example media control structure for a stream */
|
||||
static const wsfEfsMedia_t WDXS_StreamMedia =
|
||||
{
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
wdxsStreamRead,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
/*************************************************************************************************/
|
||||
/* Step 2: Read Function */
|
||||
/*************************************************************************************************/
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Example of a media read function that generates a Sine Wave.
|
||||
*
|
||||
* \param pBuf buffer to hold stream data.
|
||||
* \param address unused in streams.
|
||||
* \param len size of pBuf in bytes.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t wdxsSineRead(uint8_t *pBuf, uint32_t address, uint32_t len)
|
||||
{
|
||||
static int8_t incr = 1;
|
||||
static uint8_t dataVal = 0;
|
||||
|
||||
/* Build data in sine waveform */
|
||||
memset(pBuf, dataVal, len);
|
||||
|
||||
if (dataVal <= 127)
|
||||
{
|
||||
incr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
incr--;
|
||||
}
|
||||
|
||||
dataVal += (incr / 2);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Example of a media read function that generates a Step Wave.
|
||||
*
|
||||
* \param pBuf buffer to hold stream data.
|
||||
* \param address unused in streams.
|
||||
* \param len size of pBuf in bytes.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t wdxsStepRead(uint8_t *pBuf, uint32_t address, uint32_t len)
|
||||
{
|
||||
static int8_t count = 0;
|
||||
static int8_t incr = 25;
|
||||
static uint8_t dataVal = 0;
|
||||
|
||||
/* Build data in step waveform */
|
||||
memset(pBuf, dataVal, len);
|
||||
|
||||
if (count++ == 5)
|
||||
{
|
||||
count = 0;
|
||||
dataVal += incr;
|
||||
|
||||
if (dataVal == 0)
|
||||
incr = 25;
|
||||
|
||||
if (dataVal == 250)
|
||||
incr = -25;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Example of a media read function that generates a Sawtooth Wave.
|
||||
*
|
||||
* \param pBuf buffer to hold stream data.
|
||||
* \param address unused in streams.
|
||||
* \param len size of pBuf in bytes.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t wdxsSawtoothRead(uint8_t *pBuf, uint32_t address, uint32_t len)
|
||||
{
|
||||
static int8_t incr = 1;
|
||||
static uint8_t dataVal = 0;
|
||||
uint32_t i;
|
||||
|
||||
/* Build data in sawtooth waveform */
|
||||
for (i=0; i<len; i++)
|
||||
{
|
||||
*pBuf++ = dataVal;
|
||||
dataVal += incr;
|
||||
|
||||
if (dataVal == 0)
|
||||
incr = 1;
|
||||
else if (dataVal == 255)
|
||||
incr = -1;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Example of a media read function.
|
||||
*
|
||||
* \param pBuf buffer to hold stream data.
|
||||
* \param address unused in streams.
|
||||
* \param len size of pBuf in bytes.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
static uint8_t wdxsStreamRead(uint8_t *pBuf, uint32_t address, uint32_t len)
|
||||
{
|
||||
switch(wdxsStreamWaveform)
|
||||
{
|
||||
case WDXS_STREAM_WAVEFORM_SINE:
|
||||
wdxsSineRead(pBuf, address, len);
|
||||
break;
|
||||
|
||||
case WDXS_STREAM_WAVEFORM_STEP:
|
||||
wdxsStepRead(pBuf, address, len);
|
||||
break;
|
||||
|
||||
case WDXS_STREAM_WAVEFORM_SAWTOOTH:
|
||||
wdxsSawtoothRead(pBuf, address, len);
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/* Step 3: Register the stream media and adding the stream file. */
|
||||
/*************************************************************************************************/
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Example of creating a WDXS stream.
|
||||
*
|
||||
* \param none
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void wdxsStreamInit(void)
|
||||
{
|
||||
wsfEsfAttributes_t attr;
|
||||
|
||||
/* Register the media for the stream */
|
||||
WsfEfsRegisterMedia(&WDXS_StreamMedia, WDX_STREAM_MEDIA);
|
||||
|
||||
/* Set the attributes for the stream */
|
||||
attr.permissions = WSF_EFS_REMOTE_VISIBLE | WSF_EFS_REMOTE_GET_PERMITTED;
|
||||
attr.type = WSF_EFS_FILE_TYPE_STREAM;
|
||||
|
||||
/* Potential buffer overrun is intentional to zero out fixed length field */
|
||||
/* coverity[overrun-buffer-arg] */
|
||||
WstrnCpy(attr.name, "Stream", WSF_EFS_NAME_LEN);
|
||||
/* coverity[overrun-buffer-arg] */
|
||||
WstrnCpy(attr.version, "1.0", WSF_EFS_VERSION_LEN);
|
||||
|
||||
/* Add a file for the stream */
|
||||
WsfEfsAddFile(0, WDX_STREAM_MEDIA, &attr, 0);
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Changes the type of waveform transmitted by the stream.
|
||||
*
|
||||
* \param type - Identifier of the waveform
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void wdxsSetStreamWaveform(uint8_t type)
|
||||
{
|
||||
if (type <= WDXS_STREAM_WAVEFORM_SAWTOOTH)
|
||||
{
|
||||
wdxsStreamWaveform = type;
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \file
|
||||
*
|
||||
* \brief Wireless Data Exchange profile implementation - Stream Example.
|
||||
*
|
||||
* Copyright (c) 2013-2018 Arm Ltd.
|
||||
*
|
||||
* Copyright (c) 2019 Packetcraft, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
|
||||
#ifndef WDXS_STREAM_H
|
||||
#define WDXS_STREAM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*! \addtogroup WIRELESS_DATA_EXCHANGE_PROFILE
|
||||
* \{ */
|
||||
|
||||
/**************************************************************************************************
|
||||
Constant Definitions
|
||||
**************************************************************************************************/
|
||||
|
||||
/** \name WDXS Stream Waveform Types
|
||||
* Type of waveform to output from the Example Stream
|
||||
*/
|
||||
/**@{*/
|
||||
#define WDXS_STREAM_WAVEFORM_SINE 0
|
||||
#define WDXS_STREAM_WAVEFORM_STEP 1
|
||||
#define WDXS_STREAM_WAVEFORM_SAWTOOTH 2
|
||||
/**@}*/
|
||||
|
||||
/**************************************************************************************************
|
||||
Function Declarations
|
||||
**************************************************************************************************/
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Example of creating a WDXS stream.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void wdxsStreamInit(void);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Changes the type of waveform transmitted by the stream.
|
||||
*
|
||||
* \param type - Identifier of the waveform
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void wdxsSetStreamWaveform(uint8_t type);
|
||||
|
||||
/*! \} */ /* WIRELESS_DATA_EXCHANGE_PROFILE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WDXS_STREAM_H */
|
||||
|
||||
Reference in New Issue
Block a user