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 ******************************************************************************/
25 #include <arpa/inet.h>
29 #include "osi/allocator.h"
30 #include "stack/bt_types.h"
32 #include "bta/bta_sys.h"
33 #include "bta/bta_api.h"
34 #include "bta/bta_jv_api.h"
35 #include "bta_jv_int.h"
36 #include "bta/bta_jv_co.h"
37 #include "stack/btm_api.h"
39 #include "stack/sdp_api.h"
40 #include "stack/l2c_api.h"
41 #include "stack/port_api.h"
43 #include "stack/rfcdefs.h"
44 #include "stack/avct_api.h"
45 #include "stack/avdt_api.h"
46 #include "stack/gap_api.h"
47 #include "stack/l2c_api.h"
50 #if (defined BTA_JV_INCLUDED && BTA_JV_INCLUDED == TRUE)
51 /* one of these exists for each client */
53 struct fc_client *next_all_list;
54 struct fc_client *next_chan_list;
57 tBTA_JV_L2CAP_CBACK *p_cback;
63 unsigned init_called : 1;
66 /* one of these exists for each channel we're dealing with */
68 struct fc_channel *next;
69 struct fc_client *clients;
70 uint8_t has_server : 1;
75 static struct fc_client *fc_clients;
76 static struct fc_channel *fc_channels;
77 static uint32_t fc_next_id;
78 static pthread_once_t fc_init_once = PTHREAD_ONCE_INIT;
81 static void fc_init_work(void)
87 //more init here if needed...
90 static void __attribute__((unused)) fc_init(void)
92 pthread_once(&fc_init_once, fc_init_work);
96 static void fcchan_conn_chng_cbk(UINT16 chan, BD_ADDR bd_addr, BOOLEAN connected,
97 UINT16 reason, tBT_TRANSPORT );
98 static void fcchan_data_cbk(UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf);
101 extern void uuid_to_string_legacy(bt_uuid_t *p_uuid, char *str);
102 static inline void logu(const char *title, const uint8_t *p_uuid)
105 uuid_to_string_legacy((bt_uuid_t *)p_uuid, uuids);
106 APPL_TRACE_DEBUG("%s: %s", title, uuids);
110 static tBTA_JV_PCB *bta_jv_add_rfc_port(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pcb_open);
111 static tBTA_JV_STATUS bta_jv_free_set_pm_profile_cb(UINT32 jv_handle);
112 static void bta_jv_pm_conn_busy(tBTA_JV_PM_CB *p_cb);
113 static void bta_jv_pm_conn_idle(tBTA_JV_PM_CB *p_cb);
114 static void bta_jv_pm_state_change(tBTA_JV_PM_CB *p_cb, const tBTA_JV_CONN_STATE state);
115 tBTA_JV_STATUS bta_jv_set_pm_conn_state(tBTA_JV_PM_CB *p_cb, const tBTA_JV_CONN_STATE
118 /*******************************************************************************
120 ** Function bta_jv_alloc_sec_id
122 ** Description allocate a security id
126 *******************************************************************************/
127 UINT8 bta_jv_alloc_sec_id(void)
131 for (i = 0; i < BTA_JV_NUM_SERVICE_ID; i++) {
132 if (0 == bta_jv_cb.sec_id[i]) {
133 bta_jv_cb.sec_id[i] = BTA_JV_FIRST_SERVICE_ID + i;
134 ret = bta_jv_cb.sec_id[i];
141 static int get_sec_id_used(void)
145 for (i = 0; i < BTA_JV_NUM_SERVICE_ID; i++) {
146 if (bta_jv_cb.sec_id[i]) {
150 if (used == BTA_JV_NUM_SERVICE_ID)
151 APPL_TRACE_ERROR("get_sec_id_used, sec id exceeds the limit:%d",
152 BTA_JV_NUM_SERVICE_ID);
155 static int get_rfc_cb_used(void)
159 for (i = 0; i < BTA_JV_MAX_RFC_CONN; i++) {
160 if (bta_jv_cb.rfc_cb[i].handle ) {
164 if (used == BTA_JV_MAX_RFC_CONN)
165 APPL_TRACE_ERROR("get_sec_id_used, rfc ctrl block exceeds the limit:%d",
166 BTA_JV_MAX_RFC_CONN);
170 /*******************************************************************************
172 ** Function bta_jv_free_sec_id
174 ** Description free the given security id
178 *******************************************************************************/
179 static void bta_jv_free_sec_id(UINT8 *p_sec_id)
181 UINT8 sec_id = *p_sec_id;
183 if (sec_id >= BTA_JV_FIRST_SERVICE_ID && sec_id <= BTA_JV_LAST_SERVICE_ID) {
184 BTM_SecClrService(sec_id);
185 bta_jv_cb.sec_id[sec_id - BTA_JV_FIRST_SERVICE_ID] = 0;
189 /*******************************************************************************
191 ** Function bta_jv_alloc_rfc_cb
193 ** Description allocate a control block for the given port handle
197 *******************************************************************************/
198 tBTA_JV_RFC_CB *bta_jv_alloc_rfc_cb(UINT16 port_handle, tBTA_JV_PCB **pp_pcb)
200 tBTA_JV_RFC_CB *p_cb = NULL;
203 for (i = 0; i < BTA_JV_MAX_RFC_CONN; i++) {
204 if (0 == bta_jv_cb.rfc_cb[i].handle ) {
205 p_cb = &bta_jv_cb.rfc_cb[i];
206 /* mask handle to distinguish it with L2CAP handle */
207 p_cb->handle = (i + 1) | BTA_JV_RFCOMM_MASK;
211 for (j = 0; j < BTA_JV_MAX_RFC_SR_SESSION; j++) {
212 p_cb->rfc_hdl[j] = 0;
214 p_cb->rfc_hdl[0] = port_handle;
215 APPL_TRACE_DEBUG( "bta_jv_alloc_rfc_cb port_handle:%d handle:0x%2x",
216 port_handle, p_cb->handle);
218 p_pcb = &bta_jv_cb.port_cb[port_handle - 1];
219 p_pcb->handle = p_cb->handle;
220 p_pcb->port_handle = port_handle;
221 p_pcb->p_pm_cb = NULL;
227 APPL_TRACE_ERROR( "bta_jv_alloc_rfc_cb: port_handle:%d, ctrl block exceeds "
228 "limit:%d", port_handle, BTA_JV_MAX_RFC_CONN);
233 /*******************************************************************************
235 ** Function bta_jv_rfc_port_to_pcb
237 ** Description find the port control block associated with the given port handle
241 *******************************************************************************/
242 tBTA_JV_PCB *bta_jv_rfc_port_to_pcb(UINT16 port_handle)
244 tBTA_JV_PCB *p_pcb = NULL;
246 if ((port_handle > 0) && (port_handle <= MAX_RFC_PORTS)
247 && bta_jv_cb.port_cb[port_handle - 1].handle) {
248 p_pcb = &bta_jv_cb.port_cb[port_handle - 1];
254 /*******************************************************************************
256 ** Function bta_jv_rfc_port_to_cb
258 ** Description find the RFCOMM control block associated with the given port handle
262 *******************************************************************************/
263 tBTA_JV_RFC_CB *bta_jv_rfc_port_to_cb(UINT16 port_handle)
265 tBTA_JV_RFC_CB *p_cb = NULL;
268 if ((port_handle > 0) && (port_handle <= MAX_RFC_PORTS)
269 && bta_jv_cb.port_cb[port_handle - 1].handle) {
270 handle = bta_jv_cb.port_cb[port_handle - 1].handle;
271 handle &= BTA_JV_RFC_HDL_MASK;
272 handle &= ~BTA_JV_RFCOMM_MASK;
274 p_cb = &bta_jv_cb.rfc_cb[handle - 1];
277 APPL_TRACE_WARNING("bta_jv_rfc_port_to_cb(port_handle:0x%x):jv handle:0x%x not"
278 " FOUND", port_handle, bta_jv_cb.port_cb[port_handle - 1].handle);
283 static tBTA_JV_STATUS bta_jv_free_rfc_cb(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pcb)
285 tBTA_JV_STATUS status = BTA_JV_SUCCESS;
286 BOOLEAN remove_server = FALSE;
287 int close_pending = 0;
289 if (!p_cb || !p_pcb) {
290 APPL_TRACE_ERROR("bta_jv_free_sr_rfc_cb, p_cb or p_pcb cannot be null");
291 return BTA_JV_FAILURE;
293 APPL_TRACE_DEBUG("bta_jv_free_sr_rfc_cb: max_sess:%d, curr_sess:%d, p_pcb:%p, user:"
294 "%p, state:%d, jv handle: 0x%x" , p_cb->max_sess, p_cb->curr_sess, p_pcb,
295 p_pcb->user_data, p_pcb->state, p_pcb->handle);
297 if (p_cb->curr_sess <= 0) {
298 return BTA_JV_SUCCESS;
301 switch (p_pcb->state) {
302 case BTA_JV_ST_CL_CLOSING:
303 case BTA_JV_ST_SR_CLOSING:
304 APPL_TRACE_WARNING("bta_jv_free_sr_rfc_cb: return on closing, port state:%d, "
305 "scn:%d, p_pcb:%p, user_data:%p", p_pcb->state, p_cb->scn, p_pcb,
307 status = BTA_JV_FAILURE;
309 case BTA_JV_ST_CL_OPEN:
310 case BTA_JV_ST_CL_OPENING:
311 APPL_TRACE_DEBUG("bta_jv_free_sr_rfc_cb: state: %d, scn:%d,"
312 " user_data:%p", p_pcb->state, p_cb->scn, p_pcb->user_data);
313 p_pcb->state = BTA_JV_ST_CL_CLOSING;
315 case BTA_JV_ST_SR_LISTEN:
316 p_pcb->state = BTA_JV_ST_SR_CLOSING;
317 remove_server = TRUE;
318 APPL_TRACE_DEBUG("bta_jv_free_sr_rfc_cb: state: BTA_JV_ST_SR_LISTEN, scn:%d,"
319 " user_data:%p", p_cb->scn, p_pcb->user_data);
321 case BTA_JV_ST_SR_OPEN:
322 p_pcb->state = BTA_JV_ST_SR_CLOSING;
323 APPL_TRACE_DEBUG("bta_jv_free_sr_rfc_cb: state: BTA_JV_ST_SR_OPEN, scn:%d,"
324 " user_data:%p", p_cb->scn, p_pcb->user_data);
327 APPL_TRACE_WARNING("bta_jv_free_sr_rfc_cb():failed, ignore port state:%d, scn:"
328 "%d, p_pcb:%p, jv handle: 0x%x, port_handle: %d, user_data:%p",
329 p_pcb->state, p_cb->scn, p_pcb, p_pcb->handle, p_pcb->port_handle,
331 status = BTA_JV_FAILURE;
334 if (BTA_JV_SUCCESS == status) {
337 if (!remove_server) {
338 port_status = RFCOMM_RemoveConnection(p_pcb->port_handle);
340 port_status = RFCOMM_RemoveServer(p_pcb->port_handle);
342 if (port_status != PORT_SUCCESS) {
343 status = BTA_JV_FAILURE;
344 APPL_TRACE_WARNING("bta_jv_free_rfc_cb(jv handle: 0x%x, state %d)::"
345 "port_status: %d, port_handle: %d, close_pending: %d:Remove",
346 p_pcb->handle, p_pcb->state, port_status, p_pcb->port_handle,
350 if (!close_pending) {
351 p_pcb->port_handle = 0;
352 p_pcb->state = BTA_JV_ST_NONE;
353 bta_jv_free_set_pm_profile_cb(p_pcb->handle);
355 //Initialize congestion flags
357 p_pcb->user_data = 0;
358 int si = BTA_JV_RFC_HDL_TO_SIDX(p_pcb->handle);
359 if (0 <= si && si < BTA_JV_MAX_RFC_SR_SESSION) {
360 p_cb->rfc_hdl[si] = 0;
364 if (p_cb->curr_sess == 0) {
366 bta_jv_free_sec_id(&p_cb->sec_id);
367 p_cb->p_cback = NULL;
369 p_cb->curr_sess = -1;
372 bta_jv_free_sec_id(&p_cb->sec_id);
378 /*******************************************************************************
380 ** Function bta_jv_free_l2c_cb
382 ** Description free the given L2CAP control block
386 *******************************************************************************/
387 tBTA_JV_STATUS bta_jv_free_l2c_cb(tBTA_JV_L2C_CB *p_cb)
389 tBTA_JV_STATUS status = BTA_JV_SUCCESS;
391 if (BTA_JV_ST_NONE != p_cb->state) {
392 bta_jv_free_set_pm_profile_cb((UINT32)p_cb->handle);
393 if (GAP_ConnClose(p_cb->handle) != BT_PASS) {
394 status = BTA_JV_FAILURE;
398 p_cb->state = BTA_JV_ST_NONE;
399 bta_jv_free_sec_id(&p_cb->sec_id);
400 p_cb->p_cback = NULL;
404 /*******************************************************************************
407 ** Function bta_jv_clear_pm_cb
409 ** Description clears jv pm control block and optionally calls bta_sys_conn_close()
410 ** In general close_conn should be set to TRUE to remove registering with
413 ** WARNING: Make sure to clear pointer form port or l2c to this control block too!
415 *******************************************************************************/
416 static void bta_jv_clear_pm_cb(tBTA_JV_PM_CB *p_pm_cb, BOOLEAN close_conn)
418 /* needs to be called if registered with bta pm, otherwise we may run out of dm pm slots! */
420 bta_sys_conn_close(BTA_ID_JV, p_pm_cb->app_id, p_pm_cb->peer_bd_addr);
422 p_pm_cb->state = BTA_JV_PM_FREE_ST;
423 p_pm_cb->app_id = BTA_JV_PM_ALL;
424 p_pm_cb->handle = BTA_JV_PM_HANDLE_CLEAR;
425 bdcpy(p_pm_cb->peer_bd_addr, bd_addr_null);
428 /*******************************************************************************
430 ** Function bta_jv_free_set_pm_profile_cb
432 ** Description free pm profile control block
434 ** Returns BTA_JV_SUCCESS if cb has been freed correctly,
435 ** BTA_JV_FAILURE in case of no profile has been registered or already freed
437 *******************************************************************************/
438 static tBTA_JV_STATUS bta_jv_free_set_pm_profile_cb(UINT32 jv_handle)
440 tBTA_JV_STATUS status = BTA_JV_FAILURE;
441 tBTA_JV_PM_CB **p_cb;
442 int i, j, bd_counter = 0, appid_counter = 0;
444 for (i = 0; i < BTA_JV_PM_MAX_NUM; i++) {
446 if ((bta_jv_cb.pm_cb[i].state != BTA_JV_PM_FREE_ST) &&
447 (jv_handle == bta_jv_cb.pm_cb[i].handle)) {
448 for (j = 0; j < BTA_JV_PM_MAX_NUM; j++) {
449 if (bdcmp(bta_jv_cb.pm_cb[j].peer_bd_addr, bta_jv_cb.pm_cb[i].peer_bd_addr) == 0) {
452 if (bta_jv_cb.pm_cb[j].app_id == bta_jv_cb.pm_cb[i].app_id) {
457 APPL_TRACE_API("%s(jv_handle: 0x%2x), idx: %d, "
458 "app_id: 0x%x", __func__, jv_handle, i, bta_jv_cb.pm_cb[i].app_id);
459 APPL_TRACE_API("%s, bd_counter = %d, "
460 "appid_counter = %d", __func__, bd_counter, appid_counter);
461 if (bd_counter > 1) {
462 bta_jv_pm_conn_idle(&bta_jv_cb.pm_cb[i]);
465 if (bd_counter <= 1 || (appid_counter <= 1)) {
466 bta_jv_clear_pm_cb(&bta_jv_cb.pm_cb[i], TRUE);
468 bta_jv_clear_pm_cb(&bta_jv_cb.pm_cb[i], FALSE);
471 if (BTA_JV_RFCOMM_MASK & jv_handle) {
472 UINT32 hi = ((jv_handle & BTA_JV_RFC_HDL_MASK) & ~BTA_JV_RFCOMM_MASK) - 1;
473 UINT32 si = BTA_JV_RFC_HDL_TO_SIDX(jv_handle);
474 if (hi < BTA_JV_MAX_RFC_CONN && bta_jv_cb.rfc_cb[hi].p_cback && si
475 < BTA_JV_MAX_RFC_SR_SESSION && bta_jv_cb.rfc_cb[hi].rfc_hdl[si]) {
476 tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(bta_jv_cb.rfc_cb[hi].rfc_hdl[si]);
478 if (NULL == p_pcb->p_pm_cb)
479 APPL_TRACE_WARNING("%s(jv_handle:"
480 " 0x%x):port_handle: 0x%x, p_pm_cb: %d: no link to "
481 "pm_cb?", __func__, jv_handle, p_pcb->port_handle, i);
482 p_cb = &p_pcb->p_pm_cb;
486 if (jv_handle < BTA_JV_MAX_L2C_CONN) {
487 tBTA_JV_L2C_CB *p_l2c_cb = &bta_jv_cb.l2c_cb[jv_handle];
488 if (NULL == p_l2c_cb->p_pm_cb)
489 APPL_TRACE_WARNING("%s(jv_handle: "
490 "0x%x): p_pm_cb: %d: no link to pm_cb?", __func__, jv_handle, i);
491 p_cb = &p_l2c_cb->p_pm_cb;
496 status = BTA_JV_SUCCESS;
503 /*******************************************************************************
505 ** Function bta_jv_alloc_set_pm_profile_cb
507 ** Description set PM profile control block
509 ** Returns pointer to allocated cb or NULL in case of failure
511 *******************************************************************************/
512 static tBTA_JV_PM_CB *bta_jv_alloc_set_pm_profile_cb(UINT32 jv_handle, tBTA_JV_PM_ID app_id)
514 BOOLEAN bRfcHandle = (jv_handle & BTA_JV_RFCOMM_MASK) != 0;
515 BD_ADDR peer_bd_addr;
517 tBTA_JV_PM_CB **pp_cb;
519 for (i = 0; i < BTA_JV_PM_MAX_NUM; i++) {
521 if (bta_jv_cb.pm_cb[i].state == BTA_JV_PM_FREE_ST) {
522 /* rfc handle bd addr retrieval requires core stack handle */
524 // UINT32 hi = ((jv_handle & BTA_JV_RFC_HDL_MASK) & ~BTA_JV_RFCOMM_MASK) - 1;
525 // UINT32 si = BTA_JV_RFC_HDL_TO_SIDX(jv_handle);
526 for (j = 0; j < BTA_JV_MAX_RFC_CONN; j++) {
527 if (jv_handle == bta_jv_cb.port_cb[j].handle) {
528 pp_cb = &bta_jv_cb.port_cb[j].p_pm_cb;
529 if (PORT_SUCCESS != PORT_CheckConnection(
530 bta_jv_cb.port_cb[j].port_handle, peer_bd_addr, NULL)) {
531 i = BTA_JV_PM_MAX_NUM;
537 /* use jv handle for l2cap bd address retrieval */
538 for (j = 0; j < BTA_JV_MAX_L2C_CONN; j++) {
539 if (jv_handle == bta_jv_cb.l2c_cb[j].handle) {
540 pp_cb = &bta_jv_cb.l2c_cb[j].p_pm_cb;
541 UINT8 *p_bd_addr = GAP_ConnGetRemoteAddr((UINT16)jv_handle);
542 if (NULL != p_bd_addr) {
543 bdcpy(peer_bd_addr, p_bd_addr);
545 i = BTA_JV_PM_MAX_NUM;
551 APPL_TRACE_API("bta_jv_alloc_set_pm_profile_cb(handle 0x%2x, app_id %d): "
552 "idx: %d, (BTA_JV_PM_MAX_NUM: %d), pp_cb: %p", jv_handle, app_id,
553 i, BTA_JV_PM_MAX_NUM, (void *)pp_cb);
558 if ((i != BTA_JV_PM_MAX_NUM) && (NULL != pp_cb)) {
559 *pp_cb = &bta_jv_cb.pm_cb[i];
560 bta_jv_cb.pm_cb[i].handle = jv_handle;
561 bta_jv_cb.pm_cb[i].app_id = app_id;
562 bdcpy(bta_jv_cb.pm_cb[i].peer_bd_addr, peer_bd_addr);
563 bta_jv_cb.pm_cb[i].state = BTA_JV_PM_IDLE_ST;
564 return &bta_jv_cb.pm_cb[i];
566 APPL_TRACE_WARNING("bta_jv_alloc_set_pm_profile_cb(jv_handle: 0x%x, app_id: %d) "
567 "return NULL", jv_handle, app_id);
568 return (tBTA_JV_PM_CB *)NULL;
571 /*******************************************************************************
573 ** Function bta_jv_check_psm
575 ** Description for now use only the legal PSM per JSR82 spec
577 ** Returns TRUE, if allowed
579 *******************************************************************************/
580 BOOLEAN bta_jv_check_psm(UINT16 psm)
584 if (L2C_IS_VALID_PSM(psm)) {
586 /* see if this is defined by spec */
588 case SDP_PSM: /* 1 */
589 case BT_PSM_RFCOMM: /* 3 */
590 /* do not allow java app to use these 2 PSMs */
593 case TCS_PSM_INTERCOM: /* 5 */
594 case TCS_PSM_CORDLESS: /* 7 */
595 if ( FALSE == bta_sys_is_register(BTA_ID_CT) &&
596 FALSE == bta_sys_is_register(BTA_ID_CG) ) {
601 case BT_PSM_BNEP: /* F */
602 if (FALSE == bta_sys_is_register(BTA_ID_PAN)) {
607 case HID_PSM_CONTROL: /* 0x11 */
608 case HID_PSM_INTERRUPT: /* 0x13 */
609 //FIX: allow HID Device and HID Host to coexist
610 if ( FALSE == bta_sys_is_register(BTA_ID_HD) ||
611 FALSE == bta_sys_is_register(BTA_ID_HH) ) {
616 case AVCT_PSM: /* 0x17 */
617 case AVDT_PSM: /* 0x19 */
618 if ((FALSE == bta_sys_is_register(BTA_ID_AV)) &&
619 (FALSE == bta_sys_is_register(BTA_ID_AVK))) {
636 /*******************************************************************************
638 ** Function bta_jv_enable
640 ** Description Initialises the JAVA I/F
644 *******************************************************************************/
645 void bta_jv_enable(tBTA_JV_MSG *p_data)
647 tBTA_JV_STATUS status = BTA_JV_SUCCESS;
648 bta_jv_cb.p_dm_cback = p_data->enable.p_cback;
649 bta_jv_cb.p_dm_cback(BTA_JV_ENABLE_EVT, (tBTA_JV *)&status, 0);
650 memset(bta_jv_cb.free_psm_list, 0, sizeof(bta_jv_cb.free_psm_list));
653 /*******************************************************************************
655 ** Function bta_jv_disable
657 ** Description Disables the BT device manager
658 ** free the resources used by java
662 *******************************************************************************/
663 void bta_jv_disable (tBTA_JV_MSG *p_data)
667 APPL_TRACE_ERROR("%s", __func__);
672 * We keep a list of PSM's that have been freed from JAVA, for reuse.
673 * This function will return a free PSM, and delete it from the free
675 * If no free PSMs exist, 0 will be returned.
677 static UINT16 bta_jv_get_free_psm()
679 const int cnt = sizeof(bta_jv_cb.free_psm_list) / sizeof(bta_jv_cb.free_psm_list[0]);
680 for (int i = 0; i < cnt; i++) {
681 UINT16 psm = bta_jv_cb.free_psm_list[i];
683 APPL_TRACE_DEBUG("%s(): Reusing PSM: 0x%04d", __func__, psm)
684 bta_jv_cb.free_psm_list[i] = 0;
691 static void bta_jv_set_free_psm(UINT16 psm)
694 const int cnt = sizeof(bta_jv_cb.free_psm_list) / sizeof(bta_jv_cb.free_psm_list[0]);
695 for (int i = 0; i < cnt; i++) {
696 if (bta_jv_cb.free_psm_list[i] == 0) {
698 } else if (psm == bta_jv_cb.free_psm_list[i]) {
699 return; // PSM already freed?
702 if (free_index != -1) {
703 bta_jv_cb.free_psm_list[free_index] = psm;
704 APPL_TRACE_DEBUG("%s(): Recycling PSM: 0x%04d", __func__, psm)
706 APPL_TRACE_ERROR("%s unable to free psm 0x%x no more free slots", __func__, psm);
710 /*******************************************************************************
712 ** Function bta_jv_get_channel_id
714 ** Description Obtain a free SCN (Server Channel Number)
715 ** (RFCOMM channel or L2CAP PSM)
719 *******************************************************************************/
720 void bta_jv_get_channel_id(tBTA_JV_MSG *p_data)
724 switch (p_data->alloc_channel.type) {
725 case BTA_JV_CONN_TYPE_RFCOMM: {
726 INT32 channel = p_data->alloc_channel.channel;
729 if (BTM_TryAllocateSCN(channel) == FALSE) {
730 APPL_TRACE_ERROR("rfc channel:%d already in use or invalid", channel);
733 } else if ((channel = BTM_AllocateSCN()) == 0) {
734 APPL_TRACE_ERROR("run out of rfc channels");
738 bta_jv_cb.scn[channel - 1] = TRUE;
739 scn = (UINT8) channel;
741 if (bta_jv_cb.p_dm_cback)
742 bta_jv_cb.p_dm_cback(BTA_JV_GET_SCN_EVT, (tBTA_JV *)&scn,
743 p_data->alloc_channel.user_data);
746 case BTA_JV_CONN_TYPE_L2CAP:
747 psm = bta_jv_get_free_psm();
749 psm = L2CA_AllocatePSM();
750 APPL_TRACE_DEBUG("%s() returned PSM: 0x%04x", __func__, psm);
753 case BTA_JV_CONN_TYPE_L2CAP_LE:
759 if (bta_jv_cb.p_dm_cback) {
760 bta_jv_cb.p_dm_cback(BTA_JV_GET_PSM_EVT, (tBTA_JV *)&psm, p_data->alloc_channel.user_data);
764 /*******************************************************************************
766 ** Function bta_jv_free_scn
768 ** Description free a SCN
772 *******************************************************************************/
773 void bta_jv_free_scn(tBTA_JV_MSG *p_data)
775 UINT16 scn = p_data->free_channel.scn;
777 switch (p_data->free_channel.type) {
778 case BTA_JV_CONN_TYPE_RFCOMM: {
779 if (scn > 0 && scn <= BTA_JV_MAX_SCN && bta_jv_cb.scn[scn - 1]) {
780 /* this scn is used by JV */
781 bta_jv_cb.scn[scn - 1] = FALSE;
786 case BTA_JV_CONN_TYPE_L2CAP:
787 bta_jv_set_free_psm(scn);
789 case BTA_JV_CONN_TYPE_L2CAP_LE:
790 // TODO: Not yet implemented...
796 static inline tBT_UUID shorten_sdp_uuid(const tBT_UUID *u)
798 static uint8_t bt_base_uuid[] =
799 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB };
801 logu("in, uuid:", u->uu.uuid128);
802 APPL_TRACE_DEBUG("uuid len:%d", u->len);
804 if (memcmp(&u->uu.uuid128[4], &bt_base_uuid[4], 12) == 0) {
806 memset(&su, 0, sizeof(su));
807 if (u->uu.uuid128[0] == 0 && u->uu.uuid128[1] == 0) {
810 memcpy(&u16, &u->uu.uuid128[2], sizeof(u16));
811 su.uu.uuid16 = ntohs(u16);
812 APPL_TRACE_DEBUG("shorten to 16 bits uuid: %x", su.uu.uuid16);
816 memcpy(&u32, &u->uu.uuid128[0], sizeof(u32));
817 su.uu.uuid32 = ntohl(u32);
818 APPL_TRACE_DEBUG("shorten to 32 bits uuid: %x", su.uu.uuid32);
823 APPL_TRACE_DEBUG("cannot shorten none-reserved 128 bits uuid");
827 /*******************************************************************************
829 ** Function bta_jv_start_discovery_cback
831 ** Description Callback for Start Discovery
835 *******************************************************************************/
836 static void bta_jv_start_discovery_cback(UINT16 result, void *user_data)
838 tBTA_JV_STATUS status;
839 // UINT8 old_sdp_act = bta_jv_cb.sdp_active;
841 APPL_TRACE_DEBUG("bta_jv_start_discovery_cback res: 0x%x", result);
843 bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_NONE;
844 if (bta_jv_cb.p_dm_cback) {
845 tBTA_JV_DISCOVERY_COMP dcomp;
847 status = BTA_JV_FAILURE;
848 if (result == SDP_SUCCESS || result == SDP_DB_FULL) {
849 tSDP_DISC_REC *p_sdp_rec = NULL;
850 tSDP_PROTOCOL_ELEM pe;
851 logu("bta_jv_cb.uuid", bta_jv_cb.uuid.uu.uuid128);
852 tBT_UUID su = shorten_sdp_uuid(&bta_jv_cb.uuid);
853 logu("shorten uuid:", su.uu.uuid128);
855 p_sdp_rec = SDP_FindServiceUUIDInDb(p_bta_jv_cfg->p_sdp_db, &su, p_sdp_rec);
856 APPL_TRACE_DEBUG("p_sdp_rec:%p", p_sdp_rec);
857 if (p_sdp_rec && SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_RFCOMM, &pe)){
858 dcomp.scn[dcomp.scn_num++] = (UINT8) pe.params[0];
859 status = BTA_JV_SUCCESS;
864 dcomp.status = status;
865 bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, (tBTA_JV *)&dcomp, user_data);
869 /*******************************************************************************
871 ** Function bta_jv_start_discovery
873 ** Description Discovers services on a remote device
877 *******************************************************************************/
878 void bta_jv_start_discovery(tBTA_JV_MSG *p_data)
880 tBTA_JV_STATUS status = BTA_JV_FAILURE;
881 APPL_TRACE_DEBUG("bta_jv_start_discovery in, sdp_active:%d", bta_jv_cb.sdp_active);
882 if (bta_jv_cb.sdp_active != BTA_JV_SDP_ACT_NONE) {
883 /* SDP is still in progress */
884 status = BTA_JV_BUSY;
885 if (bta_jv_cb.p_dm_cback) {
886 bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, (tBTA_JV *)&status, p_data->start_discovery.user_data);
891 /* init the database/set up the filter */
892 APPL_TRACE_DEBUG("call SDP_InitDiscoveryDb, p_data->start_discovery.num_uuid:%d",
893 p_data->start_discovery.num_uuid);
894 SDP_InitDiscoveryDb (p_bta_jv_cfg->p_sdp_db, p_bta_jv_cfg->sdp_db_size,
895 p_data->start_discovery.num_uuid, p_data->start_discovery.uuid_list, 0, NULL);
897 /* tell SDP to keep the raw data */
898 p_bta_jv_cfg->p_sdp_db->raw_data = p_bta_jv_cfg->p_sdp_raw_data;
899 p_bta_jv_cfg->p_sdp_db->raw_size = p_bta_jv_cfg->sdp_raw_size;
901 bta_jv_cb.p_sel_raw_data = 0;
902 bta_jv_cb.uuid = p_data->start_discovery.uuid_list[0];
904 bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_YES;
905 if (!SDP_ServiceSearchAttributeRequest2(p_data->start_discovery.bd_addr,
906 p_bta_jv_cfg->p_sdp_db,
907 bta_jv_start_discovery_cback, p_data->start_discovery.user_data)) {
908 bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_NONE;
909 /* failed to start SDP. report the failure right away */
910 if (bta_jv_cb.p_dm_cback) {
911 bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, (tBTA_JV *)&status, p_data->start_discovery.user_data);
915 else report the result when the cback is called
920 * @brief Adds a protocol list and service name (if provided) to an SDP record given by
921 * sdp_handle, and marks it as browseable. This is a shortcut for defining a
922 * set of protocols that includes L2CAP, RFCOMM, and optionally OBEX.
924 * @param[in] sdp_handle: SDP handle
925 * @param[in] name: service name
926 * @param[in] channel: channel
927 * @param[in] with_obex: if TRUE, then an additional OBEX protocol UUID will be included
928 * at the end of the protocol list.
933 static bool create_base_record(const uint32_t sdp_handle, const char *name, const uint16_t channel, const bool with_obex){
934 APPL_TRACE_DEBUG("create_base_record: scn: %d, name: %s, with_obex: %d",
935 channel, name, with_obex);
937 // Setup the protocol list and add it.
938 tSDP_PROTOCOL_ELEM proto_list[SDP_MAX_LIST_ELEMS];
939 int num_proto_elements = with_obex ? 3 : 2;
941 memset(proto_list, 0, num_proto_elements * sizeof(tSDP_PROTOCOL_ELEM));
943 proto_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
944 proto_list[0].num_params = 0;
945 proto_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
946 proto_list[1].num_params = 1;
947 proto_list[1].params[0] = channel;
949 if (with_obex == TRUE) {
950 proto_list[2].protocol_uuid = UUID_PROTOCOL_OBEX;
951 proto_list[2].num_params = 0;
954 const char *stage = "protocol_list";
955 if (!SDP_AddProtocolList(sdp_handle, num_proto_elements, proto_list)){
956 APPL_TRACE_ERROR("create_base_record: failed to create base service "
957 "record, stage: %s, scn: %d, name: %s, with_obex: %d",
958 stage, channel, name, with_obex);
962 // Add the name to the SDP record.
963 if (name[0] != '\0') {
964 stage = "service_name";
965 if (!SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_NAME,
966 TEXT_STR_DESC_TYPE, (uint32_t)(strlen(name) + 1),
968 APPL_TRACE_ERROR("create_base_record: failed to create base service "
969 "record, stage: %s, scn: %d, name: %s, with_obex: %d",
970 stage, channel, name, with_obex);
975 // Mark the service as browseable.
976 uint16_t list = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
977 stage = "browseable";
978 if (!SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &list)){
979 APPL_TRACE_ERROR("create_base_record: failed to create base service "
980 "record, stage: %s, scn: %d, name: %s, with_obex: %d",
981 stage, channel, name, with_obex);
986 APPL_TRACE_DEBUG("create_base_record: successfully created base service "
987 "record, handle: 0x%08x, scn: %d, name: %s, with_obex: %d",
988 sdp_handle, channel, name, with_obex);
992 static int add_spp_sdp(const char *name, const int channel) {
993 APPL_TRACE_DEBUG("add_spp_sdp: scn %d, service_name %s", channel, name);
995 int handle = SDP_CreateRecord();
997 APPL_TRACE_ERROR("add_spp_sdp: failed to create sdp record, "
998 "service_name: %s", name);
1002 // Create the base SDP record.
1003 const char *stage = "create_base_record";
1004 if (!create_base_record(handle, name, channel, FALSE /* with_obex */)){
1005 SDP_DeleteRecord(handle);
1006 APPL_TRACE_ERROR("add_spp_sdp: failed to register SPP service, "
1007 "stage: %s, service_name: %s", stage, name);
1011 uint16_t service = UUID_SERVCLASS_SERIAL_PORT;
1012 stage = "service_class";
1013 if (!SDP_AddServiceClassIdList(handle, 1, &service)){
1014 SDP_DeleteRecord(handle);
1015 APPL_TRACE_ERROR("add_spp_sdp: failed to register SPP service, "
1016 "stage: %s, service_name: %s", stage, name);
1020 APPL_TRACE_DEBUG("add_spp_sdp: service registered successfully, "
1021 "service_name: %s, handle 0x%08x)", name, handle);
1025 /*******************************************************************************
1027 ** Function bta_jv_create_record
1029 ** Description Create an SDP record with the given attributes
1033 *******************************************************************************/
1034 void bta_jv_create_record(tBTA_JV_MSG *p_data)
1036 tBTA_JV_API_CREATE_RECORD *cr = &(p_data->create_record);
1037 tBTA_JV_CREATE_RECORD evt_data;
1039 int handle = add_spp_sdp(cr->name, cr->channel);
1040 evt_data.handle = handle;
1042 evt_data.status = BTA_JV_SUCCESS;
1044 evt_data.status = BTA_JV_FAILURE;
1047 if(bta_jv_cb.p_dm_cback) {
1048 //callback user immediately to create his own sdp record in stack thread context
1049 bta_jv_cb.p_dm_cback(BTA_JV_CREATE_RECORD_EVT, (tBTA_JV *)&evt_data, cr->user_data);
1053 /*******************************************************************************
1055 ** Function bta_jv_delete_record
1057 ** Description Delete an SDP record
1062 *******************************************************************************/
1063 void bta_jv_delete_record(tBTA_JV_MSG *p_data)
1065 tBTA_JV_API_ADD_ATTRIBUTE *dr = &(p_data->add_attr);
1067 /* this is a record created by btif layer*/
1068 SDP_DeleteRecord(dr->handle);
1072 /*******************************************************************************
1074 ** Function bta_jv_l2cap_client_cback
1076 ** Description handles the l2cap client events
1080 *******************************************************************************/
1081 static void bta_jv_l2cap_client_cback(UINT16 gap_handle, UINT16 event)
1083 tBTA_JV_L2C_CB *p_cb = &bta_jv_cb.l2c_cb[gap_handle];
1086 if (gap_handle >= BTA_JV_MAX_L2C_CONN && !p_cb->p_cback) {
1090 APPL_TRACE_DEBUG( "%s: %d evt:x%x", __func__, gap_handle, event);
1091 evt_data.l2c_open.status = BTA_JV_SUCCESS;
1092 evt_data.l2c_open.handle = gap_handle;
1095 case GAP_EVT_CONN_OPENED:
1096 bdcpy(evt_data.l2c_open.rem_bda, GAP_ConnGetRemoteAddr(gap_handle));
1097 evt_data.l2c_open.tx_mtu = GAP_ConnGetRemMtuSize(gap_handle);
1098 p_cb->state = BTA_JV_ST_CL_OPEN;
1099 p_cb->p_cback(BTA_JV_L2CAP_OPEN_EVT, &evt_data, p_cb->user_data);
1102 case GAP_EVT_CONN_CLOSED:
1103 p_cb->state = BTA_JV_ST_NONE;
1104 bta_jv_free_sec_id(&p_cb->sec_id);
1105 evt_data.l2c_close.async = TRUE;
1106 p_cb->p_cback(BTA_JV_L2CAP_CLOSE_EVT, &evt_data, p_cb->user_data);
1107 p_cb->p_cback = NULL;
1110 case GAP_EVT_CONN_DATA_AVAIL:
1111 evt_data.data_ind.handle = gap_handle;
1112 /* Reset idle timer to avoid requesting sniff mode while receiving data */
1113 bta_jv_pm_conn_busy(p_cb->p_pm_cb);
1114 p_cb->p_cback(BTA_JV_L2CAP_DATA_IND_EVT, &evt_data, p_cb->user_data);
1115 bta_jv_pm_conn_idle(p_cb->p_pm_cb);
1118 case GAP_EVT_CONN_CONGESTED:
1119 case GAP_EVT_CONN_UNCONGESTED:
1120 p_cb->cong = (event == GAP_EVT_CONN_CONGESTED) ? TRUE : FALSE;
1121 evt_data.l2c_cong.cong = p_cb->cong;
1122 p_cb->p_cback(BTA_JV_L2CAP_CONG_EVT, &evt_data, p_cb->user_data);
1130 /*******************************************************************************
1132 ** Function bta_jv_l2cap_connect
1134 ** Description makes an l2cap client connection
1138 *******************************************************************************/
1139 void bta_jv_l2cap_connect(tBTA_JV_MSG *p_data)
1141 tBTA_JV_L2C_CB *p_cb;
1142 tBTA_JV_L2CAP_CL_INIT evt_data;
1143 UINT16 handle = GAP_INVALID_HANDLE;
1145 tL2CAP_CFG_INFO cfg;
1146 tBTA_JV_API_L2CAP_CONNECT *cc = &(p_data->l2cap_connect);
1147 UINT8 chan_mode_mask = GAP_FCR_CHAN_OPT_BASIC;
1148 tL2CAP_ERTM_INFO *ertm_info = NULL;
1150 memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
1152 if (cc->has_cfg == TRUE) {
1154 if (cfg.fcr_present && cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) {
1155 chan_mode_mask = GAP_FCR_CHAN_OPT_ERTM;
1159 if (cc->has_ertm_info == TRUE) {
1160 ertm_info = &(cc->ertm_info);
1163 /* We need to use this value for MTU to be able to handle cases where cfg is not set in req. */
1164 cfg.mtu_present = TRUE;
1165 cfg.mtu = cc->rx_mtu;
1167 /* TODO: DM role manager
1168 L2CA_SetDesireRole(cc->role);
1171 sec_id = bta_jv_alloc_sec_id();
1172 evt_data.sec_id = sec_id;
1173 evt_data.status = BTA_JV_FAILURE;
1176 if (bta_jv_check_psm(cc->remote_psm)) { /* allowed */
1177 if ((handle = GAP_ConnOpen("", sec_id, 0, cc->peer_bd_addr, cc->remote_psm,
1178 &cfg, ertm_info, cc->sec_mask, chan_mode_mask,
1179 bta_jv_l2cap_client_cback)) != GAP_INVALID_HANDLE ) {
1180 evt_data.status = BTA_JV_SUCCESS;
1185 if (evt_data.status == BTA_JV_SUCCESS) {
1186 p_cb = &bta_jv_cb.l2c_cb[handle];
1187 p_cb->handle = handle;
1188 p_cb->p_cback = cc->p_cback;
1189 p_cb->user_data = cc->user_data;
1190 p_cb->psm = 0; /* not a server */
1191 p_cb->sec_id = sec_id;
1192 p_cb->state = BTA_JV_ST_CL_OPENING;
1194 bta_jv_free_sec_id(&sec_id);
1197 evt_data.handle = handle;
1198 cc->p_cback(BTA_JV_L2CAP_CL_INIT_EVT, (tBTA_JV *)&evt_data, cc->user_data);
1202 /*******************************************************************************
1204 ** Function bta_jv_l2cap_close
1206 ** Description Close an L2CAP client connection
1210 *******************************************************************************/
1211 void bta_jv_l2cap_close(tBTA_JV_MSG *p_data)
1213 tBTA_JV_L2CAP_CLOSE evt_data;
1214 tBTA_JV_API_L2CAP_CLOSE *cc = &(p_data->l2cap_close);
1215 tBTA_JV_L2CAP_CBACK *p_cback = cc->p_cb->p_cback;
1216 void *user_data = cc->p_cb->user_data;
1218 evt_data.handle = cc->handle;
1219 evt_data.status = bta_jv_free_l2c_cb(cc->p_cb);
1220 evt_data.async = FALSE;
1223 p_cback(BTA_JV_L2CAP_CLOSE_EVT, (tBTA_JV *)&evt_data, user_data);
1227 /*******************************************************************************
1229 ** Function bta_jv_l2cap_server_cback
1231 ** Description handles the l2cap server callback
1235 *******************************************************************************/
1236 static void bta_jv_l2cap_server_cback(UINT16 gap_handle, UINT16 event)
1238 tBTA_JV_L2C_CB *p_cb = &bta_jv_cb.l2c_cb[gap_handle];
1240 tBTA_JV_L2CAP_CBACK *p_cback;
1243 if (gap_handle >= BTA_JV_MAX_L2C_CONN && !p_cb->p_cback) {
1247 APPL_TRACE_DEBUG( "%s: %d evt:x%x", __func__, gap_handle, event);
1248 evt_data.l2c_open.status = BTA_JV_SUCCESS;
1249 evt_data.l2c_open.handle = gap_handle;
1252 case GAP_EVT_CONN_OPENED:
1253 bdcpy(evt_data.l2c_open.rem_bda, GAP_ConnGetRemoteAddr(gap_handle));
1254 evt_data.l2c_open.tx_mtu = GAP_ConnGetRemMtuSize(gap_handle);
1255 p_cb->state = BTA_JV_ST_SR_OPEN;
1256 p_cb->p_cback(BTA_JV_L2CAP_OPEN_EVT, &evt_data, p_cb->user_data);
1259 case GAP_EVT_CONN_CLOSED:
1260 evt_data.l2c_close.async = TRUE;
1261 evt_data.l2c_close.handle = p_cb->handle;
1262 p_cback = p_cb->p_cback;
1263 user_data = p_cb->user_data;
1264 evt_data.l2c_close.status = bta_jv_free_l2c_cb(p_cb);
1265 p_cback(BTA_JV_L2CAP_CLOSE_EVT, &evt_data, user_data);
1268 case GAP_EVT_CONN_DATA_AVAIL:
1269 evt_data.data_ind.handle = gap_handle;
1270 /* Reset idle timer to avoid requesting sniff mode while receiving data */
1271 bta_jv_pm_conn_busy(p_cb->p_pm_cb);
1272 p_cb->p_cback(BTA_JV_L2CAP_DATA_IND_EVT, &evt_data, p_cb->user_data);
1273 bta_jv_pm_conn_idle(p_cb->p_pm_cb);
1276 case GAP_EVT_CONN_CONGESTED:
1277 case GAP_EVT_CONN_UNCONGESTED:
1278 p_cb->cong = (event == GAP_EVT_CONN_CONGESTED) ? TRUE : FALSE;
1279 evt_data.l2c_cong.cong = p_cb->cong;
1280 p_cb->p_cback(BTA_JV_L2CAP_CONG_EVT, &evt_data, p_cb->user_data);
1288 /*******************************************************************************
1290 ** Function bta_jv_l2cap_start_server
1292 ** Description starts an L2CAP server
1296 *******************************************************************************/
1297 void bta_jv_l2cap_start_server(tBTA_JV_MSG *p_data)
1299 tBTA_JV_L2C_CB *p_cb;
1302 tL2CAP_CFG_INFO cfg;
1303 tBTA_JV_L2CAP_START evt_data;
1304 tBTA_JV_API_L2CAP_SERVER *ls = &(p_data->l2cap_server);
1305 // INT32 use_etm = FALSE;
1306 UINT8 chan_mode_mask = GAP_FCR_CHAN_OPT_BASIC;
1307 tL2CAP_ERTM_INFO *ertm_info = NULL;
1309 memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
1311 if (ls->has_cfg == TRUE) {
1313 if (cfg.fcr_present && cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) {
1314 chan_mode_mask = GAP_FCR_CHAN_OPT_ERTM;
1318 if (ls->has_ertm_info == TRUE) {
1319 ertm_info = &(ls->ertm_info);
1322 //FIX: MTU=0 means not present
1323 if (ls->rx_mtu > 0) {
1324 cfg.mtu_present = TRUE;
1325 cfg.mtu = ls->rx_mtu;
1327 cfg.mtu_present = FALSE;
1331 /* TODO DM role manager
1332 L2CA_SetDesireRole(ls->role);
1335 sec_id = bta_jv_alloc_sec_id();
1336 if (0 == sec_id || (FALSE == bta_jv_check_psm(ls->local_psm)) ||
1337 (handle = GAP_ConnOpen("JV L2CAP", sec_id, 1, 0, ls->local_psm, &cfg, ertm_info,
1338 ls->sec_mask, chan_mode_mask, bta_jv_l2cap_server_cback)) == GAP_INVALID_HANDLE) {
1339 bta_jv_free_sec_id(&sec_id);
1340 evt_data.status = BTA_JV_FAILURE;
1342 p_cb = &bta_jv_cb.l2c_cb[handle];
1343 evt_data.status = BTA_JV_SUCCESS;
1344 evt_data.handle = handle;
1345 evt_data.sec_id = sec_id;
1346 p_cb->p_cback = ls->p_cback;
1347 p_cb->user_data = ls->user_data;
1348 p_cb->handle = handle;
1349 p_cb->sec_id = sec_id;
1350 p_cb->state = BTA_JV_ST_SR_LISTEN;
1351 p_cb->psm = ls->local_psm;
1354 ls->p_cback(BTA_JV_L2CAP_START_EVT, (tBTA_JV *)&evt_data, ls->user_data);
1357 /*******************************************************************************
1359 ** Function bta_jv_l2cap_stop_server
1361 ** Description stops an L2CAP server
1365 *******************************************************************************/
1366 void bta_jv_l2cap_stop_server(tBTA_JV_MSG *p_data)
1368 tBTA_JV_L2C_CB *p_cb;
1369 tBTA_JV_L2CAP_CLOSE evt_data;
1370 tBTA_JV_API_L2CAP_SERVER *ls = &(p_data->l2cap_server);
1371 tBTA_JV_L2CAP_CBACK *p_cback;
1373 for (int i = 0; i < BTA_JV_MAX_L2C_CONN; i++) {
1374 if (bta_jv_cb.l2c_cb[i].psm == ls->local_psm) {
1375 p_cb = &bta_jv_cb.l2c_cb[i];
1376 p_cback = p_cb->p_cback;
1377 user_data = p_cb->user_data;
1378 evt_data.handle = p_cb->handle;
1379 evt_data.status = bta_jv_free_l2c_cb(p_cb);
1380 evt_data.async = FALSE;
1381 p_cback(BTA_JV_L2CAP_CLOSE_EVT, (tBTA_JV *)&evt_data, user_data);
1389 /*******************************************************************************
1391 ** Function bta_jv_l2cap_read
1393 ** Description Read data from an L2CAP connection
1397 *******************************************************************************/
1398 void bta_jv_l2cap_read(tBTA_JV_MSG *p_data)
1400 tBTA_JV_L2CAP_READ evt_data;
1401 tBTA_JV_API_L2CAP_READ *rc = &(p_data->l2cap_read);
1403 evt_data.status = BTA_JV_FAILURE;
1404 evt_data.handle = rc->handle;
1405 evt_data.req_id = rc->req_id;
1406 evt_data.p_data = rc->p_data;
1409 if (BT_PASS == GAP_ConnReadData(rc->handle, rc->p_data, rc->len, &evt_data.len)) {
1410 evt_data.status = BTA_JV_SUCCESS;
1413 rc->p_cback(BTA_JV_L2CAP_READ_EVT, (tBTA_JV *)&evt_data, rc->user_data);
1417 /*******************************************************************************
1419 ** Function bta_jv_l2cap_write
1421 ** Description Write data to an L2CAP connection
1425 *******************************************************************************/
1426 void bta_jv_l2cap_write(tBTA_JV_MSG *p_data)
1428 tBTA_JV_L2CAP_WRITE evt_data;
1429 tBTA_JV_API_L2CAP_WRITE *ls = &(p_data->l2cap_write);
1431 /* As we check this callback exists before the tBTA_JV_API_L2CAP_WRITE can be send through the
1432 * API this check should not be needed.
1433 * But the API is not designed to be used (safely at least) in a multi-threaded scheduler, hence
1434 * if the peer device disconnects the l2cap link after the API is called, but before this
1435 * message is handled, the ->p_cback will be cleared at this point. At first glanch this seems
1436 * highly unlikely, but for all obex-profiles with two channels connected - e.g. MAP, this
1437 * happens around 1 of 4 disconnects, as a disconnect on the server channel causes a disconnect
1438 * to be send on the client (notification) channel, but at the peer typically disconnects both
1439 * the OBEX disconnect request crosses the incoming l2cap disconnect.
1440 * If p_cback is cleared, we simply discard the data.
1441 * RISK: The caller must handle any cleanup based on another signal than BTA_JV_L2CAP_WRITE_EVT,
1442 * which is typically not possible, as the pointer to the allocated buffer is stored
1443 * in this message, and can therefore not be freed, hence we have a mem-leak-by-design.*/
1444 if (ls->p_cb->p_cback != NULL) {
1445 evt_data.status = BTA_JV_FAILURE;
1446 evt_data.handle = ls->handle;
1447 evt_data.req_id = ls->req_id;
1448 evt_data.cong = ls->p_cb->cong;
1450 bta_jv_pm_conn_busy(ls->p_cb->p_pm_cb);
1451 if (!evt_data.cong &&
1452 BT_PASS == GAP_ConnWriteData(ls->handle, ls->p_data, ls->len, &evt_data.len)) {
1453 evt_data.status = BTA_JV_SUCCESS;
1455 ls->p_cb->p_cback(BTA_JV_L2CAP_WRITE_EVT, (tBTA_JV *)&evt_data, ls->user_data);
1456 bta_jv_set_pm_conn_state(ls->p_cb->p_pm_cb, BTA_JV_CONN_IDLE);
1458 /* As this pointer is checked in the API function, this occurs only when the channel is
1459 * disconnected after the API function is called, but before the message is handled. */
1460 APPL_TRACE_ERROR("%s() ls->p_cb->p_cback == NULL", __func__);
1464 /*******************************************************************************
1466 ** Function bta_jv_l2cap_write_fixed
1468 ** Description Write data to an L2CAP connection using Fixed channels
1472 *******************************************************************************/
1473 void bta_jv_l2cap_write_fixed(tBTA_JV_MSG *p_data)
1475 tBTA_JV_L2CAP_WRITE_FIXED evt_data;
1476 tBTA_JV_API_L2CAP_WRITE_FIXED *ls = &(p_data->l2cap_write_fixed);
1477 BT_HDR *msg = (BT_HDR *)osi_malloc(sizeof(BT_HDR) + ls->len + L2CAP_MIN_OFFSET);
1479 APPL_TRACE_ERROR("%s() could not allocate msg buffer", __func__);
1482 evt_data.status = BTA_JV_FAILURE;
1483 evt_data.channel = ls->channel;
1484 memcpy(evt_data.addr, ls->addr, sizeof(evt_data.addr));
1485 evt_data.req_id = ls->req_id;
1489 memcpy(((uint8_t *)(msg + 1)) + L2CAP_MIN_OFFSET, ls->p_data, ls->len);
1491 msg->offset = L2CAP_MIN_OFFSET;
1493 L2CA_SendFixedChnlData(ls->channel, ls->addr, msg);
1495 ls->p_cback(BTA_JV_L2CAP_WRITE_FIXED_EVT, (tBTA_JV *)&evt_data, ls->user_data);
1498 /*******************************************************************************
1500 ** Function bta_jv_port_data_co_cback
1502 ** Description port data callback function of rfcomm
1507 *******************************************************************************/
1508 static int bta_jv_port_data_co_cback(UINT16 port_handle, UINT8 *buf, UINT16 len, int type)
1510 tBTA_JV_RFC_CB *p_cb = bta_jv_rfc_port_to_cb(port_handle);
1511 tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
1513 APPL_TRACE_DEBUG("%s, p_cb:%p, p_pcb:%p, len:%d, type:%d", __func__, p_cb, p_pcb, len, type);
1514 if (p_pcb != NULL) {
1516 case DATA_CO_CALLBACK_TYPE_INCOMING:
1517 bta_jv_pm_conn_busy(p_pcb->p_pm_cb);
1518 ret = bta_co_rfc_data_incoming(p_pcb->user_data, (BT_HDR *)buf);
1519 bta_jv_pm_conn_idle(p_pcb->p_pm_cb);
1521 case DATA_CO_CALLBACK_TYPE_OUTGOING_SIZE:
1522 return bta_co_rfc_data_outgoing_size(p_pcb->user_data, (int *)buf);
1523 case DATA_CO_CALLBACK_TYPE_OUTGOING:
1524 return bta_co_rfc_data_outgoing(p_pcb->user_data, buf, len);
1526 APPL_TRACE_ERROR("unknown callout type:%d", type);
1533 /*******************************************************************************
1535 ** Function bta_jv_port_mgmt_cl_cback
1537 ** Description callback for port mamangement function of rfcomm
1538 ** client connections
1542 *******************************************************************************/
1543 static void bta_jv_port_mgmt_cl_cback(UINT32 code, UINT16 port_handle)
1545 tBTA_JV_RFC_CB *p_cb = bta_jv_rfc_port_to_cb(port_handle);
1546 tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
1550 tBTA_JV_RFCOMM_CBACK *p_cback; /* the callback function */
1552 APPL_TRACE_DEBUG( "bta_jv_port_mgmt_cl_cback:code:%d, port_handle%d", code, port_handle);
1553 if (NULL == p_cb || NULL == p_cb->p_cback) {
1557 APPL_TRACE_DEBUG( "bta_jv_port_mgmt_cl_cback code=%d port_handle:%d handle:%d",
1558 code, port_handle, p_cb->handle);
1560 PORT_CheckConnection(port_handle, rem_bda, &lcid);
1562 if (code == PORT_SUCCESS) {
1563 evt_data.rfc_open.handle = p_pcb->handle;
1564 evt_data.rfc_open.status = BTA_JV_SUCCESS;
1565 bdcpy(evt_data.rfc_open.rem_bda, rem_bda);
1566 p_pcb->state = BTA_JV_ST_CL_OPEN;
1567 p_cb->p_cback(BTA_JV_RFCOMM_OPEN_EVT, &evt_data, p_pcb->user_data);
1569 evt_data.rfc_close.handle = p_pcb->handle;
1570 evt_data.rfc_close.status = BTA_JV_FAILURE;
1571 evt_data.rfc_close.port_status = code;
1572 evt_data.rfc_close.async = TRUE;
1573 if (p_pcb->state == BTA_JV_ST_CL_CLOSING) {
1574 evt_data.rfc_close.async = FALSE;
1576 //p_pcb->state = BTA_JV_ST_NONE;
1577 //p_pcb->cong = FALSE;
1578 p_cback = p_cb->p_cback;
1579 p_cback(BTA_JV_RFCOMM_CLOSE_EVT, &evt_data, p_pcb->user_data);
1580 //bta_jv_free_rfc_cb(p_cb, p_pcb);
1585 /*******************************************************************************
1587 ** Function bta_jv_port_event_cl_cback
1589 ** Description Callback for RFCOMM client port events
1593 *******************************************************************************/
1594 static void bta_jv_port_event_cl_cback(UINT32 code, UINT16 port_handle)
1596 tBTA_JV_RFC_CB *p_cb = bta_jv_rfc_port_to_cb(port_handle);
1597 tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
1600 APPL_TRACE_DEBUG( "bta_jv_port_event_cl_cback:%d", port_handle);
1601 if (NULL == p_cb || NULL == p_cb->p_cback) {
1605 APPL_TRACE_DEBUG( "bta_jv_port_event_cl_cback code=x%x port_handle:%d handle:%d",
1606 code, port_handle, p_cb->handle);
1607 if (code & PORT_EV_RXCHAR) {
1608 evt_data.data_ind.handle = p_pcb->handle;
1609 p_cb->p_cback(BTA_JV_RFCOMM_DATA_IND_EVT, &evt_data, p_pcb->user_data);
1612 if (code & PORT_EV_FC) {
1613 p_pcb->cong = (code & PORT_EV_FCS) ? FALSE : TRUE;
1614 evt_data.rfc_cong.cong = p_pcb->cong;
1615 evt_data.rfc_cong.handle = p_pcb->handle;
1616 evt_data.rfc_cong.status = BTA_JV_SUCCESS;
1617 p_cb->p_cback(BTA_JV_RFCOMM_CONG_EVT, &evt_data, p_pcb->user_data);
1620 if (code & PORT_EV_TXEMPTY) {
1621 bta_jv_pm_conn_idle(p_pcb->p_pm_cb);
1625 /*******************************************************************************
1627 ** Function bta_jv_rfcomm_connect
1629 ** Description Client initiates an RFCOMM connection
1633 *******************************************************************************/
1634 void bta_jv_rfcomm_connect(tBTA_JV_MSG *p_data)
1637 UINT32 event_mask = BTA_JV_RFC_EV_MASK;
1638 tPORT_STATE port_state;
1640 tBTA_JV_RFC_CB *p_cb = NULL;
1642 tBTA_JV_API_RFCOMM_CONNECT *cc = &(p_data->rfcomm_connect);
1643 tBTA_JV_RFCOMM_CL_INIT evt_data = {0};
1645 /* TODO DM role manager
1646 L2CA_SetDesireRole(cc->role);
1649 sec_id = bta_jv_alloc_sec_id();
1650 evt_data.sec_id = sec_id;
1651 evt_data.status = BTA_JV_SUCCESS;
1653 BTM_SetSecurityLevel(TRUE, "", sec_id, cc->sec_mask, BT_PSM_RFCOMM,
1654 BTM_SEC_PROTO_RFCOMM, cc->remote_scn) == FALSE) {
1655 evt_data.status = BTA_JV_FAILURE;
1656 APPL_TRACE_ERROR("sec_id:%d is zero or BTM_SetSecurityLevel failed, remote_scn:%d", sec_id, cc->remote_scn);
1659 if (evt_data.status == BTA_JV_SUCCESS &&
1660 RFCOMM_CreateConnection(UUID_SERVCLASS_SERIAL_PORT, cc->remote_scn, FALSE,
1661 BTA_JV_DEF_RFC_MTU, cc->peer_bd_addr, &handle, bta_jv_port_mgmt_cl_cback) != PORT_SUCCESS) {
1662 APPL_TRACE_ERROR("bta_jv_rfcomm_connect, RFCOMM_CreateConnection failed");
1663 evt_data.status = BTA_JV_FAILURE;
1665 if (evt_data.status == BTA_JV_SUCCESS) {
1666 p_cb = bta_jv_alloc_rfc_cb(handle, &p_pcb);
1668 p_cb->p_cback = cc->p_cback;
1669 p_cb->sec_id = sec_id;
1671 p_pcb->state = BTA_JV_ST_CL_OPENING;
1672 p_pcb->user_data = cc->user_data;
1673 evt_data.use_co = TRUE;
1675 PORT_SetEventCallback(handle, bta_jv_port_event_cl_cback);
1676 PORT_SetEventMask(handle, event_mask);
1677 PORT_SetDataCOCallback (handle, bta_jv_port_data_co_cback);
1679 PORT_GetState(handle, &port_state);
1681 port_state.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT);
1683 /* coverity[uninit_use_in_call]
1684 FALSE-POSITIVE: port_state is initialized at PORT_GetState() */
1685 PORT_SetState(handle, &port_state);
1687 evt_data.handle = p_pcb->handle;
1689 evt_data.status = BTA_JV_FAILURE;
1690 APPL_TRACE_ERROR("run out of rfc control block");
1693 cc->p_cback(BTA_JV_RFCOMM_CL_INIT_EVT, (tBTA_JV *)&evt_data, cc->user_data);
1694 if (evt_data.status == BTA_JV_FAILURE) {
1696 bta_jv_free_sec_id(&sec_id);
1699 RFCOMM_RemoveConnection(handle);
1704 static int find_rfc_pcb(void *user_data, tBTA_JV_RFC_CB **cb, tBTA_JV_PCB **pcb)
1709 for (i = 0; i < MAX_RFC_PORTS; i++) {
1710 UINT32 rfc_handle = bta_jv_cb.port_cb[i].handle & BTA_JV_RFC_HDL_MASK;
1711 rfc_handle &= ~BTA_JV_RFCOMM_MASK;
1712 if (rfc_handle && bta_jv_cb.port_cb[i].user_data == user_data) {
1713 *pcb = &bta_jv_cb.port_cb[i];
1714 *cb = &bta_jv_cb.rfc_cb[rfc_handle - 1];
1715 APPL_TRACE_DEBUG("find_rfc_pcb(): FOUND rfc_cb_handle 0x%x, port.jv_handle:"
1716 " 0x%x, state: %d, rfc_cb->handle: 0x%x", rfc_handle, (*pcb)->handle,
1717 (*pcb)->state, (*cb)->handle);
1721 APPL_TRACE_DEBUG("find_rfc_pcb: cannot find rfc_cb from user data:%d", (UINT32)user_data);
1725 /*******************************************************************************
1727 ** Function bta_jv_rfcomm_close
1729 ** Description Close an RFCOMM connection
1733 *******************************************************************************/
1734 void bta_jv_rfcomm_close(tBTA_JV_MSG *p_data)
1736 tBTA_JV_API_RFCOMM_CLOSE *cc = &(p_data->rfcomm_close);
1737 tBTA_JV_RFC_CB *p_cb = NULL;
1738 tBTA_JV_PCB *p_pcb = NULL;
1739 APPL_TRACE_DEBUG("bta_jv_rfcomm_close, rfc handle:%d", cc->handle);
1741 APPL_TRACE_ERROR("bta_jv_rfcomm_close, rfc handle is null");
1745 void *user_data = cc->user_data;
1746 if (!find_rfc_pcb(user_data, &p_cb, &p_pcb)) {
1749 bta_jv_free_rfc_cb(p_cb, p_pcb);
1750 APPL_TRACE_DEBUG("bta_jv_rfcomm_close: sec id in use:%d, rfc_cb in use:%d",
1751 get_sec_id_used(), get_rfc_cb_used());
1754 /*******************************************************************************
1756 ** Function bta_jv_get_num_rfc_listen
1758 ** Description when a RFCOMM connection goes down, make sure that there's only
1759 ** one port stays listening on this scn.
1763 *******************************************************************************/
1764 static UINT8 __attribute__((unused)) bta_jv_get_num_rfc_listen(tBTA_JV_RFC_CB *p_cb)
1768 if (p_cb->max_sess > 1) {
1770 for (UINT8 i = 0; i < p_cb->max_sess; i++) {
1771 if (p_cb->rfc_hdl[i] != 0) {
1772 const tBTA_JV_PCB *p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[i] - 1];
1773 if (BTA_JV_ST_SR_LISTEN == p_pcb->state) {
1782 /*******************************************************************************
1784 ** Function bta_jv_port_mgmt_sr_cback
1786 ** Description callback for port mamangement function of rfcomm
1787 ** server connections
1791 *******************************************************************************/
1792 static void bta_jv_port_mgmt_sr_cback(UINT32 code, UINT16 port_handle)
1794 tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
1795 tBTA_JV_RFC_CB *p_cb = bta_jv_rfc_port_to_cb(port_handle);
1799 // APPL_TRACE_DEBUG("bta_jv_port_mgmt_sr_cback, code:0x%x, port_handle:%d", code, (uint16_t)port_handle);
1800 if (NULL == p_cb || NULL == p_cb->p_cback) {
1801 // APPL_TRACE_ERROR("bta_jv_port_mgmt_sr_cback, p_cb:%p, p_cb->p_cback%p",
1802 // p_cb, p_cb ? p_cb->p_cback : NULL);
1805 void *user_data = p_pcb->user_data;
1806 // APPL_TRACE_DEBUG( "bta_jv_port_mgmt_sr_cback code=%p port_handle:0x%x handle:0x%x, p_pcb:%p, user:%p",
1807 // code, port_handle, p_cb->handle, p_pcb, p_pcb->user_data);
1809 PORT_CheckConnection(port_handle, rem_bda, &lcid);
1811 if (code == PORT_SUCCESS) {
1812 evt_data.rfc_srv_open.handle = p_pcb->handle;
1813 evt_data.rfc_srv_open.status = BTA_JV_SUCCESS;
1814 bdcpy(evt_data.rfc_srv_open.rem_bda, rem_bda);
1815 tBTA_JV_PCB *p_pcb_new_listen = bta_jv_add_rfc_port(p_cb, p_pcb);
1816 if (p_pcb_new_listen) {
1817 evt_data.rfc_srv_open.new_listen_handle = p_pcb_new_listen->handle;
1818 p_pcb_new_listen->user_data = p_cb->p_cback(BTA_JV_RFCOMM_SRV_OPEN_EVT, &evt_data, user_data);
1819 APPL_TRACE_DEBUG("PORT_SUCCESS: curr_sess:%d, max_sess:%d", p_cb->curr_sess, p_cb->max_sess);
1822 APPL_TRACE_ERROR("bta_jv_add_rfc_port failed to create new listen port");
1826 evt_data.rfc_close.handle = p_pcb->handle;
1827 evt_data.rfc_close.status = BTA_JV_FAILURE;
1828 evt_data.rfc_close.async = TRUE;
1829 evt_data.rfc_close.port_status = code;
1830 p_pcb->cong = FALSE;
1832 tBTA_JV_RFCOMM_CBACK *p_cback = p_cb->p_cback;
1833 APPL_TRACE_DEBUG("PORT_CLOSED before BTA_JV_RFCOMM_CLOSE_EVT: curr_sess:%d, max_sess:%d",
1834 p_cb->curr_sess, p_cb->max_sess);
1835 if (BTA_JV_ST_SR_CLOSING == p_pcb->state) {
1836 evt_data.rfc_close.async = FALSE;
1837 evt_data.rfc_close.status = BTA_JV_SUCCESS;
1839 //p_pcb->state = BTA_JV_ST_NONE;
1840 p_cback(BTA_JV_RFCOMM_CLOSE_EVT, &evt_data, user_data);
1841 //bta_jv_free_rfc_cb(p_cb, p_pcb);
1843 APPL_TRACE_DEBUG("PORT_CLOSED after BTA_JV_RFCOMM_CLOSE_EVT: curr_sess:%d, max_sess:%d",
1844 p_cb->curr_sess, p_cb->max_sess);
1848 /*******************************************************************************
1850 ** Function bta_jv_port_event_sr_cback
1852 ** Description Callback for RFCOMM server port events
1856 *******************************************************************************/
1857 static void bta_jv_port_event_sr_cback(UINT32 code, UINT16 port_handle)
1859 tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
1860 tBTA_JV_RFC_CB *p_cb = bta_jv_rfc_port_to_cb(port_handle);
1863 if (NULL == p_cb || NULL == p_cb->p_cback) {
1867 APPL_TRACE_DEBUG( "bta_jv_port_event_sr_cback code=x%x port_handle:%d handle:%d",
1868 code, port_handle, p_cb->handle);
1870 void *user_data = p_pcb->user_data;
1871 if (code & PORT_EV_RXCHAR) {
1872 evt_data.data_ind.handle = p_pcb->handle;
1873 p_cb->p_cback(BTA_JV_RFCOMM_DATA_IND_EVT, &evt_data, user_data);
1876 if (code & PORT_EV_FC) {
1877 p_pcb->cong = (code & PORT_EV_FCS) ? FALSE : TRUE;
1878 evt_data.rfc_cong.cong = p_pcb->cong;
1879 evt_data.rfc_cong.handle = p_pcb->handle;
1880 evt_data.rfc_cong.status = BTA_JV_SUCCESS;
1881 p_cb->p_cback(BTA_JV_RFCOMM_CONG_EVT, &evt_data, user_data);
1884 if (code & PORT_EV_TXEMPTY) {
1885 bta_jv_pm_conn_idle(p_pcb->p_pm_cb);
1889 /*******************************************************************************
1891 ** Function bta_jv_add_rfc_port
1893 ** Description add a port for server when the existing posts is open
1895 ** Returns return a pointer to tBTA_JV_PCB just added
1897 *******************************************************************************/
1898 static tBTA_JV_PCB *bta_jv_add_rfc_port(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pcb_open)
1900 UINT8 used = 0, i, listen = 0;
1902 tPORT_STATE port_state;
1903 UINT32 event_mask = BTA_JV_RFC_EV_MASK;
1904 tBTA_JV_PCB *p_pcb = NULL;
1905 if (p_cb->max_sess > 1) {
1906 for (i = 0; i < p_cb->max_sess; i++) {
1907 if (p_cb->rfc_hdl[i] != 0) {
1908 p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[i] - 1];
1909 if (p_pcb->state == BTA_JV_ST_SR_LISTEN) {
1911 if (p_pcb_open == p_pcb) {
1912 APPL_TRACE_DEBUG("bta_jv_add_rfc_port, port_handle:%d, change the listen port to open state",
1913 p_pcb->port_handle);
1914 p_pcb->state = BTA_JV_ST_SR_OPEN;
1917 APPL_TRACE_ERROR("bta_jv_add_rfc_port, open pcb not matching listen one,"
1918 "listen count:%d, listen pcb handle:%d, open pcb:%d",
1919 listen, p_pcb->port_handle, p_pcb_open->handle);
1924 } else if (si == 0) {
1929 APPL_TRACE_DEBUG("bta_jv_add_rfc_port max_sess=%d used:%d curr_sess:%d, listen:%d si:%d",
1930 p_cb->max_sess, used, p_cb->curr_sess, listen, si);
1931 if (used < p_cb->max_sess && listen == 1 && si) {
1933 if (RFCOMM_CreateConnection(p_cb->sec_id, p_cb->scn, TRUE,
1934 BTA_JV_DEF_RFC_MTU, (UINT8 *) bd_addr_any, &(p_cb->rfc_hdl[si]), bta_jv_port_mgmt_sr_cback) == PORT_SUCCESS) {
1936 p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[si] - 1];
1937 p_pcb->state = BTA_JV_ST_SR_LISTEN;
1938 p_pcb->port_handle = p_cb->rfc_hdl[si];
1939 p_pcb->user_data = p_pcb_open->user_data;
1941 PORT_ClearKeepHandleFlag(p_pcb->port_handle);
1942 PORT_SetEventCallback(p_pcb->port_handle, bta_jv_port_event_sr_cback);
1943 PORT_SetDataCOCallback (p_pcb->port_handle, bta_jv_port_data_co_cback);
1944 PORT_SetEventMask(p_pcb->port_handle, event_mask);
1945 PORT_GetState(p_pcb->port_handle, &port_state);
1947 port_state.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT);
1949 PORT_SetState(p_pcb->port_handle, &port_state);
1950 p_pcb->handle = BTA_JV_RFC_H_S_TO_HDL(p_cb->handle, si);
1951 APPL_TRACE_DEBUG("bta_jv_add_rfc_port: p_pcb->handle:0x%x, curr_sess:%d",
1952 p_pcb->handle, p_cb->curr_sess);
1955 APPL_TRACE_ERROR("bta_jv_add_rfc_port, cannot create new rfc listen port");
1958 APPL_TRACE_DEBUG("bta_jv_add_rfc_port: sec id in use:%d, rfc_cb in use:%d",
1959 get_sec_id_used(), get_rfc_cb_used());
1963 /*******************************************************************************
1965 ** Function bta_jv_rfcomm_start_server
1967 ** Description waits for an RFCOMM client to connect
1972 *******************************************************************************/
1973 void bta_jv_rfcomm_start_server(tBTA_JV_MSG *p_data)
1976 UINT32 event_mask = BTA_JV_RFC_EV_MASK;
1977 tPORT_STATE port_state;
1979 tBTA_JV_RFC_CB *p_cb = NULL;
1981 tBTA_JV_API_RFCOMM_SERVER *rs = &(p_data->rfcomm_server);
1982 tBTA_JV_RFCOMM_START evt_data = {0};
1983 /* TODO DM role manager
1984 L2CA_SetDesireRole(rs->role);
1986 evt_data.status = BTA_JV_FAILURE;
1987 APPL_TRACE_DEBUG("bta_jv_rfcomm_start_server: sec id in use:%d, rfc_cb in use:%d",
1988 get_sec_id_used(), get_rfc_cb_used());
1991 sec_id = bta_jv_alloc_sec_id();
1994 BTM_SetSecurityLevel(FALSE, "JV PORT", sec_id, rs->sec_mask,
1995 BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, rs->local_scn) == FALSE) {
1996 APPL_TRACE_ERROR("bta_jv_rfcomm_start_server, run out of sec_id");
2000 if (RFCOMM_CreateConnection(sec_id, rs->local_scn, TRUE,
2001 BTA_JV_DEF_RFC_MTU, (UINT8 *) bd_addr_any, &handle, bta_jv_port_mgmt_sr_cback) != PORT_SUCCESS) {
2002 APPL_TRACE_ERROR("bta_jv_rfcomm_start_server, RFCOMM_CreateConnection failed");
2007 p_cb = bta_jv_alloc_rfc_cb(handle, &p_pcb);
2009 APPL_TRACE_ERROR("bta_jv_rfcomm_start_server, run out of rfc control block");
2013 p_cb->max_sess = rs->max_session;
2014 p_cb->p_cback = rs->p_cback;
2015 p_cb->sec_id = sec_id;
2016 p_cb->scn = rs->local_scn;
2017 p_pcb->state = BTA_JV_ST_SR_LISTEN;
2018 p_pcb->user_data = rs->user_data;
2019 evt_data.status = BTA_JV_SUCCESS;
2020 evt_data.handle = p_pcb->handle;
2021 evt_data.sec_id = sec_id;
2022 evt_data.use_co = TRUE;
2024 PORT_ClearKeepHandleFlag(handle);
2025 PORT_SetEventCallback(handle, bta_jv_port_event_sr_cback);
2026 PORT_SetEventMask(handle, event_mask);
2027 PORT_GetState(handle, &port_state);
2029 port_state.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT);
2031 PORT_SetState(handle, &port_state);
2034 rs->p_cback(BTA_JV_RFCOMM_START_EVT, (tBTA_JV *)&evt_data, rs->user_data);
2035 if (evt_data.status == BTA_JV_SUCCESS) {
2036 PORT_SetDataCOCallback (handle, bta_jv_port_data_co_cback);
2039 bta_jv_free_sec_id(&sec_id);
2042 RFCOMM_RemoveConnection(handle);
2047 /*******************************************************************************
2049 ** Function bta_jv_rfcomm_stop_server
2051 ** Description stops an RFCOMM server
2055 *******************************************************************************/
2057 void bta_jv_rfcomm_stop_server(tBTA_JV_MSG *p_data)
2059 tBTA_JV_API_RFCOMM_SERVER *ls = &(p_data->rfcomm_server);
2060 tBTA_JV_RFC_CB *p_cb = NULL;
2061 tBTA_JV_PCB *p_pcb = NULL;
2062 APPL_TRACE_DEBUG("bta_jv_rfcomm_stop_server");
2064 APPL_TRACE_ERROR("bta_jv_rfcomm_stop_server, jv handle is null");
2067 void *user_data = ls->user_data;
2068 if (!find_rfc_pcb(user_data, &p_cb, &p_pcb)) {
2071 APPL_TRACE_DEBUG("bta_jv_rfcomm_stop_server: p_pcb:%p, p_pcb->port_handle:%d",
2072 p_pcb, p_pcb->port_handle);
2073 bta_jv_free_rfc_cb(p_cb, p_pcb);
2074 APPL_TRACE_DEBUG("bta_jv_rfcomm_stop_server: sec id in use:%d, rfc_cb in use:%d",
2075 get_sec_id_used(), get_rfc_cb_used());
2078 /*******************************************************************************
2080 ** Function bta_jv_rfcomm_read
2082 ** Description Read data from an RFCOMM connection
2086 *******************************************************************************/
2087 void bta_jv_rfcomm_read(tBTA_JV_MSG *p_data)
2089 tBTA_JV_API_RFCOMM_READ *rc = &(p_data->rfcomm_read);
2090 tBTA_JV_RFC_CB *p_cb = rc->p_cb;
2091 tBTA_JV_PCB *p_pcb = rc->p_pcb;
2092 tBTA_JV_RFCOMM_READ evt_data;
2094 evt_data.status = BTA_JV_FAILURE;
2095 evt_data.handle = p_pcb->handle;
2096 evt_data.req_id = rc->req_id;
2097 evt_data.p_data = rc->p_data;
2098 if (PORT_ReadData(rc->p_pcb->port_handle, (char *)rc->p_data, rc->len, &evt_data.len) ==
2100 evt_data.status = BTA_JV_SUCCESS;
2103 p_cb->p_cback(BTA_JV_RFCOMM_READ_EVT, (tBTA_JV *)&evt_data, p_pcb->user_data);
2106 /*******************************************************************************
2108 ** Function bta_jv_rfcomm_write
2110 ** Description write data to an RFCOMM connection
2114 *******************************************************************************/
2115 void bta_jv_rfcomm_write(tBTA_JV_MSG *p_data)
2117 tBTA_JV_API_RFCOMM_WRITE *wc = &(p_data->rfcomm_write);
2118 tBTA_JV_RFC_CB *p_cb = wc->p_cb;
2119 tBTA_JV_PCB *p_pcb = wc->p_pcb;
2120 tBTA_JV_RFCOMM_WRITE evt_data;
2122 evt_data.status = BTA_JV_FAILURE;
2123 evt_data.handle = p_pcb->handle;
2124 evt_data.req_id = wc->req_id;
2125 evt_data.cong = p_pcb->cong;
2126 bta_jv_pm_conn_busy(p_pcb->p_pm_cb);
2127 evt_data.len = wc->len;
2128 if (!evt_data.cong &&
2129 PORT_WriteDataCO(p_pcb->port_handle, &evt_data.len, wc->len, wc->p_data) ==
2131 evt_data.status = BTA_JV_SUCCESS;
2133 // update congestion flag
2134 evt_data.cong = p_pcb->cong;
2135 if (p_cb->p_cback) {
2136 p_cb->p_cback(BTA_JV_RFCOMM_WRITE_EVT, (tBTA_JV *)&evt_data, p_pcb->user_data);
2138 APPL_TRACE_ERROR("bta_jv_rfcomm_write :: WARNING ! No JV callback set");
2143 /*******************************************************************************
2145 ** Function bta_jv_set_pm_profile
2147 ** Description Set or free power mode profile for a JV application
2151 *******************************************************************************/
2152 void bta_jv_set_pm_profile(tBTA_JV_MSG *p_data)
2154 tBTA_JV_STATUS status;
2155 tBTA_JV_PM_CB *p_cb;
2157 APPL_TRACE_API("bta_jv_set_pm_profile(handle: 0x%x, app_id: %d, init_st: %d)",
2158 p_data->set_pm.handle, p_data->set_pm.app_id, p_data->set_pm.init_st);
2160 /* clear PM control block */
2161 if (p_data->set_pm.app_id == BTA_JV_PM_ID_CLEAR) {
2162 status = bta_jv_free_set_pm_profile_cb(p_data->set_pm.handle);
2164 if (status != BTA_JV_SUCCESS) {
2165 APPL_TRACE_WARNING("bta_jv_set_pm_profile() free pm cb failed: reason %d",
2168 } else { /* set PM control block */
2169 p_cb = bta_jv_alloc_set_pm_profile_cb(p_data->set_pm.handle,
2170 p_data->set_pm.app_id);
2173 bta_jv_pm_state_change(p_cb, p_data->set_pm.init_st);
2175 APPL_TRACE_WARNING("bta_jv_alloc_set_pm_profile_cb() failed");
2180 /*******************************************************************************
2182 ** Function bta_jv_change_pm_state
2184 ** Description change jv pm connect state, used internally
2188 *******************************************************************************/
2189 void bta_jv_change_pm_state(tBTA_JV_MSG *p_data)
2191 tBTA_JV_API_PM_STATE_CHANGE *p_msg = (tBTA_JV_API_PM_STATE_CHANGE *)p_data;
2194 bta_jv_pm_state_change(p_msg->p_cb, p_msg->state);
2199 /*******************************************************************************
2201 ** Function bta_jv_set_pm_conn_state
2203 ** Description Send pm event state change to jv state machine to serialize jv pm changes
2204 ** in relation to other jv messages. internal API use mainly.
2206 ** Params: p_cb: jv pm control block, NULL pointer returns failure
2207 ** new_state: new PM connections state, setting is forced by action function
2209 ** Returns BTA_JV_SUCCESS, BTA_JV_FAILURE (buffer allocation, or NULL ptr!)
2211 *******************************************************************************/
2212 tBTA_JV_STATUS bta_jv_set_pm_conn_state(tBTA_JV_PM_CB *p_cb, const tBTA_JV_CONN_STATE
2215 tBTA_JV_STATUS status = BTA_JV_FAILURE;
2216 tBTA_JV_API_PM_STATE_CHANGE *p_msg;
2222 APPL_TRACE_API("bta_jv_set_pm_conn_state(handle:0x%x, state: %d)", p_cb->handle,
2224 if ((p_msg = (tBTA_JV_API_PM_STATE_CHANGE *)osi_malloc(
2225 sizeof(tBTA_JV_API_PM_STATE_CHANGE))) != NULL) {
2226 p_msg->hdr.event = BTA_JV_API_PM_STATE_CHANGE_EVT;
2228 p_msg->state = new_st;
2229 bta_sys_sendmsg(p_msg);
2230 status = BTA_JV_SUCCESS;
2235 /*******************************************************************************
2237 ** Function bta_jv_pm_conn_busy
2239 ** Description set pm connection busy state (input param safe)
2241 ** Params p_cb: pm control block of jv connection
2245 *******************************************************************************/
2246 static void bta_jv_pm_conn_busy(tBTA_JV_PM_CB *p_cb)
2248 if ((NULL != p_cb) && (BTA_JV_PM_IDLE_ST == p_cb->state)) {
2249 bta_jv_pm_state_change(p_cb, BTA_JV_CONN_BUSY);
2253 /*******************************************************************************
2255 ** Function bta_jv_pm_conn_busy
2257 ** Description set pm connection busy state (input param safe)
2259 ** Params p_cb: pm control block of jv connection
2263 *******************************************************************************/
2264 static void bta_jv_pm_conn_idle(tBTA_JV_PM_CB *p_cb)
2266 if ((NULL != p_cb) && (BTA_JV_PM_IDLE_ST != p_cb->state)) {
2267 bta_jv_pm_state_change(p_cb, BTA_JV_CONN_IDLE);
2271 /*******************************************************************************
2273 ** Function bta_jv_pm_state_change
2275 ** Description Notify power manager there is state change
2277 ** Params p_cb: must be NONE NULL
2281 *******************************************************************************/
2282 static void bta_jv_pm_state_change(tBTA_JV_PM_CB *p_cb, const tBTA_JV_CONN_STATE state)
2284 APPL_TRACE_API("bta_jv_pm_state_change(p_cb: 0x%x, handle: 0x%x, busy/idle_state: %d"
2285 ", app_id: %d, conn_state: %d)", (uint32_t)p_cb, p_cb->handle, p_cb->state,
2286 p_cb->app_id, state);
2289 case BTA_JV_CONN_OPEN:
2290 bta_sys_conn_open(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr);
2293 case BTA_JV_CONN_CLOSE:
2294 bta_sys_conn_close(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr);
2297 case BTA_JV_APP_OPEN:
2298 bta_sys_app_open(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr);
2301 case BTA_JV_APP_CLOSE:
2302 bta_sys_app_close(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr);
2305 case BTA_JV_SCO_OPEN:
2306 bta_sys_sco_open(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr);
2309 case BTA_JV_SCO_CLOSE:
2310 bta_sys_sco_close(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr);
2313 case BTA_JV_CONN_IDLE:
2314 p_cb->state = BTA_JV_PM_IDLE_ST;
2315 bta_sys_idle(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr);
2318 case BTA_JV_CONN_BUSY:
2319 p_cb->state = BTA_JV_PM_BUSY_ST;
2320 bta_sys_busy(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr);
2324 APPL_TRACE_WARNING("bta_jv_pm_state_change(state: %d): Invalid state", state);
2328 /**********************************************************************************************/
2331 static struct fc_channel *fcchan_get(uint16_t chan, char create)
2333 struct fc_channel *t = fc_channels;
2334 static tL2CAP_FIXED_CHNL_REG fcr = {
2335 .pL2CA_FixedConn_Cb = fcchan_conn_chng_cbk,
2336 .pL2CA_FixedData_Cb = fcchan_data_cbk,
2337 .default_idle_tout = 0xffff,
2338 .fixed_chnl_opts = {
2339 .mode = L2CAP_FCR_BASIC_MODE,
2340 .max_transmit = 0xFF,
2341 .rtrans_tout = 2000,
2348 while (t && t->chan != chan) {
2354 } else if (!create) {
2355 return NULL; /* we cannot alloc a struct if not asked to */
2358 t = osi_calloc(sizeof(*t));
2365 if (!L2CA_RegisterFixedChannel(chan, &fcr)) {
2371 t->next = fc_channels;
2377 /* pass NULL to find servers */
2378 static struct fc_client *fcclient_find_by_addr(struct fc_client *start, BD_ADDR addr)
2380 struct fc_client *t = start;
2384 /* match client if have addr */
2385 if (addr && !memcmp(addr, &t->remote_addr, sizeof(t->remote_addr))) {
2389 /* match server if do not have addr */
2390 if (!addr && t->server) {
2394 t = t->next_all_list;
2400 static struct fc_client *fcclient_find_by_id(uint32_t id)
2402 struct fc_client *t = fc_clients;
2404 while (t && t->id != id) {
2405 t = t->next_all_list;
2411 static struct fc_client *fcclient_alloc(uint16_t chan, char server, const uint8_t *sec_id_to_use)
2413 struct fc_channel *fc = fcchan_get(chan, TRUE);
2414 struct fc_client *t;
2421 if (fc->has_server && server) {
2422 return NULL; /* no way to have multiple servers on same channel */
2425 if (sec_id_to_use) {
2426 sec_id = *sec_id_to_use;
2428 sec_id = bta_jv_alloc_sec_id();
2431 t = osi_calloc(sizeof(*t));
2433 //allocate it a unique ID
2435 t->id = ++fc_next_id;
2436 } while (!t->id || fcclient_find_by_id(t->id));
2438 //populate some params
2445 //link it in to global list
2446 t->next_all_list = fc_clients;
2449 //link it in to channel list
2450 t->next_chan_list = fc->clients;
2453 //update channel if needed
2455 fc->has_server = TRUE;
2457 } else if (!sec_id_to_use) {
2458 bta_jv_free_sec_id(&sec_id);
2464 static void fcclient_free(struct fc_client *fc)
2466 struct fc_client *t = fc_clients;
2467 struct fc_channel *tc = fcchan_get(fc->chan, FALSE);
2469 //remove from global list
2470 while (t && t->next_all_list != fc) {
2471 t = t->next_all_list;
2474 if (!t && fc != fc_clients) {
2475 return; /* prevent double-free */
2479 t->next_all_list = fc->next_all_list;
2481 fc_clients = fc->next_all_list;
2484 //remove from channel list
2488 while (t && t->next_chan_list != fc) {
2489 t = t->next_chan_list;
2493 t->next_chan_list = fc->next_chan_list;
2495 tc->clients = fc->next_chan_list;
2498 //if was server then channel no longer has a server
2500 tc->has_server = FALSE;
2505 bta_jv_free_sec_id(&fc->sec_id);
2510 static void fcchan_conn_chng_cbk(UINT16 chan, BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason, tBT_TRANSPORT transport)
2514 struct fc_channel *tc;
2515 struct fc_client *t = NULL, *new_conn;
2516 tBTA_JV_L2CAP_CBACK *p_cback = NULL;
2517 char call_init = FALSE;
2518 void *user_data = NULL;
2521 tc = fcchan_get(chan, FALSE);
2523 t = fcclient_find_by_addr(tc->clients, bd_addr); // try to find an open socked for that addr
2525 p_cback = t->p_cback;
2526 user_data = t->user_data;
2528 t = fcclient_find_by_addr(tc->clients, NULL); // try to find a listening socked for that channel
2530 //found: create a normal connection socket and assign the connection to it
2531 new_conn = fcclient_alloc(chan, FALSE, &t->sec_id);
2534 memcpy(&new_conn->remote_addr, bd_addr, sizeof(new_conn->remote_addr));
2535 new_conn->p_cback = NULL; //for now
2536 new_conn->init_called = TRUE; /*nop need to do it again */
2538 p_cback = t->p_cback;
2539 user_data = t->user_data;
2552 if (!t->init_called) {
2555 t->init_called = TRUE;
2557 init_evt.l2c_cl_init.handle = t->id;
2558 init_evt.l2c_cl_init.status = BTA_JV_SUCCESS;
2559 init_evt.l2c_cl_init.sec_id = t->sec_id;
2562 open_evt.l2c_open.handle = t->id;
2563 open_evt.l2c_open.tx_mtu = 23; /* 23, why not ?*/
2564 memcpy(&open_evt.l2c_le_open.rem_bda, &t->remote_addr, sizeof(open_evt.l2c_le_open.rem_bda));
2565 open_evt.l2c_le_open.p_p_cback = (void **)&t->p_cback;
2566 open_evt.l2c_le_open.p_user_data = &t->user_data;
2567 open_evt.l2c_le_open.status = BTA_JV_SUCCESS;
2570 open_evt.l2c_open.status = BTA_JV_SUCCESS;
2573 open_evt.l2c_open.status = BTA_JV_FAILURE;
2578 p_cback(BTA_JV_L2CAP_CL_INIT_EVT, &init_evt, user_data);
2581 //call this with lock taken so socket does not disappear from under us */
2583 p_cback(BTA_JV_L2CAP_OPEN_EVT, &open_evt, user_data);
2584 if (!t->p_cback) { /* no callback set, means they do not want this one... */
2590 static void fcchan_data_cbk(UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf)
2593 // tBTA_JV evt_open;
2594 struct fc_channel *tc;
2595 struct fc_client *t = NULL;
2596 tBTA_JV_L2CAP_CBACK *sock_cback = NULL;
2597 void *sock_user_data;
2599 tc = fcchan_get(chan, FALSE);
2601 t = fcclient_find_by_addr(tc->clients, bd_addr); // try to find an open socked for that addr and channel
2603 //no socket -> drop it
2608 sock_cback = t->p_cback;
2609 sock_user_data = t->user_data;
2610 evt_data.le_data_ind.handle = t->id;
2611 evt_data.le_data_ind.p_buf = p_buf;
2614 sock_cback(BTA_JV_L2CAP_DATA_IND_EVT, &evt_data, sock_user_data);
2619 /*******************************************************************************
2621 ** Function bta_jv_l2cap_connect_le
2623 ** Description makes an le l2cap client connection
2627 *******************************************************************************/
2628 void bta_jv_l2cap_connect_le(tBTA_JV_MSG *p_data)
2630 tBTA_JV_API_L2CAP_CONNECT *cc = &(p_data->l2cap_connect);
2633 char call_init_f = TRUE;
2634 struct fc_client *t;
2636 evt.l2c_cl_init.handle = GAP_INVALID_HANDLE;
2637 evt.l2c_cl_init.status = BTA_JV_FAILURE;
2639 t = fcclient_alloc(cc->remote_chan, FALSE, NULL);
2641 cc->p_cback(BTA_JV_L2CAP_CL_INIT_EVT, &evt, cc->user_data);
2645 t->p_cback = cc->p_cback;
2646 t->user_data = cc->user_data;
2647 memcpy(&t->remote_addr, &cc->peer_bd_addr, sizeof(t->remote_addr));
2649 t->init_called = FALSE;
2651 if (L2CA_ConnectFixedChnl(t->chan, t->remote_addr, BLE_ADDR_UNKNOWN_TYPE)) {
2653 evt.l2c_cl_init.status = BTA_JV_SUCCESS;
2654 evt.l2c_cl_init.handle = id;
2657 //it could have been deleted/moved from under us, so re-find it */
2658 t = fcclient_find_by_id(id);
2660 if (evt.l2c_cl_init.status == BTA_JV_SUCCESS) {
2661 call_init_f = !t->init_called;
2667 cc->p_cback(BTA_JV_L2CAP_CL_INIT_EVT, &evt, cc->user_data);
2669 t->init_called = TRUE;
2673 /*******************************************************************************
2675 ** Function bta_jv_l2cap_stop_server_le
2677 ** Description stops an LE L2CAP server
2681 *******************************************************************************/
2682 void bta_jv_l2cap_stop_server_le(tBTA_JV_MSG *p_data)
2685 tBTA_JV_API_L2CAP_SERVER *ls = &(p_data->l2cap_server);
2686 tBTA_JV_L2CAP_CBACK *p_cback = NULL;
2687 struct fc_channel *fcchan;
2688 struct fc_client *fcclient;
2691 evt.l2c_close.status = BTA_JV_FAILURE;
2692 evt.l2c_close.async = FALSE;
2693 evt.l2c_close.handle = GAP_INVALID_HANDLE;
2695 fcchan = fcchan_get(ls->local_chan, FALSE);
2697 while ((fcclient = fcchan->clients)) {
2698 p_cback = fcclient->p_cback;
2699 user_data = fcclient->user_data;
2701 evt.l2c_close.handle = fcclient->id;
2702 evt.l2c_close.status = BTA_JV_SUCCESS;
2703 evt.l2c_close.async = FALSE;
2705 fcclient_free(fcclient);
2708 p_cback(BTA_JV_L2CAP_CLOSE_EVT, &evt, user_data);
2714 /*******************************************************************************
2716 ** Function bta_jv_l2cap_start_server_le
2718 ** Description starts an LE L2CAP server
2722 *******************************************************************************/
2723 void bta_jv_l2cap_start_server_le(tBTA_JV_MSG *p_data)
2725 tBTA_JV_API_L2CAP_SERVER *ss = &(p_data->l2cap_server);
2726 tBTA_JV_L2CAP_START evt_data;
2727 struct fc_client *t;
2730 evt_data.handle = GAP_INVALID_HANDLE;
2731 evt_data.status = BTA_JV_FAILURE;
2734 t = fcclient_alloc(ss->local_chan, TRUE, NULL);
2739 t->p_cback = ss->p_cback;
2740 t->user_data = ss->user_data;
2742 //if we got here, we're registered...
2743 evt_data.status = BTA_JV_SUCCESS;
2744 evt_data.handle = t->id;
2745 evt_data.sec_id = t->sec_id;
2748 ss->p_cback(BTA_JV_L2CAP_START_EVT, (tBTA_JV *)&evt_data, ss->user_data);
2751 /*******************************************************************************
2753 ** Function bta_jv_l2cap_close_fixed
2755 ** Description close a fixed channel connection. calls no callbacks. idempotent
2759 *******************************************************************************/
2760 extern void bta_jv_l2cap_close_fixed (tBTA_JV_MSG *p_data)
2762 tBTA_JV_API_L2CAP_CLOSE *cc = &(p_data->l2cap_close);
2763 struct fc_client *t;
2765 t = fcclient_find_by_id(cc->handle);
2772 #endif ///defined BTA_JV_INCLUDED && BTA_JV_INCLUDED == TRUE