summaryrefslogtreecommitdiff
path: root/profiles/health/mcap.h
blob: 00f3fa851003cab5099138521a2004c15b1b8f2d (plain)
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
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
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
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2010 GSyC/LibreSoft, Universidad Rey Juan Carlos.
 *  Copyright (C) 2010 Signove
 *  Copyright (C) 2014 Intel Corporation. All rights reserved.
 *
 */

#define MCAP_VERSION	0x0100	/* current version 01.00 */

/* bytes to get MCAP Supported Procedures */
#define MCAP_SUP_PROC	0x06

/* maximum transmission unit for channels */
#define MCAP_CC_MTU	48
#define MCAP_DC_MTU	65535

/* MCAP Standard Op Codes */
#define MCAP_ERROR_RSP			0x00
#define MCAP_MD_CREATE_MDL_REQ		0x01
#define MCAP_MD_CREATE_MDL_RSP		0x02
#define MCAP_MD_RECONNECT_MDL_REQ	0x03
#define MCAP_MD_RECONNECT_MDL_RSP	0x04
#define MCAP_MD_ABORT_MDL_REQ		0x05
#define MCAP_MD_ABORT_MDL_RSP		0x06
#define MCAP_MD_DELETE_MDL_REQ		0x07
#define MCAP_MD_DELETE_MDL_RSP		0x08

/* MCAP Clock Sync Op Codes */
#define MCAP_MD_SYNC_CAP_REQ		0x11
#define MCAP_MD_SYNC_CAP_RSP		0x12
#define MCAP_MD_SYNC_SET_REQ		0x13
#define MCAP_MD_SYNC_SET_RSP		0x14
#define MCAP_MD_SYNC_INFO_IND		0x15

/* MCAP Response codes */
#define MCAP_SUCCESS			0x00
#define MCAP_INVALID_OP_CODE		0x01
#define MCAP_INVALID_PARAM_VALUE	0x02
#define MCAP_INVALID_MDEP		0x03
#define MCAP_MDEP_BUSY			0x04
#define MCAP_INVALID_MDL		0x05
#define MCAP_MDL_BUSY			0x06
#define MCAP_INVALID_OPERATION		0x07
#define MCAP_RESOURCE_UNAVAILABLE	0x08
#define MCAP_UNSPECIFIED_ERROR		0x09
#define MCAP_REQUEST_NOT_SUPPORTED	0x0A
#define MCAP_CONFIGURATION_REJECTED	0x0B

/* MDL IDs */
#define MCAP_MDLID_RESERVED		0x0000
#define MCAP_MDLID_INITIAL		0x0001
#define MCAP_MDLID_FINAL		0xFEFF
#define MCAP_ALL_MDLIDS			0xFFFF

/* MDEP IDs */
#define MCAP_MDEPID_INITIAL		0x00
#define MCAP_MDEPID_FINAL		0x7F

/* CSP special values */
#define MCAP_BTCLOCK_IMMEDIATE		0xffffffffUL
#define MCAP_TMSTAMP_DONTSET		0xffffffffffffffffULL
#define MCAP_BTCLOCK_MAX		0x0fffffff
#define MCAP_BTCLOCK_FIELD		(MCAP_BTCLOCK_MAX + 1)

#define	MCAP_CTRL_CACHED	0x01	/* MCL is cached */
#define	MCAP_CTRL_STD_OP	0x02	/* Support for standard op codes */
#define	MCAP_CTRL_SYNC_OP	0x04	/* Support for synchronization commands */
#define	MCAP_CTRL_CONN		0x08	/* MCL is in connecting process */
#define	MCAP_CTRL_FREE		0x10	/* MCL is marked as releasable */
#define	MCAP_CTRL_NOCACHE	0x20	/* MCL is marked as not cacheable */

/*
 * MCAP Request Packet Format
 */

typedef struct {
	uint8_t		op;
	uint16_t	mdl;
	uint8_t		mdep;
	uint8_t		conf;
} __attribute__ ((packed)) mcap_md_create_mdl_req;

typedef struct {
	uint8_t		op;
	uint16_t	mdl;
} __attribute__ ((packed)) mcap_md_req;

/* MCAP Response Packet Format */

typedef struct {
	uint8_t		op;
	uint8_t		rc;
	uint16_t	mdl;
	uint8_t		data[0];
} __attribute__ ((packed)) mcap_rsp;

/*  MCAP Clock Synchronization Protocol */

