1 /*
2 * Copyright (c) 2022 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "KRecvBuf.h"
17
18 #include "osal.h"
19 #include "securec.h"
20 #include "user_copy.h"
21
22 #define HDF_LOG_TAG KRecvBuf
23
24 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
25
KRecvBufUsedSize(KRecvBuf * krbCB)26 UINT32 KRecvBufUsedSize(KRecvBuf *krbCB)
27 {
28 UINT32 size;
29 UINT32 intSave;
30
31 LOS_SpinLockSave(&krbCB->lock, &intSave);
32 size = krbCB->size - krbCB->remain;
33 LOS_SpinUnlockRestore(&krbCB->lock, intSave);
34
35 return size;
36 }
37
KRecvBufWriteLinear(KRecvBuf * krbCB,const CHAR * buf,UINT32 size)38 STATIC UINT32 KRecvBufWriteLinear(KRecvBuf *krbCB, const CHAR *buf, UINT32 size)
39 {
40 UINT32 cpSize;
41 errno_t err;
42
43 // get copy size
44 cpSize = MIN(krbCB->remain, size);
45
46 if (cpSize == 0) {
47 return 0;
48 }
49
50 // copy to buffer
51 err = memcpy_s(krbCB->fifo + krbCB->wIdx, MIN((krbCB->size - krbCB->wIdx), krbCB->remain), buf, cpSize);
52 if (err != EOK) {
53 HDF_LOGE("%s: something is wrong in memcpy_s.\r\n", __func__);
54 return 0;
55 }
56
57 krbCB->remain -= cpSize;
58 krbCB->wIdx += cpSize;
59
60 // write point roll to start
61 if (krbCB->wIdx >= krbCB->size) {
62 krbCB->wIdx = 0;
63 }
64
65 return cpSize;
66 }
67
KRecvBufWriteLoop(KRecvBuf * krbCB,const CHAR * buf,UINT32 size)68 STATIC UINT32 KRecvBufWriteLoop(KRecvBuf *krbCB, const CHAR *buf, UINT32 size)
69 {
70 UINT32 right, cpSize;
71
72 // get upper part space
73 right = krbCB->size - krbCB->wIdx;
74
75 // get upper part copy size
76 cpSize = MIN(right, size);
77
78 // copy upper part
79 cpSize = KRecvBufWriteLinear(krbCB, buf, cpSize);
80 if (cpSize == 0) {
81 HDF_LOGE("%s: something is wrong in KRecvBufWriteLinear.\r\n", __func__);
82 return 0;
83 }
84
85 // copy lower part (if needed)
86 if (cpSize != size) {
87 cpSize += KRecvBufWriteLinear(krbCB, buf + cpSize, size - cpSize);
88 }
89
90 return cpSize;
91 }
92
KRecvBufWrite(KRecvBuf * krbCB,const CHAR * buf,UINT32 size)93 UINT32 KRecvBufWrite(KRecvBuf *krbCB, const CHAR *buf, UINT32 size)
94 {
95 UINT32 cpSize;
96
97 if ((krbCB == NULL) || (buf == NULL) || (size == 0)) {
98 return 0;
99 }
100
101 if ((krbCB->fifo == NULL) || (krbCB->remain == 0)) {
102 return 0;
103 }
104
105 if (krbCB->rIdx <= krbCB->wIdx) {
106 cpSize = KRecvBufWriteLoop(krbCB, buf, size);
107 } else {
108 cpSize = KRecvBufWriteLinear(krbCB, buf, size);
109 }
110
111 return cpSize;
112 }
113
KRecvBufReadLinear(KRecvBuf * krbCB,const CHAR * buf,UINT32 size)114 STATIC UINT32 KRecvBufReadLinear(KRecvBuf *krbCB, const CHAR *buf, UINT32 size)
115 {
116 UINT32 cpSize;
117 errno_t err;
118
119 // this time max size
120 cpSize = MIN((krbCB->size - krbCB->remain), (krbCB->size - krbCB->rIdx));
121
122 // copy size
123 cpSize = MIN(cpSize, size);
124
125 if (cpSize == 0) {
126 return 0;
127 }
128
129 // copy data to user space
130 err = LOS_CopyFromKernel((void *)buf, size, (void *)(krbCB->fifo + krbCB->rIdx), cpSize);
131 if (err != EOK) {
132 return 0;
133 }
134
135 krbCB->remain += cpSize;
136 krbCB->rIdx += cpSize;
137
138 if (krbCB->rIdx >= krbCB->size) {
139 krbCB->rIdx = 0;
140 }
141
142 return cpSize;
143 }
144
KRecvBufReadLoop(KRecvBuf * krbCB,const CHAR * buf,UINT32 size)145 STATIC UINT32 KRecvBufReadLoop(KRecvBuf *krbCB, const CHAR *buf, UINT32 size)
146 {
147 UINT32 right, cpSize;
148
149 // get upper part size
150 right = krbCB->size - krbCB->rIdx;
151
152 // get upper part copy size
153 cpSize = MIN(right, size);
154
155 // copy upper part
156 cpSize = KRecvBufReadLinear(krbCB, buf, cpSize);
157 if (cpSize == 0) {
158 HDF_LOGE("%s: something is wrong in KRecvBufReadLinear.\r\n", __func__);
159 return 0;
160 }
161
162 // copy lower part (if needed)
163 if (cpSize < size) {
164 cpSize += KRecvBufReadLinear(krbCB, buf + cpSize, size - cpSize);
165 }
166
167 return cpSize;
168 }
169
KRecvBufRead(KRecvBuf * krbCB,CHAR * buf,UINT32 size)170 UINT32 KRecvBufRead(KRecvBuf *krbCB, CHAR *buf, UINT32 size)
171 {
172 UINT32 cpSize;
173
174 if ((krbCB == NULL) || (buf == NULL) || (size == 0)) {
175 return 0;
176 }
177
178 if ((krbCB->fifo == NULL) || (krbCB->remain == krbCB->size)) {
179 return 0;
180 }
181
182 if (krbCB->rIdx >= krbCB->wIdx) {
183 cpSize = KRecvBufReadLoop(krbCB, buf, size);
184 } else {
185 cpSize = KRecvBufReadLinear(krbCB, buf, size);
186 }
187
188 return cpSize;
189 }
190
KRecvBufInit(KRecvBuf * krbCB,CHAR * fifo,UINT32 size)191 UINT32 KRecvBufInit(KRecvBuf *krbCB, CHAR *fifo, UINT32 size)
192 {
193 if ((krbCB == NULL) || (fifo == NULL)) {
194 return LOS_NOK;
195 }
196
197 (VOID)memset_s(krbCB, sizeof(KRecvBuf), 0, sizeof(KRecvBuf));
198 LOS_SpinInit(&krbCB->lock);
199 krbCB->size = size;
200 krbCB->remain = size;
201 krbCB->status = BUF_USED;
202 krbCB->fifo = fifo;
203
204 return LOS_OK;
205 }
206
KRecvBufDeinit(KRecvBuf * krbCB)207 VOID KRecvBufDeinit(KRecvBuf *krbCB)
208 {
209 (VOID)memset_s(krbCB, sizeof(KRecvBuf), 0, sizeof(KRecvBuf));
210 }
211
KRecvBufDump(KRecvBuf * krbCB)212 VOID KRecvBufDump(KRecvBuf *krbCB)
213 {
214 dprintf("\r\nKRecvBufDump : \r\n");
215 dprintf("\r\n rIdx : %d\r\n", krbCB->rIdx);
216 dprintf("\r\n wIdx : %d\r\n", krbCB->wIdx);
217 dprintf("\r\n size : %d\r\n", krbCB->size);
218 dprintf("\r\n status : %d\r\n", krbCB->status);
219 dprintf("\r\n remain : %d\r\n", krbCB->remain);
220 dprintf("\r\n status : %d\r\n", krbCB->status);
221 }
222