/* * Copyright (c) 2019 Actions Semiconductor Co., Ltd * * SPDX-License-Identifier: Apache-2.0 */ /** * @file cbuf interface */ #include #include "cbuf.h" #include int cbuf_read(cbuf_t *cbuf, void *buffer, int32_t len) { int32_t read_len = len; int32_t copy_len; uint32_t flags; if(!cbuf){ return 0; } if(cbuf->length < len){ return 0; } if(cbuf->read_ptr >= cbuf->capacity){ cbuf->read_ptr = 0; } //buffer is null only change read ptr and length if(!buffer){ flags = irq_lock(); cbuf->read_ptr += len; if (cbuf->capacity != 0){ cbuf->read_ptr %= cbuf->capacity; } cbuf->length -= len; irq_unlock(flags); return len; } copy_len = cbuf->capacity - cbuf->read_ptr; if(copy_len > len){ copy_len = len; } len -= copy_len; memcpy(buffer, cbuf->raw_data + cbuf->read_ptr, copy_len); if(len == 0){ cbuf->read_ptr += copy_len; }else{ memcpy((uint8_t *)buffer + copy_len, cbuf->raw_data, len); cbuf->read_ptr = len; } flags = irq_lock(); cbuf->length -= read_len; irq_unlock(flags); return read_len; } int cbuf_dma_read(cbuf_t *cbuf, cbuf_dma_t *dma, int32_t read_len) { uint32_t copy_len; if(!cbuf){ goto ret; } if(cbuf->length < read_len){ read_len = cbuf->length; goto ret; } if(cbuf->read_ptr >= cbuf->capacity){ cbuf->read_ptr = 0; } copy_len = cbuf->capacity - cbuf->read_ptr; if(copy_len > read_len){ copy_len = read_len; } dma->read_len = copy_len; dma->start_addr = cbuf->raw_data + cbuf->read_ptr; return read_len; ret: dma->read_len = 0; return 0; } int cbuf_dma_update_read_ptr(cbuf_t *cbuf, int32_t read_len) { uint32_t flags; flags = irq_lock(); cbuf->read_ptr += read_len; cbuf->length -= read_len; irq_unlock(flags); return 0; } int cbuf_prepare_read(cbuf_t *cbuf, void *buffer, int32_t len) { int32_t read_len = len; int32_t copy_len; if(!cbuf){ return 0; } if(cbuf->length < len){ return 0; } if(!buffer){ return 0; } if(cbuf->read_ptr >= cbuf->capacity){ cbuf->read_ptr = 0; } copy_len = cbuf->capacity - cbuf->read_ptr; if(copy_len > len){ copy_len = len; } len -= copy_len; memcpy(buffer, cbuf->raw_data + cbuf->read_ptr, copy_len); if(len){ memcpy((uint8_t *)buffer + copy_len, cbuf->raw_data, len); } return read_len; } int cbuf_write(cbuf_t *cbuf, void *buffer, int32_t len) { uint32_t write_len; uint32_t rem_len; uint32_t flags; if((!cbuf) || (len == 0) || (len > cbuf->capacity)){ return 0; } if((cbuf->capacity - cbuf->length) < len){ return 0; } if(cbuf->write_ptr >= cbuf->capacity){ cbuf->write_ptr = 0; } write_len = cbuf->capacity - cbuf->write_ptr; if(write_len >= len){ memcpy(cbuf->raw_data + cbuf->write_ptr, buffer, len); cbuf->write_ptr += len; }else{ rem_len = len - write_len; memcpy(cbuf->raw_data + cbuf->write_ptr, buffer, write_len); memcpy(cbuf->raw_data, (uint8_t *)buffer + write_len, rem_len); cbuf->write_ptr = rem_len; } flags = irq_lock(); cbuf->length += len; irq_unlock(flags); return len; } void cbuf_init(cbuf_t *cbuf, void *buffer, int32_t size) { uint32_t flags; flags = irq_lock(); cbuf->raw_data = buffer; cbuf->capacity = size; cbuf->write_ptr = 0; cbuf->read_ptr = 0; cbuf->length = 0; irq_unlock(flags); } void cbuf_reset(cbuf_t *cbuf) { uint32_t flags; flags = irq_lock(); cbuf->write_ptr = 0; cbuf->read_ptr = 0; cbuf->length = 0; irq_unlock(flags); } void cbuf_copy_write_ptr(cbuf_t *src, cbuf_t *dest, uint32_t len) { uint32_t flags; flags = irq_lock(); dest->write_ptr = src->write_ptr; dest->length += len; irq_unlock(flags); } void cbuf_deinit(cbuf_t *cbuf) { memset(cbuf, 0, sizeof(cbuf_t)); }