typedef struct {
	uint8_t		op;
	uint16_t	timest;
} __attribute__ ((packed)) mcap_md_sync_cap_req;

typedef struct {
	uint8_t		op;
	uint8_t		rc;
} __attribute__ ((packed)) mcap_md_sync_rsp;

typedef struct {
	uint8_t		op;
	uint8_t		rc;
	uint8_t		btclock;
	uint16_t	sltime;
	uint16_t	timestnr;
	uint16_t	timestna;
} __attribute__ ((packed)) mcap_md_sync_cap_rsp;

typedef struct {
	uint8_t		op;
	uint8_t		timestui;
	uint32_t	btclock;
	uint64_t	timestst;
} __attribute__ ((packed)) mcap_md_sync_set_req;

typedef struct {
	int8_t		op;
	uint8_t		rc;
	uint32_t	btclock;
	uint64_t	timestst;
	uint16_t	timestsa;
} __attribute__ ((packed)) mcap_md_sync_set_rsp;

typedef struct {
	uint8_t		op;
	uint32_t	btclock;
	uint64_t	timestst;
	uint16_t	timestsa;
} __attribute__ ((packed)) mcap_md_sync_info_ind;

typedef enum {
/* MCAP Error Response Codes */
	MCAP_ERROR_INVALID_OP_CODE = 1,
	MCAP_ERROR_INVALID_PARAM_VALUE,
	MCAP_ERROR_INVALID_MDEP,
	MCAP_ERROR_MDEP_BUSY,
	MCAP_ERROR_INVALID_MDL,
	MCAP_ERROR_MDL_BUSY,
	MCAP_ERROR_INVALID_OPERATION,
	MCAP_ERROR_RESOURCE_UNAVAILABLE,
	MCAP_ERROR_UNSPECIFIED_ERROR,
	MCAP_ERROR_REQUEST_NOT_SUPPORTED,
	MCAP_ERROR_CONFIGURATION_REJECTED,
/* MCAP Internal Errors */
	MCAP_ERROR_INVALID_ARGS,
	MCAP_ERROR_ALREADY_EXISTS,
	MCAP_ERROR_REQ_IGNORED,
	MCAP_ERROR_MCL_CLOSED,
	MCAP_ERROR_FAILED
} McapError;

typedef enum {
	MCAP_MDL_CB_INVALID,
	MCAP_MDL_CB_CONNECTED,		/* mcap_mdl_event_cb */
	MCAP_MDL_CB_CLOSED,		/* mcap_mdl_event_cb */
	MCAP_MDL_CB_DELETED,		/* mcap_mdl_event_cb */
	MCAP_MDL_CB_ABORTED,		/* mcap_mdl_event_cb */
	MCAP_MDL_CB_REMOTE_CONN_REQ,	/* mcap_remote_mdl_conn_req_cb */
	MCAP_MDL_CB_REMOTE_RECONN_REQ	/* mcap_remote_mdl_reconn_req_cb */
} McapMclCb;

typedef enum {
	MCL_CONNECTED,
	MCL_PENDING,
	MCL_ACTIVE,
	MCL_IDLE
} MCLState;

typedef enum {
	MCL_ACCEPTOR,
	MCL_INITIATOR
} MCLRole;

typedef enum {
	MCL_AVAILABLE,
	MCL_WAITING_RSP
} MCAPCtrl;

typedef enum {
	MDL_WAITING,
	MDL_CONNECTED,
	MDL_DELETING,
	MDL_CLOSED
} MDLState;

struct mcap_csp;
struct mcap_mdl_op_cb;
struct mcap_instance;
struct mcap_mcl;
struct mcap_mdl;
struct sync_info_ind_data;

/************ Callbacks ************/

/* MDL callbacks */

typedef void (* mcap_mdl_event_cb) (struct mcap_mdl *mdl, gpointer data);
typedef void (* mcap_mdl_operation_conf_cb) (struct mcap_mdl *mdl, uint8_t conf,
						GError *err, gpointer data);
typedef void (* mcap_mdl_operation_cb) (struct mcap_mdl *mdl, GError *err,
						gpointer data);
typedef void (* mcap_mdl_notify_cb) (GError *err, gpointer data);

/* Next function should return an MCAP appropriate response code */
typedef uint8_t (* mcap_remote_mdl_conn_req_cb) (struct mcap_mcl *mcl,
						uint8_t mdepid, uint16_t mdlid,
						uint8_t *conf, gpointer data);
typedef uint8_t (* mcap_remote_mdl_reconn_req_cb) (struct mcap_mdl *mdl,
						gpointer data);

