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; } } }
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; }
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); } }
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)); } }
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; }
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; }
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); }
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); }
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; }
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; }