1/******************************************************************************
2 *
3 *  Copyright (C) 1999-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#include <stdio.h>
19#include "gki_int.h"
20
21#if (GKI_NUM_TOTAL_BUF_POOLS > 16)
22#error Number of pools out of range (16 Max)!
23#endif
24
25#if (BTU_STACK_LITE_ENABLED == FALSE)
26static void gki_add_to_pool_list(uint8_t pool_id);
27static void gki_remove_from_pool_list(uint8_t pool_id);
28#endif /*  BTU_STACK_LITE_ENABLED == FALSE */
29
30/*******************************************************************************
31**
32** Function         gki_init_free_queue
33**
34** Description      Internal function called at startup to initialize a free
35**                  queue. It is called once for each free queue.
36**
37** Returns          void
38**
39*******************************************************************************/
40static void gki_init_free_queue(uint8_t id, uint16_t size, uint16_t total,
41                                void* p_mem) {
42  uint16_t i;
43  uint16_t act_size;
44  BUFFER_HDR_T* hdr;
45  BUFFER_HDR_T* hdr1 = NULL;
46  uint32_t* magic;
47  int32_t tempsize = size;
48  tGKI_COM_CB* p_cb = &gki_cb.com;
49
50  /* Ensure an even number of longwords */
51  tempsize = (int32_t)ALIGN_POOL(size);
52  act_size = (uint16_t)(tempsize + BUFFER_PADDING_SIZE);
53
54  /* Remember pool start and end addresses */
55  if (p_mem) {
56    p_cb->pool_start[id] = (uint8_t*)p_mem;
57    p_cb->pool_end[id] = (uint8_t*)p_mem + (act_size * total);
58  }
59
60  p_cb->pool_size[id] = act_size;
61
62  p_cb->freeq[id].size = (uint16_t)tempsize;
63  p_cb->freeq[id].total = total;
64  p_cb->freeq[id].cur_cnt = 0;
65  p_cb->freeq[id].max_cnt = 0;
66
67  /* Initialize  index table */
68  if (p_mem) {
69    hdr = (BUFFER_HDR_T*)p_mem;
70    p_cb->freeq[id].p_first = hdr;
71    for (i = 0; i < total; i++) {
72      hdr->task_id = GKI_INVALID_TASK;
73      hdr->q_id = id;
74      hdr->status = BUF_STATUS_FREE;
75      magic = (uint32_t*)((uint8_t*)hdr + BUFFER_HDR_SIZE + tempsize);
76      *magic = MAGIC_NO;
77      hdr1 = hdr;
78      hdr = (BUFFER_HDR_T*)((uint8_t*)hdr + act_size);
79      hdr1->p_next = hdr;
80    }
81    if (hdr1 != NULL) hdr = hdr1;
82    hdr->p_next = NULL;
83    p_cb->freeq[id].p_last = hdr;
84  }
85  return;
86}
87
88static bool gki_alloc_free_queue(uint8_t id) {
89  FREE_QUEUE_T* Q;
90  tGKI_COM_CB* p_cb = &gki_cb.com;
91
92  Q = &p_cb->freeq[p_cb->pool_list[id]];
93
94  if (Q->p_first == 0) {
95    void* p_mem = GKI_os_malloc((Q->size + BUFFER_PADDING_SIZE) * Q->total);
96    if (p_mem) {
97// re-initialize the queue with allocated memory
98      gki_init_free_queue(id, Q->size, Q->total, p_mem);
99      return true;
100    }
101    GKI_exception(GKI_ERROR_BUF_SIZE_TOOBIG,
102                  "gki_alloc_free_queue: Not enough memory");
103  }
104  return false;
105}
106
107/*******************************************************************************
108**
109** Function         gki_buffer_init
110**
111** Description      Called once internally by GKI at startup to initialize all
112**                  buffers and free buffer pools.
113**
114** Returns          void
115**
116*******************************************************************************/
117void gki_buffer_init(void) {
118  uint8_t i, tt, mb;
119  tGKI_COM_CB* p_cb = &gki_cb.com;
120
121  /* Initialize mailboxes */
122  for (tt = 0; tt < GKI_MAX_TASKS; tt++) {
123    for (mb = 0; mb < NUM_TASK_MBOX; mb++) {
124      p_cb->OSTaskQFirst[tt][mb] = NULL;
125      p_cb->OSTaskQLast[tt][mb] = NULL;
126    }
127  }
128
129  for (tt = 0; tt < GKI_NUM_TOTAL_BUF_POOLS; tt++) {
130    p_cb->pool_start[tt] = NULL;
131    p_cb->pool_end[tt] = NULL;
132    p_cb->pool_size[tt] = 0;
133
134    p_cb->freeq[tt].p_first = 0;
135    p_cb->freeq[tt].p_last = 0;
136    p_cb->freeq[tt].size = 0;
137    p_cb->freeq[tt].total = 0;
138    p_cb->freeq[tt].cur_cnt = 0;
139    p_cb->freeq[tt].max_cnt = 0;
140  }
141
142  /* Use default from target.h */
143  p_cb->pool_access_mask = GKI_DEF_BUFPOOL_PERM_MASK;
144
145#if (GKI_NUM_FIXED_BUF_POOLS > 0)
146  gki_init_free_queue(0, GKI_BUF0_SIZE, GKI_BUF0_MAX, p_cb->bufpool0);
147#endif
148
149#if (GKI_NUM_FIXED_BUF_POOLS > 1)
150  gki_init_free_queue(1, GKI_BUF1_SIZE, GKI_BUF1_MAX, p_cb->bufpool1);
151#endif
152
153#if (GKI_NUM_FIXED_BUF_POOLS > 2)
154  gki_init_free_queue(2, GKI_BUF2_SIZE, GKI_BUF2_MAX, p_cb->bufpool2);
155#endif
156
157#if (GKI_NUM_FIXED_BUF_POOLS > 3)
158  gki_init_free_queue(3, GKI_BUF3_SIZE, GKI_BUF3_MAX, p_cb->bufpool3);
159#endif
160
161#if (GKI_NUM_FIXED_BUF_POOLS > 4)
162  gki_init_free_queue(4, GKI_BUF4_SIZE, GKI_BUF4_MAX, p_cb->bufpool4);
163#endif
164
165#if (GKI_NUM_FIXED_BUF_POOLS > 5)
166  gki_init_free_queue(5, GKI_BUF5_SIZE, GKI_BUF5_MAX, p_cb->bufpool5);
167#endif
168
169#if (GKI_NUM_FIXED_BUF_POOLS > 6)
170  gki_init_free_queue(6, GKI_BUF6_SIZE, GKI_BUF6_MAX, p_cb->bufpool6);
171#endif
172
173#if (GKI_NUM_FIXED_BUF_POOLS > 7)
174  gki_init_free_queue(7, GKI_BUF7_SIZE, GKI_BUF7_MAX, p_cb->bufpool7);
175#endif
176
177#if (GKI_NUM_FIXED_BUF_POOLS > 8)
178  gki_init_free_queue(8, GKI_BUF8_SIZE, GKI_BUF8_MAX, p_cb->bufpool8);
179#endif
180
181#if (GKI_NUM_FIXED_BUF_POOLS > 9)
182  gki_init_free_queue(9, GKI_BUF9_SIZE, GKI_BUF9_MAX, p_cb->bufpool9);
183#endif
184
185#if (GKI_NUM_FIXED_BUF_POOLS > 10)
186  gki_init_free_queue(10, GKI_BUF10_SIZE, GKI_BUF10_MAX, p_cb->bufpool10);
187#endif
188
189#if (GKI_NUM_FIXED_BUF_POOLS > 11)
190  gki_init_free_queue(11, GKI_BUF11_SIZE, GKI_BUF11_MAX, p_cb->bufpool11);
191#endif
192
193#if (GKI_NUM_FIXED_BUF_POOLS > 12)
194  gki_init_free_queue(12, GKI_BUF12_SIZE, GKI_BUF12_MAX, p_cb->bufpool12);
195#endif
196
197#if (GKI_NUM_FIXED_BUF_POOLS > 13)
198  gki_init_free_queue(13, GKI_BUF13_SIZE, GKI_BUF13_MAX, p_cb->bufpool13);
199#endif
200
201#if (GKI_NUM_FIXED_BUF_POOLS > 14)
202  gki_init_free_queue(14, GKI_BUF14_SIZE, GKI_BUF14_MAX, p_cb->bufpool14);
203#endif
204
205#if (GKI_NUM_FIXED_BUF_POOLS > 15)
206  gki_init_free_queue(15, GKI_BUF15_SIZE, GKI_BUF15_MAX, p_cb->bufpool15);
207#endif
208
209  /* add pools to the pool_list which is arranged in the order of size */
210  for (i = 0; i < GKI_NUM_FIXED_BUF_POOLS; i++) {
211    p_cb->pool_list[i] = i;
212  }
213
214  p_cb->curr_total_no_of_pools = GKI_NUM_FIXED_BUF_POOLS;
215
216  return;
217}
218
219/*******************************************************************************
220**
221** Function         GKI_init_q
222**
223** Description      Called by an application to initialize a buffer queue.
224**
225** Returns          void
226**
227*******************************************************************************/
228void GKI_init_q(BUFFER_Q* p_q) {
229  p_q->p_first = p_q->p_last = NULL;
230  p_q->count = 0;
231
232  return;
233}
234
235/*******************************************************************************
236**
237** Function         GKI_getbuf
238**
239** Description      Called by an application to get a free buffer which
240**                  is of size greater or equal to the requested size.
241**
242**                  Note: This routine only takes buffers from public pools.
243**                        It will not use any buffers from pools
244**                        marked GKI_RESTRICTED_POOL.
245**
246** Parameters       size - (input) number of bytes needed.
247**
248** Returns          A pointer to the buffer, or NULL if none available
249**
250*******************************************************************************/
251void* GKI_getbuf(uint16_t size)
252{
253  uint8_t i;
254  FREE_QUEUE_T* Q;
255  BUFFER_HDR_T* p_hdr;
256  tGKI_COM_CB* p_cb = &gki_cb.com;
257
258  if (size == 0) {
259    GKI_exception(GKI_ERROR_BUF_SIZE_ZERO, "getbuf: Size is zero");
260    return (NULL);
261  }
262
263  /* Find the first buffer pool that is public that can hold the desired size */
264  for (i = 0; i < p_cb->curr_total_no_of_pools; i++) {
265    if (size <= p_cb->freeq[p_cb->pool_list[i]].size) break;
266  }
267
268  if (i == p_cb->curr_total_no_of_pools) {
269    GKI_exception(GKI_ERROR_BUF_SIZE_TOOBIG, "getbuf: Size is too big");
270    return (NULL);
271  }
272
273  /* Make sure the buffers aren't disturbed til finished with allocation */
274  GKI_disable();
275
276  /* search the public buffer pools that are big enough to hold the size
277   * until a free buffer is found */
278  for (; i < p_cb->curr_total_no_of_pools; i++) {
279    /* Only look at PUBLIC buffer pools (bypass RESTRICTED pools) */
280    if (((uint16_t)1 << p_cb->pool_list[i]) & p_cb->pool_access_mask) continue;
281
282    Q = &p_cb->freeq[p_cb->pool_list[i]];
283    if (Q->cur_cnt < Q->total) {
284      if (Q->p_first == 0 && gki_alloc_free_queue(i) != true) {
285        GKI_TRACE_ERROR_0("GKI_getbuf() out of buffer");
286        GKI_enable();
287        return NULL;
288      }
289
290      if (Q->p_first == 0) {
291        /* gki_alloc_free_queue() failed to alloc memory */
292        GKI_TRACE_ERROR_0("GKI_getbuf() fail alloc free queue");
293        GKI_enable();
294        return NULL;
295      }
296
297      p_hdr = Q->p_first;
298      Q->p_first = p_hdr->p_next;
299
300      if (!Q->p_first) Q->p_last = NULL;
301
302      if (++Q->cur_cnt > Q->max_cnt) Q->max_cnt = Q->cur_cnt;
303
304      GKI_enable();
305
306      p_hdr->task_id = GKI_get_taskid();
307
308      p_hdr->status = BUF_STATUS_UNLINKED;
309      p_hdr->p_next = NULL;
310      p_hdr->Type = 0;
311      return ((void*)((uint8_t*)p_hdr + BUFFER_HDR_SIZE));
312    }
313  }
314
315  GKI_TRACE_ERROR_0("GKI_getbuf() unable to allocate buffer!!!!!");
316
317  GKI_enable();
318
319  return (NULL);
320}
321
322/*******************************************************************************
323**
324** Function         GKI_getpoolbuf
325**
326** Description      Called by an application to get a free buffer from
327**                  a specific buffer pool.
328**
329**                  Note: If there are no more buffers available from the pool,
330**                        the public buffers are searched for an available
331**                        buffer.
332**
333** Parameters       pool_id - (input) pool ID to get a buffer out of.
334**
335** Returns          A pointer to the buffer, or NULL if none available
336**
337*******************************************************************************/
338void* GKI_getpoolbuf(uint8_t pool_id)
339{
340  FREE_QUEUE_T* Q;
341  BUFFER_HDR_T* p_hdr;
342  tGKI_COM_CB* p_cb = &gki_cb.com;
343
344  if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) return (NULL);
345
346  /* Make sure the buffers aren't disturbed til finished with allocation */
347  GKI_disable();
348
349  Q = &p_cb->freeq[pool_id];
350  if (Q->cur_cnt < Q->total) {
351    if (Q->p_first == 0 && gki_alloc_free_queue(pool_id) != true) return NULL;
352
353    if (Q->p_first == 0) {
354      /* gki_alloc_free_queue() failed to alloc memory */
355      GKI_TRACE_ERROR_0("GKI_getpoolbuf() fail alloc free queue");
356      return NULL;
357    }
358
359    p_hdr = Q->p_first;
360    Q->p_first = p_hdr->p_next;
361
362    if (!Q->p_first) Q->p_last = NULL;
363
364    if (++Q->cur_cnt > Q->max_cnt) Q->max_cnt = Q->cur_cnt;
365
366    GKI_enable();
367
368    p_hdr->task_id = GKI_get_taskid();
369
370    p_hdr->status = BUF_STATUS_UNLINKED;
371    p_hdr->p_next = NULL;
372    p_hdr->Type = 0;
373
374    return ((void*)((uint8_t*)p_hdr + BUFFER_HDR_SIZE));
375  }
376
377  /* If here, no buffers in the specified pool */
378  GKI_enable();
379
380  /* try for free buffers in public pools */
381  return (GKI_getbuf(p_cb->freeq[pool_id].size));
382}
383
384/*******************************************************************************
385**
386** Function         GKI_freebuf
387**
388** Description      Called by an application to return a buffer to the free
389**                  pool.
390**
391** Parameters       p_buf - (input) address of the beginning of a buffer.
392**
393** Returns          void
394**
395*******************************************************************************/
396void GKI_freebuf(void* p_buf) {
397  FREE_QUEUE_T* Q;
398  BUFFER_HDR_T* p_hdr;
399
400#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
401  if (!p_buf || gki_chk_buf_damage(p_buf)) {
402    GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Free - Buf Corrupted");
403    return;
404  }
405#endif
406
407  p_hdr = (BUFFER_HDR_T*)((uint8_t*)p_buf - BUFFER_HDR_SIZE);
408
409  if (p_hdr->status != BUF_STATUS_UNLINKED) {
410    GKI_exception(GKI_ERROR_FREEBUF_BUF_LINKED, "Freeing Linked Buf");
411    return;
412  }
413
414  if (p_hdr->q_id >= GKI_NUM_TOTAL_BUF_POOLS) {
415    GKI_exception(GKI_ERROR_FREEBUF_BAD_QID, "Bad Buf QId");
416    return;
417  }
418
419  GKI_disable();
420
421  /*
422  ** Release the buffer
423  */
424  Q = &gki_cb.com.freeq[p_hdr->q_id];
425  if (Q->p_last)
426    Q->p_last->p_next = p_hdr;
427  else
428    Q->p_first = p_hdr;
429
430  Q->p_last = p_hdr;
431  p_hdr->p_next = NULL;
432  p_hdr->status = BUF_STATUS_FREE;
433  p_hdr->task_id = GKI_INVALID_TASK;
434  if (Q->cur_cnt > 0) Q->cur_cnt--;
435
436  GKI_enable();
437
438  return;
439}
440
441/*******************************************************************************
442**
443** Function         GKI_get_buf_size
444**
445** Description      Called by an application to get the size of a buffer.
446**
447** Parameters       p_buf - (input) address of the beginning of a buffer.
448**
449** Returns          the size of the buffer
450**
451*******************************************************************************/
452uint16_t GKI_get_buf_size(void* p_buf) {
453  BUFFER_HDR_T* p_hdr;
454
455  p_hdr = (BUFFER_HDR_T*)((uint8_t*)p_buf - BUFFER_HDR_SIZE);
456
457  if ((uint32_t)p_hdr & 1) return (0);
458
459  if (p_hdr->q_id < GKI_NUM_TOTAL_BUF_POOLS) {
460    return (gki_cb.com.freeq[p_hdr->q_id].size);
461  }
462
463  return (0);
464}
465
466/*******************************************************************************
467**
468** Function         gki_chk_buf_damage
469**
470** Description      Called internally by OSS to check for buffer corruption.
471**
472** Returns          TRUE if there is a problem, else FALSE
473**
474*******************************************************************************/
475bool gki_chk_buf_damage(void* p_buf) {
476#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
477
478  uint32_t* magic;
479  magic = (uint32_t*)((uint8_t*)p_buf + GKI_get_buf_size(p_buf));
480
481  if ((uint32_t)magic & 1) return true;
482
483  if (*magic == MAGIC_NO) return false;
484
485  return true;
486
487#else
488
489  return false;
490
491#endif
492}
493
494/*******************************************************************************
495**
496** Function         GKI_send_msg
497**
498** Description      Called by applications to send a buffer to a task
499**
500** Returns          Nothing
501**
502*******************************************************************************/
503void GKI_send_msg(uint8_t task_id, uint8_t mbox, void* msg) {
504  BUFFER_HDR_T* p_hdr;
505  tGKI_COM_CB* p_cb = &gki_cb.com;
506
507  /* If task non-existant or not started, drop buffer */
508  if ((task_id >= GKI_MAX_TASKS) || (mbox >= NUM_TASK_MBOX) ||
509      (p_cb->OSRdyTbl[task_id] == TASK_DEAD)) {
510    GKI_exception(GKI_ERROR_SEND_MSG_BAD_DEST, "Sending to unknown dest");
511    GKI_freebuf(msg);
512    return;
513  }
514
515#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
516  if (gki_chk_buf_damage(msg)) {
517    GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Send - Buffer corrupted");
518    return;
519  }
520#endif
521
522  p_hdr = (BUFFER_HDR_T*)((uint8_t*)msg - BUFFER_HDR_SIZE);
523
524  if (p_hdr->status != BUF_STATUS_UNLINKED) {
525    GKI_exception(GKI_ERROR_SEND_MSG_BUF_LINKED, "Send - buffer linked");
526    return;
527  }
528
529  GKI_disable();
530
531  if (p_cb->OSTaskQFirst[task_id][mbox])
532    p_cb->OSTaskQLast[task_id][mbox]->p_next = p_hdr;
533  else
534    p_cb->OSTaskQFirst[task_id][mbox] = p_hdr;
535
536  p_cb->OSTaskQLast[task_id][mbox] = p_hdr;
537
538  p_hdr->p_next = NULL;
539  p_hdr->status = BUF_STATUS_QUEUED;
540  p_hdr->task_id = task_id;
541
542  GKI_enable();
543
544  GKI_send_event(task_id, (uint16_t)EVENT_MASK(mbox));
545
546  return;
547}
548
549/*******************************************************************************
550**
551** Function         GKI_read_mbox
552**
553** Description      Called by applications to read a buffer from one of
554**                  the task mailboxes.  A task can only read its own mailbox.
555**
556** Parameters:      mbox  - (input) mailbox ID to read (0, 1, 2, or 3)
557**
558** Returns          NULL if the mailbox was empty, else the address of a buffer
559**
560*******************************************************************************/
561void* GKI_read_mbox(uint8_t mbox) {
562  uint8_t task_id = GKI_get_taskid();
563  void* p_buf = NULL;
564  BUFFER_HDR_T* p_hdr;
565
566  if ((task_id >= GKI_MAX_TASKS) || (mbox >= NUM_TASK_MBOX)) return (NULL);
567
568  GKI_disable();
569
570  if (gki_cb.com.OSTaskQFirst[task_id][mbox]) {
571    p_hdr = gki_cb.com.OSTaskQFirst[task_id][mbox];
572    gki_cb.com.OSTaskQFirst[task_id][mbox] = p_hdr->p_next;
573
574    p_hdr->p_next = NULL;
575    p_hdr->status = BUF_STATUS_UNLINKED;
576
577    p_buf = (uint8_t*)p_hdr + BUFFER_HDR_SIZE;
578  }
579
580  GKI_enable();
581
582  return (p_buf);
583}
584
585/*******************************************************************************
586**
587** Function         GKI_enqueue
588**
589** Description      Enqueue a buffer at the tail of the queue
590**
591** Parameters:      p_q  -  (input) pointer to a queue.
592**                  p_buf - (input) address of the buffer to enqueue
593**
594** Returns          void
595**
596*******************************************************************************/
597void GKI_enqueue(BUFFER_Q* p_q, void* p_buf) {
598  BUFFER_HDR_T* p_hdr;
599
600#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
601  if (gki_chk_buf_damage(p_buf)) {
602    GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Enqueue - Buffer corrupted");
603    return;
604  }
605#endif
606
607  p_hdr = (BUFFER_HDR_T*)((uint8_t*)p_buf - BUFFER_HDR_SIZE);
608
609  if (p_hdr->status != BUF_STATUS_UNLINKED) {
610    GKI_exception(GKI_ERROR_ENQUEUE_BUF_LINKED, "Eneueue - buf already linked");
611    return;
612  }
613
614  GKI_disable();
615
616  /* Since the queue is exposed (C vs C++), keep the pointers in exposed format
617   */
618  if (p_q->p_first) {
619    BUFFER_HDR_T* p_last_hdr =
620        (BUFFER_HDR_T*)((uint8_t*)p_q->p_last - BUFFER_HDR_SIZE);
621    p_last_hdr->p_next = p_hdr;
622  } else
623    p_q->p_first = p_buf;
624
625  p_q->p_last = p_buf;
626  p_q->count++;
627
628  p_hdr->p_next = NULL;
629  p_hdr->status = BUF_STATUS_QUEUED;
630
631  GKI_enable();
632
633  return;
634}
635
636/*******************************************************************************
637**
638** Function         GKI_enqueue_head
639**
640** Description      Enqueue a buffer at the head of the queue
641**
642** Parameters:      p_q  -  (input) pointer to a queue.
643**                  p_buf - (input) address of the buffer to enqueue
644**
645** Returns          void
646**
647*******************************************************************************/
648void GKI_enqueue_head(BUFFER_Q* p_q, void* p_buf) {
649  BUFFER_HDR_T* p_hdr;
650
651#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
652  if (gki_chk_buf_damage(p_buf)) {
653    GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Enqueue - Buffer corrupted");
654    return;
655  }
656#endif
657
658  p_hdr = (BUFFER_HDR_T*)((uint8_t*)p_buf - BUFFER_HDR_SIZE);
659
660  if (p_hdr->status != BUF_STATUS_UNLINKED) {
661    GKI_exception(GKI_ERROR_ENQUEUE_BUF_LINKED,
662                  "Eneueue head - buf already linked");
663    return;
664  }
665
666  GKI_disable();
667
668  if (p_q->p_first) {
669    p_hdr->p_next = (BUFFER_HDR_T*)((uint8_t*)p_q->p_first - BUFFER_HDR_SIZE);
670    p_q->p_first = p_buf;
671  } else {
672    p_q->p_first = p_buf;
673    p_q->p_last = p_buf;
674    p_hdr->p_next = NULL;
675  }
676  p_q->count++;
677
678  p_hdr->status = BUF_STATUS_QUEUED;
679
680  GKI_enable();
681
682  return;
683}
684
685/*******************************************************************************
686**
687** Function         GKI_dequeue
688**
689** Description      Dequeues a buffer from the head of a queue
690**
691** Parameters:      p_q  - (input) pointer to a queue.
692**
693** Returns          NULL if queue is empty, else buffer
694**
695*******************************************************************************/
696void* GKI_dequeue(BUFFER_Q* p_q) {
697  BUFFER_HDR_T* p_hdr;
698
699  GKI_disable();
700
701  if (!p_q || !p_q->count) {
702    GKI_enable();
703    return (NULL);
704  }
705
706  p_hdr = (BUFFER_HDR_T*)((uint8_t*)p_q->p_first - BUFFER_HDR_SIZE);
707
708  /* Keep buffers such that GKI header is invisible
709  */
710  if (p_hdr->p_next)
711    p_q->p_first = ((uint8_t*)p_hdr->p_next + BUFFER_HDR_SIZE);
712  else {
713    p_q->p_first = NULL;
714    p_q->p_last = NULL;
715  }
716
717  p_q->count--;
718
719  p_hdr->p_next = NULL;
720  p_hdr->status = BUF_STATUS_UNLINKED;
721
722  GKI_enable();
723
724  return ((uint8_t*)p_hdr + BUFFER_HDR_SIZE);
725}
726
727/*******************************************************************************
728**
729** Function         GKI_remove_from_queue
730**
731** Description      Dequeue a buffer from the middle of the queue
732**
733** Parameters:      p_q  - (input) pointer to a queue.
734**                  p_buf - (input) address of the buffer to enqueue
735**
736** Returns          NULL if queue is empty, else buffer
737**
738*******************************************************************************/
739void* GKI_remove_from_queue(BUFFER_Q* p_q, void* p_buf) {
740  BUFFER_HDR_T* p_prev;
741  BUFFER_HDR_T* p_buf_hdr;
742
743  GKI_disable();
744
745  if (p_buf == p_q->p_first) {
746    GKI_enable();
747    return (GKI_dequeue(p_q));
748  }
749
750  p_buf_hdr = (BUFFER_HDR_T*)((uint8_t*)p_buf - BUFFER_HDR_SIZE);
751  p_prev = (BUFFER_HDR_T*)((uint8_t*)p_q->p_first - BUFFER_HDR_SIZE);
752
753  for (; p_prev; p_prev = p_prev->p_next) {
754    /* If the previous points to this one, move the pointers around */
755    if (p_prev->p_next == p_buf_hdr) {
756      p_prev->p_next = p_buf_hdr->p_next;
757
758      /* If we are removing the last guy in the queue, update p_last */
759      if (p_buf == p_q->p_last) p_q->p_last = p_prev + 1;
760
761      /* One less in the queue */
762      p_q->count--;
763
764      /* The buffer is now unlinked */
765      p_buf_hdr->p_next = NULL;
766      p_buf_hdr->status = BUF_STATUS_UNLINKED;
767
768      GKI_enable();
769      return (p_buf);
770    }
771  }
772
773  GKI_enable();
774  return (NULL);
775}
776
777/*******************************************************************************
778**
779** Function         GKI_getfirst
780**
781** Description      Return a pointer to the first buffer in a queue
782**
783** Parameters:      p_q  - (input) pointer to a queue.
784**
785** Returns          NULL if queue is empty, else buffer address
786**
787*******************************************************************************/
788void* GKI_getfirst(BUFFER_Q* p_q) { return (p_q->p_first); }
789
790/*******************************************************************************
791**
792** Function         GKI_getlast
793**
794** Description      Return a pointer to the last buffer in a queue
795**
796** Parameters:      p_q  - (input) pointer to a queue.
797**
798** Returns          NULL if queue is empty, else buffer address
799**
800*******************************************************************************/
801void* GKI_getlast(BUFFER_Q* p_q) { return (p_q->p_last); }
802
803/*******************************************************************************
804**
805** Function         GKI_getnext
806**
807** Description      Return a pointer to the next buffer in a queue
808**
809** Parameters:      p_buf - (input) pointer to the buffer to find the next one
810**                                  from.
811**
812** Returns          NULL if no more buffers in the queue, else next buffer
813**                  address
814**
815*******************************************************************************/
816void* GKI_getnext(void* p_buf) {
817  BUFFER_HDR_T* p_hdr;
818
819  p_hdr = (BUFFER_HDR_T*)((uint8_t*)p_buf - BUFFER_HDR_SIZE);
820
821  if (p_hdr->p_next)
822    return ((uint8_t*)p_hdr->p_next + BUFFER_HDR_SIZE);
823  else
824    return (NULL);
825}
826
827/*******************************************************************************
828**
829** Function         GKI_queue_is_empty
830**
831** Description      Check the status of a queue.
832**
833** Parameters:      p_q  - (input) pointer to a queue.
834**
835** Returns          TRUE if queue is empty, else FALSE
836**
837*******************************************************************************/
838bool GKI_queue_is_empty(BUFFER_Q* p_q) { return ((bool)(p_q->count == 0)); }
839
840/*******************************************************************************
841**
842** Function         GKI_find_buf_start
843**
844** Description      This function is called with an address inside a buffer,
845**                  and returns the start address ofthe buffer.
846**
847**                  The buffer should be one allocated from one of GKI's pools.
848**
849** Parameters:      p_user_area - (input) address of anywhere in a GKI buffer.
850**
851** Returns          void * - Address of the beginning of the specified buffer if
852**                           successful, otherwise NULL if unsuccessful
853**
854*******************************************************************************/
855void* GKI_find_buf_start(void* p_user_area) {
856  uint16_t xx, size;
857  uint32_t yy;
858  tGKI_COM_CB* p_cb = &gki_cb.com;
859  uint8_t* p_ua = (uint8_t*)p_user_area;
860
861  for (xx = 0; xx < GKI_NUM_TOTAL_BUF_POOLS; xx++) {
862    if ((p_ua > p_cb->pool_start[xx]) && (p_ua < p_cb->pool_end[xx])) {
863      yy = (uint32_t)(p_ua - p_cb->pool_start[xx]);
864
865      size = p_cb->pool_size[xx];
866
867      yy = (yy / size) * size;
868
869      return ((void*)(p_cb->pool_start[xx] + yy + sizeof(BUFFER_HDR_T)));
870    }
871  }
872
873  /* If here, invalid address - not in one of our buffers */
874  GKI_exception(GKI_ERROR_BUF_SIZE_ZERO, "GKI_get_buf_start:: bad addr");
875
876  return (NULL);
877}
878
879/********************************************************
880* The following functions are not needed for light stack
881*********************************************************/
882#ifndef BTU_STACK_LITE_ENABLED
883#define BTU_STACK_LITE_ENABLED FALSE
884#endif
885
886#if (BTU_STACK_LITE_ENABLED == FALSE)
887
888/*******************************************************************************
889**
890** Function         GKI_set_pool_permission
891**
892** Description      This function is called to set or change the permissions for
893**                  the specified pool ID.
894**
895** Parameters       pool_id - (input) pool ID to be set or changed
896**                  permission - (input) GKI_PUBLIC_POOL or GKI_RESTRICTED_POOL
897**
898** Returns          GKI_SUCCESS if successful
899**                  GKI_INVALID_POOL if unsuccessful
900**
901*******************************************************************************/
902uint8_t GKI_set_pool_permission(uint8_t pool_id, uint8_t permission) {
903  tGKI_COM_CB* p_cb = &gki_cb.com;
904
905  if (pool_id < GKI_NUM_TOTAL_BUF_POOLS) {
906    if (permission == GKI_RESTRICTED_POOL)
907      p_cb->pool_access_mask =
908          (uint16_t)(p_cb->pool_access_mask | (1 << pool_id));
909
910    else /* mark the pool as public */
911      p_cb->pool_access_mask =
912          (uint16_t)(p_cb->pool_access_mask & ~(1 << pool_id));
913
914    return (GKI_SUCCESS);
915  } else
916    return (GKI_INVALID_POOL);
917}
918
919/*******************************************************************************
920**
921** Function         gki_add_to_pool_list
922**
923** Description      Adds pool to the pool list which is arranged in the
924**                  order of size
925**
926** Returns          void
927**
928*******************************************************************************/
929static void gki_add_to_pool_list(uint8_t pool_id) {
930  int32_t i, j;
931  tGKI_COM_CB* p_cb = &gki_cb.com;
932
933  /* Find the position where the specified pool should be inserted into the list
934   */
935  for (i = 0; i < p_cb->curr_total_no_of_pools; i++) {
936    if (p_cb->freeq[pool_id].size <= p_cb->freeq[p_cb->pool_list[i]].size)
937      break;
938  }
939
940  /* Insert the new buffer pool ID into the list of pools */
941  for (j = p_cb->curr_total_no_of_pools; j > i; j--) {
942    p_cb->pool_list[j] = p_cb->pool_list[j - 1];
943  }
944
945  p_cb->pool_list[i] = pool_id;
946
947  return;
948}
949
950/*******************************************************************************
951**
952** Function         gki_remove_from_pool_list
953**
954** Description      Removes pool from the pool list. Called when a pool is
955**                  deleted
956**
957** Returns          void
958**
959*******************************************************************************/
960static void gki_remove_from_pool_list(uint8_t pool_id) {
961  tGKI_COM_CB* p_cb = &gki_cb.com;
962  uint8_t i;
963
964  for (i = 0; i < p_cb->curr_total_no_of_pools; i++) {
965    if (pool_id == p_cb->pool_list[i]) break;
966  }
967
968  while (i < (p_cb->curr_total_no_of_pools - 1)) {
969    p_cb->pool_list[i] = p_cb->pool_list[i + 1];
970    i++;
971  }
972
973  return;
974}
975
976/*******************************************************************************
977**
978** Function         GKI_igetpoolbuf
979**
980** Description      Called by an interrupt service routine to get a free buffer
981**                  from a specific buffer pool.
982**
983** Parameters       pool_id - (input) pool ID to get a buffer out of.
984**
985** Returns          A pointer to the buffer, or NULL if none available
986**
987*******************************************************************************/
988void* GKI_igetpoolbuf(uint8_t pool_id) {
989  FREE_QUEUE_T* Q;
990  BUFFER_HDR_T* p_hdr;
991
992  if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) return (NULL);
993
994  Q = &gki_cb.com.freeq[pool_id];
995  if (Q->cur_cnt < Q->total) {
996    p_hdr = Q->p_first;
997    Q->p_first = p_hdr->p_next;
998
999    if (!Q->p_first) Q->p_last = NULL;
1000
1001    if (++Q->cur_cnt > Q->max_cnt) Q->max_cnt = Q->cur_cnt;
1002
1003    p_hdr->task_id = GKI_get_taskid();
1004
1005    p_hdr->status = BUF_STATUS_UNLINKED;
1006    p_hdr->p_next = NULL;
1007    p_hdr->Type = 0;
1008
1009    return ((void*)((uint8_t*)p_hdr + BUFFER_HDR_SIZE));
1010  }
1011
1012  return (NULL);
1013}
1014
1015/*******************************************************************************
1016**
1017** Function         GKI_poolcount
1018**
1019** Description      Called by an application to get the total number of buffers
1020**                  in the specified buffer pool.
1021**
1022** Parameters       pool_id - (input) pool ID to get the free count of.
1023**
1024** Returns          the total number of buffers in the pool
1025**
1026*******************************************************************************/
1027uint16_t GKI_poolcount(uint8_t pool_id) {
1028  if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) return (0);
1029
1030  return (gki_cb.com.freeq[pool_id].total);
1031}
1032
1033/*******************************************************************************
1034**
1035** Function         GKI_poolfreecount
1036**
1037** Description      Called by an application to get the number of free buffers
1038**                  in the specified buffer pool.
1039**
1040** Parameters       pool_id - (input) pool ID to get the free count of.
1041**
1042** Returns          the number of free buffers in the pool
1043**
1044*******************************************************************************/
1045uint16_t GKI_poolfreecount(uint8_t pool_id) {
1046  FREE_QUEUE_T* Q;
1047
1048  if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) return (0);
1049
1050  Q = &gki_cb.com.freeq[pool_id];
1051
1052  return ((uint16_t)(Q->total - Q->cur_cnt));
1053}
1054
1055/*******************************************************************************
1056**
1057** Function         GKI_change_buf_owner
1058**
1059** Description      Called to change the task ownership of a buffer.
1060**
1061** Parameters:      p_buf   - (input) pointer to the buffer
1062**                  task_id - (input) task id to change ownership to
1063**
1064** Returns          void
1065**
1066*******************************************************************************/
1067void GKI_change_buf_owner(void* p_buf, uint8_t task_id) {
1068  BUFFER_HDR_T* p_hdr = (BUFFER_HDR_T*)((uint8_t*)p_buf - BUFFER_HDR_SIZE);
1069
1070  p_hdr->task_id = task_id;
1071
1072  return;
1073}
1074
1075#if (GKI_SEND_MSG_FROM_ISR == TRUE)
1076/*******************************************************************************
1077**
1078** Function         GKI_isend_msg
1079**
1080** Description      Called from interrupt context to send a buffer to a task
1081**
1082** Returns          Nothing
1083**
1084*******************************************************************************/
1085void GKI_isend_msg(uint8_t task_id, uint8_t mbox, void* msg) {
1086  BUFFER_HDR_T* p_hdr;
1087  tGKI_COM_CB* p_cb = &gki_cb.com;
1088
1089  /* If task non-existant or not started, drop buffer */
1090  if ((task_id >= GKI_MAX_TASKS) || (mbox >= NUM_TASK_MBOX) ||
1091      (p_cb->OSRdyTbl[task_id] == TASK_DEAD)) {
1092    GKI_exception(GKI_ERROR_SEND_MSG_BAD_DEST, "Sending to unknown dest");
1093    GKI_freebuf(msg);
1094    return;
1095  }
1096
1097#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
1098  if (gki_chk_buf_damage(msg)) {
1099    GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Send - Buffer corrupted");
1100    return;
1101  }
1102#endif
1103
1104#if (GKI_ENABLE_OWNER_CHECK == TRUE)
1105  if (gki_chk_buf_owner(msg)) {
1106    GKI_exception(GKI_ERROR_NOT_BUF_OWNER, "Send by non-owner");
1107    return;
1108  }
1109#endif
1110
1111  p_hdr = (BUFFER_HDR_T*)((uint8_t*)msg - BUFFER_HDR_SIZE);
1112
1113  if (p_hdr->status != BUF_STATUS_UNLINKED) {
1114    GKI_exception(GKI_ERROR_SEND_MSG_BUF_LINKED, "Send - buffer linked");
1115    return;
1116  }
1117
1118  if (p_cb->OSTaskQFirst[task_id][mbox])
1119    p_cb->OSTaskQLast[task_id][mbox]->p_next = p_hdr;
1120  else
1121    p_cb->OSTaskQFirst[task_id][mbox] = p_hdr;
1122
1123  p_cb->OSTaskQLast[task_id][mbox] = p_hdr;
1124
1125  p_hdr->p_next = NULL;
1126  p_hdr->status = BUF_STATUS_QUEUED;
1127  p_hdr->task_id = task_id;
1128
1129  GKI_isend_event(task_id, (uint16_t)EVENT_MASK(mbox));
1130
1131  return;
1132}
1133#endif
1134
1135/*******************************************************************************
1136**
1137** Function         GKI_create_pool
1138**
1139** Description      Called by applications to create a buffer pool.
1140**
1141** Parameters:      size - (input) length (in bytes) of each buffer in the pool
1142**                  count - (input) number of buffers to allocate for the pool
1143**                  permission - (input) restricted or public access?
1144**                                      (GKI_PUBLIC_POOL or GKI_RESTRICTED_POOL)
1145**                  p_mem_pool - (input) pointer to an OS memory pool, NULL if
1146**                                       not provided
1147**
1148** Returns          the buffer pool ID, which should be used in calls to
1149**                  GKI_getpoolbuf(). If a pool could not be created, this
1150**                  function returns 0xff.
1151**
1152*******************************************************************************/
1153uint8_t GKI_create_pool(uint16_t size, uint16_t count, uint8_t permission,
1154                        void* p_mem_pool) {
1155  uint8_t xx;
1156  uint32_t mem_needed;
1157  int32_t tempsize = size;
1158  tGKI_COM_CB* p_cb = &gki_cb.com;
1159
1160  /* First make sure the size of each pool has a valid size with room for the
1161   * header info */
1162  if (size > MAX_USER_BUF_SIZE) return (GKI_INVALID_POOL);
1163
1164  /* First, look for an unused pool */
1165  for (xx = 0; xx < GKI_NUM_TOTAL_BUF_POOLS; xx++) {
1166    if (!p_cb->pool_start[xx]) break;
1167  }
1168
1169  if (xx == GKI_NUM_TOTAL_BUF_POOLS) return (GKI_INVALID_POOL);
1170
1171  /* Ensure an even number of longwords */
1172  tempsize = (int32_t)ALIGN_POOL(size);
1173
1174  mem_needed = (tempsize + BUFFER_PADDING_SIZE) * count;
1175
1176  if (!p_mem_pool) p_mem_pool = GKI_os_malloc(mem_needed);
1177
1178  if (p_mem_pool) {
1179    /* Initialize the new pool */
1180    gki_init_free_queue(xx, size, count, p_mem_pool);
1181    gki_add_to_pool_list(xx);
1182    (void)GKI_set_pool_permission(xx, permission);
1183    p_cb->curr_total_no_of_pools++;
1184
1185    return (xx);
1186  } else
1187    return (GKI_INVALID_POOL);
1188}
1189
1190/*******************************************************************************
1191**
1192** Function         GKI_delete_pool
1193**
1194** Description      Called by applications to delete a buffer pool.  The
1195**                  function calls the operating specific function to free the
1196**                  actual memory. An exception is generated if an error is
1197**                  detected.
1198**
1199** Parameters:      pool_id - (input) Id of the poll being deleted.
1200**
1201** Returns          void
1202**
1203*******************************************************************************/
1204void GKI_delete_pool(uint8_t pool_id) {
1205  FREE_QUEUE_T* Q;
1206  tGKI_COM_CB* p_cb = &gki_cb.com;
1207
1208  if ((pool_id >= GKI_NUM_TOTAL_BUF_POOLS) || (!p_cb->pool_start[pool_id]))
1209    return;
1210
1211  GKI_disable();
1212  Q = &p_cb->freeq[pool_id];
1213
1214  if (!Q->cur_cnt) {
1215    Q->size = 0;
1216    Q->total = 0;
1217    Q->cur_cnt = 0;
1218    Q->max_cnt = 0;
1219    Q->p_first = NULL;
1220    Q->p_last = NULL;
1221
1222    GKI_os_free(p_cb->pool_start[pool_id]);
1223
1224    p_cb->pool_start[pool_id] = NULL;
1225    p_cb->pool_end[pool_id] = NULL;
1226    p_cb->pool_size[pool_id] = 0;
1227
1228    gki_remove_from_pool_list(pool_id);
1229    p_cb->curr_total_no_of_pools--;
1230  } else
1231    GKI_exception(GKI_ERROR_DELETE_POOL_BAD_QID, "Deleting bad pool");
1232
1233  GKI_enable();
1234
1235  return;
1236}
1237
1238#endif /*  BTU_STACK_LITE_ENABLED == FALSE */
1239
1240/*******************************************************************************
1241**
1242** Function         GKI_get_pool_bufsize
1243**
1244** Description      Called by an application to get the size of buffers in a
1245**                  pool
1246**
1247** Parameters       Pool ID.
1248**
1249** Returns          the size of buffers in the pool
1250**
1251*******************************************************************************/
1252uint16_t GKI_get_pool_bufsize(uint8_t pool_id) {
1253  if (pool_id < GKI_NUM_TOTAL_BUF_POOLS)
1254    return (gki_cb.com.freeq[pool_id].size);
1255
1256  return (0);
1257}
1258
1259/*******************************************************************************
1260**
1261** Function         GKI_poolutilization
1262**
1263** Description      Called by an application to get the buffer utilization
1264**                  in the specified buffer pool.
1265**
1266** Parameters       pool_id - (input) pool ID to get the free count of.
1267**
1268** Returns          % of buffers used from 0 to 100
1269**
1270*******************************************************************************/
1271uint16_t GKI_poolutilization(uint8_t pool_id) {
1272  FREE_QUEUE_T* Q;
1273
1274  if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) return (100);
1275
1276  Q = &gki_cb.com.freeq[pool_id];
1277
1278  if (Q->total == 0) return (100);
1279
1280  return ((Q->cur_cnt * 100) / Q->total);
1281}
1282