OSDN Git Service

DO NOT MERGE Add bounds check for BNEP_Write
[android-x86/system-bt.git] / stack / bnep / bnep_api.c
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 BNEP API code
22  *
23  ******************************************************************************/
24
25 #include <string.h>
26 #include "bnep_api.h"
27 #include "bnep_int.h"
28 #include "log/log.h"
29
30
31 extern fixed_queue_t *btu_general_alarm_queue;
32
33 /*******************************************************************************
34 **
35 ** Function         BNEP_Init
36 **
37 ** Description      This function initializes the BNEP unit. It should be called
38 **                  before accessing any other APIs to initialize the control block
39 **
40 ** Returns          void
41 **
42 *******************************************************************************/
43 void BNEP_Init (void)
44 {
45     memset (&bnep_cb, 0, sizeof (tBNEP_CB));
46
47 #if defined(BNEP_INITIAL_TRACE_LEVEL)
48     bnep_cb.trace_level = BNEP_INITIAL_TRACE_LEVEL;
49 #else
50     bnep_cb.trace_level = BT_TRACE_LEVEL_NONE;    /* No traces */
51 #endif
52 }
53
54
55 /*******************************************************************************
56 **
57 ** Function         BNEP_Register
58 **
59 ** Description      This function is called by the upper layer to register
60 **                  its callbacks with BNEP
61 **
62 ** Parameters:      p_reg_info - contains all callback function pointers
63 **
64 **
65 ** Returns          BNEP_SUCCESS        if registered successfully
66 **                  BNEP_FAILURE        if connection state callback is missing
67 **
68 *******************************************************************************/
69 tBNEP_RESULT BNEP_Register (tBNEP_REGISTER *p_reg_info)
70 {
71     /* There should be connection state call back registered */
72     if ((!p_reg_info) || (!(p_reg_info->p_conn_state_cb)))
73         return BNEP_SECURITY_FAIL;
74
75     bnep_cb.p_conn_ind_cb       = p_reg_info->p_conn_ind_cb;
76     bnep_cb.p_conn_state_cb     = p_reg_info->p_conn_state_cb;
77     bnep_cb.p_data_ind_cb       = p_reg_info->p_data_ind_cb;
78     bnep_cb.p_data_buf_cb       = p_reg_info->p_data_buf_cb;
79     bnep_cb.p_filter_ind_cb     = p_reg_info->p_filter_ind_cb;
80     bnep_cb.p_mfilter_ind_cb    = p_reg_info->p_mfilter_ind_cb;
81     bnep_cb.p_tx_data_flow_cb   = p_reg_info->p_tx_data_flow_cb;
82
83     if (bnep_register_with_l2cap ())
84         return BNEP_SECURITY_FAIL;
85
86     bnep_cb.profile_registered  = TRUE;
87     return BNEP_SUCCESS;
88 }
89
90
91 /*******************************************************************************
92 **
93 ** Function         BNEP_Deregister
94 **
95 ** Description      This function is called by the upper layer to de-register
96 **                  its callbacks.
97 **
98 ** Parameters:      void
99 **
100 **
101 ** Returns          void
102 **
103 *******************************************************************************/
104 void BNEP_Deregister (void)
105 {
106     /* Clear all the call backs registered */
107     bnep_cb.p_conn_ind_cb       = NULL;
108     bnep_cb.p_conn_state_cb     = NULL;
109     bnep_cb.p_data_ind_cb       = NULL;
110     bnep_cb.p_data_buf_cb       = NULL;
111     bnep_cb.p_filter_ind_cb     = NULL;
112     bnep_cb.p_mfilter_ind_cb    = NULL;
113
114     bnep_cb.profile_registered  = FALSE;
115     L2CA_Deregister (BT_PSM_BNEP);
116 }
117
118
119 /*******************************************************************************
120 **
121 ** Function         BNEP_Connect
122 **
123 ** Description      This function creates a BNEP connection to a remote
124 **                  device.
125 **
126 ** Parameters:      p_rem_addr  - BD_ADDR of the peer
127 **                  src_uuid    - source uuid for the connection
128 **                  dst_uuid    - destination uuid for the connection
129 **                  p_handle    - pointer to return the handle for the connection
130 **
131 ** Returns          BNEP_SUCCESS                if connection started
132 **                  BNEP_NO_RESOURCES           if no resources
133 **
134 *******************************************************************************/
135 tBNEP_RESULT BNEP_Connect (BD_ADDR p_rem_bda,
136                            tBT_UUID *src_uuid,
137                            tBT_UUID *dst_uuid,
138                            UINT16 *p_handle)
139 {
140     UINT16          cid;
141     tBNEP_CONN      *p_bcb = bnepu_find_bcb_by_bd_addr (p_rem_bda);
142
143     BNEP_TRACE_API ("BNEP_Connect()  BDA: %02x-%02x-%02x-%02x-%02x-%02x",
144                      p_rem_bda[0], p_rem_bda[1], p_rem_bda[2],
145                      p_rem_bda[3], p_rem_bda[4], p_rem_bda[5]);
146
147     if (!bnep_cb.profile_registered)
148         return BNEP_WRONG_STATE;
149
150     /* Both source and destination UUID lengths should be same */
151     if (src_uuid->len != dst_uuid->len)
152         return BNEP_CONN_FAILED_UUID_SIZE;
153
154     if (!p_bcb)
155     {
156         if ((p_bcb = bnepu_allocate_bcb (p_rem_bda)) == NULL)
157             return (BNEP_NO_RESOURCES);
158     }
159     else if (p_bcb->con_state != BNEP_STATE_CONNECTED)
160             return BNEP_WRONG_STATE;
161     else
162     {
163         /* Backup current UUID values to restore if role change fails */
164         memcpy ((UINT8 *)&(p_bcb->prv_src_uuid), (UINT8 *)&(p_bcb->src_uuid), sizeof (tBT_UUID));
165         memcpy ((UINT8 *)&(p_bcb->prv_dst_uuid), (UINT8 *)&(p_bcb->dst_uuid), sizeof (tBT_UUID));
166     }
167
168     /* We are the originator of this connection */
169     p_bcb->con_flags |= BNEP_FLAGS_IS_ORIG;
170
171     memcpy ((UINT8 *)&(p_bcb->src_uuid), (UINT8 *)src_uuid, sizeof (tBT_UUID));
172     memcpy ((UINT8 *)&(p_bcb->dst_uuid), (UINT8 *)dst_uuid, sizeof (tBT_UUID));
173
174     if (p_bcb->con_state == BNEP_STATE_CONNECTED)
175     {
176         /* Transition to the next appropriate state, waiting for connection confirm. */
177         p_bcb->con_state = BNEP_STATE_SEC_CHECKING;
178
179         BNEP_TRACE_API ("BNEP initiating security procedures for src uuid 0x%x",
180             p_bcb->src_uuid.uu.uuid16);
181
182 #if (defined (BNEP_DO_AUTH_FOR_ROLE_SWITCH) && BNEP_DO_AUTH_FOR_ROLE_SWITCH == TRUE)
183         btm_sec_mx_access_request (p_bcb->rem_bda, BT_PSM_BNEP, TRUE,
184                                    BTM_SEC_PROTO_BNEP,
185                                    bnep_get_uuid32(src_uuid),
186                                    &bnep_sec_check_complete, p_bcb);
187 #else
188         bnep_sec_check_complete (p_bcb->rem_bda, p_bcb, BTM_SUCCESS);
189 #endif
190
191     }
192     else
193     {
194         /* Transition to the next appropriate state, waiting for connection confirm. */
195         p_bcb->con_state = BNEP_STATE_CONN_START;
196
197         if ((cid = L2CA_ConnectReq (BT_PSM_BNEP, p_bcb->rem_bda)) != 0)
198         {
199             p_bcb->l2cap_cid = cid;
200
201         }
202         else
203         {
204             BNEP_TRACE_ERROR ("BNEP - Originate failed");
205             if (bnep_cb.p_conn_state_cb)
206                 (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_CONN_FAILED, FALSE);
207             bnepu_release_bcb (p_bcb);
208             return BNEP_CONN_FAILED;
209         }
210
211         /* Start timer waiting for connect */
212         alarm_set_on_queue(p_bcb->conn_timer, BNEP_CONN_TIMEOUT_MS,
213                            bnep_conn_timer_timeout, p_bcb,
214                            btu_general_alarm_queue);
215     }
216
217     *p_handle = p_bcb->handle;
218     return (BNEP_SUCCESS);
219 }
220
221
222 /*******************************************************************************
223 **
224 ** Function         BNEP_ConnectResp
225 **
226 ** Description      This function is called in responce to connection indication
227 **
228 **
229 ** Parameters:      handle  - handle given in the connection indication
230 **                  resp    - responce for the connection indication
231 **
232 ** Returns          BNEP_SUCCESS                if connection started
233 **                  BNEP_WRONG_HANDLE           if the connection is not found
234 **                  BNEP_WRONG_STATE            if the responce is not expected
235 **
236 *******************************************************************************/
237 tBNEP_RESULT BNEP_ConnectResp (UINT16 handle, tBNEP_RESULT resp)
238 {
239     tBNEP_CONN      *p_bcb;
240     UINT16          resp_code = BNEP_SETUP_CONN_OK;
241
242     if ((!handle) || (handle > BNEP_MAX_CONNECTIONS))
243         return (BNEP_WRONG_HANDLE);
244
245     p_bcb = &(bnep_cb.bcb[handle - 1]);
246
247     if (p_bcb->con_state != BNEP_STATE_CONN_SETUP ||
248         (!(p_bcb->con_flags & BNEP_FLAGS_SETUP_RCVD)))
249         return (BNEP_WRONG_STATE);
250
251     BNEP_TRACE_API ("BNEP_ConnectResp()  for handle %d, responce %d", handle, resp);
252
253     /* Form appropriate responce based on profile responce */
254     if      (resp == BNEP_CONN_FAILED_SRC_UUID)   resp_code = BNEP_SETUP_INVALID_SRC_UUID;
255     else if (resp == BNEP_CONN_FAILED_DST_UUID)   resp_code = BNEP_SETUP_INVALID_DEST_UUID;
256     else if (resp == BNEP_CONN_FAILED_UUID_SIZE)  resp_code = BNEP_SETUP_INVALID_UUID_SIZE;
257     else if (resp == BNEP_SUCCESS)                resp_code = BNEP_SETUP_CONN_OK;
258     else                                          resp_code = BNEP_SETUP_CONN_NOT_ALLOWED;
259
260     bnep_send_conn_responce (p_bcb, resp_code);
261     p_bcb->con_flags &= (~BNEP_FLAGS_SETUP_RCVD);
262
263     if (resp == BNEP_SUCCESS)
264         bnep_connected (p_bcb);
265     else if (p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)
266     {
267         /* Restore the original parameters */
268         p_bcb->con_state = BNEP_STATE_CONNECTED;
269         p_bcb->con_flags &= (~BNEP_FLAGS_SETUP_RCVD);
270
271         memcpy ((UINT8 *)&(p_bcb->src_uuid), (UINT8 *)&(p_bcb->prv_src_uuid), sizeof (tBT_UUID));
272         memcpy ((UINT8 *)&(p_bcb->dst_uuid), (UINT8 *)&(p_bcb->prv_dst_uuid), sizeof (tBT_UUID));
273     }
274
275     /* Process remaining part of the setup message (extension headers) */
276     if (p_bcb->p_pending_data)
277     {
278         UINT8   extension_present = TRUE, *p, ext_type;
279         UINT16  rem_len;
280
281         rem_len = p_bcb->p_pending_data->len;
282         p       = (UINT8 *)(p_bcb->p_pending_data + 1) + p_bcb->p_pending_data->offset;
283         while (extension_present && p && rem_len)
284         {
285             ext_type = *p++;
286             extension_present = ext_type >> 7;
287             ext_type &= 0x7F;
288
289             /* if unknown extension present stop processing */
290             if (ext_type)
291                 break;
292
293             p = bnep_process_control_packet (p_bcb, p, &rem_len, TRUE);
294         }
295
296         osi_free_and_reset((void **)&p_bcb->p_pending_data);
297     }
298     return (BNEP_SUCCESS);
299 }
300
301
302 /*******************************************************************************
303 **
304 ** Function         BNEP_Disconnect
305 **
306 ** Description      This function is called to close the specified connection.
307 **
308 ** Parameters:      handle   - handle of the connection
309 **
310 ** Returns          BNEP_SUCCESS                if connection is disconnected
311 **                  BNEP_WRONG_HANDLE           if no connection is not found
312 **
313 *******************************************************************************/
314 tBNEP_RESULT BNEP_Disconnect (UINT16 handle)
315 {
316     tBNEP_CONN      *p_bcb;
317
318     if ((!handle) || (handle > BNEP_MAX_CONNECTIONS))
319         return (BNEP_WRONG_HANDLE);
320
321     p_bcb = &(bnep_cb.bcb[handle - 1]);
322
323     if (p_bcb->con_state == BNEP_STATE_IDLE)
324         return (BNEP_WRONG_HANDLE);
325
326     BNEP_TRACE_API ("BNEP_Disconnect()  for handle %d", handle);
327
328     L2CA_DisconnectReq (p_bcb->l2cap_cid);
329
330     bnepu_release_bcb (p_bcb);
331
332     return (BNEP_SUCCESS);
333 }
334
335
336 /*******************************************************************************
337 **
338 ** Function         BNEP_WriteBuf
339 **
340 ** Description      This function sends data in a GKI buffer on BNEP connection
341 **
342 ** Parameters:      handle       - handle of the connection to write
343 **                  p_dest_addr  - BD_ADDR/Ethernet addr of the destination
344 **                  p_buf        - pointer to address of buffer with data
345 **                  protocol     - protocol type of the packet
346 **                  p_src_addr   - (optional) BD_ADDR/ethernet address of the source
347 **                                 (should be NULL if it is local BD Addr)
348 **                  fw_ext_present - forwarded extensions present
349 **
350 ** Returns:         BNEP_WRONG_HANDLE       - if passed handle is not valid
351 **                  BNEP_MTU_EXCEDED        - If the data length is greater than MTU
352 **                  BNEP_IGNORE_CMD         - If the packet is filtered out
353 **                  BNEP_Q_SIZE_EXCEEDED    - If the Tx Q is full
354 **                  BNEP_SUCCESS            - If written successfully
355 **
356 *******************************************************************************/
357 tBNEP_RESULT BNEP_WriteBuf (UINT16 handle,
358                             UINT8 *p_dest_addr,
359                             BT_HDR *p_buf,
360                             UINT16 protocol,
361                             UINT8 *p_src_addr,
362                             BOOLEAN fw_ext_present)
363 {
364     tBNEP_CONN      *p_bcb;
365     UINT8           *p_data;
366
367     if ((!handle) || (handle > BNEP_MAX_CONNECTIONS))
368     {
369         osi_free(p_buf);
370         return (BNEP_WRONG_HANDLE);
371     }
372
373     p_bcb = &(bnep_cb.bcb[handle - 1]);
374     /* Check MTU size */
375     if (p_buf->len > BNEP_MTU_SIZE)
376     {
377         BNEP_TRACE_ERROR ("BNEP_Write() length %d exceeded MTU %d", p_buf->len, BNEP_MTU_SIZE);
378         osi_free(p_buf);
379         return (BNEP_MTU_EXCEDED);
380     }
381
382     /* Check if the packet should be filtered out */
383     p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
384     if (bnep_is_packet_allowed (p_bcb, p_dest_addr, protocol, fw_ext_present, p_data) != BNEP_SUCCESS)
385     {
386         /*
387         ** If packet is filtered and ext headers are present
388         ** drop the data and forward the ext headers
389         */
390         if (fw_ext_present)
391         {
392             UINT8       ext, length;
393             UINT16      org_len, new_len;
394             /* parse the extension headers and findout the new packet len */
395             org_len = p_buf->len;
396             new_len = 0;
397             do {
398
399                 ext     = *p_data++;
400                 length  = *p_data++;
401                 p_data += length;
402
403                 new_len += (length + 2);
404
405                 if (new_len > org_len)
406                 {
407                     osi_free(p_buf);
408                     return BNEP_IGNORE_CMD;
409                 }
410
411             } while (ext & 0x80);
412
413             if (protocol != BNEP_802_1_P_PROTOCOL)
414                 protocol = 0;
415             else
416             {
417                 new_len += 4;
418                 if (new_len > org_len) {
419                     android_errorWriteLog(0x534e4554, "74947856");
420                     return BNEP_IGNORE_CMD;
421                 }
422                 p_data[2] = 0;
423                 p_data[3] = 0;
424             }
425             p_buf->len  = new_len;
426         }
427         else
428         {
429             osi_free(p_buf);
430             return BNEP_IGNORE_CMD;
431         }
432     }
433
434     /* Check transmit queue */
435     if (fixed_queue_length(p_bcb->xmit_q) >= BNEP_MAX_XMITQ_DEPTH)
436     {
437         osi_free(p_buf);
438         return (BNEP_Q_SIZE_EXCEEDED);
439     }
440
441     /* Build the BNEP header */
442     bnepu_build_bnep_hdr (p_bcb, p_buf, protocol, p_src_addr, p_dest_addr, fw_ext_present);
443
444     /* Send the data or queue it up */
445     bnepu_check_send_packet (p_bcb, p_buf);
446
447     return (BNEP_SUCCESS);
448 }
449
450
451 /*******************************************************************************
452 **
453 ** Function         BNEP_Write
454 **
455 ** Description      This function sends data over a BNEP connection
456 **
457 ** Parameters:      handle       - handle of the connection to write
458 **                  p_dest_addr  - BD_ADDR/Ethernet addr of the destination
459 **                  p_data       - pointer to data start
460 **                  protocol     - protocol type of the packet
461 **                  p_src_addr   - (optional) BD_ADDR/ethernet address of the source
462 **                                 (should be NULL if it is local BD Addr)
463 **                  fw_ext_present - forwarded extensions present
464 **
465 ** Returns:         BNEP_WRONG_HANDLE       - if passed handle is not valid
466 **                  BNEP_MTU_EXCEDED        - If the data length is greater than MTU
467 **                  BNEP_IGNORE_CMD         - If the packet is filtered out
468 **                  BNEP_Q_SIZE_EXCEEDED    - If the Tx Q is full
469 **                  BNEP_NO_RESOURCES       - If not able to allocate a buffer
470 **                  BNEP_SUCCESS            - If written successfully
471 **
472 *******************************************************************************/
473 tBNEP_RESULT  BNEP_Write (UINT16 handle,
474                           UINT8 *p_dest_addr,
475                           UINT8 *p_data,
476                           UINT16 len,
477                           UINT16 protocol,
478                           UINT8 *p_src_addr,
479                           BOOLEAN fw_ext_present)
480 {
481     tBNEP_CONN   *p_bcb;
482     UINT8        *p;
483
484     /* Check MTU size. Consider the possibility of having extension headers */
485     if (len > BNEP_MTU_SIZE)
486     {
487         BNEP_TRACE_ERROR ("BNEP_Write() length %d exceeded MTU %d", len, BNEP_MTU_SIZE);
488         return (BNEP_MTU_EXCEDED);
489     }
490
491     if ((!handle) || (handle > BNEP_MAX_CONNECTIONS))
492         return (BNEP_WRONG_HANDLE);
493
494     p_bcb = &(bnep_cb.bcb[handle - 1]);
495
496     /* Check if the packet should be filtered out */
497     if (bnep_is_packet_allowed (p_bcb, p_dest_addr, protocol, fw_ext_present, p_data) != BNEP_SUCCESS)
498     {
499         /*
500         ** If packet is filtered and ext headers are present
501         ** drop the data and forward the ext headers
502         */
503         if (fw_ext_present)
504         {
505             UINT8       ext, length;
506             UINT16      org_len, new_len;
507             /* parse the extension headers and findout the new packet len */
508             org_len = len;
509             new_len = 0;
510             p       = p_data;
511             do {
512
513                 ext     = *p_data++;
514                 length  = *p_data++;
515                 p_data += length;
516
517                 new_len += (length + 2);
518
519                 if (new_len > org_len)
520                     return BNEP_IGNORE_CMD;
521
522             } while (ext & 0x80);
523
524             if (protocol != BNEP_802_1_P_PROTOCOL)
525                 protocol = 0;
526             else
527             {
528                 new_len += 4;
529                 if (new_len > org_len) {
530                     android_errorWriteLog(0x534e4554, "74947856");
531                     return BNEP_IGNORE_CMD;
532                 }
533                 p_data[2] = 0;
534                 p_data[3] = 0;
535             }
536             len         = new_len;
537             p_data      = p;
538         }
539         else
540             return BNEP_IGNORE_CMD;
541     }
542
543     /* Check transmit queue */
544     if (fixed_queue_length(p_bcb->xmit_q) >= BNEP_MAX_XMITQ_DEPTH)
545         return (BNEP_Q_SIZE_EXCEEDED);
546
547     /* Get a buffer to copy the data into */
548     BT_HDR *p_buf = (BT_HDR *)osi_malloc(BNEP_BUF_SIZE);
549
550     p_buf->len = len;
551     p_buf->offset = BNEP_MINIMUM_OFFSET;
552     p = (UINT8 *)(p_buf + 1) + BNEP_MINIMUM_OFFSET;
553
554     memcpy (p, p_data, len);
555
556     /* Build the BNEP header */
557     bnepu_build_bnep_hdr (p_bcb, p_buf, protocol, p_src_addr, p_dest_addr, fw_ext_present);
558
559     /* Send the data or queue it up */
560     bnepu_check_send_packet (p_bcb, p_buf);
561
562     return (BNEP_SUCCESS);
563 }
564
565
566 /*******************************************************************************
567 **
568 ** Function         BNEP_SetProtocolFilters
569 **
570 ** Description      This function sets the protocol filters on peer device
571 **
572 ** Parameters:      handle        - Handle for the connection
573 **                  num_filters   - total number of filter ranges
574 **                  p_start_array - Array of beginings of all protocol ranges
575 **                  p_end_array   - Array of ends of all protocol ranges
576 **
577 ** Returns          BNEP_WRONG_HANDLE           - if the connection handle is not valid
578 **                  BNEP_SET_FILTER_FAIL        - if the connection is in wrong state
579 **                  BNEP_TOO_MANY_FILTERS       - if too many filters
580 **                  BNEP_SUCCESS                - if request sent successfully
581 **
582 *******************************************************************************/
583 tBNEP_RESULT BNEP_SetProtocolFilters (UINT16 handle,
584                                       UINT16 num_filters,
585                                       UINT16 *p_start_array,
586                                       UINT16 *p_end_array)
587 {
588     UINT16          xx;
589     tBNEP_CONN     *p_bcb;
590
591     if ((!handle) || (handle > BNEP_MAX_CONNECTIONS))
592         return (BNEP_WRONG_HANDLE);
593
594     p_bcb = &(bnep_cb.bcb[handle - 1]);
595
596     /* Check the connection state */
597     if ((p_bcb->con_state != BNEP_STATE_CONNECTED) &&
598         (!(p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)))
599         return (BNEP_WRONG_STATE);
600
601     /* Validate the parameters */
602     if (num_filters && (!p_start_array || !p_end_array))
603         return (BNEP_SET_FILTER_FAIL);
604
605     if (num_filters > BNEP_MAX_PROT_FILTERS)
606         return (BNEP_TOO_MANY_FILTERS);
607
608     /* Fill the filter values in connnection block */
609     for (xx = 0; xx < num_filters; xx++)
610     {
611         p_bcb->sent_prot_filter_start[xx] = *p_start_array++;
612         p_bcb->sent_prot_filter_end[xx]   = *p_end_array++;
613     }
614
615     p_bcb->sent_num_filters = num_filters;
616
617     bnepu_send_peer_our_filters (p_bcb);
618
619     return (BNEP_SUCCESS);
620 }
621
622
623 /*******************************************************************************
624 **
625 ** Function         BNEP_SetMulticastFilters
626 **
627 ** Description      This function sets the filters for multicast addresses for BNEP.
628 **
629 ** Parameters:      handle        - Handle for the connection
630 **                  num_filters   - total number of filter ranges
631 **                  p_start_array - Pointer to sequence of beginings of all
632 **                                         multicast address ranges
633 **                  p_end_array   - Pointer to sequence of ends of all
634 **                                         multicast address ranges
635 **
636 ** Returns          BNEP_WRONG_HANDLE           - if the connection handle is not valid
637 **                  BNEP_SET_FILTER_FAIL        - if the connection is in wrong state
638 **                  BNEP_TOO_MANY_FILTERS       - if too many filters
639 **                  BNEP_SUCCESS                - if request sent successfully
640 **
641 *******************************************************************************/
642 tBNEP_RESULT BNEP_SetMulticastFilters (UINT16 handle,
643                                        UINT16 num_filters,
644                                        UINT8 *p_start_array,
645                                        UINT8 *p_end_array)
646 {
647     UINT16          xx;
648     tBNEP_CONN     *p_bcb;
649
650     if ((!handle) || (handle > BNEP_MAX_CONNECTIONS))
651         return (BNEP_WRONG_HANDLE);
652
653     p_bcb = &(bnep_cb.bcb[handle - 1]);
654
655     /* Check the connection state */
656     if ((p_bcb->con_state != BNEP_STATE_CONNECTED) &&
657         (!(p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)))
658         return (BNEP_WRONG_STATE);
659
660     /* Validate the parameters */
661     if (num_filters && (!p_start_array || !p_end_array))
662         return (BNEP_SET_FILTER_FAIL);
663
664     if (num_filters > BNEP_MAX_MULTI_FILTERS)
665         return (BNEP_TOO_MANY_FILTERS);
666
667     /* Fill the multicast filter values in connnection block */
668     for (xx = 0; xx < num_filters; xx++)
669     {
670         memcpy (p_bcb->sent_mcast_filter_start[xx], p_start_array, BD_ADDR_LEN);
671         memcpy (p_bcb->sent_mcast_filter_end[xx], p_end_array, BD_ADDR_LEN);
672
673         p_start_array += BD_ADDR_LEN;
674         p_end_array   += BD_ADDR_LEN;
675     }
676
677     p_bcb->sent_mcast_filters = num_filters;
678
679     bnepu_send_peer_our_multi_filters (p_bcb);
680
681     return (BNEP_SUCCESS);
682 }
683
684 /*******************************************************************************
685 **
686 ** Function         BNEP_SetTraceLevel
687 **
688 ** Description      This function sets the trace level for BNEP. If called with
689 **                  a value of 0xFF, it simply reads the current trace level.
690 **
691 ** Returns          the new (current) trace level
692 **
693 *******************************************************************************/
694 UINT8 BNEP_SetTraceLevel (UINT8 new_level)
695 {
696     if (new_level != 0xFF)
697         bnep_cb.trace_level = new_level;
698
699     return (bnep_cb.trace_level);
700 }
701
702
703 /*******************************************************************************
704 **
705 ** Function         BNEP_GetStatus
706 **
707 ** Description      This function gets the status information for BNEP connection
708 **
709 ** Returns          BNEP_SUCCESS            - if the status is available
710 **                  BNEP_NO_RESOURCES       - if no structure is passed for output
711 **                  BNEP_WRONG_HANDLE       - if the handle is invalid
712 **                  BNEP_WRONG_STATE        - if not in connected state
713 **
714 *******************************************************************************/
715 tBNEP_RESULT BNEP_GetStatus (UINT16 handle, tBNEP_STATUS *p_status)
716 {
717 #if (defined (BNEP_SUPPORTS_STATUS_API) && BNEP_SUPPORTS_STATUS_API == TRUE)
718     tBNEP_CONN     *p_bcb;
719
720     if (!p_status)
721         return BNEP_NO_RESOURCES;
722
723     if ((!handle) || (handle > BNEP_MAX_CONNECTIONS))
724         return (BNEP_WRONG_HANDLE);
725
726     p_bcb = &(bnep_cb.bcb[handle - 1]);
727
728     memset (p_status, 0, sizeof (tBNEP_STATUS));
729     if ((p_bcb->con_state != BNEP_STATE_CONNECTED) &&
730         (!(p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)))
731         return BNEP_WRONG_STATE;
732
733     /* Read the status parameters from the connection control block */
734     p_status->con_status            = BNEP_STATUS_CONNECTED;
735     p_status->l2cap_cid             = p_bcb->l2cap_cid;
736     p_status->rem_mtu_size          = p_bcb->rem_mtu_size;
737     p_status->xmit_q_depth          = fixed_queue_length(p_bcb->xmit_q);
738     p_status->sent_num_filters      = p_bcb->sent_num_filters;
739     p_status->sent_mcast_filters    = p_bcb->sent_mcast_filters;
740     p_status->rcvd_num_filters      = p_bcb->rcvd_num_filters;
741     p_status->rcvd_mcast_filters    = p_bcb->rcvd_mcast_filters;
742
743     memcpy (p_status->rem_bda, p_bcb->rem_bda, BD_ADDR_LEN);
744     memcpy (&(p_status->src_uuid), &(p_bcb->src_uuid), sizeof (tBT_UUID));
745     memcpy (&(p_status->dst_uuid), &(p_bcb->dst_uuid), sizeof (tBT_UUID));
746
747     return BNEP_SUCCESS;
748 #else
749     return (BNEP_IGNORE_CMD);
750 #endif
751 }
752
753