ble_main.c 15.5 KB
Newer Older
1
2
3
4
5
6
7
/* card10:
 * Copied from lib/sdk/Libraries/BTLE/stack/ble-profiles/sources/apps/fit/fit_main.c
 *
 * Also have a look at lib/sdk/Applications/EvKitExamples/BLE_fit/fit_main.c which has some changes
 * to this file regarding handling of OOB paring data
 *
 * This file contains some application logic taken from the "fit" example.
8
9
10
11
12
 *
 * Things have been renamed:
 * fit -> ble
 * Fit -> Ble
 * FIT -> BLE
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
 */
#include <string.h>
#include "wsf_types.h"
#include "util/bstream.h"
#include "wsf_msg.h"
#include "wsf_trace.h"
#include "hci_api.h"
#include "dm_api.h"
#include "att_api.h"
#include "smp_api.h"
#include "app_api.h"
#include "app_db.h"
#include "app_ui.h"
#include "app_hw.h"
#include "svc_ch.h"
#include "svc_core.h"
#include "svc_hrs.h"
#include "svc_dis.h"
#include "svc_batt.h"
#include "svc_rscs.h"
#include "bas/bas_api.h"
#include "hrps/hrps_api.h"
#include "rscp/rscp_api.h"

/**************************************************************************************************
  Macros
**************************************************************************************************/

/*! WSF message event starting value */
42
#define BLE_MSG_START               0xA0
43
44
45
46

/*! WSF message event enumeration */
enum
{
47
  BLE_BATT_TIMER_IND = BLE_MSG_START,                     /*! Battery measurement timer expired */
48
49
50
51
52
53
54
55
56
57
58
59
60
};

/**************************************************************************************************
  Data Types
**************************************************************************************************/

/*! Application message type */
typedef union
{
  wsfMsgHdr_t     hdr;
  dmEvt_t         dm;
  attsCccEvt_t    ccc;
  attEvt_t        att;
61
} bleMsg_t;
62
63
64
65
66
67

/**************************************************************************************************
  Configurable Parameters
**************************************************************************************************/

/*! configurable parameters for advertising */
68
static const appAdvCfg_t bleAdvCfg =
69
70
{
  {60000,     0,     0},                  /*! Advertising durations in ms */
71
  {500/0.625,     4000/0.625,     0}                   /*! Advertising intervals in 0.625 ms units */
72
73
74
};

/*! configurable parameters for slave */
75
static const appSlaveCfg_t bleSlaveCfg =
76
77
78
79
80
{
  1,                                      /*! Maximum connections */
};

/*! configurable parameters for security */
81
static const appSecCfg_t bleSecCfg =
82
83
84
85
86
87
88
89
90
{
  DM_AUTH_BOND_FLAG | DM_AUTH_SC_FLAG,    /*! Authentication and bonding flags */
  0,                                      /*! Initiator key distribution flags */
  DM_KEY_DIST_LTK,                        /*! Responder key distribution flags */
  FALSE,                                  /*! TRUE if Out-of-band pairing data is present */
  TRUE                                    /*! TRUE to initiate security upon connection */
};

/*! configurable parameters for connection parameter update */
91
static const appUpdateCfg_t bleUpdateCfg =
92
93
94
{
  6000,                                   /*! Connection idle period in ms before attempting
                                              connection parameter update; set to zero to disable */
95
96
  800/1.25,                               /*! Minimum connection interval in 1.25ms units */
  1000/1.25,                              /*! Maximum connection interval in 1.25ms units */
97
  0,                                      /*! Connection latency */
98
  9000/10,                                /*! Supervision timeout in 10ms units */
99
100
101
102
  5                                       /*! Number of update attempts before giving up */
};

/*! battery measurement configuration */
103
static const basCfg_t bleBasCfg =
104
105
106
107
108
109
110
{
  30,       /*! Battery measurement timer expiration period in seconds */
  1,        /*! Perform battery measurement after this many timer periods */
  100       /*! Send battery level notification to peer when below this level. */
};

/*! SMP security parameter configuration */
111
static const smpCfg_t bleSmpCfg =
112
113
114
115
116
117
118
119
120
121
122
123
124
125
{
  3000,                                   /*! 'Repeated attempts' timeout in msec */
  SMP_IO_NO_IN_NO_OUT,                    /*! I/O Capability */
  7,                                      /*! Minimum encryption key length */
  16,                                     /*! Maximum encryption key length */
  3,                                      /*! Attempts to trigger 'repeated attempts' timeout */
  0,                                      /*! Device authentication requirements */
};

/**************************************************************************************************
  Advertising Data
**************************************************************************************************/

