1 /******************************************************************************
2 *
3 * Copyright (C) 2003-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 * This module contains the link control state machine and functions which
22 * operate on the link control block.
23 *
24 ******************************************************************************/
25
26 #include <string.h>
27 #include "stack/bt_types.h"
28 #include "common/bt_target.h"
29 #include "common/bt_defs.h"
30 #include "stack/avct_api.h"
31 #include "avct_int.h"
32 #include "osi/allocator.h"
33
34 #if (defined(AVCT_INCLUDED) && AVCT_INCLUDED == TRUE)
35
36 /*****************************************************************************
37 ** state machine constants and types
38 *****************************************************************************/
39
40 #if BT_TRACE_VERBOSE == TRUE
41
42 /* verbose state strings for trace */
43 const char *const avct_lcb_st_str[] = {
44 "LCB_IDLE_ST",
45 "LCB_OPENING_ST",
46 "LCB_OPEN_ST",
47 "LCB_CLOSING_ST"
48 };
49
50 /* verbose event strings for trace */
51 const char *const avct_lcb_evt_str[] = {
52 "UL_BIND_EVT",
53 "UL_UNBIND_EVT",
54 "UL_MSG_EVT",
55 "INT_CLOSE_EVT",
56 "LL_OPEN_EVT",
57 "LL_CLOSE_EVT",
58 "LL_MSG_EVT",
59 "LL_CONG_EVT"
60 };
61
62 #endif
63
64 /* lcb state machine states */
65 enum {
66 AVCT_LCB_IDLE_ST,
67 AVCT_LCB_OPENING_ST,
68 AVCT_LCB_OPEN_ST,
69 AVCT_LCB_CLOSING_ST
70 };
71
72 /* state machine action enumeration list */
73 enum {
74 AVCT_LCB_CHNL_OPEN,
75 AVCT_LCB_CHNL_DISC,
76 AVCT_LCB_SEND_MSG,
77 AVCT_LCB_OPEN_IND,
78 AVCT_LCB_OPEN_FAIL,
79 AVCT_LCB_CLOSE_IND,
80 AVCT_LCB_CLOSE_CFM,
81 AVCT_LCB_MSG_IND,
82 AVCT_LCB_CONG_IND,
83 AVCT_LCB_BIND_CONN,
84 AVCT_LCB_BIND_FAIL,
85 AVCT_LCB_UNBIND_DISC,
86 AVCT_LCB_CHK_DISC,
87 AVCT_LCB_DISCARD_MSG,
88 AVCT_LCB_DEALLOC,
89 AVCT_LCB_FREE_MSG_IND,
90 AVCT_LCB_NUM_ACTIONS
91 };
92
93 #define AVCT_LCB_IGNORE AVCT_LCB_NUM_ACTIONS
94
95 /* type for action functions */
96 typedef void (*tAVCT_LCB_ACTION)(tAVCT_LCB *p_ccb, tAVCT_LCB_EVT *p_data);
97
98 /* action function list */
99 const tAVCT_LCB_ACTION avct_lcb_action[] = {
100 avct_lcb_chnl_open,
101 avct_lcb_chnl_disc,
102 avct_lcb_send_msg,
103 avct_lcb_open_ind,
104 avct_lcb_open_fail,
105 avct_lcb_close_ind,
106 avct_lcb_close_cfm,
107 avct_lcb_msg_ind,
108 avct_lcb_cong_ind,
109 avct_lcb_bind_conn,
110 avct_lcb_bind_fail,
111 avct_lcb_unbind_disc,
112 avct_lcb_chk_disc,
113 avct_lcb_discard_msg,
114 avct_lcb_dealloc,
115 avct_lcb_free_msg_ind
116 };
117
118 /* state table information */
119 #define AVCT_LCB_ACTIONS 2 /* number of actions */
120 #define AVCT_LCB_NEXT_STATE 2 /* position of next state */
121 #define AVCT_LCB_NUM_COLS 3 /* number of columns in state tables */
122
123 /* state table for idle state */
124 const UINT8 avct_lcb_st_idle[][AVCT_LCB_NUM_COLS] = {
125 /* Event Action 1 Action 2 Next state */
126 /* UL_BIND_EVT */ {AVCT_LCB_CHNL_OPEN, AVCT_LCB_IGNORE, AVCT_LCB_OPENING_ST},
127 /* UL_UNBIND_EVT */ {AVCT_LCB_UNBIND_DISC, AVCT_LCB_IGNORE, AVCT_LCB_IDLE_ST},
128 /* UL_MSG_EVT */ {AVCT_LCB_DISCARD_MSG, AVCT_LCB_IGNORE, AVCT_LCB_IDLE_ST},
129 /* INT_CLOSE_EVT */ {AVCT_LCB_IGNORE, AVCT_LCB_IGNORE, AVCT_LCB_IDLE_ST},
130 /* LL_OPEN_EVT */ {AVCT_LCB_OPEN_IND, AVCT_LCB_IGNORE, AVCT_LCB_OPEN_ST},
131 /* LL_CLOSE_EVT */ {AVCT_LCB_CLOSE_IND, AVCT_LCB_DEALLOC, AVCT_LCB_IDLE_ST},
132 /* LL_MSG_EVT */ {AVCT_LCB_FREE_MSG_IND, AVCT_LCB_IGNORE, AVCT_LCB_IDLE_ST},
133 /* LL_CONG_EVT */ {AVCT_LCB_IGNORE, AVCT_LCB_IGNORE, AVCT_LCB_IDLE_ST}
134 };
135
136 /* state table for opening state */
137 const UINT8 avct_lcb_st_opening[][AVCT_LCB_NUM_COLS] = {
138 /* Event Action 1 Action 2 Next state */
139 /* UL_BIND_EVT */ {AVCT_LCB_IGNORE, AVCT_LCB_IGNORE, AVCT_LCB_OPENING_ST},
140 /* UL_UNBIND_EVT */ {AVCT_LCB_UNBIND_DISC, AVCT_LCB_IGNORE, AVCT_LCB_OPENING_ST},
141 /* UL_MSG_EVT */ {AVCT_LCB_DISCARD_MSG, AVCT_LCB_IGNORE, AVCT_LCB_OPENING_ST},
142 /* INT_CLOSE_EVT */ {AVCT_LCB_CHNL_DISC, AVCT_LCB_IGNORE, AVCT_LCB_CLOSING_ST},
143 /* LL_OPEN_EVT */ {AVCT_LCB_OPEN_IND, AVCT_LCB_IGNORE, AVCT_LCB_OPEN_ST},
144 /* LL_CLOSE_EVT */ {AVCT_LCB_OPEN_FAIL, AVCT_LCB_DEALLOC, AVCT_LCB_IDLE_ST},
145 /* LL_MSG_EVT */ {AVCT_LCB_FREE_MSG_IND, AVCT_LCB_IGNORE, AVCT_LCB_OPENING_ST},
146 /* LL_CONG_EVT */ {AVCT_LCB_CONG_IND, AVCT_LCB_IGNORE, AVCT_LCB_OPENING_ST}
147 };
148
149 /* state table for open state */
150 const UINT8 avct_lcb_st_open[][AVCT_LCB_NUM_COLS] = {
151 /* Event Action 1 Action 2 Next state */
152 /* UL_BIND_EVT */ {AVCT_LCB_BIND_CONN, AVCT_LCB_IGNORE, AVCT_LCB_OPEN_ST},
153 /* UL_UNBIND_EVT */ {AVCT_LCB_CHK_DISC, AVCT_LCB_IGNORE, AVCT_LCB_OPEN_ST},
154 /* UL_MSG_EVT */ {AVCT_LCB_SEND_MSG, AVCT_LCB_IGNORE, AVCT_LCB_OPEN_ST},
155 /* INT_CLOSE_EVT */ {AVCT_LCB_CHNL_DISC, AVCT_LCB_IGNORE, AVCT_LCB_CLOSING_ST},
156 /* LL_OPEN_EVT */ {AVCT_LCB_IGNORE, AVCT_LCB_IGNORE, AVCT_LCB_OPEN_ST},
157 /* LL_CLOSE_EVT */ {AVCT_LCB_CLOSE_IND, AVCT_LCB_DEALLOC, AVCT_LCB_IDLE_ST},
158 /* LL_MSG_EVT */ {AVCT_LCB_MSG_IND, AVCT_LCB_IGNORE, AVCT_LCB_OPEN_ST},
159 /* LL_CONG_EVT */ {AVCT_LCB_CONG_IND, AVCT_LCB_IGNORE, AVCT_LCB_OPEN_ST}
160 };
161
162 /* state table for closing state */
163 const UINT8 avct_lcb_st_closing[][AVCT_LCB_NUM_COLS] = {
164 /* Event Action 1 Action 2 Next state */
165 /* UL_BIND_EVT */ {AVCT_LCB_BIND_FAIL, AVCT_LCB_IGNORE, AVCT_LCB_CLOSING_ST},
166 /* UL_UNBIND_EVT */ {AVCT_LCB_IGNORE, AVCT_LCB_IGNORE, AVCT_LCB_CLOSING_ST},
167 /* UL_MSG_EVT */ {AVCT_LCB_DISCARD_MSG, AVCT_LCB_IGNORE, AVCT_LCB_CLOSING_ST},
168 /* INT_CLOSE_EVT */ {AVCT_LCB_IGNORE, AVCT_LCB_IGNORE, AVCT_LCB_CLOSING_ST},
169 /* LL_OPEN_EVT */ {AVCT_LCB_IGNORE, AVCT_LCB_IGNORE, AVCT_LCB_CLOSING_ST},
170 /* LL_CLOSE_EVT */ {AVCT_LCB_CLOSE_CFM, AVCT_LCB_DEALLOC, AVCT_LCB_IDLE_ST},
171 /* LL_MSG_EVT */ {AVCT_LCB_FREE_MSG_IND, AVCT_LCB_IGNORE, AVCT_LCB_CLOSING_ST},
172 /* LL_CONG_EVT */ {AVCT_LCB_IGNORE, AVCT_LCB_IGNORE, AVCT_LCB_CLOSING_ST}
173 };
174
175 /* type for state table */
176 typedef const UINT8 (*tAVCT_LCB_ST_TBL)[AVCT_LCB_NUM_COLS];
177
178 /* state table */
179 const tAVCT_LCB_ST_TBL avct_lcb_st_tbl[] = {
180 avct_lcb_st_idle,
181 avct_lcb_st_opening,
182 avct_lcb_st_open,
183 avct_lcb_st_closing
184 };
185
186 /*******************************************************************************
187 **
188 ** Function avct_lcb_event
189 **
190 ** Description State machine event handling function for lcb
191 **
192 **
193 ** Returns Nothing.
194 **
195 *******************************************************************************/
avct_lcb_event(tAVCT_LCB * p_lcb,UINT8 event,tAVCT_LCB_EVT * p_data)196 void avct_lcb_event(tAVCT_LCB *p_lcb, UINT8 event, tAVCT_LCB_EVT *p_data)
197 {
198 tAVCT_LCB_ST_TBL state_table;
199 UINT8 action;
200 int i;
201
202 #if BT_TRACE_VERBOSE == TRUE
203 AVCT_TRACE_EVENT("LCB lcb=%d event=%s state=%s", p_lcb->allocated, avct_lcb_evt_str[event], avct_lcb_st_str[p_lcb->state]);
204 #else
205 AVCT_TRACE_EVENT("LCB lcb=%d event=%d state=%d", p_lcb->allocated, event, p_lcb->state);
206 #endif
207
208 /* look up the state table for the current state */
209 state_table = avct_lcb_st_tbl[p_lcb->state];
210
211 /* set next state */
212 p_lcb->state = state_table[event][AVCT_LCB_NEXT_STATE];
213
214 /* execute action functions */
215 for (i = 0; i < AVCT_LCB_ACTIONS; i++) {
216 if ((action = state_table[event][i]) != AVCT_LCB_IGNORE) {
217 (*avct_lcb_action[action])(p_lcb, p_data);
218 } else {
219 break;
220 }
221 }
222 }
223
224 /*******************************************************************************
225 **
226 ** Function avct_bcb_event
227 **
228 ** Description State machine event handling function for lcb
229 **
230 **
231 ** Returns Nothing.
232 **
233 *******************************************************************************/
234 #if (AVCT_BROWSE_INCLUDED == TRUE)
avct_bcb_event(tAVCT_BCB * p_bcb,UINT8 event,tAVCT_LCB_EVT * p_data)235 void avct_bcb_event(tAVCT_BCB *p_bcb, UINT8 event, tAVCT_LCB_EVT *p_data)
236 {
237 tAVCT_LCB_ST_TBL state_table;
238 UINT8 action;
239 int i;
240
241 #if BT_TRACE_VERBOSE == TRUE
242 AVCT_TRACE_EVENT("BCB lcb=%d event=%s state=%s", p_bcb->allocated, avct_lcb_evt_str[event], avct_lcb_st_str[p_bcb->state]);
243 #else
244 AVCT_TRACE_EVENT("BCB lcb=%d event=%d state=%d", p_bcb->allocated, event, p_bcb->state);
245 #endif
246
247 /* look up the state table for the current state */
248 state_table = avct_lcb_st_tbl[p_bcb->state];
249
250 /* set next state */
251 p_bcb->state = state_table[event][AVCT_LCB_NEXT_STATE];
252
253 /* execute action functions */
254 for (i = 0; i < AVCT_LCB_ACTIONS; i++) {
255 if ((action = state_table[event][i]) != AVCT_LCB_IGNORE) {
256 (*avct_bcb_action[action])(p_bcb, p_data);
257 } else {
258 break;
259 }
260 }
261 }
262 #endif
263
264 /*******************************************************************************
265 **
266 ** Function avct_lcb_by_bd
267 **
268 ** Description This lookup function finds the lcb for a BD address.
269 **
270 **
271 ** Returns pointer to the lcb, or NULL if none found.
272 **
273 *******************************************************************************/
avct_lcb_by_bd(BD_ADDR bd_addr)274 tAVCT_LCB *avct_lcb_by_bd(BD_ADDR bd_addr)
275 {
276 tAVCT_LCB *p_lcb = &avct_cb.lcb[0];
277 int i;
278
279 for (i = 0; i < AVCT_NUM_LINKS; i++, p_lcb++) {
280 /* if allocated lcb has matching lcb */
281 if (p_lcb->allocated && (!memcmp(p_lcb->peer_addr, bd_addr, BD_ADDR_LEN))) {
282 break;
283 }
284 }
285
286 if (i == AVCT_NUM_LINKS) {
287 /* if no lcb found */
288 p_lcb = NULL;
289
290 AVCT_TRACE_DEBUG("No lcb for addr %02x-%02x-%02x-%02x-%02x-%02x",
291 bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
292 }
293 return p_lcb;
294 }
295
296 /*******************************************************************************
297 **
298 ** Function avct_lcb_alloc
299 **
300 ** Description Allocate a link control block.
301 **
302 **
303 ** Returns pointer to the lcb, or NULL if none could be allocated.
304 **
305 *******************************************************************************/
avct_lcb_alloc(BD_ADDR bd_addr)306 tAVCT_LCB *avct_lcb_alloc(BD_ADDR bd_addr)
307 {
308 tAVCT_LCB *p_lcb = &avct_cb.lcb[0];
309 int i;
310
311 for (i = 0; i < AVCT_NUM_LINKS; i++, p_lcb++) {
312 if (!p_lcb->allocated) {
313 p_lcb->allocated = (UINT8)(i + 1);
314 memcpy(p_lcb->peer_addr, bd_addr, BD_ADDR_LEN);
315 AVCT_TRACE_DEBUG("avct_lcb_alloc %d", p_lcb->allocated);
316 p_lcb->tx_q = fixed_queue_new(QUEUE_SIZE_MAX);
317 break;
318 }
319 }
320
321 if (i == AVCT_NUM_LINKS) {
322 /* out of lcbs */
323 p_lcb = NULL;
324 AVCT_TRACE_WARNING("Out of lcbs");
325 }
326 return p_lcb;
327 }
328
329 /*******************************************************************************
330 **
331 ** Function avct_lcb_dealloc
332 **
333 ** Description Deallocate a link control block.
334 **
335 **
336 ** Returns void.
337 **
338 *******************************************************************************/
avct_lcb_dealloc(tAVCT_LCB * p_lcb,tAVCT_LCB_EVT * p_data)339 void avct_lcb_dealloc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
340 {
341 UNUSED(p_data);
342
343 AVCT_TRACE_DEBUG("%s allocated: %d", __func__, p_lcb->allocated);
344
345 // Check if the LCB is still referenced
346
347 tAVCT_CCB *p_ccb = &avct_cb.ccb[0];
348 for (size_t i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
349 {
350 if (p_ccb->allocated && p_ccb->p_lcb == p_lcb)
351 {
352 AVCT_TRACE_DEBUG("%s LCB in use; lcb index: %d", __func__, i);
353 return;
354 }
355 }
356
357 // If not, de-allocate now...
358
359 AVCT_TRACE_DEBUG("%s Freeing LCB", __func__);
360 osi_free(p_lcb->p_rx_msg);
361 fixed_queue_free(p_lcb->tx_q, NULL);
362 memset(p_lcb, 0, sizeof(tAVCT_LCB));
363 }
364
365 /*******************************************************************************
366 **
367 ** Function avct_lcb_by_lcid
368 **
369 ** Description Find the LCB associated with the L2CAP LCID
370 **
371 **
372 ** Returns pointer to the lcb, or NULL if none found.
373 **
374 *******************************************************************************/
avct_lcb_by_lcid(UINT16 lcid)375 tAVCT_LCB *avct_lcb_by_lcid(UINT16 lcid)
376 {
377 tAVCT_LCB *p_lcb = &avct_cb.lcb[0];
378 int i;
379
380 for (i = 0; i < AVCT_NUM_LINKS; i++, p_lcb++) {
381 if (p_lcb->allocated && ((p_lcb->ch_lcid == lcid) || (p_lcb->conflict_lcid == lcid))) {
382 break;
383 }
384 }
385
386 if (i == AVCT_NUM_LINKS) {
387 /* out of lcbs */
388 p_lcb = NULL;
389 AVCT_TRACE_WARNING("No lcb for lcid %x", lcid);
390 }
391
392 return p_lcb;
393 }
394
395 /*******************************************************************************
396 **
397 ** Function avct_lcb_has_pid
398 **
399 ** Description See if any ccbs on this lcb have a particular pid.
400 **
401 **
402 ** Returns Pointer to CCB if PID found, NULL otherwise.
403 **
404 *******************************************************************************/
avct_lcb_has_pid(tAVCT_LCB * p_lcb,UINT16 pid)405 tAVCT_CCB *avct_lcb_has_pid(tAVCT_LCB *p_lcb, UINT16 pid)
406 {
407 tAVCT_CCB *p_ccb = &avct_cb.ccb[0];
408 int i;
409
410 for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
411 if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb) && (p_ccb->cc.pid == pid)) {
412 return p_ccb;
413 }
414 }
415 return NULL;
416 }
417
418 /*******************************************************************************
419 **
420 ** Function avct_lcb_last_ccb
421 **
422 ** Description See if given ccb is only one on the lcb.
423 **
424 **
425 ** Returns TRUE if ccb is last, FALSE otherwise.
426 **
427 *******************************************************************************/
avct_lcb_last_ccb(tAVCT_LCB * p_lcb,tAVCT_CCB * p_ccb_last)428 BOOLEAN avct_lcb_last_ccb(tAVCT_LCB *p_lcb, tAVCT_CCB *p_ccb_last)
429 {
430 tAVCT_CCB *p_ccb = &avct_cb.ccb[0];
431 int i;
432
433 AVCT_TRACE_DEBUG("avct_lcb_last_ccb");
434 for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
435 AVCT_TRACE_DEBUG("%x: aloc:%d, lcb:%p/%p, ccb:%p/%p",
436 i, p_ccb->allocated, p_ccb->p_lcb, p_lcb, p_ccb, p_ccb_last);
437 if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb) && (p_ccb != p_ccb_last)) {
438 return FALSE;
439 }
440 }
441 return TRUE;
442 }
443
444
445 #endif /* #if (defined(AVCT_INCLUDED) && AVCT_INCLUDED == TRUE) */
446