summaryrefslogtreecommitdiff
path: root/src/libmbim-glib/mbim-device.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libmbim-glib/mbim-device.c')
-rw-r--r--src/libmbim-glib/mbim-device.c119
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;
}