MMGpsSerialPort * mm_base_modem_get_port_gps (MMBaseModem *self) { g_return_val_if_fail (MM_IS_BASE_MODEM (self), NULL); return (self->priv->gps ? g_object_ref (self->priv->gps) : NULL); }
MMGpsSerialPort * mm_base_modem_peek_port_gps (MMBaseModem *self) { g_return_val_if_fail (MM_IS_BASE_MODEM (self), NULL); return self->priv->gps; }
MMQcdmSerialPort * mm_base_modem_get_port_qcdm (MMBaseModem *self) { g_return_val_if_fail (MM_IS_BASE_MODEM (self), NULL); return (self->priv->qcdm ? g_object_ref (self->priv->qcdm) : NULL); }
MMQcdmSerialPort * mm_base_modem_peek_port_qcdm (MMBaseModem *self) { g_return_val_if_fail (MM_IS_BASE_MODEM (self), NULL); return self->priv->qcdm; }
MMAtSerialPort * mm_base_modem_get_port_secondary (MMBaseModem *self) { g_return_val_if_fail (MM_IS_BASE_MODEM (self), NULL); return (self->priv->secondary ? g_object_ref (self->priv->secondary) : NULL); }
const gchar * mm_base_modem_get_plugin (MMBaseModem *self) { g_return_val_if_fail (MM_IS_BASE_MODEM (self), NULL); return self->priv->plugin; }
GCancellable * mm_base_modem_peek_cancellable (MMBaseModem *self) { g_return_val_if_fail (MM_IS_BASE_MODEM (self), NULL); return self->priv->cancellable; }
GCancellable * mm_base_modem_get_cancellable (MMBaseModem *self) { g_return_val_if_fail (MM_IS_BASE_MODEM (self), NULL); return g_object_ref (self->priv->cancellable); }
GList * mm_base_modem_peek_data_ports (MMBaseModem *self) { g_return_val_if_fail (MM_IS_BASE_MODEM (self), NULL); return self->priv->data; }
gboolean mm_base_modem_get_valid (MMBaseModem *self) { g_return_val_if_fail (MM_IS_BASE_MODEM (self), FALSE); return self->priv->valid; }
guint mm_base_modem_get_product_id (MMBaseModem *self) { g_return_val_if_fail (MM_IS_BASE_MODEM (self), 0); return self->priv->product_id; }
MMAtSerialPort * mm_base_modem_peek_port_secondary (MMBaseModem *self) { g_return_val_if_fail (MM_IS_BASE_MODEM (self), NULL); return self->priv->secondary; }
MMQmiPort * mm_base_modem_peek_port_qmi (MMBaseModem *self) { g_return_val_if_fail (MM_IS_BASE_MODEM (self), NULL); /* First QMI port in the list is the primary one always */ return (self->priv->qmi ? (MMQmiPort *)self->priv->qmi->data : NULL); }
GList * mm_base_modem_get_data_ports (MMBaseModem *self) { GList *copy; g_return_val_if_fail (MM_IS_BASE_MODEM (self), NULL); copy = g_list_copy (self->priv->data); g_list_foreach (copy, (GFunc)g_object_ref, NULL); return copy; }
void mm_base_modem_set_valid (MMBaseModem *self, gboolean new_valid) { g_return_if_fail (MM_IS_BASE_MODEM (self)); /* If validity changed OR if both old and new were invalid, notify. This * last case is to cover failures during initialization. */ if (self->priv->valid != new_valid || !new_valid) { self->priv->valid = new_valid; g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_VALID]); } }
MMPort * mm_base_modem_peek_best_data_port (MMBaseModem *self) { GList *l; g_return_val_if_fail (MM_IS_BASE_MODEM (self), NULL); /* Return first not-connected data port */ for (l = self->priv->data; l; l = g_list_next (l)) { if (!mm_port_get_connected ((MMPort *)l->data)) return (MMPort *)l->data; } return NULL; }
static gboolean ensure_qmi_client (GTask *task, MMSimQmi *self, QmiService service, QmiClient **o_client) { MMBaseModem *modem = NULL; QmiClient *client; MMPortQmi *port; g_object_get (self, MM_BASE_SIM_MODEM, &modem, NULL); g_assert (MM_IS_BASE_MODEM (modem)); port = mm_base_modem_peek_port_qmi (modem); g_object_unref (modem); if (!port) { if (task) { g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't peek QMI port"); g_object_unref (task); } return FALSE; } client = mm_port_qmi_peek_client (port, service, MM_PORT_QMI_FLAG_DEFAULT); if (!client) { if (task) { g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't peek client for service '%s'", qmi_service_get_string (service)); g_object_unref (task); } return FALSE; } *o_client = client; return TRUE; }
MMPort * mm_base_modem_get_port (MMBaseModem *self, const gchar *subsys, const gchar *name) { MMPort *port; gchar *key; g_return_val_if_fail (MM_IS_BASE_MODEM (self), NULL); g_return_val_if_fail (name != NULL, NULL); g_return_val_if_fail (subsys != NULL, NULL); /* Only 'net' or 'tty' should be given */ g_return_val_if_fail (g_str_equal (subsys, "net") || g_str_equal (subsys, "tty"), NULL); key = get_hash_key (subsys, name); port = g_hash_table_lookup (self->priv->ports, key); g_free (key); return port; }
gboolean mm_base_modem_grab_port (MMBaseModem *self, const gchar *subsys, const gchar *name, MMPortType ptype, MMAtPortFlag at_pflags, GError **error) { MMPort *port; gchar *key; g_return_val_if_fail (MM_IS_BASE_MODEM (self), FALSE); g_return_val_if_fail (subsys != NULL, FALSE); g_return_val_if_fail (name != NULL, FALSE); /* Only allow 'tty', 'net' and 'cdc-wdm' ports */ if (!g_str_equal (subsys, "net") && !g_str_equal (subsys, "tty") && !(g_str_has_prefix (subsys, "usb") && g_str_has_prefix (name, "cdc-wdm"))) { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, "Cannot add port '%s/%s', unhandled subsystem", subsys, name); return FALSE; } /* Check whether we already have it stored */ key = get_hash_key (subsys, name); port = g_hash_table_lookup (self->priv->ports, key); if (port) { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, "Cannot add port '%s/%s', already exists", subsys, name); g_free (key); return FALSE; } /* Serial ports... */ if (g_str_equal (subsys, "tty")) { if (ptype == MM_PORT_TYPE_QCDM) /* QCDM port */ port = MM_PORT (mm_qcdm_serial_port_new (name)); else if (ptype == MM_PORT_TYPE_AT) { /* AT port */ port = MM_PORT (mm_at_serial_port_new (name)); /* Set common response parser */ mm_at_serial_port_set_response_parser (MM_AT_SERIAL_PORT (port), mm_serial_parser_v1_parse, mm_serial_parser_v1_new (), mm_serial_parser_v1_destroy); /* Store flags already */ mm_at_serial_port_set_flags (MM_AT_SERIAL_PORT (port), at_pflags); } else if (ptype == MM_PORT_TYPE_GPS) { /* Raw GPS port */ port = MM_PORT (mm_gps_serial_port_new (name)); } else { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, "Cannot add port '%s/%s', unhandled serial type", subsys, name); g_free (key); return FALSE; } /* For serial ports, enable port timeout checks */ g_signal_connect (port, "timed-out", G_CALLBACK (serial_port_timed_out_cb), self); } /* Net ports... */ else if (g_str_equal (subsys, "net")) { port = MM_PORT (g_object_new (MM_TYPE_PORT, MM_PORT_DEVICE, name, MM_PORT_SUBSYS, MM_PORT_SUBSYS_NET, MM_PORT_TYPE, MM_PORT_TYPE_NET, NULL)); } /* QMI ports... */ else if (g_str_has_prefix (subsys, "usb") && g_str_has_prefix (name, "cdc-wdm")) { #if defined WITH_QMI port = MM_PORT (mm_qmi_port_new (name)); #else g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, "Cannot add port '%s/%s', QMI support not available", subsys, name); g_free (key); return FALSE; #endif } else /* We already filter out before all non-tty, non-net, non-qmi ports */ g_assert_not_reached(); mm_dbg ("(%s) type '%s' claimed by %s", name, mm_port_type_get_string (ptype), mm_base_modem_get_device (self)); /* Add it to the tracking HT. * Note: 'key' and 'port' now owned by the HT. */ g_hash_table_insert (self->priv->ports, key, port); return TRUE; }
gboolean mm_base_modem_organize_ports (MMBaseModem *self, GError **error) { GHashTableIter iter; MMPort *candidate; MMAtPortFlag flags; MMAtSerialPort *backup_primary = NULL; MMAtSerialPort *primary = NULL; MMAtSerialPort *secondary = NULL; MMAtSerialPort *backup_secondary = NULL; MMQcdmSerialPort *qcdm = NULL; MMAtSerialPort *gps_control = NULL; MMGpsSerialPort *gps = NULL; MMPort *data_primary = NULL; GList *data = NULL; #if defined WITH_QMI MMPort *qmi_primary = NULL; GList *qmi = NULL; #endif GList *l; g_return_val_if_fail (MM_IS_BASE_MODEM (self), FALSE); /* If ports have already been organized, just return success */ if (self->priv->primary) return TRUE; g_hash_table_iter_init (&iter, self->priv->ports); while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &candidate)) { switch (mm_port_get_port_type (candidate)) { case MM_PORT_TYPE_AT: g_assert (MM_IS_AT_SERIAL_PORT (candidate)); flags = mm_at_serial_port_get_flags (MM_AT_SERIAL_PORT (candidate)); if (flags & MM_AT_PORT_FLAG_PRIMARY) { if (!primary) primary = MM_AT_SERIAL_PORT (candidate); else if (!backup_primary) { /* Just in case the plugin gave us more than one primary * and no secondaries, treat additional primary ports as * secondary. */ backup_primary = MM_AT_SERIAL_PORT (candidate); } } if (!data_primary && (flags & MM_AT_PORT_FLAG_PPP)) data_primary = candidate; /* Explicitly flagged secondary ports trump NONE ports for secondary */ if (flags & MM_AT_PORT_FLAG_SECONDARY) { if (!secondary || !(mm_at_serial_port_get_flags (secondary) & MM_AT_PORT_FLAG_SECONDARY)) secondary = MM_AT_SERIAL_PORT (candidate); } if (flags & MM_AT_PORT_FLAG_GPS_CONTROL) { if (!gps_control) gps_control = MM_AT_SERIAL_PORT (candidate); } /* Fallback secondary */ if (flags == MM_AT_PORT_FLAG_NONE) { if (!secondary) secondary = MM_AT_SERIAL_PORT (candidate); else if (!backup_secondary) backup_secondary = MM_AT_SERIAL_PORT (candidate); } break; case MM_PORT_TYPE_QCDM: g_assert (MM_IS_QCDM_SERIAL_PORT (candidate)); if (!qcdm) qcdm = MM_QCDM_SERIAL_PORT (candidate); break; case MM_PORT_TYPE_NET: /* Net device (if any) is the preferred data port */ if (!data_primary || MM_IS_AT_SERIAL_PORT (data_primary)) data_primary = candidate; else /* All non-primary net ports get added to the list of data ports */ data = g_list_append (data, candidate); break; case MM_PORT_TYPE_GPS: g_assert (MM_IS_GPS_SERIAL_PORT (candidate)); if (!gps) gps = MM_GPS_SERIAL_PORT (candidate); break; #if defined WITH_QMI case MM_PORT_TYPE_QMI: if (!qmi_primary) qmi_primary = candidate; else /* All non-primary QMI ports get added to the list of QMI ports */ qmi = g_list_append (qmi, candidate); break; #endif default: /* Ignore port */ break; } } /* Fall back to a secondary port if we didn't find a primary port */ if (!primary) { #if defined WITH_QMI /* On QMI-based modems we do allow not having a primary AT port */ if (!secondary && !qmi_primary) { #else if (!secondary) { #endif g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Failed to find primary AT port"); return FALSE; } else { primary = secondary; secondary = NULL; } } /* If the plugin didn't give us any secondary ports, use any additional * primary ports or backup secondary ports as secondary. */ if (!secondary) secondary = backup_primary ? backup_primary : backup_secondary; #if defined WITH_QMI /* On QMI-based modems, we need to have at least a net port */ if (qmi_primary && !data_primary) { g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Failed to find a net port in the QMI modem"); return FALSE; } #endif /* Data port defaults to primary AT port */ if (!data_primary) data_primary = MM_PORT (primary); g_assert (data_primary); /* Reset flags on all ports; clear data port first since it might also * be the primary or secondary port. */ if (MM_IS_AT_SERIAL_PORT (data_primary)) mm_at_serial_port_set_flags (MM_AT_SERIAL_PORT (data_primary), MM_AT_PORT_FLAG_NONE); mm_at_serial_port_set_flags (primary, MM_AT_PORT_FLAG_PRIMARY); if (secondary) mm_at_serial_port_set_flags (secondary, MM_AT_PORT_FLAG_SECONDARY); if (MM_IS_AT_SERIAL_PORT (data_primary)) { flags = mm_at_serial_port_get_flags (MM_AT_SERIAL_PORT (data_primary)); mm_at_serial_port_set_flags (MM_AT_SERIAL_PORT (data_primary), flags | MM_AT_PORT_FLAG_PPP); } log_port (self, MM_PORT (primary), "at (primary)"); log_port (self, MM_PORT (secondary), "at (secondary)"); log_port (self, MM_PORT (data_primary), "data (primary)"); for (l = data; l; l = g_list_next (l)) log_port (self, MM_PORT (l->data), "data (secondary)"); log_port (self, MM_PORT (qcdm), "qcdm"); log_port (self, MM_PORT (gps_control), "gps (control)"); log_port (self, MM_PORT (gps), "gps (nmea)"); #if defined WITH_QMI log_port (self, MM_PORT (qmi_primary), "qmi (primary)"); for (l = qmi; l; l = g_list_next (l)) log_port (self, MM_PORT (l->data), "qmi (secondary)"); #endif /* We keep new refs to the objects here */ self->priv->primary = g_object_ref (primary); self->priv->secondary = (secondary ? g_object_ref (secondary) : NULL); self->priv->qcdm = (qcdm ? g_object_ref (qcdm) : NULL); self->priv->gps_control = (gps_control ? g_object_ref (gps_control) : NULL); self->priv->gps = (gps ? g_object_ref (gps) : NULL); /* Build the final list of data ports, primary port first */ self->priv->data = g_list_append (self->priv->data, g_object_ref (data_primary)); g_list_foreach (data, (GFunc)g_object_ref, NULL); self->priv->data = g_list_concat (self->priv->data, data); #if defined WITH_QMI /* Build the final list of QMI ports, primary port first */ if (qmi_primary) { self->priv->qmi = g_list_append (self->priv->qmi, g_object_ref (qmi_primary)); g_list_foreach (qmi, (GFunc)g_object_ref, NULL); self->priv->qmi = g_list_concat (self->priv->qmi, qmi); } #endif /* As soon as we get the ports organized, we initialize the modem */ mm_base_modem_initialize (self, (GAsyncReadyCallback)initialize_ready, NULL); return TRUE; } /*****************************************************************************/ /* Authorization */ gboolean mm_base_modem_authorize_finish (MMBaseModem *self, GAsyncResult *res, GError **error) { return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); } static void authorize_ready (MMAuthProvider *authp, GAsyncResult *res, GSimpleAsyncResult *simple) { GError *error = NULL; if (!mm_auth_provider_authorize_finish (authp, res, &error)) g_simple_async_result_take_error (simple, error); else g_simple_async_result_set_op_res_gboolean (simple, TRUE); g_simple_async_result_complete (simple); g_object_unref (simple); }
void mm_base_modem_release_port (MMBaseModem *self, const gchar *subsys, const gchar *name) { gchar *key; MMPort *port; GList *l; g_return_if_fail (MM_IS_BASE_MODEM (self)); g_return_if_fail (name != NULL); g_return_if_fail (subsys != NULL); if (!g_str_equal (subsys, "tty") && !g_str_equal (subsys, "net")) return; key = get_hash_key (subsys, name); /* Find the port */ port = g_hash_table_lookup (self->priv->ports, key); if (!port) { mm_warn ("(%s/%s): cannot release port, not found", subsys, name); g_free (key); return; } if (port == (MMPort *)self->priv->primary) { /* Cancel modem-wide cancellable; no further actions can be done * without a primary port. */ g_cancellable_cancel (self->priv->cancellable); g_clear_object (&self->priv->primary); } l = g_list_find (self->priv->data, port); if (l) { g_object_unref (l->data); self->priv->data = g_list_delete_link (self->priv->data, l); } if (port == (MMPort *)self->priv->secondary) g_clear_object (&self->priv->secondary); if (port == (MMPort *)self->priv->qcdm) g_clear_object (&self->priv->qcdm); if (port == (MMPort *)self->priv->gps_control) g_clear_object (&self->priv->gps_control); if (port == (MMPort *)self->priv->gps) g_clear_object (&self->priv->gps); #if defined WITH_QMI l = g_list_find (self->priv->qmi, port); if (l) { g_object_unref (l->data); self->priv->qmi = g_list_delete_link (self->priv->qmi, l); } #endif /* Remove it from the tracking HT */ mm_dbg ("(%s/%s) type %s released from %s", subsys, name, mm_port_type_get_string (mm_port_get_port_type (port)), mm_port_get_device (port)); g_hash_table_remove (self->priv->ports, key); g_free (key); }