aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Chan <benchan@chromium.org>2018-10-18 16:37:19 -0700
committerBen Chan <benchan@chromium.org>2018-10-26 09:41:44 -0700
commit408a2a9c6cef91e11a3ed5e09c140e175534822d (patch)
treeadc2acf4453cfc964e7f094f9f5dc43374f23dad
parentbeb1aab17885bd2577964790986c5a79b6c120d7 (diff)
altair-lte: migrate from SubscriptionState to Pco property
In preparation of deprecating the SubscriptionState property in the Modem3gpp interface, this CL updates the altair-lte plugin to update the Pco property in the Modem3gpp interface upon receiving %PCOINFO notification.
-rw-r--r--plugins/altair/mm-broadband-modem-altair-lte.c186
-rw-r--r--plugins/altair/mm-modem-helpers-altair-lte.c123
-rw-r--r--plugins/altair/mm-modem-helpers-altair-lte.h5
-rw-r--r--plugins/altair/tests/test-modem-helpers-altair-lte.c109
4 files changed, 183 insertions, 240 deletions
diff --git a/plugins/altair/mm-broadband-modem-altair-lte.c b/plugins/altair/mm-broadband-modem-altair-lte.c
index 8f66b7fe..03912eae 100644
--- a/plugins/altair/mm-broadband-modem-altair-lte.c
+++ b/plugins/altair/mm-broadband-modem-altair-lte.c
@@ -67,6 +67,8 @@ struct _MMBroadbandModemAltairLtePrivate {
GRegex *statcm_regex;
/* Regex for PCO notifications */
GRegex *pcoinfo_regex;
+
+ GList *pco_list;
};
static MMIfaceModem3gpp *iface_modem_3gpp_parent;
@@ -414,6 +416,29 @@ modem_3gpp_run_registration_checks_finish (MMIfaceModem3gpp *self,
}
static void
+simulate_unprovisioned_subscription_pco_update (MMBroadbandModemAltairLte *self)
+{
+ MMPco *pco;
+
+ /* Simulate a %PCOINFO notification issued to the IMS PDN that indicates an
+ * unprovisioned Verizon SIM. See mm_altair_parse_vendor_pco_info() for the
+ * detailed format of a %PCOINFO response.
+ *
+ * 1,FF00,13018405 is constructed as follows:
+ *
+ * 1: CID for IMS PDN
+ * FF 00: Container ID for the Verizon-specific PCO content
+ * 13 01 84: Binary coded decimal representation of Verizon MCC/MNC 311/084
+ * 05: Value indicating an unprovisioned SIM
+ */
+ pco = mm_altair_parse_vendor_pco_info ("%PCOINFO: 1,FF00,13018405", NULL);
+ g_assert (pco != NULL);
+ self->priv->pco_list = mm_pco_list_add (self->priv->pco_list, pco);
+ mm_iface_modem_3gpp_update_pco_list (MM_IFACE_MODEM_3GPP (self), self->priv->pco_list);
+ g_object_unref (pco);
+}
+
+static void
run_registration_checks_subscription_state_ready (MMIfaceModem3gpp *self,
GAsyncResult *res,
GTask *task)
@@ -449,7 +474,7 @@ run_registration_checks_subscription_state_ready (MMIfaceModem3gpp *self,
if (g_strcmp0 ("EPS_AND_NON_EPS_SERVICES_NOT_ALLOWED", ceer_response) == 0) {
mm_dbg ("Registration failed due to unprovisioned SIM.");
- mm_iface_modem_3gpp_update_subscription_state (self, MM_MODEM_3GPP_SUBSCRIPTION_STATE_UNPROVISIONED);
+ simulate_unprovisioned_subscription_pco_update (MM_BROADBAND_MODEM_ALTAIR_LTE (self));
} else {
mm_dbg ("Failed to find a better reason for registration failure.");
}
@@ -1099,161 +1124,30 @@ modem_3gpp_load_operator_name (MMIfaceModem3gpp *self,
}
/*****************************************************************************/
-/* Subscription State loading (3GPP interface) */
-
-typedef struct {
- gchar *pco_info;
-} LoadSubscriptionStateContext;
-
-static void
-load_subscription_state_context_free (LoadSubscriptionStateContext *ctx)
-{
- g_free (ctx->pco_info);
- g_slice_free (LoadSubscriptionStateContext, ctx);
-}
-
-static MMModem3gppSubscriptionState
-altair_vzw_pco_value_to_mm_modem_3gpp_subscription_state (guint pco_value)
-{
- switch (pco_value) {
- case 0:
- return MM_MODEM_3GPP_SUBSCRIPTION_STATE_PROVISIONED;
- case 3:
- return MM_MODEM_3GPP_SUBSCRIPTION_STATE_OUT_OF_DATA;
- case 5:
- return MM_MODEM_3GPP_SUBSCRIPTION_STATE_UNPROVISIONED;
- default:
- return MM_MODEM_3GPP_SUBSCRIPTION_STATE_UNKNOWN;
- }
-}
-
-static MMModem3gppSubscriptionState
-modem_3gpp_load_subscription_state_finish (MMIfaceModem3gpp *self,
- GAsyncResult *res,
- GError **error)
-{
- GError *inner_error = NULL;
- gssize value;
-
- value = g_task_propagate_int (G_TASK (res), &inner_error);
- if (inner_error) {
- g_propagate_error (error, inner_error);
- return MM_MODEM_3GPP_SUBSCRIPTION_STATE_UNKNOWN;
- }
- return (MMModem3gppSubscriptionState)value;
-}
-
-static void
-altair_get_subscription_state (MMIfaceModem3gpp *self,
- GTask *task)
-{
- LoadSubscriptionStateContext *ctx;
- guint pco_value = -1;
- GError *error = NULL;
- MMModem3gppSubscriptionState subscription_state;
-
- ctx = g_task_get_task_data (task);
-
- mm_dbg ("Parsing vendor PCO info: %s", ctx->pco_info);
- pco_value = mm_altair_parse_vendor_pco_info (ctx->pco_info, &error);
- if (error) {
- g_task_return_error (task, error);
- g_object_unref (task);
- return;
- }
- mm_dbg ("PCO value = %d", pco_value);
-
- subscription_state = altair_vzw_pco_value_to_mm_modem_3gpp_subscription_state (pco_value);
- g_task_return_int (task, subscription_state);
- g_object_unref (task);
-}
-
-static void
-altair_load_vendor_pco_info_ready (MMIfaceModem3gpp *self,
- GAsyncResult *res,
- GTask *task)
-{
- LoadSubscriptionStateContext *ctx;
- const gchar *response;
- GError *error = NULL;
-
- response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);
- if (error) {
- mm_dbg ("Failed to load vendor PCO info.");
- g_task_return_error (task, error);
- g_object_unref (task);
- return;
- }
- g_assert (response);
- ctx = g_task_get_task_data (task);
- ctx->pco_info = g_strdup (response);
- altair_get_subscription_state (self, task);
-}
-
-static void
-modem_3gpp_load_subscription_state (MMIfaceModem3gpp *self,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- LoadSubscriptionStateContext *ctx;
- GTask *task;
-
- ctx = g_slice_new0 (LoadSubscriptionStateContext);
-
- task = g_task_new (self, NULL, callback, user_data);
- g_task_set_task_data (task, ctx, (GDestroyNotify)load_subscription_state_context_free);
-
- mm_dbg ("Loading vendor PCO info...");
- mm_base_modem_at_command (MM_BASE_MODEM (self),
- "%PCOINFO?",
- 6,
- FALSE,
- (GAsyncReadyCallback)altair_load_vendor_pco_info_ready,
- task);
-}
-
-/*****************************************************************************/
/* PCOINFO unsolicited event handler */
static void
-altair_get_subscription_state_ready (MMBroadbandModemAltairLte *self,
- GAsyncResult *res,
- gpointer *user_data)
+altair_pco_info_changed (MMPortSerialAt *port,
+ GMatchInfo *match_info,
+ MMBroadbandModemAltairLte *self)
{
+ const gchar *pco_info;
+ MMPco *pco;
GError *error = NULL;
- MMModem3gppSubscriptionState subscription_state;
- subscription_state = (MMModem3gppSubscriptionState)g_task_propagate_int (G_TASK (res), &error);
+ pco_info = g_match_info_fetch (match_info, 0);
+
+ mm_dbg ("Parsing vendor PCO info: %s", pco_info);
+ pco = mm_altair_parse_vendor_pco_info (pco_info, &error);
if (error) {
- mm_warn ("Couldn't load Subscription State: '%s'", error->message);
+ mm_warn ("Error parsing vendor PCO info: %s", error->message);
g_error_free (error);
return;
}
- if (subscription_state != MM_MODEM_3GPP_SUBSCRIPTION_STATE_UNKNOWN)
- mm_iface_modem_3gpp_update_subscription_state (MM_IFACE_MODEM_3GPP (self), subscription_state);
-}
-
-static void
-altair_pco_info_changed (MMPortSerialAt *port,
- GMatchInfo *match_info,
- MMBroadbandModemAltairLte *self)
-{
- LoadSubscriptionStateContext *ctx;
- const gchar *response;
- GTask *task;
-
- ctx = g_slice_new0 (LoadSubscriptionStateContext);
- response = g_match_info_fetch (match_info, 0);
- ctx->pco_info = g_strdup (response);
-
- task = g_task_new (self,
- NULL,
- (GAsyncReadyCallback)altair_get_subscription_state_ready,
- NULL);
- g_task_set_task_data (task, ctx, (GDestroyNotify)load_subscription_state_context_free);
-
- altair_get_subscription_state (MM_IFACE_MODEM_3GPP (self), task);
+ self->priv->pco_list = mm_pco_list_add (self->priv->pco_list, pco);
+ mm_iface_modem_3gpp_update_pco_list (MM_IFACE_MODEM_3GPP (self), self->priv->pco_list);
+ g_object_unref (pco);
}
/*****************************************************************************/
@@ -1413,8 +1307,6 @@ iface_modem_3gpp_init (MMIfaceModem3gpp *iface)
iface->load_operator_code_finish = modem_3gpp_load_operator_code_finish;
iface->load_operator_name = modem_3gpp_load_operator_name;
iface->load_operator_name_finish = modem_3gpp_load_operator_name_finish;
- iface->load_subscription_state = modem_3gpp_load_subscription_state;
- iface->load_subscription_state_finish = modem_3gpp_load_subscription_state_finish;
}
static void
diff --git a/plugins/altair/mm-modem-helpers-altair-lte.c b/plugins/altair/mm-modem-helpers-altair-lte.c
index d5c038f1..080e719a 100644
--- a/plugins/altair/mm-modem-helpers-altair-lte.c
+++ b/plugins/altair/mm-modem-helpers-altair-lte.c
@@ -141,62 +141,17 @@ mm_altair_parse_cid (const gchar *response, GError **error)
/*****************************************************************************/
/* %PCOINFO response parser */
-typedef enum {
- MM_VZW_PCO_PROVISIONED = 0,
- MM_VZW_PCO_LIMIT_REACHED = 1,
- MM_VZW_PCO_OUT_OF_DATA = 3,
- MM_VZW_PCO_UNPROVISIONED = 5
-} MMVzwPco;
-
-static guint
-altair_extract_vzw_pco_value (const gchar *pco_payload, GError **error)
-{
- GRegex *regex;
- GMatchInfo *match_info;
- guint pco_value = -1;
-
- /* Extract PCO value from PCO payload.
- * The PCO value in the VZW network is after the VZW PLMN (MCC+MNC 311-480).
- */
- regex = g_regex_new ("130184(\\d+)", G_REGEX_RAW, 0, NULL);
- g_assert (regex);
- if (!g_regex_match_full (regex,
- pco_payload,
- strlen (pco_payload),
- 0,
- 0,
- &match_info,
- error)) {
- g_match_info_free (match_info);
- g_regex_unref (regex);
- return -1;
- }
-
- if (!g_match_info_matches (match_info) ||
- !mm_get_uint_from_match_info (match_info, 1, &pco_value))
- g_set_error (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_FAILED,
- "Failed to parse PCO value from PCO payload: '%s'",
- pco_payload);
-
- g_match_info_free (match_info);
- g_regex_unref (regex);
-
- return pco_value;
-}
-
-guint
+MMPco *
mm_altair_parse_vendor_pco_info (const gchar *pco_info, GError **error)
{
GRegex *regex;
GMatchInfo *match_info;
- guint pco_value = -1;
+ MMPco *pco = NULL;
gint num_matches;
if (!pco_info[0])
/* No APNs configured, all done */
- return -1;
+ return NULL;
/* Expected %PCOINFO response:
*
@@ -210,7 +165,7 @@ mm_altair_parse_vendor_pco_info (const gchar *pco_info, GError **error)
if (!g_regex_match_full (regex, pco_info, strlen (pco_info), 0, 0, &match_info, error)) {
g_match_info_free (match_info);
g_regex_unref (regex);
- return -1;
+ return NULL;
}
num_matches = g_match_info_get_match_count (match_info);
@@ -222,13 +177,19 @@ mm_altair_parse_vendor_pco_info (const gchar *pco_info, GError **error)
num_matches);
g_match_info_free (match_info);
g_regex_unref (regex);
- return -1;
+ return NULL;
}
while (g_match_info_matches (match_info)) {
guint pco_cid;
gchar *pco_id;
gchar *pco_payload;
+ gsize pco_payload_len;
+ gchar *pco_payload_bytes = NULL;
+ gsize pco_payload_bytes_len;
+ guint8 pco_prefix[6];
+ GByteArray *pco_raw;
+ gsize pco_raw_len;
if (!mm_get_uint_from_match_info (match_info, 1, &pco_cid)) {
g_set_error (error,
@@ -239,6 +200,12 @@ mm_altair_parse_vendor_pco_info (const gchar *pco_info, GError **error)
break;
}
+ /* We are only interested in IMS and Internet PDN PCO. */
+ if (pco_cid != MM_ALTAIR_IMS_PDN_CID && pco_cid != MM_ALTAIR_INTERNET_PDN_CID) {
+ g_match_info_next (match_info, error);
+ continue;
+ }
+
pco_id = mm_get_string_unquoted_from_match_info (match_info, 3);
if (!pco_id) {
g_set_error (error,
@@ -265,20 +232,64 @@ mm_altair_parse_vendor_pco_info (const gchar *pco_info, GError **error)
break;
}
- pco_value = altair_extract_vzw_pco_value (pco_payload, error);
+ pco_payload_len = strlen (pco_payload);
+ if (pco_payload_len % 2 == 0)
+ pco_payload_bytes = mm_utils_hexstr2bin (pco_payload, &pco_payload_bytes_len);
+
g_free (pco_payload);
- /* We are only interested in IMS and Internet PDN PCO. */
- if (pco_cid == MM_ALTAIR_IMS_PDN_CID || pco_cid == MM_ALTAIR_INTERNET_PDN_CID) {
+ if (!pco_payload_bytes) {
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Invalid PCO payload from PCO info: '%s'",
+ pco_info);
break;
}
- pco_value = -1;
- g_match_info_next (match_info, error);
+ /* Protocol Configuration Options (PCO) is an information element with an
+ * identifier (IEI) 0x27 and contains between 3 and 253 octets. See 3GPP TS
+ * 24.008 for more details on PCO.
+ *
+ * NOTE: The standard uses one-based indexing, but to better correlate to the
+ * code, zero-based indexing is used in the description hereinafter.
+ *
+ * Octet | Value
+ * --------+--------------------------------------------
+ * 0 | PCO IEI (= 0x27)
+ * 1 | Length of PCO contents (= total length - 2)
+ * 2 | bit 7 : ext
+ * | bit 6 to 3 : spare (= 0b0000)
+ * | bit 2 to 0 : Configuration protocol
+ * 3 to 4 | Element 1 ID
+ * 5 | Length of element 1 contents
+ * 6 to m | Element 1 contents
+ * ... |
+ */
+ pco_raw_len = sizeof (pco_prefix) + pco_payload_bytes_len;
+ pco_prefix[0] = 0x27;
+ pco_prefix[1] = pco_raw_len - 2;
+ pco_prefix[2] = 0x80;
+ /* Verizon uses element ID 0xFF00 for carrier-specific PCO content. */
+ pco_prefix[3] = 0xFF;
+ pco_prefix[4] = 0x00;
+ pco_prefix[5] = pco_payload_bytes_len;
+
+ pco_raw = g_byte_array_sized_new (pco_raw_len);
+ g_byte_array_append (pco_raw, pco_prefix, sizeof (pco_prefix));
+ g_byte_array_append (pco_raw, (guint8 *)pco_payload_bytes, pco_payload_bytes_len);
+ g_free (pco_payload_bytes);
+
+ pco = mm_pco_new ();
+ mm_pco_set_session_id (pco, pco_cid);
+ mm_pco_set_complete (pco, TRUE);
+ mm_pco_set_data (pco, pco_raw->data, pco_raw->len);
+ g_byte_array_unref (pco_raw);
+ break;
}
g_match_info_free (match_info);
g_regex_unref (regex);
- return pco_value;
+ return pco;
}
diff --git a/plugins/altair/mm-modem-helpers-altair-lte.h b/plugins/altair/mm-modem-helpers-altair-lte.h
index b3199978..226e7884 100644
--- a/plugins/altair/mm-modem-helpers-altair-lte.h
+++ b/plugins/altair/mm-modem-helpers-altair-lte.h
@@ -19,6 +19,9 @@
#include <glib.h>
+#define _LIBMM_INSIDE_MM
+#include <libmm-glib.h>
+
/* Bands response parser */
GArray *mm_altair_parse_bands_response (const gchar *response);
@@ -30,6 +33,6 @@ gchar *mm_altair_parse_ceer_response (const gchar *response,
guint mm_altair_parse_cid (const gchar *response, GError **error);
/* %PCOINFO response parser */
-guint mm_altair_parse_vendor_pco_info (const gchar *pco_info, GError **error);
+MMPco *mm_altair_parse_vendor_pco_info (const gchar *pco_info, GError **error);
#endif /* MM_MODEM_HELPERS_ALTAIR_H */
diff --git a/plugins/altair/tests/test-modem-helpers-altair-lte.c b/plugins/altair/tests/test-modem-helpers-altair-lte.c
index a4901cd6..ec25e5f8 100644
--- a/plugins/altair/tests/test-modem-helpers-altair-lte.c
+++ b/plugins/altair/tests/test-modem-helpers-altair-lte.c
@@ -16,6 +16,7 @@
#include <stdarg.h>
#include <stdio.h>
+#include <string.h>
#include <glib.h>
#include <glib-object.h>
#include <locale.h>
@@ -59,7 +60,7 @@ typedef struct {
} CeerTest;
static const CeerTest ceer_tests[] = {
- { "", "" }, /* Special case, sometimes the response is empty, treat it as a valid response. */
+ { "", "" }, /* Special case, sometimes the response is empty, treat it as a good response. */
{ "+CEER:", "" },
{ "+CEER: EPS_AND_NON_EPS_SERVICES_NOT_ALLOWED", "EPS_AND_NON_EPS_SERVICES_NOT_ALLOWED" },
{ "+CEER: NO_SUITABLE_CELLS_IN_TRACKING_AREA", "NO_SUITABLE_CELLS_IN_TRACKING_AREA" },
@@ -97,45 +98,81 @@ test_parse_cid (void)
g_assert (mm_altair_parse_cid ("%CGINFO:blah", NULL) == -1);
}
-static void
-test_parse_vendor_pco_info (void)
-{
- guint pco_value;
+/*****************************************************************************/
+/* Test %PCOINFO responses */
+
+typedef struct {
+ const gchar *pco_info;
+ guint32 session_id;
+ gsize pco_data_size;
+ guint8 pco_data[50];
+} TestValidPcoInfo;
+static const TestValidPcoInfo good_pco_infos[] = {
/* Valid PCO values */
- pco_value = mm_altair_parse_vendor_pco_info ("%PCOINFO: 1,1,FF00,13018400", NULL);
- g_assert (pco_value == 0);
- pco_value = mm_altair_parse_vendor_pco_info ("%PCOINFO: 1,1,FF00,13018403", NULL);
- g_assert (pco_value == 3);
- pco_value = mm_altair_parse_vendor_pco_info ("%PCOINFO: 1,1,FF00,13018405", NULL);
- g_assert (pco_value == 5);
- pco_value = mm_altair_parse_vendor_pco_info ("%PCOINFO: 1,3,FF00,13018400", NULL);
- g_assert (pco_value == 0);
- pco_value = mm_altair_parse_vendor_pco_info ("%PCOINFO: 1,3,FF00,13018403", NULL);
- g_assert (pco_value == 3);
- pco_value = mm_altair_parse_vendor_pco_info ("%PCOINFO: 1,3,FF00,13018405", NULL);
- g_assert (pco_value == 5);
- pco_value = mm_altair_parse_vendor_pco_info ("%PCOINFO:1,FF00,13018400", NULL);
- g_assert (pco_value == 0);
- pco_value = mm_altair_parse_vendor_pco_info ("%PCOINFO:1,FF00,13018403", NULL);
- g_assert (pco_value == 3);
- pco_value = mm_altair_parse_vendor_pco_info ("%PCOINFO:1,FF00,13018405", NULL);
- g_assert (pco_value == 5);
- /* Different container */
- pco_value = mm_altair_parse_vendor_pco_info ("%PCOINFO: 1,3,F000,13018401", NULL);
- g_assert (pco_value == -1);
- /* Invalid CID */
- pco_value = mm_altair_parse_vendor_pco_info ("%PCOINFO: 1,2,FF00,13018401", NULL);
- g_assert (pco_value == -1);
+ { "%PCOINFO: 1,1,FF00,13018400", 1, 10,
+ { 0x27, 0x08, 0x80, 0xFF, 0x00, 0x04, 0x13, 0x01, 0x84, 0x00 } },
+ { "%PCOINFO: 1,1,FF00,13018403", 1, 10,
+ { 0x27, 0x08, 0x80, 0xFF, 0x00, 0x04, 0x13, 0x01, 0x84, 0x03 } },
+ { "%PCOINFO: 1,1,FF00,13018405", 1, 10,
+ { 0x27, 0x08, 0x80, 0xFF, 0x00, 0x04, 0x13, 0x01, 0x84, 0x05 } },
+ { "%PCOINFO: 1,3,FF00,13018400", 3, 10,
+ { 0x27, 0x08, 0x80, 0xFF, 0x00, 0x04, 0x13, 0x01, 0x84, 0x00 } },
+ { "%PCOINFO: 1,3,FF00,13018403", 3, 10,
+ { 0x27, 0x08, 0x80, 0xFF, 0x00, 0x04, 0x13, 0x01, 0x84, 0x03 } },
+ { "%PCOINFO: 1,3,FF00,13018405", 3, 10,
+ { 0x27, 0x08, 0x80, 0xFF, 0x00, 0x04, 0x13, 0x01, 0x84, 0x05 } },
+ { "%PCOINFO:1,FF00,13018400", 1, 10,
+ { 0x27, 0x08, 0x80, 0xFF, 0x00, 0x04, 0x13, 0x01, 0x84, 0x00 } },
+ { "%PCOINFO:1,FF00,13018403", 1, 10,
+ { 0x27, 0x08, 0x80, 0xFF, 0x00, 0x04, 0x13, 0x01, 0x84, 0x03 } },
+ { "%PCOINFO:1,FF00,13018405", 1, 10,
+ { 0x27, 0x08, 0x80, 0xFF, 0x00, 0x04, 0x13, 0x01, 0x84, 0x05 } },
/* Different payload */
- pco_value = mm_altair_parse_vendor_pco_info ("%PCOINFO: 1,3,FF00,13018501", NULL);
- g_assert (pco_value == -1);
- /* Bad PCO info */
- pco_value = mm_altair_parse_vendor_pco_info ("%PCOINFO: blah,blah,FF00,13018401", NULL);
- g_assert (pco_value == -1);
+ { "%PCOINFO: 1,3,FF00,130185", 3, 9,
+ { 0x27, 0x07, 0x80, 0xFF, 0x00, 0x03, 0x13, 0x01, 0x85 } },
/* Multiline PCO info */
- pco_value = mm_altair_parse_vendor_pco_info ("%PCOINFO: 1,2,FF00,13018400\r\n%PCOINFO: 1,3,FF00,13018403", NULL);
- g_assert (pco_value == 3);
+ { "%PCOINFO: 1,2,FF00,13018400\r\n%PCOINFO: 1,3,FF00,13018403", 3, 10,
+ { 0x27, 0x08, 0x80, 0xFF, 0x00, 0x04, 0x13, 0x01, 0x84, 0x03 } },
+};
+
+static const gchar *bad_pco_infos[] = {
+ /* Different container */
+ "%PCOINFO: 1,3,F000,13018401",
+ /* Ingood CID */
+ "%PCOINFO: 1,2,FF00,13018401",
+ /* Bad PCO info */
+ "%PCOINFO: blah,blah,FF00,13018401",
+ /* Bad PCO payload */
+ "%PCOINFO: 1,1,FF00,130184011",
+};
+
+static void
+test_parse_vendor_pco_info (void)
+{
+ MMPco *pco;
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (good_pco_infos); ++i) {
+ const guint8 *pco_data;
+ gsize pco_data_size;
+
+ pco = mm_altair_parse_vendor_pco_info (good_pco_infos[i].pco_info, NULL);
+ g_assert (pco != NULL);
+ g_assert_cmpuint (mm_pco_get_session_id (pco), ==, good_pco_infos[i].session_id);
+ g_assert (mm_pco_is_complete (pco));
+ pco_data = mm_pco_get_data (pco, &pco_data_size);
+ g_assert (pco_data != NULL);
+ g_assert_cmpuint (pco_data_size, ==, good_pco_infos[i].pco_data_size);
+ g_assert_cmpmem (pco_data, pco_data_size,
+ good_pco_infos[i].pco_data, good_pco_infos[i].pco_data_size);
+ g_object_unref (pco);
+ }
+
+ for (i = 0; i < G_N_ELEMENTS (bad_pco_infos); ++i) {
+ pco = mm_altair_parse_vendor_pco_info (bad_pco_infos[i], NULL);
+ g_assert (pco == NULL);
+ }
}
int main (int argc, char **argv)