/*! advertising data, discoverable mode */
126
static const uint8_t bleAdvDataDisc[] =
127
128
129
130
131
132
133
134
135
136
137
138
139
{
  /*! flags */
  2,                                      /*! length */
  DM_ADV_TYPE_FLAGS,                      /*! AD type */
  DM_FLAG_LE_GENERAL_DISC |               /*! flags */
  DM_FLAG_LE_BREDR_NOT_SUP,

  /*! tx power */
  2,                                      /*! length */
  DM_ADV_TYPE_TX_POWER,                   /*! AD type */
  0,                                      /*! tx power */

  /*! service UUID list */
140
  5,                                      /*! length */
141
142
143
144
145
146
  DM_ADV_TYPE_16_UUID,                    /*! AD type */
  UINT16_TO_BYTES(ATT_UUID_DEVICE_INFO_SERVICE),
  UINT16_TO_BYTES(ATT_UUID_BATTERY_SERVICE)
};

/*! scan data, discoverable mode */
147
static const uint8_t bleScanDataDisc[] =
148
149
150
151
152
153
154
155
156
157
158
159
160
161
{
  /*! device name */
  7,                                      /*! length */
  DM_ADV_TYPE_LOCAL_NAME,                 /*! AD type */
  'c','a','r','d','1','0'
};

/**************************************************************************************************
  Client Characteristic Configuration Descriptors
**************************************************************************************************/

/*! enumeration of client characteristic configuration descriptors */
enum
{
162
163
164
  BLE_GATT_SC_CCC_IDX,                    /*! GATT service, service changed characteristic */
  BLE_BATT_LVL_CCC_IDX,                   /*! Battery service, battery level characteristic */
  BLE_NUM_CCC_IDX
165
166
167
};

/*! client characteristic configuration descriptors settings, indexed by above enumeration */
168
static const attsCccSet_t bleCccSet[BLE_NUM_CCC_IDX] =
169
170
{
  /* cccd handle          value range               security level */
171
172
  {GATT_SC_CH_CCC_HDL,    ATT_CLIENT_CFG_INDICATE,  DM_SEC_LEVEL_NONE},   /* BLE_GATT_SC_CCC_IDX */
  {BATT_LVL_CH_CCC_HDL,   ATT_CLIENT_CFG_NOTIFY,    DM_SEC_LEVEL_NONE},   /* BLE_BATT_LVL_CCC_IDX */
173
174
175
176
177
178
179
};

/**************************************************************************************************
  Global Variables
**************************************************************************************************/

/*! WSF handler ID */
180
wsfHandlerId_t bleHandlerId;
181
182


183
static void BleHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg);
184
185
186
187
188
189
190
191
192
/*************************************************************************************************/
/*!
 *  \brief  Application DM callback.
 *
 *  \param  pDmEvt  DM callback event
 *
 *  \return None.
 */
/*************************************************************************************************/
193
static void bleDmCback(dmEvt_t *pDmEvt)
194
195
196
197
198
199
200
201
202
{
  dmEvt_t *pMsg;
  uint16_t len;

  len = DmSizeOfEvt(pDmEvt);

  if ((pMsg = WsfMsgAlloc(len)) != NULL)
  {
    memcpy(pMsg, pDmEvt, len);
203
    WsfMsgSend(bleHandlerId, pMsg);
204
205
206
207
208
209
210
211
212
213
214
215
  }
}

/*************************************************************************************************/
/*!
 *  \brief  Application ATT callback.
 *
 *  \param  pEvt    ATT callback event
 *
 *  \return None.
 */
/*************************************************************************************************/
216
static void bleAttCback(attEvt_t *pEvt)
217
218
219
220
221
222
223
224
{
  attEvt_t *pMsg;

  if ((pMsg = WsfMsgAlloc(sizeof(attEvt_t) + pEvt->valueLen)) != NULL)
  {
    memcpy(pMsg, pEvt, sizeof(attEvt_t));
    pMsg->pValue = (uint8_t *) (pMsg + 1);
    memcpy(pMsg->pValue, pEvt->pValue, pEvt->valueLen);
225
    WsfMsgSend(bleHandlerId, pMsg);
226
227
228
229
230
231
232
233
234
235
236
237
  }
}

/*************************************************************************************************/
/*!
 *  \brief  Application ATTS client characteristic configuration callback.
 *
 *  \param  pDmEvt  DM callback event
 *
 *  \return None.
 */
