blob: e52b90b2f80c5ff10decf57b9040e30a40122ac7 [file] [log] [blame]
The Android Open Source Project5738f832012-12-12 16:00:35 -08001/******************************************************************************
2 *
3 * Copyright (C) 1999-2012 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19/******************************************************************************
20 *
21 * This file contains the L2CAP UCD code
22 *
23 ******************************************************************************/
24
Myles Watson911d1ae2016-11-28 16:44:40 -080025#include <stdio.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080026#include <stdlib.h>
27#include <string.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080028
Pavlin Radoslavov258c2532015-09-27 20:59:05 -070029#include "bt_common.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080030#include "bt_types.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080031#include "btm_api.h"
32#include "btm_int.h"
Myles Watson911d1ae2016-11-28 16:44:40 -080033#include "btu.h"
34#include "hcidefs.h"
35#include "hcimsgs.h"
36#include "l2c_int.h"
37#include "l2cdefs.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080038
39#if (L2CAP_UCD_INCLUDED == TRUE)
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -080040
Myles Watson911d1ae2016-11-28 16:44:40 -080041extern fixed_queue_t* btu_bta_alarm_queue;
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -080042
Jakub Pawlowskia484a882017-06-24 17:30:18 -070043static bool l2c_ucd_connect(const RawAddress& rem_bda);
The Android Open Source Project5738f832012-12-12 16:00:35 -080044
45/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -080046 *
47 * Function l2c_ucd_discover_cback
48 *
49 * Description UCD Discover callback
50 *
51 * Returns void
52 *
53 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -070054static void l2c_ucd_discover_cback(const RawAddress& rem_bda, uint8_t info_type,
55 uint32_t data) {
Myles Watson911d1ae2016-11-28 16:44:40 -080056 tL2C_RCB* p_rcb = &l2cb.rcb_pool[0];
57 uint16_t xx;
The Android Open Source Project5738f832012-12-12 16:00:35 -080058
Myles Watson911d1ae2016-11-28 16:44:40 -080059 L2CAP_TRACE_DEBUG("L2CAP - l2c_ucd_discover_cback");
The Android Open Source Project5738f832012-12-12 16:00:35 -080060
Myles Watson911d1ae2016-11-28 16:44:40 -080061 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
62 if (p_rcb->in_use) {
63 /* if this application is waiting UCD reception info */
64 if ((info_type == L2CAP_UCD_INFO_TYPE_RECEPTION) &&
65 (p_rcb->ucd.state & L2C_UCD_STATE_W4_RECEPTION)) {
66 p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb(rem_bda, info_type, data);
67 p_rcb->ucd.state &= ~(L2C_UCD_STATE_W4_RECEPTION);
68 }
The Android Open Source Project5738f832012-12-12 16:00:35 -080069
Myles Watson911d1ae2016-11-28 16:44:40 -080070 /* if this application is waiting UCD MTU info */
71 if ((info_type == L2CAP_UCD_INFO_TYPE_MTU) &&
72 (p_rcb->ucd.state & L2C_UCD_STATE_W4_MTU)) {
73 p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb(rem_bda, info_type, data);
74 p_rcb->ucd.state &= ~(L2C_UCD_STATE_W4_MTU);
75 }
The Android Open Source Project5738f832012-12-12 16:00:35 -080076 }
Myles Watson911d1ae2016-11-28 16:44:40 -080077 }
The Android Open Source Project5738f832012-12-12 16:00:35 -080078}
79
80/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -080081 *
82 * Function l2c_ucd_data_ind_cback
83 *
84 * Description UCD Data callback
85 *
86 * Returns void
87 *
88 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -070089static void l2c_ucd_data_ind_cback(const RawAddress& rem_bda, BT_HDR* p_buf) {
Myles Watson911d1ae2016-11-28 16:44:40 -080090 uint8_t* p;
91 uint16_t psm;
92 tL2C_RCB* p_rcb;
The Android Open Source Project5738f832012-12-12 16:00:35 -080093
Myles Watson911d1ae2016-11-28 16:44:40 -080094 L2CAP_TRACE_DEBUG("L2CAP - l2c_ucd_data_ind_cback");
The Android Open Source Project5738f832012-12-12 16:00:35 -080095
Myles Watson911d1ae2016-11-28 16:44:40 -080096 p = (uint8_t*)(p_buf + 1) + p_buf->offset;
97 STREAM_TO_UINT16(psm, p)
The Android Open Source Project5738f832012-12-12 16:00:35 -080098
Myles Watson911d1ae2016-11-28 16:44:40 -080099 p_buf->offset += L2CAP_UCD_OVERHEAD;
100 p_buf->len -= L2CAP_UCD_OVERHEAD;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800101
Myles Watson911d1ae2016-11-28 16:44:40 -0800102 p_rcb = l2cu_find_rcb_by_psm(psm);
103 if (p_rcb == NULL) {
104 L2CAP_TRACE_ERROR("L2CAP - no RCB for l2c_ucd_data_ind_cback, PSM: 0x%04x",
105 psm);
106 osi_free(p_buf);
107 } else {
108 p_rcb->ucd.cb_info.pL2CA_UCD_Data_Cb(rem_bda, p_buf);
109 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800110}
111
112/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800113 *
114 * Function l2c_ucd_congestion_status_cback
115 *
116 * Description UCD Congestion Status callback
117 *
118 * Returns void
119 *
120 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700121static void l2c_ucd_congestion_status_cback(const RawAddress& rem_bda,
Myles Watson911d1ae2016-11-28 16:44:40 -0800122 bool is_congested) {
123 tL2C_RCB* p_rcb = &l2cb.rcb_pool[0];
124 uint16_t xx;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800125
Myles Watson911d1ae2016-11-28 16:44:40 -0800126 L2CAP_TRACE_DEBUG("L2CAP - l2c_ucd_congestion_status_cback");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800127
Myles Watson911d1ae2016-11-28 16:44:40 -0800128 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
129 if ((p_rcb->in_use) && (p_rcb->ucd.state != L2C_UCD_STATE_UNUSED)) {
130 if (p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb) {
131 L2CAP_TRACE_DEBUG(
132 "L2CAP - Calling UCDCongestionStatus_Cb (%d), PSM=0x%04x, BDA: "
133 "%08x%04x,",
134 is_congested, p_rcb->psm, (rem_bda[0] << 24) + (rem_bda[1] << 16) +
135 (rem_bda[2] << 8) + rem_bda[3],
136 (rem_bda[4] << 8) + rem_bda[5]);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800137
Myles Watson911d1ae2016-11-28 16:44:40 -0800138 p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb(rem_bda,
139 is_congested);
140 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800141 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800142 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800143}
144
145/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800146 *
147 * Function l2c_ucd_disconnect_ind_cback
148 *
Myles Watson9ca07092016-11-28 16:41:53 -0800149 * Description UCD disconnect callback (Prevent to access null pointer)
Myles Watsonee96a3c2016-11-23 14:49:54 -0800150 *
151 * Returns void
152 *
153 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800154static void l2c_ucd_disconnect_ind_cback(uint16_t cid, bool result) {
155 /* do nothing */
The Android Open Source Project5738f832012-12-12 16:00:35 -0800156}
157
158/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800159 *
160 * Function l2c_ucd_config_ind_cback
161 *
162 * Description UCD config callback (This prevent to access null pointer)
163 *
164 * Returns void
165 *
166 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800167static void l2c_ucd_config_ind_cback(uint16_t cid, tL2CAP_CFG_INFO* p_cfg) {
168 /* do nothing */
The Android Open Source Project5738f832012-12-12 16:00:35 -0800169}
170
171/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800172 *
173 * Function l2c_ucd_config_cfm_cback
174 *
175 * Description UCD config callback (This prevent to access null pointer)
176 *
177 * Returns void
178 *
179 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800180static void l2c_ucd_config_cfm_cback(uint16_t cid, tL2CAP_CFG_INFO* p_cfg) {
181 /* do nothing */
The Android Open Source Project5738f832012-12-12 16:00:35 -0800182}
183
184/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800185 *
186 * Function L2CA_UcdRegister
187 *
188 * Description Register PSM on UCD.
189 *
190 * Parameters: tL2CAP_UCD_CB_INFO
191 *
192 * Return value: true if successs
193 *
194 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800195bool L2CA_UcdRegister(uint16_t psm, tL2CAP_UCD_CB_INFO* p_cb_info) {
196 tL2C_RCB* p_rcb;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800197
Myles Watson911d1ae2016-11-28 16:44:40 -0800198 L2CAP_TRACE_API("L2CA_UcdRegister() PSM: 0x%04x", psm);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800199
Myles Watson911d1ae2016-11-28 16:44:40 -0800200 if ((!p_cb_info->pL2CA_UCD_Discover_Cb) || (!p_cb_info->pL2CA_UCD_Data_Cb)) {
201 L2CAP_TRACE_ERROR("L2CAP - no callback registering PSM(0x%04x) on UCD",
202 psm);
203 return (false);
204 }
205
206 p_rcb = l2cu_find_rcb_by_psm(psm);
207 if (p_rcb == NULL) {
208 L2CAP_TRACE_ERROR("L2CAP - no RCB for L2CA_UcdRegister, PSM: 0x%04x", psm);
209 return (false);
210 }
211
212 p_rcb->ucd.state = L2C_UCD_STATE_W4_DATA;
213 p_rcb->ucd.cb_info = *p_cb_info;
214
215 /* check if master rcb is created for UCD */
216 p_rcb = l2cu_find_rcb_by_psm(L2C_UCD_RCB_ID);
217 if (p_rcb == NULL) {
218 p_rcb = l2cu_allocate_rcb(L2C_UCD_RCB_ID);
219 if (p_rcb == NULL) {
220 L2CAP_TRACE_ERROR("L2CAP - no RCB available for L2CA_UcdRegister");
221 return (false);
222 } else {
223 /* these callback functions will forward data to each UCD application */
224 p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb = l2c_ucd_discover_cback;
225 p_rcb->ucd.cb_info.pL2CA_UCD_Data_Cb = l2c_ucd_data_ind_cback;
226 p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb =
227 l2c_ucd_congestion_status_cback;
228
229 memset(&p_rcb->api, 0, sizeof(tL2CAP_APPL_INFO));
230 p_rcb->api.pL2CA_DisconnectInd_Cb = l2c_ucd_disconnect_ind_cback;
231
232 /* This will make L2CAP check UCD congestion callback */
233 p_rcb->api.pL2CA_CongestionStatus_Cb = NULL;
234
235 /* do nothing but prevent crash */
236 p_rcb->api.pL2CA_ConfigInd_Cb = l2c_ucd_config_ind_cback;
237 p_rcb->api.pL2CA_ConfigCfm_Cb = l2c_ucd_config_cfm_cback;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800238 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800239 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800240
Myles Watson911d1ae2016-11-28 16:44:40 -0800241 return (true);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800242}
243
244/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800245 *
246 * Function L2CA_UcdDeregister
247 *
248 * Description Deregister PSM on UCD.
249 *
250 * Parameters: PSM
251 *
252 * Return value: true if successs
253 *
254 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800255bool L2CA_UcdDeregister(uint16_t psm) {
256 tL2C_CCB* p_ccb;
257 tL2C_RCB* p_rcb;
258 uint16_t xx;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800259
Myles Watson911d1ae2016-11-28 16:44:40 -0800260 L2CAP_TRACE_API("L2CA_UcdDeregister() PSM: 0x%04x", psm);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800261
Myles Watson911d1ae2016-11-28 16:44:40 -0800262 p_rcb = l2cu_find_rcb_by_psm(psm);
263 if (p_rcb == NULL) {
264 L2CAP_TRACE_ERROR("L2CAP - no RCB for L2CA_UcdDeregister, PSM: 0x%04x",
265 psm);
266 return (false);
267 }
268
269 p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;
270
271 /* check this was the last UCD registration */
272 p_rcb = &l2cb.rcb_pool[0];
273
274 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
275 if ((p_rcb->in_use) && (p_rcb->ucd.state != L2C_UCD_STATE_UNUSED))
276 return (true);
277 }
278
279 /* delete master rcb for UCD */
280 p_rcb = l2cu_find_rcb_by_psm(L2C_UCD_RCB_ID);
281 if (p_rcb != NULL) {
282 l2cu_release_rcb(p_rcb);
283 }
284
285 /* delete CCB for UCD */
286 p_ccb = l2cb.ccb_pool;
287 for (xx = 0; xx < MAX_L2CAP_CHANNELS; xx++) {
288 if ((p_ccb->in_use) && (p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID)) {
289 l2cu_release_ccb(p_ccb);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800290 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800291 p_ccb++;
292 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800293
Myles Watson911d1ae2016-11-28 16:44:40 -0800294 return (true);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800295}
296
297/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800298 *
299 * Function L2CA_UcdDiscover
300 *
301 * Description Discover UCD of remote device.
302 *
303 * Parameters: PSM
304 * BD_ADDR of remote device
305 * info_type : L2CAP_UCD_INFO_TYPE_RECEPTION
306 * L2CAP_UCD_INFO_TYPE_MTU
307 *
308 *
309 * Return value: true if successs
310 *
311 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700312bool L2CA_UcdDiscover(uint16_t psm, const RawAddress& rem_bda,
Jakub Pawlowskic2276b02017-06-09 16:00:25 -0700313 uint8_t info_type) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800314 tL2C_LCB* p_lcb;
315 tL2C_CCB* p_ccb;
316 tL2C_RCB* p_rcb;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800317
Myles Watson911d1ae2016-11-28 16:44:40 -0800318 L2CAP_TRACE_API(
319 "L2CA_UcdDiscover() PSM: 0x%04x BDA: %08x%04x, InfoType=0x%02x", psm,
320 (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
321 (rem_bda[4] << 8) + rem_bda[5], info_type);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800322
Myles Watson911d1ae2016-11-28 16:44:40 -0800323 /* Fail if the PSM is not registered */
324 if (((p_rcb = l2cu_find_rcb_by_psm(psm)) == NULL) ||
325 (p_rcb->ucd.state == L2C_UCD_STATE_UNUSED)) {
326 L2CAP_TRACE_WARNING("L2CAP - no RCB for L2CA_UcdDiscover, PSM: 0x%04x",
327 psm);
328 return (false);
329 }
330
331 /* First, see if we already have a link to the remote */
332 /* then find the channel control block for UCD. */
333 if (((p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_BR_EDR)) ==
334 NULL) ||
335 ((p_ccb = l2cu_find_ccb_by_cid(p_lcb, L2CAP_CONNECTIONLESS_CID)) ==
336 NULL)) {
337 if (l2c_ucd_connect(rem_bda) == false) {
338 return (false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800339 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800340 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800341
Myles Watson911d1ae2016-11-28 16:44:40 -0800342 /* set waiting flags in rcb */
343
344 if (info_type & L2CAP_UCD_INFO_TYPE_RECEPTION)
345 p_rcb->ucd.state |= L2C_UCD_STATE_W4_RECEPTION;
346
347 if (info_type & L2CAP_UCD_INFO_TYPE_MTU)
348 p_rcb->ucd.state |= L2C_UCD_STATE_W4_MTU;
349
350 /* if link is already established */
351 if ((p_lcb) && (p_lcb->link_state == LST_CONNECTED)) {
352 if (!p_ccb) {
353 p_ccb = l2cu_find_ccb_by_cid(p_lcb, L2CAP_CONNECTIONLESS_CID);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800354 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800355 l2c_ucd_check_pending_info_req(p_ccb);
356 }
357 return (true);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800358}
359
360/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800361 *
362 * Function L2CA_UcdDataWrite
363 *
364 * Description Send UCD to remote device
365 *
366 * Parameters: PSM
367 * BD Address of remote
368 * Pointer to buffer of type BT_HDR
369 * flags : L2CAP_FLUSHABLE_CH_BASED
370 * L2CAP_FLUSHABLE_PKT
371 * L2CAP_NON_FLUSHABLE_PKT
372 *
373 * Return value L2CAP_DW_SUCCESS, if data accepted
374 * L2CAP_DW_FAILED, if error
375 *
376 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700377uint16_t L2CA_UcdDataWrite(uint16_t psm, const RawAddress& rem_bda,
Jakub Pawlowskic2276b02017-06-09 16:00:25 -0700378 BT_HDR* p_buf, uint16_t flags) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800379 tL2C_LCB* p_lcb;
380 tL2C_CCB* p_ccb;
381 tL2C_RCB* p_rcb;
382 uint8_t* p;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800383
Myles Watson911d1ae2016-11-28 16:44:40 -0800384 L2CAP_TRACE_API(
385 "L2CA_UcdDataWrite() PSM: 0x%04x BDA: %08x%04x", psm,
386 (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
387 (rem_bda[4] << 8) + rem_bda[5]);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800388
Myles Watson911d1ae2016-11-28 16:44:40 -0800389 /* Fail if the PSM is not registered */
390 if (((p_rcb = l2cu_find_rcb_by_psm(psm)) == NULL) ||
391 (p_rcb->ucd.state == L2C_UCD_STATE_UNUSED)) {
392 L2CAP_TRACE_WARNING("L2CAP - no RCB for L2CA_UcdDataWrite, PSM: 0x%04x",
393 psm);
394 osi_free(p_buf);
395 return (L2CAP_DW_FAILED);
396 }
397
398 /* First, see if we already have a link to the remote */
399 /* then find the channel control block for UCD */
400 if (((p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_BR_EDR)) ==
401 NULL) ||
402 ((p_ccb = l2cu_find_ccb_by_cid(p_lcb, L2CAP_CONNECTIONLESS_CID)) ==
403 NULL)) {
404 if (l2c_ucd_connect(rem_bda) == false) {
405 osi_free(p_buf);
406 return (L2CAP_DW_FAILED);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800407 }
408
Myles Watson911d1ae2016-11-28 16:44:40 -0800409 /* If we still don't have lcb and ccb after connect attempt, then can't
410 * proceed */
411 if (((p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_BR_EDR)) ==
412 NULL) ||
413 ((p_ccb = l2cu_find_ccb_by_cid(p_lcb, L2CAP_CONNECTIONLESS_CID)) ==
414 NULL)) {
415 osi_free(p_buf);
416 return (L2CAP_DW_FAILED);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800417 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800418 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800419
Myles Watson911d1ae2016-11-28 16:44:40 -0800420 /* write PSM */
421 p_buf->offset -= L2CAP_UCD_OVERHEAD;
422 p_buf->len += L2CAP_UCD_OVERHEAD;
423 p = (uint8_t*)(p_buf + 1) + p_buf->offset;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800424
Myles Watson911d1ae2016-11-28 16:44:40 -0800425 UINT16_TO_STREAM(p, psm);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800426
Myles Watson911d1ae2016-11-28 16:44:40 -0800427 /* UCD MTU check */
428 if ((p_lcb->ucd_mtu) && (p_buf->len > p_lcb->ucd_mtu)) {
429 L2CAP_TRACE_WARNING(
430 "L2CAP - Handle: 0x%04x UCD bigger than peer's UCD mtu size cannot be "
431 "sent",
432 p_lcb->handle);
433 osi_free(p_buf);
434 return (L2CAP_DW_FAILED);
435 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800436
Myles Watson911d1ae2016-11-28 16:44:40 -0800437 /* If already congested, do not accept any more packets */
438 if (p_ccb->cong_sent) {
439 L2CAP_TRACE_ERROR(
440 "L2CAP - Handle: 0x%04x UCD cannot be sent, already congested count: "
441 "%u buff_quota: %u",
442 p_lcb->handle, (fixed_queue_length(p_ccb->xmit_hold_q) +
443 fixed_queue_length(p_lcb->ucd_out_sec_pending_q)),
444 p_ccb->buff_quota);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800445
Myles Watson911d1ae2016-11-28 16:44:40 -0800446 osi_free(p_buf);
447 return (L2CAP_DW_FAILED);
448 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800449
Myles Watson911d1ae2016-11-28 16:44:40 -0800450 /* channel based, packet based flushable or non-flushable */
451 p_buf->layer_specific = flags;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800452
Myles Watson911d1ae2016-11-28 16:44:40 -0800453 l2c_csm_execute(p_ccb, L2CEVT_L2CA_DATA_WRITE, p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800454
Myles Watson911d1ae2016-11-28 16:44:40 -0800455 if (p_ccb->cong_sent)
456 return (L2CAP_DW_CONGESTED);
457 else
458 return (L2CAP_DW_SUCCESS);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800459}
460
461/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800462 *
463 * Function L2CA_UcdSetIdleTimeout
464 *
465 * Description Set UCD Idle timeout.
466 *
467 * Parameters: BD Addr
468 * Timeout in second
469 *
470 * Return value: true if successs
471 *
472 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700473bool L2CA_UcdSetIdleTimeout(const RawAddress& rem_bda, uint16_t timeout) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800474 tL2C_LCB* p_lcb;
475 tL2C_CCB* p_ccb;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800476
Myles Watson911d1ae2016-11-28 16:44:40 -0800477 L2CAP_TRACE_API(
478 "L2CA_UcdSetIdleTimeout() Timeout: 0x%04x BDA: %08x%04x", timeout,
479 (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
480 (rem_bda[4] << 8) + rem_bda[5]);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800481
Myles Watson911d1ae2016-11-28 16:44:40 -0800482 /* First, see if we already have a link to the remote */
483 /* then find the channel control block. */
484 if (((p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_BR_EDR)) ==
485 NULL) ||
486 ((p_ccb = l2cu_find_ccb_by_cid(p_lcb, L2CAP_CONNECTIONLESS_CID)) ==
487 NULL)) {
488 L2CAP_TRACE_WARNING("L2CAP - no UCD channel");
489 return (false);
490 } else {
491 p_ccb->fixed_chnl_idle_tout = timeout;
492 return (true);
493 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800494}
495
496/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800497 *
498 * Function L2CA_UCDSetTxPriority
499 *
500 * Description Sets the transmission priority for a connectionless channel.
501 *
502 * Returns true if a valid channel, else false
503 *
504 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700505bool L2CA_UCDSetTxPriority(const RawAddress& rem_bda,
Jakub Pawlowskic2276b02017-06-09 16:00:25 -0700506 tL2CAP_CHNL_PRIORITY priority) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800507 tL2C_LCB* p_lcb;
508 tL2C_CCB* p_ccb;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800509
Myles Watson911d1ae2016-11-28 16:44:40 -0800510 L2CAP_TRACE_API(
511 "L2CA_UCDSetTxPriority() priority: 0x%02x BDA: %08x%04x", priority,
512 (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
513 (rem_bda[4] << 8) + rem_bda[5]);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800514
Myles Watson911d1ae2016-11-28 16:44:40 -0800515 p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_BR_EDR);
516 if (p_lcb == NULL) {
517 L2CAP_TRACE_WARNING("L2CAP - no LCB for L2CA_UCDSetTxPriority");
518 return (false);
519 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800520
Myles Watson911d1ae2016-11-28 16:44:40 -0800521 /* Find the channel control block */
522 p_ccb = l2cu_find_ccb_by_cid(p_lcb, L2CAP_CONNECTIONLESS_CID);
523 if (p_ccb == NULL) {
524 L2CAP_TRACE_WARNING("L2CAP - no CCB for L2CA_UCDSetTxPriority");
525 return (false);
526 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800527
Myles Watson911d1ae2016-11-28 16:44:40 -0800528 /* it will update the order of CCB in LCB by priority and update round robin
529 * service variables */
530 l2cu_change_pri_ccb(p_ccb, priority);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800531
Myles Watson911d1ae2016-11-28 16:44:40 -0800532 return (true);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800533}
534
535/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800536 *
537 * Function l2c_ucd_connect
538 *
539 * Description Connect UCD to remote device.
540 *
541 * Parameters: BD_ADDR of remote device
542 *
543 * Return value: true if successs
544 *
545 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700546static bool l2c_ucd_connect(const RawAddress& rem_bda) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800547 tL2C_LCB* p_lcb;
548 tL2C_CCB* p_ccb;
549 tL2C_RCB* p_rcb;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800550
Myles Watson911d1ae2016-11-28 16:44:40 -0800551 L2CAP_TRACE_DEBUG(
552 "l2c_ucd_connect() BDA: %08x%04x",
553 (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
554 (rem_bda[4] << 8) + rem_bda[5]);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800555
Myles Watson911d1ae2016-11-28 16:44:40 -0800556 /* Fail if we have not established communications with the controller */
557 if (!BTM_IsDeviceUp()) {
558 L2CAP_TRACE_WARNING("l2c_ucd_connect - BTU not ready");
559 return (false);
560 }
561
562 /* First, see if we already have a link to the remote */
563 p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_BR_EDR);
564 if (p_lcb == NULL) {
565 /* No link. Get an LCB and start link establishment */
566 if (((p_lcb = l2cu_allocate_lcb(rem_bda, false, BT_TRANSPORT_BR_EDR)) ==
567 NULL) ||
568 (l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR) == false)) {
569 L2CAP_TRACE_WARNING("L2CAP - conn not started l2c_ucd_connect");
570 return (false);
571 }
572 } else if (p_lcb->info_rx_bits & (1 << L2CAP_EXTENDED_FEATURES_INFO_TYPE)) {
573 if (!(p_lcb->peer_ext_fea & L2CAP_EXTFEA_UCD_RECEPTION)) {
574 L2CAP_TRACE_WARNING(
575 "L2CAP - UCD is not supported by peer, l2c_ucd_connect");
576 return (false);
577 }
578 }
579
580 /* Find the channel control block. */
581 p_ccb = l2cu_find_ccb_by_cid(p_lcb, L2CAP_CONNECTIONLESS_CID);
582 if (p_ccb == NULL) {
583 /* Allocate a channel control block */
584 p_ccb = l2cu_allocate_ccb(p_lcb, 0);
585 if (p_ccb == NULL) {
586 L2CAP_TRACE_WARNING("L2CAP - no CCB for l2c_ucd_connect");
587 return (false);
588 } else {
589 /* Set CID for the connection */
590 p_ccb->local_cid = L2CAP_CONNECTIONLESS_CID;
591 p_ccb->remote_cid = L2CAP_CONNECTIONLESS_CID;
592
593 /* Set the default idle timeout value to use */
594 p_ccb->fixed_chnl_idle_tout = L2CAP_UCD_IDLE_TIMEOUT;
595
596 /* Set the default channel priority value to use */
597 l2cu_change_pri_ccb(p_ccb, L2CAP_UCD_CH_PRIORITY);
598
599 p_rcb = l2cu_find_rcb_by_psm(L2C_UCD_RCB_ID);
600 if (p_rcb == NULL) {
601 L2CAP_TRACE_WARNING("L2CAP - no UCD registered, l2c_ucd_connect");
Marie Janssend19e0782016-07-15 12:48:27 -0700602 return (false);
Myles Watson911d1ae2016-11-28 16:44:40 -0800603 }
604 /* Save UCD registration info */
605 p_ccb->p_rcb = p_rcb;
606
607 /* There is no configuration, so if the link is up, the channel is up */
608 if (p_lcb->link_state == LST_CONNECTED) {
609 p_ccb->chnl_state = CST_OPEN;
610 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800611 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800612 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800613
Myles Watson911d1ae2016-11-28 16:44:40 -0800614 return (true);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800615}
616
617/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800618 *
619 * Function l2c_ucd_delete_sec_pending_q
620 *
621 * Description discard all of UCD packets in security pending queue
622 *
623 * Returns None
624 *
625 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800626void l2c_ucd_delete_sec_pending_q(tL2C_LCB* p_lcb) {
627 /* clean up any security pending UCD */
628 while (!fixed_queue_is_empty(p_lcb->ucd_out_sec_pending_q))
629 osi_free(fixed_queue_try_dequeue(p_lcb->ucd_out_sec_pending_q));
630 fixed_queue_free(p_lcb->ucd_out_sec_pending_q, NULL);
631 p_lcb->ucd_out_sec_pending_q = NULL;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800632
Myles Watson911d1ae2016-11-28 16:44:40 -0800633 while (!fixed_queue_is_empty(p_lcb->ucd_in_sec_pending_q))
634 osi_free(fixed_queue_try_dequeue(p_lcb->ucd_in_sec_pending_q));
635 fixed_queue_free(p_lcb->ucd_in_sec_pending_q);
636 p_lcb->ucd_in_sec_pending_q = NULL;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800637}
638
639/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800640 *
641 * Function l2c_ucd_check_pending_info_req
642 *
643 * Description check if any application is waiting for UCD information
644 *
645 * Return true if any pending UCD info request
646 *
647 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800648bool l2c_ucd_check_pending_info_req(tL2C_CCB* p_ccb) {
649 tL2C_RCB* p_rcb = &l2cb.rcb_pool[0];
650 uint16_t xx;
651 bool pending = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800652
Myles Watson911d1ae2016-11-28 16:44:40 -0800653 if (p_ccb == NULL) {
654 L2CAP_TRACE_ERROR("L2CAP - NULL p_ccb in l2c_ucd_check_pending_info_req");
655 return (false);
656 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800657
Myles Watson911d1ae2016-11-28 16:44:40 -0800658 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
659 if (p_rcb->in_use) {
660 /* if application is waiting UCD reception info */
661 if (p_rcb->ucd.state & L2C_UCD_STATE_W4_RECEPTION) {
662 /* if this information is available */
663 if (p_ccb->p_lcb->info_rx_bits &
664 (1 << L2CAP_EXTENDED_FEATURES_INFO_TYPE)) {
665 if (!(p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_UCD_RECEPTION)) {
666 L2CAP_TRACE_WARNING(
667 "L2CAP - UCD is not supported by peer, "
668 "l2c_ucd_check_pending_info_req");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800669
Myles Watson911d1ae2016-11-28 16:44:40 -0800670 l2c_ucd_delete_sec_pending_q(p_ccb->p_lcb);
671 l2cu_release_ccb(p_ccb);
672 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800673
Myles Watson911d1ae2016-11-28 16:44:40 -0800674 p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb(
675 p_ccb->p_lcb->remote_bd_addr, L2CAP_UCD_INFO_TYPE_RECEPTION,
676 p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_UCD_RECEPTION);
677 } else {
678 pending = true;
679 if (p_ccb->p_lcb->w4_info_rsp == false) {
680 l2cu_send_peer_info_req(p_ccb->p_lcb,
681 L2CAP_EXTENDED_FEATURES_INFO_TYPE);
682 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800683 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800684 }
685
686 /* if application is waiting for UCD MTU */
687 if (p_rcb->ucd.state & L2C_UCD_STATE_W4_MTU) {
688 /* if this information is available */
689 if (p_ccb->p_lcb->info_rx_bits & (1 << L2CAP_CONNLESS_MTU_INFO_TYPE)) {
690 p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb(
691 p_ccb->p_lcb->remote_bd_addr, L2CAP_UCD_INFO_TYPE_MTU,
692 p_ccb->p_lcb->ucd_mtu);
693 } else {
694 pending = true;
695 if (p_ccb->p_lcb->w4_info_rsp == false) {
696 l2cu_send_peer_info_req(p_ccb->p_lcb, L2CAP_CONNLESS_MTU_INFO_TYPE);
697 }
698 }
699 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800700 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800701 }
702 return (pending);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800703}
704
705/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800706 *
707 * Function l2c_ucd_enqueue_pending_out_sec_q
708 *
709 * Description enqueue outgoing UCD packet into security pending queue
710 * and check congestion
711 *
712 * Return None
713 *
714 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800715void l2c_ucd_enqueue_pending_out_sec_q(tL2C_CCB* p_ccb, void* p_data) {
716 fixed_queue_enqueue(p_ccb->p_lcb->ucd_out_sec_pending_q, p_data);
717 l2cu_check_channel_congestion(p_ccb);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800718}
719
720/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800721 *
722 * Function l2c_ucd_check_pending_out_sec_q
723 *
724 * Description check outgoing security
725 *
726 * Return true if any UCD packet for security
727 *
728 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800729bool l2c_ucd_check_pending_out_sec_q(tL2C_CCB* p_ccb) {
730 BT_HDR* p_buf =
731 (BT_HDR*)fixed_queue_try_peek_first(p_ccb->p_lcb->ucd_out_sec_pending_q);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800732
Myles Watson911d1ae2016-11-28 16:44:40 -0800733 if (p_buf != NULL) {
734 uint16_t psm;
735 uint8_t* p = (uint8_t*)(p_buf + 1) + p_buf->offset;
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700736
Myles Watson911d1ae2016-11-28 16:44:40 -0800737 STREAM_TO_UINT16(psm, p)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800738
Myles Watson911d1ae2016-11-28 16:44:40 -0800739 p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP;
740 btm_sec_l2cap_access_req(p_ccb->p_lcb->remote_bd_addr, psm,
741 p_ccb->p_lcb->handle, CONNLESS_ORIG,
742 &l2c_link_sec_comp, p_ccb);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800743
Myles Watson911d1ae2016-11-28 16:44:40 -0800744 return (true);
745 }
746 return (false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800747}
748
749/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800750 *
751 * Function l2c_ucd_send_pending_out_sec_q
752 *
753 * Description dequeue UCD packet from security pending queue and
754 * enqueue it into CCB
755 *
756 * Return None
757 *
758 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800759void l2c_ucd_send_pending_out_sec_q(tL2C_CCB* p_ccb) {
760 BT_HDR* p_buf =
761 (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_out_sec_pending_q);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800762
Myles Watson911d1ae2016-11-28 16:44:40 -0800763 if (p_buf != NULL) {
764 l2c_enqueue_peer_data(p_ccb, (BT_HDR*)p_buf);
765 l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, NULL);
766 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800767}
768
769/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800770 *
771 * Function l2c_ucd_discard_pending_out_sec_q
772 *
773 * Description dequeue UCD packet from security pending queue and
774 * discard it.
775 *
776 * Return None
777 *
778 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800779void l2c_ucd_discard_pending_out_sec_q(tL2C_CCB* p_ccb) {
780 BT_HDR* p_buf =
781 (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_out_sec_pending_q);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800782
Myles Watson911d1ae2016-11-28 16:44:40 -0800783 /* we may need to report to application */
784 osi_free(p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800785}
786
787/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800788 *
789 * Function l2c_ucd_check_pending_in_sec_q
790 *
791 * Description check incoming security
792 *
793 * Return true if any UCD packet for security
794 *
795 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800796bool l2c_ucd_check_pending_in_sec_q(tL2C_CCB* p_ccb) {
797 BT_HDR* p_buf =
798 (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_in_sec_pending_q);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800799
Myles Watson911d1ae2016-11-28 16:44:40 -0800800 if (p_buf != NULL) {
801 uint16_t psm;
802 uint8_t* p = (uint8_t*)(p_buf + 1) + p_buf->offset;
803 STREAM_TO_UINT16(psm, p)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800804
Myles Watson911d1ae2016-11-28 16:44:40 -0800805 p_ccb->chnl_state = CST_TERM_W4_SEC_COMP;
806 btm_sec_l2cap_access_req(p_ccb->p_lcb->remote_bd_addr, psm,
807 p_ccb->p_lcb->handle, CONNLESS_TERM,
808 &l2c_link_sec_comp, p_ccb);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800809
Myles Watson911d1ae2016-11-28 16:44:40 -0800810 return (true);
811 }
812 return (false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800813}
814
815/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800816 *
817 * Function l2c_ucd_send_pending_in_sec_q
818 *
819 * Description dequeue UCD packet from security pending queue and
820 * send it to application
821 *
822 * Return None
823 *
824 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800825void l2c_ucd_send_pending_in_sec_q(tL2C_CCB* p_ccb) {
826 BT_HDR* p_buf =
827 (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_in_sec_pending_q)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800828
Myles Watson911d1ae2016-11-28 16:44:40 -0800829 if (p_buf != NULL) {
830 p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Data_Cb(p_ccb->p_lcb->remote_bd_addr,
831 (BT_HDR*)p_buf);
832 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800833}
834
835/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800836 *
837 * Function l2c_ucd_discard_pending_in_sec_q
838 *
839 * Description dequeue UCD packet from security pending queue and
840 * discard it.
841 *
842 * Return None
843 *
844 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800845void l2c_ucd_discard_pending_in_sec_q(tL2C_CCB* p_ccb) {
846 BT_HDR* p_buf =
847 (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_in_sec_pending_q);
848 osi_free(p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800849}
850
851/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800852 *
853 * Function l2c_ucd_check_rx_pkts
854 *
855 * Description Check if UCD reception is registered.
856 * Process received UCD packet if application is expecting.
857 *
858 * Return true if UCD reception is registered
859 *
860 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800861bool l2c_ucd_check_rx_pkts(tL2C_LCB* p_lcb, BT_HDR* p_msg) {
862 tL2C_CCB* p_ccb;
863 tL2C_RCB* p_rcb;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800864
Myles Watson911d1ae2016-11-28 16:44:40 -0800865 if (((p_ccb = l2cu_find_ccb_by_cid(p_lcb, L2CAP_CONNECTIONLESS_CID)) !=
866 NULL) ||
867 ((p_rcb = l2cu_find_rcb_by_psm(L2C_UCD_RCB_ID)) != NULL)) {
868 if (p_ccb == NULL) {
869 /* Allocate a channel control block */
870 p_ccb = l2cu_allocate_ccb(p_lcb, 0);
871 if (p_ccb == NULL) {
872 L2CAP_TRACE_WARNING("L2CAP - no CCB for UCD reception");
873 osi_free(p_msg);
Marie Janssend19e0782016-07-15 12:48:27 -0700874 return true;
Myles Watson911d1ae2016-11-28 16:44:40 -0800875 } else {
876 /* Set CID for the connection */
877 p_ccb->local_cid = L2CAP_CONNECTIONLESS_CID;
878 p_ccb->remote_cid = L2CAP_CONNECTIONLESS_CID;
879
880 /* Set the default idle timeout value to use */
881 p_ccb->fixed_chnl_idle_tout = L2CAP_UCD_IDLE_TIMEOUT;
882
883 /* Set the default channel priority value to use */
884 l2cu_change_pri_ccb(p_ccb, L2CAP_UCD_CH_PRIORITY);
885
886 /* Save registration info */
887 p_ccb->p_rcb = p_rcb;
888
889 p_ccb->chnl_state = CST_OPEN;
890 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800891 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800892 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_DATA, p_msg);
893 return true;
894 } else
895 return false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800896}
897
898/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800899 *
900 * Function l2c_ucd_process_event
901 *
Myles Watson9ca07092016-11-28 16:41:53 -0800902 * Description This is called from main state machine when LCID is
903 * connectionless. Process the event if it is for UCD.
Myles Watsonee96a3c2016-11-23 14:49:54 -0800904 *
905 * Return true if the event is consumed by UCD
Myles Watson9ca07092016-11-28 16:41:53 -0800906 * false if the event needs to be processed by the main state
907 * machine
Myles Watsonee96a3c2016-11-23 14:49:54 -0800908 *
909 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800910bool l2c_ucd_process_event(tL2C_CCB* p_ccb, uint16_t event, void* p_data) {
911 /* if the event is not processed by this function, this variable will be set
912 * to false */
913 bool done = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800914
Myles Watson911d1ae2016-11-28 16:44:40 -0800915 switch (p_ccb->chnl_state) {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800916 case CST_CLOSED:
Myles Watson911d1ae2016-11-28 16:44:40 -0800917 switch (event) {
918 case L2CEVT_LP_CONNECT_CFM: /* Link came up */
919 /* check if waiting for UCD info */
920 if (!l2c_ucd_check_pending_info_req(p_ccb)) {
921 /* check if any outgoing UCD packet is waiting security check */
922 if (!l2c_ucd_check_pending_out_sec_q(p_ccb)) {
923 p_ccb->chnl_state = CST_OPEN;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800924 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800925 }
926 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800927
Myles Watson911d1ae2016-11-28 16:44:40 -0800928 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
929 fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data);
930 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800931
Myles Watson911d1ae2016-11-28 16:44:40 -0800932 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
933 l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data);
934 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800935
936 case L2CEVT_L2CAP_INFO_RSP:
Myles Watson911d1ae2016-11-28 16:44:40 -0800937 /* check if waiting for UCD info */
938 if (!l2c_ucd_check_pending_info_req(p_ccb)) {
939 /* check if any outgoing UCD packet is waiting security check */
940 if (!l2c_ucd_check_pending_out_sec_q(p_ccb)) {
941 p_ccb->chnl_state = CST_OPEN;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800942 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800943 }
944 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800945
946 default:
Myles Watson911d1ae2016-11-28 16:44:40 -0800947 done = false; /* main state machine continues to process event */
948 break;
949 }
950 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800951
952 case CST_ORIG_W4_SEC_COMP:
Myles Watson911d1ae2016-11-28 16:44:40 -0800953 switch (event) {
954 case L2CEVT_SEC_RE_SEND_CMD: /* BTM has enough info to proceed */
955 /* check if any outgoing UCD packet is waiting security check */
956 if (!l2c_ucd_check_pending_out_sec_q(p_ccb)) {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800957 p_ccb->chnl_state = CST_OPEN;
Myles Watson911d1ae2016-11-28 16:44:40 -0800958 }
959 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800960
Myles Watson911d1ae2016-11-28 16:44:40 -0800961 case L2CEVT_SEC_COMP: /* Security completed success */
962 p_ccb->chnl_state = CST_OPEN;
963 l2c_ucd_send_pending_out_sec_q(p_ccb);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800964
Myles Watson911d1ae2016-11-28 16:44:40 -0800965 if (!fixed_queue_is_empty(p_ccb->p_lcb->ucd_out_sec_pending_q)) {
966 /* start a timer to send next UCD packet in OPEN state */
967 /* it will prevent stack overflow */
968 alarm_set_on_queue(p_ccb->l2c_ccb_timer, 0, l2c_ccb_timer_timeout,
969 p_ccb, btu_general_alarm_queue);
970 } else {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800971 /* start a timer for idle timeout of UCD */
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -0800972 period_ms_t timeout_ms = p_ccb->fixed_chnl_idle_tout * 1000;
973 alarm_set_on_queue(p_ccb->l2c_ccb_timer, timeout_ms,
974 l2c_ccb_timer_timeout, p_ccb,
975 btu_general_alarm_queue);
Myles Watson911d1ae2016-11-28 16:44:40 -0800976 }
977 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800978
Myles Watson911d1ae2016-11-28 16:44:40 -0800979 case L2CEVT_SEC_COMP_NEG:
980 p_ccb->chnl_state = CST_OPEN;
981 l2c_ucd_discard_pending_out_sec_q(p_ccb);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800982
Myles Watson911d1ae2016-11-28 16:44:40 -0800983 /* start a timer for idle timeout of UCD */
984 period_ms_t timeout_ms = p_ccb->fixed_chnl_idle_tout * 1000;
985 alarm_set_on_queue(p_ccb->l2c_ccb_timer, timeout_ms,
986 l2c_ccb_timer_timeout, p_ccb,
987 btu_general_alarm_queue);
988 break;
989
990 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
991 l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data);
992 break;
993
994 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
995 fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data);
996 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800997
998 case L2CEVT_L2CAP_INFO_RSP:
Myles Watson911d1ae2016-11-28 16:44:40 -0800999 /* check if waiting for UCD info */
1000 l2c_ucd_check_pending_info_req(p_ccb);
1001 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001002
1003 default:
Myles Watson911d1ae2016-11-28 16:44:40 -08001004 done = false; /* main state machine continues to process event */
1005 break;
1006 }
1007 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001008
1009 case CST_TERM_W4_SEC_COMP:
Myles Watson911d1ae2016-11-28 16:44:40 -08001010 switch (event) {
The Android Open Source Project5738f832012-12-12 16:00:35 -08001011 case L2CEVT_SEC_COMP:
Myles Watson911d1ae2016-11-28 16:44:40 -08001012 p_ccb->chnl_state = CST_OPEN;
1013 l2c_ucd_send_pending_in_sec_q(p_ccb);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001014
Myles Watson911d1ae2016-11-28 16:44:40 -08001015 if (!fixed_queue_is_empty(p_ccb->p_lcb->ucd_in_sec_pending_q)) {
1016 /* start a timer to check next UCD packet in OPEN state */
1017 /* it will prevent stack overflow */
1018 alarm_set_on_queue(p_ccb->l2c_ccb_timer, 0, l2c_ccb_timer_timeout,
1019 p_ccb, btu_general_alarm_queue);
1020 } else {
The Android Open Source Project5738f832012-12-12 16:00:35 -08001021 /* start a timer for idle timeout of UCD */
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08001022 period_ms_t timeout_ms = p_ccb->fixed_chnl_idle_tout * 1000;
1023 alarm_set_on_queue(p_ccb->l2c_ccb_timer, timeout_ms,
1024 l2c_ccb_timer_timeout, p_ccb,
1025 btu_general_alarm_queue);
Myles Watson911d1ae2016-11-28 16:44:40 -08001026 }
1027 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001028
Myles Watson911d1ae2016-11-28 16:44:40 -08001029 case L2CEVT_SEC_COMP_NEG:
1030 if (((tL2C_CONN_INFO*)p_data)->status == BTM_DELAY_CHECK) {
1031 done = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001032 break;
Myles Watson911d1ae2016-11-28 16:44:40 -08001033 }
1034 p_ccb->chnl_state = CST_OPEN;
1035 l2c_ucd_discard_pending_in_sec_q(p_ccb);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001036
Myles Watson911d1ae2016-11-28 16:44:40 -08001037 /* start a timer for idle timeout of UCD */
1038 period_ms_t timeout_ms = p_ccb->fixed_chnl_idle_tout * 1000;
1039 alarm_set_on_queue(p_ccb->l2c_ccb_timer, timeout_ms,
1040 l2c_ccb_timer_timeout, p_ccb,
1041 btu_general_alarm_queue);
1042 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001043
Myles Watson911d1ae2016-11-28 16:44:40 -08001044 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
1045 l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data);
1046 break;
1047
1048 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
1049 fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data);
1050 break;
1051
1052 case L2CEVT_SEC_RE_SEND_CMD: /* BTM has enough info to proceed */
1053 /* check if any incoming UCD packet is waiting security check */
1054 if (!l2c_ucd_check_pending_in_sec_q(p_ccb)) {
1055 p_ccb->chnl_state = CST_OPEN;
1056 }
1057 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001058
1059 case L2CEVT_L2CAP_INFO_RSP:
Myles Watson911d1ae2016-11-28 16:44:40 -08001060 /* check if waiting for UCD info */
1061 l2c_ucd_check_pending_info_req(p_ccb);
1062 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001063
1064 default:
Myles Watson911d1ae2016-11-28 16:44:40 -08001065 done = false; /* main state machine continues to process event */
1066 break;
1067 }
1068 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001069
1070 case CST_OPEN:
Myles Watson911d1ae2016-11-28 16:44:40 -08001071 switch (event) {
1072 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
1073 /* stop idle timer of UCD */
1074 alarm_cancel(p_ccb->l2c_ccb_timer);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001075
Myles Watson911d1ae2016-11-28 16:44:40 -08001076 fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data);
1077 l2c_ucd_check_pending_in_sec_q(p_ccb);
1078 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001079
Myles Watson911d1ae2016-11-28 16:44:40 -08001080 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
1081 /* stop idle timer of UCD */
1082 alarm_cancel(p_ccb->l2c_ccb_timer);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001083
Myles Watson911d1ae2016-11-28 16:44:40 -08001084 l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001085
Myles Watson911d1ae2016-11-28 16:44:40 -08001086 /* success changes state, failure stays in current state */
1087 l2c_ucd_check_pending_out_sec_q(p_ccb);
1088 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001089
1090 case L2CEVT_TIMEOUT:
Myles Watson911d1ae2016-11-28 16:44:40 -08001091 /* check if any UCD packet is waiting security check */
1092 if ((!l2c_ucd_check_pending_in_sec_q(p_ccb)) &&
1093 (!l2c_ucd_check_pending_out_sec_q(p_ccb))) {
1094 l2cu_release_ccb(p_ccb);
1095 }
1096 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001097
1098 case L2CEVT_L2CAP_INFO_RSP:
Myles Watson911d1ae2016-11-28 16:44:40 -08001099 /* check if waiting for UCD info */
1100 l2c_ucd_check_pending_info_req(p_ccb);
1101 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001102
1103 default:
Myles Watson911d1ae2016-11-28 16:44:40 -08001104 done = false; /* main state machine continues to process event */
1105 break;
1106 }
1107 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001108
1109 default:
Myles Watson911d1ae2016-11-28 16:44:40 -08001110 done = false; /* main state machine continues to process event */
1111 break;
1112 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001113
Myles Watson911d1ae2016-11-28 16:44:40 -08001114 return done;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001115}
1116#endif /* (L2CAP_UCD_INCLUDED == TRUE) */