diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2015-12-27 22:52:23 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2016-01-24 16:56:25 +0100 |
commit | 7af76cd9dde951bc7bcaf540a926110794d24484 (patch) | |
tree | 5e77a39589b4408eca5c052844200c660ed9d7b4 | |
parent | 4ff70bbd7e3cd62810322f4d273a03d8f3943248 (diff) | |
download | external_libqmi-7af76cd9dde951bc7bcaf540a926110794d24484.zip external_libqmi-7af76cd9dde951bc7bcaf540a926110794d24484.tar.gz external_libqmi-7af76cd9dde951bc7bcaf540a926110794d24484.tar.bz2 |
libqmi-glib,device: new getter/setter for the expected data format in the kernel
Userspace is in charge of defining the data format to be used in the WWAN net
interface, both in the device itself (e.g. through CTL or WDA requests) and also
in the kernel (e.g. through /sys/class/net/<WWAN>/qmi/raw_ip sysfs files).
These new API methods allow to query and modify the data format expected by the
kernel.
-rw-r--r-- | docs/reference/libqmi-glib/libqmi-glib-common.sections | 7 | ||||
-rw-r--r-- | src/libqmi-glib/qmi-device.c | 179 | ||||
-rw-r--r-- | src/libqmi-glib/qmi-device.h | 19 |
3 files changed, 204 insertions, 1 deletions
diff --git a/docs/reference/libqmi-glib/libqmi-glib-common.sections b/docs/reference/libqmi-glib/libqmi-glib-common.sections index f5d5619..2893851 100644 --- a/docs/reference/libqmi-glib/libqmi-glib-common.sections +++ b/docs/reference/libqmi-glib/libqmi-glib-common.sections @@ -50,6 +50,7 @@ QmiDevice QmiDeviceOpenFlags QmiDeviceReleaseClientFlags QmiDeviceServiceVersionInfo +QmiDeviceExpectedDataFormat qmi_device_new qmi_device_new_finish qmi_device_get_file @@ -57,6 +58,8 @@ qmi_device_peek_file qmi_device_get_path qmi_device_get_path_display qmi_device_get_wwan_iface +qmi_device_get_expected_data_format +qmi_device_set_expected_data_format qmi_device_is_open qmi_device_open qmi_device_open_finish @@ -73,6 +76,7 @@ qmi_device_get_service_version_info qmi_device_get_service_version_info_finish qmi_device_open_flags_build_string_from_mask qmi_device_release_client_flags_build_string_from_mask +qmi_device_expected_data_format_get_string <SUBSECTION Standard> QmiDeviceClass QMI_DEVICE @@ -83,13 +87,16 @@ QMI_IS_DEVICE_CLASS QMI_TYPE_DEVICE QMI_TYPE_DEVICE_OPEN_FLAGS QMI_TYPE_DEVICE_RELEASE_CLIENT_FLAGS +QMI_TYPE_DEVICE_EXPECTED_DATA_FORMAT QmiDevicePrivate qmi_device_get_type qmi_device_open_flags_get_type qmi_device_release_client_flags_get_type +qmi_device_expected_data_format_get_type <SUBSECTION Private> qmi_device_open_flags_get_string qmi_device_release_client_flags_get_string +qmi_device_expected_data_format_build_string_from_mask </SECTION> <SECTION> diff --git a/src/libqmi-glib/qmi-device.c b/src/libqmi-glib/qmi-device.c index 9c0bc38..6603fb7 100644 --- a/src/libqmi-glib/qmi-device.c +++ b/src/libqmi-glib/qmi-device.c @@ -21,6 +21,7 @@ * Copyright (C) 2012-2015 Aleksander Morgado <aleksander@aleksander.es> */ +#include <stdio.h> #include <errno.h> #include <string.h> #include <fcntl.h> @@ -678,7 +679,7 @@ reload_wwan_iface_name (QmiDevice *self) * @self: a #QmiDevice. * * Get the WWAN interface name associated with this /dev/cdc-wdm control port. - * This value will be loaded the first time it's asked for it. + * This value will be loaded every time it's asked for it. * * Returns: UTF-8 encoded network interface name, or %NULL if not available. */ @@ -692,6 +693,182 @@ qmi_device_get_wwan_iface (QmiDevice *self) } /*****************************************************************************/ +/* Expected data format */ + +static gboolean +get_expected_data_format (QmiDevice *self, + const gchar *sysfs_path, + GError **error) +{ + QmiDeviceExpectedDataFormat expected = QMI_DEVICE_EXPECTED_DATA_FORMAT_UNKNOWN; + gchar value = '\0'; + FILE *f; + + g_debug ("[%s] Reading expected data format from: %s", + self->priv->path_display, + sysfs_path); + + if (!(f = fopen (sysfs_path, "r"))) { + g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), + "Failed to open file '%s': %s", + sysfs_path, g_strerror (errno)); + goto out; + } + + if (fread (&value, 1, 1, f) != 1) { + g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), + "Failed to read from file '%s': %s", + sysfs_path, g_strerror (errno)); + goto out; + } + + if (value == 'Y') + expected = QMI_DEVICE_EXPECTED_DATA_FORMAT_RAW_IP; + else if (value == 'N') + expected = QMI_DEVICE_EXPECTED_DATA_FORMAT_802_3; + else + g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED, + "Unexpected sysfs file contents"); + + out: + g_prefix_error (error, "Expected data format not retrieved properly: "); + if (f) + fclose (f); + return expected; +} + +static gboolean +set_expected_data_format (QmiDevice *self, + const gchar *sysfs_path, + QmiDeviceExpectedDataFormat requested, + GError **error) +{ + gboolean status = FALSE; + gchar value; + FILE *f; + + g_debug ("[%s] Writing expected data format to: %s", + self->priv->path_display, + sysfs_path); + + if (requested == QMI_DEVICE_EXPECTED_DATA_FORMAT_RAW_IP) + value = 'Y'; + else if (requested == QMI_DEVICE_EXPECTED_DATA_FORMAT_802_3) + value = 'N'; + else + g_assert_not_reached (); + + if (!(f = fopen (sysfs_path, "w"))) { + g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), + "Failed to open file '%s' for R/W: %s", + sysfs_path, g_strerror (errno)); + goto out; + } + + if (fwrite (&value, 1, 1, f) != 1) { + g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), + "Failed to write to file '%s': %s", + sysfs_path, g_strerror (errno)); + goto out; + } + + status = TRUE; + + out: + g_prefix_error (error, "Expected data format not updated properly: "); + if (f) + fclose (f); + return status; +} + +static QmiDeviceExpectedDataFormat +common_get_set_expected_data_format (QmiDevice *self, + QmiDeviceExpectedDataFormat requested, + GError **error) +{ + gchar *sysfs_path = NULL; + QmiDeviceExpectedDataFormat expected = QMI_DEVICE_EXPECTED_DATA_FORMAT_UNKNOWN; + gboolean readonly; + + readonly = (requested == QMI_DEVICE_EXPECTED_DATA_FORMAT_UNKNOWN); + + /* Make sure we load the WWAN iface name */ + reload_wwan_iface_name (self); + if (!self->priv->wwan_iface) { + g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED, + "Unknown wwan iface"); + goto out; + } + + /* Build sysfs file path and open it */ + sysfs_path = g_strdup_printf ("/sys/class/net/%s/qmi/raw_ip", self->priv->wwan_iface); + + /* Set operation? */ + if (!readonly && !set_expected_data_format (self, sysfs_path, requested, error)) + goto out; + + /* Get/Set operations */ + if ((expected = get_expected_data_format (self, sysfs_path, error)) == QMI_DEVICE_EXPECTED_DATA_FORMAT_UNKNOWN) + goto out; + + /* If we requested an update but we didn't read that value, report an error */ + if (!readonly && (requested != expected)) { + g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED, + "Expected data format not updated properly to '%s': got '%s' instead", + qmi_device_expected_data_format_get_string (requested), + qmi_device_expected_data_format_get_string (expected)); + expected = QMI_DEVICE_EXPECTED_DATA_FORMAT_UNKNOWN; + } + + out: + g_free (sysfs_path); + return expected; +} + +/** + * qmi_device_get_expected_data_format: + * @self: a #QmiDevice. + * @error: Return location for error or %NULL. + * + * Retrieves the data format currently expected by the kernel in the network + * interface. + * + * If @QMI_DEVICE_EXPECTED_DATA_FORMAT_UNKNOWN is returned, the user should assume + * that 802.3 is the expected format. + * + * Returns: a valid #QmiDeviceExpectedDataFormat, or @QMI_DEVICE_EXPECTED_DATA_FORMAT_UNKNOWN if @error is set. + */ +QmiDeviceExpectedDataFormat +qmi_device_get_expected_data_format (QmiDevice *self, + GError **error) +{ + g_return_val_if_fail (QMI_IS_DEVICE (self), QMI_DEVICE_EXPECTED_DATA_FORMAT_UNKNOWN); + + return common_get_set_expected_data_format (self, QMI_DEVICE_EXPECTED_DATA_FORMAT_UNKNOWN, error); +} + +/** + * qmi_device_set_expected_data_format: + * @self: a #QmiDevice. + * @format: a known #QmiDeviceExpectedDataFormat. + * @error: Return location for error or %NULL. + * + * Configures the data format currently expected by the kernel in the network + * interface. + * + * Returns: %TRUE if successful, or #NULL if @error is set. + */ +gboolean +qmi_device_set_expected_data_format (QmiDevice *self, + QmiDeviceExpectedDataFormat format, + GError **error) +{ + g_return_val_if_fail (QMI_IS_DEVICE (self), FALSE); + + return (common_get_set_expected_data_format (self, format, error) != QMI_DEVICE_EXPECTED_DATA_FORMAT_UNKNOWN); +} + +/*****************************************************************************/ /* Register/Unregister clients that want to receive indications */ static gpointer diff --git a/src/libqmi-glib/qmi-device.h b/src/libqmi-glib/qmi-device.h index 09a0766..58651e1 100644 --- a/src/libqmi-glib/qmi-device.h +++ b/src/libqmi-glib/qmi-device.h @@ -201,6 +201,25 @@ void qmi_device_get_service_version_info (QmiDevice *self, GArray *qmi_device_get_service_version_info_finish (QmiDevice *self, GAsyncResult *res, GError **error); +/** + * QmiDeviceExpectedDataFormat: + * @QMI_DEVICE_EXPECTED_DATA_FORMAT_UNKNOWN: Unknown. + * @QMI_DEVICE_EXPECTED_DATA_FORMAT_802_3: 802.3. + * @QMI_DEVICE_EXPECTED_DATA_FORMAT_RAW_IP: Raw IP. + * + * Data format expected by the kernel. + */ +typedef enum { + QMI_DEVICE_EXPECTED_DATA_FORMAT_UNKNOWN, + QMI_DEVICE_EXPECTED_DATA_FORMAT_802_3, + QMI_DEVICE_EXPECTED_DATA_FORMAT_RAW_IP, +} QmiDeviceExpectedDataFormat; + +QmiDeviceExpectedDataFormat qmi_device_get_expected_data_format (QmiDevice *self, + GError **error); +gboolean qmi_device_set_expected_data_format (QmiDevice *self, + QmiDeviceExpectedDataFormat format, + GError **error); G_END_DECLS |