mm-broadband-modem-qmi: reprobe on qmi-proxy death

This allows us to reprobe the modem and respawn the
qmi-proxy in case it dies on us. This gets us access
to the modem and unsolicited notifications again. Do
this by connecting to the device-removed signal on
QmiDevice.

---
Rebased on top of git master by
Aleksander Morgado <aleksander@aleksander.es>
This commit is contained in:
Eric Caruso
2017-10-20 10:10:47 -07:00
committed by Aleksander Morgado
parent b4278615fc
commit 098c4c0271
4 changed files with 77 additions and 7 deletions

View File

@@ -341,7 +341,7 @@ dnl-----------------------------------------------------------------------------
dnl QMI support (enabled by default)
dnl
LIBQMI_VERSION=1.17.900
LIBQMI_VERSION=1.19.1
AC_ARG_WITH(qmi, AS_HELP_STRING([--without-qmi], [Build without QMI support]), [], [with_qmi=yes])
AM_CONDITIONAL(WITH_QMI, test "x$with_qmi" = "xyes")

View File

@@ -126,6 +126,9 @@ struct _MMBroadbandModemQmiPrivate {
/* Firmware helpers */
GList *firmware_list;
MMFirmwareProperties *current_firmware;
/* For notifying when the qmi-proxy connection is dead */
guint qmi_device_removed_id;
};
/*****************************************************************************/
@@ -11198,6 +11201,54 @@ parent_initialization_started (GTask *task)
task);
}
static void
qmi_device_removed_cb (QmiDevice *device,
MMBroadbandModemQmi *self)
{
/* Reprobe the modem here so we can get notifications back. */
mm_info ("Connection to qmi-proxy for %s lost, reprobing",
qmi_device_get_path_display (device));
g_signal_handler_disconnect (device, self->priv->qmi_device_removed_id);
self->priv->qmi_device_removed_id = 0;
mm_base_modem_set_reprobe (MM_BASE_MODEM (self), TRUE);
mm_base_modem_set_valid (MM_BASE_MODEM (self), FALSE);
}
static void
track_qmi_device_removed (MMBroadbandModemQmi *self,
MMPortQmi* qmi)
{
QmiDevice *device;
device = mm_port_qmi_peek_device (qmi);
g_assert (device);
self->priv->qmi_device_removed_id = g_signal_connect (
device,
QMI_DEVICE_SIGNAL_REMOVED,
G_CALLBACK (qmi_device_removed_cb),
self);
}
static void
untrack_qmi_device_removed (MMBroadbandModemQmi *self,
MMPortQmi* qmi)
{
QmiDevice *device;
if (self->priv->qmi_device_removed_id == 0)
return;
device = mm_port_qmi_peek_device (qmi);
if (!device)
return;
g_signal_handler_disconnect (device, self->priv->qmi_device_removed_id);
self->priv->qmi_device_removed_id = 0;
}
static void allocate_next_client (GTask *task);
static void
@@ -11225,11 +11276,14 @@ static void
allocate_next_client (GTask *task)
{
InitializationStartedContext *ctx;
MMBroadbandModemQmi *self;
self = g_task_get_source_object (task);
ctx = g_task_get_task_data (task);
if (ctx->services[ctx->service_index] == QMI_SERVICE_UNKNOWN) {
/* Done we are, launch parent's callback */
/* Done we are, track device removal and launch parent's callback */
track_qmi_device_removed (self, ctx->qmi);
parent_initialization_started (task);
return;
}
@@ -11312,7 +11366,9 @@ initialization_started (MMBroadbandModem *self,
}
if (mm_port_qmi_is_open (ctx->qmi)) {
/* Nothing to be done, just launch parent's callback */
/* Nothing to be done, just track device removal and launch parent's
* callback */
track_qmi_device_removed (MM_BROADBAND_MODEM_QMI (self), ctx->qmi);
parent_initialization_started (task);
return;
}
@@ -11368,10 +11424,12 @@ finalize (GObject *object)
MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (object);
qmi = mm_base_modem_peek_port_qmi (MM_BASE_MODEM (self));
/* If we did open the QMI port during initialization, close it now */
if (qmi &&
mm_port_qmi_is_open (qmi)) {
mm_port_qmi_close (qmi);
if (qmi) {
/* Disconnect signal handler for qmi-proxy disappearing, if it exists */
untrack_qmi_device_removed (self, qmi);
/* If we did open the QMI port during initialization, close it now */
if (mm_port_qmi_is_open (qmi))
mm_port_qmi_close (qmi);
}
g_free (self->priv->imei);

View File

@@ -72,6 +72,16 @@ mm_port_qmi_get_client (MMPortQmi *self,
/*****************************************************************************/
QmiDevice *
mm_port_qmi_peek_device (MMPortQmi *self)
{
g_return_val_if_fail (MM_IS_PORT_QMI (self), NULL);
return self->priv->qmi_device;
}
/*****************************************************************************/
typedef struct {
ServiceInfo *info;
} AllocateClientContext;

View File

@@ -82,6 +82,8 @@ QmiClient *mm_port_qmi_get_client (MMPortQmi *self,
QmiService service,
MMPortQmiFlag flag);
QmiDevice *mm_port_qmi_peek_device (MMPortQmi *self);
gboolean mm_port_qmi_llp_is_raw_ip (MMPortQmi *self);
#endif /* MM_PORT_QMI_H */