Home | History | Annotate | Download | only in srvc
      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