Skip to content
Snippets Groups Projects
Commit f9ea6778 authored by Aleksander Morgado's avatar Aleksander Morgado
Browse files

ms-uicc-low-level-access: add support for 'Read Record' operation

  $ sudo mbimcli -p -d /dev/wwan0mbim0 --ms-query-uicc-read-record="application-id=A0000000871002FF34FF0789312E30FF,file-path=3F002FE2"
  [/dev/wwan0mbim0] UICC file record read:
  	Status word 1: 144
  	Status word 2: 0
  	         Data: 98:43:70:77:00:10:85:84:36:F8
parent 88bb60ba
No related branches found
No related tags found
1 merge request!154Implement UICC file read operations from Microsoft Extensions
......@@ -191,6 +191,31 @@
"format" : "string" },
{ "name" : "Data",
"format" : "ref-byte-array" } ],
"response" : [ { "name" : "Version",
"format" : "guint32" },
{ "name" : "StatusWord1",
"format" : "guint32" },
{ "name" : "StatusWord2",
"format" : "guint32" },
{ "name" : "Data",
"format" : "ref-byte-array" } ] },
// *********************************************************************************
{ "name" : "Read Record",
"type" : "Command",
"since" : "1.28",
"query" : [ { "name" : "Version",
"format" : "guint32" },
{ "name" : "ApplicationId",
"format" : "ref-byte-array" },
{ "name" : "FilePath",
"format" : "ref-byte-array" },
{ "name" : "RecordNumber",
"format" : "guint32" },
{ "name" : "LocalPin",
"format" : "string" },
{ "name" : "Data",
"format" : "ref-byte-array" } ],
"response" : [ { "name" : "Version",
"format" : "guint32" },
{ "name" : "StatusWord1",
......
......@@ -179,7 +179,7 @@ static const CidConfig cid_qdu_config [MBIM_CID_QDU_LAST] = {
};
/* Note: index of the array is CID-1 */
#define MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_LAST MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_READ_BINARY
#define MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_LAST MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_READ_RECORD
static const CidConfig cid_ms_uicc_low_level_access_config [MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_LAST] = {
{ NO_SET, QUERY, NO_NOTIFY }, /* MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_ATR */
{ SET, NO_QUERY, NO_NOTIFY }, /* MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_OPEN_CHANNEL */
......@@ -190,6 +190,7 @@ static const CidConfig cid_ms_uicc_low_level_access_config [MBIM_CID_MS_UICC_LOW
{ NO_SET, QUERY, NO_NOTIFY }, /* MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_APPLICATION_LIST */
{ NO_SET, QUERY, NO_NOTIFY }, /* MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_FILE_STATUS */
{ SET, QUERY, NO_NOTIFY }, /* MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_READ_BINARY */
{ SET, QUERY, NO_NOTIFY }, /* MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_READ_RECORD */
};
/* Note: index of the array is CID-1 */
......
......@@ -380,6 +380,7 @@ typedef enum { /*< since=1.18 >*/
* @MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_APPLICATION_LIST: Retrieve application list. Since 1.28.
* @MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_FILE_STATUS: Retrieve information about a specific UICC file. Since 1.28.
* @MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_READ_BINARY: Read a UICC binary file. Since 1.28.
* @MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_READ_RECORD: Read a UICC linear fixed or cyclic file. Since 1.28.
*
* MBIM commands in the %MBIM_SERVICE_MS_UICC_LOW_LEVEL_ACCESS service.
*
......@@ -396,6 +397,7 @@ typedef enum { /*< since=1.26 >*/
MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_APPLICATION_LIST = 7,
MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_FILE_STATUS = 8,
MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_READ_BINARY = 9,
MBIM_CID_MS_UICC_LOW_LEVEL_ACCESS_READ_RECORD = 10,
} MbimCidMsUiccLowLevelAccess;
/**
......
......@@ -34,6 +34,7 @@ static Context *ctx;
static gboolean query_uicc_application_list_flag;
static gchar *query_uicc_file_status_str;
static gchar *query_uicc_read_binary_str;
static gchar *query_uicc_read_record_str;
static GOptionEntry entries[] = {
{ "ms-query-uicc-application-list", 0, 0, G_OPTION_ARG_NONE, &query_uicc_application_list_flag,
......@@ -48,6 +49,10 @@ static GOptionEntry entries[] = {
"Read UICC binary file (allowed keys: application-id, file-path, read-offset, read-size, local-pin and data)",
"[\"key=value,...\"]"
},
{ "ms-query-uicc-read-record", 0, 0, G_OPTION_ARG_STRING, &query_uicc_read_record_str,
"Read UICC record file (allowed keys: application-id, file-path, record-number, local-pin and data)",
"[\"key=value,...\"]"
},
{ NULL }
};
......@@ -77,7 +82,8 @@ mbimcli_ms_uicc_low_level_access_options_enabled (void)
n_actions = query_uicc_application_list_flag +
!!query_uicc_file_status_str +
!!query_uicc_read_binary_str;
!!query_uicc_read_binary_str +
!!query_uicc_read_record_str;
if (n_actions > 1) {
g_printerr ("error: too many Microsoft UICC Low Level Access Service actions requested\n");
......@@ -109,6 +115,147 @@ shutdown (gboolean operation_status)
mbimcli_async_operation_done (operation_status);
}
static void
read_record_query_ready (MbimDevice *device,
GAsyncResult *res)
{
g_autoptr(MbimMessage) response = NULL;
g_autoptr(GError) error = NULL;
guint32 status_word_1;
guint32 status_word_2;
const guint8 *data;
guint32 data_size;
g_autofree gchar *data_str = NULL;
response = mbim_device_command_finish (device, res, &error);
if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
g_printerr ("error: operation failed: %s\n", error->message);
shutdown (FALSE);
return;
}
if (!mbim_message_ms_uicc_low_level_access_read_record_response_parse (
response,
NULL, /* version */
&status_word_1,
&status_word_2,
&data_size,
&data,
&error)) {
g_printerr ("error: couldn't parse response message: %s\n", error->message);
shutdown (FALSE);
return;
}
data_str = mbim_common_str_hex (data, data_size, ':');
g_print ("[%s] UICC file record read:\n"
"\tStatus word 1: %u\n"
"\tStatus word 2: %u\n"
"\t Data: %s\n",
mbim_device_get_path_display (device),
status_word_1,
status_word_2,
data_str);
shutdown (TRUE);
}
typedef struct {
gsize application_id_size;
guint8 *application_id;
gsize file_path_size;
guint8 *file_path;
guint32 record_number;
gchar *local_pin;
gsize data_size;
guint8 *data;
} ReadRecordQueryProperties;
static void
read_record_query_properties_clear (ReadRecordQueryProperties *props)
{
g_clear_pointer (&props->application_id, g_free);
g_clear_pointer (&props->file_path, g_free);
g_clear_pointer (&props->local_pin, g_free);
g_clear_pointer (&props->data, g_free);
}
G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(ReadRecordQueryProperties, read_record_query_properties_clear);
static gboolean
read_record_query_properties_handle (const gchar *key,
const gchar *value,
GError **error,
gpointer user_data)
{
ReadRecordQueryProperties *props = user_data;
if (g_ascii_strcasecmp (key, "application-id") == 0) {
g_clear_pointer (&props->application_id, g_free);
props->application_id_size = 0;
props->application_id = mbimcli_read_buffer_from_string (value, -1, &props->application_id_size, error);
if (!props->application_id)
return FALSE;
} else if (g_ascii_strcasecmp (key, "file-path") == 0) {
g_clear_pointer (&props->file_path, g_free);
props->file_path_size = 0;
props->file_path = mbimcli_read_buffer_from_string (value, -1, &props->file_path_size, error);
if (!props->file_path)
return FALSE;
} else if (g_ascii_strcasecmp (key, "record-number") == 0) {
if (!mbimcli_read_uint_from_string (value, &props->record_number)) {
g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED,
"Failed to parse field as an integer");
return FALSE;
}
} else if (g_ascii_strcasecmp (key, "local-pin") == 0) {
g_clear_pointer (&props->local_pin, g_free);
props->local_pin = g_strdup (value);
} else if (g_ascii_strcasecmp (key, "data") == 0) {
g_clear_pointer (&props->data, g_free);
props->data_size = 0;
props->data = mbimcli_read_buffer_from_string (value, -1, &props->data_size, error);
if (!props->data)
return FALSE;
} else {
g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED,
"unrecognized option '%s'", key);
return FALSE;
}
return TRUE;
}
static gboolean
read_record_query_input_parse (const gchar *str,
ReadRecordQueryProperties *props,
GError **error)
{
if (!mbimcli_parse_key_value_string (str,
error,
read_record_query_properties_handle,
props))
return FALSE;
if (!props->application_id_size || !props->application_id) {
g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED,
"Option 'application-id' is missing");
return FALSE;
}
if (!props->file_path_size || !props->file_path) {
g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_FAILED,
"Option 'file-path' is missing");
return FALSE;
}
/* all the other fields are optional */
return TRUE;
}
static void
read_binary_query_ready (MbimDevice *device,
GAsyncResult *res)
......@@ -555,5 +702,45 @@ mbimcli_ms_uicc_low_level_access_run (MbimDevice *device,
return;
}
/* Request to UICC read record? */
if (query_uicc_read_record_str) {
g_auto(ReadRecordQueryProperties) props = {
.application_id_size = 0,
.application_id = NULL,
.file_path_size = 0,
.file_path = NULL,
.record_number = 0,
.local_pin = NULL,
.data_size = 0,
.data = NULL,
};
g_debug ("Asynchronously reading from UICC record...");
if (!read_record_query_input_parse (query_uicc_read_record_str, &props, &error)) {
g_printerr ("error: couldn't parse input arguments: %s\n", error->message);
shutdown (FALSE);
return;
}
request = mbim_message_ms_uicc_low_level_access_read_record_query_new (1, /* version fixed */
props.application_id_size,
props.application_id,
props.file_path_size,
props.file_path,
props.record_number,
props.local_pin,
props.data_size,
props.data,
NULL);
mbim_device_command (ctx->device,
request,
10,
ctx->cancellable,
(GAsyncReadyCallback)read_record_query_ready,
NULL);
return;
}
g_warn_if_reached ();
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment