1
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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
113
114
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
139
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/* ... */
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "host/ble_hs.h"
#include "host/ble_uuid.h"
#include "services/gap/ble_svc_gap.h"
#include "services/gatt/ble_svc_gatt.h"
#include "ble_cts_prph.h"
#include "services/cts/ble_svc_cts.h"
#include <time.h>
#include "sys/time.h"11 includes
void
gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
{
char buf[BLE_UUID_STR_LEN];
switch (ctxt->op) {
case BLE_GATT_REGISTER_OP_SVC:
MODLOG_DFLT(DEBUG, "registered service %s with handle=%d\n",
ble_uuid_to_str(ctxt->svc.svc_def->uuid, buf),
ctxt->svc.handle);
break;
...
case BLE_GATT_REGISTER_OP_CHR:
MODLOG_DFLT(DEBUG, "registering characteristic %s with "
"def_handle=%d val_handle=%d\n",
ble_uuid_to_str(ctxt->chr.chr_def->uuid, buf),
ctxt->chr.def_handle,
ctxt->chr.val_handle);
break;
...
case BLE_GATT_REGISTER_OP_DSC:
MODLOG_DFLT(DEBUG, "registering descriptor %s with handle=%d\n",
ble_uuid_to_str(ctxt->dsc.dsc_def->uuid, buf),
ctxt->dsc.handle);
break;
...
default:
assert(0);
break;...
}{...}
}{ ... }
static struct ble_svc_cts_local_time_info local_info = { .timezone = 0, .dst_offset = TIME_STANDARD };
static struct timeval last_updated;
uint8_t adjust_reason;
int fetch_current_time(struct ble_svc_cts_curr_time *ctime) {
time_t now;
struct tm timeinfo;
struct timeval tv_now;
time(&now);
localtime_r(&now, &timeinfo);
gettimeofday(&tv_now, NULL);
if(ctime != NULL) {
ctime->et_256.d_d_t.d_t.year = timeinfo.tm_year + 1900;
ctime->et_256.d_d_t.d_t.month = timeinfo.tm_mon + 1;
ctime->et_256.d_d_t.d_t.day = timeinfo.tm_mday;
ctime->et_256.d_d_t.d_t.hours = timeinfo.tm_hour;
ctime->et_256.d_d_t.d_t.minutes = timeinfo.tm_min;
ctime->et_256.d_d_t.d_t.seconds = timeinfo.tm_sec;
/* ... */
ctime->et_256.d_d_t.day_of_week = timeinfo.tm_wday + 1;
ctime->et_256.fractions_256 = (((uint64_t)tv_now.tv_usec * 256L )/ 1000000L);
ctime->adjust_reason = adjust_reason;
}{...}
return 0;
}{ ... }
int set_current_time(struct ble_svc_cts_curr_time ctime) {
time_t now;
struct tm timeinfo;
struct timeval tv_now;
timeinfo.tm_year= ctime.et_256.d_d_t.d_t.year - 1900 ;
timeinfo.tm_mon = ctime.et_256.d_d_t.d_t.month - 1;
timeinfo.tm_mday = ctime.et_256.d_d_t.d_t.day;
timeinfo.tm_hour = ctime.et_256.d_d_t.d_t.hours;
timeinfo.tm_min = ctime.et_256.d_d_t.d_t.minutes;
timeinfo.tm_sec = ctime.et_256.d_d_t.d_t.seconds;
timeinfo.tm_wday = ctime.et_256.d_d_t.day_of_week - 1;
now = mktime(&timeinfo);
tv_now.tv_sec = now;
settimeofday(&tv_now, NULL);
gettimeofday(&last_updated, NULL);
adjust_reason = ctime.adjust_reason;
return 0;
}{ ... }
int fetch_local_time_info(struct ble_svc_cts_local_time_info *info) {
if(info != NULL) {
memcpy(info, &local_info, sizeof local_info);
}{...}
return 0;
}{ ... }
int set_local_time_info(struct ble_svc_cts_local_time_info info) {
/* ... */
local_info.timezone = info.timezone;
local_info.dst_offset = info.dst_offset;
gettimeofday(&last_updated, NULL);
return 0;
}{ ... }
int fetch_reference_time_info(struct ble_svc_cts_reference_time_info *info) {
struct timeval tv_now;
uint64_t days_since_update;
uint64_t hours_since_update;
gettimeofday(&tv_now, NULL);
tv_now.tv_sec -= last_updated.tv_sec;
info->time_source = TIME_SOURCE_MANUAL;
info->time_accuracy = 0;
days_since_update = (tv_now.tv_sec / 86400L);
hours_since_update = (tv_now.tv_sec / 3600);
info->days_since_update = days_since_update < 255 ? days_since_update : 255;
if(days_since_update > 254) {
info->hours_since_update = 255;
}{...}
else {
hours_since_update = (tv_now.tv_sec % 86400L) / 3600;
info->hours_since_update = hours_since_update;
}{...}
adjust_reason = (CHANGE_OF_DST_MASK | CHANGE_OF_TIME_ZONE_MASK);
return 0;
}{ ... }
int
gatt_svr_init(void)
{
struct ble_svc_cts_cfg cfg;
ble_svc_gap_init();
ble_svc_gatt_init();
cfg.fetch_time_cb = fetch_current_time;
cfg.local_time_info_cb = fetch_local_time_info;
cfg.ref_time_info_cb = fetch_reference_time_info;
cfg.set_time_cb = set_current_time;
cfg.set_local_time_info_cb = set_local_time_info;
ble_svc_cts_init(cfg);
return 0;
}{ ... }