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