1 /******************************************************************************
2 *
3 * Copyright (C) 2009-2012 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 /*******************************************************************************
20 *
21 * Filename: btif_profile_queue.c
22 *
23 * Description: Bluetooth remote device connection queuing implementation.
24 *
25 ******************************************************************************/
26
27 #include <hardware/bluetooth.h>
28
29 #define LOG_TAG "BTIF_QUEUE"
30 #include "btif_common.h"
31 #include "btif_profile_queue.h"
32 #include "gki.h"
33
34 /*******************************************************************************
35 ** Local type definitions
36 *******************************************************************************/
37
38 typedef enum {
39 BTIF_QUEUE_CONNECT_EVT,
40 BTIF_QUEUE_ADVANCE_EVT
41 } btif_queue_event_t;
42
43 typedef struct connect_node_tag
44 {
45 bt_bdaddr_t bda;
46 uint16_t uuid;
47 uint16_t busy;
48 void *p_cb;
49 struct connect_node_tag *p_next;
50 } __attribute__((packed))connect_node_t;
51
52
53 /*******************************************************************************
54 ** Static variables
55 *******************************************************************************/
56
57 static connect_node_t *connect_queue;
58
59
60 /*******************************************************************************
61 ** Queue helper functions
62 *******************************************************************************/
63
queue_int_add(connect_node_t * p_param)64 static void queue_int_add(connect_node_t *p_param)
65 {
66 connect_node_t *p_list = connect_queue;
67 connect_node_t *p_node = GKI_getbuf(sizeof(connect_node_t));
68 ASSERTC(p_node != NULL, "Failed to allocate new list node", 0);
69
70 memcpy(p_node, p_param, sizeof(connect_node_t));
71
72 if (connect_queue == NULL)
73 {
74 connect_queue = p_node;
75 return;
76 }
77
78 while (p_list->p_next)
79 p_list = p_list->p_next;
80 p_list->p_next = p_node;
81 }
82
queue_int_advance()83 static void queue_int_advance()
84 {
85 connect_node_t *p_head = connect_queue;
86 if (connect_queue == NULL)
87 return;
88
89 connect_queue = connect_queue->p_next;
90 GKI_freebuf(p_head);
91 }
92
queue_int_connect_next()93 static bt_status_t queue_int_connect_next()
94 {
95 connect_node_t* p_head = connect_queue;
96
97 if (p_head == NULL)
98 return BT_STATUS_FAIL;
99
100 /* If the queue is currently busy, we return success anyway,
101 * since the connection has been queued... */
102 if (p_head->busy != FALSE)
103 return BT_STATUS_SUCCESS;
104
105 p_head->busy = TRUE;
106 return (*(btif_connect_cb_t*)p_head->p_cb)(&p_head->bda);
107 }
108
queue_int_handle_evt(UINT16 event,char * p_param)109 static void queue_int_handle_evt(UINT16 event, char *p_param)
110 {
111 switch(event)
112 {
113 case BTIF_QUEUE_CONNECT_EVT:
114 queue_int_add((connect_node_t*)p_param);
115 break;
116
117 case BTIF_QUEUE_ADVANCE_EVT:
118 queue_int_advance();
119 break;
120 }
121
122 queue_int_connect_next();
123 }
124
125 /*******************************************************************************
126 **
127 ** Function btif_queue_connect
128 **
129 ** Description Add a new connection to the queue and trigger the next
130 ** scheduled connection.
131 **
132 ** Returns BT_STATUS_SUCCESS if successful
133 **
134 *******************************************************************************/
btif_queue_connect(uint16_t uuid,const bt_bdaddr_t * bda,btif_connect_cb_t * connect_cb)135 bt_status_t btif_queue_connect(uint16_t uuid, const bt_bdaddr_t *bda,
136 btif_connect_cb_t *connect_cb)
137 {
138 connect_node_t node;
139 memset(&node, 0, sizeof(connect_node_t));
140 memcpy(&(node.bda), bda, sizeof(bt_bdaddr_t));
141 node.uuid = uuid;
142 node.p_cb = connect_cb;
143
144 return btif_transfer_context(queue_int_handle_evt, BTIF_QUEUE_CONNECT_EVT,
145 (char*)&node, sizeof(connect_node_t), NULL);
146 }
147
148 /*******************************************************************************
149 **
150 ** Function btif_queue_advance
151 **
152 ** Description Clear the queue's busy status and advance to the next
153 ** scheduled connection.
154 **
155 ** Returns void
156 **
157 *******************************************************************************/
btif_queue_advance()158 void btif_queue_advance()
159 {
160 btif_transfer_context(queue_int_handle_evt, BTIF_QUEUE_ADVANCE_EVT,
161 NULL, 0, NULL);
162 }
163
164
165 /*******************************************************************************
166 **
167 ** Function btif_queue_release
168 **
169 ** Description Free up all the queue nodes and set the queue head to NULL
170 **
171 ** Returns void
172 **
173 *******************************************************************************/
btif_queue_release()174 void btif_queue_release()
175 {
176 connect_node_t *current = connect_queue;
177
178 while (current != NULL)
179 {
180 connect_node_t *next = current->p_next;
181 GKI_freebuf(current);
182 current = next;
183 }
184
185 connect_queue = NULL;
186 }
187
188