1 /* 2 * 3 * BlueZ - Bluetooth protocol stack for Linux 4 * 5 * Copyright (C) 2008-2010 Nokia Corporation 6 * Copyright (C) 2004-2010 Marcel Holtmann <marcel (at) holtmann.org> 7 * 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 * 23 */ 24 25 #ifdef HAVE_CONFIG_H 26 #include <config.h> 27 #endif 28 29 #include <stdlib.h> 30 #include <stdio.h> 31 #include <unistd.h> 32 #include <fcntl.h> 33 #include <stdint.h> 34 #include <string.h> 35 #include <glib.h> 36 #include <dbus/dbus.h> 37 #include <gdbus.h> 38 39 #include "log.h" 40 #include "telephony.h" 41 42 /* SSC D-Bus definitions */ 43 #define SSC_DBUS_NAME "com.nokia.phone.SSC" 44 #define SSC_DBUS_IFACE "com.nokia.phone.SSC" 45 #define SSC_DBUS_PATH "/com/nokia/phone/SSC" 46 47 /* libcsnet D-Bus definitions */ 48 #define NETWORK_BUS_NAME "com.nokia.phone.net" 49 #define NETWORK_INTERFACE "Phone.Net" 50 #define NETWORK_PATH "/com/nokia/phone/net" 51 52 /* Mask bits for supported services */ 53 #define NETWORK_MASK_GPRS_SUPPORT 0x01 54 #define NETWORK_MASK_CS_SERVICES 0x02 55 #define NETWORK_MASK_EGPRS_SUPPORT 0x04 56 #define NETWORK_MASK_HSDPA_AVAIL 0x08 57 #define NETWORK_MASK_HSUPA_AVAIL 0x10 58 59 /* network get cell info: cell type */ 60 #define NETWORK_UNKNOWN_CELL 0 61 #define NETWORK_GSM_CELL 1 62 #define NETWORK_WCDMA_CELL 2 63 64 enum net_registration_status { 65 NETWORK_REG_STATUS_HOME = 0x00, 66 NETWORK_REG_STATUS_ROAM, 67 NETWORK_REG_STATUS_ROAM_BLINK, 68 NETWORK_REG_STATUS_NOSERV, 69 NETWORK_REG_STATUS_NOSERV_SEARCHING, 70 NETWORK_REG_STATUS_NOSERV_NOTSEARCHING, 71 NETWORK_REG_STATUS_NOSERV_NOSIM, 72 NETWORK_REG_STATUS_POWER_OFF = 0x08, 73 NETWORK_REG_STATUS_NSPS, 74 NETWORK_REG_STATUS_NSPS_NO_COVERAGE, 75 NETWORK_REG_STATUS_NOSERV_SIM_REJECTED_BY_NW 76 }; 77 78 enum network_types { 79 NETWORK_GSM_HOME_PLMN = 0, 80 NETWORK_GSM_PREFERRED_PLMN, 81 NETWORK_GSM_FORBIDDEN_PLMN, 82 NETWORK_GSM_OTHER_PLMN, 83 NETWORK_GSM_NO_PLMN_AVAIL 84 }; 85 86 enum network_alpha_tag_name_type { 87 NETWORK_HARDCODED_LATIN_OPER_NAME = 0, 88 NETWORK_HARDCODED_USC2_OPER_NAME, 89 NETWORK_NITZ_SHORT_OPER_NAME, 90 NETWORK_NITZ_FULL_OPER_NAME, 91 }; 92 93 #define TELEPHONY_MAEMO_PATH "/com/nokia/MaemoTelephony" 94 #define TELEPHONY_MAEMO_INTERFACE "com.nokia.MaemoTelephony" 95 96 #define CALLERID_BASE "/var/lib/bluetooth/maemo-callerid-" 97 #define ALLOWED_FLAG_FILE "/var/lib/bluetooth/maemo-callerid-allowed" 98 #define RESTRICTED_FLAG_FILE "/var/lib/bluetooth/maemo-callerid-restricted" 99 #define NONE_FLAG_FILE "/var/lib/bluetooth/maemo-callerid-none" 100 101 static uint32_t callerid = 0; 102 103 /* CSD CALL plugin D-Bus definitions */ 104 #define CSD_CALL_BUS_NAME "com.nokia.csd.Call" 105 #define CSD_CALL_INTERFACE "com.nokia.csd.Call" 106 #define CSD_CALL_INSTANCE "com.nokia.csd.Call.Instance" 107 #define CSD_CALL_CONFERENCE "com.nokia.csd.Call.Conference" 108 #define CSD_CALL_PATH "/com/nokia/csd/call" 109 #define CSD_CALL_CONFERENCE_PATH "/com/nokia/csd/call/conference" 110 111 /* Call status values as exported by the CSD CALL plugin */ 112 #define CSD_CALL_STATUS_IDLE 0 113 #define CSD_CALL_STATUS_CREATE 1 114 #define CSD_CALL_STATUS_COMING 2 115 #define CSD_CALL_STATUS_PROCEEDING 3 116 #define CSD_CALL_STATUS_MO_ALERTING 4 117 #define CSD_CALL_STATUS_MT_ALERTING 5 118 #define CSD_CALL_STATUS_WAITING 6 119 #define CSD_CALL_STATUS_ANSWERED 7 120 #define CSD_CALL_STATUS_ACTIVE 8 121 #define CSD_CALL_STATUS_MO_RELEASE 9 122 #define CSD_CALL_STATUS_MT_RELEASE 10 123 #define CSD_CALL_STATUS_HOLD_INITIATED 11 124 #define CSD_CALL_STATUS_HOLD 12 125 #define CSD_CALL_STATUS_RETRIEVE_INITIATED 13 126 #define CSD_CALL_STATUS_RECONNECT_PENDING 14 127 #define CSD_CALL_STATUS_TERMINATED 15 128 #define CSD_CALL_STATUS_SWAP_INITIATED 16 129 130 #define CALL_FLAG_NONE 0 131 #define CALL_FLAG_PRESENTATION_ALLOWED 0x01 132 #define CALL_FLAG_PRESENTATION_RESTRICTED 0x02 133 134 /* SIM Phonebook D-Bus definitions */ 135 #define SIM_PHONEBOOK_BUS_NAME "com.nokia.phone.SIM" 136 #define SIM_PHONEBOOK_INTERFACE "Phone.Sim.Phonebook" 137 #define SIM_PHONEBOOK_PATH "/com/nokia/phone/SIM/phonebook" 138 139 #define PHONEBOOK_INDEX_FIRST_ENTRY 0xFFFF 140 #define PHONEBOOK_INDEX_NEXT_FREE_LOCATION 0xFFFE 141 142 enum sim_phonebook_type { 143 SIM_PHONEBOOK_TYPE_ADN = 0x0, 144 SIM_PHONEBOOK_TYPE_SDN, 145 SIM_PHONEBOOK_TYPE_FDN, 146 SIM_PHONEBOOK_TYPE_VMBX, 147 SIM_PHONEBOOK_TYPE_MBDN, 148 SIM_PHONEBOOK_TYPE_EN, 149 SIM_PHONEBOOK_TYPE_MSISDN 150 }; 151 152 enum sim_phonebook_location_type { 153 SIM_PHONEBOOK_LOCATION_EXACT = 0x0, 154 SIM_PHONEBOOK_LOCATION_NEXT 155 }; 156 157 struct csd_call { 158 char *object_path; 159 int status; 160 gboolean originating; 161 gboolean emergency; 162 gboolean on_hold; 163 gboolean conference; 164 char *number; 165 gboolean setup; 166 }; 167 168 static struct { 169 uint8_t status; 170 uint16_t lac; 171 uint32_t cell_id; 172 uint32_t operator_code; 173 uint32_t country_code; 174 uint8_t network_type; 175 uint8_t supported_services; 176 uint16_t signals_bar; 177 char *operator_name; 178 } net = { 179 .status = NETWORK_REG_STATUS_NOSERV, 180 .lac = 0, 181 .cell_id = 0, 182 .operator_code = 0, 183 .country_code = 0, 184 .network_type = NETWORK_GSM_NO_PLMN_AVAIL, 185 .supported_services = 0, 186 .signals_bar = 0, 187 .operator_name = NULL, 188 }; 189 190 static DBusConnection *connection = NULL; 191 192 static GSList *calls = NULL; 193 194 /* Reference count for determining the call indicator status */ 195 static GSList *active_calls = NULL; 196 197 static char *msisdn = NULL; /* Subscriber number */ 198 static char *vmbx = NULL; /* Voice mailbox number */ 199 200 /* HAL battery namespace key values */ 201 static int battchg_cur = -1; /* "battery.charge_level.current" */ 202 static int battchg_last = -1; /* "battery.charge_level.last_full" */ 203 static int battchg_design = -1; /* "battery.charge_level.design" */ 204 205 static gboolean get_calls_active = FALSE; 206 207 static gboolean events_enabled = FALSE; 208 209 /* Supported set of call hold operations */ 210 static const char *chld_str = "0,1,1x,2,2x,3,4"; 211 212 /* Response and hold state 213 * -1 = none 214 * 0 = incoming call is put on hold in the AG 215 * 1 = held incoming call is accepted in the AG 216 * 2 = held incoming call is rejected in the AG 217 */ 218 static int response_and_hold = -1; 219 220 static char *last_dialed_number = NULL; 221 222 /* Timer for tracking call creation requests */ 223 static guint create_request_timer = 0; 224 225 static struct indicator maemo_indicators[] = 226 { 227 { "battchg", "0-5", 5, TRUE }, 228 { "signal", "0-5", 0, TRUE }, 229 { "service", "0,1", 0, TRUE }, 230 { "call", "0,1", 0, TRUE }, 231 { "callsetup", "0-3", 0, TRUE }, 232 { "callheld", "0-2", 0, FALSE }, 233 { "roam", "0,1", 0, TRUE }, 234 { NULL } 235 }; 236 237 static char *call_status_str[] = { 238 "IDLE", 239 "CREATE", 240 "COMING", 241 "PROCEEDING", 242 "MO_ALERTING", 243 "MT_ALERTING", 244 "WAITING", 245 "ANSWERED", 246 "ACTIVE", 247 "MO_RELEASE", 248 "MT_RELEASE", 249 "HOLD_INITIATED", 250 "HOLD", 251 "RETRIEVE_INITIATED", 252 "RECONNECT_PENDING", 253 "TERMINATED", 254 "SWAP_INITIATED", 255 "???" 256 }; 257 258 static struct csd_call *find_call(const char *path) 259 { 260 GSList *l; 261 262 for (l = calls; l != NULL; l = l->next) { 263 struct csd_call *call = l->data; 264 265 if (g_str_equal(call->object_path, path)) 266 return call; 267 } 268 269 return NULL; 270 } 271 272 static struct csd_call *find_non_held_call(void) 273 { 274 GSList *l; 275 276 for (l = calls; l != NULL; l = l->next) { 277 struct csd_call *call = l->data; 278 279 if (call->status == CSD_CALL_STATUS_IDLE) 280 continue; 281 282 if (call->status != CSD_CALL_STATUS_HOLD) 283 return call; 284 } 285 286 return NULL; 287 } 288 289 static struct csd_call *find_non_idle_call(void) 290 { 291 GSList *l; 292 293 for (l = calls; l != NULL; l = l->next) { 294 struct csd_call *call = l->data; 295 296 if (call->status != CSD_CALL_STATUS_IDLE) 297 return call; 298 } 299 300 return NULL; 301 } 302 303 static struct csd_call *find_call_with_status(int status) 304 { 305 GSList *l; 306 307 for (l = calls; l != NULL; l = l->next) { 308 struct csd_call *call = l->data; 309 310 if (call->status == status) 311 return call; 312 } 313 314 return NULL; 315 } 316 317 static int release_conference(void) 318 { 319 DBusMessage *msg; 320 321 DBG("telephony-maemo: releasing conference call"); 322 323 msg = dbus_message_new_method_call(CSD_CALL_BUS_NAME, 324 CSD_CALL_CONFERENCE_PATH, 325 CSD_CALL_INSTANCE, 326 "Release"); 327 if (!msg) { 328 error("Unable to allocate new D-Bus message"); 329 return -ENOMEM; 330 } 331 332 g_dbus_send_message(connection, msg); 333 334 return 0; 335 } 336 337 static int release_call(struct csd_call *call) 338 { 339 DBusMessage *msg; 340 341 msg = dbus_message_new_method_call(CSD_CALL_BUS_NAME, 342 call->object_path, 343 CSD_CALL_INSTANCE, 344 "Release"); 345 if (!msg) { 346 error("Unable to allocate new D-Bus message"); 347 return -ENOMEM; 348 } 349 350 g_dbus_send_message(connection, msg); 351 352 return 0; 353 } 354 355 static int answer_call(struct csd_call *call) 356 { 357 DBusMessage *msg; 358 359 msg = dbus_message_new_method_call(CSD_CALL_BUS_NAME, 360 call->object_path, 361 CSD_CALL_INSTANCE, 362 "Answer"); 363 if (!msg) { 364 error("Unable to allocate new D-Bus message"); 365 return -ENOMEM; 366 } 367 368 g_dbus_send_message(connection, msg); 369 370 return 0; 371 } 372 373 static int split_call(struct csd_call *call) 374 { 375 DBusMessage *msg; 376 377 msg = dbus_message_new_method_call(CSD_CALL_BUS_NAME, 378 call->object_path, 379 CSD_CALL_INSTANCE, 380 "Split"); 381 if (!msg) { 382 error("Unable to allocate new D-Bus message"); 383 return -ENOMEM; 384 } 385 386 g_dbus_send_message(connection, msg); 387 388 return 0; 389 } 390 391 static int unhold_call(struct csd_call *call) 392 { 393 DBusMessage *msg; 394 395 msg = dbus_message_new_method_call(CSD_CALL_BUS_NAME, CSD_CALL_PATH, 396 CSD_CALL_INTERFACE, 397 "Unhold"); 398 if (!msg) { 399 error("Unable to allocate new D-Bus message"); 400 return -ENOMEM; 401 } 402 403 g_dbus_send_message(connection, msg); 404 405 return 0; 406 } 407 408 static int hold_call(struct csd_call *call) 409 { 410 DBusMessage *msg; 411 412 msg = dbus_message_new_method_call(CSD_CALL_BUS_NAME, CSD_CALL_PATH, 413 CSD_CALL_INTERFACE, 414 "Hold"); 415 if (!msg) { 416 error("Unable to allocate new D-Bus message"); 417 return -ENOMEM; 418 } 419 420 g_dbus_send_message(connection, msg); 421 422 return 0; 423 } 424 425 static int swap_calls(void) 426 { 427 DBusMessage *msg; 428 429 msg = dbus_message_new_method_call(CSD_CALL_BUS_NAME, CSD_CALL_PATH, 430 CSD_CALL_INTERFACE, 431 "Swap"); 432 if (!msg) { 433 error("Unable to allocate new D-Bus message"); 434 return -ENOMEM; 435 } 436 437 g_dbus_send_message(connection, msg); 438 439 return 0; 440 } 441 442 static int create_conference(void) 443 { 444 DBusMessage *msg; 445 446 msg = dbus_message_new_method_call(CSD_CALL_BUS_NAME, CSD_CALL_PATH, 447 CSD_CALL_INTERFACE, 448 "Conference"); 449 if (!msg) { 450 error("Unable to allocate new D-Bus message"); 451 return -ENOMEM; 452 } 453 454 g_dbus_send_message(connection, msg); 455 456 return 0; 457 } 458 459 static int call_transfer(void) 460 { 461 DBusMessage *msg; 462 463 msg = dbus_message_new_method_call(CSD_CALL_BUS_NAME, CSD_CALL_PATH, 464 CSD_CALL_INTERFACE, 465 "Transfer"); 466 if (!msg) { 467 error("Unable to allocate new D-Bus message"); 468 return -ENOMEM; 469 } 470 471 g_dbus_send_message(connection, msg); 472 473 return 0; 474 } 475 476 static int number_type(const char *number) 477 { 478 if (number == NULL) 479 return NUMBER_TYPE_TELEPHONY; 480 481 if (number[0] == '+' || strncmp(number, "00", 2) == 0) 482 return NUMBER_TYPE_INTERNATIONAL; 483 484 return NUMBER_TYPE_TELEPHONY; 485 } 486 487 void telephony_device_connected(void *telephony_device) 488 { 489 struct csd_call *coming; 490 491 DBG("telephony-maemo: device %p connected", telephony_device); 492 493 coming = find_call_with_status(CSD_CALL_STATUS_MT_ALERTING); 494 if (coming) { 495 if (find_call_with_status(CSD_CALL_STATUS_ACTIVE)) 496 telephony_call_waiting_ind(coming->number, 497 number_type(coming->number)); 498 else 499 telephony_incoming_call_ind(coming->number, 500 number_type(coming->number)); 501 } 502 } 503 504 void telephony_device_disconnected(void *telephony_device) 505 { 506 DBG("telephony-maemo: device %p disconnected", telephony_device); 507 events_enabled = FALSE; 508 } 509 510 void telephony_event_reporting_req(void *telephony_device, int ind) 511 { 512 events_enabled = ind == 1 ? TRUE : FALSE; 513 514 telephony_event_reporting_rsp(telephony_device, CME_ERROR_NONE); 515 } 516 517 void telephony_response_and_hold_req(void *telephony_device, int rh) 518 { 519 response_and_hold = rh; 520 521 telephony_response_and_hold_ind(response_and_hold); 522 523 telephony_response_and_hold_rsp(telephony_device, CME_ERROR_NONE); 524 } 525 526 void telephony_last_dialed_number_req(void *telephony_device) 527 { 528 DBG("telephony-maemo: last dialed number request"); 529 530 if (last_dialed_number) 531 telephony_dial_number_req(telephony_device, 532 last_dialed_number); 533 else 534 telephony_last_dialed_number_rsp(telephony_device, 535 CME_ERROR_NOT_ALLOWED); 536 } 537 538 void telephony_terminate_call_req(void *telephony_device) 539 { 540 struct csd_call *call; 541 int err; 542 543 call = find_call_with_status(CSD_CALL_STATUS_ACTIVE); 544 if (!call) 545 call = find_non_idle_call(); 546 547 if (!call) { 548 error("No active call"); 549 telephony_terminate_call_rsp(telephony_device, 550 CME_ERROR_NOT_ALLOWED); 551 return; 552 } 553 554 if (call->conference) 555 err = release_conference(); 556 else 557 err = release_call(call); 558 559 if (err < 0) 560 telephony_terminate_call_rsp(telephony_device, 561 CME_ERROR_AG_FAILURE); 562 else 563 telephony_terminate_call_rsp(telephony_device, CME_ERROR_NONE); 564 } 565 566 void telephony_answer_call_req(void *telephony_device) 567 { 568 struct csd_call *call; 569 570 call = find_call_with_status(CSD_CALL_STATUS_COMING); 571 if (!call) 572 call = find_call_with_status(CSD_CALL_STATUS_MT_ALERTING); 573 574 if (!call) 575 call = find_call_with_status(CSD_CALL_STATUS_PROCEEDING); 576 577 if (!call) 578 call = find_call_with_status(CSD_CALL_STATUS_WAITING); 579 580 if (!call) { 581 telephony_answer_call_rsp(telephony_device, 582 CME_ERROR_NOT_ALLOWED); 583 return; 584 } 585 586 if (answer_call(call) < 0) 587 telephony_answer_call_rsp(telephony_device, 588 CME_ERROR_AG_FAILURE); 589 else 590 telephony_answer_call_rsp(telephony_device, CME_ERROR_NONE); 591 } 592 593 static int send_method_call(const char *dest, const char *path, 594 const char *interface, const char *method, 595 DBusPendingCallNotifyFunction cb, 596 void *user_data, int type, ...) 597 { 598 DBusMessage *msg; 599 DBusPendingCall *call; 600 va_list args; 601 602 msg = dbus_message_new_method_call(dest, path, interface, method); 603 if (!msg) { 604 error("Unable to allocate new D-Bus %s message", method); 605 return -ENOMEM; 606 } 607 608 va_start(args, type); 609 610 if (!dbus_message_append_args_valist(msg, type, args)) { 611 dbus_message_unref(msg); 612 va_end(args); 613 return -EIO; 614 } 615 616 va_end(args); 617 618 if (!cb) { 619 g_dbus_send_message(connection, msg); 620 return 0; 621 } 622 623 if (!dbus_connection_send_with_reply(connection, msg, &call, -1)) { 624 error("Sending %s failed", method); 625 dbus_message_unref(msg); 626 return -EIO; 627 } 628 629 dbus_pending_call_set_notify(call, cb, user_data, NULL); 630 dbus_pending_call_unref(call); 631 dbus_message_unref(msg); 632 633 return 0; 634 } 635 636 static const char *memory_dial_lookup(int location) 637 { 638 if (location == 1) 639 return vmbx; 640 else 641 return NULL; 642 } 643 644 void telephony_dial_number_req(void *telephony_device, const char *number) 645 { 646 uint32_t flags = callerid; 647 int ret; 648 649 DBG("telephony-maemo: dial request to %s", number); 650 651 if (strncmp(number, "*31#", 4) == 0) { 652 number += 4; 653 flags = CALL_FLAG_PRESENTATION_ALLOWED; 654 } else if (strncmp(number, "#31#", 4) == 0) { 655 number += 4; 656 flags = CALL_FLAG_PRESENTATION_RESTRICTED; 657 } else if (number[0] == '>') { 658 const char *location = &number[1]; 659 660 number = memory_dial_lookup(strtol(&number[1], NULL, 0)); 661 if (!number) { 662 error("No number at memory location %s", location); 663 telephony_dial_number_rsp(telephony_device, 664 CME_ERROR_INVALID_INDEX); 665 return; 666 } 667 } 668 669 ret = send_method_call(CSD_CALL_BUS_NAME, CSD_CALL_PATH, 670 CSD_CALL_INTERFACE, "CreateWith", 671 NULL, NULL, 672 DBUS_TYPE_STRING, &number, 673 DBUS_TYPE_UINT32, &flags, 674 DBUS_TYPE_INVALID); 675 if (ret < 0) { 676 telephony_dial_number_rsp(telephony_device, 677 CME_ERROR_AG_FAILURE); 678 return; 679 } 680 681 telephony_dial_number_rsp(telephony_device, CME_ERROR_NONE); 682 } 683 684 void telephony_transmit_dtmf_req(void *telephony_device, char tone) 685 { 686 int ret; 687 char buf[2] = { tone, '\0' }, *buf_ptr = buf; 688 689 DBG("telephony-maemo: transmit dtmf: %s", buf); 690 691 ret = send_method_call(CSD_CALL_BUS_NAME, CSD_CALL_PATH, 692 CSD_CALL_INTERFACE, "SendDTMF", 693 NULL, NULL, 694 DBUS_TYPE_STRING, &buf_ptr, 695 DBUS_TYPE_INVALID); 696 if (ret < 0) { 697 telephony_transmit_dtmf_rsp(telephony_device, 698 CME_ERROR_AG_FAILURE); 699 return; 700 } 701 702 telephony_transmit_dtmf_rsp(telephony_device, CME_ERROR_NONE); 703 } 704 705 void telephony_subscriber_number_req(void *telephony_device) 706 { 707 DBG("telephony-maemo: subscriber number request"); 708 if (msisdn) 709 telephony_subscriber_number_ind(msisdn, 710 number_type(msisdn), 711 SUBSCRIBER_SERVICE_VOICE); 712 telephony_subscriber_number_rsp(telephony_device, CME_ERROR_NONE); 713 } 714 715 static int csd_status_to_hfp(struct csd_call *call) 716 { 717 switch (call->status) { 718 case CSD_CALL_STATUS_IDLE: 719 case CSD_CALL_STATUS_MO_RELEASE: 720 case CSD_CALL_STATUS_MT_RELEASE: 721 case CSD_CALL_STATUS_TERMINATED: 722 return -1; 723 case CSD_CALL_STATUS_CREATE: 724 return CALL_STATUS_DIALING; 725 case CSD_CALL_STATUS_WAITING: 726 return CALL_STATUS_WAITING; 727 case CSD_CALL_STATUS_PROCEEDING: 728 /* PROCEEDING can happen in outgoing/incoming */ 729 if (call->originating) 730 return CALL_STATUS_DIALING; 731 else 732 return CALL_STATUS_INCOMING; 733 case CSD_CALL_STATUS_COMING: 734 return CALL_STATUS_INCOMING; 735 case CSD_CALL_STATUS_MO_ALERTING: 736 return CALL_STATUS_ALERTING; 737 case CSD_CALL_STATUS_MT_ALERTING: 738 return CALL_STATUS_INCOMING; 739 case CSD_CALL_STATUS_ANSWERED: 740 case CSD_CALL_STATUS_ACTIVE: 741 case CSD_CALL_STATUS_RECONNECT_PENDING: 742 case CSD_CALL_STATUS_SWAP_INITIATED: 743 case CSD_CALL_STATUS_HOLD_INITIATED: 744 return CALL_STATUS_ACTIVE; 745 case CSD_CALL_STATUS_RETRIEVE_INITIATED: 746 case CSD_CALL_STATUS_HOLD: 747 return CALL_STATUS_HELD; 748 default: 749 return -1; 750 } 751 } 752 753 void telephony_list_current_calls_req(void *telephony_device) 754 { 755 GSList *l; 756 int i; 757 758 DBG("telephony-maemo: list current calls request"); 759 760 for (l = calls, i = 1; l != NULL; l = l->next, i++) { 761 struct csd_call *call = l->data; 762 int status, direction, multiparty; 763 764 status = csd_status_to_hfp(call); 765 if (status < 0) 766 continue; 767 768 direction = call->originating ? 769 CALL_DIR_OUTGOING : CALL_DIR_INCOMING; 770 771 multiparty = call->conference ? 772 CALL_MULTIPARTY_YES : CALL_MULTIPARTY_NO; 773 774 telephony_list_current_call_ind(i, direction, status, 775 CALL_MODE_VOICE, multiparty, 776 call->number, 777 number_type(call->number)); 778 } 779 780 telephony_list_current_calls_rsp(telephony_device, CME_ERROR_NONE); 781 } 782 783 void telephony_operator_selection_req(void *telephony_device) 784 { 785 telephony_operator_selection_ind(OPERATOR_MODE_AUTO, 786 net.operator_name ? net.operator_name : ""); 787 telephony_operator_selection_rsp(telephony_device, CME_ERROR_NONE); 788 } 789 790 static void foreach_call_with_status(int status, 791 int (*func)(struct csd_call *call)) 792 { 793 GSList *l; 794 795 for (l = calls; l != NULL; l = l->next) { 796 struct csd_call *call = l->data; 797 798 if (call->status == status) 799 func(call); 800 } 801 } 802 803 void telephony_call_hold_req(void *telephony_device, const char *cmd) 804 { 805 const char *idx; 806 struct csd_call *call; 807 int err = 0; 808 809 DBG("telephony-maemo: got call hold request %s", cmd); 810 811 if (strlen(cmd) > 1) 812 idx = &cmd[1]; 813 else 814 idx = NULL; 815 816 if (idx) 817 call = g_slist_nth_data(calls, strtol(idx, NULL, 0) - 1); 818 else 819 call = NULL; 820 821 switch (cmd[0]) { 822 case '0': 823 foreach_call_with_status(CSD_CALL_STATUS_HOLD, release_call); 824 foreach_call_with_status(CSD_CALL_STATUS_WAITING, 825 release_call); 826 break; 827 case '1': 828 if (idx) { 829 if (call) 830 err = release_call(call); 831 break; 832 } 833 foreach_call_with_status(CSD_CALL_STATUS_ACTIVE, release_call); 834 call = find_call_with_status(CSD_CALL_STATUS_WAITING); 835 if (call) 836 err = answer_call(call); 837 break; 838 case '2': 839 if (idx) { 840 if (call) 841 err = split_call(call); 842 } else { 843 struct csd_call *held, *wait; 844 845 call = find_call_with_status(CSD_CALL_STATUS_ACTIVE); 846 held = find_call_with_status(CSD_CALL_STATUS_HOLD); 847 wait = find_call_with_status(CSD_CALL_STATUS_WAITING); 848 849 if (wait) 850 err = answer_call(wait); 851 else if (call && held) 852 err = swap_calls(); 853 else { 854 if (call) 855 err = hold_call(call); 856 if (held) 857 err = unhold_call(held); 858 } 859 } 860 break; 861 case '3': 862 if (find_call_with_status(CSD_CALL_STATUS_HOLD) || 863 find_call_with_status(CSD_CALL_STATUS_WAITING)) 864 err = create_conference(); 865 break; 866 case '4': 867 err = call_transfer(); 868 break; 869 default: 870 DBG("Unknown call hold request"); 871 break; 872 } 873 874 if (err) 875 telephony_call_hold_rsp(telephony_device, 876 CME_ERROR_AG_FAILURE); 877 else 878 telephony_call_hold_rsp(telephony_device, CME_ERROR_NONE); 879 } 880 881 void telephony_nr_and_ec_req(void *telephony_device, gboolean enable) 882 { 883 DBG("telephony-maemo: got %s NR and EC request", 884 enable ? "enable" : "disable"); 885 telephony_nr_and_ec_rsp(telephony_device, CME_ERROR_NONE); 886 } 887 888 void telephony_key_press_req(void *telephony_device, const char *keys) 889 { 890 struct csd_call *active, *waiting; 891 int err; 892 893 DBG("telephony-maemo: got key press request for %s", keys); 894 895 waiting = find_call_with_status(CSD_CALL_STATUS_COMING); 896 if (!waiting) 897 waiting = find_call_with_status(CSD_CALL_STATUS_MT_ALERTING); 898 if (!waiting) 899 waiting = find_call_with_status(CSD_CALL_STATUS_PROCEEDING); 900 901 active = find_call_with_status(CSD_CALL_STATUS_ACTIVE); 902 903 if (waiting) 904 err = answer_call(waiting); 905 else if (active) 906 err = release_call(active); 907 else 908 err = 0; 909 910 if (err < 0) 911 telephony_key_press_rsp(telephony_device, 912 CME_ERROR_AG_FAILURE); 913 else 914 telephony_key_press_rsp(telephony_device, CME_ERROR_NONE); 915 } 916 917 void telephony_voice_dial_req(void *telephony_device, gboolean enable) 918 { 919 DBG("telephony-maemo: got %s voice dial request", 920 enable ? "enable" : "disable"); 921 922 telephony_voice_dial_rsp(telephony_device, CME_ERROR_NOT_SUPPORTED); 923 } 924 925 static void handle_incoming_call(DBusMessage *msg) 926 { 927 const char *number, *call_path; 928 struct csd_call *call; 929 930 if (!dbus_message_get_args(msg, NULL, 931 DBUS_TYPE_OBJECT_PATH, &call_path, 932 DBUS_TYPE_STRING, &number, 933 DBUS_TYPE_INVALID)) { 934 error("Unexpected parameters in Call.Coming() signal"); 935 return; 936 } 937 938 call = find_call(call_path); 939 if (!call) { 940 error("Didn't find any matching call object for %s", 941 call_path); 942 return; 943 } 944 945 DBG("Incoming call to %s from number %s", call_path, number); 946 947 g_free(call->number); 948 call->number = g_strdup(number); 949 950 telephony_update_indicator(maemo_indicators, "callsetup", 951 EV_CALLSETUP_INCOMING); 952 953 if (find_call_with_status(CSD_CALL_STATUS_ACTIVE)) 954 telephony_call_waiting_ind(call->number, 955 number_type(call->number)); 956 else 957 telephony_incoming_call_ind(call->number, 958 number_type(call->number)); 959 } 960 961 static void handle_outgoing_call(DBusMessage *msg) 962 { 963 const char *number, *call_path; 964 struct csd_call *call; 965 966 if (!dbus_message_get_args(msg, NULL, 967 DBUS_TYPE_OBJECT_PATH, &call_path, 968 DBUS_TYPE_STRING, &number, 969 DBUS_TYPE_INVALID)) { 970 error("Unexpected parameters in Call.Created() signal"); 971 return; 972 } 973 974 call = find_call(call_path); 975 if (!call) { 976 error("Didn't find any matching call object for %s", 977 call_path); 978 return; 979 } 980 981 DBG("Outgoing call from %s to number %s", call_path, number); 982 983 g_free(call->number); 984 call->number = g_strdup(number); 985 986 g_free(last_dialed_number); 987 last_dialed_number = g_strdup(number); 988 989 if (create_request_timer) { 990 g_source_remove(create_request_timer); 991 create_request_timer = 0; 992 } 993 } 994 995 static gboolean create_timeout(gpointer user_data) 996 { 997 telephony_update_indicator(maemo_indicators, "callsetup", 998 EV_CALLSETUP_INACTIVE); 999 create_request_timer = 0; 1000 return FALSE; 1001 } 1002 1003 static void handle_create_requested(DBusMessage *msg) 1004 { 1005 DBG("Call.CreateRequested()"); 1006 1007 if (create_request_timer) 1008 g_source_remove(create_request_timer); 1009 1010 create_request_timer = g_timeout_add_seconds(5, create_timeout, NULL); 1011 1012 telephony_update_indicator(maemo_indicators, "callsetup", 1013 EV_CALLSETUP_OUTGOING); 1014 } 1015 1016 static void handle_call_status(DBusMessage *msg, const char *call_path) 1017 { 1018 struct csd_call *call; 1019 dbus_uint32_t status, cause_type, cause; 1020 int callheld = telephony_get_indicator(maemo_indicators, "callheld"); 1021 1022 if (!dbus_message_get_args(msg, NULL, 1023 DBUS_TYPE_UINT32, &status, 1024 DBUS_TYPE_UINT32, &cause_type, 1025 DBUS_TYPE_UINT32, &cause, 1026 DBUS_TYPE_INVALID)) { 1027 error("Unexpected paramters in Instance.CallStatus() signal"); 1028 return; 1029 } 1030 1031 call = find_call(call_path); 1032 if (!call) { 1033 error("Didn't find any matching call object for %s", 1034 call_path); 1035 return; 1036 } 1037 1038 if (status > 16) { 1039 error("Invalid call status %u", status); 1040 return; 1041 } 1042 1043 DBG("Call %s changed from %s to %s", call_path, 1044 call_status_str[call->status], call_status_str[status]); 1045 1046 if (call->status == (int) status) { 1047 DBG("Ignoring CSD Call state change to existing state"); 1048 return; 1049 } 1050 1051 call->status = (int) status; 1052 1053 switch (status) { 1054 case CSD_CALL_STATUS_IDLE: 1055 if (call->setup) { 1056 telephony_update_indicator(maemo_indicators, 1057 "callsetup", 1058 EV_CALLSETUP_INACTIVE); 1059 if (!call->originating) 1060 telephony_calling_stopped_ind(); 1061 } 1062 1063 g_free(call->number); 1064 call->number = NULL; 1065 call->originating = FALSE; 1066 call->emergency = FALSE; 1067 call->on_hold = FALSE; 1068 call->conference = FALSE; 1069 call->setup = FALSE; 1070 break; 1071 case CSD_CALL_STATUS_CREATE: 1072 call->originating = TRUE; 1073 call->setup = TRUE; 1074 break; 1075 case CSD_CALL_STATUS_COMING: 1076 call->originating = FALSE; 1077 call->setup = TRUE; 1078 break; 1079 case CSD_CALL_STATUS_PROCEEDING: 1080 break; 1081 case CSD_CALL_STATUS_MO_ALERTING: 1082 telephony_update_indicator(maemo_indicators, "callsetup", 1083 EV_CALLSETUP_ALERTING); 1084 break; 1085 case CSD_CALL_STATUS_MT_ALERTING: 1086 break; 1087 case CSD_CALL_STATUS_WAITING: 1088 break; 1089 case CSD_CALL_STATUS_ANSWERED: 1090 break; 1091 case CSD_CALL_STATUS_ACTIVE: 1092 if (call->on_hold) { 1093 call->on_hold = FALSE; 1094 if (find_call_with_status(CSD_CALL_STATUS_HOLD)) 1095 telephony_update_indicator(maemo_indicators, 1096 "callheld", 1097 EV_CALLHELD_MULTIPLE); 1098 else 1099 telephony_update_indicator(maemo_indicators, 1100 "callheld", 1101 EV_CALLHELD_NONE); 1102 } else { 1103 if (!g_slist_find(active_calls, call)) 1104 active_calls = g_slist_prepend(active_calls, call); 1105 if (g_slist_length(active_calls) == 1) 1106 telephony_update_indicator(maemo_indicators, 1107 "call", 1108 EV_CALL_ACTIVE); 1109 /* Upgrade callheld status if necessary */ 1110 if (callheld == EV_CALLHELD_ON_HOLD) 1111 telephony_update_indicator(maemo_indicators, 1112 "callheld", 1113 EV_CALLHELD_MULTIPLE); 1114 telephony_update_indicator(maemo_indicators, 1115 "callsetup", 1116 EV_CALLSETUP_INACTIVE); 1117 if (!call->originating) 1118 telephony_calling_stopped_ind(); 1119 call->setup = FALSE; 1120 } 1121 break; 1122 case CSD_CALL_STATUS_MO_RELEASE: 1123 case CSD_CALL_STATUS_MT_RELEASE: 1124 active_calls = g_slist_remove(active_calls, call); 1125 if (g_slist_length(active_calls) == 0) 1126 telephony_update_indicator(maemo_indicators, "call", 1127 EV_CALL_INACTIVE); 1128 break; 1129 case CSD_CALL_STATUS_HOLD_INITIATED: 1130 break; 1131 case CSD_CALL_STATUS_HOLD: 1132 call->on_hold = TRUE; 1133 if (find_non_held_call()) 1134 telephony_update_indicator(maemo_indicators, 1135 "callheld", 1136 EV_CALLHELD_MULTIPLE); 1137 else 1138 telephony_update_indicator(maemo_indicators, 1139 "callheld", 1140 EV_CALLHELD_ON_HOLD); 1141 break; 1142 case CSD_CALL_STATUS_RETRIEVE_INITIATED: 1143 break; 1144 case CSD_CALL_STATUS_RECONNECT_PENDING: 1145 break; 1146 case CSD_CALL_STATUS_TERMINATED: 1147 if (call->on_hold && 1148 !find_call_with_status(CSD_CALL_STATUS_HOLD)) 1149 telephony_update_indicator(maemo_indicators, 1150 "callheld", 1151 EV_CALLHELD_NONE); 1152 else if (callheld == EV_CALLHELD_MULTIPLE && 1153 find_call_with_status(CSD_CALL_STATUS_HOLD)) 1154 telephony_update_indicator(maemo_indicators, 1155 "callheld", 1156 EV_CALLHELD_ON_HOLD); 1157 break; 1158 case CSD_CALL_STATUS_SWAP_INITIATED: 1159 break; 1160 default: 1161 error("Unknown call status %u", status); 1162 break; 1163 } 1164 } 1165 1166 static void handle_conference(DBusMessage *msg, gboolean joined) 1167 { 1168 const char *path; 1169 struct csd_call *call; 1170 1171 if (!dbus_message_get_args(msg, NULL, 1172 DBUS_TYPE_OBJECT_PATH, &path, 1173 DBUS_TYPE_INVALID)) { 1174 error("Unexpected parameters in Conference.%s", 1175 dbus_message_get_member(msg)); 1176 return; 1177 } 1178 1179 call = find_call(path); 1180 if (!call) { 1181 error("Conference signal for unknown call %s", path); 1182 return; 1183 } 1184 1185 DBG("Call %s %s the conference", path, joined ? "joined" : "left"); 1186 1187 call->conference = joined; 1188 } 1189 1190 static void get_operator_name_reply(DBusPendingCall *pending_call, 1191 void *user_data) 1192 { 1193 DBusMessage *reply; 1194 DBusError err; 1195 const char *name; 1196 dbus_int32_t net_err; 1197 1198 reply = dbus_pending_call_steal_reply(pending_call); 1199 1200 dbus_error_init(&err); 1201 if (dbus_set_error_from_message(&err, reply)) { 1202 error("get_operator_name failed: %s, %s", 1203 err.name, err.message); 1204 dbus_error_free(&err); 1205 goto done; 1206 } 1207 1208 dbus_error_init(&err); 1209 if (!dbus_message_get_args(reply, &err, 1210 DBUS_TYPE_STRING, &name, 1211 DBUS_TYPE_INT32, &net_err, 1212 DBUS_TYPE_INVALID)) { 1213 error("Unexpected get_operator_name reply parameters: %s, %s", 1214 err.name, err.message); 1215 dbus_error_free(&err); 1216 goto done; 1217 } 1218 1219 if (net_err != 0) { 1220 error("get_operator_name failed with code %d", net_err); 1221 goto done; 1222 } 1223 1224 if (strlen(name) == 0) 1225 goto done; 1226 1227 g_free(net.operator_name); 1228 net.operator_name = g_strdup(name); 1229 1230 DBG("telephony-maemo: operator name updated: %s", name); 1231 1232 done: 1233 dbus_message_unref(reply); 1234 } 1235 1236 static void resolve_operator_name(uint32_t operator, uint32_t country) 1237 { 1238 uint8_t name_type = NETWORK_HARDCODED_LATIN_OPER_NAME; 1239 1240 send_method_call(NETWORK_BUS_NAME, NETWORK_PATH, 1241 NETWORK_INTERFACE, "get_operator_name", 1242 get_operator_name_reply, NULL, 1243 DBUS_TYPE_BYTE, &name_type, 1244 DBUS_TYPE_UINT32, &operator, 1245 DBUS_TYPE_UINT32, &country, 1246 DBUS_TYPE_INVALID); 1247 } 1248 1249 static void update_registration_status(uint8_t status, uint16_t lac, 1250 uint32_t cell_id, 1251 uint32_t operator_code, 1252 uint32_t country_code, 1253 uint8_t network_type, 1254 uint8_t supported_services) 1255 { 1256 if (net.status != status) { 1257 switch (status) { 1258 case NETWORK_REG_STATUS_HOME: 1259 telephony_update_indicator(maemo_indicators, "roam", 1260 EV_ROAM_INACTIVE); 1261 if (net.status >= NETWORK_REG_STATUS_NOSERV) 1262 telephony_update_indicator(maemo_indicators, 1263 "service", 1264 EV_SERVICE_PRESENT); 1265 break; 1266 case NETWORK_REG_STATUS_ROAM: 1267 case NETWORK_REG_STATUS_ROAM_BLINK: 1268 telephony_update_indicator(maemo_indicators, "roam", 1269 EV_ROAM_ACTIVE); 1270 if (net.status >= NETWORK_REG_STATUS_NOSERV) 1271 telephony_update_indicator(maemo_indicators, 1272 "service", 1273 EV_SERVICE_PRESENT); 1274 break; 1275 case NETWORK_REG_STATUS_NOSERV: 1276 case NETWORK_REG_STATUS_NOSERV_SEARCHING: 1277 case NETWORK_REG_STATUS_NOSERV_NOTSEARCHING: 1278 case NETWORK_REG_STATUS_NOSERV_NOSIM: 1279 case NETWORK_REG_STATUS_POWER_OFF: 1280 case NETWORK_REG_STATUS_NSPS: 1281 case NETWORK_REG_STATUS_NSPS_NO_COVERAGE: 1282 case NETWORK_REG_STATUS_NOSERV_SIM_REJECTED_BY_NW: 1283 if (net.status < NETWORK_REG_STATUS_NOSERV) 1284 telephony_update_indicator(maemo_indicators, 1285 "service", 1286 EV_SERVICE_NONE); 1287 break; 1288 } 1289 1290 net.status = status; 1291 } 1292 1293 net.lac = lac; 1294 net.cell_id = cell_id; 1295 1296 if (net.operator_code != operator_code || 1297 net.country_code != country_code) { 1298 g_free(net.operator_name); 1299 net.operator_name = NULL; 1300 resolve_operator_name(operator_code, country_code); 1301 net.operator_code = operator_code; 1302 net.country_code = country_code; 1303 } 1304 1305 net.network_type = network_type; 1306 net.supported_services = supported_services; 1307 } 1308 1309 static void handle_registration_status_change(DBusMessage *msg) 1310 { 1311 uint8_t status; 1312 dbus_uint16_t lac, network_type, supported_services; 1313 dbus_uint32_t cell_id, operator_code, country_code; 1314 1315 if (!dbus_message_get_args(msg, NULL, 1316 DBUS_TYPE_BYTE, &status, 1317 DBUS_TYPE_UINT16, &lac, 1318 DBUS_TYPE_UINT32, &cell_id, 1319 DBUS_TYPE_UINT32, &operator_code, 1320 DBUS_TYPE_UINT32, &country_code, 1321 DBUS_TYPE_BYTE, &network_type, 1322 DBUS_TYPE_BYTE, &supported_services, 1323 DBUS_TYPE_INVALID)) { 1324 error("Unexpected parameters in registration_status_change"); 1325 return; 1326 } 1327 1328 update_registration_status(status, lac, cell_id, operator_code, 1329 country_code, network_type, 1330 supported_services); 1331 } 1332 1333 static void update_signal_strength(uint8_t signals_bar) 1334 { 1335 int signal; 1336 1337 if (signals_bar > 100) { 1338 DBG("signals_bar greater than expected: %u", signals_bar); 1339 signals_bar = 100; 1340 } 1341 1342 if (net.signals_bar == signals_bar) 1343 return; 1344 1345 /* A simple conversion from 0-100 to 0-5 (used by HFP) */ 1346 signal = (signals_bar + 20) / 21; 1347 1348 telephony_update_indicator(maemo_indicators, "signal", signal); 1349 1350 net.signals_bar = signals_bar; 1351 1352 DBG("Signal strength updated: %u/100, %d/5", signals_bar, signal); 1353 } 1354 1355 static void handle_signal_strength_change(DBusMessage *msg) 1356 { 1357 uint8_t signals_bar, rssi_in_dbm; 1358 1359 if (!dbus_message_get_args(msg, NULL, 1360 DBUS_TYPE_BYTE, &signals_bar, 1361 DBUS_TYPE_BYTE, &rssi_in_dbm, 1362 DBUS_TYPE_INVALID)) { 1363 error("Unexpected parameters in signal_strength_change"); 1364 return; 1365 } 1366 1367 update_signal_strength(signals_bar); 1368 } 1369 1370 static gboolean iter_get_basic_args(DBusMessageIter *iter, 1371 int first_arg_type, ...) 1372 { 1373 int type; 1374 va_list ap; 1375 1376 va_start(ap, first_arg_type); 1377 1378 for (type = first_arg_type; type != DBUS_TYPE_INVALID; 1379 type = va_arg(ap, int)) { 1380 void *value = va_arg(ap, void *); 1381 int real_type = dbus_message_iter_get_arg_type(iter); 1382 1383 if (real_type != type) { 1384 error("iter_get_basic_args: expected %c but got %c", 1385 (char) type, (char) real_type); 1386 break; 1387 } 1388 1389 dbus_message_iter_get_basic(iter, value); 1390 dbus_message_iter_next(iter); 1391 } 1392 1393 va_end(ap); 1394 1395 return type == DBUS_TYPE_INVALID ? TRUE : FALSE; 1396 } 1397 1398 static void hal_battery_level_reply(DBusPendingCall *call, void *user_data) 1399 { 1400 DBusError err; 1401 DBusMessage *reply; 1402 dbus_int32_t level; 1403 int *value = user_data; 1404 1405 reply = dbus_pending_call_steal_reply(call); 1406 1407 dbus_error_init(&err); 1408 if (dbus_set_error_from_message(&err, reply)) { 1409 error("hald replied with an error: %s, %s", 1410 err.name, err.message); 1411 dbus_error_free(&err); 1412 goto done; 1413 } 1414 1415 dbus_error_init(&err); 1416 if (dbus_message_get_args(reply, &err, 1417 DBUS_TYPE_INT32, &level, 1418 DBUS_TYPE_INVALID) == FALSE) { 1419 error("Unable to parse GetPropertyInteger reply: %s, %s", 1420 err.name, err.message); 1421 dbus_error_free(&err); 1422 goto done; 1423 } 1424 1425 *value = (int) level; 1426 1427 if (value == &battchg_last) 1428 DBG("telephony-maemo: battery.charge_level.last_full is %d", 1429 *value); 1430 else if (value == &battchg_design) 1431 DBG("telephony-maemo: battery.charge_level.design is %d", 1432 *value); 1433 else 1434 DBG("telephony-maemo: battery.charge_level.current is %d", 1435 *value); 1436 1437 if ((battchg_design > 0 || battchg_last > 0) && battchg_cur >= 0) { 1438 int new, max; 1439 1440 if (battchg_last > 0) 1441 max = battchg_last; 1442 else 1443 max = battchg_design; 1444 1445 new = battchg_cur * 5 / max; 1446 1447 telephony_update_indicator(maemo_indicators, "battchg", new); 1448 } 1449 done: 1450 dbus_message_unref(reply); 1451 } 1452 1453 static void hal_get_integer(const char *path, const char *key, void *user_data) 1454 { 1455 send_method_call("org.freedesktop.Hal", path, 1456 "org.freedesktop.Hal.Device", 1457 "GetPropertyInteger", 1458 hal_battery_level_reply, user_data, 1459 DBUS_TYPE_STRING, &key, 1460 DBUS_TYPE_INVALID); 1461 } 1462 1463 static void handle_hal_property_modified(DBusMessage *msg) 1464 { 1465 DBusMessageIter iter, array; 1466 dbus_int32_t num_changes; 1467 const char *path; 1468 1469 path = dbus_message_get_path(msg); 1470 1471 dbus_message_iter_init(msg, &iter); 1472 1473 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32) { 1474 error("Unexpected signature in hal PropertyModified signal"); 1475 return; 1476 } 1477 1478 dbus_message_iter_get_basic(&iter, &num_changes); 1479 dbus_message_iter_next(&iter); 1480 1481 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) { 1482 error("Unexpected signature in hal PropertyModified signal"); 1483 return; 1484 } 1485 1486 dbus_message_iter_recurse(&iter, &array); 1487 1488 while (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_INVALID) { 1489 DBusMessageIter prop; 1490 const char *name; 1491 dbus_bool_t added, removed; 1492 1493 dbus_message_iter_recurse(&array, &prop); 1494 1495 if (!iter_get_basic_args(&prop, 1496 DBUS_TYPE_STRING, &name, 1497 DBUS_TYPE_BOOLEAN, &added, 1498 DBUS_TYPE_BOOLEAN, &removed, 1499 DBUS_TYPE_INVALID)) { 1500 error("Invalid hal PropertyModified parameters"); 1501 break; 1502 } 1503 1504 if (g_str_equal(name, "battery.charge_level.last_full")) 1505 hal_get_integer(path, name, &battchg_last); 1506 else if (g_str_equal(name, "battery.charge_level.current")) 1507 hal_get_integer(path, name, &battchg_cur); 1508 else if (g_str_equal(name, "battery.charge_level.design")) 1509 hal_get_integer(path, name, &battchg_design); 1510 1511 dbus_message_iter_next(&array); 1512 } 1513 } 1514 1515 static void csd_call_free(struct csd_call *call) 1516 { 1517 if (!call) 1518 return; 1519 1520 g_free(call->object_path); 1521 g_free(call->number); 1522 1523 g_free(call); 1524 } 1525 1526 static void parse_call_list(DBusMessageIter *iter) 1527 { 1528 do { 1529 DBusMessageIter call_iter; 1530 struct csd_call *call; 1531 const char *object_path, *number; 1532 dbus_uint32_t status; 1533 dbus_bool_t originating, terminating, emerg, on_hold, conf; 1534 1535 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRUCT) { 1536 error("Unexpected signature in GetCallInfoAll reply"); 1537 break; 1538 } 1539 1540 dbus_message_iter_recurse(iter, &call_iter); 1541 1542 if (!iter_get_basic_args(&call_iter, 1543 DBUS_TYPE_OBJECT_PATH, &object_path, 1544 DBUS_TYPE_UINT32, &status, 1545 DBUS_TYPE_BOOLEAN, &originating, 1546 DBUS_TYPE_BOOLEAN, &terminating, 1547 DBUS_TYPE_BOOLEAN, &emerg, 1548 DBUS_TYPE_BOOLEAN, &on_hold, 1549 DBUS_TYPE_BOOLEAN, &conf, 1550 DBUS_TYPE_STRING, &number, 1551 DBUS_TYPE_INVALID)) { 1552 error("Parsing call D-Bus parameters failed"); 1553 break; 1554 } 1555 1556 call = find_call(object_path); 1557 if (!call) { 1558 call = g_new0(struct csd_call, 1); 1559 call->object_path = g_strdup(object_path); 1560 call->status = (int) status; 1561 calls = g_slist_append(calls, call); 1562 DBG("telephony-maemo: new csd call instance at %s", 1563 object_path); 1564 } 1565 1566 if (call->status == CSD_CALL_STATUS_IDLE) 1567 continue; 1568 1569 /* CSD gives incorrect call_hold property sometimes */ 1570 if ((call->status != CSD_CALL_STATUS_HOLD && on_hold) || 1571 (call->status == CSD_CALL_STATUS_HOLD && 1572 !on_hold)) { 1573 error("Conflicting call status and on_hold property!"); 1574 on_hold = call->status == CSD_CALL_STATUS_HOLD; 1575 } 1576 1577 call->originating = originating; 1578 call->on_hold = on_hold; 1579 call->conference = conf; 1580 g_free(call->number); 1581 call->number = g_strdup(number); 1582 1583 } while (dbus_message_iter_next(iter)); 1584 } 1585 1586 static void signal_strength_reply(DBusPendingCall *call, void *user_data) 1587 { 1588 DBusError err; 1589 DBusMessage *reply; 1590 uint8_t signals_bar, rssi_in_dbm; 1591 dbus_int32_t net_err; 1592 1593 reply = dbus_pending_call_steal_reply(call); 1594 1595 dbus_error_init(&err); 1596 if (dbus_set_error_from_message(&err, reply)) { 1597 error("Unable to get signal strength: %s, %s", 1598 err.name, err.message); 1599 dbus_error_free(&err); 1600 goto done; 1601 } 1602 1603 dbus_error_init(&err); 1604 if (!dbus_message_get_args(reply, &err, 1605 DBUS_TYPE_BYTE, &signals_bar, 1606 DBUS_TYPE_BYTE, &rssi_in_dbm, 1607 DBUS_TYPE_INT32, &net_err, 1608 DBUS_TYPE_INVALID)) { 1609 error("Unable to parse signal_strength reply: %s, %s", 1610 err.name, err.message); 1611 dbus_error_free(&err); 1612 return; 1613 } 1614 1615 if (net_err != 0) { 1616 error("get_signal_strength failed with code %d", net_err); 1617 return; 1618 } 1619 1620 update_signal_strength(signals_bar); 1621 1622 done: 1623 dbus_message_unref(reply); 1624 } 1625 1626 static int get_signal_strength(void) 1627 { 1628 return send_method_call(NETWORK_BUS_NAME, NETWORK_PATH, 1629 NETWORK_INTERFACE, "get_signal_strength", 1630 signal_strength_reply, NULL, 1631 DBUS_TYPE_INVALID); 1632 } 1633 1634 static void registration_status_reply(DBusPendingCall *call, void *user_data) 1635 { 1636 DBusError err; 1637 DBusMessage *reply; 1638 uint8_t status; 1639 dbus_uint16_t lac, network_type, supported_services; 1640 dbus_uint32_t cell_id, operator_code, country_code; 1641 dbus_int32_t net_err; 1642 1643 reply = dbus_pending_call_steal_reply(call); 1644 1645 dbus_error_init(&err); 1646 if (dbus_set_error_from_message(&err, reply)) { 1647 error("Unable to get registration status: %s, %s", 1648 err.name, err.message); 1649 dbus_error_free(&err); 1650 goto done; 1651 } 1652 1653 dbus_error_init(&err); 1654 if (!dbus_message_get_args(reply, &err, 1655 DBUS_TYPE_BYTE, &status, 1656 DBUS_TYPE_UINT16, &lac, 1657 DBUS_TYPE_UINT32, &cell_id, 1658 DBUS_TYPE_UINT32, &operator_code, 1659 DBUS_TYPE_UINT32, &country_code, 1660 DBUS_TYPE_BYTE, &network_type, 1661 DBUS_TYPE_BYTE, &supported_services, 1662 DBUS_TYPE_INT32, &net_err, 1663 DBUS_TYPE_INVALID)) { 1664 error("Unable to parse registration_status_change reply:" 1665 " %s, %s", err.name, err.message); 1666 dbus_error_free(&err); 1667 return; 1668 } 1669 1670 if (net_err != 0) { 1671 error("get_registration_status failed with code %d", net_err); 1672 return; 1673 } 1674 1675 update_registration_status(status, lac, cell_id, operator_code, 1676 country_code, network_type, 1677 supported_services); 1678 1679 get_signal_strength(); 1680 1681 done: 1682 dbus_message_unref(reply); 1683 } 1684 1685 static int get_registration_status(void) 1686 { 1687 return send_method_call(NETWORK_BUS_NAME, NETWORK_PATH, 1688 NETWORK_INTERFACE, "get_registration_status", 1689 registration_status_reply, NULL, 1690 DBUS_TYPE_INVALID); 1691 } 1692 1693 static void call_info_reply(DBusPendingCall *call, void *user_data) 1694 { 1695 DBusError err; 1696 DBusMessage *reply; 1697 DBusMessageIter iter, sub;; 1698 1699 get_calls_active = FALSE; 1700 1701 reply = dbus_pending_call_steal_reply(call); 1702 1703 dbus_error_init(&err); 1704 if (dbus_set_error_from_message(&err, reply)) { 1705 error("csd replied with an error: %s, %s", 1706 err.name, err.message); 1707 dbus_error_free(&err); 1708 goto done; 1709 } 1710 1711 dbus_message_iter_init(reply, &iter); 1712 1713 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) { 1714 error("Unexpected signature in GetCallInfoAll return"); 1715 goto done; 1716 } 1717 1718 dbus_message_iter_recurse(&iter, &sub); 1719 1720 parse_call_list(&sub); 1721 1722 get_registration_status(); 1723 1724 done: 1725 dbus_message_unref(reply); 1726 } 1727 1728 static void hal_find_device_reply(DBusPendingCall *call, void *user_data) 1729 { 1730 DBusError err; 1731 DBusMessage *reply; 1732 DBusMessageIter iter, sub; 1733 const char *path; 1734 char match_string[256]; 1735 int type; 1736 1737 reply = dbus_pending_call_steal_reply(call); 1738 1739 dbus_error_init(&err); 1740 if (dbus_set_error_from_message(&err, reply)) { 1741 error("hald replied with an error: %s, %s", 1742 err.name, err.message); 1743 dbus_error_free(&err); 1744 goto done; 1745 } 1746 1747 dbus_message_iter_init(reply, &iter); 1748 1749 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) { 1750 error("Unexpected signature in FindDeviceByCapability return"); 1751 goto done; 1752 } 1753 1754 dbus_message_iter_recurse(&iter, &sub); 1755 1756 type = dbus_message_iter_get_arg_type(&sub); 1757 1758 if (type != DBUS_TYPE_OBJECT_PATH && type != DBUS_TYPE_STRING) { 1759 error("No hal device with battery capability found"); 1760 goto done; 1761 } 1762 1763 dbus_message_iter_get_basic(&sub, &path); 1764 1765 DBG("telephony-maemo: found battery device at %s", path); 1766 1767 snprintf(match_string, sizeof(match_string), 1768 "type='signal'," 1769 "path='%s'," 1770 "interface='org.freedesktop.Hal.Device'," 1771 "member='PropertyModified'", path); 1772 dbus_bus_add_match(connection, match_string, NULL); 1773 1774 hal_get_integer(path, "battery.charge_level.last_full", &battchg_last); 1775 hal_get_integer(path, "battery.charge_level.current", &battchg_cur); 1776 hal_get_integer(path, "battery.charge_level.design", &battchg_design); 1777 1778 done: 1779 dbus_message_unref(reply); 1780 } 1781 1782 static void phonebook_read_reply(DBusPendingCall *call, void *user_data) 1783 { 1784 DBusError derr; 1785 DBusMessage *reply; 1786 const char *name, *number; 1787 char **number_type = user_data; 1788 dbus_int32_t current_location, err; 1789 1790 reply = dbus_pending_call_steal_reply(call); 1791 1792 dbus_error_init(&derr); 1793 if (dbus_set_error_from_message(&derr, reply)) { 1794 error("SIM.Phonebook replied with an error: %s, %s", 1795 derr.name, derr.message); 1796 dbus_error_free(&derr); 1797 goto done; 1798 } 1799 1800 dbus_error_init(&derr); 1801 if (dbus_message_get_args(reply, &derr, 1802 DBUS_TYPE_STRING, &name, 1803 DBUS_TYPE_STRING, &number, 1804 DBUS_TYPE_INT32, ¤t_location, 1805 DBUS_TYPE_INT32, &err, 1806 DBUS_TYPE_INVALID) == FALSE) { 1807 error("Unable to parse SIM.Phonebook.read arguments: %s, %s", 1808 derr.name, derr.message); 1809 dbus_error_free(&derr); 1810 goto done; 1811 } 1812 1813 if (err != 0) { 1814 error("SIM.Phonebook.read failed with error %d", err); 1815 if (number_type == &vmbx) 1816 vmbx = g_strdup(getenv("VMBX_NUMBER")); 1817 goto done; 1818 } 1819 1820 if (number_type == &msisdn) { 1821 g_free(msisdn); 1822 msisdn = g_strdup(number); 1823 DBG("Got MSISDN %s (%s)", number, name); 1824 } else { 1825 g_free(vmbx); 1826 vmbx = g_strdup(number); 1827 DBG("Got voice mailbox number %s (%s)", number, name); 1828 } 1829 1830 done: 1831 dbus_message_unref(reply); 1832 } 1833 1834 static void csd_init(void) 1835 { 1836 dbus_uint32_t location; 1837 uint8_t pb_type, location_type; 1838 int ret; 1839 1840 ret = send_method_call(CSD_CALL_BUS_NAME, CSD_CALL_PATH, 1841 CSD_CALL_INTERFACE, "GetCallInfoAll", 1842 call_info_reply, NULL, DBUS_TYPE_INVALID); 1843 if (ret < 0) { 1844 error("Unable to sent GetCallInfoAll method call"); 1845 return; 1846 } 1847 1848 get_calls_active = TRUE; 1849 1850 pb_type = SIM_PHONEBOOK_TYPE_MSISDN; 1851 location = PHONEBOOK_INDEX_FIRST_ENTRY; 1852 location_type = SIM_PHONEBOOK_LOCATION_NEXT; 1853 1854 ret = send_method_call(SIM_PHONEBOOK_BUS_NAME, SIM_PHONEBOOK_PATH, 1855 SIM_PHONEBOOK_INTERFACE, "read", 1856 phonebook_read_reply, &msisdn, 1857 DBUS_TYPE_BYTE, &pb_type, 1858 DBUS_TYPE_INT32, &location, 1859 DBUS_TYPE_BYTE, &location_type, 1860 DBUS_TYPE_INVALID); 1861 if (ret < 0) { 1862 error("Unable to send " SIM_PHONEBOOK_INTERFACE ".read()"); 1863 return; 1864 } 1865 1866 pb_type = SIM_PHONEBOOK_TYPE_MBDN; 1867 location = PHONEBOOK_INDEX_FIRST_ENTRY; 1868 location_type = SIM_PHONEBOOK_LOCATION_NEXT; 1869 1870 ret = send_method_call(SIM_PHONEBOOK_BUS_NAME, SIM_PHONEBOOK_PATH, 1871 SIM_PHONEBOOK_INTERFACE, "read", 1872 phonebook_read_reply, &vmbx, 1873 DBUS_TYPE_BYTE, &pb_type, 1874 DBUS_TYPE_INT32, &location, 1875 DBUS_TYPE_BYTE, &location_type, 1876 DBUS_TYPE_INVALID); 1877 if (ret < 0) { 1878 error("Unable to send " SIM_PHONEBOOK_INTERFACE ".read()"); 1879 return; 1880 } 1881 } 1882 1883 static inline DBusMessage *invalid_args(DBusMessage *msg) 1884 { 1885 return g_dbus_create_error(msg,"org.bluez.Error.InvalidArguments", 1886 "Invalid arguments in method call"); 1887 } 1888 1889 static uint32_t get_callflag(const char *callerid_setting) 1890 { 1891 if (callerid_setting != NULL) { 1892 if (g_str_equal(callerid_setting, "allowed")) 1893 return CALL_FLAG_PRESENTATION_ALLOWED; 1894 else if (g_str_equal(callerid_setting, "restricted")) 1895 return CALL_FLAG_PRESENTATION_RESTRICTED; 1896 else 1897 return CALL_FLAG_NONE; 1898 } else 1899 return CALL_FLAG_NONE; 1900 } 1901 1902 static void generate_flag_file(const char *filename) 1903 { 1904 int fd; 1905 1906 if (g_file_test(ALLOWED_FLAG_FILE, G_FILE_TEST_EXISTS) || 1907 g_file_test(RESTRICTED_FLAG_FILE, G_FILE_TEST_EXISTS) || 1908 g_file_test(NONE_FLAG_FILE, G_FILE_TEST_EXISTS)) 1909 return; 1910 1911 fd = open(filename, O_WRONLY | O_CREAT, 0); 1912 if (fd >= 0) 1913 close(fd); 1914 } 1915 1916 static void save_callerid_to_file(const char *callerid_setting) 1917 { 1918 char callerid_file[FILENAME_MAX]; 1919 1920 snprintf(callerid_file, sizeof(callerid_file), "%s%s", 1921 CALLERID_BASE, callerid_setting); 1922 1923 if (g_file_test(ALLOWED_FLAG_FILE, G_FILE_TEST_EXISTS)) 1924 rename(ALLOWED_FLAG_FILE, callerid_file); 1925 else if (g_file_test(RESTRICTED_FLAG_FILE, G_FILE_TEST_EXISTS)) 1926 rename(RESTRICTED_FLAG_FILE, callerid_file); 1927 else if (g_file_test(NONE_FLAG_FILE, G_FILE_TEST_EXISTS)) 1928 rename(NONE_FLAG_FILE, callerid_file); 1929 else 1930 generate_flag_file(callerid_file); 1931 } 1932 1933 static uint32_t callerid_from_file(void) 1934 { 1935 if (g_file_test(ALLOWED_FLAG_FILE, G_FILE_TEST_EXISTS)) 1936 return CALL_FLAG_PRESENTATION_ALLOWED; 1937 else if (g_file_test(RESTRICTED_FLAG_FILE, G_FILE_TEST_EXISTS)) 1938 return CALL_FLAG_PRESENTATION_RESTRICTED; 1939 else if (g_file_test(NONE_FLAG_FILE, G_FILE_TEST_EXISTS)) 1940 return CALL_FLAG_NONE; 1941 else 1942 return CALL_FLAG_NONE; 1943 } 1944 1945 static DBusMessage *set_callerid(DBusConnection *conn, DBusMessage *msg, 1946 void *data) 1947 { 1948 const char *callerid_setting; 1949 1950 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, 1951 &callerid_setting, 1952 DBUS_TYPE_INVALID) == FALSE) 1953 return invalid_args(msg); 1954 1955 if (g_str_equal(callerid_setting, "allowed") || 1956 g_str_equal(callerid_setting, "restricted") || 1957 g_str_equal(callerid_setting, "none")) { 1958 save_callerid_to_file(callerid_setting); 1959 callerid = get_callflag(callerid_setting); 1960 DBG("telephony-maemo setting callerid flag: %s", 1961 callerid_setting); 1962 return dbus_message_new_method_return(msg); 1963 } 1964 1965 error("telephony-maemo: invalid argument %s for method call" 1966 " SetCallerId", callerid_setting); 1967 return invalid_args(msg); 1968 } 1969 1970 static GDBusMethodTable telephony_maemo_methods[] = { 1971 {"SetCallerId", "s", "", set_callerid, 1972 G_DBUS_METHOD_FLAG_ASYNC}, 1973 { } 1974 }; 1975 1976 static void handle_modem_state(DBusMessage *msg) 1977 { 1978 const char *state; 1979 1980 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &state, 1981 DBUS_TYPE_INVALID)) { 1982 error("Unexpected modem state parameters"); 1983 return; 1984 } 1985 1986 DBG("SSC modem state: %s", state); 1987 1988 if (calls != NULL || get_calls_active) 1989 return; 1990 1991 if (g_str_equal(state, "cmt_ready") || g_str_equal(state, "online")) 1992 csd_init(); 1993 } 1994 1995 static void modem_state_reply(DBusPendingCall *call, void *user_data) 1996 { 1997 DBusMessage *reply = dbus_pending_call_steal_reply(call); 1998 DBusError err; 1999 2000 dbus_error_init(&err); 2001 if (dbus_set_error_from_message(&err, reply)) { 2002 error("get_modem_status: %s, %s", err.name, err.message); 2003 dbus_error_free(&err); 2004 } else 2005 handle_modem_state(reply); 2006 2007 dbus_message_unref(reply); 2008 } 2009 2010 static DBusHandlerResult signal_filter(DBusConnection *conn, 2011 DBusMessage *msg, void *data) 2012 { 2013 const char *path = dbus_message_get_path(msg); 2014 2015 if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) 2016 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 2017 2018 if (dbus_message_is_signal(msg, CSD_CALL_INTERFACE, "Coming")) 2019 handle_incoming_call(msg); 2020 else if (dbus_message_is_signal(msg, CSD_CALL_INTERFACE, "Created")) 2021 handle_outgoing_call(msg); 2022 else if (dbus_message_is_signal(msg, CSD_CALL_INTERFACE, 2023 "CreateRequested")) 2024 handle_create_requested(msg); 2025 else if (dbus_message_is_signal(msg, CSD_CALL_INSTANCE, "CallStatus")) 2026 handle_call_status(msg, path); 2027 else if (dbus_message_is_signal(msg, CSD_CALL_CONFERENCE, "Joined")) 2028 handle_conference(msg, TRUE); 2029 else if (dbus_message_is_signal(msg, CSD_CALL_CONFERENCE, "Left")) 2030 handle_conference(msg, FALSE); 2031 else if (dbus_message_is_signal(msg, NETWORK_INTERFACE, 2032 "registration_status_change")) 2033 handle_registration_status_change(msg); 2034 else if (dbus_message_is_signal(msg, NETWORK_INTERFACE, 2035 "signal_strength_change")) 2036 handle_signal_strength_change(msg); 2037 else if (dbus_message_is_signal(msg, "org.freedesktop.Hal.Device", 2038 "PropertyModified")) 2039 handle_hal_property_modified(msg); 2040 else if (dbus_message_is_signal(msg, SSC_DBUS_IFACE, 2041 "modem_state_changed_ind")) 2042 handle_modem_state(msg); 2043 2044 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 2045 } 2046 2047 int telephony_init(void) 2048 { 2049 const char *battery_cap = "battery"; 2050 uint32_t features = AG_FEATURE_EC_ANDOR_NR | 2051 AG_FEATURE_INBAND_RINGTONE | 2052 AG_FEATURE_REJECT_A_CALL | 2053 AG_FEATURE_ENHANCED_CALL_STATUS | 2054 AG_FEATURE_ENHANCED_CALL_CONTROL | 2055 AG_FEATURE_EXTENDED_ERROR_RESULT_CODES | 2056 AG_FEATURE_THREE_WAY_CALLING; 2057 2058 connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); 2059 2060 if (!dbus_connection_add_filter(connection, signal_filter, 2061 NULL, NULL)) 2062 error("Can't add signal filter"); 2063 2064 dbus_bus_add_match(connection, 2065 "type=signal,interface=" CSD_CALL_INTERFACE, NULL); 2066 dbus_bus_add_match(connection, 2067 "type=signal,interface=" CSD_CALL_INSTANCE, NULL); 2068 dbus_bus_add_match(connection, 2069 "type=signal,interface=" CSD_CALL_CONFERENCE, NULL); 2070 dbus_bus_add_match(connection, 2071 "type=signal,interface=" NETWORK_INTERFACE, NULL); 2072 dbus_bus_add_match(connection, 2073 "type=signal,interface=" SSC_DBUS_IFACE 2074 ",member=modem_state_changed_ind", NULL); 2075 2076 if (send_method_call(SSC_DBUS_NAME, SSC_DBUS_PATH, SSC_DBUS_IFACE, 2077 "get_modem_state", modem_state_reply, 2078 NULL, DBUS_TYPE_INVALID) < 0) 2079 error("Unable to send " SSC_DBUS_IFACE ".get_modem_state()"); 2080 2081 generate_flag_file(NONE_FLAG_FILE); 2082 callerid = callerid_from_file(); 2083 2084 if (!g_dbus_register_interface(connection, TELEPHONY_MAEMO_PATH, 2085 TELEPHONY_MAEMO_INTERFACE, telephony_maemo_methods, 2086 NULL, NULL, NULL, NULL)) { 2087 error("telephony-maemo interface %s init failed on path %s", 2088 TELEPHONY_MAEMO_INTERFACE, TELEPHONY_MAEMO_PATH); 2089 } 2090 2091 DBG("telephony-maemo registering %s interface on path %s", 2092 TELEPHONY_MAEMO_INTERFACE, TELEPHONY_MAEMO_PATH); 2093 2094 telephony_ready_ind(features, maemo_indicators, response_and_hold, 2095 chld_str); 2096 if (send_method_call("org.freedesktop.Hal", 2097 "/org/freedesktop/Hal/Manager", 2098 "org.freedesktop.Hal.Manager", 2099 "FindDeviceByCapability", 2100 hal_find_device_reply, NULL, 2101 DBUS_TYPE_STRING, &battery_cap, 2102 DBUS_TYPE_INVALID) < 0) 2103 error("Unable to send HAL method call"); 2104 2105 return 0; 2106 } 2107 2108 void telephony_exit(void) 2109 { 2110 g_slist_foreach(calls, (GFunc) csd_call_free, NULL); 2111 g_slist_free(calls); 2112 calls = NULL; 2113 2114 dbus_connection_remove_filter(connection, signal_filter, NULL); 2115 2116 dbus_connection_unref(connection); 2117 connection = NULL; 2118 } 2119