1 /* 2 * 3 * MCAP for BlueZ - Bluetooth protocol stack for Linux 4 * 5 * Copyright (C) 2010 GSyC/LibreSoft, Universidad Rey Juan Carlos. 6 * Copyright (C) 2010 Signove 7 * 8 * Authors: 9 * Santiago Carot-Nemesio <sancane at gmail.com> 10 * Jose Antonio Santos-Cadenas <santoscadenas at gmail.com> 11 * Elvis Pftzenreuter <epx at signove.com> 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License as published by 15 * the Free Software Foundation; either version 2 of the License, or 16 * (at your option) any later version. 17 * 18 * This program is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software 25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 26 * 27 */ 28 29 #include "btio.h" 30 #include <stdint.h> 31 #include <netinet/in.h> 32 #include <time.h> 33 #include <stdlib.h> 34 #include <bluetooth/bluetooth.h> 35 #include <bluetooth/l2cap.h> 36 #include "../src/adapter.h" 37 #include "../src/manager.h" 38 #include <sys/ioctl.h> 39 40 #include "config.h" 41 #include "log.h" 42 43 #include <bluetooth/bluetooth.h> 44 #include "mcap.h" 45 #include "mcap_lib.h" 46 #include "mcap_internal.h" 47 48 #define MCAP_BTCLOCK_HALF (MCAP_BTCLOCK_FIELD / 2) 49 #define CLK CLOCK_MONOTONIC 50 51 #define MCAP_CSP_ERROR g_quark_from_static_string("mcap-csp-error-quark") 52 #define MAX_RETRIES 10 53 #define SAMPLE_COUNT 20 54 55 struct mcap_csp { 56 uint64_t base_tmstamp; /* CSP base timestamp */ 57 struct timespec base_time; /* CSP base time when timestamp set */ 58 guint local_caps; /* CSP-Master: have got remote caps */ 59 guint remote_caps; /* CSP-Slave: remote master got caps */ 60 guint rem_req_acc; /* CSP-Slave: accuracy required by master */ 61 guint ind_expected; /* CSP-Master: indication expected */ 62 MCAPCtrl csp_req; /* CSP-Master: Request control flag */ 63 guint ind_timer; /* CSP-Slave: indication timer */ 64 guint set_timer; /* CSP-Slave: delayed set timer */ 65 void *set_data; /* CSP-Slave: delayed set data */ 66 void *csp_priv_data; /* CSP-Master: In-flight request data */ 67 }; 68 69 struct mcap_sync_cap_cbdata { 70 mcap_sync_cap_cb cb; 71 gpointer user_data; 72 }; 73 74 struct mcap_sync_set_cbdata { 75 mcap_sync_set_cb cb; 76 gpointer user_data; 77 }; 78 79 struct csp_caps { 80 int ts_acc; /* timestamp accuracy */ 81 int ts_res; /* timestamp resolution */ 82 int latency; /* Read BT clock latency */ 83 int preempt_thresh; /* Preemption threshold for latency */ 84 int syncleadtime_ms; /* SyncLeadTime in ms */ 85 }; 86 87 struct sync_set_data { 88 uint8_t update; 89 uint32_t sched_btclock; 90 uint64_t timestamp; 91 int ind_freq; 92 gboolean role; 93 }; 94 95 #define hton64(x) ntoh64(x) 96 97 static gboolean csp_caps_initialized = FALSE; 98 struct csp_caps _caps; 99 100 static int send_sync_cmd(struct mcap_mcl *mcl, const void *buf, uint32_t size) 101 { 102 int sock; 103 104 if (mcl->cc == NULL) 105 return -1; 106 107 sock = g_io_channel_unix_get_fd(mcl->cc); 108 return mcap_send_data(sock, buf, size); 109 } 110 111 static int send_unsupported_cap_req(struct mcap_mcl *mcl) 112 { 113 mcap_md_sync_cap_rsp *cmd; 114 int sent; 115 116 cmd = g_new0(mcap_md_sync_cap_rsp, 1); 117 cmd->op = MCAP_MD_SYNC_CAP_RSP; 118 cmd->rc = MCAP_REQUEST_NOT_SUPPORTED; 119 120 sent = send_sync_cmd(mcl, cmd, sizeof(*cmd)); 121 g_free(cmd); 122 123 return sent; 124 } 125 126 static int send_unsupported_set_req(struct mcap_mcl *mcl) 127 { 128 mcap_md_sync_set_rsp *cmd; 129 int sent; 130 131 cmd = g_new0(mcap_md_sync_set_rsp, 1); 132 cmd->op = MCAP_MD_SYNC_SET_RSP; 133 cmd->rc = MCAP_REQUEST_NOT_SUPPORTED; 134 135 sent = send_sync_cmd(mcl, cmd, sizeof(*cmd)); 136 g_free(cmd); 137 138 return sent; 139 } 140 141 static void reset_tmstamp(struct mcap_csp *csp, struct timespec *base_time, 142 uint64_t new_tmstamp) 143 { 144 csp->base_tmstamp = new_tmstamp; 145 if (base_time) 146 csp->base_time = *base_time; 147 else 148 clock_gettime(CLK, &csp->base_time); 149 } 150 151 void mcap_sync_init(struct mcap_mcl *mcl) 152 { 153 if (!mcl->mi->csp_enabled) { 154 mcl->csp = NULL; 155 return; 156 } 157 158 mcl->csp = g_new0(struct mcap_csp, 1); 159 160 mcl->csp->rem_req_acc = 10000; /* safe divisor */ 161 mcl->csp->set_data = NULL; 162 mcl->csp->csp_priv_data = NULL; 163 164 reset_tmstamp(mcl->csp, NULL, 0); 165 } 166 167 void mcap_sync_stop(struct mcap_mcl *mcl) 168 { 169 if (!mcl->csp) 170 return; 171 172 if (mcl->csp->ind_timer) 173 g_source_remove(mcl->csp->ind_timer); 174 175 if (mcl->csp->set_timer) 176 g_source_remove(mcl->csp->set_timer); 177 178 if (mcl->csp->set_data) 179 g_free(mcl->csp->set_data); 180 181 if (mcl->csp->csp_priv_data) 182 g_free(mcl->csp->csp_priv_data); 183 184 mcl->csp->ind_timer = 0; 185 mcl->csp->set_timer = 0; 186 mcl->csp->set_data = NULL; 187 mcl->csp->csp_priv_data = NULL; 188 189 g_free(mcl->csp); 190 mcl->csp = NULL; 191 } 192 193 static uint64_t time_us(struct timespec *tv) 194 { 195 return tv->tv_sec * 1000000 + tv->tv_nsec / 1000; 196 } 197 198 static int64_t bt2us(int bt) 199 { 200 return bt * 312.5; 201 } 202 203 static int bt2ms(int bt) 204 { 205 return bt * 312.5 / 1000; 206 } 207 208 static int btoffset(uint32_t btclk1, uint32_t btclk2) 209 { 210 int offset = btclk2 - btclk1; 211 212 if (offset <= -MCAP_BTCLOCK_HALF) 213 offset += MCAP_BTCLOCK_FIELD; 214 else if (offset > MCAP_BTCLOCK_HALF) 215 offset -= MCAP_BTCLOCK_FIELD; 216 217 return offset; 218 } 219 220 static int btdiff(uint32_t btclk1, uint32_t btclk2) 221 { 222 return btoffset(btclk1, btclk2); 223 } 224 225 static gboolean valid_btclock(uint32_t btclk) 226 { 227 return btclk <= MCAP_BTCLOCK_MAX; 228 } 229 230 /* This call may fail; either deal with retry or use read_btclock_retry */ 231 static gboolean read_btclock(struct mcap_mcl *mcl, uint32_t *btclock, 232 uint16_t *btaccuracy) 233 { 234 int which = 1; 235 struct btd_adapter *adapter; 236 237 adapter = manager_find_adapter(&mcl->mi->src); 238 239 if (!adapter) 240 return FALSE; 241 242 if (btd_adapter_read_clock(adapter, &mcl->addr, which, 1000, 243 btclock, btaccuracy) < 0) 244 return FALSE; 245 246 return TRUE; 247 } 248 249 static gboolean read_btclock_retry(struct mcap_mcl *mcl, uint32_t *btclock, 250 uint16_t *btaccuracy) 251 { 252 int retries = 5; 253 254 while (--retries >= 0) { 255 if (read_btclock(mcl, btclock, btaccuracy)) 256 return TRUE; 257 DBG("CSP: retrying to read bt clock..."); 258 } 259 260 return FALSE; 261 } 262 263 static gboolean get_btrole(struct mcap_mcl *mcl) 264 { 265 int sock, flags; 266 socklen_t len; 267 268 if (mcl->cc == NULL) 269 return -1; 270 271 sock = g_io_channel_unix_get_fd(mcl->cc); 272 len = sizeof(flags); 273 274 if (getsockopt(sock, SOL_L2CAP, L2CAP_LM, &flags, &len)) 275 DBG("CSP: could not read role"); 276 277 return flags & L2CAP_LM_MASTER; 278 } 279 280 uint64_t mcap_get_timestamp(struct mcap_mcl *mcl, 281 struct timespec *given_time) 282 { 283 struct timespec now; 284 uint64_t tmstamp; 285 286 if (!mcl->csp) 287 return MCAP_TMSTAMP_DONTSET; 288 289 if (given_time) 290 now = *given_time; 291 else 292 clock_gettime(CLK, &now); 293 294 tmstamp = time_us(&now) - time_us(&mcl->csp->base_time) 295 + mcl->csp->base_tmstamp; 296 297 return tmstamp; 298 } 299 300 uint32_t mcap_get_btclock(struct mcap_mcl *mcl) 301 { 302 uint32_t btclock; 303 uint16_t accuracy; 304 305 if (!mcl->csp) 306 return MCAP_BTCLOCK_IMMEDIATE; 307 308 if (!read_btclock_retry(mcl, &btclock, &accuracy)) 309 btclock = 0xffffffff; 310 311 return btclock; 312 } 313 314 static gboolean initialize_caps(struct mcap_mcl *mcl) 315 { 316 struct timespec t1, t2; 317 int latencies[SAMPLE_COUNT]; 318 int latency, avg, dev; 319 uint32_t btclock; 320 uint16_t btaccuracy; 321 int i; 322 int retries; 323 324 clock_getres(CLK, &t1); 325 326 _caps.ts_res = time_us(&t1); 327 if (_caps.ts_res < 1) 328 _caps.ts_res = 1; 329 330 _caps.ts_acc = 20; /* ppm, estimated */ 331 332 /* A little exercise before measuing latency */ 333 clock_gettime(CLK, &t1); 334 read_btclock_retry(mcl, &btclock, &btaccuracy); 335 336 /* Read clock a number of times and measure latency */ 337 avg = 0; 338 i = 0; 339 retries = MAX_RETRIES; 340 while (i < SAMPLE_COUNT && retries > 0) { 341 clock_gettime(CLK, &t1); 342 if (!read_btclock(mcl, &btclock, &btaccuracy)) { 343 retries--; 344 continue; 345 } 346 clock_gettime(CLK, &t2); 347 348 latency = time_us(&t2) - time_us(&t1); 349 latencies[i] = latency; 350 avg += latency; 351 i++; 352 } 353 354 if (retries <= 0) 355 return FALSE; 356 357 /* Calculate average and deviation */ 358 avg /= SAMPLE_COUNT; 359 dev = 0; 360 for (i = 0; i < SAMPLE_COUNT; ++i) 361 dev += abs(latencies[i] - avg); 362 dev /= SAMPLE_COUNT; 363 364 /* Calculate corrected average, without 'freak' latencies */ 365 latency = 0; 366 for (i = 0; i < SAMPLE_COUNT; ++i) { 367 if (latencies[i] > (avg + dev * 6)) 368 latency += avg; 369 else 370 latency += latencies[i]; 371 } 372 latency /= SAMPLE_COUNT; 373 374 _caps.latency = latency; 375 _caps.preempt_thresh = latency * 4; 376 _caps.syncleadtime_ms = latency * 50 / 1000; 377 378 csp_caps_initialized = TRUE; 379 return TRUE; 380 } 381 382 static struct csp_caps *caps(struct mcap_mcl *mcl) 383 { 384 if (!csp_caps_initialized) 385 if (!initialize_caps(mcl)) { 386 /* Temporary failure in reading BT clock */ 387 return NULL; 388 } 389 390 return &_caps; 391 } 392 393 static int send_sync_cap_rsp(struct mcap_mcl *mcl, uint8_t rspcode, 394 uint8_t btclockres, uint16_t synclead, 395 uint16_t tmstampres, uint16_t tmstampacc) 396 { 397 mcap_md_sync_cap_rsp *rsp; 398 int sent; 399 400 rsp = g_new0(mcap_md_sync_cap_rsp, 1); 401 402 rsp->op = MCAP_MD_SYNC_CAP_RSP; 403 rsp->rc = rspcode; 404 405 rsp->btclock = btclockres; 406 rsp->sltime = htons(synclead); 407 rsp->timestnr = htons(tmstampres); 408 rsp->timestna = htons(tmstampacc); 409 410 sent = send_sync_cmd(mcl, rsp, sizeof(*rsp)); 411 g_free(rsp); 412 413 return sent; 414 } 415 416 static void proc_sync_cap_req(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len) 417 { 418 mcap_md_sync_cap_req *req; 419 uint16_t required_accuracy; 420 uint16_t our_accuracy; 421 uint32_t btclock; 422 uint16_t btres; 423 424 if (len != sizeof(mcap_md_sync_cap_req)) { 425 send_sync_cap_rsp(mcl, MCAP_INVALID_PARAM_VALUE, 426 0, 0, 0, 0); 427 return; 428 } 429 430 if (!caps(mcl)) { 431 send_sync_cap_rsp(mcl, MCAP_RESOURCE_UNAVAILABLE, 432 0, 0, 0, 0); 433 return; 434 } 435 436 req = (mcap_md_sync_cap_req *) cmd; 437 required_accuracy = ntohs(req->timest); 438 our_accuracy = caps(mcl)->ts_acc; 439 440 if (required_accuracy < our_accuracy || required_accuracy < 1) { 441 send_sync_cap_rsp(mcl, MCAP_RESOURCE_UNAVAILABLE, 442 0, 0, 0, 0); 443 return; 444 } 445 446 if (!read_btclock_retry(mcl, &btclock, &btres)) { 447 send_sync_cap_rsp(mcl, MCAP_RESOURCE_UNAVAILABLE, 448 0, 0, 0, 0); 449 return; 450 } 451 452 mcl->csp->remote_caps = 1; 453 mcl->csp->rem_req_acc = required_accuracy; 454 455 send_sync_cap_rsp(mcl, MCAP_SUCCESS, btres, 456 caps(mcl)->syncleadtime_ms, 457 caps(mcl)->ts_res, our_accuracy); 458 } 459 460 static int send_sync_set_rsp(struct mcap_mcl *mcl, uint8_t rspcode, 461 uint32_t btclock, uint64_t timestamp, 462 uint16_t tmstampres) 463 { 464 mcap_md_sync_set_rsp *rsp; 465 int sent; 466 467 rsp = g_new0(mcap_md_sync_set_rsp, 1); 468 469 rsp->op = MCAP_MD_SYNC_SET_RSP; 470 rsp->rc = rspcode; 471 rsp->btclock = htonl(btclock); 472 rsp->timestst = hton64(timestamp); 473 rsp->timestsa = htons(tmstampres); 474 475 sent = send_sync_cmd(mcl, rsp, sizeof(*rsp)); 476 g_free(rsp); 477 478 return sent; 479 } 480 481 static gboolean get_all_clocks(struct mcap_mcl *mcl, uint32_t *btclock, 482 struct timespec *base_time, 483 uint64_t *timestamp) 484 { 485 int latency; 486 int retry = 5; 487 uint16_t btres; 488 struct timespec t0; 489 490 if (!caps(mcl)) 491 return FALSE; 492 493 latency = caps(mcl)->preempt_thresh + 1; 494 495 while (latency > caps(mcl)->preempt_thresh && --retry >= 0) { 496 497 clock_gettime(CLK, &t0); 498 499 if (!read_btclock(mcl, btclock, &btres)) 500 continue; 501 502 clock_gettime(CLK, base_time); 503 504 /* Tries to detect preemption between clock_gettime 505 * and read_btclock by measuring transaction time 506 */ 507 latency = time_us(base_time) - time_us(&t0); 508 } 509 510 *timestamp = mcap_get_timestamp(mcl, base_time); 511 512 return TRUE; 513 } 514 515 static gboolean sync_send_indication(gpointer user_data) 516 { 517 struct mcap_mcl *mcl; 518 mcap_md_sync_info_ind *cmd; 519 uint32_t btclock; 520 uint64_t tmstamp; 521 struct timespec base_time; 522 int sent; 523 524 if (!user_data) 525 return FALSE; 526 527 mcl = user_data; 528 529 if (!caps(mcl)) 530 return FALSE; 531 532 if (!get_all_clocks(mcl, &btclock, &base_time, &tmstamp)) 533 return FALSE; 534 535 cmd = g_new0(mcap_md_sync_info_ind, 1); 536 537 cmd->op = MCAP_MD_SYNC_INFO_IND; 538 cmd->btclock = htonl(btclock); 539 cmd->timestst = hton64(tmstamp); 540 cmd->timestsa = htons(caps(mcl)->latency); 541 542 sent = send_sync_cmd(mcl, cmd, sizeof(*cmd)); 543 g_free(cmd); 544 545 return !sent; 546 } 547 548 static gboolean proc_sync_set_req_phase2(gpointer user_data) 549 { 550 struct mcap_mcl *mcl; 551 struct sync_set_data *data; 552 uint8_t update; 553 uint32_t sched_btclock; 554 uint64_t new_tmstamp; 555 int ind_freq; 556 int role; 557 uint32_t btclock; 558 uint64_t tmstamp; 559 struct timespec base_time; 560 uint16_t tmstampacc; 561 gboolean reset; 562 int delay; 563 564 if (!user_data) 565 return FALSE; 566 567 mcl = user_data; 568 569 if (!mcl->csp->set_data) 570 return FALSE; 571 572 data = mcl->csp->set_data; 573 update = data->update; 574 sched_btclock = data->sched_btclock; 575 new_tmstamp = data->timestamp; 576 ind_freq = data->ind_freq; 577 role = data->role; 578 579 if (!caps(mcl)) { 580 send_sync_set_rsp(mcl, MCAP_UNSPECIFIED_ERROR, 0, 0, 0); 581 return FALSE; 582 } 583 584 if (!get_all_clocks(mcl, &btclock, &base_time, &tmstamp)) { 585 send_sync_set_rsp(mcl, MCAP_UNSPECIFIED_ERROR, 0, 0, 0); 586 return FALSE; 587 } 588 589 if (get_btrole(mcl) != role) { 590 send_sync_set_rsp(mcl, MCAP_INVALID_OPERATION, 0, 0, 0); 591 return FALSE; 592 } 593 594 reset = (new_tmstamp != MCAP_TMSTAMP_DONTSET); 595 596 if (reset) { 597 if (sched_btclock != MCAP_BTCLOCK_IMMEDIATE) { 598 delay = bt2us(btdiff(sched_btclock, btclock)); 599 if (delay >= 0 || ((new_tmstamp - delay) > 0)) { 600 new_tmstamp += delay; 601 DBG("CSP: reset w/ delay %dus, compensated", 602 delay); 603 } else 604 DBG("CSP: reset w/ delay %dus, uncompensated", 605 delay); 606 } 607 608 reset_tmstamp(mcl->csp, &base_time, new_tmstamp); 609 tmstamp = new_tmstamp; 610 } 611 612 tmstampacc = caps(mcl)->latency + caps(mcl)->ts_acc; 613 614 if (mcl->csp->ind_timer) { 615 g_source_remove(mcl->csp->ind_timer); 616 mcl->csp->ind_timer = 0; 617 } 618 619 if (update) { 620 int when = ind_freq + caps(mcl)->syncleadtime_ms; 621 mcl->csp->ind_timer = g_timeout_add(when, 622 sync_send_indication, 623 mcl); 624 } 625 626 send_sync_set_rsp(mcl, MCAP_SUCCESS, btclock, tmstamp, tmstampacc); 627 628 /* First indication after set is immediate */ 629 if (update) 630 sync_send_indication(mcl); 631 632 return FALSE; 633 } 634 635 static void proc_sync_set_req(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len) 636 { 637 mcap_md_sync_set_req *req; 638 uint32_t sched_btclock, cur_btclock; 639 uint16_t btres; 640 uint8_t update; 641 uint64_t timestamp; 642 struct sync_set_data *set_data; 643 int phase2_delay, ind_freq, when; 644 645 if (len != sizeof(mcap_md_sync_set_req)) { 646 send_sync_set_rsp(mcl, MCAP_INVALID_PARAM_VALUE, 0, 0, 0); 647 return; 648 } 649 650 req = (mcap_md_sync_set_req *) cmd; 651 sched_btclock = ntohl(req->btclock); 652 update = req->timestui; 653 timestamp = ntoh64(req->timestst); 654 655 if (sched_btclock != MCAP_BTCLOCK_IMMEDIATE && 656 !valid_btclock(sched_btclock)) { 657 send_sync_set_rsp(mcl, MCAP_INVALID_PARAM_VALUE, 0, 0, 0); 658 return; 659 } 660 661 if (update > 1) { 662 send_sync_set_rsp(mcl, MCAP_INVALID_PARAM_VALUE, 0, 0, 0); 663 return; 664 } 665 666 if (!mcl->csp->remote_caps) { 667 /* Remote side did not ask our capabilities yet */ 668 send_sync_set_rsp(mcl, MCAP_INVALID_PARAM_VALUE, 0, 0, 0); 669 return; 670 } 671 672 if (!caps(mcl)) { 673 send_sync_set_rsp(mcl, MCAP_UNSPECIFIED_ERROR, 0, 0, 0); 674 return; 675 } 676 677 if (!read_btclock_retry(mcl, &cur_btclock, &btres)) { 678 send_sync_set_rsp(mcl, MCAP_UNSPECIFIED_ERROR, 0, 0, 0); 679 return; 680 } 681 682 if (sched_btclock == MCAP_BTCLOCK_IMMEDIATE) 683 phase2_delay = 0; 684 else { 685 phase2_delay = btdiff(cur_btclock, sched_btclock); 686 687 if (phase2_delay < 0) { 688 /* can not reset in the past tense */ 689 send_sync_set_rsp(mcl, MCAP_INVALID_PARAM_VALUE, 690 0, 0, 0); 691 return; 692 } 693 694 /* Convert to miliseconds */ 695 phase2_delay = bt2ms(phase2_delay); 696 697 if (phase2_delay > 61*1000) { 698 /* More than 60 seconds in the future */ 699 send_sync_set_rsp(mcl, MCAP_INVALID_PARAM_VALUE, 700 0, 0, 0); 701 return; 702 } else if (phase2_delay < caps(mcl)->latency / 1000) { 703 /* Too fast for us to do in time */ 704 send_sync_set_rsp(mcl, MCAP_INVALID_PARAM_VALUE, 705 0, 0, 0); 706 return; 707 } 708 } 709 710 if (update) { 711 /* Indication frequency: required accuracy divided by ours */ 712 /* Converted to milisseconds */ 713 ind_freq = (1000 * mcl->csp->rem_req_acc) / caps(mcl)->ts_acc; 714 715 if (ind_freq < MAX(caps(mcl)->latency * 2 / 1000, 100)) { 716 /* Too frequent, we can't handle */ 717 send_sync_set_rsp(mcl, MCAP_INVALID_PARAM_VALUE, 718 0, 0, 0); 719 return; 720 } 721 722 DBG("CSP: indication every %dms", ind_freq); 723 } else 724 ind_freq = 0; 725 726 if (mcl->csp->ind_timer) { 727 /* Old indications are no longer sent */ 728 g_source_remove(mcl->csp->ind_timer); 729 mcl->csp->ind_timer = 0; 730 } 731 732 if (!mcl->csp->set_data) 733 mcl->csp->set_data = g_new0(struct sync_set_data, 1); 734 735 set_data = (struct sync_set_data *) mcl->csp->set_data; 736 737 set_data->update = update; 738 set_data->sched_btclock = sched_btclock; 739 set_data->timestamp = timestamp; 740 set_data->ind_freq = ind_freq; 741 set_data->role = get_btrole(mcl); 742 743 /* TODO is there some way to schedule a call based directly on 744 * a BT clock value, instead of this estimation that uses 745 * the SO clock? */ 746 747 if (phase2_delay > 0) { 748 when = phase2_delay + caps(mcl)->syncleadtime_ms; 749 mcl->csp->set_timer = g_timeout_add(when, 750 proc_sync_set_req_phase2, 751 mcl); 752 } else 753 proc_sync_set_req_phase2(mcl); 754 755 /* First indication is immediate */ 756 if (update) 757 sync_send_indication(mcl); 758 } 759 760 static void proc_sync_cap_rsp(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len) 761 { 762 mcap_md_sync_cap_rsp *rsp; 763 uint8_t mcap_err; 764 uint8_t btclockres; 765 uint16_t synclead; 766 uint16_t tmstampres; 767 uint16_t tmstampacc; 768 struct mcap_sync_cap_cbdata *cbdata; 769 mcap_sync_cap_cb cb; 770 gpointer user_data; 771 772 if (mcl->csp->csp_req != MCAP_MD_SYNC_CAP_REQ) { 773 DBG("CSP: got unexpected cap respose"); 774 return; 775 } 776 777 if (!mcl->csp->csp_priv_data) { 778 DBG("CSP: no priv data for cap respose"); 779 return; 780 } 781 782 cbdata = mcl->csp->csp_priv_data; 783 cb = cbdata->cb; 784 user_data = cbdata->user_data; 785 g_free(cbdata); 786 787 mcl->csp->csp_priv_data = NULL; 788 mcl->csp->csp_req = 0; 789 790 if (len != sizeof(mcap_md_sync_cap_rsp)) { 791 DBG("CSP: got corrupted cap respose"); 792 return; 793 } 794 795 rsp = (mcap_md_sync_cap_rsp *) cmd; 796 mcap_err = rsp->rc; 797 btclockres = rsp->btclock; 798 synclead = ntohs(rsp->sltime); 799 tmstampres = ntohs(rsp->timestnr); 800 tmstampacc = ntohs(rsp->timestna); 801 802 if (!mcap_err) 803 mcl->csp->local_caps = TRUE; 804 805 cb(mcl, mcap_err, btclockres, synclead, tmstampres, tmstampacc, NULL, 806 user_data); 807 } 808 809 static void proc_sync_set_rsp(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len) 810 { 811 mcap_md_sync_set_rsp *rsp; 812 uint8_t mcap_err; 813 uint32_t btclock; 814 uint64_t timestamp; 815 uint16_t accuracy; 816 struct mcap_sync_set_cbdata *cbdata; 817 mcap_sync_set_cb cb; 818 gpointer user_data; 819 820 if (mcl->csp->csp_req != MCAP_MD_SYNC_SET_REQ) { 821 DBG("CSP: got unexpected set respose"); 822 return; 823 } 824 825 if (!mcl->csp->csp_priv_data) { 826 DBG("CSP: no priv data for set respose"); 827 return; 828 } 829 830 cbdata = mcl->csp->csp_priv_data; 831 cb = cbdata->cb; 832 user_data = cbdata->user_data; 833 g_free(cbdata); 834 835 mcl->csp->csp_priv_data = NULL; 836 mcl->csp->csp_req = 0; 837 838 if (len != sizeof(mcap_md_sync_set_rsp)) { 839 DBG("CSP: got corrupted set respose"); 840 return; 841 } 842 843 rsp = (mcap_md_sync_set_rsp *) cmd; 844 mcap_err = rsp->rc; 845 btclock = ntohl(rsp->btclock); 846 timestamp = ntoh64(rsp->timestst); 847 accuracy = ntohs(rsp->timestsa); 848 849 if (!mcap_err && !valid_btclock(btclock)) 850 mcap_err = MCAP_ERROR_INVALID_ARGS; 851 852 cb(mcl, mcap_err, btclock, timestamp, accuracy, NULL, user_data); 853 } 854 855 static void proc_sync_info_ind(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len) 856 { 857 mcap_md_sync_info_ind *req; 858 struct sync_info_ind_data data; 859 uint32_t btclock; 860 861 if (!mcl->csp->ind_expected) { 862 DBG("CSP: received unexpected info indication"); 863 return; 864 } 865 866 if (len != sizeof(mcap_md_sync_info_ind)) 867 return; 868 869 req = (mcap_md_sync_info_ind *) cmd; 870 871 btclock = ntohl(req->btclock); 872 873 if (!valid_btclock(btclock)) 874 return; 875 876 data.btclock = btclock; 877 data.timestamp = ntoh64(req->timestst); 878 data.accuracy = ntohs(req->timestsa); 879 880 if (mcl->mi->mcl_sync_infoind_cb) 881 mcl->mi->mcl_sync_infoind_cb(mcl, &data); 882 } 883 884 void proc_sync_cmd(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len) 885 { 886 if (!mcl->mi->csp_enabled || !mcl->csp) { 887 switch (cmd[0]) { 888 case MCAP_MD_SYNC_CAP_REQ: 889 send_unsupported_cap_req(mcl); 890 break; 891 case MCAP_MD_SYNC_SET_REQ: 892 send_unsupported_set_req(mcl); 893 break; 894 } 895 return; 896 } 897 898 switch (cmd[0]) { 899 case MCAP_MD_SYNC_CAP_REQ: 900 proc_sync_cap_req(mcl, cmd, len); 901 break; 902 case MCAP_MD_SYNC_CAP_RSP: 903 proc_sync_cap_rsp(mcl, cmd, len); 904 break; 905 case MCAP_MD_SYNC_SET_REQ: 906 proc_sync_set_req(mcl, cmd, len); 907 break; 908 case MCAP_MD_SYNC_SET_RSP: 909 proc_sync_set_rsp(mcl, cmd, len); 910 break; 911 case MCAP_MD_SYNC_INFO_IND: 912 proc_sync_info_ind(mcl, cmd, len); 913 break; 914 } 915 } 916 917 void mcap_sync_cap_req(struct mcap_mcl *mcl, uint16_t reqacc, 918 mcap_sync_cap_cb cb, gpointer user_data, 919 GError **err) 920 { 921 struct mcap_sync_cap_cbdata *cbdata; 922 mcap_md_sync_cap_req *cmd; 923 924 if (!mcl->mi->csp_enabled || !mcl->csp) { 925 g_set_error(err, 926 MCAP_CSP_ERROR, 927 MCAP_ERROR_RESOURCE_UNAVAILABLE, 928 "CSP not enabled for the instance"); 929 return; 930 } 931 932 if (mcl->csp->csp_req) { 933 g_set_error(err, 934 MCAP_CSP_ERROR, 935 MCAP_ERROR_RESOURCE_UNAVAILABLE, 936 "Pending CSP request"); 937 return; 938 } 939 940 mcl->csp->csp_req = MCAP_MD_SYNC_CAP_REQ; 941 cmd = g_new0(mcap_md_sync_cap_req, 1); 942 943 cmd->op = MCAP_MD_SYNC_CAP_REQ; 944 cmd->timest = htons(reqacc); 945 946 cbdata = g_new0(struct mcap_sync_cap_cbdata, 1); 947 cbdata->cb = cb; 948 cbdata->user_data = user_data; 949 mcl->csp->csp_priv_data = cbdata; 950 951 send_sync_cmd(mcl, cmd, sizeof(*cmd)); 952 953 g_free(cmd); 954 } 955 956 void mcap_sync_set_req(struct mcap_mcl *mcl, uint8_t update, uint32_t btclock, 957 uint64_t timestamp, mcap_sync_set_cb cb, 958 gpointer user_data, GError **err) 959 { 960 mcap_md_sync_set_req *cmd; 961 struct mcap_sync_set_cbdata *cbdata; 962 963 if (!mcl->mi->csp_enabled || !mcl->csp) { 964 g_set_error(err, 965 MCAP_CSP_ERROR, 966 MCAP_ERROR_RESOURCE_UNAVAILABLE, 967 "CSP not enabled for the instance"); 968 return; 969 } 970 971 if (!mcl->csp->local_caps) { 972 g_set_error(err, 973 MCAP_CSP_ERROR, 974 MCAP_ERROR_RESOURCE_UNAVAILABLE, 975 "Did not get CSP caps from slave yet"); 976 return; 977 } 978 979 if (mcl->csp->csp_req) { 980 g_set_error(err, 981 MCAP_CSP_ERROR, 982 MCAP_ERROR_RESOURCE_UNAVAILABLE, 983 "Pending CSP request"); 984 return; 985 } 986 987 mcl->csp->csp_req = MCAP_MD_SYNC_SET_REQ; 988 cmd = g_new0(mcap_md_sync_set_req, 1); 989 990 cmd->op = MCAP_MD_SYNC_SET_REQ; 991 cmd->timestui = update; 992 cmd->btclock = htonl(btclock); 993 cmd->timestst = hton64(timestamp); 994 995 mcl->csp->ind_expected = update; 996 997 cbdata = g_new0(struct mcap_sync_set_cbdata, 1); 998 cbdata->cb = cb; 999 cbdata->user_data = user_data; 1000 mcl->csp->csp_priv_data = cbdata; 1001 1002 send_sync_cmd(mcl, cmd, sizeof(*cmd)); 1003 1004 g_free(cmd); 1005 } 1006 1007 void mcap_enable_csp(struct mcap_instance *mi) 1008 { 1009 mi->csp_enabled = TRUE; 1010 } 1011 1012 void mcap_disable_csp(struct mcap_instance *mi) 1013 { 1014 mi->csp_enabled = FALSE; 1015 } 1016