/*************************************************************************************************/
238
static void bleCccCback(attsCccEvt_t *pEvt)
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
{
  attsCccEvt_t  *pMsg;
  appDbHdl_t    dbHdl;

  /* if CCC not set from initialization and there's a device record */
  if ((pEvt->handle != ATT_HANDLE_NONE) &&
      ((dbHdl = AppDbGetHdl((dmConnId_t) pEvt->hdr.param)) != APP_DB_HDL_NONE))
  {
    /* store value in device database */
    AppDbSetCccTblValue(dbHdl, pEvt->idx, pEvt->value);
  }

  if ((pMsg = WsfMsgAlloc(sizeof(attsCccEvt_t))) != NULL)
  {
    memcpy(pMsg, pEvt, sizeof(attsCccEvt_t));
254
    WsfMsgSend(bleHandlerId, pMsg);
255
256
257
258
259
260
261
262
263
264
265
266
267
268
  }
}



/*************************************************************************************************/
/*!
 *  \brief  Process CCC state change.
 *
 *  \param  pMsg    Pointer to message.
 *
 *  \return None.
 */
/*************************************************************************************************/
269
static void bleProcCccState(bleMsg_t *pMsg)
270
271
272
273
{
  APP_TRACE_INFO3("ccc state ind value:%d handle:%d idx:%d", pMsg->ccc.value, pMsg->ccc.handle, pMsg->ccc.idx);

  /* handle battery level CCC */
274
  if (pMsg->ccc.idx == BLE_BATT_LVL_CCC_IDX)
275
276
277
  {
    if (pMsg->ccc.value == ATT_CLIENT_CFG_NOTIFY)
    {
278
      BasMeasBattStart((dmConnId_t) pMsg->ccc.hdr.param, BLE_BATT_TIMER_IND, BLE_BATT_LVL_CCC_IDX);
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
    }
    else
    {
      BasMeasBattStop((dmConnId_t) pMsg->ccc.hdr.param);
    }
    return;
  }
}

/*************************************************************************************************/
/*!
 *  \brief  Perform UI actions on connection close.
 *
 *  \param  pMsg    Pointer to message.
 *
 *  \return None.
 */
/*************************************************************************************************/
297
static void bleClose(bleMsg_t *pMsg)
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
{
  /* stop battery measurement */
  BasMeasBattStop((dmConnId_t) pMsg->hdr.param);
}

/*************************************************************************************************/
/*!
 *  \brief  Set up advertising and other procedures that need to be performed after
 *          device reset.
 *
 *  \param  pMsg    Pointer to message.
 *
 *  \return None.
 */
/*************************************************************************************************/
313
static void bleSetup(bleMsg_t *pMsg)
314
315
{
  /* set advertising and scan response data for discoverable mode */
316
317
  AppAdvSetData(APP_ADV_DATA_DISCOVERABLE, sizeof(bleAdvDataDisc), (uint8_t *) bleAdvDataDisc);
  AppAdvSetData(APP_SCAN_DATA_DISCOVERABLE, sizeof(bleScanDataDisc), (uint8_t *) bleScanDataDisc);
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336

  /* set advertising and scan response data for connectable mode */
  AppAdvSetData(APP_ADV_DATA_CONNECTABLE, 0, NULL);
  AppAdvSetData(APP_SCAN_DATA_CONNECTABLE, 0, NULL);

  /* start advertising; automatically set connectable/discoverable mode and bondable mode */
  AppAdvStart(APP_MODE_AUTO_INIT);
}


/*************************************************************************************************/
/*!
 *  \brief  Process messages from the event handler.
 *
 *  \param  pMsg    Pointer to message.
 *
 *  \return None.
 */
