initial commit
This commit is contained in:
@@ -0,0 +1,423 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file amdtp_common.c
|
||||
//!
|
||||
//! @brief This file provides the shared functions for the AMDTP service.
|
||||
//!
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "amdtp_common.h"
|
||||
#include "amota_crc32.h"
|
||||
#include "am_util.h"
|
||||
|
||||
extern void amdtps_timeout_timer_expired(void *data, UINT16 datalen);
|
||||
|
||||
void
|
||||
resetPkt(amdtpPacket_t *pkt)
|
||||
{
|
||||
pkt->offset = 0;
|
||||
pkt->header.pktType = AMDTP_PKT_TYPE_UNKNOWN;
|
||||
pkt->len = 0;
|
||||
}
|
||||
|
||||
eAmdtpStatus_t
|
||||
AmdtpReceivePkt(amdtpCb_t *amdtpCb, amdtpPacket_t *pkt, uint16_t len, uint8_t *pValue)
|
||||
{
|
||||
uint8_t dataIdx = 0;
|
||||
uint32_t calDataCrc = 0;
|
||||
uint16_t header = 0;
|
||||
|
||||
if (pkt->offset == 0 && len < AMDTP_PREFIX_SIZE_IN_PKT)
|
||||
{
|
||||
AMDTP_TRC("Invalid packet!!!\n");
|
||||
AmdtpSendReply(amdtpCb, AMDTP_STATUS_INVALID_PKT_LENGTH, NULL, 0);
|
||||
return AMDTP_STATUS_INVALID_PKT_LENGTH;
|
||||
}
|
||||
|
||||
// new packet
|
||||
if (pkt->offset == 0)
|
||||
{
|
||||
BT_UNPACK_LE_2_BYTE(&pkt->len, pValue);
|
||||
BT_UNPACK_LE_2_BYTE(&header, &pValue[2]);
|
||||
pkt->header.pktType = (header & PACKET_TYPE_BIT_MASK) >> PACKET_TYPE_BIT_OFFSET;
|
||||
pkt->header.pktSn = (header & PACKET_SN_BIT_MASK) >> PACKET_SN_BIT_OFFSET;
|
||||
pkt->header.encrypted = (header & PACKET_ENCRYPTION_BIT_MASK) >> PACKET_ENCRYPTION_BIT_OFFSET;
|
||||
pkt->header.ackEnabled = (header & PACKET_ACK_BIT_MASK) >> PACKET_ACK_BIT_OFFSET;
|
||||
dataIdx = AMDTP_PREFIX_SIZE_IN_PKT;
|
||||
if (pkt->header.pktType == AMDTP_PKT_TYPE_DATA)
|
||||
{
|
||||
amdtpCb->rxState = AMDTP_STATE_GETTING_DATA;
|
||||
}
|
||||
#ifdef AMDTP_DEBUG_ON
|
||||
AMDTP_TRC("pkt len = 0x%x\n", pkt->len);
|
||||
AMDTP_TRC("pkt header = 0x%x\n", header);
|
||||
#endif
|
||||
AMDTP_TRC("type = %d, sn = %d\n", pkt->header.pktType, pkt->header.pktSn);
|
||||
AMDTP_TRC("enc = %d, ackEnabled = %d\n", pkt->header.encrypted, pkt->header.ackEnabled);
|
||||
}
|
||||
|
||||
// make sure we have enough space for new data
|
||||
if (pkt->offset + len - dataIdx > AMDTP_PACKET_SIZE)
|
||||
{
|
||||
AMDTP_TRC("not enough buffer size!!!\n");
|
||||
if (pkt->header.pktType == AMDTP_PKT_TYPE_DATA)
|
||||
{
|
||||
amdtpCb->rxState = AMDTP_STATE_RX_IDLE;
|
||||
}
|
||||
|
||||
// reset pkt
|
||||
resetPkt(pkt);
|
||||
AmdtpSendReply(amdtpCb, AMDTP_STATUS_INSUFFICIENT_BUFFER, NULL, 0);
|
||||
return AMDTP_STATUS_INSUFFICIENT_BUFFER;
|
||||
}
|
||||
|
||||
// copy new data into buffer and also save crc into it if it's the last frame in a packet
|
||||
// 4 bytes crc is included in pkt length
|
||||
memcpy(pkt->data + pkt->offset, pValue + dataIdx, len - dataIdx);
|
||||
pkt->offset += (len - dataIdx);
|
||||
|
||||
// whole packet received
|
||||
if (pkt->offset >= pkt->len)
|
||||
{
|
||||
uint32_t peerCrc = 0;
|
||||
//
|
||||
// check CRC
|
||||
//
|
||||
BT_UNPACK_LE_4_BYTE(&peerCrc, pkt->data + pkt->len - AMDTP_CRC_SIZE_IN_PKT);
|
||||
calDataCrc = AmotaCrc32(0xFFFFFFFFU, pkt->len - AMDTP_CRC_SIZE_IN_PKT, pkt->data);
|
||||
#ifdef AMDTP_DEBUG_ON
|
||||
AMDTP_TRC("calDataCrc = 0x%x\n", calDataCrc);
|
||||
AMDTP_TRC("peerCrc = 0x%x\n", peerCrc);
|
||||
AMDTP_TRC("len: %d\n", pkt->len);
|
||||
#endif
|
||||
|
||||
if (peerCrc != calDataCrc)
|
||||
{
|
||||
AMDTP_TRC("crc error\n");
|
||||
|
||||
if (pkt->header.pktType == AMDTP_PKT_TYPE_DATA)
|
||||
{
|
||||
amdtpCb->rxState = AMDTP_STATE_RX_IDLE;
|
||||
}
|
||||
// reset pkt
|
||||
resetPkt(pkt);
|
||||
|
||||
AmdtpSendReply(amdtpCb, AMDTP_STATUS_CRC_ERROR, NULL, 0);
|
||||
|
||||
return AMDTP_STATUS_CRC_ERROR;
|
||||
}
|
||||
|
||||
return AMDTP_STATUS_RECEIVE_DONE;
|
||||
}
|
||||
|
||||
return AMDTP_STATUS_RECEIVE_CONTINUE;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// AMDTP packet handler
|
||||
//
|
||||
//*****************************************************************************
|
||||
void
|
||||
AmdtpPacketHandler(amdtpCb_t *amdtpCb, eAmdtpPktType_t type, uint16_t len, uint8_t *buf)
|
||||
{
|
||||
#ifdef AMDTP_DEBUG_ON
|
||||
AMDTP_TRC("received packet type = %d, len = %d\n", type, len);
|
||||
#endif
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case AMDTP_PKT_TYPE_DATA:
|
||||
//
|
||||
// data package recevied
|
||||
//
|
||||
// record packet serial number
|
||||
amdtpCb->lastRxPktSn = amdtpCb->rxPkt.header.pktSn;
|
||||
AmdtpSendReply(amdtpCb, AMDTP_STATUS_SUCCESS, NULL, 0);
|
||||
if (amdtpCb->recvCback)
|
||||
{
|
||||
amdtpCb->recvCback(buf, len);
|
||||
}
|
||||
|
||||
amdtpCb->rxState = AMDTP_STATE_RX_IDLE;
|
||||
resetPkt(&amdtpCb->rxPkt);
|
||||
break;
|
||||
|
||||
case AMDTP_PKT_TYPE_ACK:
|
||||
{
|
||||
eAmdtpStatus_t status = (eAmdtpStatus_t)buf[0];
|
||||
// stop tx timeout timer
|
||||
if (BT_TIMER_HANDLE_INIT_VAL != amdtpCb->timeoutTimer)
|
||||
{
|
||||
#ifdef AMDTP_DEBUG_ON
|
||||
API_RESULT retval = API_SUCCESS;
|
||||
retval = BT_stop_timer (amdtpCb->timeoutTimer);
|
||||
AMDTP_TRC (
|
||||
"[AMDTP]: Stopping Timer with result 0x%04X, timer handle %p\n",
|
||||
retval, amdtpCb->timeoutTimer);
|
||||
#else
|
||||
BT_stop_timer (amdtpCb->timeoutTimer);
|
||||
#endif
|
||||
amdtpCb->timeoutTimer = BT_TIMER_HANDLE_INIT_VAL;
|
||||
}
|
||||
|
||||
if (amdtpCb->txState != AMDTP_STATE_TX_IDLE)
|
||||
{
|
||||
#ifdef AMDTP_DEBUG_ON
|
||||
AMDTP_TRC("set txState back to idle, state = %d\n", amdtpCb->txState);
|
||||
#endif
|
||||
amdtpCb->txState = AMDTP_STATE_TX_IDLE;
|
||||
}
|
||||
|
||||
if (status == AMDTP_STATUS_CRC_ERROR || status == AMDTP_STATUS_RESEND_REPLY)
|
||||
{
|
||||
// resend packet
|
||||
AmdtpSendPacketHandler(amdtpCb);
|
||||
}
|
||||
else
|
||||
{
|
||||
// increase packet serial number if send successfully
|
||||
if (status == AMDTP_STATUS_SUCCESS)
|
||||
{
|
||||
amdtpCb->txPktSn++;
|
||||
if (amdtpCb->txPktSn == 16)
|
||||
{
|
||||
amdtpCb->txPktSn = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// packet transfer successful or other error
|
||||
// reset packet
|
||||
resetPkt(&amdtpCb->txPkt);
|
||||
|
||||
// notify application layer
|
||||
if (amdtpCb->transCback)
|
||||
{
|
||||
amdtpCb->transCback(status);
|
||||
}
|
||||
}
|
||||
resetPkt(&amdtpCb->ackPkt);
|
||||
}
|
||||
break;
|
||||
|
||||
case AMDTP_PKT_TYPE_CONTROL:
|
||||
{
|
||||
eAmdtpControl_t control = (eAmdtpControl_t)buf[0];
|
||||
uint8_t resendPktSn = buf[1];
|
||||
if (control == AMDTP_CONTROL_RESEND_REQ)
|
||||
{
|
||||
AMDTP_TRC("resendPktSn = %d, lastRxPktSn = %d\n", resendPktSn, amdtpCb->lastRxPktSn);
|
||||
amdtpCb->rxState = AMDTP_STATE_RX_IDLE;
|
||||
resetPkt(&amdtpCb->rxPkt);
|
||||
if (resendPktSn > amdtpCb->lastRxPktSn)
|
||||
{
|
||||
AmdtpSendReply(amdtpCb, AMDTP_STATUS_RESEND_REPLY, NULL, 0);
|
||||
}
|
||||
else if (resendPktSn == amdtpCb->lastRxPktSn)
|
||||
{
|
||||
AmdtpSendReply(amdtpCb, AMDTP_STATUS_SUCCESS, NULL, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
AMDTP_ERR("resendPktSn = %d, lastRxPktSn = %d\n", resendPktSn, amdtpCb->lastRxPktSn);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AMDTP_TRC("unexpected contrl = %d\n", control);
|
||||
}
|
||||
resetPkt(&amdtpCb->ackPkt);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AmdtpBuildPkt(amdtpCb_t *amdtpCb, eAmdtpPktType_t type, BOOLEAN encrypted, BOOLEAN enableACK, uint8_t *buf, uint16_t len)
|
||||
{
|
||||
uint16_t header = 0;
|
||||
uint32_t calDataCrc;
|
||||
amdtpPacket_t *pkt;
|
||||
|
||||
if (type == AMDTP_PKT_TYPE_DATA)
|
||||
{
|
||||
pkt = &amdtpCb->txPkt;
|
||||
header = amdtpCb->txPktSn << PACKET_SN_BIT_OFFSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
pkt = &amdtpCb->ackPkt;
|
||||
}
|
||||
|
||||
//
|
||||
// Prepare header frame to be sent first
|
||||
//
|
||||
// length
|
||||
pkt->len = len + AMDTP_PREFIX_SIZE_IN_PKT + AMDTP_CRC_SIZE_IN_PKT;
|
||||
pkt->data[0] = (len + AMDTP_CRC_SIZE_IN_PKT) & 0xff;
|
||||
pkt->data[1] = ((len + AMDTP_CRC_SIZE_IN_PKT) >> 8) & 0xff;
|
||||
|
||||
// header
|
||||
header = header | (type << PACKET_TYPE_BIT_OFFSET);
|
||||
if (encrypted)
|
||||
{
|
||||
header = header | (1 << PACKET_ENCRYPTION_BIT_OFFSET);
|
||||
}
|
||||
if (enableACK)
|
||||
{
|
||||
header = header | (1 << PACKET_ACK_BIT_OFFSET);
|
||||
}
|
||||
pkt->data[2] = (header & 0xff);
|
||||
pkt->data[3] = (header >> 8);
|
||||
|
||||
// copy data
|
||||
memcpy(&(pkt->data[AMDTP_PREFIX_SIZE_IN_PKT]), buf, len);
|
||||
calDataCrc = AmotaCrc32(0xFFFFFFFFU, len, buf);
|
||||
|
||||
// add checksum
|
||||
pkt->data[AMDTP_PREFIX_SIZE_IN_PKT + len] = (calDataCrc & 0xff);
|
||||
pkt->data[AMDTP_PREFIX_SIZE_IN_PKT + len + 1] = ((calDataCrc >> 8) & 0xff);
|
||||
pkt->data[AMDTP_PREFIX_SIZE_IN_PKT + len + 2] = ((calDataCrc >> 16) & 0xff);
|
||||
pkt->data[AMDTP_PREFIX_SIZE_IN_PKT + len + 3] = ((calDataCrc >> 24) & 0xff);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Send Reply to Sender
|
||||
//
|
||||
//*****************************************************************************
|
||||
void
|
||||
AmdtpSendReply(amdtpCb_t *amdtpCb, eAmdtpStatus_t status, uint8_t *data, uint16_t len)
|
||||
{
|
||||
uint8_t buf[ATT_DEFAULT_PAYLOAD_LEN] = {0};
|
||||
eAmdtpStatus_t st;
|
||||
|
||||
buf[0] = status;
|
||||
if (len > 0)
|
||||
{
|
||||
memcpy(buf + 1, data, len);
|
||||
}
|
||||
st = amdtpCb->ack_sender_func(AMDTP_PKT_TYPE_ACK, false, false, buf, len + 1);
|
||||
if (st != AMDTP_STATUS_SUCCESS)
|
||||
{
|
||||
AMDTP_ERR("AmdtpSendReply status = %d\n", status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Send control message to Receiver
|
||||
//
|
||||
//*****************************************************************************
|
||||
void
|
||||
AmdtpSendControl(amdtpCb_t *amdtpCb, eAmdtpControl_t control, uint8_t *data, uint16_t len)
|
||||
{
|
||||
uint8_t buf[ATT_DEFAULT_PAYLOAD_LEN] = {0};
|
||||
eAmdtpStatus_t st;
|
||||
|
||||
buf[0] = control;
|
||||
if (len > 0)
|
||||
{
|
||||
memcpy(buf + 1, data, len);
|
||||
}
|
||||
st = amdtpCb->ack_sender_func(AMDTP_PKT_TYPE_CONTROL, false, false, buf, len + 1);
|
||||
if (st != AMDTP_STATUS_SUCCESS)
|
||||
{
|
||||
AMDTP_ERR("AmdtpSendControl status = %d\n", st);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AmdtpSendPacketHandler(amdtpCb_t *amdtpCb)
|
||||
{
|
||||
uint16_t transferSize = 0;
|
||||
uint16_t remainingBytes = 0;
|
||||
amdtpPacket_t *txPkt = &amdtpCb->txPkt;
|
||||
API_RESULT retval = API_SUCCESS;
|
||||
|
||||
if ( amdtpCb->txState == AMDTP_STATE_TX_IDLE )
|
||||
{
|
||||
txPkt->offset = 0;
|
||||
amdtpCb->txState = AMDTP_STATE_SENDING;
|
||||
}
|
||||
|
||||
if ( txPkt->offset >= txPkt->len )
|
||||
{
|
||||
// done sent packet
|
||||
amdtpCb->txState = AMDTP_STATE_WAITING_ACK;
|
||||
// start tx timeout timer
|
||||
if (BT_TIMER_HANDLE_INIT_VAL != amdtpCb->timeoutTimer)
|
||||
{
|
||||
retval = BT_stop_timer (amdtpCb->timeoutTimer);
|
||||
AMDTP_TRC (
|
||||
"[AMDTP]: Stopping Timer with result 0x%04X, timer handle %p\n",
|
||||
retval, amdtpCb->timeoutTimer);
|
||||
amdtpCb->timeoutTimer = BT_TIMER_HANDLE_INIT_VAL;
|
||||
}
|
||||
|
||||
retval = BT_start_timer
|
||||
(
|
||||
&amdtpCb->timeoutTimer,
|
||||
amdtpCb->txTimeout,
|
||||
amdtps_timeout_timer_expired,
|
||||
NULL,
|
||||
0
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
remainingBytes = txPkt->len - txPkt->offset;
|
||||
transferSize = ((amdtpCb->attMtuSize - 3) > remainingBytes)
|
||||
? remainingBytes
|
||||
: (amdtpCb->attMtuSize - 3);
|
||||
// send packet
|
||||
amdtpCb->data_sender_func(&txPkt->data[txPkt->offset], transferSize);
|
||||
txPkt->offset += transferSize;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! @file amdtp_common.h
|
||||
//!
|
||||
//! @brief This file provides the shared functions for the AMDTP service.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2020, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifndef AMDTP_COMMON_H
|
||||
#define AMDTP_COMMON_H
|
||||
|
||||
#include "BT_api.h"
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Macro definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
#define BT_MODULE_BIT_MASK_AMDTPS 0x00020000
|
||||
#define BT_MODULE_ID_AMDTPS (BT_MODULE_PAGE_2 | BT_MODULE_BIT_MASK_AMDTPS)
|
||||
#define AMDTP_ERR(...) BT_debug_error(BT_MODULE_ID_AMDTPS, __VA_ARGS__)
|
||||
#define AMDTP_TRC(...) BT_debug_trace(BT_MODULE_ID_AMDTPS, __VA_ARGS__)
|
||||
|
||||
#define AMDTP_MAX_PAYLOAD_SIZE 2048 //512
|
||||
#define AMDTP_PACKET_SIZE (AMDTP_MAX_PAYLOAD_SIZE + AMDTP_PREFIX_SIZE_IN_PKT + AMDTP_CRC_SIZE_IN_PKT) // Bytes
|
||||
#define AMDTP_LENGTH_SIZE_IN_PKT 2
|
||||
#define AMDTP_HEADER_SIZE_IN_PKT 2
|
||||
#define AMDTP_CRC_SIZE_IN_PKT 4
|
||||
#define AMDTP_PREFIX_SIZE_IN_PKT AMDTP_LENGTH_SIZE_IN_PKT + AMDTP_HEADER_SIZE_IN_PKT
|
||||
|
||||
#define PACKET_TYPE_BIT_OFFSET 12
|
||||
#define PACKET_TYPE_BIT_MASK (0xf << PACKET_TYPE_BIT_OFFSET)
|
||||
#define PACKET_SN_BIT_OFFSET 8
|
||||
#define PACKET_SN_BIT_MASK (0xf << PACKET_SN_BIT_OFFSET)
|
||||
#define PACKET_ENCRYPTION_BIT_OFFSET 7
|
||||
#define PACKET_ENCRYPTION_BIT_MASK (0x1 << PACKET_ENCRYPTION_BIT_OFFSET)
|
||||
#define PACKET_ACK_BIT_OFFSET 6
|
||||
#define PACKET_ACK_BIT_MASK (0x1 << PACKET_ACK_BIT_OFFSET)
|
||||
|
||||
#define TX_TIMEOUT_DEFAULT 1 // 1 second
|
||||
#define ATT_DEFAULT_PAYLOAD_LEN 20
|
||||
|
||||
//
|
||||
// amdtp states
|
||||
//
|
||||
typedef enum eAmdtpState
|
||||
{
|
||||
AMDTP_STATE_INIT,
|
||||
AMDTP_STATE_TX_IDLE,
|
||||
AMDTP_STATE_RX_IDLE,
|
||||
AMDTP_STATE_SENDING,
|
||||
AMDTP_STATE_GETTING_DATA,
|
||||
AMDTP_STATE_WAITING_ACK,
|
||||
AMDTP_STATE_MAX
|
||||
}eAmdtpState_t;
|
||||
|
||||
//
|
||||
// amdtp packet type
|
||||
//
|
||||
typedef enum eAmdtpPktType
|
||||
{
|
||||
AMDTP_PKT_TYPE_UNKNOWN,
|
||||
AMDTP_PKT_TYPE_DATA,
|
||||
AMDTP_PKT_TYPE_ACK,
|
||||
AMDTP_PKT_TYPE_CONTROL,
|
||||
AMDTP_PKT_TYPE_MAX
|
||||
}eAmdtpPktType_t;
|
||||
|
||||
typedef enum eAmdtpControl
|
||||
{
|
||||
AMDTP_CONTROL_RESEND_REQ,
|
||||
AMDTP_CONTROL_MAX
|
||||
}eAmdtpControl_t;
|
||||
|
||||
//
|
||||
// amdtp status
|
||||
//
|
||||
typedef enum eAmdtpStatus
|
||||
{
|
||||
AMDTP_STATUS_SUCCESS,
|
||||
AMDTP_STATUS_CRC_ERROR,
|
||||
AMDTP_STATUS_INVALID_METADATA_INFO,
|
||||
AMDTP_STATUS_INVALID_PKT_LENGTH,
|
||||
AMDTP_STATUS_INSUFFICIENT_BUFFER,
|
||||
AMDTP_STATUS_UNKNOWN_ERROR,
|
||||
AMDTP_STATUS_BUSY,
|
||||
AMDTP_STATUS_TX_NOT_READY, // no connection or tx busy
|
||||
AMDTP_STATUS_RESEND_REPLY,
|
||||
AMDTP_STATUS_RECEIVE_CONTINUE,
|
||||
AMDTP_STATUS_RECEIVE_DONE,
|
||||
AMDTP_STATUS_MAX
|
||||
}eAmdtpStatus_t;
|
||||
|
||||
//
|
||||
// packet prefix structure
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
uint8_t pktType : 4;
|
||||
uint8_t pktSn : 4;
|
||||
uint8_t encrypted : 1;
|
||||
uint32_t ackEnabled : 1;
|
||||
uint32_t reserved : 6; // Reserved for future usage
|
||||
}
|
||||
amdtpPktHeader_t;
|
||||
|
||||
//
|
||||
// packet
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
uint16_t offset;
|
||||
uint16_t len; // data plus checksum
|
||||
amdtpPktHeader_t header;
|
||||
uint8_t *data;
|
||||
}
|
||||
amdtpPacket_t;
|
||||
|
||||
/*! Application data reception callback */
|
||||
typedef void (*amdtpRecvCback_t)(uint8_t *buf, uint16_t len);
|
||||
|
||||
/*! Application data transmission result callback */
|
||||
typedef void (*amdtpTransCback_t)(eAmdtpStatus_t status);
|
||||
|
||||
typedef void (*amdtp_reply_func_t)(eAmdtpStatus_t status, uint8_t *data, uint16_t len);
|
||||
|
||||
typedef void (*amdtp_packet_handler_func_t)(eAmdtpPktType_t type, uint16_t len, uint8_t *buf);
|
||||
|
||||
typedef eAmdtpStatus_t (*amdtp_ack_sender_func_t)(eAmdtpPktType_t type, BOOLEAN encrypted, BOOLEAN enableACK, uint8_t *buf, uint16_t len);
|
||||
|
||||
typedef void (*amdtp_data_sender_func_t)(uint8_t *buf, uint16_t len);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
eAmdtpState_t txState;
|
||||
eAmdtpState_t rxState;
|
||||
amdtpPacket_t rxPkt;
|
||||
amdtpPacket_t txPkt;
|
||||
amdtpPacket_t ackPkt;
|
||||
uint8_t txPktSn; // data packet serial number for Tx
|
||||
uint8_t lastRxPktSn; // last received data packet serial number
|
||||
uint16_t attMtuSize;
|
||||
BT_timer_handle timeoutTimer; // timeout timer after DTP update done
|
||||
uint8_t txTimeout; // timeout in second unit
|
||||
amdtpRecvCback_t recvCback; // application callback for data reception
|
||||
amdtpTransCback_t transCback; // application callback for tx complete status
|
||||
amdtp_data_sender_func_t data_sender_func;
|
||||
amdtp_ack_sender_func_t ack_sender_func;
|
||||
}
|
||||
amdtpCb_t;
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// function definitions
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
void
|
||||
AmdtpBuildPkt(amdtpCb_t *amdtpCb, eAmdtpPktType_t type, BOOLEAN encrypted, BOOLEAN enableACK, uint8_t *buf, uint16_t len);
|
||||
|
||||
eAmdtpStatus_t
|
||||
AmdtpReceivePkt(amdtpCb_t *amdtpCb, amdtpPacket_t *pkt, uint16_t len, uint8_t *pValue);
|
||||
|
||||
void
|
||||
AmdtpSendReply(amdtpCb_t *amdtpCb, eAmdtpStatus_t status, uint8_t *data, uint16_t len);
|
||||
|
||||
void
|
||||
AmdtpSendControl(amdtpCb_t *amdtpCb, eAmdtpControl_t control, uint8_t *data, uint16_t len);
|
||||
|
||||
void
|
||||
AmdtpSendPacketHandler(amdtpCb_t *amdtpCb);
|
||||
|
||||
void
|
||||
AmdtpPacketHandler(amdtpCb_t *amdtpCb, eAmdtpPktType_t type, uint16_t len, uint8_t *buf);
|
||||
|
||||
void
|
||||
resetPkt(amdtpPacket_t *pkt);
|
||||
|
||||
#endif // AMDTP_COMMON_H
|
||||
Reference in New Issue
Block a user