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 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*******************************************************************************/ 80void 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*******************************************************************************/ 95void 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*******************************************************************************/ 129void *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*******************************************************************************/ 146void *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*******************************************************************************/ 183void *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*******************************************************************************/ 204void *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*******************************************************************************/ 220void *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*******************************************************************************/ 266void 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*******************************************************************************/ 290void 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*******************************************************************************/ 305void utils_unlock (void) 306{ 307 pthread_mutex_unlock(&utils_mutex); 308} 309 310