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