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