1/******************************************************************************
2 *
3 *  Copyright (C) 2001-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 main BNEP functions
22 *
23 ******************************************************************************/
24
25#include "bt_target.h"
26#include <stdlib.h>
27#include <string.h>
28#include <stdio.h>
29
30#include "gki.h"
31#include "bt_types.h"
32#include "l2cdefs.h"
33#include "hcidefs.h"
34#include "hcimsgs.h"
35
36#include "l2c_api.h"
37#include "l2cdefs.h"
38
39#include "btu.h"
40#include "btm_api.h"
41
42#include "bnep_api.h"
43#include "bnep_int.h"
44#include "bt_utils.h"
45
46
47/********************************************************************************/
48/*                       G L O B A L    B N E P       D A T A                   */
49/********************************************************************************/
50#if BNEP_DYNAMIC_MEMORY == FALSE
51tBNEP_CB   bnep_cb;
52#endif
53
54const UINT16 bnep_frame_hdr_sizes[] = {14, 1, 2, 8, 8};
55
56/********************************************************************************/
57/*              L O C A L    F U N C T I O N     P R O T O T Y P E S            */
58/********************************************************************************/
59static void bnep_connect_ind (BD_ADDR  bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id);
60static void bnep_connect_cfm (UINT16 l2cap_cid, UINT16 result);
61static void bnep_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
62static void bnep_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
63static void bnep_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed);
64static void bnep_disconnect_cfm (UINT16 l2cap_cid, UINT16 result);
65static void bnep_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg);
66static void bnep_congestion_ind (UINT16 lcid, BOOLEAN is_congested);
67
68static void bnep_read_addr_cb (void *p_bda);
69
70
71/*******************************************************************************
72**
73** Function         bnep_register_with_l2cap
74**
75** Description      This function registers BNEP PSM with L2CAP
76**
77** Returns          void
78**
79*******************************************************************************/
80tBNEP_RESULT bnep_register_with_l2cap (void)
81{
82    /* Initialize the L2CAP configuration. We only care about MTU and flush */
83    memset(&bnep_cb.l2cap_my_cfg, 0, sizeof(tL2CAP_CFG_INFO));
84
85    bnep_cb.l2cap_my_cfg.mtu_present            = TRUE;
86    bnep_cb.l2cap_my_cfg.mtu                    = BNEP_MTU_SIZE;
87    bnep_cb.l2cap_my_cfg.flush_to_present       = TRUE;
88    bnep_cb.l2cap_my_cfg.flush_to               = BNEP_FLUSH_TO;
89
90    bnep_cb.reg_info.pL2CA_ConnectInd_Cb        = bnep_connect_ind;
91    bnep_cb.reg_info.pL2CA_ConnectCfm_Cb        = bnep_connect_cfm;
92    bnep_cb.reg_info.pL2CA_ConfigInd_Cb         = bnep_config_ind;
93    bnep_cb.reg_info.pL2CA_ConfigCfm_Cb         = bnep_config_cfm;
94    bnep_cb.reg_info.pL2CA_DisconnectInd_Cb     = bnep_disconnect_ind;
95    bnep_cb.reg_info.pL2CA_DisconnectCfm_Cb     = bnep_disconnect_cfm;
96    bnep_cb.reg_info.pL2CA_DataInd_Cb           = bnep_data_ind;
97    bnep_cb.reg_info.pL2CA_CongestionStatus_Cb  = bnep_congestion_ind;
98
99    /* Now, register with L2CAP */
100    if (!L2CA_Register (BT_PSM_BNEP, &bnep_cb.reg_info))
101    {
102        BNEP_TRACE_ERROR ("BNEP - Registration failed");
103        return BNEP_SECURITY_FAIL;
104    }
105
106    return BNEP_SUCCESS;
107}
108
109
110/*******************************************************************************
111**
112** Function         bnep_connect_ind
113**
114** Description      This function handles an inbound connection indication
115**                  from L2CAP. This is the case where we are acting as a
116**                  server.
117**
118** Returns          void
119**
120*******************************************************************************/
121static void bnep_connect_ind (BD_ADDR  bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id)
122{
123    tBNEP_CONN    *p_bcb = bnepu_find_bcb_by_bd_addr (bd_addr);
124    UNUSED(psm);
125
126    /* If we are not acting as server, or already have a connection, or have */
127    /* no more resources to handle the connection, reject the connection.    */
128    if (!(bnep_cb.profile_registered) || (p_bcb)
129     || ((p_bcb = bnepu_allocate_bcb(bd_addr)) == NULL))
130    {
131        L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_NO_PSM, 0);
132        return;
133    }
134
135    /* Transition to the next appropriate state, waiting for config setup. */
136    p_bcb->con_state = BNEP_STATE_CFG_SETUP;
137
138    /* Save the L2CAP Channel ID. */
139    p_bcb->l2cap_cid = l2cap_cid;
140
141    /* Send response to the L2CAP layer. */
142    L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK);
143
144    /* Send a Configuration Request. */
145    L2CA_ConfigReq (l2cap_cid, &bnep_cb.l2cap_my_cfg);
146
147    /* Start timer waiting for config setup */
148    btu_start_timer (&p_bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_CONN_TIMEOUT);
149
150    BNEP_TRACE_EVENT("BNEP - Rcvd L2CAP conn ind, CID: 0x%x", p_bcb->l2cap_cid);
151
152}
153
154
155/*******************************************************************************
156**
157** Function         bnep_connect_cfm
158**
159** Description      This function handles the connect confirm events
160**                  from L2CAP. This is the case when we are acting as a
161**                  client and have sent a connect request.
162**
163** Returns          void
164**
165*******************************************************************************/
166static void bnep_connect_cfm (UINT16 l2cap_cid, UINT16 result)
167{
168    tBNEP_CONN    *bcb;
169
170    /* Find CCB based on CID */
171    if ((bcb = bnepu_find_bcb_by_cid (l2cap_cid)) == NULL)
172    {
173        BNEP_TRACE_WARNING ("BNEP - Rcvd conn cnf for unknown CID 0x%x", l2cap_cid);
174        return;
175    }
176
177    /* If the connection response contains success status, then */
178    /* Transition to the next state and startup the timer.      */
179    if ((result == L2CAP_CONN_OK) && (bcb->con_state == BNEP_STATE_CONN_START))
180    {
181        bcb->con_state = BNEP_STATE_CFG_SETUP;
182
183        /* Send a Configuration Request. */
184        L2CA_ConfigReq (l2cap_cid, &bnep_cb.l2cap_my_cfg);
185
186        /* Start timer waiting for config results */
187        btu_start_timer (&bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_CONN_TIMEOUT);
188
189        BNEP_TRACE_EVENT ("BNEP - got conn cnf, sent cfg req, CID: 0x%x", bcb->l2cap_cid);
190    }
191    else
192    {
193        BNEP_TRACE_WARNING ("BNEP - Rcvd conn cnf with error: 0x%x  CID 0x%x", result, bcb->l2cap_cid);
194
195        /* Tell the upper layer, if he has a callback */
196        if (bnep_cb.p_conn_state_cb &&
197            bcb->con_flags & BNEP_FLAGS_IS_ORIG)
198        {
199            (*bnep_cb.p_conn_state_cb) (bcb->handle, bcb->rem_bda, BNEP_CONN_FAILED, FALSE);
200        }
201
202        bnepu_release_bcb (bcb);
203    }
204}
205
206/*******************************************************************************
207**
208** Function         bnep_config_ind
209**
210** Description      This function processes the L2CAP configuration indication
211**                  event.
212**
213** Returns          void
214**
215*******************************************************************************/
216static void bnep_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg)
217{
218    tBNEP_CONN    *p_bcb;
219    UINT16        result, mtu = 0;
220
221    /* Find CCB based on CID */
222    if ((p_bcb = bnepu_find_bcb_by_cid (l2cap_cid)) == NULL)
223    {
224        BNEP_TRACE_WARNING ("BNEP - Rcvd L2CAP cfg ind, unknown CID: 0x%x", l2cap_cid);
225        return;
226    }
227
228    BNEP_TRACE_EVENT ("BNEP - Rcvd cfg ind, CID: 0x%x", l2cap_cid);
229
230    /* Remember the remote MTU size */
231    if ((!p_cfg->mtu_present) || (p_cfg->mtu < BNEP_MIN_MTU_SIZE))
232    {
233        mtu                     = p_cfg->mtu;
234        p_cfg->flush_to_present = FALSE;
235        p_cfg->mtu_present      = TRUE;
236        p_cfg->mtu              = BNEP_MIN_MTU_SIZE;
237        p_cfg->result           = result = L2CAP_CFG_UNACCEPTABLE_PARAMS;
238    }
239    else
240    {
241        if (p_cfg->mtu > BNEP_MTU_SIZE)
242            p_bcb->rem_mtu_size = BNEP_MTU_SIZE;
243        else
244            p_bcb->rem_mtu_size = p_cfg->mtu;
245
246        /* For now, always accept configuration from the other side */
247        p_cfg->flush_to_present = FALSE;
248        p_cfg->mtu_present      = FALSE;
249        p_cfg->result           = result = L2CAP_CFG_OK;
250    }
251
252    L2CA_ConfigRsp (l2cap_cid, p_cfg);
253
254    if (result != L2CAP_CFG_OK)
255    {
256        BNEP_TRACE_EVENT ("BNEP - Rcvd cfg ind with bad MTU %d, CID: 0x%x", mtu, l2cap_cid);
257        return;
258    }
259
260    p_bcb->con_flags |= BNEP_FLAGS_HIS_CFG_DONE;
261
262    if (p_bcb->con_flags & BNEP_FLAGS_MY_CFG_DONE)
263    {
264        p_bcb->con_state = BNEP_STATE_SEC_CHECKING;
265
266        /* Start timer waiting for setup or response */
267        btu_start_timer (&p_bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_HOST_TIMEOUT);
268
269        if (p_bcb->con_flags & BNEP_FLAGS_IS_ORIG)
270        {
271            btm_sec_mx_access_request (p_bcb->rem_bda, BT_PSM_BNEP, TRUE,
272                                       BTM_SEC_PROTO_BNEP,
273                                       bnep_get_uuid32(&(p_bcb->src_uuid)),
274                                       &bnep_sec_check_complete, p_bcb);
275        }
276    }
277}
278
279
280/*******************************************************************************
281**
282** Function         bnep_config_cfm
283**
284** Description      This function processes the L2CAP configuration confirmation
285**                  event.
286**
287** Returns          void
288**
289*******************************************************************************/
290static void bnep_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg)
291{
292    tBNEP_CONN    *p_bcb;
293
294    BNEP_TRACE_EVENT ("BNEP - Rcvd cfg cfm, CID: 0x%x  Result: %d", l2cap_cid, p_cfg->result);
295
296    /* Find CCB based on CID */
297    if ((p_bcb = bnepu_find_bcb_by_cid (l2cap_cid)) == NULL)
298    {
299        BNEP_TRACE_WARNING ("BNEP - Rcvd L2CAP cfg ind, unknown CID: 0x%x", l2cap_cid);
300        return;
301    }
302
303    /* For now, always accept configuration from the other side */
304    if (p_cfg->result == L2CAP_CFG_OK)
305    {
306        p_bcb->con_flags |= BNEP_FLAGS_MY_CFG_DONE;
307
308        if (p_bcb->con_flags & BNEP_FLAGS_HIS_CFG_DONE)
309        {
310            p_bcb->con_state = BNEP_STATE_SEC_CHECKING;
311
312            /* Start timer waiting for setup or response */
313            btu_start_timer (&p_bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_HOST_TIMEOUT);
314
315            if (p_bcb->con_flags & BNEP_FLAGS_IS_ORIG)
316            {
317                btm_sec_mx_access_request (p_bcb->rem_bda, BT_PSM_BNEP, TRUE,
318                                           BTM_SEC_PROTO_BNEP,
319                                           bnep_get_uuid32(&(p_bcb->src_uuid)),
320                                           &bnep_sec_check_complete, p_bcb);
321            }
322        }
323    }
324    else
325    {
326        /* Tell the upper layer, if he has a callback */
327        if ((p_bcb->con_flags & BNEP_FLAGS_IS_ORIG) && (bnep_cb.p_conn_state_cb))
328        {
329            (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_CONN_FAILED_CFG, FALSE);
330        }
331
332        L2CA_DisconnectReq (p_bcb->l2cap_cid);
333
334        bnepu_release_bcb (p_bcb);
335    }
336}
337
338
339/*******************************************************************************
340**
341** Function         bnep_disconnect_ind
342**
343** Description      This function handles a disconnect event from L2CAP. If
344**                  requested to, we ack the disconnect before dropping the CCB
345**
346** Returns          void
347**
348*******************************************************************************/
349static void bnep_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed)
350{
351    tBNEP_CONN    *p_bcb;
352
353    if (ack_needed)
354        L2CA_DisconnectRsp (l2cap_cid);
355
356    /* Find CCB based on CID */
357    if ((p_bcb = bnepu_find_bcb_by_cid (l2cap_cid)) == NULL)
358    {
359        BNEP_TRACE_WARNING ("BNEP - Rcvd L2CAP disc, unknown CID: 0x%x", l2cap_cid);
360        return;
361    }
362
363    BNEP_TRACE_EVENT ("BNEP - Rcvd L2CAP disc, CID: 0x%x", l2cap_cid);
364
365    /* Tell the user if he has a callback */
366    if (p_bcb->con_state == BNEP_STATE_CONNECTED)
367    {
368        if (bnep_cb.p_conn_state_cb)
369            (*bnep_cb.p_conn_state_cb)(p_bcb->handle, p_bcb->rem_bda, BNEP_CONN_DISCONNECTED, FALSE);
370    }
371    else
372    {
373        if (((p_bcb->con_flags & BNEP_FLAGS_IS_ORIG) && (bnep_cb.p_conn_state_cb)) ||
374            p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)
375            (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_CONN_FAILED, FALSE);
376    }
377
378    bnepu_release_bcb (p_bcb);
379}
380
381
382
383/*******************************************************************************
384**
385** Function         bnep_disconnect_cfm
386**
387** Description      This function gets the disconnect confirm event from L2CAP
388**
389** Returns          void
390**
391*******************************************************************************/
392static void bnep_disconnect_cfm (UINT16 l2cap_cid, UINT16 result)
393{
394    BNEP_TRACE_EVENT ("BNEP - Rcvd L2CAP disc cfm, CID: 0x%x, Result 0x%x", l2cap_cid, result);
395}
396
397
398
399/*******************************************************************************
400**
401** Function         bnep_congestion_ind
402**
403** Description      This is a callback function called by L2CAP when
404**                  congestion status changes
405**
406*******************************************************************************/
407static void bnep_congestion_ind (UINT16 l2cap_cid, BOOLEAN is_congested)
408{
409    tBNEP_CONN    *p_bcb;
410
411    /* Find BCB based on CID */
412    if ((p_bcb = bnepu_find_bcb_by_cid (l2cap_cid)) == NULL)
413    {
414        BNEP_TRACE_WARNING ("BNEP - Rcvd L2CAP cong, unknown CID: 0x%x", l2cap_cid);
415        return;
416    }
417
418    if (is_congested)
419   {
420        p_bcb->con_flags |= BNEP_FLAGS_L2CAP_CONGESTED;
421       if(bnep_cb.p_tx_data_flow_cb)
422       {
423           bnep_cb.p_tx_data_flow_cb(p_bcb->handle, BNEP_TX_FLOW_OFF);
424       }
425   }
426    else
427    {
428        p_bcb->con_flags &= ~BNEP_FLAGS_L2CAP_CONGESTED;
429
430       if(bnep_cb.p_tx_data_flow_cb)
431       {
432           bnep_cb.p_tx_data_flow_cb(p_bcb->handle, BNEP_TX_FLOW_ON);
433       }
434
435        /* While not congested, send as many buffers as we can */
436        while (!(p_bcb->con_flags & BNEP_FLAGS_L2CAP_CONGESTED))
437        {
438            BT_HDR   *p_buf = (BT_HDR *)GKI_dequeue (&p_bcb->xmit_q);
439
440            if (!p_buf)
441                break;
442
443            L2CA_DataWrite (l2cap_cid, p_buf);
444        }
445    }
446}
447
448
449
450/*******************************************************************************
451**
452** Function         bnep_data_ind
453**
454** Description      This function is called when data is received from L2CAP.
455**                  if we are the originator of the connection, we are the SDP
456**                  client, and the received message is queued up for the client.
457**
458**                  If we are the destination of the connection, we are the SDP
459**                  server, so the message is passed to the server processing
460**                  function.
461**
462** Returns          void
463**
464*******************************************************************************/
465static void bnep_data_ind (UINT16 l2cap_cid, BT_HDR *p_buf)
466{
467    tBNEP_CONN    *p_bcb;
468    UINT8         *p = (UINT8 *)(p_buf + 1) + p_buf->offset;
469    UINT16        rem_len = p_buf->len;
470    UINT8         type, ctrl_type, ext_type = 0;
471    BOOLEAN       extension_present, fw_ext_present;
472    UINT16        protocol = 0;
473    UINT8         *p_src_addr, *p_dst_addr;
474
475
476    /* Find CCB based on CID */
477    if ((p_bcb = bnepu_find_bcb_by_cid (l2cap_cid)) == NULL)
478    {
479        BNEP_TRACE_WARNING ("BNEP - Rcvd L2CAP data, unknown CID: 0x%x", l2cap_cid);
480        GKI_freebuf (p_buf);
481        return;
482    }
483
484    /* Get the type and extension bits */
485    type = *p++;
486    extension_present = type >> 7;
487    type &= 0x7f;
488    if ((rem_len <= bnep_frame_hdr_sizes[type]) || (rem_len > BNEP_MTU_SIZE))
489    {
490        BNEP_TRACE_EVENT ("BNEP - rcvd frame, bad len: %d  type: 0x%02x", p_buf->len, type);
491        GKI_freebuf (p_buf);
492        return;
493    }
494
495    rem_len--;
496
497    if ((p_bcb->con_state != BNEP_STATE_CONNECTED) &&
498        (!(p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)) &&
499        (type != BNEP_FRAME_CONTROL))
500    {
501        BNEP_TRACE_WARNING ("BNEP - Ignored L2CAP data while in state: %d, CID: 0x%x",
502                            p_bcb->con_state, l2cap_cid);
503
504        if (extension_present)
505        {
506            /*
507            ** When there is no connection if a data packet is received
508            ** with unknown control extension headers then those should be processed
509            ** according to complain/ignore law
510            */
511            UINT8       ext, length, *p_data;
512            UINT16      org_len, new_len;
513            /* parse the extension headers and process unknown control headers */
514            org_len = rem_len;
515            new_len = 0;
516            p_data  = p;
517            do {
518
519                ext     = *p++;
520                length  = *p++;
521                p += length;
522
523                if ((!(ext & 0x7F)) && (*p > BNEP_FILTER_MULTI_ADDR_RESPONSE_MSG))
524                    bnep_send_command_not_understood (p_bcb, *p);
525
526                new_len += (length + 2);
527
528                if (new_len > org_len)
529                    break;
530
531            } while (ext & 0x80);
532        }
533
534        GKI_freebuf (p_buf);
535        return;
536    }
537
538    if (type > BNEP_FRAME_COMPRESSED_ETHERNET_DEST_ONLY)
539    {
540        BNEP_TRACE_EVENT ("BNEP - rcvd frame, unknown type: 0x%02x", type);
541        GKI_freebuf (p_buf);
542        return;
543    }
544
545    BNEP_TRACE_DEBUG ("BNEP - rcv frame, type: %d len: %d Ext: %d", type, p_buf->len, extension_present);
546
547    /* Initialize addresses to 'not supplied' */
548    p_src_addr = p_dst_addr = NULL;
549
550    switch (type)
551    {
552    case BNEP_FRAME_GENERAL_ETHERNET:
553        p_dst_addr = p;
554        p += BD_ADDR_LEN;
555        p_src_addr = p;
556        p += BD_ADDR_LEN;
557        BE_STREAM_TO_UINT16 (protocol, p);
558        rem_len -= 14;
559        break;
560
561    case BNEP_FRAME_CONTROL:
562        ctrl_type = *p;
563        p = bnep_process_control_packet (p_bcb, p, &rem_len, FALSE);
564
565        if (ctrl_type == BNEP_SETUP_CONNECTION_REQUEST_MSG &&
566            p_bcb->con_state != BNEP_STATE_CONNECTED &&
567            extension_present && p && rem_len)
568        {
569            p_bcb->p_pending_data = (BT_HDR *)GKI_getbuf (rem_len);
570            if (p_bcb->p_pending_data)
571            {
572                memcpy ((UINT8 *)(p_bcb->p_pending_data + 1), p, rem_len);
573                p_bcb->p_pending_data->len    = rem_len;
574                p_bcb->p_pending_data->offset = 0;
575            }
576        }
577        else
578        {
579            while (extension_present && p && rem_len)
580            {
581                ext_type = *p++;
582                extension_present = ext_type >> 7;
583                ext_type &= 0x7F;
584
585                /* if unknown extension present stop processing */
586                if (ext_type)
587                    break;
588
589                p = bnep_process_control_packet (p_bcb, p, &rem_len, TRUE);
590            }
591        }
592        GKI_freebuf (p_buf);
593        return;
594
595    case BNEP_FRAME_COMPRESSED_ETHERNET:
596        BE_STREAM_TO_UINT16 (protocol, p);
597        rem_len -= 2;
598        break;
599
600    case BNEP_FRAME_COMPRESSED_ETHERNET_SRC_ONLY:
601        p_src_addr = p;
602        p += BD_ADDR_LEN;
603        BE_STREAM_TO_UINT16 (protocol, p);
604        rem_len -= 8;
605        break;
606
607    case BNEP_FRAME_COMPRESSED_ETHERNET_DEST_ONLY:
608        p_dst_addr = p;
609        p += BD_ADDR_LEN;
610        BE_STREAM_TO_UINT16 (protocol, p);
611        rem_len -= 8;
612        break;
613    }
614
615    /* Process the header extension if there is one */
616    while (extension_present && p && rem_len)
617    {
618        ext_type = *p;
619        extension_present = ext_type >> 7;
620        ext_type &= 0x7F;
621
622        /* if unknown extension present stop processing */
623        if (ext_type)
624        {
625            BNEP_TRACE_EVENT ("Data extension type 0x%x found", ext_type);
626            break;
627        }
628
629        p++;
630        rem_len--;
631        p = bnep_process_control_packet (p_bcb, p, &rem_len, TRUE);
632    }
633
634    p_buf->offset += p_buf->len - rem_len;
635    p_buf->len     = rem_len;
636
637    /* Always give the upper layer MAC addresses */
638    if (!p_src_addr)
639        p_src_addr = (UINT8 *) p_bcb->rem_bda;
640
641    if (!p_dst_addr)
642        p_dst_addr = (UINT8 *) bnep_cb.my_bda;
643
644    /* check whether there are any extensions to be forwarded */
645    if (ext_type)
646        fw_ext_present = TRUE;
647    else
648        fw_ext_present = FALSE;
649
650    if (bnep_cb.p_data_buf_cb)
651    {
652        (*bnep_cb.p_data_buf_cb)(p_bcb->handle, p_src_addr, p_dst_addr, protocol, p_buf, fw_ext_present);
653    }
654    else if (bnep_cb.p_data_ind_cb)
655    {
656        (*bnep_cb.p_data_ind_cb)(p_bcb->handle, p_src_addr, p_dst_addr, protocol, p, rem_len, fw_ext_present);
657        GKI_freebuf (p_buf);
658    }
659}
660
661
662
663/*******************************************************************************
664**
665** Function         bnep_process_timeout
666**
667** Description      This function processes a timeout. If it is a startup
668**                  timeout, we check for reading our BD address. If it
669**                  is an L2CAP timeout, we send a disconnect req to L2CAP.
670**
671** Returns          void
672**
673*******************************************************************************/
674void bnep_process_timeout (TIMER_LIST_ENT  *p_tle)
675{
676    tBNEP_CONN *p_bcb;
677
678    if (!p_tle->param)
679    {
680        if (!bnep_cb.got_my_bd_addr)
681        {
682            if (BTM_IsDeviceUp())
683                BTM_ReadLocalDeviceAddr (bnep_read_addr_cb);
684
685            btu_start_timer (&bnep_cb.bnep_tle, BTU_TTYPE_BNEP, 2);
686        }
687        return;
688    }
689
690    p_bcb = (tBNEP_CONN *)p_tle->param;
691
692    BNEP_TRACE_EVENT ("BNEP - CCB timeout in state: %d  CID: 0x%x flags %x, re_transmit %d",
693                       p_bcb->con_state, p_bcb->l2cap_cid, p_bcb->con_flags, p_bcb->re_transmits);
694
695    if (p_bcb->con_state == BNEP_STATE_CONN_SETUP)
696    {
697        BNEP_TRACE_EVENT ("BNEP - CCB timeout in state: %d  CID: 0x%x",
698                           p_bcb->con_state, p_bcb->l2cap_cid);
699
700        if (!(p_bcb->con_flags & BNEP_FLAGS_IS_ORIG))
701        {
702            L2CA_DisconnectReq (p_bcb->l2cap_cid);
703
704            bnepu_release_bcb (p_bcb);
705            return;
706        }
707
708        if (p_bcb->re_transmits++ != BNEP_MAX_RETRANSMITS)
709        {
710            bnep_send_conn_req (p_bcb);
711            btu_start_timer (&p_bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_CONN_TIMEOUT);
712        }
713        else
714        {
715            L2CA_DisconnectReq (p_bcb->l2cap_cid);
716
717            if ((p_bcb->con_flags & BNEP_FLAGS_IS_ORIG) && (bnep_cb.p_conn_state_cb))
718                (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_CONN_FAILED, FALSE);
719
720            bnepu_release_bcb (p_bcb);
721            return;
722        }
723    }
724    else if (p_bcb->con_state != BNEP_STATE_CONNECTED)
725    {
726        BNEP_TRACE_EVENT ("BNEP - CCB timeout in state: %d  CID: 0x%x",
727                           p_bcb->con_state, p_bcb->l2cap_cid);
728
729        L2CA_DisconnectReq (p_bcb->l2cap_cid);
730
731        /* Tell the user if he has a callback */
732        if ((p_bcb->con_flags & BNEP_FLAGS_IS_ORIG) && (bnep_cb.p_conn_state_cb))
733            (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_CONN_FAILED, FALSE);
734
735        bnepu_release_bcb (p_bcb);
736    }
737#if (defined (BNEP_SUPPORTS_PROT_FILTERS) && BNEP_SUPPORTS_PROT_FILTERS == TRUE)
738    else if (p_bcb->con_flags & BNEP_FLAGS_FILTER_RESP_PEND)
739    {
740        if (p_bcb->re_transmits++ != BNEP_MAX_RETRANSMITS)
741        {
742            bnepu_send_peer_our_filters (p_bcb);
743            btu_start_timer (&p_bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_FILTER_SET_TIMEOUT);
744        }
745        else
746        {
747            L2CA_DisconnectReq (p_bcb->l2cap_cid);
748
749            /* Tell the user if he has a callback */
750            if (bnep_cb.p_conn_state_cb)
751                (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_SET_FILTER_FAIL, FALSE);
752
753            bnepu_release_bcb (p_bcb);
754            return;
755        }
756    }
757#endif
758#if (defined (BNEP_SUPPORTS_MULTI_FILTERS) && BNEP_SUPPORTS_MULTI_FILTERS == TRUE)
759    else if (p_bcb->con_flags & BNEP_FLAGS_MULTI_RESP_PEND)
760    {
761        if (p_bcb->re_transmits++ != BNEP_MAX_RETRANSMITS)
762        {
763            bnepu_send_peer_our_multi_filters (p_bcb);
764            btu_start_timer (&p_bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_FILTER_SET_TIMEOUT);
765        }
766        else
767        {
768            L2CA_DisconnectReq (p_bcb->l2cap_cid);
769
770            /* Tell the user if he has a callback */
771            if (bnep_cb.p_conn_state_cb)
772                (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_SET_FILTER_FAIL, FALSE);
773
774            bnepu_release_bcb (p_bcb);
775            return;
776        }
777    }
778#endif
779}
780
781
782/*******************************************************************************
783**
784** Function         bnep_connected
785**
786** Description      This function is called when a connection is established
787**                  (after config).
788**
789** Returns          void
790**
791*******************************************************************************/
792void bnep_connected (tBNEP_CONN *p_bcb)
793{
794    BOOLEAN     is_role_change;
795
796    if (p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)
797        is_role_change = TRUE;
798    else
799        is_role_change = FALSE;
800
801    p_bcb->con_state = BNEP_STATE_CONNECTED;
802    p_bcb->con_flags |= BNEP_FLAGS_CONN_COMPLETED;
803    p_bcb->con_flags &= (~BNEP_FLAGS_SETUP_RCVD);
804
805    /* Ensure timer is stopped */
806    btu_stop_timer (&p_bcb->conn_tle);
807    p_bcb->re_transmits = 0;
808
809    /* Tell the upper layer, if he has a callback */
810    if (bnep_cb.p_conn_state_cb)
811        (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_SUCCESS, is_role_change);
812}
813
814
815/*******************************************************************************
816**
817** Function         bnep_read_addr_cb
818**
819** Description      This function is called by BTM when the local BD address
820**                  is read. It saves the BD address, and flags it as read.
821**
822** Returns          void
823**
824*******************************************************************************/
825static void bnep_read_addr_cb (void *p_bda)
826{
827    UINT8 *bda = (UINT8 *)p_bda;
828    if (p_bda &&
829            (bda[0] | bda[1] | bda[2] | bda[3] | bda[4] | bda[5]) != 0)
830    {
831        /* Save my BD address */
832        memcpy (bnep_cb.my_bda, p_bda, BD_ADDR_LEN);
833
834        bnep_cb.got_my_bd_addr = TRUE;
835    }
836    else
837        /* Retry after a couple seconds */
838        btu_start_timer (&bnep_cb.bnep_tle, BTU_TTYPE_BNEP, 2);
839}
840
841