/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details: * * Copyright (C) 2008 - 2009 Novell, Inc. * Copyright (C) 2009 - 2012 Red Hat, Inc. * Copyright (C) 2012 Google, Inc. */ #ifndef MM_MODEM_HELPERS_H #define MM_MODEM_HELPERS_H #include #define _LIBMM_INSIDE_MM #include #include "glib-object.h" #include "mm-charsets.h" /* NOTE: * We will use the following nomenclature for the different AT commands referred * - AT+SOMETHING --> "Exec" command * - AT+SOMETHING? --> "Read" command * - AT+SOMETHING=X,X --> "Write" command * - AT+SOMETHING=? --> "Test" command */ /*****************************************************************************/ /* Common utilities */ /*****************************************************************************/ #define MM_MODEM_CAPABILITY_3GPP \ (MM_MODEM_CAPABILITY_GSM_UMTS | \ MM_MODEM_CAPABILITY_LTE | \ MM_MODEM_CAPABILITY_5GNR) gchar *mm_strip_quotes (gchar *str); const gchar *mm_strip_tag (const gchar *str, const gchar *cmd); gchar **mm_split_string_groups (const gchar *str); GArray *mm_parse_uint_list (const gchar *str, GError **error); guint mm_count_bits_set (gulong number); guint mm_find_bit_set (gulong number); gchar *mm_create_device_identifier (guint vid, guint pid, gpointer log_object, const gchar *ati, const gchar *ati1, const gchar *gsn, const gchar *revision, const gchar *model, const gchar *manf); guint mm_netmask_to_cidr (const gchar *netmask); GArray *mm_filter_current_bands (const GArray *supported_bands, const GArray *current_bands); gchar *mm_new_iso8601_time (guint year, guint month, guint day, guint hour, guint minute, guint second, gboolean have_offset, gint offset_minutes); GArray *mm_filter_supported_modes (const GArray *all, const GArray *supported_combinations, gpointer log_object); gchar *mm_bcd_to_string (const guint8 *bcd, gsize bcd_len, gboolean low_nybble_first); /*****************************************************************************/ /* VOICE specific helpers and utilities */ /*****************************************************************************/ GRegex *mm_voice_ring_regex_get (void); GRegex *mm_voice_cring_regex_get (void); GRegex *mm_voice_clip_regex_get (void); GRegex *mm_voice_ccwa_regex_get (void); /* +CLCC response parser */ typedef struct { guint index; MMCallDirection direction; MMCallState state; gchar *number; /* optional */ } MMCallInfo; gboolean mm_3gpp_parse_clcc_response (const gchar *str, gpointer log_object, GList **out_list, GError **error); void mm_3gpp_call_info_list_free (GList *call_info_list); /*****************************************************************************/ /* SERIAL specific helpers and utilities */ /* AT+IFC=? response parser. * For simplicity, we'll only consider flow control methods available in both * TE and TA. */ typedef enum { /*< underscore_name=mm_flow_control >*/ MM_FLOW_CONTROL_UNKNOWN = 0, MM_FLOW_CONTROL_NONE = 1 << 0, /* IFC=0,0 */ MM_FLOW_CONTROL_XON_XOFF = 1 << 1, /* IFC=1,1 */ MM_FLOW_CONTROL_RTS_CTS = 1 << 2, /* IFC=2,2 */ } MMFlowControl; MMFlowControl mm_parse_ifc_test_response (const gchar *response, gpointer log_object, GError **error); MMFlowControl mm_flow_control_from_string (const gchar *str, GError **error); /*****************************************************************************/ /* 3GPP specific helpers and utilities */ /*****************************************************************************/ /* Common Regex getters */ GPtrArray *mm_3gpp_creg_regex_get (gboolean solicited); void mm_3gpp_creg_regex_destroy (GPtrArray *array); GRegex *mm_3gpp_ciev_regex_get (void); GRegex *mm_3gpp_cgev_regex_get (void); GRegex *mm_3gpp_cusd_regex_get (void); GRegex *mm_3gpp_cmti_regex_get (void); GRegex *mm_3gpp_cds_regex_get (void); /* AT+WS46=? response parser: returns array of MMModemMode values */ GArray *mm_3gpp_parse_ws46_test_response (const gchar *response, gpointer log_object, GError **error); /* AT+COPS=? (network scan) response parser */ typedef struct { MMModem3gppNetworkAvailability status; gchar *operator_long; gchar *operator_short; gchar *operator_code; /* mandatory */ MMModemAccessTechnology access_tech; } MM3gppNetworkInfo; void mm_3gpp_network_info_list_free (GList *info_list); GList *mm_3gpp_parse_cops_test_response (const gchar *reply, MMModemCharset cur_charset, gpointer log_object, GError **error); /* AT+COPS? (current operator) response parser */ gboolean mm_3gpp_parse_cops_read_response (const gchar *response, guint *out_mode, guint *out_format, gchar **out_operator, MMModemAccessTechnology *out_act, GError **error); /* Logic to compare two APN names */ gboolean mm_3gpp_cmp_apn_name (const gchar *requested, const gchar *existing); /* AT+CGDCONT=? (PDP context format) test parser */ typedef struct { guint min_cid; guint max_cid; MMBearerIpFamily pdp_type; } MM3gppPdpContextFormat; void mm_3gpp_pdp_context_format_list_free (GList *pdp_format_list); GList *mm_3gpp_parse_cgdcont_test_response (const gchar *reply, gpointer log_object, GError **error); gboolean mm_3gpp_pdp_context_format_list_find_range (GList *pdp_format_list, MMBearerIpFamily ip_family, guint *out_min_cid, guint *out_max_cid); /* AT+CGDCONT? (PDP context query) response parser */ typedef struct { guint cid; MMBearerIpFamily pdp_type; gchar *apn; } MM3gppPdpContext; void mm_3gpp_pdp_context_list_free (GList *pdp_list); GList *mm_3gpp_parse_cgdcont_read_response (const gchar *reply, GError **error); /* AT+CGACT? (active PDP context query) response parser */ typedef struct { guint cid; gboolean active; } MM3gppPdpContextActive; void mm_3gpp_pdp_context_active_list_free (GList *pdp_active_list); gint mm_3gpp_pdp_context_active_cmp (MM3gppPdpContextActive *a, MM3gppPdpContextActive *b); GList *mm_3gpp_parse_cgact_read_response (const gchar *reply, GError **error); /* CREG/CGREG response/unsolicited message parser */ gboolean mm_3gpp_parse_creg_response (GMatchInfo *info, gpointer log_object, MMModem3gppRegistrationState *out_reg_state, gulong *out_lac, gulong *out_ci, MMModemAccessTechnology *out_act, gboolean *out_cgreg, gboolean *out_cereg, gboolean *out_c5greg, GError **error); /* AT+CMGF=? (SMS message format) response parser */ gboolean mm_3gpp_parse_cmgf_test_response (const gchar *reply, gboolean *sms_pdu_supported, gboolean *sms_text_supported, GError **error); /* AT+CPMS=? (Preferred SMS storage) response parser */ gboolean mm_3gpp_parse_cpms_test_response (const gchar *reply, GArray **mem1, GArray **mem2, GArray **mem3, GError **error); /* AT+CPMS? (Current SMS storage) response parser */ gboolean mm_3gpp_parse_cpms_query_response (const gchar *reply, MMSmsStorage *mem1, MMSmsStorage *mem2, GError** error); gboolean mm_3gpp_get_cpms_storage_match (GMatchInfo *match_info, const gchar *match_name, MMSmsStorage *storage, GError **error); /* AT+CSCS=? (Supported charsets) response parser */ gboolean mm_3gpp_parse_cscs_test_response (const gchar *reply, MMModemCharset *out_charsets); /* AT+CLCK=? (Supported locks) response parser */ gboolean mm_3gpp_parse_clck_test_response (const gchar *reply, MMModem3gppFacility *out_facilities); /* AT+CLCK=X,X,X... (Current locks) response parser */ gboolean mm_3gpp_parse_clck_write_response (const gchar *reply, gboolean *enabled); /* AT+CNUM (Own numbers) response parser */ GStrv mm_3gpp_parse_cnum_exec_response (const gchar *reply); /* AT+CMER=? (Mobile Equipment Event Reporting) response parser */ typedef enum { /*< underscore_name=mm_3gpp_cmer_mode >*/ MM_3GPP_CMER_MODE_NONE = 0, MM_3GPP_CMER_MODE_DISCARD_URCS = 1 << 0, MM_3GPP_CMER_MODE_DISCARD_URCS_IF_LINK_RESERVED = 1 << 1, MM_3GPP_CMER_MODE_BUFFER_URCS_IF_LINK_RESERVED = 1 << 2, MM_3GPP_CMER_MODE_FORWARD_URCS = 1 << 3, } MM3gppCmerMode; typedef enum { /*< underscore_name=mm_3gpp_cmer_ind >*/ MM_3GPP_CMER_IND_NONE = 0, /* no indicator event reporting */ MM_3GPP_CMER_IND_DISABLE = 1 << 0, /* Only indicator events that are not caused by +CIND */ MM_3GPP_CMER_IND_ENABLE_NOT_CAUSED_BY_CIND = 1 << 1, /* All indicator events */ MM_3GPP_CMER_IND_ENABLE_ALL = 1 << 2, } MM3gppCmerInd; gchar *mm_3gpp_build_cmer_set_request (MM3gppCmerMode mode, MM3gppCmerInd ind); gboolean mm_3gpp_parse_cmer_test_response (const gchar *reply, gpointer log_object, MM3gppCmerMode *supported_modes, MM3gppCmerInd *supported_inds, GError **error); /* AT+CIND=? (Supported indicators) response parser */ typedef struct MM3gppCindResponse MM3gppCindResponse; GHashTable *mm_3gpp_parse_cind_test_response (const gchar *reply, GError **error); const gchar *mm_3gpp_cind_response_get_desc (MM3gppCindResponse *r); guint mm_3gpp_cind_response_get_index (MM3gppCindResponse *r); gint mm_3gpp_cind_response_get_min (MM3gppCindResponse *r); gint mm_3gpp_cind_response_get_max (MM3gppCindResponse *r); /* AT+CIND? (Current indicators) response parser */ GByteArray *mm_3gpp_parse_cind_read_response (const gchar *reply, GError **error); /* +CGEV indication parser */ typedef enum { MM_3GPP_CGEV_UNKNOWN, MM_3GPP_CGEV_NW_DETACH, MM_3GPP_CGEV_ME_DETACH, MM_3GPP_CGEV_NW_CLASS, MM_3GPP_CGEV_ME_CLASS, MM_3GPP_CGEV_NW_ACT_PRIMARY, MM_3GPP_CGEV_ME_ACT_PRIMARY, MM_3GPP_CGEV_NW_ACT_SECONDARY, MM_3GPP_CGEV_ME_ACT_SECONDARY, MM_3GPP_CGEV_NW_DEACT_PRIMARY, MM_3GPP_CGEV_ME_DEACT_PRIMARY, MM_3GPP_CGEV_NW_DEACT_SECONDARY, MM_3GPP_CGEV_ME_DEACT_SECONDARY, MM_3GPP_CGEV_NW_DEACT_PDP, MM_3GPP_CGEV_ME_DEACT_PDP, MM_3GPP_CGEV_NW_MODIFY, MM_3GPP_CGEV_ME_MODIFY, MM_3GPP_CGEV_REJECT, MM_3GPP_CGEV_NW_REACT, } MM3gppCgev; MM3gppCgev mm_3gpp_parse_cgev_indication_action (const gchar *str); gboolean mm_3gpp_parse_cgev_indication_pdp (const gchar *str, MM3gppCgev type, gchar **out_pdp_type, gchar **out_pdp_addr, guint *out_cid, GError **error); gboolean mm_3gpp_parse_cgev_indication_primary (const gchar *str, MM3gppCgev type, guint *out_cid, GError **error); gboolean mm_3gpp_parse_cgev_indication_secondary (const gchar *str, MM3gppCgev type, guint *out_p_cid, guint *out_cid, guint *out_event_type, GError **error); /* AT+CMGL=4 (list sms parts) response parser */ typedef struct { gint index; gint status; gchar *pdu; } MM3gppPduInfo; void mm_3gpp_pdu_info_free (MM3gppPduInfo *info); void mm_3gpp_pdu_info_list_free (GList *info_list); GList *mm_3gpp_parse_pdu_cmgl_response (const gchar *str, GError **error); /* AT+CMGR (Read message) response parser */ MM3gppPduInfo *mm_3gpp_parse_cmgr_read_response (const gchar *reply, guint index, GError **error); /* AT+CRSM response parser */ gboolean mm_3gpp_parse_crsm_response (const gchar *reply, guint *sw1, guint *sw2, gchar **hex, GError **error); /* AT+CGCONTRDP=N response parser */ gboolean mm_3gpp_parse_cgcontrdp_response (const gchar *response, guint *out_cid, guint *out_bearer_id, gchar **out_apn, gchar **out_local_address, gchar **out_subnet, gchar **out_gateway_address, gchar **out_dns_primary_address, gchar **out_dns_secondary_address, GError **error); /* CFUN? response parser * Note: a custom method with values not translated into MMModemPowerState is * provided, because they may be vendor specific. */ gboolean mm_3gpp_parse_cfun_query_response (const gchar *response, guint *out_state, GError **error); gboolean mm_3gpp_parse_cfun_query_generic_response (const gchar *response, MMModemPowerState *out_state, GError **error); /* +CESQ response parser */ gboolean mm_3gpp_parse_cesq_response (const gchar *response, guint *out_rxlev, guint *out_ber, guint *out_rscp, guint *out_ecn0, guint *out_rsrq, guint *out_rsrp, GError **error); gboolean mm_3gpp_cesq_response_to_signal_info (const gchar *response, gpointer log_object, MMSignal **out_gsm, MMSignal **out_umts, MMSignal **out_lte, GError **error); /* CEMODE? response parser */ gchar *mm_3gpp_build_cemode_set_request (MMModem3gppEpsUeModeOperation mode); gboolean mm_3gpp_parse_cemode_query_response (const gchar *response, MMModem3gppEpsUeModeOperation *out_mode, GError **error); /* CCWA service query response parser */ gboolean mm_3gpp_parse_ccwa_service_query_response (const gchar *response, gpointer log_object, gboolean *status, GError **error); /* Additional 3GPP-specific helpers */ MMModem3gppFacility mm_3gpp_acronym_to_facility (const gchar *str); const gchar *mm_3gpp_facility_to_acronym (MMModem3gppFacility facility); MMModemAccessTechnology mm_string_to_access_tech (const gchar *string); void mm_3gpp_normalize_operator (gchar **operator, MMModemCharset cur_charset, gpointer log_object); gboolean mm_3gpp_parse_operator_id (const gchar *operator_id, guint16 *mcc, guint16 *mnc, gboolean *three_digit_mnc, GError **error); const gchar *mm_3gpp_get_pdp_type_from_ip_family (MMBearerIpFamily family); MMBearerIpFamily mm_3gpp_get_ip_family_from_pdp_type (const gchar *pdp_type); gboolean mm_3gpp_normalize_ip_family (MMBearerIpFamily *family); char *mm_3gpp_parse_iccid (const char *raw_iccid, GError **error); gboolean mm_3gpp_rscp_level_to_rscp (guint rscp_level, gpointer log_object, gdouble *out_rscp); gboolean mm_3gpp_rxlev_to_rssi (guint rxlev, gpointer log_object, gdouble *out_rssi); gboolean mm_3gpp_ecn0_level_to_ecio (guint ecn0_level, gpointer log_object, gdouble *out_ecio); gboolean mm_3gpp_rsrq_level_to_rsrq (guint rsrq_level, gpointer log_object, gdouble *out_rsrq); gboolean mm_3gpp_rsrp_level_to_rsrp (guint rsrp_level, gpointer log_object, gdouble *out_rsrp); gboolean mm_3gpp_rssnr_level_to_rssnr (gint rssnr_level, gpointer log_object, gdouble *out_rssnr); GStrv mm_3gpp_parse_emergency_numbers (const char *raw, GError **error); /* PDP context -> profile */ MM3gppProfile *mm_3gpp_profile_new_from_pdp_context (MM3gppPdpContext *pdp_context); /* Profile list operations */ GList *mm_3gpp_profile_list_new_from_pdp_context_list (GList *pdp_context_list); void mm_3gpp_profile_list_free (GList *profile_list); gint mm_3gpp_profile_list_find_empty (GList *profile_list, gint min_profile_id, gint max_profile_id, GError **error); gint mm_3gpp_profile_list_find_best (GList *profile_list, MM3gppProfile *requested, GEqualFunc cmp_apn, MM3gppProfileCmpFlags cmp_flags, gint min_profile_id, gint max_profile_id, gpointer log_object, MM3gppProfile **out_reused, gboolean *out_overwritten); MM3gppProfile *mm_3gpp_profile_list_find_by_profile_id (GList *profile_list, gint profile_id, GError **error); /*****************************************************************************/ /* CDMA specific helpers and utilities */ /*****************************************************************************/ /* AT+SPSERVICE? response parser */ gboolean mm_cdma_parse_spservice_read_response (const gchar *reply, MMModemCdmaRegistrationState *out_cdma_1x_state, MMModemCdmaRegistrationState *out_evdo_state); /* Generic ERI response parser */ gboolean mm_cdma_parse_eri (const gchar *reply, gboolean *out_roaming, guint32 *out_ind, const gchar **out_desc); /* AT+CRM=? response parser */ gboolean mm_cdma_parse_crm_test_response (const gchar *reply, MMModemCdmaRmProtocol *min, MMModemCdmaRmProtocol *max, GError **error); /* Additional CDMA-specific helpers */ #define MM_MODEM_CDMA_SID_UNKNOWN 99999 #define MM_MODEM_CDMA_NID_UNKNOWN 99999 MMModemCdmaRmProtocol mm_cdma_get_rm_protocol_from_index (guint index, GError **error); guint mm_cdma_get_index_from_rm_protocol (MMModemCdmaRmProtocol protocol, GError **error); gint mm_cdma_normalize_class (const gchar *orig_class); gchar mm_cdma_normalize_band (const gchar *long_band, gint *out_class); gboolean mm_parse_gsn (const char *gsn, gchar **out_imei, gchar **out_meid, gchar **out_esn); /* +CCLK response parser */ gboolean mm_parse_cclk_response (const gchar *response, gchar **iso8601p, MMNetworkTimezone **tzp, GError **error); /* +CSIM response parser */ gint mm_parse_csim_response (const gchar *response, GError **error); gboolean mm_parse_supl_address (const gchar *supl, gchar **out_fqdn, guint32 *out_ip, guint16 *out_port, GError **error); /*****************************************************************************/ /* SIM specific helpers and utilities */ /*****************************************************************************/ /* +CPOL? response parser (for a single entry) - accepts only numeric operator format*/ gboolean mm_sim_parse_cpol_query_response (const gchar *response, guint *out_index, gchar **out_operator_code, gboolean *out_gsm_act, gboolean *out_gsm_compact_act, gboolean *out_utran_act, gboolean *out_eutran_act, gboolean *out_ngran_act, guint *out_act_count, GError **error); /* +CPOL=? response parser for getting supported min and max index */ gboolean mm_sim_parse_cpol_test_response (const gchar *response, guint *out_min_index, guint *out_max_index, GError **error); /*****************************************************************************/ /* Useful when clamp-ing an unsigned integer with implicit low limit set to 0, * and in order to avoid -Wtype-limits warnings. */ #define MM_CLAMP_HIGH(x, high) (((x) > (high)) ? (high) : (x)) /*****************************************************************************/ /* Helper function to decode eid read from esim */ gchar *mm_decode_eid (const gchar *eid, gsize eid_len); #endif /* MM_MODEM_HELPERS_H */