Beispiel #1
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);
}
Beispiel #2
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 #3
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;
}