1094332d3Sopenharmony_ci/*
2094332d3Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3094332d3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4094332d3Sopenharmony_ci * you may not use this file except in compliance with the License.
5094332d3Sopenharmony_ci * You may obtain a copy of the License at
6094332d3Sopenharmony_ci *
7094332d3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8094332d3Sopenharmony_ci *
9094332d3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10094332d3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11094332d3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12094332d3Sopenharmony_ci * See the License for the specific language governing permissions and
13094332d3Sopenharmony_ci * limitations under the License.
14094332d3Sopenharmony_ci */
15094332d3Sopenharmony_ci
16094332d3Sopenharmony_ci#ifndef HDF_USB_DATA_FIFO_H
17094332d3Sopenharmony_ci#define HDF_USB_DATA_FIFO_H
18094332d3Sopenharmony_ci
19094332d3Sopenharmony_ci#include "hdf_base.h"
20094332d3Sopenharmony_ci#include "hdf_log.h"
21094332d3Sopenharmony_ci
22094332d3Sopenharmony_ci#ifndef MIN
23094332d3Sopenharmony_ci#define MIN(a, b) ((a) < (b) ? (a) : (b))
24094332d3Sopenharmony_ci#endif
25094332d3Sopenharmony_ci
26094332d3Sopenharmony_ci#ifndef MAX
27094332d3Sopenharmony_ci#define MAX(a, b) ((a) > (b) ? (a) : (b))
28094332d3Sopenharmony_ci#endif
29094332d3Sopenharmony_ci
30094332d3Sopenharmony_cistruct DataFifo {
31094332d3Sopenharmony_ci    uint32_t rdIdx;
32094332d3Sopenharmony_ci    uint32_t wrIdx;
33094332d3Sopenharmony_ci    uint32_t size;
34094332d3Sopenharmony_ci    void     *data;
35094332d3Sopenharmony_ci};
36094332d3Sopenharmony_ci
37094332d3Sopenharmony_ci/* DataFifo Helper function */
38094332d3Sopenharmony_cistatic inline void DataFifoInit(struct DataFifo *fifo, uint32_t size, void *data)
39094332d3Sopenharmony_ci{
40094332d3Sopenharmony_ci    if (size == 0) {
41094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: Fifo size is zero", __func__);
42094332d3Sopenharmony_ci        return;
43094332d3Sopenharmony_ci    }
44094332d3Sopenharmony_ci    fifo->rdIdx = 0;
45094332d3Sopenharmony_ci    fifo->wrIdx = 0;
46094332d3Sopenharmony_ci    fifo->size = size;
47094332d3Sopenharmony_ci    fifo->data = data;
48094332d3Sopenharmony_ci}
49094332d3Sopenharmony_ci
50094332d3Sopenharmony_cistatic inline bool DataFifoIsInitialized(struct DataFifo *fifo)
51094332d3Sopenharmony_ci{
52094332d3Sopenharmony_ci    return fifo->size != 0;
53094332d3Sopenharmony_ci}
54094332d3Sopenharmony_ci
55094332d3Sopenharmony_cistatic inline void DataFifoReset(struct DataFifo *fifo)
56094332d3Sopenharmony_ci{
57094332d3Sopenharmony_ci    fifo->rdIdx = fifo->wrIdx = 0;
58094332d3Sopenharmony_ci}
59094332d3Sopenharmony_ci
60094332d3Sopenharmony_cistatic inline uint32_t DataFifoLen(struct DataFifo *fifo)
61094332d3Sopenharmony_ci{
62094332d3Sopenharmony_ci    return fifo->wrIdx - fifo->rdIdx;
63094332d3Sopenharmony_ci}
64094332d3Sopenharmony_ci
65094332d3Sopenharmony_cistatic inline bool DataFifoIsEmpty(struct DataFifo *fifo)
66094332d3Sopenharmony_ci{
67094332d3Sopenharmony_ci    return fifo->wrIdx == fifo->rdIdx;
68094332d3Sopenharmony_ci}
69094332d3Sopenharmony_ci
70094332d3Sopenharmony_cistatic inline bool DataFifoIsFull(struct DataFifo *fifo)
71094332d3Sopenharmony_ci{
72094332d3Sopenharmony_ci    return DataFifoLen(fifo) > (fifo->size - 1);
73094332d3Sopenharmony_ci}
74094332d3Sopenharmony_ci
75094332d3Sopenharmony_cistatic inline uint32_t DataFifoAvailSize(struct DataFifo *fifo)
76094332d3Sopenharmony_ci{
77094332d3Sopenharmony_ci    return fifo->size - DataFifoLen(fifo);
78094332d3Sopenharmony_ci}
79094332d3Sopenharmony_ci
80094332d3Sopenharmony_cistatic inline void DataFifoSkip(struct DataFifo *fifo, uint32_t size)
81094332d3Sopenharmony_ci{
82094332d3Sopenharmony_ci    fifo->rdIdx += size;
83094332d3Sopenharmony_ci}
84094332d3Sopenharmony_ci
85094332d3Sopenharmony_cistatic inline uint32_t DataFifoWrite(struct DataFifo *fifo, uint8_t *data, uint32_t size)
86094332d3Sopenharmony_ci{
87094332d3Sopenharmony_ci    uint32_t mask = fifo->size - 1;
88094332d3Sopenharmony_ci    uint8_t *buf = (uint8_t *)fifo->data;
89094332d3Sopenharmony_ci    uint8_t *end;
90094332d3Sopenharmony_ci
91094332d3Sopenharmony_ci    size = MIN(size, DataFifoAvailSize(fifo));
92094332d3Sopenharmony_ci    end = data + size;
93094332d3Sopenharmony_ci    while (data < end) {
94094332d3Sopenharmony_ci        buf[fifo->wrIdx++ & mask] = *data++;
95094332d3Sopenharmony_ci    }
96094332d3Sopenharmony_ci    return size;
97094332d3Sopenharmony_ci}
98094332d3Sopenharmony_ci
99094332d3Sopenharmony_cistatic inline uint32_t DataFifoRead(struct DataFifo *fifo, uint8_t *data, uint32_t size)
100094332d3Sopenharmony_ci{
101094332d3Sopenharmony_ci    uint32_t mask = fifo->size - 1;
102094332d3Sopenharmony_ci    uint8_t *buf = (uint8_t *)fifo->data;
103094332d3Sopenharmony_ci    uint8_t *end;
104094332d3Sopenharmony_ci
105094332d3Sopenharmony_ci    size = MIN(size, DataFifoLen(fifo));
106094332d3Sopenharmony_ci    end = data + size;
107094332d3Sopenharmony_ci    while (data < end) {
108094332d3Sopenharmony_ci        *data++ = buf[fifo->rdIdx++ & mask];
109094332d3Sopenharmony_ci    }
110094332d3Sopenharmony_ci    return size;
111094332d3Sopenharmony_ci}
112094332d3Sopenharmony_ci
113094332d3Sopenharmony_ci#endif /* HDF_USB_DATA_FIFO_H */
114