diff options
author | Ben Chan <benchan@chromium.org> | 2018-10-18 16:37:19 -0700 |
---|---|---|
committer | Ben Chan <benchan@chromium.org> | 2018-10-26 09:41:44 -0700 |
commit | 408a2a9c6cef91e11a3ed5e09c140e175534822d (patch) | |
tree | adc2acf4453cfc964e7f094f9f5dc43374f23dad | |
parent | beb1aab17885bd2577964790986c5a79b6c120d7 (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.c | 186 | ||||
-rw-r--r-- | plugins/altair/mm-modem-helpers-altair-lte.c | 123 | ||||
-rw-r--r-- | plugins/altair/mm-modem-helpers-altair-lte.h | 5 | ||||
-rw-r--r-- | plugins/altair/tests/test-modem-helpers-altair-lte.c | 109 |
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) |