/* MCL callbacks */

typedef void (* mcap_mcl_event_cb) (struct mcap_mcl *mcl, gpointer data);
typedef void (* mcap_mcl_connect_cb) (struct mcap_mcl *mcl, GError *err,
								gpointer data);

/* CSP callbacks */

typedef void (* mcap_info_ind_event_cb) (struct mcap_mcl *mcl,
					struct sync_info_ind_data *data);

typedef void (* mcap_sync_cap_cb) (struct mcap_mcl *mcl,
					uint8_t mcap_err,
					uint8_t btclockres,
					uint16_t synclead,
					uint16_t tmstampres,
					uint16_t tmstampacc,
					GError *err,
					gpointer data);

typedef void (* mcap_sync_set_cb) (struct mcap_mcl *mcl,
					uint8_t mcap_err,
					uint32_t btclock,
					uint64_t timestamp,
					uint16_t accuracy,
					GError *err,
					gpointer data);

struct mcap_mdl_cb {
	mcap_mdl_event_cb		mdl_connected;	/* Remote device has created a MDL */
	mcap_mdl_event_cb		mdl_closed;	/* Remote device has closed a MDL */
	mcap_mdl_event_cb		mdl_deleted;	/* Remote device requested deleting a MDL */
	mcap_mdl_event_cb		mdl_aborted;	/* Remote device aborted the mdl creation */
	mcap_remote_mdl_conn_req_cb	mdl_conn_req;	/* Remote device requested creating a MDL */
	mcap_remote_mdl_reconn_req_cb	mdl_reconn_req;	/* Remote device requested reconnecting a MDL */
	gpointer			user_data;	/* User data */
};

struct mcap_instance {
	bdaddr_t		src;			/* Source address */
	GIOChannel		*ccio;			/* Control Channel IO */
	GIOChannel		*dcio;			/* Data Channel IO */
	GSList			*mcls;			/* MCAP instance list */
	GSList			*cached;		/* List with all cached MCLs (MAX_CACHED macro) */
	BtIOSecLevel		sec;			/* Security level */
	mcap_mcl_event_cb	mcl_connected_cb;	/* New MCL connected */
	mcap_mcl_event_cb	mcl_reconnected_cb;	/* Old MCL has been reconnected */
	mcap_mcl_event_cb	mcl_disconnected_cb;	/* MCL disconnected */
	mcap_mcl_event_cb	mcl_uncached_cb;	/* MCL has been removed from MCAP cache */
	mcap_info_ind_event_cb	mcl_sync_infoind_cb;	/* (CSP Central) Received info indication */
	gpointer		user_data;		/* Data to be provided in callbacks */
	int			ref;			/* Reference counter */

	gboolean		csp_enabled;		/* CSP: functionality enabled */
};

struct mcap_mcl {
	struct mcap_instance	*mi;		/* MCAP instance where this MCL belongs */
	bdaddr_t		addr;		/* Device address */
	GIOChannel		*cc;		/* MCAP Control Channel IO */
	guint			wid;		/* MCL Watcher id */
	GSList			*mdls;		/* List of Data Channels shorted by mdlid */
	MCLState		state;		/* Current MCL State */
	MCLRole			role;		/* Initiator or acceptor of this MCL */
	MCAPCtrl		req;		/* Request control flag */
	struct mcap_mdl_op_cb	*priv_data;	/* Temporal data to manage responses */
	struct mcap_mdl_cb	*cb;		/* MDL callbacks */
	guint			tid;		/* Timer id for waiting for a response */
	uint8_t			*lcmd;		/* Last command sent */
	int			ref;		/* References counter */
	uint8_t			ctrl;		/* MCL control flag */
	uint16_t		next_mdl;	/* id used to create next MDL */
	struct mcap_csp		*csp;		/* CSP control structure */
};

struct mcap_mdl {
	struct mcap_mcl		*mcl;		/* MCL where this MDL belongs */
	GIOChannel		*dc;		/* MCAP Data Channel IO */
	guint			wid;		/* MDL Watcher id */
	uint16_t		mdlid;		/* MDL id */
	uint8_t			mdep_id;	/* MCAP Data End Point */
	MDLState		state;		/* MDL state */
	int			ref;		/* References counter */
};

struct sync_info_ind_data {
	uint32_t	btclock;
	uint64_t	timestamp;
	uint16_t	accuracy;
};

/************ Operations ************/

/* MDL operations */

