• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 2009-2012 Broadcom 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  *
21  *  Filename:      utils.c
22  *
23  *  Description:   Contains helper functions
24  *
25  ******************************************************************************/
26 
27 #include <errno.h>
28 #include <pthread.h>
29 #include <time.h>
30 #include "bt_hci_bdroid.h"
31 #include "utils.h"
32 
33 /******************************************************************************
34 **  Static variables
35 ******************************************************************************/
36 
37 static pthread_mutex_t utils_mutex;
38 
39 /*****************************************************************************
40 **   UTILS INTERFACE FUNCTIONS
41 *****************************************************************************/
42 
43 /*******************************************************************************
44 **
45 ** Function        utils_init
46 **
47 ** Description     Utils initialization
48 **
49 ** Returns         None
50 **
51 *******************************************************************************/
utils_init(void)52 void utils_init (void)
53 {
54     pthread_mutex_init(&utils_mutex, NULL);
55 }
56 
57 /*******************************************************************************
58 **
59 ** Function        utils_cleanup
60 **
61 ** Description     Utils cleanup
62 **
63 ** Returns         None
64 **
65 *******************************************************************************/
utils_cleanup(void)66 void utils_cleanup (void)
67 {
68     pthread_mutex_destroy(&utils_mutex);
69 }
70 
71 /*******************************************************************************
72 **
73 ** Function        utils_queue_init
74 **
75 ** Description     Initialize the given buffer queue
76 **
77 ** Returns         None
78 **
79 *******************************************************************************/
utils_queue_init(BUFFER_Q * p_q)80 void utils_queue_init (BUFFER_Q *p_q)
81 {
82     p_q->p_first = p_q->p_last = NULL;
83     p_q->count = 0;
84 }
85 
86 /*******************************************************************************
87 **
88 ** Function        utils_enqueue
89 **
90 ** Description     Enqueue a buffer at the tail of the given queue
91 **
92 ** Returns         None
93 **
94 *******************************************************************************/
utils_enqueue(BUFFER_Q * p_q,void * p_buf)95 void utils_enqueue (BUFFER_Q *p_q, void *p_buf)
96 {
97     HC_BUFFER_HDR_T    *p_hdr;
98 
99     p_hdr = (HC_BUFFER_HDR_T *) ((uint8_t *) p_buf - BT_HC_BUFFER_HDR_SIZE);
100 
101     pthread_mutex_lock(&utils_mutex);
102 
103     if (p_q->p_last)
104     {
105         HC_BUFFER_HDR_T *p_last_hdr = \
106           (HC_BUFFER_HDR_T *)((uint8_t *)p_q->p_last - BT_HC_BUFFER_HDR_SIZE);
107 
108         p_last_hdr->p_next = p_hdr;
109     }
110     else
111         p_q->p_first = p_buf;
112 
113     p_q->p_last = p_buf;
114     p_q->count++;
115 
116     p_hdr->p_next = NULL;
117 
118     pthread_mutex_unlock(&utils_mutex);
119 }
120 /*******************************************************************************
121 **
122 ** Function        utils_dequeue
123 **
124 ** Description     Dequeues a buffer from the head of the given queue
125 **
126 ** Returns         NULL if queue is empty, else buffer
127 **
128 *******************************************************************************/
utils_dequeue(BUFFER_Q * p_q)129 void *utils_dequeue (BUFFER_Q *p_q)
130 {
131     pthread_mutex_lock(&utils_mutex);
132     void* p_buf =  utils_dequeue_unlocked(p_q);
133     pthread_mutex_unlock(&utils_mutex);
134     return p_buf;
135 }
136 
137 /*******************************************************************************
138 **
139 ** Function        utils_dequeue_unlocked
140 **
141 ** Description     Dequeues a buffer from the head of the given queue without lock
142 **
143 ** Returns         NULL if queue is empty, else buffer
144 **
145 *******************************************************************************/
utils_dequeue_unlocked(BUFFER_Q * p_q)146 void *utils_dequeue_unlocked (BUFFER_Q *p_q)
147 {
148     HC_BUFFER_HDR_T    *p_hdr;
149 
150 
151     if (!p_q || !p_q->count)
152     {
153         return (NULL);
154     }
155 
156     p_hdr=(HC_BUFFER_HDR_T *)((uint8_t *)p_q->p_first-BT_HC_BUFFER_HDR_SIZE);
157 
158     if (p_hdr->p_next)
159         p_q->p_first = ((uint8_t *)p_hdr->p_next + BT_HC_BUFFER_HDR_SIZE);
160     else
161     {
162         p_q->p_first = NULL;
163         p_q->p_last  = NULL;
164     }
165 
166     p_q->count--;
167 
168     p_hdr->p_next = NULL;
169     return ((uint8_t *)p_hdr + BT_HC_BUFFER_HDR_SIZE);
170 }
171 
172 /*******************************************************************************
173 **
174 ** Function        utils_getnext
175 **
176 ** Description     Return a pointer to the next buffer linked to the given
177 **                 buffer
178 **
179 ** Returns         NULL if the given buffer does not point to any next buffer,
180 **                 else next buffer address
181 **
182 *******************************************************************************/
utils_getnext(void * p_buf)183 void *utils_getnext (void *p_buf)
184 {
185     HC_BUFFER_HDR_T    *p_hdr;
186 
187     p_hdr = (HC_BUFFER_HDR_T *) ((uint8_t *) p_buf - BT_HC_BUFFER_HDR_SIZE);
188 
189     if (p_hdr->p_next)
190         return ((uint8_t *)p_hdr->p_next + BT_HC_BUFFER_HDR_SIZE);
191     else
192         return (NULL);
193 }
194 
195 /*******************************************************************************
196 **
197 ** Function        utils_remove_from_queue
198 **
199 ** Description     Dequeue the given buffer from the middle of the given queue
200 **
201 ** Returns         NULL if the given queue is empty, else the given buffer
202 **
203 *******************************************************************************/
utils_remove_from_queue(BUFFER_Q * p_q,void * p_buf)204 void *utils_remove_from_queue (BUFFER_Q *p_q, void *p_buf)
205 {
206     pthread_mutex_lock(&utils_mutex);
207     p_buf = utils_remove_from_queue_unlocked(p_q, p_buf);
208     pthread_mutex_unlock(&utils_mutex);
209     return p_buf;
210 }
211 /*******************************************************************************
212 **
213 ** Function        utils_remove_from_queue_unlocked
214 **
215 ** Description     Dequeue the given buffer from the middle of the given queue
216 **
217 ** Returns         NULL if the given queue is empty, else the given buffer
218 **
219 *******************************************************************************/
utils_remove_from_queue_unlocked(BUFFER_Q * p_q,void * p_buf)220 void *utils_remove_from_queue_unlocked (BUFFER_Q *p_q, void *p_buf)
221 {
222     HC_BUFFER_HDR_T    *p_prev;
223     HC_BUFFER_HDR_T    *p_buf_hdr;
224 
225 
226     if (p_buf == p_q->p_first)
227     {
228         return (utils_dequeue_unlocked (p_q));
229     }
230 
231     p_buf_hdr = (HC_BUFFER_HDR_T *)((uint8_t *)p_buf - BT_HC_BUFFER_HDR_SIZE);
232     p_prev=(HC_BUFFER_HDR_T *)((uint8_t *)p_q->p_first-BT_HC_BUFFER_HDR_SIZE);
233 
234     for ( ; p_prev; p_prev = p_prev->p_next)
235     {
236         /* If the previous points to this one, move the pointers around */
237         if (p_prev->p_next == p_buf_hdr)
238         {
239             p_prev->p_next = p_buf_hdr->p_next;
240 
241             /* If we are removing the last guy in the queue, update p_last */
242             if (p_buf == p_q->p_last)
243                 p_q->p_last = p_prev + 1;
244 
245             /* One less in the queue */
246             p_q->count--;
247 
248             /* The buffer is now unlinked */
249             p_buf_hdr->p_next = NULL;
250 
251             return (p_buf);
252         }
253     }
254     return (NULL);
255 }
256 
257 /*******************************************************************************
258 **
259 ** Function        utils_delay
260 **
261 ** Description     sleep unconditionally for timeout milliseconds
262 **
263 ** Returns         None
264 **
265 *******************************************************************************/
utils_delay(uint32_t timeout)266 void utils_delay (uint32_t timeout)
267 {
268     struct timespec delay;
269     int err;
270 
271     delay.tv_sec = timeout / 1000;
272     delay.tv_nsec = 1000 * 1000 * (timeout%1000);
273 
274     /* [u]sleep can't be used because it uses SIGALRM */
275     do {
276         err = nanosleep(&delay, &delay);
277     } while (err < 0 && errno ==EINTR);
278 }
279 
280 /*******************************************************************************
281 **
282 ** Function        utils_lock
283 **
284 ** Description     application calls this function before entering critical
285 **                 section
286 **
287 ** Returns         None
288 **
289 *******************************************************************************/
utils_lock(void)290 void utils_lock (void)
291 {
292     pthread_mutex_lock(&utils_mutex);
293 }
294 
295 /*******************************************************************************
296 **
297 ** Function        utils_unlock
298 **
299 ** Description     application calls this function when leaving critical
300 **                 section
301 **
302 ** Returns         None
303 **
304 *******************************************************************************/
utils_unlock(void)305 void utils_unlock (void)
306 {
307     pthread_mutex_unlock(&utils_mutex);
308 }
309 
310