1/******************************************************************************
2 *
3 *  Copyright (C) 2009-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 is the implementation file for the HeaLth device profile (HL)
22 *  subsystem call-out functions.
23 *
24 ******************************************************************************/
25
26#include <ctype.h>
27#include <errno.h>
28#include <fcntl.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <sys/socket.h>
33#include <sys/types.h>
34#include <sys/un.h>
35#include <time.h>
36
37#include "bta_api.h"
38#include "bta_hl_api.h"
39#include "bta_hl_ci.h"
40#include "bta_hl_co.h"
41#include "bta_sys.h"
42#include "btif_hl.h"
43#include "btif_util.h"
44#include "btm_api.h"
45#include "osi/include/osi.h"
46
47/*****************************************************************************
48 *  Constants and Data Types
49 ****************************************************************************/
50/**************************
51 *  Common Definitions
52 **************************/
53
54/*******************************************************************************
55 *
56 * Function        bta_hl_co_get_num_of_mdep
57 *
58 * Description     This function is called to get the number of MDEPs for this
59 *                 application ID
60 *
61 * Parameters      app_id - application ID
62 *                 p_num_of_mdep (output) - number of MDEP configurations
63 *                                          supported by the application
64 *
65 * Returns         true on success
66 *
67 ******************************************************************************/
68bool bta_hl_co_get_num_of_mdep(uint8_t app_id, uint8_t* p_num_of_mdep) {
69  uint8_t app_idx;
70  bool success = false;
71
72  if (btif_hl_find_app_idx(app_id, &app_idx)) {
73    *p_num_of_mdep = p_btif_hl_cb->acb[app_idx].sup_feature.num_of_mdeps;
74    success = true;
75  }
76
77  BTIF_TRACE_DEBUG("%s success=%d num_mdeps=%d", __func__, success,
78                   *p_num_of_mdep);
79  return success;
80}
81
82/*******************************************************************************
83 *
84 * Function        bta_hl_co_advrtise_source_sdp
85 *
86 * Description     This function is called to find out whether the SOURCE MDEP
87 *                 configuration information should be advertise in the SDP or
88 *                 not.
89 *
90 * Parameters      app_id - application ID
91 *
92 * Returns         true when advertise the SOURCE MDEP configuration
93 *                            information
94 *
95 ******************************************************************************/
96bool bta_hl_co_advrtise_source_sdp(uint8_t app_id) {
97  bool advertize_source_sdp = false;
98  uint8_t app_idx;
99
100  if (btif_hl_find_app_idx(app_id, &app_idx)) {
101    advertize_source_sdp =
102        p_btif_hl_cb->acb[app_idx].sup_feature.advertize_source_sdp;
103  }
104
105  BTIF_TRACE_DEBUG("%s advertize_flag=%d", __func__, advertize_source_sdp);
106
107  return advertize_source_sdp;
108}
109/*******************************************************************************
110 *
111 * Function        bta_hl_co_get_mdep_config
112 *
113 * Description     This function is called to get the supported feature
114 *                 configuration for the specified mdep index and it also
115 *                 assigns the MDEP ID for the specified mdep index
116 *
117 * Parameters      app_id - HDP application ID
118 *                 mdep_idx - the mdep index
119 *                  mdep_counter - number of mdeps
120 *                 mdep_id  - the assigned MDEP ID for the specified medp_idx
121 *                 p_mdl_cfg (output) - pointer to the MDEP configuration
122 *
123 *
124 * Returns         Bloolean - true success
125 ******************************************************************************/
126bool bta_hl_co_get_mdep_config(uint8_t app_id, uint8_t mdep_idx,
127                               uint8_t mdep_counter, tBTA_HL_MDEP_ID mdep_id,
128                               tBTA_HL_MDEP_CFG* p_mdep_cfg) {
129  uint8_t idx;
130  uint8_t app_idx;
131  bool success = false;
132
133  BTIF_TRACE_DEBUG("%s app_id=%d mdep_idx=%d mdep_id=%d mdep_counter=%d",
134                   __func__, app_id, mdep_idx, mdep_id, mdep_counter);
135
136  if (btif_hl_find_app_idx(app_id, &app_idx)) {
137    idx = mdep_idx - mdep_counter - 1;
138    p_btif_hl_cb->acb[app_idx].sup_feature.mdep[idx].mdep_id = mdep_id;
139    memcpy(p_mdep_cfg,
140           &p_btif_hl_cb->acb[app_idx].sup_feature.mdep[idx].mdep_cfg,
141           sizeof(tBTA_HL_MDEP_CFG));
142
143    success = true;
144  }
145
146  BTIF_TRACE_DEBUG("%s success=%d mdep_idx=%d mdep_id=%d", __func__, success,
147                   mdep_idx, mdep_id);
148
149  return success;
150}
151
152/*******************************************************************************
153 *
154 * Function        bta_hl_co_get_echo_config
155 *
156 * Description     This function is called to get the echo test
157 *                 maximum APDU size configurations
158 *
159 * Parameters      app_id - HDP application ID
160 *                 p_echo_cfg (output) - pointer to the Echo test maximum APDU
161 *                                       size configuration
162 *
163 * Returns         Bloolean - true success
164 ******************************************************************************/
165bool bta_hl_co_get_echo_config(uint8_t app_id, tBTA_HL_ECHO_CFG* p_echo_cfg) {
166  uint8_t app_idx;
167  bool success = false;
168  btif_hl_app_cb_t* p_acb;
169  tBTA_HL_SUP_FEATURE* p_sup;
170
171  BTIF_TRACE_DEBUG("%s app_id=%d", __func__, app_id);
172
173  if (btif_hl_find_app_idx(app_id, &app_idx)) {
174    p_acb = BTIF_HL_GET_APP_CB_PTR(app_idx);
175    p_sup = &p_acb->sup_feature;
176    p_echo_cfg->max_rx_apdu_size = p_sup->echo_cfg.max_rx_apdu_size;
177    p_echo_cfg->max_tx_apdu_size = p_sup->echo_cfg.max_tx_apdu_size;
178    success = true;
179  }
180
181  BTIF_TRACE_DEBUG("%s success=%d max tx_size=%d rx_size=%d", __func__, success,
182                   p_echo_cfg->max_tx_apdu_size, p_echo_cfg->max_rx_apdu_size);
183
184  return success;
185}
186
187/*******************************************************************************
188 *
189 * Function        bta_hl_co_save_mdl
190 *
191 * Description     This function is called to save a MDL configuration item in
192 *                 persistent storage
193 *
194 * Parameters      app_id - HDP application ID
195 *                 item_idx - the MDL configuration storage index
196 *                 p_mdl_cfg - pointer to the MDL configuration data
197 *
198 * Returns        void
199 *
200 ******************************************************************************/
201void bta_hl_co_save_mdl(uint8_t mdep_id, uint8_t item_idx,
202                        tBTA_HL_MDL_CFG* p_mdl_cfg) {
203  BTIF_TRACE_DEBUG("%s mdep_id =%d, item_idx=%d active=%d mdl_id=%d time=%d",
204                   __func__, mdep_id, item_idx, p_mdl_cfg->active,
205                   p_mdl_cfg->mdl_id, p_mdl_cfg->time);
206
207  btif_hl_save_mdl_cfg(mdep_id, item_idx, p_mdl_cfg);
208}
209
210/*******************************************************************************
211 *
212 * Function        bta_hl_co_delete_mdl
213 *
214 * Description     This function is called to delete a MDL configuration item in
215 *                 persistent storage
216 *
217 * Parameters      app_id - HDP application ID
218 *                 item_idx - the MDL configuration storage index
219 *
220 * Returns          void
221 *
222 ******************************************************************************/
223void bta_hl_co_delete_mdl(uint8_t mdep_id, uint8_t item_idx) {
224  BTIF_TRACE_DEBUG("%s mdep_id=%d, item_idx=%d", __func__, mdep_id, item_idx);
225
226  btif_hl_delete_mdl_cfg(mdep_id, item_idx);
227}
228
229/*******************************************************************************
230 *
231 * Function         bta_hl_co_get_mdl_config
232 *
233 * Description     This function is called to get the MDL configuration
234 *                 from the persistent memory. This function shall only be
235 *                 called once after the device is powered up
236 *
237 * Parameters      app_id - HDP application ID
238 *                 buffer_size - the unit of the buffer size is
239 *                               sizeof(tBTA_HL_MDL_CFG)
240 *                 p_mdl_buf - Point to the starting location of the buffer
241 *
242 * Returns         bool
243 *
244 *
245 ******************************************************************************/
246bool bta_hl_co_load_mdl_config(uint8_t app_id, uint8_t buffer_size,
247                               tBTA_HL_MDL_CFG* p_mdl_buf) {
248  bool result = true;
249  uint8_t i;
250  tBTA_HL_MDL_CFG* p;
251
252  BTIF_TRACE_DEBUG("%s app_id=%d, num_items=%d", __func__, app_id, buffer_size);
253
254  if (buffer_size > BTA_HL_NUM_MDL_CFGS) {
255    result = false;
256    return result;
257  }
258  result = btif_hl_load_mdl_config(app_id, buffer_size, p_mdl_buf);
259
260  if (result) {
261    for (i = 0, p = p_mdl_buf; i < buffer_size; i++, p++) {
262      if (p->active) {
263        BTIF_TRACE_DEBUG(
264            "i=%d mdl_id=0x%x dch_mode=%d local mdep_role=%d mdep_id=%d mtu=%d",
265            i, p->mdl_id, p->dch_mode, p->local_mdep_role, p->local_mdep_role,
266            p->mtu);
267      }
268    }
269  }
270
271  BTIF_TRACE_DEBUG("%s success=%d num_items=%d", __func__, result, buffer_size);
272
273  return result;
274}
275
276/*******************************************************************************
277 *
278 * Function         bta_hl_co_get_tx_data
279 *
280 * Description     Get the data to be sent
281 *
282 * Parameters      app_id - HDP application ID
283 *                 mdl_handle - MDL handle
284 *                 buf_size - the size of the buffer
285 *                 p_buf - the buffer pointer
286 *                 evt - the evt to be passed back to the HL in the
287 *                       bta_hl_ci_get_tx_data call-in function
288 *
289 * Returns        Void
290 *
291 ******************************************************************************/
292void bta_hl_co_get_tx_data(uint8_t app_id, tBTA_HL_MDL_HANDLE mdl_handle,
293                           uint16_t buf_size, uint8_t* p_buf, uint16_t evt) {
294  uint8_t app_idx, mcl_idx, mdl_idx;
295  btif_hl_mdl_cb_t* p_dcb;
296  tBTA_HL_STATUS status = BTA_HL_STATUS_FAIL;
297
298  BTIF_TRACE_DEBUG("%s app_id=%d mdl_handle=0x%x buf_size=%d", __func__, app_id,
299                   mdl_handle, buf_size);
300
301  if (btif_hl_find_mdl_idx_using_handle(mdl_handle, &app_idx, &mcl_idx,
302                                        &mdl_idx)) {
303    p_dcb = BTIF_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
304
305    if ((p_dcb->tx_size <= buf_size) && p_dcb->p_tx_pkt) {
306      memcpy(p_buf, p_dcb->p_tx_pkt, p_dcb->tx_size);
307      osi_free_and_reset((void**)&p_dcb->p_tx_pkt);
308      p_dcb->tx_size = 0;
309      status = BTA_HL_STATUS_OK;
310    }
311  }
312
313  bta_hl_ci_get_tx_data(mdl_handle, status, evt);
314}
315
316/*******************************************************************************
317 *
318 * Function        bta_hl_co_put_rx_data
319 *
320 * Description     Put the received data
321 *
322 * Parameters      app_id - HDP application ID
323 *                 mdl_handle - MDL handle
324 *                 data_size - the size of the data
325 *                 p_data - the data pointer
326 *                 evt - the evt to be passed back to the HL in the
327 *                       bta_hl_ci_put_rx_data call-in function
328 *
329 * Returns        Void
330 *
331 ******************************************************************************/
332void bta_hl_co_put_rx_data(uint8_t app_id, tBTA_HL_MDL_HANDLE mdl_handle,
333                           uint16_t data_size, uint8_t* p_data, uint16_t evt) {
334  uint8_t app_idx, mcl_idx, mdl_idx;
335  btif_hl_mdl_cb_t* p_dcb;
336  tBTA_HL_STATUS status = BTA_HL_STATUS_FAIL;
337  BTIF_TRACE_DEBUG("%s app_id=%d mdl_handle=0x%x data_size=%d", __func__,
338                   app_id, mdl_handle, data_size);
339
340  if (btif_hl_find_mdl_idx_using_handle(mdl_handle, &app_idx, &mcl_idx,
341                                        &mdl_idx)) {
342    p_dcb = BTIF_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
343
344    p_dcb->p_rx_pkt = (uint8_t*)osi_malloc(data_size);
345    memcpy(p_dcb->p_rx_pkt, p_data, data_size);
346    if (p_dcb->p_scb) {
347      BTIF_TRACE_DEBUG("app_idx=%d mcl_idx=0x%x mdl_idx=0x%x data_size=%d",
348                       app_idx, mcl_idx, mdl_idx, data_size);
349      ssize_t r;
350      OSI_NO_INTR(
351          r = send(p_dcb->p_scb->socket_id[1], p_dcb->p_rx_pkt, data_size, 0));
352      if (r == data_size) {
353        BTIF_TRACE_DEBUG("socket send success data_size=%d", data_size);
354        status = BTA_HL_STATUS_OK;
355      } else {
356        BTIF_TRACE_ERROR("socket send failed r=%d data_size=%d", r, data_size);
357      }
358    }
359    osi_free_and_reset((void**)&p_dcb->p_rx_pkt);
360  }
361
362  bta_hl_ci_put_rx_data(mdl_handle, status, evt);
363}
364
365/*******************************************************************************
366 *
367 * Function         bta_hl_co_get_tx_data
368 *
369 * Description     Get the Echo data to be sent
370 *
371 * Parameters      app_id - HDP application ID
372 *                 mcl_handle - MCL handle
373 *                 buf_size - the size of the buffer
374 *                 p_buf - the buffer pointer
375 *                 evt - the evt to be passed back to the HL in the
376 *                       bta_hl_ci_get_tx_data call-in function
377 *
378 * Returns        Void
379 *
380 ******************************************************************************/
381void bta_hl_co_get_echo_data(UNUSED_ATTR uint8_t app_id,
382                             tBTA_HL_MCL_HANDLE mcl_handle,
383                             UNUSED_ATTR uint16_t buf_size,
384                             UNUSED_ATTR uint8_t* p_buf, uint16_t evt) {
385  tBTA_HL_STATUS status = BTA_HL_STATUS_FAIL;
386
387  BTIF_TRACE_ERROR("%s not supported", __func__);
388  bta_hl_ci_get_echo_data(mcl_handle, status, evt);
389}
390
391/*******************************************************************************
392 *
393 * Function        bta_hl_co_put_echo_data
394 *
395 * Description     Put the received loopback echo data
396 *
397 * Parameters      app_id - HDP application ID
398 *                 mcl_handle - MCL handle
399 *                 data_size - the size of the data
400 *                 p_data - the data pointer
401 *                 evt - the evt to be passed back to the HL in the
402 *                       bta_hl_ci_put_echo_data call-in function
403 *
404 * Returns        Void
405 *
406 ******************************************************************************/
407void bta_hl_co_put_echo_data(UNUSED_ATTR uint8_t app_id,
408                             tBTA_HL_MCL_HANDLE mcl_handle,
409                             UNUSED_ATTR uint16_t data_size,
410                             UNUSED_ATTR uint8_t* p_data, uint16_t evt) {
411  tBTA_HL_STATUS status = BTA_HL_STATUS_FAIL;
412
413  BTIF_TRACE_ERROR("%s not supported", __func__);
414  bta_hl_ci_put_echo_data(mcl_handle, status, evt);
415}
416