1 /******************************************************************************
2 *
3 * Copyright (C) 2006-2012 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 /******************************************************************************
20 *
21 * This file contains action functions for BTA JV APIs.
22 *
23 ******************************************************************************/
24
25 #include <pthread.h>
26 #include <stdlib.h>
27
28 #include "osi/allocator.h"
29 #include "osi/osi.h"
30 #include "stack/bt_types.h"
31 #include "bta/utl.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"
38 #include "btm_int.h"
39 #include "stack/sdp_api.h"
40 #include "stack/l2c_api.h"
41 #include "stack/port_api.h"
42 #include <string.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"
48
49
50 #if (defined BTA_JV_INCLUDED && BTA_JV_INCLUDED == TRUE)
51 #if BTA_JV_L2CAP_INCLUDED
52 /* one of these exists for each client */
53 struct fc_client {
54 struct fc_client *next_all_list;
55 struct fc_client *next_chan_list;
56 BD_ADDR remote_addr;
57 uint32_t id;
58 tBTA_JV_L2CAP_CBACK *p_cback;
59 void *user_data;
60 uint16_t handle;
61 uint16_t chan;
62 uint8_t sec_id;
63 unsigned server : 1;
64 unsigned init_called : 1;
65 };
66
67 /* one of these exists for each channel we're dealing with */
68 struct fc_channel {
69 struct fc_channel *next;
70 struct fc_client *clients;
71 uint8_t has_server : 1;
72 uint16_t chan;
73 };
74
75
76 static struct fc_client *fc_clients;
77 static struct fc_channel *fc_channels;
78 static uint32_t fc_next_id;
79 static pthread_once_t fc_init_once = PTHREAD_ONCE_INIT;
80
81
fc_init_work(void)82 static void fc_init_work(void)
83 {
84 fc_clients = NULL;
85 fc_channels = NULL;
86 fc_next_id = 0;
87
88 //more init here if needed...
89 }
90
fc_init(void)91 static void __attribute__((unused)) fc_init(void)
92 {
93 pthread_once(&fc_init_once, fc_init_work);
94 }
95
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);
99 #endif /* BTA_JV_L2CAP_INCLUDED */
100
101 extern void uuid_to_string_legacy(bt_uuid_t *p_uuid, char *str);
logu(const char * title,const uint8_t * p_uuid)102 static inline void logu(const char *title, const uint8_t *p_uuid)
103 {
104 char uuids[128];
105 uuid_to_string_legacy((bt_uuid_t *)p_uuid, uuids);
106 APPL_TRACE_DEBUG("%s: %s", title, uuids);
107 }
108
109
110 static tBTA_JV_STATUS bta_jv_free_set_pm_profile_cb(UINT32 jv_handle);
111 static void bta_jv_pm_conn_busy(tBTA_JV_PM_CB *p_cb);
112 static void bta_jv_pm_conn_idle(tBTA_JV_PM_CB *p_cb);
113 static void bta_jv_pm_state_change(tBTA_JV_PM_CB *p_cb, const tBTA_JV_CONN_STATE state);
114 tBTA_JV_STATUS bta_jv_set_pm_conn_state(tBTA_JV_PM_CB *p_cb, const tBTA_JV_CONN_STATE new_st);
115
116 #if BT_SDP_BQB_INCLUDED
117 static BOOLEAN s_sdp_bqb_add_language_attr_flag = FALSE;
118 #endif /* BT_SDP_BQB_INCLUDED */
119
120 #if BTA_JV_RFCOMM_INCLUDED
121 static tBTA_JV_PCB *bta_jv_add_rfc_port(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pcb_open);
122 static int find_rfc_pcb(void *user_data, tBTA_JV_RFC_CB **cb, tBTA_JV_PCB **pcb);
123 static void bta_jv_port_mgmt_sr_cback(UINT32 code, UINT16 port_handle, void* data);
124 static void bta_jv_port_event_sr_cback(UINT32 code, UINT16 port_handle);
125 static int bta_jv_port_data_co_cback(UINT16 port_handle, UINT8 *buf, UINT16 len, int type);
126 #endif /* BTA_JV_RFCOMM_INCLUDED */
127 /*******************************************************************************
128 **
129 ** Function bta_jv_alloc_sec_id
130 **
131 ** Description allocate a security id
132 **
133 ** Returns
134 **
135 *******************************************************************************/
bta_jv_alloc_sec_id(void)136 UINT8 bta_jv_alloc_sec_id(void)
137 {
138 UINT8 ret = 0;
139 int i;
140 for (i = 0; i < BTA_JV_NUM_SERVICE_ID; i++) {
141 if (0 == bta_jv_cb.sec_id[i]) {
142 bta_jv_cb.sec_id[i] = BTA_JV_FIRST_SERVICE_ID + i;
143 ret = bta_jv_cb.sec_id[i];
144 break;
145 }
146 }
147 return ret;
148
149 }
get_sec_id_used(void)150 UNUSED_ATTR static int get_sec_id_used(void)
151 {
152 int i;
153 int used = 0;
154 for (i = 0; i < BTA_JV_NUM_SERVICE_ID; i++) {
155 if (bta_jv_cb.sec_id[i]) {
156 used++;
157 }
158 }
159 if (used == BTA_JV_NUM_SERVICE_ID) {
160 APPL_TRACE_ERROR("get_sec_id_used, sec id exceeds the limit:%d",
161 BTA_JV_NUM_SERVICE_ID);
162 }
163 return used;
164 }
165 #if BTA_JV_RFCOMM_INCLUDED
get_rfc_cb_used(void)166 UNUSED_ATTR static int get_rfc_cb_used(void)
167 {
168 int i;
169 int used = 0;
170 for (i = 0; i < BTA_JV_MAX_RFC_CONN; i++) {
171 if (bta_jv_cb.rfc_cb[i].handle ) {
172 used++;
173 }
174 }
175 if (used == BTA_JV_MAX_RFC_CONN) {
176 APPL_TRACE_ERROR("get_sec_id_used, rfc ctrl block exceeds the limit:%d",
177 BTA_JV_MAX_RFC_CONN);
178 }
179 return used;
180 }
181 #endif /* BTA_JV_RFCOMM_INCLUDED */
182
183 /*******************************************************************************
184 **
185 ** Function bta_jv_free_sec_id
186 **
187 ** Description free the given security id
188 **
189 ** Returns
190 **
191 *******************************************************************************/
bta_jv_free_sec_id(UINT8 * p_sec_id)192 static void bta_jv_free_sec_id(UINT8 *p_sec_id)
193 {
194 UINT8 sec_id = *p_sec_id;
195 *p_sec_id = 0;
196 if (sec_id >= BTA_JV_FIRST_SERVICE_ID && sec_id <= BTA_JV_LAST_SERVICE_ID) {
197 BTM_SecClrService(sec_id);
198 bta_jv_cb.sec_id[sec_id - BTA_JV_FIRST_SERVICE_ID] = 0;
199 }
200 }
201
202 #if BTA_JV_RFCOMM_INCLUDED
203 /*******************************************************************************
204 **
205 ** Function bta_jv_alloc_rfc_cb
206 **
207 ** Description allocate a control block for the given port handle
208 **
209 ** Returns
210 **
211 *******************************************************************************/
bta_jv_alloc_rfc_cb(UINT16 port_handle,tBTA_JV_PCB ** pp_pcb)212 tBTA_JV_RFC_CB *bta_jv_alloc_rfc_cb(UINT16 port_handle, tBTA_JV_PCB **pp_pcb)
213 {
214 tBTA_JV_RFC_CB *p_cb = NULL;
215 tBTA_JV_PCB *p_pcb;
216 int i, j;
217 for (i = 0; i < BTA_JV_MAX_RFC_CONN; i++) {
218 if (0 == bta_jv_cb.rfc_cb[i].handle ) {
219 p_cb = &bta_jv_cb.rfc_cb[i];
220 /* mask handle to distinguish it with L2CAP handle */
221 p_cb->handle = (i + 1) | BTA_JV_RFCOMM_MASK;
222
223 p_cb->max_sess = 1;
224 p_cb->curr_sess = 1;
225 for (j = 0; j < BTA_JV_MAX_RFC_SR_SESSION; j++) {
226 p_cb->rfc_hdl[j] = 0;
227 }
228 p_cb->rfc_hdl[0] = port_handle;
229 APPL_TRACE_DEBUG( "bta_jv_alloc_rfc_cb port_handle:%d handle:0x%2x",
230 port_handle, p_cb->handle);
231
232 p_pcb = &bta_jv_cb.port_cb[port_handle - 1];
233 p_pcb->handle = p_cb->handle;
234 p_pcb->port_handle = port_handle;
235 p_pcb->p_pm_cb = NULL;
236 *pp_pcb = p_pcb;
237 break;
238 }
239 }
240 if (p_cb == NULL) {
241 APPL_TRACE_ERROR( "bta_jv_alloc_rfc_cb: port_handle:%d, ctrl block exceeds "
242 "limit:%d", port_handle, BTA_JV_MAX_RFC_CONN);
243 }
244 return p_cb;
245 }
246
247 /*******************************************************************************
248 **
249 ** Function bta_jv_rfc_port_to_pcb
250 **
251 ** Description find the port control block associated with the given port handle
252 **
253 ** Returns
254 **
255 *******************************************************************************/
bta_jv_rfc_port_to_pcb(UINT16 port_handle)256 tBTA_JV_PCB *bta_jv_rfc_port_to_pcb(UINT16 port_handle)
257 {
258 tBTA_JV_PCB *p_pcb = NULL;
259
260 if ((port_handle > 0) && (port_handle <= MAX_RFC_PORTS)
261 && bta_jv_cb.port_cb[port_handle - 1].handle) {
262 p_pcb = &bta_jv_cb.port_cb[port_handle - 1];
263 }
264
265 return p_pcb;
266 }
267
268 /*******************************************************************************
269 **
270 ** Function bta_jv_rfc_port_to_cb
271 **
272 ** Description find the RFCOMM control block associated with the given port handle
273 **
274 ** Returns
275 **
276 *******************************************************************************/
bta_jv_rfc_port_to_cb(UINT16 port_handle)277 tBTA_JV_RFC_CB *bta_jv_rfc_port_to_cb(UINT16 port_handle)
278 {
279 tBTA_JV_RFC_CB *p_cb = NULL;
280 UINT32 handle;
281
282 if ((port_handle > 0) && (port_handle <= MAX_RFC_PORTS)
283 && bta_jv_cb.port_cb[port_handle - 1].handle) {
284 handle = bta_jv_cb.port_cb[port_handle - 1].handle;
285 handle &= BTA_JV_RFC_HDL_MASK;
286 handle &= ~BTA_JV_RFCOMM_MASK;
287 if (handle) {
288 p_cb = &bta_jv_cb.rfc_cb[handle - 1];
289 }
290 } else {
291 APPL_TRACE_WARNING("bta_jv_rfc_port_to_cb(port_handle:0x%x):jv handle:0x%x not"
292 " FOUND", port_handle, bta_jv_cb.port_cb[port_handle - 1].handle);
293 }
294 return p_cb;
295 }
296
bta_jv_free_rfc_cb(tBTA_JV_RFC_CB * p_cb,tBTA_JV_PCB * p_pcb,BOOLEAN close_server,BOOLEAN close_pending)297 static tBTA_JV_STATUS bta_jv_free_rfc_cb(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pcb, BOOLEAN close_server, BOOLEAN close_pending)
298 {
299 tBTA_JV_STATUS status = BTA_JV_SUCCESS;
300 BOOLEAN remove_server = FALSE;
301
302 UINT8 used = 0, i, listen = 0;
303 tPORT_STATE port_state;
304 UINT32 event_mask = BTA_JV_RFC_EV_MASK;
305 UINT32 scn_num = (UINT32)p_cb->scn;
306 tBTA_JV evt_data = {0};
307
308 if (!p_cb || !p_pcb) {
309 APPL_TRACE_ERROR("bta_jv_free_sr_rfc_cb, p_cb or p_pcb cannot be null");
310 return BTA_JV_FAILURE;
311 }
312 APPL_TRACE_DEBUG("bta_jv_free_sr_rfc_cb: max_sess:%d, curr_sess:%d, p_pcb:%p, user:"
313 "%p, state:%d, jv handle: 0x%x" , p_cb->max_sess, p_cb->curr_sess, p_pcb,
314 p_pcb->user_data, p_pcb->state, p_pcb->handle);
315
316 if (p_cb->curr_sess <= 0) {
317 return BTA_JV_SUCCESS;
318 }
319
320 switch (p_pcb->state) {
321 case BTA_JV_ST_CL_CLOSING:
322 case BTA_JV_ST_SR_CLOSING:
323 APPL_TRACE_DEBUG("bta_jv_free_sr_rfc_cb: return on closing, port state:%d, "
324 "scn:%d, p_pcb:%p, user_data:%p", p_pcb->state, p_cb->scn, p_pcb,
325 p_pcb->user_data);
326 status = BTA_JV_FAILURE;
327 break;
328 case BTA_JV_ST_CL_OPEN:
329 case BTA_JV_ST_CL_OPENING:
330 APPL_TRACE_DEBUG("bta_jv_free_sr_rfc_cb: state: %d, scn:%d,"
331 " user_data:%p", p_pcb->state, p_cb->scn, p_pcb->user_data);
332 p_pcb->state = BTA_JV_ST_CL_CLOSING;
333 break;
334 case BTA_JV_ST_SR_LISTEN:
335 p_pcb->state = BTA_JV_ST_SR_CLOSING;
336 remove_server = TRUE;
337 APPL_TRACE_DEBUG("bta_jv_free_sr_rfc_cb: state: BTA_JV_ST_SR_LISTEN, scn:%d,"
338 " user_data:%p", p_cb->scn, p_pcb->user_data);
339 break;
340 case BTA_JV_ST_SR_OPEN:
341 p_pcb->state = BTA_JV_ST_SR_CLOSING;
342 APPL_TRACE_DEBUG("bta_jv_free_sr_rfc_cb: state: BTA_JV_ST_SR_OPEN, scn:%d,"
343 " user_data:%p", p_cb->scn, p_pcb->user_data);
344 break;
345 default:
346 APPL_TRACE_WARNING("bta_jv_free_sr_rfc_cb():failed, ignore port state:%d, scn:"
347 "%d, p_pcb:%p, jv handle: 0x%x, port_handle: %d, user_data:%p",
348 p_pcb->state, p_cb->scn, p_pcb, p_pcb->handle, p_pcb->port_handle,
349 p_pcb->user_data);
350 status = BTA_JV_FAILURE;
351 break;
352 }
353 if (BTA_JV_SUCCESS == status) {
354 int port_status;
355
356 if (!remove_server) {
357 port_status = RFCOMM_RemoveConnection(p_pcb->port_handle);
358 } else {
359 port_status = RFCOMM_RemoveServer(p_pcb->port_handle);
360 }
361 if (port_status != PORT_SUCCESS) {
362 status = BTA_JV_FAILURE;
363 APPL_TRACE_WARNING("bta_jv_free_rfc_cb(jv handle: 0x%x, state %d)::"
364 "port_status: %d, port_handle: %d, close_pending: %d:Remove",
365 p_pcb->handle, p_pcb->state, port_status, p_pcb->port_handle,
366 close_pending);
367 }
368 }
369 if (!close_pending) {
370 p_pcb->port_handle = 0;
371 p_pcb->state = BTA_JV_ST_NONE;
372 bta_jv_free_set_pm_profile_cb(p_pcb->handle);
373
374 //Initialize congestion flags
375 p_pcb->cong = FALSE;
376 p_pcb->user_data = 0;
377 int si = BTA_JV_RFC_HDL_TO_SIDX(p_pcb->handle);
378 if (0 <= si && si < BTA_JV_MAX_RFC_SR_SESSION) {
379 p_cb->rfc_hdl[si] = 0;
380 }
381 p_pcb->handle = 0;
382 p_cb->curr_sess--;
383
384 /* only needs a listening port when has a server */
385 if (!close_server && (p_cb->max_sess > 1) && (p_cb->scn != 0)) {
386 for (i = 0; i < p_cb->max_sess; i++) {
387 if (p_cb->rfc_hdl[i] != 0) {
388 p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[i] - 1];
389 if (p_pcb->state == BTA_JV_ST_SR_LISTEN) {
390 listen++;
391 }
392 used++;
393 }
394 }
395 APPL_TRACE_DEBUG("%s max_sess=%d used:%d curr_sess:%d, listen:%d si:%d", __func__, p_cb->max_sess, used,
396 p_cb->curr_sess, listen, si);
397 if (used < p_cb->max_sess &&
398 listen == 0 &&
399 0 <= si &&
400 si < BTA_JV_MAX_RFC_SR_SESSION) {
401 /* make sure the server has a listen port */
402 if ((RFCOMM_CreateConnection(p_cb->sec_id, p_cb->scn, TRUE,
403 BTA_JV_DEF_RFC_MTU, (UINT8 *)bd_addr_any, &(p_cb->rfc_hdl[si]), bta_jv_port_mgmt_sr_cback) == PORT_SUCCESS) &&
404 (p_cb->rfc_hdl[si] != 0)) {
405 p_cb->curr_sess++;
406 p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[si] - 1];
407 p_pcb->state = BTA_JV_ST_SR_LISTEN;
408 p_pcb->port_handle = p_cb->rfc_hdl[si];
409 // p_pcb->user_data = p_pcb_open->user_data;
410
411 PORT_ClearKeepHandleFlag(p_pcb->port_handle);
412 PORT_SetEventCallback(p_pcb->port_handle, bta_jv_port_event_sr_cback);
413 PORT_SetDataCOCallback(p_pcb->port_handle, bta_jv_port_data_co_cback);
414 PORT_SetEventMask(p_pcb->port_handle, event_mask);
415 PORT_GetState(p_pcb->port_handle, &port_state);
416
417 port_state.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT);
418
419 PORT_SetState(p_pcb->port_handle, &port_state);
420 p_pcb->handle = BTA_JV_RFC_H_S_TO_HDL(p_cb->handle, si);
421 APPL_TRACE_DEBUG("%s: p_pcb->handle:0x%x, curr_sess:%d", __func__,
422 p_pcb->handle, p_cb->curr_sess);
423
424 evt_data.rfc_srv_open.handle = 0;
425 evt_data.rfc_srv_open.new_listen_handle = p_pcb->handle;
426 evt_data.rfc_srv_open.status = BTA_JV_SUCCESS;
427 p_pcb->user_data = p_cb->p_cback(BTA_JV_RFCOMM_SRV_OPEN_EVT, &evt_data, (void *)scn_num);
428 }
429 }
430 }
431
432 if (p_cb->curr_sess == 0) {
433 p_cb->scn = 0;
434 bta_jv_free_sec_id(&p_cb->sec_id);
435 p_cb->p_cback = NULL;
436 p_cb->handle = 0;
437 p_cb->curr_sess = -1;
438 }
439 }
440 return status;
441 }
442 #endif /* BTA_JV_RFCOMM_INCLUDED */
443
444 #if BTA_JV_L2CAP_INCLUDED
445 /*******************************************************************************
446 **
447 ** Function bta_jv_free_l2c_cb
448 **
449 ** Description free the given L2CAP control block
450 **
451 ** Returns
452 **
453 *******************************************************************************/
bta_jv_free_l2c_cb(tBTA_JV_L2C_CB * p_cb)454 tBTA_JV_STATUS bta_jv_free_l2c_cb(tBTA_JV_L2C_CB *p_cb)
455 {
456 tBTA_JV_STATUS status = BTA_JV_SUCCESS;
457
458 if (BTA_JV_ST_NONE != p_cb->state) {
459 bta_jv_free_set_pm_profile_cb((UINT32)p_cb->handle);
460 if (GAP_ConnClose(p_cb->handle) != BT_PASS) {
461 status = BTA_JV_FAILURE;
462 }
463 }
464 p_cb->psm = 0;
465 p_cb->state = BTA_JV_ST_NONE;
466 bta_jv_free_sec_id(&p_cb->sec_id);
467 p_cb->p_cback = NULL;
468 return status;
469 }
470 #endif /* BTA_JV_L2CAP_INCLUDED */
471
472 /*******************************************************************************
473 **
474 **
475 ** Function bta_jv_clear_pm_cb
476 **
477 ** Description clears jv pm control block and optionally calls bta_sys_conn_close()
478 ** In general close_conn should be set to TRUE to remove registering with
479 ** dm pm!
480 **
481 ** WARNING: Make sure to clear pointer form port or l2c to this control block too!
482 **
483 *******************************************************************************/
bta_jv_clear_pm_cb(tBTA_JV_PM_CB * p_pm_cb,BOOLEAN close_conn)484 static void bta_jv_clear_pm_cb(tBTA_JV_PM_CB *p_pm_cb, BOOLEAN close_conn)
485 {
486 /* needs to be called if registered with bta pm, otherwise we may run out of dm pm slots! */
487 if (close_conn) {
488 bta_sys_conn_close(BTA_ID_JV, p_pm_cb->app_id, p_pm_cb->peer_bd_addr);
489 }
490 p_pm_cb->state = BTA_JV_PM_FREE_ST;
491 p_pm_cb->app_id = BTA_JV_PM_ALL;
492 p_pm_cb->handle = BTA_JV_PM_HANDLE_CLEAR;
493 bdcpy(p_pm_cb->peer_bd_addr, bd_addr_null);
494 }
495
496 /*******************************************************************************
497 **
498 ** Function bta_jv_free_set_pm_profile_cb
499 **
500 ** Description free pm profile control block
501 **
502 ** Returns BTA_JV_SUCCESS if cb has been freed correctly,
503 ** BTA_JV_FAILURE in case of no profile has been registered or already freed
504 **
505 *******************************************************************************/
bta_jv_free_set_pm_profile_cb(UINT32 jv_handle)506 static tBTA_JV_STATUS bta_jv_free_set_pm_profile_cb(UINT32 jv_handle)
507 {
508 tBTA_JV_STATUS status = BTA_JV_FAILURE;
509 tBTA_JV_PM_CB **p_cb;
510 int i, j, bd_counter = 0, appid_counter = 0;
511
512 for (i = 0; i < BTA_JV_PM_MAX_NUM; i++) {
513 p_cb = NULL;
514 if ((bta_jv_cb.pm_cb[i].state != BTA_JV_PM_FREE_ST) &&
515 (jv_handle == bta_jv_cb.pm_cb[i].handle)) {
516 for (j = 0; j < BTA_JV_PM_MAX_NUM; j++) {
517 if (bdcmp(bta_jv_cb.pm_cb[j].peer_bd_addr, bta_jv_cb.pm_cb[i].peer_bd_addr) == 0) {
518 bd_counter++;
519 }
520 if (bta_jv_cb.pm_cb[j].app_id == bta_jv_cb.pm_cb[i].app_id) {
521 appid_counter++;
522 }
523 }
524
525 APPL_TRACE_API("%s(jv_handle: 0x%2x), idx: %d, app_id: 0x%x", __func__, jv_handle, i, bta_jv_cb.pm_cb[i].app_id);
526 APPL_TRACE_API("%s, bd_counter = %d, appid_counter = %d", __func__, bd_counter, appid_counter);
527 if (bd_counter > 1) {
528 bta_jv_pm_conn_idle(&bta_jv_cb.pm_cb[i]);
529 }
530
531 if (bd_counter <= 1 || (appid_counter <= 1)) {
532 bta_jv_clear_pm_cb(&bta_jv_cb.pm_cb[i], TRUE);
533 } else {
534 bta_jv_clear_pm_cb(&bta_jv_cb.pm_cb[i], FALSE);
535 }
536
537 if (BTA_JV_RFCOMM_MASK & jv_handle) {
538 #if BTA_JV_RFCOMM_INCLUDED
539 UINT32 hi = ((jv_handle & BTA_JV_RFC_HDL_MASK) & ~BTA_JV_RFCOMM_MASK) - 1;
540 UINT32 si = BTA_JV_RFC_HDL_TO_SIDX(jv_handle);
541 if (hi < BTA_JV_MAX_RFC_CONN && bta_jv_cb.rfc_cb[hi].p_cback && si
542 < BTA_JV_MAX_RFC_SR_SESSION && bta_jv_cb.rfc_cb[hi].rfc_hdl[si]) {
543 tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(bta_jv_cb.rfc_cb[hi].rfc_hdl[si]);
544 if (p_pcb) {
545 if (NULL == p_pcb->p_pm_cb) {
546 APPL_TRACE_WARNING("%s(jv_handle: 0x%x):port_handle: 0x%x, p_pm_cb: %d: no link to pm_cb?",
547 __func__, jv_handle, p_pcb->port_handle, i);
548 }
549 p_cb = &p_pcb->p_pm_cb;
550 }
551 }
552 #endif /* BTA_JV_RFCOMM_INCLUDED */
553 }
554 #if BTA_JV_L2CAP_INCLUDED
555 else {
556 if (jv_handle < BTA_JV_MAX_L2C_CONN) {
557 tBTA_JV_L2C_CB *p_l2c_cb = &bta_jv_cb.l2c_cb[jv_handle];
558 if (NULL == p_l2c_cb->p_pm_cb) {
559 APPL_TRACE_WARNING("%s(jv_handle: "
560 "0x%x): p_pm_cb: %d: no link to pm_cb?", __func__, jv_handle, i);
561 }
562 p_cb = &p_l2c_cb->p_pm_cb;
563 }
564 }
565 #endif /* BTA_JV_L2CAP_INCLUDED */
566
567 if (p_cb) {
568 *p_cb = NULL;
569 status = BTA_JV_SUCCESS;
570 }
571 }
572 }
573 return status;
574 }
575
576 /*******************************************************************************
577 **
578 ** Function bta_jv_alloc_set_pm_profile_cb
579 **
580 ** Description set PM profile control block
581 **
582 ** Returns pointer to allocated cb or NULL in case of failure
583 **
584 *******************************************************************************/
bta_jv_alloc_set_pm_profile_cb(UINT32 jv_handle,tBTA_JV_PM_ID app_id)585 static tBTA_JV_PM_CB *bta_jv_alloc_set_pm_profile_cb(UINT32 jv_handle, tBTA_JV_PM_ID app_id)
586 {
587 BOOLEAN bRfcHandle = (jv_handle & BTA_JV_RFCOMM_MASK) != 0;
588 BD_ADDR peer_bd_addr;
589 int i, j;
590 tBTA_JV_PM_CB **pp_cb;
591
592 for (i = 0; i < BTA_JV_PM_MAX_NUM; i++) {
593 pp_cb = NULL;
594 if (bta_jv_cb.pm_cb[i].state == BTA_JV_PM_FREE_ST) {
595 /* rfc handle bd addr retrieval requires core stack handle */
596 if (bRfcHandle) {
597 #if BTA_JV_RFCOMM_INCLUDED
598 // UINT32 hi = ((jv_handle & BTA_JV_RFC_HDL_MASK) & ~BTA_JV_RFCOMM_MASK) - 1;
599 // UINT32 si = BTA_JV_RFC_HDL_TO_SIDX(jv_handle);
600 for (j = 0; j < BTA_JV_MAX_RFC_CONN; j++) {
601 if (jv_handle == bta_jv_cb.port_cb[j].handle) {
602 pp_cb = &bta_jv_cb.port_cb[j].p_pm_cb;
603 if (PORT_SUCCESS !=
604 PORT_CheckConnection(bta_jv_cb.port_cb[j].port_handle, FALSE, peer_bd_addr, NULL)) {
605 i = BTA_JV_PM_MAX_NUM;
606 }
607 break;
608 }
609 }
610 #endif /* BTA_JV_RFCOMM_INCLUDED */
611 }
612 #if BTA_JV_L2CAP_INCLUDED
613 else {
614 /* use jv handle for l2cap bd address retrieval */
615 for (j = 0; j < BTA_JV_MAX_L2C_CONN; j++) {
616 if (jv_handle == bta_jv_cb.l2c_cb[j].handle) {
617 pp_cb = &bta_jv_cb.l2c_cb[j].p_pm_cb;
618 UINT8 *p_bd_addr = GAP_ConnGetRemoteAddr((UINT16)jv_handle);
619 if (NULL != p_bd_addr) {
620 bdcpy(peer_bd_addr, p_bd_addr);
621 } else {
622 i = BTA_JV_PM_MAX_NUM;
623 }
624 break;
625 }
626 }
627 }
628 #endif /* BTA_JV_L2CAP_INCLUDED */
629 APPL_TRACE_API("bta_jv_alloc_set_pm_profile_cb(handle 0x%2x, app_id %d): "
630 "idx: %d, (BTA_JV_PM_MAX_NUM: %d), pp_cb: %p", jv_handle, app_id,
631 i, BTA_JV_PM_MAX_NUM, (void *)pp_cb);
632 break;
633 }
634 }
635
636 if ((i != BTA_JV_PM_MAX_NUM) && (NULL != pp_cb)) {
637 *pp_cb = &bta_jv_cb.pm_cb[i];
638 bta_jv_cb.pm_cb[i].handle = jv_handle;
639 bta_jv_cb.pm_cb[i].app_id = app_id;
640 bdcpy(bta_jv_cb.pm_cb[i].peer_bd_addr, peer_bd_addr);
641 bta_jv_cb.pm_cb[i].state = BTA_JV_PM_IDLE_ST;
642 return &bta_jv_cb.pm_cb[i];
643 }
644 APPL_TRACE_WARNING("bta_jv_alloc_set_pm_profile_cb(jv_handle: 0x%x, app_id: %d) "
645 "return NULL", jv_handle, app_id);
646 return (tBTA_JV_PM_CB *)NULL;
647 }
648
649 /*******************************************************************************
650 **
651 ** Function bta_jv_check_psm
652 **
653 ** Description for now use only the legal PSM per JSR82 spec
654 **
655 ** Returns TRUE, if allowed
656 **
657 *******************************************************************************/
bta_jv_check_psm(UINT16 psm)658 BOOLEAN bta_jv_check_psm(UINT16 psm)
659 {
660 BOOLEAN ret = FALSE;
661
662 if (L2C_IS_VALID_PSM(psm)) {
663 if (psm < 0x1001) {
664 /* see if this is defined by spec */
665 switch (psm) {
666 case SDP_PSM: /* 1 */
667 case BT_PSM_RFCOMM: /* 3 */
668 /* do not allow java app to use these 2 PSMs */
669 break;
670
671 case TCS_PSM_INTERCOM: /* 5 */
672 case TCS_PSM_CORDLESS: /* 7 */
673 if ( FALSE == bta_sys_is_register(BTA_ID_CT) &&
674 FALSE == bta_sys_is_register(BTA_ID_CG) ) {
675 ret = TRUE;
676 }
677 break;
678
679 case BT_PSM_BNEP: /* F */
680 if (FALSE == bta_sys_is_register(BTA_ID_PAN)) {
681 ret = TRUE;
682 }
683 break;
684
685 case HID_PSM_CONTROL: /* 0x11 */
686 case HID_PSM_INTERRUPT: /* 0x13 */
687 //FIX: allow HID Device and HID Host to coexist
688 if ( FALSE == bta_sys_is_register(BTA_ID_HD) ||
689 FALSE == bta_sys_is_register(BTA_ID_HH) ) {
690 ret = TRUE;
691 }
692 break;
693
694 case AVCT_PSM: /* 0x17 */
695 case AVDT_PSM: /* 0x19 */
696 if ((FALSE == bta_sys_is_register(BTA_ID_AV)) &&
697 (FALSE == bta_sys_is_register(BTA_ID_AVK))) {
698 ret = TRUE;
699 }
700 break;
701
702 default:
703 ret = TRUE;
704 break;
705 }
706 } else {
707 ret = TRUE;
708 }
709 }
710 return ret;
711 }
712
713 /*******************************************************************************
714 **
715 ** Function bta_jv_enable
716 **
717 ** Description Initialises the JAVA I/F
718 **
719 ** Returns void
720 **
721 *******************************************************************************/
bta_jv_enable(tBTA_JV_MSG * p_data)722 void bta_jv_enable(tBTA_JV_MSG *p_data)
723 {
724 tBTA_UTL_COD cod;
725
726 tBTA_JV_STATUS status = BTA_JV_SUCCESS;
727 bta_jv_cb.p_dm_cback = p_data->enable.p_cback;
728 bta_jv_cb.p_dm_cback(BTA_JV_ENABLE_EVT, (tBTA_JV *)&status, 0);
729 memset(bta_jv_cb.free_psm_list, 0, sizeof(bta_jv_cb.free_psm_list));
730
731 /* Set the Class of Device */
732 cod.major = BTM_COD_MAJOR_UNCLASSIFIED;
733 cod.minor = BTM_COD_MINOR_UNCLASSIFIED;
734 utl_set_device_class(&cod, BTA_UTL_SET_COD_MAJOR_MINOR);
735 }
736
737 /*******************************************************************************
738 **
739 ** Function bta_jv_disable
740 **
741 ** Description Disables the BT device manager
742 ** free the resources used by java
743 **
744 ** Returns void
745 **
746 *******************************************************************************/
bta_jv_disable(tBTA_JV_MSG * p_data)747 void bta_jv_disable (tBTA_JV_MSG *p_data)
748 {
749 tBTA_JV_STATUS evt_data;
750 evt_data = BTA_JV_SUCCESS;
751 // UNUSED(p_data);
752 if (p_data->disable.p_cback) {
753 p_data->disable.p_cback(BTA_JV_DISABLE_EVT, (tBTA_JV *)&evt_data, NULL);
754 }
755 }
756
757
758 /**
759 * We keep a list of PSM's that have been freed from JAVA, for reuse.
760 * This function will return a free PSM, and delete it from the free
761 * list.
762 * If no free PSMs exist, 0 will be returned.
763 */
bta_jv_get_free_psm(void)764 static UINT16 bta_jv_get_free_psm(void)
765 {
766 const int cnt = sizeof(bta_jv_cb.free_psm_list) / sizeof(bta_jv_cb.free_psm_list[0]);
767 for (int i = 0; i < cnt; i++) {
768 UINT16 psm = bta_jv_cb.free_psm_list[i];
769 if (psm != 0) {
770 APPL_TRACE_DEBUG("%s(): Reusing PSM: 0x%04d", __func__, psm)
771 bta_jv_cb.free_psm_list[i] = 0;
772 return psm;
773 }
774 }
775 return 0;
776 }
777
bta_jv_set_free_psm(UINT16 psm)778 static void bta_jv_set_free_psm(UINT16 psm)
779 {
780 int free_index = -1;
781 const int cnt = sizeof(bta_jv_cb.free_psm_list) / sizeof(bta_jv_cb.free_psm_list[0]);
782 for (int i = 0; i < cnt; i++) {
783 if (bta_jv_cb.free_psm_list[i] == 0) {
784 free_index = i;
785 } else if (psm == bta_jv_cb.free_psm_list[i]) {
786 return; // PSM already freed?
787 }
788 }
789 if (free_index != -1) {
790 bta_jv_cb.free_psm_list[free_index] = psm;
791 APPL_TRACE_DEBUG("%s(): Recycling PSM: 0x%04d", __func__, psm)
792 } else {
793 APPL_TRACE_ERROR("%s unable to free psm 0x%x no more free slots", __func__, psm);
794 }
795 }
796
797 /*******************************************************************************
798 **
799 ** Function bta_jv_get_channel_id
800 **
801 ** Description Obtain a free SCN (Server Channel Number)
802 ** (RFCOMM channel or L2CAP PSM)
803 **
804 ** Returns void
805 **
806 *******************************************************************************/
bta_jv_get_channel_id(tBTA_JV_MSG * p_data)807 void bta_jv_get_channel_id(tBTA_JV_MSG *p_data)
808 {
809 UINT16 psm = 0;
810
811 switch (p_data->alloc_channel.type) {
812 case BTA_JV_CONN_TYPE_RFCOMM: {
813 INT32 channel = p_data->alloc_channel.channel;
814 UINT8 scn = 0;
815 if (channel > 0) {
816 if (BTM_TryAllocateSCN(channel) == FALSE) {
817 APPL_TRACE_ERROR("rfc channel:%d already in use or invalid", channel);
818 channel = 0;
819 }
820 } else if ((channel = BTM_AllocateSCN()) == 0) {
821 APPL_TRACE_ERROR("run out of rfc channels");
822 channel = 0;
823 }
824 if (channel != 0) {
825 bta_jv_cb.scn[channel - 1] = TRUE;
826 scn = (UINT8) channel;
827 }
828 if (bta_jv_cb.p_dm_cback) {
829 bta_jv_cb.p_dm_cback(BTA_JV_GET_SCN_EVT, (tBTA_JV *)&scn,
830 p_data->alloc_channel.user_data);
831 }
832 return;
833 }
834 case BTA_JV_CONN_TYPE_L2CAP:
835 psm = bta_jv_get_free_psm();
836 if (psm == 0) {
837 psm = L2CA_AllocatePSM();
838 APPL_TRACE_DEBUG("%s() returned PSM: 0x%04x", __func__, psm);
839 }
840 break;
841 case BTA_JV_CONN_TYPE_L2CAP_LE:
842 break;
843 default:
844 break;
845 }
846
847 if (bta_jv_cb.p_dm_cback) {
848 bta_jv_cb.p_dm_cback(BTA_JV_GET_PSM_EVT, (tBTA_JV *)&psm, p_data->alloc_channel.user_data);
849 }
850 }
851
852 /*******************************************************************************
853 **
854 ** Function bta_jv_free_scn
855 **
856 ** Description free a SCN
857 **
858 ** Returns void
859 **
860 *******************************************************************************/
bta_jv_free_scn(tBTA_JV_MSG * p_data)861 void bta_jv_free_scn(tBTA_JV_MSG *p_data)
862 {
863 tBTA_JV_API_FREE_CHANNEL *fc = &(p_data->free_channel);
864 UINT16 scn = fc->scn;
865 tBTA_JV_FREE_SCN evt_data = {
866 .status = BTA_JV_SUCCESS,
867 .server_status = BTA_JV_SERVER_STATUS_MAX,
868 .scn = scn
869 };
870
871 tBTA_JV_FREE_SCN_USER_DATA *user_data = NULL;
872 #if BTA_JV_RFCOMM_INCLUDED
873 tBTA_JV_RFC_CB *p_cb = NULL;
874 tBTA_JV_PCB *p_pcb = NULL;
875 #endif /* BTA_JV_RFCOMM_INCLUDED */
876
877 switch (p_data->free_channel.type) {
878 case BTA_JV_CONN_TYPE_RFCOMM: {
879 #if BTA_JV_RFCOMM_INCLUDED
880 if (scn > 0 && scn <= BTA_JV_MAX_SCN && bta_jv_cb.scn[scn - 1]) {
881 /* this scn is used by JV */
882 bta_jv_cb.scn[scn - 1] = FALSE;
883 BTM_FreeSCN(scn);
884 }
885 if (fc->user_data) {
886 user_data = (tBTA_JV_FREE_SCN_USER_DATA *)fc->user_data;
887 evt_data.server_status = user_data->server_status;
888 if (user_data->server_status == BTA_JV_SERVER_RUNNING && find_rfc_pcb((void *)user_data->slot_id, &p_cb, &p_pcb)) {
889 /* if call bta_jv_rfcomm_stop_server successfully, find_rfc_pcb shall return false */
890 evt_data.status = BTA_JV_FAILURE;
891 }
892
893 if (fc->p_cback) {
894 fc->p_cback(BTA_JV_FREE_SCN_EVT, (tBTA_JV *)&evt_data, (void *)user_data);
895 }
896 }
897 #endif /* BTA_JV_RFCOMM_INCLUDED */
898 break;
899 }
900 case BTA_JV_CONN_TYPE_L2CAP:
901 bta_jv_set_free_psm(scn);
902 if (fc->p_cback) {
903 fc->p_cback(BTA_JV_FREE_SCN_EVT, (tBTA_JV *)&evt_data, (void *)user_data);
904 }
905 break;
906 case BTA_JV_CONN_TYPE_L2CAP_LE:
907 // TODO: Not yet implemented...
908 break;
909 default:
910 break;
911 }
912 }
shorten_sdp_uuid(const tBT_UUID * u)913 static inline tBT_UUID shorten_sdp_uuid(const tBT_UUID *u)
914 {
915 static uint8_t bt_base_uuid[] =
916 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB };
917
918 logu("in, uuid:", u->uu.uuid128);
919 APPL_TRACE_DEBUG("uuid len:%d", u->len);
920 if (u->len == 16) {
921 if (memcmp(&u->uu.uuid128[4], &bt_base_uuid[4], 12) == 0) {
922 tBT_UUID su;
923 memset(&su, 0, sizeof(su));
924 if (u->uu.uuid128[0] == 0 && u->uu.uuid128[1] == 0) {
925 su.len = 2;
926 uint16_t u16;
927 memcpy(&u16, &u->uu.uuid128[2], sizeof(u16));
928 su.uu.uuid16 = ntohs(u16);
929 APPL_TRACE_DEBUG("shorten to 16 bits uuid: %x", su.uu.uuid16);
930 } else {
931 su.len = 4;
932 uint32_t u32;
933 memcpy(&u32, &u->uu.uuid128[0], sizeof(u32));
934 su.uu.uuid32 = ntohl(u32);
935 APPL_TRACE_DEBUG("shorten to 32 bits uuid: %x", su.uu.uuid32);
936 }
937 return su;
938 }
939 }
940 APPL_TRACE_DEBUG("cannot shorten none-reserved 128 bits uuid");
941 return *u;
942 }
943
944 /*******************************************************************************
945 **
946 ** Function bta_jv_start_discovery_cback
947 **
948 ** Description Callback for Start Discovery
949 **
950 ** Returns void
951 **
952 *******************************************************************************/
bta_jv_start_discovery_cback(UINT16 result,void * user_data)953 static void bta_jv_start_discovery_cback(UINT16 result, void *user_data)
954 {
955 tBTA_JV_STATUS status;
956 // UINT8 old_sdp_act = bta_jv_cb.sdp_active;
957
958 APPL_TRACE_DEBUG("bta_jv_start_discovery_cback res: 0x%x", result);
959
960 bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_NONE;
961 if (bta_jv_cb.p_dm_cback) {
962 tBTA_JV_DISCOVERY_COMP dcomp;
963 dcomp.scn_num = 0;
964 status = BTA_JV_FAILURE;
965 if (result == SDP_SUCCESS || result == SDP_DB_FULL) {
966 tSDP_DISC_REC *p_sdp_rec = NULL;
967 tSDP_DISC_ATTR *p_attr = NULL;
968 tSDP_PROTOCOL_ELEM pe;
969 logu("bta_jv_cb.uuid", bta_jv_cb.uuid.uu.uuid128);
970 tBT_UUID su = shorten_sdp_uuid(&bta_jv_cb.uuid);
971 logu("shorten uuid:", su.uu.uuid128);
972 do{
973 p_sdp_rec = SDP_FindServiceUUIDInDb(p_bta_jv_cfg->p_sdp_db, &su, p_sdp_rec);
974 APPL_TRACE_DEBUG("p_sdp_rec:%p", p_sdp_rec);
975 if (p_sdp_rec && SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_RFCOMM, &pe)){
976 dcomp.scn[dcomp.scn_num] = (UINT8) pe.params[0];
977 if ((p_attr = SDP_FindAttributeInRec(p_sdp_rec, ATTR_ID_SERVICE_NAME)) != NULL) {
978 dcomp.service_name[dcomp.scn_num] = (char *)p_attr->attr_value.v.array;
979 } else {
980 dcomp.service_name[dcomp.scn_num] = NULL;
981 }
982 dcomp.scn_num++;
983 status = BTA_JV_SUCCESS;
984 }
985 } while (p_sdp_rec);
986 }
987
988 dcomp.status = status;
989 bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, (tBTA_JV *)&dcomp, user_data);
990 }
991 }
992
993 /*******************************************************************************
994 **
995 ** Function bta_jv_start_discovery
996 **
997 ** Description Discovers services on a remote device
998 **
999 ** Returns void
1000 **
1001 *******************************************************************************/
bta_jv_start_discovery(tBTA_JV_MSG * p_data)1002 void bta_jv_start_discovery(tBTA_JV_MSG *p_data)
1003 {
1004 tBTA_JV_STATUS status = BTA_JV_FAILURE;
1005 APPL_TRACE_DEBUG("bta_jv_start_discovery in, sdp_active:%d", bta_jv_cb.sdp_active);
1006 if (bta_jv_cb.sdp_active != BTA_JV_SDP_ACT_NONE) {
1007 /* SDP is still in progress */
1008 status = BTA_JV_BUSY;
1009 if (bta_jv_cb.p_dm_cback) {
1010 bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, (tBTA_JV *)&status, p_data->start_discovery.user_data);
1011 }
1012 return;
1013 }
1014
1015 /* init the database/set up the filter */
1016 APPL_TRACE_DEBUG("call SDP_InitDiscoveryDb, p_data->start_discovery.num_uuid:%d",
1017 p_data->start_discovery.num_uuid);
1018 SDP_InitDiscoveryDb (p_bta_jv_cfg->p_sdp_db, p_bta_jv_cfg->sdp_db_size,
1019 p_data->start_discovery.num_uuid, p_data->start_discovery.uuid_list, 0, NULL);
1020
1021 /* tell SDP to keep the raw data */
1022 p_bta_jv_cfg->p_sdp_db->raw_data = p_bta_jv_cfg->p_sdp_raw_data;
1023 p_bta_jv_cfg->p_sdp_db->raw_size = p_bta_jv_cfg->sdp_raw_size;
1024
1025 bta_jv_cb.p_sel_raw_data = 0;
1026 bta_jv_cb.uuid = p_data->start_discovery.uuid_list[0];
1027
1028 bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_YES;
1029 if (!SDP_ServiceSearchAttributeRequest2(p_data->start_discovery.bd_addr,
1030 p_bta_jv_cfg->p_sdp_db,
1031 bta_jv_start_discovery_cback, p_data->start_discovery.user_data)) {
1032 bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_NONE;
1033 /* failed to start SDP. report the failure right away */
1034 if (bta_jv_cb.p_dm_cback) {
1035 bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, (tBTA_JV *)&status, p_data->start_discovery.user_data);
1036 }
1037 }
1038 /*
1039 else report the result when the cback is called
1040 */
1041 }
1042
1043 /*******************************************************************************
1044 **
1045 ** Function sdp_bqb_add_language_attr_ctrl
1046 **
1047 ** Description Control adding of the language attribute for SDP BQB test
1048 **
1049 ** Returns void
1050 **
1051 *******************************************************************************/
1052 #if BT_SDP_BQB_INCLUDED
sdp_bqb_add_language_attr_ctrl(BOOLEAN enable)1053 void sdp_bqb_add_language_attr_ctrl(BOOLEAN enable)
1054 {
1055 s_sdp_bqb_add_language_attr_flag = enable;
1056 }
1057 #endif /* BT_SDP_BQB_INCLUDED */
1058
1059 /**
1060 * @brief Adds a protocol list and service name (if provided) to an SDP record given by
1061 * sdp_handle, and marks it as browseable. This is a shortcut for defining a
1062 * set of protocols that includes L2CAP, RFCOMM, and optionally OBEX.
1063 *
1064 * @param[in] sdp_handle: SDP handle
1065 * @param[in] name: service name
1066 * @param[in] channel: channel
1067 * @param[in] with_obex: if TRUE, then an additional OBEX protocol UUID will be included
1068 * at the end of the protocol list.
1069 * @return
1070 * - TRUE : success
1071 * - other : failed
1072 */
create_base_record(const uint32_t sdp_handle,const char * name,const uint16_t channel,const bool with_obex)1073 static bool create_base_record(const uint32_t sdp_handle, const char *name, const uint16_t channel, const bool with_obex){
1074 APPL_TRACE_DEBUG("create_base_record: scn: %d, name: %s, with_obex: %d",
1075 channel, name, with_obex);
1076
1077 // Setup the protocol list and add it.
1078 tSDP_PROTOCOL_ELEM proto_list[SDP_MAX_LIST_ELEMS];
1079 int num_proto_elements = with_obex ? 3 : 2;
1080
1081 memset(proto_list, 0, num_proto_elements * sizeof(tSDP_PROTOCOL_ELEM));
1082
1083 proto_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
1084 proto_list[0].num_params = 0;
1085 proto_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
1086 proto_list[1].num_params = 1;
1087 proto_list[1].params[0] = channel;
1088
1089 if (with_obex == TRUE) {
1090 proto_list[2].protocol_uuid = UUID_PROTOCOL_OBEX;
1091 proto_list[2].num_params = 0;
1092 }
1093
1094 const char *stage = "protocol_list";
1095 if (!SDP_AddProtocolList(sdp_handle, num_proto_elements, proto_list)){
1096 APPL_TRACE_ERROR("create_base_record: failed to create base service "
1097 "record, stage: %s, scn: %d, name: %s, with_obex: %d",
1098 stage, channel, name, with_obex);
1099 return FALSE;
1100 }
1101
1102 stage = "profile_descriptor_list";
1103 if (!SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_SERIAL_PORT, SPP_VERSION)){
1104 APPL_TRACE_ERROR("create_base_record: failed to create base service "
1105 "record, stage: %s, scn: %d, name: %s, with_obex: %d",
1106 stage, channel, name, with_obex);
1107 return FALSE;
1108 }
1109
1110 #if BT_SDP_BQB_INCLUDED
1111 // SDP/SR/SA/BV-09-C,SDP/SR/SSA/BV-13-C
1112 if (s_sdp_bqb_add_language_attr_flag == TRUE) {
1113 stage = "language_base";
1114 if (!SDP_AddLanguageBaseAttrIDList(sdp_handle, LANG_ID_CODE_ENGLISH, LANG_ID_CHAR_ENCODE_UTF8, LANGUAGE_BASE_ID)) {
1115 APPL_TRACE_ERROR("create_base_record: failed to create base service "
1116 "record, stage: %s, scn: %d, name: %s, with_obex: %d",
1117 stage, channel, name, with_obex);
1118 return FALSE;
1119 }
1120 }
1121 #endif /* BT_SDP_BQB_INCLUDED */
1122
1123 // Add the name to the SDP record.
1124 if (name[0] != '\0') {
1125 stage = "service_name";
1126 if (!SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_NAME,
1127 TEXT_STR_DESC_TYPE, (uint32_t)(strlen(name) + 1),
1128 (uint8_t *)name)){
1129 APPL_TRACE_ERROR("create_base_record: failed to create base service "
1130 "record, stage: %s, scn: %d, name: %s, with_obex: %d",
1131 stage, channel, name, with_obex);
1132 return FALSE;
1133 }
1134 }
1135
1136 // Mark the service as browseable.
1137 uint16_t list = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
1138 stage = "browseable";
1139 if (!SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &list)){
1140 APPL_TRACE_ERROR("create_base_record: failed to create base service "
1141 "record, stage: %s, scn: %d, name: %s, with_obex: %d",
1142 stage, channel, name, with_obex);
1143 return FALSE;
1144 }
1145
1146
1147 APPL_TRACE_DEBUG("create_base_record: successfully created base service "
1148 "record, handle: 0x%08x, scn: %d, name: %s, with_obex: %d",
1149 sdp_handle, channel, name, with_obex);
1150
1151 UNUSED(stage);
1152
1153 return TRUE;
1154 }
1155
add_spp_sdp(const char * name,const int channel)1156 static int add_spp_sdp(const char *name, const int channel) {
1157 APPL_TRACE_DEBUG("add_spp_sdp: scn %d, service_name %s", channel, name);
1158
1159 int handle = SDP_CreateRecord();
1160 if (handle == 0) {
1161 APPL_TRACE_ERROR("add_spp_sdp: failed to create sdp record, "
1162 "service_name: %s", name);
1163 return 0;
1164 }
1165
1166 // Create the base SDP record.
1167 const char *stage = "create_base_record";
1168 if (!create_base_record(handle, name, channel, FALSE /* with_obex */)){
1169 SDP_DeleteRecord(handle);
1170 APPL_TRACE_ERROR("add_spp_sdp: failed to register SPP service, "
1171 "stage: %s, service_name: %s", stage, name);
1172 return 0;
1173 }
1174
1175 uint16_t service = UUID_SERVCLASS_SERIAL_PORT;
1176 stage = "service_class";
1177 if (!SDP_AddServiceClassIdList(handle, 1, &service)){
1178 SDP_DeleteRecord(handle);
1179 APPL_TRACE_ERROR("add_spp_sdp: failed to register SPP service, "
1180 "stage: %s, service_name: %s", stage, name);
1181 return 0;
1182 }
1183
1184 APPL_TRACE_DEBUG("add_spp_sdp: service registered successfully, "
1185 "service_name: %s, handle 0x%08x)", name, handle);
1186 UNUSED(stage);
1187
1188 return handle;
1189 }
1190
1191 /*******************************************************************************
1192 **
1193 ** Function bta_jv_create_record
1194 **
1195 ** Description Create an SDP record with the given attributes
1196 **
1197 ** Returns void
1198 **
1199 *******************************************************************************/
bta_jv_create_record(tBTA_JV_MSG * p_data)1200 void bta_jv_create_record(tBTA_JV_MSG *p_data)
1201 {
1202 tBTA_JV_API_CREATE_RECORD *cr = &(p_data->create_record);
1203 tBTA_JV_CREATE_RECORD evt_data;
1204
1205 int handle = add_spp_sdp(cr->name, cr->channel);
1206 evt_data.handle = handle;
1207 if (handle) {
1208 evt_data.status = BTA_JV_SUCCESS;
1209 } else {
1210 evt_data.status = BTA_JV_FAILURE;
1211 }
1212
1213 if(bta_jv_cb.p_dm_cback) {
1214 //callback user immediately to create his own sdp record in stack thread context
1215 bta_jv_cb.p_dm_cback(BTA_JV_CREATE_RECORD_EVT, (tBTA_JV *)&evt_data, cr->user_data);
1216 }
1217 }
1218
1219 /*******************************************************************************
1220 **
1221 ** Function bta_jv_delete_record
1222 **
1223 ** Description Delete an SDP record
1224 **
1225 **
1226 ** Returns void
1227 **
1228 *******************************************************************************/
bta_jv_delete_record(tBTA_JV_MSG * p_data)1229 void bta_jv_delete_record(tBTA_JV_MSG *p_data)
1230 {
1231 tBTA_JV_API_ADD_ATTRIBUTE *dr = &(p_data->add_attr);
1232 if (dr->handle) {
1233 /* this is a record created by btif layer*/
1234 SDP_DeleteRecord(dr->handle);
1235 }
1236 }
1237
1238 #if BTA_JV_L2CAP_INCLUDED
1239 /*******************************************************************************
1240 **
1241 ** Function bta_jv_l2cap_client_cback
1242 **
1243 ** Description handles the l2cap client events
1244 **
1245 ** Returns void
1246 **
1247 *******************************************************************************/
bta_jv_l2cap_client_cback(UINT16 gap_handle,UINT16 event)1248 static void bta_jv_l2cap_client_cback(UINT16 gap_handle, UINT16 event)
1249 {
1250 if (gap_handle >= BTA_JV_MAX_L2C_CONN) {
1251 APPL_TRACE_WARNING("Invalid gap_handle: %u", gap_handle);
1252 return;
1253 }
1254
1255 tBTA_JV_L2C_CB *p_cb = &bta_jv_cb.l2c_cb[gap_handle];
1256 tBTA_JV evt_data = {0};
1257
1258 if (!p_cb->p_cback) {
1259 return;
1260 }
1261
1262 APPL_TRACE_DEBUG( "%s: %d evt:x%x", __func__, gap_handle, event);
1263 evt_data.l2c_open.status = BTA_JV_SUCCESS;
1264 evt_data.l2c_open.handle = gap_handle;
1265
1266 switch (event) {
1267 case GAP_EVT_CONN_OPENED:
1268 bdcpy(evt_data.l2c_open.rem_bda, GAP_ConnGetRemoteAddr(gap_handle));
1269 evt_data.l2c_open.tx_mtu = GAP_ConnGetRemMtuSize(gap_handle);
1270 p_cb->state = BTA_JV_ST_CL_OPEN;
1271 p_cb->p_cback(BTA_JV_L2CAP_OPEN_EVT, &evt_data, p_cb->user_data);
1272 break;
1273
1274 case GAP_EVT_CONN_CLOSED:
1275 p_cb->state = BTA_JV_ST_NONE;
1276 bta_jv_free_sec_id(&p_cb->sec_id);
1277 evt_data.l2c_close.async = TRUE;
1278 p_cb->p_cback(BTA_JV_L2CAP_CLOSE_EVT, &evt_data, p_cb->user_data);
1279 p_cb->p_cback = NULL;
1280 break;
1281
1282 case GAP_EVT_CONN_DATA_AVAIL:
1283 evt_data.data_ind.handle = gap_handle;
1284 /* Reset idle timer to avoid requesting sniff mode while receiving data */
1285 bta_jv_pm_conn_busy(p_cb->p_pm_cb);
1286 p_cb->p_cback(BTA_JV_L2CAP_DATA_IND_EVT, &evt_data, p_cb->user_data);
1287 bta_jv_pm_conn_idle(p_cb->p_pm_cb);
1288 break;
1289
1290 case GAP_EVT_CONN_CONGESTED:
1291 case GAP_EVT_CONN_UNCONGESTED:
1292 p_cb->cong = (event == GAP_EVT_CONN_CONGESTED) ? TRUE : FALSE;
1293 evt_data.l2c_cong.cong = p_cb->cong;
1294 p_cb->p_cback(BTA_JV_L2CAP_CONG_EVT, &evt_data, p_cb->user_data);
1295 break;
1296
1297 default:
1298 break;
1299 }
1300 }
1301
1302 /*******************************************************************************
1303 **
1304 ** Function bta_jv_l2cap_connect
1305 **
1306 ** Description makes an l2cap client connection
1307 **
1308 ** Returns void
1309 **
1310 *******************************************************************************/
bta_jv_l2cap_connect(tBTA_JV_MSG * p_data)1311 void bta_jv_l2cap_connect(tBTA_JV_MSG *p_data)
1312 {
1313 tBTA_JV_L2C_CB *p_cb;
1314 tBTA_JV_L2CAP_CL_INIT evt_data;
1315 UINT16 handle = GAP_INVALID_HANDLE;
1316 UINT8 sec_id;
1317 tL2CAP_CFG_INFO cfg;
1318 tBTA_JV_API_L2CAP_CONNECT *cc = &(p_data->l2cap_connect);
1319 UINT8 chan_mode_mask = GAP_FCR_CHAN_OPT_BASIC;
1320 tL2CAP_ERTM_INFO *ertm_info = NULL;
1321
1322 memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
1323
1324 if (cc->has_cfg == TRUE) {
1325 cfg = cc->cfg;
1326 if (cfg.fcr_present && cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) {
1327 chan_mode_mask |= GAP_FCR_CHAN_OPT_ERTM;
1328 }
1329 }
1330
1331 if (cc->has_ertm_info == TRUE) {
1332 ertm_info = &(cc->ertm_info);
1333 }
1334
1335 /* We need to use this value for MTU to be able to handle cases where cfg is not set in req. */
1336 cfg.mtu_present = TRUE;
1337 cfg.mtu = cc->rx_mtu;
1338
1339 /* TODO: DM role manager
1340 L2CA_SetDesireRole(cc->role);
1341 */
1342
1343 sec_id = bta_jv_alloc_sec_id();
1344 evt_data.sec_id = sec_id;
1345 evt_data.status = BTA_JV_FAILURE;
1346
1347 if (sec_id) {
1348 if (bta_jv_check_psm(cc->remote_psm)) { /* allowed */
1349 if ((handle = GAP_ConnOpen("", sec_id, 0, cc->peer_bd_addr, cc->remote_psm,
1350 &cfg, ertm_info, cc->sec_mask, chan_mode_mask,
1351 bta_jv_l2cap_client_cback)) != GAP_INVALID_HANDLE ) {
1352 evt_data.status = BTA_JV_SUCCESS;
1353 }
1354 }
1355 }
1356
1357 if (evt_data.status == BTA_JV_SUCCESS) {
1358 p_cb = &bta_jv_cb.l2c_cb[handle];
1359 p_cb->handle = handle;
1360 p_cb->p_cback = cc->p_cback;
1361 p_cb->user_data = cc->user_data;
1362 p_cb->psm = 0; /* not a server */
1363 p_cb->sec_id = sec_id;
1364 p_cb->state = BTA_JV_ST_CL_OPENING;
1365 } else {
1366 bta_jv_free_sec_id(&sec_id);
1367 }
1368
1369 evt_data.handle = handle;
1370 cc->p_cback(BTA_JV_L2CAP_CL_INIT_EVT, (tBTA_JV *)&evt_data, cc->user_data);
1371 }
1372
1373
1374 /*******************************************************************************
1375 **
1376 ** Function bta_jv_l2cap_close
1377 **
1378 ** Description Close an L2CAP client connection
1379 **
1380 ** Returns void
1381 **
1382 *******************************************************************************/
bta_jv_l2cap_close(tBTA_JV_MSG * p_data)1383 void bta_jv_l2cap_close(tBTA_JV_MSG *p_data)
1384 {
1385 tBTA_JV_L2CAP_CLOSE evt_data;
1386 tBTA_JV_API_L2CAP_CLOSE *cc = &(p_data->l2cap_close);
1387 void *user_data = cc->user_data;
1388
1389 evt_data.handle = cc->handle;
1390 evt_data.status = bta_jv_free_l2c_cb(cc->p_cb);
1391 evt_data.async = FALSE;
1392
1393 if (cc->p_cback) {
1394 cc->p_cback(BTA_JV_L2CAP_CLOSE_EVT, (tBTA_JV *)&evt_data, user_data);
1395 }
1396 }
1397
1398 /*******************************************************************************
1399 **
1400 ** Function bta_jv_l2cap_server_cback
1401 **
1402 ** Description handles the l2cap server callback
1403 **
1404 ** Returns void
1405 **
1406 *******************************************************************************/
bta_jv_l2cap_server_cback(UINT16 gap_handle,UINT16 event)1407 static void bta_jv_l2cap_server_cback(UINT16 gap_handle, UINT16 event)
1408 {
1409 if (gap_handle >= BTA_JV_MAX_L2C_CONN) {
1410 APPL_TRACE_WARNING("Invalid gap_handle: %u", gap_handle);
1411 return;
1412 }
1413
1414 tBTA_JV_L2C_CB *p_cb = &bta_jv_cb.l2c_cb[gap_handle];
1415 tBTA_JV evt_data = {0};
1416 tBTA_JV_L2CAP_CBACK *p_cback;
1417 void *user_data;
1418
1419 if (!p_cb->p_cback) {
1420 return;
1421 }
1422
1423 APPL_TRACE_DEBUG( "%s: %d evt:x%x", __func__, gap_handle, event);
1424 evt_data.l2c_open.status = BTA_JV_SUCCESS;
1425 evt_data.l2c_open.handle = gap_handle;
1426
1427 switch (event) {
1428 case GAP_EVT_CONN_OPENED:
1429 bdcpy(evt_data.l2c_open.rem_bda, GAP_ConnGetRemoteAddr(gap_handle));
1430 evt_data.l2c_open.tx_mtu = GAP_ConnGetRemMtuSize(gap_handle);
1431 p_cb->state = BTA_JV_ST_SR_OPEN;
1432 p_cb->p_cback(BTA_JV_L2CAP_OPEN_EVT, &evt_data, p_cb->user_data);
1433 break;
1434
1435 case GAP_EVT_CONN_CLOSED:
1436 evt_data.l2c_close.async = TRUE;
1437 evt_data.l2c_close.handle = p_cb->handle;
1438 p_cback = p_cb->p_cback;
1439 user_data = p_cb->user_data;
1440 evt_data.l2c_close.status = bta_jv_free_l2c_cb(p_cb);
1441 p_cback(BTA_JV_L2CAP_CLOSE_EVT, &evt_data, user_data);
1442 break;
1443
1444 case GAP_EVT_CONN_DATA_AVAIL:
1445 evt_data.data_ind.handle = gap_handle;
1446 /* Reset idle timer to avoid requesting sniff mode while receiving data */
1447 bta_jv_pm_conn_busy(p_cb->p_pm_cb);
1448 p_cb->p_cback(BTA_JV_L2CAP_DATA_IND_EVT, &evt_data, p_cb->user_data);
1449 bta_jv_pm_conn_idle(p_cb->p_pm_cb);
1450 break;
1451
1452 case GAP_EVT_CONN_CONGESTED:
1453 case GAP_EVT_CONN_UNCONGESTED:
1454 p_cb->cong = (event == GAP_EVT_CONN_CONGESTED) ? TRUE : FALSE;
1455 evt_data.l2c_cong.cong = p_cb->cong;
1456 p_cb->p_cback(BTA_JV_L2CAP_CONG_EVT, &evt_data, p_cb->user_data);
1457 break;
1458
1459 default:
1460 break;
1461 }
1462 }
1463
1464 /*******************************************************************************
1465 **
1466 ** Function bta_jv_l2cap_start_server
1467 **
1468 ** Description starts an L2CAP server
1469 **
1470 ** Returns void
1471 **
1472 *******************************************************************************/
bta_jv_l2cap_start_server(tBTA_JV_MSG * p_data)1473 void bta_jv_l2cap_start_server(tBTA_JV_MSG *p_data)
1474 {
1475 tBTA_JV_L2C_CB *p_cb;
1476 UINT8 sec_id;
1477 UINT16 handle;
1478 tL2CAP_CFG_INFO cfg;
1479 tBTA_JV_L2CAP_START evt_data;
1480 tBTA_JV_API_L2CAP_SERVER *ls = &(p_data->l2cap_server);
1481 // INT32 use_etm = FALSE;
1482 UINT8 chan_mode_mask = GAP_FCR_CHAN_OPT_BASIC;
1483 tL2CAP_ERTM_INFO *ertm_info = NULL;
1484
1485 memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
1486
1487 if (ls->has_cfg == TRUE) {
1488 cfg = ls->cfg;
1489 if (cfg.fcr_present && cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) {
1490 chan_mode_mask |= GAP_FCR_CHAN_OPT_ERTM;
1491 }
1492 }
1493
1494 if (ls->has_ertm_info == TRUE) {
1495 ertm_info = &(ls->ertm_info);
1496 }
1497
1498 //FIX: MTU=0 means not present
1499 if (ls->rx_mtu > 0) {
1500 cfg.mtu_present = TRUE;
1501 cfg.mtu = ls->rx_mtu;
1502 } else {
1503 cfg.mtu_present = FALSE;
1504 cfg.mtu = 0;
1505 }
1506
1507 /* TODO DM role manager
1508 L2CA_SetDesireRole(ls->role);
1509 */
1510
1511 sec_id = bta_jv_alloc_sec_id();
1512 if (0 == sec_id || (FALSE == bta_jv_check_psm(ls->local_psm)) ||
1513 (handle = GAP_ConnOpen("JV L2CAP", sec_id, 1, 0, ls->local_psm, &cfg, ertm_info,
1514 ls->sec_mask, chan_mode_mask, bta_jv_l2cap_server_cback)) == GAP_INVALID_HANDLE) {
1515 bta_jv_free_sec_id(&sec_id);
1516 evt_data.status = BTA_JV_FAILURE;
1517 } else {
1518 p_cb = &bta_jv_cb.l2c_cb[handle];
1519 evt_data.status = BTA_JV_SUCCESS;
1520 evt_data.handle = handle;
1521 evt_data.sec_id = sec_id;
1522 p_cb->p_cback = ls->p_cback;
1523 p_cb->user_data = ls->user_data;
1524 p_cb->handle = handle;
1525 p_cb->sec_id = sec_id;
1526 p_cb->state = BTA_JV_ST_SR_LISTEN;
1527 p_cb->psm = ls->local_psm;
1528 }
1529
1530 ls->p_cback(BTA_JV_L2CAP_START_EVT, (tBTA_JV *)&evt_data, ls->user_data);
1531 }
1532
1533 /*******************************************************************************
1534 **
1535 ** Function bta_jv_l2cap_stop_server
1536 **
1537 ** Description stops an L2CAP server
1538 **
1539 ** Returns void
1540 **
1541 *******************************************************************************/
bta_jv_l2cap_stop_server(tBTA_JV_MSG * p_data)1542 void bta_jv_l2cap_stop_server(tBTA_JV_MSG *p_data)
1543 {
1544 tBTA_JV_L2C_CB *p_cb;
1545 tBTA_JV_L2CAP_CLOSE evt_data;
1546 tBTA_JV_API_L2CAP_SERVER *ls = &(p_data->l2cap_server);
1547 tBTA_JV_L2CAP_CBACK *p_cback;
1548 void *user_data;
1549 for (int i = 0; i < BTA_JV_MAX_L2C_CONN; i++) {
1550 if (bta_jv_cb.l2c_cb[i].psm == ls->local_psm) {
1551 p_cb = &bta_jv_cb.l2c_cb[i];
1552 p_cback = p_cb->p_cback;
1553 user_data = p_cb->user_data;
1554 evt_data.handle = p_cb->handle;
1555 evt_data.status = bta_jv_free_l2c_cb(p_cb);
1556 evt_data.async = FALSE;
1557 p_cback(BTA_JV_L2CAP_CLOSE_EVT, (tBTA_JV *)&evt_data, user_data);
1558 break;
1559 }
1560 }
1561 }
1562
1563
1564
1565 /*******************************************************************************
1566 **
1567 ** Function bta_jv_l2cap_read
1568 **
1569 ** Description Read data from an L2CAP connection
1570 **
1571 ** Returns void
1572 **
1573 *******************************************************************************/
bta_jv_l2cap_read(tBTA_JV_MSG * p_data)1574 void bta_jv_l2cap_read(tBTA_JV_MSG *p_data)
1575 {
1576 tBTA_JV_L2CAP_READ evt_data;
1577 tBTA_JV_API_L2CAP_READ *rc = &(p_data->l2cap_read);
1578
1579 evt_data.status = BTA_JV_FAILURE;
1580 evt_data.handle = rc->handle;
1581 evt_data.req_id = rc->req_id;
1582 evt_data.p_data = rc->p_data;
1583 evt_data.len = 0;
1584
1585 if (BT_PASS == GAP_ConnReadData(rc->handle, rc->p_data, rc->len, &evt_data.len)) {
1586 evt_data.status = BTA_JV_SUCCESS;
1587 }
1588
1589 rc->p_cback(BTA_JV_L2CAP_READ_EVT, (tBTA_JV *)&evt_data, rc->user_data);
1590 }
1591
1592
1593 /*******************************************************************************
1594 **
1595 ** Function bta_jv_l2cap_write
1596 **
1597 ** Description Write data to an L2CAP connection
1598 **
1599 ** Returns void
1600 **
1601 *******************************************************************************/
bta_jv_l2cap_write(tBTA_JV_MSG * p_data)1602 void bta_jv_l2cap_write(tBTA_JV_MSG *p_data)
1603 {
1604 tBTA_JV_L2CAP_WRITE evt_data;
1605 tBTA_JV_API_L2CAP_WRITE *ls = &(p_data->l2cap_write);
1606
1607 /* As we check this callback exists before the tBTA_JV_API_L2CAP_WRITE can be send through the
1608 * API this check should not be needed.
1609 * But the API is not designed to be used (safely at least) in a multi-threaded scheduler, hence
1610 * if the peer device disconnects the l2cap link after the API is called, but before this
1611 * message is handled, the ->p_cback will be cleared at this point. At first glanch this seems
1612 * highly unlikely, but for all obex-profiles with two channels connected - e.g. MAP, this
1613 * happens around 1 of 4 disconnects, as a disconnect on the server channel causes a disconnect
1614 * to be send on the client (notification) channel, but at the peer typically disconnects both
1615 * the OBEX disconnect request crosses the incoming l2cap disconnect.
1616 * If p_cback is cleared, we simply discard the data.
1617 * RISK: The caller must handle any cleanup based on another signal than BTA_JV_L2CAP_WRITE_EVT,
1618 * which is typically not possible, as the pointer to the allocated buffer is stored
1619 * in this message, and can therefore not be freed, hence we have a mem-leak-by-design.*/
1620 if (ls->p_cb->p_cback != NULL) {
1621 evt_data.status = BTA_JV_FAILURE;
1622 evt_data.handle = ls->handle;
1623 evt_data.req_id = ls->req_id;
1624 evt_data.cong = ls->p_cb->cong;
1625 evt_data.len = 0;
1626 bta_jv_pm_conn_busy(ls->p_cb->p_pm_cb);
1627 if (!evt_data.cong &&
1628 BT_PASS == GAP_ConnWriteData(ls->handle, ls->p_data, ls->len, &evt_data.len)) {
1629 evt_data.status = BTA_JV_SUCCESS;
1630 }
1631 ls->p_cb->p_cback(BTA_JV_L2CAP_WRITE_EVT, (tBTA_JV *)&evt_data, ls->user_data);
1632 bta_jv_set_pm_conn_state(ls->p_cb->p_pm_cb, BTA_JV_CONN_IDLE);
1633 } else {
1634 /* As this pointer is checked in the API function, this occurs only when the channel is
1635 * disconnected after the API function is called, but before the message is handled. */
1636 APPL_TRACE_ERROR("%s() ls->p_cb->p_cback == NULL", __func__);
1637 }
1638 }
1639
1640 /*******************************************************************************
1641 **
1642 ** Function bta_jv_l2cap_write_fixed
1643 **
1644 ** Description Write data to an L2CAP connection using Fixed channels
1645 **
1646 ** Returns void
1647 **
1648 *******************************************************************************/
bta_jv_l2cap_write_fixed(tBTA_JV_MSG * p_data)1649 void bta_jv_l2cap_write_fixed(tBTA_JV_MSG *p_data)
1650 {
1651 tBTA_JV_L2CAP_WRITE_FIXED evt_data;
1652 tBTA_JV_API_L2CAP_WRITE_FIXED *ls = &(p_data->l2cap_write_fixed);
1653 BT_HDR *msg = (BT_HDR *)osi_malloc(sizeof(BT_HDR) + ls->len + L2CAP_MIN_OFFSET);
1654 if (!msg) {
1655 APPL_TRACE_ERROR("%s() could not allocate msg buffer", __func__);
1656 return;
1657 }
1658 evt_data.status = BTA_JV_FAILURE;
1659 evt_data.channel = ls->channel;
1660 memcpy(evt_data.addr, ls->addr, sizeof(evt_data.addr));
1661 evt_data.req_id = ls->req_id;
1662 evt_data.len = 0;
1663
1664
1665 memcpy(((uint8_t *)(msg + 1)) + L2CAP_MIN_OFFSET, ls->p_data, ls->len);
1666 msg->len = ls->len;
1667 msg->offset = L2CAP_MIN_OFFSET;
1668
1669 L2CA_SendFixedChnlData(ls->channel, ls->addr, msg);
1670
1671 ls->p_cback(BTA_JV_L2CAP_WRITE_FIXED_EVT, (tBTA_JV *)&evt_data, ls->user_data);
1672 }
1673 #endif /* BTA_JV_L2CAP_INCLUDED */
1674
1675 #if BTA_JV_RFCOMM_INCLUDED
1676 /*******************************************************************************
1677 **
1678 ** Function bta_jv_port_data_co_cback
1679 **
1680 ** Description port data callback function of rfcomm
1681 ** connections
1682 **
1683 ** Returns void
1684 **
1685 *******************************************************************************/
bta_jv_port_data_co_cback(UINT16 port_handle,UINT8 * buf,UINT16 len,int type)1686 static int bta_jv_port_data_co_cback(UINT16 port_handle, UINT8 *buf, UINT16 len, int type)
1687 {
1688 tBTA_JV_RFC_CB *p_cb = bta_jv_rfc_port_to_cb(port_handle);
1689 tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
1690 int ret = 0;
1691 APPL_TRACE_DEBUG("%s, p_cb:%p, p_pcb:%p, len:%d, type:%d", __func__, p_cb, p_pcb, len, type);
1692 UNUSED(p_cb);
1693 if (p_pcb != NULL) {
1694 switch (type) {
1695 case DATA_CO_CALLBACK_TYPE_INCOMING:
1696 bta_jv_pm_conn_busy(p_pcb->p_pm_cb);
1697 ret = bta_co_rfc_data_incoming(p_pcb->user_data, (BT_HDR *)buf);
1698 bta_jv_pm_conn_idle(p_pcb->p_pm_cb);
1699 return ret;
1700 case DATA_CO_CALLBACK_TYPE_OUTGOING_SIZE:
1701 return bta_co_rfc_data_outgoing_size(p_pcb->user_data, (int *)buf);
1702 case DATA_CO_CALLBACK_TYPE_OUTGOING:
1703 return bta_co_rfc_data_outgoing(p_pcb->user_data, buf, len);
1704 default:
1705 APPL_TRACE_ERROR("unknown callout type:%d", type);
1706 break;
1707 }
1708 }
1709 return 0;
1710 }
1711
1712 /*******************************************************************************
1713 **
1714 ** Function bta_jv_port_mgmt_cl_cback
1715 **
1716 ** Description callback for port mamangement function of rfcomm
1717 ** client connections
1718 **
1719 ** Returns void
1720 **
1721 *******************************************************************************/
bta_jv_port_mgmt_cl_cback(UINT32 code,UINT16 port_handle,void * data)1722 static void bta_jv_port_mgmt_cl_cback(UINT32 code, UINT16 port_handle, void* data)
1723 {
1724 tBTA_JV_RFC_CB *p_cb = bta_jv_rfc_port_to_cb(port_handle);
1725 tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
1726 tBTA_JV evt_data = {0};
1727 BD_ADDR rem_bda = {0};
1728 UINT16 lcid;
1729 tBTA_JV_RFCOMM_CBACK *p_cback; /* the callback function */
1730 tPORT_MGMT_CL_CALLBACK_ARG *p_mgmt_cb_arg = (tPORT_MGMT_CL_CALLBACK_ARG *)data;
1731 void *user_data = NULL;
1732
1733 APPL_TRACE_DEBUG( "bta_jv_port_mgmt_cl_cback:code:%d, port_handle%d", code, port_handle);
1734 if (NULL == p_cb || NULL == p_cb->p_cback) {
1735 return;
1736 }
1737
1738 APPL_TRACE_DEBUG( "bta_jv_port_mgmt_cl_cback code=%d port_handle:%d handle:%d",
1739 code, port_handle, p_cb->handle);
1740
1741 PORT_CheckConnection(port_handle, FALSE, rem_bda, &lcid);
1742
1743 if (code == PORT_SUCCESS) {
1744 evt_data.rfc_open.handle = p_pcb->handle;
1745 evt_data.rfc_open.status = BTA_JV_SUCCESS;
1746 bdcpy(evt_data.rfc_open.rem_bda, rem_bda);
1747 p_pcb->state = BTA_JV_ST_CL_OPEN;
1748 if (p_mgmt_cb_arg) {
1749 evt_data.rfc_open.peer_mtu = p_mgmt_cb_arg->peer_mtu;
1750 }
1751 p_cb->p_cback(BTA_JV_RFCOMM_OPEN_EVT, &evt_data, p_pcb->user_data);
1752 } else {
1753 evt_data.rfc_close.handle = p_pcb->handle;
1754 evt_data.rfc_close.status = BTA_JV_FAILURE;
1755 evt_data.rfc_close.port_status = code;
1756 evt_data.rfc_close.async = TRUE;
1757 if (p_pcb->state == BTA_JV_ST_CL_CLOSING) {
1758 evt_data.rfc_close.async = FALSE;
1759 evt_data.rfc_close.status = BTA_JV_SUCCESS;
1760 }
1761 p_cback = p_cb->p_cback;
1762 user_data = p_pcb->user_data;
1763
1764 // To free up resources.
1765 p_pcb->state = BTA_JV_ST_CL_CLOSING;
1766 bta_jv_free_rfc_cb(p_cb, p_pcb, FALSE, FALSE);
1767 p_cback(BTA_JV_RFCOMM_CLOSE_EVT, &evt_data, user_data);
1768 }
1769 }
1770
1771 /*******************************************************************************
1772 **
1773 ** Function bta_jv_port_event_cl_cback
1774 **
1775 ** Description Callback for RFCOMM client port events
1776 **
1777 ** Returns void
1778 **
1779 *******************************************************************************/
bta_jv_port_event_cl_cback(UINT32 code,UINT16 port_handle)1780 static void bta_jv_port_event_cl_cback(UINT32 code, UINT16 port_handle)
1781 {
1782 tBTA_JV_RFC_CB *p_cb = bta_jv_rfc_port_to_cb(port_handle);
1783 tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
1784 tBTA_JV evt_data = {0};
1785
1786 APPL_TRACE_DEBUG( "bta_jv_port_event_cl_cback:%d", port_handle);
1787 if (NULL == p_cb || NULL == p_cb->p_cback) {
1788 return;
1789 }
1790
1791 APPL_TRACE_DEBUG( "bta_jv_port_event_cl_cback code=x%x port_handle:%d handle:%d",
1792 code, port_handle, p_cb->handle);
1793 if (code & PORT_EV_RXCHAR) {
1794 evt_data.data_ind.handle = p_pcb->handle;
1795 p_cb->p_cback(BTA_JV_RFCOMM_DATA_IND_EVT, &evt_data, p_pcb->user_data);
1796 }
1797
1798 if (code & PORT_EV_FC) {
1799 p_pcb->cong = (code & PORT_EV_FCS) ? FALSE : TRUE;
1800 evt_data.rfc_cong.cong = p_pcb->cong;
1801 evt_data.rfc_cong.handle = p_pcb->handle;
1802 evt_data.rfc_cong.status = BTA_JV_SUCCESS;
1803 p_cb->p_cback(BTA_JV_RFCOMM_CONG_EVT, &evt_data, p_pcb->user_data);
1804 }
1805
1806 if (code & PORT_EV_TXEMPTY) {
1807 bta_jv_pm_conn_idle(p_pcb->p_pm_cb);
1808 }
1809 }
1810
1811 /*******************************************************************************
1812 **
1813 ** Function bta_jv_rfcomm_config
1814 **
1815 ** Description Configure RFCOMM
1816 **
1817 ** Returns void
1818 **
1819 *******************************************************************************/
bta_jv_rfcomm_config(tBTA_JV_MSG * p_data)1820 void bta_jv_rfcomm_config(tBTA_JV_MSG *p_data)
1821 {
1822 APPL_TRACE_DEBUG("%s enable_l2cap_ertm:%d", __func__, p_data->rfcomm_config.enable_l2cap_ertm);
1823
1824 PORT_SetL2capErtm(p_data->rfcomm_config.enable_l2cap_ertm);
1825 }
1826
1827 /*******************************************************************************
1828 **
1829 ** Function bta_jv_rfcomm_connect
1830 **
1831 ** Description Client initiates an RFCOMM connection
1832 **
1833 ** Returns void
1834 **
1835 *******************************************************************************/
bta_jv_rfcomm_connect(tBTA_JV_MSG * p_data)1836 void bta_jv_rfcomm_connect(tBTA_JV_MSG *p_data)
1837 {
1838 UINT16 handle = 0;
1839 UINT32 event_mask = BTA_JV_RFC_EV_MASK;
1840 tPORT_STATE port_state;
1841 UINT8 sec_id = 0;
1842 tBTA_JV_RFC_CB *p_cb = NULL;
1843 tBTA_JV_PCB *p_pcb;
1844 tBTA_JV_API_RFCOMM_CONNECT *cc = &(p_data->rfcomm_connect);
1845 tBTA_JV_RFCOMM_CL_INIT evt_data = {0};
1846
1847 /* TODO DM role manager
1848 L2CA_SetDesireRole(cc->role);
1849 */
1850
1851 sec_id = bta_jv_alloc_sec_id();
1852 evt_data.sec_id = sec_id;
1853 evt_data.status = BTA_JV_SUCCESS;
1854 if (0 == sec_id ||
1855 BTM_SetSecurityLevel(TRUE, "", sec_id, cc->sec_mask, BT_PSM_RFCOMM,
1856 BTM_SEC_PROTO_RFCOMM, cc->remote_scn) == FALSE) {
1857 evt_data.status = BTA_JV_FAILURE;
1858 APPL_TRACE_ERROR("sec_id:%d is zero or BTM_SetSecurityLevel failed, remote_scn:%d", sec_id, cc->remote_scn);
1859 }
1860
1861 if (evt_data.status == BTA_JV_SUCCESS &&
1862 RFCOMM_CreateConnection(UUID_SERVCLASS_SERIAL_PORT, cc->remote_scn, FALSE,
1863 BTA_JV_DEF_RFC_MTU, cc->peer_bd_addr, &handle, bta_jv_port_mgmt_cl_cback) != PORT_SUCCESS) {
1864 APPL_TRACE_ERROR("bta_jv_rfcomm_connect, RFCOMM_CreateConnection failed");
1865 evt_data.status = BTA_JV_FAILURE;
1866 }
1867 if (evt_data.status == BTA_JV_SUCCESS) {
1868 p_cb = bta_jv_alloc_rfc_cb(handle, &p_pcb);
1869 if (p_cb) {
1870 p_cb->p_cback = cc->p_cback;
1871 p_cb->sec_id = sec_id;
1872 p_cb->scn = 0;
1873 p_pcb->state = BTA_JV_ST_CL_OPENING;
1874 p_pcb->user_data = cc->user_data;
1875 evt_data.use_co = TRUE;
1876
1877 PORT_SetEventCallback(handle, bta_jv_port_event_cl_cback);
1878 PORT_SetEventMask(handle, event_mask);
1879 PORT_SetDataCOCallback (handle, bta_jv_port_data_co_cback);
1880
1881 PORT_GetState(handle, &port_state);
1882
1883 port_state.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT);
1884
1885 /* coverity[uninit_use_in_call]
1886 FALSE-POSITIVE: port_state is initialized at PORT_GetState() */
1887 PORT_SetState(handle, &port_state);
1888
1889 evt_data.handle = p_pcb->handle;
1890 } else {
1891 evt_data.status = BTA_JV_FAILURE;
1892 APPL_TRACE_ERROR("run out of rfc control block");
1893 }
1894 }
1895 cc->p_cback(BTA_JV_RFCOMM_CL_INIT_EVT, (tBTA_JV *)&evt_data, cc->user_data);
1896 if (evt_data.status == BTA_JV_FAILURE) {
1897 if (sec_id) {
1898 bta_jv_free_sec_id(&sec_id);
1899 }
1900 if (handle) {
1901 RFCOMM_RemoveConnection(handle);
1902 }
1903 }
1904 }
1905
find_rfc_pcb(void * user_data,tBTA_JV_RFC_CB ** cb,tBTA_JV_PCB ** pcb)1906 static int find_rfc_pcb(void *user_data, tBTA_JV_RFC_CB **cb, tBTA_JV_PCB **pcb)
1907 {
1908 *cb = NULL;
1909 *pcb = NULL;
1910 int i;
1911 for (i = 0; i < MAX_RFC_PORTS; i++) {
1912 UINT32 rfc_handle = bta_jv_cb.port_cb[i].handle & BTA_JV_RFC_HDL_MASK;
1913 rfc_handle &= ~BTA_JV_RFCOMM_MASK;
1914 if (rfc_handle && bta_jv_cb.port_cb[i].user_data == user_data) {
1915 *pcb = &bta_jv_cb.port_cb[i];
1916 *cb = &bta_jv_cb.rfc_cb[rfc_handle - 1];
1917 APPL_TRACE_DEBUG("find_rfc_pcb(): FOUND rfc_cb_handle 0x%x, port.jv_handle:"
1918 " 0x%x, state: %d, rfc_cb->handle: 0x%x", rfc_handle, (*pcb)->handle,
1919 (*pcb)->state, (*cb)->handle);
1920 return 1;
1921 }
1922 }
1923 APPL_TRACE_DEBUG("find_rfc_pcb: cannot find rfc_cb from user data:%d", (UINT32)user_data);
1924 return 0;
1925 }
1926
1927 /*******************************************************************************
1928 **
1929 ** Function bta_jv_rfcomm_close
1930 **
1931 ** Description Close an RFCOMM connection
1932 **
1933 ** Returns void
1934 **
1935 *******************************************************************************/
bta_jv_rfcomm_close(tBTA_JV_MSG * p_data)1936 void bta_jv_rfcomm_close(tBTA_JV_MSG *p_data)
1937 {
1938 tBTA_JV_API_RFCOMM_CLOSE *cc = &(p_data->rfcomm_close);
1939 tBTA_JV_RFC_CB *p_cb = NULL;
1940 tBTA_JV_PCB *p_pcb = NULL;
1941 APPL_TRACE_DEBUG("%s, rfc handle:%d",__func__, cc->handle);
1942 if (!cc->handle) {
1943 APPL_TRACE_ERROR("%s, rfc handle is null", __func__);
1944 return;
1945 }
1946
1947 void *user_data = cc->user_data;
1948 if (!find_rfc_pcb(user_data, &p_cb, &p_pcb)) {
1949 return;
1950 }
1951
1952 bta_jv_free_rfc_cb(p_cb, p_pcb, FALSE, TRUE);
1953
1954 APPL_TRACE_DEBUG("%s: sec id in use:%d, rfc_cb in use:%d",__func__,
1955 get_sec_id_used(), get_rfc_cb_used());
1956 }
1957
1958 /*******************************************************************************
1959 **
1960 ** Function bta_jv_get_num_rfc_listen
1961 **
1962 ** Description when a RFCOMM connection goes down, make sure that there's only
1963 ** one port stays listening on this scn.
1964 **
1965 ** Returns
1966 **
1967 *******************************************************************************/
bta_jv_get_num_rfc_listen(tBTA_JV_RFC_CB * p_cb)1968 static UINT8 __attribute__((unused)) bta_jv_get_num_rfc_listen(tBTA_JV_RFC_CB *p_cb)
1969 {
1970 UINT8 listen = 1;
1971
1972 if (p_cb->max_sess > 1) {
1973 listen = 0;
1974 for (UINT8 i = 0; i < p_cb->max_sess; i++) {
1975 if (p_cb->rfc_hdl[i] != 0) {
1976 const tBTA_JV_PCB *p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[i] - 1];
1977 if (BTA_JV_ST_SR_LISTEN == p_pcb->state) {
1978 listen++;
1979 }
1980 }
1981 }
1982 }
1983 return listen;
1984 }
1985
1986 /*******************************************************************************
1987 **
1988 ** Function bta_jv_port_mgmt_sr_cback
1989 **
1990 ** Description callback for port mamangement function of rfcomm
1991 ** server connections
1992 **
1993 ** Returns void
1994 **
1995 *******************************************************************************/
bta_jv_port_mgmt_sr_cback(UINT32 code,UINT16 port_handle,void * data)1996 static void bta_jv_port_mgmt_sr_cback(UINT32 code, UINT16 port_handle, void *data)
1997 {
1998 tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
1999 tBTA_JV_RFC_CB *p_cb = bta_jv_rfc_port_to_cb(port_handle);
2000 tBTA_JV evt_data = {0};
2001 BD_ADDR rem_bda = {0};
2002 UINT16 lcid;
2003 tPORT_MGMT_SR_CALLBACK_ARG *p_mgmt_cb_arg = (tPORT_MGMT_SR_CALLBACK_ARG *)data;
2004 void *user_data = NULL;
2005 void *new_user_data = NULL;
2006 int status;
2007 int failed = TRUE;
2008
2009 // APPL_TRACE_DEBUG("bta_jv_port_mgmt_sr_cback, code:0x%x, port_handle:%d", code, (uint16_t)port_handle);
2010 if (NULL == p_cb || NULL == p_cb->p_cback) {
2011 // APPL_TRACE_ERROR("bta_jv_port_mgmt_sr_cback, p_cb:%p, p_cb->p_cback%p",
2012 // p_cb, p_cb ? p_cb->p_cback : NULL);
2013 return;
2014 }
2015 user_data = p_pcb->user_data;
2016 // APPL_TRACE_DEBUG( "bta_jv_port_mgmt_sr_cback code=%p port_handle:0x%x handle:0x%x, p_pcb:%p, user:%p",
2017 // code, port_handle, p_cb->handle, p_pcb, p_pcb->user_data);
2018
2019 if (p_mgmt_cb_arg) {
2020 if ((status = PORT_CheckConnection(port_handle, p_mgmt_cb_arg->ignore_rfc_state, rem_bda, &lcid)) !=
2021 PORT_SUCCESS) {
2022 APPL_TRACE_WARNING("PORT_CheckConnection status:%d", status);
2023 }
2024 } else {
2025 PORT_CheckConnection(port_handle, FALSE, rem_bda, &lcid);
2026 }
2027
2028 if (code == PORT_SUCCESS) {
2029 failed = FALSE;
2030 /* accept the connection defaulted */
2031 if (p_mgmt_cb_arg) {
2032 p_mgmt_cb_arg->accept = TRUE;
2033 }
2034 evt_data.rfc_srv_open.handle = p_pcb->handle;
2035 evt_data.rfc_srv_open.status = BTA_JV_SUCCESS;
2036 evt_data.rfc_srv_open.peer_mtu = p_mgmt_cb_arg->peer_mtu;
2037 bdcpy(evt_data.rfc_srv_open.rem_bda, rem_bda);
2038 tBTA_JV_PCB *p_pcb_new_listen = bta_jv_add_rfc_port(p_cb, p_pcb);
2039 if (p_pcb_new_listen) {
2040 evt_data.rfc_srv_open.new_listen_handle = p_pcb_new_listen->handle;
2041 new_user_data = p_cb->p_cback(BTA_JV_RFCOMM_SRV_OPEN_EVT, &evt_data, user_data);
2042 if (new_user_data) {
2043 p_pcb_new_listen->user_data = new_user_data;
2044 APPL_TRACE_DEBUG("PORT_SUCCESS: curr_sess:%d, max_sess:%d", p_cb->curr_sess,
2045 p_cb->max_sess);
2046 } else {
2047 /**
2048 * new_user_data is NULL, which means the upper layer runs out of slot source.
2049 * Tells the caller to reject this connection.
2050 */
2051 APPL_TRACE_ERROR("create new listen port, but upper layer reject connection");
2052 p_pcb_new_listen->user_data = NULL;
2053 p_pcb->state = BTA_JV_ST_SR_LISTEN;
2054 bta_jv_free_rfc_cb(p_cb, p_pcb_new_listen, FALSE, FALSE);
2055 if (p_mgmt_cb_arg) {
2056 p_mgmt_cb_arg->accept = FALSE;
2057 }
2058 }
2059 } else {
2060 evt_data.rfc_srv_open.new_listen_handle = 0;
2061 new_user_data = p_cb->p_cback(BTA_JV_RFCOMM_SRV_OPEN_EVT, &evt_data, user_data);
2062 if (new_user_data) {
2063 APPL_TRACE_DEBUG("PORT_SUCCESS: curr_sess:%d, max_sess:%d", p_cb->curr_sess,
2064 p_cb->max_sess);
2065 } else {
2066 /**
2067 * new_user_data is NULL, which means the upper layer runs out of slot source.
2068 * Tells the caller to reject this connection.
2069 */
2070 APPL_TRACE_ERROR("no listen port, and upper layer reject connection");
2071 p_pcb->state = BTA_JV_ST_SR_LISTEN;
2072 if (p_mgmt_cb_arg) {
2073 p_mgmt_cb_arg->accept = FALSE;
2074 }
2075 }
2076 APPL_TRACE_ERROR("bta_jv_add_rfc_port failed to create new listen port");
2077 }
2078 }
2079
2080 if (failed) {
2081 evt_data.rfc_close.handle = p_pcb->handle;
2082 evt_data.rfc_close.status = BTA_JV_FAILURE;
2083 evt_data.rfc_close.async = TRUE;
2084 evt_data.rfc_close.port_status = code;
2085 p_pcb->cong = FALSE;
2086
2087 tBTA_JV_RFCOMM_CBACK *p_cback = p_cb->p_cback;
2088 APPL_TRACE_DEBUG("PORT_CLOSED before BTA_JV_RFCOMM_CLOSE_EVT: curr_sess:%d, max_sess:%d",
2089 p_cb->curr_sess, p_cb->max_sess);
2090 if (BTA_JV_ST_SR_CLOSING == p_pcb->state) {
2091 evt_data.rfc_close.async = FALSE;
2092 evt_data.rfc_close.status = BTA_JV_SUCCESS;
2093 }
2094
2095 // To free up resources.
2096 p_pcb->state = BTA_JV_ST_SR_CLOSING;
2097 bta_jv_free_rfc_cb(p_cb, p_pcb, FALSE, FALSE);
2098 p_cback(BTA_JV_RFCOMM_CLOSE_EVT, &evt_data, user_data);
2099 APPL_TRACE_DEBUG("PORT_CLOSED after BTA_JV_RFCOMM_CLOSE_EVT: curr_sess:%d, max_sess:%d",
2100 p_cb->curr_sess, p_cb->max_sess);
2101 }
2102 }
2103
2104 /*******************************************************************************
2105 **
2106 ** Function bta_jv_port_event_sr_cback
2107 **
2108 ** Description Callback for RFCOMM server port events
2109 **
2110 ** Returns void
2111 **
2112 *******************************************************************************/
bta_jv_port_event_sr_cback(UINT32 code,UINT16 port_handle)2113 static void bta_jv_port_event_sr_cback(UINT32 code, UINT16 port_handle)
2114 {
2115 tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
2116 tBTA_JV_RFC_CB *p_cb = bta_jv_rfc_port_to_cb(port_handle);
2117 tBTA_JV evt_data = {0};
2118
2119 if (NULL == p_cb || NULL == p_cb->p_cback) {
2120 return;
2121 }
2122
2123 APPL_TRACE_DEBUG( "bta_jv_port_event_sr_cback code=x%x port_handle:%d handle:%d",
2124 code, port_handle, p_cb->handle);
2125
2126 void *user_data = p_pcb->user_data;
2127 if (code & PORT_EV_RXCHAR) {
2128 evt_data.data_ind.handle = p_pcb->handle;
2129 p_cb->p_cback(BTA_JV_RFCOMM_DATA_IND_EVT, &evt_data, user_data);
2130 }
2131
2132 if (code & PORT_EV_FC) {
2133 p_pcb->cong = (code & PORT_EV_FCS) ? FALSE : TRUE;
2134 evt_data.rfc_cong.cong = p_pcb->cong;
2135 evt_data.rfc_cong.handle = p_pcb->handle;
2136 evt_data.rfc_cong.status = BTA_JV_SUCCESS;
2137 p_cb->p_cback(BTA_JV_RFCOMM_CONG_EVT, &evt_data, user_data);
2138 }
2139
2140 if (code & PORT_EV_TXEMPTY) {
2141 bta_jv_pm_conn_idle(p_pcb->p_pm_cb);
2142 }
2143 }
2144
2145 /*******************************************************************************
2146 **
2147 ** Function bta_jv_add_rfc_port
2148 **
2149 ** Description add a port for server when the existing posts is open
2150 **
2151 ** Returns return a pointer to tBTA_JV_PCB just added
2152 **
2153 *******************************************************************************/
bta_jv_add_rfc_port(tBTA_JV_RFC_CB * p_cb,tBTA_JV_PCB * p_pcb_open)2154 static tBTA_JV_PCB *bta_jv_add_rfc_port(tBTA_JV_RFC_CB *p_cb, tBTA_JV_PCB *p_pcb_open)
2155 {
2156 UINT8 used = 0, i, listen = 0;
2157 UINT32 si = 0;
2158 tPORT_STATE port_state;
2159 UINT32 event_mask = BTA_JV_RFC_EV_MASK;
2160 tBTA_JV_PCB *p_pcb = NULL;
2161 if (p_cb->max_sess > 1) {
2162 for (i = 0; i < p_cb->max_sess; i++) {
2163 if (p_cb->rfc_hdl[i] != 0) {
2164 p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[i] - 1];
2165 if (p_pcb->state == BTA_JV_ST_SR_LISTEN) {
2166 listen++;
2167 if (p_pcb_open == p_pcb) {
2168 APPL_TRACE_DEBUG("bta_jv_add_rfc_port, port_handle:%d, change the listen port to open state",
2169 p_pcb->port_handle);
2170 p_pcb->state = BTA_JV_ST_SR_OPEN;
2171
2172 } else {
2173 APPL_TRACE_ERROR("bta_jv_add_rfc_port, open pcb not matching listen one,"
2174 "listen count:%d, listen pcb handle:%d, open pcb:%d",
2175 listen, p_pcb->port_handle, p_pcb_open->handle);
2176 return NULL;
2177 }
2178 }
2179 used++;
2180 } else if (si == 0) {
2181 si = i + 1;
2182 }
2183 }
2184
2185 p_pcb = NULL;
2186 APPL_TRACE_DEBUG("bta_jv_add_rfc_port max_sess=%d used:%d curr_sess:%d, listen:%d si:%d",
2187 p_cb->max_sess, used, p_cb->curr_sess, listen, si);
2188 if (used < p_cb->max_sess && listen == 1 && si) {
2189 si--;
2190 if (RFCOMM_CreateConnection(p_cb->sec_id, p_cb->scn, TRUE,
2191 BTA_JV_DEF_RFC_MTU, (UINT8 *) bd_addr_any, &(p_cb->rfc_hdl[si]), bta_jv_port_mgmt_sr_cback) == PORT_SUCCESS) {
2192 p_cb->curr_sess++;
2193 p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[si] - 1];
2194 p_pcb->state = BTA_JV_ST_SR_LISTEN;
2195 p_pcb->port_handle = p_cb->rfc_hdl[si];
2196 p_pcb->user_data = p_pcb_open->user_data;
2197
2198 PORT_ClearKeepHandleFlag(p_pcb->port_handle);
2199 PORT_SetEventCallback(p_pcb->port_handle, bta_jv_port_event_sr_cback);
2200 PORT_SetDataCOCallback (p_pcb->port_handle, bta_jv_port_data_co_cback);
2201 PORT_SetEventMask(p_pcb->port_handle, event_mask);
2202 PORT_GetState(p_pcb->port_handle, &port_state);
2203
2204 port_state.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT);
2205
2206 PORT_SetState(p_pcb->port_handle, &port_state);
2207 p_pcb->handle = BTA_JV_RFC_H_S_TO_HDL(p_cb->handle, si);
2208 APPL_TRACE_DEBUG("bta_jv_add_rfc_port: p_pcb->handle:0x%x, curr_sess:%d",
2209 p_pcb->handle, p_cb->curr_sess);
2210 }
2211 } else {
2212 /* avoid p_pcb always points to the last element of rfc_hdl */
2213 APPL_TRACE_ERROR("bta_jv_add_rfc_port, cannot create new rfc listen port");
2214 }
2215 }
2216 APPL_TRACE_DEBUG("bta_jv_add_rfc_port: sec id in use:%d, rfc_cb in use:%d",
2217 get_sec_id_used(), get_rfc_cb_used());
2218 return p_pcb;
2219 }
2220
2221 /*******************************************************************************
2222 **
2223 ** Function bta_jv_rfcomm_start_server
2224 **
2225 ** Description waits for an RFCOMM client to connect
2226 **
2227 **
2228 ** Returns void
2229 **
2230 *******************************************************************************/
bta_jv_rfcomm_start_server(tBTA_JV_MSG * p_data)2231 void bta_jv_rfcomm_start_server(tBTA_JV_MSG *p_data)
2232 {
2233 UINT16 handle = 0;
2234 UINT32 event_mask = BTA_JV_RFC_EV_MASK;
2235 tPORT_STATE port_state;
2236 UINT8 sec_id = 0;
2237 tBTA_JV_RFC_CB *p_cb = NULL;
2238 tBTA_JV_PCB *p_pcb;
2239 tBTA_JV_API_RFCOMM_SERVER *rs = &(p_data->rfcomm_server);
2240 tBTA_JV_RFCOMM_START evt_data = {0};
2241 /* TODO DM role manager
2242 L2CA_SetDesireRole(rs->role);
2243 */
2244 evt_data.status = BTA_JV_FAILURE;
2245 APPL_TRACE_DEBUG("bta_jv_rfcomm_start_server: sec id in use:%d, rfc_cb in use:%d",
2246 get_sec_id_used(), get_rfc_cb_used());
2247
2248 do {
2249 sec_id = bta_jv_alloc_sec_id();
2250
2251 if (0 == sec_id ||
2252 BTM_SetSecurityLevel(FALSE, "JV PORT", sec_id, rs->sec_mask,
2253 BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, rs->local_scn) == FALSE) {
2254 APPL_TRACE_ERROR("bta_jv_rfcomm_start_server, run out of sec_id");
2255 break;
2256 }
2257
2258 if (RFCOMM_CreateConnection(sec_id, rs->local_scn, TRUE,
2259 BTA_JV_DEF_RFC_MTU, (UINT8 *) bd_addr_any, &handle, bta_jv_port_mgmt_sr_cback) != PORT_SUCCESS) {
2260 APPL_TRACE_ERROR("bta_jv_rfcomm_start_server, RFCOMM_CreateConnection failed");
2261 break;
2262 }
2263
2264
2265 p_cb = bta_jv_alloc_rfc_cb(handle, &p_pcb);
2266 if (!p_cb) {
2267 APPL_TRACE_ERROR("bta_jv_rfcomm_start_server, run out of rfc control block");
2268 break;
2269 }
2270
2271 p_cb->max_sess = rs->max_session;
2272 p_cb->p_cback = rs->p_cback;
2273 p_cb->sec_id = sec_id;
2274 p_cb->scn = rs->local_scn;
2275 p_pcb->state = BTA_JV_ST_SR_LISTEN;
2276 p_pcb->user_data = rs->user_data;
2277 evt_data.status = BTA_JV_SUCCESS;
2278 evt_data.handle = p_pcb->handle;
2279 evt_data.sec_id = sec_id;
2280 evt_data.scn = rs->local_scn;
2281 evt_data.use_co = TRUE;
2282
2283 PORT_ClearKeepHandleFlag(handle);
2284 PORT_SetEventCallback(handle, bta_jv_port_event_sr_cback);
2285 PORT_SetEventMask(handle, event_mask);
2286 PORT_GetState(handle, &port_state);
2287
2288 port_state.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT);
2289
2290 PORT_SetState(handle, &port_state);
2291 } while (0);
2292
2293 rs->p_cback(BTA_JV_RFCOMM_START_EVT, (tBTA_JV *)&evt_data, rs->user_data);
2294 if (evt_data.status == BTA_JV_SUCCESS) {
2295 PORT_SetDataCOCallback (handle, bta_jv_port_data_co_cback);
2296 } else {
2297 if (sec_id) {
2298 bta_jv_free_sec_id(&sec_id);
2299 }
2300 if (handle) {
2301 RFCOMM_RemoveConnection(handle);
2302 }
2303 }
2304 }
2305
2306 /*******************************************************************************
2307 **
2308 ** Function bta_jv_rfcomm_stop_server
2309 **
2310 ** Description stops an RFCOMM server
2311 **
2312 ** Returns void
2313 **
2314 *******************************************************************************/
2315
bta_jv_rfcomm_stop_server(tBTA_JV_MSG * p_data)2316 void bta_jv_rfcomm_stop_server(tBTA_JV_MSG *p_data)
2317 {
2318 tBTA_JV_API_RFCOMM_SERVER *ls = &(p_data->rfcomm_server);
2319 tBTA_JV_RFC_CB *p_cb = NULL;
2320 tBTA_JV_PCB *p_pcb = NULL;
2321 APPL_TRACE_DEBUG("bta_jv_rfcomm_stop_server");
2322 if (!ls->handle) {
2323 APPL_TRACE_ERROR("bta_jv_rfcomm_stop_server, jv handle is null");
2324 return;
2325 }
2326 void *user_data = ls->user_data;
2327 if (!find_rfc_pcb(user_data, &p_cb, &p_pcb)) {
2328 return;
2329 }
2330 APPL_TRACE_DEBUG("bta_jv_rfcomm_stop_server: p_pcb:%p, p_pcb->port_handle:%d",
2331 p_pcb, p_pcb->port_handle);
2332 bta_jv_free_rfc_cb(p_cb, p_pcb, TRUE, FALSE);
2333 APPL_TRACE_DEBUG("bta_jv_rfcomm_stop_server: sec id in use:%d, rfc_cb in use:%d",
2334 get_sec_id_used(), get_rfc_cb_used());
2335 }
2336
2337 /*******************************************************************************
2338 **
2339 ** Function bta_jv_rfcomm_read
2340 **
2341 ** Description Read data from an RFCOMM connection
2342 **
2343 ** Returns void
2344 **
2345 *******************************************************************************/
bta_jv_rfcomm_read(tBTA_JV_MSG * p_data)2346 void bta_jv_rfcomm_read(tBTA_JV_MSG *p_data)
2347 {
2348 tBTA_JV_API_RFCOMM_READ *rc = &(p_data->rfcomm_read);
2349 tBTA_JV_RFC_CB *p_cb = rc->p_cb;
2350 tBTA_JV_PCB *p_pcb = rc->p_pcb;
2351 tBTA_JV_RFCOMM_READ evt_data;
2352
2353 evt_data.status = BTA_JV_FAILURE;
2354 evt_data.handle = p_pcb->handle;
2355 evt_data.req_id = rc->req_id;
2356 evt_data.p_data = rc->p_data;
2357 if (PORT_ReadData(rc->p_pcb->port_handle, (char *)rc->p_data, rc->len, &evt_data.len) ==
2358 PORT_SUCCESS) {
2359 evt_data.status = BTA_JV_SUCCESS;
2360 }
2361
2362 p_cb->p_cback(BTA_JV_RFCOMM_READ_EVT, (tBTA_JV *)&evt_data, p_pcb->user_data);
2363 }
2364
2365 /*******************************************************************************
2366 **
2367 ** Function bta_jv_rfcomm_write
2368 **
2369 ** Description write data to an RFCOMM connection
2370 **
2371 ** Returns void
2372 **
2373 *******************************************************************************/
bta_jv_rfcomm_write(tBTA_JV_MSG * p_data)2374 void bta_jv_rfcomm_write(tBTA_JV_MSG *p_data)
2375 {
2376 tBTA_JV_API_RFCOMM_WRITE *wc = &(p_data->rfcomm_write);
2377 tBTA_JV_RFC_CB *p_cb = wc->p_cb;
2378 tBTA_JV_PCB *p_pcb = wc->p_pcb;
2379 tBTA_JV_RFCOMM_WRITE evt_data;
2380
2381 evt_data.status = BTA_JV_FAILURE;
2382 evt_data.handle = p_pcb->handle;
2383 evt_data.req_id = wc->req_id;
2384 evt_data.old_cong = p_pcb->cong;
2385 bta_jv_pm_conn_busy(p_pcb->p_pm_cb);
2386 evt_data.len = -1;
2387 if (!evt_data.old_cong &&
2388 PORT_WriteDataCO(p_pcb->port_handle, &evt_data.len, wc->len, wc->p_data) ==
2389 PORT_SUCCESS) {
2390 evt_data.status = BTA_JV_SUCCESS;
2391 }
2392 // update congestion flag
2393 evt_data.cong = p_pcb->cong;
2394 if (p_cb->p_cback) {
2395 p_cb->p_cback(BTA_JV_RFCOMM_WRITE_EVT, (tBTA_JV *)&evt_data, p_pcb->user_data);
2396 } else {
2397 APPL_TRACE_ERROR("bta_jv_rfcomm_write :: WARNING ! No JV callback set");
2398 }
2399
2400 }
2401
2402 /*******************************************************************************
2403 **
2404 ** Function bta_jv_rfcomm_flow_control
2405 **
2406 ** Description give credits to the peer
2407 **
2408 ** Returns void
2409 **
2410 *******************************************************************************/
bta_jv_rfcomm_flow_control(tBTA_JV_MSG * p_data)2411 void bta_jv_rfcomm_flow_control(tBTA_JV_MSG *p_data)
2412 {
2413 tBTA_JV_API_RFCOMM_FLOW_CONTROL *fc = &(p_data->rfcomm_fc);
2414
2415 tBTA_JV_PCB *p_pcb = fc->p_pcb;
2416 PORT_FlowControl_GiveCredit(p_pcb->port_handle, TRUE, fc->credits_given);
2417 }
2418 #endif /* BTA_JV_RFCOMM_INCLUDED */
2419
2420 /*******************************************************************************
2421 **
2422 ** Function bta_jv_set_pm_profile
2423 **
2424 ** Description Set or free power mode profile for a JV application
2425 **
2426 ** Returns void
2427 **
2428 *******************************************************************************/
bta_jv_set_pm_profile(tBTA_JV_MSG * p_data)2429 void bta_jv_set_pm_profile(tBTA_JV_MSG *p_data)
2430 {
2431 tBTA_JV_STATUS status;
2432 tBTA_JV_PM_CB *p_cb;
2433
2434 APPL_TRACE_API("bta_jv_set_pm_profile(handle: 0x%x, app_id: %d, init_st: %d)",
2435 p_data->set_pm.handle, p_data->set_pm.app_id, p_data->set_pm.init_st);
2436
2437 /* clear PM control block */
2438 if (p_data->set_pm.app_id == BTA_JV_PM_ID_CLEAR) {
2439 status = bta_jv_free_set_pm_profile_cb(p_data->set_pm.handle);
2440
2441 if (status != BTA_JV_SUCCESS) {
2442 APPL_TRACE_WARNING("bta_jv_set_pm_profile() free pm cb failed: reason %d",
2443 status);
2444 }
2445 } else { /* set PM control block */
2446 p_cb = bta_jv_alloc_set_pm_profile_cb(p_data->set_pm.handle,
2447 p_data->set_pm.app_id);
2448
2449 if (NULL != p_cb) {
2450 bta_jv_pm_state_change(p_cb, p_data->set_pm.init_st);
2451 } else {
2452 APPL_TRACE_WARNING("bta_jv_alloc_set_pm_profile_cb() failed");
2453 }
2454 }
2455 }
2456
2457 /*******************************************************************************
2458 **
2459 ** Function bta_jv_change_pm_state
2460 **
2461 ** Description change jv pm connect state, used internally
2462 **
2463 ** Returns void
2464 **
2465 *******************************************************************************/
bta_jv_change_pm_state(tBTA_JV_MSG * p_data)2466 void bta_jv_change_pm_state(tBTA_JV_MSG *p_data)
2467 {
2468 tBTA_JV_API_PM_STATE_CHANGE *p_msg = (tBTA_JV_API_PM_STATE_CHANGE *)p_data;
2469
2470 if (p_msg->p_cb) {
2471 bta_jv_pm_state_change(p_msg->p_cb, p_msg->state);
2472 }
2473 }
2474
2475
2476 /*******************************************************************************
2477 **
2478 ** Function bta_jv_set_pm_conn_state
2479 **
2480 ** Description Send pm event state change to jv state machine to serialize jv pm changes
2481 ** in relation to other jv messages. internal API use mainly.
2482 **
2483 ** Params: p_cb: jv pm control block, NULL pointer returns failure
2484 ** new_state: new PM connections state, setting is forced by action function
2485 **
2486 ** Returns BTA_JV_SUCCESS, BTA_JV_FAILURE (buffer allocation, or NULL ptr!)
2487 **
2488 *******************************************************************************/
bta_jv_set_pm_conn_state(tBTA_JV_PM_CB * p_cb,const tBTA_JV_CONN_STATE new_st)2489 tBTA_JV_STATUS bta_jv_set_pm_conn_state(tBTA_JV_PM_CB *p_cb, const tBTA_JV_CONN_STATE
2490 new_st)
2491 {
2492 tBTA_JV_STATUS status = BTA_JV_FAILURE;
2493 tBTA_JV_API_PM_STATE_CHANGE *p_msg;
2494
2495 if (NULL == p_cb) {
2496 return status;
2497 }
2498
2499 APPL_TRACE_API("bta_jv_set_pm_conn_state(handle:0x%x, state: %d)", p_cb->handle,
2500 new_st);
2501 if ((p_msg = (tBTA_JV_API_PM_STATE_CHANGE *)osi_malloc(
2502 sizeof(tBTA_JV_API_PM_STATE_CHANGE))) != NULL) {
2503 p_msg->hdr.event = BTA_JV_API_PM_STATE_CHANGE_EVT;
2504 p_msg->p_cb = p_cb;
2505 p_msg->state = new_st;
2506 bta_sys_sendmsg(p_msg);
2507 status = BTA_JV_SUCCESS;
2508 }
2509 return (status);
2510 }
2511
2512 /*******************************************************************************
2513 **
2514 ** Function bta_jv_pm_conn_busy
2515 **
2516 ** Description set pm connection busy state (input param safe)
2517 **
2518 ** Params p_cb: pm control block of jv connection
2519 **
2520 ** Returns void
2521 **
2522 *******************************************************************************/
bta_jv_pm_conn_busy(tBTA_JV_PM_CB * p_cb)2523 static void bta_jv_pm_conn_busy(tBTA_JV_PM_CB *p_cb)
2524 {
2525 if ((NULL != p_cb) && (BTA_JV_PM_IDLE_ST == p_cb->state)) {
2526 bta_jv_pm_state_change(p_cb, BTA_JV_CONN_BUSY);
2527 }
2528 }
2529
2530 /*******************************************************************************
2531 **
2532 ** Function bta_jv_pm_conn_busy
2533 **
2534 ** Description set pm connection busy state (input param safe)
2535 **
2536 ** Params p_cb: pm control block of jv connection
2537 **
2538 ** Returns void
2539 **
2540 *******************************************************************************/
bta_jv_pm_conn_idle(tBTA_JV_PM_CB * p_cb)2541 static void bta_jv_pm_conn_idle(tBTA_JV_PM_CB *p_cb)
2542 {
2543 if ((NULL != p_cb) && (BTA_JV_PM_IDLE_ST != p_cb->state)) {
2544 bta_jv_pm_state_change(p_cb, BTA_JV_CONN_IDLE);
2545 }
2546 }
2547
2548 /*******************************************************************************
2549 **
2550 ** Function bta_jv_pm_state_change
2551 **
2552 ** Description Notify power manager there is state change
2553 **
2554 ** Params p_cb: must be NONE NULL
2555 **
2556 ** Returns void
2557 **
2558 *******************************************************************************/
bta_jv_pm_state_change(tBTA_JV_PM_CB * p_cb,const tBTA_JV_CONN_STATE state)2559 static void bta_jv_pm_state_change(tBTA_JV_PM_CB *p_cb, const tBTA_JV_CONN_STATE state)
2560 {
2561 APPL_TRACE_API("bta_jv_pm_state_change(p_cb: 0x%x, handle: 0x%x, busy/idle_state: %d"
2562 ", app_id: %d, conn_state: %d)", (uint32_t)p_cb, p_cb->handle, p_cb->state,
2563 p_cb->app_id, state);
2564
2565 switch (state) {
2566 case BTA_JV_CONN_OPEN:
2567 bta_sys_conn_open(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr);
2568 break;
2569
2570 case BTA_JV_CONN_CLOSE:
2571 bta_sys_conn_close(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr);
2572 break;
2573
2574 case BTA_JV_APP_OPEN:
2575 bta_sys_app_open(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr);
2576 break;
2577
2578 case BTA_JV_APP_CLOSE:
2579 bta_sys_app_close(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr);
2580 break;
2581
2582 case BTA_JV_SCO_OPEN:
2583 bta_sys_sco_open(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr);
2584 break;
2585
2586 case BTA_JV_SCO_CLOSE:
2587 bta_sys_sco_close(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr);
2588 break;
2589
2590 case BTA_JV_CONN_IDLE:
2591 p_cb->state = BTA_JV_PM_IDLE_ST;
2592 bta_sys_idle(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr);
2593 break;
2594
2595 case BTA_JV_CONN_BUSY:
2596 p_cb->state = BTA_JV_PM_BUSY_ST;
2597 bta_sys_busy(BTA_ID_JV, p_cb->app_id, p_cb->peer_bd_addr);
2598 break;
2599
2600 default:
2601 APPL_TRACE_WARNING("bta_jv_pm_state_change(state: %d): Invalid state", state);
2602 break;
2603 }
2604 }
2605 /**********************************************************************************************/
2606
2607 #if BTA_JV_L2CAP_INCLUDED
fcchan_get(uint16_t chan,char create)2608 static struct fc_channel *fcchan_get(uint16_t chan, char create)
2609 {
2610 struct fc_channel *t = fc_channels;
2611 static tL2CAP_FIXED_CHNL_REG fcr = {
2612 .pL2CA_FixedConn_Cb = fcchan_conn_chng_cbk,
2613 .pL2CA_FixedData_Cb = fcchan_data_cbk,
2614 .default_idle_tout = 0xffff,
2615 .fixed_chnl_opts = {
2616 .mode = L2CAP_FCR_BASIC_MODE,
2617 .max_transmit = 0xFF,
2618 .rtrans_tout = 2000,
2619 .mon_tout = 12000,
2620 .mps = 670,
2621 .tx_win_sz = 1,
2622 },
2623 };
2624
2625 while (t && t->chan != chan) {
2626 t = t->next;
2627 }
2628
2629 if (t) {
2630 return t;
2631 } else if (!create) {
2632 return NULL; /* we cannot alloc a struct if not asked to */
2633 }
2634
2635 t = osi_calloc(sizeof(*t));
2636 if (!t) {
2637 return NULL;
2638 }
2639
2640 t->chan = chan;
2641
2642 if (!L2CA_RegisterFixedChannel(chan, &fcr)) {
2643 osi_free(t);
2644 return NULL;
2645 }
2646
2647 //link it in
2648 t->next = fc_channels;
2649 fc_channels = t;
2650
2651 return t;
2652 }
2653
2654 /* pass NULL to find servers */
fcclient_find_by_addr(struct fc_client * start,BD_ADDR addr)2655 static struct fc_client *fcclient_find_by_addr(struct fc_client *start, BD_ADDR addr)
2656 {
2657 struct fc_client *t = start;
2658
2659 while (t) {
2660
2661 /* match client if have addr */
2662 if (addr && !memcmp(addr, &t->remote_addr, sizeof(t->remote_addr))) {
2663 break;
2664 }
2665
2666 /* match server if do not have addr */
2667 if (!addr && t->server) {
2668 break;
2669 }
2670
2671 t = t->next_all_list;
2672 }
2673
2674 return t;
2675 }
2676
fcclient_find_by_id(uint32_t id)2677 static struct fc_client *fcclient_find_by_id(uint32_t id)
2678 {
2679 struct fc_client *t = fc_clients;
2680
2681 while (t && t->id != id) {
2682 t = t->next_all_list;
2683 }
2684
2685 return t;
2686 }
2687
fcclient_alloc(uint16_t chan,char server,const uint8_t * sec_id_to_use)2688 static struct fc_client *fcclient_alloc(uint16_t chan, char server, const uint8_t *sec_id_to_use)
2689 {
2690 struct fc_channel *fc = fcchan_get(chan, TRUE);
2691 struct fc_client *t;
2692 uint8_t sec_id;
2693
2694 if (!fc) {
2695 return NULL;
2696 }
2697
2698 if (fc->has_server && server) {
2699 return NULL; /* no way to have multiple servers on same channel */
2700 }
2701
2702 if (sec_id_to_use) {
2703 sec_id = *sec_id_to_use;
2704 } else {
2705 sec_id = bta_jv_alloc_sec_id();
2706 }
2707
2708 t = osi_calloc(sizeof(*t));
2709 if (t) {
2710 //allocate it a unique ID
2711 do {
2712 t->id = ++fc_next_id;
2713 } while (!t->id || fcclient_find_by_id(t->id));
2714
2715 //populate some params
2716 t->chan = chan;
2717 t->server = server;
2718
2719 //get a security id
2720 t->sec_id = sec_id;
2721
2722 //link it in to global list
2723 t->next_all_list = fc_clients;
2724 fc_clients = t;
2725
2726 //link it in to channel list
2727 t->next_chan_list = fc->clients;
2728 fc->clients = t;
2729
2730 //update channel if needed
2731 if (server) {
2732 fc->has_server = TRUE;
2733 }
2734 } else if (!sec_id_to_use) {
2735 bta_jv_free_sec_id(&sec_id);
2736 }
2737
2738 return t;
2739 }
2740
fcclient_free(struct fc_client * fc)2741 static void fcclient_free(struct fc_client *fc)
2742 {
2743 struct fc_client *t = fc_clients;
2744 struct fc_channel *tc = fcchan_get(fc->chan, FALSE);
2745
2746 //remove from global list
2747 while (t && t->next_all_list != fc) {
2748 t = t->next_all_list;
2749 }
2750
2751 if (!t && fc != fc_clients) {
2752 return; /* prevent double-free */
2753 }
2754
2755 if (t) {
2756 t->next_all_list = fc->next_all_list;
2757 } else {
2758 fc_clients = fc->next_all_list;
2759 }
2760
2761 //remove from channel list
2762 if (tc) {
2763 t = tc->clients;
2764
2765 while (t && t->next_chan_list != fc) {
2766 t = t->next_chan_list;
2767 }
2768
2769 if (t) {
2770 t->next_chan_list = fc->next_chan_list;
2771 } else {
2772 tc->clients = fc->next_chan_list;
2773 }
2774
2775 //if was server then channel no longer has a server
2776 if (fc->server) {
2777 tc->has_server = FALSE;
2778 }
2779 }
2780
2781 //free security id
2782 bta_jv_free_sec_id(&fc->sec_id);
2783
2784 osi_free(fc);
2785 }
2786
fcchan_conn_chng_cbk(UINT16 chan,BD_ADDR bd_addr,BOOLEAN connected,UINT16 reason,tBT_TRANSPORT transport)2787 static void fcchan_conn_chng_cbk(UINT16 chan, BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason, tBT_TRANSPORT transport)
2788 {
2789 tBTA_JV init_evt;
2790 tBTA_JV open_evt;
2791 struct fc_channel *tc;
2792 struct fc_client *t = NULL, *new_conn;
2793 tBTA_JV_L2CAP_CBACK *p_cback = NULL;
2794 char call_init = FALSE;
2795 void *user_data = NULL;
2796
2797
2798 tc = fcchan_get(chan, FALSE);
2799 if (tc) {
2800 t = fcclient_find_by_addr(tc->clients, bd_addr); // try to find an open socked for that addr
2801 if (t) {
2802 p_cback = t->p_cback;
2803 user_data = t->user_data;
2804 } else {
2805 t = fcclient_find_by_addr(tc->clients, NULL); // try to find a listening socked for that channel
2806 if (t) {
2807 //found: create a normal connection socket and assign the connection to it
2808 new_conn = fcclient_alloc(chan, FALSE, &t->sec_id);
2809 if (new_conn) {
2810
2811 memcpy(&new_conn->remote_addr, bd_addr, sizeof(new_conn->remote_addr));
2812 new_conn->p_cback = NULL; //for now
2813 new_conn->init_called = TRUE; /*nop need to do it again */
2814
2815 p_cback = t->p_cback;
2816 user_data = t->user_data;
2817
2818 t = new_conn;
2819 }
2820 } else {
2821 //drop it
2822 return;
2823 }
2824 }
2825 }
2826
2827 if (t) {
2828
2829 if (!t->init_called) {
2830
2831 call_init = TRUE;
2832 t->init_called = TRUE;
2833
2834 init_evt.l2c_cl_init.handle = t->id;
2835 init_evt.l2c_cl_init.status = BTA_JV_SUCCESS;
2836 init_evt.l2c_cl_init.sec_id = t->sec_id;
2837 }
2838
2839 open_evt.l2c_open.handle = t->id;
2840 open_evt.l2c_open.tx_mtu = 23; /* 23, why not ?*/
2841 memcpy(&open_evt.l2c_le_open.rem_bda, &t->remote_addr, sizeof(open_evt.l2c_le_open.rem_bda));
2842 open_evt.l2c_le_open.p_p_cback = (void **)&t->p_cback;
2843 open_evt.l2c_le_open.p_user_data = &t->user_data;
2844 open_evt.l2c_le_open.status = BTA_JV_SUCCESS;
2845
2846 if (connected) {
2847 open_evt.l2c_open.status = BTA_JV_SUCCESS;
2848 } else {
2849 fcclient_free(t);
2850 open_evt.l2c_open.status = BTA_JV_FAILURE;
2851 }
2852 }
2853
2854 if (call_init) {
2855 p_cback(BTA_JV_L2CAP_CL_INIT_EVT, &init_evt, user_data);
2856 }
2857
2858 //call this with lock taken so socket does not disappear from under us */
2859 if (p_cback) {
2860 p_cback(BTA_JV_L2CAP_OPEN_EVT, &open_evt, user_data);
2861 if (!t->p_cback) { /* no callback set, means they do not want this one... */
2862 fcclient_free(t);
2863 }
2864 }
2865 }
2866
fcchan_data_cbk(UINT16 chan,BD_ADDR bd_addr,BT_HDR * p_buf)2867 static void fcchan_data_cbk(UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf)
2868 {
2869 tBTA_JV evt_data = {0};
2870 // tBTA_JV evt_open;
2871 struct fc_channel *tc;
2872 struct fc_client *t = NULL;
2873 tBTA_JV_L2CAP_CBACK *sock_cback = NULL;
2874 void *sock_user_data;
2875
2876 tc = fcchan_get(chan, FALSE);
2877 if (tc) {
2878 t = fcclient_find_by_addr(tc->clients, bd_addr); // try to find an open socked for that addr and channel
2879 if (!t) {
2880 //no socket -> drop it
2881 return;
2882 }
2883 }
2884
2885 sock_cback = t->p_cback;
2886 sock_user_data = t->user_data;
2887 evt_data.le_data_ind.handle = t->id;
2888 evt_data.le_data_ind.p_buf = p_buf;
2889
2890 if (sock_cback) {
2891 sock_cback(BTA_JV_L2CAP_DATA_IND_EVT, &evt_data, sock_user_data);
2892 }
2893 }
2894
2895
2896 /*******************************************************************************
2897 **
2898 ** Function bta_jv_l2cap_connect_le
2899 **
2900 ** Description makes an le l2cap client connection
2901 **
2902 ** Returns void
2903 **
2904 *******************************************************************************/
bta_jv_l2cap_connect_le(tBTA_JV_MSG * p_data)2905 void bta_jv_l2cap_connect_le(tBTA_JV_MSG *p_data)
2906 {
2907 tBTA_JV_API_L2CAP_CONNECT *cc = &(p_data->l2cap_connect);
2908 tBTA_JV evt;
2909 uint32_t id;
2910 char call_init_f = TRUE;
2911 struct fc_client *t;
2912
2913 evt.l2c_cl_init.handle = GAP_INVALID_HANDLE;
2914 evt.l2c_cl_init.status = BTA_JV_FAILURE;
2915
2916 t = fcclient_alloc(cc->remote_chan, FALSE, NULL);
2917 if (!t) {
2918 cc->p_cback(BTA_JV_L2CAP_CL_INIT_EVT, &evt, cc->user_data);
2919 return;
2920 }
2921
2922 t->p_cback = cc->p_cback;
2923 t->user_data = cc->user_data;
2924 memcpy(&t->remote_addr, &cc->peer_bd_addr, sizeof(t->remote_addr));
2925 id = t->id;
2926 t->init_called = FALSE;
2927
2928 if (L2CA_ConnectFixedChnl(t->chan, t->remote_addr, BLE_ADDR_UNKNOWN_TYPE, FALSE)) {
2929
2930 evt.l2c_cl_init.status = BTA_JV_SUCCESS;
2931 evt.l2c_cl_init.handle = id;
2932 }
2933
2934 //it could have been deleted/moved from under us, so re-find it */
2935 t = fcclient_find_by_id(id);
2936 if (t) {
2937 if (evt.l2c_cl_init.status == BTA_JV_SUCCESS) {
2938 call_init_f = !t->init_called;
2939 } else {
2940 fcclient_free(t);
2941 }
2942 }
2943 if (call_init_f) {
2944 cc->p_cback(BTA_JV_L2CAP_CL_INIT_EVT, &evt, cc->user_data);
2945 }
2946 t->init_called = TRUE;
2947 }
2948
2949
2950 /*******************************************************************************
2951 **
2952 ** Function bta_jv_l2cap_stop_server_le
2953 **
2954 ** Description stops an LE L2CAP server
2955 **
2956 ** Returns void
2957 **
2958 *******************************************************************************/
bta_jv_l2cap_stop_server_le(tBTA_JV_MSG * p_data)2959 void bta_jv_l2cap_stop_server_le(tBTA_JV_MSG *p_data)
2960 {
2961 tBTA_JV evt;
2962 tBTA_JV_API_L2CAP_SERVER *ls = &(p_data->l2cap_server);
2963 tBTA_JV_L2CAP_CBACK *p_cback = NULL;
2964 struct fc_channel *fcchan;
2965 struct fc_client *fcclient;
2966 void *user_data;
2967
2968 evt.l2c_close.status = BTA_JV_FAILURE;
2969 evt.l2c_close.async = FALSE;
2970 evt.l2c_close.handle = GAP_INVALID_HANDLE;
2971
2972 fcchan = fcchan_get(ls->local_chan, FALSE);
2973 if (fcchan) {
2974 while ((fcclient = fcchan->clients)) {
2975 p_cback = fcclient->p_cback;
2976 user_data = fcclient->user_data;
2977
2978 evt.l2c_close.handle = fcclient->id;
2979 evt.l2c_close.status = BTA_JV_SUCCESS;
2980 evt.l2c_close.async = FALSE;
2981
2982 fcclient_free(fcclient);
2983
2984 if (p_cback) {
2985 p_cback(BTA_JV_L2CAP_CLOSE_EVT, &evt, user_data);
2986 }
2987 }
2988 }
2989 }
2990
2991 /*******************************************************************************
2992 **
2993 ** Function bta_jv_l2cap_start_server_le
2994 **
2995 ** Description starts an LE L2CAP server
2996 **
2997 ** Returns void
2998 **
2999 *******************************************************************************/
bta_jv_l2cap_start_server_le(tBTA_JV_MSG * p_data)3000 void bta_jv_l2cap_start_server_le(tBTA_JV_MSG *p_data)
3001 {
3002 tBTA_JV_API_L2CAP_SERVER *ss = &(p_data->l2cap_server);
3003 tBTA_JV_L2CAP_START evt_data;
3004 struct fc_client *t;
3005 // uint16_t handle;
3006
3007 evt_data.handle = GAP_INVALID_HANDLE;
3008 evt_data.status = BTA_JV_FAILURE;
3009
3010
3011 t = fcclient_alloc(ss->local_chan, TRUE, NULL);
3012 if (!t) {
3013 goto out;
3014 }
3015
3016 t->p_cback = ss->p_cback;
3017 t->user_data = ss->user_data;
3018
3019 //if we got here, we're registered...
3020 evt_data.status = BTA_JV_SUCCESS;
3021 evt_data.handle = t->id;
3022 evt_data.sec_id = t->sec_id;
3023
3024 out:
3025 ss->p_cback(BTA_JV_L2CAP_START_EVT, (tBTA_JV *)&evt_data, ss->user_data);
3026 }
3027
3028 /*******************************************************************************
3029 **
3030 ** Function bta_jv_l2cap_close_fixed
3031 **
3032 ** Description close a fixed channel connection. calls no callbacks. idempotent
3033 **
3034 ** Returns void
3035 **
3036 *******************************************************************************/
bta_jv_l2cap_close_fixed(tBTA_JV_MSG * p_data)3037 extern void bta_jv_l2cap_close_fixed (tBTA_JV_MSG *p_data)
3038 {
3039 tBTA_JV_API_L2CAP_CLOSE *cc = &(p_data->l2cap_close);
3040 struct fc_client *t;
3041
3042 t = fcclient_find_by_id(cc->handle);
3043 if (t) {
3044 fcclient_free(t);
3045 }
3046 }
3047 #endif /* BTA_JV_L2CAP_INCLUDED */
3048
3049 #endif ///defined BTA_JV_INCLUDED && BTA_JV_INCLUDED == TRUE
3050