1 /**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20 #include <assert.h>
21 #include <string.h>
22
23 #include "sysinit/sysinit.h"
24 #include "syscfg/syscfg.h"
25 #include "host/ble_hs.h"
26 #include "host/ble_gap.h"
27 #include "services/bas/ble_svc_bas.h"
28
29 /* Characteristic value handles */
30 #if MYNEWT_VAL(BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE) > 0
31 static uint16_t ble_svc_bas_battery_handle;
32 #endif
33
34 /* Battery level */
35 uint8_t ble_svc_bas_battery_level;
36
37 /* Access function */
38 static int
39 ble_svc_bas_access(uint16_t conn_handle, uint16_t attr_handle,
40 struct ble_gatt_access_ctxt *ctxt, void *arg);
41
42 static const struct ble_gatt_svc_def ble_svc_bas_defs[] = {
43 {
44 /*** Battery Service. */
45 .type = BLE_GATT_SVC_TYPE_PRIMARY,
46 .uuid = BLE_UUID16_DECLARE(BLE_SVC_BAS_UUID16),
47 .characteristics = (struct ble_gatt_chr_def[]) { {
48 /*** Battery level characteristic */
49 .uuid = BLE_UUID16_DECLARE(BLE_SVC_BAS_CHR_UUID16_BATTERY_LEVEL),
50 .access_cb = ble_svc_bas_access,
51 #if MYNEWT_VAL(BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE) > 0
52 .val_handle = &ble_svc_bas_battery_handle,
53 #endif
54 .flags = BLE_GATT_CHR_F_READ |
55 #if MYNEWT_VAL(BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE) > 0
56 BLE_GATT_CHR_F_NOTIFY |
57 #endif
58 MYNEWT_VAL(BLE_SVC_BAS_BATTERY_LEVEL_READ_PERM),
59 }, {
60 0, /* No more characteristics in this service. */
61 } },
62 },
63
64 {
65 0, /* No more services. */
66 },
67 };
68
69 /**
70 * BAS access function
71 */
72 static int
ble_svc_bas_access(uint16_t conn_handle,uint16_t attr_handle,struct ble_gatt_access_ctxt * ctxt,void * arg)73 ble_svc_bas_access(uint16_t conn_handle, uint16_t attr_handle,
74 struct ble_gatt_access_ctxt *ctxt,
75 void *arg)
76 {
77 uint16_t uuid16 = ble_uuid_u16(ctxt->chr->uuid);
78 int rc;
79
80 switch (uuid16) {
81 case BLE_SVC_BAS_CHR_UUID16_BATTERY_LEVEL:
82 assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR);
83 rc = os_mbuf_append(ctxt->om, &ble_svc_bas_battery_level,
84 sizeof ble_svc_bas_battery_level);
85 return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
86
87 default:
88 assert(0);
89 return BLE_ATT_ERR_UNLIKELY;
90 }
91 }
92
93
94 /**
95 * Set the battery level, must be between 0 and 100.
96 * If greater than 100, it will be silently set to 100.
97 */
98 int
ble_svc_bas_battery_level_set(uint8_t level)99 ble_svc_bas_battery_level_set(uint8_t level) {
100 if (level > 100)
101 level = 100;
102 if (ble_svc_bas_battery_level != level) {
103 ble_svc_bas_battery_level = level;
104 #if MYNEWT_VAL(BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE) > 0
105 ble_gatts_chr_updated(ble_svc_bas_battery_handle);
106 #endif
107 }
108 return 0;
109 }
110
111 /**
112 * Initialize the Battery Service.
113 */
114 void
ble_svc_bas_init(void)115 ble_svc_bas_init(void)
116 {
117 int rc;
118
119 /* Ensure this function only gets called by sysinit. */
120 SYSINIT_ASSERT_ACTIVE();
121
122 rc = ble_gatts_count_cfg(ble_svc_bas_defs);
123 SYSINIT_PANIC_ASSERT(rc == 0);
124
125 rc = ble_gatts_add_svcs(ble_svc_bas_defs);
126 SYSINIT_PANIC_ASSERT(rc == 0);
127 }
128