summaryrefslogtreecommitdiffstats
path: root/gki/common
diff options
context:
space:
mode:
Diffstat (limited to 'gki/common')
-rw-r--r--gki/common/gki.h494
-rw-r--r--gki/common/gki_buffer.c1481
-rw-r--r--gki/common/gki_common.h390
-rw-r--r--gki/common/gki_debug.c354
-rw-r--r--gki/common/gki_inet.h47
-rw-r--r--gki/common/gki_time.c1023
6 files changed, 3789 insertions, 0 deletions
diff --git a/gki/common/gki.h b/gki/common/gki.h
new file mode 100644
index 0000000..5180dcd
--- /dev/null
+++ b/gki/common/gki.h
@@ -0,0 +1,494 @@
+/******************************************************************************
+ *
+ * Copyright (C) 1999-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+#ifndef GKI_H
+#define GKI_H
+
+
+/* Include platform-specific over-rides */
+#if (defined(NFC_STANDALONE) && (NFC_STANDALONE == TRUE))
+ #include "gki_target.h"
+#else
+ /* For non-nfc_standalone, include Bluetooth definitions */
+ #include "bt_target.h"
+#endif
+
+
+
+#include "bt_types.h"
+
+/* Error codes */
+#define GKI_SUCCESS 0x00
+#define GKI_FAILURE 0x01
+#define GKI_INVALID_TASK 0xF0
+#define GKI_INVALID_POOL 0xFF
+
+
+/************************************************************************
+** Mailbox definitions. Each task has 4 mailboxes that are used to
+** send buffers to the task.
+*/
+#define TASK_MBOX_0 0
+#define TASK_MBOX_1 1
+#define TASK_MBOX_2 2
+#define TASK_MBOX_3 3
+
+#define NUM_TASK_MBOX 4
+
+/************************************************************************
+** Event definitions.
+**
+** There are 4 reserved events used to signal messages rcvd in task mailboxes.
+** There are 4 reserved events used to signal timeout events.
+** There are 8 general purpose events available for applications.
+*/
+#define MAX_EVENTS 16
+
+#define TASK_MBOX_0_EVT_MASK 0x0001
+#define TASK_MBOX_1_EVT_MASK 0x0002
+#define TASK_MBOX_2_EVT_MASK 0x0004
+#define TASK_MBOX_3_EVT_MASK 0x0008
+
+
+#define TIMER_0 0
+#define TIMER_1 1
+#define TIMER_2 2
+#define TIMER_3 3
+
+#define TIMER_0_EVT_MASK 0x0010
+#define TIMER_1_EVT_MASK 0x0020
+#define TIMER_2_EVT_MASK 0x0040
+#define TIMER_3_EVT_MASK 0x0080
+
+#define APPL_EVT_0 8
+#define APPL_EVT_1 9
+#define APPL_EVT_2 10
+#define APPL_EVT_3 11
+#define APPL_EVT_4 12
+#define APPL_EVT_5 13
+#define APPL_EVT_6 14
+#define APPL_EVT_7 15
+
+#define EVENT_MASK(evt) ((UINT16)(0x0001 << (evt)))
+
+/************************************************************************
+** Max Time Queue
+**/
+#ifndef GKI_MAX_TIMER_QUEUES
+#define GKI_MAX_TIMER_QUEUES 3
+#endif
+
+/************************************************************************
+** Macro to determine the pool buffer size based on the GKI POOL ID at compile time.
+** Pool IDs index from 0 to GKI_NUM_FIXED_BUF_POOLS - 1
+*/
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 1)
+
+#ifndef GKI_POOL_ID_0
+#define GKI_POOL_ID_0 0
+#endif /* ifndef GKI_POOL_ID_0 */
+
+#ifndef GKI_BUF0_SIZE
+#define GKI_BUF0_SIZE 0
+#endif /* ifndef GKI_BUF0_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 1 */
+
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 2)
+
+#ifndef GKI_POOL_ID_1
+#define GKI_POOL_ID_1 0
+#endif /* ifndef GKI_POOL_ID_1 */
+
+#ifndef GKI_BUF1_SIZE
+#define GKI_BUF1_SIZE 0
+#endif /* ifndef GKI_BUF1_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 2 */
+
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 3)
+
+#ifndef GKI_POOL_ID_2
+#define GKI_POOL_ID_2 0
+#endif /* ifndef GKI_POOL_ID_2 */
+
+#ifndef GKI_BUF2_SIZE
+#define GKI_BUF2_SIZE 0
+#endif /* ifndef GKI_BUF2_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 3 */
+
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 4)
+
+#ifndef GKI_POOL_ID_3
+#define GKI_POOL_ID_3 0
+#endif /* ifndef GKI_POOL_ID_4 */
+
+#ifndef GKI_BUF3_SIZE
+#define GKI_BUF3_SIZE 0
+#endif /* ifndef GKI_BUF3_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 4 */
+
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 5)
+
+#ifndef GKI_POOL_ID_4
+#define GKI_POOL_ID_4 0
+#endif /* ifndef GKI_POOL_ID_4 */
+
+#ifndef GKI_BUF4_SIZE
+#define GKI_BUF4_SIZE 0
+#endif /* ifndef GKI_BUF4_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 5 */
+
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 6)
+
+#ifndef GKI_POOL_ID_5
+#define GKI_POOL_ID_5 0
+#endif /* ifndef GKI_POOL_ID_5 */
+
+#ifndef GKI_BUF5_SIZE
+#define GKI_BUF5_SIZE 0
+#endif /* ifndef GKI_BUF5_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 6 */
+
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 7)
+
+#ifndef GKI_POOL_ID_6
+#define GKI_POOL_ID_6 0
+#endif /* ifndef GKI_POOL_ID_6 */
+
+#ifndef GKI_BUF6_SIZE
+#define GKI_BUF6_SIZE 0
+#endif /* ifndef GKI_BUF6_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 7 */
+
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 8)
+
+#ifndef GKI_POOL_ID_7
+#define GKI_POOL_ID_7 0
+#endif /* ifndef GKI_POOL_ID_7 */
+
+#ifndef GKI_BUF7_SIZE
+#define GKI_BUF7_SIZE 0
+#endif /* ifndef GKI_BUF7_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 8 */
+
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 9)
+
+#ifndef GKI_POOL_ID_8
+#define GKI_POOL_ID_8 0
+#endif /* ifndef GKI_POOL_ID_8 */
+
+#ifndef GKI_BUF8_SIZE
+#define GKI_BUF8_SIZE 0
+#endif /* ifndef GKI_BUF8_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 9 */
+
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 10)
+
+#ifndef GKI_POOL_ID_9
+#define GKI_POOL_ID_9 0
+#endif /* ifndef GKI_POOL_ID_9 */
+
+#ifndef GKI_BUF9_SIZE
+#define GKI_BUF9_SIZE 0
+#endif /* ifndef GKI_BUF9_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 10 */
+
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 11)
+
+#ifndef GKI_POOL_ID_10
+#define GKI_POOL_ID_10 0
+#endif /* ifndef GKI_POOL_ID_10 */
+
+#ifndef GKI_BUF10_SIZE
+#define GKI_BUF10_SIZE 0
+#endif /* ifndef GKI_BUF10_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 11 */
+
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 12)
+
+#ifndef GKI_POOL_ID_11
+#define GKI_POOL_ID_11 0
+#endif /* ifndef GKI_POOL_ID_11 */
+
+#ifndef GKI_BUF11_SIZE
+#define GKI_BUF11_SIZE 0
+#endif /* ifndef GKI_BUF11_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 12 */
+
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 13)
+
+#ifndef GKI_POOL_ID_12
+#define GKI_POOL_ID_12 0
+#endif /* ifndef GKI_POOL_ID_12 */
+
+#ifndef GKI_BUF12_SIZE
+#define GKI_BUF12_SIZE 0
+#endif /* ifndef GKI_BUF12_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 13 */
+
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 14)
+
+#ifndef GKI_POOL_ID_13
+#define GKI_POOL_ID_13 0
+#endif /* ifndef GKI_POOL_ID_13 */
+
+#ifndef GKI_BUF13_SIZE
+#define GKI_BUF13_SIZE 0
+#endif /* ifndef GKI_BUF13_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 14 */
+
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 15)
+
+#ifndef GKI_POOL_ID_14
+#define GKI_POOL_ID_14 0
+#endif /* ifndef GKI_POOL_ID_14 */
+
+#ifndef GKI_BUF14_SIZE
+#define GKI_BUF14_SIZE 0
+#endif /* ifndef GKI_BUF14_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 15 */
+
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 16)
+
+#ifndef GKI_POOL_ID_15
+#define GKI_POOL_ID_15 0
+#endif /* ifndef GKI_POOL_ID_15 */
+
+#ifndef GKI_BUF15_SIZE
+#define GKI_BUF15_SIZE 0
+#endif /* ifndef GKI_BUF15_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 16 */
+
+
+/* Timer list entry callback type
+*/
+typedef void (TIMER_CBACK)(void *p_tle);
+#ifndef TIMER_PARAM_TYPE
+#ifdef WIN2000
+#define TIMER_PARAM_TYPE void *
+#else
+#define TIMER_PARAM_TYPE UINT32
+#endif
+#endif
+/* Define a timer list entry
+*/
+typedef struct _tle
+{
+ struct _tle *p_next;
+ struct _tle *p_prev;
+ TIMER_CBACK *p_cback;
+ INT32 ticks;
+ TIMER_PARAM_TYPE param;
+ UINT16 event;
+ UINT8 in_use;
+} TIMER_LIST_ENT;
+
+/* Define a timer list queue
+*/
+typedef struct
+{
+ TIMER_LIST_ENT *p_first;
+ TIMER_LIST_ENT *p_last;
+ INT32 last_ticks;
+} TIMER_LIST_Q;
+
+
+/***********************************************************************
+** This queue is a general purpose buffer queue, for application use.
+*/
+typedef struct
+{
+ void *p_first;
+ void *p_last;
+ UINT16 count;
+} BUFFER_Q;
+
+#define GKI_IS_QUEUE_EMPTY(p_q) ((p_q)->count == 0)
+
+/* Task constants
+*/
+#ifndef TASKPTR
+typedef void (*TASKPTR)(UINT32);
+#endif
+
+
+#define GKI_PUBLIC_POOL 0 /* General pool accessible to GKI_getbuf() */
+#define GKI_RESTRICTED_POOL 1 /* Inaccessible pool to GKI_getbuf() */
+
+/***********************************************************************
+** Function prototypes
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Task management
+*/
+GKI_API extern UINT8 GKI_create_task (TASKPTR, UINT8, INT8 *, UINT16 *, UINT16);
+GKI_API extern void GKI_destroy_task(UINT8 task_id);
+GKI_API extern void GKI_task_self_cleanup(UINT8 task_id);
+GKI_API extern void GKI_exit_task(UINT8);
+GKI_API extern UINT8 GKI_get_taskid(void);
+GKI_API extern void GKI_init(void);
+GKI_API extern void GKI_shutdown(void);
+GKI_API extern INT8 *GKI_map_taskname(UINT8);
+GKI_API extern UINT8 GKI_resume_task(UINT8);
+GKI_API extern void GKI_run(void *);
+GKI_API extern void GKI_freeze(void);
+GKI_API extern void GKI_stop(void);
+GKI_API extern UINT8 GKI_suspend_task(UINT8);
+GKI_API extern UINT8 GKI_is_task_running(UINT8);
+
+/* memory management
+*/
+GKI_API extern void GKI_shiftdown (UINT8 *p_mem, UINT32 len, UINT32 shift_amount);
+GKI_API extern void GKI_shiftup (UINT8 *p_dest, UINT8 *p_src, UINT32 len);
+
+/* To send buffers and events between tasks
+*/
+GKI_API extern UINT8 GKI_isend_event (UINT8, UINT16);
+GKI_API extern void GKI_isend_msg (UINT8, UINT8, void *);
+GKI_API extern void *GKI_read_mbox (UINT8);
+GKI_API extern void GKI_send_msg (UINT8, UINT8, void *);
+GKI_API extern UINT8 GKI_send_event (UINT8, UINT16);
+
+
+/* To get and release buffers, change owner and get size
+*/
+GKI_API extern void GKI_change_buf_owner (void *, UINT8);
+GKI_API extern UINT8 GKI_create_pool (UINT16, UINT16, UINT8, void *);
+GKI_API extern void GKI_delete_pool (UINT8);
+GKI_API extern void *GKI_find_buf_start (void *);
+GKI_API extern void GKI_freebuf (void *);
+GKI_API extern void *GKI_getbuf (UINT16);
+GKI_API extern UINT16 GKI_get_buf_size (void *);
+GKI_API extern void *GKI_getpoolbuf (UINT8);
+GKI_API extern UINT16 GKI_poolcount (UINT8);
+GKI_API extern UINT16 GKI_poolfreecount (UINT8);
+GKI_API extern UINT16 GKI_poolutilization (UINT8);
+GKI_API extern void GKI_register_mempool (void *p_mem);
+GKI_API extern UINT8 GKI_set_pool_permission(UINT8, UINT8);
+
+
+/* User buffer queue management
+*/
+GKI_API extern void *GKI_dequeue (BUFFER_Q *);
+GKI_API extern void GKI_enqueue (BUFFER_Q *, void *);
+GKI_API extern void GKI_enqueue_head (BUFFER_Q *, void *);
+GKI_API extern void *GKI_getfirst (BUFFER_Q *);
+GKI_API extern void *GKI_getlast (BUFFER_Q *);
+GKI_API extern void *GKI_getnext (void *);
+GKI_API extern void GKI_init_q (BUFFER_Q *);
+GKI_API extern BOOLEAN GKI_queue_is_empty(BUFFER_Q *);
+GKI_API extern void *GKI_remove_from_queue (BUFFER_Q *, void *);
+GKI_API extern UINT16 GKI_get_pool_bufsize (UINT8);
+
+/* Timer management
+*/
+GKI_API extern void GKI_add_to_timer_list (TIMER_LIST_Q *, TIMER_LIST_ENT *);
+GKI_API extern void GKI_delay(UINT32);
+GKI_API extern UINT32 GKI_get_tick_count(void);
+GKI_API extern INT8 *GKI_get_time_stamp(INT8 *);
+GKI_API extern void GKI_init_timer_list (TIMER_LIST_Q *);
+GKI_API extern void GKI_init_timer_list_entry (TIMER_LIST_ENT *);
+GKI_API extern INT32 GKI_ready_to_sleep (void);
+GKI_API extern void GKI_remove_from_timer_list (TIMER_LIST_Q *, TIMER_LIST_ENT *);
+GKI_API extern void GKI_start_timer(UINT8, INT32, BOOLEAN);
+GKI_API extern void GKI_stop_timer (UINT8);
+GKI_API extern void GKI_timer_update(INT32);
+GKI_API extern UINT16 GKI_update_timer_list (TIMER_LIST_Q *, INT32);
+GKI_API extern UINT32 GKI_get_remaining_ticks (TIMER_LIST_Q *, TIMER_LIST_ENT *);
+GKI_API extern UINT16 GKI_wait(UINT16, UINT32);
+
+/* Start and Stop system time tick callback
+ * true for start system tick if time queue is not empty
+ * false to stop system tick if time queue is empty
+*/
+typedef void (SYSTEM_TICK_CBACK)(BOOLEAN);
+
+/* Time queue management for system ticks
+*/
+GKI_API extern BOOLEAN GKI_timer_queue_empty (void);
+GKI_API extern void GKI_timer_queue_register_callback(SYSTEM_TICK_CBACK *);
+
+/* Disable Interrupts, Enable Interrupts
+*/
+GKI_API extern void GKI_enable(void);
+GKI_API extern void GKI_disable(void);
+GKI_API extern void GKI_sched_lock(void);
+GKI_API extern void GKI_sched_unlock(void);
+
+/* Allocate (Free) memory from an OS
+*/
+GKI_API extern void *GKI_os_malloc (UINT32);
+GKI_API extern void GKI_os_free (void *);
+
+/* os timer operation */
+GKI_API extern UINT32 GKI_get_os_tick_count(void);
+
+/* Exception handling
+*/
+GKI_API extern void GKI_exception (UINT16, char *);
+
+#if GKI_DEBUG == TRUE
+GKI_API extern void GKI_PrintBufferUsage(UINT8 *p_num_pools, UINT16 *p_cur_used);
+GKI_API extern void GKI_PrintBuffer(void);
+GKI_API extern void GKI_print_task(void);
+#else
+#undef GKI_PrintBufferUsage
+#define GKI_PrintBuffer() NULL
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
diff --git a/gki/common/gki_buffer.c b/gki/common/gki_buffer.c
new file mode 100644
index 0000000..f474bab
--- /dev/null
+++ b/gki/common/gki_buffer.c
@@ -0,0 +1,1481 @@
+/******************************************************************************
+ *
+ * Copyright (C) 1999-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+#include "gki_int.h"
+#include <cutils/log.h>
+
+#if (GKI_NUM_TOTAL_BUF_POOLS > 16)
+#error Number of pools out of range (16 Max)!
+#endif
+
+static void gki_add_to_pool_list(UINT8 pool_id);
+static void gki_remove_from_pool_list(UINT8 pool_id);
+
+/*******************************************************************************
+**
+** Function gki_init_free_queue
+**
+** Description Internal function called at startup to initialize a free
+** queue. It is called once for each free queue.
+**
+** Returns void
+**
+*******************************************************************************/
+static void gki_init_free_queue (UINT8 id, UINT16 size, UINT16 total, void *p_mem)
+{
+ UINT16 i;
+ UINT16 act_size;
+ BUFFER_HDR_T *hdr;
+ BUFFER_HDR_T *hdr1 = NULL;
+ UINT32 *magic;
+ INT32 tempsize = size;
+ tGKI_COM_CB *p_cb = &gki_cb.com;
+
+ /* Ensure an even number of longwords */
+ tempsize = (INT32)ALIGN_POOL(size);
+ act_size = (UINT16)(tempsize + BUFFER_PADDING_SIZE);
+
+ /* Remember pool start and end addresses */
+// btla-specific ++
+ if(p_mem)
+ {
+ p_cb->pool_start[id] = (UINT8 *)p_mem;
+ p_cb->pool_end[id] = (UINT8 *)p_mem + (act_size * total);
+ }
+// btla-specific --
+
+ p_cb->pool_size[id] = act_size;
+
+ p_cb->freeq[id].size = (UINT16) tempsize;
+ p_cb->freeq[id].total = total;
+ p_cb->freeq[id].cur_cnt = 0;
+ p_cb->freeq[id].max_cnt = 0;
+
+ /* Initialize index table */
+// btla-specific ++
+ if(p_mem)
+ {
+ hdr = (BUFFER_HDR_T *)p_mem;
+ p_cb->freeq[id].p_first = hdr;
+ for (i = 0; i < total; i++)
+ {
+ hdr->task_id = GKI_INVALID_TASK;
+ hdr->q_id = id;
+ hdr->status = BUF_STATUS_FREE;
+ magic = (UINT32 *)((UINT8 *)hdr + BUFFER_HDR_SIZE + tempsize);
+ *magic = MAGIC_NO;
+ hdr1 = hdr;
+ hdr = (BUFFER_HDR_T *)((UINT8 *)hdr + act_size);
+ hdr1->p_next = hdr;
+ }
+ hdr1->p_next = NULL;
+ p_cb->freeq[id].p_last = hdr1;
+ }
+// btla-specific --
+ return;
+}
+
+// btla-specific ++
+#ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS
+static BOOLEAN gki_alloc_free_queue(UINT8 id)
+{
+ FREE_QUEUE_T *Q;
+ tGKI_COM_CB *p_cb = &gki_cb.com;
+ GKI_TRACE("\ngki_alloc_free_queue in, id:%d \n", (int)id );
+
+ Q = &p_cb->freeq[p_cb->pool_list[id]];
+
+ if(Q->p_first == 0)
+ {
+ void* p_mem = GKI_os_malloc((Q->size + BUFFER_PADDING_SIZE) * Q->total);
+ if(p_mem)
+ {
+ //re-initialize the queue with allocated memory
+ GKI_TRACE("\ngki_alloc_free_queue calling gki_init_free_queue, id:%d size:%d, totol:%d\n", id, Q->size, Q->total);
+ gki_init_free_queue(id, Q->size, Q->total, p_mem);
+ GKI_TRACE("\ngki_alloc_free_queue ret OK, id:%d size:%d, totol:%d\n", id, Q->size, Q->total);
+ return TRUE;
+ }
+ GKI_exception (GKI_ERROR_BUF_SIZE_TOOBIG, "gki_alloc_free_queue: Not enough memory");
+ }
+ GKI_TRACE("\ngki_alloc_free_queue out failed, id:%d\n", id);
+ return FALSE;
+}
+
+void gki_dealloc_free_queue(void)
+{
+ UINT8 i;
+ tGKI_COM_CB *p_cb = &gki_cb.com;
+
+ for (i=0; i < p_cb->curr_total_no_of_pools; i++)
+ {
+ if ( 0 < p_cb->freeq[i].max_cnt )
+ {
+ GKI_os_free(p_cb->pool_start[i]);
+
+ p_cb->freeq[i].cur_cnt = 0;
+ p_cb->freeq[i].max_cnt = 0;
+ p_cb->freeq[i].p_first = NULL;
+ p_cb->freeq[i].p_last = NULL;
+
+ p_cb->pool_start[i] = NULL;
+ p_cb->pool_end[i] = NULL;
+ p_cb->pool_size[i] = 0;
+ }
+ }
+}
+
+#endif
+// btla-specific --
+
+/*******************************************************************************
+**
+** Function gki_buffer_init
+**
+** Description Called once internally by GKI at startup to initialize all
+** buffers and free buffer pools.
+**
+** Returns void
+**
+*******************************************************************************/
+void gki_buffer_init(void)
+{
+ UINT8 i, tt, mb;
+ tGKI_COM_CB *p_cb = &gki_cb.com;
+
+ /* Initialize mailboxes */
+ for (tt = 0; tt < GKI_MAX_TASKS; tt++)
+ {
+ for (mb = 0; mb < NUM_TASK_MBOX; mb++)
+ {
+ p_cb->OSTaskQFirst[tt][mb] = NULL;
+ p_cb->OSTaskQLast [tt][mb] = NULL;
+ }
+ }
+
+ for (tt = 0; tt < GKI_NUM_TOTAL_BUF_POOLS; tt++)
+ {
+ p_cb->pool_start[tt] = NULL;
+ p_cb->pool_end[tt] = NULL;
+ p_cb->pool_size[tt] = 0;
+
+ p_cb->freeq[tt].p_first = 0;
+ p_cb->freeq[tt].p_last = 0;
+ p_cb->freeq[tt].size = 0;
+ p_cb->freeq[tt].total = 0;
+ p_cb->freeq[tt].cur_cnt = 0;
+ p_cb->freeq[tt].max_cnt = 0;
+ }
+
+ /* Use default from target.h */
+ p_cb->pool_access_mask = GKI_DEF_BUFPOOL_PERM_MASK;
+
+// btla-specific ++
+#if (!defined GKI_USE_DEFERED_ALLOC_BUF_POOLS && (GKI_USE_DYNAMIC_BUFFERS == TRUE))
+// btla-specific --
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 0)
+ p_cb->bufpool0 = (UINT8 *)GKI_os_malloc ((GKI_BUF0_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF0_MAX);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 1)
+ p_cb->bufpool1 = (UINT8 *)GKI_os_malloc ((GKI_BUF1_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF1_MAX);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 2)
+ p_cb->bufpool2 = (UINT8 *)GKI_os_malloc ((GKI_BUF2_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF2_MAX);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 3)
+ p_cb->bufpool3 = (UINT8 *)GKI_os_malloc ((GKI_BUF3_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF3_MAX);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 4)
+ p_cb->bufpool4 = (UINT8 *)GKI_os_malloc ((GKI_BUF4_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF4_MAX);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 5)
+ p_cb->bufpool5 = (UINT8 *)GKI_os_malloc ((GKI_BUF5_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF5_MAX);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 6)
+ p_cb->bufpool6 = (UINT8 *)GKI_os_malloc ((GKI_BUF6_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF6_MAX);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 7)
+ p_cb->bufpool7 = (UINT8 *)GKI_os_malloc ((GKI_BUF7_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF7_MAX);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 8)
+ p_cb->bufpool8 = (UINT8 *)GKI_os_malloc ((GKI_BUF8_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF8_MAX);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 9)
+ p_cb->bufpool9 = (UINT8 *)GKI_os_malloc ((GKI_BUF9_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF9_MAX);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 10)
+ p_cb->bufpool10 = (UINT8 *)GKI_os_malloc ((GKI_BUF10_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF10_MAX);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 11)
+ p_cb->bufpool11 = (UINT8 *)GKI_os_malloc ((GKI_BUF11_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF11_MAX);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 12)
+ p_cb->bufpool12 = (UINT8 *)GKI_os_malloc ((GKI_BUF12_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF12_MAX);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 13)
+ p_cb->bufpool13 = (UINT8 *)GKI_os_malloc ((GKI_BUF13_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF13_MAX);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 14)
+ p_cb->bufpool14 = (UINT8 *)GKI_os_malloc ((GKI_BUF14_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF14_MAX);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 15)
+ p_cb->bufpool15 = (UINT8 *)GKI_os_malloc ((GKI_BUF15_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF15_MAX);
+#endif
+
+#endif
+
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 0)
+ gki_init_free_queue(0, GKI_BUF0_SIZE, GKI_BUF0_MAX, p_cb->bufpool0);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 1)
+ gki_init_free_queue(1, GKI_BUF1_SIZE, GKI_BUF1_MAX, p_cb->bufpool1);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 2)
+ gki_init_free_queue(2, GKI_BUF2_SIZE, GKI_BUF2_MAX, p_cb->bufpool2);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 3)
+ gki_init_free_queue(3, GKI_BUF3_SIZE, GKI_BUF3_MAX, p_cb->bufpool3);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 4)
+ gki_init_free_queue(4, GKI_BUF4_SIZE, GKI_BUF4_MAX, p_cb->bufpool4);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 5)
+ gki_init_free_queue(5, GKI_BUF5_SIZE, GKI_BUF5_MAX, p_cb->bufpool5);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 6)
+ gki_init_free_queue(6, GKI_BUF6_SIZE, GKI_BUF6_MAX, p_cb->bufpool6);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 7)
+ gki_init_free_queue(7, GKI_BUF7_SIZE, GKI_BUF7_MAX, p_cb->bufpool7);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 8)
+ gki_init_free_queue(8, GKI_BUF8_SIZE, GKI_BUF8_MAX, p_cb->bufpool8);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 9)
+ gki_init_free_queue(9, GKI_BUF9_SIZE, GKI_BUF9_MAX, p_cb->bufpool9);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 10)
+ gki_init_free_queue(10, GKI_BUF10_SIZE, GKI_BUF10_MAX, p_cb->bufpool10);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 11)
+ gki_init_free_queue(11, GKI_BUF11_SIZE, GKI_BUF11_MAX, p_cb->bufpool11);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 12)
+ gki_init_free_queue(12, GKI_BUF12_SIZE, GKI_BUF12_MAX, p_cb->bufpool12);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 13)
+ gki_init_free_queue(13, GKI_BUF13_SIZE, GKI_BUF13_MAX, p_cb->bufpool13);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 14)
+ gki_init_free_queue(14, GKI_BUF14_SIZE, GKI_BUF14_MAX, p_cb->bufpool14);
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 15)
+ gki_init_free_queue(15, GKI_BUF15_SIZE, GKI_BUF15_MAX, p_cb->bufpool15);
+#endif
+
+ /* add pools to the pool_list which is arranged in the order of size */
+ for(i=0; i < GKI_NUM_FIXED_BUF_POOLS ; i++)
+ {
+ p_cb->pool_list[i] = i;
+ }
+
+ p_cb->curr_total_no_of_pools = GKI_NUM_FIXED_BUF_POOLS;
+
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_init_q
+**
+** Description Called by an application to initialize a buffer queue.
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_init_q (BUFFER_Q *p_q)
+{
+ p_q->p_first = p_q->p_last = NULL;
+ p_q->count = 0;
+
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_getbuf
+**
+** Description Called by an application to get a free buffer which
+** is of size greater or equal to the requested size.
+**
+** Note: This routine only takes buffers from public pools.
+** It will not use any buffers from pools
+** marked GKI_RESTRICTED_POOL.
+**
+** Parameters size - (input) number of bytes needed.
+**
+** Returns A pointer to the buffer, or NULL if none available
+**
+*******************************************************************************/
+void *GKI_getbuf (UINT16 size)
+{
+ UINT8 i;
+ FREE_QUEUE_T *Q;
+ BUFFER_HDR_T *p_hdr;
+ tGKI_COM_CB *p_cb = &gki_cb.com;
+
+ if (size == 0)
+ {
+ GKI_exception (GKI_ERROR_BUF_SIZE_ZERO, "getbuf: Size is zero");
+ return (NULL);
+ }
+
+ /* Find the first buffer pool that is public that can hold the desired size */
+ for (i=0; i < p_cb->curr_total_no_of_pools; i++)
+ {
+ if ( size <= p_cb->freeq[p_cb->pool_list[i]].size )
+ break;
+ }
+
+ if(i == p_cb->curr_total_no_of_pools)
+ {
+ GKI_exception (GKI_ERROR_BUF_SIZE_TOOBIG, "getbuf: Size is too big");
+ return (NULL);
+ }
+
+ /* Make sure the buffers aren't disturbed til finished with allocation */
+ GKI_disable();
+
+ /* search the public buffer pools that are big enough to hold the size
+ * until a free buffer is found */
+ for ( ; i < p_cb->curr_total_no_of_pools; i++)
+ {
+ /* Only look at PUBLIC buffer pools (bypass RESTRICTED pools) */
+ if (((UINT16)1 << p_cb->pool_list[i]) & p_cb->pool_access_mask)
+ continue;
+
+ Q = &p_cb->freeq[p_cb->pool_list[i]];
+ if(Q->cur_cnt < Q->total)
+ {
+// btla-specific ++
+ #ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS
+ if(Q->p_first == 0 && gki_alloc_free_queue(i) != TRUE)
+ return NULL;
+ #endif
+// btla-specific --
+ p_hdr = Q->p_first;
+ Q->p_first = p_hdr->p_next;
+
+ if (!Q->p_first)
+ Q->p_last = NULL;
+
+ if(++Q->cur_cnt > Q->max_cnt)
+ Q->max_cnt = Q->cur_cnt;
+
+ GKI_enable();
+
+ p_hdr->task_id = GKI_get_taskid();
+
+ p_hdr->status = BUF_STATUS_UNLINKED;
+ p_hdr->p_next = NULL;
+ p_hdr->Type = 0;
+
+ return ((void *) ((UINT8 *)p_hdr + BUFFER_HDR_SIZE));
+ }
+ }
+
+ GKI_enable();
+
+ return (NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_getpoolbuf
+**
+** Description Called by an application to get a free buffer from
+** a specific buffer pool.
+**
+** Note: If there are no more buffers available from the pool,
+** the public buffers are searched for an available buffer.
+**
+** Parameters pool_id - (input) pool ID to get a buffer out of.
+**
+** Returns A pointer to the buffer, or NULL if none available
+**
+*******************************************************************************/
+void *GKI_getpoolbuf (UINT8 pool_id)
+{
+ FREE_QUEUE_T *Q;
+ BUFFER_HDR_T *p_hdr;
+ tGKI_COM_CB *p_cb = &gki_cb.com;
+
+ if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
+ return (NULL);
+
+ /* Make sure the buffers aren't disturbed til finished with allocation */
+ GKI_disable();
+
+ Q = &p_cb->freeq[pool_id];
+ if(Q->cur_cnt < Q->total)
+ {
+// btla-specific ++
+#ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS
+ if(Q->p_first == 0 && gki_alloc_free_queue(pool_id) != TRUE)
+ return NULL;
+#endif
+// btla-specific --
+ p_hdr = Q->p_first;
+ Q->p_first = p_hdr->p_next;
+
+ if (!Q->p_first)
+ Q->p_last = NULL;
+
+ if(++Q->cur_cnt > Q->max_cnt)
+ Q->max_cnt = Q->cur_cnt;
+
+ GKI_enable();
+
+
+ p_hdr->task_id = GKI_get_taskid();
+
+ p_hdr->status = BUF_STATUS_UNLINKED;
+ p_hdr->p_next = NULL;
+ p_hdr->Type = 0;
+
+ return ((void *) ((UINT8 *)p_hdr + BUFFER_HDR_SIZE));
+ }
+
+ /* If here, no buffers in the specified pool */
+ GKI_enable();
+
+ /* try for free buffers in public pools */
+ return (GKI_getbuf(p_cb->freeq[pool_id].size));
+
+}
+
+/*******************************************************************************
+**
+** Function GKI_freebuf
+**
+** Description Called by an application to return a buffer to the free pool.
+**
+** Parameters p_buf - (input) address of the beginning of a buffer.
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_freebuf (void *p_buf)
+{
+ FREE_QUEUE_T *Q;
+ BUFFER_HDR_T *p_hdr;
+
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ if (!p_buf || gki_chk_buf_damage(p_buf))
+ {
+ GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Free - Buf Corrupted");
+ return;
+ }
+#endif
+
+ p_hdr = (BUFFER_HDR_T *) ((UINT8 *)p_buf - BUFFER_HDR_SIZE);
+
+ if (p_hdr->status != BUF_STATUS_UNLINKED)
+ {
+ GKI_exception(GKI_ERROR_FREEBUF_BUF_LINKED, "Freeing Linked Buf");
+ return;
+ }
+
+ if (p_hdr->q_id >= GKI_NUM_TOTAL_BUF_POOLS)
+ {
+ GKI_exception(GKI_ERROR_FREEBUF_BAD_QID, "Bad Buf QId");
+ return;
+ }
+
+ GKI_disable();
+
+ /*
+ ** Release the buffer
+ */
+ Q = &gki_cb.com.freeq[p_hdr->q_id];
+ if (Q->p_last)
+ Q->p_last->p_next = p_hdr;
+ else
+ Q->p_first = p_hdr;
+
+ Q->p_last = p_hdr;
+ p_hdr->p_next = NULL;
+ p_hdr->status = BUF_STATUS_FREE;
+ p_hdr->task_id = GKI_INVALID_TASK;
+ if (Q->cur_cnt > 0)
+ Q->cur_cnt--;
+
+ GKI_enable();
+
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_get_buf_size
+**
+** Description Called by an application to get the size of a buffer.
+**
+** Parameters p_buf - (input) address of the beginning of a buffer.
+**
+** Returns the size of the buffer
+**
+*******************************************************************************/
+UINT16 GKI_get_buf_size (void *p_buf)
+{
+ BUFFER_HDR_T *p_hdr;
+
+ p_hdr = (BUFFER_HDR_T *)((UINT8 *) p_buf - BUFFER_HDR_SIZE);
+
+ if ((UINT32)p_hdr & 1)
+ return (0);
+
+ if (p_hdr->q_id < GKI_NUM_TOTAL_BUF_POOLS)
+ {
+ return (gki_cb.com.freeq[p_hdr->q_id].size);
+ }
+
+ return (0);
+}
+
+/*******************************************************************************
+**
+** Function gki_chk_buf_damage
+**
+** Description Called internally by OSS to check for buffer corruption.
+**
+** Returns TRUE if there is a problem, else FALSE
+**
+*******************************************************************************/
+BOOLEAN gki_chk_buf_damage(void *p_buf)
+{
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+
+ UINT32 *magic;
+ magic = (UINT32 *)((UINT8 *) p_buf + GKI_get_buf_size(p_buf));
+
+ if ((UINT32)magic & 1)
+ return (TRUE);
+
+ if (*magic == MAGIC_NO)
+ return (FALSE);
+
+ return (TRUE);
+
+#else
+
+ return (FALSE);
+
+#endif
+}
+
+/*******************************************************************************
+**
+** Function GKI_send_msg
+**
+** Description Called by applications to send a buffer to a task
+**
+** Returns Nothing
+**
+*******************************************************************************/
+void GKI_send_msg (UINT8 task_id, UINT8 mbox, void *msg)
+{
+ BUFFER_HDR_T *p_hdr;
+ tGKI_COM_CB *p_cb = &gki_cb.com;
+
+ /* If task non-existant or not started, drop buffer */
+ if ((task_id >= GKI_MAX_TASKS) || (mbox >= NUM_TASK_MBOX) || (p_cb->OSRdyTbl[task_id] == TASK_DEAD))
+ {
+ GKI_exception(GKI_ERROR_SEND_MSG_BAD_DEST, "Sending to unknown dest");
+ GKI_freebuf (msg);
+ return;
+ }
+
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ if (gki_chk_buf_damage(msg))
+ {
+ GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Send - Buffer corrupted");
+ return;
+ }
+#endif
+
+ p_hdr = (BUFFER_HDR_T *) ((UINT8 *) msg - BUFFER_HDR_SIZE);
+
+ if (p_hdr->status != BUF_STATUS_UNLINKED)
+ {
+ GKI_exception(GKI_ERROR_SEND_MSG_BUF_LINKED, "Send - buffer linked");
+ return;
+ }
+
+ GKI_disable();
+
+ if (p_cb->OSTaskQFirst[task_id][mbox])
+ p_cb->OSTaskQLast[task_id][mbox]->p_next = p_hdr;
+ else
+ p_cb->OSTaskQFirst[task_id][mbox] = p_hdr;
+
+ p_cb->OSTaskQLast[task_id][mbox] = p_hdr;
+
+ p_hdr->p_next = NULL;
+ p_hdr->status = BUF_STATUS_QUEUED;
+ p_hdr->task_id = task_id;
+
+
+ GKI_enable();
+
+ GKI_send_event(task_id, (UINT16)EVENT_MASK(mbox));
+
+ return;
+}
+
+/*******************************************************************************
+**
+** Function GKI_read_mbox
+**
+** Description Called by applications to read a buffer from one of
+** the task mailboxes. A task can only read its own mailbox.
+**
+** Parameters: mbox - (input) mailbox ID to read (0, 1, 2, or 3)
+**
+** Returns NULL if the mailbox was empty, else the address of a buffer
+**
+*******************************************************************************/
+void *GKI_read_mbox (UINT8 mbox)
+{
+ UINT8 task_id = GKI_get_taskid();
+ void *p_buf = NULL;
+ BUFFER_HDR_T *p_hdr;
+
+ if ((task_id >= GKI_MAX_TASKS) || (mbox >= NUM_TASK_MBOX))
+ return (NULL);
+
+ GKI_disable();
+
+ if (gki_cb.com.OSTaskQFirst[task_id][mbox])
+ {
+ p_hdr = gki_cb.com.OSTaskQFirst[task_id][mbox];
+ gki_cb.com.OSTaskQFirst[task_id][mbox] = p_hdr->p_next;
+
+ p_hdr->p_next = NULL;
+ p_hdr->status = BUF_STATUS_UNLINKED;
+
+ p_buf = (UINT8 *)p_hdr + BUFFER_HDR_SIZE;
+ }
+
+ GKI_enable();
+
+ return (p_buf);
+}
+
+
+
+/*******************************************************************************
+**
+** Function GKI_enqueue
+**
+** Description Enqueue a buffer at the tail of the queue
+**
+** Parameters: p_q - (input) pointer to a queue.
+** p_buf - (input) address of the buffer to enqueue
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_enqueue (BUFFER_Q *p_q, void *p_buf)
+{
+ BUFFER_HDR_T *p_hdr;
+
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ if (gki_chk_buf_damage(p_buf))
+ {
+ GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Enqueue - Buffer corrupted");
+ return;
+ }
+#endif
+
+ p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
+
+ if (p_hdr->status != BUF_STATUS_UNLINKED)
+ {
+ GKI_exception(GKI_ERROR_ENQUEUE_BUF_LINKED, "Eneueue - buf already linked");
+ return;
+ }
+
+ GKI_disable();
+
+ /* Since the queue is exposed (C vs C++), keep the pointers in exposed format */
+ if (p_q->p_last)
+ {
+ BUFFER_HDR_T *p_last_hdr = (BUFFER_HDR_T *)((UINT8 *)p_q->p_last - BUFFER_HDR_SIZE);
+ p_last_hdr->p_next = p_hdr;
+ }
+ else
+ p_q->p_first = p_buf;
+
+ p_q->p_last = p_buf;
+ p_q->count++;
+
+ p_hdr->p_next = NULL;
+ p_hdr->status = BUF_STATUS_QUEUED;
+
+ GKI_enable();
+
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_enqueue_head
+**
+** Description Enqueue a buffer at the head of the queue
+**
+** Parameters: p_q - (input) pointer to a queue.
+** p_buf - (input) address of the buffer to enqueue
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_enqueue_head (BUFFER_Q *p_q, void *p_buf)
+{
+ BUFFER_HDR_T *p_hdr;
+
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ if (gki_chk_buf_damage(p_buf))
+ {
+ GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Enqueue - Buffer corrupted");
+ return;
+ }
+#endif
+
+ p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
+
+ if (p_hdr->status != BUF_STATUS_UNLINKED)
+ {
+ GKI_exception(GKI_ERROR_ENQUEUE_BUF_LINKED, "Eneueue head - buf already linked");
+ return;
+ }
+
+ GKI_disable();
+
+ if (p_q->p_first)
+ {
+ p_hdr->p_next = (BUFFER_HDR_T *)((UINT8 *)p_q->p_first - BUFFER_HDR_SIZE);
+ p_q->p_first = p_buf;
+ }
+ else
+ {
+ p_q->p_first = p_buf;
+ p_q->p_last = p_buf;
+ p_hdr->p_next = NULL;
+ }
+ p_q->count++;
+
+ p_hdr->status = BUF_STATUS_QUEUED;
+
+ GKI_enable();
+
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_dequeue
+**
+** Description Dequeues a buffer from the head of a queue
+**
+** Parameters: p_q - (input) pointer to a queue.
+**
+** Returns NULL if queue is empty, else buffer
+**
+*******************************************************************************/
+void *GKI_dequeue (BUFFER_Q *p_q)
+{
+ BUFFER_HDR_T *p_hdr;
+
+ GKI_disable();
+
+ if (!p_q || !p_q->count)
+ {
+ GKI_enable();
+ return (NULL);
+ }
+
+ p_hdr = (BUFFER_HDR_T *)((UINT8 *)p_q->p_first - BUFFER_HDR_SIZE);
+
+ /* Keep buffers such that GKI header is invisible
+ */
+ if (p_hdr->p_next)
+ p_q->p_first = ((UINT8 *)p_hdr->p_next + BUFFER_HDR_SIZE);
+ else
+ {
+ p_q->p_first = NULL;
+ p_q->p_last = NULL;
+ }
+
+ p_q->count--;
+
+ p_hdr->p_next = NULL;
+ p_hdr->status = BUF_STATUS_UNLINKED;
+
+ GKI_enable();
+
+ return ((UINT8 *)p_hdr + BUFFER_HDR_SIZE);
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_remove_from_queue
+**
+** Description Dequeue a buffer from the middle of the queue
+**
+** Parameters: p_q - (input) pointer to a queue.
+** p_buf - (input) address of the buffer to enqueue
+**
+** Returns NULL if queue is empty, else buffer
+**
+*******************************************************************************/
+void *GKI_remove_from_queue (BUFFER_Q *p_q, void *p_buf)
+{
+ BUFFER_HDR_T *p_prev;
+ BUFFER_HDR_T *p_buf_hdr;
+
+ GKI_disable();
+
+ if (p_buf == p_q->p_first)
+ {
+ GKI_enable();
+ return (GKI_dequeue (p_q));
+ }
+
+ p_buf_hdr = (BUFFER_HDR_T *)((UINT8 *)p_buf - BUFFER_HDR_SIZE);
+ p_prev = (BUFFER_HDR_T *)((UINT8 *)p_q->p_first - BUFFER_HDR_SIZE);
+
+ for ( ; p_prev; p_prev = p_prev->p_next)
+ {
+ /* If the previous points to this one, move the pointers around */
+ if (p_prev->p_next == p_buf_hdr)
+ {
+ p_prev->p_next = p_buf_hdr->p_next;
+
+ /* If we are removing the last guy in the queue, update p_last */
+ if (p_buf == p_q->p_last)
+ p_q->p_last = p_prev + 1;
+
+ /* One less in the queue */
+ p_q->count--;
+
+ /* The buffer is now unlinked */
+ p_buf_hdr->p_next = NULL;
+ p_buf_hdr->status = BUF_STATUS_UNLINKED;
+
+ GKI_enable();
+ return (p_buf);
+ }
+ }
+
+ GKI_enable();
+ return (NULL);
+}
+
+/*******************************************************************************
+**
+** Function GKI_getfirst
+**
+** Description Return a pointer to the first buffer in a queue
+**
+** Parameters: p_q - (input) pointer to a queue.
+**
+** Returns NULL if queue is empty, else buffer address
+**
+*******************************************************************************/
+void *GKI_getfirst (BUFFER_Q *p_q)
+{
+ return (p_q->p_first);
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_getlast
+**
+** Description Return a pointer to the last buffer in a queue
+**
+** Parameters: p_q - (input) pointer to a queue.
+**
+** Returns NULL if queue is empty, else buffer address
+**
+*******************************************************************************/
+void *GKI_getlast (BUFFER_Q *p_q)
+{
+ return (p_q->p_last);
+}
+
+/*******************************************************************************
+**
+** Function GKI_getnext
+**
+** Description Return a pointer to the next buffer in a queue
+**
+** Parameters: p_buf - (input) pointer to the buffer to find the next one from.
+**
+** Returns NULL if no more buffers in the queue, else next buffer address
+**
+*******************************************************************************/
+void *GKI_getnext (void *p_buf)
+{
+ BUFFER_HDR_T *p_hdr;
+
+ p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
+
+ if (p_hdr->p_next)
+ return ((UINT8 *)p_hdr->p_next + BUFFER_HDR_SIZE);
+ else
+ return (NULL);
+}
+
+
+
+/*******************************************************************************
+**
+** Function GKI_queue_is_empty
+**
+** Description Check the status of a queue.
+**
+** Parameters: p_q - (input) pointer to a queue.
+**
+** Returns TRUE if queue is empty, else FALSE
+**
+*******************************************************************************/
+BOOLEAN GKI_queue_is_empty(BUFFER_Q *p_q)
+{
+ return ((BOOLEAN) (p_q->count == 0));
+}
+
+/*******************************************************************************
+**
+** Function GKI_find_buf_start
+**
+** Description This function is called with an address inside a buffer,
+** and returns the start address ofthe buffer.
+**
+** The buffer should be one allocated from one of GKI's pools.
+**
+** Parameters: p_user_area - (input) address of anywhere in a GKI buffer.
+**
+** Returns void * - Address of the beginning of the specified buffer if successful,
+** otherwise NULL if unsuccessful
+**
+*******************************************************************************/
+void *GKI_find_buf_start (void *p_user_area)
+{
+ UINT16 xx, size;
+ UINT32 yy;
+ tGKI_COM_CB *p_cb = &gki_cb.com;
+ UINT8 *p_ua = (UINT8 *)p_user_area;
+
+ for (xx = 0; xx < GKI_NUM_TOTAL_BUF_POOLS; xx++)
+ {
+ if ((p_ua > p_cb->pool_start[xx]) && (p_ua < p_cb->pool_end[xx]))
+ {
+ yy = (UINT32)(p_ua - p_cb->pool_start[xx]);
+
+ size = p_cb->pool_size[xx];
+
+ yy = (yy / size) * size;
+
+ return ((void *) (p_cb->pool_start[xx] + yy + sizeof(BUFFER_HDR_T)) );
+ }
+ }
+
+ /* If here, invalid address - not in one of our buffers */
+ GKI_exception (GKI_ERROR_BUF_SIZE_ZERO, "GKI_get_buf_start:: bad addr");
+
+ return (NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_set_pool_permission
+**
+** Description This function is called to set or change the permissions for
+** the specified pool ID.
+**
+** Parameters pool_id - (input) pool ID to be set or changed
+** permission - (input) GKI_PUBLIC_POOL or GKI_RESTRICTED_POOL
+**
+** Returns GKI_SUCCESS if successful
+** GKI_INVALID_POOL if unsuccessful
+**
+*******************************************************************************/
+UINT8 GKI_set_pool_permission(UINT8 pool_id, UINT8 permission)
+{
+ tGKI_COM_CB *p_cb = &gki_cb.com;
+
+ if (pool_id < GKI_NUM_TOTAL_BUF_POOLS)
+ {
+ if (permission == GKI_RESTRICTED_POOL)
+ p_cb->pool_access_mask = (UINT16)(p_cb->pool_access_mask | (1 << pool_id));
+
+ else /* mark the pool as public */
+ p_cb->pool_access_mask = (UINT16)(p_cb->pool_access_mask & ~(1 << pool_id));
+
+ return (GKI_SUCCESS);
+ }
+ else
+ return (GKI_INVALID_POOL);
+}
+
+/*******************************************************************************
+**
+** Function gki_add_to_pool_list
+**
+** Description Adds pool to the pool list which is arranged in the
+** order of size
+**
+** Returns void
+**
+*******************************************************************************/
+static void gki_add_to_pool_list(UINT8 pool_id)
+{
+
+ INT32 i, j;
+ tGKI_COM_CB *p_cb = &gki_cb.com;
+
+ /* Find the position where the specified pool should be inserted into the list */
+ for(i=0; i < p_cb->curr_total_no_of_pools; i++)
+ {
+
+ if(p_cb->freeq[pool_id].size <= p_cb->freeq[ p_cb->pool_list[i] ].size)
+ break;
+ }
+
+ /* Insert the new buffer pool ID into the list of pools */
+ for(j = p_cb->curr_total_no_of_pools; j > i; j--)
+ {
+ p_cb->pool_list[j] = p_cb->pool_list[j-1];
+ }
+
+ p_cb->pool_list[i] = pool_id;
+
+ return;
+}
+
+/*******************************************************************************
+**
+** Function gki_remove_from_pool_list
+**
+** Description Removes pool from the pool list. Called when a pool is deleted
+**
+** Returns void
+**
+*******************************************************************************/
+static void gki_remove_from_pool_list(UINT8 pool_id)
+{
+ tGKI_COM_CB *p_cb = &gki_cb.com;
+ UINT8 i;
+
+ for(i=0; i < p_cb->curr_total_no_of_pools; i++)
+ {
+ if(pool_id == p_cb->pool_list[i])
+ break;
+ }
+
+ while (i < (p_cb->curr_total_no_of_pools - 1))
+ {
+ p_cb->pool_list[i] = p_cb->pool_list[i+1];
+ i++;
+ }
+
+ return;
+}
+
+/*******************************************************************************
+**
+** Function GKI_igetpoolbuf
+**
+** Description Called by an interrupt service routine to get a free buffer from
+** a specific buffer pool.
+**
+** Parameters pool_id - (input) pool ID to get a buffer out of.
+**
+** Returns A pointer to the buffer, or NULL if none available
+**
+*******************************************************************************/
+void *GKI_igetpoolbuf (UINT8 pool_id)
+{
+ FREE_QUEUE_T *Q;
+ BUFFER_HDR_T *p_hdr;
+
+ if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
+ return (NULL);
+
+
+ Q = &gki_cb.com.freeq[pool_id];
+ if(Q->cur_cnt < Q->total)
+ {
+ p_hdr = Q->p_first;
+ Q->p_first = p_hdr->p_next;
+
+ if (!Q->p_first)
+ Q->p_last = NULL;
+
+ if(++Q->cur_cnt > Q->max_cnt)
+ Q->max_cnt = Q->cur_cnt;
+
+ p_hdr->task_id = GKI_get_taskid();
+
+ p_hdr->status = BUF_STATUS_UNLINKED;
+ p_hdr->p_next = NULL;
+ p_hdr->Type = 0;
+
+ return ((void *) ((UINT8 *)p_hdr + BUFFER_HDR_SIZE));
+ }
+
+ return (NULL);
+}
+
+/*******************************************************************************
+**
+** Function GKI_poolcount
+**
+** Description Called by an application to get the total number of buffers
+** in the specified buffer pool.
+**
+** Parameters pool_id - (input) pool ID to get the free count of.
+**
+** Returns the total number of buffers in the pool
+**
+*******************************************************************************/
+UINT16 GKI_poolcount (UINT8 pool_id)
+{
+ if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
+ return (0);
+
+ return (gki_cb.com.freeq[pool_id].total);
+}
+
+/*******************************************************************************
+**
+** Function GKI_poolfreecount
+**
+** Description Called by an application to get the number of free buffers
+** in the specified buffer pool.
+**
+** Parameters pool_id - (input) pool ID to get the free count of.
+**
+** Returns the number of free buffers in the pool
+**
+*******************************************************************************/
+UINT16 GKI_poolfreecount (UINT8 pool_id)
+{
+ FREE_QUEUE_T *Q;
+
+ if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
+ return (0);
+
+ Q = &gki_cb.com.freeq[pool_id];
+
+ return ((UINT16)(Q->total - Q->cur_cnt));
+}
+
+/*******************************************************************************
+**
+** Function GKI_change_buf_owner
+**
+** Description Called to change the task ownership of a buffer.
+**
+** Parameters: p_buf - (input) pointer to the buffer
+** task_id - (input) task id to change ownership to
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_change_buf_owner (void *p_buf, UINT8 task_id)
+{
+ BUFFER_HDR_T *p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
+
+ p_hdr->task_id = task_id;
+
+ return;
+}
+
+#if (defined(GKI_SEND_MSG_FROM_ISR) && GKI_SEND_MSG_FROM_ISR == TRUE)
+/*******************************************************************************
+**
+** Function GKI_isend_msg
+**
+** Description Called from interrupt context to send a buffer to a task
+**
+** Returns Nothing
+**
+*******************************************************************************/
+void GKI_isend_msg (UINT8 task_id, UINT8 mbox, void *msg)
+{
+ BUFFER_HDR_T *p_hdr;
+ tGKI_COM_CB *p_cb = &gki_cb.com;
+
+ /* If task non-existant or not started, drop buffer */
+ if ((task_id >= GKI_MAX_TASKS) || (mbox >= NUM_TASK_MBOX) || (p_cb->OSRdyTbl[task_id] == TASK_DEAD))
+ {
+ GKI_exception(GKI_ERROR_SEND_MSG_BAD_DEST, "Sending to unknown dest");
+ GKI_freebuf (msg);
+ return;
+ }
+
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ if (gki_chk_buf_damage(msg))
+ {
+ GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Send - Buffer corrupted");
+ return;
+ }
+#endif
+
+#if (GKI_ENABLE_OWNER_CHECK == TRUE)
+ if (gki_chk_buf_owner(msg))
+ {
+ GKI_exception(GKI_ERROR_NOT_BUF_OWNER, "Send by non-owner");
+ return;
+ }
+#endif
+
+ p_hdr = (BUFFER_HDR_T *) ((UINT8 *) msg - BUFFER_HDR_SIZE);
+
+ if (p_hdr->status != BUF_STATUS_UNLINKED)
+ {
+ GKI_exception(GKI_ERROR_SEND_MSG_BUF_LINKED, "Send - buffer linked");
+ return;
+ }
+
+ if (p_cb->OSTaskQFirst[task_id][mbox])
+ p_cb->OSTaskQLast[task_id][mbox]->p_next = p_hdr;
+ else
+ p_cb->OSTaskQFirst[task_id][mbox] = p_hdr;
+
+ p_cb->OSTaskQLast[task_id][mbox] = p_hdr;
+
+ p_hdr->p_next = NULL;
+ p_hdr->status = BUF_STATUS_QUEUED;
+ p_hdr->task_id = task_id;
+
+ GKI_isend_event(task_id, (UINT16)EVENT_MASK(mbox));
+
+ return;
+}
+#endif
+
+/*******************************************************************************
+**
+** Function GKI_create_pool
+**
+** Description Called by applications to create a buffer pool.
+**
+** Parameters: size - (input) length (in bytes) of each buffer in the pool
+** count - (input) number of buffers to allocate for the pool
+** permission - (input) restricted or public access?
+** (GKI_PUBLIC_POOL or GKI_RESTRICTED_POOL)
+** p_mem_pool - (input) pointer to an OS memory pool, NULL if not provided
+**
+** Returns the buffer pool ID, which should be used in calls to
+** GKI_getpoolbuf(). If a pool could not be created, this
+** function returns 0xff.
+**
+*******************************************************************************/
+UINT8 GKI_create_pool (UINT16 size, UINT16 count, UINT8 permission, void *p_mem_pool)
+{
+ UINT8 xx;
+ UINT32 mem_needed;
+ INT32 tempsize = size;
+ tGKI_COM_CB *p_cb = &gki_cb.com;
+
+ /* First make sure the size of each pool has a valid size with room for the header info */
+ if (size > MAX_USER_BUF_SIZE)
+ return (GKI_INVALID_POOL);
+
+ /* First, look for an unused pool */
+ for (xx = 0; xx < GKI_NUM_TOTAL_BUF_POOLS; xx++)
+ {
+ if (!p_cb->pool_start[xx])
+ break;
+ }
+
+ if (xx == GKI_NUM_TOTAL_BUF_POOLS)
+ return (GKI_INVALID_POOL);
+
+ /* Ensure an even number of longwords */
+ tempsize = (INT32)ALIGN_POOL(size);
+
+ mem_needed = (tempsize + BUFFER_PADDING_SIZE) * count;
+
+ if (!p_mem_pool)
+ p_mem_pool = GKI_os_malloc(mem_needed);
+
+ if (p_mem_pool)
+ {
+ /* Initialize the new pool */
+ gki_init_free_queue (xx, size, count, p_mem_pool);
+ gki_add_to_pool_list(xx);
+ (void) GKI_set_pool_permission (xx, permission);
+ p_cb->curr_total_no_of_pools++;
+
+ return (xx);
+ }
+ else
+ return (GKI_INVALID_POOL);
+}
+
+/*******************************************************************************
+**
+** Function GKI_delete_pool
+**
+** Description Called by applications to delete a buffer pool. The function
+** calls the operating specific function to free the actual memory.
+** An exception is generated if an error is detected.
+**
+** Parameters: pool_id - (input) Id of the poll being deleted.
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_delete_pool (UINT8 pool_id)
+{
+ FREE_QUEUE_T *Q;
+ tGKI_COM_CB *p_cb = &gki_cb.com;
+
+ if ((pool_id >= GKI_NUM_TOTAL_BUF_POOLS) || (!p_cb->pool_start[pool_id]))
+ return;
+
+ GKI_disable();
+ Q = &p_cb->freeq[pool_id];
+
+ if (!Q->cur_cnt)
+ {
+ Q->size = 0;
+ Q->total = 0;
+ Q->cur_cnt = 0;
+ Q->max_cnt = 0;
+ Q->p_first = NULL;
+ Q->p_last = NULL;
+
+ GKI_os_free (p_cb->pool_start[pool_id]);
+
+ p_cb->pool_start[pool_id] = NULL;
+ p_cb->pool_end[pool_id] = NULL;
+ p_cb->pool_size[pool_id] = 0;
+
+ gki_remove_from_pool_list(pool_id);
+ p_cb->curr_total_no_of_pools--;
+ }
+ else
+ GKI_exception(GKI_ERROR_DELETE_POOL_BAD_QID, "Deleting bad pool");
+
+ GKI_enable();
+
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_get_pool_bufsize
+**
+** Description Called by an application to get the size of buffers in a pool
+**
+** Parameters Pool ID.
+**
+** Returns the size of buffers in the pool
+**
+*******************************************************************************/
+UINT16 GKI_get_pool_bufsize (UINT8 pool_id)
+{
+ if (pool_id < GKI_NUM_TOTAL_BUF_POOLS)
+ return (gki_cb.com.freeq[pool_id].size);
+
+ return (0);
+}
+
+/*******************************************************************************
+**
+** Function GKI_poolutilization
+**
+** Description Called by an application to get the buffer utilization
+** in the specified buffer pool.
+**
+** Parameters pool_id - (input) pool ID to get the free count of.
+**
+** Returns % of buffers used from 0 to 100
+**
+*******************************************************************************/
+UINT16 GKI_poolutilization (UINT8 pool_id)
+{
+ FREE_QUEUE_T *Q;
+
+ if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
+ return (100);
+
+ Q = &gki_cb.com.freeq[pool_id];
+
+ if (Q->total == 0)
+ return (100);
+
+ return ((Q->cur_cnt * 100) / Q->total);
+}
+
diff --git a/gki/common/gki_common.h b/gki/common/gki_common.h
new file mode 100644
index 0000000..9bc5005
--- /dev/null
+++ b/gki/common/gki_common.h
@@ -0,0 +1,390 @@
+/******************************************************************************
+ *
+ * Copyright (C) 1999-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+#ifndef GKI_COMMON_H
+#define GKI_COMMON_H
+
+#include "gki.h"
+#include "dyn_mem.h"
+
+/* Task States: (For OSRdyTbl) */
+#define TASK_DEAD 0 /* b0000 */
+#define TASK_READY 1 /* b0001 */
+#define TASK_WAIT 2 /* b0010 */
+#define TASK_DELAY 4 /* b0100 */
+#define TASK_SUSPEND 8 /* b1000 */
+
+
+/********************************************************************
+** Internal Error codes
+*********************************************************************/
+#define GKI_ERROR_BUF_CORRUPTED 0xFFFF
+#define GKI_ERROR_NOT_BUF_OWNER 0xFFFE
+#define GKI_ERROR_FREEBUF_BAD_QID 0xFFFD
+#define GKI_ERROR_FREEBUF_BUF_LINKED 0xFFFC
+#define GKI_ERROR_SEND_MSG_BAD_DEST 0xFFFB
+#define GKI_ERROR_SEND_MSG_BUF_LINKED 0xFFFA
+#define GKI_ERROR_ENQUEUE_BUF_LINKED 0xFFF9
+#define GKI_ERROR_DELETE_POOL_BAD_QID 0xFFF8
+#define GKI_ERROR_BUF_SIZE_TOOBIG 0xFFF7
+#define GKI_ERROR_BUF_SIZE_ZERO 0xFFF6
+#define GKI_ERROR_ADDR_NOT_IN_BUF 0xFFF5
+
+
+/********************************************************************
+** Misc constants
+*********************************************************************/
+
+#define GKI_MAX_INT32 (0x7fffffffL)
+#define GKI_MAX_TIMESTAMP (0xffffffffL)
+
+/********************************************************************
+** Buffer Management Data Structures
+*********************************************************************/
+
+typedef struct _buffer_hdr
+{
+ struct _buffer_hdr *p_next; /* next buffer in the queue */
+ UINT8 q_id; /* id of the queue */
+ UINT8 task_id; /* task which allocated the buffer*/
+ UINT8 status; /* FREE, UNLINKED or QUEUED */
+ UINT8 Type;
+} BUFFER_HDR_T;
+
+typedef struct _free_queue
+{
+ BUFFER_HDR_T *p_first; /* first buffer in the queue */
+ BUFFER_HDR_T *p_last; /* last buffer in the queue */
+ UINT16 size; /* size of the buffers in the pool */
+ UINT16 total; /* toatal number of buffers */
+ UINT16 cur_cnt; /* number of buffers currently allocated */
+ UINT16 max_cnt; /* maximum number of buffers allocated at any time */
+} FREE_QUEUE_T;
+
+
+/* Buffer related defines
+*/
+#define ALIGN_POOL(pl_size) ( (((pl_size) + 3) / sizeof(UINT32)) * sizeof(UINT32))
+#define BUFFER_HDR_SIZE (sizeof(BUFFER_HDR_T)) /* Offset past header */
+#define BUFFER_PADDING_SIZE (sizeof(BUFFER_HDR_T) + sizeof(UINT32)) /* Header + Magic Number */
+#define MAX_USER_BUF_SIZE ((UINT16)0xffff - BUFFER_PADDING_SIZE) /* pool size must allow for header */
+#define MAGIC_NO 0xDDBADDBA
+
+#define BUF_STATUS_FREE 0
+#define BUF_STATUS_UNLINKED 1
+#define BUF_STATUS_QUEUED 2
+
+// btla-specific ++
+#define GKI_USE_DEFERED_ALLOC_BUF_POOLS
+// btla-specific --
+
+/* Exception related structures (Used in debug mode only)
+*/
+#if (GKI_DEBUG == TRUE)
+typedef struct
+{
+ UINT16 type;
+ UINT8 taskid;
+ UINT8 msg[GKI_MAX_EXCEPTION_MSGLEN];
+} EXCEPTION_T;
+#endif
+
+
+/* Put all GKI variables into one control block
+*/
+typedef struct
+{
+ /* Task management variables
+ */
+ /* The stack and stack size are not used on Windows
+ */
+// btla-specific ++
+#if (!defined GKI_USE_DEFERED_ALLOC_BUF_POOLS && (GKI_USE_DYNAMIC_BUFFERS == FALSE))
+// btla-specific --
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 0)
+ UINT8 bufpool0[(ALIGN_POOL(GKI_BUF0_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF0_MAX];
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 1)
+ UINT8 bufpool1[(ALIGN_POOL(GKI_BUF1_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF1_MAX];
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 2)
+ UINT8 bufpool2[(ALIGN_POOL(GKI_BUF2_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF2_MAX];
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 3)
+ UINT8 bufpool3[(ALIGN_POOL(GKI_BUF3_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF3_MAX];
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 4)
+ UINT8 bufpool4[(ALIGN_POOL(GKI_BUF4_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF4_MAX];
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 5)
+ UINT8 bufpool5[(ALIGN_POOL(GKI_BUF5_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF5_MAX];
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 6)
+ UINT8 bufpool6[(ALIGN_POOL(GKI_BUF6_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF6_MAX];
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 7)
+ UINT8 bufpool7[(ALIGN_POOL(GKI_BUF7_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF7_MAX];
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 8)
+ UINT8 bufpool8[(ALIGN_POOL(GKI_BUF8_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF8_MAX];
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 9)
+ UINT8 bufpool9[(ALIGN_POOL(GKI_BUF9_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF9_MAX];
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 10)
+ UINT8 bufpool10[(ALIGN_POOL(GKI_BUF10_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF10_MAX];
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 11)
+ UINT8 bufpool11[(ALIGN_POOL(GKI_BUF11_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF11_MAX];
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 12)
+ UINT8 bufpool12[(ALIGN_POOL(GKI_BUF12_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF12_MAX];
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 13)
+ UINT8 bufpool13[(ALIGN_POOL(GKI_BUF13_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF13_MAX];
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 14)
+ UINT8 bufpool14[(ALIGN_POOL(GKI_BUF14_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF14_MAX];
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 15)
+ UINT8 bufpool15[(ALIGN_POOL(GKI_BUF15_SIZE) + BUFFER_PADDING_SIZE) * GKI_BUF15_MAX];
+#endif
+
+#else
+/* Definitions for dynamic buffer use */
+#if (GKI_NUM_FIXED_BUF_POOLS > 0)
+ UINT8 *bufpool0;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 1)
+ UINT8 *bufpool1;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 2)
+ UINT8 *bufpool2;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 3)
+ UINT8 *bufpool3;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 4)
+ UINT8 *bufpool4;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 5)
+ UINT8 *bufpool5;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 6)
+ UINT8 *bufpool6;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 7)
+ UINT8 *bufpool7;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 8)
+ UINT8 *bufpool8;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 9)
+ UINT8 *bufpool9;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 10)
+ UINT8 *bufpool10;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 11)
+ UINT8 *bufpool11;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 12)
+ UINT8 *bufpool12;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 13)
+ UINT8 *bufpool13;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 14)
+ UINT8 *bufpool14;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 15)
+ UINT8 *bufpool15;
+#endif
+
+#endif
+
+ UINT8 *OSStack[GKI_MAX_TASKS]; /* pointer to beginning of stack */
+ UINT16 OSStackSize[GKI_MAX_TASKS]; /* stack size available to each task */
+
+
+ INT8 *OSTName[GKI_MAX_TASKS]; /* name of the task */
+
+ UINT8 OSRdyTbl[GKI_MAX_TASKS]; /* current state of the task */
+ UINT16 OSWaitEvt[GKI_MAX_TASKS]; /* events that have to be processed by the task */
+ UINT16 OSWaitForEvt[GKI_MAX_TASKS]; /* events the task is waiting for*/
+
+ UINT32 OSTicks; /* system ticks from start */
+ UINT32 OSIdleCnt; /* idle counter */
+ INT16 OSDisableNesting; /* counter to keep track of interrupt disable nesting */
+ INT16 OSLockNesting; /* counter to keep track of sched lock nesting */
+ INT16 OSIntNesting; /* counter to keep track of interrupt nesting */
+
+ /* Timer related variables
+ */
+ INT32 OSTicksTilExp; /* Number of ticks till next timer expires */
+#if (defined(GKI_DELAY_STOP_SYS_TICK) && (GKI_DELAY_STOP_SYS_TICK > 0))
+ UINT32 OSTicksTilStop; /* inactivity delay timer; OS Ticks till stopping system tick */
+#endif
+ INT32 OSNumOrigTicks; /* Number of ticks between last timer expiration to the next one */
+
+ INT32 OSWaitTmr [GKI_MAX_TASKS]; /* ticks the task has to wait, for specific events */
+
+ /* Only take up space timers used in the system (GKI_NUM_TIMERS defined in target.h) */
+#if (GKI_NUM_TIMERS > 0)
+ INT32 OSTaskTmr0 [GKI_MAX_TASKS];
+ INT32 OSTaskTmr0R [GKI_MAX_TASKS];
+#endif
+
+#if (GKI_NUM_TIMERS > 1)
+ INT32 OSTaskTmr1 [GKI_MAX_TASKS];
+ INT32 OSTaskTmr1R [GKI_MAX_TASKS];
+#endif
+
+#if (GKI_NUM_TIMERS > 2)
+ INT32 OSTaskTmr2 [GKI_MAX_TASKS];
+ INT32 OSTaskTmr2R [GKI_MAX_TASKS];
+#endif
+
+#if (GKI_NUM_TIMERS > 3)
+ INT32 OSTaskTmr3 [GKI_MAX_TASKS];
+ INT32 OSTaskTmr3R [GKI_MAX_TASKS];
+#endif
+
+
+
+ /* Buffer related variables
+ */
+ BUFFER_HDR_T *OSTaskQFirst[GKI_MAX_TASKS][NUM_TASK_MBOX]; /* array of pointers to the first event in the task mailbox */
+ BUFFER_HDR_T *OSTaskQLast [GKI_MAX_TASKS][NUM_TASK_MBOX]; /* array of pointers to the last event in the task mailbox */
+
+ /* Define the buffer pool management variables
+ */
+ FREE_QUEUE_T freeq[GKI_NUM_TOTAL_BUF_POOLS];
+
+ UINT16 pool_buf_size[GKI_NUM_TOTAL_BUF_POOLS];
+ UINT16 pool_max_count[GKI_NUM_TOTAL_BUF_POOLS];
+ UINT16 pool_additions[GKI_NUM_TOTAL_BUF_POOLS];
+
+ /* Define the buffer pool start addresses
+ */
+ UINT8 *pool_start[GKI_NUM_TOTAL_BUF_POOLS]; /* array of pointers to the start of each buffer pool */
+ UINT8 *pool_end[GKI_NUM_TOTAL_BUF_POOLS]; /* array of pointers to the end of each buffer pool */
+ UINT16 pool_size[GKI_NUM_TOTAL_BUF_POOLS]; /* actual size of the buffers in a pool */
+
+ /* Define the buffer pool access control variables */
+ void *p_user_mempool; /* User O/S memory pool */
+ UINT16 pool_access_mask; /* Bits are set if the corresponding buffer pool is a restricted pool */
+ UINT8 pool_list[GKI_NUM_TOTAL_BUF_POOLS]; /* buffer pools arranged in the order of size */
+ UINT8 curr_total_no_of_pools; /* number of fixed buf pools + current number of dynamic pools */
+
+ BOOLEAN timer_nesting; /* flag to prevent timer interrupt nesting */
+
+ /* Time queue arrays */
+ TIMER_LIST_Q *timer_queues[GKI_MAX_TIMER_QUEUES];
+ /* System tick callback */
+ SYSTEM_TICK_CBACK *p_tick_cb;
+ BOOLEAN system_tick_running; /* TRUE if system tick is running. Valid only if p_tick_cb is not NULL */
+
+#if (GKI_DEBUG == TRUE)
+ UINT16 ExceptionCnt; /* number of GKI exceptions that have happened */
+ EXCEPTION_T Exception[GKI_MAX_EXCEPTION];
+#endif
+
+} tGKI_COM_CB;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Internal GKI function prototypes
+*/
+GKI_API extern BOOLEAN gki_chk_buf_damage(void *);
+extern BOOLEAN gki_chk_buf_owner(void *);
+extern void gki_buffer_init (void);
+extern void gki_timers_init(void);
+extern void gki_adjust_timer_count (INT32);
+
+#ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS
+extern void gki_dealloc_free_queue(void);
+#endif
+
+extern void OSStartRdy(void);
+extern void OSCtxSw(void);
+extern void OSIntCtxSw(void);
+extern void OSSched(void);
+extern void OSIntEnter(void);
+extern void OSIntExit(void);
+
+
+/* Debug aids
+*/
+typedef void (*FP_PRINT)(char *, ...);
+
+#if (GKI_DEBUG == TRUE)
+
+typedef void (*PKT_PRINT)(UINT8 *, UINT16);
+
+extern void gki_print_task(FP_PRINT);
+extern void gki_print_exception(FP_PRINT);
+extern void gki_print_timer(FP_PRINT);
+extern void gki_print_stack(FP_PRINT);
+extern void gki_print_buffer(FP_PRINT);
+extern void gki_print_buffer_statistics(FP_PRINT, INT16);
+GKI_API extern void gki_print_used_bufs (FP_PRINT, UINT8);
+extern void gki_dump(UINT8 *, UINT16, FP_PRINT);
+extern void gki_dump2(UINT16 *, UINT16, FP_PRINT);
+extern void gki_dump4(UINT32 *, UINT16, FP_PRINT);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/gki/common/gki_debug.c b/gki/common/gki_debug.c
new file mode 100644
index 0000000..46d7e38
--- /dev/null
+++ b/gki/common/gki_debug.c
@@ -0,0 +1,354 @@
+/******************************************************************************
+ *
+ * Copyright (C) 1999-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "gki_int.h"
+
+#if (GKI_DEBUG == TRUE)
+
+const INT8 * const OSTaskStates[] =
+{
+ (INT8 *)"DEAD", /* 0 */
+ (INT8 *)"REDY", /* 1 */
+ (INT8 *)"WAIT", /* 2 */
+ (INT8 *)"",
+ (INT8 *)"DELY", /* 4 */
+ (INT8 *)"",
+ (INT8 *)"",
+ (INT8 *)"",
+ (INT8 *)"SUSP", /* 8 */
+};
+
+
+/*******************************************************************************
+**
+** Function GKI_PrintBufferUsage
+**
+** Description Displays Current Buffer Pool summary
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_PrintBufferUsage(UINT8 *p_num_pools, UINT16 *p_cur_used)
+{
+ int i;
+ FREE_QUEUE_T *p;
+ UINT8 num = gki_cb.com.curr_total_no_of_pools;
+ UINT16 cur[GKI_NUM_TOTAL_BUF_POOLS];
+
+ GKI_TRACE_0("");
+ GKI_TRACE_0("--- GKI Buffer Pool Summary (R - restricted, P - public) ---");
+
+ GKI_TRACE_0("POOL SIZE USED MAXU TOTAL");
+ GKI_TRACE_0("------------------------------");
+ for (i = 0; i < gki_cb.com.curr_total_no_of_pools; i++)
+ {
+ p = &gki_cb.com.freeq[i];
+ if ((1 << i) & gki_cb.com.pool_access_mask)
+ {
+ GKI_TRACE_5("%02d: (R), %4d, %3d, %3d, %3d",
+ i, p->size, p->cur_cnt, p->max_cnt, p->total);
+ }
+ else
+ {
+ GKI_TRACE_5("%02d: (P), %4d, %3d, %3d, %3d",
+ i, p->size, p->cur_cnt, p->max_cnt, p->total);
+ }
+ cur[i] = p->cur_cnt;
+ }
+ if (p_num_pools)
+ *p_num_pools = num;
+ if (p_cur_used)
+ memcpy(p_cur_used, cur, num*2);
+}
+
+/*******************************************************************************
+**
+** Function GKI_PrintBuffer
+**
+** Description Called internally by OSS to print the buffer pools
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_PrintBuffer(void)
+{
+ UINT16 i;
+ for(i=0; i<GKI_NUM_TOTAL_BUF_POOLS; i++)
+ {
+ GKI_TRACE_5("pool:%4u free %4u cur %3u max %3u total%3u", i, gki_cb.com.freeq[i].size,
+ gki_cb.com.freeq[i].cur_cnt, gki_cb.com.freeq[i].max_cnt, gki_cb.com.freeq[i].total);
+ }
+}
+
+/*******************************************************************************
+**
+** Function gki_calc_stack
+**
+** Description This function tries to calculate the amount of
+** stack used by looking non magic num. Magic num is consider
+** the first byte in the stack.
+**
+** Returns the number of unused byte on the stack. 4 in case of stack overrun
+**
+*******************************************************************************/
+UINT16 gki_calc_stack (UINT8 task)
+{
+ int j, stacksize;
+ UINT32 MagicNum;
+ UINT32 *p;
+
+ stacksize = (int) gki_cb.com.OSStackSize[task];
+ p = (UINT32 *)gki_cb.com.OSStack[task]; /* assume stack is aligned, */
+ MagicNum = *p;
+
+ for(j = 0; j < stacksize; j++)
+ {
+ if(*p++ != MagicNum) break;
+ }
+
+ return (j * sizeof(UINT32));
+}
+
+/*******************************************************************************
+**
+** Function GKI_print_task
+**
+** Description Print task stack usage.
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_print_task(void)
+{
+#ifdef _BT_WIN32
+ GKI_TRACE_0("Service not available under insight");
+#else
+ UINT8 TaskId;
+
+ GKI_TRACE_0("TID TASKNAME STATE FREE_STACK STACK");
+ for(TaskId=0; TaskId < GKI_MAX_TASKS; TaskId++)
+ {
+ if (gki_cb.com.OSRdyTbl[TaskId] != TASK_DEAD)
+ {
+ GKI_TRACE_5("%2u %-8s %-5s 0x%04X 0x%04X Bytes",
+ (UINT16)TaskId, gki_cb.com.OSTName[TaskId],
+ OSTaskStates[gki_cb.com.OSRdyTbl[TaskId]],
+ gki_calc_stack(TaskId), gki_cb.com.OSStackSize[TaskId]);
+
+ }
+ }
+#endif
+}
+
+
+/*******************************************************************************
+**
+** Function gki_print_buffer_statistics
+**
+** Description Called internally by OSS to print the buffer pools statistics
+**
+** Returns void
+**
+*******************************************************************************/
+void gki_print_buffer_statistics(FP_PRINT print, INT16 pool)
+{
+ UINT16 i;
+ BUFFER_HDR_T *hdr;
+ UINT16 size,act_size,maxbuffs;
+ UINT32 *magic;
+
+ if (pool > GKI_NUM_TOTAL_BUF_POOLS || pool < 0)
+ {
+ print("Not a valid Buffer pool\n");
+ return;
+ }
+
+ size = gki_cb.com.freeq[pool].size;
+ maxbuffs = gki_cb.com.freeq[pool].total;
+ act_size = size + BUFFER_PADDING_SIZE;
+ print("Buffer Pool[%u] size=%u cur_cnt=%u max_cnt=%u total=%u\n",
+ pool, gki_cb.com.freeq[pool].size,
+ gki_cb.com.freeq[pool].cur_cnt, gki_cb.com.freeq[pool].max_cnt, gki_cb.com.freeq[pool].total);
+
+ print(" Owner State Sanity\n");
+ print("----------------------------\n");
+ hdr = (BUFFER_HDR_T *)(gki_cb.com.pool_start[pool]);
+ for(i=0; i<maxbuffs; i++)
+ {
+ magic = (UINT32 *)((UINT8 *)hdr + BUFFER_HDR_SIZE + size);
+ print("%3d: 0x%02x %4d %10s\n", i, hdr->task_id, hdr->status, (*magic == MAGIC_NO)?"OK":"CORRUPTED");
+ hdr = (BUFFER_HDR_T *)((UINT8 *)hdr + act_size);
+ }
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function gki_print_used_bufs
+**
+** Description Dumps used buffers in the particular pool
+**
+*******************************************************************************/
+GKI_API void gki_print_used_bufs (FP_PRINT print, UINT8 pool_id)
+{
+ UINT8 *p_start;
+ UINT16 buf_size;
+ UINT16 num_bufs;
+ BUFFER_HDR_T *p_hdr;
+ UINT16 i;
+ UINT32 *magic;
+ UINT16 *p;
+
+
+ if ((pool_id >= GKI_NUM_TOTAL_BUF_POOLS) || (gki_cb.com.pool_start[pool_id] != 0))
+ {
+ print("Not a valid Buffer pool\n");
+ return;
+ }
+
+ p_start = gki_cb.com.pool_start[pool_id];
+ buf_size = gki_cb.com.freeq[pool_id].size + BUFFER_PADDING_SIZE;
+ num_bufs = gki_cb.com.freeq[pool_id].total;
+
+ for (i = 0; i < num_bufs; i++, p_start += buf_size)
+ {
+ p_hdr = (BUFFER_HDR_T *)p_start;
+ magic = (UINT32 *)((UINT8 *)p_hdr + buf_size - sizeof(UINT32));
+ p = (UINT16 *) p_hdr;
+
+ if (p_hdr->status != BUF_STATUS_FREE)
+ {
+ print ("%d:0x%x (Q:%d,Task:%s,Stat:%d,%s) %04x %04x %04x %04x %04x %04x %04x %04x\n",
+ i, p_hdr,
+ p_hdr->q_id,
+ GKI_map_taskname(p_hdr->task_id),
+ p_hdr->status,
+ (*magic == MAGIC_NO)? "OK" : "CORRUPTED",
+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
+ }
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function gki_print_task
+**
+** Description This function prints the task states.
+**
+** Returns void
+**
+*******************************************************************************/
+void gki_print_task (FP_PRINT print)
+{
+ UINT8 i;
+
+ print("TID VID TASKNAME STATE WAIT WAITFOR TIMEOUT STACK\n");
+ print("-------------------------------------------------\n");
+ for(i=0; i<GKI_MAX_TASKS; i++)
+ {
+ if (gki_cb.com.OSRdyTbl[i] != TASK_DEAD)
+ {
+ print("%2u %-8s %-5s %04X %04X %7u %u/%u Bytes\n",
+ (UINT16)i, gki_cb.com.OSTName[i],
+ OSTaskStates[gki_cb.com.OSRdyTbl[i]],
+ gki_cb.com.OSWaitEvt[i], gki_cb.com.OSWaitForEvt[i],
+ gki_cb.com.OSWaitTmr[i], gki_calc_stack(i), gki_cb.com.OSStackSize[i]);
+ }
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function gki_print_exception
+**
+** Description This function prints the exception information.
+**
+** Returns void
+**
+*******************************************************************************/
+void gki_print_exception(FP_PRINT print)
+{
+ UINT16 i;
+ EXCEPTION_T *pExp;
+
+ print ("GKI Exceptions:\n");
+ for (i = 0; i < gki_cb.com.ExceptionCnt; i++)
+ {
+ pExp = &gki_cb.com.Exception[i];
+ print("%d: Type=%d, Task=%d: %s\n", i,
+ (INT32)pExp->type, (INT32)pExp->taskid, (INT8 *)pExp->msg);
+ }
+}
+
+
+/*****************************************************************************/
+void gki_dump (UINT8 *s, UINT16 len, FP_PRINT print)
+{
+ UINT16 i, j;
+
+ for(i=0, j=0; i<len; i++)
+ {
+ if(j == 0)
+ print("\n%lX: %02X, ", &s[i], s[i]);
+ else if(j == 7)
+ print("%02X, ", s[i]);
+ else
+ print("%02X, ", s[i]);
+ if(++j == 16)
+ j=0;
+ }
+ print("\n");
+}
+
+void gki_dump2 (UINT16 *s, UINT16 len, FP_PRINT print)
+{
+ UINT16 i, j;
+
+ for(i=0, j=0; i<len; i++)
+ {
+ if(j == 0)
+ print("\n%lX: %04X, ", &s[i], s[i]);
+ else
+ print("%04X, ", s[i]);
+ if(++j == 8)
+ j=0;
+ }
+ print("\n");
+}
+
+void gki_dump4 (UINT32 *s, UINT16 len, FP_PRINT print)
+{
+ UINT16 i, j;
+
+ for(i=0, j=0; i<len; i++)
+ {
+ if(j == 0)
+ print("\n%lX: %08lX, ", &s[i], s[i]);
+ else
+ print("%08lX, ", s[i]);
+ if(++j == 4)
+ j=0;
+ }
+ print("\n");
+}
+
+
+#endif
diff --git a/gki/common/gki_inet.h b/gki/common/gki_inet.h
new file mode 100644
index 0000000..6640931
--- /dev/null
+++ b/gki/common/gki_inet.h
@@ -0,0 +1,47 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2002-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+#ifndef GKI_INET_H
+#define GKI_INET_H
+
+#include "data_types.h"
+
+#define htons ntohs
+#define htonl ntohl
+
+#define htonets nettohs
+#define htonetl nettohl
+
+#if BIG_ENDIAN == TRUE
+#define ntohs(n) (n)
+#define ntohl(n) (n)
+#define ntoh6(n) (n)
+
+#define nettohs(n) (n)
+#define nettohl(n) (n)
+#else
+extern UINT16 ntohs(UINT16 n);
+extern UINT32 ntohl(UINT32 n);
+extern UINT8 *ntoh6(UINT8 *p);
+
+#define nettohs(n) ((UINT16)((((n) << 8) & 0xff00) | (((n) >> 8) & 0x00ff)))
+#define nettohl(n) ((((n) & 0x000000ff) << 24) | (((n) << 8) & 0x00ff0000) | \
+ (((n) >> 8) & 0x0000ff00) | (((n) >> 24) & 0x000000ff))
+#endif
+
+#endif /* GKI_INET_H */
+
diff --git a/gki/common/gki_time.c b/gki/common/gki_time.c
new file mode 100644
index 0000000..a9af8fa
--- /dev/null
+++ b/gki/common/gki_time.c
@@ -0,0 +1,1023 @@
+/******************************************************************************
+ *
+ * Copyright (C) 1999-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+#include "gki_int.h"
+
+#ifndef BT_ERROR_TRACE_0
+#define BT_ERROR_TRACE_0(l,m)
+#endif
+
+/* Make sure that this has been defined in target.h */
+#ifndef GKI_NUM_TIMERS
+#error NO TIMERS: Must define at least 1 timer in the system!
+#endif
+
+
+#define GKI_NO_NEW_TMRS_STARTED (0x7fffffffL) /* Largest signed positive timer count */
+#define GKI_UNUSED_LIST_ENTRY (0x80000000L) /* Marks an unused timer list entry (initial value) */
+#define GKI_MAX_INT32 (0x7fffffffL)
+
+/*******************************************************************************
+**
+** Function gki_timers_init
+**
+** Description This internal function is called once at startup to initialize
+** all the timer structures.
+**
+** Returns void
+**
+*******************************************************************************/
+void gki_timers_init(void)
+{
+ UINT8 tt;
+
+ gki_cb.com.OSTicksTilExp = 0; /* Remaining time (of OSTimeCurTimeout) before next timer expires */
+ gki_cb.com.OSNumOrigTicks = 0;
+#if (defined(GKI_DELAY_STOP_SYS_TICK) && (GKI_DELAY_STOP_SYS_TICK > 0))
+ gki_cb.com.OSTicksTilStop = 0; /* clear inactivity delay timer */
+#endif
+
+ for (tt = 0; tt < GKI_MAX_TASKS; tt++)
+ {
+ gki_cb.com.OSWaitTmr [tt] = 0;
+
+#if (GKI_NUM_TIMERS > 0)
+ gki_cb.com.OSTaskTmr0 [tt] = 0;
+ gki_cb.com.OSTaskTmr0R [tt] = 0;
+#endif
+
+#if (GKI_NUM_TIMERS > 1)
+ gki_cb.com.OSTaskTmr1 [tt] = 0;
+ gki_cb.com.OSTaskTmr1R [tt] = 0;
+#endif
+
+#if (GKI_NUM_TIMERS > 2)
+ gki_cb.com.OSTaskTmr2 [tt] = 0;
+ gki_cb.com.OSTaskTmr2R [tt] = 0;
+#endif
+
+#if (GKI_NUM_TIMERS > 3)
+ gki_cb.com.OSTaskTmr3 [tt] = 0;
+ gki_cb.com.OSTaskTmr3R [tt] = 0;
+#endif
+ }
+
+ for (tt = 0; tt < GKI_MAX_TIMER_QUEUES; tt++)
+ {
+ gki_cb.com.timer_queues[tt] = NULL;
+ }
+
+ gki_cb.com.p_tick_cb = NULL;
+ gki_cb.com.system_tick_running = FALSE;
+
+ return;
+}
+
+/*******************************************************************************
+**
+** Function gki_timers_is_timer_running
+**
+** Description This internal function is called to test if any gki timer are running
+**
+**
+** Returns TRUE if at least one time is running in the system, FALSE else.
+**
+*******************************************************************************/
+BOOLEAN gki_timers_is_timer_running(void)
+{
+ UINT8 tt;
+ for (tt = 0; tt < GKI_MAX_TASKS; tt++)
+ {
+
+#if (GKI_NUM_TIMERS > 0)
+ if(gki_cb.com.OSTaskTmr0 [tt])
+ {
+ return TRUE;
+ }
+#endif
+
+#if (GKI_NUM_TIMERS > 1)
+ if(gki_cb.com.OSTaskTmr1 [tt] )
+ {
+ return TRUE;
+ }
+#endif
+
+#if (GKI_NUM_TIMERS > 2)
+ if(gki_cb.com.OSTaskTmr2 [tt] )
+ {
+ return TRUE;
+ }
+#endif
+
+#if (GKI_NUM_TIMERS > 3)
+ if(gki_cb.com.OSTaskTmr3 [tt] )
+ {
+ return TRUE;
+ }
+#endif
+ }
+
+ return FALSE;
+
+}
+
+/*******************************************************************************
+**
+** Function GKI_get_tick_count
+**
+** Description This function returns the current system ticks
+**
+** Returns The current number of system ticks
+**
+*******************************************************************************/
+UINT32 GKI_get_tick_count(void)
+{
+ return gki_cb.com.OSTicks;
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_ready_to_sleep
+**
+** Description This function returns the number of system ticks until the
+** next timer will expire. It is typically called by a power
+** savings manager to find out how long it can have the system
+** sleep before it needs to service the next entry.
+**
+** Parameters: None
+**
+** Returns Number of ticks til the next timer expires
+** Note: the value is a signed value. This value should be
+** compared to x > 0, to avoid misinterpreting negative tick
+** values.
+**
+*******************************************************************************/
+INT32 GKI_ready_to_sleep (void)
+{
+ return (gki_cb.com.OSTicksTilExp);
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_start_timer
+**
+** Description An application can call this function to start one of
+** it's four general purpose timers. Any of the four timers
+** can be 1-shot or continuous. If a timer is already running,
+** it will be reset to the new parameters.
+**
+** Parameters tnum - (input) timer number to be started (TIMER_0,
+** TIMER_1, TIMER_2, or TIMER_3)
+** ticks - (input) the number of system ticks til the
+** timer expires.
+** is_continuous - (input) TRUE if timer restarts automatically,
+** else FALSE if it is a 'one-shot'.
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_start_timer (UINT8 tnum, INT32 ticks, BOOLEAN is_continuous)
+{
+ INT32 reload;
+ INT32 orig_ticks;
+ UINT8 task_id = GKI_get_taskid();
+ BOOLEAN bad_timer = FALSE;
+
+ if (ticks <= 0)
+ ticks = 1;
+
+ orig_ticks = ticks; /* save the ticks in case adjustment is necessary */
+
+
+ /* If continuous timer, set reload, else set it to 0 */
+ if (is_continuous)
+ reload = ticks;
+ else
+ reload = 0;
+
+ GKI_disable();
+
+ if(gki_timers_is_timer_running() == FALSE)
+ {
+#if (defined(GKI_DELAY_STOP_SYS_TICK) && (GKI_DELAY_STOP_SYS_TICK > 0))
+ /* if inactivity delay timer is not running, start system tick */
+ if(gki_cb.com.OSTicksTilStop == 0)
+ {
+#endif
+ if(gki_cb.com.p_tick_cb)
+ {
+ /* start system tick */
+ gki_cb.com.system_tick_running = TRUE;
+ (gki_cb.com.p_tick_cb) (TRUE);
+ }
+#if (defined(GKI_DELAY_STOP_SYS_TICK) && (GKI_DELAY_STOP_SYS_TICK > 0))
+ }
+ else
+ {
+ /* clear inactivity delay timer */
+ gki_cb.com.OSTicksTilStop = 0;
+ }
+#endif
+ }
+ /* Add the time since the last task timer update.
+ ** Note that this works when no timers are active since
+ ** both OSNumOrigTicks and OSTicksTilExp are 0.
+ */
+ if (GKI_MAX_INT32 - (gki_cb.com.OSNumOrigTicks - gki_cb.com.OSTicksTilExp) > ticks)
+ {
+ ticks += gki_cb.com.OSNumOrigTicks - gki_cb.com.OSTicksTilExp;
+ }
+ else
+ ticks = GKI_MAX_INT32;
+
+ switch (tnum)
+ {
+#if (GKI_NUM_TIMERS > 0)
+ case TIMER_0:
+ gki_cb.com.OSTaskTmr0R[task_id] = reload;
+ gki_cb.com.OSTaskTmr0 [task_id] = ticks;
+ break;
+#endif
+
+#if (GKI_NUM_TIMERS > 1)
+ case TIMER_1:
+ gki_cb.com.OSTaskTmr1R[task_id] = reload;
+ gki_cb.com.OSTaskTmr1 [task_id] = ticks;
+ break;
+#endif
+
+#if (GKI_NUM_TIMERS > 2)
+ case TIMER_2:
+ gki_cb.com.OSTaskTmr2R[task_id] = reload;
+ gki_cb.com.OSTaskTmr2 [task_id] = ticks;
+ break;
+#endif
+
+#if (GKI_NUM_TIMERS > 3)
+ case TIMER_3:
+ gki_cb.com.OSTaskTmr3R[task_id] = reload;
+ gki_cb.com.OSTaskTmr3 [task_id] = ticks;
+ break;
+#endif
+ default:
+ bad_timer = TRUE; /* Timer number is bad, so do not use */
+ }
+
+ /* Update the expiration timeout if a legitimate timer */
+ if (!bad_timer)
+ {
+ /* Only update the timeout value if it is less than any other newly started timers */
+ gki_adjust_timer_count (orig_ticks);
+ }
+
+ GKI_enable();
+
+}
+
+/*******************************************************************************
+**
+** Function GKI_stop_timer
+**
+** Description An application can call this function to stop one of
+** it's four general purpose timers. There is no harm in
+** stopping a timer that is already stopped.
+**
+** Parameters tnum - (input) timer number to be started (TIMER_0,
+** TIMER_1, TIMER_2, or TIMER_3)
+** Returns void
+**
+*******************************************************************************/
+void GKI_stop_timer (UINT8 tnum)
+{
+ UINT8 task_id = GKI_get_taskid();
+
+ switch (tnum)
+ {
+#if (GKI_NUM_TIMERS > 0)
+ case TIMER_0:
+ gki_cb.com.OSTaskTmr0R[task_id] = 0;
+ gki_cb.com.OSTaskTmr0 [task_id] = 0;
+ break;
+#endif
+
+#if (GKI_NUM_TIMERS > 1)
+ case TIMER_1:
+ gki_cb.com.OSTaskTmr1R[task_id] = 0;
+ gki_cb.com.OSTaskTmr1 [task_id] = 0;
+ break;
+#endif
+
+#if (GKI_NUM_TIMERS > 2)
+ case TIMER_2:
+ gki_cb.com.OSTaskTmr2R[task_id] = 0;
+ gki_cb.com.OSTaskTmr2 [task_id] = 0;
+ break;
+#endif
+
+#if (GKI_NUM_TIMERS > 3)
+ case TIMER_3:
+ gki_cb.com.OSTaskTmr3R[task_id] = 0;
+ gki_cb.com.OSTaskTmr3 [task_id] = 0;
+ break;
+#endif
+ }
+
+ GKI_disable();
+
+ if (gki_timers_is_timer_running() == FALSE)
+ {
+ if (gki_cb.com.p_tick_cb)
+ {
+#if (defined(GKI_DELAY_STOP_SYS_TICK) && (GKI_DELAY_STOP_SYS_TICK > 0))
+ /* if inactivity delay timer is not running */
+ if ((gki_cb.com.system_tick_running)&&(gki_cb.com.OSTicksTilStop == 0))
+ {
+ /* set inactivity delay timer */
+ /* when timer expires, system tick will be stopped */
+ gki_cb.com.OSTicksTilStop = GKI_DELAY_STOP_SYS_TICK;
+ }
+#else
+ gki_cb.com.system_tick_running = FALSE;
+ gki_cb.com.p_tick_cb(FALSE); /* stop system tick */
+#endif
+ }
+ }
+
+ GKI_enable();
+
+
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_timer_update
+**
+** Description This function is called by an OS to drive the GKI's timers.
+** It is typically called at every system tick to
+** update the timers for all tasks, and check for timeouts.
+**
+** Note: It has been designed to also allow for variable tick updates
+** so that systems with strict power savings requirements can
+** have the update occur at variable intervals.
+**
+** Parameters: ticks_since_last_update - (input) This is the number of TICKS that have
+** occurred since the last time GKI_timer_update was called.
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_timer_update (INT32 ticks_since_last_update)
+{
+ UINT8 task_id;
+ long next_expiration; /* Holds the next soonest expiration time after this update */
+
+ /* Increment the number of ticks used for time stamps */
+ gki_cb.com.OSTicks += ticks_since_last_update;
+
+ /* If any timers are running in any tasks, decrement the remaining time til
+ * the timer updates need to take place (next expiration occurs)
+ */
+ gki_cb.com.OSTicksTilExp -= ticks_since_last_update;
+
+ /* Don't allow timer interrupt nesting */
+ if (gki_cb.com.timer_nesting)
+ return;
+
+ gki_cb.com.timer_nesting = 1;
+
+#if (defined(GKI_DELAY_STOP_SYS_TICK) && (GKI_DELAY_STOP_SYS_TICK > 0))
+ /* if inactivity delay timer is set and expired */
+ if (gki_cb.com.OSTicksTilStop)
+ {
+ if( gki_cb.com.OSTicksTilStop <= (UINT32)ticks_since_last_update )
+ {
+ if(gki_cb.com.p_tick_cb)
+ {
+ gki_cb.com.system_tick_running = FALSE;
+ (gki_cb.com.p_tick_cb) (FALSE); /* stop system tick */
+ }
+ gki_cb.com.OSTicksTilStop = 0; /* clear inactivity delay timer */
+ gki_cb.com.timer_nesting = 0;
+ return;
+ }
+ else
+ gki_cb.com.OSTicksTilStop -= ticks_since_last_update;
+ }
+#endif
+
+ /* No need to update the ticks if no timeout has occurred */
+ if (gki_cb.com.OSTicksTilExp > 0)
+ {
+ gki_cb.com.timer_nesting = 0;
+ return;
+ }
+
+ next_expiration = GKI_NO_NEW_TMRS_STARTED;
+
+ /* If here then gki_cb.com.OSTicksTilExp <= 0. If negative, then increase gki_cb.com.OSNumOrigTicks
+ to account for the difference so timer updates below are decremented by the full number
+ of ticks. gki_cb.com.OSNumOrigTicks is reset at the bottom of this function so changing this
+ value only affects the timer updates below
+ */
+ gki_cb.com.OSNumOrigTicks -= gki_cb.com.OSTicksTilExp;
+
+#if GKI_TIMER_LIST_NOPREEMPT == TRUE
+ /* Protect this section because if a GKI_timer_stop happens between:
+ * - gki_cb.com.OSTaskTmr0[task_id] -= gki_cb.com.OSNumOrigTicks;
+ * - gki_cb.com.OSTaskTmr0[task_id] = gki_cb.com.OSTaskTmr0R[task_id];
+ * then the timer may appear stopped while it is about to be reloaded.
+ * Note: Not needed if this function cannot be preempted (typical).
+ */
+ GKI_disable();
+#endif
+
+ /* Check for OS Task Timers */
+ for (task_id = 0; task_id < GKI_MAX_TASKS; task_id++)
+ {
+ if (gki_cb.com.OSWaitTmr[task_id] > 0) /* If timer is running */
+ {
+ gki_cb.com.OSWaitTmr[task_id] -= gki_cb.com.OSNumOrigTicks;
+ if (gki_cb.com.OSWaitTmr[task_id] <= 0)
+ {
+ /* Timer Expired */
+ gki_cb.com.OSRdyTbl[task_id] = TASK_READY;
+ }
+ }
+
+#if (GKI_NUM_TIMERS > 0)
+ /* If any timer is running, decrement */
+ if (gki_cb.com.OSTaskTmr0[task_id] > 0)
+ {
+ gki_cb.com.OSTaskTmr0[task_id] -= gki_cb.com.OSNumOrigTicks;
+
+ if (gki_cb.com.OSTaskTmr0[task_id] <= 0)
+ {
+ /* Reload timer and set Timer 0 Expired event mask */
+ gki_cb.com.OSTaskTmr0[task_id] = gki_cb.com.OSTaskTmr0R[task_id];
+
+#if (defined(GKI_TIMER_UPDATES_FROM_ISR) && GKI_TIMER_UPDATES_FROM_ISR == TRUE)
+ GKI_isend_event (task_id, TIMER_0_EVT_MASK);
+#else
+ GKI_send_event (task_id, TIMER_0_EVT_MASK);
+#endif
+ }
+ }
+
+ /* Check to see if this timer is the next one to expire */
+ if (gki_cb.com.OSTaskTmr0[task_id] > 0 && gki_cb.com.OSTaskTmr0[task_id] < next_expiration)
+ next_expiration = gki_cb.com.OSTaskTmr0[task_id];
+#endif
+
+#if (GKI_NUM_TIMERS > 1)
+ /* If any timer is running, decrement */
+ if (gki_cb.com.OSTaskTmr1[task_id] > 0)
+ {
+ gki_cb.com.OSTaskTmr1[task_id] -= gki_cb.com.OSNumOrigTicks;
+
+ if (gki_cb.com.OSTaskTmr1[task_id] <= 0)
+ {
+ /* Reload timer and set Timer 1 Expired event mask */
+ gki_cb.com.OSTaskTmr1[task_id] = gki_cb.com.OSTaskTmr1R[task_id];
+
+#if (defined(GKI_TIMER_UPDATES_FROM_ISR) && GKI_TIMER_UPDATES_FROM_ISR == TRUE)
+ GKI_isend_event (task_id, TIMER_1_EVT_MASK);
+#else
+ GKI_send_event (task_id, TIMER_1_EVT_MASK);
+#endif
+ }
+ }
+
+ /* Check to see if this timer is the next one to expire */
+ if (gki_cb.com.OSTaskTmr1[task_id] > 0 && gki_cb.com.OSTaskTmr1[task_id] < next_expiration)
+ next_expiration = gki_cb.com.OSTaskTmr1[task_id];
+#endif
+
+#if (GKI_NUM_TIMERS > 2)
+ /* If any timer is running, decrement */
+ if (gki_cb.com.OSTaskTmr2[task_id] > 0)
+ {
+ gki_cb.com.OSTaskTmr2[task_id] -= gki_cb.com.OSNumOrigTicks;
+
+ if (gki_cb.com.OSTaskTmr2[task_id] <= 0)
+ {
+ /* Reload timer and set Timer 2 Expired event mask */
+ gki_cb.com.OSTaskTmr2[task_id] = gki_cb.com.OSTaskTmr2R[task_id];
+
+#if (defined(GKI_TIMER_UPDATES_FROM_ISR) && GKI_TIMER_UPDATES_FROM_ISR == TRUE)
+ GKI_isend_event (task_id, TIMER_2_EVT_MASK);
+#else
+ GKI_send_event (task_id, TIMER_2_EVT_MASK);
+#endif
+ }
+ }
+
+ /* Check to see if this timer is the next one to expire */
+ if (gki_cb.com.OSTaskTmr2[task_id] > 0 && gki_cb.com.OSTaskTmr2[task_id] < next_expiration)
+ next_expiration = gki_cb.com.OSTaskTmr2[task_id];
+#endif
+
+#if (GKI_NUM_TIMERS > 3)
+ /* If any timer is running, decrement */
+ if (gki_cb.com.OSTaskTmr3[task_id] > 0)
+ {
+ gki_cb.com.OSTaskTmr3[task_id] -= gki_cb.com.OSNumOrigTicks;
+
+ if (gki_cb.com.OSTaskTmr3[task_id] <= 0)
+ {
+ /* Reload timer and set Timer 3 Expired event mask */
+ gki_cb.com.OSTaskTmr3[task_id] = gki_cb.com.OSTaskTmr3R[task_id];
+
+#if (defined(GKI_TIMER_UPDATES_FROM_ISR) && GKI_TIMER_UPDATES_FROM_ISR == TRUE)
+ GKI_isend_event (task_id, TIMER_3_EVT_MASK);
+#else
+ GKI_send_event (task_id, TIMER_3_EVT_MASK);
+#endif
+ }
+ }
+
+ /* Check to see if this timer is the next one to expire */
+ if (gki_cb.com.OSTaskTmr3[task_id] > 0 && gki_cb.com.OSTaskTmr3[task_id] < next_expiration)
+ next_expiration = gki_cb.com.OSTaskTmr3[task_id];
+#endif
+
+ }
+
+#if GKI_TIMER_LIST_NOPREEMPT == TRUE
+ /* End the critical section */
+ GKI_enable();
+#endif
+
+ /* Set the next timer experation value if there is one to start */
+ if (next_expiration < GKI_NO_NEW_TMRS_STARTED)
+ {
+ gki_cb.com.OSTicksTilExp = gki_cb.com.OSNumOrigTicks = next_expiration;
+ }
+ else
+ {
+ gki_cb.com.OSTicksTilExp = gki_cb.com.OSNumOrigTicks = 0;
+ }
+
+ gki_cb.com.timer_nesting = 0;
+
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_timer_queue_empty
+**
+** Description This function is called by applications to see whether the timer
+** queue is empty
+**
+** Parameters
+**
+** Returns BOOLEAN
+**
+*******************************************************************************/
+BOOLEAN GKI_timer_queue_empty (void)
+{
+ UINT8 tt;
+
+ for (tt = 0; tt < GKI_MAX_TIMER_QUEUES; tt++)
+ {
+ if (gki_cb.com.timer_queues[tt])
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function GKI_timer_queue_register_callback
+**
+** Description This function is called by applications to register system tick
+** start/stop callback for time queues
+**
+**
+** Parameters p_callback - (input) pointer to the system tick callback
+**
+** Returns BOOLEAN
+**
+*******************************************************************************/
+void GKI_timer_queue_register_callback (SYSTEM_TICK_CBACK *p_callback)
+{
+ gki_cb.com.p_tick_cb = p_callback;
+
+ return;
+}
+
+/*******************************************************************************
+**
+** Function GKI_init_timer_list
+**
+** Description This function is called by applications when they
+** want to initialize a timer list.
+**
+** Parameters p_timer_listq - (input) pointer to the timer list queue object
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_init_timer_list (TIMER_LIST_Q *p_timer_listq)
+{
+ p_timer_listq->p_first = NULL;
+ p_timer_listq->p_last = NULL;
+ p_timer_listq->last_ticks = 0;
+
+ return;
+}
+
+/*******************************************************************************
+**
+** Function GKI_init_timer_list_entry
+**
+** Description This function is called by the applications when they
+** want to initialize a timer list entry. This must be
+** done prior to first use of the entry.
+**
+** Parameters p_tle - (input) pointer to a timer list queue entry
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_init_timer_list_entry (TIMER_LIST_ENT *p_tle)
+{
+ p_tle->p_next = NULL;
+ p_tle->p_prev = NULL;
+ p_tle->ticks = GKI_UNUSED_LIST_ENTRY;
+ p_tle->in_use = FALSE;
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_update_timer_list
+**
+** Description This function is called by the applications when they
+** want to update a timer list. This should be at every
+** timer list unit tick, e.g. once per sec, once per minute etc.
+**
+** Parameters p_timer_listq - (input) pointer to the timer list queue object
+** num_units_since_last_update - (input) number of units since the last update
+** (allows for variable unit update)
+**
+** NOTE: The following timer list update routines should not be used for exact time
+** critical purposes. The timer tasks should be used when exact timing is needed.
+**
+** Returns the number of timers that have expired
+**
+*******************************************************************************/
+UINT16 GKI_update_timer_list (TIMER_LIST_Q *p_timer_listq, INT32 num_units_since_last_update)
+{
+ TIMER_LIST_ENT *p_tle;
+ UINT16 num_time_out = 0;
+ INT32 rem_ticks;
+ INT32 temp_ticks;
+
+ p_tle = p_timer_listq->p_first;
+
+ /* First, get the guys who have previously timed out */
+ /* Note that the tick value of the timers should always be '0' */
+ while ((p_tle) && (p_tle->ticks <= 0))
+ {
+ num_time_out++;
+ p_tle = p_tle->p_next;
+ }
+
+ /* Timer entriy tick values are relative to the preceeding entry */
+ rem_ticks = num_units_since_last_update;
+
+ /* Now, adjust remaining timer entries */
+ while ((p_tle != NULL) && (rem_ticks > 0))
+ {
+ temp_ticks = p_tle->ticks;
+ p_tle->ticks -= rem_ticks;
+
+ /* See if this timer has just timed out */
+ if (p_tle->ticks <= 0)
+ {
+ /* We set the number of ticks to '0' so that the legacy code
+ * that assumes a '0' or nonzero value will still work as coded. */
+ p_tle->ticks = 0;
+
+ num_time_out++;
+ }
+
+ rem_ticks -= temp_ticks; /* Decrement the remaining ticks to process */
+ p_tle = p_tle->p_next;
+ }
+
+ if (p_timer_listq->last_ticks > 0)
+ {
+ p_timer_listq->last_ticks -= num_units_since_last_update;
+
+ /* If the last timer has expired set last_ticks to 0 so that other list update
+ * functions will calculate correctly
+ */
+ if (p_timer_listq->last_ticks < 0)
+ p_timer_listq->last_ticks = 0;
+ }
+
+ return (num_time_out);
+}
+
+/*******************************************************************************
+**
+** Function GKI_get_remaining_ticks
+**
+** Description This function is called by an application to get remaining
+** ticks to expire
+**
+** Parameters p_timer_listq - (input) pointer to the timer list queue object
+** p_target_tle - (input) pointer to a timer list queue entry
+**
+** Returns 0 if timer is not used or timer is not in the list
+** remaining ticks if success
+**
+*******************************************************************************/
+UINT32 GKI_get_remaining_ticks (TIMER_LIST_Q *p_timer_listq, TIMER_LIST_ENT *p_target_tle)
+{
+ TIMER_LIST_ENT *p_tle;
+ UINT32 rem_ticks = 0;
+
+ if (p_target_tle->in_use)
+ {
+ p_tle = p_timer_listq->p_first;
+
+ /* adding up all of ticks in previous entries */
+ while ((p_tle)&&(p_tle != p_target_tle))
+ {
+ rem_ticks += p_tle->ticks;
+ p_tle = p_tle->p_next;
+ }
+
+ /* if found target entry */
+ if (p_tle == p_target_tle)
+ {
+ rem_ticks += p_tle->ticks;
+ }
+ else
+ {
+ BT_ERROR_TRACE_0(TRACE_LAYER_GKI, "GKI_get_remaining_ticks: No timer entry in the list");
+ return(0);
+ }
+ }
+ else
+ {
+ BT_ERROR_TRACE_0(TRACE_LAYER_GKI, "GKI_get_remaining_ticks: timer entry is not active");
+ }
+
+ return (rem_ticks);
+}
+
+/*******************************************************************************
+**
+** Function GKI_add_to_timer_list
+**
+** Description This function is called by an application to add a timer
+** entry to a timer list.
+**
+** Note: A timer value of '0' will effectively insert an already
+** expired event. Negative tick values will be ignored.
+**
+** Parameters p_timer_listq - (input) pointer to the timer list queue object
+** p_tle - (input) pointer to a timer list queue entry
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_add_to_timer_list (TIMER_LIST_Q *p_timer_listq, TIMER_LIST_ENT *p_tle)
+{
+ UINT32 nr_ticks_total;
+ UINT8 tt;
+ TIMER_LIST_ENT *p_temp;
+
+ /* Only process valid tick values */
+ if (p_tle->ticks >= 0)
+ {
+ /* If this entry is the last in the list */
+ if (p_tle->ticks >= p_timer_listq->last_ticks)
+ {
+ /* If this entry is the only entry in the list */
+ if (p_timer_listq->p_first == NULL)
+ p_timer_listq->p_first = p_tle;
+ else
+ {
+ /* Insert the entry onto the end of the list */
+ if (p_timer_listq->p_last != NULL)
+ p_timer_listq->p_last->p_next = p_tle;
+
+ p_tle->p_prev = p_timer_listq->p_last;
+ }
+
+ p_tle->p_next = NULL;
+ p_timer_listq->p_last = p_tle;
+ nr_ticks_total = p_tle->ticks;
+ p_tle->ticks -= p_timer_listq->last_ticks;
+
+ p_timer_listq->last_ticks = nr_ticks_total;
+ }
+ else /* This entry needs to be inserted before the last entry */
+ {
+ /* Find the entry that the new one needs to be inserted in front of */
+ p_temp = p_timer_listq->p_first;
+ while (p_tle->ticks > p_temp->ticks)
+ {
+ /* Update the tick value if looking at an unexpired entry */
+ if (p_temp->ticks > 0)
+ p_tle->ticks -= p_temp->ticks;
+
+ p_temp = p_temp->p_next;
+ }
+
+ /* The new entry is the first in the list */
+ if (p_temp == p_timer_listq->p_first)
+ {
+ p_tle->p_next = p_timer_listq->p_first;
+ p_timer_listq->p_first->p_prev = p_tle;
+ p_timer_listq->p_first = p_tle;
+ }
+ else
+ {
+ p_temp->p_prev->p_next = p_tle;
+ p_tle->p_prev = p_temp->p_prev;
+ p_temp->p_prev = p_tle;
+ p_tle->p_next = p_temp;
+ }
+ p_temp->ticks -= p_tle->ticks;
+ }
+
+ p_tle->in_use = TRUE;
+
+ /* if we already add this timer queue to the array */
+ for (tt = 0; tt < GKI_MAX_TIMER_QUEUES; tt++)
+ {
+ if (gki_cb.com.timer_queues[tt] == p_timer_listq)
+ return;
+ }
+ /* add this timer queue to the array */
+ for (tt = 0; tt < GKI_MAX_TIMER_QUEUES; tt++)
+ {
+ if (gki_cb.com.timer_queues[tt] == NULL)
+ break;
+ }
+ if (tt < GKI_MAX_TIMER_QUEUES)
+ {
+ gki_cb.com.timer_queues[tt] = p_timer_listq;
+ }
+ }
+
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_remove_from_timer_list
+**
+** Description This function is called by an application to remove a timer
+** entry from a timer list.
+**
+** Parameters p_timer_listq - (input) pointer to the timer list queue object
+** p_tle - (input) pointer to a timer list queue entry
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_remove_from_timer_list (TIMER_LIST_Q *p_timer_listq, TIMER_LIST_ENT *p_tle)
+{
+ UINT8 tt;
+
+ /* Verify that the entry is valid */
+ if (p_tle == NULL || p_tle->in_use == FALSE || p_timer_listq->p_first == NULL)
+ {
+ return;
+ }
+
+ /* Add the ticks remaining in this timer (if any) to the next guy in the list.
+ ** Note: Expired timers have a tick value of '0'.
+ */
+ if (p_tle->p_next != NULL)
+ {
+ p_tle->p_next->ticks += p_tle->ticks;
+ }
+ else
+ {
+ p_timer_listq->last_ticks -= p_tle->ticks;
+ }
+
+ /* Unlink timer from the list.
+ */
+ if (p_timer_listq->p_first == p_tle)
+ {
+ p_timer_listq->p_first = p_tle->p_next;
+
+ if (p_timer_listq->p_first != NULL)
+ p_timer_listq->p_first->p_prev = NULL;
+
+ if (p_timer_listq->p_last == p_tle)
+ p_timer_listq->p_last = NULL;
+ }
+ else
+ {
+ if (p_timer_listq->p_last == p_tle)
+ {
+ p_timer_listq->p_last = p_tle->p_prev;
+
+ if (p_timer_listq->p_last != NULL)
+ p_timer_listq->p_last->p_next = NULL;
+ }
+ else
+ {
+ if (p_tle->p_next != NULL && p_tle->p_next->p_prev == p_tle)
+ p_tle->p_next->p_prev = p_tle->p_prev;
+ else
+ {
+ /* Error case - chain messed up ?? */
+ return;
+ }
+
+ if (p_tle->p_prev != NULL && p_tle->p_prev->p_next == p_tle)
+ p_tle->p_prev->p_next = p_tle->p_next;
+ else
+ {
+ /* Error case - chain messed up ?? */
+ return;
+ }
+ }
+ }
+
+ p_tle->p_next = p_tle->p_prev = NULL;
+ p_tle->ticks = GKI_UNUSED_LIST_ENTRY;
+ p_tle->in_use = FALSE;
+
+ /* if timer queue is empty */
+ if (p_timer_listq->p_first == NULL && p_timer_listq->p_last == NULL)
+ {
+ for (tt = 0; tt < GKI_MAX_TIMER_QUEUES; tt++)
+ {
+ if (gki_cb.com.timer_queues[tt] == p_timer_listq)
+ {
+ gki_cb.com.timer_queues[tt] = NULL;
+ break;
+ }
+ }
+ }
+
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function gki_adjust_timer_count
+**
+** Description This function is called whenever a new timer or GKI_wait occurs
+** to adjust (if necessary) the current time til the first expiration.
+** This only needs to make an adjustment if the new timer (in ticks) is
+** less than the number of ticks remaining on the current timer.
+**
+** Parameters: ticks - (input) number of system ticks of the new timer entry
+**
+** NOTE: This routine MUST be called while interrupts are disabled to
+** avoid updates while adjusting the timer variables.
+**
+** Returns void
+**
+*******************************************************************************/
+void gki_adjust_timer_count (INT32 ticks)
+{
+ if (ticks > 0)
+ {
+ /* See if the new timer expires before the current first expiration */
+ if (gki_cb.com.OSNumOrigTicks == 0 || (ticks < gki_cb.com.OSTicksTilExp && gki_cb.com.OSTicksTilExp > 0))
+ {
+ gki_cb.com.OSNumOrigTicks = (gki_cb.com.OSNumOrigTicks - gki_cb.com.OSTicksTilExp) + ticks;
+ gki_cb.com.OSTicksTilExp = ticks;
+ }
+ }
+
+ return;
+}