/*************************************************************************************************/
337
static void bleProcMsg(bleMsg_t *pMsg)
338
339
340
341
342
{
  uint8_t uiEvent = APP_UI_NONE;

  switch(pMsg->hdr.event)
  {
343
    case BLE_BATT_TIMER_IND:
344
345
346
347
348
349
350
351
      BasProcMsg(&pMsg->hdr);
      break;

    case ATTS_HANDLE_VALUE_CNF:
      BasProcMsg(&pMsg->hdr);
      break;

    case ATTS_CCC_STATE_IND:
352
      bleProcCccState(pMsg);
353
354
355
356
      break;

    case DM_RESET_CMPL_IND:
      DmSecGenerateEccKeyReq();
357
      bleSetup(pMsg);
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
      uiEvent = APP_UI_RESET_CMPL;
      break;

    case DM_ADV_START_IND:
      uiEvent = APP_UI_ADV_START;
      break;

    case DM_ADV_STOP_IND:
      uiEvent = APP_UI_ADV_STOP;
      break;

    case DM_CONN_OPEN_IND:
      BasProcMsg(&pMsg->hdr);
      uiEvent = APP_UI_CONN_OPEN;
      break;

    case DM_CONN_CLOSE_IND:
375
      bleClose(pMsg);
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
      uiEvent = APP_UI_CONN_CLOSE;
      break;

    case DM_SEC_PAIR_CMPL_IND:
      uiEvent = APP_UI_SEC_PAIR_CMPL;
      break;

    case DM_SEC_PAIR_FAIL_IND:
      uiEvent = APP_UI_SEC_PAIR_FAIL;
      break;

    case DM_SEC_ENCRYPT_IND:
      uiEvent = APP_UI_SEC_ENCRYPT;
      break;

    case DM_SEC_ENCRYPT_FAIL_IND:
      uiEvent = APP_UI_SEC_ENCRYPT_FAIL;
      break;

    case DM_SEC_AUTH_REQ_IND:
      AppHandlePasskey(&pMsg->dm.authReq);
      break;

    case DM_SEC_ECC_KEY_IND:
      DmSecSetEccKey(&pMsg->dm.eccMsg.data.key);
      break;

    case DM_SEC_COMPARE_IND:
      AppHandleNumericComparison(&pMsg->dm.cnfInd);
      break;

    case DM_HW_ERROR_IND:
      uiEvent = APP_UI_HW_ERROR;
      break;

    default:
      break;
  }

  if (uiEvent != APP_UI_NONE)
  {
    AppUiAction(uiEvent);
  }
}

/*************************************************************************************************/
/*!
 *  \brief  Application handler init function called during system initialization.
 *
 *  \param  handlerID  WSF handler ID.
 *
 *  \return None.
 */
/*************************************************************************************************/
430
static void BleHandlerInit(void)
431
{
432
  APP_TRACE_INFO0("BleHandlerInit");
433
434

  /* store handler ID */
435
  bleHandlerId =WsfOsSetNextHandler(BleHandler);
436
437

  /* Set configuration pointers */
438
439
440
441
  pAppAdvCfg = (appAdvCfg_t *) &bleAdvCfg;
  pAppSlaveCfg = (appSlaveCfg_t *) &bleSlaveCfg;
  pAppSecCfg = (appSecCfg_t *) &bleSecCfg;
  pAppUpdateCfg = (appUpdateCfg_t *) &bleUpdateCfg;
442
443
444
445
446

  /* Initialize application framework */
  AppSlaveInit();

  /* Set stack configuration pointers */
447
  pSmpCfg = (smpCfg_t *) &bleSmpCfg;
448
449

  /* initialize battery service server */
450
  BasInit(bleHandlerId, (basCfg_t *) &bleBasCfg);
451
452
453
454
455
456
457
458
459
460
461
462
}

/*************************************************************************************************/
/*!
 *  \brief  WSF event handler for application.
 *
 *  \param  event   WSF event mask.
 *  \param  pMsg    WSF message.
 *
 *  \return None.
 */
/*************************************************************************************************/
463
static void BleHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg)
464
465
466
{
  if (pMsg != NULL)
  {
467
    APP_TRACE_INFO1("Ble got evt %d", pMsg->event);
468
469
470
471
472
473
474
475
476
477
478

    if (pMsg->event >= DM_CBACK_START && pMsg->event <= DM_CBACK_END)
    {
      /* process advertising and connection-related messages */
      AppSlaveProcDmMsg((dmEvt_t *) pMsg);

      /* process security-related messages */
      AppSlaveSecProcDmMsg((dmEvt_t *) pMsg);
    }

    /* perform profile and user interface-related operations */
479
    bleProcMsg((bleMsg_t *) pMsg);
480
481
482
483
484
485
486
487
488
489
  }
}

/*************************************************************************************************/
/*!
 *  \brief  Start the application.
 *
 *  \return None.
 */
/*************************************************************************************************/
490
void BleStart(void)
491
{
schneider's avatar
schneider committed
492

493
  BleHandlerInit();
schneider's avatar
schneider committed
494

495
  /* Register for stack callbacks */
496
497
498
  DmRegister(bleDmCback);
  DmConnRegister(DM_CLIENT_ID_APP, bleDmCback);
  AttRegister(bleAttCback);
499
  AttConnRegister(AppServerConnCback);
500
  AttsCccRegister(BLE_NUM_CCC_IDX, (attsCccSet_t *) bleCccSet, bleCccCback);
501
502
503

  /* Initialize attribute server database */
  SvcCoreAddGroup();
504
  SvcDisAddGroup(); // Device Information Service
505
506
507
508
509
510
  SvcBattCbackRegister(BasReadCback, NULL);
  SvcBattAddGroup();

  /* Reset the device */
  DmDevReset();
}