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