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 37static 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*******************************************************************************/ 52void 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*******************************************************************************/ 66void 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*******************************************************************************/ 79void 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*******************************************************************************/ 94void 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*******************************************************************************/ 128void *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*******************************************************************************/ 145void *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*******************************************************************************/ 182void *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*******************************************************************************/ 203void *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*******************************************************************************/ 219void *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*******************************************************************************/ 265void 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*******************************************************************************/ 289void 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*******************************************************************************/ 304void utils_unlock (void) 305{ 306 pthread_mutex_unlock(&utils_mutex); 307} 308 309