gboolean mcap_create_mdl(struct mcap_mcl *mcl,
				uint8_t mdepid,
				uint8_t conf,
				mcap_mdl_operation_conf_cb connect_cb,
				gpointer user_data,
				GDestroyNotify destroy,
				GError **err);
gboolean mcap_reconnect_mdl(struct mcap_mdl *mdl,
				mcap_mdl_operation_cb reconnect_cb,
				gpointer user_data,
				GDestroyNotify destroy,
				GError **err);
gboolean mcap_delete_all_mdls(struct mcap_mcl *mcl,
				mcap_mdl_notify_cb delete_cb,
				gpointer user_data,
				GDestroyNotify destroy,
				GError **err);
gboolean mcap_delete_mdl(struct mcap_mdl *mdl,
				mcap_mdl_notify_cb delete_cb,
				gpointer user_data,
				GDestroyNotify destroy,
				GError **err);
gboolean mcap_connect_mdl(struct mcap_mdl *mdl,
				uint8_t mode,
				uint16_t dcpsm,
				mcap_mdl_operation_cb connect_cb,
				gpointer user_data,
				GDestroyNotify destroy,
				GError **err);
gboolean mcap_mdl_abort(struct mcap_mdl *mdl,
				mcap_mdl_notify_cb abort_cb,
				gpointer user_data,
				GDestroyNotify destroy,
				GError **err);

int mcap_mdl_get_fd(struct mcap_mdl *mdl);
uint16_t mcap_mdl_get_mdlid(struct mcap_mdl *mdl);
struct mcap_mdl *mcap_mdl_ref(struct mcap_mdl *mdl);
void mcap_mdl_unref(struct mcap_mdl *mdl);

/* MCL operations */

gboolean mcap_create_mcl(struct mcap_instance *mi,
				const bdaddr_t *addr,
				uint16_t ccpsm,
				mcap_mcl_connect_cb connect_cb,
				gpointer user_data,
				GDestroyNotify destroy,
				GError **err);
void mcap_close_mcl(struct mcap_mcl *mcl, gboolean cache);
gboolean mcap_mcl_set_cb(struct mcap_mcl *mcl, gpointer user_data,
					GError **gerr, McapMclCb cb1, ...);
void mcap_mcl_get_addr(struct mcap_mcl *mcl, bdaddr_t *addr);
struct mcap_mcl *mcap_mcl_ref(struct mcap_mcl *mcl);
void mcap_mcl_unref(struct mcap_mcl *mcl);

/* CSP operations */

void mcap_enable_csp(struct mcap_instance *mi);
void mcap_disable_csp(struct mcap_instance *mi);
uint64_t mcap_get_timestamp(struct mcap_mcl *mcl,
				struct timespec *given_time);
uint32_t mcap_get_btclock(struct mcap_mcl *mcl);

void mcap_sync_cap_req(struct mcap_mcl *mcl,
			uint16_t reqacc,
			mcap_sync_cap_cb cb,
			gpointer user_data,
			GError **err);

void mcap_sync_set_req(struct mcap_mcl *mcl,
			uint8_t update,
			uint32_t btclock,
			uint64_t timestamp,
			mcap_sync_set_cb cb,
			gpointer user_data,
			GError **err);

/* MCAP main operations */

struct mcap_instance *mcap_create_instance(const bdaddr_t *src,
					BtIOSecLevel sec, uint16_t ccpsm,
					uint16_t dcpsm,
					mcap_mcl_event_cb mcl_connected,
					mcap_mcl_event_cb mcl_reconnected,
					mcap_mcl_event_cb mcl_disconnected,
					mcap_mcl_event_cb mcl_uncached,
					mcap_info_ind_event_cb mcl_sync_info_ind,
					gpointer user_data,
					GError **gerr);
void mcap_release_instance(struct mcap_instance *mi);

struct mcap_instance *mcap_instance_ref(struct mcap_instance *mi);
void mcap_instance_unref(struct mcap_instance *mi);

uint16_t mcap_get_ctrl_psm(struct mcap_instance *mi, GError **err);
uint16_t mcap_get_data_psm(struct mcap_instance *mi, GError **err);

gboolean mcap_set_data_chan_mode(struct mcap_instance *mi, uint8_t mode,
								GError **err);

int mcap_send_data(int sock, const void *buf, uint32_t size);

void proc_sync_cmd(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len);
void mcap_sync_init(struct mcap_mcl *mcl);
void mcap_sync_stop(struct mcap_mcl *mcl);