[PATCH 1/3] libqmi-glib, device: new getter/setter for the expected data format in the kernel
Dan Williams
dcbw at redhat.com
Wed Jan 6 09:04:59 PST 2016
On Tue, 2015-12-29 at 17:39 +0100, Aleksander Morgado wrote:
> 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//qmi/raw_ip sysfs files).
>
> These new API methods allow to query and modify the data format expected by the
> kernel.
> ---
> .../libqmi-glib/libqmi-glib-common.sections | 7 +
> src/libqmi-glib/qmi-device.c | 179 ++++++++++++++++++++-
> src/libqmi-glib/qmi-device.h | 19 +++
> 3 files changed, 204 insertions(+), 1 deletion(-)
>
> 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
>
> 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
>
> qmi_device_open_flags_get_string
> qmi_device_release_client_flags_get_string
> +qmi_device_expected_data_format_build_string_from_mask
>
>
>
> diff --git a/src/libqmi-glib/qmi-device.c b/src/libqmi-glib/qmi-device.c
> index c9d05c0..198db60 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 at aleksander.es>
> */
>
> +#include
> #include
> #include
> #include
> @@ -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;
> + }
Would just g_file_get_contents() work here? Or is that too heavy?
Otherwise looks fine.
Dan
> + 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
>
More information about the libqmi-devel
mailing list