Beispiel #1
0
static DBusMessage *ussd_respond(DBusConnection *conn, DBusMessage *msg,
					void *data)
{
	struct ofono_ussd *ussd = data;
	const char *str;
	int dcs = 0x0f;
	unsigned char buf[160];
	long num_packed;

	if (ussd->pending)
		return __ofono_error_busy(msg);

	if (ussd->state != USSD_STATE_USER_ACTION)
		return __ofono_error_not_active(msg);

	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &str,
					DBUS_TYPE_INVALID) == FALSE)
		return __ofono_error_invalid_args(msg);

	if (strlen(str) == 0)
		return __ofono_error_invalid_format(msg);

	if (!ussd_encode(str, &num_packed, buf))
		return __ofono_error_invalid_format(msg);

	if (ussd->driver->request == NULL)
		return __ofono_error_not_implemented(msg);

	ussd->pending = dbus_message_ref(msg);

	ussd->driver->request(ussd, dcs, buf, num_packed,
				ussd_response_callback, ussd);

	return NULL;
}
Beispiel #2
0
static DBusMessage *ussd_initiate(DBusConnection *conn, DBusMessage *msg,
					void *data)
{
	struct ofono_ussd *ussd = data;
	struct ofono_modem *modem = __ofono_atom_get_modem(ussd->atom);
	struct ofono_voicecall *vc;
	gboolean call_in_progress;
	const char *str;
	int dcs = 0x0f;
	unsigned char buf[160];
	long num_packed;

	if (__ofono_ussd_is_busy(ussd))
		return __ofono_error_busy(msg);

	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &str,
					DBUS_TYPE_INVALID) == FALSE)
		return __ofono_error_invalid_args(msg);

	if (strlen(str) == 0)
		return __ofono_error_invalid_format(msg);

	DBG("checking if this is a recognized control string");
	if (recognized_control_string(ussd, str, msg))
		return NULL;

	vc = __ofono_atom_find(OFONO_ATOM_TYPE_VOICECALL, modem);
	if (vc)
		call_in_progress = __ofono_voicecall_is_busy(vc,
					OFONO_VOICECALL_INTERACTION_NONE);
	else
		call_in_progress = FALSE;

	DBG("No.., checking if this is a USSD string");
	if (!valid_ussd_string(str, call_in_progress))
		return __ofono_error_not_recognized(msg);

	if (!ussd_encode(str, &num_packed, buf))
		return __ofono_error_invalid_format(msg);

	if (ussd->driver->request == NULL)
		return __ofono_error_not_implemented(msg);

	DBG("OK, running USSD request");

	ussd->pending = dbus_message_ref(msg);

	ussd->driver->request(ussd, dcs, buf, num_packed, ussd_callback, ussd);

	return NULL;
}
Beispiel #3
0
/*
 * Pre-process a SMS text message and deliver it [D-Bus SendMessage()]
 *
 * @conn: D-Bus connection
 * @msg: message data (telephone number and text)
 * @data: SMS object to use for transmision
 *
 * An alphabet is chosen for the text and it (might be) segmented in
 * fragments by sms_text_prepare() into @msg_list. A queue list @entry
 * is created by tx_queue_entry_new() and g_queue_push_tail()
 * appends that entry to the SMS transmit queue. Then the tx_next()
 * function is scheduled to run to process the queue.
 */
