1 /******************************************************************************
2 *
3 * Copyright (C) 2004-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 file contains the PAN main functions and state machine.
22 *
23 ******************************************************************************/
24
25 #include "bt_target.h"
26
27 #if (BTA_PAN_INCLUDED == TRUE)
28
29 #include <string.h>
30
31 #include "bt_common.h"
32 #include "bta_api.h"
33 #include "bta_pan_api.h"
34 #include "bta_pan_int.h"
35 #include "bta_sys.h"
36 #include "osi/include/osi.h"
37 #include "pan_api.h"
38 #include "utl.h"
39
40 /*****************************************************************************
41 * Constants and types
42 ****************************************************************************/
43
44 /* state machine action enumeration list */
45 enum {
46 BTA_PAN_API_CLOSE,
47 BTA_PAN_TX_PATH,
48 BTA_PAN_RX_PATH,
49 BTA_PAN_TX_FLOW,
50 BTA_PAN_WRITE_BUF,
51 BTA_PAN_CONN_OPEN,
52 BTA_PAN_CONN_CLOSE,
53 BTA_PAN_FREE_BUF,
54 BTA_PAN_IGNORE
55 };
56
57 /* type for action functions */
58 typedef void (*tBTA_PAN_ACTION)(tBTA_PAN_SCB* p_scb, tBTA_PAN_DATA* p_data);
59
60 /* action function list */
61 const tBTA_PAN_ACTION bta_pan_action[] = {
62 bta_pan_api_close, bta_pan_tx_path, bta_pan_rx_path, bta_pan_tx_flow,
63 bta_pan_write_buf, bta_pan_conn_open, bta_pan_conn_close, bta_pan_free_buf,
64
65 };
66
67 /* state table information */
68 #define BTA_PAN_ACTIONS 1 /* number of actions */
69 #define BTA_PAN_NEXT_STATE 1 /* position of next state */
70 #define BTA_PAN_NUM_COLS 2 /* number of columns in state tables */
71
72 /* state table for listen state */
73 const uint8_t bta_pan_st_idle[][BTA_PAN_NUM_COLS] = {
74 /* API_CLOSE */ {BTA_PAN_API_CLOSE, BTA_PAN_IDLE_ST},
75 /* CI_TX_READY */ {BTA_PAN_IGNORE, BTA_PAN_IDLE_ST},
76 /* CI_RX_READY */ {BTA_PAN_IGNORE, BTA_PAN_IDLE_ST},
77 /* CI_TX_FLOW */ {BTA_PAN_IGNORE, BTA_PAN_IDLE_ST},
78 /* CI_RX_WRITE */ {BTA_PAN_IGNORE, BTA_PAN_IDLE_ST},
79 /* CI_RX_WRITEBUF */ {BTA_PAN_IGNORE, BTA_PAN_IDLE_ST},
80 /* PAN_CONN_OPEN */ {BTA_PAN_CONN_OPEN, BTA_PAN_OPEN_ST},
81 /* PAN_CONN_CLOSE */ {BTA_PAN_CONN_OPEN, BTA_PAN_IDLE_ST},
82 /* FLOW_ENABLE */ {BTA_PAN_IGNORE, BTA_PAN_IDLE_ST},
83 /* BNEP_DATA */ {BTA_PAN_IGNORE, BTA_PAN_IDLE_ST}
84
85 };
86
87 /* state table for open state */
88 const uint8_t bta_pan_st_open[][BTA_PAN_NUM_COLS] = {
89 /* API_CLOSE */ {BTA_PAN_API_CLOSE, BTA_PAN_OPEN_ST},
90 /* CI_TX_READY */ {BTA_PAN_TX_PATH, BTA_PAN_OPEN_ST},
91 /* CI_RX_READY */ {BTA_PAN_RX_PATH, BTA_PAN_OPEN_ST},
92 /* CI_TX_FLOW */ {BTA_PAN_TX_FLOW, BTA_PAN_OPEN_ST},
93 /* CI_RX_WRITE */ {BTA_PAN_IGNORE, BTA_PAN_OPEN_ST},
94 /* CI_RX_WRITEBUF */ {BTA_PAN_WRITE_BUF, BTA_PAN_OPEN_ST},
95 /* PAN_CONN_OPEN */ {BTA_PAN_IGNORE, BTA_PAN_OPEN_ST},
96 /* PAN_CONN_CLOSE */ {BTA_PAN_CONN_CLOSE, BTA_PAN_IDLE_ST},
97 /* FLOW_ENABLE */ {BTA_PAN_RX_PATH, BTA_PAN_OPEN_ST},
98 /* BNEP_DATA */ {BTA_PAN_TX_PATH, BTA_PAN_OPEN_ST}};
99
100 /* state table for closing state */
101 const uint8_t bta_pan_st_closing[][BTA_PAN_NUM_COLS] = {
102 /* API_CLOSE */ {BTA_PAN_IGNORE, BTA_PAN_CLOSING_ST},
103 /* CI_TX_READY */ {BTA_PAN_TX_PATH, BTA_PAN_CLOSING_ST},
104 /* CI_RX_READY */ {BTA_PAN_RX_PATH, BTA_PAN_CLOSING_ST},
105 /* CI_TX_FLOW */ {BTA_PAN_TX_FLOW, BTA_PAN_CLOSING_ST},
106 /* CI_RX_WRITE */ {BTA_PAN_IGNORE, BTA_PAN_CLOSING_ST},
107 /* CI_RX_WRITEBUF */ {BTA_PAN_FREE_BUF, BTA_PAN_CLOSING_ST},
108 /* PAN_CONN_OPEN */ {BTA_PAN_IGNORE, BTA_PAN_CLOSING_ST},
109 /* PAN_CONN_CLOSE */ {BTA_PAN_CONN_CLOSE, BTA_PAN_IDLE_ST},
110 /* FLOW_ENABLE */ {BTA_PAN_RX_PATH, BTA_PAN_CLOSING_ST},
111 /* BNEP_DATA */ {BTA_PAN_TX_PATH, BTA_PAN_CLOSING_ST}};
112
113 /* type for state table */
114 typedef const uint8_t (*tBTA_PAN_ST_TBL)[BTA_PAN_NUM_COLS];
115
116 /* state table */
117 const tBTA_PAN_ST_TBL bta_pan_st_tbl[] = {bta_pan_st_idle, bta_pan_st_open,
118 bta_pan_st_closing};
119
120 /*****************************************************************************
121 * Global data
122 ****************************************************************************/
123
124 /* PAN control block */
125 tBTA_PAN_CB bta_pan_cb;
126
127 /*******************************************************************************
128 *
129 * Function bta_pan_scb_alloc
130 *
131 * Description Allocate a PAN server control block.
132 *
133 *
134 * Returns pointer to the scb, or NULL if none could be allocated.
135 *
136 ******************************************************************************/
bta_pan_scb_alloc(void)137 tBTA_PAN_SCB* bta_pan_scb_alloc(void) {
138 tBTA_PAN_SCB* p_scb = &bta_pan_cb.scb[0];
139 int i;
140
141 for (i = 0; i < BTA_PAN_NUM_CONN; i++, p_scb++) {
142 if (!p_scb->in_use) {
143 p_scb->in_use = true;
144 APPL_TRACE_DEBUG("bta_pan_scb_alloc %d", i);
145 break;
146 }
147 }
148
149 if (i == BTA_PAN_NUM_CONN) {
150 /* out of scbs */
151 p_scb = NULL;
152 APPL_TRACE_WARNING("Out of scbs");
153 }
154 return p_scb;
155 }
156
157 /*******************************************************************************
158 *
159 * Function bta_pan_sm_execute
160 *
161 * Description State machine event handling function for PAN
162 *
163 *
164 * Returns void
165 *
166 ******************************************************************************/
bta_pan_sm_execute(tBTA_PAN_SCB * p_scb,uint16_t event,tBTA_PAN_DATA * p_data)167 static void bta_pan_sm_execute(tBTA_PAN_SCB* p_scb, uint16_t event,
168 tBTA_PAN_DATA* p_data) {
169 tBTA_PAN_ST_TBL state_table;
170 uint8_t action;
171 int i;
172
173 APPL_TRACE_EVENT("PAN scb=%d event=0x%x state=%d", bta_pan_scb_to_idx(p_scb),
174 event, p_scb->state);
175
176 /* look up the state table for the current state */
177 state_table = bta_pan_st_tbl[p_scb->state];
178
179 event &= 0x00FF;
180
181 /* set next state */
182 p_scb->state = state_table[event][BTA_PAN_NEXT_STATE];
183
184 /* execute action functions */
185 for (i = 0; i < BTA_PAN_ACTIONS; i++) {
186 action = state_table[event][i];
187 if (action != BTA_PAN_IGNORE) {
188 (*bta_pan_action[action])(p_scb, p_data);
189 } else {
190 break;
191 }
192 }
193 }
194
195 /*******************************************************************************
196 *
197 * Function bta_pan_api_enable
198 *
199 * Description Handle an API enable event.
200 *
201 *
202 * Returns void
203 *
204 ******************************************************************************/
bta_pan_api_enable(tBTA_PAN_DATA * p_data)205 static void bta_pan_api_enable(tBTA_PAN_DATA* p_data) {
206 /* initialize control block */
207 memset(&bta_pan_cb, 0, sizeof(bta_pan_cb));
208
209 /* store callback function */
210 bta_pan_cb.p_cback = p_data->api_enable.p_cback;
211 bta_pan_enable(p_data);
212 }
213
214 /*******************************************************************************
215 *
216 * Function bta_pan_api_disable
217 *
218 * Description Handle an API disable event.
219 *
220 *
221 * Returns void
222 *
223 ******************************************************************************/
bta_pan_api_disable(UNUSED_ATTR tBTA_PAN_DATA * p_data)224 static void bta_pan_api_disable(UNUSED_ATTR tBTA_PAN_DATA* p_data) {
225 bta_pan_disable();
226 }
227
228 /*******************************************************************************
229 *
230 * Function bta_pan_api_open
231 *
232 * Description Handle an API listen event.
233 *
234 *
235 * Returns void
236 *
237 ******************************************************************************/
bta_pan_api_open(tBTA_PAN_DATA * p_data)238 static void bta_pan_api_open(tBTA_PAN_DATA* p_data) {
239 tBTA_PAN_SCB* p_scb;
240 tBTA_PAN bta_pan;
241
242 /* allocate an scb */
243 p_scb = bta_pan_scb_alloc();
244 if (p_scb != NULL) {
245 bta_pan_open(p_scb, p_data);
246 } else {
247 bta_pan.open.bd_addr = p_data->api_open.bd_addr;
248 bta_pan.open.status = BTA_PAN_FAIL;
249 bta_pan_cb.p_cback(BTA_PAN_OPEN_EVT, &bta_pan);
250 }
251 }
252 /*******************************************************************************
253 *
254 * Function bta_pan_scb_dealloc
255 *
256 * Description Deallocate a link control block.
257 *
258 *
259 * Returns void
260 *
261 ******************************************************************************/
bta_pan_scb_dealloc(tBTA_PAN_SCB * p_scb)262 void bta_pan_scb_dealloc(tBTA_PAN_SCB* p_scb) {
263 APPL_TRACE_DEBUG("bta_pan_scb_dealloc %d", bta_pan_scb_to_idx(p_scb));
264 fixed_queue_free(p_scb->data_queue, NULL);
265 memset(p_scb, 0, sizeof(tBTA_PAN_SCB));
266 }
267
268 /*******************************************************************************
269 *
270 * Function bta_pan_scb_to_idx
271 *
272 * Description Given a pointer to an scb, return its index.
273 *
274 *
275 * Returns Index of scb.
276 *
277 ******************************************************************************/
bta_pan_scb_to_idx(tBTA_PAN_SCB * p_scb)278 uint8_t bta_pan_scb_to_idx(tBTA_PAN_SCB* p_scb) {
279 return ((uint8_t)(p_scb - bta_pan_cb.scb)) + 1;
280 }
281
282 /*******************************************************************************
283 *
284 * Function bta_pan_scb_by_handle
285 *
286 * Description Find scb associated with handle.
287 *
288 *
289 * Returns Pointer to scb or NULL if not found.
290 *
291 ******************************************************************************/
bta_pan_scb_by_handle(uint16_t handle)292 tBTA_PAN_SCB* bta_pan_scb_by_handle(uint16_t handle) {
293 tBTA_PAN_SCB* p_scb = &bta_pan_cb.scb[0];
294 uint8_t i;
295
296 for (i = 0; i < BTA_PAN_NUM_CONN; i++, p_scb++) {
297 if (p_scb->handle == handle) {
298 return p_scb;
299 ;
300 }
301 }
302
303 APPL_TRACE_WARNING("No scb for handle %d", handle);
304
305 return NULL;
306 }
307
308 /*******************************************************************************
309 *
310 * Function bta_pan_hdl_event
311 *
312 * Description Data gateway main event handling function.
313 *
314 *
315 * Returns void
316 *
317 ******************************************************************************/
bta_pan_hdl_event(BT_HDR * p_msg)318 bool bta_pan_hdl_event(BT_HDR* p_msg) {
319 tBTA_PAN_SCB* p_scb;
320 bool freebuf = true;
321
322 switch (p_msg->event) {
323 /* handle enable event */
324 case BTA_PAN_API_ENABLE_EVT:
325 bta_pan_api_enable((tBTA_PAN_DATA*)p_msg);
326 break;
327
328 /* handle disable event */
329 case BTA_PAN_API_DISABLE_EVT:
330 bta_pan_api_disable((tBTA_PAN_DATA*)p_msg);
331 break;
332
333 /* handle set role event */
334 case BTA_PAN_API_SET_ROLE_EVT:
335 bta_pan_set_role((tBTA_PAN_DATA*)p_msg);
336 break;
337
338 /* handle open event */
339 case BTA_PAN_API_OPEN_EVT:
340 bta_pan_api_open((tBTA_PAN_DATA*)p_msg);
341 break;
342
343 /* events that require buffer not be released */
344 case BTA_PAN_CI_RX_WRITEBUF_EVT:
345 freebuf = false;
346 p_scb = bta_pan_scb_by_handle(p_msg->layer_specific);
347 if (p_scb != NULL) {
348 bta_pan_sm_execute(p_scb, p_msg->event, (tBTA_PAN_DATA*)p_msg);
349 }
350 break;
351
352 /* all other events */
353 default:
354 p_scb = bta_pan_scb_by_handle(p_msg->layer_specific);
355 if (p_scb != NULL) {
356 bta_pan_sm_execute(p_scb, p_msg->event, (tBTA_PAN_DATA*)p_msg);
357 }
358 break;
359 }
360 return freebuf;
361 }
362 #endif /* BTA_PAN_INCLUDED */
363