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