blob: a20ba5fd084fc60f808dd44b8e93578928a7c45c [file] [log] [blame]
/*
* Copyright (c) 2020 Demant
*
* SPDX-License-Identifier: Apache-2.0
*
* Run this test from zephyr directory as:
*
* ./scripts/twister --coverage -p native_posix -v -T tests/bluetooth/ctrl_isoal/
*
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <zephyr/types.h>
#include <zephyr/ztest.h>
#include <zephyr/ztest_error_hook.h>
#include <zephyr/toolchain.h>
#include <zephyr/sys/util.h>
#include <zephyr/kernel.h>
#include <zephyr/bluetooth/bluetooth.h>
#include "util/memq.h"
#include "pdu_df.h"
#include "lll/pdu_vendor.h"
#include "pdu.h"
#include "ll.h"
#include "lll.h"
#include "lll_conn_iso.h"
#include "lll_iso_tx.h"
#include "isoal.h"
#include "isoal_test_common.h"
#include "isoal_test_debug.h"
/**
* Intializes a RX PDU buffer
* @param[in] buf Pointer to buffer structure
*/
void isoal_test_init_rx_pdu_buffer(struct rx_pdu_meta_buffer *buf)
{
memset(buf, 0, sizeof(struct rx_pdu_meta_buffer));
buf->pdu_meta.meta = &buf->meta;
buf->pdu_meta.pdu = (struct pdu_iso *) &buf->pdu[0];
}
/**
* Initializes a RX SDU buffer
* @param[in] buf Pointer to buffer structure
*/
void isoal_test_init_rx_sdu_buffer(struct rx_sdu_frag_buffer *buf)
{
memset(buf, 0, sizeof(struct rx_sdu_frag_buffer));
}
/**
* Creates an unframed PDU fragment according to provided parameters
* @param[in] llid LLID as Start / Continue or Complete / End
* @param[in] dataptr Test data to fill PDU payload
* @param[in] length Length of PDU payload
* @param[in] payload_number Payload number (Meta Information)
* @param[in] timestamp PDU reception Time (Meta Information)
* @param[in] status PDU data validity
* @param[out] pdu_meta PDU buffer including meta structure
*/
void isoal_test_create_unframed_pdu(uint8_t llid,
uint8_t *dataptr,
uint8_t length,
uint64_t payload_number,
uint32_t timestamp,
uint8_t status,
struct isoal_pdu_rx *pdu_meta)
{
zassert_not_null(pdu_meta, "");
zassert_not_null(pdu_meta->meta, "");
zassert_not_null(pdu_meta->pdu, "");
memset(pdu_meta->meta, 0, sizeof(*pdu_meta->meta));
memset(pdu_meta->pdu, 0, sizeof(*pdu_meta->pdu));
pdu_meta->meta->payload_number = payload_number;
pdu_meta->meta->timestamp = timestamp;
pdu_meta->meta->status = status;
pdu_meta->pdu->ll_id = llid;
pdu_meta->pdu->len = length;
memcpy(pdu_meta->pdu->payload, dataptr, length);
isoal_test_debug_print_rx_pdu(pdu_meta);
}
/**
* Insert a new segment in the given PDU
* @param[In] sc !Start / Continuation bit
* @param[In] cmplt Complete bit
* @param[In] time_offset Time Offset (us)
* @param[In] dataptr Pointer to data to fill in segment
* @param[In] length Length of data
* @param[In/Out] pdu_meta PDU structure including meta information
* @return PDU data location index
*/
uint16_t isoal_test_insert_segment(bool sc, bool cmplt, uint32_t time_offset, uint8_t *dataptr,
uint8_t length, struct isoal_pdu_rx *pdu_meta)
{
struct pdu_iso_sdu_sh seg_hdr;
uint16_t pdu_payload_size;
uint8_t hdr_write_size;
uint16_t pdu_data_loc;
pdu_payload_size = pdu_meta->pdu->len + length + PDU_ISO_SEG_HDR_SIZE +
(sc ? 0 : PDU_ISO_SEG_TIMEOFFSET_SIZE);
hdr_write_size = PDU_ISO_SEG_HDR_SIZE + (sc ? 0 : PDU_ISO_SEG_TIMEOFFSET_SIZE);
memset(&seg_hdr, 0, sizeof(seg_hdr));
zassert_true(pdu_payload_size <= TEST_RX_PDU_PAYLOAD_MAX,
"pdu_payload_size (%d)", pdu_payload_size);
seg_hdr.sc = sc;
seg_hdr.cmplt = cmplt;
seg_hdr.len = length + (sc ? 0 : PDU_ISO_SEG_TIMEOFFSET_SIZE);
if (!sc) {
seg_hdr.timeoffset = time_offset;
}
memcpy(&pdu_meta->pdu->payload[pdu_meta->pdu->len], &seg_hdr, hdr_write_size);
pdu_meta->pdu->len += hdr_write_size;
memcpy(&pdu_meta->pdu->payload[pdu_meta->pdu->len], dataptr, length);
pdu_data_loc = pdu_meta->pdu->len;
pdu_meta->pdu->len += length;
isoal_test_debug_print_rx_pdu(pdu_meta);
return pdu_data_loc;
}
/**
* Create and fill in base information for a framed PDU
* @param[In] payload_number Payload number (Meta Information)
* @param[In] timestamp Adjusted RX time stamp (CIS anchorpoint)
* @param[In] status PDU error status
* @param[In/Out] pdu_meta PDU structure including meta information
*/
void isoal_test_create_framed_pdu_base(uint64_t payload_number, uint32_t timestamp, uint8_t status,
struct isoal_pdu_rx *pdu_meta)
{
zassert_not_null(pdu_meta, "");
zassert_not_null(pdu_meta->meta, "");
zassert_not_null(pdu_meta->pdu, "");
memset(pdu_meta->meta, 0, sizeof(*pdu_meta->meta));
memset(pdu_meta->pdu, 0, sizeof(*pdu_meta->pdu));
pdu_meta->meta->payload_number = payload_number;
pdu_meta->meta->timestamp = timestamp;
pdu_meta->meta->status = status;
pdu_meta->pdu->ll_id = PDU_BIS_LLID_FRAMED;
pdu_meta->pdu->len = 0;
isoal_test_debug_print_rx_pdu(pdu_meta);
}
/**
* Adds a single SDU framed segment to the given PDU
* @param[In] dataptr Pointer to data to fill in segment
* @param[In] length Length of data
* @param[In] time_offset Time offset
* @param[In/Out] pdu_meta PDU structure including meta information
* @return PDU data location index
*/
uint16_t isoal_test_add_framed_pdu_single(uint8_t *dataptr, uint8_t length, uint32_t time_offset,
struct isoal_pdu_rx *pdu_meta)
{
zassert_not_null(pdu_meta, "");
zassert_not_null(pdu_meta->meta, "");
zassert_not_null(pdu_meta->pdu, "");
return isoal_test_insert_segment(false, true, time_offset, dataptr, length, pdu_meta);
}
/**
* Adds a starting SDU framed segment to the given PDU
* @param[In] dataptr Pointer to data to fill in segment
* @param[In] length Length of data
* @param[In] time_offset Time offset
* @param[In/Out] pdu_meta PDU structure including meta information
* @return PDU data location index
*/
uint16_t isoal_test_add_framed_pdu_start(uint8_t *dataptr, uint8_t length, uint32_t time_offset,
struct isoal_pdu_rx *pdu_meta)
{
zassert_not_null(pdu_meta, "");
zassert_not_null(pdu_meta->meta, "");
zassert_not_null(pdu_meta->pdu, "");
return isoal_test_insert_segment(false, false, time_offset, dataptr, length, pdu_meta);
}
/**
* Adds a continuation SDU framed segment to the given PDU
* @param[In] dataptr Pointer to data to fill in segment
* @param[In] length Length of data
* @param[In/Out] pdu_meta PDU structure including meta information
* @return PDU data location index
*/
uint16_t isoal_test_add_framed_pdu_cont(uint8_t *dataptr,
uint8_t length,
struct isoal_pdu_rx *pdu_meta)
{
zassert_not_null(pdu_meta, "");
zassert_not_null(pdu_meta->meta, "");
zassert_not_null(pdu_meta->pdu, "");
return isoal_test_insert_segment(true, false, 0, dataptr, length, pdu_meta);
}
/**
* Adds an end SDU framed segment to the given PDU
* @param[In] dataptr Pointer to data to fill in segment
* @param[In] length Length of data
* @param[In/Out] pdu_meta PDU structure including meta information
* @return PDU data location index
*/
uint16_t isoal_test_add_framed_pdu_end(uint8_t *dataptr,
uint8_t length,
struct isoal_pdu_rx *pdu_meta)
{
zassert_not_null(pdu_meta, "");
zassert_not_null(pdu_meta->meta, "");
zassert_not_null(pdu_meta->pdu, "");
return isoal_test_insert_segment(true, true, 0, dataptr, length, pdu_meta);
}
/**
* Intializes a TX PDU buffer
* @param[in] buf Pointer to buffer structure
*/
void isoal_test_init_tx_pdu_buffer(struct tx_pdu_meta_buffer *buf)
{
memset(buf, 0, sizeof(struct tx_pdu_meta_buffer));
}
/**
* Initializes a TX SDU buffer
* @param[in] buf Pointer to buffer structure
*/
void isoal_test_init_tx_sdu_buffer(struct tx_sdu_frag_buffer *buf)
{
memset(buf, 0, sizeof(struct tx_sdu_frag_buffer));
buf->sdu_tx.dbuf = buf->sdu_payload;
}
/**
* Initialize the given test data buffer with a ramp pattern
* @param buf Test data buffer pointer
* @param size Length of test data
*/
void init_test_data_buffer(uint8_t *buf, uint16_t size)
{
zassert_not_null(buf, "");
for (uint16_t i = 0; i < size; i++) {
buf[i] = (uint8_t)(i & 0x00FF);
}
}