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