-
Notifications
You must be signed in to change notification settings - Fork 6
/
timeapp_discovery.c
301 lines (258 loc) · 8.9 KB
/
timeapp_discovery.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
/**************************************************************************************************
Filename: timeapp_discovery.c
Revised: Laura Kassovic @ MbientLab
Revision: 1/21/2014
Description: Time App service and characteristic discovery routines.
Copyright 2011 - 2013 Texas Instruments Incorporated. All rights reserved.
**************************************************************************************************/
/*********************************************************************
* INCLUDES
*/
#include "bcomdef.h"
#include "OSAL.h"
#include "OnBoard.h"
#include "gatt.h"
#include "gatt_uuid.h"
#include "gatt_profile_uuid.h"
#include "timeapp.h"
#include "battservice.h"
/*********************************************************************
* MACROS
*/
/*********************************************************************
* TYPEDEFS
*/
/*********************************************************************
* GLOBAL VARIABLES
*/
/*********************************************************************
* EXTERNAL VARIABLES
*/
// Attribute handle cache
uint16 timeAppHdlCache[HDL_CACHE_LEN];
/*********************************************************************
* EXTERNAL FUNCTIONS
*/
/*********************************************************************
* LOCAL VARIABLES
*/
// Attribute handles used during discovery
static uint16 timeAppSvcStartHdl;
static uint16 timeAppSvcEndHdl;
static uint8 timeAppEndHdlIdx;
/*********************************************************************
* LOCAL FUNCTIONS
*/
static uint8 TimeAppDiscAlertNtf( uint8 state, gattMsgEvent_t *pMsg );
/*********************************************************************
* @fn timeAppDiscStart()
*
* @brief Start service discovery.
*
*
* @return New discovery state.
*/
uint8 timeAppDiscStart( void )
{
// Clear handle cache
osal_memset( timeAppHdlCache, 0, sizeof(timeAppHdlCache) );
// Start discovery with first service
return timeAppDiscGattMsg( DISC_ANCS_START, NULL );
}
/*********************************************************************
* @fn timeAppDiscGattMsg()
*
* @brief Handle GATT messages for characteristic discovery.
*
* @param state - Discovery state.
* @param pMsg - GATT message.
*
* @return New discovery state.
*/
uint8 timeAppDiscGattMsg( uint8 state, gattMsgEvent_t *pMsg )
{
// Execute discovery function for service
do
{
switch ( state & 0xF0 )
{
// Alert notification service
case DISC_ANCS_START:
state = TimeAppDiscAlertNtf( state, pMsg );
if ( state == DISC_FAILED )
{
state = DISC_IDLE;
}
break;
default:
break;
}
} while ( (state != 0) && ((state & 0x0F) == 0) );
return state;
}
/*********************************************************************
* @fn TimeAppDiscAlertNtf()
*
* @brief Alert notification service and characteristic discovery.
*
* @param state - Discovery state.
* @param pMsg - GATT message.
*
* @return New discovery state.
*/
static uint8 TimeAppDiscAlertNtf( uint8 state, gattMsgEvent_t *pMsg )
{
uint8 newState = state;
switch ( state )
{
case DISC_ANCS_START:
{
uint8 uuid[ATT_UUID_SIZE] = ANCS_SVC_UUID;
// Initialize service discovery variables
timeAppSvcStartHdl = timeAppSvcEndHdl = 0;
timeAppEndHdlIdx = 0;
// Discover service by UUID
GATT_DiscPrimaryServiceByUUID( timeAppConnHandle, uuid,
ATT_UUID_SIZE, timeAppTaskId );
newState = DISC_ANCS_SVC;
}
break;
case DISC_ANCS_SVC:
// Service found, store handles
if ( pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP &&
pMsg->msg.findByTypeValueRsp.numInfo > 0 )
{
timeAppSvcStartHdl = pMsg->msg.findByTypeValueRsp.handlesInfo[0].handle;
timeAppSvcEndHdl = pMsg->msg.findByTypeValueRsp.handlesInfo[0].grpEndHandle;
}
// If procedure complete
if ( ( pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP &&
pMsg->hdr.status == bleProcedureComplete ) ||
( pMsg->method == ATT_ERROR_RSP ) )
{
// If service found
if ( timeAppSvcStartHdl != 0 )
{
// Discover all characteristics
GATT_DiscAllChars( timeAppConnHandle, timeAppSvcStartHdl,
timeAppSvcEndHdl, timeAppTaskId );
newState = DISC_ANCS_CHAR;
}
else
{
// Service not found
newState = DISC_FAILED;
}
}
break;
case DISC_ANCS_CHAR:
{
uint8 i;
uint8 *p;
uint16 handle;
uint16 uuid;
// Characteristics found
if ( pMsg->method == ATT_READ_BY_TYPE_RSP &&
pMsg->msg.readByTypeRsp.numPairs > 0 &&
pMsg->msg.readByTypeRsp.len == CHAR_DESC_HDL_UUID128_LEN )
{
// For each characteristic declaration
p = pMsg->msg.readByTypeRsp.dataList;
for ( i = pMsg->msg.readByTypeRsp.numPairs; i > 0; i-- )
{
// Parse characteristic declaration
handle = BUILD_UINT16(p[3], p[4]);
uuid = BUILD_UINT16(p[5], p[6]);
// If looking for end handle
if ( timeAppEndHdlIdx != 0 )
{
// End handle is one less than handle of characteristic declaration
timeAppHdlCache[timeAppEndHdlIdx] = BUILD_UINT16(p[0], p[1]) - 1;
timeAppEndHdlIdx = 0;
}
// If UUID is of interest, store handle
switch ( uuid )
{
case ANCS_NOTIF_CHAR_UUID:
timeAppHdlCache[HDL_ANCS_NTF_NOTIF_START] = handle;
timeAppEndHdlIdx = HDL_ANCS_NTF_NOTIF_END;
break;
default:
break;
}
p += CHAR_DESC_HDL_UUID128_LEN;
}
}
// If procedure complete
if ( ( pMsg->method == ATT_READ_BY_TYPE_RSP &&
pMsg->hdr.status == bleProcedureComplete ) ||
( pMsg->method == ATT_ERROR_RSP ) )
{
// Special case of end handle at end of service
if ( timeAppEndHdlIdx != 0 )
{
timeAppHdlCache[timeAppEndHdlIdx] = timeAppSvcEndHdl;
timeAppEndHdlIdx = 0;
}
// If didn't find mandatory characteristic
if ( timeAppHdlCache[HDL_ANCS_NTF_NOTIF_START] == 0 )
{
newState = DISC_FAILED;
}
else if ( timeAppHdlCache[HDL_ANCS_NTF_NOTIF_START] <
timeAppHdlCache[HDL_ANCS_NTF_NOTIF_END] )
{
// Discover characteristic descriptors
GATT_DiscAllCharDescs( timeAppConnHandle,
timeAppHdlCache[HDL_ANCS_NTF_NOTIF_START] + 1,
timeAppHdlCache[HDL_ANCS_NTF_NOTIF_END],
timeAppTaskId );
newState = DISC_ANCS_CCCD;
}
else
{
newState = DISC_IDLE;
}
}
}
break;
case DISC_ANCS_CCCD:
{
uint8 i;
// Characteristic descriptors found
if ( pMsg->method == ATT_FIND_INFO_RSP &&
pMsg->msg.findInfoRsp.numInfo > 0 &&
pMsg->msg.findInfoRsp.format == ATT_HANDLE_BT_UUID_TYPE )
{
// For each handle/uuid pair
for ( i = 0; i < pMsg->msg.findInfoRsp.numInfo; i++ )
{
// Look for CCCD
if ( (pMsg->msg.findInfoRsp.info.btPair[i].uuid[0] ==
LO_UINT16(GATT_CLIENT_CHAR_CFG_UUID)) &&
(pMsg->msg.findInfoRsp.info.btPair[i].uuid[1] ==
HI_UINT16(GATT_CLIENT_CHAR_CFG_UUID)) )
{
// CCCD found
timeAppHdlCache[HDL_ANCS_NTF_CCCD] =
pMsg->msg.findInfoRsp.info.btPair[i].handle;
break;
}
}
}
// If procedure complete
if ( ( pMsg->method == ATT_FIND_INFO_RSP &&
pMsg->hdr.status == bleProcedureComplete ) ||
( pMsg->method == ATT_ERROR_RSP ) )
{
newState = DISC_IDLE;
}
}
break;
default:
break;
}
return newState;
}
/*********************************************************************
*********************************************************************/