1/******************************************************************************
2 *
3 *  Copyright (C) 1999-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 main functions to support PAN profile
22 *  commands and events.
23 *
24 *****************************************************************************/
25
26#include <string.h>
27#include "gki.h"
28#include "bt_types.h"
29#include "bnep_api.h"
30#include "pan_api.h"
31#include "pan_int.h"
32#include "sdp_api.h"
33#include "sdpdefs.h"
34#include "l2c_api.h"
35#include "hcidefs.h"
36#include "btm_api.h"
37
38
39/*******************************************************************************
40**
41** Function         PAN_Register
42**
43** Description      This function is called by the application to register
44**                  its callbacks with PAN profile. The application then
45**                  should set the PAN role explicitly.
46**
47** Parameters:      p_register - contains all callback function pointers
48**
49**
50** Returns          none
51**
52*******************************************************************************/
53void PAN_Register (tPAN_REGISTER *p_register)
54{
55    BTM_SetDiscoverability (BTM_GENERAL_DISCOVERABLE, 0, 0);
56    BTM_SetConnectability (BTM_CONNECTABLE, 0, 0);
57
58    pan_register_with_bnep ();
59
60    if (!p_register)
61        return;
62
63    pan_cb.pan_conn_state_cb    = p_register->pan_conn_state_cb;
64    pan_cb.pan_bridge_req_cb    = p_register->pan_bridge_req_cb;
65    pan_cb.pan_data_buf_ind_cb  = p_register->pan_data_buf_ind_cb;
66    pan_cb.pan_data_ind_cb      = p_register->pan_data_ind_cb;
67    pan_cb.pan_pfilt_ind_cb     = p_register->pan_pfilt_ind_cb;
68    pan_cb.pan_mfilt_ind_cb     = p_register->pan_mfilt_ind_cb;
69    pan_cb.pan_tx_data_flow_cb  = p_register->pan_tx_data_flow_cb;
70
71    return;
72}
73
74
75
76/*******************************************************************************
77**
78** Function         PAN_Deregister
79**
80** Description      This function is called by the application to de-register
81**                  its callbacks with PAN profile. This will make the PAN to
82**                  become inactive. This will deregister PAN services from SDP
83**                  and close all active connections
84**
85** Parameters:      none
86**
87**
88** Returns          none
89**
90*******************************************************************************/
91void PAN_Deregister (void)
92{
93    pan_cb.pan_bridge_req_cb    = NULL;
94    pan_cb.pan_data_buf_ind_cb  = NULL;
95    pan_cb.pan_data_ind_cb      = NULL;
96    pan_cb.pan_conn_state_cb    = NULL;
97    pan_cb.pan_pfilt_ind_cb     = NULL;
98    pan_cb.pan_mfilt_ind_cb     = NULL;
99
100    PAN_SetRole (PAN_ROLE_INACTIVE, NULL, NULL, NULL, NULL);
101    BNEP_Deregister ();
102
103    return;
104}
105
106
107
108
109/*******************************************************************************
110**
111** Function         PAN_SetRole
112**
113** Description      This function is called by the application to set the PAN
114**                  profile role. This should be called after PAN_Register.
115**                  This can be called any time to change the PAN role
116**
117** Parameters:      role        - is bit map of roles to be active
118**                                      PAN_ROLE_CLIENT is for PANU role
119**                                      PAN_ROLE_GN_SERVER is for GN role
120**                                      PAN_ROLE_NAP_SERVER is for NAP role
121**                  sec_mask    - Security mask for different roles
122**                                      It is array of UINT8. The byte represent the
123**                                      security for roles PANU, GN and NAP in order
124**                  p_user_name - Service name for PANU role
125**                  p_gn_name   - Service name for GN role
126**                  p_nap_name  - Service name for NAP role
127**                                      Can be NULL if user wants it to be default
128**
129** Returns          PAN_SUCCESS     - if the role is set successfully
130**                  PAN_FAILURE     - if the role is not valid
131**
132*******************************************************************************/
133tPAN_RESULT PAN_SetRole (UINT8 role,
134                         UINT8 *sec_mask,
135                         char *p_user_name,
136                         char *p_gn_name,
137                         char *p_nap_name)
138{
139    char                *p_desc;
140    UINT8               security[3] = {PAN_PANU_SECURITY_LEVEL,
141                                       PAN_GN_SECURITY_LEVEL,
142                                       PAN_NAP_SECURITY_LEVEL};
143    UINT8               *p_sec;
144
145    /* If the role is not a valid combination reject it */
146    if ((!(role & (PAN_ROLE_CLIENT | PAN_ROLE_GN_SERVER | PAN_ROLE_NAP_SERVER))) &&
147        role != PAN_ROLE_INACTIVE)
148    {
149        PAN_TRACE_ERROR1 ("PAN role %d is invalid", role);
150        return PAN_FAILURE;
151    }
152
153    /* If the current active role is same as the role being set do nothing */
154    if (pan_cb.role == role)
155    {
156        PAN_TRACE_EVENT1 ("PAN role already was set to: %d", role);
157        return PAN_SUCCESS;
158    }
159
160    if (!sec_mask)
161        p_sec = security;
162    else
163        p_sec = sec_mask;
164
165    /* Register all the roles with SDP */
166    PAN_TRACE_API1 ("PAN_SetRole() called with role 0x%x", role);
167#if (defined (PAN_SUPPORTS_ROLE_NAP) && PAN_SUPPORTS_ROLE_NAP == TRUE)
168    /* Check the service name */
169    if ((p_nap_name == NULL) || (*p_nap_name == 0))
170        p_nap_name = PAN_NAP_DEFAULT_SERVICE_NAME;
171
172    if (role & PAN_ROLE_NAP_SERVER)
173    {
174        /* Registering for NAP service with SDP */
175        p_desc = PAN_NAP_DEFAULT_DESCRIPTION;
176
177        if (pan_cb.pan_nap_sdp_handle != 0)
178            SDP_DeleteRecord (pan_cb.pan_nap_sdp_handle);
179
180        pan_cb.pan_nap_sdp_handle = pan_register_with_sdp (UUID_SERVCLASS_NAP, p_sec[2], p_nap_name, p_desc);
181// btla-specific ++
182        bta_sys_add_uuid(UUID_SERVCLASS_NAP);
183// btla-specific --
184    }
185    /* If the NAP role is already active and now being cleared delete the record */
186    else if (pan_cb.role & PAN_ROLE_NAP_SERVER)
187    {
188        if (pan_cb.pan_nap_sdp_handle != 0)
189        {
190            SDP_DeleteRecord (pan_cb.pan_nap_sdp_handle);
191            pan_cb.pan_nap_sdp_handle = 0;
192// btla-specific ++
193            bta_sys_remove_uuid(UUID_SERVCLASS_NAP);
194// btla-specific --
195        }
196    }
197#endif
198
199#if (defined (PAN_SUPPORTS_ROLE_GN) && PAN_SUPPORTS_ROLE_GN == TRUE)
200    /* Check the service name */
201    if ((p_gn_name == NULL) || (*p_gn_name == 0))
202        p_gn_name = PAN_GN_DEFAULT_SERVICE_NAME;
203
204    if (role & PAN_ROLE_GN_SERVER)
205    {
206        /* Registering for GN service with SDP */
207        p_desc = PAN_GN_DEFAULT_DESCRIPTION;
208
209        if (pan_cb.pan_gn_sdp_handle != 0)
210            SDP_DeleteRecord (pan_cb.pan_gn_sdp_handle);
211
212        pan_cb.pan_gn_sdp_handle = pan_register_with_sdp (UUID_SERVCLASS_GN, p_sec[1], p_gn_name, p_desc);
213// btla-specific ++
214        bta_sys_add_uuid(UUID_SERVCLASS_GN);
215// btla-specific --
216    }
217    /* If the GN role is already active and now being cleared delete the record */
218    else if (pan_cb.role & PAN_ROLE_GN_SERVER)
219    {
220        if (pan_cb.pan_gn_sdp_handle != 0)
221        {
222            SDP_DeleteRecord (pan_cb.pan_gn_sdp_handle);
223            pan_cb.pan_gn_sdp_handle = 0;
224// btla-specific ++
225            bta_sys_remove_uuid(UUID_SERVCLASS_GN);
226// btla-specific --
227        }
228    }
229#endif
230
231#if (defined (PAN_SUPPORTS_ROLE_PANU) && PAN_SUPPORTS_ROLE_PANU == TRUE)
232    /* Check the service name */
233    if ((p_user_name == NULL) || (*p_user_name == 0))
234        p_user_name = PAN_PANU_DEFAULT_SERVICE_NAME;
235
236    if (role & PAN_ROLE_CLIENT)
237    {
238        /* Registering for PANU service with SDP */
239        p_desc = PAN_PANU_DEFAULT_DESCRIPTION;
240        if (pan_cb.pan_user_sdp_handle != 0)
241            SDP_DeleteRecord (pan_cb.pan_user_sdp_handle);
242
243        pan_cb.pan_user_sdp_handle = pan_register_with_sdp (UUID_SERVCLASS_PANU, p_sec[0], p_user_name, p_desc);
244// btla-specific ++
245        bta_sys_add_uuid(UUID_SERVCLASS_PANU);
246// btla-specific --
247    }
248    /* If the PANU role is already active and now being cleared delete the record */
249    else if (pan_cb.role & PAN_ROLE_CLIENT)
250    {
251        if (pan_cb.pan_user_sdp_handle != 0)
252        {
253            SDP_DeleteRecord (pan_cb.pan_user_sdp_handle);
254            pan_cb.pan_user_sdp_handle = 0;
255// btla-specific ++
256            bta_sys_remove_uuid(UUID_SERVCLASS_PANU);
257// btla-specific --
258        }
259    }
260#endif
261
262    /* Check if it is a shutdown request */
263    if (role == PAN_ROLE_INACTIVE)
264        pan_close_all_connections ();
265
266    pan_cb.role = role;
267    PAN_TRACE_EVENT1 ("PAN role set to: %d", role);
268    return PAN_SUCCESS;
269}
270
271
272
273/*******************************************************************************
274**
275** Function         PAN_Connect
276**
277** Description      This function is called by the application to initiate a
278**                  connection to the remote device
279**
280** Parameters:      rem_bda     - BD Addr of the remote device
281**                  src_role    - Role of the local device for the connection
282**                  dst_role    - Role of the remote device for the connection
283**                                      PAN_ROLE_CLIENT is for PANU role
284**                                      PAN_ROLE_GN_SERVER is for GN role
285**                                      PAN_ROLE_NAP_SERVER is for NAP role
286**                  *handle     - Pointer for returning Handle to the connection
287**
288** Returns          PAN_SUCCESS      - if the connection is initiated successfully
289**                  PAN_NO_RESOURCES - resources are not sufficent
290**                  PAN_FAILURE      - if the connection cannot be initiated
291**                                           this can be because of the combination of
292**                                           src and dst roles may not be valid or
293**                                           allowed at that point of time
294**
295*******************************************************************************/
296tPAN_RESULT PAN_Connect (BD_ADDR rem_bda, UINT8 src_role, UINT8 dst_role, UINT16 *handle)
297{
298    tPAN_CONN       *pcb;
299    tBNEP_RESULT    result;
300    tBT_UUID        src_uuid, dst_uuid;
301    UINT8           service_id;
302    UINT32 mx_chan_id;
303
304    /*
305    ** Initialize the handle so that in case of failure return values
306    ** the profile will not get confused
307    */
308    *handle = BNEP_INVALID_HANDLE;
309
310    /* Check if PAN is active or not */
311    if (!(pan_cb.role & src_role))
312    {
313        PAN_TRACE_ERROR1 ("PAN is not active for the role %d", src_role);
314        return PAN_FAILURE;
315    }
316
317    /* Validate the parameters before proceeding */
318    if ((src_role != PAN_ROLE_CLIENT && src_role != PAN_ROLE_GN_SERVER && src_role != PAN_ROLE_NAP_SERVER) ||
319        (dst_role != PAN_ROLE_CLIENT && dst_role != PAN_ROLE_GN_SERVER && dst_role != PAN_ROLE_NAP_SERVER))
320    {
321        PAN_TRACE_ERROR2 ("Either source %d or destination role %d is invalid", src_role, dst_role);
322        return PAN_FAILURE;
323    }
324
325    /* Check if connection exists for this remote device */
326    pcb = pan_get_pcb_by_addr (rem_bda);
327
328    /* If we are PANU for this role validate destination role */
329    if (src_role == PAN_ROLE_CLIENT)
330    {
331        if ((pan_cb.num_conns > 1) || (pan_cb.num_conns && (!pcb)))
332        {
333            /*
334            ** If the request is not for existing connection reject it
335            ** because if there is already a connection we cannot accept
336            ** another connection in PANU role
337            */
338            PAN_TRACE_ERROR0 ("Cannot make PANU connections when there are more than one connection");
339            return PAN_INVALID_SRC_ROLE;
340        }
341
342        src_uuid.uu.uuid16 = UUID_SERVCLASS_PANU;
343        if (dst_role == PAN_ROLE_CLIENT)
344        {
345            service_id = BTM_SEC_SERVICE_BNEP_PANU;
346            dst_uuid.uu.uuid16 = UUID_SERVCLASS_PANU;
347        }
348        else if (dst_role == PAN_ROLE_GN_SERVER)
349        {
350            service_id = BTM_SEC_SERVICE_BNEP_GN;
351            dst_uuid.uu.uuid16 = UUID_SERVCLASS_GN;
352        }
353        else
354        {
355            service_id = BTM_SEC_SERVICE_BNEP_NAP;
356            dst_uuid.uu.uuid16 = UUID_SERVCLASS_NAP;
357        }
358        mx_chan_id = dst_uuid.uu.uuid16;
359    }
360    /* If destination is PANU role validate source role */
361    else if (dst_role == PAN_ROLE_CLIENT)
362    {
363        if (pan_cb.num_conns && pan_cb.active_role == PAN_ROLE_CLIENT && !pcb)
364        {
365            PAN_TRACE_ERROR0 ("Device already have a connection in PANU role");
366            return PAN_INVALID_SRC_ROLE;
367        }
368
369        dst_uuid.uu.uuid16 = UUID_SERVCLASS_PANU;
370        if (src_role == PAN_ROLE_GN_SERVER)
371        {
372            service_id = BTM_SEC_SERVICE_BNEP_GN;
373            src_uuid.uu.uuid16 = UUID_SERVCLASS_GN;
374        }
375        else
376        {
377            service_id = BTM_SEC_SERVICE_BNEP_NAP;
378            src_uuid.uu.uuid16 = UUID_SERVCLASS_NAP;
379        }
380        mx_chan_id = src_uuid.uu.uuid16;
381    }
382    /* The role combination is not valid */
383    else
384    {
385        PAN_TRACE_ERROR2 ("Source %d and Destination roles %d are not valid combination",
386            src_role, dst_role);
387        return PAN_FAILURE;
388    }
389
390    /* Allocate control block and initiate connection */
391    if (!pcb)
392        pcb = pan_allocate_pcb (rem_bda, BNEP_INVALID_HANDLE);
393    if (!pcb)
394    {
395        PAN_TRACE_ERROR0 ("PAN Connection failed because of no resources");
396        return PAN_NO_RESOURCES;
397    }
398    BTM_SetOutService(rem_bda, BTM_SEC_SERVICE_BNEP_PANU, mx_chan_id);
399
400    PAN_TRACE_API6 ("PAN_Connect() for BD Addr %x.%x.%x.%x.%x.%x",
401        rem_bda[0], rem_bda[1], rem_bda[2], rem_bda[3], rem_bda[4], rem_bda[5]);
402    if (pcb->con_state == PAN_STATE_IDLE)
403    {
404        pan_cb.num_conns++;
405    }
406    else if (pcb->con_state == PAN_STATE_CONNECTED)
407    {
408        pcb->con_flags |= PAN_FLAGS_CONN_COMPLETED;
409    }
410    else
411        /* PAN connection is still in progress */
412        return PAN_WRONG_STATE;
413
414    pcb->con_state = PAN_STATE_CONN_START;
415    pcb->prv_src_uuid = pcb->src_uuid;
416    pcb->prv_dst_uuid = pcb->dst_uuid;
417
418    pcb->src_uuid     = src_uuid.uu.uuid16;
419    pcb->dst_uuid     = dst_uuid.uu.uuid16;
420
421    src_uuid.len      = 2;
422    dst_uuid.len      = 2;
423
424    result = BNEP_Connect (rem_bda, &src_uuid, &dst_uuid, &(pcb->handle));
425    if (result != BNEP_SUCCESS)
426    {
427        pan_release_pcb (pcb);
428        return result;
429    }
430
431    PAN_TRACE_DEBUG1 ("PAN_Connect() current active role set to %d", src_role);
432    pan_cb.prv_active_role = pan_cb.active_role;
433    pan_cb.active_role = src_role;
434    *handle = pcb->handle;
435    return PAN_SUCCESS;
436}
437
438
439
440
441/*******************************************************************************
442**
443** Function         PAN_Disconnect
444**
445** Description      This is used to disconnect the connection
446**
447** Parameters:      handle           - handle for the connection
448**
449** Returns          PAN_SUCCESS      - if the connection is closed successfully
450**                  PAN_FAILURE      - if the connection is not found or
451**                                           there is an error in disconnecting
452**
453*******************************************************************************/
454tPAN_RESULT PAN_Disconnect (UINT16 handle)
455{
456    tPAN_CONN       *pcb;
457    tBNEP_RESULT    result;
458
459    /* Check if the connection exists */
460    pcb = pan_get_pcb_by_handle (handle);
461    if(!pcb)
462    {
463        PAN_TRACE_ERROR1 ("PAN connection not found for the handle %d", handle);
464        return PAN_FAILURE;
465    }
466
467    result = BNEP_Disconnect (pcb->handle);
468    if (pcb->con_state == PAN_STATE_CONNECTED)
469        pan_cb.num_conns--;
470
471    if (pan_cb.pan_bridge_req_cb && pcb->src_uuid == UUID_SERVCLASS_NAP)
472        (*pan_cb.pan_bridge_req_cb) (pcb->rem_bda, FALSE);
473
474    pan_release_pcb (pcb);
475
476    if (result != BNEP_SUCCESS)
477    {
478        PAN_TRACE_EVENT0 ("Error in closing PAN connection");
479        return PAN_FAILURE;
480    }
481
482    PAN_TRACE_EVENT0 ("PAN connection closed");
483    return PAN_SUCCESS;
484}
485
486
487/*******************************************************************************
488**
489** Function         PAN_Write
490**
491** Description      This sends data over the PAN connections. If this is called
492**                  on GN or NAP side and the packet is multicast or broadcast
493**                  it will be sent on all the links. Otherwise the correct link
494**                  is found based on the destination address and forwarded on it
495**                  If the return value is not PAN_SUCCESS the application should
496**                  take care of releasing the message buffer
497**
498** Parameters:      handle   - handle for the connection
499**                  dst      - MAC or BD Addr of the destination device
500**                  src      - MAC or BD Addr of the source who sent this packet
501**                  protocol - protocol of the ethernet packet like IP or ARP
502**                  p_data   - pointer to the data
503**                  len      - length of the data
504**                  ext      - to indicate that extension headers present
505**
506** Returns          PAN_SUCCESS       - if the data is sent successfully
507**                  PAN_FAILURE       - if the connection is not found or
508**                                           there is an error in sending data
509**
510*******************************************************************************/
511tPAN_RESULT PAN_Write (UINT16 handle, BD_ADDR dst, BD_ADDR src, UINT16 protocol, UINT8 *p_data, UINT16 len, BOOLEAN ext)
512{
513    tPAN_CONN       *pcb;
514    UINT16          i;
515    tBNEP_RESULT    result;
516
517    if (pan_cb.role == PAN_ROLE_INACTIVE || (!(pan_cb.num_conns)))
518    {
519        PAN_TRACE_ERROR0 ("PAN is not active Data write failed");
520        return PAN_FAILURE;
521    }
522
523    /* Check if it is broadcast or multicast packet */
524    if (dst[0] & 0x01)
525    {
526        for (i=0; i<MAX_PAN_CONNS; i++)
527        {
528            if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED)
529                BNEP_Write (pan_cb.pcb[i].handle, dst, p_data, len, protocol, src, ext);
530        }
531
532        return PAN_SUCCESS;
533    }
534
535    if (pan_cb.active_role == PAN_ROLE_CLIENT)
536    {
537        /* Data write is on PANU connection */
538        for (i=0; i<MAX_PAN_CONNS; i++)
539        {
540            if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED &&
541                pan_cb.pcb[i].src_uuid == UUID_SERVCLASS_PANU)
542                break;
543        }
544
545        if (i == MAX_PAN_CONNS)
546        {
547            PAN_TRACE_ERROR0 ("PAN Don't have any user connections");
548            return PAN_FAILURE;
549        }
550
551        result = BNEP_Write (pan_cb.pcb[i].handle, dst, p_data, len, protocol, src, ext);
552        if (result == BNEP_IGNORE_CMD)
553        {
554            PAN_TRACE_DEBUG0 ("PAN ignored data for PANU connection");
555            return result;
556        }
557        else if (result != BNEP_SUCCESS)
558        {
559            PAN_TRACE_ERROR0 ("PAN failed to write data for the PANU connection");
560            return result;
561        }
562
563        PAN_TRACE_DEBUG0 ("PAN successfully wrote data for the PANU connection");
564        return PAN_SUCCESS;
565    }
566
567    pcb = pan_get_pcb_by_handle (handle);
568    if (!pcb)
569    {
570        PAN_TRACE_ERROR0 ("PAN Data write for wrong addr");
571        return PAN_FAILURE;
572    }
573
574    if (pcb->con_state != PAN_STATE_CONNECTED)
575    {
576        PAN_TRACE_ERROR0 ("PAN Data write when conn is not active");
577        return PAN_FAILURE;
578    }
579
580    result = BNEP_Write (pcb->handle, dst, p_data, len, protocol, src, ext);
581    if (result == BNEP_IGNORE_CMD)
582    {
583        PAN_TRACE_DEBUG0 ("PAN ignored data write to PANU");
584        return result;
585    }
586    else if (result != BNEP_SUCCESS)
587    {
588        PAN_TRACE_ERROR0 ("PAN failed to send data to the PANU");
589        return result;
590    }
591
592    PAN_TRACE_DEBUG0 ("PAN successfully sent data to the PANU");
593    return PAN_SUCCESS;
594}
595
596
597/*******************************************************************************
598**
599** Function         PAN_WriteBuf
600**
601** Description      This sends data over the PAN connections. If this is called
602**                  on GN or NAP side and the packet is multicast or broadcast
603**                  it will be sent on all the links. Otherwise the correct link
604**                  is found based on the destination address and forwarded on it
605**                  If the return value is not PAN_SUCCESS the application should
606**                  take care of releasing the message buffer
607**
608** Parameters:      handle   - handle for the connection
609**                  dst      - MAC or BD Addr of the destination device
610**                  src      - MAC or BD Addr of the source who sent this packet
611**                  protocol - protocol of the ethernet packet like IP or ARP
612**                  p_buf    - pointer to the data buffer
613**                  ext      - to indicate that extension headers present
614**
615** Returns          PAN_SUCCESS       - if the data is sent successfully
616**                  PAN_FAILURE       - if the connection is not found or
617**                                           there is an error in sending data
618**
619*******************************************************************************/
620tPAN_RESULT PAN_WriteBuf (UINT16 handle, BD_ADDR dst, BD_ADDR src, UINT16 protocol, BT_HDR *p_buf, BOOLEAN ext)
621{
622    tPAN_CONN       *pcb;
623    UINT16          i;
624    tBNEP_RESULT    result;
625
626    /* Check if it is broadcast or multicast packet */
627    if (dst[0] & 0x01)
628    {
629        UINT8       *p_data;
630        UINT16      len;
631
632        p_data  = (UINT8 *)(p_buf + 1) + p_buf->offset;
633        len     = p_buf->len;
634        PAN_Write (handle, dst, src, protocol, p_data, len, ext);
635        GKI_freebuf (p_buf);
636        return PAN_SUCCESS;
637    }
638
639    if (pan_cb.role == PAN_ROLE_INACTIVE || (!(pan_cb.num_conns)))
640    {
641        PAN_TRACE_ERROR0 ("PAN is not active Data write failed");
642        GKI_freebuf (p_buf);
643        return PAN_FAILURE;
644    }
645
646    /* Check if the data write is on PANU side */
647    if (pan_cb.active_role == PAN_ROLE_CLIENT)
648    {
649        /* Data write is on PANU connection */
650        for (i=0; i<MAX_PAN_CONNS; i++)
651        {
652            if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED &&
653                pan_cb.pcb[i].src_uuid == UUID_SERVCLASS_PANU)
654                break;
655        }
656
657        if (i == MAX_PAN_CONNS)
658        {
659            PAN_TRACE_ERROR0 ("PAN Don't have any user connections");
660            GKI_freebuf (p_buf);
661            return PAN_FAILURE;
662        }
663
664        result = BNEP_WriteBuf (pan_cb.pcb[i].handle, dst, p_buf, protocol, src, ext);
665        if (result == BNEP_IGNORE_CMD)
666        {
667            PAN_TRACE_DEBUG0 ("PAN ignored data write for PANU connection");
668            return result;
669        }
670        else if (result != BNEP_SUCCESS)
671        {
672            PAN_TRACE_ERROR0 ("PAN failed to write data for the PANU connection");
673            return result;
674        }
675
676        PAN_TRACE_DEBUG0 ("PAN successfully wrote data for the PANU connection");
677        return PAN_SUCCESS;
678    }
679
680    /* findout to which connection the data is meant for */
681    pcb = pan_get_pcb_by_handle (handle);
682    if (!pcb)
683    {
684        PAN_TRACE_ERROR0 ("PAN Buf write for wrong handle");
685        GKI_freebuf (p_buf);
686        return PAN_FAILURE;
687    }
688
689    if (pcb->con_state != PAN_STATE_CONNECTED)
690    {
691        PAN_TRACE_ERROR0 ("PAN Buf write when conn is not active");
692        GKI_freebuf (p_buf);
693        return PAN_FAILURE;
694    }
695
696    result = BNEP_WriteBuf (pcb->handle, dst, p_buf, protocol, src, ext);
697    if (result == BNEP_IGNORE_CMD)
698    {
699        PAN_TRACE_DEBUG0 ("PAN ignored data buf write to PANU");
700        return result;
701    }
702    else if (result != BNEP_SUCCESS)
703    {
704        PAN_TRACE_ERROR0 ("PAN failed to send data buf to the PANU");
705        return result;
706    }
707
708    PAN_TRACE_DEBUG0 ("PAN successfully sent data buf to the PANU");
709    return PAN_SUCCESS;
710}
711
712
713/*******************************************************************************
714**
715** Function         PAN_SetProtocolFilters
716**
717** Description      This function is used to set protocol filters on the peer
718**
719** Parameters:      handle      - handle for the connection
720**                  num_filters - number of protocol filter ranges
721**                  start       - array of starting protocol numbers
722**                  end         - array of ending protocol numbers
723**
724**
725** Returns          PAN_SUCCESS        if protocol filters are set successfully
726**                  PAN_FAILURE        if connection not found or error in setting
727**
728*******************************************************************************/
729tPAN_RESULT PAN_SetProtocolFilters (UINT16 handle,
730                                    UINT16 num_filters,
731                                    UINT16 *p_start_array,
732                                    UINT16 *p_end_array)
733{
734#if (defined (BNEP_SUPPORTS_PROT_FILTERS) && BNEP_SUPPORTS_PROT_FILTERS == TRUE)
735    tPAN_CONN       *pcb;
736    tPAN_RESULT     result;
737
738    /* Check if the connection exists */
739    pcb = pan_get_pcb_by_handle (handle);
740    if(!pcb)
741    {
742        PAN_TRACE_ERROR1 ("PAN connection not found for the handle %d", handle);
743        return PAN_FAILURE;
744    }
745
746    result = BNEP_SetProtocolFilters (pcb->handle, num_filters, p_start_array, p_end_array);
747    if (result != BNEP_SUCCESS)
748    {
749        PAN_TRACE_ERROR1 ("PAN failed to set protocol filters for handle %d", handle);
750        return result;
751    }
752
753    PAN_TRACE_API1 ("PAN successfully sent protocol filters for handle %d", handle);
754    return PAN_SUCCESS;
755#else
756    return PAN_FAILURE;
757#endif
758}
759
760
761
762/*******************************************************************************
763**
764** Function         PAN_SetMulticastFilters
765**
766** Description      This function is used to set multicast filters on the peer
767**
768** Parameters:      handle      - handle for the connection
769**                  num_filters - number of multicast filter ranges
770**                  start       - array of starting multicast filter addresses
771**                  end         - array of ending multicast filter addresses
772**
773**
774** Returns          PAN_SUCCESS        if multicast filters are set successfully
775**                  PAN_FAILURE        if connection not found or error in setting
776**
777*******************************************************************************/
778tBNEP_RESULT PAN_SetMulticastFilters (UINT16 handle,
779                                      UINT16 num_mcast_filters,
780                                      UINT8 *p_start_array,
781                                      UINT8 *p_end_array)
782{
783#if (defined (BNEP_SUPPORTS_MULTI_FILTERS) && BNEP_SUPPORTS_MULTI_FILTERS == TRUE)
784    tPAN_CONN       *pcb;
785    tPAN_RESULT     result;
786
787    /* Check if the connection exists */
788    pcb = pan_get_pcb_by_handle (handle);
789    if(!pcb)
790    {
791        PAN_TRACE_ERROR1 ("PAN connection not found for the handle %d", handle);
792        return PAN_FAILURE;
793    }
794
795    result = BNEP_SetMulticastFilters (pcb->handle,
796                            num_mcast_filters, p_start_array, p_end_array);
797    if (result != BNEP_SUCCESS)
798    {
799        PAN_TRACE_ERROR1 ("PAN failed to set multicast filters for handle %d", handle);
800        return result;
801    }
802
803    PAN_TRACE_API1 ("PAN successfully sent multicast filters for handle %d", handle);
804    return PAN_SUCCESS;
805#else
806    return PAN_FAILURE;
807#endif
808}
809
810
811/*******************************************************************************
812**
813** Function         PAN_SetTraceLevel
814**
815** Description      This function sets the trace level for PAN. If called with
816**                  a value of 0xFF, it simply reads the current trace level.
817**
818** Returns          the new (current) trace level
819**
820*******************************************************************************/
821UINT8 PAN_SetTraceLevel (UINT8 new_level)
822{
823    if (new_level != 0xFF)
824        pan_cb.trace_level = new_level;
825    else
826        pan_dump_status ();
827
828    return (pan_cb.trace_level);
829}
830
831/*******************************************************************************
832**
833** Function         PAN_Init
834**
835** Description      This function initializes the PAN module variables
836**
837** Parameters:      none
838**
839** Returns          none
840**
841*******************************************************************************/
842void PAN_Init (void)
843{
844    memset (&pan_cb, 0, sizeof (tPAN_CB));
845
846#if defined(PAN_INITIAL_TRACE_LEVEL)
847    pan_cb.trace_level = PAN_INITIAL_TRACE_LEVEL;
848#else
849    pan_cb.trace_level = BT_TRACE_LEVEL_NONE;    /* No traces */
850#endif
851}
852
853
854