blob: 62bf2482066dfeebe97aaf03e886cf829717ceaa [file] [log] [blame]
/*
* Copyright 2020 HIMSA II K/S - www.himsa.com. Represented by EHIMA -
* www.ehima.com
*
* 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.
*/
#pragma once
#include <algorithm>
#include <deque>
#include "os/logging/log_adapter.h"
#include "stack/gatt/gatt_int.h"
#include "types/raw_address.h"
#define EATT_MIN_MTU_MPS (64)
#define EATT_DEFAULT_MTU (256)
#define EATT_MAX_TX_MTU (1024)
#define EATT_ALL_CIDS (0xFFFF)
namespace bluetooth {
namespace eatt {
/* Enums */
enum class EattChannelState : uint8_t {
EATT_CHANNEL_PENDING = 0x00,
EATT_CHANNEL_OPENED,
EATT_CHANNEL_RECONFIGURING,
};
class EattChannel {
public:
/* Pointer to EattDevice */
RawAddress bda_;
uint16_t cid_;
uint16_t tx_mtu_;
uint16_t rx_mtu_;
EattChannelState state_;
/* Used to keep server commands */
tGATT_SR_CMD server_outstanding_cmd_;
/* Used to veryfy indication confirmation*/
uint16_t indicate_handle_;
/* local app confirm to indication timer */
alarm_t* ind_ack_timer_;
/* indication confirmation timer */
alarm_t* ind_confirmation_timer_;
/* GATT client command queue */
std::deque<tGATT_CMD_Q> cl_cmd_q_;
EattChannel(RawAddress& bda, uint16_t cid, uint16_t tx_mtu, uint16_t rx_mtu)
: bda_(bda),
cid_(cid),
rx_mtu_(rx_mtu),
state_(EattChannelState::EATT_CHANNEL_PENDING),
indicate_handle_(0),
ind_ack_timer_(NULL),
ind_confirmation_timer_(NULL) {
cl_cmd_q_ = std::deque<tGATT_CMD_Q>();
EattChannelSetTxMTU(tx_mtu);
}
~EattChannel() {
if (ind_ack_timer_ != NULL) {
alarm_free(ind_ack_timer_);
}
if (ind_confirmation_timer_ != NULL) {
alarm_free(ind_confirmation_timer_);
}
}
void EattChannelSetState(EattChannelState state) {
if (state_ == EattChannelState::EATT_CHANNEL_PENDING) {
if (state == EattChannelState::EATT_CHANNEL_OPENED) {
memset(&server_outstanding_cmd_, 0, sizeof(tGATT_SR_CMD));
char name[64];
sprintf(name, "eatt_ind_ack_timer_%s_cid_0x%04x",
ADDRESS_TO_LOGGABLE_CSTR(bda_), cid_);
ind_ack_timer_ = alarm_new(name);
sprintf(name, "eatt_ind_conf_timer_%s_cid_0x%04x",
ADDRESS_TO_LOGGABLE_CSTR(bda_), cid_);
ind_confirmation_timer_ = alarm_new(name);
}
}
state_ = state;
}
void EattChannelSetTxMTU(uint16_t tx_mtu) {
this->tx_mtu_ = std::min<uint16_t>(tx_mtu, EATT_MAX_TX_MTU);
}
};
/* Interface class */
class EattExtension {
public:
EattExtension();
EattExtension(const EattExtension&) = delete;
EattExtension& operator=(const EattExtension&) = delete;
virtual ~EattExtension();
static EattExtension* GetInstance() {
static EattExtension* instance = new EattExtension();
return instance;
}
static void AddFromStorage(const RawAddress& bd_addr);
/**
* Checks if EATT is supported on peer device.
*
* @param bd_addr peer device address
*/
virtual bool IsEattSupportedByPeer(const RawAddress& bd_addr);
/**
* Connect at maximum 5 EATT channels to peer device.
*
* @param bd_addr peer device address
*/
virtual void Connect(const RawAddress& bd_addr);
/**
* Disconnect all EATT channels to peer device.
*
* @param bd_addr peer device address
* @param cid remote channel id (EATT_ALL_CIDS for all)
*/
virtual void Disconnect(const RawAddress& bd_addr,
uint16_t cid = EATT_ALL_CIDS);
/**
* Reconfigure EATT channel for give CID
*
* @param bd_addr peer device address
* @param cid channel id
* @param mtu new maximum transmit unit available of local device
*/
virtual void Reconfigure(const RawAddress& bd_addr, uint16_t cid,
uint16_t mtu);
/**
* Reconfigure all EATT channels to peer device.
*
* @param bd_addr peer device address
* @param mtu new maximum transmit unit available of local device
*/
virtual void ReconfigureAll(const RawAddress& bd_addr, uint16_t mtu);
/* Below methods required by GATT implementation */
/**
* Find EATT channel by cid.
*
* @param bd_addr peer device address
* @param cid channel id
*
* @return Eatt Channel instance.
*/
virtual EattChannel* FindEattChannelByCid(const RawAddress& bd_addr,
uint16_t cid);
/**
* Find EATT channel by transaction id.
*
* @param bd_addr peer device address
* @param trans_id transaction id
*
* @return pointer to EATT channel.
*/
virtual EattChannel* FindEattChannelByTransId(const RawAddress& bd_addr,
uint32_t trans_id);
/**
* Check if EATT channel on given handle is waiting for a indication
* confirmation
*
* @param bd_addr peer device address
* @param indication_handle handle of the pending indication
*
* @return true if confirmation is pending false otherwise
*/
virtual bool IsIndicationPending(const RawAddress& bd_addr,
uint16_t indication_handle);
/**
* Get EATT channel available for indication.
*
* @param bd_addr peer device address
*
* @return pointer to EATT channel.
*/
virtual EattChannel* GetChannelAvailableForIndication(
const RawAddress& bd_addr);
/**
* Free Resources.
*
* (Maybe not needed)
* @param bd_addr peer device address
*
*/
virtual void FreeGattResources(const RawAddress& bd_addr);
/**
* Check if there is any EATT channels having some msg in its send queue
*
* @param bd_addr peer device address
*
* @return true when there is at least one EATT channel ready to send
*/
virtual bool IsOutstandingMsgInSendQueue(const RawAddress& bd_addr);
/**
* Get EATT channel ready to send.
*
* @param bd_addr peer device address
*
* @return pointer to EATT channel.
*/
virtual EattChannel* GetChannelWithQueuedDataToSend(
const RawAddress& bd_addr);
/**
* Get EATT channel available to send GATT request.
*
* @param bd_addr peer device address
*
* @return pointer to EATT channel.
*/
virtual EattChannel* GetChannelAvailableForClientRequest(
const RawAddress& bd_addr);
/**
* Start GATT indication timer per CID.
*
* @param bd_addr peer device address
* @param cid channel id
*/
virtual void StartIndicationConfirmationTimer(const RawAddress& bd_addr,
uint16_t cid);
/**
* Stop GATT indication timer per CID.
*
* @param bd_addr peer device address
* @param cid channel id
*/
virtual void StopIndicationConfirmationTimer(const RawAddress& bd_addr,
uint16_t cid);
/**
* Start application time for incoming indication on given CID
*
* @param bd_addr peer device address
* @param cid channel id
*/
virtual void StartAppIndicationTimer(const RawAddress& bd_addr, uint16_t cid);
/**
* Stop application time for incoming indication on given CID
*
* @param bd_addr peer device address
* @param cid channel id
*/
virtual void StopAppIndicationTimer(const RawAddress& bd_addr, uint16_t cid);
/**
* Starts the EattExtension module
*/
void Start();
/**
* Stops the EattExtension module
*/
void Stop();
private:
struct impl;
std::unique_ptr<impl> pimpl_;
};
} // namespace eatt
} // namespace bluetooth