[PATCH v2] huawei: implement modem power up and down
Dan Williams
dcbw at redhat.com
Mon Aug 5 21:06:01 PDT 2013
On Fri, 2013-08-02 at 18:07 -0700, Ben Chan wrote:
> This patch is originally developed by:
> Franko Fang <fangxiaozhi at huawei.com>
>
> And then reviewed and updated by:
> Ben Chan <benchan at chromium.org>
Pushed this one, thanks. I don't have a modem with RFSWITCH that I can
find at the moment, but this worked for devices that do not support
RFSWITCH.
Thanks,
Dan
> ---
> plugins/huawei/mm-broadband-modem-huawei.c | 218 +++++++++++++++++++++++++++++
> 1 file changed, 218 insertions(+)
>
> diff --git a/plugins/huawei/mm-broadband-modem-huawei.c b/plugins/huawei/mm-broadband-modem-huawei.c
> index eb13a1b..15f3524 100644
> --- a/plugins/huawei/mm-broadband-modem-huawei.c
> +++ b/plugins/huawei/mm-broadband-modem-huawei.c
> @@ -67,6 +67,12 @@ typedef enum {
> NDISDUP_SUPPORTED
> } NdisdupSupport;
>
> +typedef enum {
> + RFSWITCH_SUPPORT_UNKNOWN,
> + RFSWITCH_NOT_SUPPORTED,
> + RFSWITCH_SUPPORTED
> +} RfswitchSupport;
> +
> struct _MMBroadbandModemHuaweiPrivate {
> /* Regex for signal quality related notifications */
> GRegex *rssi_regex;
> @@ -89,6 +95,7 @@ struct _MMBroadbandModemHuaweiPrivate {
> GRegex *ndisstat_regex;
>
> NdisdupSupport ndisdup_support;
> + RfswitchSupport rfswitch_support;
>
> gboolean sysinfoex_supported;
> gboolean sysinfoex_support_checked;
> @@ -2536,6 +2543,210 @@ modem_time_load_network_time (MMIfaceModemTime *self,
> }
>
> /*****************************************************************************/
> +/* Power state loading (Modem interface) */
> +
> +static void
> +parent_load_power_state_ready (MMIfaceModem *self,
> + GAsyncResult *res,
> + GSimpleAsyncResult *result)
> +{
> + GError *error = NULL;
> + MMModemPowerState power_state;
> +
> + power_state = iface_modem_parent->load_power_state_finish (self, res, &error);
> + if (error)
> + g_simple_async_result_take_error (result, error);
> + else
> + g_simple_async_result_set_op_res_gpointer (result, GUINT_TO_POINTER (power_state), NULL);
> +
> + g_simple_async_result_complete (result);
> + g_object_unref (result);
> +}
> +
> +static void
> +huawei_rfswitch_check_ready (MMBaseModem *_self,
> + GAsyncResult *res,
> + GSimpleAsyncResult *result)
> +{
> + MMBroadbandModemHuawei *self = MM_BROADBAND_MODEM_HUAWEI (_self);
> + GError *error = NULL;
> + const gchar *response;
> + gint sw_state;
> +
> + response = mm_base_modem_at_command_finish (_self, res, &error);
> + if (response) {
> + response = mm_strip_tag (response, "^RFSWITCH:");
> + if (sscanf (response, "%d", &sw_state) != 1 ||
> + (sw_state != 0 && sw_state != 1)) {
> + mm_warn ("Couldn't parse ^RFSWITCH response: '%s'", response);
> + error = g_error_new (MM_CORE_ERROR,
> + MM_CORE_ERROR_FAILED,
> + "Couldn't parse ^RFSWITCH response: '%s'",
> + response);
> + }
> + }
> +
> + switch (self->priv->rfswitch_support) {
> + case RFSWITCH_SUPPORT_UNKNOWN:
> + if (error) {
> + mm_dbg ("The device does not support ^RFSWITCH");
> + self->priv->rfswitch_support = RFSWITCH_NOT_SUPPORTED;
> + g_error_free (error);
> + /* Fall back to parent's load_power_state */
> + iface_modem_parent->load_power_state (MM_IFACE_MODEM (self),
> + (GAsyncReadyCallback)parent_load_power_state_ready,
> + result);
> + return;
> + }
> +
> + mm_dbg ("The device supports ^RFSWITCH");
> + self->priv->rfswitch_support = RFSWITCH_SUPPORTED;
> + break;
> + case RFSWITCH_SUPPORTED:
> + break;
> + default:
> + g_assert_not_reached ();
> + break;
> + }
> +
> + if (error)
> + g_simple_async_result_take_error (result, error);
> + else
> + g_simple_async_result_set_op_res_gpointer (result,
> + sw_state ?
> + GUINT_TO_POINTER (MM_MODEM_POWER_STATE_ON) :
> + GUINT_TO_POINTER (MM_MODEM_POWER_STATE_LOW),
> + NULL);
> +
> + g_simple_async_result_complete (result);
> + g_object_unref (result);
> +}
> +
> +static MMModemPowerState
> +load_power_state_finish (MMIfaceModem *self,
> + GAsyncResult *res,
> + GError **error)
> +{
> + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
> + return MM_MODEM_POWER_STATE_UNKNOWN;
> +
> + return (MMModemPowerState)GPOINTER_TO_UINT (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
> +}
> +
> +static void
> +load_power_state (MMIfaceModem *self,
> + GAsyncReadyCallback callback,
> + gpointer user_data)
> +{
> + GSimpleAsyncResult *result;
> +
> + result = g_simple_async_result_new (G_OBJECT (self),
> + callback,
> + user_data,
> + load_power_state);
> +
> + switch (MM_BROADBAND_MODEM_HUAWEI (self)->priv->rfswitch_support) {
> + case RFSWITCH_SUPPORT_UNKNOWN:
> + case RFSWITCH_SUPPORTED: {
> + mm_base_modem_at_command (MM_BASE_MODEM (self),
> + "^RFSWITCH?",
> + 3,
> + FALSE,
> + (GAsyncReadyCallback)huawei_rfswitch_check_ready,
> + result);
> + break;
> + }
> + case RFSWITCH_NOT_SUPPORTED:
> + /* Run parent's load_power_state */
> + iface_modem_parent->load_power_state (self,
> + (GAsyncReadyCallback)parent_load_power_state_ready,
> + result);
> + break;
> + default:
> + g_assert_not_reached ();
> + break;
> + }
> +}
> +
> +/*****************************************************************************/
> +/* Modem power up (Modem interface) */
> +
> +static gboolean
> +huawei_modem_power_up_finish (MMIfaceModem *self,
> + GAsyncResult *res,
> + GError **error)
> +{
> + return !!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error);
> +}
> +
> +static void
> +huawei_modem_power_up (MMIfaceModem *self,
> + GAsyncReadyCallback callback,
> + gpointer user_data)
> +{
> + switch (MM_BROADBAND_MODEM_HUAWEI (self)->priv->rfswitch_support) {
> + case RFSWITCH_NOT_SUPPORTED:
> + mm_base_modem_at_command (MM_BASE_MODEM (self),
> + "+CFUN=1",
> + 30,
> + FALSE,
> + callback,
> + user_data);
> + break;
> + case RFSWITCH_SUPPORTED:
> + mm_base_modem_at_command (MM_BASE_MODEM (self),
> + "^RFSWITCH=1",
> + 30,
> + FALSE,
> + callback,
> + user_data);
> + break;
> + default:
> + g_assert_not_reached ();
> + break;
> + }
> +}
> +
> +/*****************************************************************************/
> +/* Modem power down (Modem interface) */
> +
> +static gboolean
> +huawei_modem_power_down_finish (MMIfaceModem *self,
> + GAsyncResult *res,
> + GError **error)
> +{
> + return !!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error);
> +}
> +
> +static void
> +huawei_modem_power_down (MMIfaceModem *self,
> + GAsyncReadyCallback callback,
> + gpointer user_data)
> +{
> + switch (MM_BROADBAND_MODEM_HUAWEI (self)->priv->rfswitch_support) {
> + case RFSWITCH_NOT_SUPPORTED:
> + mm_base_modem_at_command (MM_BASE_MODEM (self),
> + "+CFUN=0",
> + 30,
> + FALSE,
> + callback,
> + user_data);
> + break;
> + case RFSWITCH_SUPPORTED:
> + mm_base_modem_at_command (MM_BASE_MODEM (self),
> + "^RFSWITCH=0",
> + 30,
> + FALSE,
> + callback,
> + user_data);
> + break;
> + default:
> + g_assert_not_reached ();
> + break;
> + }
> +}
> +
> +/*****************************************************************************/
> /* Check support (Time interface) */
>
> static gboolean
> @@ -2700,6 +2911,7 @@ mm_broadband_modem_huawei_init (MMBroadbandModemHuawei *self)
> G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
>
> self->priv->ndisdup_support = NDISDUP_SUPPORT_UNKNOWN;
> + self->priv->rfswitch_support = RFSWITCH_SUPPORT_UNKNOWN;
>
> self->priv->sysinfoex_supported = FALSE;
> self->priv->sysinfoex_support_checked = FALSE;
> @@ -2751,6 +2963,12 @@ iface_modem_init (MMIfaceModem *iface)
> iface->load_signal_quality_finish = modem_load_signal_quality_finish;
> iface->create_bearer = huawei_modem_create_bearer;
> iface->create_bearer_finish = huawei_modem_create_bearer_finish;
> + iface->load_power_state = load_power_state;
> + iface->load_power_state_finish = load_power_state_finish;
> + iface->modem_power_up = huawei_modem_power_up;
> + iface->modem_power_up_finish = huawei_modem_power_up_finish;
> + iface->modem_power_down = huawei_modem_power_down;
> + iface->modem_power_down_finish = huawei_modem_power_down_finish;
> }
>
> static void
More information about the ModemManager-devel
mailing list