static void connection_enabled (MMAtSerialPort *port, GMatchInfo *match_info, gpointer user_data) { MMModemIcera *self = MM_MODEM_ICERA (user_data); MMAtSerialPort *primary; char *str; int status, cid, tmp; cid = mm_generic_gsm_get_cid (MM_GENERIC_GSM (self)); if (cid < 0) return; str = g_match_info_fetch (match_info, 1); g_return_if_fail (str != NULL); tmp = atoi (str); g_free (str); /* Make sure the unsolicited message's CID matches the current CID */ if (tmp != cid) return; str = g_match_info_fetch (match_info, 2); g_return_if_fail (str != NULL); status = atoi (str); g_free (str); switch (status) { case 0: /* Disconnected */ if (mm_modem_get_state (MM_MODEM (self)) >= MM_MODEM_STATE_CONNECTED) mm_modem_disconnect (MM_MODEM (self), icera_disconnect_done, NULL); break; case 1: /* Connected */ connect_pending_done (self); break; case 2: /* Connecting */ break; case 3: /* Call setup failure? */ primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM(self), MM_AT_PORT_FLAG_PRIMARY); g_assert (primary); /* Get additional error details */ mm_at_serial_port_queue_command (primary, "AT%IER?", 3, query_network_error_code_done, self); break; default: mm_warn ("Unknown Icera connect status %d", status); break; } }
static void unsolicited_disable_done (MMModem *modem, GError *error, gpointer user_data) { MMCallbackInfo *info = user_data; /* Handle modem removal, but ignore other errors */ if (g_error_matches (error, MM_MODEM_ERROR, MM_MODEM_ERROR_REMOVED)) info->error = g_error_copy (error); else if (!modem) { info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_REMOVED, "The modem was removed."); } if (info->error) { mm_callback_info_schedule (info); return; } /* Otherwise, kill any existing connection */ if (mm_generic_gsm_get_cid (MM_GENERIC_GSM (modem)) >= 0) hso_call_control (MM_MODEM_HSO (modem), FALSE, TRUE, disable_done, info); else disable_done (modem, NULL, info); }
static void nwstate_changed (MMAtSerialPort *port, GMatchInfo *info, gpointer user_data) { MMModemIcera *self = MM_MODEM_ICERA (user_data); MMModemGsmAccessTech act = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN; char *str; int rssi = -1; str = g_match_info_fetch (info, 1); if (str) { rssi = atoi (str); rssi = CLAMP (rssi, -1, 5); g_free (str); } /* Check the <connection state> field first for the connected access * technology, otherwise if not connected (ie, "-") use the available * access technology from the <tech> field. */ str = g_match_info_fetch (info, 4); if (!str || (strcmp (str, "-") == 0)) { g_free (str); str = g_match_info_fetch (info, 3); } if (str) { act = nwstate_to_act (str); g_free (str); } MM_MODEM_ICERA_GET_PRIVATE (self)->last_act = act; mm_generic_gsm_update_access_technology (MM_GENERIC_GSM (self), act); }
static void icera_connected (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) { MMCallbackInfo *info = (MMCallbackInfo *) user_data; /* If the modem has already been removed, return without * scheduling callback */ if (mm_callback_info_check_modem_removed (info)) return; if (error) { mm_generic_gsm_connect_complete (MM_GENERIC_GSM (info->modem), error, info); } else { MMModemIcera *self = MM_MODEM_ICERA (info->modem); MMModemIceraPrivate *priv = MM_MODEM_ICERA_GET_PRIVATE (self); g_warn_if_fail (priv->connect_pending_id == 0); if (priv->connect_pending_id) g_source_remove (priv->connect_pending_id); priv->connect_pending_data = info; priv->connect_pending_id = g_timeout_add_seconds (30, icera_connect_timed_out, self); } }
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; }
static void _internal_hso_modem_authenticate (MMModemHso *self, MMCallbackInfo *info) { MMModemHsoPrivate *priv = MM_MODEM_HSO_GET_PRIVATE (self); MMAtSerialPort *primary; gint cid; char *command; primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (self), MM_PORT_TYPE_PRIMARY); g_assert (primary); cid = hso_get_cid (self); g_warn_if_fail (cid >= 0); /* Both user and password are required; otherwise firmware returns an error */ if (!priv->username || !priv->password) command = g_strdup_printf ("%s=%d,0", auth_commands[priv->auth_idx], cid); else { command = g_strdup_printf ("%s=%d,1,\"%s\",\"%s\"", auth_commands[priv->auth_idx], cid, priv->password ? priv->password : "", priv->username ? priv->username : ""); } mm_at_serial_port_queue_command (primary, command, 3, auth_done, info); g_free (command); }
void mm_modem_icera_change_unsolicited_messages (MMModemIcera *self, gboolean enabled) { MMAtSerialPort *primary; primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (self), MM_AT_PORT_FLAG_PRIMARY); g_assert (primary); mm_at_serial_port_queue_command (primary, enabled ? "%NWSTATE=1" : "%NWSTATE=0", 3, NULL, NULL); }
static void disable (MMModem *modem, MMModemFn callback, gpointer user_data) { MMModemHso *self = MM_MODEM_HSO (modem); MMModemHsoPrivate *priv = MM_MODEM_HSO_GET_PRIVATE (self); MMCallbackInfo *info; mm_generic_gsm_pending_registration_stop (MM_GENERIC_GSM (modem)); g_free (priv->username); priv->username = NULL; g_free (priv->password); priv->password = NULL; info = mm_callback_info_new (modem, callback, user_data); /* Turn off unsolicited messages so they don't pile up in the modem */ option_change_unsolicited_messages (MM_GENERIC_GSM (modem), FALSE, unsolicited_disable_done, info); }
static gint _get_cid (MMModemIcera *self) { gint cid; cid = mm_generic_gsm_get_cid (MM_GENERIC_GSM (self)); if (cid < 0) { g_warn_if_fail (cid >= 0); cid = 0; } return cid; }
void mm_modem_icera_get_local_timestamp (MMModemIcera *self, MMModemIceraTimestampFn callback, gpointer user_data) { MMCallbackInfo *info; MMAtSerialPort *primary; info = mm_callback_info_icera_timestamp_new (self, callback, user_data); primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (self), MM_AT_PORT_FLAG_PRIMARY); g_assert (primary); mm_at_serial_port_queue_command (primary, "*TLTS", 3, get_local_timestamp_done, info); }
static void icera_call_control (MMModemIcera *self, gboolean activate, MMAtSerialResponseFn callback, gpointer user_data) { char *command; MMAtSerialPort *primary; primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (self), MM_AT_PORT_FLAG_PRIMARY); g_assert (primary); command = g_strdup_printf ("%%IPDPACT=%d,%d", _get_cid (self), activate ? 1 : 0); mm_at_serial_port_queue_command (primary, command, 3, callback, user_data); g_free (command); }
static void get_ip4_config (MMModem *modem, MMModemIp4Fn callback, gpointer user_data) { MMCallbackInfo *info; char *command; MMAtSerialPort *primary; info = mm_callback_info_new_full (modem, ip4_config_invoke, G_CALLBACK (callback), user_data); command = g_strdup_printf ("AT_OWANDATA=%d", hso_get_cid (MM_MODEM_HSO (modem))); primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY); g_assert (primary); mm_at_serial_port_queue_command (primary, command, 3, get_ip4_config_done, info); g_free (command); }
static void old_context_clear_done (MMModem *modem, GError *error, gpointer user_data) { MMCallbackInfo *info = (MMCallbackInfo *) user_data; GError *tmp_error; tmp_error = mm_modem_check_removed (modem, error); if (tmp_error) { mm_generic_gsm_connect_complete (MM_GENERIC_GSM (modem), tmp_error, info); g_clear_error (&tmp_error); } else { /* Success, activate the PDP context and start the data session */ hso_call_control (MM_MODEM_HSO (modem), TRUE, FALSE, hso_enabled, info); } }
static void connect_auth_done (MMModem *modem, GError *error, gpointer user_data) { MMCallbackInfo *info = (MMCallbackInfo *) user_data; GError *tmp_error; tmp_error = mm_modem_check_removed (modem, error); if (tmp_error) { mm_generic_gsm_connect_complete (MM_GENERIC_GSM (modem), tmp_error, info); g_clear_error (&tmp_error); } else { /* Now connect; kill any existing connections first */ hso_call_control (MM_MODEM_HSO (modem), FALSE, TRUE, old_context_clear_done, info); } }
void mm_modem_icera_get_allowed_mode (MMModemIcera *self, MMModemUIntFn callback, gpointer user_data) { MMCallbackInfo *info; MMAtSerialPort *port; info = mm_callback_info_uint_new (MM_MODEM (self), callback, user_data); port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (self), &info->error); if (!port) { mm_callback_info_schedule (info); return; } mm_at_serial_port_queue_command (port, "%IPSYS?", 3, get_allowed_mode_done, info); }
static void hso_enabled (MMModem *modem, GError *error, gpointer user_data) { MMCallbackInfo *info = (MMCallbackInfo *) user_data; GError *tmp_error; tmp_error = mm_modem_check_removed (modem, error); if (tmp_error) { mm_generic_gsm_connect_complete (MM_GENERIC_GSM (modem), tmp_error, info); g_clear_error (&tmp_error); } else { MMModemHsoPrivate *priv = MM_MODEM_HSO_GET_PRIVATE (modem); priv->connect_pending_data = info; priv->connect_pending_id = g_timeout_add_seconds (30, hso_connect_timed_out, modem); } }
void mm_modem_icera_set_allowed_mode (MMModemIcera *self, MMModemGsmAllowedMode mode, MMModemFn callback, gpointer user_data) { MMCallbackInfo *info; MMAtSerialPort *port; char *command; int i; info = mm_callback_info_new (MM_MODEM (self), callback, user_data); port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (self), &info->error); if (!port) { mm_callback_info_schedule (info); return; } switch (mode) { case MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY: i = 0; break; case MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY: i = 1; break; case MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED: i = 2; break; case MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED: i = 3; break; case MM_MODEM_GSM_ALLOWED_MODE_ANY: default: i = 5; break; } command = g_strdup_printf ("%%IPSYS=%d", i); mm_at_serial_port_queue_command (port, command, 3, set_allowed_mode_done, info); g_free (command); }
static void auth_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) { MMCallbackInfo *info = (MMCallbackInfo *) user_data; /* If the modem has already been removed, return without * scheduling callback */ if (mm_callback_info_check_modem_removed (info)) return; if (error) mm_generic_gsm_connect_complete (MM_GENERIC_GSM (info->modem), error, info); else { /* Ensure the PDP context is deactivated */ icera_call_control (MM_MODEM_ICERA (info->modem), FALSE, old_context_clear_done, info); } }
static void hso_call_control (MMModemHso *self, gboolean activate, gboolean ignore_errors, MMModemFn callback, gpointer user_data) { MMCallbackInfo *info; char *command; MMAtSerialPort *primary; info = mm_callback_info_new (MM_MODEM (self), callback, user_data); mm_callback_info_set_data (info, IGNORE_ERRORS_TAG, GUINT_TO_POINTER (ignore_errors), NULL); command = g_strdup_printf ("AT_OWANCALL=%d,%d,1", hso_get_cid (self), activate ? 1 : 0); primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (self), MM_PORT_TYPE_PRIMARY); g_assert (primary); mm_at_serial_port_queue_command (primary, command, 3, hso_call_control_done, info); g_free (command); }
void mm_modem_icera_get_ip4_config (MMModemIcera *self, MMModemIp4Fn callback, gpointer user_data) { MMCallbackInfo *info; char *command; MMAtSerialPort *primary; info = mm_callback_info_new_full (MM_MODEM (self), ip4_config_invoke, G_CALLBACK (callback), user_data); primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (self), MM_AT_PORT_FLAG_PRIMARY); g_assert (primary); command = g_strdup_printf ("%%IPDPADDR=%d", _get_cid (self)); mm_at_serial_port_queue_command (primary, command, 3, get_ip4_config_done, info); g_free (command); }
static void connect_pending_done (MMModemIcera *self) { MMModemIceraPrivate *priv = MM_MODEM_ICERA_GET_PRIVATE (self); GError *error = NULL; if (priv->connect_pending_data) { if (priv->connect_pending_data->error) { error = priv->connect_pending_data->error; priv->connect_pending_data->error = NULL; } /* Complete the connect */ mm_generic_gsm_connect_complete (MM_GENERIC_GSM (self), error, priv->connect_pending_data); priv->connect_pending_data = NULL; } if (priv->connect_pending_id) { g_source_remove (priv->connect_pending_id); priv->connect_pending_id = 0; } }
void mm_modem_icera_do_connect (MMModemIcera *self, const char *number, MMModemFn callback, gpointer user_data) { MMModem *modem = MM_MODEM (self); MMModemIceraPrivate *priv = MM_MODEM_ICERA_GET_PRIVATE (self); MMCallbackInfo *info; MMAtSerialPort *primary; gint cid; char *command; mm_modem_set_state (modem, MM_MODEM_STATE_CONNECTING, MM_MODEM_STATE_REASON_NONE); info = mm_callback_info_new (modem, callback, user_data); primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (self), MM_AT_PORT_FLAG_PRIMARY); g_assert (primary); cid = _get_cid (self); /* Both user and password are required; otherwise firmware returns an error */ if (!priv->username || !priv->password) command = g_strdup_printf ("%%IPDPCFG=%d,0,0,\"\",\"\"", cid); else { command = g_strdup_printf ("%%IPDPCFG=%d,0,1,\"%s\",\"%s\"", cid, priv->username ? priv->username : "", priv->password ? priv->password : ""); } mm_at_serial_port_queue_command (primary, command, 3, auth_done, info); g_free (command); }
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; }