1 /******************************************************************************
2 *
3 * Copyright (C) 2009-2018 Realtek Corporation.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18 /******************************************************************************
19 *
20 * Module Name:
21 * bt_skbuff.c
22 *
23 * Abstract:
24 * Data buffer managerment through whole bluetooth stack.
25 *
26 * Major Change History:
27 * When Who What
28 * --------------------------------------------------------------
29 * 2010-06-11 W.Bi Created.
30 *
31 * Notes:
32 * To reduce memory copy when pass data buffer to other layers,
33 * RTK_BUFFER is designed referring to linux socket buffer.
34 * But I still wonder its effect, since RTK_BUFFER is much bigger
35 * than original data buffer.RTK_BUFFER will reduce its member if
36 * it would not reach what i had expected.
37 *
38 ******************************************************************************/
39
40 #define LOG_TAG "bt_h5"
41 #undef NDEBUG
42 #include <utils/Log.h>
43 #include <stdlib.h>
44 #include <fcntl.h>
45
46 #include <termios.h>
47 #include <errno.h>
48 #include <pthread.h>
49
50 #include "string.h"
51 #include "hci_h5_int.h"
52 #include "bt_list.h"
53 #include "bt_skbuff.h"
54 #define IN
55 #define OUT
56
57 // ****************************************************************************
58 // CONSTANT DEFINITION
59 // ****************************************************************************
60 /// default header size
61 /// l2cap header(8)+hci acl(4)
62 #define DEFAULT_HEADER_SIZE (8 + 4)
63
64 // RTK_BUFFER data buffer alignment
65 #define RTB_ALIGN 4
66
67 // do alignment with RTB_ALIGN
68 #define RTB_DATA_ALIGN(_Length) (((_Length) + (RTB_ALIGN - 1)) & (~(RTB_ALIGN - 1)))
69
70 // ****************************************************************************
71 // STRUCTURE DEFINITION
72 // ****************************************************************************
73 typedef struct _RTB_QUEUE_HEAD {
74 RT_LIST_HEAD List;
75 uint32_t QueueLen;
76 pthread_mutex_t Lock;
77 uint8_t Id[RTB_QUEUE_ID_LENGTH];
78 } *PRTB_QUEUE_HEAD;
79
80 // ****************************************************************************
81 // FUNCTION
82 // ****************************************************************************
83 /**
84 check whether queue is empty
85 \return : FALSE Queue is not empty
86 TRU Queue is empty
87 */
RtbQueueIsEmpty(IN RTB_QUEUE_HEAD * RtkQueueHead)88 bool RtbQueueIsEmpty(IN RTB_QUEUE_HEAD *RtkQueueHead)
89 {
90 return RtkQueueHead->QueueLen > 0 ? false : true;
91 }
92
93 /**
94 Allocate a RTK_BUFFER with specified data length and reserved headroom.
95 If caller does not know actual headroom to reserve for further usage, specify it to zero to use default value.
96 \param [IN] Length <uint32_t> : current data buffer length to allcated
97 \param [IN] HeadRoom <uint32_t> : if caller knows reserved head space, set it; otherwise set 0 to
98 use default value \return pointer to RTK_BUFFER if succeed, null otherwise
99 */
RtbAllocate(uint32_t Length,uint32_t HeadRoom)100 RTK_BUFFER *RtbAllocate(uint32_t Length, uint32_t HeadRoom)
101 {
102 RTK_BUFFER *Rtb = NULL;
103 /// Rtb buffer length:
104 /// RTK_BUFFER 48
105 /// HeadRoom HeadRomm or 12
106 /// Length
107 /// memory size: 48 + Length + 12(default) + 8*2(header for each memory) ---> a multiple of 8
108 /// example: (48 + 8)+ (300 + 12 + 8) = 372
109 Rtb = malloc(sizeof(RTK_BUFFER));
110 if (Rtb) {
111 uint32_t BufferLen = HeadRoom ? (Length + HeadRoom) : (Length + DEFAULT_HEADER_SIZE);
112 BufferLen = RTB_DATA_ALIGN(BufferLen);
113 Rtb->Head = malloc(BufferLen);
114 if (Rtb->Head) {
115 Rtb->HeadRoom = HeadRoom ? HeadRoom : DEFAULT_HEADER_SIZE;
116 Rtb->Data = Rtb->Head + Rtb->HeadRoom;
117 Rtb->End = Rtb->Data;
118 Rtb->Tail = Rtb->End + Length;
119 Rtb->Length = 0;
120 ListInitializeHeader(&Rtb->List);
121 Rtb->RefCount = 1;
122 return Rtb;
123 }
124 }
125
126 if (Rtb) {
127 if (Rtb->Head) {
128 free(Rtb->Head);
129 }
130 free(Rtb);
131 }
132 return NULL;
133 }
134
135 /**
136 Free specified Rtk_buffer
137 \param [IN] RtkBuffer <RTK_BUFFER*> : buffer to free
138 */
RtbFree(RTK_BUFFER * RtkBuffer)139 void RtbFree(RTK_BUFFER *RtkBuffer)
140 {
141 if (RtkBuffer) {
142 free(RtkBuffer->Head);
143 free(RtkBuffer);
144 }
145 return;
146 }
147
148 /**
149 Add a specified length protocol header to the start of data buffer hold by specified rtk_buffer.
150 This function extends used data area of the buffer at the buffer start.
151 \param [IN OUT] RtkBuffer <RTK_BUFFER*> : data buffer to add
152 \param [IN] Length <uint32_t> : header length
153 \return Pointer to the first byte of the extra data is returned
154 */
RtbAddHead(RTK_BUFFER * RtkBuffer,uint32_t Length)155 uint8_t *RtbAddHead(RTK_BUFFER *RtkBuffer, uint32_t Length)
156 {
157 if ((uint32_t)(RtkBuffer->Data - RtkBuffer->Head) >= Length) {
158 RtkBuffer->Data -= Length;
159 RtkBuffer->Length += Length;
160 RtkBuffer->HeadRoom -= Length;
161 return RtkBuffer->Data;
162 }
163 return NULL;
164 }
165 /**
166 Remove a specified length data from the start of data buffer hold by specified rtk_buffer.
167 This function returns the memory to the headroom.
168 \param [IN OUT] RtkBuffer <RTK_BUFFER*> : data buffer to remove
169 \param [IN] Length <uint32_t> : header length
170 \return Pointer to the next data in the buffer is returned, usually useless
171 */
RtbRemoveHead(RTK_BUFFER * RtkBuffer,uint32_t Length)172 unsigned char RtbRemoveHead(RTK_BUFFER *RtkBuffer, uint32_t Length)
173 {
174 if (RtkBuffer->Length >= Length) {
175 RtkBuffer->Data += Length;
176 RtkBuffer->Length -= Length;
177 RtkBuffer->HeadRoom += Length;
178 return true;
179 }
180 return false;
181 }
182
183 /**
184 Add a specified length protocol header to the end of data buffer hold by specified rtk_buffer.
185 This function extends used data area of the buffer at the buffer end.
186 \param [IN OUT] RtkBuffer <RTK_BUFFER*> : data buffer to add
187 \param [IN] Length <uint32_t> : header length
188 \return Pointer to the first byte of the extra data is returned
189 */
RtbAddTail(RTK_BUFFER * RtkBuffer,uint32_t Length)190 uint8_t *RtbAddTail(RTK_BUFFER *RtkBuffer, uint32_t Length)
191 {
192 if ((uint32_t)(RtkBuffer->Tail - RtkBuffer->End) >= Length) {
193 uint8_t *Tmp = RtkBuffer->End;
194 RtkBuffer->End += Length;
195 RtkBuffer->Length += Length;
196 return Tmp;
197 }
198 return NULL;
199 }
200
RtbRemoveTail(IN OUT RTK_BUFFER * RtkBuffer,IN uint32_t Length)201 unsigned char RtbRemoveTail(IN OUT RTK_BUFFER *RtkBuffer, IN uint32_t Length)
202 {
203 if ((uint32_t)(RtkBuffer->End - RtkBuffer->Data) >= Length) {
204 RtkBuffer->End -= Length;
205 RtkBuffer->Length -= Length;
206 return true;
207 }
208 return false;
209 }
210 // ****************************************************************************
211 // RTB list manipulation
212 // ****************************************************************************
213 /**
214 Initialize a rtb queue.
215 \return Initialized rtb queue if succeed, otherwise NULL
216 */
RtbQueueInit()217 RTB_QUEUE_HEAD *RtbQueueInit()
218 {
219 RTB_QUEUE_HEAD *RtbQueue = NULL;
220 int ret = 0;
221 RtbQueue = malloc(sizeof(RTB_QUEUE_HEAD));
222 if (RtbQueue) {
223 ret = pthread_mutex_init(&RtbQueue->Lock, NULL);
224 if (!ret) {
225 ListInitializeHeader(&RtbQueue->List);
226 RtbQueue->QueueLen = 0;
227 return RtbQueue;
228 }
229 }
230
231 // error code comes here
232 if (RtbQueue) {
233 free(RtbQueue);
234 }
235 return NULL;
236 }
237
238 /**
239 Free a rtb queue.
240 \param [IN] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
241 */
RtbQueueFree(RTB_QUEUE_HEAD * RtkQueueHead)242 void RtbQueueFree(RTB_QUEUE_HEAD *RtkQueueHead)
243 {
244 if (RtkQueueHead) {
245 RtbEmptyQueue(RtkQueueHead);
246 pthread_mutex_destroy(&RtkQueueHead->Lock);
247 free(RtkQueueHead);
248 }
249 }
250
251 /**
252 Queue specified RtkBuffer into a RtkQueue at list tail.
253 \param [IN OUT] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
254 \param [IN] RtkBuffer <RTK_BUFFER*> : Rtk buffer to add
255 */
RtbQueueTail(IN OUT RTB_QUEUE_HEAD * RtkQueueHead,IN RTK_BUFFER * RtkBuffer)256 void RtbQueueTail(IN OUT RTB_QUEUE_HEAD *RtkQueueHead, IN RTK_BUFFER *RtkBuffer)
257 {
258 pthread_mutex_lock(&RtkQueueHead->Lock);
259 ListAddToTail(&RtkBuffer->List, &RtkQueueHead->List);
260 RtkQueueHead->QueueLen++;
261 pthread_mutex_unlock(&RtkQueueHead->Lock);
262 }
263
264 /**
265 Queue specified RtkBuffer into a RtkQueue at list Head.
266 \param [IN OUT] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
267 \param [IN] RtkBuffer <RTK_BUFFER*> : Rtk buffer to add
268 */
RtbQueueHead(IN OUT RTB_QUEUE_HEAD * RtkQueueHead,IN RTK_BUFFER * RtkBuffer)269 void RtbQueueHead(IN OUT RTB_QUEUE_HEAD *RtkQueueHead, IN RTK_BUFFER *RtkBuffer)
270 {
271 pthread_mutex_lock(&RtkQueueHead->Lock);
272 ListAddToHead(&RtkBuffer->List, &RtkQueueHead->List);
273 RtkQueueHead->QueueLen++;
274 pthread_mutex_unlock(&RtkQueueHead->Lock);
275 }
276
277 /**
278 Insert new Rtkbuffer in the old buffer
279 \param [IN OUT] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
280 \param [IN] OldRtkBuffer <RTK_BUFFER*> : old rtk buffer
281 \param [IN] NewRtkBuffer <RTK_BUFFER*> : Rtk buffer to add
282 */
RtbInsertBefore(IN OUT RTB_QUEUE_HEAD * RtkQueueHead,IN RTK_BUFFER * pOldRtkBuffer,IN RTK_BUFFER * pNewRtkBuffer)283 void RtbInsertBefore(IN OUT RTB_QUEUE_HEAD *RtkQueueHead, IN RTK_BUFFER *pOldRtkBuffer, IN RTK_BUFFER *pNewRtkBuffer)
284 {
285 pthread_mutex_lock(&RtkQueueHead->Lock);
286 ListAdd(&pNewRtkBuffer->List, pOldRtkBuffer->List.Prev, &pOldRtkBuffer->List);
287 RtkQueueHead->QueueLen++;
288 pthread_mutex_unlock(&RtkQueueHead->Lock);
289 }
290
291 /**
292 check whether the buffer is the last node in the queue
293 */
RtbNodeIsLast(IN RTB_QUEUE_HEAD * RtkQueueHead,IN RTK_BUFFER * pRtkBuffer)294 unsigned char RtbNodeIsLast(IN RTB_QUEUE_HEAD *RtkQueueHead, IN RTK_BUFFER *pRtkBuffer)
295 {
296 RTK_BUFFER *pBuf;
297 pthread_mutex_lock(&RtkQueueHead->Lock);
298
299 pBuf = (RTK_BUFFER *)RtkQueueHead->List.Prev;
300 if (pBuf == pRtkBuffer) {
301 pthread_mutex_unlock(&RtkQueueHead->Lock);
302 return true;
303 }
304 pthread_mutex_unlock(&RtkQueueHead->Lock);
305 return false;
306 }
307
308 /**
309 get the next buffer node after the specified buffer in the queue
310 if the specified buffer is the last node in the queue , return NULL
311 \param [IN] RtkBuffer <RTK_BUFFER*> : Rtk Queue
312 \param [IN] RtkBuffer <RTK_BUFFER*> : Rtk buffer
313 \return node after the specified buffer
314 */
RtbQueueNextNode(IN RTB_QUEUE_HEAD * RtkQueueHead,IN RTK_BUFFER * pRtkBuffer)315 RTK_BUFFER *RtbQueueNextNode(IN RTB_QUEUE_HEAD *RtkQueueHead, IN RTK_BUFFER *pRtkBuffer)
316 {
317 RTK_BUFFER *pBuf;
318 pthread_mutex_lock(&RtkQueueHead->Lock);
319 pBuf = (RTK_BUFFER *)RtkQueueHead->List.Prev;
320 if (pBuf == pRtkBuffer) {
321 pthread_mutex_unlock(&RtkQueueHead->Lock);
322 return NULL; ///< if it is already the last node in the queue , return NULL
323 }
324 pBuf = (RTK_BUFFER *)pRtkBuffer->List.Next;
325 pthread_mutex_unlock(&RtkQueueHead->Lock);
326 return pBuf; ///< return next node after this node
327 }
328
329 /**
330 Delete specified RtkBuffer from a RtkQueue.
331 It don't hold spinlock itself, so caller must hold it at someplace.
332 \param [IN OUT] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
333 \param [IN] RtkBuffer <RTK_BUFFER*> : Rtk buffer to Remove
334 */
RtbRemoveNode(IN OUT RTB_QUEUE_HEAD * RtkQueueHead,IN RTK_BUFFER * RtkBuffer)335 void RtbRemoveNode(IN OUT RTB_QUEUE_HEAD *RtkQueueHead, IN RTK_BUFFER *RtkBuffer)
336 {
337 RtkQueueHead->QueueLen--;
338 ListDeleteNode(&RtkBuffer->List);
339 }
340
341 /**
342 Get the RtkBuffer which is the head of a RtkQueue
343 \param [IN OUT] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
344 \return head of the RtkQueue , otherwise NULL
345 */
RtbTopQueue(IN RTB_QUEUE_HEAD * RtkQueueHead)346 RTK_BUFFER *RtbTopQueue(IN RTB_QUEUE_HEAD *RtkQueueHead)
347 {
348 RTK_BUFFER *Rtb = NULL;
349 pthread_mutex_lock(&RtkQueueHead->Lock);
350
351 if (RtbQueueIsEmpty(RtkQueueHead)) {
352 pthread_mutex_unlock(&RtkQueueHead->Lock);
353 return NULL;
354 }
355
356 Rtb = (RTK_BUFFER *)RtkQueueHead->List.Next;
357 pthread_mutex_unlock(&RtkQueueHead->Lock);
358
359 return Rtb;
360 }
361
362 /**
363 Remove a RtkBuffer from specified rtkqueue at list tail.
364 \param [IN OUT] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
365 \return removed rtkbuffer if succeed, otherwise NULL
366 */
RtbDequeueTail(IN OUT RTB_QUEUE_HEAD * RtkQueueHead)367 RTK_BUFFER *RtbDequeueTail(IN OUT RTB_QUEUE_HEAD *RtkQueueHead)
368 {
369 RTK_BUFFER *Rtb = NULL;
370
371 pthread_mutex_lock(&RtkQueueHead->Lock);
372 if (RtbQueueIsEmpty(RtkQueueHead)) {
373 pthread_mutex_unlock(&RtkQueueHead->Lock);
374 return NULL;
375 }
376 Rtb = (RTK_BUFFER *)RtkQueueHead->List.Prev;
377 RtbRemoveNode(RtkQueueHead, Rtb);
378 pthread_mutex_unlock(&RtkQueueHead->Lock);
379
380 return Rtb;
381 }
382
383 /**
384 Remove a RtkBuffer from specified rtkqueue at list head.
385 \param [IN OUT] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
386 \return removed rtkbuffer if succeed, otherwise NULL
387 */
RtbDequeueHead(IN OUT RTB_QUEUE_HEAD * RtkQueueHead)388 RTK_BUFFER *RtbDequeueHead(IN OUT RTB_QUEUE_HEAD *RtkQueueHead)
389 {
390 RTK_BUFFER *Rtb = NULL;
391 pthread_mutex_lock(&RtkQueueHead->Lock);
392
393 if (RtbQueueIsEmpty(RtkQueueHead)) {
394 pthread_mutex_unlock(&RtkQueueHead->Lock);
395 return NULL;
396 }
397 Rtb = (RTK_BUFFER *)RtkQueueHead->List.Next;
398 RtbRemoveNode(RtkQueueHead, Rtb);
399 pthread_mutex_unlock(&RtkQueueHead->Lock);
400 return Rtb;
401 }
402
403 /**
404 Get current rtb queue's length.
405 \param [IN] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
406 \return current queue's length
407 */
RtbGetQueueLen(IN RTB_QUEUE_HEAD * RtkQueueHead)408 signed long RtbGetQueueLen(IN RTB_QUEUE_HEAD *RtkQueueHead)
409 {
410 return RtkQueueHead->QueueLen;
411 }
412
413 /**
414 Empty the rtkqueue.
415 \param [IN OUT] RtkQueueHead <RTB_QUEUE_HEAD*> : Rtk Queue
416 */
RtbEmptyQueue(IN OUT RTB_QUEUE_HEAD * RtkQueueHead)417 void RtbEmptyQueue(IN OUT RTB_QUEUE_HEAD *RtkQueueHead)
418 {
419 RTK_BUFFER *Rtb = NULL;
420 pthread_mutex_lock(&RtkQueueHead->Lock);
421
422 while (!RtbQueueIsEmpty(RtkQueueHead)) {
423 Rtb = (RTK_BUFFER *)RtkQueueHead->List.Next;
424 RtbRemoveNode(RtkQueueHead, Rtb);
425 RtbFree(Rtb);
426 }
427
428 pthread_mutex_unlock(&RtkQueueHead->Lock);
429 return;
430 }
431
432 /// Annie_tmp
RtbCheckQueueLen(IN RTB_QUEUE_HEAD * RtkQueueHead,IN uint8_t Len)433 unsigned char RtbCheckQueueLen(IN RTB_QUEUE_HEAD *RtkQueueHead, IN uint8_t Len)
434 {
435 return RtkQueueHead->QueueLen < Len ? true : false;
436 }
437
438 /**
439 clone buffer for upper or lower layer, because original buffer should be stored in l2cap
440 \param <RTK_BUFFER* pDataBuffer: original buffer
441 \return cloned buffer
442 */
RtbCloneBuffer(IN RTK_BUFFER * pDataBuffer)443 RTK_BUFFER *RtbCloneBuffer(IN RTK_BUFFER *pDataBuffer)
444 {
445 RTK_BUFFER *pNewBuffer = NULL;
446 if (pDataBuffer) {
447 pNewBuffer = RtbAllocate(pDataBuffer->Length, 0);
448 if (!pNewBuffer) {
449 return NULL;
450 }
451 if (pDataBuffer && pDataBuffer->Data) {
452 (void)memcpy_s(pNewBuffer->Data, pNewBuffer->Length, pDataBuffer->Data, pDataBuffer->Length);
453 } else {
454 RtbFree(pNewBuffer);
455 return NULL;
456 }
457 pNewBuffer->Length = pDataBuffer->Length;
458 }
459 return pNewBuffer;
460 }
461