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);
|