diff options
Diffstat (limited to 'src/libmbim-glib/mbim-device.c')
-rw-r--r-- | src/libmbim-glib/mbim-device.c | 119 |
1 files changed, 100 insertions, 19 deletions
diff --git a/src/libmbim-glib/mbim-device.c b/src/libmbim-glib/mbim-device.c index c0bb5da..a001940 100644 --- a/src/libmbim-glib/mbim-device.c +++ b/src/libmbim-glib/mbim-device.c @@ -23,6 +23,11 @@ * Implementation based on the 'QmiDevice' GObject from libqmi-glib. */ +#include <config.h> + +#define _GNU_SOURCE +#include <stdlib.h> +#include <unistd.h> #include <errno.h> #include <string.h> #include <fcntl.h> @@ -30,11 +35,14 @@ #include <unistd.h> #include <gio/gio.h> #include <gio/gunixsocketaddress.h> -#include <gudev/gudev.h> #include <sys/ioctl.h> #define IOCTL_WDM_MAX_COMMAND _IOR('H', 0xA0, guint16) #define RETRY_TIMEOUT_SECS 5 +#if WITH_UDEV +# include <gudev/gudev.h> +#endif + #include "mbim-utils.h" #include "mbim-device.h" #include "mbim-message.h" @@ -762,21 +770,17 @@ struct usb_cdc_mbim_desc { guint8 bmNetworkCapabilities; } __attribute__ ((packed)); -static guint16 -read_max_control_transfer (MbimDevice *self) +#if WITH_UDEV + +static gchar * +get_descriptors_filepath (MbimDevice *self) { - static const guint8 mbim_signature[4] = { 0x0c, 0x24, 0x1b, 0x00 }; - guint16 max = MAX_CONTROL_TRANSFER; GUdevClient *client; GUdevDevice *device = NULL; GUdevDevice *parent_device = NULL; GUdevDevice *grandparent_device = NULL; gchar *descriptors_path = NULL; gchar *device_basename = NULL; - GError *error = NULL; - gchar *contents = NULL; - gsize length = 0; - guint i; client = g_udev_client_new (NULL); if (!G_UDEV_IS_CLIENT (client)) { @@ -826,6 +830,93 @@ read_max_control_transfer (MbimDevice *self) g_udev_device_get_sysfs_path (grandparent_device), "descriptors", NULL); + +out: + g_free (device_basename); + if (parent_device) + g_object_unref (parent_device); + if (grandparent_device) + g_object_unref (grandparent_device); + if (device) + g_object_unref (device); + if (client) + g_object_unref (client); + + return descriptors_path; +} + +#else + +static gchar * +get_descriptors_filepath (MbimDevice *self) +{ + static const gchar *subsystems[] = { "usbmisc", "usb" }; + guint i; + gchar *device_basename; + gchar *descriptors_path = NULL; + + device_basename = g_path_get_basename (self->priv->path); + + for (i = 0; !descriptors_path && i < G_N_ELEMENTS (subsystems); i++) { + gchar *tmp; + gchar *path; + + /* parent sysfs can be built directly using subsystem and name; e.g. for subsystem + * usbmisc and name cdc-wdm0: + * $ realpath /sys/class/usbmisc/cdc-wdm0/device + * /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.5/2-1.5:2.0 + */ + tmp = g_strdup_printf ("/sys/class/%s/%s/device", subsystems[i], device_basename); + path = canonicalize_file_name (tmp); + g_free (tmp); + + if (g_file_test (path, G_FILE_TEST_EXISTS)) { + /* Now look for the parent dir with descriptors file. */ + gchar *dirname; + + dirname = g_path_get_dirname (path); + descriptors_path = g_build_path (G_DIR_SEPARATOR_S, + dirname, + "descriptors", + NULL); + g_free (dirname); + } + g_free (path); + } + + g_free (device_basename); + + if (descriptors_path && !g_file_test (descriptors_path, G_FILE_TEST_EXISTS)) { + g_warning ("[%s] Descriptors file doesn't exist", + self->priv->path_display); + g_free (descriptors_path); + descriptors_path = NULL; + } + + return descriptors_path; +} + +#endif + +static guint16 +read_max_control_transfer (MbimDevice *self) +{ + static const guint8 mbim_signature[4] = { 0x0c, 0x24, 0x1b, 0x00 }; + guint16 max = MAX_CONTROL_TRANSFER; + gchar *descriptors_path; + GError *error = NULL; + gchar *contents = NULL; + gsize length = 0; + guint i; + + /* Build descriptors filepath */ + descriptors_path = get_descriptors_filepath (self); + if (!descriptors_path) { + g_warning ("[%s] Couldn't get descriptors file path", + self->priv->path_display); + goto out; + } + if (!g_file_get_contents (descriptors_path, &contents, &length, @@ -859,16 +950,6 @@ read_max_control_transfer (MbimDevice *self) out: g_free (contents); - g_free (device_basename); - g_free (descriptors_path); - if (parent_device) - g_object_unref (parent_device); - if (grandparent_device) - g_object_unref (grandparent_device); - if (device) - g_object_unref (device); - if (client) - g_object_unref (client); return max; } |