static void port_grabbed (MMGenericCdma *cdma, MMPort *port, MMAtPortFlags pflags, gpointer user_data) { GRegex *regex; gboolean evdo0 = FALSE, evdoA = FALSE; if (MM_IS_AT_SERIAL_PORT (port)) { g_object_set (G_OBJECT (port), MM_PORT_CARRIER_DETECT, FALSE, NULL); /* 1x signal level */ regex = g_regex_new ("\\r\\n\\^RSSILVL:(\\d+)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, handle_1x_quality_change, cdma, NULL); g_regex_unref (regex); g_object_get (G_OBJECT (cdma), MM_GENERIC_CDMA_EVDO_REV0, &evdo0, MM_GENERIC_CDMA_EVDO_REVA, &evdoA, NULL); if (evdo0 || evdoA) { /* EVDO signal level */ regex = g_regex_new ("\\r\\n\\^HRSSILVL:(\\d+)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, handle_evdo_quality_change, cdma, NULL); g_regex_unref (regex); } } }
static gboolean grab_port (MMModem *modem, const char *subsys, const char *name, MMPortType suggested_type, gpointer user_data, GError **error) { MMGenericGsm *gsm = MM_GENERIC_GSM (modem); MMPortType ptype = MM_PORT_TYPE_IGNORED; MMPort *port = NULL; if (suggested_type == MM_PORT_TYPE_UNKNOWN) { if (!mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_PRIMARY)) ptype = MM_PORT_TYPE_PRIMARY; else if (!mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_SECONDARY)) ptype = MM_PORT_TYPE_SECONDARY; } else ptype = suggested_type; port = mm_generic_gsm_grab_port (gsm, subsys, name, ptype, error); if (port && MM_IS_AT_SERIAL_PORT (port)) { mm_at_serial_port_set_response_parser (MM_AT_SERIAL_PORT (port), mm_serial_parser_v1_e1_parse, mm_serial_parser_v1_e1_new (), mm_serial_parser_v1_e1_destroy); } return !!port; }
gboolean mm_base_modem_has_at_port (MMBaseModem *self) { GHashTableIter iter; gpointer value; gpointer key; /* We'll iterate the ht of ports, looking for any port which is AT */ g_hash_table_iter_init (&iter, self->priv->ports); while (g_hash_table_iter_next (&iter, &key, &value)) { if (MM_IS_AT_SERIAL_PORT (value)) return TRUE; } return FALSE; }
void mm_at_serial_port_set_response_parser (MMAtSerialPort *self, MMAtSerialResponseParserFn fn, gpointer user_data, GDestroyNotify notify) { MMAtSerialPortPrivate *priv = MM_AT_SERIAL_PORT_GET_PRIVATE (self); g_return_if_fail (MM_IS_AT_SERIAL_PORT (self)); if (priv->response_parser_notify) priv->response_parser_notify (priv->response_parser_user_data); priv->response_parser_fn = fn; priv->response_parser_user_data = user_data; priv->response_parser_notify = notify; }
void mm_at_serial_port_add_unsolicited_msg_handler (MMAtSerialPort *self, GRegex *regex, MMAtSerialUnsolicitedMsgFn callback, gpointer user_data, GDestroyNotify notify) { MMAtUnsolicitedMsgHandler *handler; MMAtSerialPortPrivate *priv; g_return_if_fail (MM_IS_AT_SERIAL_PORT (self)); g_return_if_fail (regex != NULL); handler = g_slice_new (MMAtUnsolicitedMsgHandler); handler->regex = g_regex_ref (regex); handler->callback = callback; handler->user_data = user_data; handler->notify = notify; priv = MM_AT_SERIAL_PORT_GET_PRIVATE (self); priv->unsolicited_msg_handlers = g_slist_append (priv->unsolicited_msg_handlers, handler); }
void mm_at_serial_port_queue_command_cached (MMAtSerialPort *self, const char *command, guint32 timeout_seconds, MMAtSerialResponseFn callback, gpointer user_data) { GByteArray *buf; g_return_if_fail (self != NULL); g_return_if_fail (MM_IS_AT_SERIAL_PORT (self)); g_return_if_fail (command != NULL); buf = at_command_to_byte_array (command); g_return_if_fail (buf != NULL); mm_serial_port_queue_command_cached (MM_SERIAL_PORT (self), buf, TRUE, timeout_seconds, (MMSerialResponseFn) callback, user_data); }
static gboolean grab_port (MMModem *modem, const char *subsys, const char *name, MMPortType suggested_type, gpointer user_data, GError **error) { MMGenericGsm *gsm = MM_GENERIC_GSM (modem); MMPortType ptype = MM_PORT_TYPE_IGNORED; const char *sys[] = { "tty", "net", NULL }; GUdevClient *client; GUdevDevice *device = NULL; MMPort *port = NULL; const char *sysfs_path; client = g_udev_client_new (sys); if (!client) { g_set_error (error, 0, 0, "Could not get udev client."); return FALSE; } device = g_udev_client_query_by_subsystem_and_name (client, subsys, name); if (!device) { g_set_error (error, 0, 0, "Could not get udev device."); goto out; } sysfs_path = g_udev_device_get_sysfs_path (device); if (!sysfs_path) { g_set_error (error, 0, 0, "Could not get udev device sysfs path."); goto out; } if (!strcmp (subsys, "tty")) { char *hsotype_path; char *contents = NULL; hsotype_path = g_build_filename (sysfs_path, "hsotype", NULL); if (g_file_get_contents (hsotype_path, &contents, NULL, NULL)) { if (g_str_has_prefix (contents, "Control")) ptype = MM_PORT_TYPE_PRIMARY; else if (g_str_has_prefix (contents, "Application") || g_str_has_prefix (contents, "Application2")) ptype = MM_PORT_TYPE_SECONDARY; g_free (contents); } g_free (hsotype_path); } port = mm_generic_gsm_grab_port (gsm, subsys, name, ptype, error); if (!port) goto out; if (MM_IS_AT_SERIAL_PORT (port)) { g_object_set (G_OBJECT (port), MM_SERIAL_PORT_SEND_DELAY, (guint64) 10000, NULL); if (ptype == MM_PORT_TYPE_PRIMARY) { GRegex *regex; regex = g_regex_new ("_OWANCALL: (\\d),\\s*(\\d)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, connection_enabled, modem, NULL); g_regex_unref (regex); regex = g_regex_new ("\\r\\n\\+PACSP0\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, NULL, NULL, NULL); g_regex_unref (regex); } option_register_unsolicted_handlers (gsm, MM_AT_SERIAL_PORT (port)); } out: if (device) g_object_unref (device); g_object_unref (client); return !!port; }
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); }