1dbba0e652e0ce23dd691df3c03979ec6e32c8db3Matthew Xie/******************************************************************************
2dbba0e652e0ce23dd691df3c03979ec6e32c8db3Matthew Xie *
3dbba0e652e0ce23dd691df3c03979ec6e32c8db3Matthew Xie *  Copyright (C) 1999-2013 Broadcom Corporation
4dbba0e652e0ce23dd691df3c03979ec6e32c8db3Matthew Xie *
5dbba0e652e0ce23dd691df3c03979ec6e32c8db3Matthew Xie *  Licensed under the Apache License, Version 2.0 (the "License");
6dbba0e652e0ce23dd691df3c03979ec6e32c8db3Matthew Xie *  you may not use this file except in compliance with the License.
7dbba0e652e0ce23dd691df3c03979ec6e32c8db3Matthew Xie *  You may obtain a copy of the License at:
8dbba0e652e0ce23dd691df3c03979ec6e32c8db3Matthew Xie *
9dbba0e652e0ce23dd691df3c03979ec6e32c8db3Matthew Xie *  http://www.apache.org/licenses/LICENSE-2.0
10dbba0e652e0ce23dd691df3c03979ec6e32c8db3Matthew Xie *
11dbba0e652e0ce23dd691df3c03979ec6e32c8db3Matthew Xie *  Unless required by applicable law or agreed to in writing, software
12dbba0e652e0ce23dd691df3c03979ec6e32c8db3Matthew Xie *  distributed under the License is distributed on an "AS IS" BASIS,
13dbba0e652e0ce23dd691df3c03979ec6e32c8db3Matthew Xie *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14dbba0e652e0ce23dd691df3c03979ec6e32c8db3Matthew Xie *  See the License for the specific language governing permissions and
15dbba0e652e0ce23dd691df3c03979ec6e32c8db3Matthew Xie *  limitations under the License.
16dbba0e652e0ce23dd691df3c03979ec6e32c8db3Matthew Xie *
17dbba0e652e0ce23dd691df3c03979ec6e32c8db3Matthew Xie ******************************************************************************/
182e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach
192e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach#include "bt_target.h"
205cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen#include "bt_utils.h"
21911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "btcore/include/uuid.h"
222e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach#include "gatt_api.h"
232e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach#include "gatt_int.h"
24d7ffd64accbd50a27289a388856e56244ccbb5daMyles Watson#include "osi/include/osi.h"
25911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "srvc_battery_int.h"
26911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "srvc_eng_int.h"
272e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach
28911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#define BA_MAX_CHAR_NUM 1
299ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson
309ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson/* max 3 descriptors, 1 desclration and 1 value */
31911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#define BA_MAX_ATTR_NUM (BA_MAX_CHAR_NUM * 5 + 1)
322e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach
332e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach#ifndef BATTER_LEVEL_PROP
34911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#define BATTER_LEVEL_PROP (GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY)
352e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach#endif
362e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach
372e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach#ifndef BATTER_LEVEL_PERM
38911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#define BATTER_LEVEL_PERM (GATT_PERM_READ)
392e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach#endif
402e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach
412e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre EisenbachtBATTERY_CB battery_cb;
422e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach
432e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach/*******************************************************************************
44ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *   battery_valid_handle_range
45ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
46ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *   validate a handle to be a DIS attribute handle or not.
47ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
48911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool battery_valid_handle_range(uint16_t handle) {
49911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t i = 0;
50911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBA_INST* p_inst = &battery_cb.battery_inst[0];
51911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
52911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (; i < BA_MAX_INT_NUM; i++, p_inst++) {
53911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (handle == p_inst->ba_level_hdl || handle == p_inst->clt_cfg_hdl ||
54911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        handle == p_inst->rpt_ref_hdl || handle == p_inst->pres_fmt_hdl) {
55911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return true;
562e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach    }
57911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
58911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return false;
592e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach}
602e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach/*******************************************************************************
61ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *   battery_s_write_attr_value
62ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
63ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *   Process write DIS attribute request.
64ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
65911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint8_t battery_s_write_attr_value(uint8_t clcb_idx, tGATT_WRITE_REQ* p_value,
66911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                   tGATT_STATUS* p_status) {
67911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t *p = p_value->value, i;
68911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t handle = p_value->handle;
69911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBA_INST* p_inst = &battery_cb.battery_inst[0];
70911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tGATT_STATUS st = GATT_NOT_FOUND;
71911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBA_WRITE_DATA cfg;
72911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t act = SRVC_ACT_RSP;
73911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
74911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (i = 0; i < BA_MAX_INT_NUM; i++, p_inst++) {
75911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* read battery level */
76911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (handle == p_inst->clt_cfg_hdl) {
77911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      memcpy(cfg.remote_bda, srvc_eng_cb.clcb[clcb_idx].bda, BD_ADDR_LEN);
78911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      STREAM_TO_UINT16(cfg.clt_cfg, p);
79911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
80911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_inst->p_cback) {
81911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_inst->pending_clcb_idx = clcb_idx;
82911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_inst->pending_evt = BA_WRITE_CLT_CFG_REQ;
83911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_inst->pending_handle = handle;
84911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        cfg.need_rsp = p_value->need_rsp;
85911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        act = SRVC_ACT_PENDING;
86911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
87911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (*p_inst->p_cback)(p_inst->app_id, BA_WRITE_CLT_CFG_REQ, &cfg);
88911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
89911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else /* all other handle is not writable */
902e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach    {
91911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      st = GATT_WRITE_NOT_PERMIT;
92911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      break;
932e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach    }
94911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
95911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  *p_status = st;
962e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach
97911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return act;
982e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach}
992e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach/*******************************************************************************
100ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *   BA Attributes Database Server Request callback
101ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
102911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint8_t battery_s_read_attr_value(uint8_t clcb_idx, uint16_t handle,
103911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                  UNUSED_ATTR tGATT_VALUE* p_value,
104911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                  bool is_long, tGATT_STATUS* p_status) {
105911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t i;
106911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBA_INST* p_inst = &battery_cb.battery_inst[0];
107911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tGATT_STATUS st = GATT_NOT_FOUND;
108911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t act = SRVC_ACT_RSP;
109911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
110911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (i = 0; i < BA_MAX_INT_NUM; i++, p_inst++) {
111911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* read battery level */
112911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (handle == p_inst->ba_level_hdl || handle == p_inst->clt_cfg_hdl ||
113911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        handle == p_inst->rpt_ref_hdl || handle == p_inst->pres_fmt_hdl) {
114911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (is_long) st = GATT_NOT_LONG;
115911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
116911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_inst->p_cback) {
117911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (handle == p_inst->ba_level_hdl)
118911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_inst->pending_evt = BA_READ_LEVEL_REQ;
119911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (handle == p_inst->clt_cfg_hdl)
120911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_inst->pending_evt = BA_READ_CLT_CFG_REQ;
121911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (handle == p_inst->pres_fmt_hdl)
122911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_inst->pending_evt = BA_READ_PRE_FMT_REQ;
123911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (handle == p_inst->rpt_ref_hdl)
124911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_inst->pending_evt = BA_READ_RPT_REF_REQ;
125911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
126911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_inst->pending_clcb_idx = clcb_idx;
127911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_inst->pending_handle = handle;
128911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        act = SRVC_ACT_PENDING;
129911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
130911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (*p_inst->p_cback)(p_inst->app_id, p_inst->pending_evt, NULL);
131911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      } else /* application is not registered */
132911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        st = GATT_ERR_UNLIKELY;
133911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      break;
1342e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach    }
135911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* else attribute not found */
136911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1372e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach
138911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  *p_status = st;
139911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return act;
1402e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach}
1412e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach
1422e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach/*******************************************************************************
143ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
144ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         battery_gatt_c_read_ba_req
145ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
146ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Read remote device BA level attribute request.
147ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
148ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
149ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
150ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
151911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool battery_gatt_c_read_ba_req(UNUSED_ATTR uint16_t conn_id) { return true; }
1522e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach
1532e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach/*******************************************************************************
154ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
155ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         battery_c_cmpl_cback
156ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
157ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Client operation complete callback.
158ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
159ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
160ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
161ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
162911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid battery_c_cmpl_cback(UNUSED_ATTR tSRVC_CLCB* p_clcb,
163911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                          UNUSED_ATTR tGATTC_OPTYPE op,
164911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                          UNUSED_ATTR tGATT_STATUS status,
165911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                          UNUSED_ATTR tGATT_CL_COMPLETE* p_data) {}
1662e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach
1672e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach/*******************************************************************************
168ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
169ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         Battery_Instantiate
170ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
171ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Instantiate a Battery service
172ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
173ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint16_t Battery_Instantiate(uint8_t app_id, tBA_REG_INFO* p_reg_info) {
175911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t srvc_hdl = 0;
176911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tGATT_STATUS status = GATT_ERROR;
177911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBA_INST* p_inst;
178911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
179911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (battery_cb.inst_id == BA_MAX_INT_NUM) {
180911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    GATT_TRACE_ERROR("MAX battery service has been reached");
181911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return 0;
182911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
183911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
184911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_inst = &battery_cb.battery_inst[battery_cb.inst_id];
185911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
186911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  btgatt_db_element_t service[BA_MAX_ATTR_NUM] = {};
187911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
188911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bt_uuid_t service_uuid;
189911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uuid_128_from_16(&service_uuid, UUID_SERVCLASS_BATTERY);
190911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  service[0].type = /* p_reg_info->is_pri */ BTGATT_DB_PRIMARY_SERVICE;
191911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  service[0].uuid = service_uuid;
192911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
193911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bt_uuid_t char_uuid;
194911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uuid_128_from_16(&char_uuid, GATT_UUID_BATTERY_LEVEL);
195911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  service[1].type = BTGATT_DB_CHARACTERISTIC;
196911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  service[1].uuid = char_uuid;
197911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  service[1].properties = GATT_CHAR_PROP_BIT_READ;
198911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY)
199911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    service[1].properties |= GATT_CHAR_PROP_BIT_NOTIFY;
200911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
201911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int i = 2;
202911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY) {
203911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    bt_uuid_t desc_uuid;
204911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    uuid_128_from_16(&desc_uuid, GATT_UUID_CHAR_CLIENT_CONFIG);
205911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
206911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    service[i].type = BTGATT_DB_DESCRIPTOR;
207911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    service[i].uuid = desc_uuid;
208911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    service[i].permissions = (GATT_PERM_READ | GATT_PERM_WRITE);
209911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    i++;
210911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
211911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
212911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* need presentation format descriptor? */
213911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_reg_info->ba_level_descr & BA_LEVEL_PRE_FMT) {
214911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    bt_uuid_t desc_uuid;
215911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    uuid_128_from_16(&desc_uuid, GATT_UUID_CHAR_PRESENT_FORMAT);
216911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
217911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    service[i].type = BTGATT_DB_DESCRIPTOR;
218911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    service[i].uuid = desc_uuid;
219911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    service[i].permissions = GATT_PERM_READ;
220911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    i++;
221911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
222911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
223911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* need presentation format descriptor? */
224911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_reg_info->ba_level_descr & BA_LEVEL_RPT_REF) {
225911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    bt_uuid_t desc_uuid;
226911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    uuid_128_from_16(&desc_uuid, GATT_UUID_RPT_REF_DESCR);
227911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
228911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    service[i].type = BTGATT_DB_DESCRIPTOR;
229911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    service[i].uuid = desc_uuid;
230911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    service[i].permissions = GATT_PERM_READ;
231911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    i++;
232911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
233911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
234911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  GATTS_AddService(srvc_eng_cb.gatt_if, service, i);
235911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
236911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (status != GATT_SUCCESS) {
237911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    battery_cb.inst_id--;
238911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    GATT_TRACE_ERROR("%s: Failed to add battery servuce!", __func__);
239911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
240911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
241911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  battery_cb.inst_id++;
242911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
243911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_inst->app_id = app_id;
244911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_inst->p_cback = p_reg_info->p_cback;
245911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
246911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  srvc_hdl = service[0].attribute_handle;
247911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_inst->ba_level_hdl = service[1].attribute_handle;
248911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
249911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  i = 2;
250911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY) {
251911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_inst->clt_cfg_hdl = service[i].attribute_handle;
252911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    i++;
253911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
254911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
255911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_reg_info->ba_level_descr & BA_LEVEL_PRE_FMT) {
256911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_inst->pres_fmt_hdl = service[i].attribute_handle;
257911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    i++;
258911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
259911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
260911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_reg_info->ba_level_descr & BA_LEVEL_RPT_REF) {
261911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_inst->rpt_ref_hdl = service[i].attribute_handle;
262911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    i++;
263911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
264911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
265911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return srvc_hdl;
2662e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach}
2672e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach/*******************************************************************************
268ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
269ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         Battery_Rsp
270ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
271ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Respond to a battery service request
272ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
273ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
274911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid Battery_Rsp(uint8_t app_id, tGATT_STATUS st, uint8_t event,
275911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                 tBA_RSP_DATA* p_rsp) {
276911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBA_INST* p_inst = &battery_cb.battery_inst[0];
277911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tGATTS_RSP rsp;
278911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* pp;
279911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
280911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t i = 0;
281911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  while (i < BA_MAX_INT_NUM) {
282911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_inst->app_id == app_id && p_inst->ba_level_hdl != 0) break;
283911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    i++;
284911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
285911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
286911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (i == BA_MAX_INT_NUM) return;
287911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
288911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  memset(&rsp, 0, sizeof(tGATTS_RSP));
289911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
290911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_inst->pending_evt == event) {
291911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    switch (event) {
292911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      case BA_READ_CLT_CFG_REQ:
293911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        rsp.attr_value.handle = p_inst->pending_handle;
294911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        rsp.attr_value.len = 2;
295911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        pp = rsp.attr_value.value;
296911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        UINT16_TO_STREAM(pp, p_rsp->clt_cfg);
297911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        srvc_sr_rsp(p_inst->pending_clcb_idx, st, &rsp);
298911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        break;
299911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
300911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      case BA_READ_LEVEL_REQ:
301911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        rsp.attr_value.handle = p_inst->pending_handle;
302911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        rsp.attr_value.len = 1;
303911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        pp = rsp.attr_value.value;
304911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        UINT8_TO_STREAM(pp, p_rsp->ba_level);
305911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        srvc_sr_rsp(p_inst->pending_clcb_idx, st, &rsp);
306911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        break;
307911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
308911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      case BA_WRITE_CLT_CFG_REQ:
309911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        srvc_sr_rsp(p_inst->pending_clcb_idx, st, NULL);
310911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        break;
311911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
312911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      case BA_READ_RPT_REF_REQ:
313911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        rsp.attr_value.handle = p_inst->pending_handle;
314911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        rsp.attr_value.len = 2;
315911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        pp = rsp.attr_value.value;
316911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        UINT8_TO_STREAM(pp, p_rsp->rpt_ref.rpt_id);
317911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        UINT8_TO_STREAM(pp, p_rsp->rpt_ref.rpt_type);
318911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        srvc_sr_rsp(p_inst->pending_clcb_idx, st, &rsp);
319911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        break;
320911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
321911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      default:
322911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        break;
3232e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach    }
324911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_inst->pending_clcb_idx = 0;
325911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_inst->pending_evt = 0;
326911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_inst->pending_handle = 0;
327911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
328911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return;
3292e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach}
3302e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach/*******************************************************************************
331ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
332ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         Battery_Notify
333ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
334ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Send battery level notification
335ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
336ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
337911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid Battery_Notify(uint8_t app_id, BD_ADDR remote_bda, uint8_t battery_level) {
338911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBA_INST* p_inst = &battery_cb.battery_inst[0];
339911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t i = 0;
3402e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach
341911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  while (i < BA_MAX_INT_NUM) {
342911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_inst->app_id == app_id && p_inst->ba_level_hdl != 0) break;
343911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    i++;
344911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3452e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach
346911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (i == BA_MAX_INT_NUM || p_inst->clt_cfg_hdl == 0) return;
3472e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach
348911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  srvc_sr_notify(remote_bda, p_inst->ba_level_hdl, 1, &battery_level);
3492e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach}
3502e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach/*******************************************************************************
351ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
352ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         Battery_ReadBatteryLevel
353ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
354ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Read remote device Battery Level information.
355ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
356ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
357ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
358ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
359911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool Battery_ReadBatteryLevel(UNUSED_ATTR BD_ADDR peer_bda) {
360911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* to be implemented */
361911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return true;
3622e7fa68bfd9723b7ec7b6b0b128d89f31a2e06eeAndre Eisenbach}
363