Chinaunix首页 | 论坛 | 博客
  • 博客访问: 663196
  • 博文数量: 78
  • 博客积分: 4990
  • 博客等级: 上校
  • 技术积分: 1386
  • 用 户 组: 普通用户
  • 注册时间: 2007-07-13 19:25
文章分类

全部博文(78)

文章存档

2010年(6)

2009年(25)

2008年(47)

我的朋友

分类: C/C++

2009-01-15 11:08:42

gpephone之dbus分析(1)
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等函数的实现见附件
文件: 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));    

阅读(914) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~