1 /****************************************************************************** 2 * 3 * Copyright 1999-2013 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 #include "bt_target.h" 20 #include "bt_utils.h" 21 #include "gatt_api.h" 22 #include "gatt_int.h" 23 #include "osi/include/osi.h" 24 #include "srvc_battery_int.h" 25 #include "srvc_eng_int.h" 26 27 #define BA_MAX_CHAR_NUM 1 28 29 /* max 3 descriptors, 1 desclration and 1 value */ 30 #define BA_MAX_ATTR_NUM (BA_MAX_CHAR_NUM * 5 + 1) 31 32 #ifndef BATTER_LEVEL_PROP 33 #define BATTER_LEVEL_PROP (GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY) 34 #endif 35 36 #ifndef BATTER_LEVEL_PERM 37 #define BATTER_LEVEL_PERM (GATT_PERM_READ) 38 #endif 39 40 tBATTERY_CB battery_cb; 41 42 /******************************************************************************* 43 * battery_valid_handle_range 44 * 45 * validate a handle to be a DIS attribute handle or not. 46 ******************************************************************************/ 47 bool battery_valid_handle_range(uint16_t handle) { 48 uint8_t i = 0; 49 tBA_INST* p_inst = &battery_cb.battery_inst[0]; 50 51 for (; i < BA_MAX_INT_NUM; i++, p_inst++) { 52 if (handle == p_inst->ba_level_hdl || handle == p_inst->clt_cfg_hdl || 53 handle == p_inst->rpt_ref_hdl || handle == p_inst->pres_fmt_hdl) { 54 return true; 55 } 56 } 57 return false; 58 } 59 /******************************************************************************* 60 * battery_s_write_attr_value 61 * 62 * Process write DIS attribute request. 63 ******************************************************************************/ 64 uint8_t battery_s_write_attr_value(uint8_t clcb_idx, tGATT_WRITE_REQ* p_value, 65 tGATT_STATUS* p_status) { 66 uint8_t *p = p_value->value, i; 67 uint16_t handle = p_value->handle; 68 tBA_INST* p_inst = &battery_cb.battery_inst[0]; 69 tGATT_STATUS st = GATT_NOT_FOUND; 70 tBA_WRITE_DATA cfg; 71 uint8_t act = SRVC_ACT_RSP; 72 73 for (i = 0; i < BA_MAX_INT_NUM; i++, p_inst++) { 74 /* read battery level */ 75 if (handle == p_inst->clt_cfg_hdl) { 76 cfg.remote_bda = srvc_eng_cb.clcb[clcb_idx].bda; 77 STREAM_TO_UINT16(cfg.clt_cfg, p); 78 79 if (p_inst->p_cback) { 80 p_inst->pending_clcb_idx = clcb_idx; 81 p_inst->pending_evt = BA_WRITE_CLT_CFG_REQ; 82 p_inst->pending_handle = handle; 83 cfg.need_rsp = p_value->need_rsp; 84 act = SRVC_ACT_PENDING; 85 86 (*p_inst->p_cback)(p_inst->app_id, BA_WRITE_CLT_CFG_REQ, &cfg); 87 } 88 } else /* all other handle is not writable */ 89 { 90 st = GATT_WRITE_NOT_PERMIT; 91 break; 92 } 93 } 94 *p_status = st; 95 96 return act; 97 } 98 /******************************************************************************* 99 * BA Attributes Database Server Request callback 100 ******************************************************************************/ 101 uint8_t battery_s_read_attr_value(uint8_t clcb_idx, uint16_t handle, 102 UNUSED_ATTR tGATT_VALUE* p_value, 103 bool is_long, tGATT_STATUS* p_status) { 104 uint8_t i; 105 tBA_INST* p_inst = &battery_cb.battery_inst[0]; 106 tGATT_STATUS st = GATT_NOT_FOUND; 107 uint8_t act = SRVC_ACT_RSP; 108 109 for (i = 0; i < BA_MAX_INT_NUM; i++, p_inst++) { 110 /* read battery level */ 111 if (handle == p_inst->ba_level_hdl || handle == p_inst->clt_cfg_hdl || 112 handle == p_inst->rpt_ref_hdl || handle == p_inst->pres_fmt_hdl) { 113 if (is_long) st = GATT_NOT_LONG; 114 115 if (p_inst->p_cback) { 116 if (handle == p_inst->ba_level_hdl) 117 p_inst->pending_evt = BA_READ_LEVEL_REQ; 118 if (handle == p_inst->clt_cfg_hdl) 119 p_inst->pending_evt = BA_READ_CLT_CFG_REQ; 120 if (handle == p_inst->pres_fmt_hdl) 121 p_inst->pending_evt = BA_READ_PRE_FMT_REQ; 122 if (handle == p_inst->rpt_ref_hdl) 123 p_inst->pending_evt = BA_READ_RPT_REF_REQ; 124 125 p_inst->pending_clcb_idx = clcb_idx; 126 p_inst->pending_handle = handle; 127 act = SRVC_ACT_PENDING; 128 129 (*p_inst->p_cback)(p_inst->app_id, p_inst->pending_evt, NULL); 130 } else /* application is not registered */ 131 st = GATT_ERR_UNLIKELY; 132 break; 133 } 134 /* else attribute not found */ 135 } 136 137 *p_status = st; 138 return act; 139 } 140 141 /******************************************************************************* 142 * 143 * Function battery_gatt_c_read_ba_req 144 * 145 * Description Read remote device BA level attribute request. 146 * 147 * Returns void 148 * 149 ******************************************************************************/ 150 bool battery_gatt_c_read_ba_req(UNUSED_ATTR uint16_t conn_id) { return true; } 151 152 /******************************************************************************* 153 * 154 * Function battery_c_cmpl_cback 155 * 156 * Description Client operation complete callback. 157 * 158 * Returns void 159 * 160 ******************************************************************************/ 161 void battery_c_cmpl_cback(UNUSED_ATTR tSRVC_CLCB* p_clcb, 162 UNUSED_ATTR tGATTC_OPTYPE op, 163 UNUSED_ATTR tGATT_STATUS status, 164 UNUSED_ATTR tGATT_CL_COMPLETE* p_data) {} 165 166 /******************************************************************************* 167 * 168 * Function Battery_Instantiate 169 * 170 * Description Instantiate a Battery service 171 * 172 ******************************************************************************/ 173 uint16_t Battery_Instantiate(uint8_t app_id, tBA_REG_INFO* p_reg_info) { 174 uint16_t srvc_hdl = 0; 175 tGATT_STATUS status = GATT_ERROR; 176 tBA_INST* p_inst; 177 178 if (battery_cb.inst_id == BA_MAX_INT_NUM) { 179 LOG(ERROR) << "MAX battery service has been reached"; 180 return 0; 181 } 182 183 p_inst = &battery_cb.battery_inst[battery_cb.inst_id]; 184 185 btgatt_db_element_t service[BA_MAX_ATTR_NUM] = {}; 186 187 bluetooth::Uuid service_uuid = 188 bluetooth::Uuid::From16Bit(UUID_SERVCLASS_BATTERY); 189 service[0].type = /* p_reg_info->is_pri */ BTGATT_DB_PRIMARY_SERVICE; 190 service[0].uuid = service_uuid; 191 192 bluetooth::Uuid char_uuid = 193 bluetooth::Uuid::From16Bit(GATT_UUID_BATTERY_LEVEL); 194 service[1].type = BTGATT_DB_CHARACTERISTIC; 195 service[1].uuid = char_uuid; 196 service[1].properties = GATT_CHAR_PROP_BIT_READ; 197 if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY) 198 service[1].properties |= GATT_CHAR_PROP_BIT_NOTIFY; 199 200 int i = 2; 201 if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY) { 202 bluetooth::Uuid desc_uuid = 203 bluetooth::Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG); 204 205 service[i].type = BTGATT_DB_DESCRIPTOR; 206 service[i].uuid = desc_uuid; 207 service[i].permissions = (GATT_PERM_READ | GATT_PERM_WRITE); 208 i++; 209 } 210 211 /* need presentation format descriptor? */ 212 if (p_reg_info->ba_level_descr & BA_LEVEL_PRE_FMT) { 213 bluetooth::Uuid desc_uuid = 214 bluetooth::Uuid::From16Bit(GATT_UUID_CHAR_PRESENT_FORMAT); 215 216 service[i].type = BTGATT_DB_DESCRIPTOR; 217 service[i].uuid = desc_uuid; 218 service[i].permissions = GATT_PERM_READ; 219 i++; 220 } 221 222 /* need presentation format descriptor? */ 223 if (p_reg_info->ba_level_descr & BA_LEVEL_RPT_REF) { 224 bluetooth::Uuid desc_uuid = 225 bluetooth::Uuid::From16Bit(GATT_UUID_RPT_REF_DESCR); 226 227 service[i].type = BTGATT_DB_DESCRIPTOR; 228 service[i].uuid = desc_uuid; 229 service[i].permissions = GATT_PERM_READ; 230 i++; 231 } 232 233 GATTS_AddService(srvc_eng_cb.gatt_if, service, i); 234 235 if (status != GATT_SUCCESS) { 236 battery_cb.inst_id--; 237 LOG(ERROR) << __func__ << " Failed to add battery servuce!"; 238 } 239 240 battery_cb.inst_id++; 241 242 p_inst->app_id = app_id; 243 p_inst->p_cback = p_reg_info->p_cback; 244 245 srvc_hdl = service[0].attribute_handle; 246 p_inst->ba_level_hdl = service[1].attribute_handle; 247 248 i = 2; 249 if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY) { 250 p_inst->clt_cfg_hdl = service[i].attribute_handle; 251 i++; 252 } 253 254 if (p_reg_info->ba_level_descr & BA_LEVEL_PRE_FMT) { 255 p_inst->pres_fmt_hdl = service[i].attribute_handle; 256 i++; 257 } 258 259 if (p_reg_info->ba_level_descr & BA_LEVEL_RPT_REF) { 260 p_inst->rpt_ref_hdl = service[i].attribute_handle; 261 i++; 262 } 263 264 return srvc_hdl; 265 } 266 /******************************************************************************* 267 * 268 * Function Battery_Rsp 269 * 270 * Description Respond to a battery service request 271 * 272 ******************************************************************************/ 273 void Battery_Rsp(uint8_t app_id, tGATT_STATUS st, uint8_t event, 274 tBA_RSP_DATA* p_rsp) { 275 tBA_INST* p_inst = &battery_cb.battery_inst[0]; 276 tGATTS_RSP rsp; 277 uint8_t* pp; 278 279 uint8_t i = 0; 280 while (i < BA_MAX_INT_NUM) { 281 if (p_inst->app_id == app_id && p_inst->ba_level_hdl != 0) break; 282 i++; 283 } 284 285 if (i == BA_MAX_INT_NUM) return; 286 287 memset(&rsp, 0, sizeof(tGATTS_RSP)); 288 289 if (p_inst->pending_evt == event) { 290 switch (event) { 291 case BA_READ_CLT_CFG_REQ: 292 rsp.attr_value.handle = p_inst->pending_handle; 293 rsp.attr_value.len = 2; 294 pp = rsp.attr_value.value; 295 UINT16_TO_STREAM(pp, p_rsp->clt_cfg); 296 srvc_sr_rsp(p_inst->pending_clcb_idx, st, &rsp); 297 break; 298 299 case BA_READ_LEVEL_REQ: 300 rsp.attr_value.handle = p_inst->pending_handle; 301 rsp.attr_value.len = 1; 302 pp = rsp.attr_value.value; 303 UINT8_TO_STREAM(pp, p_rsp->ba_level); 304 srvc_sr_rsp(p_inst->pending_clcb_idx, st, &rsp); 305 break; 306 307 case BA_WRITE_CLT_CFG_REQ: 308 srvc_sr_rsp(p_inst->pending_clcb_idx, st, NULL); 309 break; 310 311 case BA_READ_RPT_REF_REQ: 312 rsp.attr_value.handle = p_inst->pending_handle; 313 rsp.attr_value.len = 2; 314 pp = rsp.attr_value.value; 315 UINT8_TO_STREAM(pp, p_rsp->rpt_ref.rpt_id); 316 UINT8_TO_STREAM(pp, p_rsp->rpt_ref.rpt_type); 317 srvc_sr_rsp(p_inst->pending_clcb_idx, st, &rsp); 318 break; 319 320 default: 321 break; 322 } 323 p_inst->pending_clcb_idx = 0; 324 p_inst->pending_evt = 0; 325 p_inst->pending_handle = 0; 326 } 327 return; 328 } 329 /******************************************************************************* 330 * 331 * Function Battery_Notify 332 * 333 * Description Send battery level notification 334 * 335 ******************************************************************************/ 336 void Battery_Notify(uint8_t app_id, const RawAddress& remote_bda, 337 uint8_t battery_level) { 338 tBA_INST* p_inst = &battery_cb.battery_inst[0]; 339 uint8_t i = 0; 340 341 while (i < BA_MAX_INT_NUM) { 342 if (p_inst->app_id == app_id && p_inst->ba_level_hdl != 0) break; 343 i++; 344 } 345 346 if (i == BA_MAX_INT_NUM || p_inst->clt_cfg_hdl == 0) return; 347 348 srvc_sr_notify(remote_bda, p_inst->ba_level_hdl, 1, &battery_level); 349 } 350 /******************************************************************************* 351 * 352 * Function Battery_ReadBatteryLevel 353 * 354 * Description Read remote device Battery Level information. 355 * 356 * Returns void 357 * 358 ******************************************************************************/ 359 bool Battery_ReadBatteryLevel(const RawAddress&) { 360 /* to be implemented */ 361 return true; 362 } 363