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 <stdio.h>
22 #include <string.h>
23 #include "host/ble_hs.h"
24 #include "host/ble_uuid.h"
25 #include "blehr_sens.h"
26
27 static const char *manuf_name = "Apache Mynewt";
28 static const char *model_num = "Mynewt HR Sensor";
29 uint16_t hrs_hrm_handle;
30
31 static int
32 gatt_svr_chr_access_heart_rate(uint16_t conn_handle, uint16_t attr_handle,
33 struct ble_gatt_access_ctxt *ctxt, void *arg);
34
35 static int
36 gatt_svr_chr_access_device_info(uint16_t conn_handle, uint16_t attr_handle,
37 struct ble_gatt_access_ctxt *ctxt, void *arg);
38
39 static const struct ble_gatt_svc_def gatt_svr_svcs[] = {
40 {
41 /* Service: Heart-rate */
42 .type = BLE_GATT_SVC_TYPE_PRIMARY,
43 .uuid = BLE_UUID16_DECLARE(GATT_HRS_UUID),
44 .characteristics = (struct ble_gatt_chr_def[]) { {
45 /* Characteristic: Heart-rate measurement */
46 .uuid = BLE_UUID16_DECLARE(GATT_HRS_MEASUREMENT_UUID),
47 .access_cb = gatt_svr_chr_access_heart_rate,
48 .val_handle = &hrs_hrm_handle,
49 .flags = BLE_GATT_CHR_F_NOTIFY,
50 }, {
51 /* Characteristic: Body sensor location */
52 .uuid = BLE_UUID16_DECLARE(GATT_HRS_BODY_SENSOR_LOC_UUID),
53 .access_cb = gatt_svr_chr_access_heart_rate,
54 .flags = BLE_GATT_CHR_F_READ,
55 }, {
56 0, /* No more characteristics in this service */
57 }, }
58 },
59
60 {
61 /* Service: Device Information */
62 .type = BLE_GATT_SVC_TYPE_PRIMARY,
63 .uuid = BLE_UUID16_DECLARE(GATT_DEVICE_INFO_UUID),
64 .characteristics = (struct ble_gatt_chr_def[]) { {
65 /* Characteristic: * Manufacturer name */
66 .uuid = BLE_UUID16_DECLARE(GATT_MANUFACTURER_NAME_UUID),
67 .access_cb = gatt_svr_chr_access_device_info,
68 .flags = BLE_GATT_CHR_F_READ,
69 }, {
70 /* Characteristic: Model number string */
71 .uuid = BLE_UUID16_DECLARE(GATT_MODEL_NUMBER_UUID),
72 .access_cb = gatt_svr_chr_access_device_info,
73 .flags = BLE_GATT_CHR_F_READ,
74 }, {
75 0, /* No more characteristics in this service */
76 }, }
77 },
78
79 {
80 0, /* No more services */
81 },
82 };
83
84 static int
gatt_svr_chr_access_heart_rate(uint16_t conn_handle,uint16_t attr_handle,struct ble_gatt_access_ctxt * ctxt,void * arg)85 gatt_svr_chr_access_heart_rate(uint16_t conn_handle, uint16_t attr_handle,
86 struct ble_gatt_access_ctxt *ctxt, void *arg)
87 {
88 /* Sensor location, set to "Chest" */
89 static uint8_t body_sens_loc = 0x01;
90 uint16_t uuid;
91 int rc;
92
93 uuid = ble_uuid_u16(ctxt->chr->uuid);
94
95 if (uuid == GATT_HRS_BODY_SENSOR_LOC_UUID) {
96 rc = os_mbuf_append(ctxt->om, &body_sens_loc, sizeof(body_sens_loc));
97
98 return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
99 }
100
101 assert(0);
102 return BLE_ATT_ERR_UNLIKELY;
103 }
104
105 static int
gatt_svr_chr_access_device_info(uint16_t conn_handle,uint16_t attr_handle,struct ble_gatt_access_ctxt * ctxt,void * arg)106 gatt_svr_chr_access_device_info(uint16_t conn_handle, uint16_t attr_handle,
107 struct ble_gatt_access_ctxt *ctxt, void *arg)
108 {
109 uint16_t uuid;
110 int rc;
111
112 uuid = ble_uuid_u16(ctxt->chr->uuid);
113
114 if (uuid == GATT_MODEL_NUMBER_UUID) {
115 rc = os_mbuf_append(ctxt->om, model_num, strlen(model_num));
116 return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
117 }
118
119 if (uuid == GATT_MANUFACTURER_NAME_UUID) {
120 rc = os_mbuf_append(ctxt->om, manuf_name, strlen(manuf_name));
121 return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
122 }
123
124 assert(0);
125 return BLE_ATT_ERR_UNLIKELY;
126 }
127
128 void
gatt_svr_register_cb(struct ble_gatt_register_ctxt * ctxt,void * arg)129 gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
130 {
131 char buf[BLE_UUID_STR_LEN];
132
133 switch (ctxt->op) {
134 case BLE_GATT_REGISTER_OP_SVC:
135 MODLOG_DFLT(DEBUG, "registered service %s with handle=%d\n",
136 ble_uuid_to_str(ctxt->svc.svc_def->uuid, buf),
137 ctxt->svc.handle);
138 break;
139
140 case BLE_GATT_REGISTER_OP_CHR:
141 MODLOG_DFLT(DEBUG, "registering characteristic %s with "
142 "def_handle=%d val_handle=%d\n",
143 ble_uuid_to_str(ctxt->chr.chr_def->uuid, buf),
144 ctxt->chr.def_handle,
145 ctxt->chr.val_handle);
146 break;
147
148 case BLE_GATT_REGISTER_OP_DSC:
149 MODLOG_DFLT(DEBUG, "registering descriptor %s with handle=%d\n",
150 ble_uuid_to_str(ctxt->dsc.dsc_def->uuid, buf),
151 ctxt->dsc.handle);
152 break;
153
154 default:
155 assert(0);
156 break;
157 }
158 }
159
160 int
gatt_svr_init(void)161 gatt_svr_init(void)
162 {
163 int rc;
164
165 rc = ble_gatts_count_cfg(gatt_svr_svcs);
166 if (rc != 0) {
167 return rc;
168 }
169
170 rc = ble_gatts_add_svcs(gatt_svr_svcs);
171 if (rc != 0) {
172 return rc;
173 }
174
175 return 0;
176 }
177
178