use core::ffi::c_void;
use core::ptr;
use crate::config::*;
use crate::kernel::tasks::*;
use crate::port::*;
use crate::types::*;
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
extern crate alloc;
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
use alloc::alloc::{alloc, dealloc, Layout};
pub const sbTYPE_STREAM_BUFFER: BaseType_t = 0;
pub const sbTYPE_MESSAGE_BUFFER: BaseType_t = 1;
pub const sbTYPE_STREAM_BATCHING_BUFFER: BaseType_t = 2;
const sbBYTES_TO_STORE_MESSAGE_LENGTH: usize =
core::mem::size_of::<configMESSAGE_BUFFER_LENGTH_TYPE>();
const sbFLAGS_IS_MESSAGE_BUFFER: u8 = 1;
const sbFLAGS_IS_STATICALLY_ALLOCATED: u8 = 2;
const sbFLAGS_IS_BATCHING_BUFFER: u8 = 4;
pub type configMESSAGE_BUFFER_LENGTH_TYPE = u32;
const tskDEFAULT_INDEX_TO_NOTIFY: UBaseType_t = 0;
pub type StreamBufferHandle_t = *mut c_void;
pub type StreamBufferCallbackFunction_t = Option<
extern "C" fn(
xStreamBuffer: StreamBufferHandle_t,
xIsInsideISR: BaseType_t,
pxHigherPriorityTaskWoken: *mut BaseType_t,
),
>;
#[repr(C)]
pub struct StreamBuffer_t {
pub xTail: usize,
pub xHead: usize,
pub xLength: usize,
pub xTriggerLevelBytes: usize,
pub xTaskWaitingToReceive: TaskHandle_t,
pub xTaskWaitingToSend: TaskHandle_t,
pub pucBuffer: *mut u8,
pub ucFlags: u8,
#[cfg(feature = "trace-facility")]
pub uxStreamBufferNumber: UBaseType_t,
pub uxNotificationIndex: UBaseType_t,
}
#[repr(C)]
pub struct StaticStreamBuffer_t {
_reserved: [u8; core::mem::size_of::<StreamBuffer_t>()],
}
impl StaticStreamBuffer_t {
pub const fn new() -> Self {
StaticStreamBuffer_t {
_reserved: [0u8; core::mem::size_of::<StreamBuffer_t>()],
}
}
}
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
pub unsafe fn xStreamBufferGenericCreate(
xBufferSizeBytes: usize,
mut xTriggerLevelBytes: usize,
xStreamBufferType: BaseType_t,
pxSendCompletedCallback: StreamBufferCallbackFunction_t,
pxReceiveCompletedCallback: StreamBufferCallbackFunction_t,
) -> StreamBufferHandle_t {
let ucFlags: u8;
if xStreamBufferType == sbTYPE_MESSAGE_BUFFER {
ucFlags = sbFLAGS_IS_MESSAGE_BUFFER;
configASSERT(xBufferSizeBytes > sbBYTES_TO_STORE_MESSAGE_LENGTH);
} else if xStreamBufferType == sbTYPE_STREAM_BATCHING_BUFFER {
ucFlags = sbFLAGS_IS_BATCHING_BUFFER;
configASSERT(xBufferSizeBytes > 0);
} else {
ucFlags = 0;
configASSERT(xBufferSizeBytes > 0);
}
configASSERT(xTriggerLevelBytes <= xBufferSizeBytes);
if xTriggerLevelBytes == 0 {
xTriggerLevelBytes = 1;
}
let xBufferSizeBytes = xBufferSizeBytes + 1;
let total_size = core::mem::size_of::<StreamBuffer_t>() + xBufferSizeBytes;
let layout = Layout::from_size_align(total_size, core::mem::align_of::<StreamBuffer_t>())
.expect("Invalid layout");
let pvAllocatedMemory = alloc(layout);
if !pvAllocatedMemory.is_null() {
let pxStreamBuffer = pvAllocatedMemory as *mut StreamBuffer_t;
let pucBuffer = pvAllocatedMemory.add(core::mem::size_of::<StreamBuffer_t>());
prvInitialiseNewStreamBuffer(
pxStreamBuffer,
pucBuffer,
xBufferSizeBytes,
xTriggerLevelBytes,
ucFlags,
pxSendCompletedCallback,
pxReceiveCompletedCallback,
);
pxStreamBuffer as StreamBufferHandle_t
} else {
ptr::null_mut()
}
}
pub unsafe fn xStreamBufferGenericCreateStatic(
xBufferSizeBytes: usize,
mut xTriggerLevelBytes: usize,
xStreamBufferType: BaseType_t,
pucStreamBufferStorageArea: *mut u8,
pxStaticStreamBuffer: *mut StaticStreamBuffer_t,
pxSendCompletedCallback: StreamBufferCallbackFunction_t,
pxReceiveCompletedCallback: StreamBufferCallbackFunction_t,
) -> StreamBufferHandle_t {
configASSERT(!pucStreamBufferStorageArea.is_null());
configASSERT(!pxStaticStreamBuffer.is_null());
configASSERT(xTriggerLevelBytes <= xBufferSizeBytes);
if xTriggerLevelBytes == 0 {
xTriggerLevelBytes = 1;
}
let ucFlags: u8;
if xStreamBufferType == sbTYPE_MESSAGE_BUFFER {
ucFlags = sbFLAGS_IS_MESSAGE_BUFFER | sbFLAGS_IS_STATICALLY_ALLOCATED;
configASSERT(xBufferSizeBytes > sbBYTES_TO_STORE_MESSAGE_LENGTH);
} else if xStreamBufferType == sbTYPE_STREAM_BATCHING_BUFFER {
ucFlags = sbFLAGS_IS_BATCHING_BUFFER | sbFLAGS_IS_STATICALLY_ALLOCATED;
configASSERT(xBufferSizeBytes > 0);
} else {
ucFlags = sbFLAGS_IS_STATICALLY_ALLOCATED;
}
if !pucStreamBufferStorageArea.is_null() && !pxStaticStreamBuffer.is_null() {
let pxStreamBuffer = pxStaticStreamBuffer as *mut StreamBuffer_t;
prvInitialiseNewStreamBuffer(
pxStreamBuffer,
pucStreamBufferStorageArea,
xBufferSizeBytes,
xTriggerLevelBytes,
ucFlags,
pxSendCompletedCallback,
pxReceiveCompletedCallback,
);
pxStreamBuffer as StreamBufferHandle_t
} else {
ptr::null_mut()
}
}
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
#[inline(always)]
pub unsafe fn xStreamBufferCreate(
xBufferSizeBytes: usize,
xTriggerLevelBytes: usize,
) -> StreamBufferHandle_t {
xStreamBufferGenericCreate(
xBufferSizeBytes,
xTriggerLevelBytes,
sbTYPE_STREAM_BUFFER,
None,
None,
)
}
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
#[inline(always)]
pub unsafe fn xMessageBufferCreate(xBufferSizeBytes: usize) -> StreamBufferHandle_t {
xStreamBufferGenericCreate(xBufferSizeBytes, 1, sbTYPE_MESSAGE_BUFFER, None, None)
}
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
#[inline(always)]
pub unsafe fn xStreamBatchingBufferCreate(
xBufferSizeBytes: usize,
xTriggerLevelBytes: usize,
) -> StreamBufferHandle_t {
xStreamBufferGenericCreate(
xBufferSizeBytes,
xTriggerLevelBytes,
sbTYPE_STREAM_BATCHING_BUFFER,
None,
None,
)
}
pub unsafe fn vStreamBufferDelete(xStreamBuffer: StreamBufferHandle_t) {
configASSERT(!xStreamBuffer.is_null());
let pxStreamBuffer = xStreamBuffer as *mut StreamBuffer_t;
if ((*pxStreamBuffer).ucFlags & sbFLAGS_IS_STATICALLY_ALLOCATED) == 0 {
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
{
let total_size = core::mem::size_of::<StreamBuffer_t>() + (*pxStreamBuffer).xLength;
let layout =
Layout::from_size_align(total_size, core::mem::align_of::<StreamBuffer_t>())
.expect("Invalid layout");
dealloc(pxStreamBuffer as *mut u8, layout);
}
} else {
ptr::write_bytes(pxStreamBuffer, 0, 1);
}
}
pub unsafe fn xStreamBufferReset(xStreamBuffer: StreamBufferHandle_t) -> BaseType_t {
configASSERT(!xStreamBuffer.is_null());
let pxStreamBuffer = xStreamBuffer as *mut StreamBuffer_t;
let mut xReturn: BaseType_t = pdFAIL;
portENTER_CRITICAL();
{
if (*pxStreamBuffer).xTaskWaitingToReceive.is_null()
&& (*pxStreamBuffer).xTaskWaitingToSend.is_null()
{
prvInitialiseNewStreamBuffer(
pxStreamBuffer,
(*pxStreamBuffer).pucBuffer,
(*pxStreamBuffer).xLength,
(*pxStreamBuffer).xTriggerLevelBytes,
(*pxStreamBuffer).ucFlags,
None,
None,
);
xReturn = pdPASS;
}
}
portEXIT_CRITICAL();
xReturn
}
pub unsafe fn xStreamBufferResetFromISR(xStreamBuffer: StreamBufferHandle_t) -> BaseType_t {
configASSERT(!xStreamBuffer.is_null());
let pxStreamBuffer = xStreamBuffer as *mut StreamBuffer_t;
let mut xReturn: BaseType_t = pdFAIL;
let uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
if (*pxStreamBuffer).xTaskWaitingToReceive.is_null()
&& (*pxStreamBuffer).xTaskWaitingToSend.is_null()
{
prvInitialiseNewStreamBuffer(
pxStreamBuffer,
(*pxStreamBuffer).pucBuffer,
(*pxStreamBuffer).xLength,
(*pxStreamBuffer).xTriggerLevelBytes,
(*pxStreamBuffer).ucFlags,
None,
None,
);
xReturn = pdPASS;
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
xReturn
}
pub unsafe fn xStreamBufferBytesAvailable(xStreamBuffer: StreamBufferHandle_t) -> usize {
configASSERT(!xStreamBuffer.is_null());
let pxStreamBuffer = xStreamBuffer as *const StreamBuffer_t;
prvBytesInBuffer(pxStreamBuffer)
}
pub unsafe fn xStreamBufferSpacesAvailable(xStreamBuffer: StreamBufferHandle_t) -> usize {
configASSERT(!xStreamBuffer.is_null());
let pxStreamBuffer = xStreamBuffer as *const StreamBuffer_t;
let mut xSpace: usize;
let mut xOriginalTail: usize;
loop {
xOriginalTail = (*pxStreamBuffer).xTail;
xSpace = (*pxStreamBuffer).xLength + (*pxStreamBuffer).xTail;
xSpace -= (*pxStreamBuffer).xHead;
if xOriginalTail == (*pxStreamBuffer).xTail {
break;
}
}
xSpace -= 1;
if xSpace >= (*pxStreamBuffer).xLength {
xSpace -= (*pxStreamBuffer).xLength;
}
xSpace
}
pub unsafe fn xStreamBufferIsEmpty(xStreamBuffer: StreamBufferHandle_t) -> BaseType_t {
configASSERT(!xStreamBuffer.is_null());
let pxStreamBuffer = xStreamBuffer as *const StreamBuffer_t;
if (*pxStreamBuffer).xHead == (*pxStreamBuffer).xTail {
pdTRUE
} else {
pdFALSE
}
}
pub unsafe fn xStreamBufferIsFull(xStreamBuffer: StreamBufferHandle_t) -> BaseType_t {
configASSERT(!xStreamBuffer.is_null());
let pxStreamBuffer = xStreamBuffer as *const StreamBuffer_t;
let xBytesToStoreMessageLength = if ((*pxStreamBuffer).ucFlags & sbFLAGS_IS_MESSAGE_BUFFER) != 0
{
sbBYTES_TO_STORE_MESSAGE_LENGTH
} else {
0
};
if xStreamBufferSpacesAvailable(xStreamBuffer) <= xBytesToStoreMessageLength {
pdTRUE
} else {
pdFALSE
}
}
pub unsafe fn xStreamBufferSetTriggerLevel(
xStreamBuffer: StreamBufferHandle_t,
mut xTriggerLevel: usize,
) -> BaseType_t {
configASSERT(!xStreamBuffer.is_null());
let pxStreamBuffer = xStreamBuffer as *mut StreamBuffer_t;
if xTriggerLevel == 0 {
xTriggerLevel = 1;
}
if xTriggerLevel < (*pxStreamBuffer).xLength {
(*pxStreamBuffer).xTriggerLevelBytes = xTriggerLevel;
pdPASS
} else {
pdFALSE
}
}
pub unsafe fn xStreamBufferNextMessageLengthBytes(xStreamBuffer: StreamBufferHandle_t) -> usize {
configASSERT(!xStreamBuffer.is_null());
let pxStreamBuffer = xStreamBuffer as *mut StreamBuffer_t;
if ((*pxStreamBuffer).ucFlags & sbFLAGS_IS_MESSAGE_BUFFER) != 0 {
let xBytesAvailable = prvBytesInBuffer(pxStreamBuffer);
if xBytesAvailable > sbBYTES_TO_STORE_MESSAGE_LENGTH {
let mut xTempReturn: configMESSAGE_BUFFER_LENGTH_TYPE = 0;
prvReadBytesFromBuffer(
pxStreamBuffer,
&mut xTempReturn as *mut _ as *mut u8,
sbBYTES_TO_STORE_MESSAGE_LENGTH,
(*pxStreamBuffer).xTail,
);
xTempReturn as usize
} else {
0
}
} else {
0
}
}
pub unsafe fn xStreamBufferSend(
xStreamBuffer: StreamBufferHandle_t,
pvTxData: *const c_void,
xDataLengthBytes: usize,
mut xTicksToWait: TickType_t,
) -> usize {
configASSERT(!pvTxData.is_null());
configASSERT(!xStreamBuffer.is_null());
let pxStreamBuffer = xStreamBuffer as *mut StreamBuffer_t;
let mut xSpace: usize = 0;
let mut xRequiredSpace = xDataLengthBytes;
let xMaxReportedSpace = (*pxStreamBuffer).xLength - 1;
if ((*pxStreamBuffer).ucFlags & sbFLAGS_IS_MESSAGE_BUFFER) != 0 {
xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH;
if xRequiredSpace > xMaxReportedSpace {
xTicksToWait = 0;
}
} else {
if xRequiredSpace > xMaxReportedSpace {
xRequiredSpace = xMaxReportedSpace;
}
}
if xTicksToWait != 0 {
let mut xTimeOut = TimeOut_t::default();
vTaskSetTimeOutState(&mut xTimeOut);
loop {
portENTER_CRITICAL();
{
xSpace = xStreamBufferSpacesAvailable(xStreamBuffer);
if xSpace < xRequiredSpace {
configASSERT((*pxStreamBuffer).xTaskWaitingToSend.is_null());
(*pxStreamBuffer).xTaskWaitingToSend = xTaskGetCurrentTaskHandle();
} else {
portEXIT_CRITICAL();
break;
}
}
portEXIT_CRITICAL();
xTaskNotifyWait(0, 0, ptr::null_mut(), xTicksToWait);
(*pxStreamBuffer).xTaskWaitingToSend = ptr::null_mut();
if xTaskCheckForTimeOut(&mut xTimeOut, &mut xTicksToWait) != pdFALSE {
break;
}
}
}
if xSpace == 0 {
xSpace = xStreamBufferSpacesAvailable(xStreamBuffer);
}
let xReturn = prvWriteMessageToBuffer(
pxStreamBuffer,
pvTxData,
xDataLengthBytes,
xSpace,
xRequiredSpace,
);
if xReturn > 0 {
if prvBytesInBuffer(pxStreamBuffer) >= (*pxStreamBuffer).xTriggerLevelBytes {
sbSEND_COMPLETED(pxStreamBuffer);
}
}
xReturn
}
pub unsafe fn xStreamBufferSendFromISR(
xStreamBuffer: StreamBufferHandle_t,
pvTxData: *const c_void,
xDataLengthBytes: usize,
pxHigherPriorityTaskWoken: *mut BaseType_t,
) -> usize {
configASSERT(!pvTxData.is_null());
configASSERT(!xStreamBuffer.is_null());
let pxStreamBuffer = xStreamBuffer as *mut StreamBuffer_t;
let mut xRequiredSpace = xDataLengthBytes;
if ((*pxStreamBuffer).ucFlags & sbFLAGS_IS_MESSAGE_BUFFER) != 0 {
xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH;
}
let xSpace = xStreamBufferSpacesAvailable(xStreamBuffer);
let xReturn = prvWriteMessageToBuffer(
pxStreamBuffer,
pvTxData,
xDataLengthBytes,
xSpace,
xRequiredSpace,
);
if xReturn > 0 {
if prvBytesInBuffer(pxStreamBuffer) >= (*pxStreamBuffer).xTriggerLevelBytes {
sbSEND_COMPLETE_FROM_ISR(pxStreamBuffer, pxHigherPriorityTaskWoken);
}
}
xReturn
}
pub unsafe fn xStreamBufferReceive(
xStreamBuffer: StreamBufferHandle_t,
pvRxData: *mut c_void,
xBufferLengthBytes: usize,
xTicksToWait: TickType_t,
) -> usize {
configASSERT(!pvRxData.is_null());
configASSERT(!xStreamBuffer.is_null());
let pxStreamBuffer = xStreamBuffer as *mut StreamBuffer_t;
let mut xReceivedLength: usize = 0;
let mut xBytesAvailable: usize;
let xBytesToStoreMessageLength = if ((*pxStreamBuffer).ucFlags & sbFLAGS_IS_MESSAGE_BUFFER) != 0
{
sbBYTES_TO_STORE_MESSAGE_LENGTH
} else if ((*pxStreamBuffer).ucFlags & sbFLAGS_IS_BATCHING_BUFFER) != 0 {
(*pxStreamBuffer).xTriggerLevelBytes
} else {
0
};
if xTicksToWait != 0 {
portENTER_CRITICAL();
{
xBytesAvailable = prvBytesInBuffer(pxStreamBuffer);
if xBytesAvailable <= xBytesToStoreMessageLength {
configASSERT((*pxStreamBuffer).xTaskWaitingToReceive.is_null());
(*pxStreamBuffer).xTaskWaitingToReceive = xTaskGetCurrentTaskHandle();
}
}
portEXIT_CRITICAL();
if xBytesAvailable <= xBytesToStoreMessageLength {
xTaskNotifyWait(0, 0, ptr::null_mut(), xTicksToWait);
(*pxStreamBuffer).xTaskWaitingToReceive = ptr::null_mut();
xBytesAvailable = prvBytesInBuffer(pxStreamBuffer);
}
} else {
xBytesAvailable = prvBytesInBuffer(pxStreamBuffer);
}
if xBytesAvailable > xBytesToStoreMessageLength {
xReceivedLength = prvReadMessageFromBuffer(
pxStreamBuffer,
pvRxData,
xBufferLengthBytes,
xBytesAvailable,
);
if xReceivedLength != 0 {
sbRECEIVE_COMPLETED(pxStreamBuffer);
}
}
xReceivedLength
}
pub unsafe fn xStreamBufferReceiveFromISR(
xStreamBuffer: StreamBufferHandle_t,
pvRxData: *mut c_void,
xBufferLengthBytes: usize,
pxHigherPriorityTaskWoken: *mut BaseType_t,
) -> usize {
configASSERT(!pvRxData.is_null());
configASSERT(!xStreamBuffer.is_null());
let pxStreamBuffer = xStreamBuffer as *mut StreamBuffer_t;
let mut xReceivedLength: usize = 0;
let xBytesToStoreMessageLength = if ((*pxStreamBuffer).ucFlags & sbFLAGS_IS_MESSAGE_BUFFER) != 0
{
sbBYTES_TO_STORE_MESSAGE_LENGTH
} else {
0
};
let xBytesAvailable = prvBytesInBuffer(pxStreamBuffer);
if xBytesAvailable > xBytesToStoreMessageLength {
xReceivedLength = prvReadMessageFromBuffer(
pxStreamBuffer,
pvRxData,
xBufferLengthBytes,
xBytesAvailable,
);
if xReceivedLength != 0 {
sbRECEIVE_COMPLETED_FROM_ISR(pxStreamBuffer, pxHigherPriorityTaskWoken);
}
}
xReceivedLength
}
pub unsafe fn uxStreamBufferGetStreamBufferNotificationIndex(
xStreamBuffer: StreamBufferHandle_t,
) -> UBaseType_t {
configASSERT(!xStreamBuffer.is_null());
let pxStreamBuffer = xStreamBuffer as *const StreamBuffer_t;
(*pxStreamBuffer).uxNotificationIndex
}
pub unsafe fn vStreamBufferSetStreamBufferNotificationIndex(
xStreamBuffer: StreamBufferHandle_t,
uxNotificationIndex: UBaseType_t,
) {
configASSERT(!xStreamBuffer.is_null());
let pxStreamBuffer = xStreamBuffer as *mut StreamBuffer_t;
configASSERT((*pxStreamBuffer).xTaskWaitingToReceive.is_null());
configASSERT((*pxStreamBuffer).xTaskWaitingToSend.is_null());
(*pxStreamBuffer).uxNotificationIndex = uxNotificationIndex;
}
pub unsafe fn xStreamBufferSendCompletedFromISR(
xStreamBuffer: StreamBufferHandle_t,
pxHigherPriorityTaskWoken: *mut BaseType_t,
) -> BaseType_t {
configASSERT(!xStreamBuffer.is_null());
let pxStreamBuffer = xStreamBuffer as *mut StreamBuffer_t;
let mut xReturn: BaseType_t = pdFALSE;
let uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
if !(*pxStreamBuffer).xTaskWaitingToReceive.is_null() {
xTaskNotifyFromISR(
(*pxStreamBuffer).xTaskWaitingToReceive,
0,
eNoAction as i32,
pxHigherPriorityTaskWoken,
);
(*pxStreamBuffer).xTaskWaitingToReceive = ptr::null_mut();
xReturn = pdTRUE;
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
xReturn
}
pub unsafe fn xStreamBufferReceiveCompletedFromISR(
xStreamBuffer: StreamBufferHandle_t,
pxHigherPriorityTaskWoken: *mut BaseType_t,
) -> BaseType_t {
configASSERT(!xStreamBuffer.is_null());
let pxStreamBuffer = xStreamBuffer as *mut StreamBuffer_t;
let mut xReturn: BaseType_t = pdFALSE;
let uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
if !(*pxStreamBuffer).xTaskWaitingToSend.is_null() {
xTaskNotifyFromISR(
(*pxStreamBuffer).xTaskWaitingToSend,
0,
eNoAction as i32,
pxHigherPriorityTaskWoken,
);
(*pxStreamBuffer).xTaskWaitingToSend = ptr::null_mut();
xReturn = pdTRUE;
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
xReturn
}
unsafe fn prvInitialiseNewStreamBuffer(
pxStreamBuffer: *mut StreamBuffer_t,
pucBuffer: *mut u8,
xBufferSizeBytes: usize,
xTriggerLevelBytes: usize,
ucFlags: u8,
_pxSendCompletedCallback: StreamBufferCallbackFunction_t,
_pxReceiveCompletedCallback: StreamBufferCallbackFunction_t,
) {
ptr::write_bytes(pxStreamBuffer, 0, 1);
(*pxStreamBuffer).pucBuffer = pucBuffer;
(*pxStreamBuffer).xLength = xBufferSizeBytes;
(*pxStreamBuffer).xTriggerLevelBytes = xTriggerLevelBytes;
(*pxStreamBuffer).ucFlags = ucFlags;
(*pxStreamBuffer).uxNotificationIndex = tskDEFAULT_INDEX_TO_NOTIFY;
}
unsafe fn prvBytesInBuffer(pxStreamBuffer: *const StreamBuffer_t) -> usize {
let mut xCount = (*pxStreamBuffer).xLength + (*pxStreamBuffer).xHead;
xCount -= (*pxStreamBuffer).xTail;
if xCount >= (*pxStreamBuffer).xLength {
xCount -= (*pxStreamBuffer).xLength;
}
xCount
}
unsafe fn prvWriteBytesToBuffer(
pxStreamBuffer: *mut StreamBuffer_t,
pucData: *const u8,
xCount: usize,
mut xHead: usize,
) -> usize {
configASSERT(xCount > 0);
let xFirstLength = core::cmp::min((*pxStreamBuffer).xLength - xHead, xCount);
ptr::copy_nonoverlapping(
pucData,
(*pxStreamBuffer).pucBuffer.add(xHead),
xFirstLength,
);
if xCount > xFirstLength {
ptr::copy_nonoverlapping(
pucData.add(xFirstLength),
(*pxStreamBuffer).pucBuffer,
xCount - xFirstLength,
);
}
xHead += xCount;
if xHead >= (*pxStreamBuffer).xLength {
xHead -= (*pxStreamBuffer).xLength;
}
xHead
}
unsafe fn prvReadBytesFromBuffer(
pxStreamBuffer: *mut StreamBuffer_t,
pucData: *mut u8,
xCount: usize,
mut xTail: usize,
) -> usize {
configASSERT(xCount > 0);
let xFirstLength = core::cmp::min((*pxStreamBuffer).xLength - xTail, xCount);
ptr::copy_nonoverlapping(
(*pxStreamBuffer).pucBuffer.add(xTail),
pucData,
xFirstLength,
);
if xCount > xFirstLength {
ptr::copy_nonoverlapping(
(*pxStreamBuffer).pucBuffer,
pucData.add(xFirstLength),
xCount - xFirstLength,
);
}
xTail += xCount;
if xTail >= (*pxStreamBuffer).xLength {
xTail -= (*pxStreamBuffer).xLength;
}
xTail
}
unsafe fn prvWriteMessageToBuffer(
pxStreamBuffer: *mut StreamBuffer_t,
pvTxData: *const c_void,
mut xDataLengthBytes: usize,
xSpace: usize,
xRequiredSpace: usize,
) -> usize {
let mut xNextHead = (*pxStreamBuffer).xHead;
if ((*pxStreamBuffer).ucFlags & sbFLAGS_IS_MESSAGE_BUFFER) != 0 {
if xSpace >= xRequiredSpace {
let xMessageLength = xDataLengthBytes as configMESSAGE_BUFFER_LENGTH_TYPE;
xNextHead = prvWriteBytesToBuffer(
pxStreamBuffer,
&xMessageLength as *const _ as *const u8,
sbBYTES_TO_STORE_MESSAGE_LENGTH,
xNextHead,
);
} else {
xDataLengthBytes = 0;
}
} else {
xDataLengthBytes = core::cmp::min(xDataLengthBytes, xSpace);
}
if xDataLengthBytes != 0 {
(*pxStreamBuffer).xHead = prvWriteBytesToBuffer(
pxStreamBuffer,
pvTxData as *const u8,
xDataLengthBytes,
xNextHead,
);
}
xDataLengthBytes
}
unsafe fn prvReadMessageFromBuffer(
pxStreamBuffer: *mut StreamBuffer_t,
pvRxData: *mut c_void,
xBufferLengthBytes: usize,
mut xBytesAvailable: usize,
) -> usize {
let mut xNextTail = (*pxStreamBuffer).xTail;
let xNextMessageLength: usize;
if ((*pxStreamBuffer).ucFlags & sbFLAGS_IS_MESSAGE_BUFFER) != 0 {
let mut xTempMessageLength: configMESSAGE_BUFFER_LENGTH_TYPE = 0;
xNextTail = prvReadBytesFromBuffer(
pxStreamBuffer,
&mut xTempMessageLength as *mut _ as *mut u8,
sbBYTES_TO_STORE_MESSAGE_LENGTH,
xNextTail,
);
xNextMessageLength = xTempMessageLength as usize;
xBytesAvailable -= sbBYTES_TO_STORE_MESSAGE_LENGTH;
if xNextMessageLength > xBufferLengthBytes {
return 0;
}
} else {
xNextMessageLength = xBufferLengthBytes;
}
let xCount = core::cmp::min(xNextMessageLength, xBytesAvailable);
if xCount != 0 {
(*pxStreamBuffer).xTail =
prvReadBytesFromBuffer(pxStreamBuffer, pvRxData as *mut u8, xCount, xNextTail);
}
xCount
}
#[inline(always)]
unsafe fn sbSEND_COMPLETED(pxStreamBuffer: *mut StreamBuffer_t) {
vTaskSuspendAll();
if !(*pxStreamBuffer).xTaskWaitingToReceive.is_null() {
xTaskNotify((*pxStreamBuffer).xTaskWaitingToReceive, 0, eNoAction as i32);
(*pxStreamBuffer).xTaskWaitingToReceive = ptr::null_mut();
}
xTaskResumeAll();
}
#[inline(always)]
unsafe fn sbSEND_COMPLETE_FROM_ISR(
pxStreamBuffer: *mut StreamBuffer_t,
pxHigherPriorityTaskWoken: *mut BaseType_t,
) {
let uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
if !(*pxStreamBuffer).xTaskWaitingToReceive.is_null() {
xTaskNotifyFromISR(
(*pxStreamBuffer).xTaskWaitingToReceive,
0,
eNoAction as i32,
pxHigherPriorityTaskWoken,
);
(*pxStreamBuffer).xTaskWaitingToReceive = ptr::null_mut();
}
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
}
#[inline(always)]
unsafe fn sbRECEIVE_COMPLETED(pxStreamBuffer: *mut StreamBuffer_t) {
vTaskSuspendAll();
if !(*pxStreamBuffer).xTaskWaitingToSend.is_null() {
xTaskNotify((*pxStreamBuffer).xTaskWaitingToSend, 0, eNoAction as i32);
(*pxStreamBuffer).xTaskWaitingToSend = ptr::null_mut();
}
xTaskResumeAll();
}
#[inline(always)]
unsafe fn sbRECEIVE_COMPLETED_FROM_ISR(
pxStreamBuffer: *mut StreamBuffer_t,
pxHigherPriorityTaskWoken: *mut BaseType_t,
) {
let uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
if !(*pxStreamBuffer).xTaskWaitingToSend.is_null() {
xTaskNotifyFromISR(
(*pxStreamBuffer).xTaskWaitingToSend,
0,
eNoAction as i32,
pxHigherPriorityTaskWoken,
);
(*pxStreamBuffer).xTaskWaitingToSend = ptr::null_mut();
}
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
}
const eNoAction: u32 = 0;
#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
pub unsafe fn xStreamBufferGetStaticBuffers(
xStreamBuffer: StreamBufferHandle_t,
ppucStreamBufferStorageArea: *mut *mut u8,
ppxStaticStreamBuffer: *mut *mut StaticStreamBuffer_t,
) -> BaseType_t {
configASSERT(!xStreamBuffer.is_null());
let pxStreamBuffer = xStreamBuffer as *mut StreamBuffer_t;
let xReturn: BaseType_t;
if ((*pxStreamBuffer).ucFlags & sbFLAGS_IS_STATICALLY_ALLOCATED) != 0 {
xReturn = pdTRUE;
if !ppucStreamBufferStorageArea.is_null() {
*ppucStreamBufferStorageArea = (*pxStreamBuffer).pucBuffer;
}
if !ppxStaticStreamBuffer.is_null() {
*ppxStaticStreamBuffer = pxStreamBuffer as *mut StaticStreamBuffer_t;
}
} else {
xReturn = pdFALSE;
}
xReturn
}
#[cfg(feature = "trace-facility")]
pub unsafe fn uxStreamBufferGetStreamBufferNumber(
xStreamBuffer: StreamBufferHandle_t,
) -> UBaseType_t {
configASSERT(!xStreamBuffer.is_null());
let pxStreamBuffer = xStreamBuffer as *const StreamBuffer_t;
(*pxStreamBuffer).uxStreamBufferNumber
}
#[cfg(feature = "trace-facility")]
pub unsafe fn vStreamBufferSetStreamBufferNumber(
xStreamBuffer: StreamBufferHandle_t,
uxStreamBufferNumber: UBaseType_t,
) {
configASSERT(!xStreamBuffer.is_null());
let pxStreamBuffer = xStreamBuffer as *mut StreamBuffer_t;
(*pxStreamBuffer).uxStreamBufferNumber = uxStreamBufferNumber;
}
#[cfg(feature = "trace-facility")]
pub unsafe fn ucStreamBufferGetStreamBufferType(xStreamBuffer: StreamBufferHandle_t) -> u8 {
configASSERT(!xStreamBuffer.is_null());
let pxStreamBuffer = xStreamBuffer as *const StreamBuffer_t;
(*pxStreamBuffer).ucFlags & sbFLAGS_IS_MESSAGE_BUFFER
}