1 /*
2 * Copyright (C) 2019-2020 Alibaba Group Holding Limited
3 */
4
5 #include <stdlib.h>
6 #include <string.h>
7 #include <stdio.h>
8 //#include <aos/osal_debug.h>
9 #include <aos/ble.h>
10 #include <yoc/hrs.h>
11
12 #define TAG "HRS"
13
14 enum {
15 HRS_IDX_SVC,
16 HRS_IDX_MEA_CHAR,
17 HRS_IDX_MEA_VAL,
18 HRS_IDX_MEA_CCC,
19 HRS_IDX_BODY_CHAR,
20 HRS_IDX_BODY_VAL,
21 HRS_IDX_CONTROL_CHAR,
22 HRS_IDX_CONTROL_VAL,
23
24 HRS_IDX_MAX,
25 };
26
27 static slist_t hrs_list = {NULL};
28 gatt_service hrs_service;
29
30 //static struct bt_gatt_ccc_cfg_t ccc_data[2] = {};
31
32 static gatt_attr_t hrs_attrs[HRS_IDX_MAX] = {
33 [HRS_IDX_SVC] = GATT_PRIMARY_SERVICE_DEFINE(UUID_HRS),
34 [HRS_IDX_MEA_CHAR] = GATT_CHAR_DEFINE(UUID_HRS_MEASUREMENT, GATT_CHRC_PROP_NOTIFY),
35 [HRS_IDX_MEA_VAL] = GATT_CHAR_VAL_DEFINE(UUID_HRS_MEASUREMENT, GATT_PERM_NONE),
36 [HRS_IDX_MEA_CCC] = GATT_CHAR_CCC_DEFINE(),
37 [HRS_IDX_BODY_CHAR] = GATT_CHAR_DEFINE(UUID_HRS_BODY_SENSOR, GATT_CHRC_PROP_READ),
38 [HRS_IDX_BODY_VAL] = GATT_CHAR_VAL_DEFINE(UUID_HRS_BODY_SENSOR, GATT_PERM_NONE),
39 [HRS_IDX_CONTROL_CHAR] = GATT_CHAR_DEFINE(UUID_HRS_CONTROL_POINT, GATT_CHRC_PROP_WRITE),
40 [HRS_IDX_CONTROL_VAL] = GATT_CHAR_VAL_DEFINE(UUID_HRS_CONTROL_POINT, GATT_PERM_NONE),
41 };
42
get_hrs(uint16_t hrs_svc_handle)43 static inline hrs_t *get_hrs(uint16_t hrs_svc_handle)
44 {
45 slist_t *tmp;
46 hrs_t *node;
47
48 slist_for_each_entry_safe(&hrs_list, tmp, node, hrs_t, next) {
49 if (node->hrs_svc_handle == hrs_svc_handle) {
50 return node;
51 }
52 }
53
54 return NULL;
55 }
56
57
58
event_char_read(ble_event_en event,void * event_data)59 static void event_char_read(ble_event_en event, void *event_data)
60 {
61 evt_data_gatt_char_read_t *e = (evt_data_gatt_char_read_t *)event_data;
62
63 hrs_t *hrs = get_hrs(e->char_handle - HRS_IDX_MEA_VAL);
64
65 if (hrs == NULL) {
66 return;
67 }
68
69 LOGD(TAG, "event_char_read conn handle %d char handle 0x%04x, len %d, offset %d",
70 e->conn_handle, e->char_handle, e->len, e->offset);
71
72 e->data = &hrs->hrs_mea_level;
73 e->len = 1;
74 }
75
76
conn_change(ble_event_en event,void * event_data)77 static void conn_change(ble_event_en event, void *event_data)
78 {
79 evt_data_gap_conn_change_t *e = (evt_data_gap_conn_change_t *)event_data;
80
81 slist_t *tmp;
82 hrs_t *node;
83 slist_for_each_entry_safe(&hrs_list, tmp, node, hrs_t, next) {
84 if (e->connected == CONNECTED) {
85 node->conn_handle = e->conn_handle;
86 } else {
87 node->conn_handle = 0xFFFF;
88 }
89 }
90 }
91
92
93
event_char_ccc_change(ble_event_en event,void * event_data)94 static void event_char_ccc_change(ble_event_en event, void *event_data)
95 {
96 evt_data_gatt_char_ccc_change_t *e = (evt_data_gatt_char_ccc_change_t *)event_data;
97 hrs_t *hrs = get_hrs(e->char_handle - HRS_IDX_MEA_CCC);
98
99 if (hrs == NULL) {
100 return;
101 }
102
103 hrs->mea_ccc = e->ccc_value;
104 }
105
106
107
hrs_event_callback(ble_event_en event,void * event_data)108 static int hrs_event_callback(ble_event_en event, void *event_data)
109 {
110 switch (event) {
111 case EVENT_GAP_CONN_CHANGE:
112 conn_change(event, event_data);
113 break;
114
115 case EVENT_GATT_CHAR_READ:
116 event_char_read(event, event_data);
117 break;
118
119 case EVENT_GATT_CHAR_CCC_CHANGE:
120 event_char_ccc_change(event, event_data);
121 break;
122
123 default:
124 break;
125 }
126
127 return 0;
128 }
129
130 static ble_event_cb_t ble_cb = {
131 .callback = hrs_event_callback,
132 };
133
hrs_init(hrs_t * hrs)134 hrs_handle_t hrs_init(hrs_t *hrs)
135 {
136 int ret = 0;
137
138 if (hrs == NULL) {
139 return NULL;
140 }
141
142 ret = ble_stack_event_register(&ble_cb);
143
144 if (ret) {
145 goto err;
146 }
147
148 ret = ble_stack_gatt_registe_service(&hrs_service,hrs_attrs, BLE_ARRAY_NUM(hrs_attrs));
149
150 if (ret < 0) {
151 goto err;
152 }
153
154 hrs->conn_handle = 0xFFFF;
155 hrs->hrs_svc_handle = ret;
156 hrs->hrs_mea_level = 0xFF;
157 hrs->mea_ccc = 0;
158
159 slist_add(&hrs->next, &hrs_list);
160 return hrs;
161
162 err:
163 return NULL;
164 }
165
166
hrs_measure_level_update(hrs_handle_t handle,uint8_t * data,uint8_t length)167 int hrs_measure_level_update(hrs_handle_t handle, uint8_t *data, uint8_t length)
168 {
169 if (handle == NULL) {
170 return -BLE_STACK_ERR_NULL;
171 }
172
173 hrs_t *hrs = handle;
174
175 if (data[1] != hrs->hrs_mea_level) {
176 hrs->hrs_mea_level = data[1];
177
178 if (hrs->conn_handle != 0xFFFF && hrs->mea_ccc == CCC_VALUE_NOTIFY) {
179 LOGD(TAG, "data:%x", data[1]);
180 return ble_stack_gatt_notificate(hrs->conn_handle,
181 hrs->hrs_svc_handle + HRS_IDX_MEA_VAL,
182 data, length);
183 }
184 }
185
186 return 0;
187 }
188
189
190
191
192