oFono学习笔记——GATChat(1):主要结构体分析

1. 背景

回顾一下当今智能手机的架构。目前,很多智能手机都是采用双处理器架构:一个处理器用来运行操作系统相关的工作,应用程序都是运行在这个上面,所以这个处理器又叫Application Processor(AP),一个处理器用来负责和无线射频通讯相关的工作,即Baseband Processor(BP)。AP与BP之间最常见的是使用串口相连接。AP与BP之间通讯协议就是AT命令。

当下,每一个Mobile OS都有自己的一套机制来解决AP与BP之间的AT通讯问题。Android中使用Rild,而在Tizen IVI中,则是使用Ofono这个开源架构。而oFono中使用GATChat这个库来实现AP与BP之间AT通讯。下面就是对GATChat这个库的一些分析。

2. GAtChat结构体分析

在gatchat.c中定义了GAtChat

 1 /*gatchat.h*/
 2 typedef struct _GAtChat GAtChat;
 3 
 4 /*gatchat.c*/
 5 struct _GAtChat {
 6     gint ref_count;      
 7     struct at_chat *parent;  
 8     guint group;
 9     GAtChat *slave;
10 }; 

2.1 ref_count

因为GAtChat这个库是基于GLib来编写的,因此其中借鉴了GLib的一些思想。当结构体中ref_count减为0时,当前GAtChat将会被删除。每一次引用和解引用都会修改ref_count的值。

 1 GAtChat *g_at_chat_ref(GAtChat *chat)
 2 {
 3     if (chat == NULL)
 4         return NULL;
 5 
 6     g_atomic_int_inc(&chat->ref_count);/*ref_count+1*/
 7 
 8     return chat;
 9 }
10 
11 void g_at_chat_unref(GAtChat *chat)
12 {
13     gboolean is_zero;
14 
15     if (chat == NULL)
16         return;
17         
18     /*ref_count-1, 并判断ref_count是否为0*/
19     is_zero = g_atomic_int_dec_and_test(&chat->ref_count);
20 
21     if (is_zero == FALSE)
22         return;
23     /*当ref_count为0,删除当前chat*/
24     if (chat->slave != NULL)
25         g_at_chat_unref(chat->slave);
26 
27     at_chat_cancel_group(chat->parent, chat->group);
28     g_at_chat_unregister_all(chat);
29     at_chat_unref(chat->parent);
30 
31     g_free(chat);
32 }

 2.2 struct at_chat 

在gatchat.c中定义了at_chat结构体:

 1 struct at_chat {
 2     gint ref_count;                     /* Ref count */
 3     guint next_cmd_id;                  /* Next command id */
 4     guint next_notify_id;              /* Next notify id */
 5     guint next_gid;                      /* Next group id */
 6     GAtIO *io;                        /* AT IO */
 7     GQueue *command_queue;          /* Command queue */
 8     guint cmd_bytes_written;            /* bytes written from cmd */
 9     GHashTable *notify_list;            /* List of notification reg */
10     GAtDisconnectFunc user_disconnect;    /* user disconnect func */
11     gpointer user_disconnect_data;         /* user disconnect data */
12     guint read_so_far;                  /* Number of bytes processed */
13     gboolean suspended;         /* Are we suspended? */
14     GAtDebugFunc debugf;        /* debugging output function */
15     gpointer debug_data;             /* Data to pass to debug func */
16     char *pdu_notify;               /* Unsolicited Resp w/ PDU */
17     GSList *response_lines;          /* char * lines of the response */
18     char *wakeup;                   /* command sent to wakeup modem */
19     gint timeout_source;
20     gdouble inactivity_time;         /* Period of inactivity */
21     guint wakeup_timeout;            /* How long to wait for resp */
22     GTimer *wakeup_timer;            /* Keep track of elapsed time */
23     GAtSyntax *syntax;
24     gboolean destroyed;             /* Re-entrancy guard */
25     gboolean in_read_handler;        /* Re-entrancy guard */
26     gboolean in_notify;
27     GSList *terminator_list;         /* Non-standard terminator */
28     guint16 terminator_blacklist;    /* Blacklisted terinators */
29 };

看到这个结构体第一感觉会比较晕,有些在不同的应用场合下并不会用到,这里挑出一些比较重要的做说明:

1. io,这里决定了AT命令使用怎样的IO方式传送给BP。IO的方式可以是UART,USB,Socket等等。。。

2. commond_quque字段,这说明了所有的AT命令都是放到这个队列中进行缓存再依次发送的。

3. pdu_notify字段, 这个字段根据注释可以猜测是用来存储unsolicited response(非请求结果码)以及PDU信息的。

4. response_lines字段,这是一个GList类型,所以它是用来存储AT命令返回的solicited response(请求结果码信息)。

5. syntax字段, 类型为GATSyntax,这说明这个结构负责和AT命令语法相关的内容,也就是说AT命令的语法语义分析都是在这里进行的。

6. terminator_list字段,这个GList负责存储非标准的结束符,比如标准AT命令都是以OK结尾,而你的模块是以XX结尾,这样你就需要将XX添加到terminator_list中来。

  2.3 group

GAtChat的组标示,可以把一个GAtChat分成若干个组,每一个组负责不同的工作。比如一个组负责和设备信息相关的AT命令的处理,一个组负责和GPRS相关的AT命令的处理。每创建一个分组需要调用g_at_chat_clone函数

 1 GAtChat *g_at_chat_clone(GAtChat *clone)
 2 {
 3     GAtChat *chat;
 4 
 5     if (clone == NULL)
 6         return NULL;
 7 
 8     chat = g_try_new0(GAtChat, 1);
 9     if (chat == NULL)
10         return NULL;
11 
12     chat->parent = clone->parent;
13     chat->group = chat->parent->next_gid++;    /*创建分组*/
14     chat->ref_count = 1;
15     g_atomic_int_inc(&chat->parent->ref_count);
16 
17     if (clone->slave != NULL)
18         chat->slave = g_at_chat_clone(clone->slave);
19 
20     return chat;
21 }

  2.4 GAtChat *slave

字面理解这个一个slave chat。多数情况下,GPRS/GSM/3G模块上只有一个物理UART,为了让设备可以上网和打电话,我们需要在操作系统中虚拟出两个UART,一个UART专门负责AT命令的发送以及接收。另一个UART负责网络数据的透传。在oFono中,一般使用slave chat来做AT命令的收发。

3.总结

以上是我个人对GAtChat的一些理解,并不一定保证正确性。要是各位大大发现其中有错误的话,欢迎指正。接下来的文章将对GAtChat这个库是如何发送以及接收AT命令的全过程进行分析。

 

 

 

posted @ 2013-07-02 11:32  ZHX_1Q89  阅读(2106)  评论(4编辑  收藏  举报