• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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