Import Mbed OS hard-float snapshot
This commit is contained in:
@@ -0,0 +1,373 @@
|
||||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2017-2017 ARM Limited
|
||||
*
|
||||
* 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 <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ble/internal/BLEInstanceBase.h"
|
||||
#include "ble/BLE.h"
|
||||
#include "ble/Gap.h"
|
||||
#include "CordioHCIDriver.h"
|
||||
#include "hci_api.h"
|
||||
#include "hci_cmd.h"
|
||||
#include "hci_core.h"
|
||||
#include "bstream.h"
|
||||
#include "hci_mbed_os_adaptation.h"
|
||||
|
||||
#define HCI_RESET_RAND_CNT 4
|
||||
|
||||
namespace ble {
|
||||
|
||||
namespace {
|
||||
|
||||
static void hciCoreReadMaxDataLen(void)
|
||||
{
|
||||
/* if LE Data Packet Length Extensions is supported by Controller and included */
|
||||
if ((hciCoreCb.leSupFeat & HCI_LE_SUP_FEAT_DATA_LEN_EXT) &&
|
||||
(hciLeSupFeatCfg & HCI_LE_SUP_FEAT_DATA_LEN_EXT)) {
|
||||
/* send next command in sequence */
|
||||
HciLeReadMaxDataLen();
|
||||
} else {
|
||||
/* send next command in sequence */
|
||||
HciLeRandCmd();
|
||||
}
|
||||
}
|
||||
|
||||
static void hciCoreReadResolvingListSize(void)
|
||||
{
|
||||
/* if LL Privacy is supported by Controller and included */
|
||||
if ((hciCoreCb.leSupFeat & HCI_LE_SUP_FEAT_PRIVACY) &&
|
||||
(hciLeSupFeatCfg & HCI_LE_SUP_FEAT_PRIVACY)) {
|
||||
/* send next command in sequence */
|
||||
HciLeReadResolvingListSize();
|
||||
} else {
|
||||
hciCoreCb.resListSize = 0;
|
||||
|
||||
/* send next command in sequence */
|
||||
hciCoreReadMaxDataLen();
|
||||
}
|
||||
}
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
||||
|
||||
CordioHCIDriver::CordioHCIDriver(CordioHCITransportDriver& transport_driver) :
|
||||
_transport_driver(transport_driver) { }
|
||||
|
||||
void CordioHCIDriver::initialize()
|
||||
{
|
||||
_transport_driver.initialize();
|
||||
do_initialize();
|
||||
}
|
||||
|
||||
void CordioHCIDriver::terminate()
|
||||
{
|
||||
do_terminate();
|
||||
_transport_driver.terminate();
|
||||
}
|
||||
|
||||
buf_pool_desc_t CordioHCIDriver::get_default_buffer_pool_description()
|
||||
{
|
||||
static union {
|
||||
uint8_t buffer[2250];
|
||||
uint64_t align;
|
||||
};
|
||||
static const wsfBufPoolDesc_t pool_desc[] = {
|
||||
{ 16, 16 },
|
||||
{ 32, 16 },
|
||||
{ 64, 8 },
|
||||
{ 128, 4 },
|
||||
{ 272, 1 }
|
||||
};
|
||||
|
||||
return buf_pool_desc_t(buffer, pool_desc);
|
||||
}
|
||||
|
||||
void CordioHCIDriver::set_random_static_address(const ble::address_t& address)
|
||||
{
|
||||
ble_error_t err = BLEInstanceBase::deviceInstance().getGap().setRandomStaticAddress(address);
|
||||
MBED_ASSERT(err == BLE_ERROR_NONE);
|
||||
}
|
||||
|
||||
|
||||
void CordioHCIDriver::start_reset_sequence()
|
||||
{
|
||||
/* send an HCI Reset command to start the sequence */
|
||||
HciResetCmd();
|
||||
}
|
||||
|
||||
void CordioHCIDriver::handle_reset_sequence(uint8_t *pMsg)
|
||||
{
|
||||
uint16_t opcode;
|
||||
static uint8_t randCnt;
|
||||
|
||||
/* if event is a command complete event */
|
||||
if (*pMsg == HCI_CMD_CMPL_EVT) {
|
||||
/* parse parameters */
|
||||
pMsg += HCI_EVT_HDR_LEN;
|
||||
pMsg++; /* skip num packets */
|
||||
BSTREAM_TO_UINT16(opcode, pMsg);
|
||||
pMsg++; /* skip status */
|
||||
|
||||
/* decode opcode */
|
||||
switch (opcode) {
|
||||
case HCI_OPCODE_RESET:
|
||||
/* initialize rand command count */
|
||||
randCnt = 0;
|
||||
|
||||
/* send next command in sequence */
|
||||
HciSetEventMaskCmd((uint8_t *) hciEventMask);
|
||||
break;
|
||||
|
||||
case HCI_OPCODE_SET_EVENT_MASK:
|
||||
/* send next command in sequence */
|
||||
HciLeSetEventMaskCmd((uint8_t *) hciLeEventMask);
|
||||
break;
|
||||
|
||||
case HCI_OPCODE_LE_SET_EVENT_MASK:
|
||||
/* send next command in sequence */
|
||||
HciSetEventMaskPage2Cmd((uint8_t *) hciEventMaskPage2);
|
||||
break;
|
||||
|
||||
case HCI_OPCODE_SET_EVENT_MASK_PAGE2:
|
||||
/* send next command in sequence */
|
||||
HciReadBdAddrCmd();
|
||||
break;
|
||||
|
||||
case HCI_OPCODE_READ_BD_ADDR: {
|
||||
/* parse and store event parameters */
|
||||
BdaCpy(hciCoreCb.bdAddr, pMsg);
|
||||
|
||||
ble::address_t static_address;
|
||||
|
||||
if (get_random_static_address(static_address)) {
|
||||
// note: will send the HCI command to send the random address
|
||||
set_random_static_address(static_address.data());
|
||||
} else {
|
||||
/* send next command in sequence */
|
||||
HciLeReadBufSizeCmd();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case HCI_OPCODE_LE_SET_RAND_ADDR:
|
||||
/* send next command in sequence */
|
||||
HciLeReadBufSizeCmd();
|
||||
break;
|
||||
|
||||
case HCI_OPCODE_LE_READ_BUF_SIZE:
|
||||
/* parse and store event parameters */
|
||||
BSTREAM_TO_UINT16(hciCoreCb.bufSize, pMsg);
|
||||
BSTREAM_TO_UINT8(hciCoreCb.numBufs, pMsg);
|
||||
|
||||
/* initialize ACL buffer accounting */
|
||||
hciCoreCb.availBufs = hciCoreCb.numBufs;
|
||||
|
||||
/* send next command in sequence */
|
||||
HciLeReadSupStatesCmd();
|
||||
break;
|
||||
|
||||
case HCI_OPCODE_LE_READ_SUP_STATES:
|
||||
/* parse and store event parameters */
|
||||
memcpy(hciCoreCb.leStates, pMsg, HCI_LE_STATES_LEN);
|
||||
|
||||
/* send next command in sequence */
|
||||
HciLeReadWhiteListSizeCmd();
|
||||
break;
|
||||
|
||||
case HCI_OPCODE_LE_READ_WHITE_LIST_SIZE:
|
||||
/* parse and store event parameters */
|
||||
BSTREAM_TO_UINT8(hciCoreCb.whiteListSize, pMsg);
|
||||
|
||||
/* send next command in sequence */
|
||||
HciLeReadLocalSupFeatCmd();
|
||||
break;
|
||||
|
||||
case HCI_OPCODE_LE_READ_LOCAL_SUP_FEAT:
|
||||
/* parse and store event parameters */
|
||||
BSTREAM_TO_UINT16(hciCoreCb.leSupFeat, pMsg);
|
||||
|
||||
/* send next command in sequence */
|
||||
hciCoreReadResolvingListSize();
|
||||
break;
|
||||
|
||||
case HCI_OPCODE_LE_READ_RES_LIST_SIZE:
|
||||
/* parse and store event parameters */
|
||||
BSTREAM_TO_UINT8(hciCoreCb.resListSize, pMsg);
|
||||
|
||||
/* send next command in sequence */
|
||||
hciCoreReadMaxDataLen();
|
||||
break;
|
||||
|
||||
case HCI_OPCODE_LE_READ_MAX_DATA_LEN: {
|
||||
uint16_t maxTxOctets;
|
||||
uint16_t maxTxTime;
|
||||
|
||||
BSTREAM_TO_UINT16(maxTxOctets, pMsg);
|
||||
BSTREAM_TO_UINT16(maxTxTime, pMsg);
|
||||
|
||||
/* use Controller's maximum supported payload octets and packet duration times
|
||||
* for transmission as Host's suggested values for maximum transmission number
|
||||
* of payload octets and maximum packet transmission time for new connections.
|
||||
*/
|
||||
HciLeWriteDefDataLen(maxTxOctets, maxTxTime);
|
||||
} break;
|
||||
|
||||
case HCI_OPCODE_LE_WRITE_DEF_DATA_LEN:
|
||||
if (hciCoreCb.extResetSeq) {
|
||||
/* send first extended command */
|
||||
HciReadLocalVerInfoCmd();
|
||||
} else {
|
||||
/* initialize extended parameters */
|
||||
hciCoreCb.maxAdvDataLen = 0;
|
||||
hciCoreCb.numSupAdvSets = 0;
|
||||
hciCoreCb.perAdvListSize = 0;
|
||||
|
||||
/* send next command in sequence */
|
||||
HciLeRandCmd();
|
||||
}
|
||||
break;
|
||||
|
||||
case HCI_OPCODE_READ_LOCAL_VER_INFO:
|
||||
case HCI_OPCODE_LE_READ_MAX_ADV_DATA_LEN:
|
||||
case HCI_OPCODE_LE_READ_NUM_SUP_ADV_SETS:
|
||||
case HCI_OPCODE_LE_READ_PER_ADV_LIST_SIZE:
|
||||
if (hciCoreCb.extResetSeq) {
|
||||
/* send next extended command in sequence */
|
||||
(*hciCoreCb.extResetSeq)(pMsg, opcode);
|
||||
}
|
||||
break;
|
||||
|
||||
case HCI_OPCODE_LE_RAND:
|
||||
/* check if need to send second rand command */
|
||||
if (randCnt < (HCI_RESET_RAND_CNT-1)) {
|
||||
randCnt++;
|
||||
HciLeRandCmd();
|
||||
} else {
|
||||
/* last command in sequence; set resetting state and call callback */
|
||||
signal_reset_sequence_done();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CordioHCIDriver::get_random_static_address(ble::address_t& address)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void CordioHCIDriver::signal_reset_sequence_done()
|
||||
{
|
||||
hci_mbed_os_signal_reset_sequence_done();
|
||||
}
|
||||
|
||||
uint16_t CordioHCIDriver::write(uint8_t type, uint16_t len, uint8_t *pData)
|
||||
{
|
||||
return _transport_driver.write(type, len, pData);
|
||||
}
|
||||
|
||||
void CordioHCIDriver::on_host_stack_inactivity()
|
||||
{
|
||||
}
|
||||
void CordioHCIDriver::handle_test_end(bool success, uint16_t packets)
|
||||
{
|
||||
if (_test_end_handler) {
|
||||
_test_end_handler(success, packets);
|
||||
_test_end_handler = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ble_error_t CordioHCIDriver::rf_test_start_le_receiver_test(
|
||||
test_end_handler_t test_end_handler, uint8_t channel
|
||||
)
|
||||
{
|
||||
if (_test_end_handler) {
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (!test_end_handler) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
_test_end_handler = test_end_handler;
|
||||
uint8_t *buf = hciCmdAlloc(HCI_OPCODE_LE_RECEIVER_TEST, HCI_LEN_LE_RECEIVER_TEST);
|
||||
|
||||
if (buf) {
|
||||
uint8_t* p = buf + HCI_CMD_HDR_LEN;
|
||||
UINT8_TO_BSTREAM(p, channel);
|
||||
hciCmdSend(buf);
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
ble_error_t CordioHCIDriver::rf_test_start_le_transmitter_test(
|
||||
test_end_handler_t test_end_handler, uint8_t channel, uint8_t length, uint8_t type
|
||||
)
|
||||
{
|
||||
if (_test_end_handler) {
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (!test_end_handler) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
_test_end_handler = test_end_handler;
|
||||
uint8_t *buf = hciCmdAlloc(HCI_OPCODE_LE_TRANSMITTER_TEST, HCI_LEN_LE_TRANSMITTER_TEST);
|
||||
|
||||
if (buf) {
|
||||
uint8_t* p = buf + HCI_CMD_HDR_LEN;
|
||||
UINT8_TO_BSTREAM(p, channel);
|
||||
UINT8_TO_BSTREAM(p, length);
|
||||
UINT8_TO_BSTREAM(p, type);
|
||||
hciCmdSend(buf);
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
ble_error_t CordioHCIDriver::rf_test_end()
|
||||
{
|
||||
if (!_test_end_handler) {
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
uint8_t *buf = hciCmdAlloc(HCI_OPCODE_LE_TEST_END, HCI_LEN_LE_TEST_END);
|
||||
|
||||
if (buf) {
|
||||
hciCmdSend(buf);
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
ble_error_t CordioHCIDriver::set_tx_power(int8_t level_db)
|
||||
{
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
} // namespace ble
|
||||
@@ -0,0 +1,232 @@
|
||||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2017-2017 ARM Limited
|
||||
*
|
||||
* 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 IMPL_HCI_DRIVER_H_
|
||||
#define IMPL_HCI_DRIVER_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <BLETypes.h>
|
||||
#include "wsf_buf.h"
|
||||
#include "CordioHCITransportDriver.h"
|
||||
#include "ble/common/ble/blecommon.h"
|
||||
#include "mbed.h"
|
||||
|
||||
namespace ble {
|
||||
|
||||
/**
|
||||
* Contain description of the memory pool used by the Cordio stack.
|
||||
*/
|
||||
struct buf_pool_desc_t {
|
||||
/**
|
||||
* Create a new memory pool description
|
||||
* @param buffer the Buffer used by the memory pool.
|
||||
* @param pool_desc How the memory is split
|
||||
*/
|
||||
template<size_t BufferSize, size_t PoolCount>
|
||||
buf_pool_desc_t(
|
||||
uint8_t (&buffer)[BufferSize],
|
||||
const wsfBufPoolDesc_t (&pool_desc)[PoolCount]
|
||||
) : buffer_memory(buffer), buffer_size(BufferSize),
|
||||
pool_description(pool_desc), pool_count(PoolCount)
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t* buffer_memory; /// Pointer to the buffer memory
|
||||
size_t buffer_size; /// Size of the buffer
|
||||
const wsfBufPoolDesc_t* pool_description; /// Pointer to the first element describing the pool
|
||||
size_t pool_count; /// Number of pools
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class of the HCI driver use by the BLE port of the Cordio stack.
|
||||
* This class provide to the stack:
|
||||
* - The buffer necessary to run BLE API
|
||||
* - The reset sequence of the BLE module
|
||||
* - Access to the write function of the underlying HCITransport driver.
|
||||
*/
|
||||
class CordioHCIDriver {
|
||||
|
||||
// hook for internal tests and passthrough driver
|
||||
friend class CordioHCIHook;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a new instance of an HCI driver.
|
||||
* @param transport_driver The driver used to communicate with the chip.
|
||||
*/
|
||||
CordioHCIDriver(CordioHCITransportDriver& transport_driver);
|
||||
|
||||
/**
|
||||
* Driver destructor
|
||||
*/
|
||||
virtual ~CordioHCIDriver() { }
|
||||
|
||||
/**
|
||||
* Return the set of memory pool which will be used by the Cordio stack
|
||||
*/
|
||||
virtual buf_pool_desc_t get_buffer_pool_description() = 0;
|
||||
|
||||
/**
|
||||
* Initialize the HCI driver.
|
||||
* This function start by initializing the transport driver then it delegates
|
||||
* what's remain of the initialization to the function do_initialize.
|
||||
*/
|
||||
void initialize();
|
||||
|
||||
/**
|
||||
* Termination of the driver.
|
||||
* It call in sequence:
|
||||
* - do_terminate
|
||||
* - terminate the transport driver.
|
||||
*/
|
||||
void terminate();
|
||||
|
||||
/**
|
||||
* Start the reset sequence of the BLE module.
|
||||
*/
|
||||
virtual void start_reset_sequence();
|
||||
|
||||
/**
|
||||
* Handle HCI messages received during the reset sequence.
|
||||
*
|
||||
* @param msg The HCI message received.
|
||||
* @note The driver should signal to the stack that the initialization
|
||||
* sequence is done by calling the function: signal_reset_sequence_done.
|
||||
*/
|
||||
virtual void handle_reset_sequence(uint8_t *msg);
|
||||
|
||||
/**
|
||||
* Get the random static address of the controller
|
||||
*
|
||||
* @return false if the address has not been set and true otherwise.
|
||||
*/
|
||||
virtual bool get_random_static_address(ble::address_t& address);
|
||||
|
||||
/**
|
||||
* Signal to the stack that the reset sequence has been done.
|
||||
*/
|
||||
void signal_reset_sequence_done();
|
||||
|
||||
/**
|
||||
* Write data in the transport channel.
|
||||
*
|
||||
* @param type The type of packet to transmit. It might be an HCI command
|
||||
* packet, ACL packet or EVT packet. Depending on the type of transport
|
||||
* it can prefix the packet itself.
|
||||
* @param len Number of bytes to transmit.
|
||||
* @param pData pointer to the data to transmit.
|
||||
*
|
||||
* @return The number of bytes which have been transmited.
|
||||
*/
|
||||
uint16_t write(uint8_t type, uint16_t len, uint8_t *pData);
|
||||
|
||||
/**
|
||||
* React to host stack inactivity.
|
||||
*
|
||||
* The host stack invoke this function when it is inactive. It allows a
|
||||
* driver to put its controller to sleep if all the conditions are met.
|
||||
*
|
||||
* Any call to write signals to the driver that the host stack is active.
|
||||
*/
|
||||
virtual void on_host_stack_inactivity();
|
||||
|
||||
/* BLE Tester commands */
|
||||
|
||||
/**
|
||||
* This will be called by host part of the stack to indicate the end of the test.
|
||||
*
|
||||
* @param success True if the TEST END command was a success.
|
||||
* @param packets Number of packets received during the test.
|
||||
* @return BLE_ERROR_NONE on success.
|
||||
*/
|
||||
void handle_test_end(bool success, uint16_t packets);
|
||||
|
||||
/** Callback to inform the caller of the result of the test, the parameters are success and the
|
||||
* number of packets received.
|
||||
*/
|
||||
typedef mbed::Callback<void(bool, uint16_t)> test_end_handler_t;
|
||||
|
||||
/**
|
||||
* Start BLE receiver test. Call rf_test_end when you want to stop.
|
||||
* @param test_end_handler Handler that will be called with the number of packets received.
|
||||
* @param channel Channel to use.
|
||||
* @return BLE_ERROR_NONE on success.
|
||||
*/
|
||||
ble_error_t rf_test_start_le_receiver_test(test_end_handler_t test_end_handler, uint8_t channel);
|
||||
|
||||
/**
|
||||
* Start BLE transmitter test. Call rf_test_end when you want to stop.
|
||||
* @param test_end_handler Handler that will be called with status and the number of packets set to 0.
|
||||
* @param channel Channel to use.
|
||||
* @param length Size of payload.
|
||||
* @param type Type of pattern to transmit @see BLE spec Volume 6 Part F, Section 4.1.5.
|
||||
* @return BLE_ERROR_NONE on success.
|
||||
*/
|
||||
ble_error_t rf_test_start_le_transmitter_test(test_end_handler_t test_end_handler, uint8_t channel,
|
||||
uint8_t length, uint8_t type);
|
||||
|
||||
/**
|
||||
* Complete the test. This will trigger the end test event which will call handle_test_end
|
||||
* @return BLE_ERROR_NONE on success.
|
||||
*/
|
||||
ble_error_t rf_test_end();
|
||||
|
||||
/**
|
||||
* Set desired transmit power. Value equal or bigger will be used from available levels.
|
||||
* Consult chip documentation for available values. Actual TX power is not guaranteed
|
||||
* and is down to the implementation.
|
||||
*
|
||||
* @param level_db Signal level in dBm.
|
||||
* @return BLE_ERROR_NONE on success.
|
||||
*/
|
||||
virtual ble_error_t set_tx_power(int8_t level_db);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Return a default set of memory pool that the Cordio stack can use.
|
||||
* This function can be used to implement get_buffer_pool_description().
|
||||
*/
|
||||
buf_pool_desc_t get_default_buffer_pool_description();
|
||||
|
||||
/**
|
||||
* Allows the driver to set a random static address. Unlike the HCI command
|
||||
* this function reports the random static address to the whole BLE system.
|
||||
* @param random_static_address The random static address to set.
|
||||
*/
|
||||
void set_random_static_address(const ble::address_t& random_static_address);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Initialize the chip.
|
||||
* The transport is up at that time.
|
||||
*/
|
||||
virtual void do_initialize() = 0;
|
||||
|
||||
/**
|
||||
* Terminate the driver
|
||||
*/
|
||||
virtual void do_terminate() = 0;
|
||||
|
||||
protected:
|
||||
test_end_handler_t _test_end_handler;
|
||||
private:
|
||||
CordioHCITransportDriver& _transport_driver;
|
||||
};
|
||||
|
||||
} // namespace ble
|
||||
|
||||
#endif /* IMPL_HCI_DRIVER_H_ */
|
||||
@@ -0,0 +1,45 @@
|
||||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2017-2017 ARM Limited
|
||||
*
|
||||
* 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 <algorithm>
|
||||
#include <limits>
|
||||
|
||||
#include "CordioHCITransportDriver.h"
|
||||
#include "CordioHCIDriver.h"
|
||||
|
||||
extern "C" void hciTrSerialRxIncoming(uint8_t *pBuf, uint8_t len);
|
||||
|
||||
namespace ble {
|
||||
|
||||
CordioHCITransportDriver::data_received_handler_t
|
||||
CordioHCITransportDriver::data_received_handler = hciTrSerialRxIncoming;
|
||||
|
||||
void CordioHCITransportDriver::on_data_received(uint8_t* data, uint16_t len)
|
||||
{
|
||||
while (len) {
|
||||
uint8_t chunk_length = std::min(len, (uint16_t) std::numeric_limits<uint8_t>::max());
|
||||
data_received_handler(data, chunk_length);
|
||||
len = len - chunk_length;
|
||||
data = data + chunk_length;
|
||||
}
|
||||
}
|
||||
|
||||
void CordioHCITransportDriver::set_data_received_handler(data_received_handler_t handler)
|
||||
{
|
||||
data_received_handler = handler;
|
||||
}
|
||||
|
||||
} // namespace ble
|
||||
@@ -0,0 +1,81 @@
|
||||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2017-2017 ARM Limited
|
||||
*
|
||||
* 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 IMPL_HCI_TRANSPORT_DRIVER_H_
|
||||
#define IMPL_HCI_TRANSPORT_DRIVER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace ble {
|
||||
|
||||
/**
|
||||
* Base class of the HCI transport driver.
|
||||
* It allow the stack to write data in the HCI channel.
|
||||
*/
|
||||
class CordioHCITransportDriver {
|
||||
|
||||
// hook for internal tests and passthrough driver
|
||||
friend class CordioHCIHook;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Driver destructor.
|
||||
*/
|
||||
virtual ~CordioHCITransportDriver() { }
|
||||
|
||||
/**
|
||||
* Inialization of the transport.
|
||||
*/
|
||||
virtual void initialize() = 0;
|
||||
|
||||
/**
|
||||
* termination of the transport.
|
||||
*/
|
||||
virtual void terminate() = 0;
|
||||
|
||||
/**
|
||||
* Write data in the transport channel.
|
||||
*
|
||||
* @param type The type of packet to transmit. It might be an HCI command
|
||||
* packet, ACL packet or EVT packet. Depending on the type of transport
|
||||
* it can prefix the packet itself.
|
||||
* @param len Number of bytes to transmit.
|
||||
* @param pData Pointer to the data to transmit. This is an WSF buffer
|
||||
* and if CORDIO_ZERO_COPY_HCI is enabled we receive ownership.
|
||||
*
|
||||
* @return The number of bytes which have been transmited.
|
||||
*/
|
||||
virtual uint16_t write(uint8_t type, uint16_t len, uint8_t *pData) = 0;
|
||||
|
||||
/**
|
||||
* The driver shall call this function whenever data bytes are received.
|
||||
*
|
||||
* @param data Pointer to the data received.
|
||||
* @param len Number of bytes received.
|
||||
*/
|
||||
static void on_data_received(uint8_t* data, uint16_t len);
|
||||
|
||||
private:
|
||||
typedef void (*data_received_handler_t)(uint8_t* data, uint8_t len);
|
||||
|
||||
static data_received_handler_t data_received_handler;
|
||||
|
||||
static void set_data_received_handler(data_received_handler_t handler);
|
||||
};
|
||||
|
||||
} // namespace ble
|
||||
|
||||
#endif /* IMPL_HCI_TRANSPORT_DRIVER_H_ */
|
||||
@@ -0,0 +1,72 @@
|
||||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2017-2017 ARM Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if DEVICE_SERIAL && DEVICE_SERIAL_FC
|
||||
|
||||
#include "H4TransportDriver.h"
|
||||
|
||||
namespace ble {
|
||||
|
||||
H4TransportDriver::H4TransportDriver(PinName tx, PinName rx, PinName cts, PinName rts, int baud) :
|
||||
uart(tx, rx, baud), cts(cts), rts(rts) { }
|
||||
|
||||
void H4TransportDriver::initialize()
|
||||
{
|
||||
uart.format(
|
||||
/* bits */ 8,
|
||||
/* parity */ SerialBase::None,
|
||||
/* stop bit */ 1
|
||||
);
|
||||
|
||||
uart.set_flow_control(
|
||||
/* flow */ SerialBase::RTSCTS,
|
||||
/* rts */ rts,
|
||||
/* cts */ cts
|
||||
);
|
||||
|
||||
uart.attach(
|
||||
callback(this, &H4TransportDriver::on_controller_irq),
|
||||
SerialBase::RxIrq
|
||||
);
|
||||
}
|
||||
|
||||
void H4TransportDriver::terminate() { }
|
||||
|
||||
uint16_t H4TransportDriver::write(uint8_t type, uint16_t len, uint8_t *pData)
|
||||
{
|
||||
uint16_t i = 0;
|
||||
while (i < len + 1) {
|
||||
uint8_t to_write = i == 0 ? type : pData[i - 1];
|
||||
while (uart.writeable() == 0);
|
||||
uart.write(&to_write, 1);
|
||||
++i;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
void H4TransportDriver::on_controller_irq()
|
||||
{
|
||||
while (uart.readable()) {
|
||||
uint8_t char_received;
|
||||
if (uart.read(&char_received, 1)) {
|
||||
on_data_received(&char_received, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ble
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,81 @@
|
||||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2017-2017 ARM Limited
|
||||
*
|
||||
* 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 IMPL_H4_TRANSPORT_DRIVER_H_
|
||||
#define IMPL_H4_TRANSPORT_DRIVER_H_
|
||||
|
||||
#if (DEVICE_SERIAL && DEVICE_SERIAL_FC) || defined(DOXYGEN_ONLY)
|
||||
|
||||
#include <stdint.h>
|
||||
#include "mbed.h"
|
||||
#include "CordioHCITransportDriver.h"
|
||||
|
||||
namespace ble {
|
||||
|
||||
/**
|
||||
* Implementation of the H4 driver.
|
||||
*
|
||||
* @note This HCI transport implementation is not accessible to devices that do
|
||||
* not expose serial flow control.
|
||||
*/
|
||||
class H4TransportDriver : public CordioHCITransportDriver {
|
||||
public:
|
||||
/**
|
||||
* Initialize the transport driver.
|
||||
*
|
||||
* @param tx tx pin name.
|
||||
* @param rx rx pin name
|
||||
* @param cts cts pin name
|
||||
* @param rts rts pin name.
|
||||
* @param baud baud use to communicate with the ble module
|
||||
*/
|
||||
H4TransportDriver(PinName tx, PinName rx, PinName cts, PinName rts, int baud);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~H4TransportDriver() { }
|
||||
|
||||
/**
|
||||
* @see CordioHCITransportDriver::initialize
|
||||
*/
|
||||
virtual void initialize();
|
||||
|
||||
/**
|
||||
* @see CordioHCITransportDriver::terminate
|
||||
*/
|
||||
virtual void terminate();
|
||||
|
||||
/**
|
||||
* @see CordioHCITransportDriver::write
|
||||
*/
|
||||
virtual uint16_t write(uint8_t type, uint16_t len, uint8_t *pData);
|
||||
|
||||
private:
|
||||
void on_controller_irq();
|
||||
|
||||
// Use UnbufferedSerial as we don't require locking primitives.
|
||||
// We access the peripheral in interrupt context.
|
||||
UnbufferedSerial uart;
|
||||
PinName cts;
|
||||
PinName rts;
|
||||
};
|
||||
|
||||
} // namespace ble
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* IMPL_H4_TRANSPORT_DRIVER_H_ */
|
||||
Reference in New Issue
Block a user