static DBusMessage *sms_send_message(DBusConnection *conn, DBusMessage *msg,
					void *data)
{
	struct ofono_sms *sms = data;
	const char *to;
	const char *text;
	GSList *msg_list;
	struct ofono_modem *modem;
	unsigned int flags;
	gboolean use_16bit_ref = FALSE;
	int err;
	struct ofono_uuid uuid;

	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &to,
					DBUS_TYPE_STRING, &text,
					DBUS_TYPE_INVALID))
		return __ofono_error_invalid_args(msg);

	if (valid_phone_number_format(to) == FALSE)
		return __ofono_error_invalid_format(msg);

	msg_list = sms_text_prepare_with_alphabet(to, text, sms->ref,
						use_16bit_ref,
						sms->use_delivery_reports,
						sms->alphabet);

	if (msg_list == NULL)
		return __ofono_error_invalid_format(msg);

	flags = OFONO_SMS_SUBMIT_FLAG_RECORD_HISTORY;
	flags |= OFONO_SMS_SUBMIT_FLAG_RETRY;
	flags |= OFONO_SMS_SUBMIT_FLAG_EXPOSE_DBUS;
	if (sms->use_delivery_reports)
		flags |= OFONO_SMS_SUBMIT_FLAG_REQUEST_SR;

	err = __ofono_sms_txq_submit(sms, msg_list, flags, &uuid,
					message_queued, msg);

	g_slist_foreach(msg_list, (GFunc) g_free, NULL);
	g_slist_free(msg_list);

	if (err < 0)
		return __ofono_error_failed(msg);

	modem = __ofono_atom_get_modem(sms->atom);
	__ofono_history_sms_send_pending(modem, &uuid, to, time(NULL), text);

	return NULL;
}
Beispiel #4
0
static DBusMessage *stk_register_agent(DBusConnection *conn,
					DBusMessage *msg, void *data)
{
	struct ofono_stk *stk = data;
	const char *agent_path;

	if (stk->default_agent)
		return __ofono_error_busy(msg);

	if (dbus_message_get_args(msg, NULL,
					DBUS_TYPE_OBJECT_PATH, &agent_path,
					DBUS_TYPE_INVALID) == FALSE)
		return __ofono_error_invalid_args(msg);

	if (!__ofono_dbus_valid_object_path(agent_path))
		return __ofono_error_invalid_format(msg);

	stk->default_agent = stk_agent_new(agent_path,
						dbus_message_get_sender(msg),
						FALSE);
	if (!stk->default_agent)
		return __ofono_error_failed(msg);

	stk_agent_set_removed_notify(stk->default_agent,
					default_agent_notify, stk);

	if (!stk->session_agent)
		stk->current_agent = stk->default_agent;

	return dbus_message_new_method_return(msg);
}
Beispiel #5
0
static DBusMessage *cm_acm_reset(DBusConnection *conn, DBusMessage *msg,
					void *data)
{
	struct ofono_call_meter *cm = data;
	const char *pin2;

	if (cm->driver->acm_reset == NULL)
		return __ofono_error_not_implemented(msg);

	if (cm->pending)
		return __ofono_error_busy(msg);

	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pin2,
					DBUS_TYPE_INVALID) == FALSE)
		return __ofono_error_invalid_args(msg);

	if (!__ofono_is_valid_sim_pin(pin2, OFONO_SIM_PASSWORD_SIM_PIN2))
		return __ofono_error_invalid_format(msg);

	cm->pending = dbus_message_ref(msg);

	cm->driver->acm_reset(cm, pin2, acm_reset_callback, cm);

	return NULL;
}
Beispiel #6
0
static DBusMessage *gnss_register_agent(DBusConnection *conn,
					DBusMessage *msg, void *data)
{
	struct ofono_gnss *gnss = data;
	const char *agent_path;

	if (gnss->pending)
		return __ofono_error_busy(msg);

	if (gnss->posr_agent)
		return __ofono_error_busy(msg);

	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH,
				&agent_path, DBUS_TYPE_INVALID) == FALSE)
		return __ofono_error_invalid_args(msg);

	if (!__ofono_dbus_valid_object_path(agent_path))
		return __ofono_error_invalid_format(msg);

	gnss->posr_agent = gnss_agent_new(agent_path,
						dbus_message_get_sender(msg));

	if (gnss->posr_agent == NULL)
		return __ofono_error_failed(msg);

	gnss_agent_set_removed_notify(gnss->posr_agent,
					gnss_agent_notify, gnss);

	gnss->driver->set_position_reporting(gnss, TRUE, gnss_register_agent_cb,
						gnss);

	gnss->pending = dbus_message_ref(msg);

	return NULL;
}
Beispiel #7
0
static DBusMessage *stk_select_item(DBusConnection *conn,
					DBusMessage *msg, void *data)
{
	struct ofono_stk *stk = data;
	const char *agent_path;
	unsigned char selection, i;
	struct stk_envelope e;
	struct stk_menu *menu = stk->main_menu;

	if (stk->pending)
		return __ofono_error_busy(msg);

	if (stk->session_agent || !menu)
		return __ofono_error_busy(msg);

	if (dbus_message_get_args(msg, NULL,
					DBUS_TYPE_BYTE, &selection,
					DBUS_TYPE_OBJECT_PATH, &agent_path,
					DBUS_TYPE_INVALID) == FALSE)
		return __ofono_error_invalid_args(msg);

	if (!__ofono_dbus_valid_object_path(agent_path))
		return __ofono_error_invalid_format(msg);

	for (i = 0; i < selection && menu->items[i].text; i++);

	if (i != selection)
		return __ofono_error_invalid_format(msg);

	memset(&e, 0, sizeof(e));
	e.type = STK_ENVELOPE_TYPE_MENU_SELECTION;
	e.src = STK_DEVICE_IDENTITY_TYPE_KEYPAD,
	e.menu_selection.item_id = menu->items[selection].item_id;
	e.menu_selection.help_request = FALSE;

	if (stk_send_envelope(stk, &e, menu_selection_envelope_cb, 0))
		return __ofono_error_failed(msg);

	stk->pending = dbus_message_ref(msg);

	return NULL;
}
Beispiel #8
0
static DBusMessage *cm_set_property(DBusConnection *conn, DBusMessage *msg,
					void *data)
{
	struct ofono_call_meter *cm = data;
	DBusMessageIter iter;
	DBusMessageIter var;
	const char *name, *passwd = "";
	struct call_meter_property *property;

	if (cm->pending)
		return __ofono_error_busy(msg);

	if (!dbus_message_iter_init(msg, &iter))
		return __ofono_error_invalid_args(msg);

	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
		return __ofono_error_invalid_args(msg);

	dbus_message_iter_get_basic(&iter, &name);

	dbus_message_iter_next(&iter);

	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
		return __ofono_error_invalid_args(msg);

	dbus_message_iter_recurse(&iter, &var);

	if (!dbus_message_iter_next(&iter))
		return __ofono_error_invalid_args(msg);

	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
		return __ofono_error_invalid_args(msg);

	dbus_message_iter_get_basic(&iter, &passwd);

	if (!__ofono_is_valid_sim_pin(passwd, OFONO_SIM_PASSWORD_SIM_PIN2))
		return __ofono_error_invalid_format(msg);

	for (property = cm_properties; property->name; property++) {
		if (strcmp(name, property->name))
			continue;

		if (dbus_message_iter_get_arg_type(&var) != property->type)
			return __ofono_error_invalid_args(msg);

		return property->set(msg, cm, &var, passwd);
	}

	return __ofono_error_invalid_args(msg);
}
Beispiel #9
0
static gboolean recognized_passwd_change_string(struct ofono_ussd *ussd,
						int type, char *sc,
						char *sia, char *sib,
						char *sic, char *sid,
						char *dn, DBusMessage *msg)
{
	GSList *l = ussd->ss_passwd_list;

	switch (type) {
	case SS_CONTROL_TYPE_ACTIVATION:
	case SS_CONTROL_TYPE_REGISTRATION:
		break;

	default:
		return FALSE;
	}

	if (strcmp(sc, "03") || strlen(dn))
		return FALSE;

	/* If SIC & SID don't match, then we just bail out here */
	if (strcmp(sic, sid)) {
		DBusConnection *conn = ofono_dbus_get_connection();
		DBusMessage *reply = __ofono_error_invalid_format(msg);
		g_dbus_send_message(conn, reply);
		return TRUE;
	}

	while ((l = g_slist_find_custom(l, sia,
			ssc_entry_find_by_service)) != NULL) {
		struct ssc_entry *entry = l->data;
		ofono_ussd_passwd_cb_t cb = entry->cb;

		if (cb(sia, sib, sic, msg, entry->user))
			return TRUE;

		l = l->next;
	}

	return FALSE;
}
Beispiel #10
0
static DBusMessage *push_notification_register_agent(DBusConnection *conn,
						DBusMessage *msg, void *data)
{
	struct push_notification *pn = data;
	const char *agent_path;

	if (pn->agent)
		return __ofono_error_busy(msg);

	if (dbus_message_get_args(msg, NULL,
					DBUS_TYPE_OBJECT_PATH, &agent_path,
					DBUS_TYPE_INVALID) == FALSE)
		return __ofono_error_invalid_args(msg);

	if (!__ofono_dbus_valid_object_path(agent_path))
		return __ofono_error_invalid_format(msg);

	pn->agent = sms_agent_new(AGENT_INTERFACE,
					dbus_message_get_sender(msg),
					agent_path);

	if (pn->agent == NULL)
		return __ofono_error_failed(msg);

	sms_agent_set_removed_notify(pn->agent, agent_exited, pn);

	pn->push_watch[0] = __ofono_sms_datagram_watch_add(pn->sms,
							push_received,
							WAP_PUSH_DST_PORT,
							WAP_PUSH_SRC_PORT,
							pn, NULL);

	pn->push_watch[1] = __ofono_sms_datagram_watch_add(pn->sms,
							push_received,
							WAP_PUSH_DST_PORT,
							0, pn, NULL);

	return dbus_message_new_method_return(msg);
}
Beispiel #11
0
static DBusMessage *prop_set_cur(DBusMessage *msg, struct ofono_call_meter *cm,
				DBusMessageIter *var, const char *pin2)
{
	const char *value;

	if (cm->driver->puct_set == NULL || cm->driver->puct_query == NULL)
		return __ofono_error_not_implemented(msg);

	dbus_message_iter_get_basic(var, &value);

	if (strlen(value) > 3)
		return __ofono_error_invalid_format(msg);

	cm->pending = dbus_message_ref(msg);

	if (cm->flags & CALL_METER_FLAG_HAVE_PUCT)
		cm->driver->puct_set(cm, value, cm->ppu, pin2,
					set_puct_callback, cm);
	else
		cm->driver->puct_query(cm, set_puct_initial_query_callback, cm);

	return NULL;
}
Beispiel #12
0
static DBusMessage *cf_disable_all(DBusConnection *conn, DBusMessage *msg,
					void *data)
{
	struct ofono_call_forwarding *cf = data;
	const char *strtype;
	int type;

	if (cf->driver->erasure == NULL)
		return __ofono_error_not_implemented(msg);

	if (__ofono_call_forwarding_is_busy(cf) ||
			__ofono_ussd_is_busy(cf->ussd))
		return __ofono_error_busy(msg);

	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &strtype,
					DBUS_TYPE_INVALID) == FALSE)
		return __ofono_error_invalid_args(msg);

	if (!strcmp(strtype, "all") || !strcmp(strtype, ""))
		type = CALL_FORWARDING_TYPE_ALL;
	else if (!strcmp(strtype, "conditional"))
		type = CALL_FORWARDING_TYPE_ALL_CONDITIONAL;
	else
		return __ofono_error_invalid_format(msg);

	cf->pending = dbus_message_ref(msg);

	if (type == CALL_FORWARDING_TYPE_ALL)
		cf->driver->erasure(cf, type, BEARER_CLASS_DEFAULT,
				disable_all_callback, cf);
	else
		cf->driver->erasure(cf, type, BEARER_CLASS_DEFAULT,
				disable_conditional_callback, cf);

	return NULL;
}
Beispiel #13
0
static DBusMessage *sms_set_property(DBusConnection *conn, DBusMessage *msg,
					void *data)
{
	struct ofono_sms *sms = data;
	DBusMessageIter iter;
	DBusMessageIter var;
	const char *property;

	if (sms->pending)
		return __ofono_error_busy(msg);

	if (!dbus_message_iter_init(msg, &iter))
		return __ofono_error_invalid_args(msg);

	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
		return __ofono_error_invalid_args(msg);

	dbus_message_iter_get_basic(&iter, &property);
	dbus_message_iter_next(&iter);

	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
		return __ofono_error_invalid_args(msg);

	dbus_message_iter_recurse(&iter, &var);

	if (!strcmp(property, "ServiceCenterAddress")) {
		const char *value;
		struct ofono_phone_number sca;

		if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_STRING)
			return __ofono_error_invalid_args(msg);

		dbus_message_iter_get_basic(&var, &value);

		if (strlen(value) == 0 || !valid_phone_number_format(value))
			return __ofono_error_invalid_format(msg);

		if (sms->driver->sca_set == NULL ||
				sms->driver->sca_query == NULL)
			return __ofono_error_not_implemented(msg);

		string_to_phone_number(value, &sca);

		sms->pending = dbus_message_ref(msg);

		sms->driver->sca_set(sms, &sca, sca_set_callback, sms);
		return NULL;
	}

	if (!strcmp(property, "Bearer")) {
		const char *value;
		int bearer;

		if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_STRING)
			return __ofono_error_invalid_args(msg);

		dbus_message_iter_get_basic(&var, &value);

		if (sms_bearer_from_string(value, &bearer) != TRUE)
			return __ofono_error_invalid_format(msg);

		if (sms->driver->bearer_set == NULL ||
				sms->driver->bearer_query == NULL)
			return __ofono_error_not_implemented(msg);

		sms->pending = dbus_message_ref(msg);

		sms->driver->bearer_set(sms, bearer, bearer_set_callback, sms);
		return NULL;
	}

	if (!strcmp(property, "UseDeliveryReports")) {
		const char *path = __ofono_atom_get_path(sms->atom);
		dbus_bool_t value;

		if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_BOOLEAN)
			return __ofono_error_invalid_args(msg);

		dbus_message_iter_get_basic(&var, &value);

		g_dbus_send_reply(conn, msg, DBUS_TYPE_INVALID);

		if (sms->use_delivery_reports != (ofono_bool_t) value) {
			sms->use_delivery_reports = value;
			ofono_dbus_signal_property_changed(conn, path,
						OFONO_MESSAGE_MANAGER_INTERFACE,
						"UseDeliveryReports",
						DBUS_TYPE_BOOLEAN, &value);
		}

		return NULL;
	}

	if (!strcmp(property, "Alphabet")) {
		const char *value;
		enum sms_alphabet alphabet;

		if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_STRING)
			return __ofono_error_invalid_args(msg);

		dbus_message_iter_get_basic(&var, &value);

		if (!sms_alphabet_from_string(value, &alphabet))
			return __ofono_error_invalid_format(msg);

		set_alphabet(sms, alphabet);

		g_dbus_send_reply(conn, msg, DBUS_TYPE_INVALID);
		return NULL;
	}

	return __ofono_error_invalid_args(msg);
}
Beispiel #14
0
static gboolean cf_ss_control(int type, const char *sc,
				const char *sia, const char *sib,
				const char *sic, const char *dn,
				DBusMessage *msg, void *data)
{
	struct ofono_call_forwarding *cf = data;
	DBusConnection *conn = ofono_dbus_get_connection();
	int cls = BEARER_CLASS_SS_DEFAULT;
	int timeout = DEFAULT_NO_REPLY_TIMEOUT;
	int cf_type;
	DBusMessage *reply;
	struct ofono_phone_number ph;
	void *operation = NULL;

	/* Before we do anything, make sure we're actually initialized */
	if (cf == NULL)
		return FALSE;

	if (__ofono_call_forwarding_is_busy(cf)) {
		reply = __ofono_error_busy(msg);
		g_dbus_send_message(conn, reply);

		return TRUE;
	}

	DBG("Received call forwarding ss control request");

	DBG("type: %d, sc: %s, sia: %s, sib: %s, sic: %s, dn: %s",
		type, sc, sia, sib, sic, dn);

	if (!strcmp(sc, "21"))
		cf_type = CALL_FORWARDING_TYPE_UNCONDITIONAL;
	else if (!strcmp(sc, "67"))
		cf_type = CALL_FORWARDING_TYPE_BUSY;
	else if (!strcmp(sc, "61"))
		cf_type = CALL_FORWARDING_TYPE_NO_REPLY;
	else if (!strcmp(sc, "62"))
		cf_type = CALL_FORWARDING_TYPE_NOT_REACHABLE;
	else if (!strcmp(sc, "002"))
		cf_type = CALL_FORWARDING_TYPE_ALL;
	else if (!strcmp(sc, "004"))
		cf_type = CALL_FORWARDING_TYPE_ALL_CONDITIONAL;
	else
		return FALSE;

	if (strlen(sia) &&
		(type == SS_CONTROL_TYPE_QUERY ||
		type == SS_CONTROL_TYPE_ERASURE ||
		type == SS_CONTROL_TYPE_DEACTIVATION))
		goto error;

	/*
	 * Activation / Registration is figured context specific according to
	 * 22.030 Section 6.5.2 "The UE shall determine from the context
	 * whether, an entry of a single *, activation or registration
	 * was intended."
	 */
	if (type == SS_CONTROL_TYPE_ACTIVATION && strlen(sia) > 0)
		type = SS_CONTROL_TYPE_REGISTRATION;

	if (type == SS_CONTROL_TYPE_REGISTRATION &&
		!valid_phone_number_format(sia))
		goto error;

	if (strlen(sib) > 0) {
		long service_code;
		char *end;

		service_code = strtoul(sib, &end, 10);

		if (end == sib || *end != '\0')
			goto error;

		cls = mmi_service_code_to_bearer_class(service_code);

		if (cls == 0)
			goto error;
	}

	if (strlen(sic) > 0) {
		char *end;

		if  (type != SS_CONTROL_TYPE_REGISTRATION)
			goto error;

		if (cf_type != CALL_FORWARDING_TYPE_ALL &&
			cf_type != CALL_FORWARDING_TYPE_ALL_CONDITIONAL &&
			cf_type != CALL_FORWARDING_TYPE_NO_REPLY)
			goto error;

		timeout = strtoul(sic, &end, 10);

		if (end == sic || *end != '\0')
			goto error;

		if (timeout < 1 || timeout > 30)
			goto error;
	}

	switch (type) {
	case SS_CONTROL_TYPE_REGISTRATION:
		operation = cf->driver->registration;
		break;
	case SS_CONTROL_TYPE_ACTIVATION:
		operation = cf->driver->activation;
		break;
	case SS_CONTROL_TYPE_DEACTIVATION:
		operation = cf->driver->deactivation;
		break;
	case SS_CONTROL_TYPE_ERASURE:
		operation = cf->driver->erasure;
		break;
	case SS_CONTROL_TYPE_QUERY:
		operation = cf->driver->query;
		break;
	}

	if (operation == NULL) {
		reply = __ofono_error_not_implemented(msg);
		g_dbus_send_message(conn, reply);

		return TRUE;
	}

	cf->ss_req = g_try_new0(struct cf_ss_request, 1);

	if (cf->ss_req == NULL) {
		reply = __ofono_error_failed(msg);
		g_dbus_send_message(conn, reply);

		return TRUE;
	}

	cf->ss_req->ss_type = type;
	cf->ss_req->cf_type = cf_type;
	cf->ss_req->cls = cls;

	cf->pending = dbus_message_ref(msg);

	switch (cf->ss_req->cf_type) {
	case CALL_FORWARDING_TYPE_ALL:
		cf->query_next = CALL_FORWARDING_TYPE_UNCONDITIONAL;
		cf->query_end = CALL_FORWARDING_TYPE_NOT_REACHABLE;
		break;
	case CALL_FORWARDING_TYPE_ALL_CONDITIONAL:
		cf->query_next = CALL_FORWARDING_TYPE_BUSY;
		cf->query_end = CALL_FORWARDING_TYPE_NOT_REACHABLE;
		break;
	default:
		cf->query_next = cf->ss_req->cf_type;
		cf->query_end = cf->ss_req->cf_type;
		break;
	}

	/*
	 * Some modems don't understand all classes very well, particularly
	 * the older models.  So if the bearer class is the default, we
	 * just use the more commonly understood value of 7 since BEARER_SMS
	 * is not applicable to CallForwarding conditions according to 22.004
	 * Annex A
	 */
	if (cls == BEARER_CLASS_SS_DEFAULT)
		cls = BEARER_CLASS_DEFAULT;

	switch (cf->ss_req->ss_type) {
	case SS_CONTROL_TYPE_REGISTRATION:
		string_to_phone_number(sia, &ph);
		cf->driver->registration(cf, cf_type, cls, &ph, timeout,
					cf_ss_control_callback, cf);
		break;
	case SS_CONTROL_TYPE_ACTIVATION:
		cf->driver->activation(cf, cf_type, cls, cf_ss_control_callback,
					cf);
		break;
	case SS_CONTROL_TYPE_DEACTIVATION:
		cf->driver->deactivation(cf, cf_type, cls,
					cf_ss_control_callback, cf);
		break;
	case SS_CONTROL_TYPE_ERASURE:
		cf->driver->erasure(cf, cf_type, cls, cf_ss_control_callback,
					cf);
		break;
	case SS_CONTROL_TYPE_QUERY:
		ss_set_query_next_cf_cond(cf);
		break;
	}

	return TRUE;

error:
	reply = __ofono_error_invalid_format(msg);
	g_dbus_send_message(conn, reply);
	return TRUE;
}
Beispiel #15
0
static gboolean cb_ss_control(int type, const char *sc,
				const char *sia, const char *sib,
				const char *sic, const char *dn,
				DBusMessage *msg, void *data)
{
	struct ofono_call_barring *cb = data;
	DBusConnection *conn = ofono_dbus_get_connection();
	int cls = BEARER_CLASS_DEFAULT;
	const char *fac;
	DBusMessage *reply;
	void *operation = NULL;
	int i;

	if (cb->pending) {
		reply = __ofono_error_busy(msg);
		g_dbus_send_message(conn, reply);

		return TRUE;
	}

	DBG("Received call barring ss control request");

	DBG("type: %d, sc: %s, sia: %s, sib: %s, sic: %s, dn: %s",
		type, sc, sia, sib, sic, dn);

	fac = cb_ss_service_to_fac(sc);
	if (!fac)
		return FALSE;

	cb_set_query_bounds(cb, fac, type == SS_CONTROL_TYPE_QUERY);

	i = 0;
	while (cb_locks[i].name && strcmp(cb_locks[i].fac, fac))
		i++;

	cb->ss_req_lock = i;

	if (strlen(sic) > 0)
		goto bad_format;

	if (strlen(dn) > 0)
		goto bad_format;

	if (type != SS_CONTROL_TYPE_QUERY && !is_valid_pin(sia, PIN_TYPE_NET))
		goto bad_format;

	switch (type) {
	case SS_CONTROL_TYPE_ACTIVATION:
	case SS_CONTROL_TYPE_DEACTIVATION:
	case SS_CONTROL_TYPE_REGISTRATION:
	case SS_CONTROL_TYPE_ERASURE:
		operation = cb->driver->set;
		break;
	case SS_CONTROL_TYPE_QUERY:
		operation = cb->driver->query;
		break;
	default:
		break;
	}

	if (!operation) {
		reply = __ofono_error_not_implemented(msg);
		g_dbus_send_message(conn, reply);

		return TRUE;
	}

	/* According to 27.007, AG, AC and AB only work with mode = 0
	 * We support query by querying all relevant types, since we must
	 * do this for the deactivation case anyway
	 */
	if ((!strcmp(fac, "AG") || !strcmp(fac, "AC") || !strcmp(fac, "AB")) &&
		(type == SS_CONTROL_TYPE_ACTIVATION ||
			type == SS_CONTROL_TYPE_REGISTRATION))
		goto bad_format;

	if (strlen(sib) > 0) {
		long service_code;
		char *end;

		service_code = strtoul(sib, &end, 10);

		if (end == sib || *end != '\0')
			goto bad_format;

		cls = mmi_service_code_to_bearer_class(service_code);

		if (cls == 0)
			goto bad_format;
	}

	cb->ss_req_cls = cls;
	cb->pending = dbus_message_ref(msg);

	switch (type) {
	case SS_CONTROL_TYPE_ACTIVATION:
	case SS_CONTROL_TYPE_REGISTRATION:
		cb->ss_req_type = SS_CONTROL_TYPE_ACTIVATION;
		cb->driver->set(cb, fac, 1, sia, cls,
				cb_ss_set_lock_callback, cb);
		break;
	case SS_CONTROL_TYPE_ERASURE:
	case SS_CONTROL_TYPE_DEACTIVATION:
		cb->ss_req_type = SS_CONTROL_TYPE_DEACTIVATION;
		cb->driver->set(cb, fac, 0, sia, cls,
				cb_ss_set_lock_callback, cb);
		break;
	case SS_CONTROL_TYPE_QUERY:
		cb->ss_req_type = SS_CONTROL_TYPE_QUERY;
		cb_ss_query_next_lock(cb);
		break;
	}

	return TRUE;

bad_format:
	reply = __ofono_error_invalid_format(msg);
	g_dbus_send_message(conn, reply);
	return TRUE;
}
Beispiel #16
0
static DBusMessage *cv_set_property(DBusConnection *conn, DBusMessage *msg,
					void *data)
{
	struct ofono_call_volume *cv = data;
	DBusMessageIter iter;
	DBusMessageIter var;
	const char *property;

	if (cv->pending)
		return __ofono_error_busy(msg);

	if (!dbus_message_iter_init(msg, &iter))
		return __ofono_error_invalid_args(msg);

	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
		return __ofono_error_invalid_args(msg);

	dbus_message_iter_get_basic(&iter, &property);
	dbus_message_iter_next(&iter);

	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
		return __ofono_error_invalid_args(msg);

	dbus_message_iter_recurse(&iter, &var);

	if (g_str_equal(property, "SpeakerVolume") == TRUE) {
		unsigned char percent;

		if (cv->driver->speaker_volume == NULL)
			return __ofono_error_not_implemented(msg);

		if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_BYTE)
			return __ofono_error_invalid_args(msg);

		dbus_message_iter_get_basic(&var, &percent);

		if (percent > 100)
			return __ofono_error_invalid_format(msg);

		if (percent == cv->speaker_volume)
			return dbus_message_new_method_return(msg);

		cv->pending_volume = percent;
		cv->pending = dbus_message_ref(msg);
		cv->driver->speaker_volume(cv, percent, sv_set_callback, cv);

		return NULL;
	} else if (g_str_equal(property, "MicrophoneVolume") == TRUE) {
		unsigned char percent;

		if (cv->driver->microphone_volume == NULL)
			return __ofono_error_not_implemented(msg);

		if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_BYTE)
			return __ofono_error_invalid_args(msg);

		dbus_message_iter_get_basic(&var, &percent);

		if (percent > 100)
			return __ofono_error_invalid_format(msg);

		if (percent == cv->microphone_volume)
			return dbus_message_new_method_return(msg);

		cv->pending_volume = percent;
		cv->pending = dbus_message_ref(msg);
		cv->driver->microphone_volume(cv, percent, mv_set_callback, cv);

		return NULL;
	} else if (g_str_equal(property, "Muted") == TRUE) {
		dbus_bool_t muted;

		if (cv->driver->mute == NULL)
			return __ofono_error_not_implemented(msg);

		if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_BOOLEAN)
			return __ofono_error_invalid_args(msg);

		dbus_message_iter_get_basic(&var, &muted);

		if (muted == (dbus_bool_t) cv->muted)
			return dbus_message_new_method_return(msg);

		cv->muted_pending = muted;
		cv->pending = dbus_message_ref(msg);
		cv->driver->mute(cv, muted, muted_set_callback, cv);

		return NULL;
	}

	return __ofono_error_invalid_args(msg);
}
Beispiel #17
0
static DBusMessage *cf_set_property(DBusConnection *conn, DBusMessage *msg,
					void *data)
{
	struct ofono_call_forwarding *cf = data;
	struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
	DBusMessageIter iter;
	DBusMessageIter var;
	const char *property;
	int cls;
	int type;

	if (ofono_modem_get_online(modem) == FALSE)
		return __ofono_error_not_available(msg);

	if (__ofono_call_forwarding_is_busy(cf) ||
			__ofono_ussd_is_busy(cf->ussd))
		return __ofono_error_busy(msg);

	if (!dbus_message_iter_init(msg, &iter))
		return __ofono_error_invalid_args(msg);

	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
		return __ofono_error_invalid_args(msg);

	dbus_message_iter_get_basic(&iter, &property);
	dbus_message_iter_next(&iter);

	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
		return __ofono_error_invalid_args(msg);

	dbus_message_iter_recurse(&iter, &var);

	if (cf_condition_timeout_property(property, &cls)) {
		dbus_uint16_t timeout;
		GSList *l;
		struct ofono_call_forwarding_condition *c;

		type = CALL_FORWARDING_TYPE_NO_REPLY;

		if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_UINT16)
			return __ofono_error_invalid_args(msg);

		dbus_message_iter_get_basic(&var, &timeout);

		if (timeout < 1 || timeout > 30)
			return __ofono_error_invalid_format(msg);

		l = g_slist_find_custom(cf->cf_conditions[type],
				GINT_TO_POINTER(cls),
				cf_condition_find_with_cls);

		if (l == NULL)
			return __ofono_error_failed(msg);

		c = l->data;

		return set_property_request(cf, msg, type, cls,
						&c->phone_number, timeout);
	} else if (cf_condition_enabled_property(cf, property, &type, &cls)) {
		struct ofono_phone_number ph;
		const char *number;
		int timeout;

		ph.number[0] = '\0';
		ph.type = 129;

		if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_STRING)
			return __ofono_error_invalid_args(msg);

		dbus_message_iter_get_basic(&var, &number);

		if (strlen(number) > 0 && !valid_phone_number_format(number))
			return __ofono_error_invalid_format(msg);

		if (number[0] != '\0')
			string_to_phone_number(number, &ph);

		timeout = cf_find_timeout(cf->cf_conditions[type], cls);

		return set_property_request(cf, msg, type, cls, &ph,
						timeout);
	}

	return __ofono_error_invalid_args(msg);
}