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