Re: [PATCH v7 10/10] mbim/network-registration: add support for manual registration

Andres Salomon <[email protected]> Fri, 12 Dec 2025 05:33:14 -0500
Newsgroups dev.linux.lists.ofono
Message-ID <[email protected]>
On 11/28/25 12:36, Muhammad Asif wrote:
> Adds support for scanning available operators, and manually registering
> to a selected network.
[...]
> diff --git a/drivers/mbimmodem/network-registration.c b/drivers/mbimmodem/network-registration.c
> index ded1bf69..e95dd73a 100644
> --- a/drivers/mbimmodem/network-registration.c
> +++ b/drivers/mbimmodem/network-registration.c
> @@ -204,6 +204,70 @@ static void mbim_current_operator(struct ofono_netreg *netreg,
>   	CALLBACK_WITH_FAILURE(cb, NULL, data);
>   }
>   
> +static void mbim_list_operators_cb(struct mbim_message *message,
> +						void *user)
> +{
> +	struct cb_data *cb = user;
> +	ofono_netreg_operator_list_cb_t cb_func = cb->cb;
> +	struct ofono_network_operator *list = NULL;
> +
> +	uint32_t providers_count, provider_state, cellular_class;
> +	uint32_t rssi, error_rate;
> +	char *provider_id, *provider_name;
> +	struct mbim_message_iter iter;
> +	int i = 0;
> +
> +	if (!mbim_message_get_arguments(message, "ua(susuuu)", &providers_count, &iter)) {
> +		CALLBACK_WITH_FAILURE(cb_func, 0, NULL, cb->data);
> +		return;
> +	}
> +
> +	list = l_new(struct ofono_network_operator, providers_count);
> +
> +	while (mbim_message_iter_next_entry(&iter, &provider_id, &provider_state,
> +					&provider_name, &cellular_class, &rssi, &error_rate)) {
> +
> +		strcpy(list[i].name, provider_name);

This should probably be a strncpy using OFONO_MAX_OPERATOR_NAME_LENGTH.


> +		strncpy(list[i].mcc, provider_id, OFONO_MAX_MCC_LENGTH);
> +		list[i].mcc[OFONO_MAX_MCC_LENGTH] = '\0';
> +
> +		strncpy(list[i].mnc, provider_id + OFONO_MAX_MCC_LENGTH, OFONO_MAX_MNC_LENGTH);
> +		list[i].mnc[OFONO_MAX_MNC_LENGTH] = '\0';
> +
> +		list[i].status = mbim_provider_state_to_status(provider_state);
> +		list[i].tech = -1;
> +
> +		i++;
> +	}
> +
> +	if (list)
> +		CALLBACK_WITH_SUCCESS(cb_func, providers_count, list, cb->data);
> +	else
> +		CALLBACK_WITH_FAILURE(cb_func, 0, NULL, cb->data);
> +}
> +
> +static void mbim_list_operators(struct ofono_netreg *netreg,
> +					ofono_netreg_operator_list_cb_t cb, void *user_data)
> +{
> +	struct netreg_data *nd = ofono_netreg_get_data(netreg);
> +	struct cb_data *cbd = cb_data_new(cb, user_data);
> +	struct mbim_message *message;
> +
> +	message = mbim_message_new(mbim_uuid_basic_connect,
> +						MBIM_CID_VISIBLE_PROVIDERS,
> +						MBIM_COMMAND_TYPE_QUERY);
> +	/* "0" is a full scan, whereas "1" means a restricted scan */
> +	mbim_message_set_arguments(message, "u", 0);
> +
> +	if (mbim_device_send(nd->device, NETREG_GROUP, message,
> +						mbim_list_operators_cb, cbd, l_free) > 0)
> +		return;
> +
> +	l_free(cbd);
> +	mbim_message_unref(message);
> +	CALLBACK_WITH_FAILURE(cb, 0, NULL, user_data);
> +}
> +
>   static void mbim_register_state_set_cb(struct mbim_message *message, void *user)
>   {
>   	struct cb_data *cbd = user;
> @@ -233,7 +297,42 @@ static void mbim_register_auto(struct ofono_netreg *netreg,
>   	message = mbim_message_new(mbim_uuid_basic_connect,
>   					MBIM_CID_REGISTER_STATE,
>   					MBIM_COMMAND_TYPE_SET);
> -	mbim_message_set_arguments(message, "suu", NULL, 0, data_class);
> +	mbim_message_set_arguments(message, "suu", NULL,
> +					MBIM_REGISTER_TYPE_AUTOMATIC, data_class);
> +
> +	if (mbim_device_send(nd->device, NETREG_GROUP, message,
> +				mbim_register_state_set_cb, cbd, l_free) > 0)
> +		return;
> +
> +	l_free(cbd);
> +	mbim_message_unref(message);
> +	CALLBACK_WITH_FAILURE(cb, data);
> +}
> +
> +static void mbim_register_manual(struct ofono_netreg *netreg,
> +				const char *mcc, const char *mnc,
> +				ofono_netreg_register_cb_t cb, void *data)
> +{
> +	static const uint32_t data_class = MBIM_DATA_CLASS_GPRS |
> +						MBIM_DATA_CLASS_EDGE |
> +						MBIM_DATA_CLASS_UMTS |
> +						MBIM_DATA_CLASS_HSDPA |
> +						MBIM_DATA_CLASS_HSUPA |
> +						MBIM_DATA_CLASS_LTE;
> +	struct netreg_data *nd = ofono_netreg_get_data(netreg);
> +	struct cb_data *cbd = cb_data_new(cb, data);
> +	struct mbim_message *message;
> +	L_AUTO_FREE_VAR(char *, provider_id) = NULL;
> +
> +	DBG("");
> +
> +	provider_id = l_strdup_printf("%s%s", mcc, mnc);
> +
> +	message = mbim_message_new(mbim_uuid_basic_connect,
> +					MBIM_CID_REGISTER_STATE,
> +					MBIM_COMMAND_TYPE_SET);
> +	mbim_message_set_arguments(message, "suu", provider_id,
> +					MBIM_REGISTER_TYPE_MANUAL, data_class);
>   

Given that mbim_register_auto and mbim_register_manual are almost the 
exact same function except for the MBIM_REGISTER_TYPE_* argument and 
provider_id (which is leaked, btw; should probably be deleted in 
mbim_register_state_set_cb?)... maybe it makes sense to have a common 
function for these two, with mbim_register_auto and mbim_register_manual 
calling it?



>   	if (mbim_device_send(nd->device, NETREG_GROUP, message,
>   				mbim_register_state_set_cb, cbd, l_free) > 0)
> @@ -385,7 +484,9 @@ static const struct ofono_netreg_driver driver = {
>   	.remove				= mbim_netreg_remove,
>   	.registration_status		= mbim_registration_status,
>   	.current_operator		= mbim_current_operator,
> +	.list_operators			= mbim_list_operators,
>   	.register_auto			= mbim_register_auto,
> +	.register_manual		= mbim_register_manual,
>   	.strength			= mbim_signal_strength,
>   };
>   
> diff --git a/drivers/mbimmodem/util.c b/drivers/mbimmodem/util.c
> index 731764fc..45b7af9b 100644
> --- a/drivers/mbimmodem/util.c
> +++ b/drivers/mbimmodem/util.c
> @@ -39,6 +39,26 @@ int mbim_data_class_to_tech(uint32_t n)
>   	return -1;

>