1 /* 2 * 3 * MCAP for BlueZ - Bluetooth protocol stack for Linux 4 * 5 * Copyright (C) 2010 GSyC/LibreSoft, Universidad Rey Juan Carlos. 6 * 7 * Authors: 8 * Santiago Carot-Nemesio <sancane at gmail.com> 9 * Jose Antonio Santos-Cadenas <santoscadenas at gmail.com> 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 * 25 */ 26 27 #include "log.h" 28 #include "error.h" 29 30 #include <netinet/in.h> 31 #include <stdlib.h> 32 #include <errno.h> 33 #include <unistd.h> 34 35 #include "btio.h" 36 #include <bluetooth/bluetooth.h> 37 #include <bluetooth/l2cap.h> 38 #include "mcap.h" 39 #include "mcap_lib.h" 40 #include "mcap_internal.h" 41 42 #define RESPONSE_TIMER 6 /* seconds */ 43 #define MAX_CACHED 10 /* 10 devices */ 44 45 #define MCAP_ERROR g_quark_from_static_string("mcap-error-quark") 46 47 #define RELEASE_TIMER(__mcl) do { \ 48 if (__mcl->tid) { \ 49 g_source_remove(__mcl->tid); \ 50 __mcl->tid = 0; \ 51 } \ 52 } while(0) 53 54 struct connect_mcl { 55 struct mcap_mcl *mcl; /* MCL for this operation */ 56 mcap_mcl_connect_cb connect_cb; /* Connect callback */ 57 GDestroyNotify destroy; /* Destroy callback */ 58 gpointer user_data; /* Callback user data */ 59 }; 60 61 typedef union { 62 mcap_mdl_operation_cb op; 63 mcap_mdl_operation_conf_cb op_conf; 64 mcap_mdl_notify_cb notify; 65 } mcap_cb_type; 66 67 struct mcap_mdl_op_cb { 68 struct mcap_mdl *mdl; /* MDL for this operation */ 69 mcap_cb_type cb; /* Operation callback */ 70 GDestroyNotify destroy; /* Destroy callback */ 71 gpointer user_data; /* Callback user data */ 72 }; 73 74 /* MCAP finite state machine functions */ 75 static void proc_req_connected(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t l); 76 static void proc_req_pending(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t l); 77 static void proc_req_active(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t l); 78 79 static void (*proc_req[])(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len) = { 80 proc_req_connected, 81 proc_req_pending, 82 proc_req_active 83 }; 84 85 static void mcap_cache_mcl(struct mcap_mcl *mcl); 86 87 static void default_mdl_connected_cb(struct mcap_mdl *mdl, gpointer data) 88 { 89 DBG("MCAP Unmanaged mdl connection"); 90 } 91 92 static void default_mdl_closed_cb(struct mcap_mdl *mdl, gpointer data) 93 { 94 DBG("MCAP Unmanaged mdl closed"); 95 } 96 97 static void default_mdl_deleted_cb(struct mcap_mdl *mdl, gpointer data) 98 { 99 DBG("MCAP Unmanaged mdl deleted"); 100 } 101 102 static void default_mdl_aborted_cb(struct mcap_mdl *mdl, gpointer data) 103 { 104 DBG("MCAP Unmanaged mdl aborted"); 105 } 106 107 static uint8_t default_mdl_conn_req_cb(struct mcap_mcl *mcl, 108 uint8_t mdepid, uint16_t mdlid, 109 uint8_t *conf, gpointer data) 110 { 111 DBG("MCAP mdl remote connection aborted"); 112 /* Due to this callback isn't managed this request won't be supported */ 113 return MCAP_REQUEST_NOT_SUPPORTED; 114 } 115 116 static uint8_t default_mdl_reconn_req_cb(struct mcap_mdl *mdl, 117 gpointer data) 118 { 119 DBG("MCAP mdl remote reconnection aborted"); 120 /* Due to this callback isn't managed this request won't be supported */ 121 return MCAP_REQUEST_NOT_SUPPORTED; 122 } 123 124 static void set_default_cb(struct mcap_mcl *mcl) 125 { 126 if (!mcl->cb) 127 mcl->cb = g_new0(struct mcap_mdl_cb, 1); 128 129 mcl->cb->mdl_connected = default_mdl_connected_cb; 130 mcl->cb->mdl_closed = default_mdl_closed_cb; 131 mcl->cb->mdl_deleted = default_mdl_deleted_cb; 132 mcl->cb->mdl_aborted = default_mdl_aborted_cb; 133 mcl->cb->mdl_conn_req = default_mdl_conn_req_cb; 134 mcl->cb->mdl_reconn_req = default_mdl_reconn_req_cb; 135 } 136 137 static char *error2str(uint8_t rc) 138 { 139 switch (rc) { 140 case MCAP_SUCCESS: 141 return "Success"; 142 case MCAP_INVALID_OP_CODE: 143 return "Invalid Op Code"; 144 case MCAP_INVALID_PARAM_VALUE: 145 return "Invalid Parameter Value"; 146 case MCAP_INVALID_MDEP: 147 return "Invalid MDEP"; 148 case MCAP_MDEP_BUSY: 149 return "MDEP Busy"; 150 case MCAP_INVALID_MDL: 151 return "Invalid MDL"; 152 case MCAP_MDL_BUSY: 153 return "MDL Busy"; 154 case MCAP_INVALID_OPERATION: 155 return "Invalid Operation"; 156 case MCAP_RESOURCE_UNAVAILABLE: 157 return "Resource Unavailable"; 158 case MCAP_UNSPECIFIED_ERROR: 159 return "Unspecified Error"; 160 case MCAP_REQUEST_NOT_SUPPORTED: 161 return "Request Not Supported"; 162 case MCAP_CONFIGURATION_REJECTED: 163 return "Configuration Rejected"; 164 default: 165 return "Unknown Response Code"; 166 } 167 } 168 169 static gboolean mcap_send_std_opcode(struct mcap_mcl *mcl, void *cmd, 170 uint32_t size, GError **err) 171 { 172 if (mcl->state == MCL_IDLE) { 173 g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED, 174 "MCL is not connected"); 175 return FALSE; 176 } 177 178 if (mcl->req != MCL_AVAILABLE) { 179 g_set_error(err, MCAP_ERROR, MCAP_ERROR_RESOURCE_UNAVAILABLE, 180 "Pending request"); 181 return FALSE; 182 } 183 184 if (!(mcl->ctrl & MCAP_CTRL_STD_OP)) { 185 g_set_error(err, MCAP_ERROR, MCAP_ERROR_REQUEST_NOT_SUPPORTED, 186 "Remote does not support standard opcodes"); 187 return FALSE; 188 } 189 190 if (mcl->state == MCL_PENDING) { 191 g_set_error(err, MCAP_ERROR, MCAP_ERROR_INVALID_OPERATION, 192 "Not Std Op. Codes can be sent in PENDING State"); 193 return FALSE; 194 } 195 196 if (mcap_send_data(g_io_channel_unix_get_fd(mcl->cc), cmd, size) < 0) { 197 g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED, 198 "Command can't be sent, write error"); 199 return FALSE; 200 } 201 202 mcl->lcmd = cmd; 203 mcl->req = MCL_WAITING_RSP; 204 205 return TRUE; 206 } 207 208 static void update_mcl_state(struct mcap_mcl *mcl) 209 { 210 GSList *l; 211 struct mcap_mdl *mdl; 212 213 if (mcl->state == MCL_PENDING) 214 return; 215 216 for (l = mcl->mdls; l; l = l->next) { 217 mdl = l->data; 218 219 if (mdl->state == MDL_CONNECTED) { 220 mcl->state = MCL_ACTIVE; 221 return; 222 } 223 } 224 225 mcl->state = MCL_CONNECTED; 226 } 227 228 static void shutdown_mdl(struct mcap_mdl *mdl) 229 { 230 mdl->state = MDL_CLOSED; 231 232 if (mdl->wid) { 233 g_source_remove(mdl->wid); 234 mdl->wid = 0; 235 } 236 237 if (mdl->dc) { 238 g_io_channel_shutdown(mdl->dc, TRUE, NULL); 239 g_io_channel_unref(mdl->dc); 240 mdl->dc = NULL; 241 } 242 } 243 244 static void free_mdl(struct mcap_mdl *mdl) 245 { 246 if (!mdl) 247 return; 248 249 mcap_mcl_unref(mdl->mcl); 250 g_free(mdl); 251 } 252 253 static gint cmp_mdl_state(gconstpointer a, gconstpointer b) 254 { 255 const struct mcap_mdl *mdl = a; 256 const MDLState *st = b; 257 258 if (mdl->state == *st) 259 return 0; 260 else if (mdl->state < *st) 261 return -1; 262 else 263 return 1; 264 } 265 266 static void free_mcap_mdl_op(struct mcap_mdl_op_cb *op) 267 { 268 if (op->destroy) 269 op->destroy(op->user_data); 270 271 if (op->mdl) 272 mcap_mdl_unref(op->mdl); 273 274 g_free(op); 275 } 276 277 static void free_mcl_priv_data(struct mcap_mcl *mcl) 278 { 279 free_mcap_mdl_op(mcl->priv_data); 280 mcl->priv_data = NULL; 281 } 282 283 static void mcap_notify_error(struct mcap_mcl *mcl, GError *err) 284 { 285 struct mcap_mdl_op_cb *con = mcl->priv_data; 286 struct mcap_mdl *mdl; 287 MDLState st; 288 GSList *l; 289 290 if (!con || !mcl->lcmd) 291 return; 292 293 switch (mcl->lcmd[0]) { 294 case MCAP_MD_CREATE_MDL_REQ: 295 st = MDL_WAITING; 296 l = g_slist_find_custom(mcl->mdls, &st, cmp_mdl_state); 297 mdl = l->data; 298 mcl->mdls = g_slist_remove(mcl->mdls, mdl); 299 mcap_mdl_unref(mdl); 300 update_mcl_state(mcl); 301 con->cb.op_conf(NULL, 0, err, con->user_data); 302 break; 303 case MCAP_MD_ABORT_MDL_REQ: 304 st = MDL_WAITING; 305 l = g_slist_find_custom(mcl->mdls, &st, cmp_mdl_state); 306 shutdown_mdl(l->data); 307 update_mcl_state(mcl); 308 con->cb.notify(err, con->user_data); 309 break; 310 case MCAP_MD_DELETE_MDL_REQ: 311 for (l = mcl->mdls; l; l = l->next) { 312 mdl = l->data; 313 if (mdl->state == MDL_DELETING) 314 mdl->state = (mdl->dc) ? MDL_CONNECTED : 315 MDL_CLOSED; 316 } 317 update_mcl_state(mcl); 318 con->cb.notify(err, con->user_data); 319 break; 320 case MCAP_MD_RECONNECT_MDL_REQ: 321 st = MDL_WAITING; 322 l = g_slist_find_custom(mcl->mdls, &st, cmp_mdl_state); 323 shutdown_mdl(l->data); 324 update_mcl_state(mcl); 325 con->cb.op(NULL, err, con->user_data); 326 break; 327 } 328 329 free_mcl_priv_data(mcl); 330 g_free(mcl->lcmd); 331 mcl->lcmd = NULL; 332 } 333 334 int mcap_send_data(int sock, const void *buf, uint32_t size) 335 { 336 const uint8_t *buf_b = buf; 337 uint32_t sent = 0; 338 339 while (sent < size) { 340 int n = write(sock, buf_b + sent, size - sent); 341 if (n < 0) 342 return -1; 343 sent += n; 344 } 345 346 return 0; 347 } 348 349 static int mcap_send_cmd(struct mcap_mcl *mcl, uint8_t oc, uint8_t rc, 350 uint16_t mdl, uint8_t *data, size_t len) 351 { 352 mcap_rsp *cmd; 353 int sock, sent; 354 355 if (mcl->cc == NULL) 356 return -1; 357 358 sock = g_io_channel_unix_get_fd(mcl->cc); 359 360 cmd = g_malloc(sizeof(mcap_rsp) + len); 361 cmd->op = oc; 362 cmd->rc = rc; 363 cmd->mdl = htons(mdl); 364 365 if (data && len > 0) 366 memcpy(cmd->data, data, len); 367 368 sent = mcap_send_data(sock, cmd, sizeof(mcap_rsp) + len); 369 g_free(cmd); 370 371 return sent; 372 } 373 374 static struct mcap_mdl *get_mdl(struct mcap_mcl *mcl, uint16_t mdlid) 375 { 376 GSList *l; 377 struct mcap_mdl *mdl; 378 379 for (l = mcl->mdls; l; l = l->next) { 380 mdl = l->data; 381 if (mdlid == mdl->mdlid) 382 return mdl; 383 } 384 385 return NULL; 386 } 387 388 static uint16_t generate_mdlid(struct mcap_mcl *mcl) 389 { 390 uint16_t mdlid = mcl->next_mdl; 391 struct mcap_mdl *mdl; 392 393 do { 394 mdl = get_mdl(mcl, mdlid); 395 if (!mdl) { 396 mcl->next_mdl = (mdlid % MCAP_MDLID_FINAL) + 1; 397 return mdlid; 398 } else 399 mdlid = (mdlid % MCAP_MDLID_FINAL) + 1; 400 } while (mdlid != mcl->next_mdl); 401 402 /* No more mdlids availables */ 403 return 0; 404 } 405 406 static mcap_md_req *create_req(uint8_t op, uint16_t mdl_id) 407 { 408 mcap_md_req *req_cmd; 409 410 req_cmd = g_new0(mcap_md_req, 1); 411 412 req_cmd->op = op; 413 req_cmd->mdl = htons(mdl_id); 414 415 return req_cmd; 416 } 417 418 static mcap_md_create_mdl_req *create_mdl_req(uint16_t mdl_id, uint8_t mdep, 419 uint8_t conf) 420 { 421 mcap_md_create_mdl_req *req_mdl; 422 423 req_mdl = g_new0(mcap_md_create_mdl_req, 1); 424 425 req_mdl->op = MCAP_MD_CREATE_MDL_REQ; 426 req_mdl->mdl = htons(mdl_id); 427 req_mdl->mdep = mdep; 428 req_mdl->conf = conf; 429 430 return req_mdl; 431 } 432 433 static gint compare_mdl(gconstpointer a, gconstpointer b) 434 { 435 const struct mcap_mdl *mdla = a; 436 const struct mcap_mdl *mdlb = b; 437 438 if (mdla->mdlid == mdlb->mdlid) 439 return 0; 440 else if (mdla->mdlid < mdlb->mdlid) 441 return -1; 442 else 443 return 1; 444 } 445 446 static gboolean wait_response_timer(gpointer data) 447 { 448 struct mcap_mcl *mcl = data; 449 450 GError *gerr = NULL; 451 452 RELEASE_TIMER(mcl); 453 454 g_set_error(&gerr, MCAP_ERROR, MCAP_ERROR_FAILED, 455 "Timeout waiting response"); 456 457 mcap_notify_error(mcl, gerr); 458 459 g_error_free(gerr); 460 mcl->mi->mcl_disconnected_cb(mcl, mcl->mi->user_data); 461 mcap_cache_mcl(mcl); 462 463 return FALSE; 464 } 465 466 gboolean mcap_create_mdl(struct mcap_mcl *mcl, 467 uint8_t mdepid, 468 uint8_t conf, 469 mcap_mdl_operation_conf_cb connect_cb, 470 gpointer user_data, 471 GDestroyNotify destroy, 472 GError **err) 473 { 474 struct mcap_mdl *mdl; 475 struct mcap_mdl_op_cb *con; 476 mcap_md_create_mdl_req *cmd; 477 uint16_t id; 478 479 id = generate_mdlid(mcl); 480 if (!id) { 481 g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED, 482 "Not more mdlids available"); 483 return FALSE; 484 } 485 486 mdl = g_new0(struct mcap_mdl, 1); 487 mdl->mcl = mcap_mcl_ref(mcl); 488 mdl->mdlid = id; 489 mdl->mdep_id = mdepid; 490 mdl->state = MDL_WAITING; 491 492 con = g_new0(struct mcap_mdl_op_cb, 1); 493 con->mdl = mcap_mdl_ref(mdl); 494 con->cb.op_conf = connect_cb; 495 con->destroy = destroy; 496 con->user_data = user_data; 497 498 cmd = create_mdl_req(id, mdepid, conf); 499 if (!mcap_send_std_opcode(mcl, cmd, sizeof(mcap_md_create_mdl_req), 500 err)) { 501 mcap_mdl_unref(con->mdl); 502 g_free(con); 503 g_free(cmd); 504 return FALSE; 505 } 506 507 mcl->state = MCL_ACTIVE; 508 mcl->priv_data = con; 509 510 mcl->mdls = g_slist_insert_sorted(mcl->mdls, mcap_mdl_ref(mdl), 511 compare_mdl); 512 mcl->tid = g_timeout_add_seconds(RESPONSE_TIMER, wait_response_timer, 513 mcl); 514 return TRUE; 515 } 516 517 gboolean mcap_reconnect_mdl(struct mcap_mdl *mdl, 518 mcap_mdl_operation_cb reconnect_cb, 519 gpointer user_data, 520 GDestroyNotify destroy, 521 GError **err) 522 { 523 struct mcap_mdl_op_cb *con; 524 struct mcap_mcl *mcl = mdl->mcl; 525 mcap_md_req *cmd; 526 527 if (mdl->state != MDL_CLOSED) { 528 g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED, 529 "MDL is not closed"); 530 return FALSE; 531 } 532 533 cmd = create_req(MCAP_MD_RECONNECT_MDL_REQ, mdl->mdlid); 534 if (!mcap_send_std_opcode(mcl, cmd, sizeof(mcap_md_req), err)) { 535 g_free(cmd); 536 return FALSE; 537 } 538 539 mdl->state = MDL_WAITING; 540 541 con = g_new0(struct mcap_mdl_op_cb, 1); 542 con->mdl = mcap_mdl_ref(mdl); 543 con->cb.op = reconnect_cb; 544 con->destroy = destroy; 545 con->user_data = user_data; 546 547 mcl->state = MCL_ACTIVE; 548 mcl->priv_data = con; 549 550 mcl->tid = g_timeout_add_seconds(RESPONSE_TIMER, wait_response_timer, 551 mcl); 552 return TRUE; 553 } 554 555 static gboolean send_delete_req(struct mcap_mcl *mcl, 556 struct mcap_mdl_op_cb *con, 557 uint16_t mdlid, 558 GError **err) 559 { 560 mcap_md_req *cmd; 561 562 cmd = create_req(MCAP_MD_DELETE_MDL_REQ, mdlid); 563 if (!mcap_send_std_opcode(mcl, cmd, sizeof(mcap_md_req), err)) { 564 g_free(cmd); 565 return FALSE; 566 } 567 568 mcl->priv_data = con; 569 570 mcl->tid = g_timeout_add_seconds(RESPONSE_TIMER, wait_response_timer, 571 mcl); 572 return TRUE; 573 } 574 575 gboolean mcap_delete_all_mdls(struct mcap_mcl *mcl, 576 mcap_mdl_notify_cb delete_cb, 577 gpointer user_data, 578 GDestroyNotify destroy, 579 GError **err) 580 { 581 GSList *l; 582 struct mcap_mdl *mdl; 583 struct mcap_mdl_op_cb *con; 584 585 DBG("MCL in state: %d", mcl->state); 586 if (!mcl->mdls) { 587 g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED, 588 "There are not MDLs created"); 589 return FALSE; 590 } 591 592 for (l = mcl->mdls; l; l = l->next) { 593 mdl = l->data; 594 if (mdl->state != MDL_WAITING) 595 mdl->state = MDL_DELETING; 596 } 597 598 con = g_new0(struct mcap_mdl_op_cb, 1); 599 con->mdl = NULL; 600 con->cb.notify = delete_cb; 601 con->destroy = destroy; 602 con->user_data = user_data; 603 604 605 if (!send_delete_req(mcl, con, MCAP_ALL_MDLIDS, err)) { 606 g_free(con); 607 return FALSE; 608 } 609 610 return TRUE; 611 } 612 613 gboolean mcap_delete_mdl(struct mcap_mdl *mdl, mcap_mdl_notify_cb delete_cb, 614 gpointer user_data, 615 GDestroyNotify destroy, 616 GError **err) 617 { 618 struct mcap_mcl *mcl= mdl->mcl; 619 struct mcap_mdl_op_cb *con; 620 GSList *l; 621 622 l = g_slist_find(mcl->mdls, mdl); 623 624 if (!l) { 625 g_set_error(err, MCAP_ERROR, MCAP_ERROR_INVALID_MDL, 626 "%s" , error2str(MCAP_INVALID_MDEP)); 627 return FALSE; 628 } 629 630 if (mdl->state == MDL_WAITING) { 631 g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED, 632 "Mdl is not created"); 633 return FALSE; 634 } 635 636 mdl->state = MDL_DELETING; 637 638 con = g_new0(struct mcap_mdl_op_cb, 1); 639 con->mdl = mcap_mdl_ref(mdl); 640 con->cb.notify = delete_cb; 641 con->destroy = destroy; 642 con->user_data = user_data; 643 644 if (!send_delete_req(mcl, con, mdl->mdlid, err)) { 645 mcap_mdl_unref(con->mdl); 646 g_free(con); 647 return FALSE; 648 } 649 650 return TRUE; 651 } 652 653 gboolean mcap_mdl_abort(struct mcap_mdl *mdl, mcap_mdl_notify_cb abort_cb, 654 gpointer user_data, 655 GDestroyNotify destroy, 656 GError **err) 657 { 658 struct mcap_mdl_op_cb *con; 659 struct mcap_mcl *mcl = mdl->mcl; 660 mcap_md_req *cmd; 661 662 if (mdl->state != MDL_WAITING) { 663 g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED, 664 "Mdl in invalid state"); 665 return FALSE; 666 } 667 668 cmd = create_req(MCAP_MD_ABORT_MDL_REQ, mdl->mdlid); 669 if (!mcap_send_std_opcode(mcl, cmd, sizeof(mcap_md_req), err)) { 670 g_free(cmd); 671 return FALSE; 672 } 673 674 con = g_new0(struct mcap_mdl_op_cb, 1); 675 con->mdl = mcap_mdl_ref(mdl); 676 con->cb.notify = abort_cb; 677 con->destroy = destroy; 678 con->user_data = user_data; 679 680 mcl->priv_data = con; 681 mcl->tid = g_timeout_add_seconds(RESPONSE_TIMER, wait_response_timer, 682 mcl); 683 return TRUE; 684 } 685 686 static struct mcap_mcl *find_mcl(GSList *list, const bdaddr_t *addr) 687 { 688 struct mcap_mcl *mcl; 689 690 for (; list; list = list->next) { 691 mcl = list->data; 692 693 if (!bacmp(&mcl->addr, addr)) 694 return mcl; 695 } 696 697 return NULL; 698 } 699 700 int mcap_mdl_get_fd(struct mcap_mdl *mdl) 701 { 702 if (!mdl || mdl->state != MDL_CONNECTED) 703 return -ENOTCONN; 704 705 return g_io_channel_unix_get_fd(mdl->dc); 706 } 707 708 uint16_t mcap_mdl_get_mdlid(struct mcap_mdl *mdl) 709 { 710 if (!mdl) 711 return MCAP_MDLID_RESERVED; 712 713 return mdl->mdlid; 714 } 715 716 static void close_mcl(struct mcap_mcl *mcl, gboolean cache_requested) 717 { 718 gboolean save = ((!(mcl->ctrl & MCAP_CTRL_FREE)) && cache_requested); 719 720 RELEASE_TIMER(mcl); 721 722 if (mcl->cc) { 723 g_io_channel_shutdown(mcl->cc, TRUE, NULL); 724 g_io_channel_unref(mcl->cc); 725 mcl->cc = NULL; 726 } 727 728 if (mcl->wid) { 729 g_source_remove(mcl->wid); 730 mcl->wid = 0; 731 } 732 733 if (mcl->lcmd) { 734 g_free(mcl->lcmd); 735 mcl->lcmd = NULL; 736 } 737 738 if (mcl->priv_data) 739 free_mcl_priv_data(mcl); 740 741 g_slist_foreach(mcl->mdls, (GFunc) shutdown_mdl, NULL); 742 743 mcap_sync_stop(mcl); 744 745 mcl->state = MCL_IDLE; 746 747 if (save) 748 return; 749 750 g_slist_foreach(mcl->mdls, (GFunc) mcap_mdl_unref, NULL); 751 g_slist_free(mcl->mdls); 752 mcl->mdls = NULL; 753 } 754 755 static void mcap_mcl_shutdown(struct mcap_mcl *mcl) 756 { 757 close_mcl(mcl, TRUE); 758 } 759 760 static void mcap_mcl_release(struct mcap_mcl *mcl) 761 { 762 close_mcl(mcl, FALSE); 763 } 764 765 static void mcap_cache_mcl(struct mcap_mcl *mcl) 766 { 767 GSList *l; 768 struct mcap_mcl *last; 769 int len; 770 771 if (mcl->ctrl & MCAP_CTRL_CACHED) 772 return; 773 774 mcl->mi->mcls = g_slist_remove(mcl->mi->mcls, mcl); 775 776 if (mcl->ctrl & MCAP_CTRL_NOCACHE) { 777 mcl->mi->cached = g_slist_remove(mcl->mi->cached, mcl); 778 mcap_mcl_release(mcl); 779 mcap_mcl_unref(mcl); 780 return; 781 } 782 783 DBG("Caching MCL"); 784 785 len = g_slist_length(mcl->mi->cached); 786 if (len == MAX_CACHED) { 787 /* Remove the latest cached mcl */ 788 l = g_slist_last(mcl->mi->cached); 789 last = l->data; 790 mcl->mi->cached = g_slist_remove(mcl->mi->cached, last); 791 last->ctrl &= ~MCAP_CTRL_CACHED; 792 if (last->ctrl & MCAP_CTRL_CONN) { 793 /* We have to release this MCL if */ 794 /* connection is not succesful */ 795 last->ctrl |= MCAP_CTRL_FREE; 796 } else { 797 mcap_mcl_release(last); 798 last->mi->mcl_uncached_cb(last, last->mi->user_data); 799 } 800 mcap_mcl_unref(last); 801 } 802 803 mcl->mi->cached = g_slist_prepend(mcl->mi->cached, mcl); 804 mcl->ctrl |= MCAP_CTRL_CACHED; 805 mcap_mcl_shutdown(mcl); 806 } 807 808 static void mcap_uncache_mcl(struct mcap_mcl *mcl) 809 { 810 if (!(mcl->ctrl & MCAP_CTRL_CACHED)) 811 return; 812 813 DBG("Got MCL from cache"); 814 815 mcl->mi->cached = g_slist_remove(mcl->mi->cached, mcl); 816 mcl->mi->mcls = g_slist_prepend(mcl->mi->mcls, mcl); 817 mcl->ctrl &= ~MCAP_CTRL_CACHED; 818 mcl->ctrl &= ~MCAP_CTRL_FREE; 819 } 820 821 void mcap_close_mcl(struct mcap_mcl *mcl, gboolean cache) 822 { 823 if (!mcl) 824 return; 825 826 if (mcl->ctrl & MCAP_CTRL_FREE) { 827 mcap_mcl_release(mcl); 828 return; 829 } 830 831 if (!cache) 832 mcl->ctrl |= MCAP_CTRL_NOCACHE; 833 834 if (mcl->cc) { 835 g_io_channel_shutdown(mcl->cc, TRUE, NULL); 836 g_io_channel_unref(mcl->cc); 837 mcl->cc = NULL; 838 mcl->state = MCL_IDLE; 839 } else if ((mcl->ctrl & MCAP_CTRL_CACHED) && 840 (mcl->ctrl & MCAP_CTRL_NOCACHE)) { 841 mcl->ctrl &= ~MCAP_CTRL_CACHED; 842 mcl->mi->cached = g_slist_remove(mcl->mi->cached, mcl); 843 mcap_mcl_release(mcl); 844 mcap_mcl_unref(mcl); 845 } 846 } 847 848 struct mcap_mcl *mcap_mcl_ref(struct mcap_mcl *mcl) 849 { 850 mcl->ref++; 851 852 DBG("mcap_mcl_ref(%p): ref=%d", mcl, mcl->ref); 853 854 return mcl; 855 } 856 857 void mcap_mcl_unref(struct mcap_mcl *mcl) 858 { 859 mcl->ref--; 860 861 DBG("mcap_mcl_unref(%p): ref=%d", mcl, mcl->ref); 862 863 if (mcl->ref > 0) 864 return; 865 866 mcap_mcl_release(mcl); 867 mcap_instance_unref(mcl->mi); 868 g_free(mcl->cb); 869 g_free(mcl); 870 } 871 872 static gboolean parse_set_opts(struct mcap_mdl_cb *mdl_cb, GError **err, 873 McapMclCb cb1, va_list args) 874 { 875 McapMclCb cb = cb1; 876 struct mcap_mdl_cb *c; 877 878 c = g_new0(struct mcap_mdl_cb, 1); 879 880 while (cb != MCAP_MDL_CB_INVALID) { 881 switch (cb) { 882 case MCAP_MDL_CB_CONNECTED: 883 c->mdl_connected = va_arg(args, mcap_mdl_event_cb); 884 break; 885 case MCAP_MDL_CB_CLOSED: 886 c->mdl_closed = va_arg(args, mcap_mdl_event_cb); 887 break; 888 case MCAP_MDL_CB_DELETED: 889 c->mdl_deleted = va_arg(args, mcap_mdl_event_cb); 890 break; 891 case MCAP_MDL_CB_ABORTED: 892 c->mdl_aborted = va_arg(args, mcap_mdl_event_cb); 893 break; 894 case MCAP_MDL_CB_REMOTE_CONN_REQ: 895 c->mdl_conn_req = va_arg(args, 896 mcap_remote_mdl_conn_req_cb); 897 break; 898 case MCAP_MDL_CB_REMOTE_RECONN_REQ: 899 c->mdl_reconn_req = va_arg(args, 900 mcap_remote_mdl_reconn_req_cb); 901 break; 902 default: 903 g_set_error(err, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS, 904 "Unknown option %d", cb); 905 return FALSE; 906 } 907 cb = va_arg(args, int); 908 } 909 910 /* Set new callbacks */ 911 if (c->mdl_connected) 912 mdl_cb->mdl_connected = c->mdl_connected; 913 if (c->mdl_closed) 914 mdl_cb->mdl_closed = c->mdl_closed; 915 if (c->mdl_deleted) 916 mdl_cb->mdl_deleted = c->mdl_deleted; 917 if (c->mdl_aborted) 918 mdl_cb->mdl_aborted = c->mdl_aborted; 919 if (c->mdl_conn_req) 920 mdl_cb->mdl_conn_req = c->mdl_conn_req; 921 if (c->mdl_reconn_req) 922 mdl_cb->mdl_reconn_req = c->mdl_reconn_req; 923 924 g_free(c); 925 926 return TRUE; 927 } 928 929 gboolean mcap_mcl_set_cb(struct mcap_mcl *mcl, gpointer user_data, 930 GError **gerr, McapMclCb cb1, ...) 931 { 932 va_list args; 933 gboolean ret; 934 935 va_start(args, cb1); 936 ret = parse_set_opts(mcl->cb, gerr, cb1, args); 937 va_end(args); 938 939 if (!ret) 940 return FALSE; 941 942 mcl->cb->user_data = user_data; 943 return TRUE; 944 } 945 946 void mcap_mcl_get_addr(struct mcap_mcl *mcl, bdaddr_t *addr) 947 { 948 bacpy(addr, &mcl->addr); 949 } 950 951 static void mcap_del_mdl(gpointer elem, gpointer user_data) 952 { 953 struct mcap_mdl *mdl = elem; 954 gboolean notify = *(gboolean *) user_data; 955 956 shutdown_mdl(mdl); 957 if (notify) 958 mdl->mcl->cb->mdl_deleted(mdl, mdl->mcl->cb->user_data); 959 960 mcap_mdl_unref(mdl); 961 } 962 963 static gboolean check_cmd_req_length(struct mcap_mcl *mcl, void *cmd, 964 uint32_t rlen, uint32_t explen, uint8_t rspcod) 965 { 966 mcap_md_req *req; 967 uint16_t mdl_id; 968 969 if (rlen != explen) { 970 if (rlen >= sizeof(mcap_md_req)) { 971 req = cmd; 972 mdl_id = ntohs(req->mdl); 973 } else { 974 /* We can't get mdlid */ 975 mdl_id = MCAP_MDLID_RESERVED; 976 } 977 mcap_send_cmd(mcl, rspcod, MCAP_INVALID_PARAM_VALUE, mdl_id, 978 NULL, 0); 979 return FALSE; 980 } 981 return TRUE; 982 } 983 984 static void process_md_create_mdl_req(struct mcap_mcl *mcl, void *cmd, 985 uint32_t len) 986 { 987 mcap_md_create_mdl_req *req; 988 struct mcap_mdl *mdl; 989 uint16_t mdl_id; 990 uint8_t mdep_id; 991 uint8_t cfga, conf; 992 uint8_t rsp; 993 994 if (!check_cmd_req_length(mcl, cmd, len, sizeof(mcap_md_create_mdl_req), 995 MCAP_MD_CREATE_MDL_RSP)) 996 return; 997 998 req = cmd; 999 mdl_id = ntohs(req->mdl); 1000 if (mdl_id < MCAP_MDLID_INITIAL || mdl_id > MCAP_MDLID_FINAL) { 1001 mcap_send_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, MCAP_INVALID_MDL, 1002 mdl_id, NULL, 0); 1003 return; 1004 } 1005 1006 mdep_id = req->mdep; 1007 if (mdep_id > MCAP_MDEPID_FINAL) { 1008 mcap_send_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, MCAP_INVALID_MDEP, 1009 mdl_id, NULL, 0); 1010 return; 1011 } 1012 1013 mdl = get_mdl(mcl, mdl_id); 1014 if (mdl && (mdl->state == MDL_WAITING || mdl->state == MDL_DELETING )) { 1015 /* Creation request arrives for a MDL that is being managed 1016 * at current moment */ 1017 mcap_send_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, MCAP_MDL_BUSY, 1018 mdl_id, NULL, 0); 1019 return; 1020 } 1021 1022 cfga = conf = req->conf; 1023 /* Callback to upper layer */ 1024 rsp = mcl->cb->mdl_conn_req(mcl, mdep_id, mdl_id, &conf, 1025 mcl->cb->user_data); 1026 if (mcl->state == MCL_IDLE) { 1027 /* MCL has been closed int the callback */ 1028 return; 1029 } 1030 1031 if (cfga != 0 && cfga != conf) { 1032 /* Remote device set default configuration but upper profile */ 1033 /* has changed it. Protocol Error: force closing the MCL by */ 1034 /* remote device using UNSPECIFIED_ERROR response */ 1035 mcap_send_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, 1036 MCAP_UNSPECIFIED_ERROR, mdl_id, NULL, 0); 1037 return; 1038 } 1039 if (rsp != MCAP_SUCCESS) { 1040 mcap_send_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, rsp, mdl_id, 1041 NULL, 0); 1042 return; 1043 } 1044 1045 if (!mdl) { 1046 mdl = g_new0(struct mcap_mdl, 1); 1047 mdl->mcl = mcap_mcl_ref(mcl); 1048 mdl->mdlid = mdl_id; 1049 mcl->mdls = g_slist_insert_sorted(mcl->mdls, mcap_mdl_ref(mdl), 1050 compare_mdl); 1051 } else if (mdl->state == MDL_CONNECTED) { 1052 /* MCAP specification says that we should close the MCL if 1053 * it is open when we receive a MD_CREATE_MDL_REQ */ 1054 shutdown_mdl(mdl); 1055 } 1056 1057 mdl->mdep_id = mdep_id; 1058 mdl->state = MDL_WAITING; 1059 1060 mcl->state = MCL_PENDING; 1061 mcap_send_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, MCAP_SUCCESS, mdl_id, 1062 &conf, 1); 1063 } 1064 1065 static void process_md_reconnect_mdl_req(struct mcap_mcl *mcl, void *cmd, 1066 uint32_t len) 1067 { 1068 mcap_md_req *req; 1069 struct mcap_mdl *mdl; 1070 uint16_t mdl_id; 1071 uint8_t rsp; 1072 1073 if (!check_cmd_req_length(mcl, cmd, len, sizeof(mcap_md_req), 1074 MCAP_MD_RECONNECT_MDL_RSP)) 1075 return; 1076 1077 req = cmd; 1078 mdl_id = ntohs(req->mdl); 1079 1080 mdl = get_mdl(mcl, mdl_id); 1081 if (!mdl) { 1082 mcap_send_cmd(mcl, MCAP_MD_RECONNECT_MDL_RSP, MCAP_INVALID_MDL, 1083 mdl_id, NULL, 0); 1084 return; 1085 } else if (mdl->state == MDL_WAITING || mdl->state == MDL_DELETING ) { 1086 /* Creation request arrives for a MDL that is being managed 1087 * at current moment */ 1088 mcap_send_cmd(mcl, MCAP_MD_RECONNECT_MDL_RSP, MCAP_MDL_BUSY, 1089 mdl_id, NULL, 0); 1090 return; 1091 } 1092 1093 /* Callback to upper layer */ 1094 rsp = mcl->cb->mdl_reconn_req(mdl, mcl->cb->user_data); 1095 if (mcl->state == MCL_IDLE) 1096 return; 1097 1098 if (rsp != MCAP_SUCCESS) { 1099 mcap_send_cmd(mcl, MCAP_MD_RECONNECT_MDL_RSP, rsp, mdl_id, 1100 NULL, 0); 1101 return; 1102 } 1103 1104 if (mdl->state == MDL_CONNECTED) 1105 shutdown_mdl(mdl); 1106 1107 mdl->state = MDL_WAITING; 1108 mcl->state = MCL_PENDING; 1109 mcap_send_cmd(mcl, MCAP_MD_RECONNECT_MDL_RSP, MCAP_SUCCESS, mdl_id, 1110 NULL, 0); 1111 } 1112 1113 static void process_md_abort_mdl_req(struct mcap_mcl *mcl, void *cmd, 1114 uint32_t len) 1115 { 1116 mcap_md_req *req; 1117 GSList *l; 1118 struct mcap_mdl *mdl, *abrt; 1119 uint16_t mdl_id; 1120 1121 if (!check_cmd_req_length(mcl, cmd, len, sizeof(mcap_md_req), 1122 MCAP_MD_ABORT_MDL_RSP)) 1123 return; 1124 1125 req = cmd; 1126 mdl_id = ntohs(req->mdl); 1127 mcl->state = MCL_CONNECTED; 1128 abrt = NULL; 1129 for (l = mcl->mdls; l; l = l->next) { 1130 mdl = l->data; 1131 if (mdl_id == mdl->mdlid && mdl->state == MDL_WAITING) { 1132 abrt = mdl; 1133 if (mcl->state != MCL_CONNECTED) 1134 break; 1135 continue; 1136 } 1137 if (mdl->state == MDL_CONNECTED && mcl->state != MCL_ACTIVE) 1138 mcl->state = MCL_ACTIVE; 1139 1140 if (abrt && mcl->state == MCL_ACTIVE) 1141 break; 1142 } 1143 1144 if (!abrt) { 1145 mcap_send_cmd(mcl, MCAP_MD_ABORT_MDL_RSP, MCAP_INVALID_MDL, 1146 mdl_id, NULL, 0); 1147 return; 1148 } 1149 1150 mcl->cb->mdl_aborted(abrt, mcl->cb->user_data); 1151 abrt->state = MDL_CLOSED; 1152 mcap_send_cmd(mcl, MCAP_MD_ABORT_MDL_RSP, MCAP_SUCCESS, mdl_id, 1153 NULL, 0); 1154 } 1155 1156 static void process_md_delete_mdl_req(struct mcap_mcl *mcl, void *cmd, 1157 uint32_t len) 1158 { 1159 mcap_md_req *req; 1160 struct mcap_mdl *mdl, *aux; 1161 uint16_t mdlid; 1162 gboolean notify; 1163 GSList *l; 1164 1165 if (!check_cmd_req_length(mcl, cmd, len, sizeof(mcap_md_req), 1166 MCAP_MD_DELETE_MDL_RSP)) 1167 return; 1168 1169 req = cmd; 1170 mdlid = ntohs(req->mdl); 1171 if (mdlid == MCAP_ALL_MDLIDS) { 1172 notify = FALSE; 1173 g_slist_foreach(mcl->mdls, mcap_del_mdl, ¬ify); 1174 g_slist_free(mcl->mdls); 1175 mcl->mdls = NULL; 1176 mcl->state = MCL_CONNECTED; 1177 /* NULL mdl means ALL_MDLS */ 1178 mcl->cb->mdl_deleted(NULL, mcl->cb->user_data); 1179 goto resp; 1180 } 1181 1182 if (mdlid < MCAP_MDLID_INITIAL || mdlid > MCAP_MDLID_FINAL) { 1183 mcap_send_cmd(mcl, MCAP_MD_DELETE_MDL_RSP, MCAP_INVALID_MDL, 1184 mdlid, NULL, 0); 1185 return; 1186 } 1187 1188 for (l = mcl->mdls, mdl = NULL; l; l = l->next) { 1189 aux = l->data; 1190 if (aux->mdlid == mdlid) { 1191 mdl = aux; 1192 break; 1193 } 1194 } 1195 1196 if (!mdl || mdl->state == MDL_WAITING) { 1197 mcap_send_cmd(mcl, MCAP_MD_DELETE_MDL_RSP, MCAP_INVALID_MDL, 1198 mdlid, NULL, 0); 1199 return; 1200 } 1201 1202 mcl->mdls = g_slist_remove(mcl->mdls, mdl); 1203 update_mcl_state(mcl); 1204 notify = TRUE; 1205 mcap_del_mdl(mdl, ¬ify); 1206 1207 resp: 1208 mcap_send_cmd(mcl, MCAP_MD_DELETE_MDL_RSP, MCAP_SUCCESS, mdlid, 1209 NULL, 0); 1210 } 1211 1212 static void invalid_req_state(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len) 1213 { 1214 uint16_t mdlr; 1215 1216 error("Invalid cmd received (op code = %d) in state %d", cmd[0], 1217 mcl->state); 1218 /* Get previously mdlid sent to generate an appropriate 1219 * response if it is possible */ 1220 mdlr = len < sizeof(mcap_md_req) ? MCAP_MDLID_RESERVED : 1221 ntohs(((mcap_md_req *) cmd)->mdl); 1222 mcap_send_cmd(mcl, cmd[0]+1, MCAP_INVALID_OPERATION, mdlr, NULL, 0); 1223 } 1224 1225 /* Function used to process commands depending of MCL state */ 1226 static void proc_req_connected(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len) 1227 { 1228 switch (cmd[0]) { 1229 case MCAP_MD_CREATE_MDL_REQ: 1230 process_md_create_mdl_req(mcl, cmd, len); 1231 break; 1232 case MCAP_MD_RECONNECT_MDL_REQ: 1233 process_md_reconnect_mdl_req(mcl, cmd, len); 1234 break; 1235 case MCAP_MD_DELETE_MDL_REQ: 1236 process_md_delete_mdl_req(mcl, cmd, len); 1237 break; 1238 default: 1239 invalid_req_state(mcl, cmd, len); 1240 } 1241 } 1242 1243 static void proc_req_pending(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len) 1244 { 1245 if (cmd[0] == MCAP_MD_ABORT_MDL_REQ) 1246 process_md_abort_mdl_req(mcl, cmd, len); 1247 else 1248 invalid_req_state(mcl, cmd, len); 1249 } 1250 1251 static void proc_req_active(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len) 1252 { 1253 switch (cmd[0]) { 1254 case MCAP_MD_CREATE_MDL_REQ: 1255 process_md_create_mdl_req(mcl, cmd, len); 1256 break; 1257 case MCAP_MD_RECONNECT_MDL_REQ: 1258 process_md_reconnect_mdl_req(mcl, cmd, len); 1259 break; 1260 case MCAP_MD_DELETE_MDL_REQ: 1261 process_md_delete_mdl_req(mcl, cmd, len); 1262 break; 1263 default: 1264 invalid_req_state(mcl, cmd, len); 1265 } 1266 } 1267 1268 /* Function used to process replies */ 1269 static gboolean check_err_rsp(struct mcap_mcl *mcl, mcap_rsp *rsp, 1270 uint32_t rlen, uint32_t len, GError **gerr) 1271 { 1272 mcap_md_req *cmdlast = (mcap_md_req *) mcl->lcmd; 1273 gint err = MCAP_ERROR_FAILED; 1274 gboolean close = FALSE; 1275 char *msg; 1276 1277 if (rsp->op == MCAP_ERROR_RSP) { 1278 msg = "MCAP_ERROR_RSP received"; 1279 close = FALSE; 1280 goto fail; 1281 } 1282 1283 /* Check if the response matches with the last request */ 1284 if (rlen < sizeof(mcap_rsp) || (mcl->lcmd[0] + 1) != rsp->op) { 1285 msg = "Protocol error"; 1286 close = FALSE; 1287 goto fail; 1288 } 1289 1290 if (rlen < len) { 1291 msg = "Protocol error"; 1292 close = FALSE; 1293 goto fail; 1294 } 1295 1296 if (rsp->mdl != cmdlast->mdl) { 1297 msg = "MDLID received doesn't match with MDLID sent"; 1298 close = TRUE; 1299 goto fail; 1300 } 1301 1302 if (rsp->rc == MCAP_REQUEST_NOT_SUPPORTED) { 1303 msg = "Remote does not support opcodes"; 1304 mcl->ctrl &= ~MCAP_CTRL_STD_OP; 1305 goto fail; 1306 } 1307 1308 if (rsp->rc == MCAP_UNSPECIFIED_ERROR) { 1309 msg = "Unspecified error"; 1310 close = TRUE; 1311 goto fail; 1312 } 1313 1314 if (rsp->rc != MCAP_SUCCESS) { 1315 msg = error2str(rsp->rc); 1316 err = rsp->rc; 1317 goto fail; 1318 } 1319 1320 return FALSE; 1321 1322 fail: 1323 g_set_error(gerr, MCAP_ERROR, err, "%s", msg); 1324 return close; 1325 } 1326 1327 static gboolean process_md_create_mdl_rsp(struct mcap_mcl *mcl, 1328 mcap_rsp *rsp, uint32_t len) 1329 { 1330 mcap_md_create_mdl_req *cmdlast = (mcap_md_create_mdl_req *) mcl->lcmd; 1331 struct mcap_mdl_op_cb *conn = mcl->priv_data; 1332 mcap_mdl_operation_conf_cb connect_cb = conn->cb.op_conf; 1333 gpointer user_data = conn->user_data; 1334 struct mcap_mdl *mdl = conn->mdl; 1335 uint8_t conf = cmdlast->conf; 1336 gboolean close; 1337 GError *gerr = NULL; 1338 1339 close = check_err_rsp(mcl, rsp, len, sizeof(mcap_rsp) + 1, &gerr); 1340 g_free(mcl->lcmd); 1341 mcl->lcmd = NULL; 1342 mcl->req = MCL_AVAILABLE; 1343 1344 if (gerr) 1345 goto fail; 1346 1347 /* Check if preferences changed */ 1348 if (conf != 0x00 && rsp->data[0] != conf) { 1349 g_set_error(&gerr, MCAP_ERROR, MCAP_ERROR_FAILED, 1350 "Configuration changed"); 1351 close = TRUE; 1352 goto fail; 1353 } 1354 1355 connect_cb(mdl, rsp->data[0], gerr, user_data); 1356 return close; 1357 1358 fail: 1359 connect_cb(NULL, 0, gerr, user_data); 1360 mcl->mdls = g_slist_remove(mcl->mdls, mdl); 1361 mcap_mdl_unref(mdl); 1362 g_error_free(gerr); 1363 update_mcl_state(mcl); 1364 return close; 1365 } 1366 1367 static gboolean process_md_reconnect_mdl_rsp(struct mcap_mcl *mcl, 1368 mcap_rsp *rsp, uint32_t len) 1369 { 1370 struct mcap_mdl_op_cb *reconn = mcl->priv_data; 1371 mcap_mdl_operation_cb reconn_cb = reconn->cb.op; 1372 gpointer user_data = reconn->user_data; 1373 struct mcap_mdl *mdl = reconn->mdl; 1374 GError *gerr = NULL; 1375 gboolean close; 1376 1377 close = check_err_rsp(mcl, rsp, len, sizeof(mcap_rsp), &gerr); 1378 1379 g_free(mcl->lcmd); 1380 mcl->lcmd = NULL; 1381 mcl->req = MCL_AVAILABLE; 1382 1383 reconn_cb(mdl, gerr, user_data); 1384 if (!gerr) 1385 return close; 1386 1387 g_error_free(gerr); 1388 shutdown_mdl(mdl); 1389 update_mcl_state(mcl); 1390 1391 if (rsp->rc != MCAP_INVALID_MDL) 1392 return close; 1393 1394 /* Remove cached mdlid */ 1395 mcl->mdls = g_slist_remove(mcl->mdls, mdl); 1396 mcl->cb->mdl_deleted(mdl, mcl->cb->user_data); 1397 mcap_mdl_unref(mdl); 1398 1399 return close; 1400 } 1401 1402 static gboolean process_md_abort_mdl_rsp(struct mcap_mcl *mcl, 1403 mcap_rsp *rsp, uint32_t len) 1404 { 1405 struct mcap_mdl_op_cb *abrt = mcl->priv_data; 1406 mcap_mdl_notify_cb abrt_cb = abrt->cb.notify; 1407 gpointer user_data = abrt->user_data; 1408 struct mcap_mdl *mdl = abrt->mdl; 1409 GError *gerr = NULL; 1410 gboolean close; 1411 1412 close = check_err_rsp(mcl, rsp, len, sizeof(mcap_rsp), &gerr); 1413 1414 g_free(mcl->lcmd); 1415 mcl->lcmd = NULL; 1416 mcl->req = MCL_AVAILABLE; 1417 1418 abrt_cb(gerr, user_data); 1419 shutdown_mdl(mdl); 1420 1421 if (len >= sizeof(mcap_rsp) && rsp->rc == MCAP_INVALID_MDL) { 1422 mcl->mdls = g_slist_remove(mcl->mdls, mdl); 1423 mcl->cb->mdl_deleted(mdl, mcl->cb->user_data); 1424 mcap_mdl_unref(mdl); 1425 } 1426 1427 if (gerr) 1428 g_error_free(gerr); 1429 1430 update_mcl_state(mcl); 1431 1432 return close; 1433 } 1434 1435 static void restore_mdl(gpointer elem, gpointer data) 1436 { 1437 struct mcap_mdl *mdl = elem; 1438 1439 if (mdl->state == MDL_DELETING) { 1440 if (mdl->dc) 1441 mdl->state = MDL_CONNECTED; 1442 else 1443 mdl->state = MDL_CLOSED; 1444 } else if (mdl->state == MDL_CLOSED) 1445 mdl->mcl->cb->mdl_closed(mdl, mdl->mcl->cb->user_data); 1446 } 1447 1448 static void check_mdl_del_err(struct mcap_mdl *mdl, mcap_rsp *rsp) 1449 { 1450 if (rsp->rc != MCAP_ERROR_INVALID_MDL) { 1451 restore_mdl(mdl, NULL); 1452 return; 1453 } 1454 1455 /* MDL does not exist in remote side, we can delete it */ 1456 mdl->mcl->mdls = g_slist_remove(mdl->mcl->mdls, mdl); 1457 mcap_mdl_unref(mdl); 1458 } 1459 1460 static gboolean process_md_delete_mdl_rsp(struct mcap_mcl *mcl, mcap_rsp *rsp, 1461 uint32_t len) 1462 { 1463 struct mcap_mdl_op_cb *del = mcl->priv_data; 1464 struct mcap_mdl *mdl = del->mdl; 1465 mcap_mdl_notify_cb deleted_cb = del->cb.notify; 1466 gpointer user_data = del->user_data; 1467 mcap_md_req *cmdlast = (mcap_md_req *) mcl->lcmd; 1468 uint16_t mdlid = ntohs(cmdlast->mdl); 1469 GError *gerr = NULL; 1470 gboolean close; 1471 gboolean notify = FALSE; 1472 1473 close = check_err_rsp(mcl, rsp, len, sizeof(mcap_rsp), &gerr); 1474 1475 g_free(mcl->lcmd); 1476 mcl->lcmd = NULL; 1477 mcl->req = MCL_AVAILABLE; 1478 1479 if (gerr) { 1480 if (mdl) 1481 check_mdl_del_err(mdl, rsp); 1482 else 1483 g_slist_foreach(mcl->mdls, restore_mdl, NULL); 1484 deleted_cb(gerr, user_data); 1485 g_error_free(gerr); 1486 return close; 1487 } 1488 1489 if (mdlid == MCAP_ALL_MDLIDS) { 1490 g_slist_foreach(mcl->mdls, mcap_del_mdl, ¬ify); 1491 g_slist_free(mcl->mdls); 1492 mcl->mdls = NULL; 1493 mcl->state = MCL_CONNECTED; 1494 } else { 1495 mcl->mdls = g_slist_remove(mcl->mdls, mdl); 1496 update_mcl_state(mcl); 1497 mcap_del_mdl(mdl, ¬ify); 1498 } 1499 1500 deleted_cb(gerr, user_data); 1501 1502 return close; 1503 } 1504 1505 static void post_process_rsp(struct mcap_mcl *mcl, struct mcap_mdl_op_cb *op) 1506 { 1507 if (mcl->priv_data != op) { 1508 /* Queued MCAP request in some callback. */ 1509 /* We should not delete the mcl private data */ 1510 free_mcap_mdl_op(op); 1511 } else { 1512 /* This is not a queued request. It's safe */ 1513 /* delete the mcl private data here. */ 1514 free_mcl_priv_data(mcl); 1515 } 1516 } 1517 1518 static void proc_response(struct mcap_mcl *mcl, void *buf, uint32_t len) 1519 { 1520 struct mcap_mdl_op_cb *op = mcl->priv_data; 1521 mcap_rsp *rsp = buf; 1522 gboolean close; 1523 1524 RELEASE_TIMER(mcl); 1525 1526 switch (mcl->lcmd[0] + 1) { 1527 case MCAP_MD_CREATE_MDL_RSP: 1528 close = process_md_create_mdl_rsp(mcl, rsp, len); 1529 post_process_rsp(mcl, op); 1530 break; 1531 case MCAP_MD_RECONNECT_MDL_RSP: 1532 close = process_md_reconnect_mdl_rsp(mcl, rsp, len); 1533 post_process_rsp(mcl, op); 1534 break; 1535 case MCAP_MD_ABORT_MDL_RSP: 1536 close = process_md_abort_mdl_rsp(mcl, rsp, len); 1537 post_process_rsp(mcl, op); 1538 break; 1539 case MCAP_MD_DELETE_MDL_RSP: 1540 close = process_md_delete_mdl_rsp(mcl, rsp, len); 1541 post_process_rsp(mcl, op); 1542 break; 1543 default: 1544 DBG("Unknown cmd response received (op code = %d)", rsp->op); 1545 close = TRUE; 1546 break; 1547 } 1548 1549 if (close) { 1550 mcl->mi->mcl_disconnected_cb(mcl, mcl->mi->user_data); 1551 mcap_cache_mcl(mcl); 1552 } 1553 } 1554 1555 static void proc_cmd(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len) 1556 { 1557 GError *gerr = NULL; 1558 1559 if (cmd[0] > MCAP_MD_SYNC_INFO_IND || 1560 (cmd[0] > MCAP_MD_DELETE_MDL_RSP && 1561 cmd[0] < MCAP_MD_SYNC_CAP_REQ)) { 1562 error("Unknown cmd received (op code = %d)", cmd[0]); 1563 mcap_send_cmd(mcl, MCAP_ERROR_RSP, MCAP_INVALID_OP_CODE, 1564 MCAP_MDLID_RESERVED, NULL, 0); 1565 return; 1566 } 1567 1568 if (cmd[0] >= MCAP_MD_SYNC_CAP_REQ && 1569 cmd[0] <= MCAP_MD_SYNC_INFO_IND) { 1570 proc_sync_cmd(mcl, cmd, len); 1571 return; 1572 } 1573 1574 if (!(mcl->ctrl & MCAP_CTRL_STD_OP)) { 1575 /* In case the remote device doesn't work correctly */ 1576 error("Remote device does not support opcodes, cmd ignored"); 1577 return; 1578 } 1579 1580 if (mcl->req == MCL_WAITING_RSP) { 1581 if (cmd[0] & 0x01) { 1582 /* Request arrived when a response is expected */ 1583 if (mcl->role == MCL_INITIATOR) 1584 /* ignore */ 1585 return; 1586 /* Initiator will ignore our last request */ 1587 RELEASE_TIMER(mcl); 1588 mcl->req = MCL_AVAILABLE; 1589 g_set_error(&gerr, MCAP_ERROR, MCAP_ERROR_REQ_IGNORED, 1590 "Initiator sent a request with more priority"); 1591 mcap_notify_error(mcl, gerr); 1592 proc_req[mcl->state](mcl, cmd, len); 1593 return; 1594 } 1595 proc_response(mcl, cmd, len); 1596 } else if (cmd[0] & 0x01) 1597 proc_req[mcl->state](mcl, cmd, len); 1598 } 1599 1600 static gboolean mdl_event_cb(GIOChannel *chan, GIOCondition cond, gpointer data) 1601 { 1602 1603 struct mcap_mdl *mdl = data; 1604 gboolean notify; 1605 1606 DBG("Close MDL %d", mdl->mdlid); 1607 1608 notify = (mdl->state == MDL_CONNECTED); 1609 shutdown_mdl(mdl); 1610 1611 update_mcl_state(mdl->mcl); 1612 1613 if (notify) { 1614 /*Callback to upper layer */ 1615 mdl->mcl->cb->mdl_closed(mdl, mdl->mcl->cb->user_data); 1616 } 1617 1618 return FALSE; 1619 } 1620 1621 static void mcap_connect_mdl_cb(GIOChannel *chan, GError *conn_err, 1622 gpointer data) 1623 { 1624 struct mcap_mdl_op_cb *con = data; 1625 struct mcap_mdl *mdl = con->mdl; 1626 mcap_mdl_operation_cb cb = con->cb.op; 1627 gpointer user_data = con->user_data; 1628 1629 DBG("mdl connect callback"); 1630 1631 if (conn_err) { 1632 DBG("ERROR: mdl connect callback"); 1633 mdl->state = MDL_CLOSED; 1634 g_io_channel_unref(mdl->dc); 1635 mdl->dc = NULL; 1636 cb(mdl, conn_err, user_data); 1637 return; 1638 } 1639 1640 mdl->state = MDL_CONNECTED; 1641 mdl->wid = g_io_add_watch_full(mdl->dc, G_PRIORITY_DEFAULT, 1642 G_IO_ERR | G_IO_HUP | G_IO_NVAL, 1643 (GIOFunc) mdl_event_cb, 1644 mcap_mdl_ref(mdl), 1645 (GDestroyNotify) mcap_mdl_unref); 1646 1647 cb(mdl, conn_err, user_data); 1648 } 1649 1650 gboolean mcap_connect_mdl(struct mcap_mdl *mdl, uint8_t mode, 1651 uint16_t dcpsm, 1652 mcap_mdl_operation_cb connect_cb, 1653 gpointer user_data, 1654 GDestroyNotify destroy, 1655 GError **err) 1656 { 1657 struct mcap_mdl_op_cb *con; 1658 1659 if (mdl->state != MDL_WAITING) { 1660 g_set_error(err, MCAP_ERROR, MCAP_ERROR_INVALID_MDL, 1661 "%s", error2str(MCAP_INVALID_MDL)); 1662 return FALSE; 1663 } 1664 1665 if ((mode != L2CAP_MODE_ERTM) && (mode != L2CAP_MODE_STREAMING)) { 1666 g_set_error(err, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS, 1667 "Invalid MDL configuration"); 1668 return FALSE; 1669 } 1670 1671 con = g_new0(struct mcap_mdl_op_cb, 1); 1672 con->mdl = mcap_mdl_ref(mdl); 1673 con->cb.op = connect_cb; 1674 con->destroy = destroy; 1675 con->user_data = user_data; 1676 1677 mdl->dc = bt_io_connect(BT_IO_L2CAP, mcap_connect_mdl_cb, con, 1678 (GDestroyNotify) free_mcap_mdl_op, err, 1679 BT_IO_OPT_SOURCE_BDADDR, &mdl->mcl->mi->src, 1680 BT_IO_OPT_DEST_BDADDR, &mdl->mcl->addr, 1681 BT_IO_OPT_PSM, dcpsm, 1682 BT_IO_OPT_MTU, MCAP_DC_MTU, 1683 BT_IO_OPT_SEC_LEVEL, mdl->mcl->mi->sec, 1684 BT_IO_OPT_MODE, mode, 1685 BT_IO_OPT_INVALID); 1686 if (!mdl->dc) { 1687 DBG("MDL Connection error"); 1688 mdl->state = MDL_CLOSED; 1689 mcap_mdl_unref(con->mdl); 1690 g_free(con); 1691 return FALSE; 1692 } 1693 1694 return TRUE; 1695 } 1696 1697 static gboolean mcl_control_cb(GIOChannel *chan, GIOCondition cond, 1698 gpointer data) 1699 { 1700 GError *gerr = NULL; 1701 struct mcap_mcl *mcl = data; 1702 int sk, len; 1703 uint8_t buf[MCAP_CC_MTU]; 1704 1705 if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) 1706 goto fail; 1707 1708 sk = g_io_channel_unix_get_fd(chan); 1709 len = read(sk, buf, sizeof(buf)); 1710 if (len < 0) 1711 goto fail; 1712 1713 proc_cmd(mcl, buf, (uint32_t) len); 1714 return TRUE; 1715 1716 fail: 1717 if (mcl->state != MCL_IDLE) { 1718 if (mcl->req == MCL_WAITING_RSP) { 1719 /* notify error in pending callback */ 1720 g_set_error(&gerr, MCAP_ERROR, MCAP_ERROR_MCL_CLOSED, 1721 "MCL closed"); 1722 mcap_notify_error(mcl, gerr); 1723 g_error_free(gerr); 1724 } 1725 mcl->mi->mcl_disconnected_cb(mcl, mcl->mi->user_data); 1726 } 1727 mcap_cache_mcl(mcl); 1728 return FALSE; 1729 } 1730 1731 static void mcap_connect_mcl_cb(GIOChannel *chan, GError *conn_err, 1732 gpointer user_data) 1733 { 1734 char dstaddr[18]; 1735 struct connect_mcl *con = user_data; 1736 struct mcap_mcl *aux, *mcl = con->mcl; 1737 mcap_mcl_connect_cb connect_cb = con->connect_cb; 1738 gpointer data = con->user_data; 1739 GError *gerr = NULL; 1740 1741 mcl->ctrl &= ~MCAP_CTRL_CONN; 1742 1743 if (conn_err) { 1744 if (mcl->ctrl & MCAP_CTRL_FREE) { 1745 mcap_mcl_release(mcl); 1746 mcl->mi->mcl_uncached_cb(mcl, mcl->mi->user_data); 1747 } 1748 connect_cb(NULL, conn_err, data); 1749 return; 1750 } 1751 1752 ba2str(&mcl->addr, dstaddr); 1753 1754 aux = find_mcl(mcl->mi->mcls, &mcl->addr); 1755 if (aux) { 1756 /* Double MCL connection case */ 1757 error("MCL error: Device %s is already connected", dstaddr); 1758 g_set_error(&gerr, MCAP_ERROR, MCAP_ERROR_ALREADY_EXISTS, 1759 "MCL %s is already connected", dstaddr); 1760 connect_cb(NULL, gerr, data); 1761 g_error_free(gerr); 1762 return; 1763 } 1764 1765 mcl->state = MCL_CONNECTED; 1766 mcl->role = MCL_INITIATOR; 1767 mcl->req = MCL_AVAILABLE; 1768 mcl->ctrl |= MCAP_CTRL_STD_OP; 1769 1770 mcap_sync_init(mcl); 1771 1772 if (mcl->ctrl & MCAP_CTRL_CACHED) 1773 mcap_uncache_mcl(mcl); 1774 else { 1775 mcl->ctrl &= ~MCAP_CTRL_FREE; 1776 mcl->mi->mcls = g_slist_prepend(mcl->mi->mcls, 1777 mcap_mcl_ref(mcl)); 1778 } 1779 1780 mcl->wid = g_io_add_watch_full(mcl->cc, G_PRIORITY_DEFAULT, 1781 G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, 1782 (GIOFunc) mcl_control_cb, 1783 mcap_mcl_ref(mcl), 1784 (GDestroyNotify) mcap_mcl_unref); 1785 connect_cb(mcl, gerr, data); 1786 } 1787 1788 static void set_mdl_properties(GIOChannel *chan, struct mcap_mdl *mdl) 1789 { 1790 struct mcap_mcl *mcl = mdl->mcl; 1791 1792 mdl->state = MDL_CONNECTED; 1793 mdl->dc = g_io_channel_ref(chan); 1794 mdl->wid = g_io_add_watch_full(mdl->dc, G_PRIORITY_DEFAULT, 1795 G_IO_ERR | G_IO_HUP | G_IO_NVAL, 1796 (GIOFunc) mdl_event_cb, 1797 mcap_mdl_ref(mdl), 1798 (GDestroyNotify) mcap_mdl_unref); 1799 1800 mcl->state = MCL_ACTIVE; 1801 mcl->cb->mdl_connected(mdl, mcl->cb->user_data); 1802 } 1803 1804 static void mcl_io_destroy(gpointer data) 1805 { 1806 struct connect_mcl *con = data; 1807 1808 mcap_mcl_unref(con->mcl); 1809 if (con->destroy) 1810 con->destroy(con->user_data); 1811 g_free(con); 1812 } 1813 1814 gboolean mcap_create_mcl(struct mcap_instance *mi, 1815 const bdaddr_t *addr, 1816 uint16_t ccpsm, 1817 mcap_mcl_connect_cb connect_cb, 1818 gpointer user_data, 1819 GDestroyNotify destroy, 1820 GError **err) 1821 { 1822 struct mcap_mcl *mcl; 1823 struct connect_mcl *con; 1824 1825 mcl = find_mcl(mi->mcls, addr); 1826 if (mcl) { 1827 g_set_error(err, MCAP_ERROR, MCAP_ERROR_ALREADY_EXISTS, 1828 "MCL is already connected."); 1829 return FALSE; 1830 } 1831 1832 mcl = find_mcl(mi->cached, addr); 1833 if (!mcl) { 1834 mcl = g_new0(struct mcap_mcl, 1); 1835 mcl->mi = mcap_instance_ref(mi); 1836 mcl->state = MCL_IDLE; 1837 bacpy(&mcl->addr, addr); 1838 set_default_cb(mcl); 1839 mcl->next_mdl = (rand() % MCAP_MDLID_FINAL) + 1; 1840 } 1841 1842 mcl->ctrl |= MCAP_CTRL_CONN; 1843 1844 con = g_new0(struct connect_mcl, 1); 1845 con->mcl = mcap_mcl_ref(mcl); 1846 con->connect_cb = connect_cb; 1847 con->destroy = destroy; 1848 con->user_data = user_data; 1849 1850 mcl->cc = bt_io_connect(BT_IO_L2CAP, mcap_connect_mcl_cb, con, 1851 mcl_io_destroy, err, 1852 BT_IO_OPT_SOURCE_BDADDR, &mi->src, 1853 BT_IO_OPT_DEST_BDADDR, addr, 1854 BT_IO_OPT_PSM, ccpsm, 1855 BT_IO_OPT_MTU, MCAP_CC_MTU, 1856 BT_IO_OPT_SEC_LEVEL, mi->sec, 1857 BT_IO_OPT_MODE, L2CAP_MODE_ERTM, 1858 BT_IO_OPT_INVALID); 1859 if (!mcl->cc) { 1860 mcl->ctrl &= ~MCAP_CTRL_CONN; 1861 if (mcl->ctrl & MCAP_CTRL_FREE) { 1862 mcap_mcl_release(mcl); 1863 mcl->mi->mcl_uncached_cb(mcl, mcl->mi->user_data); 1864 } 1865 mcap_mcl_unref(con->mcl); 1866 g_free(con); 1867 return FALSE; 1868 } 1869 1870 return TRUE; 1871 } 1872 1873 static void connect_dc_event_cb(GIOChannel *chan, GError *gerr, 1874 gpointer user_data) 1875 { 1876 struct mcap_instance *mi = user_data; 1877 struct mcap_mcl *mcl; 1878 struct mcap_mdl *mdl; 1879 GError *err = NULL; 1880 bdaddr_t dst; 1881 GSList *l; 1882 1883 if (gerr) 1884 return; 1885 1886 bt_io_get(chan, BT_IO_L2CAP, &err, 1887 BT_IO_OPT_DEST_BDADDR, &dst, 1888 BT_IO_OPT_INVALID); 1889 if (err) { 1890 error("%s", err->message); 1891 g_error_free(err); 1892 goto drop; 1893 } 1894 1895 mcl = find_mcl(mi->mcls, &dst); 1896 if (!mcl || mcl->state != MCL_PENDING) 1897 goto drop; 1898 1899 for (l = mcl->mdls; l; l = l->next) { 1900 mdl = l->data; 1901 if (mdl->state == MDL_WAITING) { 1902 set_mdl_properties(chan, mdl); 1903 return; 1904 } 1905 } 1906 1907 drop: 1908 g_io_channel_shutdown(chan, TRUE, NULL); 1909 } 1910 1911 static void set_mcl_conf(GIOChannel *chan, struct mcap_mcl *mcl) 1912 { 1913 gboolean reconn; 1914 1915 mcl->state = MCL_CONNECTED; 1916 mcl->role = MCL_ACCEPTOR; 1917 mcl->req = MCL_AVAILABLE; 1918 mcl->cc = g_io_channel_ref(chan); 1919 mcl->ctrl |= MCAP_CTRL_STD_OP; 1920 1921 mcap_sync_init(mcl); 1922 1923 reconn = (mcl->ctrl & MCAP_CTRL_CACHED); 1924 if (reconn) 1925 mcap_uncache_mcl(mcl); 1926 else 1927 mcl->mi->mcls = g_slist_prepend(mcl->mi->mcls, 1928 mcap_mcl_ref(mcl)); 1929 1930 mcl->wid = g_io_add_watch_full(mcl->cc, G_PRIORITY_DEFAULT, 1931 G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, 1932 (GIOFunc) mcl_control_cb, 1933 mcap_mcl_ref(mcl), 1934 (GDestroyNotify) mcap_mcl_unref); 1935 1936 /* Callback to report new MCL */ 1937 if (reconn) 1938 mcl->mi->mcl_reconnected_cb(mcl, mcl->mi->user_data); 1939 else 1940 mcl->mi->mcl_connected_cb(mcl, mcl->mi->user_data); 1941 } 1942 1943 static void connect_mcl_event_cb(GIOChannel *chan, GError *gerr, 1944 gpointer user_data) 1945 { 1946 struct mcap_instance *mi = user_data; 1947 struct mcap_mcl *mcl; 1948 bdaddr_t dst; 1949 char address[18], srcstr[18]; 1950 GError *err = NULL; 1951 1952 if (gerr) 1953 return; 1954 1955 bt_io_get(chan, BT_IO_L2CAP, &err, 1956 BT_IO_OPT_DEST_BDADDR, &dst, 1957 BT_IO_OPT_DEST, address, 1958 BT_IO_OPT_INVALID); 1959 if (err) { 1960 error("%s", err->message); 1961 g_error_free(err); 1962 goto drop; 1963 } 1964 1965 ba2str(&mi->src, srcstr); 1966 mcl = find_mcl(mi->mcls, &dst); 1967 if (mcl) { 1968 error("Control channel already created with %s on adapter %s", 1969 address, srcstr); 1970 goto drop; 1971 } 1972 1973 mcl = find_mcl(mi->cached, &dst); 1974 if (!mcl) { 1975 mcl = g_new0(struct mcap_mcl, 1); 1976 mcl->mi = mcap_instance_ref(mi); 1977 bacpy(&mcl->addr, &dst); 1978 set_default_cb(mcl); 1979 mcl->next_mdl = (rand() % MCAP_MDLID_FINAL) + 1; 1980 } 1981 1982 set_mcl_conf(chan, mcl); 1983 1984 return; 1985 drop: 1986 g_io_channel_shutdown(chan, TRUE, NULL); 1987 } 1988 1989 struct mcap_instance *mcap_create_instance(bdaddr_t *src, 1990 BtIOSecLevel sec, 1991 uint16_t ccpsm, 1992 uint16_t dcpsm, 1993 mcap_mcl_event_cb mcl_connected, 1994 mcap_mcl_event_cb mcl_reconnected, 1995 mcap_mcl_event_cb mcl_disconnected, 1996 mcap_mcl_event_cb mcl_uncached, 1997 mcap_info_ind_event_cb mcl_sync_info_ind, 1998 gpointer user_data, 1999 GError **gerr) 2000 { 2001 struct mcap_instance *mi; 2002 2003 if (sec < BT_IO_SEC_MEDIUM) { 2004 g_set_error(gerr, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS, 2005 "Security level can't be minor of %d", 2006 BT_IO_SEC_MEDIUM); 2007 return NULL; 2008 } 2009 2010 if (!(mcl_connected && mcl_reconnected && 2011 mcl_disconnected && mcl_uncached)) { 2012 g_set_error(gerr, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS, 2013 "The callbacks can't be null"); 2014 return NULL; 2015 } 2016 2017 mi = g_new0(struct mcap_instance, 1); 2018 2019 bacpy(&mi->src, src); 2020 2021 mi->sec = sec; 2022 mi->mcl_connected_cb = mcl_connected; 2023 mi->mcl_reconnected_cb = mcl_reconnected; 2024 mi->mcl_disconnected_cb = mcl_disconnected; 2025 mi->mcl_uncached_cb = mcl_uncached; 2026 mi->mcl_sync_infoind_cb = mcl_sync_info_ind; 2027 mi->user_data = user_data; 2028 mi->csp_enabled = FALSE; 2029 2030 /* Listen incoming connections in control channel */ 2031 mi->ccio = bt_io_listen(BT_IO_L2CAP, connect_mcl_event_cb, NULL, mi, 2032 NULL, gerr, 2033 BT_IO_OPT_SOURCE_BDADDR, &mi->src, 2034 BT_IO_OPT_PSM, ccpsm, 2035 BT_IO_OPT_MTU, MCAP_CC_MTU, 2036 BT_IO_OPT_SEC_LEVEL, sec, 2037 BT_IO_OPT_MODE, L2CAP_MODE_ERTM, 2038 BT_IO_OPT_INVALID); 2039 if (!mi->ccio) { 2040 error("%s", (*gerr)->message); 2041 g_free(mi); 2042 return NULL; 2043 } 2044 2045 /* Listen incoming connections in data channels */ 2046 mi->dcio = bt_io_listen(BT_IO_L2CAP, connect_dc_event_cb, NULL, mi, 2047 NULL, gerr, 2048 BT_IO_OPT_SOURCE_BDADDR, &mi->src, 2049 BT_IO_OPT_PSM, dcpsm, 2050 BT_IO_OPT_MTU, MCAP_DC_MTU, 2051 BT_IO_OPT_SEC_LEVEL, sec, 2052 BT_IO_OPT_INVALID); 2053 if (!mi->dcio) { 2054 g_io_channel_shutdown(mi->ccio, TRUE, NULL); 2055 g_io_channel_unref(mi->ccio); 2056 mi->ccio = NULL; 2057 error("%s", (*gerr)->message); 2058 g_free(mi); 2059 return NULL; 2060 } 2061 2062 /* Initialize random seed to generate mdlids for this instance */ 2063 srand(time(NULL)); 2064 2065 return mcap_instance_ref(mi);; 2066 } 2067 2068 void mcap_release_instance(struct mcap_instance *mi) 2069 { 2070 GSList *l; 2071 2072 if (!mi) 2073 return; 2074 2075 if (mi->ccio) { 2076 g_io_channel_shutdown(mi->ccio, TRUE, NULL); 2077 g_io_channel_unref(mi->ccio); 2078 mi->ccio = NULL; 2079 } 2080 2081 if (mi->dcio) { 2082 g_io_channel_shutdown(mi->dcio, TRUE, NULL); 2083 g_io_channel_unref(mi->dcio); 2084 mi->dcio = NULL; 2085 } 2086 2087 for (l = mi->mcls; l; l = l->next) { 2088 mcap_mcl_release(l->data); 2089 mcap_mcl_unref(l->data); 2090 } 2091 2092 g_slist_free(mi->mcls); 2093 mi->mcls = NULL; 2094 2095 for (l = mi->cached; l; l = l->next) { 2096 mcap_mcl_release(l->data); 2097 mcap_mcl_unref(l->data); 2098 } 2099 2100 g_slist_free(mi->cached); 2101 mi->cached = NULL; 2102 } 2103 2104 struct mcap_instance *mcap_instance_ref(struct mcap_instance *mi) 2105 { 2106 mi->ref++; 2107 2108 DBG("mcap_instance_ref(%p): ref=%d", mi, mi->ref); 2109 2110 return mi; 2111 } 2112 2113 void mcap_instance_unref(struct mcap_instance *mi) 2114 { 2115 mi->ref--; 2116 2117 DBG("mcap_instance_unref(%p): ref=%d", mi, mi->ref); 2118 2119 if (mi->ref > 0) 2120 return; 2121 2122 mcap_release_instance(mi); 2123 g_free(mi); 2124 } 2125 2126 uint16_t mcap_get_ctrl_psm(struct mcap_instance *mi, GError **err) 2127 { 2128 uint16_t lpsm; 2129 2130 if (!(mi && mi->ccio)) { 2131 g_set_error(err, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS, 2132 "Invalid MCAP instance"); 2133 return 0; 2134 } 2135 2136 if (!bt_io_get(mi->ccio, BT_IO_L2CAP, err, 2137 BT_IO_OPT_PSM, &lpsm, 2138 BT_IO_OPT_INVALID)) 2139 return 0; 2140 2141 return lpsm; 2142 } 2143 2144 uint16_t mcap_get_data_psm(struct mcap_instance *mi, GError **err) 2145 { 2146 uint16_t lpsm; 2147 2148 if (!(mi && mi->dcio)) { 2149 g_set_error(err, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS, 2150 "Invalid MCAP instance"); 2151 return 0; 2152 } 2153 2154 if (!bt_io_get(mi->dcio, BT_IO_L2CAP, err, 2155 BT_IO_OPT_PSM, &lpsm, 2156 BT_IO_OPT_INVALID)) 2157 return 0; 2158 2159 return lpsm; 2160 } 2161 2162 gboolean mcap_set_data_chan_mode(struct mcap_instance *mi, uint8_t mode, 2163 GError **err) 2164 { 2165 if (!(mi && mi->dcio)) { 2166 g_set_error(err, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS, 2167 "Invalid MCAP instance"); 2168 return FALSE; 2169 } 2170 2171 return bt_io_set(mi->dcio, BT_IO_L2CAP, err, BT_IO_OPT_MODE, mode, 2172 BT_IO_OPT_INVALID); 2173 } 2174 2175 struct mcap_mdl *mcap_mdl_ref(struct mcap_mdl *mdl) 2176 { 2177 mdl->ref++; 2178 2179 DBG("mcap_mdl_ref(%p): ref=%d", mdl, mdl->ref); 2180 2181 return mdl; 2182 } 2183 2184 void mcap_mdl_unref(struct mcap_mdl *mdl) 2185 { 2186 mdl->ref--; 2187 2188 DBG("mcap_mdl_unref(%p): ref=%d", mdl, mdl->ref); 2189 2190 if (mdl->ref > 0) 2191 return; 2192 2193 free_mdl(mdl); 2194 } 2195