コード例 #1
0
static void
propagate_port_mode_results (GList *probes)
{
    MMDevice *device;
    GList *l;
    gboolean primary_flagged = FALSE;

    g_assert (probes != NULL);
    device = mm_port_probe_peek_device (MM_PORT_PROBE (probes->data));

    /* Now we propagate the tags to the specific port probes */
    for (l = probes; l; l = g_list_next (l)) {
        MMPortSerialAtFlag at_port_flags = MM_PORT_SERIAL_AT_FLAG_NONE;
        gint usbif;

        usbif = g_udev_device_get_property_as_int (mm_port_probe_peek_port (MM_PORT_PROBE (l->data)), "ID_USB_INTERFACE_NUM");

        if (GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (device), TAG_GETPORTMODE_SUPPORTED))) {
            if (usbif + 1 == GPOINTER_TO_INT (g_object_get_data (G_OBJECT (device), TAG_HUAWEI_PCUI_PORT))) {
                at_port_flags = MM_PORT_SERIAL_AT_FLAG_PRIMARY;
                primary_flagged = TRUE;
            } else if (usbif + 1 == GPOINTER_TO_INT (g_object_get_data (G_OBJECT (device), TAG_HUAWEI_MODEM_PORT)))
                at_port_flags = MM_PORT_SERIAL_AT_FLAG_PPP;
            else if (!g_object_get_data (G_OBJECT (device), TAG_HUAWEI_MODEM_PORT) &&
                     usbif + 1 == GPOINTER_TO_INT (g_object_get_data (G_OBJECT (device), TAG_HUAWEI_NDIS_PORT)))
                /* If NDIS reported only instead of MDM, use it */
                at_port_flags = MM_PORT_SERIAL_AT_FLAG_PPP;
        } else if (usbif == 0 &&
                   mm_port_probe_is_at (MM_PORT_PROBE (l->data))) {
            /* If GETPORTMODE is not supported, we assume usbif 0 is the modem port */
            at_port_flags = MM_PORT_SERIAL_AT_FLAG_PPP;

            /* /\* TODO. */
            /*  * For CDMA modems we assume usbif0 is both primary and PPP, since */
            /*  * they don't have problems with talking on secondary ports. */
            /*  *\/ */
            /* if (caps & CAP_CDMA) */
            /*     pflags |= MM_PORT_SERIAL_AT_FLAG_PRIMARY; */
        }

        g_object_set_data (G_OBJECT (l->data), TAG_AT_PORT_FLAGS, GUINT_TO_POINTER (at_port_flags));
    }

    if (primary_flagged)
        return;

    /* For devices exposing a cdc-wdm port, make sure it gets flagged as primary, if there is none
     * already */
    for (l = probes; l; l = g_list_next (l)) {
        MMPortProbe *probe = MM_PORT_PROBE (l->data);

        if (mm_port_probe_is_at (probe) &&
            g_str_has_prefix (mm_port_probe_get_port_subsys (probe), "usb") &&
            g_str_has_prefix (mm_port_probe_get_port_name (probe), "cdc-wdm")) {
            /* Flag as PRIMARY and do nothing else */
            g_object_set_data (G_OBJECT (probe), TAG_AT_PORT_FLAGS, GUINT_TO_POINTER (MM_PORT_SERIAL_AT_FLAG_PRIMARY));
            break;
        }
    }
}
コード例 #2
0
static void
try_next_usbif (MMDevice *device)
{
    FirstInterfaceContext *fi_ctx;
    GList *l;
    gint closest;

    fi_ctx = g_object_get_data (G_OBJECT (device), TAG_FIRST_INTERFACE_CONTEXT);
    g_assert (fi_ctx != NULL);

    /* Look for the next closest one among the list of interfaces in the device,
     * and enable that one as being first */
    closest = G_MAXINT;
    for (l = mm_device_peek_port_probe_list (device); l; l = g_list_next (l)) {
        gint usbif;

        usbif = g_udev_device_get_property_as_int (mm_port_probe_peek_port (MM_PORT_PROBE (l->data)), "ID_USB_INTERFACE_NUM");
        if (usbif == fi_ctx->first_usbif) {
            g_warn_if_reached ();
        } else if (usbif > fi_ctx->first_usbif &&
                   usbif < closest) {
            closest = usbif;
        }
    }

    if (closest == G_MAXINT) {
        /* Retry with interface 0... */
        closest = 0;
    }

    mm_dbg ("(Huawei) Will try initial probing with interface '%d' instead", closest);

    fi_ctx->first_usbif = closest;
}
コード例 #3
0
static void
uevent_cb (GUdevClient * client, const gchar * action, GUdevDevice * device,
    GstV4l2DeviceProvider * self)
{
  GstDeviceProvider *provider = GST_DEVICE_PROVIDER (self);

  /* Not V4L2, ignoring */
  if (g_udev_device_get_property_as_int (device, "ID_V4L_VERSION") != 2)
    return;

  if (!strcmp (action, "add")) {
    GstDevice *gstdev = NULL;

    gstdev = gst_v4l2_device_provider_device_from_udev (self, device);

    if (gstdev)
      gst_device_provider_device_add (provider, gstdev);
  } else if (!strcmp (action, "remove")) {
    GstV4l2Device *gstdev = NULL;
    GList *item;

    GST_OBJECT_LOCK (self);
    for (item = provider->devices; item; item = item->next) {
      gstdev = item->data;

      if (!strcmp (gstdev->syspath, g_udev_device_get_sysfs_path (device))) {
        gst_object_ref (gstdev);
        break;
      }

      gstdev = NULL;
    }
    GST_OBJECT_UNLOCK (provider);

    if (gstdev) {
      gst_device_provider_device_remove (provider, GST_DEVICE (gstdev));
      g_object_unref (gstdev);
    }
  } else {
    GST_WARNING ("Unhandled action %s", action);
  }
}
コード例 #4
0
static void
propagate_port_mode_results (GList *probes)
{
    MMDevice *device;
    GList *l;

    g_assert (probes != NULL);
    device = mm_port_probe_peek_device (MM_PORT_PROBE (probes->data));

    /* Now we propagate the tags to the specific port probes */
    for (l = probes; l; l = g_list_next (l)) {
        MMAtPortFlag at_port_flags = MM_AT_PORT_FLAG_NONE;
        gint usbif;

        usbif = g_udev_device_get_property_as_int (mm_port_probe_peek_port (MM_PORT_PROBE (l->data)), "ID_USB_INTERFACE_NUM");

        if (GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (device), TAG_GETPORTMODE_SUPPORTED))) {
            if (usbif + 1 == GPOINTER_TO_INT (g_object_get_data (G_OBJECT (device), TAG_HUAWEI_PCUI_PORT)))
                at_port_flags = MM_AT_PORT_FLAG_PRIMARY;
            else if (usbif + 1 == GPOINTER_TO_INT (g_object_get_data (G_OBJECT (device), TAG_HUAWEI_MODEM_PORT)))
                at_port_flags = MM_AT_PORT_FLAG_PPP;
            else if (!g_object_get_data (G_OBJECT (device), TAG_HUAWEI_MODEM_PORT) &&
                     usbif + 1 == GPOINTER_TO_INT (g_object_get_data (G_OBJECT (device), TAG_HUAWEI_NDIS_PORT)))
                /* If NDIS reported only instead of MDM, use it */
                at_port_flags = MM_AT_PORT_FLAG_PPP;
        } else if (usbif == 0 &&
                   mm_port_probe_is_at (MM_PORT_PROBE (l->data))) {
            /* If GETPORTMODE is not supported, we assume usbif 0 is the modem port */
            at_port_flags = MM_AT_PORT_FLAG_PPP;

            /* /\* TODO. */
            /*  * For CDMA modems we assume usbif0 is both primary and PPP, since */
            /*  * they don't have problems with talking on secondary ports. */
            /*  *\/ */
            /* if (caps & CAP_CDMA) */
            /*     pflags |= MM_AT_PORT_FLAG_PRIMARY; */
        }

        g_object_set_data (G_OBJECT (l->data), TAG_AT_PORT_FLAGS, GUINT_TO_POINTER (at_port_flags));
    }
}
コード例 #5
0
static void
try_next_usbif (MMDevice *device)
{
    FirstInterfaceContext *fi_ctx;
    GList *l;
    gint closest;

    fi_ctx = g_object_get_data (G_OBJECT (device), TAG_FIRST_INTERFACE_CONTEXT);
    g_assert (fi_ctx != NULL);

    /* Look for the next closest one among the list of interfaces in the device,
     * and enable that one as being first */
    closest = G_MAXINT;
    for (l = mm_device_peek_port_probe_list (device); l; l = g_list_next (l)) {
        MMPortProbe *probe = MM_PORT_PROBE (l->data);

        /* Only expect ttys for next probing attempt */
        if (g_str_equal (mm_port_probe_get_port_subsys (probe), "tty")) {
            gint usbif;

            usbif = g_udev_device_get_property_as_int (mm_port_probe_peek_port (probe), "ID_USB_INTERFACE_NUM");
            if (usbif == fi_ctx->first_usbif) {
                /* This is the one we just probed, which wasn't yet removed, so just skip it */
            } else if (usbif > fi_ctx->first_usbif &&
                       usbif < closest) {
                closest = usbif;
            }
        }
    }

    if (closest == G_MAXINT) {
        /* No more ttys to try! Just return something */
        closest = 0;
        mm_dbg ("(Huawei) No more ports to run initial probing");
    } else {
        mm_dbg ("(Huawei) Will try initial probing with interface '%d' instead", closest);
    }

    fi_ctx->first_usbif = closest;
}
コード例 #6
0
static gpointer
provider_thread (gpointer data)
{
  GstV4l2DeviceProvider *provider = data;
  GMainContext *context = NULL;
  GMainLoop *loop = NULL;
  GUdevClient *client;
  GList *devices;
  static const gchar *subsystems[] = { "video4linux", NULL };

  GST_OBJECT_LOCK (provider);
  if (provider->context)
    context = g_main_context_ref (provider->context);
  if (provider->loop)
    loop = g_main_loop_ref (provider->loop);

  if (context == NULL || loop == NULL) {
    provider->started = TRUE;
    g_cond_broadcast (&provider->started_cond);
    GST_OBJECT_UNLOCK (provider);
    return NULL;
  }
  GST_OBJECT_UNLOCK (provider);

  g_main_context_push_thread_default (context);

  client = g_udev_client_new (subsystems);

  g_signal_connect (client, "uevent", G_CALLBACK (uevent_cb), provider);

  devices = g_udev_client_query_by_subsystem (client, "video4linux");

  while (devices) {
    GUdevDevice *udev_device = devices->data;
    GstDevice *gstdev;

    devices = g_list_remove (devices, udev_device);

    if (g_udev_device_get_property_as_int (udev_device, "ID_V4L_VERSION") == 2) {
      gstdev =
          gst_v4l2_device_provider_device_from_udev (provider, udev_device);
      if (gstdev)
        gst_device_provider_device_add (GST_DEVICE_PROVIDER (provider), gstdev);
    }

    g_object_unref (udev_device);
  }

  GST_OBJECT_LOCK (provider);
  provider->started = TRUE;
  g_cond_broadcast (&provider->started_cond);
  GST_OBJECT_UNLOCK (provider);

  g_main_loop_run (loop);
  g_main_loop_unref (loop);

  g_object_unref (client);
  g_main_context_unref (context);

  gst_object_unref (provider);

  return NULL;
}
コード例 #7
0
static void
huawei_custom_init (MMPortProbe *probe,
                    MMAtSerialPort *port,
                    GCancellable *cancellable,
                    GAsyncReadyCallback callback,
                    gpointer user_data)
{
    MMDevice *device;
    FirstInterfaceContext *fi_ctx;
    HuaweiCustomInitContext *ctx;

    device = mm_port_probe_peek_device (probe);

    /* The primary port (called the "modem" port in the Windows drivers) is
     * always USB interface 0, and we need to detect that interface first for
     * two reasons: (1) to disable unsolicited messages on other ports that
     * may fill up the buffer and crash the device, and (2) to attempt to get
     * the port layout for hints about what the secondary port is (called the
     * "pcui" port in Windows).  Thus we probe USB interface 0 first and defer
     * probing other interfaces until we've got if0, at which point we allow
     * the other ports to be probed too.
     */
    fi_ctx = g_object_get_data (G_OBJECT (device), TAG_FIRST_INTERFACE_CONTEXT);
    if (!fi_ctx) {
        /* This is the first time we ask for the context. Set it up. */
        fi_ctx = g_slice_new0 (FirstInterfaceContext);
        g_object_set_data_full (G_OBJECT (device),
                                TAG_FIRST_INTERFACE_CONTEXT,
                                fi_ctx,
                                (GDestroyNotify)first_interface_context_free);
        /* The timeout is controlled in the data set in 'device', and therefore
         * it should be safe to assume that the timeout will not get fired after
         * having disposed 'device' */
        fi_ctx->timeout_id = g_timeout_add_seconds (MAX_WAIT_TIME,
                                                    (GSourceFunc)first_interface_missing_timeout_cb,
                                                    device);

        /* By default, we'll ask the Huawei plugin to start probing usbif 0 */
        fi_ctx->first_usbif = 0;

        /* Custom init of the Huawei plugin is to be run only in the first
         * interface. We'll control here whether we did run it already or not. */
        fi_ctx->custom_init_run = FALSE;
    }

    ctx = g_slice_new (HuaweiCustomInitContext);
    ctx->result = g_simple_async_result_new (G_OBJECT (probe),
                                             callback,
                                             user_data,
                                             huawei_custom_init);
    ctx->probe = g_object_ref (probe);
    ctx->port = g_object_ref (port);
    ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
    ctx->curc_done = FALSE;
    ctx->curc_retries = 3;
    ctx->getportmode_done = FALSE;
    ctx->getportmode_retries = 3;

    /* Custom init only to be run in the first interface */
    if (g_udev_device_get_property_as_int (mm_port_probe_peek_port (probe),
                                           "ID_USB_INTERFACE_NUM") != fi_ctx->first_usbif) {

        if (fi_ctx->custom_init_run)
            /* If custom init was run already, we can consider this as successfully run */
            g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
        else
            /* Otherwise, we'll need to defer the probing a bit more */
            g_simple_async_result_set_error (ctx->result,
                                             MM_CORE_ERROR,
                                             MM_CORE_ERROR_RETRY,
                                             "Defer needed");

        huawei_custom_init_context_complete_and_free (ctx);
        return;
    }

    /* We can run custom init in the first interface! clear the timeout as it is no longer needed */
    g_source_remove (fi_ctx->timeout_id);
    fi_ctx->timeout_id = 0;

    huawei_custom_init_step (ctx);
}
コード例 #8
0
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 void
empathy_camera_device_monitor_added (EmpathyCameraDeviceMonitor *monitor,
                                    GUdevDevice               *udevice)
{
  const char *device_file;
  const char *product_name;
  const char *vendor;
  const char *product;
  const char *bus;
  gint        vendor_id   = 0;
  gint        product_id  = 0;
  gint        v4l_version = 0;

  const gchar *devpath = g_udev_device_get_property (udevice, "DEVPATH");

  GST_INFO ("Checking udev device '%s'", devpath);

  bus = g_udev_device_get_property (udevice, "ID_BUS");
  if (g_strcmp0 (bus, "usb") == 0)
  {
    vendor = g_udev_device_get_property (udevice, "ID_VENDOR_ID");
    if (vendor != NULL)
      vendor_id = g_ascii_strtoll (vendor, NULL, 16);
    product = g_udev_device_get_property (udevice, "ID_MODEL_ID");
    if (product != NULL)
      product_id = g_ascii_strtoll (product, NULL, 16);
    if (vendor_id == 0 || product_id == 0)
    {
      GST_WARNING ("Error getting vendor and product id");
    }
    else
    {
      GST_INFO ("Found device %04x:%04x, getting capabilities...", vendor_id, product_id);
    }
  }
  else
  {
    GST_INFO ("Not an usb device, skipping vendor and model id retrieval");
  }

  device_file = g_udev_device_get_device_file (udevice);
  if (device_file == NULL)
  {
    GST_WARNING ("Error getting V4L device");
    return;
  }

  /* vbi devices support capture capability too, but cannot be used,
   * so detect them by device name */
  if (strstr (device_file, "vbi"))
  {
    GST_INFO ("Skipping vbi device: %s", device_file);
    return;
  }

  v4l_version = g_udev_device_get_property_as_int (udevice, "ID_V4L_VERSION");
  if (v4l_version == 2 || v4l_version == 1)
  {
    const char *caps;

    caps = g_udev_device_get_property (udevice, "ID_V4L_CAPABILITIES");
    if (caps == NULL || strstr (caps, ":capture:") == NULL)
    {
      GST_WARNING ("Device %s seems to not have the capture capability, (radio tuner?)"
                   "Removing it from device list.", device_file);
      return;
    }
    product_name = g_udev_device_get_property (udevice, "ID_V4L_PRODUCT");
  }
  else if (v4l_version == 0)
  {
    GST_ERROR ("Fix your udev installation to include v4l_id, ignoring %s", device_file);
    return;
  }
  else
  {
    g_assert_not_reached ();
  }

  g_signal_emit (monitor, monitor_signals[ADDED], 0,
                 devpath,
                 device_file,
                 product_name,
                 v4l_version);
}
コード例 #10
0
static MMModem *
grab_port (MMPluginBase *base,
           MMModem *existing,
           MMPluginBaseSupportsTask *task,
           GError **error)
{
    GUdevDevice *port = NULL;
    MMModem *modem = NULL;
    const char *name, *subsys, *devfile, *sysfs_path;
    guint32 caps;
    guint16 vendor = 0, product = 0;
    MMPortType ptype;
    int usbif;
    MMAtPortFlags pflags = MM_AT_PORT_FLAG_NONE;

    port = mm_plugin_base_supports_task_get_port (task);
    g_assert (port);

    devfile = g_udev_device_get_device_file (port);
    if (!devfile) {
        g_set_error (error, 0, 0, "Could not get port's sysfs file.");
        return NULL;
    }

    subsys = g_udev_device_get_subsystem (port);
    name = g_udev_device_get_name (port);

    if (!mm_plugin_base_get_device_ids (base, subsys, name, &vendor, &product)) {
        g_set_error (error, 0, 0, "Could not get modem product ID.");
        return NULL;
    }

    usbif = g_udev_device_get_property_as_int (port, "ID_USB_INTERFACE_NUM");
    if (usbif < 0) {
        g_set_error (error, 0, 0, "Could not get USB device interface number.");
        return NULL;
    }

    caps = mm_plugin_base_supports_task_get_probed_capabilities (task);
    ptype = mm_plugin_base_probed_capabilities_to_port_type (caps);

    if (usbif + 1 == GPOINTER_TO_INT (g_object_get_data (G_OBJECT (base), TAG_HUAWEI_PCUI_PORT)))
        pflags = MM_AT_PORT_FLAG_PRIMARY;
    else if (usbif + 1 == GPOINTER_TO_INT (g_object_get_data (G_OBJECT (base), TAG_HUAWEI_MODEM_PORT)))
        pflags = MM_AT_PORT_FLAG_PPP;
    else if (!g_object_get_data (G_OBJECT (base), TAG_GETPORTMODE_SUPPORTED)) {
        /* If GETPORTMODE is not supported, we assume usbif 0 is the modem port */
        if ((usbif == 0) && (ptype == MM_PORT_TYPE_AT)) {
            pflags = MM_AT_PORT_FLAG_PPP;

            /* For CDMA modems we assume usbif0 is both primary and PPP, since
             * they don't have problems with talking on secondary ports.
             */
            if (caps & CAP_CDMA)
                pflags |= MM_AT_PORT_FLAG_PRIMARY;
        }
    }

    sysfs_path = mm_plugin_base_supports_task_get_physdev_path (task);
    if (!existing) {
        if (caps & MM_PLUGIN_BASE_PORT_CAP_GSM) {
            modem = mm_modem_huawei_gsm_new (sysfs_path,
                                             mm_plugin_base_supports_task_get_driver (task),
                                             mm_plugin_get_name (MM_PLUGIN (base)),
                                             vendor,
                                             product);
        } else if (caps & CAP_CDMA) {
            modem = mm_modem_huawei_cdma_new (sysfs_path,
                                              mm_plugin_base_supports_task_get_driver (task),
                                              mm_plugin_get_name (MM_PLUGIN (base)),
                                              !!(caps & MM_PLUGIN_BASE_PORT_CAP_IS856),
                                              !!(caps & MM_PLUGIN_BASE_PORT_CAP_IS856_A),
                                              vendor,
                                              product);
        }

        if (modem) {
            if (!mm_modem_grab_port (modem, subsys, name, ptype, pflags, NULL, error)) {
                g_object_unref (modem);
                return NULL;
            }
        }
    } else {
        modem = existing;
        if (!mm_modem_grab_port (modem, subsys, name, ptype, pflags, NULL, error))
            return NULL;
    }

    return modem;
}
コード例 #11
0
static MMPluginSupportsResult
supports_port (MMPluginBase *base,
               MMModem *existing,
               MMPluginBaseSupportsTask *task)
{
    GUdevDevice *port;
    const char *subsys, *name, *driver;
    int usbif;
    guint16 vendor = 0, product = 0;

    /* Can't do anything with non-serial ports */
    port = mm_plugin_base_supports_task_get_port (task);
    if (strcmp (g_udev_device_get_subsystem (port), "tty"))
        return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;

    subsys = g_udev_device_get_subsystem (port);
    name = g_udev_device_get_name (port);

    if (!mm_plugin_base_get_device_ids (base, subsys, name, &vendor, &product))
        return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;

    if (vendor != 0x12d1)
        return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;

    /* The Gobi driver should claim Huawei Gobi modems */
    driver = mm_plugin_base_supports_task_get_driver (task);
    if (g_strcmp0 (driver, "qcserial") == 0)
        return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;

    usbif = g_udev_device_get_property_as_int (port, "ID_USB_INTERFACE_NUM");
    if (usbif < 0)
        return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;

    /* The primary port (called the "modem" port in the Windows drivers) is
     * always USB interface 0, and we need to detect that interface first for
     * two reasons: (1) to disable unsolicited messages on other ports that
     * may fill up the buffer and crash the device, and (2) to attempt to get
     * the port layout for hints about what the secondary port is (called the
     * "pcui" port in Windows).  Thus we probe USB interface 0 first and defer
     * probing other interfaces until we've got if0, at which point we allow
     * the other ports to be probed too.
     */
    if (!existing && usbif != 0)
        return MM_PLUGIN_SUPPORTS_PORT_DEFER;

    /* Check if a previous probing was already launched in this port */
    if (mm_plugin_base_supports_task_propagate_cached (task)) {
        guint32 level;

        /* A previous probing was already done, use its results */
        level = get_level_for_capabilities (mm_plugin_base_supports_task_get_probed_capabilities (task));
        if (level) {
            mm_plugin_base_supports_task_complete (task, level);
            return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
        }
        return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
    }

    /* Turn off unsolicited messages on secondary ports until needed,
     * and try to get a port map from the modem.  The response will
     * get handled in custom_init_response().
     */
    if (usbif == 0) {
        mm_plugin_base_supports_task_add_custom_init_command (task,
                                                              "AT^CURC=0",
                                                              3,   /* delay */
                                                              curc_response_cb,
                                                              NULL);

        mm_plugin_base_supports_task_add_custom_init_command (task,
                                                              "AT^GETPORTMODE",
                                                              3,   /* delay */
                                                              getportmode_response_cb,
                                                              NULL);
    }

    /* Kick off a probe */
    if (mm_plugin_base_probe_port (base, task, 100000, NULL))
        return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;

    return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
}