broadband-modem-mbim,bearer-mbim: support connect from MBIMEx v3.0

Whenever MBIMEx v3.0 is enabled, the logic should create requests and
parse responses using the updated format.

Based on an initial implementation by Som_SP <somashekhar.puttagangaiah@intel.com>
This commit is contained in:
Aleksander Morgado
2021-11-21 14:48:04 +01:00
parent 9940bd9dbe
commit 3382e421cc
2 changed files with 287 additions and 114 deletions

View File

@@ -604,6 +604,7 @@ connect_set_ready (MbimDevice *device,
MMBearerMbim *self; MMBearerMbim *self;
ConnectContext *ctx; ConnectContext *ctx;
GError *error = NULL; GError *error = NULL;
g_autoptr(GError) inner_error = NULL;
g_autoptr(MbimMessage) response = NULL; g_autoptr(MbimMessage) response = NULL;
guint32 session_id; guint32 session_id;
MbimActivationState activation_state; MbimActivationState activation_state;
@@ -613,12 +614,16 @@ connect_set_ready (MbimDevice *device,
ctx = g_task_get_task_data (task); ctx = g_task_get_task_data (task);
response = mbim_device_command_finish (device, res, &error); response = mbim_device_command_finish (device, res, &error);
if (response && if (!response ||
(mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error) || (!mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error) &&
error->code == MBIM_STATUS_ERROR_FAILURE)) { (error->code != MBIM_STATUS_ERROR_FAILURE))) {
g_autoptr(GError) inner_error = NULL; g_task_return_error (task, error);
g_object_unref (task);
return;
}
if (mbim_message_connect_response_parse ( if (mbim_device_check_ms_mbimex_version (device, 3, 0)) {
if (!mbim_message_ms_basic_connect_v3_connect_response_parse (
response, response,
&session_id, &session_id,
&activation_state, &activation_state,
@@ -626,26 +631,47 @@ connect_set_ready (MbimDevice *device,
&ctx->activated_ip_type, &ctx->activated_ip_type,
NULL, /* context_type */ NULL, /* context_type */
&nw_error, &nw_error,
&inner_error)) { NULL, /* media_preference */
/* Report the IP type we asked for and the one returned by the modem */ NULL, /* access_string */
mm_obj_dbg (self, "session ID '%u': %s (requested IP type: %s, activated IP type: %s, nw error: %s)", NULL, /* unnamed_ies */
session_id, &inner_error))
mbim_activation_state_get_string (activation_state), g_prefix_error (&inner_error, "Failed processing MBIMEx v3.0 connect response: ");
mbim_context_ip_type_get_string (ctx->requested_ip_type), else
mbim_context_ip_type_get_string (ctx->activated_ip_type), mm_obj_dbg (self, "processed MBIMEx v3.0 connect response");
mbim_nw_error_get_string (nw_error)); } else {
/* If the response reports an ACTIVATED state, we're good even if if (!mbim_message_connect_response_parse (
* there is a nw_error set (e.g. asking for IPv4v6 may return a response,
* 'pdp-type-ipv4-only-allowed' nw_error). */ &session_id,
if (activation_state != MBIM_ACTIVATION_STATE_ACTIVATED && &activation_state,
activation_state != MBIM_ACTIVATION_STATE_ACTIVATING) { NULL, /* voice_call_state */
g_clear_error (&error); &ctx->activated_ip_type,
error = mm_mobile_equipment_error_from_mbim_nw_error (nw_error, self); NULL, /* context_type */
} &nw_error,
} else { &inner_error))
/* Prefer the error from the result to the parsing error */ g_prefix_error (&inner_error, "Failed processing connect response: ");
if (!error) else
error = g_steal_pointer (&inner_error); mm_obj_dbg (self, "processed connect response");
}
/* Prefer the error from the result to the parsing error */
if (inner_error) {
if (!error)
error = g_steal_pointer (&inner_error);
} else {
/* Report the IP type we asked for and the one returned by the modem */
mm_obj_dbg (self, "session ID '%u': %s (requested IP type: %s, activated IP type: %s, nw error: %s)",
session_id,
mbim_activation_state_get_string (activation_state),
mbim_context_ip_type_get_string (ctx->requested_ip_type),
mbim_context_ip_type_get_string (ctx->activated_ip_type),
mbim_nw_error_get_string (nw_error));
/* If the response reports an ACTIVATED state, we're good even if
* there is a nw_error set (e.g. asking for IPv4v6 may return a
* 'pdp-type-ipv4-only-allowed' nw_error). */
if (activation_state != MBIM_ACTIVATION_STATE_ACTIVATED &&
activation_state != MBIM_ACTIVATION_STATE_ACTIVATING) {
g_clear_error (&error);
error = mm_mobile_equipment_error_from_mbim_nw_error (nw_error, self);
} }
} }
@@ -687,26 +713,40 @@ check_disconnected_ready (MbimDevice *device,
ConnectContext *ctx; ConnectContext *ctx;
g_autoptr(MbimMessage) response = NULL; g_autoptr(MbimMessage) response = NULL;
guint32 session_id; guint32 session_id;
MbimActivationState activation_state; MbimActivationState activation_state = MBIM_ACTIVATION_STATE_UNKNOWN;
self = g_task_get_source_object (task); self = g_task_get_source_object (task);
ctx = g_task_get_task_data (task); ctx = g_task_get_task_data (task);
response = mbim_device_command_finish (device, res, NULL); response = mbim_device_command_finish (device, res, NULL);
if (response && if (response && mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, NULL)) {
mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, NULL) && if (mbim_device_check_ms_mbimex_version (device, 3, 0))
mbim_message_connect_response_parse ( mbim_message_ms_basic_connect_v3_connect_response_parse (
response, response,
&session_id, &session_id,
&activation_state, &activation_state,
NULL, /* voice_call_state */ NULL, /* voice_call_state */
NULL, /* ip_type */ NULL, /* ip_type */
NULL, /* context_type */ NULL, /* context_type */
NULL, /* nw_error */ NULL, /* nw_error */
NULL)) { NULL, /* media_preference */
NULL, /* access_string */
NULL, /* unnamed_ies */
NULL);
else
mbim_message_connect_response_parse (
response,
&session_id,
&activation_state,
NULL, /* voice_call_state */
NULL, /* ip_type */
NULL, /* context_type */
NULL, /* nw_error */
NULL);
}
if (activation_state != MBIM_ACTIVATION_STATE_UNKNOWN)
mm_obj_dbg (self, "session ID '%u': %s", session_id, mbim_activation_state_get_string (activation_state)); mm_obj_dbg (self, "session ID '%u': %s", session_id, mbim_activation_state_get_string (activation_state));
} else
activation_state = MBIM_ACTIVATION_STATE_UNKNOWN;
/* Some modem (e.g. Huawei ME936) reports MBIM_ACTIVATION_STATE_UNKNOWN /* Some modem (e.g. Huawei ME936) reports MBIM_ACTIVATION_STATE_UNKNOWN
* when being queried for the activation state before an IP session has * when being queried for the activation state before an IP session has
@@ -1068,37 +1108,66 @@ connect_context_step (GTask *task)
ctx->step++; ctx->step++;
/* fall through */ /* fall through */
case CONNECT_STEP_CHECK_DISCONNECTED: case CONNECT_STEP_CHECK_DISCONNECTED: {
MbimDevice *device;
mm_obj_dbg (self, "checking if session %u is disconnected...", ctx->session_id); mm_obj_dbg (self, "checking if session %u is disconnected...", ctx->session_id);
message = mbim_message_connect_query_new (
ctx->session_id, device = mm_port_mbim_peek_device (ctx->mbim);
MBIM_ACTIVATION_STATE_UNKNOWN, if (mbim_device_check_ms_mbimex_version (device, 3, 0))
MBIM_VOICE_CALL_STATE_NONE, message = mbim_message_ms_basic_connect_v3_connect_query_new (ctx->session_id, NULL);
MBIM_CONTEXT_IP_TYPE_DEFAULT, else
mbim_uuid_from_context_type (MBIM_CONTEXT_TYPE_INTERNET), message = mbim_message_connect_query_new (
0, ctx->session_id,
NULL); MBIM_ACTIVATION_STATE_UNKNOWN,
mbim_device_command (mm_port_mbim_peek_device (ctx->mbim), MBIM_VOICE_CALL_STATE_NONE,
MBIM_CONTEXT_IP_TYPE_DEFAULT,
mbim_uuid_from_context_type (MBIM_CONTEXT_TYPE_INTERNET),
0,
NULL);
mbim_device_command (device,
message, message,
10, 10,
NULL, NULL,
(GAsyncReadyCallback)check_disconnected_ready, (GAsyncReadyCallback)check_disconnected_ready,
task); task);
return; return;
}
case CONNECT_STEP_ENSURE_DISCONNECTED: {
MbimDevice *device;
case CONNECT_STEP_ENSURE_DISCONNECTED:
mm_obj_dbg (self, "ensuring session %u is disconnected...", ctx->session_id); mm_obj_dbg (self, "ensuring session %u is disconnected...", ctx->session_id);
message = mbim_message_connect_set_new (
ctx->session_id, device = mm_port_mbim_peek_device (ctx->mbim);
MBIM_ACTIVATION_COMMAND_DEACTIVATE, if (mbim_device_check_ms_mbimex_version (device, 3, 0))
"", message = mbim_message_ms_basic_connect_v3_connect_set_new (
"", ctx->session_id,
"", MBIM_ACTIVATION_COMMAND_DEACTIVATE,
MBIM_COMPRESSION_NONE, MBIM_COMPRESSION_NONE,
MBIM_AUTH_PROTOCOL_NONE, MBIM_AUTH_PROTOCOL_NONE,
MBIM_CONTEXT_IP_TYPE_DEFAULT, MBIM_CONTEXT_IP_TYPE_DEFAULT,
mbim_uuid_from_context_type (MBIM_CONTEXT_TYPE_INTERNET), mbim_uuid_from_context_type (MBIM_CONTEXT_TYPE_INTERNET),
NULL); MBIM_ACCESS_MEDIA_TYPE_UNKNOWN,
"", /* access string */
"", /* user name */
"", /* password */
NULL, /* unnamed ies */
NULL);
else
message = mbim_message_connect_set_new (
ctx->session_id,
MBIM_ACTIVATION_COMMAND_DEACTIVATE,
"",
"",
"",
MBIM_COMPRESSION_NONE,
MBIM_AUTH_PROTOCOL_NONE,
MBIM_CONTEXT_IP_TYPE_DEFAULT,
mbim_uuid_from_context_type (MBIM_CONTEXT_TYPE_INTERNET),
NULL);
mbim_device_command (mm_port_mbim_peek_device (ctx->mbim), mbim_device_command (mm_port_mbim_peek_device (ctx->mbim),
message, message,
MM_BASE_BEARER_DEFAULT_DISCONNECTION_TIMEOUT, MM_BASE_BEARER_DEFAULT_DISCONNECTION_TIMEOUT,
@@ -1106,21 +1175,42 @@ connect_context_step (GTask *task)
(GAsyncReadyCallback)ensure_disconnected_ready, (GAsyncReadyCallback)ensure_disconnected_ready,
task); task);
return; return;
}
case CONNECT_STEP_CONNECT: {
MbimDevice *device;
case CONNECT_STEP_CONNECT:
mm_obj_dbg (self, "launching %s connection in session %u...", mm_obj_dbg (self, "launching %s connection in session %u...",
mbim_context_ip_type_get_string (ctx->requested_ip_type), ctx->session_id); mbim_context_ip_type_get_string (ctx->requested_ip_type), ctx->session_id);
message = mbim_message_connect_set_new (
ctx->session_id, device = mm_port_mbim_peek_device (ctx->mbim);
MBIM_ACTIVATION_COMMAND_ACTIVATE, if (mbim_device_check_ms_mbimex_version (device, 3, 0))
ctx->apn ? ctx->apn : "", message = mbim_message_ms_basic_connect_v3_connect_set_new (
ctx->user ? ctx->user : "", ctx->session_id,
ctx->password ? ctx->password : "", MBIM_ACTIVATION_COMMAND_ACTIVATE,
MBIM_COMPRESSION_NONE, MBIM_COMPRESSION_NONE,
ctx->auth, ctx->auth,
ctx->requested_ip_type, ctx->requested_ip_type,
mbim_uuid_from_context_type (ctx->context_type), mbim_uuid_from_context_type (ctx->context_type),
NULL); MBIM_ACCESS_MEDIA_TYPE_UNKNOWN,
ctx->apn ? ctx->apn : "",
ctx->user ? ctx->user : "",
ctx->password ? ctx->password : "",
NULL, /* unnamed ies */
NULL);
else
message = mbim_message_connect_set_new (
ctx->session_id,
MBIM_ACTIVATION_COMMAND_ACTIVATE,
ctx->apn ? ctx->apn : "",
ctx->user ? ctx->user : "",
ctx->password ? ctx->password : "",
MBIM_COMPRESSION_NONE,
ctx->auth,
ctx->requested_ip_type,
mbim_uuid_from_context_type (ctx->context_type),
NULL);
mbim_device_command (mm_port_mbim_peek_device (ctx->mbim), mbim_device_command (mm_port_mbim_peek_device (ctx->mbim),
message, message,
MM_BASE_BEARER_DEFAULT_CONNECTION_TIMEOUT, MM_BASE_BEARER_DEFAULT_CONNECTION_TIMEOUT,
@@ -1128,6 +1218,7 @@ connect_context_step (GTask *task)
(GAsyncReadyCallback)connect_set_ready, (GAsyncReadyCallback)connect_set_ready,
task); task);
return; return;
}
case CONNECT_STEP_IP_CONFIGURATION: case CONNECT_STEP_IP_CONFIGURATION:
mm_obj_dbg (self, "querying IP configuration..."); mm_obj_dbg (self, "querying IP configuration...");
@@ -1399,15 +1490,29 @@ disconnect_set_ready (MbimDevice *device,
if (result || if (result ||
g_error_matches (error, MBIM_STATUS_ERROR, MBIM_STATUS_ERROR_FAILURE) || g_error_matches (error, MBIM_STATUS_ERROR, MBIM_STATUS_ERROR_FAILURE) ||
g_error_matches (error, MBIM_STATUS_ERROR, MBIM_STATUS_ERROR_CONTEXT_NOT_ACTIVATED)) { g_error_matches (error, MBIM_STATUS_ERROR, MBIM_STATUS_ERROR_CONTEXT_NOT_ACTIVATED)) {
parsed_result = mbim_message_connect_response_parse ( if (mbim_device_check_ms_mbimex_version (device, 3, 0))
response, parsed_result = mbim_message_ms_basic_connect_v3_connect_response_parse (
&session_id, response,
&activation_state, &session_id,
NULL, /* voice_call_state */ &activation_state,
NULL, /* ip_type */ NULL, /* voice_call_state */
NULL, /* context_type */ NULL, /* ip_type */
&nw_error, NULL, /* context_type */
&inner_error); &nw_error,
NULL, /* media_preference */
NULL, /* access_string */
NULL, /* unnamed_ies */
&inner_error);
else
parsed_result = mbim_message_connect_response_parse (
response,
&session_id,
&activation_state,
NULL, /* voice_call_state */
NULL, /* ip_type */
NULL, /* context_type */
&nw_error,
&inner_error);
} }
/* Now handle different response / error cases */ /* Now handle different response / error cases */
@@ -1472,18 +1577,35 @@ disconnect_context_step (GTask *task)
case DISCONNECT_STEP_DISCONNECT: { case DISCONNECT_STEP_DISCONNECT: {
g_autoptr(MbimMessage) message = NULL; g_autoptr(MbimMessage) message = NULL;
MbimDevice *device;
message = mbim_message_connect_set_new ( device = mm_port_mbim_peek_device (ctx->mbim);
ctx->session_id, if (mbim_device_check_ms_mbimex_version (device, 3, 0))
MBIM_ACTIVATION_COMMAND_DEACTIVATE, message = mbim_message_ms_basic_connect_v3_connect_set_new (
"", ctx->session_id,
"", MBIM_ACTIVATION_COMMAND_DEACTIVATE,
"", MBIM_COMPRESSION_NONE,
MBIM_COMPRESSION_NONE, MBIM_AUTH_PROTOCOL_NONE,
MBIM_AUTH_PROTOCOL_NONE, MBIM_CONTEXT_IP_TYPE_DEFAULT,
MBIM_CONTEXT_IP_TYPE_DEFAULT, mbim_uuid_from_context_type (MBIM_CONTEXT_TYPE_INTERNET),
mbim_uuid_from_context_type (MBIM_CONTEXT_TYPE_INTERNET), MBIM_ACCESS_MEDIA_TYPE_UNKNOWN,
NULL); "",
"",
"",
NULL,
NULL);
else
message = mbim_message_connect_set_new (
ctx->session_id,
MBIM_ACTIVATION_COMMAND_DEACTIVATE,
"",
"",
"",
MBIM_COMPRESSION_NONE,
MBIM_AUTH_PROTOCOL_NONE,
MBIM_CONTEXT_IP_TYPE_DEFAULT,
mbim_uuid_from_context_type (MBIM_CONTEXT_TYPE_INTERNET),
NULL);
mbim_device_command (mm_port_mbim_peek_device (ctx->mbim), mbim_device_command (mm_port_mbim_peek_device (ctx->mbim),
message, message,
MM_BASE_BEARER_DEFAULT_DISCONNECTION_TIMEOUT, MM_BASE_BEARER_DEFAULT_DISCONNECTION_TIMEOUT,
@@ -1598,17 +1720,46 @@ reload_connection_status_ready (MbimDevice *device,
self = g_task_get_source_object (task); self = g_task_get_source_object (task);
response = mbim_device_command_finish (device, res, &error); response = mbim_device_command_finish (device, res, &error);
if (!response || if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
!mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error) || g_prefix_error (&error, "Cannot load session ID '%u' status: ",
!mbim_message_connect_response_parse ( mm_bearer_mbim_get_session_id (MM_BEARER_MBIM (self)));
response, g_task_return_error (task, error);
&session_id, g_object_unref (task);
&activation_state, return;
NULL, /* voice_call_state */ }
NULL, /* ip_type */
NULL, /* context_type */ if (mbim_device_check_ms_mbimex_version (device, 3, 0)) {
NULL, /* nw_error */ if (!mbim_message_ms_basic_connect_v3_connect_response_parse (
&error)) { response,
&session_id,
&activation_state,
NULL, /* voice_call_state */
NULL, /* ip_type */
NULL, /* context_type */
NULL, /* nw_error */
NULL, /* media_preference */
NULL, /* access_string */
NULL, /* unnamed_ies */
&error))
g_prefix_error (&error, "Failed processing MBIMEx v3.0 connect response: ");
else
mm_obj_dbg (self, "processed MBIMEx v3.0 connect response");
} else {
if (!mbim_message_connect_response_parse (
response,
&session_id,
&activation_state,
NULL, /* voice_call_state */
NULL, /* ip_type */
NULL, /* context_type */
NULL, /* nw_error */
&error))
g_prefix_error (&error, "Failed processing connect response: ");
else
mm_obj_dbg (self, "processed connect response");
}
if (error) {
g_prefix_error (&error, "Cannot load session ID '%u' status: ", g_prefix_error (&error, "Cannot load session ID '%u' status: ",
mm_bearer_mbim_get_session_id (MM_BEARER_MBIM (self))); mm_bearer_mbim_get_session_id (MM_BEARER_MBIM (self)));
g_task_return_error (task, error); g_task_return_error (task, error);

View File

@@ -3871,17 +3871,39 @@ basic_connect_notification_connect (MMBroadbandModemMbim *self,
const MbimUuid *context_type; const MbimUuid *context_type;
guint32 nw_error; guint32 nw_error;
g_autoptr(MMBearerList) bearer_list = NULL; g_autoptr(MMBearerList) bearer_list = NULL;
g_autoptr(GError) error = NULL;
if (!mbim_message_connect_notification_parse ( if (mbim_device_check_ms_mbimex_version (device, 3, 0)) {
notification, if (!mbim_message_ms_basic_connect_v3_connect_notification_parse (
&session_id, notification,
&activation_state, &session_id,
NULL, /* voice_call_state */ &activation_state,
NULL, /* ip_type */ NULL, /* voice_call_state */
&context_type, NULL, /* ip_type */
&nw_error, &context_type, /* context_type */
NULL)) { &nw_error,
return; NULL, /* media_preference */
NULL, /* access_string */
NULL, /* unnamed_ies */
&error)) {
mm_obj_warn (self, "Failed processing MBIMEx v3.0 connect notification: %s", error->message);
return;
}
mm_obj_dbg (self, "processed MBIMEx v3.0 connect notification");
} else {
if (!mbim_message_connect_notification_parse (
notification,
&session_id,
&activation_state,
NULL, /* voice_call_state */
NULL, /* ip_type */
&context_type,
&nw_error,
&error)) {
mm_obj_warn (self, "Failed processing connect notification: %s", error->message);
return;
}
mm_obj_dbg (self, "processed connect notification");
} }
g_object_get (self, g_object_get (self,