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