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 */
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};
56
57/* type for action functions */
58typedef void (*tBTA_PAN_ACTION)(tBTA_PAN_SCB* p_scb, tBTA_PAN_DATA* p_data);
59
60/* action function list */
61const 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 */
73const 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 */
88const 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 */
101const 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 */
114typedef const uint8_t (*tBTA_PAN_ST_TBL)[BTA_PAN_NUM_COLS];
115
116/* state table */
117const 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 */
125tBTA_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 ******************************************************************************/
137tBTA_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 ******************************************************************************/
167static 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 ******************************************************************************/
205static 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 ******************************************************************************/
224static 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 ******************************************************************************/
238static 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 ******************************************************************************/
262void 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 ******************************************************************************/
278uint8_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 ******************************************************************************/
292tBTA_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 ******************************************************************************/
318bool 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