在D-Bus中,“bus”是核心的概念,它是一个通道:不同的程序可以通过这个通道做些操作,比如方法调用、发送信号和监听特定的信号。主要有两种不同的通道:session bus(会话通道),system bus(系统通道): /** * Well-known bus types. See dbus_bus_get(). */ typedef enum { DBUS_BUS_SESSION, /**< The login session bus */ DBUS_BUS_SYSTEM, /**< The systemwide bus */ DBUS_BUS_STARTER /**< The bus that started us, if any */ } DBusBusType;
- 会话通道处理连接到同一桌面任务的不同程序之间的通信,即被同一个用户启动和运行
- 系统通道是为了处于不同会话环境中的不同程序之间提供通信。这种通道的最常用的方面就是发送系统消息,比如:插入一个新的存储设备;有新的网络连接;等等.
通常情况下,只会存在一个系统通道,但是可以有不同的会话通道(每人一个桌面会话)。在Internet Tablet产品中,所有的应用程序都是使用一个用户ID运行的,所以只有一个会话通道,这一点是和Linux桌面系统是有明显区别的,请留意。
在系统中通道的存在形式是什么呢?是以bus daemon的形式出现的,bus daemon是一个特殊的进程:这个进程可以从一个进程传递消息给另外一个进程。当然了,如果有很多applications链接到这个通道上,这个daemon进程就会把消息转发给这些链接的所有程序。在最底层,D-Bus只支持点对点的通信,一般使用本地套接字(AF_UNIX)在应用和bus daemon之间通信。D-Bus的点对点是经过bus daemon抽象过的,由bus daemon来完成寻址和发送消息,因此每个应用不必要关心要把消息发给哪个进程。(注:这个寻址定位是通过service 名字实现的)。 gpephone主要有几个大模块: 1、gpe-applaucher (主要是管理各进程,如一个模块通过gpe-applaucher启动另一个模块,主要是通过iac,注:iac只不过是对dbus进行封装), 2、phoneserver(一、监听电话,短信,电话本这3个模块的dbus请求,根据请求构造AT并通过串口发送到modem,二、监听modem返回给串口的数据或者监听未知事件(如来电,来短信)的数据到来,并通过dbus发给电话的基本应用:voicecall,sms3、电话的基本应用:voicecall,sms,phonebook,其他的应用如通话记录,日程
dbus的基本要素: 总线类型(对于应用,一般是DBUS_BUS_SESSION,我们不必关心) 服务器名(一般是本进程的标号,bus消息发送的目地通过它来区分) path(也称object) interface(接口) method(方法) 对于同一个path可以,可以有多个interface,同一个interface可以有多个method,一般只有服务器名,path,interface,method都相同时,才认为是同一个请求
前面说到,要有一个bus daemon,我们秩序在后台启动它就行了,至于它具体的工作原理,我们不必理会了。 Xfbdev -dpi 75 -br -pn -rgba rgb :0 -noreset -mouse /dev/null,2& //启动tinyX $V_ROOT/bin/dbus-daemon --config-file=$V_ROOT/etc/dbus-1/session.conf --print-address > $TMP_FILE &
1、voicecall模块:
#define PHONE_VOICE_SERVICE "lips.voice.service" #define PHONE_VOICE_OBJECT "/phone/voice/service" #define PHONE_VOICE_INTERFACE "phone.voice.service"
#define VOC_APP_METHOD_CALLING_INVOKE "invoke_calling" #define VOC_APP_METHOD_NUM_RETURN "num_return" int main (int argc, char *argv[]) { .........................
context = iac_initialize (); //主要是通过dbus_bus_get(DBUS_BUS_SESSION, &error);创建一个dbus的DBUS_BUS_SESSION总线类型连接 if (context == NULL) { g_print ("%s(): iac_context initialization failure\n", __FUNCTION__);
return EXIT_FAILURE; } if (iac_register_service (context, PHONE_VOICE_SERVICE) == IAC_ERROR)//主要是dbus_bus_request_name(context->conn, service, 0, &error);注册dbus的服务器名,PHONE_VOICE_SERVICE是voicecall进程的标志 { g_print ("%s(): cannot register service\n", __FUNCTION__);
return EXIT_FAILURE; } ................................................ ............................................. if (iac_register_listener (context, PHONE_VOICE_OBJECT, PHONE_VOICE_INTERFACE, cb_ui_action, NULL) != IAC_OK)//创建服务器是PHONE_VOICE_SERVICE,路径是PHONE_VOICE_OBJECT,接口是PHONE_VOICE_INTERFACE 的监听,有这种DBUS请求时会立即执行函数cb_ui_action
...................... }//end main() 在voicecall进程中,在进行打电话操作时主要做了如下 session_bus = dbus_init ();//dbus_init ,dbus_message_new_method_call等函数的实现见附件
|
文件: |
dbus-if.tar.gz |
大小: |
3KB |
下载: |
下载 | | if (!session_bus) { g_warning ("Failed to connect to the D-BUS daemon: %s", error.message); dbus_error_free (&error); return VOC_ERR_CARRIER; }
DBusConnection *bus; bus = session_bus ;DBusMessage *message; DBusError error;
dbus_error_init (&error);
message = dbus_message_new_method_call (PHONE_SERVER_SERVICE, PHONE_SERVER_VOICE_OBJECT, PHONE_SERVER_VOICE_INTERFACE, "dial"); 注: #define PHONE_SERVER_SERVICE " lips.phone.server" //phoneserver模块的标志,表明该dbus请求发给phoneserver模块#define PHONE_SERVER_VOICE_OBJECT " /phone/server/voice" #define PHONE_SERVER_VOICE_INTERFACE "phone.server.voice"
if (message == NULL) { printf ("Failed to contruct message\n"); dbus_error_free (&error); return VOC_ERR_CARRIER; }
/* Append the event to the signal when method=dial, the lid not cid is added in other ocasions, cid is added */ dbus_message_append_args (message, DBUS_TYPE_UINT32, &evt, DBUS_TYPE_UINT32, &sid, DBUS_TYPE_UINT32, &lid, DBUS_TYPE_STRING, &remote, //DBUS_TYPE_STRING, &pmethod, DBUS_TYPE_INVALID);
DBusMessage *reply = NULL;
dbus_error_init (&error); reply = dbus_connection_send_with_reply_and_block (bus, message, 2000, &error); if (dbus_error_is_set (&error)) { g_print ("Could not get create a new call!error: %s\n", error.message); dbus_error_free (&error);
return VOC_ERR_CARRIER; } if (dbus_message_get_args (reply, &error, DBUS_TYPE_UINT32, cid_create, DBUS_TYPE_INVALID)) { g_print ("successfully getting cid = %d!\n", *cid_create); } else { g_print ("error getting cid with error: %s\n", error.message); dbus_error_free (&error); dbus_message_unref (message); dbus_message_unref (reply); return VOC_ERR_CARRIER; } dbus_message_unref (message); dbus_message_unref (reply);
同时在初始化的地方还注册了2个来监听(主要是监听phoneserver的发过来的 dbus) dbus_add_msg_listener_mc (PHONE_VOICE_INTERFACE, PHONE_VOICE_DELIVER_EVENT, cb_psevt); dbus_add_msg_listener_mc (PHONE_VOICE_INTERFACE, PHONE_VOICE_DELIVER_UNSEVENT, cb_unspsevt);
注: static gboolean cb_ui_action (const gchar *interface, const gchar *method, iac_arguments_t *arguments, iac_arguments_t *replay, gpointer user_data) {
g_print ("\n\naaaaaaaaaaaaa_bbbbbbbbbbbbb_cccccccccccc_dddddddd\n\n");
if (!strcmp (method, VOC_APP_METHOD_CALLING_INVOKE)) return cb_calling (arguments, user_data); else if (!strcmp (method, VOC_APP_METHOD_NUM_RETURN)) return cb_num_return (arguments, user_data); else return IAC_ERROR; }
注:同时还注册了发送AT请求成功(服务器端phoneserver成功到请求后认为是成功,构造AT和往modem发at都是由服务器来完成)后的回调函数voc_cb_dial,见如下: if (voc_dial (appsid, 1, &cid, g_strdup (rnum))) //jd { printf ("DIAL error!\n"); create_msgdialog ("Can't create a new call!", MSG_NORMAL_TIMEOUT); return; } else { printf ("in %s, appsid=%d,cid=%d\n", __FUNCTION__, appsid, cid); g_print ("voc_cb_dial:0x%08x", (guint32) voc_cb_dial); voc_call_evt_register (appsid, cid, VOC_EVT_CALL_STATUS, NULL, voc_cb_dial, g_strdup (rnum));
| | | |