在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));
阅读(2061) | 评论(0) | 转发(0) |