1 /******************************************************************************
3 * Copyright (C) 2006-2012 Broadcom Corporation
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ******************************************************************************/
19 /******************************************************************************
21 * This file contains action functions for BTA JV APIs.
23 ******************************************************************************/
24 #include <hardware/bluetooth.h>
25 #include <arpa/inet.h>
30 #include "osi/include/allocator.h"
33 #include "bt_common.h"
37 #include "bta_jv_api.h"
38 #include "bta_jv_int.h"
39 #include "bta_jv_co.h"
51 #include "osi/include/osi.h"
53 extern fixed_queue_t *btu_general_alarm_queue;
54 /* one of these exists for each client */
56 struct fc_client *next_all_list;
57 struct fc_client *next_chan_list;
60 tBTA_JV_L2CAP_CBACK *p_cback;
66 unsigned init_called : 1;
69 /* one of these exists for each channel we're dealing with */
71 struct fc_channel *next;
72 struct fc_client *clients;
73 uint8_t has_server : 1;
78 static struct fc_client *fc_clients;
79 static struct fc_channel *fc_channels;
80 static uint32_t fc_next_id;
83 static void fcchan_conn_chng_cbk(UINT16 chan, BD_ADDR bd_addr, BOOLEAN connected,
84 UINT16 reason, tBT_TRANSPORT );
85 static void fcchan_data_cbk(UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf);
88 extern void uuid_to_string_legacy(bt_uuid_t *p_uuid, char *str);
89 static inline void logu(const char* title, const uint8_t * p_uuid)
92 uuid_to_string_legacy((bt_uuid_t*)p_uuid, uuids);
93 APPL_TRACE_DEBUG("%s: %s", title, uuids);
97 static tBTA_JV_PCB * bta_jv_add_rfc_port(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pcb_open);
98 static tBTA_JV_STATUS bta_jv_free_set_pm_profile_cb(UINT32 jv_handle);
99 static void bta_jv_pm_conn_busy(tBTA_JV_PM_CB *p_cb);
100 static void bta_jv_pm_conn_idle(tBTA_JV_PM_CB *p_cb);
101 static void bta_jv_pm_state_change(tBTA_JV_PM_CB *p_cb, const tBTA_JV_CONN_STATE state);
102 tBTA_JV_STATUS bta_jv_set_pm_conn_state(tBTA_JV_PM_CB *p_cb, const tBTA_JV_CONN_STATE
105 /*******************************************************************************
107 ** Function bta_jv_alloc_sec_id
109 ** Description allocate a security id
113 *******************************************************************************/
114 UINT8 bta_jv_alloc_sec_id(void)
118 for(i=0; i<BTA_JV_NUM_SERVICE_ID; i++)
120 if(0 == bta_jv_cb.sec_id[i])
122 bta_jv_cb.sec_id[i] = BTA_JV_FIRST_SERVICE_ID + i;
123 ret = bta_jv_cb.sec_id[i];
130 static int get_sec_id_used(void)
134 for(i=0; i<BTA_JV_NUM_SERVICE_ID; i++)
136 if(bta_jv_cb.sec_id[i])
139 if (used == BTA_JV_NUM_SERVICE_ID)
140 APPL_TRACE_ERROR("get_sec_id_used, sec id exceeds the limit:%d",
141 BTA_JV_NUM_SERVICE_ID);
144 static int get_rfc_cb_used(void)
148 for(i=0; i<BTA_JV_MAX_RFC_CONN; i++)
150 if(bta_jv_cb.rfc_cb[i].handle )
153 if (used == BTA_JV_MAX_RFC_CONN)
154 APPL_TRACE_ERROR("get_sec_id_used, rfc ctrl block exceeds the limit:%d",
155 BTA_JV_MAX_RFC_CONN);
159 /*******************************************************************************
161 ** Function bta_jv_free_sec_id
163 ** Description free the given security id
167 *******************************************************************************/
168 static void bta_jv_free_sec_id(UINT8 *p_sec_id)
170 UINT8 sec_id = *p_sec_id;
172 if(sec_id >= BTA_JV_FIRST_SERVICE_ID && sec_id <= BTA_JV_LAST_SERVICE_ID)
174 BTM_SecClrService(sec_id);
175 bta_jv_cb.sec_id[sec_id - BTA_JV_FIRST_SERVICE_ID] = 0;
179 /*******************************************************************************
181 ** Function bta_jv_alloc_rfc_cb
183 ** Description allocate a control block for the given port handle
187 *******************************************************************************/
188 tBTA_JV_RFC_CB * bta_jv_alloc_rfc_cb(UINT16 port_handle, tBTA_JV_PCB **pp_pcb)
190 tBTA_JV_RFC_CB *p_cb = NULL;
193 for(i=0; i<BTA_JV_MAX_RFC_CONN; i++)
195 if (0 == bta_jv_cb.rfc_cb[i].handle )
197 p_cb = &bta_jv_cb.rfc_cb[i];
198 /* mask handle to distinguish it with L2CAP handle */
199 p_cb->handle = (i + 1) | BTA_JV_RFCOMM_MASK;
203 for (j = 0; j < BTA_JV_MAX_RFC_SR_SESSION; j++)
204 p_cb->rfc_hdl[j] = 0;
205 p_cb->rfc_hdl[0] = port_handle;
206 APPL_TRACE_DEBUG( "bta_jv_alloc_rfc_cb port_handle:%d handle:0x%2x",
207 port_handle, p_cb->handle);
209 p_pcb = &bta_jv_cb.port_cb[port_handle - 1];
210 p_pcb->handle = p_cb->handle;
211 p_pcb->port_handle = port_handle;
212 p_pcb->p_pm_cb = NULL;
219 APPL_TRACE_ERROR( "bta_jv_alloc_rfc_cb: port_handle:%d, ctrl block exceeds "
220 "limit:%d", port_handle, BTA_JV_MAX_RFC_CONN);
225 /*******************************************************************************
227 ** Function bta_jv_rfc_port_to_pcb
229 ** Description find the port control block associated with the given port handle
233 *******************************************************************************/
234 tBTA_JV_PCB * bta_jv_rfc_port_to_pcb(UINT16 port_handle)
236 tBTA_JV_PCB *p_pcb = NULL;
238 if ((port_handle > 0) && (port_handle <= MAX_RFC_PORTS)
239 && bta_jv_cb.port_cb[port_handle - 1].handle)
241 p_pcb = &bta_jv_cb.port_cb[port_handle - 1];
247 /*******************************************************************************
249 ** Function bta_jv_rfc_port_to_cb
251 ** Description find the RFCOMM control block associated with the given port handle
255 *******************************************************************************/
256 tBTA_JV_RFC_CB * bta_jv_rfc_port_to_cb(UINT16 port_handle)
258 tBTA_JV_RFC_CB *p_cb = NULL;
261 if ((port_handle > 0) && (port_handle <= MAX_RFC_PORTS)
262 && bta_jv_cb.port_cb[port_handle - 1].handle)
264 handle = bta_jv_cb.port_cb[port_handle - 1].handle;
265 handle &= BTA_JV_RFC_HDL_MASK;
266 handle &= ~BTA_JV_RFCOMM_MASK;
268 p_cb = &bta_jv_cb.rfc_cb[handle - 1];
272 APPL_TRACE_WARNING("bta_jv_rfc_port_to_cb(port_handle:0x%x):jv handle:0x%x not"
273 " FOUND", port_handle, bta_jv_cb.port_cb[port_handle - 1].handle);
278 static tBTA_JV_STATUS bta_jv_free_rfc_cb(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pcb)
280 tBTA_JV_STATUS status = BTA_JV_SUCCESS;
281 BOOLEAN remove_server = FALSE;
282 int close_pending = 0;
286 APPL_TRACE_ERROR("bta_jv_free_sr_rfc_cb, p_cb or p_pcb cannot be null");
287 return BTA_JV_FAILURE;
289 APPL_TRACE_DEBUG("bta_jv_free_sr_rfc_cb: max_sess:%d, curr_sess:%d, p_pcb:%p, user:"
290 "%p, state:%d, jv handle: 0x%x" ,p_cb->max_sess, p_cb->curr_sess, p_pcb,
291 p_pcb->user_data, p_pcb->state, p_pcb->handle);
293 if (p_cb->curr_sess <= 0)
294 return BTA_JV_SUCCESS;
296 switch (p_pcb->state)
298 case BTA_JV_ST_CL_CLOSING:
299 case BTA_JV_ST_SR_CLOSING:
300 APPL_TRACE_WARNING("bta_jv_free_sr_rfc_cb: return on closing, port state:%d, "
301 "scn:%d, p_pcb:%p, user_data:%p", p_pcb->state, p_cb->scn, p_pcb,
303 status = BTA_JV_FAILURE;
305 case BTA_JV_ST_CL_OPEN:
306 case BTA_JV_ST_CL_OPENING:
307 APPL_TRACE_DEBUG("bta_jv_free_sr_rfc_cb: state: %d, scn:%d,"
308 " user_data:%p", p_pcb->state, p_cb->scn, p_pcb->user_data);
309 p_pcb->state = BTA_JV_ST_CL_CLOSING;
311 case BTA_JV_ST_SR_LISTEN:
312 p_pcb->state = BTA_JV_ST_SR_CLOSING;
313 remove_server = TRUE;
314 APPL_TRACE_DEBUG("bta_jv_free_sr_rfc_cb: state: BTA_JV_ST_SR_LISTEN, scn:%d,"
315 " user_data:%p", p_cb->scn, p_pcb->user_data);
317 case BTA_JV_ST_SR_OPEN:
318 p_pcb->state = BTA_JV_ST_SR_CLOSING;
319 APPL_TRACE_DEBUG("bta_jv_free_sr_rfc_cb: state: BTA_JV_ST_SR_OPEN, scn:%d,"
320 " user_data:%p", p_cb->scn, p_pcb->user_data);
323 APPL_TRACE_WARNING("bta_jv_free_sr_rfc_cb():failed, ignore port state:%d, scn:"
324 "%d, p_pcb:%p, jv handle: 0x%x, port_handle: %d, user_data:%p",
325 p_pcb->state, p_cb->scn, p_pcb, p_pcb->handle, p_pcb->port_handle,
327 status = BTA_JV_FAILURE;
330 if (BTA_JV_SUCCESS == status)
335 port_status = RFCOMM_RemoveConnection(p_pcb->port_handle);
337 port_status = RFCOMM_RemoveServer(p_pcb->port_handle);
338 if (port_status != PORT_SUCCESS)
340 status = BTA_JV_FAILURE;
341 APPL_TRACE_WARNING("bta_jv_free_rfc_cb(jv handle: 0x%x, state %d)::"
342 "port_status: %d, port_handle: %d, close_pending: %d:Remove",
343 p_pcb->handle, p_pcb->state, port_status, p_pcb->port_handle,
349 p_pcb->port_handle = 0;
350 p_pcb->state = BTA_JV_ST_NONE;
351 bta_jv_free_set_pm_profile_cb(p_pcb->handle);
353 //Initialize congestion flags
355 p_pcb->user_data = 0;
356 int si = BTA_JV_RFC_HDL_TO_SIDX(p_pcb->handle);
357 if (0 <= si && si < BTA_JV_MAX_RFC_SR_SESSION)
358 p_cb->rfc_hdl[si] = 0;
361 if (p_cb->curr_sess == 0)
364 bta_jv_free_sec_id(&p_cb->sec_id);
365 p_cb->p_cback = NULL;
367 p_cb->curr_sess = -1;
370 bta_jv_free_sec_id(&p_cb->sec_id);
376 /*******************************************************************************
378 ** Function bta_jv_free_l2c_cb
380 ** Description free the given L2CAP control block
384 *******************************************************************************/
385 tBTA_JV_STATUS bta_jv_free_l2c_cb(tBTA_JV_L2C_CB *p_cb)
387 tBTA_JV_STATUS status = BTA_JV_SUCCESS;
389 if(BTA_JV_ST_NONE != p_cb->state)
391 bta_jv_free_set_pm_profile_cb((UINT32)p_cb->handle);
392 if (GAP_ConnClose(p_cb->handle) != BT_PASS)
393 status = BTA_JV_FAILURE;
396 p_cb->state = BTA_JV_ST_NONE;
398 bta_jv_free_sec_id(&p_cb->sec_id);
399 p_cb->p_cback = NULL;
403 /*******************************************************************************
406 ** Function bta_jv_clear_pm_cb
408 ** Description clears jv pm control block and optionally calls bta_sys_conn_close()
409 ** In general close_conn should be set to TRUE to remove registering with
412 ** WARNING: Make sure to clear pointer form port or l2c to this control block too!
414 *******************************************************************************/
415 static void bta_jv_clear_pm_cb(tBTA_JV_PM_CB *p_pm_cb, BOOLEAN close_conn)
417 /* needs to be called if registered with bta pm, otherwise we may run out of dm pm slots! */
419 bta_sys_conn_close(BTA_ID_JV, p_pm_cb->app_id, p_pm_cb->peer_bd_addr);
421 /* Ensure that timer is stopped */
422 alarm_cancel(p_pm_cb->idle_timer);
423 p_pm_cb->state = BTA_JV_PM_FREE_ST;
424 p_pm_cb->app_id = BTA_JV_PM_ALL;
425 p_pm_cb->handle = BTA_JV_PM_HANDLE_CLEAR;
426 bdcpy(p_pm_cb->peer_bd_addr, bd_addr_null);
429 /*******************************************************************************
431 ** Function bta_jv_free_set_pm_profile_cb
433 ** Description free pm profile control block
435 ** Returns BTA_JV_SUCCESS if cb has been freed correctly,
436 ** BTA_JV_FAILURE in case of no profile has been registered or already freed
438 *******************************************************************************/
439 static tBTA_JV_STATUS bta_jv_free_set_pm_profile_cb(UINT32 jv_handle)
441 tBTA_JV_STATUS status = BTA_JV_FAILURE;
442 tBTA_JV_PM_CB **p_cb;
443 int i, j, bd_counter = 0, appid_counter = 0;
445 for (i = 0; i < BTA_JV_PM_MAX_NUM; i++)
448 if ((bta_jv_cb.pm_cb[i].state != BTA_JV_PM_FREE_ST) &&
449 (jv_handle == bta_jv_cb.pm_cb[i].handle))
451 for (j = 0; j < BTA_JV_PM_MAX_NUM; j++)
453 if (bdcmp(bta_jv_cb.pm_cb[j].peer_bd_addr, bta_jv_cb.pm_cb[i].peer_bd_addr) == 0)
455 if (bta_jv_cb.pm_cb[j].app_id == bta_jv_cb.pm_cb[i].app_id)
459 APPL_TRACE_API("%s(jv_handle: 0x%2x), idx: %d, "
460 "app_id: 0x%x",__func__, jv_handle, i, bta_jv_cb.pm_cb[i].app_id);
461 APPL_TRACE_API("%s, bd_counter = %d, "
462 "appid_counter = %d", __func__, bd_counter, appid_counter);
465 bta_jv_pm_conn_idle(&bta_jv_cb.pm_cb[i]);
468 if (bd_counter <= 1 || (appid_counter <= 1))
470 bta_jv_clear_pm_cb(&bta_jv_cb.pm_cb[i], TRUE);
474 bta_jv_clear_pm_cb(&bta_jv_cb.pm_cb[i], FALSE);
477 if (BTA_JV_RFCOMM_MASK & jv_handle)
479 UINT32 hi = ((jv_handle & BTA_JV_RFC_HDL_MASK) & ~BTA_JV_RFCOMM_MASK) - 1;
480 UINT32 si = BTA_JV_RFC_HDL_TO_SIDX(jv_handle);
481 if (hi < BTA_JV_MAX_RFC_CONN && bta_jv_cb.rfc_cb[hi].p_cback && si
482 < BTA_JV_MAX_RFC_SR_SESSION && bta_jv_cb.rfc_cb[hi].rfc_hdl[si])
484 tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(bta_jv_cb.rfc_cb[hi].rfc_hdl[si]);
487 if (NULL == p_pcb->p_pm_cb)
488 APPL_TRACE_WARNING("%s(jv_handle:"
489 " 0x%x):port_handle: 0x%x, p_pm_cb: %d: no link to "
490 "pm_cb?", __func__, jv_handle, p_pcb->port_handle, i);
491 p_cb = &p_pcb->p_pm_cb;
497 if (jv_handle < BTA_JV_MAX_L2C_CONN)
499 tBTA_JV_L2C_CB *p_l2c_cb = &bta_jv_cb.l2c_cb[jv_handle];
500 if (NULL == p_l2c_cb->p_pm_cb)
501 APPL_TRACE_WARNING("%s(jv_handle: "
502 "0x%x): p_pm_cb: %d: no link to pm_cb?", __func__, jv_handle, i);
503 p_cb = &p_l2c_cb->p_pm_cb;
509 status = BTA_JV_SUCCESS;
516 /*******************************************************************************
518 ** Function bta_jv_alloc_set_pm_profile_cb
520 ** Description set PM profile control block
522 ** Returns pointer to allocated cb or NULL in case of failure
524 *******************************************************************************/
525 static tBTA_JV_PM_CB *bta_jv_alloc_set_pm_profile_cb(UINT32 jv_handle, tBTA_JV_PM_ID app_id)
527 BOOLEAN bRfcHandle = (jv_handle & BTA_JV_RFCOMM_MASK) != 0;
528 BD_ADDR peer_bd_addr;
530 tBTA_JV_PM_CB **pp_cb;
532 for (i = 0; i < BTA_JV_PM_MAX_NUM; i++)
535 if (bta_jv_cb.pm_cb[i].state == BTA_JV_PM_FREE_ST)
537 /* rfc handle bd addr retrieval requires core stack handle */
540 for (j = 0; j < BTA_JV_MAX_RFC_CONN; j++)
542 if (jv_handle == bta_jv_cb.port_cb[j].handle)
544 pp_cb = &bta_jv_cb.port_cb[j].p_pm_cb;
545 if (PORT_SUCCESS != PORT_CheckConnection(
546 bta_jv_cb.port_cb[j].port_handle, peer_bd_addr, NULL))
547 i = BTA_JV_PM_MAX_NUM;
554 /* use jv handle for l2cap bd address retrieval */
555 for (j = 0; j < BTA_JV_MAX_L2C_CONN; j++)
557 if (jv_handle == bta_jv_cb.l2c_cb[j].handle)
559 pp_cb = &bta_jv_cb.l2c_cb[j].p_pm_cb;
560 UINT8 *p_bd_addr = GAP_ConnGetRemoteAddr((UINT16)jv_handle);
561 if (NULL != p_bd_addr)
562 bdcpy(peer_bd_addr, p_bd_addr);
564 i = BTA_JV_PM_MAX_NUM;
569 APPL_TRACE_API("bta_jv_alloc_set_pm_profile_cb(handle 0x%2x, app_id %d): "
570 "idx: %d, (BTA_JV_PM_MAX_NUM: %d), pp_cb: 0x%x", jv_handle, app_id,
571 i, BTA_JV_PM_MAX_NUM, pp_cb);
576 if ((i != BTA_JV_PM_MAX_NUM) && (NULL != pp_cb))
578 *pp_cb = &bta_jv_cb.pm_cb[i];
579 bta_jv_cb.pm_cb[i].handle = jv_handle;
580 bta_jv_cb.pm_cb[i].app_id = app_id;
581 bdcpy(bta_jv_cb.pm_cb[i].peer_bd_addr, peer_bd_addr);
582 bta_jv_cb.pm_cb[i].state = BTA_JV_PM_IDLE_ST;
584 bta_jv_cb.pm_cb[i].idle_timer = alarm_new("bta.jv_idle_timer");
585 APPL_TRACE_DEBUG("bta_jv_alloc_set_pm_profile_cb: %d, PM_cb: %p", i, &bta_jv_cb.pm_cb[i]);
586 return &bta_jv_cb.pm_cb[i];
588 APPL_TRACE_WARNING("bta_jv_alloc_set_pm_profile_cb(jv_handle: 0x%x, app_id: %d) "
589 "return NULL", jv_handle, app_id);
590 return (tBTA_JV_PM_CB *)NULL;
593 /*******************************************************************************
595 ** Function bta_jv_check_psm
597 ** Description for now use only the legal PSM per JSR82 spec
599 ** Returns TRUE, if allowed
601 *******************************************************************************/
602 BOOLEAN bta_jv_check_psm(UINT16 psm)
606 if (L2C_IS_VALID_PSM(psm))
610 /* see if this is defined by spec */
613 case SDP_PSM: /* 1 */
614 case BT_PSM_RFCOMM: /* 3 */
615 /* do not allow java app to use these 2 PSMs */
618 case TCS_PSM_INTERCOM: /* 5 */
619 case TCS_PSM_CORDLESS: /* 7 */
620 if( FALSE == bta_sys_is_register(BTA_ID_CT) &&
621 FALSE == bta_sys_is_register(BTA_ID_CG) )
625 case BT_PSM_BNEP: /* F */
626 if(FALSE == bta_sys_is_register(BTA_ID_PAN))
630 case HID_PSM_CONTROL: /* 0x11 */
631 case HID_PSM_INTERRUPT: /* 0x13 */
632 //FIX: allow HID Device and HID Host to coexist
633 if( FALSE == bta_sys_is_register(BTA_ID_HD) ||
634 FALSE == bta_sys_is_register(BTA_ID_HH) )
638 case AVCT_PSM: /* 0x17 */
639 case AVDT_PSM: /* 0x19 */
640 if ((FALSE == bta_sys_is_register(BTA_ID_AV)) &&
641 (FALSE == bta_sys_is_register(BTA_ID_AVK)))
659 /*******************************************************************************
661 ** Function bta_jv_enable
663 ** Description Initialises the JAVA I/F
667 *******************************************************************************/
668 void bta_jv_enable(tBTA_JV_MSG *p_data)
670 tBTA_JV_STATUS status = BTA_JV_SUCCESS;
671 bta_jv_cb.p_dm_cback = p_data->enable.p_cback;
672 bta_jv_cb.p_dm_cback(BTA_JV_ENABLE_EVT, (tBTA_JV *)&status, 0);
673 memset(bta_jv_cb.free_psm_list,0,sizeof(bta_jv_cb.free_psm_list));
676 /*******************************************************************************
678 ** Function bta_jv_disable
680 ** Description Disables the BT device manager
681 ** free the resources used by java
685 *******************************************************************************/
686 void bta_jv_disable (tBTA_JV_MSG *p_data)
690 APPL_TRACE_ERROR("%s",__func__);
695 * We keep a list of PSM's that have been freed from JAVA, for reuse.
696 * This function will return a free PSM, and delete it from the free
698 * If no free PSMs exist, 0 will be returned.
700 static UINT16 bta_jv_get_free_psm() {
701 const int cnt = sizeof(bta_jv_cb.free_psm_list)/sizeof(bta_jv_cb.free_psm_list[0]);
702 for (int i = 0; i < cnt; i++) {
703 UINT16 psm = bta_jv_cb.free_psm_list[i];
705 APPL_TRACE_DEBUG("%s(): Reusing PSM: 0x%04d", __func__, psm)
706 bta_jv_cb.free_psm_list[i] = 0;
713 static void bta_jv_set_free_psm(UINT16 psm) {
715 const int cnt = sizeof(bta_jv_cb.free_psm_list)/sizeof(bta_jv_cb.free_psm_list[0]);
716 for (int i = 0; i < cnt; i++) {
717 if (bta_jv_cb.free_psm_list[i] == 0) {
719 } else if (psm == bta_jv_cb.free_psm_list[i]) {
720 return; // PSM already freed?
723 if (free_index != -1) {
724 bta_jv_cb.free_psm_list[free_index] = psm;
725 APPL_TRACE_DEBUG("%s(): Recycling PSM: 0x%04d", __func__, psm)
727 APPL_TRACE_ERROR("%s unable to free psm 0x%x no more free slots",__func__, psm);
731 /*******************************************************************************
733 ** Function bta_jv_get_channel_id
735 ** Description Obtain a free SCN (Server Channel Number)
736 ** (RFCOMM channel or L2CAP PSM)
740 *******************************************************************************/
741 void bta_jv_get_channel_id(tBTA_JV_MSG *p_data)
745 switch (p_data->alloc_channel.type) {
746 case BTA_JV_CONN_TYPE_RFCOMM: {
747 INT32 channel = p_data->alloc_channel.channel;
751 if (BTM_TryAllocateSCN(channel) == FALSE)
753 APPL_TRACE_ERROR("rfc channel:%d already in use or invalid", channel);
756 } else if ((channel = BTM_AllocateSCN()) == 0) {
757 APPL_TRACE_ERROR("run out of rfc channels");
761 bta_jv_cb.scn[channel-1] = TRUE;
762 scn = (UINT8) channel;
764 if (bta_jv_cb.p_dm_cback)
765 bta_jv_cb.p_dm_cback(BTA_JV_GET_SCN_EVT, (tBTA_JV *)&scn,
766 p_data->alloc_channel.user_data);
769 case BTA_JV_CONN_TYPE_L2CAP:
770 psm = bta_jv_get_free_psm();
772 psm = L2CA_AllocatePSM();
773 APPL_TRACE_DEBUG("%s() returned PSM: 0x%04x", __func__, psm);
776 case BTA_JV_CONN_TYPE_L2CAP_LE:
782 if (bta_jv_cb.p_dm_cback)
783 bta_jv_cb.p_dm_cback(BTA_JV_GET_PSM_EVT, (tBTA_JV *)&psm, p_data->alloc_channel.user_data);
786 /*******************************************************************************
788 ** Function bta_jv_free_scn
790 ** Description free a SCN
794 *******************************************************************************/
795 void bta_jv_free_scn(tBTA_JV_MSG *p_data)
797 UINT16 scn = p_data->free_channel.scn;
799 switch (p_data->free_channel.type) {
800 case BTA_JV_CONN_TYPE_RFCOMM: {
801 if (scn > 0 && scn <= BTA_JV_MAX_SCN && bta_jv_cb.scn[scn-1])
803 /* this scn is used by JV */
804 bta_jv_cb.scn[scn-1] = FALSE;
809 case BTA_JV_CONN_TYPE_L2CAP:
810 bta_jv_set_free_psm(scn);
812 case BTA_JV_CONN_TYPE_L2CAP_LE:
813 // TODO: Not yet implemented...
819 static inline tBT_UUID shorten_sdp_uuid(const tBT_UUID* u)
821 static uint8_t bt_base_uuid[] =
822 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB };
824 logu("in, uuid:", u->uu.uuid128);
825 APPL_TRACE_DEBUG("uuid len:%d", u->len);
828 if(memcmp(&u->uu.uuid128[4], &bt_base_uuid[4], 12) == 0)
831 memset(&su, 0, sizeof(su));
832 if(u->uu.uuid128[0] == 0 && u->uu.uuid128[1] == 0)
836 memcpy(&u16, &u->uu.uuid128[2], sizeof(u16));
837 su.uu.uuid16 = ntohs(u16);
838 APPL_TRACE_DEBUG("shorten to 16 bits uuid: %x", su.uu.uuid16);
844 memcpy(&u32, &u->uu.uuid128[0], sizeof(u32));
845 su.uu.uuid32 = ntohl(u32);
846 APPL_TRACE_DEBUG("shorten to 32 bits uuid: %x", su.uu.uuid32);
851 APPL_TRACE_DEBUG("cannot shorten none-reserved 128 bits uuid");
855 /*******************************************************************************
857 ** Function bta_jv_start_discovery_cback
859 ** Description Callback for Start Discovery
863 *******************************************************************************/
864 static void bta_jv_start_discovery_cback(UINT16 result, void * user_data)
866 tBTA_JV_STATUS status;
868 APPL_TRACE_DEBUG("bta_jv_start_discovery_cback res: 0x%x", result);
870 bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_NONE;
871 if(bta_jv_cb.p_dm_cback)
873 tBTA_JV_DISCOVERY_COMP dcomp;
875 status = BTA_JV_FAILURE;
876 if (result == SDP_SUCCESS || result == SDP_DB_FULL)
878 tSDP_DISC_REC *p_sdp_rec = NULL;
879 tSDP_PROTOCOL_ELEM pe;
880 logu("bta_jv_cb.uuid", bta_jv_cb.uuid.uu.uuid128);
881 tBT_UUID su = shorten_sdp_uuid(&bta_jv_cb.uuid);
882 logu("shorten uuid:", su.uu.uuid128);
883 p_sdp_rec = SDP_FindServiceUUIDInDb(p_bta_jv_cfg->p_sdp_db, &su, p_sdp_rec);
884 APPL_TRACE_DEBUG("p_sdp_rec:%p", p_sdp_rec);
885 if (p_sdp_rec && SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_RFCOMM, &pe))
887 dcomp.scn = (UINT8) pe.params[0];
888 status = BTA_JV_SUCCESS;
892 dcomp.status = status;
893 bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, (tBTA_JV *)&dcomp, user_data);
897 /*******************************************************************************
899 ** Function bta_jv_start_discovery
901 ** Description Discovers services on a remote device
905 *******************************************************************************/
906 void bta_jv_start_discovery(tBTA_JV_MSG *p_data)
908 tBTA_JV_STATUS status = BTA_JV_FAILURE;
909 APPL_TRACE_DEBUG("bta_jv_start_discovery in, sdp_active:%d", bta_jv_cb.sdp_active);
910 if (bta_jv_cb.sdp_active != BTA_JV_SDP_ACT_NONE)
912 /* SDP is still in progress */
913 status = BTA_JV_BUSY;
914 if(bta_jv_cb.p_dm_cback)
915 bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, (tBTA_JV *)&status, p_data->start_discovery.user_data);
919 /* init the database/set up the filter */
920 APPL_TRACE_DEBUG("call SDP_InitDiscoveryDb, p_data->start_discovery.num_uuid:%d",
921 p_data->start_discovery.num_uuid);
922 SDP_InitDiscoveryDb (p_bta_jv_cfg->p_sdp_db, p_bta_jv_cfg->sdp_db_size,
923 p_data->start_discovery.num_uuid, p_data->start_discovery.uuid_list, 0, NULL);
925 /* tell SDP to keep the raw data */
926 p_bta_jv_cfg->p_sdp_db->raw_data = p_bta_jv_cfg->p_sdp_raw_data;
927 p_bta_jv_cfg->p_sdp_db->raw_size = p_bta_jv_cfg->sdp_raw_size;
929 bta_jv_cb.p_sel_raw_data = 0;
930 bta_jv_cb.uuid = p_data->start_discovery.uuid_list[0];
932 bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_YES;
933 if (!SDP_ServiceSearchAttributeRequest2(p_data->start_discovery.bd_addr,
934 p_bta_jv_cfg->p_sdp_db,
935 bta_jv_start_discovery_cback, p_data->start_discovery.user_data))
937 bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_NONE;
938 /* failed to start SDP. report the failure right away */
939 if(bta_jv_cb.p_dm_cback)
940 bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, (tBTA_JV *)&status, p_data->start_discovery.user_data);
943 else report the result when the cback is called
947 /*******************************************************************************
949 ** Function bta_jv_create_record
951 ** Description Create an SDP record with the given attributes
955 *******************************************************************************/
956 void bta_jv_create_record(tBTA_JV_MSG *p_data)
958 tBTA_JV_API_CREATE_RECORD *cr = &(p_data->create_record);
959 tBTA_JV_CREATE_RECORD evt_data;
960 evt_data.status = BTA_JV_SUCCESS;
961 if(bta_jv_cb.p_dm_cback)
962 //callback user immediately to create his own sdp record in stack thread context
963 bta_jv_cb.p_dm_cback(BTA_JV_CREATE_RECORD_EVT, (tBTA_JV *)&evt_data, cr->user_data);
966 /*******************************************************************************
968 ** Function bta_jv_delete_record
970 ** Description Delete an SDP record
975 *******************************************************************************/
976 void bta_jv_delete_record(tBTA_JV_MSG *p_data)
978 tBTA_JV_API_ADD_ATTRIBUTE *dr = &(p_data->add_attr);
981 /* this is a record created by btif layer*/
982 SDP_DeleteRecord(dr->handle);
986 /*******************************************************************************
988 ** Function bta_jv_l2cap_client_cback
990 ** Description handles the l2cap client events
994 *******************************************************************************/
995 static void bta_jv_l2cap_client_cback(UINT16 gap_handle, UINT16 event)
997 tBTA_JV_L2C_CB *p_cb = &bta_jv_cb.l2c_cb[gap_handle];
1000 if (gap_handle >= BTA_JV_MAX_L2C_CONN && !p_cb->p_cback)
1003 APPL_TRACE_DEBUG( "%s: %d evt:x%x",__func__, gap_handle, event);
1004 evt_data.l2c_open.status = BTA_JV_SUCCESS;
1005 evt_data.l2c_open.handle = gap_handle;
1009 case GAP_EVT_CONN_OPENED:
1010 bdcpy(evt_data.l2c_open.rem_bda, GAP_ConnGetRemoteAddr(gap_handle));
1011 evt_data.l2c_open.tx_mtu = GAP_ConnGetRemMtuSize(gap_handle);
1012 p_cb->state = BTA_JV_ST_CL_OPEN;
1013 p_cb->p_cback(BTA_JV_L2CAP_OPEN_EVT, &evt_data, p_cb->user_data);
1016 case GAP_EVT_CONN_CLOSED:
1017 p_cb->state = BTA_JV_ST_NONE;
1018 bta_jv_free_sec_id(&p_cb->sec_id);
1019 evt_data.l2c_close.async = TRUE;
1020 p_cb->p_cback(BTA_JV_L2CAP_CLOSE_EVT, &evt_data, p_cb->user_data);
1021 p_cb->p_cback = NULL;
1024 case GAP_EVT_CONN_DATA_AVAIL:
1025 evt_data.data_ind.handle = gap_handle;
1026 /* Reset idle timer to avoid requesting sniff mode while receiving data */
1027 bta_jv_pm_conn_busy(p_cb->p_pm_cb);
1028 p_cb->p_cback(BTA_JV_L2CAP_DATA_IND_EVT, &evt_data, p_cb->user_data);
1029 bta_jv_pm_conn_idle(p_cb->p_pm_cb);
1032 case GAP_EVT_TX_EMPTY:
1033 bta_jv_pm_conn_idle(p_cb->p_pm_cb);
1036 case GAP_EVT_CONN_CONGESTED:
1037 case GAP_EVT_CONN_UNCONGESTED:
1038 p_cb->cong = (event == GAP_EVT_CONN_CONGESTED) ? TRUE : FALSE;
1039 evt_data.l2c_cong.cong = p_cb->cong;
1040 p_cb->p_cback(BTA_JV_L2CAP_CONG_EVT, &evt_data, p_cb->user_data);
1048 /*******************************************************************************
1050 ** Function bta_jv_l2cap_connect
1052 ** Description makes an l2cap client connection
1056 *******************************************************************************/
1057 void bta_jv_l2cap_connect(tBTA_JV_MSG *p_data)
1059 tBTA_JV_L2C_CB *p_cb;
1060 tBTA_JV_L2CAP_CL_INIT evt_data;
1061 UINT16 handle=GAP_INVALID_HANDLE;
1063 tL2CAP_CFG_INFO cfg;
1064 tBTA_JV_API_L2CAP_CONNECT *cc = &(p_data->l2cap_connect);
1065 UINT8 chan_mode_mask = GAP_FCR_CHAN_OPT_BASIC;
1066 tL2CAP_ERTM_INFO *ertm_info = NULL;
1068 memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
1070 if (cc->has_cfg == TRUE)
1073 if (cfg.fcr_present && cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) {
1074 chan_mode_mask = GAP_FCR_CHAN_OPT_ERTM;
1078 if (cc->has_ertm_info == TRUE)
1080 ertm_info = &(cc->ertm_info);
1083 /* We need to use this value for MTU to be able to handle cases where cfg is not set in req. */
1084 cfg.mtu_present = TRUE;
1085 cfg.mtu = cc->rx_mtu;
1087 /* TODO: DM role manager
1088 L2CA_SetDesireRole(cc->role);
1091 sec_id = bta_jv_alloc_sec_id();
1092 evt_data.sec_id = sec_id;
1093 evt_data.status = BTA_JV_FAILURE;
1097 /* PSM checking is not required for LE COC */
1098 if ((cc->type != BTA_JV_CONN_TYPE_L2CAP) || (bta_jv_check_psm(cc->remote_psm))) /* allowed */
1100 if ((handle = GAP_ConnOpen("", sec_id, 0, cc->peer_bd_addr, cc->remote_psm,
1101 &cfg, ertm_info, cc->sec_mask, chan_mode_mask,
1102 bta_jv_l2cap_client_cback, cc->type)) != GAP_INVALID_HANDLE )
1104 evt_data.status = BTA_JV_SUCCESS;
1109 if (evt_data.status == BTA_JV_SUCCESS)
1111 p_cb = &bta_jv_cb.l2c_cb[handle];
1112 p_cb->handle = handle;
1113 p_cb->p_cback = cc->p_cback;
1114 p_cb->user_data = cc->user_data;
1115 p_cb->psm = 0; /* not a server */
1116 p_cb->sec_id = sec_id;
1117 p_cb->state = BTA_JV_ST_CL_OPENING;
1121 bta_jv_free_sec_id(&sec_id);
1124 evt_data.handle = handle;
1126 cc->p_cback(BTA_JV_L2CAP_CL_INIT_EVT, (tBTA_JV *)&evt_data, cc->user_data);
1130 /*******************************************************************************
1132 ** Function bta_jv_l2cap_close
1134 ** Description Close an L2CAP client connection
1138 *******************************************************************************/
1139 void bta_jv_l2cap_close(tBTA_JV_MSG *p_data)
1141 tBTA_JV_L2CAP_CLOSE evt_data;
1142 tBTA_JV_API_L2CAP_CLOSE *cc = &(p_data->l2cap_close);
1143 tBTA_JV_L2CAP_CBACK *p_cback = cc->p_cb->p_cback;
1144 void *user_data = cc->p_cb->user_data;
1146 evt_data.handle = cc->handle;
1147 evt_data.status = bta_jv_free_l2c_cb(cc->p_cb);
1148 evt_data.async = FALSE;
1151 p_cback(BTA_JV_L2CAP_CLOSE_EVT, (tBTA_JV *)&evt_data, user_data);
1154 /*******************************************************************************
1156 ** Function bta_jv_l2cap_server_cback
1158 ** Description handles the l2cap server callback
1162 *******************************************************************************/
1163 static void bta_jv_l2cap_server_cback(UINT16 gap_handle, UINT16 event)
1165 tBTA_JV_L2C_CB *p_cb = &bta_jv_cb.l2c_cb[gap_handle];
1167 tBTA_JV_L2CAP_CBACK *p_cback;
1170 if (gap_handle >= BTA_JV_MAX_L2C_CONN && !p_cb->p_cback)
1173 APPL_TRACE_DEBUG( "%s: %d evt:x%x", __func__, gap_handle, event);
1174 evt_data.l2c_open.status = BTA_JV_SUCCESS;
1175 evt_data.l2c_open.handle = gap_handle;
1179 case GAP_EVT_CONN_OPENED:
1180 bdcpy(evt_data.l2c_open.rem_bda, GAP_ConnGetRemoteAddr(gap_handle));
1181 evt_data.l2c_open.tx_mtu = GAP_ConnGetRemMtuSize(gap_handle);
1182 p_cb->state = BTA_JV_ST_SR_OPEN;
1183 p_cb->p_cback(BTA_JV_L2CAP_OPEN_EVT, &evt_data, p_cb->user_data);
1186 case GAP_EVT_CONN_CLOSED:
1187 evt_data.l2c_close.async = TRUE;
1188 evt_data.l2c_close.handle = p_cb->handle;
1189 p_cback = p_cb->p_cback;
1190 user_data = p_cb->user_data;
1191 evt_data.l2c_close.status = bta_jv_free_l2c_cb(p_cb);
1192 p_cback(BTA_JV_L2CAP_CLOSE_EVT, &evt_data, user_data);
1195 case GAP_EVT_CONN_DATA_AVAIL:
1196 evt_data.data_ind.handle = gap_handle;
1197 /* Reset idle timer to avoid requesting sniff mode while receiving data */
1198 bta_jv_pm_conn_busy(p_cb->p_pm_cb);
1199 p_cb->p_cback(BTA_JV_L2CAP_DATA_IND_EVT, &evt_data, p_cb->user_data);
1200 bta_jv_pm_conn_idle(p_cb->p_pm_cb);
1203 case GAP_EVT_TX_EMPTY:
1204 bta_jv_pm_conn_idle(p_cb->p_pm_cb);
1207 case GAP_EVT_CONN_CONGESTED:
1208 case GAP_EVT_CONN_UNCONGESTED:
1209 p_cb->cong = (event == GAP_EVT_CONN_CONGESTED) ? TRUE : FALSE;
1210 evt_data.l2c_cong.cong = p_cb->cong;
1211 p_cb->p_cback(BTA_JV_L2CAP_CONG_EVT, &evt_data, p_cb->user_data);
1219 /*******************************************************************************
1221 ** Function bta_jv_l2cap_start_server
1223 ** Description starts an L2CAP server
1227 *******************************************************************************/
1228 void bta_jv_l2cap_start_server(tBTA_JV_MSG *p_data)
1230 tBTA_JV_L2C_CB *p_cb;
1233 tL2CAP_CFG_INFO cfg;
1234 tBTA_JV_L2CAP_START evt_data;
1235 tBTA_JV_API_L2CAP_SERVER *ls = &(p_data->l2cap_server);
1236 UINT8 chan_mode_mask = GAP_FCR_CHAN_OPT_BASIC;
1237 tL2CAP_ERTM_INFO *ertm_info = NULL;
1239 memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
1241 if (ls->has_cfg == TRUE) {
1243 if (cfg.fcr_present && cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) {
1244 chan_mode_mask = GAP_FCR_CHAN_OPT_ERTM;
1248 if (ls->has_ertm_info == TRUE) {
1249 ertm_info = &(ls->ertm_info);
1252 //FIX: MTU=0 means not present
1255 cfg.mtu_present = TRUE;
1256 cfg.mtu = ls->rx_mtu;
1260 cfg.mtu_present = FALSE;
1264 /* TODO DM role manager
1265 L2CA_SetDesireRole(ls->role);
1268 sec_id = bta_jv_alloc_sec_id();
1269 /* PSM checking is not required for LE COC */
1270 if (0 == sec_id || ((ls->type == BTA_JV_CONN_TYPE_L2CAP) && (FALSE == bta_jv_check_psm(ls->local_psm))) ||
1271 (handle = GAP_ConnOpen("JV L2CAP", sec_id, 1, 0, ls->local_psm, &cfg, ertm_info,
1272 ls->sec_mask, chan_mode_mask, bta_jv_l2cap_server_cback, ls->type)) == GAP_INVALID_HANDLE)
1274 bta_jv_free_sec_id(&sec_id);
1275 evt_data.status = BTA_JV_FAILURE;
1279 p_cb = &bta_jv_cb.l2c_cb[handle];
1280 evt_data.status = BTA_JV_SUCCESS;
1281 evt_data.handle = handle;
1282 evt_data.sec_id = sec_id;
1283 p_cb->p_cback = ls->p_cback;
1284 p_cb->user_data = ls->user_data;
1285 p_cb->handle = handle;
1286 p_cb->sec_id = sec_id;
1287 p_cb->state = BTA_JV_ST_SR_LISTEN;
1288 p_cb->psm = ls->local_psm;
1292 ls->p_cback(BTA_JV_L2CAP_START_EVT, (tBTA_JV *)&evt_data, ls->user_data);
1295 /*******************************************************************************
1297 ** Function bta_jv_l2cap_stop_server
1299 ** Description stops an L2CAP server
1303 *******************************************************************************/
1304 void bta_jv_l2cap_stop_server(tBTA_JV_MSG *p_data)
1306 tBTA_JV_L2C_CB *p_cb;
1307 tBTA_JV_L2CAP_CLOSE evt_data;
1308 tBTA_JV_API_L2CAP_SERVER *ls = &(p_data->l2cap_server);
1309 tBTA_JV_L2CAP_CBACK *p_cback;
1311 for (int i = 0; i < BTA_JV_MAX_L2C_CONN; i++)
1313 if (bta_jv_cb.l2c_cb[i].psm == ls->local_psm)
1315 p_cb = &bta_jv_cb.l2c_cb[i];
1316 p_cback = p_cb->p_cback;
1317 user_data = p_cb->user_data;
1318 evt_data.handle = p_cb->handle;
1319 evt_data.status = bta_jv_free_l2c_cb(p_cb);
1320 evt_data.async = FALSE;
1322 p_cback(BTA_JV_L2CAP_CLOSE_EVT, (tBTA_JV *)&evt_data, ls->user_data);
1330 /*******************************************************************************
1332 ** Function bta_jv_l2cap_read
1334 ** Description Read data from an L2CAP connection
1338 *******************************************************************************/
1339 void bta_jv_l2cap_read(tBTA_JV_MSG *p_data)
1341 tBTA_JV_L2CAP_READ evt_data;
1342 tBTA_JV_API_L2CAP_READ *rc = &(p_data->l2cap_read);
1344 evt_data.status = BTA_JV_FAILURE;
1345 evt_data.handle = rc->handle;
1346 evt_data.req_id = rc->req_id;
1347 evt_data.p_data = rc->p_data;
1350 if (BT_PASS == GAP_ConnReadData(rc->handle, rc->p_data, rc->len, &evt_data.len))
1352 evt_data.status = BTA_JV_SUCCESS;
1355 rc->p_cback(BTA_JV_L2CAP_READ_EVT, (tBTA_JV *)&evt_data, rc->user_data);
1359 /*******************************************************************************
1361 ** Function bta_jv_l2cap_write
1363 ** Description Write data to an L2CAP connection
1367 *******************************************************************************/
1368 void bta_jv_l2cap_write(tBTA_JV_MSG *p_data)
1370 tBTA_JV_L2CAP_WRITE evt_data;
1371 tBTA_JV_API_L2CAP_WRITE *ls = &(p_data->l2cap_write);
1373 /* As we check this callback exists before the tBTA_JV_API_L2CAP_WRITE can be send through the
1374 * API this check should not be needed.
1375 * But the API is not designed to be used (safely at least) in a multi-threaded scheduler, hence
1376 * if the peer device disconnects the l2cap link after the API is called, but before this
1377 * message is handled, the ->p_cback will be cleared at this point. At first glanch this seems
1378 * highly unlikely, but for all obex-profiles with two channels connected - e.g. MAP, this
1379 * happens around 1 of 4 disconnects, as a disconnect on the server channel causes a disconnect
1380 * to be send on the client (notification) channel, but at the peer typically disconnects both
1381 * the OBEX disconnect request crosses the incoming l2cap disconnect.
1382 * If p_cback is cleared, we simply discard the data.
1383 * RISK: The caller must handle any cleanup based on another signal than BTA_JV_L2CAP_WRITE_EVT,
1384 * which is typically not possible, as the pointer to the allocated buffer is stored
1385 * in this message, and can therefore not be freed, hence we have a mem-leak-by-design.*/
1386 if (ls->p_cb->p_cback != NULL) {
1387 evt_data.status = BTA_JV_FAILURE;
1388 evt_data.handle = ls->handle;
1389 evt_data.req_id = ls->req_id;
1390 evt_data.cong = ls->p_cb->cong;
1392 bta_jv_pm_conn_busy(ls->p_cb->p_pm_cb);
1393 if (!evt_data.cong &&
1394 BT_PASS == GAP_ConnWriteData(ls->handle, ls->p_data, ls->len, &evt_data.len))
1396 evt_data.status = BTA_JV_SUCCESS;
1398 ls->p_cb->p_cback(BTA_JV_L2CAP_WRITE_EVT, (tBTA_JV *)&evt_data, ls->user_data);
1400 /* As this pointer is checked in the API function, this occurs only when the channel is
1401 * disconnected after the API function is called, but before the message is handled. */
1402 APPL_TRACE_ERROR("%s() ls->p_cb->p_cback == NULL", __func__);
1406 /*******************************************************************************
1408 ** Function bta_jv_l2cap_write_fixed
1410 ** Description Write data to an L2CAP connection using Fixed channels
1414 *******************************************************************************/
1415 void bta_jv_l2cap_write_fixed(tBTA_JV_MSG *p_data)
1417 tBTA_JV_L2CAP_WRITE_FIXED evt_data;
1418 tBTA_JV_API_L2CAP_WRITE_FIXED *ls = &(p_data->l2cap_write_fixed);
1419 BT_HDR *msg = (BT_HDR *)osi_malloc(sizeof(BT_HDR) + ls->len + L2CAP_MIN_OFFSET);
1421 evt_data.status = BTA_JV_FAILURE;
1422 evt_data.channel = ls->channel;
1423 memcpy(evt_data.addr, ls->addr, sizeof(evt_data.addr));
1424 evt_data.req_id = ls->req_id;
1428 memcpy(((uint8_t*)(msg + 1)) + L2CAP_MIN_OFFSET, ls->p_data, ls->len);
1430 msg->offset = L2CAP_MIN_OFFSET;
1432 L2CA_SendFixedChnlData(ls->channel, ls->addr, msg);
1434 ls->p_cback(BTA_JV_L2CAP_WRITE_FIXED_EVT, (tBTA_JV *)&evt_data, ls->user_data);
1437 /*******************************************************************************
1439 ** Function bta_jv_port_data_co_cback
1441 ** Description port data callback function of rfcomm
1446 *******************************************************************************/
1447 static int bta_jv_port_data_co_cback(UINT16 port_handle, UINT8 *buf, UINT16 len, int type)
1449 tBTA_JV_RFC_CB *p_cb = bta_jv_rfc_port_to_cb(port_handle);
1450 tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
1452 APPL_TRACE_DEBUG("%s, p_cb:%p, p_pcb:%p, len:%d, type:%d", __func__, p_cb, p_pcb, len, type);
1457 case DATA_CO_CALLBACK_TYPE_INCOMING:
1458 bta_jv_pm_conn_busy(p_pcb->p_pm_cb);
1459 ret = bta_co_rfc_data_incoming(p_pcb->user_data, (BT_HDR*)buf);
1460 bta_jv_pm_conn_idle(p_pcb->p_pm_cb);
1462 case DATA_CO_CALLBACK_TYPE_OUTGOING_SIZE:
1463 return bta_co_rfc_data_outgoing_size(p_pcb->user_data, (int*)buf);
1464 case DATA_CO_CALLBACK_TYPE_OUTGOING:
1465 return bta_co_rfc_data_outgoing(p_pcb->user_data, buf, len);
1467 APPL_TRACE_ERROR("unknown callout type:%d", type);
1474 /*******************************************************************************
1476 ** Function bta_jv_port_mgmt_cl_cback
1478 ** Description callback for port mamangement function of rfcomm
1479 ** client connections
1483 *******************************************************************************/
1484 static void bta_jv_port_mgmt_cl_cback(UINT32 code, UINT16 port_handle)
1486 tBTA_JV_RFC_CB *p_cb = bta_jv_rfc_port_to_cb(port_handle);
1487 tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
1491 tBTA_JV_RFCOMM_CBACK *p_cback; /* the callback function */
1493 APPL_TRACE_DEBUG( "bta_jv_port_mgmt_cl_cback:code:%d, port_handle%d", code, port_handle);
1494 /* Fix for below Klockwork issue
1495 * Pointer 'p_pcb' returned from call to function 'bta_jv_rfc_port_to_pcb' at line 1490
1496 * may be NULL and may be dereferenced at line 1500*/
1497 if(NULL == p_cb || NULL == p_cb->p_cback || NULL == p_pcb)
1500 APPL_TRACE_DEBUG( "bta_jv_port_mgmt_cl_cback code=%d port_handle:%d handle:%d",
1501 code, port_handle, p_cb->handle);
1503 PORT_CheckConnection(port_handle, rem_bda, &lcid);
1505 if(code == PORT_SUCCESS)
1507 evt_data.rfc_open.handle = p_cb->handle;
1508 evt_data.rfc_open.status = BTA_JV_SUCCESS;
1509 bdcpy(evt_data.rfc_open.rem_bda, rem_bda);
1510 p_pcb->state = BTA_JV_ST_CL_OPEN;
1511 p_cb->p_cback(BTA_JV_RFCOMM_OPEN_EVT, &evt_data, p_pcb->user_data);
1515 evt_data.rfc_close.handle = p_cb->handle;
1516 evt_data.rfc_close.status = BTA_JV_FAILURE;
1517 evt_data.rfc_close.port_status = code;
1518 evt_data.rfc_close.async = TRUE;
1519 if (p_pcb->state == BTA_JV_ST_CL_CLOSING)
1521 evt_data.rfc_close.async = FALSE;
1523 //p_pcb->state = BTA_JV_ST_NONE;
1524 //p_pcb->cong = FALSE;
1525 p_cback = p_cb->p_cback;
1526 p_cback(BTA_JV_RFCOMM_CLOSE_EVT, &evt_data, p_pcb->user_data);
1527 //bta_jv_free_rfc_cb(p_cb, p_pcb);
1532 /*******************************************************************************
1534 ** Function bta_jv_port_event_cl_cback
1536 ** Description Callback for RFCOMM client port events
1540 *******************************************************************************/
1541 static void bta_jv_port_event_cl_cback(UINT32 code, UINT16 port_handle)
1543 tBTA_JV_RFC_CB *p_cb = bta_jv_rfc_port_to_cb(port_handle);
1544 tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
1547 APPL_TRACE_DEBUG( "bta_jv_port_event_cl_cback:%d", port_handle);
1548 /* Fix for below Klockwork issue
1549 * Pointer 'p_pcb' returned from call to function 'bta_jv_rfc_port_to_pcb' at line 1547
1550 * may be NULL and may be dereferenced at line 1554*/
1551 if (NULL == p_cb || NULL == p_cb->p_cback || NULL == p_pcb)
1554 APPL_TRACE_DEBUG( "bta_jv_port_event_cl_cback code=x%x port_handle:%d handle:%d",
1555 code, port_handle, p_cb->handle);
1556 if (code & PORT_EV_RXCHAR)
1558 evt_data.data_ind.handle = p_cb->handle;
1559 p_cb->p_cback(BTA_JV_RFCOMM_DATA_IND_EVT, &evt_data, p_pcb->user_data);
1562 if (code & PORT_EV_FC)
1564 p_pcb->cong = (code & PORT_EV_FCS) ? FALSE : TRUE;
1565 evt_data.rfc_cong.cong = p_pcb->cong;
1566 evt_data.rfc_cong.handle = p_cb->handle;
1567 evt_data.rfc_cong.status = BTA_JV_SUCCESS;
1568 p_cb->p_cback(BTA_JV_RFCOMM_CONG_EVT, &evt_data, p_pcb->user_data);
1571 if (code & PORT_EV_TXEMPTY)
1573 bta_jv_pm_conn_idle(p_pcb->p_pm_cb);
1577 /*******************************************************************************
1579 ** Function bta_jv_rfcomm_connect
1581 ** Description Client initiates an RFCOMM connection
1585 *******************************************************************************/
1586 void bta_jv_rfcomm_connect(tBTA_JV_MSG *p_data)
1589 UINT32 event_mask = BTA_JV_RFC_EV_MASK;
1590 tPORT_STATE port_state;
1592 tBTA_JV_RFC_CB *p_cb = NULL;
1594 tBTA_JV_API_RFCOMM_CONNECT *cc = &(p_data->rfcomm_connect);
1595 tBTA_JV_RFCOMM_CL_INIT evt_data;
1597 /* TODO DM role manager
1598 L2CA_SetDesireRole(cc->role);
1601 sec_id = bta_jv_alloc_sec_id();
1602 memset(&evt_data, 0, sizeof(evt_data));
1603 evt_data.sec_id = sec_id;
1604 evt_data.status = BTA_JV_SUCCESS;
1606 BTM_SetSecurityLevel(TRUE, "", sec_id, cc->sec_mask, BT_PSM_RFCOMM,
1607 BTM_SEC_PROTO_RFCOMM, cc->remote_scn) == FALSE)
1609 evt_data.status = BTA_JV_FAILURE;
1610 APPL_TRACE_ERROR("sec_id:%d is zero or BTM_SetSecurityLevel failed, remote_scn:%d", sec_id, cc->remote_scn);
1613 if (evt_data.status == BTA_JV_SUCCESS &&
1614 RFCOMM_CreateConnection(UUID_SERVCLASS_SERIAL_PORT, cc->remote_scn, FALSE,
1615 BTA_JV_DEF_RFC_MTU, cc->peer_bd_addr, &handle, bta_jv_port_mgmt_cl_cback) != PORT_SUCCESS)
1617 APPL_TRACE_ERROR("bta_jv_rfcomm_connect, RFCOMM_CreateConnection failed");
1618 evt_data.status = BTA_JV_FAILURE;
1620 if (evt_data.status == BTA_JV_SUCCESS)
1622 p_cb = bta_jv_alloc_rfc_cb(handle, &p_pcb);
1625 p_cb->p_cback = cc->p_cback;
1626 p_cb->sec_id = sec_id;
1628 p_pcb->state = BTA_JV_ST_CL_OPENING;
1629 p_pcb->user_data = cc->user_data;
1630 evt_data.use_co = TRUE;
1632 PORT_SetEventCallback(handle, bta_jv_port_event_cl_cback);
1633 PORT_SetEventMask(handle, event_mask);
1634 PORT_SetDataCOCallback (handle, bta_jv_port_data_co_cback);
1636 PORT_GetState(handle, &port_state);
1638 port_state.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT);
1640 /* coverity[uninit_use_in_call]
1641 FALSE-POSITIVE: port_state is initialized at PORT_GetState() */
1642 PORT_SetState(handle, &port_state);
1644 evt_data.handle = p_cb->handle;
1648 evt_data.status = BTA_JV_FAILURE;
1649 APPL_TRACE_ERROR("run out of rfc control block");
1652 cc->p_cback(BTA_JV_RFCOMM_CL_INIT_EVT, (tBTA_JV *)&evt_data, cc->user_data);
1653 if(evt_data.status == BTA_JV_FAILURE)
1656 bta_jv_free_sec_id(&sec_id);
1658 RFCOMM_RemoveConnection(handle);
1662 static int find_rfc_pcb(void* user_data, tBTA_JV_RFC_CB **cb, tBTA_JV_PCB **pcb)
1667 for (i = 0; i < MAX_RFC_PORTS; i++)
1669 UINT32 rfc_handle = bta_jv_cb.port_cb[i].handle & BTA_JV_RFC_HDL_MASK;
1670 rfc_handle &= ~BTA_JV_RFCOMM_MASK;
1671 if (rfc_handle && bta_jv_cb.port_cb[i].user_data == user_data)
1673 *pcb = &bta_jv_cb.port_cb[i];
1674 *cb = &bta_jv_cb.rfc_cb[rfc_handle - 1];
1675 APPL_TRACE_DEBUG("find_rfc_pcb(): FOUND rfc_cb_handle 0x%x, port.jv_handle:"
1676 " 0x%x, state: %d, rfc_cb->handle: 0x%x", rfc_handle, (*pcb)->handle,
1677 (*pcb)->state, (*cb)->handle);
1681 APPL_TRACE_DEBUG("find_rfc_pcb: cannot find rfc_cb from user data: %u", PTR_TO_UINT(user_data));
1685 /*******************************************************************************
1687 ** Function bta_jv_rfcomm_close
1689 ** Description Close an RFCOMM connection
1693 *******************************************************************************/
1694 void bta_jv_rfcomm_close(tBTA_JV_MSG *p_data)
1696 tBTA_JV_API_RFCOMM_CLOSE *cc = &(p_data->rfcomm_close);
1697 tBTA_JV_RFC_CB *p_cb = NULL;
1698 tBTA_JV_PCB *p_pcb = NULL;
1699 APPL_TRACE_DEBUG("bta_jv_rfcomm_close, rfc handle:%d", cc->handle);
1702 APPL_TRACE_ERROR("bta_jv_rfcomm_close, rfc handle is null");
1706 void* user_data = cc->user_data;
1707 if (!find_rfc_pcb(user_data, &p_cb, &p_pcb))
1709 bta_jv_free_rfc_cb(p_cb, p_pcb);
1710 APPL_TRACE_DEBUG("bta_jv_rfcomm_close: sec id in use:%d, rfc_cb in use:%d",
1711 get_sec_id_used(), get_rfc_cb_used());
1714 /*******************************************************************************
1716 ** Function bta_jv_port_mgmt_sr_cback
1718 ** Description callback for port mamangement function of rfcomm
1719 ** server connections
1723 *******************************************************************************/
1724 static void bta_jv_port_mgmt_sr_cback(UINT32 code, UINT16 port_handle)
1726 tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
1727 tBTA_JV_RFC_CB *p_cb = bta_jv_rfc_port_to_cb(port_handle);
1731 APPL_TRACE_DEBUG("bta_jv_port_mgmt_sr_cback, code:%d, port_handle:%d", code, port_handle);
1732 /* Fix for below Klockwork issue
1733 * Pointer 'p_pcb' returned from call to function 'bta_jv_rfc_port_to_pcb' at line 1729
1734 * may be NULL and may be dereferenced at line 1738*/
1735 if (NULL == p_cb || NULL == p_cb->p_cback || NULL == p_pcb)
1738 void *user_data = p_pcb->user_data;
1739 APPL_TRACE_DEBUG( "bta_jv_port_mgmt_sr_cback code=%d port_handle:0x%x handle:0x%x, p_pcb:%p, user:%d",
1740 code, port_handle, p_cb->handle, p_pcb, p_pcb->user_data);
1742 PORT_CheckConnection(port_handle, rem_bda, &lcid);
1744 if (code == PORT_SUCCESS)
1746 evt_data.rfc_srv_open.handle = p_pcb->handle;
1747 evt_data.rfc_srv_open.status = BTA_JV_SUCCESS;
1748 bdcpy(evt_data.rfc_srv_open.rem_bda, rem_bda);
1749 tBTA_JV_PCB *p_pcb_new_listen = bta_jv_add_rfc_port(p_cb, p_pcb);
1750 if (p_pcb_new_listen)
1752 evt_data.rfc_srv_open.new_listen_handle = p_pcb_new_listen->handle;
1753 p_pcb_new_listen->user_data = p_cb->p_cback(BTA_JV_RFCOMM_SRV_OPEN_EVT, &evt_data, user_data);
1754 APPL_TRACE_DEBUG("PORT_SUCCESS: curr_sess:%d, max_sess:%d", p_cb->curr_sess, p_cb->max_sess);
1758 APPL_TRACE_ERROR("bta_jv_add_rfc_port failed to create new listen port");
1762 evt_data.rfc_close.handle = p_cb->handle;
1763 evt_data.rfc_close.status = BTA_JV_FAILURE;
1764 evt_data.rfc_close.async = TRUE;
1765 evt_data.rfc_close.port_status = code;
1766 p_pcb->cong = FALSE;
1768 tBTA_JV_RFCOMM_CBACK *p_cback = p_cb->p_cback;
1769 APPL_TRACE_DEBUG("PORT_CLOSED before BTA_JV_RFCOMM_CLOSE_EVT: curr_sess:%d, max_sess:%d",
1770 p_cb->curr_sess, p_cb->max_sess);
1771 if (BTA_JV_ST_SR_CLOSING == p_pcb->state)
1773 evt_data.rfc_close.async = FALSE;
1774 evt_data.rfc_close.status = BTA_JV_SUCCESS;
1776 //p_pcb->state = BTA_JV_ST_NONE;
1777 p_cback(BTA_JV_RFCOMM_CLOSE_EVT, &evt_data, user_data);
1778 //bta_jv_free_rfc_cb(p_cb, p_pcb);
1780 APPL_TRACE_DEBUG("PORT_CLOSED after BTA_JV_RFCOMM_CLOSE_EVT: curr_sess:%d, max_sess:%d",
1781 p_cb->curr_sess, p_cb->max_sess);
1785 /*******************************************************************************
1787 ** Function bta_jv_port_event_sr_cback
1789 ** Description Callback for RFCOMM server port events
1793 *******************************************************************************/
1794 static void bta_jv_port_event_sr_cback(UINT32 code, UINT16 port_handle)
1796 tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
1797 tBTA_JV_RFC_CB *p_cb = bta_jv_rfc_port_to_cb(port_handle);
1800 if (NULL == p_cb || NULL == p_cb->p_cback || NULL == p_pcb)
1803 APPL_TRACE_DEBUG( "bta_jv_port_event_sr_cback code=x%x port_handle:%d handle:%d",
1804 code, port_handle, p_cb->handle);
1806 void *user_data = p_pcb->user_data;
1807 if (code & PORT_EV_RXCHAR)
1809 evt_data.data_ind.handle = p_cb->handle;
1810 p_cb->p_cback(BTA_JV_RFCOMM_DATA_IND_EVT, &evt_data, user_data);
1813 if (code & PORT_EV_FC)
1815 p_pcb->cong = (code & PORT_EV_FCS) ? FALSE : TRUE;
1816 evt_data.rfc_cong.cong = p_pcb->cong;
1817 evt_data.rfc_cong.handle = p_cb->handle;
1818 evt_data.rfc_cong.status = BTA_JV_SUCCESS;
1819 p_cb->p_cback(BTA_JV_RFCOMM_CONG_EVT, &evt_data, user_data);
1822 if (code & PORT_EV_TXEMPTY)
1824 bta_jv_pm_conn_idle(p_pcb->p_pm_cb);
1828 /*******************************************************************************
1830 ** Function bta_jv_add_rfc_port
1832 ** Description add a port for server when the existing posts is open
1834 ** Returns return a pointer to tBTA_JV_PCB just added
1836 *******************************************************************************/
1837 static tBTA_JV_PCB * bta_jv_add_rfc_port(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pcb_open)
1839 UINT8 used = 0, i, listen=0;
1841 tPORT_STATE port_state;
1842 UINT32 event_mask = BTA_JV_RFC_EV_MASK;
1843 tBTA_JV_PCB *p_pcb = NULL;
1844 if (p_cb->max_sess > 1)
1846 for (i=0; i < p_cb->max_sess; i++)
1848 if (p_cb->rfc_hdl[i] != 0)
1850 p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[i] - 1];
1851 if (p_pcb->state == BTA_JV_ST_SR_LISTEN)
1854 if (p_pcb_open == p_pcb)
1856 APPL_TRACE_DEBUG("bta_jv_add_rfc_port, port_handle:%d, change the listen port to open state",
1857 p_pcb->port_handle);
1858 p_pcb->state = BTA_JV_ST_SR_OPEN;
1863 APPL_TRACE_ERROR("bta_jv_add_rfc_port, open pcb not matching listen one,"
1864 "listen count:%d, listen pcb handle:%d, open pcb:%d",
1865 listen, p_pcb->port_handle, p_pcb_open->handle);
1877 APPL_TRACE_DEBUG("bta_jv_add_rfc_port max_sess=%d used:%d curr_sess:%d, listen:%d si:%d",
1878 p_cb->max_sess, used, p_cb->curr_sess, listen, si);
1879 if (used < p_cb->max_sess && listen == 1 && si)
1882 if (RFCOMM_CreateConnection(p_cb->sec_id, p_cb->scn, TRUE,
1883 BTA_JV_DEF_RFC_MTU, (UINT8 *) bd_addr_any, &(p_cb->rfc_hdl[si]), bta_jv_port_mgmt_sr_cback) == PORT_SUCCESS)
1886 p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[si] - 1];
1887 p_pcb->state = BTA_JV_ST_SR_LISTEN;
1888 p_pcb->port_handle = p_cb->rfc_hdl[si];
1889 p_pcb->user_data = p_pcb_open->user_data;
1891 PORT_ClearKeepHandleFlag(p_pcb->port_handle);
1892 PORT_SetEventCallback(p_pcb->port_handle, bta_jv_port_event_sr_cback);
1893 PORT_SetDataCOCallback (p_pcb->port_handle, bta_jv_port_data_co_cback);
1894 PORT_SetEventMask(p_pcb->port_handle, event_mask);
1895 PORT_GetState(p_pcb->port_handle, &port_state);
1897 port_state.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT);
1899 PORT_SetState(p_pcb->port_handle, &port_state);
1900 p_pcb->handle = BTA_JV_RFC_H_S_TO_HDL(p_cb->handle, si);
1901 APPL_TRACE_DEBUG("bta_jv_add_rfc_port: p_pcb->handle:0x%x, curr_sess:%d",
1902 p_pcb->handle, p_cb->curr_sess);
1906 APPL_TRACE_ERROR("bta_jv_add_rfc_port, cannot create new rfc listen port");
1908 APPL_TRACE_DEBUG("bta_jv_add_rfc_port: sec id in use:%d, rfc_cb in use:%d",
1909 get_sec_id_used(), get_rfc_cb_used());
1913 /*******************************************************************************
1915 ** Function bta_jv_rfcomm_start_server
1917 ** Description waits for an RFCOMM client to connect
1922 *******************************************************************************/
1923 void bta_jv_rfcomm_start_server(tBTA_JV_MSG *p_data)
1926 UINT32 event_mask = BTA_JV_RFC_EV_MASK;
1927 tPORT_STATE port_state;
1929 tBTA_JV_RFC_CB *p_cb = NULL;
1931 tBTA_JV_API_RFCOMM_SERVER *rs = &(p_data->rfcomm_server);
1932 tBTA_JV_RFCOMM_START evt_data;
1934 /* TODO DM role manager
1935 L2CA_SetDesireRole(rs->role);
1937 memset(&evt_data, 0, sizeof(evt_data));
1938 evt_data.status = BTA_JV_FAILURE;
1939 APPL_TRACE_DEBUG("bta_jv_rfcomm_start_server: sec id in use:%d, rfc_cb in use:%d",
1940 get_sec_id_used(), get_rfc_cb_used());
1944 sec_id = bta_jv_alloc_sec_id();
1947 BTM_SetSecurityLevel(FALSE, "JV PORT", sec_id, rs->sec_mask,
1948 BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, rs->local_scn) == FALSE)
1950 APPL_TRACE_ERROR("bta_jv_rfcomm_start_server, run out of sec_id");
1954 if (RFCOMM_CreateConnection(sec_id, rs->local_scn, TRUE,
1955 BTA_JV_DEF_RFC_MTU, (UINT8 *) bd_addr_any, &handle, bta_jv_port_mgmt_sr_cback) != PORT_SUCCESS)
1957 APPL_TRACE_ERROR("bta_jv_rfcomm_start_server, RFCOMM_CreateConnection failed");
1962 p_cb = bta_jv_alloc_rfc_cb(handle, &p_pcb);
1965 APPL_TRACE_ERROR("bta_jv_rfcomm_start_server, run out of rfc control block");
1969 p_cb->max_sess = rs->max_session;
1970 p_cb->p_cback = rs->p_cback;
1971 p_cb->sec_id = sec_id;
1972 p_cb->scn = rs->local_scn;
1973 p_pcb->state = BTA_JV_ST_SR_LISTEN;
1974 p_pcb->user_data = rs->user_data;
1975 evt_data.status = BTA_JV_SUCCESS;
1976 evt_data.handle = p_cb->handle;
1977 evt_data.sec_id = sec_id;
1978 evt_data.use_co = TRUE;
1980 PORT_ClearKeepHandleFlag(handle);
1981 PORT_SetEventCallback(handle, bta_jv_port_event_sr_cback);
1982 PORT_SetEventMask(handle, event_mask);
1983 PORT_GetState(handle, &port_state);
1985 port_state.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT);
1987 PORT_SetState(handle, &port_state);
1990 rs->p_cback(BTA_JV_RFCOMM_START_EVT, (tBTA_JV *)&evt_data, rs->user_data);
1991 if (evt_data.status == BTA_JV_SUCCESS)
1993 PORT_SetDataCOCallback (handle, bta_jv_port_data_co_cback);
1998 bta_jv_free_sec_id(&sec_id);
2000 RFCOMM_RemoveConnection(handle);
2004 /*******************************************************************************
2006 ** Function bta_jv_rfcomm_stop_server
2008 ** Description stops an RFCOMM server
2012 *******************************************************************************/
2014 void bta_jv_rfcomm_stop_server(tBTA_JV_MSG *p_data)
2016 tBTA_JV_API_RFCOMM_SERVER *ls = &(p_data->rfcomm_server);
2017 tBTA_JV_RFC_CB *p_cb = NULL;
2018 tBTA_JV_PCB *p_pcb = NULL;
2019 APPL_TRACE_DEBUG("bta_jv_rfcomm_stop_server");
2022 APPL_TRACE_ERROR("bta_jv_rfcomm_stop_server, jv handle is null");
2025 void* user_data = ls->user_data;
2026 if (!find_rfc_pcb(user_data, &p_cb, &p_pcb))
2028 APPL_TRACE_DEBUG("bta_jv_rfcomm_stop_server: p_pcb:%p, p_pcb->port_handle:%d",
2029 p_pcb, p_pcb->port_handle);
2030 bta_jv_free_rfc_cb(p_cb, p_pcb);
2031 APPL_TRACE_DEBUG("bta_jv_rfcomm_stop_server: sec id in use:%d, rfc_cb in use:%d",
2032 get_sec_id_used(), get_rfc_cb_used());
2035 /*******************************************************************************
2037 ** Function bta_jv_rfcomm_write
2039 ** Description write data to an RFCOMM connection
2043 *******************************************************************************/
2044 void bta_jv_rfcomm_write(tBTA_JV_MSG *p_data)
2046 tBTA_JV_API_RFCOMM_WRITE *wc = &(p_data->rfcomm_write);
2047 tBTA_JV_RFC_CB *p_cb = wc->p_cb;
2048 tBTA_JV_PCB *p_pcb = wc->p_pcb;
2049 tBTA_JV_RFCOMM_WRITE evt_data;
2052 if (p_pcb->state == BTA_JV_ST_NONE) {
2053 APPL_TRACE_ERROR("bta_jv_rfcomm_write : Incorect state (%d) to write data, returning",
2058 evt_data.status = BTA_JV_FAILURE;
2059 evt_data.handle = p_cb->handle;
2060 evt_data.req_id = wc->req_id;
2061 evt_data.cong = p_pcb->cong;
2063 bta_jv_pm_conn_busy(p_pcb->p_pm_cb);
2064 if (!evt_data.cong &&
2065 PORT_WriteDataCO(p_pcb->port_handle, &evt_data.len) ==
2068 evt_data.status = BTA_JV_SUCCESS;
2070 //update congestion flag
2071 evt_data.cong = p_pcb->cong;
2074 p_cb->p_cback(BTA_JV_RFCOMM_WRITE_EVT, (tBTA_JV *)&evt_data, p_pcb->user_data);
2078 APPL_TRACE_ERROR("bta_jv_rfcomm_write :: WARNING ! No JV callback set");
2082 /*******************************************************************************
2084 ** Function bta_jv_set_pm_profile
2086 ** Description Set or free power mode profile for a JV application
2090 *******************************************************************************/
2091 void bta_jv_set_pm_profile(tBTA_JV_MSG *p_data)
2093 tBTA_JV_STATUS status;
2094 tBTA_JV_PM_CB *p_cb;
2096 APPL_TRACE_API("bta_jv_set_pm_profile(handle: 0x%x, app_id: %d, init_st: %d)",
2097 p_data->set_pm.handle, p_data->set_pm.app_id, p_data->set_pm.init_st);
2099 /* clear PM control block */
2100 if (p_data->set_pm.app_id == BTA_JV_PM_ID_CLEAR)
2102 status = bta_jv_free_set_pm_profile_cb(p_data->set_pm.handle);
2104 if (status != BTA_JV_SUCCESS)
2106 APPL_TRACE_WARNING("bta_jv_set_pm_profile() free pm cb failed: reason %d",
2110 else /* set PM control block */
2112 p_cb = bta_jv_alloc_set_pm_profile_cb(p_data->set_pm.handle,
2113 p_data->set_pm.app_id);
2116 bta_jv_pm_state_change(p_cb, p_data->set_pm.init_st);
2118 APPL_TRACE_WARNING("bta_jv_alloc_set_pm_profile_cb() failed");
2122 /*******************************************************************************
2124 ** Function bta_jv_change_pm_state
2126 ** Description change jv pm connect state, used internally
2130 *******************************************************************************/
2131 void bta_jv_change_pm_state(tBTA_JV_MSG *p_data)
2133 tBTA_JV_API_PM_STATE_CHANGE *p_msg = (tBTA_JV_API_PM_STATE_CHANGE *)p_data;
2136 bta_jv_pm_state_change(p_msg->p_cb, p_msg->state);
2140 /*******************************************************************************
2142 ** Function bta_jv_set_pm_conn_state
2144 ** Description Send pm event state change to jv state machine to serialize jv pm changes
2145 ** in relation to other jv messages. internal API use mainly.
2147 ** Params: p_cb: jv pm control block, NULL pointer returns failure
2148 ** new_state: new PM connections state, setting is forced by action function
2150 ** Returns BTA_JV_SUCCESS, BTA_JV_FAILURE (buffer allocation, or NULL ptr!)
2152 *******************************************************************************/
2153 tBTA_JV_STATUS bta_jv_set_pm_conn_state(tBTA_JV_PM_CB *p_cb, const tBTA_JV_CONN_STATE
2157 return BTA_JV_FAILURE;
2159 APPL_TRACE_API("%s: handle:0x%x, state: %d", __func__, p_cb->handle,
2162 tBTA_JV_API_PM_STATE_CHANGE *p_msg =
2163 (tBTA_JV_API_PM_STATE_CHANGE *)osi_malloc(sizeof(tBTA_JV_API_PM_STATE_CHANGE));
2164 p_msg->hdr.event = BTA_JV_API_PM_STATE_CHANGE_EVT;
2166 p_msg->state = new_st;
2168 bta_sys_sendmsg(p_msg);
2170 return BTA_JV_SUCCESS;
2173 /*******************************************************************************
2175 ** Function bta_jv_pm_conn_busy
2177 ** Description set pm connection busy state (input param safe)
2179 ** Params p_cb: pm control block of jv connection
2183 *******************************************************************************/
2184 static void bta_jv_pm_conn_busy(tBTA_JV_PM_CB *p_cb)
2186 if ((NULL != p_cb) && (BTA_JV_PM_IDLE_ST == p_cb->state))
2188 if (alarm_is_scheduled(p_cb->idle_timer))
2190 alarm_cancel(p_cb->idle_timer);
2191 p_cb->state = BTA_JV_PM_BUSY_ST;
2195 APPL_TRACE_DEBUG("bta_jv_pm_conn_busy");
2196 bta_jv_pm_state_change(p_cb, BTA_JV_CONN_BUSY);
2202 /*******************************************************************************
2204 ** Function bta_jv_pm_conn_idle
2206 ** Description set pm connection idle state (input param safe)
2208 ** Params p_cb: pm control block of jv connection
2212 *******************************************************************************/
2213 static void bta_jv_pm_conn_idle(tBTA_JV_PM_CB *p_cb)
2215 if ((NULL != p_cb) && (BTA_JV_PM_IDLE_ST != p_cb->state)) {
2216 APPL_TRACE_DEBUG("bta_jv_pm_conn_idle, p_cb: %p", p_cb);
2217 p_cb->state = BTA_JV_PM_IDLE_ST;
2218 /* start intermediate idle timer for 1s */
2219 alarm_set_on_queue(p_cb->idle_timer, BTA_JV_IDLE_TIMEOUT_MS,
2220 bta_jv_idle_timeout_handler, p_cb, btu_general_alarm_queue);
2224 /*******************************************************************************
2226 ** Function bta_jv_pm_state_change
2228 ** Description Notify power manager there is state change
2230 ** Params p_cb: must be NONE NULL
2234 *******************************************************************************/
2235 static void bta_jv_pm_state_change(tBTA_JV_PM_CB *p_cb, const tBTA_JV_CONN_STATE state)
2237 APPL_TRACE_API("bta_jv_pm_state_change(p_cb: 0x%x, handle: 0x%x, busy/idle_state: %d"
2238 ", app_id: %d, conn_state: %d)", p_cb, p_cb->handle, p_cb->state,
2239 p_cb->app_id, state);
2243 case BTA_JV_CONN_OPEN:
2244 bta_sys_conn_open(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr);
2247 case BTA_JV_CONN_CLOSE:
2248 bta_sys_conn_close(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr);
2251 case BTA_JV_APP_OPEN:
2252 bta_sys_app_open(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr);
2255 case BTA_JV_APP_CLOSE:
2256 bta_sys_app_close(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr);
2259 case BTA_JV_SCO_OPEN:
2260 bta_sys_sco_open(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr);
2263 case BTA_JV_SCO_CLOSE:
2264 bta_sys_sco_close(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr);
2267 case BTA_JV_CONN_IDLE:
2268 p_cb->state = BTA_JV_PM_IDLE_ST;
2269 bta_sys_idle(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr);
2272 case BTA_JV_CONN_BUSY:
2273 p_cb->state = BTA_JV_PM_BUSY_ST;
2274 bta_sys_busy(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr);
2278 APPL_TRACE_WARNING("bta_jv_pm_state_change(state: %d): Invalid state", state);
2282 /**********************************************************************************************/
2285 static struct fc_channel *fcchan_get(uint16_t chan, char create)
2287 struct fc_channel *t = fc_channels;
2288 static tL2CAP_FIXED_CHNL_REG fcr = {
2289 .pL2CA_FixedConn_Cb = fcchan_conn_chng_cbk,
2290 .pL2CA_FixedData_Cb = fcchan_data_cbk,
2291 .default_idle_tout = 0xffff,
2292 .fixed_chnl_opts = {
2293 .mode = L2CAP_FCR_BASIC_MODE,
2294 .max_transmit = 0xFF,
2295 .rtrans_tout = 2000,
2302 while (t && t->chan != chan)
2308 return NULL; /* we cannot alloc a struct if not asked to */
2310 t = osi_calloc(sizeof(*t));
2313 if (!L2CA_RegisterFixedChannel(chan, &fcr)) {
2319 t->next = fc_channels;
2325 /* pass NULL to find servers */
2326 static struct fc_client *fcclient_find_by_addr(struct fc_client *start, BD_ADDR addr)
2328 struct fc_client *t = start;
2332 /* match client if have addr */
2333 if (addr && !memcmp(addr, &t->remote_addr, sizeof(t->remote_addr)))
2336 /* match server if do not have addr */
2337 if (!addr && t->server)
2340 t = t->next_all_list;
2346 static struct fc_client *fcclient_find_by_id(uint32_t id)
2348 struct fc_client *t = fc_clients;
2350 while (t && t->id != id)
2351 t = t->next_all_list;
2356 static struct fc_client *fcclient_alloc(uint16_t chan, char server, const uint8_t *sec_id_to_use)
2358 struct fc_channel *fc = fcchan_get(chan, TRUE);
2359 struct fc_client *t;
2365 if (fc->has_server && server)
2366 return NULL; /* no way to have multiple servers on same channel */
2369 sec_id = *sec_id_to_use;
2371 sec_id = bta_jv_alloc_sec_id();
2373 t = osi_calloc(sizeof(*t));
2374 // Allocate it a unique ID
2376 t->id = ++fc_next_id;
2377 } while (!t->id || fcclient_find_by_id(t->id));
2379 // Populate some params
2383 // Get a security id
2386 // Link it in to global list
2387 t->next_all_list = fc_clients;
2390 // Link it in to channel list
2391 t->next_chan_list = fc->clients;
2394 // Update channel if needed
2396 fc->has_server = TRUE;
2401 static void fcclient_free(struct fc_client *fc)
2403 struct fc_client *t = fc_clients;
2404 struct fc_channel *tc = fcchan_get(fc->chan, FALSE);
2406 //remove from global list
2407 while (t && t->next_all_list != fc)
2408 t = t->next_all_list;
2410 if (!t && fc != fc_clients)
2411 return; /* prevent double-free */
2414 t->next_all_list = fc->next_all_list;
2416 fc_clients = fc->next_all_list;
2418 //remove from channel list
2422 while (t && t->next_chan_list != fc)
2423 t = t->next_chan_list;
2426 t->next_chan_list = fc->next_chan_list;
2428 tc->clients = fc->next_chan_list;
2430 //if was server then channel no longer has a server
2432 tc->has_server = FALSE;
2436 bta_jv_free_sec_id(&fc->sec_id);
2441 static void fcchan_conn_chng_cbk(UINT16 chan, BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason, tBT_TRANSPORT transport)
2445 struct fc_channel *tc;
2446 struct fc_client *t = NULL, *new_conn;
2447 tBTA_JV_L2CAP_CBACK *p_cback = NULL;
2448 char call_init = FALSE;
2449 void *user_data = NULL;
2452 tc = fcchan_get(chan, FALSE);
2454 t = fcclient_find_by_addr(tc->clients, bd_addr); // try to find an open socked for that addr
2456 p_cback = t->p_cback;
2457 user_data = t->user_data;
2459 t = fcclient_find_by_addr(tc->clients, NULL); // try to find a listening socked for that channel
2461 //found: create a normal connection socket and assign the connection to it
2462 new_conn = fcclient_alloc(chan, FALSE, &t->sec_id);
2465 memcpy(&new_conn->remote_addr, bd_addr, sizeof(new_conn->remote_addr));
2466 new_conn->p_cback = NULL; //for now
2467 new_conn->init_called = TRUE; /*nop need to do it again */
2469 p_cback = t->p_cback;
2470 user_data = t->user_data;
2483 if (!t->init_called) {
2486 t->init_called = TRUE;
2488 init_evt.l2c_cl_init.handle = t->id;
2489 init_evt.l2c_cl_init.status = BTA_JV_SUCCESS;
2490 init_evt.l2c_cl_init.sec_id = t->sec_id;
2493 open_evt.l2c_open.handle = t->id;
2494 open_evt.l2c_open.tx_mtu = 23; /* 23, why not ?*/
2495 memcpy(&open_evt.l2c_le_open.rem_bda, &t->remote_addr, sizeof(open_evt.l2c_le_open.rem_bda));
2496 open_evt.l2c_le_open.p_p_cback = (void**)&t->p_cback;
2497 open_evt.l2c_le_open.p_user_data = &t->user_data;
2498 open_evt.l2c_le_open.status = BTA_JV_SUCCESS;
2501 open_evt.l2c_open.status = BTA_JV_SUCCESS;
2504 open_evt.l2c_open.status = BTA_JV_FAILURE;
2508 if (call_init && p_cback)
2509 p_cback(BTA_JV_L2CAP_CL_INIT_EVT, &init_evt, user_data);
2511 //call this with lock taken so socket does not disappear from under us */
2513 p_cback(BTA_JV_L2CAP_OPEN_EVT, &open_evt, user_data);
2514 if (!t->p_cback) /* no callback set, means they do not want this one... */
2519 static void fcchan_data_cbk(UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf)
2522 struct fc_channel *tc;
2523 struct fc_client *t = NULL;
2524 tBTA_JV_L2CAP_CBACK *sock_cback = NULL;
2525 void *sock_user_data;
2527 tc = fcchan_get(chan, FALSE);
2529 t = fcclient_find_by_addr(tc->clients, bd_addr); // try to find an open socked for that addr and channel
2531 //no socket -> drop it
2535 /* Fix for below klockwork issue
2536 * Null pointer 't' that comes from line 2508
2537 * may be dereferenced at line 2525*/
2540 sock_cback = t->p_cback;
2541 sock_user_data = t->user_data;
2542 evt_data.le_data_ind.handle = t->id;
2544 evt_data.le_data_ind.p_buf = p_buf;
2547 sock_cback(BTA_JV_L2CAP_DATA_IND_EVT, &evt_data, sock_user_data);
2551 /*******************************************************************************
2553 ** Function bta_jv_l2cap_connect_le
2555 ** Description makes an le l2cap client connection
2559 *******************************************************************************/
2560 void bta_jv_l2cap_connect_le(tBTA_JV_MSG *p_data)
2562 tBTA_JV_API_L2CAP_CONNECT *cc = &(p_data->l2cap_connect);
2565 char call_init_f = TRUE;
2566 struct fc_client *t;
2568 evt.l2c_cl_init.handle = GAP_INVALID_HANDLE;
2569 evt.l2c_cl_init.status = BTA_JV_FAILURE;
2571 t = fcclient_alloc(cc->remote_chan, FALSE, NULL);
2573 cc->p_cback(BTA_JV_L2CAP_CL_INIT_EVT, &evt, cc->user_data);
2577 t->p_cback = cc->p_cback;
2578 t->user_data = cc->user_data;
2579 memcpy(&t->remote_addr, &cc->peer_bd_addr, sizeof(t->remote_addr));
2581 t->init_called = FALSE;
2583 if (L2CA_ConnectFixedChnl(t->chan, t->remote_addr)) {
2585 evt.l2c_cl_init.status = BTA_JV_SUCCESS;
2586 evt.l2c_cl_init.handle = id;
2589 //it could have been deleted/moved from under us, so re-find it */
2590 t = fcclient_find_by_id(id);
2592 if (evt.l2c_cl_init.status == BTA_JV_SUCCESS)
2593 call_init_f = !t->init_called;
2598 cc->p_cback(BTA_JV_L2CAP_CL_INIT_EVT, &evt, cc->user_data);
2600 t->init_called = TRUE;
2604 /*******************************************************************************
2606 ** Function bta_jv_l2cap_stop_server_le
2608 ** Description stops an LE L2CAP server
2612 *******************************************************************************/
2613 void bta_jv_l2cap_stop_server_le(tBTA_JV_MSG *p_data)
2616 tBTA_JV_API_L2CAP_SERVER *ls = &(p_data->l2cap_server);
2617 tBTA_JV_L2CAP_CBACK *p_cback = NULL;
2618 struct fc_channel *fcchan;
2619 struct fc_client *fcclient;
2622 evt.l2c_close.status = BTA_JV_FAILURE;
2623 evt.l2c_close.async = FALSE;
2624 evt.l2c_close.handle = GAP_INVALID_HANDLE;
2626 fcchan = fcchan_get(ls->local_chan, FALSE);
2628 while((fcclient = fcchan->clients)) {
2629 p_cback = fcclient->p_cback;
2630 user_data = fcclient->user_data;
2632 evt.l2c_close.handle = fcclient->id;
2633 evt.l2c_close.status = BTA_JV_SUCCESS;
2634 evt.l2c_close.async = FALSE;
2636 fcclient_free(fcclient);
2639 p_cback(BTA_JV_L2CAP_CLOSE_EVT, &evt, user_data);
2644 /*******************************************************************************
2646 ** Function bta_jv_l2cap_start_server_le
2648 ** Description starts an LE L2CAP server
2652 *******************************************************************************/
2653 void bta_jv_l2cap_start_server_le(tBTA_JV_MSG *p_data)
2655 tBTA_JV_API_L2CAP_SERVER *ss = &(p_data->l2cap_server);
2656 tBTA_JV_L2CAP_START evt_data;
2657 struct fc_client *t;
2659 evt_data.handle = GAP_INVALID_HANDLE;
2660 evt_data.status = BTA_JV_FAILURE;
2663 t = fcclient_alloc(ss->local_chan, TRUE, NULL);
2667 t->p_cback = ss->p_cback;
2668 t->user_data = ss->user_data;
2670 //if we got here, we're registered...
2671 evt_data.status = BTA_JV_SUCCESS;
2672 evt_data.handle = t->id;
2673 evt_data.sec_id = t->sec_id;
2676 ss->p_cback(BTA_JV_L2CAP_START_EVT, (tBTA_JV *)&evt_data, ss->user_data);
2679 /*******************************************************************************
2681 ** Function bta_jv_l2cap_close_fixed
2683 ** Description close a fixed channel connection. calls no callbacks. idempotent
2687 *******************************************************************************/
2688 extern void bta_jv_l2cap_close_fixed (tBTA_JV_MSG *p_data)
2690 tBTA_JV_API_L2CAP_CLOSE *cc = &(p_data->l2cap_close);
2691 struct fc_client *t;
2693 t = fcclient_find_by_id(cc->handle);
2698 /*******************************************************************************
2700 ** Function bta_jv_idle_timeout_handler
2702 ** Description Bta JV specific idle timeout handler
2707 *******************************************************************************/
2708 void bta_jv_idle_timeout_handler(void *tle) {
2709 tBTA_JV_PM_CB *p_cb = (tBTA_JV_PM_CB *)tle;;
2710 APPL_TRACE_DEBUG("%s p_cb: %p", __func__, p_cb);
2711 if ((NULL != p_cb) && (BTA_JV_PM_IDLE_ST == p_cb->state))
2713 bta_jv_pm_state_change(p_cb, BTA_JV_CONN_IDLE);