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 #include "sysinit/sysinit.h"
23 #include "host/ble_hs.h"
24 #include "services/ias/ble_svc_ias.h"
25
26 /* Callback function */
27 static ble_svc_ias_event_fn *ble_svc_ias_cb_fn;
28
29 /* Alert level */
30 static uint8_t ble_svc_ias_alert_level;
31
32 /* Write characteristic function */
33 static int
34 ble_svc_ias_chr_write(struct os_mbuf *om, uint16_t min_len,
35 uint16_t max_len, void *dst,
36 uint16_t *len);
37
38 /* Access function */
39 static int
40 ble_svc_ias_access(uint16_t conn_handle, uint16_t attr_handle,
41 struct ble_gatt_access_ctxt *ctxt, void *arg);
42
43 static const struct ble_gatt_svc_def ble_svc_ias_defs[] = {
44 {
45 /*** Service: Immediate Alert Service (IAS). */
46 .type = BLE_GATT_SVC_TYPE_PRIMARY,
47 .uuid = BLE_UUID16_DECLARE(BLE_SVC_IAS_UUID16),
48 .characteristics = (struct ble_gatt_chr_def[]) { {
49 /*** Characteristic: Alert Level. */
50 .uuid = BLE_UUID16_DECLARE(BLE_SVC_IAS_CHR_UUID16_ALERT_LEVEL),
51 .access_cb = ble_svc_ias_access,
52 .flags = BLE_GATT_CHR_F_WRITE_NO_RSP,
53 }, {
54 0, /* No more characteristics in this service. */
55 } },
56 },
57
58 {
59 0, /* No more services. */
60 },
61 };
62
63 /**
64 * Writes the received value from a characteristic write to
65 * the given destination.
66 */
67 static int
ble_svc_ias_chr_write(struct os_mbuf * om,uint16_t min_len,uint16_t max_len,void * dst,uint16_t * len)68 ble_svc_ias_chr_write(struct os_mbuf *om, uint16_t min_len,
69 uint16_t max_len, void *dst,
70 uint16_t *len)
71 {
72 uint16_t om_len;
73 int rc;
74
75 om_len = OS_MBUF_PKTLEN(om);
76 if (om_len < min_len || om_len > max_len) {
77 return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
78 }
79
80 rc = ble_hs_mbuf_to_flat(om, dst, max_len, len);
81 if (rc != 0) {
82 return BLE_ATT_ERR_UNLIKELY;
83 }
84
85 return 0;
86 }
87
88 /**
89 * Simple write access callback for the alert level
90 * characteristic.
91 */
92 static int
ble_svc_ias_access(uint16_t conn_handle,uint16_t attr_handle,struct ble_gatt_access_ctxt * ctxt,void * arg)93 ble_svc_ias_access(uint16_t conn_handle, uint16_t attr_handle,
94 struct ble_gatt_access_ctxt *ctxt, void *arg)
95 {
96 int rc;
97
98 assert(ctxt->chr == &ble_svc_ias_defs[0].characteristics[0]);
99
100 switch (ctxt->op) {
101 case BLE_GATT_ACCESS_OP_WRITE_CHR:
102 rc = ble_svc_ias_chr_write(ctxt->om,
103 sizeof ble_svc_ias_alert_level,
104 sizeof ble_svc_ias_alert_level,
105 &ble_svc_ias_alert_level, NULL);
106 /* Call the IAS event function */
107 if (ble_svc_ias_cb_fn) {
108 ble_svc_ias_cb_fn(ble_svc_ias_alert_level);
109 }
110 return rc;
111
112 default:
113 assert(0);
114 return BLE_ATT_ERR_UNLIKELY;
115 }
116
117 return 0;
118 }
119
120 /**
121 * Designates the specified function as the IAS callback. This callback is
122 * necessary for this service to function properly.
123 *
124 * @param cb The callback function to call when
125 * the client signals an alert.
126 */
127 void
ble_svc_ias_set_cb(ble_svc_ias_event_fn * cb)128 ble_svc_ias_set_cb(ble_svc_ias_event_fn *cb)
129 {
130 ble_svc_ias_cb_fn = cb;
131 }
132
133 /**
134 * Initialize the IAS package.
135 */
136 void
ble_svc_ias_init(void)137 ble_svc_ias_init(void)
138 {
139 int rc;
140
141 /* Ensure this function only gets called by sysinit. */
142 SYSINIT_ASSERT_ACTIVE();
143
144 rc = ble_gatts_count_cfg(ble_svc_ias_defs);
145 SYSINIT_PANIC_ASSERT(rc == 0);
146
147 rc = ble_gatts_add_svcs(ble_svc_ias_defs);
148 SYSINIT_PANIC_ASSERT(rc == 0);
149 }
150