1 #include <stdlib.h>
2 #include <string.h>
3 #include <stdio.h>
4 //#include <aos/osal_debug.h>
5 #include <aos/ble.h>
6 #include <yoc/bas.h>
7
8 #define TAG "BAS"
9
10 enum {
11 BAS_IDX_SVC,
12 BAS_IDX_LEVEL_CHAR,
13 BAS_IDX_LEVEL_VAL,
14 BAS_IDX_LEVEL_CCC,
15
16 BAS_IDX_MAX,
17 };
18
19 static slist_t bas_list = {NULL};
20
21 gatt_service bas_service;
22
23 static gatt_attr_t bas_attrs[BAS_IDX_MAX] = {
24 [BAS_IDX_SVC] = GATT_PRIMARY_SERVICE_DEFINE(UUID_BAS),
25 [BAS_IDX_LEVEL_CHAR] = GATT_CHAR_DEFINE(UUID_BAS_BATTERY_LEVEL, GATT_CHRC_PROP_READ | GATT_CHRC_PROP_NOTIFY),
26 [BAS_IDX_LEVEL_VAL] = GATT_CHAR_VAL_DEFINE(UUID_BAS_BATTERY_LEVEL, GATT_PERM_READ),
27 [BAS_IDX_LEVEL_CCC] = GATT_CHAR_CCC_DEFINE(),
28 };
29
get_bas(uint16_t bas_svc_handle)30 static inline bas_t *get_bas(uint16_t bas_svc_handle)
31 {
32 slist_t *tmp;
33 bas_t *node;
34
35 slist_for_each_entry_safe(&bas_list, tmp, node, bas_t, next) {
36 if (node->bas_svc_handle == bas_svc_handle) {
37 return node;
38 }
39 }
40
41 return NULL;
42 }
43
event_char_read(ble_event_en event,void * event_data)44 static void event_char_read(ble_event_en event, void *event_data)
45 {
46 evt_data_gatt_char_read_t *e = (evt_data_gatt_char_read_t *)event_data;
47
48 bas_t *bas = get_bas(e->char_handle - BAS_IDX_LEVEL_VAL);
49
50 if (bas == NULL) {
51 return;
52 }
53
54 e->data = &bas->battery_level;
55 e->len = 1;
56 }
57
conn_change(ble_event_en event,void * event_data)58 static void conn_change(ble_event_en event, void *event_data)
59 {
60 evt_data_gap_conn_change_t *e = (evt_data_gap_conn_change_t *)event_data;
61
62 slist_t *tmp;
63 bas_t *node;
64 slist_for_each_entry_safe(&bas_list, tmp, node, bas_t, next) {
65 if (e->connected == CONNECTED) {
66 node->conn_handle = e->conn_handle;
67 } else {
68 node->conn_handle = 0xFFFF;
69 }
70 }
71 }
72
event_char_ccc_change(ble_event_en event,void * event_data)73 static void event_char_ccc_change(ble_event_en event, void *event_data)
74 {
75 evt_data_gatt_char_ccc_change_t *e = (evt_data_gatt_char_ccc_change_t *)event_data;
76 bas_t *bas = get_bas(e->char_handle - BAS_IDX_LEVEL_CCC);
77
78 if (bas == NULL) {
79 return;
80 }
81
82 bas->ccc = e->ccc_value;
83 }
84
bas_event_callback(ble_event_en event,void * event_data)85 static int bas_event_callback(ble_event_en event, void *event_data)
86 {
87 switch (event) {
88 case EVENT_GAP_CONN_CHANGE:
89 conn_change(event, event_data);
90 break;
91
92 case EVENT_GATT_CHAR_READ:
93 event_char_read(event, event_data);
94 break;
95
96 case EVENT_GATT_CHAR_CCC_CHANGE:
97 event_char_ccc_change(event, event_data);
98 break;
99
100 default:
101 break;
102 }
103
104 return 0;
105 }
106
107 static ble_event_cb_t ble_cb = {
108 .callback = bas_event_callback,
109 };
110
111
bas_init(bas_t * bas)112 bas_handle_t bas_init(bas_t *bas)
113 {
114 int ret = 0;
115
116 if (bas == NULL) {
117 return NULL;
118 }
119
120 ret = ble_stack_event_register(&ble_cb);
121
122 if (ret) {
123 goto err;
124 }
125
126 ret = ble_stack_gatt_registe_service(&bas_service, bas_attrs, BLE_ARRAY_NUM(bas_attrs));
127
128 if (ret < 0) {
129 goto err;
130 }
131
132 bas->conn_handle = 0xFFFF;
133 bas->bas_svc_handle = ret;
134 bas->battery_level = 0xFF;
135 bas->ccc = 0;
136
137 slist_add(&bas->next, &bas_list);
138 return bas;
139
140 err:
141 ///free(bas);
142 return NULL;
143 }
144
bas_level_update(bas_handle_t handle,uint8_t level)145 int bas_level_update(bas_handle_t handle, uint8_t level)
146 {
147 if (handle == NULL) {
148 return -BLE_STACK_ERR_NULL;
149 }
150
151 bas_t *bas = handle;
152
153 if (level != bas->battery_level) {
154 bas->battery_level = level;
155
156 if (bas->conn_handle != 0xFFFF && bas->ccc == CCC_VALUE_NOTIFY) {
157 return ble_stack_gatt_notificate(bas->conn_handle,
158 bas->bas_svc_handle + BAS_IDX_LEVEL_VAL,
159 &level, 1);
160 }
161 }
162
163 return 0;
164 }
165
166