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
47extern fixed_queue_t *btu_general_alarm_queue;
48
49/*******************************************************************************
50**  Static variables
51********************************************************************************/
52static int user_app_count = 0;
53static btgatt_multi_adv_common_data *p_multi_adv_com_data_cb = NULL;
54
55btgatt_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
82void 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
89void 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
101int 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
162int 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
184int 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
210void 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
248void 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
255BOOLEAN 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
440void 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
463void 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
481void 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
497void 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