gboolean
mm_plugin_base_get_device_ids (MMPluginBase *self,
                               const char *subsys,
                               const char *name,
                               guint16 *vendor,
                               guint16 *product)
{
    MMPluginBasePrivate *priv;
    GUdevDevice *device = NULL;
    const char *vid, *pid;
    gboolean success = FALSE;

    g_return_val_if_fail (self != NULL, FALSE);
    g_return_val_if_fail (MM_IS_PLUGIN_BASE (self), FALSE);
    g_return_val_if_fail (subsys != NULL, FALSE);
    g_return_val_if_fail (name != NULL, FALSE);
    if (vendor)
        g_return_val_if_fail (*vendor == 0, FALSE);
    if (product)
        g_return_val_if_fail (*product == 0, FALSE);

    priv = MM_PLUGIN_BASE_GET_PRIVATE (self);

    device = g_udev_client_query_by_subsystem_and_name (priv->client, subsys, name);
    if (!device)
        goto out;

    vid = g_udev_device_get_property (device, "ID_VENDOR_ID");
    if (!vid || (strlen (vid) != 4))
        goto out;

    if (vendor) {
        *vendor = (guint16) (hex2byte (vid + 2) & 0xFF);
        *vendor |= (guint16) ((hex2byte (vid) & 0xFF) << 8);
    }

    pid = g_udev_device_get_property (device, "ID_MODEL_ID");
    if (!pid || (strlen (pid) != 4)) {
        *vendor = 0;
        goto out;
    }

    if (product) {
        *product = (guint16) (hex2byte (pid + 2) & 0xFF);
        *product |= (guint16) ((hex2byte (pid) & 0xFF) << 8);
    }

    success = TRUE;

out:
    if (device)
        g_object_unref (device);
    return success;
}
static MMPluginSupportsResult
supports_port (MMPlugin *plugin,
               const char *subsys,
               const char *name,
               const char *physdev_path,
               MMModem *existing,
               MMSupportsPortResultFunc callback,
               gpointer callback_data)
{
    MMPluginBase *self = MM_PLUGIN_BASE (plugin);
    MMPluginBasePrivate *priv = MM_PLUGIN_BASE_GET_PRIVATE (self);
    GUdevDevice *port = NULL;
    char *driver = NULL, *key = NULL;
    MMPluginBaseSupportsTask *task;
    MMPluginSupportsResult result = MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;

    key = get_key (subsys, name);
    task = g_hash_table_lookup (priv->tasks, key);
    if (task) {
        g_free (key);
        g_return_val_if_fail (task == NULL, MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED);
    }

    port = g_udev_client_query_by_subsystem_and_name (priv->client, subsys, name);
    if (!port)
        goto out;

    driver = get_driver_name (port);
    if (!driver)
        goto out;

    task = supports_task_new (self, port, physdev_path, driver, callback, callback_data);
    g_assert (task);
    g_hash_table_insert (priv->tasks, g_strdup (key), g_object_ref (task));

    result = MM_PLUGIN_BASE_GET_CLASS (self)->supports_port (self, existing, task);
    if (result != MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS) {
        /* If the plugin doesn't support the port at all, the supports task is
         * not needed.
         */
        g_hash_table_remove (priv->tasks, key);
    }
    g_object_unref (task);

out:
    if (port)
        g_object_unref (port);
    g_free (key);
    g_free (driver);
    return result;
}
static void
recheck_killswitches (NMRfkillManager *self)
{
	NMRfkillManagerPrivate *priv = NM_RFKILL_MANAGER_GET_PRIVATE (self);
	GSList *iter;
	RfKillState poll_states[RFKILL_TYPE_MAX];
	RfKillState platform_states[RFKILL_TYPE_MAX];
	gboolean platform_checked[RFKILL_TYPE_MAX];
	int i;

	/* Default state is unblocked */
	for (i = 0; i < RFKILL_TYPE_MAX; i++) {
		poll_states[i] = RFKILL_UNBLOCKED;
		platform_states[i] = RFKILL_UNBLOCKED;
		platform_checked[i] = FALSE;
	}

	/* Poll the states of all killswitches */
	for (iter = priv->killswitches; iter; iter = g_slist_next (iter)) {
		Killswitch *ks = iter->data;
		GUdevDevice *device;
		RfKillState dev_state;
		int sysfs_state;

		device = g_udev_client_query_by_subsystem_and_name (priv->client, "rfkill", ks->name);
		if (device) {
			sysfs_state = g_udev_device_get_property_as_int (device, "RFKILL_STATE");
			dev_state = sysfs_state_to_nm_state (sysfs_state);

			nm_log_dbg (LOGD_RFKILL, "%s rfkill%s switch %s state now %d/%u",
			            rfkill_type_to_desc (ks->rtype),
			            ks->platform ? " platform" : "",
			            ks->name,
			            sysfs_state,
			            dev_state);

			if (ks->platform == FALSE) {
				if (dev_state > poll_states[ks->rtype])
					poll_states[ks->rtype] = dev_state;
			} else {
				platform_checked[ks->rtype] = TRUE;
				if (dev_state > platform_states[ks->rtype])
					platform_states[ks->rtype] = dev_state;
			}
			g_object_unref (device);
		}
	}

	/* Log and emit change signal for final rfkill states */
	for (i = 0; i < RFKILL_TYPE_MAX; i++) {
		if (platform_checked[i] == TRUE) {
			/* blocked platform switch state overrides device state, otherwise
			 * let the device state stand. (bgo #655773)
			 */
			if (platform_states[i] != RFKILL_UNBLOCKED)
				poll_states[i] = platform_states[i];
		}

		if (poll_states[i] != priv->rfkill_states[i]) {
			nm_log_dbg (LOGD_RFKILL, "%s rfkill state now '%s'",
			            rfkill_type_to_desc (i),
			            rfkill_state_to_desc (poll_states[i]));

			priv->rfkill_states[i] = poll_states[i];
			g_signal_emit (self, signals[RFKILL_CHANGED], 0, i, priv->rfkill_states[i]);
		}
	}
}
static gboolean
grab_port (MMModem *modem,
           const char *subsys,
           const char *name,
           MMPortType suggested_type,
           gpointer user_data,
           GError **error)
{
    MMGenericGsm *gsm = MM_GENERIC_GSM (modem);
    MMPortType ptype = MM_PORT_TYPE_IGNORED;
    const char *sys[] = { "tty", "net", NULL };
    GUdevClient *client;
    GUdevDevice *device = NULL;
    MMPort *port = NULL;
    const char *sysfs_path;

    client = g_udev_client_new (sys);
    if (!client) {
        g_set_error (error, 0, 0, "Could not get udev client.");
        return FALSE;
    }

    device = g_udev_client_query_by_subsystem_and_name (client, subsys, name);
    if (!device) {
        g_set_error (error, 0, 0, "Could not get udev device.");
        goto out;
    }

    sysfs_path = g_udev_device_get_sysfs_path (device);
    if (!sysfs_path) {
        g_set_error (error, 0, 0, "Could not get udev device sysfs path.");
        goto out;
    }

    if (!strcmp (subsys, "tty")) {
        char *hsotype_path;
        char *contents = NULL;

        hsotype_path = g_build_filename (sysfs_path, "hsotype", NULL);
        if (g_file_get_contents (hsotype_path, &contents, NULL, NULL)) {
            if (g_str_has_prefix (contents, "Control"))
                ptype = MM_PORT_TYPE_PRIMARY;
            else if (g_str_has_prefix (contents, "Application") || g_str_has_prefix (contents, "Application2"))
                ptype = MM_PORT_TYPE_SECONDARY;
            g_free (contents);
        }
        g_free (hsotype_path);
    }

    port = mm_generic_gsm_grab_port (gsm, subsys, name, ptype, error);
    if (!port)
        goto out;

    if (MM_IS_AT_SERIAL_PORT (port)) {
        g_object_set (G_OBJECT (port), MM_SERIAL_PORT_SEND_DELAY, (guint64) 10000, NULL);
        if (ptype == MM_PORT_TYPE_PRIMARY) {
            GRegex *regex;

            regex = g_regex_new ("_OWANCALL: (\\d),\\s*(\\d)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
            mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, connection_enabled, modem, NULL);
            g_regex_unref (regex);

            regex = g_regex_new ("\\r\\n\\+PACSP0\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
            mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, NULL, NULL, NULL);
            g_regex_unref (regex);
        }
        option_register_unsolicted_handlers (gsm, MM_AT_SERIAL_PORT (port));
    }

out:
    if (device)
        g_object_unref (device);
    g_object_unref (client);
    return !!port;
}
Beispiel #5
0
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;
}
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);
}