在
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,sms
3、电话的基本应用: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等函数的实现见附件
![](http://blog.chinaunix.net/fileicon/zip.gif) |
文件: | 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));
|
|
|