1 /******************************************************************************
2 *
3 * Copyright (C) 2014 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 * Filename: btif_gatt_multi_adv_util.c
22 *
23 * Description: Multi ADV helper implementation
24 *
25 *******************************************************************************/
26
27 #define LOG_TAG "bt_btif_gatt"
28
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33
34 #include "btu.h"
35 #include "bt_target.h"
36
37 #if (BLE_INCLUDED == TRUE)
38
39 #include <hardware/bluetooth.h>
40 #include <hardware/bt_gatt.h>
41
42 #include "bta_gatt_api.h"
43 #include "btif_common.h"
44 #include "btif_gatt_multi_adv_util.h"
45 #include "btif_gatt_util.h"
46
47 extern fixed_queue_t *btu_general_alarm_queue;
48
49 /*******************************************************************************
50 ** Static variables
51 ********************************************************************************/
52 static int user_app_count = 0;
53 static btgatt_multi_adv_common_data *p_multi_adv_com_data_cb = NULL;
54
btif_obtain_multi_adv_data_cb()55 btgatt_multi_adv_common_data *btif_obtain_multi_adv_data_cb()
56 {
57 int max_adv_inst = BTM_BleMaxMultiAdvInstanceCount();
58 if (0 == max_adv_inst)
59 max_adv_inst = 1;
60
61 BTIF_TRACE_DEBUG("%s, Count:%d", __FUNCTION__, max_adv_inst);
62
63 if (NULL == p_multi_adv_com_data_cb)
64 {
65 p_multi_adv_com_data_cb = osi_calloc(sizeof(btgatt_multi_adv_common_data));
66 /* Storing both client_if and inst_id details */
67 p_multi_adv_com_data_cb->clntif_map =
68 osi_calloc((max_adv_inst * INST_ID_IDX_MAX) * sizeof(INT8));
69
70 p_multi_adv_com_data_cb->inst_cb =
71 osi_calloc((max_adv_inst + 1) * sizeof(btgatt_multi_adv_inst_cb));
72
73 for (int i = 0; i < max_adv_inst * 2; i += 2) {
74 p_multi_adv_com_data_cb->clntif_map[i] = INVALID_ADV_INST;
75 p_multi_adv_com_data_cb->clntif_map[i+1] = INVALID_ADV_INST;
76 }
77 }
78
79 return p_multi_adv_com_data_cb;
80 }
81
btif_gattc_incr_app_count(void)82 void btif_gattc_incr_app_count(void)
83 {
84 // TODO: Instead of using a fragile reference counter here, one could
85 // simply track the client_if instances that are in the map.
86 ++user_app_count;
87 }
88
btif_gattc_decr_app_count(void)89 void btif_gattc_decr_app_count(void)
90 {
91 if (user_app_count > 0)
92 user_app_count--;
93
94 if ((user_app_count == 0) && (p_multi_adv_com_data_cb != NULL)) {
95 osi_free(p_multi_adv_com_data_cb->clntif_map);
96 osi_free(p_multi_adv_com_data_cb->inst_cb);
97 osi_free_and_reset((void **)&p_multi_adv_com_data_cb);
98 }
99 }
100
btif_multi_adv_add_instid_map(int client_if,int inst_id,BOOLEAN gen_temp_instid)101 int btif_multi_adv_add_instid_map(int client_if, int inst_id, BOOLEAN gen_temp_instid)
102 {
103 int i=1;
104
105 btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
106 if (NULL == p_multi_adv_data_cb)
107 return INVALID_ADV_INST;
108
109 for (i=1; i < BTM_BleMaxMultiAdvInstanceCount(); i++)
110 {
111 if (client_if == p_multi_adv_data_cb->clntif_map[i + i])
112 {
113 if (!gen_temp_instid)
114 {
115 // Write the final inst_id value obtained from stack layer
116 p_multi_adv_data_cb->clntif_map[i + (i + 1)] = inst_id;
117 BTIF_TRACE_DEBUG("%s -Index: %d, Found client_if: %d", __FUNCTION__,
118 i, p_multi_adv_data_cb->clntif_map[i + i]);
119 break;
120 }
121 else
122 {
123 //Store the passed in inst_id value
124 if (inst_id != INVALID_ADV_INST)
125 p_multi_adv_data_cb->clntif_map[i + (i + 1)] = inst_id;
126 else
127 p_multi_adv_data_cb->clntif_map[i + (i + 1)] = (i + 1);
128
129 BTIF_TRACE_DEBUG("%s - Index:%d,Found client_if: %d", __FUNCTION__,
130 i, p_multi_adv_data_cb->clntif_map[i + i]);
131 break;
132 }
133 }
134 }
135
136 if (i < BTM_BleMaxMultiAdvInstanceCount())
137 return i;
138
139 // If client ID if is not found, then write both values
140 for (i=1; i < BTM_BleMaxMultiAdvInstanceCount(); i++)
141 {
142 if (INVALID_ADV_INST == p_multi_adv_data_cb->clntif_map[i + i])
143 {
144 p_multi_adv_data_cb->clntif_map[i + i] = client_if;
145 if (inst_id != INVALID_ADV_INST)
146 p_multi_adv_data_cb->clntif_map[i + (i + 1)] = inst_id;
147 else
148 p_multi_adv_data_cb->clntif_map[i + (i + 1)] = (i + 1);
149 BTIF_TRACE_DEBUG("%s -Not found - Index:%d, client_if: %d, Inst ID: %d",
150 __FUNCTION__,i,
151 p_multi_adv_data_cb->clntif_map[i + i],
152 p_multi_adv_data_cb->clntif_map[i + (i + 1)]);
153 break;
154 }
155 }
156
157 if (i < BTM_BleMaxMultiAdvInstanceCount())
158 return i;
159 return INVALID_ADV_INST;
160 }
161
btif_multi_adv_instid_for_clientif(int client_if)162 int btif_multi_adv_instid_for_clientif(int client_if)
163 {
164 int i=1, ret = INVALID_ADV_INST;
165
166 btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
167
168 if (NULL == p_multi_adv_data_cb)
169 return INVALID_ADV_INST;
170
171 // Retrieve the existing inst_id for the client_if value
172 for (i=1; i < BTM_BleMaxMultiAdvInstanceCount(); i++)
173 {
174 if (client_if == p_multi_adv_data_cb->clntif_map[i + i])
175 {
176 BTIF_TRACE_DEBUG("%s - Client if found", __FUNCTION__, client_if);
177 ret = p_multi_adv_data_cb->clntif_map[i + (i + 1)];
178 }
179 }
180
181 return ret;
182 }
183
btif_gattc_obtain_idx_for_datacb(int value,int clnt_inst_index)184 int btif_gattc_obtain_idx_for_datacb(int value, int clnt_inst_index)
185 {
186 int i=1;
187
188 btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
189
190 if (NULL == p_multi_adv_data_cb)
191 return INVALID_ADV_INST;
192
193 // Retrieve the array index for the inst_id value
194 for (i=1; i < BTM_BleMaxMultiAdvInstanceCount(); i++)
195 {
196 if (value == p_multi_adv_data_cb->clntif_map[i + (i + clnt_inst_index)])
197 break;
198 }
199
200 if (i < BTM_BleMaxMultiAdvInstanceCount())
201 {
202 BTIF_TRACE_DEBUG("%s, %d",__FUNCTION__,i);
203 return i;
204 }
205
206 BTIF_TRACE_DEBUG("%s Invalid instance",__FUNCTION__);
207 return INVALID_ADV_INST;
208 }
209
btif_gattc_adv_data_packager(int client_if,bool set_scan_rsp,bool include_name,bool include_txpower,int min_interval,int max_interval,int appearance,int manufacturer_len,char * manufacturer_data,int service_data_len,char * service_data,int service_uuid_len,char * service_uuid,btif_adv_data_t * p_multi_adv_inst)210 void btif_gattc_adv_data_packager(int client_if, bool set_scan_rsp,
211 bool include_name, bool include_txpower, int min_interval, int max_interval,
212 int appearance, int manufacturer_len, char* manufacturer_data,
213 int service_data_len, char* service_data, int service_uuid_len,
214 char* service_uuid, btif_adv_data_t *p_multi_adv_inst)
215 {
216 memset(p_multi_adv_inst, 0 , sizeof(btif_adv_data_t));
217
218 p_multi_adv_inst->client_if = (uint8_t) client_if;
219 p_multi_adv_inst->set_scan_rsp = set_scan_rsp;
220 p_multi_adv_inst->include_name = include_name;
221 p_multi_adv_inst->include_txpower = include_txpower;
222 p_multi_adv_inst->min_interval = min_interval;
223 p_multi_adv_inst->max_interval = max_interval;
224 p_multi_adv_inst->appearance = appearance;
225 p_multi_adv_inst->manufacturer_len = manufacturer_len;
226
227 if (manufacturer_len > 0)
228 {
229 p_multi_adv_inst->p_manufacturer_data = osi_malloc(manufacturer_len);
230 memcpy(p_multi_adv_inst->p_manufacturer_data, manufacturer_data, manufacturer_len);
231 }
232
233 p_multi_adv_inst->service_data_len = service_data_len;
234 if (service_data_len > 0)
235 {
236 p_multi_adv_inst->p_service_data = osi_malloc(service_data_len);
237 memcpy(p_multi_adv_inst->p_service_data, service_data, service_data_len);
238 }
239
240 p_multi_adv_inst->service_uuid_len = service_uuid_len;
241 if (service_uuid_len > 0)
242 {
243 p_multi_adv_inst->p_service_uuid = osi_malloc(service_uuid_len);
244 memcpy(p_multi_adv_inst->p_service_uuid, service_uuid, service_uuid_len);
245 }
246 }
247
btif_gattc_adv_data_cleanup(btif_adv_data_t * adv)248 void btif_gattc_adv_data_cleanup(btif_adv_data_t* adv)
249 {
250 osi_free_and_reset((void **)&adv->p_service_data);
251 osi_free_and_reset((void **)&adv->p_service_uuid);
252 osi_free_and_reset((void **)&adv->p_manufacturer_data);
253 }
254
btif_gattc_copy_datacb(int cbindex,const btif_adv_data_t * p_adv_data,BOOLEAN bInstData)255 BOOLEAN btif_gattc_copy_datacb(int cbindex, const btif_adv_data_t *p_adv_data,
256 BOOLEAN bInstData) {
257 btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
258 if (NULL == p_multi_adv_data_cb || cbindex < 0)
259 return false;
260
261 BTIF_TRACE_DEBUG("%s", __func__);
262
263 memset(&p_multi_adv_data_cb->inst_cb[cbindex].data, 0,
264 sizeof(p_multi_adv_data_cb->inst_cb[cbindex].data));
265 p_multi_adv_data_cb->inst_cb[cbindex].mask = 0;
266
267 if (!p_adv_data->set_scan_rsp)
268 {
269 p_multi_adv_data_cb->inst_cb[cbindex].mask = BTM_BLE_AD_BIT_FLAGS;
270 p_multi_adv_data_cb->inst_cb[cbindex].data.flag = ADV_FLAGS_GENERAL;
271 if (p_multi_adv_data_cb->inst_cb[cbindex].timeout_s)
272 p_multi_adv_data_cb->inst_cb[cbindex].data.flag = ADV_FLAGS_LIMITED;
273 if (p_multi_adv_data_cb->inst_cb[cbindex].param.adv_type == BTA_BLE_NON_CONNECT_EVT)
274 p_multi_adv_data_cb->inst_cb[cbindex].data.flag &=
275 ~(BTA_DM_LIMITED_DISC | BTA_DM_GENERAL_DISC);
276 if (p_multi_adv_data_cb->inst_cb[cbindex].data.flag == 0)
277 p_multi_adv_data_cb->inst_cb[cbindex].mask = 0;
278 }
279
280 if (p_adv_data->include_name)
281 p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_DEV_NAME;
282
283 if (p_adv_data->include_txpower)
284 p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_TX_PWR;
285
286 if (false == bInstData && p_adv_data->min_interval > 0 && p_adv_data->max_interval > 0 &&
287 p_adv_data->max_interval > p_adv_data->min_interval)
288 {
289 p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_INT_RANGE;
290 p_multi_adv_data_cb->inst_cb[cbindex].data.int_range.low =
291 p_adv_data->min_interval;
292 p_multi_adv_data_cb->inst_cb[cbindex].data.int_range.hi =
293 p_adv_data->max_interval;
294 }
295 else
296 if (true == bInstData)
297 {
298 if (p_multi_adv_data_cb->inst_cb[cbindex].param.adv_int_min > 0 &&
299 p_multi_adv_data_cb->inst_cb[cbindex].param.adv_int_max > 0 &&
300 p_multi_adv_data_cb->inst_cb[cbindex].param.adv_int_max >
301 p_multi_adv_data_cb->inst_cb[cbindex].param.adv_int_min)
302 {
303 p_multi_adv_data_cb->inst_cb[cbindex].data.int_range.low =
304 p_multi_adv_data_cb->inst_cb[cbindex].param.adv_int_min;
305 p_multi_adv_data_cb->inst_cb[cbindex].data.int_range.hi =
306 p_multi_adv_data_cb->inst_cb[cbindex].param.adv_int_max;
307 }
308
309 if (p_adv_data->include_txpower)
310 {
311 p_multi_adv_data_cb->inst_cb[cbindex].data.tx_power =
312 p_multi_adv_data_cb->inst_cb[cbindex].param.tx_power;
313 }
314 }
315
316 if (p_adv_data->appearance != 0)
317 {
318 p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_APPEARANCE;
319 p_multi_adv_data_cb->inst_cb[cbindex].data.appearance = p_adv_data->appearance;
320 }
321
322 if (p_adv_data->manufacturer_len > 0 &&
323 p_adv_data->p_manufacturer_data != NULL &&
324 p_adv_data->manufacturer_len < MAX_SIZE_MANUFACTURER_DATA)
325 {
326 p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_MANU;
327 p_multi_adv_data_cb->inst_cb[cbindex].data.manu.len =
328 p_adv_data->manufacturer_len;
329 memcpy(&p_multi_adv_data_cb->inst_cb[cbindex].data.manu.val,
330 p_adv_data->p_manufacturer_data, p_adv_data->manufacturer_len);
331 }
332
333 if (p_adv_data->service_data_len > 0 &&
334 p_adv_data->p_service_data != NULL &&
335 p_adv_data->service_data_len < MAX_SIZE_PROPRIETARY_ELEMENT)
336 {
337 BTIF_TRACE_DEBUG("%s - In service_data", __func__);
338 tBTA_BLE_PROPRIETARY *p_prop = &p_multi_adv_data_cb->inst_cb[cbindex].data.proprietary;
339 p_prop->num_elem = 1;
340
341 tBTA_BLE_PROP_ELEM *p_elem = &p_prop->elem[0];
342 p_elem->adv_type = BTM_BLE_AD_TYPE_SERVICE_DATA;
343 p_elem->len = p_adv_data->service_data_len;
344 memcpy(p_elem->val, p_adv_data->p_service_data,
345 p_adv_data->service_data_len);
346
347 p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_PROPRIETARY;
348 }
349
350 if (p_adv_data->service_uuid_len && p_adv_data->p_service_uuid)
351 {
352 UINT16 *p_uuid_out16 = NULL;
353 UINT32 *p_uuid_out32 = NULL;
354 for (int position = 0; position < p_adv_data->service_uuid_len; position += LEN_UUID_128)
355 {
356 bt_uuid_t uuid;
357 memset(&uuid, 0, sizeof(uuid));
358 memcpy(&uuid.uu, p_adv_data->p_service_uuid + position, LEN_UUID_128);
359
360 tBT_UUID bt_uuid;
361 memset(&bt_uuid, 0, sizeof(bt_uuid));
362 btif_to_bta_uuid(&bt_uuid, &uuid);
363
364 switch(bt_uuid.len)
365 {
366 case (LEN_UUID_16):
367 {
368 if (p_multi_adv_data_cb->inst_cb[cbindex].data.services.num_service == 0)
369 {
370 p_multi_adv_data_cb->inst_cb[cbindex].data.services.list_cmpl = FALSE;
371 p_uuid_out16 = p_multi_adv_data_cb->inst_cb[cbindex].data.services.uuid;
372 }
373
374 if (p_multi_adv_data_cb->inst_cb[cbindex].data.services.num_service < MAX_16BIT_SERVICES)
375 {
376 BTIF_TRACE_DEBUG("%s - In 16-UUID_data", __func__);
377 p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_SERVICE;
378 ++p_multi_adv_data_cb->inst_cb[cbindex].data.services.num_service;
379 *p_uuid_out16++ = bt_uuid.uu.uuid16;
380 }
381 break;
382 }
383
384 case (LEN_UUID_32):
385 {
386 if (p_multi_adv_data_cb->inst_cb[cbindex].data.service_32b.num_service == 0)
387 {
388 p_multi_adv_data_cb->inst_cb[cbindex].data.service_32b.list_cmpl = FALSE;
389 p_uuid_out32 = p_multi_adv_data_cb->inst_cb[cbindex].data.service_32b.uuid;
390 }
391
392 if (p_multi_adv_data_cb->inst_cb[cbindex].data.service_32b.num_service < MAX_32BIT_SERVICES)
393 {
394 BTIF_TRACE_DEBUG("%s - In 32-UUID_data", __func__);
395 p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_SERVICE_32;
396 ++p_multi_adv_data_cb->inst_cb[cbindex].data.service_32b.num_service;
397 *p_uuid_out32++ = bt_uuid.uu.uuid32;
398 }
399 break;
400 }
401
402 case (LEN_UUID_128):
403 {
404 /* Currently, only one 128-bit UUID is supported */
405 if (p_multi_adv_data_cb->inst_cb[cbindex].data.services_128b.num_service == 0)
406 {
407 BTIF_TRACE_DEBUG("%s - In 128-UUID_data", __FUNCTION__);
408 p_multi_adv_data_cb->inst_cb[cbindex].mask |=
409 BTM_BLE_AD_BIT_SERVICE_128;
410 memcpy(p_multi_adv_data_cb->inst_cb[cbindex]
411 .data.services_128b.uuid128,
412 bt_uuid.uu.uuid128, LEN_UUID_128);
413 BTIF_TRACE_DEBUG(
414 "%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x",
415 bt_uuid.uu.uuid128[0], bt_uuid.uu.uuid128[1],
416 bt_uuid.uu.uuid128[2], bt_uuid.uu.uuid128[3],
417 bt_uuid.uu.uuid128[4], bt_uuid.uu.uuid128[5],
418 bt_uuid.uu.uuid128[6], bt_uuid.uu.uuid128[7],
419 bt_uuid.uu.uuid128[8], bt_uuid.uu.uuid128[9],
420 bt_uuid.uu.uuid128[10], bt_uuid.uu.uuid128[11],
421 bt_uuid.uu.uuid128[12], bt_uuid.uu.uuid128[13],
422 bt_uuid.uu.uuid128[14], bt_uuid.uu.uuid128[15]);
423 ++p_multi_adv_data_cb->inst_cb[cbindex]
424 .data.services_128b.num_service;
425 p_multi_adv_data_cb->inst_cb[cbindex]
426 .data.services_128b.list_cmpl = TRUE;
427 }
428 break;
429 }
430
431 default:
432 break;
433 }
434 }
435 }
436
437 return true;
438 }
439
btif_gattc_clear_clientif(int client_if,BOOLEAN stop_timer)440 void btif_gattc_clear_clientif(int client_if, BOOLEAN stop_timer)
441 {
442 btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
443 if (NULL == p_multi_adv_data_cb)
444 return;
445
446 // Clear both the inst_id and client_if values
447 for (int i=0; i < BTM_BleMaxMultiAdvInstanceCount()*2; i+=2)
448 {
449 if (client_if == p_multi_adv_data_cb->clntif_map[i])
450 {
451 btif_gattc_cleanup_inst_cb(p_multi_adv_data_cb->clntif_map[i+1], stop_timer);
452 if (stop_timer)
453 {
454 p_multi_adv_data_cb->clntif_map[i] = INVALID_ADV_INST;
455 p_multi_adv_data_cb->clntif_map[i+1] = INVALID_ADV_INST;
456 BTIF_TRACE_DEBUG("Cleaning up index %d for clnt_if :%d,", i/2, client_if);
457 }
458 break;
459 }
460 }
461 }
462
btif_gattc_cleanup_inst_cb(int inst_id,BOOLEAN stop_timer)463 void btif_gattc_cleanup_inst_cb(int inst_id, BOOLEAN stop_timer)
464 {
465 // Check for invalid instance id
466 if (inst_id < 0 || inst_id >= BTM_BleMaxMultiAdvInstanceCount())
467 return;
468
469 btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
470 if (NULL == p_multi_adv_data_cb)
471 return;
472
473 int cbindex = (STD_ADV_INSTID == inst_id) ?
474 STD_ADV_INSTID : btif_gattc_obtain_idx_for_datacb(inst_id, INST_ID_IDX);
475 if (cbindex < 0) return;
476
477 BTIF_TRACE_DEBUG("%s: inst_id %d, cbindex %d", __func__, inst_id, cbindex);
478 btif_gattc_cleanup_multi_inst_cb(&p_multi_adv_data_cb->inst_cb[cbindex], stop_timer);
479 }
480
btif_gattc_cleanup_multi_inst_cb(btgatt_multi_adv_inst_cb * p_multi_inst_cb,BOOLEAN stop_timer)481 void btif_gattc_cleanup_multi_inst_cb(btgatt_multi_adv_inst_cb *p_multi_inst_cb,
482 BOOLEAN stop_timer)
483 {
484 if (p_multi_inst_cb == NULL)
485 return;
486
487 // Discoverability timer cleanup
488 if (stop_timer)
489 {
490 alarm_free(p_multi_inst_cb->multi_adv_timer);
491 p_multi_inst_cb->multi_adv_timer = NULL;
492 }
493
494 memset(&p_multi_inst_cb->data, 0, sizeof(p_multi_inst_cb->data));
495 }
496
btif_multi_adv_timer_ctrl(int client_if,alarm_callback_t cb)497 void btif_multi_adv_timer_ctrl(int client_if, alarm_callback_t cb)
498 {
499 int inst_id = btif_multi_adv_instid_for_clientif(client_if);
500 if (inst_id == INVALID_ADV_INST)
501 return;
502
503 int cbindex = btif_gattc_obtain_idx_for_datacb(inst_id, INST_ID_IDX);
504 if (cbindex == INVALID_ADV_INST)
505 return;
506
507 btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
508 if (p_multi_adv_data_cb == NULL)
509 return;
510
511 btgatt_multi_adv_inst_cb *inst_cb = &p_multi_adv_data_cb->inst_cb[cbindex];
512 if (cb == NULL)
513 {
514 alarm_free(inst_cb->multi_adv_timer);
515 inst_cb->multi_adv_timer = NULL;
516 } else {
517 if (inst_cb->timeout_s != 0)
518 {
519 alarm_free(inst_cb->multi_adv_timer);
520 inst_cb->multi_adv_timer = alarm_new("btif_gatt.multi_adv_timer");
521 alarm_set_on_queue(inst_cb->multi_adv_timer,
522 inst_cb->timeout_s * 1000,
523 cb, INT_TO_PTR(client_if),
524 btu_general_alarm_queue);
525 }
526 }
527 }
528
529 #endif
530