| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494 |
- /*
- * Copyright (c) 2022, Egahp
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- #ifndef USB_RINGBUFFER_H
- #define USB_RINGBUFFER_H
- #include <stdint.h>
- #include <stdbool.h>
- #include <string.h>
- #ifdef __cplusplus
- extern "C" {
- #endif
- typedef struct {
- uint32_t in; /*!< Define the write pointer. */
- uint32_t out; /*!< Define the read pointer. */
- uint32_t mask; /*!< Define the write and read pointer mask. */
- void *pool; /*!< Define the memory pointer. */
- } usb_ringbuffer_t;
- /*****************************************************************************
- * @brief init ringbuffer
- *
- * @param[in] rb ringbuffer instance
- * @param[in] pool memory pool address
- * @param[in] size memory size in byte,
- * must be power of 2 !!!
- *
- * @retval int 0:Success -1:Error
- *****************************************************************************/
- static inline int usb_ringbuffer_init(usb_ringbuffer_t *rb, void *pool, uint32_t size)
- {
- if (NULL == rb) {
- return -1;
- }
- if (NULL == pool) {
- return -1;
- }
- if ((size < 2) || (size & (size - 1))) {
- return -1;
- }
- rb->in = 0;
- rb->out = 0;
- rb->mask = size - 1;
- rb->pool = pool;
- return 0;
- }
- /*****************************************************************************
- * @brief reset ringbuffer, clean all data,
- * should be add lock in multithread
- *
- * @param[in] rb ringbuffer instance
- *
- *****************************************************************************/
- static inline void usb_ringbuffer_reset(usb_ringbuffer_t *rb)
- {
- rb->in = 0;
- rb->out = 0;
- }
- /*****************************************************************************
- * @brief reset ringbuffer, clean all data,
- * should be add lock in multithread,
- * in single read thread not need lock
- *
- * @param[in] rb ringbuffer instance
- *
- *****************************************************************************/
- static inline void usb_ringbuffer_reset_read(usb_ringbuffer_t *rb)
- {
- rb->out = rb->in;
- }
- /*****************************************************************************
- * @brief get ringbuffer total size in byte
- *
- * @param[in] rb ringbuffer instance
- *
- * @retval uint32_t total size in byte
- *****************************************************************************/
- static inline uint32_t usb_ringbuffer_get_size(usb_ringbuffer_t *rb)
- {
- return rb->mask + 1;
- }
- /*****************************************************************************
- * @brief get ringbuffer used size in byte
- *
- * @param[in] rb ringbuffer instance
- *
- * @retval uint32_t used size in byte
- *****************************************************************************/
- static inline uint32_t usb_ringbuffer_get_used(usb_ringbuffer_t *rb)
- {
- return rb->in - rb->out;
- }
- /*****************************************************************************
- * @brief get ringbuffer free size in byte
- *
- * @param[in] rb ringbuffer instance
- *
- * @retval uint32_t free size in byte
- *****************************************************************************/
- static inline uint32_t usb_ringbuffer_get_free(usb_ringbuffer_t *rb)
- {
- return (rb->mask + 1) - (rb->in - rb->out);
- }
- /*****************************************************************************
- * @brief check if ringbuffer is full
- *
- * @param[in] rb ringbuffer instance
- *
- * @retval true full
- * @retval false not full
- *****************************************************************************/
- static inline bool usb_ringbuffer_check_full(usb_ringbuffer_t *rb)
- {
- return usb_ringbuffer_get_used(rb) > rb->mask;
- }
- /*****************************************************************************
- * @brief check if ringbuffer is empty
- *
- * @param[in] rb ringbuffer instance
- *
- * @retval true empty
- * @retval false not empty
- *****************************************************************************/
- static inline bool usb_ringbuffer_check_empty(usb_ringbuffer_t *rb)
- {
- return rb->in == rb->out;
- }
- /*****************************************************************************
- * @brief write one byte to ringbuffer,
- * should be add lock in multithread,
- * in single write thread not need lock
- *
- * @param[in] rb ringbuffer instance
- * @param[in] byte data
- *
- * @retval true Success
- * @retval false ringbuffer is full
- *****************************************************************************/
- static inline bool usb_ringbuffer_write_byte(usb_ringbuffer_t *rb, uint8_t byte)
- {
- if (usb_ringbuffer_check_full(rb)) {
- return false;
- }
- ((uint8_t *)(rb->pool))[rb->in & rb->mask] = byte;
- rb->in++;
- return true;
- }
- /*****************************************************************************
- * @brief overwrite one byte to ringbuffer, drop oldest data,
- * should be add lock always
- *
- * @param[in] rb ringbuffer instance
- * @param[in] byte data
- *
- * @retval true Success
- * @retval false always return true
- *****************************************************************************/
- static inline bool usb_ringbuffer_overwrite_byte(usb_ringbuffer_t *rb, uint8_t byte)
- {
- if (usb_ringbuffer_check_full(rb)) {
- rb->out++;
- }
- ((uint8_t *)(rb->pool))[rb->in & rb->mask] = byte;
- rb->in++;
- return true;
- }
- /*****************************************************************************
- * @brief peek one byte from ringbuffer,
- * should be add lock in multithread,
- * in single read thread not need lock
- *
- * @param[in] rb ringbuffer instance
- * @param[in] byte pointer to save data
- *
- * @retval true Success
- * @retval false ringbuffer is empty
- *****************************************************************************/
- static inline bool usb_ringbuffer_peek_byte(usb_ringbuffer_t *rb, uint8_t *byte)
- {
- if (usb_ringbuffer_check_empty(rb)) {
- return false;
- }
- *byte = ((uint8_t *)(rb->pool))[rb->out & rb->mask];
- return true;
- }
- /*****************************************************************************
- * @brief read one byte from ringbuffer,
- * should be add lock in multithread,
- * in single read thread not need lock
- *
- * @param[in] rb ringbuffer instance
- * @param[in] byte pointer to save data
- *
- * @retval true Success
- * @retval false ringbuffer is empty
- *****************************************************************************/
- static inline bool usb_ringbuffer_read_byte(usb_ringbuffer_t *rb, uint8_t *byte)
- {
- bool ret;
- ret = usb_ringbuffer_peek_byte(rb, byte);
- rb->out += ret;
- return ret;
- }
- /*****************************************************************************
- * @brief drop one byte from ringbuffer,
- * should be add lock in multithread,
- * in single read thread not need lock
- *
- * @param[in] rb ringbuffer instance
- *
- * @retval true Success
- * @retval false ringbuffer is empty
- *****************************************************************************/
- static inline bool usb_ringbuffer_drop_byte(usb_ringbuffer_t *rb)
- {
- if (usb_ringbuffer_check_empty(rb)) {
- return false;
- }
- rb->out += 1;
- return true;
- }
- /*****************************************************************************
- * @brief write data to ringbuffer,
- * should be add lock in multithread,
- * in single write thread not need lock
- *
- * @param[in] rb ringbuffer instance
- * @param[in] data data pointer
- * @param[in] size size in byte
- *
- * @retval uint32_t actual write size in byte
- *****************************************************************************/
- static inline uint32_t usb_ringbuffer_write(usb_ringbuffer_t *rb, void *data, uint32_t size)
- {
- uint32_t unused;
- uint32_t offset;
- uint32_t remain;
- unused = (rb->mask + 1) - (rb->in - rb->out);
- if (size > unused) {
- size = unused;
- }
- offset = rb->in & rb->mask;
- remain = rb->mask + 1 - offset;
- remain = remain > size ? size : remain;
- memcpy(((uint8_t *)(rb->pool)) + offset, data, remain);
- memcpy(rb->pool, (uint8_t *)data + remain, size - remain);
- rb->in += size;
- return size;
- }
- /*****************************************************************************
- * @brief write data to ringbuffer,
- * should be add lock always
- *
- * @param[in] rb ringbuffer instance
- * @param[in] data data pointer
- * @param[in] size size in byte
- *
- * @retval uint32_t actual write size in byte
- *****************************************************************************/
- static inline uint32_t usb_ringbuffer_overwrite(usb_ringbuffer_t *rb, void *data, uint32_t size)
- {
- uint32_t unused;
- uint32_t offset;
- uint32_t remain;
- unused = (rb->mask + 1) - (rb->in - rb->out);
- if (size > unused) {
- if (size > (rb->mask + 1)) {
- size = rb->mask + 1;
- }
- rb->out += size - unused;
- }
- offset = rb->in & rb->mask;
- remain = rb->mask + 1 - offset;
- remain = remain > size ? size : remain;
- memcpy(((uint8_t *)(rb->pool)) + offset, data, remain);
- memcpy(rb->pool, (uint8_t *)data + remain, size - remain);
- rb->in += size;
- return size;
- }
- /*****************************************************************************
- * @brief peek data from ringbuffer
- * should be add lock in multithread,
- * in single read thread not need lock
- *
- * @param[in] rb ringbuffer instance
- * @param[in] data data pointer
- * @param[in] size size in byte
- *
- * @retval uint32_t actual peek size in byte
- *****************************************************************************/
- static inline uint32_t usb_ringbuffer_peek(usb_ringbuffer_t *rb, void *data, uint32_t size)
- {
- uint32_t used;
- uint32_t offset;
- uint32_t remain;
- used = rb->in - rb->out;
- if (size > used) {
- size = used;
- }
- offset = rb->out & rb->mask;
- remain = rb->mask + 1 - offset;
- remain = remain > size ? size : remain;
- memcpy(data, ((uint8_t *)(rb->pool)) + offset, remain);
- memcpy((uint8_t *)data + remain, rb->pool, size - remain);
- return size;
- }
- /*****************************************************************************
- * @brief read data from ringbuffer
- * should be add lock in multithread,
- * in single read thread not need lock
- *
- * @param[in] rb ringbuffer instance
- * @param[in] data data pointer
- * @param[in] size size in byte
- *
- * @retval uint32_t actual read size in byte
- *****************************************************************************/
- static inline uint32_t usb_ringbuffer_read(usb_ringbuffer_t *rb, void *data, uint32_t size)
- {
- size = usb_ringbuffer_peek(rb, data, size);
- rb->out += size;
- return size;
- }
- /*****************************************************************************
- * @brief drop data from ringbuffer
- * should be add lock in multithread,
- * in single read thread not need lock
- *
- * @param[in] rb ringbuffer instance
- * @param[in] size size in byte
- *
- * @retval uint32_t actual drop size in byte
- *****************************************************************************/
- static inline uint32_t usb_ringbuffer_drop(usb_ringbuffer_t *rb, uint32_t size)
- {
- uint32_t used;
- used = rb->in - rb->out;
- if (size > used) {
- size = used;
- }
- rb->out += size;
- return size;
- }
- /*****************************************************************************
- * @brief linear write setup, get write pointer and max linear size.
- *
- * @param[in] rb ringbuffer instance
- * @param[in] size pointer to store max linear size in byte
- *
- * @retval void* write memory pointer
- *****************************************************************************/
- static inline void *usb_ringbuffer_linear_write_setup(usb_ringbuffer_t *rb, uint32_t *size)
- {
- uint32_t unused;
- uint32_t offset;
- uint32_t remain;
- unused = (rb->mask + 1) - (rb->in - rb->out);
- offset = rb->in & rb->mask;
- remain = rb->mask + 1 - offset;
- remain = remain > unused ? unused : remain;
- if (remain) {
- *size = remain;
- return ((uint8_t *)(rb->pool)) + offset;
- } else {
- *size = unused - remain;
- return rb->pool;
- }
- }
- /*****************************************************************************
- * @brief linear read setup, get read pointer and max linear size.
- *
- * @param[in] rb ringbuffer instance
- * @param[in] size pointer to store max linear size in byte
- *
- * @retval void*
- *****************************************************************************/
- static inline void *usb_ringbuffer_linear_read_setup(usb_ringbuffer_t *rb, uint32_t *size)
- {
- uint32_t used;
- uint32_t offset;
- uint32_t remain;
- used = rb->in - rb->out;
- offset = rb->out & rb->mask;
- remain = rb->mask + 1 - offset;
- remain = remain > used ? used : remain;
- if (remain) {
- *size = remain;
- return ((uint8_t *)(rb->pool)) + offset;
- } else {
- *size = used - remain;
- return rb->pool;
- }
- }
- /*****************************************************************************
- * @brief linear write done, add write pointer only
- *
- * @param[in] rb ringbuffer instance
- * @param[in] size write size in byte
- *
- * @retval uint32_t actual write size in byte
- *****************************************************************************/
- static inline uint32_t usb_ringbuffer_linear_write_done(usb_ringbuffer_t *rb, uint32_t size)
- {
- uint32_t unused;
- unused = (rb->mask + 1) - (rb->in - rb->out);
- if (size > unused) {
- size = unused;
- }
- rb->in += size;
- return size;
- }
- /*****************************************************************************
- * @brief linear read done, add read pointer only
- *
- * @param[in] rb ringbuffer instance
- * @param[in] size read size in byte
- *
- * @retval uint32_t actual read size in byte
- *****************************************************************************/
- static inline uint32_t usb_ringbuffer_linear_read_done(usb_ringbuffer_t *rb, uint32_t size)
- {
- return usb_ringbuffer_drop(rb, size);
- }
- #ifdef __cplusplus
- }
- #endif
- #endif
|