Home | History | Annotate | Download | only in src
      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 *******************************************************************************/
     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 *******************************************************************************/
     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 *******************************************************************************/
     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 *******************************************************************************/
     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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    305 void utils_unlock (void)
    306 {
    307     pthread_mutex_unlock(&utils_mutex);
    308 }
    309 
    310