diff options
author | Aleksander Morgado <aleksandermj@chromium.org> | 2023-10-25 16:59:22 +0000 |
---|---|---|
committer | Aleksander Morgado <aleksandermj@chromium.org> | 2023-10-26 12:35:50 +0000 |
commit | 81d2655950a3fc2381c81708074f10e665e75660 (patch) | |
tree | 4d39bf45a354351b0fe1725d1c673eee8c6d91d9 | |
parent | 59aae421a1169ff77edb8f83e6f078b09ca20ce0 (diff) |
error-helpers: allow registering error mappings
E.g. from QMI/MBIM errors into MM errors.
-rw-r--r-- | src/mm-error-helpers.c | 111 | ||||
-rw-r--r-- | src/mm-error-helpers.h | 4 |
2 files changed, 113 insertions, 2 deletions
diff --git a/src/mm-error-helpers.c b/src/mm-error-helpers.c index 81fc995c..daa1e550 100644 --- a/src/mm-error-helpers.c +++ b/src/mm-error-helpers.c @@ -519,6 +519,113 @@ cdma_activation_error_get_string (MMCdmaActivationError code) } /******************************************************************************/ +/* Registered error mappings */ + +typedef struct { + GQuark error_domain; + gint error_code; +} DomainCodePair; + +static guint +domain_code_pair_hash_func (const DomainCodePair *pair) +{ + gint64 val; + + /* The value of the GQuark error domain is selected during runtime based on the amount of + * error types that are registered in the type system. */ + val = ((gint64)pair->error_domain << 31) | pair->error_code; + return g_int64_hash (&val); +} + +static gboolean +domain_code_pair_equal_func (const DomainCodePair *a, + const DomainCodePair *b) +{ + return (a->error_domain == b->error_domain) && (a->error_code == b->error_code); +} + +static void +domain_code_pair_free (DomainCodePair *pair) +{ + g_slice_free (DomainCodePair, pair); +} + +/* Map of a input domain/code error to an output domain/code error. This HT exists + * for as long as the process is running, it is not explicitly freed on exit. */ +static GHashTable *error_mappings; + +void +mm_register_error_mapping (GQuark input_error_domain, + gint input_error_code, + GQuark output_error_domain, + gint output_error_code) +{ + DomainCodePair *input; + DomainCodePair *output; + + if (G_UNLIKELY (!error_mappings)) + error_mappings = g_hash_table_new_full ((GHashFunc)domain_code_pair_hash_func, + (GEqualFunc)domain_code_pair_equal_func, + (GDestroyNotify)domain_code_pair_free, + (GDestroyNotify)domain_code_pair_free); + + input = g_slice_new0 (DomainCodePair); + input->error_domain = input_error_domain; + input->error_code = input_error_code; + + /* ensure no other error is registered with the same hash, we don't want or + * expect dupicates*/ + g_assert (!g_hash_table_lookup (error_mappings, input)); + + output = g_slice_new0 (DomainCodePair); + output->error_domain = output_error_domain; + output->error_code = output_error_code; + + g_hash_table_insert (error_mappings, input, output); +} + +static GError * +normalize_mapped_error (const GError *error) +{ + DomainCodePair *output = NULL; + const gchar *input_error_type; + +#if defined WITH_QMI + if (error->domain == QMI_CORE_ERROR) + input_error_type = "QMI core"; + else if (error->domain == QMI_PROTOCOL_ERROR) + input_error_type = "QMI protocol"; + else +#endif +#if defined WITH_MBIM + if (error->domain == MBIM_CORE_ERROR) + input_error_type = "MBIM core"; + else if (error->domain == MBIM_PROTOCOL_ERROR) + input_error_type = "MBIM protocol"; + else if (error->domain == MBIM_STATUS_ERROR) + input_error_type = "MBIM status"; + else +#endif + input_error_type = "unknown domain"; + + if (error_mappings) { + DomainCodePair input; + + input.error_domain = error->domain; + input.error_code = error->code; + output = g_hash_table_lookup (error_mappings, &input); + } + + if (!output) + return g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Unhandled %s error (%u): %s", + input_error_type, error->code, error->message); + + return g_error_new (output->error_domain, output->error_code, + "%s error: %s", input_error_type, error->message); +} + +/******************************************************************************/ /* Takes a GError of any kind and ensures that the returned GError is a * MM-defined one. */ @@ -570,6 +677,6 @@ mm_normalize_error (const GError *error) if (error->domain == MM_CDMA_ACTIVATION_ERROR) return normalize_mm_error (error, cdma_activation_error_get_string (error->code), "CDMA activation"); - /* Generic fallback */ - return g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "%s", error->message); + /* Normalize mapped errors */ + return normalize_mapped_error (error); } diff --git a/src/mm-error-helpers.h b/src/mm-error-helpers.h index d0effac7..ec1c2c6b 100644 --- a/src/mm-error-helpers.h +++ b/src/mm-error-helpers.h @@ -29,5 +29,9 @@ GError *mm_mobile_equipment_error_for_string (const gchar *str, gpo GError *mm_message_error_for_code (MMMessageError code, gpointer log_object); GError *mm_message_error_for_string (const gchar *str, gpointer log_object); GError *mm_normalize_error (const GError *error); +void mm_register_error_mapping (GQuark input_error_domain, + gint input_error_code, + GQuark output_error_domain, + gint output_error_code); #endif /* MM_ERROR_HELPERS_H */ |