static gboolean input_accel_open (GUdevDevice *device, ReadingsUpdateFunc callback_func, gpointer user_data) { const gchar * const subsystems[] = { "input", NULL }; const char *mount_matrix; drv_data = g_new0 (DrvData, 1); drv_data->dev = g_object_ref (device); drv_data->parent = g_udev_device_get_parent (drv_data->dev); drv_data->dev_path = g_udev_device_get_device_file (device); drv_data->name = g_udev_device_get_property (device, "NAME"); drv_data->client = g_udev_client_new (subsystems); mount_matrix = g_udev_device_get_property (device, "ACCEL_MOUNT_MATRIX"); if (!parse_mount_matrix (mount_matrix, &drv_data->mount_matrix)) { g_warning ("Invalid mount-matrix ('%s'), falling back to identity", mount_matrix); parse_mount_matrix (NULL, &drv_data->mount_matrix); } drv_data->callback_func = callback_func; drv_data->user_data = user_data; g_signal_connect (drv_data->client, "uevent", G_CALLBACK (uevent_received), NULL); g_idle_add (first_values, NULL); return TRUE; }
/** * cd_plugin_is_device_embedded: **/ static gboolean cd_plugin_is_device_embedded (GUdevDevice *device) { GUdevDevice *p = device; const gchar *removable; gboolean embedded = FALSE; guint i; g_autoptr(GPtrArray) array = NULL; /* get a chain of all the parent devices */ array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); do { p = g_udev_device_get_parent (p); if (p == NULL) break; g_ptr_array_add (array, p); } while (TRUE); /* find a parent with a removable sysfs file */ for (i = 0; i < array->len; i++) { p = g_ptr_array_index (array, i); removable = g_udev_device_get_sysfs_attr (p, "removable"); if (removable != NULL) { if (g_strcmp0 (removable, "fixed") == 0) embedded = TRUE; break; } } return embedded; }
static char * get_bus (GUdevDevice *device) { const char *subsystem; char *bus_str; GUdevDevice *parent; bus_str = get_uinput_subsystem (device); if (bus_str) return bus_str; subsystem = g_udev_device_get_subsystem (device); parent = g_object_ref (device); while (parent && ((g_strcmp0 (subsystem, "input") == 0) || (g_strcmp0 (subsystem, "hid") == 0)) ){ GUdevDevice *old_parent = parent; parent = g_udev_device_get_parent (old_parent); if (parent) subsystem = g_udev_device_get_subsystem (parent); g_object_unref (old_parent); } if (parent) { if (g_strcmp0 (subsystem, "tty") == 0 || g_strcmp0 (subsystem, "serio") == 0) bus_str = g_strdup ("serial"); else bus_str = g_strdup (subsystem); g_object_unref (parent); } else bus_str = strdup("unknown"); return bus_str; }
static char * get_driver_name (GUdevDevice *device) { GUdevDevice *parent = NULL; const char *driver, *subsys; char *ret = NULL; driver = g_udev_device_get_driver (device); if (!driver) { parent = g_udev_device_get_parent (device); if (parent) driver = g_udev_device_get_driver (parent); /* Check for bluetooth; it's driver is a bunch of levels up so we * just check for the subsystem of the parent being bluetooth. */ if (!driver && parent) { subsys = g_udev_device_get_subsystem (parent); if (subsys && !strcmp (subsys, "bluetooth")) driver = "bluetooth"; } } if (driver) ret = g_strdup (driver); if (parent) g_object_unref (parent); return ret; }
static gboolean fu_altos_device_find_tty (FuAltosDevice *self, GError **error) { GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (self)); g_autoptr(GList) devices = NULL; g_autoptr(GUdevClient) gudev_client = g_udev_client_new (NULL); /* find all tty devices */ devices = g_udev_client_query_by_subsystem (gudev_client, "tty"); for (GList *l = devices; l != NULL; l = l->next) { GUdevDevice *dev = G_UDEV_DEVICE (l->data); /* get the tty device */ const gchar *dev_file = g_udev_device_get_device_file (dev); if (dev_file == NULL) continue; /* get grandparent */ dev = g_udev_device_get_parent (dev); if (dev == NULL) continue; dev = g_udev_device_get_parent (dev); if (dev == NULL) continue; /* check correct device */ if (g_udev_device_get_sysfs_attr_as_int (dev, "busnum") != g_usb_device_get_bus (usb_device)) continue; if (g_udev_device_get_sysfs_attr_as_int (dev, "devnum") != g_usb_device_get_address (usb_device)) continue; /* success */ self->tty = g_strdup (dev_file); return TRUE; } /* failure */ g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED, "failed to find tty for %u:%u", g_usb_device_get_bus (usb_device), g_usb_device_get_address (usb_device)); return FALSE; }
static Killswitch * killswitch_new (GUdevDevice *device, RfKillType rtype) { Killswitch *ks; GUdevDevice *parent = NULL, *grandparent = NULL; const char *driver, *subsys, *parent_subsys = NULL; ks = g_malloc0 (sizeof (Killswitch)); ks->name = g_strdup (g_udev_device_get_name (device)); ks->seqnum = g_udev_device_get_seqnum (device); ks->path = g_strdup (g_udev_device_get_sysfs_path (device)); ks->rtype = rtype; driver = g_udev_device_get_property (device, "DRIVER"); subsys = g_udev_device_get_subsystem (device); /* Check parent for various attributes */ parent = g_udev_device_get_parent (device); if (parent) { parent_subsys = g_udev_device_get_subsystem (parent); if (!driver) driver = g_udev_device_get_property (parent, "DRIVER"); if (!driver) { /* Sigh; try the grandparent */ grandparent = g_udev_device_get_parent (parent); if (grandparent) driver = g_udev_device_get_property (grandparent, "DRIVER"); } } if (!driver) driver = "(unknown)"; ks->driver = g_strdup (driver); if ( g_strcmp0 (subsys, "platform") == 0 || g_strcmp0 (parent_subsys, "platform") == 0 || g_strcmp0 (subsys, "acpi") == 0 || g_strcmp0 (parent_subsys, "acpi") == 0) ks->platform = TRUE; if (grandparent) g_object_unref (grandparent); if (parent) g_object_unref (parent); return ks; }
static gboolean device_is_serial(GUdevDevice * device) { GUdevDevice *parent; parent = g_udev_device_get_parent(device); if (parent) { /* Serial driver */ if (g_strcmp0(g_udev_device_get_name(parent), "serial8250") == 0) { g_object_unref(parent); return TRUE; } g_object_unref(parent); } return FALSE; }
static gboolean device_is_usb_serial(GUdevDevice * device) { GUdevDevice *parent; parent = g_udev_device_get_parent(device); if (parent) { /* Serial driver */ if (g_strcmp0(g_udev_device_get_subsystem(parent), "usb-serial") == 0) { g_object_unref(parent); return TRUE; } g_object_unref(parent); } return FALSE; }
const char * nmp_utils_udev_get_driver (GUdevDevice *device) { GUdevDevice *parent = NULL, *grandparent = NULL; const char *driver, *subsys; driver = g_udev_device_get_driver (device); if (driver) goto out; /* Try the parent */ parent = g_udev_device_get_parent (device); if (parent) { driver = g_udev_device_get_driver (parent); if (!driver) { /* Try the grandparent if it's an ibmebus device or if the * subsys is NULL which usually indicates some sort of * platform device like a 'gadget' net interface. */ subsys = g_udev_device_get_subsystem (parent); if ( (g_strcmp0 (subsys, "ibmebus") == 0) || (subsys == NULL)) { grandparent = g_udev_device_get_parent (parent); if (grandparent) driver = g_udev_device_get_driver (grandparent); } } } g_clear_object (&parent); g_clear_object (&grandparent); out: /* Intern the string so we don't have to worry about memory * management in NMPlatformLink. */ return g_intern_string (driver); }
static void dump_device_and_parent(GUdevDevice * device, guint indent) { const gchar *const *list; const gchar *const *iter; GUdevDevice *parent; char propstr[500]; guint32 namelen = 0, i; println(indent, "------------------------------------------------------"); println(indent, "%-20s %s", _("Name:"), g_udev_device_get_name(device)); println(indent, "%-20s %s", _("Type:"), g_udev_device_get_devtype(device)); println(indent, "%-20s %s", _("Subsystem:"), g_udev_device_get_subsystem(device)); println(indent, "%-20s %s", _("Number:"), g_udev_device_get_number(device)); println(indent, "%-20s %s", _("Path:"), g_udev_device_get_sysfs_path(device)); println(indent, "%-20s %s", _("Driver:"), g_udev_device_get_driver(device)); println(indent, "%-20s %lld", _("Sequential Number:"), (long long int)g_udev_device_get_seqnum(device)); println(indent, "%-20s %s", _("Device File:"), g_udev_device_get_device_file(device)); println(indent, " "); println(indent, _("Properties:")); /* Get longest property name length for alignment */ list = g_udev_device_get_property_keys(device); for (iter = list; iter && *iter; iter++) { if (strlen(*iter) > namelen) namelen = strlen(*iter); } namelen++; for (iter = list; iter && *iter; iter++) { strcpy(propstr, *iter); strcat(propstr, ":"); for (i = 0; i < namelen - strlen(*iter); i++) strcat(propstr, " "); strcat(propstr, g_udev_device_get_property(device, *iter)); println(indent + 2, "%s", propstr); } println(indent, " "); parent = g_udev_device_get_parent(device); if (parent) { dump_device_and_parent(parent, indent + 4); g_object_unref(parent); } }
static gboolean dev_get_attrs (GUdevDevice *udev_device, const char **out_ifname, const char **out_path, char **out_driver) { GUdevDevice *parent = NULL; const char *ifname, *driver, *path; g_return_val_if_fail (udev_device != NULL, FALSE); g_return_val_if_fail (out_ifname != NULL, FALSE); g_return_val_if_fail (out_path != NULL, FALSE); g_return_val_if_fail (out_driver != NULL, FALSE); ifname = g_udev_device_get_name (udev_device); if (!ifname) { nm_log_dbg (LOGD_HW, "failed to get device's interface"); return FALSE; } path = g_udev_device_get_sysfs_path (udev_device); if (!path) { nm_log_warn (LOGD_HW, "couldn't determine device path; ignoring..."); return FALSE; } driver = g_udev_device_get_driver (udev_device); if (!driver) { /* Try the parent */ parent = g_udev_device_get_parent (udev_device); if (parent) { driver = g_udev_device_get_driver (parent); g_object_unref (parent); } } *out_ifname = ifname; *out_path = path; *out_driver = g_strdup (driver); return TRUE; }
/* Overriding SUBSYSTEM isn't allowed in udev (works sometimes, but not * always). For evemu devices we need to set custom properties to make them * detected by libwacom. */ static char * get_uinput_subsystem (GUdevDevice *device) { const char *bus_str; GUdevDevice *parent; bus_str = NULL; parent = g_object_ref (device); while (parent && !g_udev_device_get_property_as_boolean (parent, "UINPUT_DEVICE")) { GUdevDevice *old_parent = parent; parent = g_udev_device_get_parent (old_parent); g_object_unref (old_parent); } if (parent) { bus_str = g_udev_device_get_property (parent, "UINPUT_SUBSYSTEM"); g_object_unref (parent); } return bus_str ? g_strdup (bus_str) : NULL; }
static GUdevDevice * find_physical_device (GUdevDevice *child) { GUdevDevice *iter, *old = NULL; GUdevDevice *physdev = NULL; const char *subsys, *type, *name; guint32 i = 0; gboolean is_usb = FALSE, is_pci = FALSE, is_pcmcia = FALSE, is_platform = FALSE; gboolean is_pnp = FALSE; g_return_val_if_fail (child != NULL, NULL); /* Bluetooth rfcomm devices are "virtual" and don't necessarily have * parents at all. */ name = g_udev_device_get_name (child); if (name && strncmp (name, "rfcomm", 6) == 0) return g_object_ref (child); iter = g_object_ref (child); while (iter && i++ < 8) { subsys = g_udev_device_get_subsystem (iter); if (subsys) { if (is_usb || g_str_has_prefix (subsys, "usb")) { is_usb = TRUE; type = g_udev_device_get_devtype (iter); if (type && !strcmp (type, "usb_device")) { physdev = iter; break; } } else if (is_pcmcia || !strcmp (subsys, "pcmcia")) { GUdevDevice *pcmcia_parent; const char *tmp_subsys; is_pcmcia = TRUE; /* If the parent of this PCMCIA device is no longer part of * the PCMCIA subsystem, we want to stop since we're looking * for the base PCMCIA device, not the PCMCIA controller which * is usually PCI or some other bus type. */ pcmcia_parent = g_udev_device_get_parent (iter); if (pcmcia_parent) { tmp_subsys = g_udev_device_get_subsystem (pcmcia_parent); if (tmp_subsys && strcmp (tmp_subsys, "pcmcia")) physdev = iter; g_object_unref (pcmcia_parent); if (physdev) break; } } else if (is_platform || !strcmp (subsys, "platform")) { /* Take the first platform parent as the physical device */ is_platform = TRUE; physdev = iter; break; } else if (is_pci || !strcmp (subsys, "pci")) { is_pci = TRUE; physdev = iter; break; } else if (is_pnp || !strcmp (subsys, "pnp")) { is_pnp = TRUE; physdev = iter; break; } } old = iter; iter = g_udev_device_get_parent (old); g_object_unref (old); } return physdev; }
static gboolean get_device_info (const char *path, int *vendor_id, int *product_id, char **name, WacomBusType *bus, WacomIntegrationFlags *integration_flags, WacomError *error) { GUdevClient *client; GUdevDevice *device; const char * const subsystems[] = { "input", NULL }; gboolean retval; char *bus_str; const char *devname; #if NEED_G_TYPE_INIT g_type_init(); #endif retval = FALSE; /* The integration flags from device info are unset by default */ *integration_flags = WACOM_DEVICE_INTEGRATED_UNSET; *name = NULL; bus_str = NULL; client = g_udev_client_new (subsystems); device = g_udev_client_query_by_device_file (client, path); if (device == NULL) { libwacom_error_set(error, WERROR_INVALID_PATH, "Could not find device '%s' in udev", path); goto out; } /* Touchpads are only for the "Finger" part of Bamboo devices */ if (!is_tablet_or_touchpad(device)) { GUdevDevice *parent; parent = g_udev_device_get_parent(device); if (!parent || !is_tablet_or_touchpad(parent)) { libwacom_error_set(error, WERROR_INVALID_PATH, "Device '%s' is not a tablet", path); g_object_unref (parent); goto out; } g_object_unref (parent); } /* Is the device integrated in display? */ devname = g_udev_device_get_name (device); if (devname != NULL) { char *sysfs_path, *contents; sysfs_path = g_build_filename ("/sys/class/input", devname, "device/properties", NULL); if (g_file_get_contents (sysfs_path, &contents, NULL, NULL)) { int flag; flag = atoi(contents); flag &= (1 << INPUT_PROP_DIRECT) | (1 << INPUT_PROP_POINTER); /* * To ensure we are dealing with a screen tablet, need * to check that it has DIRECT and non-POINTER (DIRECT * alone is not sufficient since it's set for drawing * tablets as well) */ if (flag == (1 << INPUT_PROP_DIRECT)) *integration_flags = WACOM_DEVICE_INTEGRATED_DISPLAY; else *integration_flags = WACOM_DEVICE_INTEGRATED_NONE; g_free (contents); } g_free (sysfs_path); } *name = g_strdup (g_udev_device_get_sysfs_attr (device, "name")); /* Try getting the name from the parent if that fails */ if (*name == NULL) { GUdevDevice *parent; parent = g_udev_device_get_parent (device); if (!parent) goto out; *name = g_strdup (g_udev_device_get_sysfs_attr (parent, "name")); g_object_unref (parent); } /* Parse the PRODUCT attribute (for Bluetooth, USB, I2C) */ retval = get_bus_vid_pid (device, bus, vendor_id, product_id, error); if (retval) goto out; bus_str = get_bus (device); *bus = bus_from_str (bus_str); if (*bus == WBUSTYPE_SERIAL) { /* The serial bus uses 0:0 as the vid/pid */ *vendor_id = 0; *product_id = 0; retval = TRUE; } else { libwacom_error_set(error, WERROR_UNKNOWN_MODEL, "Unsupported bus '%s'", bus_str); } out: if (bus_str != NULL) g_free (bus_str); if (retval == FALSE) g_free (*name); if (device != NULL) g_object_unref (device); if (client != NULL) g_object_unref (client); return retval; }
static gboolean get_bus_vid_pid (GUdevDevice *device, WacomBusType *bus, int *vendor_id, int *product_id, WacomError *error) { GUdevDevice *parent; const char *product_str; gchar **splitted_product = NULL; unsigned int bus_id; gboolean retval = FALSE; /* Parse that: * E: PRODUCT=5/56a/81/100 * into: * vendor 0x56a * product 0x81 */ parent = g_object_ref (device); product_str = g_udev_device_get_property (device, "PRODUCT"); while (!product_str && parent) { GUdevDevice *old_parent = parent; parent = g_udev_device_get_parent (old_parent); if (parent) product_str = g_udev_device_get_property (parent, "PRODUCT"); g_object_unref (old_parent); } if (!product_str) /* PRODUCT not found, hoping the old method will work */ goto out; splitted_product = g_strsplit (product_str, "/", 4); if (g_strv_length (splitted_product) != 4) { libwacom_error_set(error, WERROR_UNKNOWN_MODEL, "Unable to parse model identification"); goto out; } bus_id = (int)strtoul (splitted_product[0], NULL, 16); *vendor_id = (int)strtol (splitted_product[1], NULL, 16); *product_id = (int)strtol (splitted_product[2], NULL, 16); switch (bus_id) { case 3: *bus = WBUSTYPE_USB; retval = TRUE; break; case 5: *bus = WBUSTYPE_BLUETOOTH; retval = TRUE; break; case 24: *bus = WBUSTYPE_I2C; retval = TRUE; break; } out: if (splitted_product) g_strfreev (splitted_product); g_object_unref (parent); return retval; }
static void nm_device_update_description (NMDevice *device) { NMDevicePrivate *priv; const char *subsys[3] = { "net", "tty", NULL }; GUdevDevice *udev_device = NULL, *tmpdev; const char *ifname; guint32 count = 0; const char *vendor, *model; g_return_if_fail (NM_IS_DEVICE (device)); priv = NM_DEVICE_GET_PRIVATE (device); if (!priv->client) { priv->client = g_udev_client_new (subsys); if (!priv->client) return; } ifname = nm_device_get_iface (device); if (!ifname) return; if (NM_IS_DEVICE_ETHERNET (device) || NM_IS_DEVICE_WIFI (device)) udev_device = g_udev_client_query_by_subsystem_and_name (priv->client, "net", ifname); else if (NM_IS_GSM_DEVICE (device) || NM_IS_CDMA_DEVICE (device)) udev_device = g_udev_client_query_by_subsystem_and_name (priv->client, "tty", ifname); if (!udev_device) return; g_free (priv->product); priv->product = NULL; g_free (priv->vendor); priv->vendor = NULL; /* Walk up the chain of the device and its parents a few steps to grab * vendor and device ID information off it. */ tmpdev = udev_device; while ((count++ < 3) && tmpdev && (!priv->vendor || !priv->product)) { if (!priv->vendor) priv->vendor = get_decoded_property (tmpdev, "ID_VENDOR_ENC"); if (!priv->product) priv->product = get_decoded_property (tmpdev, "ID_MODEL_ENC"); tmpdev = g_udev_device_get_parent (tmpdev); } /* If we didn't get strings directly from the device, try database strings */ tmpdev = udev_device; count = 0; while ((count++ < 3) && tmpdev && (!priv->vendor || !priv->product)) { if (!priv->vendor) { vendor = g_udev_device_get_property (tmpdev, "ID_VENDOR_FROM_DATABASE"); if (vendor) priv->vendor = g_strdup (vendor); } if (!priv->product) { model = g_udev_device_get_property (tmpdev, "ID_MODEL_FROM_DATABASE"); if (model) priv->product = g_strdup (model); } tmpdev = g_udev_device_get_parent (tmpdev); } _nm_object_queue_notify (NM_OBJECT (device), NM_DEVICE_VENDOR); _nm_object_queue_notify (NM_OBJECT (device), NM_DEVICE_PRODUCT); }
MMQmiPort * mm_base_modem_peek_port_qmi_for_data (MMBaseModem *self, MMPort *data, GError **error) { MMQmiPort *found; GUdevClient *client; GUdevDevice *data_device; GUdevDevice *data_device_parent; GList *l; if (mm_port_get_subsys (data) != MM_PORT_SUBSYS_NET) { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, "Cannot look for QMI port associated to a non-net data port"); return NULL; } /* don't listen for uevents */ client = g_udev_client_new (NULL); /* Get udev device for the data port */ data_device = (g_udev_client_query_by_subsystem_and_name ( client, "net", mm_port_get_device (data))); if (!data_device) { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't find udev device for port 'net/%s'", mm_port_get_device (data)); g_object_unref (client); return NULL; } /* Get parent of the data device */ data_device_parent = g_udev_device_get_parent (data_device); if (!data_device_parent) { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't get udev device parent for port 'net/%s'", mm_port_get_device (data)); g_object_unref (data_device); g_object_unref (client); return NULL; } /* Now walk the list of QMI ports looking for a match */ found = NULL; for (l = self->priv->qmi; l && !found; l = g_list_next (l)) { GUdevDevice *qmi_device; GUdevDevice *qmi_device_parent; /* Get udev device for the QMI port */ qmi_device = (g_udev_client_query_by_subsystem_and_name ( client, "usb", mm_port_get_device (MM_PORT (l->data)))); if (!qmi_device) { qmi_device = (g_udev_client_query_by_subsystem_and_name ( client, "usbmisc", mm_port_get_device (MM_PORT (l->data)))); if (!qmi_device) { mm_warn ("Couldn't get udev device for QMI port '%s'", mm_port_get_device (MM_PORT (l->data))); continue; } } /* Get parent of the QMI device */ qmi_device_parent = g_udev_device_get_parent (qmi_device); g_object_unref (qmi_device); if (!data_device_parent) { mm_warn ("Couldn't get udev device parent for QMI port '%s'", mm_port_get_device (MM_PORT (l->data))); continue; } if (g_str_equal (g_udev_device_get_sysfs_path (data_device_parent), g_udev_device_get_sysfs_path (qmi_device_parent))) found = MM_QMI_PORT (l->data); g_object_unref (qmi_device_parent); } g_object_unref (data_device_parent); g_object_unref (data_device); g_object_unref (client); if (!found) { /* For the case where we have only 1 data port and 1 QMI port and they * don't match with the previous rules (e.g. in some Huawei modems), * just return the found one */ if (g_list_length (self->priv->data) == 1 && g_list_length (self->priv->qmi) == 1 && self->priv->data->data == data) { mm_info ("Assuming QMI port '%s' is associated to net/%s", mm_port_get_device (MM_PORT (self->priv->qmi->data)), mm_port_get_device (data)); found = MM_QMI_PORT (self->priv->qmi->data); } else { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_NOT_FOUND, "Couldn't find associated QMI port for 'net/%s'", mm_port_get_device (data)); return NULL; } } return found; }