mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	bluez5: backend-native: Link with ModemManager Voice object
The Voice object lists the Call objects, which provides status of each call. +CIND call indicator is set if at least one of the call is active. +CIND callsetup indicator is set if one of the call is in ringing in or out or dialing state.
This commit is contained in:
		
							parent
							
								
									275d2bc603
								
							
						
					
					
						commit
						5b40ed62b4
					
				
					 3 changed files with 304 additions and 3 deletions
				
			
		| 
						 | 
				
			
			@ -84,6 +84,8 @@ struct modem {
 | 
			
		|||
	unsigned int signal_strength;
 | 
			
		||||
	bool network_is_roaming;
 | 
			
		||||
	char *operator_name;
 | 
			
		||||
	bool active_call;
 | 
			
		||||
	unsigned int call_setup;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct impl {
 | 
			
		||||
| 
						 | 
				
			
			@ -111,6 +113,7 @@ struct impl {
 | 
			
		|||
	struct modem modem;
 | 
			
		||||
 | 
			
		||||
	void *modemmanager;
 | 
			
		||||
	struct spa_source *ring_timer;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct transport_data {
 | 
			
		||||
| 
						 | 
				
			
			@ -816,9 +819,9 @@ static bool rfcomm_hfp_ag(struct rfcomm *rfcomm, char* buf)
 | 
			
		|||
		rfcomm_send_reply(rfcomm, "+CIND:%s", CIND_INDICATORS);
 | 
			
		||||
		rfcomm_send_reply(rfcomm, "OK");
 | 
			
		||||
	} else if (spa_strstartswith(buf, "AT+CIND?")) {
 | 
			
		||||
		rfcomm_send_reply(rfcomm, "+CIND: %d,%d,0,0,%d,%d", backend->modem.network_has_service,
 | 
			
		||||
		                  rfcomm->cind_call_active,
 | 
			
		||||
		                  backend->modem.signal_strength, backend->modem.network_is_roaming);
 | 
			
		||||
		rfcomm_send_reply(rfcomm, "+CIND: %d,%d,%d,0,%d,%d", backend->modem.network_has_service,
 | 
			
		||||
		                  backend->modem.active_call, backend->modem.call_setup, backend->modem.signal_strength,
 | 
			
		||||
		                  backend->modem.network_is_roaming);
 | 
			
		||||
		rfcomm_send_reply(rfcomm, "OK");
 | 
			
		||||
	} else if (spa_strstartswith(buf, "AT+CMER")) {
 | 
			
		||||
		int mode, keyp, disp, ind;
 | 
			
		||||
| 
						 | 
				
			
			@ -2333,6 +2336,58 @@ static void send_ciev_for_each_rfcomm(struct impl *backend, int indicator, int v
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ring_timer_event(void *data, uint64_t expirations)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *backend = data;
 | 
			
		||||
	struct timespec ts;
 | 
			
		||||
	const uint64_t timeout = 1 * SPA_NSEC_PER_SEC;
 | 
			
		||||
	struct rfcomm *rfcomm;
 | 
			
		||||
 | 
			
		||||
	ts.tv_sec = timeout / SPA_NSEC_PER_SEC;
 | 
			
		||||
	ts.tv_nsec = timeout % SPA_NSEC_PER_SEC;
 | 
			
		||||
	spa_loop_utils_update_timer(backend->loop_utils, backend->ring_timer, &ts, NULL, false);
 | 
			
		||||
 | 
			
		||||
	spa_list_for_each(rfcomm, &backend->rfcomm_list, link) {
 | 
			
		||||
		if (rfcomm->slc_configured)
 | 
			
		||||
			rfcomm_send_reply(rfcomm, "RING");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void set_call_active(bool active, void *user_data)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *backend = user_data;
 | 
			
		||||
 | 
			
		||||
	if (backend->modem.active_call != active) {
 | 
			
		||||
		backend->modem.active_call = active;
 | 
			
		||||
		send_ciev_for_each_rfcomm(backend, CIND_CALL, active);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void set_call_setup(enum call_setup value, void *user_data)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *backend = user_data;
 | 
			
		||||
	enum call_setup old = backend->modem.call_setup;
 | 
			
		||||
 | 
			
		||||
	if (backend->modem.call_setup != value) {
 | 
			
		||||
		backend->modem.call_setup = value;
 | 
			
		||||
		send_ciev_for_each_rfcomm(backend, CIND_CALLSETUP, value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (value == CIND_CALLSETUP_INCOMING) {
 | 
			
		||||
		if (backend->ring_timer == NULL)
 | 
			
		||||
			backend->ring_timer = spa_loop_utils_add_timer(backend->loop_utils, ring_timer_event, backend);
 | 
			
		||||
 | 
			
		||||
		if (backend->ring_timer == NULL) {
 | 
			
		||||
			spa_log_warn(backend->log, "Failed to create ring timer");
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ring_timer_event(backend, 0);
 | 
			
		||||
	} else if (old == CIND_CALLSETUP_INCOMING) {
 | 
			
		||||
		spa_loop_utils_update_timer(backend->loop_utils, backend->ring_timer, NULL, NULL, false);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void set_modem_operator_name(const char *name, void *user_data)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *backend = user_data;
 | 
			
		||||
| 
						 | 
				
			
			@ -2389,6 +2444,9 @@ static int backend_native_free(void *data)
 | 
			
		|||
		backend->modemmanager = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (backend->ring_timer)
 | 
			
		||||
		spa_loop_utils_destroy_source(backend->loop_utils, backend->ring_timer);
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_BLUEZ_5_BACKEND_HSP_NATIVE
 | 
			
		||||
	dbus_connection_unregister_object_path(backend->conn, PROFILE_HSP_AG);
 | 
			
		||||
	dbus_connection_unregister_object_path(backend->conn, PROFILE_HSP_HS);
 | 
			
		||||
| 
						 | 
				
			
			@ -2443,6 +2501,8 @@ static const struct mm_ops mm_ops = {
 | 
			
		|||
	.set_modem_signal_strength = set_modem_signal_strength,
 | 
			
		||||
	.set_modem_operator_name = set_modem_operator_name,
 | 
			
		||||
	.set_modem_roaming = set_modem_roaming,
 | 
			
		||||
	.set_call_active = set_call_active,
 | 
			
		||||
	.set_call_setup = set_call_setup,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct spa_bt_backend *backend_native_new(struct spa_bt_monitor *monitor,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,6 +31,18 @@
 | 
			
		|||
 | 
			
		||||
#define DBUS_INTERFACE_OBJECTMANAGER "org.freedesktop.DBus.ObjectManager"
 | 
			
		||||
 | 
			
		||||
struct call {
 | 
			
		||||
	struct spa_list link;
 | 
			
		||||
	struct impl *this;
 | 
			
		||||
	DBusPendingCall *pending;
 | 
			
		||||
 | 
			
		||||
	char *path;
 | 
			
		||||
	char *number;
 | 
			
		||||
	bool call_indicator;
 | 
			
		||||
	MMCallDirection direction;
 | 
			
		||||
	MMCallState state;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct modem {
 | 
			
		||||
	char *path;
 | 
			
		||||
	bool network_has_service;
 | 
			
		||||
| 
						 | 
				
			
			@ -50,6 +62,7 @@ struct impl {
 | 
			
		|||
	void *user_data;
 | 
			
		||||
 | 
			
		||||
	struct modem modem;
 | 
			
		||||
	struct spa_list call_list;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static bool mm_dbus_connection_send_with_reply(struct impl *this, DBusMessage *m, DBusPendingCall **pending_return,
 | 
			
		||||
| 
						 | 
				
			
			@ -77,6 +90,132 @@ static bool mm_dbus_connection_send_with_reply(struct impl *this, DBusMessage *m
 | 
			
		|||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void mm_call_state_changed(struct impl *this)
 | 
			
		||||
{
 | 
			
		||||
	struct call *call;
 | 
			
		||||
	bool call_indicator = false;
 | 
			
		||||
	enum call_setup call_setup_indicator = CIND_CALLSETUP_NONE;
 | 
			
		||||
 | 
			
		||||
	spa_list_for_each(call, &this->call_list, link) {
 | 
			
		||||
		call_indicator |= (call->state == MM_CALL_STATE_ACTIVE);
 | 
			
		||||
 | 
			
		||||
		if (call->state == MM_CALL_STATE_RINGING_IN && call_setup_indicator < CIND_CALLSETUP_INCOMING)
 | 
			
		||||
			call_setup_indicator = CIND_CALLSETUP_INCOMING;
 | 
			
		||||
		else if (call->state == MM_CALL_STATE_DIALING && call_setup_indicator < CIND_CALLSETUP_DIALING)
 | 
			
		||||
			call_setup_indicator = CIND_CALLSETUP_DIALING;
 | 
			
		||||
		else if (call->state == MM_CALL_STATE_RINGING_OUT && call_setup_indicator < CIND_CALLSETUP_ALERTING)
 | 
			
		||||
			call_setup_indicator = CIND_CALLSETUP_ALERTING;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (this->ops->set_call_active)
 | 
			
		||||
		this->ops->set_call_active(call_indicator, this->user_data);
 | 
			
		||||
 | 
			
		||||
	if (this->ops->set_call_setup)
 | 
			
		||||
		this->ops->set_call_setup(call_setup_indicator, this->user_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void mm_get_call_properties_reply(DBusPendingCall *pending, void *user_data)
 | 
			
		||||
{
 | 
			
		||||
	struct call *call = user_data;
 | 
			
		||||
	struct impl *this = call->this;
 | 
			
		||||
	DBusMessage *r;
 | 
			
		||||
	DBusMessageIter arg_i, element_i;
 | 
			
		||||
	MMCallDirection direction;
 | 
			
		||||
	MMCallState state;
 | 
			
		||||
 | 
			
		||||
	spa_assert(call->pending == pending);
 | 
			
		||||
	dbus_pending_call_unref(pending);
 | 
			
		||||
	call->pending = NULL;
 | 
			
		||||
 | 
			
		||||
	r = dbus_pending_call_steal_reply(pending);
 | 
			
		||||
	if (r == NULL)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (dbus_message_is_error(r, DBUS_ERROR_UNKNOWN_METHOD)) {
 | 
			
		||||
		spa_log_warn(this->log, "ModemManager D-Bus Call not available");
 | 
			
		||||
		goto finish;
 | 
			
		||||
	}
 | 
			
		||||
	if (dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR) {
 | 
			
		||||
		spa_log_error(this->log, "GetAll() failed: %s", dbus_message_get_error_name(r));
 | 
			
		||||
		goto finish;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!dbus_message_iter_init(r, &arg_i) || !spa_streq(dbus_message_get_signature(r), "a{sv}")) {
 | 
			
		||||
		spa_log_error(this->log, "Invalid arguments in GetAll() reply");
 | 
			
		||||
		goto finish;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	spa_log_debug(this->log, "Call path: %s", call->path);
 | 
			
		||||
 | 
			
		||||
	dbus_message_iter_recurse(&arg_i, &element_i);
 | 
			
		||||
	while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
 | 
			
		||||
		DBusMessageIter i, value_i;
 | 
			
		||||
		const char *key;
 | 
			
		||||
 | 
			
		||||
		dbus_message_iter_recurse(&element_i, &i);
 | 
			
		||||
 | 
			
		||||
		dbus_message_iter_get_basic(&i, &key);
 | 
			
		||||
		dbus_message_iter_next(&i);
 | 
			
		||||
		dbus_message_iter_recurse(&i, &value_i);
 | 
			
		||||
 | 
			
		||||
		if (spa_streq(key, MM_CALL_PROPERTY_DIRECTION)) {
 | 
			
		||||
			dbus_message_iter_get_basic(&value_i, &direction);
 | 
			
		||||
			spa_log_debug(this->log, "Call direction: %u", direction);
 | 
			
		||||
			call->direction = direction;
 | 
			
		||||
		} else if (spa_streq(key, MM_CALL_PROPERTY_NUMBER)) {
 | 
			
		||||
			char *number;
 | 
			
		||||
 | 
			
		||||
			dbus_message_iter_get_basic(&value_i, &number);
 | 
			
		||||
			spa_log_debug(this->log, "Call number: %s", number);
 | 
			
		||||
			if (call->number)
 | 
			
		||||
				free(call->number);
 | 
			
		||||
			call->number = strdup(number);
 | 
			
		||||
		} else if (spa_streq(key, MM_CALL_PROPERTY_STATE)) {
 | 
			
		||||
			dbus_message_iter_get_basic(&value_i, &state);
 | 
			
		||||
			spa_log_debug(this->log, "Call state: %u", state);
 | 
			
		||||
			call->state = state;
 | 
			
		||||
			mm_call_state_changed(this);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		dbus_message_iter_next(&element_i);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
finish:
 | 
			
		||||
	dbus_message_unref(r);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static DBusHandlerResult mm_parse_voice_properties(struct impl *this, DBusMessageIter *props_i)
 | 
			
		||||
{
 | 
			
		||||
	while (dbus_message_iter_get_arg_type(props_i) != DBUS_TYPE_INVALID) {
 | 
			
		||||
		DBusMessageIter i, value_i, element_i;
 | 
			
		||||
		const char *key;
 | 
			
		||||
 | 
			
		||||
		dbus_message_iter_recurse(props_i, &i);
 | 
			
		||||
 | 
			
		||||
		dbus_message_iter_get_basic(&i, &key);
 | 
			
		||||
		dbus_message_iter_next(&i);
 | 
			
		||||
		dbus_message_iter_recurse(&i, &value_i);
 | 
			
		||||
 | 
			
		||||
		if (spa_streq(key, MM_MODEM_VOICE_PROPERTY_CALLS)) {
 | 
			
		||||
			spa_log_debug(this->log, "Voice properties");
 | 
			
		||||
			dbus_message_iter_recurse(&value_i, &element_i);
 | 
			
		||||
 | 
			
		||||
			while (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) {
 | 
			
		||||
				const char *call_object;
 | 
			
		||||
 | 
			
		||||
				dbus_message_iter_get_basic(&element_i, &call_object);
 | 
			
		||||
				spa_log_debug(this->log, "  Call: %s", call_object);
 | 
			
		||||
 | 
			
		||||
				dbus_message_iter_next(&element_i);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		dbus_message_iter_next(props_i);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return DBUS_HANDLER_RESULT_HANDLED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static DBusHandlerResult mm_parse_modem3gpp_properties(struct impl *this, DBusMessageIter *props_i)
 | 
			
		||||
{
 | 
			
		||||
	while (dbus_message_iter_get_arg_type(props_i) != DBUS_TYPE_INVALID) {
 | 
			
		||||
| 
						 | 
				
			
			@ -221,6 +360,9 @@ static DBusHandlerResult mm_parse_interfaces(struct impl *this, DBusMessageIter
 | 
			
		|||
		} else if (spa_streq(interface, MM_DBUS_INTERFACE_MODEM_MODEM3GPP)) {
 | 
			
		||||
			spa_log_debug(this->log, "Found Modem3GPP interface %s, path %s", interface, path);
 | 
			
		||||
			mm_parse_modem3gpp_properties(this, &props_i);
 | 
			
		||||
		} else if (spa_streq(interface, MM_DBUS_INTERFACE_MODEM_VOICE)) {
 | 
			
		||||
			spa_log_debug(this->log, "Found Voice interface %s, path %s", interface, path);
 | 
			
		||||
			mm_parse_voice_properties(this, &props_i);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		dbus_message_iter_next(&element_i);
 | 
			
		||||
| 
						 | 
				
			
			@ -267,6 +409,33 @@ finish:
 | 
			
		|||
	dbus_message_unref(r);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void call_free(struct call *call) {
 | 
			
		||||
	spa_list_remove(&call->link);
 | 
			
		||||
 | 
			
		||||
	if (call->pending != NULL) {
 | 
			
		||||
		dbus_pending_call_cancel(call->pending);
 | 
			
		||||
		dbus_pending_call_unref(call->pending);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (call->number)
 | 
			
		||||
		free(call->number);
 | 
			
		||||
	if (call->path)
 | 
			
		||||
		free(call->path);
 | 
			
		||||
	free(call);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void mm_clean_voice(struct impl *this)
 | 
			
		||||
{
 | 
			
		||||
	struct call *call;
 | 
			
		||||
 | 
			
		||||
	spa_list_consume(call, &this->call_list, link)
 | 
			
		||||
		call_free(call);
 | 
			
		||||
	if (this->ops->set_call_setup)
 | 
			
		||||
		this->ops->set_call_setup(CIND_CALLSETUP_NONE, this->user_data);
 | 
			
		||||
	if (this->ops->set_call_active)
 | 
			
		||||
		this->ops->set_call_active(false, this->user_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void mm_clean_modem3gpp(struct impl *this)
 | 
			
		||||
{
 | 
			
		||||
	if (this->ops->set_modem_operator_name)
 | 
			
		||||
| 
						 | 
				
			
			@ -312,6 +481,7 @@ static DBusHandlerResult mm_filter_cb(DBusConnection *bus, DBusMessage *m, void
 | 
			
		|||
		if (spa_streq(name, MM_DBUS_SERVICE)) {
 | 
			
		||||
			if (old_owner && *old_owner) {
 | 
			
		||||
				spa_log_debug(this->log, "ModemManager daemon disappeared (%s)", old_owner);
 | 
			
		||||
				mm_clean_voice(this);
 | 
			
		||||
				mm_clean_modem3gpp(this);
 | 
			
		||||
				mm_clean_modem(this);
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -355,6 +525,9 @@ static DBusHandlerResult mm_filter_cb(DBusConnection *bus, DBusMessage *m, void
 | 
			
		|||
				} else if (spa_streq(iface, MM_DBUS_INTERFACE_MODEM_MODEM3GPP)) {
 | 
			
		||||
					spa_log_debug(this->log, "Modem3GPP interface %s removed, path %s", iface, path);
 | 
			
		||||
					mm_clean_modem3gpp(this);
 | 
			
		||||
				} else if (spa_streq(iface, MM_DBUS_INTERFACE_MODEM_VOICE)) {
 | 
			
		||||
					spa_log_debug(this->log, "Voice interface %s removed, path %s", iface, path);
 | 
			
		||||
					mm_clean_voice(this);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				dbus_message_iter_next(&element_i);
 | 
			
		||||
| 
						 | 
				
			
			@ -383,7 +556,58 @@ static DBusHandlerResult mm_filter_cb(DBusConnection *bus, DBusMessage *m, void
 | 
			
		|||
		} else if (spa_streq(interface, MM_DBUS_INTERFACE_MODEM_MODEM3GPP)) {
 | 
			
		||||
			spa_log_debug(this->log, "Properties changed on %s", path);
 | 
			
		||||
			mm_parse_modem3gpp_properties(this, &props_i);
 | 
			
		||||
		} else if (spa_streq(interface, MM_DBUS_INTERFACE_MODEM_VOICE)) {
 | 
			
		||||
			spa_log_debug(this->log, "Properties changed on %s", path);
 | 
			
		||||
			mm_parse_voice_properties(this, &props_i);
 | 
			
		||||
		}
 | 
			
		||||
	} else if (dbus_message_is_signal(m, MM_DBUS_INTERFACE_MODEM_VOICE, MM_MODEM_VOICE_SIGNAL_CALLADDED)) {
 | 
			
		||||
		DBusMessageIter iface_i;
 | 
			
		||||
		const char *path;
 | 
			
		||||
		struct call *call_object;
 | 
			
		||||
		const char *mm_call_interface = MM_DBUS_INTERFACE_CALL;
 | 
			
		||||
 | 
			
		||||
		if (!dbus_message_iter_init(m, &iface_i) || !spa_streq(dbus_message_get_signature(m), "o")) {
 | 
			
		||||
				spa_log_error(this->log, "Invalid signature found in %s", MM_MODEM_VOICE_SIGNAL_CALLADDED);
 | 
			
		||||
				goto finish;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		dbus_message_iter_get_basic(&iface_i, &path);
 | 
			
		||||
		spa_log_debug(this->log, "New call: %s", path);
 | 
			
		||||
 | 
			
		||||
		call_object = calloc(1, sizeof(struct call));
 | 
			
		||||
		if (call_object == NULL)
 | 
			
		||||
			return DBUS_HANDLER_RESULT_NEED_MEMORY;
 | 
			
		||||
		call_object->this = this;
 | 
			
		||||
		call_object->path = strdup(path);
 | 
			
		||||
		spa_list_append(&this->call_list, &call_object->link);
 | 
			
		||||
 | 
			
		||||
		m = dbus_message_new_method_call(MM_DBUS_SERVICE, path, DBUS_INTERFACE_PROPERTIES, "GetAll");
 | 
			
		||||
		if (m == NULL)
 | 
			
		||||
			goto finish;
 | 
			
		||||
		dbus_message_append_args(m, DBUS_TYPE_STRING, &mm_call_interface, DBUS_TYPE_INVALID);
 | 
			
		||||
		if (!mm_dbus_connection_send_with_reply(this, m, &call_object->pending, mm_get_call_properties_reply, call_object)) {
 | 
			
		||||
			spa_log_error(this->log, "dbus call failure");
 | 
			
		||||
			dbus_message_unref(m);
 | 
			
		||||
			goto finish;
 | 
			
		||||
		}
 | 
			
		||||
	} else if (dbus_message_is_signal(m, MM_DBUS_INTERFACE_MODEM_VOICE, MM_MODEM_VOICE_SIGNAL_CALLDELETED)) {
 | 
			
		||||
		const char *path;
 | 
			
		||||
		DBusMessageIter iface_i;
 | 
			
		||||
		struct call *call, *call_tmp;
 | 
			
		||||
 | 
			
		||||
		if (!dbus_message_iter_init(m, &iface_i) || !spa_streq(dbus_message_get_signature(m), "o")) {
 | 
			
		||||
				spa_log_error(this->log, "Invalid signature found in %s", MM_MODEM_VOICE_SIGNAL_CALLDELETED);
 | 
			
		||||
				goto finish;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		dbus_message_iter_get_basic(&iface_i, &path);
 | 
			
		||||
		spa_log_debug(this->log, "Call ended: %s", path);
 | 
			
		||||
 | 
			
		||||
		spa_list_for_each_safe(call, call_tmp, &this->call_list, link) {
 | 
			
		||||
			if (spa_streq(call->path, path))
 | 
			
		||||
				call_free(call);
 | 
			
		||||
		}
 | 
			
		||||
		mm_call_state_changed(this);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
finish:
 | 
			
		||||
| 
						 | 
				
			
			@ -416,6 +640,12 @@ static int add_filters(struct impl *this)
 | 
			
		|||
	dbus_bus_add_match(this->conn,
 | 
			
		||||
			"type='signal',sender='" MM_DBUS_SERVICE "',"
 | 
			
		||||
			"interface='" DBUS_INTERFACE_PROPERTIES "',member='" DBUS_SIGNAL_PROPERTIES_CHANGED "'", &err);
 | 
			
		||||
	dbus_bus_add_match(this->conn,
 | 
			
		||||
			"type='signal',sender='" MM_DBUS_SERVICE "',"
 | 
			
		||||
			"interface='" MM_DBUS_INTERFACE_MODEM_VOICE "',member='" MM_MODEM_VOICE_SIGNAL_CALLADDED "'", &err);
 | 
			
		||||
	dbus_bus_add_match(this->conn,
 | 
			
		||||
			"type='signal',sender='" MM_DBUS_SERVICE "',"
 | 
			
		||||
			"interface='" MM_DBUS_INTERFACE_MODEM_VOICE "',member='" MM_MODEM_VOICE_SIGNAL_CALLDELETED "'", &err);
 | 
			
		||||
 | 
			
		||||
	this->filters_added = true;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -484,6 +714,7 @@ void *mm_register(struct spa_log *log, void *dbus_connection, const struct mm_op
 | 
			
		|||
	this->conn = dbus_connection;
 | 
			
		||||
	this->ops = ops;
 | 
			
		||||
	this->user_data = user_data;
 | 
			
		||||
	spa_list_init(&this->call_list);
 | 
			
		||||
 | 
			
		||||
	if (add_filters(this) < 0) {
 | 
			
		||||
		goto fail;
 | 
			
		||||
| 
						 | 
				
			
			@ -520,6 +751,7 @@ void mm_unregister(void *data)
 | 
			
		|||
		dbus_pending_call_unref(this->pending);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mm_clean_voice(this);
 | 
			
		||||
	mm_clean_modem3gpp(this);
 | 
			
		||||
	mm_clean_modem(this);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,11 +27,20 @@
 | 
			
		|||
 | 
			
		||||
#include "defs.h"
 | 
			
		||||
 | 
			
		||||
enum call_setup {
 | 
			
		||||
	CIND_CALLSETUP_NONE = 0,
 | 
			
		||||
	CIND_CALLSETUP_INCOMING,
 | 
			
		||||
	CIND_CALLSETUP_DIALING,
 | 
			
		||||
	CIND_CALLSETUP_ALERTING
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mm_ops {
 | 
			
		||||
	void (*set_modem_service)(bool available, void *user_data);
 | 
			
		||||
	void (*set_modem_signal_strength)(unsigned int strength, void *user_data);
 | 
			
		||||
	void (*set_modem_operator_name)(const char *name, void *user_data);
 | 
			
		||||
	void (*set_modem_roaming)(bool is_roaming, void *user_data);
 | 
			
		||||
	void (*set_call_active)(bool active, void *user_data);
 | 
			
		||||
	void (*set_call_setup)(enum call_setup value, void *user_data);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_BLUEZ_5_BACKEND_NATIVE_MM
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue