如何为蜂窝调制解调器建立GIOStream与GDBusConnection连接
问题:使用libmm-glib建立与蜂窝调制解调器的GDBusConnection
我在Ubuntu 20.04系统上,尝试用libmm-glib编写程序收集Telit LE910C4-NF调制解调器的信息,但卡在了建立GIOStream并创建GDBusConnection这一步。命令行查看设备时发现/dev/ttyUSB0、/dev/ttyUSB4被标记为"ignored",尝试用/dev/cdc-wdm0初始化GFile也失败了。
我的预期操作步骤:
- 获取与调制解调器关联的GFile(不确定该用哪个设备路径)
- 用GFile构建GIOStream
- 用GIOStream构建GDBusConnection
- 用GDBusConnection构建MMManager
- 通过MMManager查询调制解调器信息
编译命令
gcc main.c -I/usr/include/libmm-glib -I/usr/include/ModemManager -I/usr/include/glib-2.0 -I/usr/lib/aarch64-linux-gnu/glib-2.0/include -lglib-2.0 -lz -lgio-2.0 -lpthread -lmm-glib
原代码
#include <libmm-glib.h> #include <gio/gio.h> //#include <gtk/gtk.h> #include <stdio.h> int main (void) { printf("begin 1\n"); GCancellable *cancellable; GError **ppError; MMManager *pManager; GDBusAuthObserver *observer; GDBusObjectManagerClientFlags flags = G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE; const gchar *guid = NULL; //g_type_init(); //GFile * save = g_file_new_for_path("/org/freedesktop/ModemManager1/Modem/3"); //GFile * save = g_file_new_for_path("/sys/devices/platform/soc@0/32c00000.bus/32e50000.usb/ci_hdrc.1/usb1/1-1/1-1.3"); GFile * save = g_file_new_for_path("/dev/ttyUSB0"); if(save == NULL) { printf("null GFile\n"); } else { printf("GFile OK\n"); } GFileIOStream *pStream = g_file_open_readwrite(save, NULL, NULL); if(pStream == NULL) { printf("null pStream\n"); } else { printf("pStream OK\n"); } GDBusConnection *pConnection= g_dbus_connection_new_sync(pStream, guid, // for authent. as a server flags, NULL, // observer, NULL, // cancellable, ppError); if(pConnection == NULL) { printf("null GDBusConnection\n"); } pManager = mm_manager_new_sync(pConnection, flags, cancellable, ppError); if(pManager == NULL) { printf("null pManager\n"); } mm_manager_scan_devices_sync(pManager, cancellable, ppError); MMObject modem; printf("d\n"); //const gchar* pChar = mm_object_get_path(&modem); //free resources here printf("end\n"); return(0); }
设备信息
----------------------------- General | path: /org/freedesktop/ModemManager1/Modem/3 | device id: ----------------------------- Hardware | manufacturer: Telit | model: LE910C4-NF | firmware revision: 25.21.660 1 [Mar 04 2021 12:00:00] | carrier config: default | h/w revision: 1.30 | supported: gsm-umts, lte | current: gsm-umts, lte | equipment id: ----------------------------- System | device: /sys/devices/platform/soc@0/32c00000.bus/32e50000.usb/ci_hdrc.1/usb1/1-1/1-1.3 | drivers: qmi_wwan, option | plugin: telit | primary port: cdc-wdm0 | ports: cdc-wdm0 (qmi), ttyUSB0 (ignored), ttyUSB1 (gps), | ttyUSB4 (ignored), wwan0 (net) ----------------------------- Status | state: failed | failed reason: sim-missing | power state: on | signal quality: 0% (cached) ----------------------------- Modes | supported: allowed: 3g; preferred: none | allowed: 4g; preferred: none | allowed: 3g, 4g; preferred: 4g | allowed: 3g, 4g; preferred: 3g | current: allowed: any; preferred: none ----------------------------- Bands | supported: utran-4, utran-5, utran-2, eutran-2, eutran-4, eutran-5, | eutran-12, eutran-13, eutran-14, eutran-66, eutran-71 ----------------------------- IP | supported: ipv4, ipv6, ipv4v6 ----------------------------- SIM | sim slot paths: slot 1: none (active) | slot 2: none
解决方案
核心问题分析
你走了弯路:libmm-glib的正常用法是通过系统D-Bus总线连接到ModemManager服务,而不是直接打开设备文件构建GDBusConnection。直接操作tty或cdc-wdm设备是底层方式,libmm-glib已经封装了这些细节,不需要手动处理。
正确实现步骤
- 连接到系统D-Bus(ModemManager服务运行在系统总线上)
- 通过D-Bus连接获取MMManager实例
- 从MMManager中枚举调制解调器对象
- 查询指定调制解调器的信息
修正后的代码
#include <libmm-glib.h> #include <gio/gio.h> #include <stdio.h> int main(void) { printf("begin\n"); GError *error = NULL; MMManager *manager; GList *modems, *l; // 初始化GLib类型系统(GLib 2.36+可省略,但显式调用更安全) g_type_init(); // 连接到系统D-Bus并获取MMManager实例 manager = mm_manager_new_sync(NULL, NULL, &error); if (!manager) { g_printerr("Failed to create MMManager: %s\n", error->message); g_error_free(error); return 1; } // 扫描并获取所有调制解调器 modems = mm_manager_get_modems(manager); if (!modems) { printf("No modems found\n"); g_object_unref(manager); return 0; } // 遍历调制解调器并打印信息 for (l = modems; l != NULL; l = l->next) { MMObject *obj = MM_OBJECT(l->data); MMModem *modem = mm_object_get_modem(obj); const gchar *path = g_dbus_object_get_path(G_DBUS_OBJECT(obj)); const gchar *model = mm_modem_get_model(modem); const gchar *manufacturer = mm_modem_get_manufacturer(modem); MMModemState state = mm_modem_get_state(modem); printf("Modem Path: %s\n", path); printf("Manufacturer: %s\n", manufacturer); printf("Model: %s\n", model); printf("State: %s\n", mm_modem_state_get_string(state)); printf("-------------------------\n"); g_object_unref(modem); } // 释放资源 g_list_free_full(modems, g_object_unref); g_object_unref(manager); printf("end\n"); return 0; }
关键说明
- 为什么不需要直接操作设备文件:ModemManager服务已经负责与硬件设备的通信,libmm-glib作为客户端只需要通过D-Bus与ModemManager交互即可。
- 关于"ignored"端口:这些端口是ModemManager识别后不需要用于控制的端口(比如某些调试端口),正常控制用的是primary port(这里是cdc-wdm0),但同样不需要你直接操作。
- 权限问题:运行程序需要足够权限,要么用sudo,要么将用户添加到
dialout或plugdev组:sudo usermod -aG dialout $USER sudo usermod -aG plugdev $USER
编译命令保持不变
gcc main.c -I/usr/include/libmm-glib -I/usr/include/ModemManager -I/usr/include/glib-2.0 -I/usr/lib/aarch64-linux-gnu/glib-2.0/include -lglib-2.0 -lz -lgio-2.0 -lpthread -lmm-glib
内容的提问来源于stack exchange,提问作者sasukenebe
相关产品推荐
相关产品推荐

