Android——4.2 - 3G移植之路之 AT 通信 (四)

在前文Android——4.2 - 3G移植之路之 reference-ril .pppd 拨号上网 (三)中分析了3G连接网络的流程,其中有说道通过AT指令建立连接,

在这里记录一下3G中的AT通信.

撰写不易,转载请注明出处:http://blog.csdn.net/jscese/article/details/41083363

概念:

来自AT命令手册中的概念如下:

TE

Terminal Equipment

终端设备 与DTE 等价 比如一个计算机

它是和信息网络的一端相接的可提供必要功能的设备 这些功能使得用户通过接入协议

能接入网络 如发送信息和接收信息 也可指由线路 电路 信道 数据链路的终端或起点组成的设备

TA

Terminal Adapter

终端适配器 与DCE 等价

提供终端适配功能的物理实体 是一种接口设备

DCE

Data Circuit terminating Equipment

数据电路终接设备

一种接口设备 在线路之间进行代码或信号转换 同数据终端设备实现接口 能够建立

保持和释放数据终端设备与数据传输线之间的连接

DTE

Data Terminal Equipment

数据终端设备

它具有向计算机输入和接收计算机输出的能力 与数据通信线路连接的通信控制能力以

及一定的数据处理能力

ME

Mobile Equipment

移动设备 比如GSM 话机就属于ME

移动台中的一种发射机或接收机或发射机与接收机二者的组合

MS

Mobile Station

移动台

在移动通信业务中 可以在移动中使用的通信站 包括车 船 载台便携台和手持机

AT

即Attention

AT 命令集是从TEDTETADCE  发送的 通过TA ,TE 发送AT 命令来控制MS  的功能 与GSM 网络业务进行交互

用户可以通过AT 命令进行呼叫 短信 电话本 数据业务 补充业务 传真等方面的控制

这里只是应用到android设备(TE)与3G模块(TA)之间的通信

不同芯片的3G模块所支持的AT 指令集会有差异,具体需要查看对应规格书.

角色:

在前文 Android——RIL 机制源码分析 中知道:

android电话系统的ril驱动文件目录是在源码/hardware/ril下,其中包含:

rild— ril主体控制机制,

libril— ril与上层socket通信,

reference-ril— ril与serial设备AT指令通信

这三个文件夹,其中reference-ril是第三方驱动,根据不同的设备选择不同.

也就是说 AT 指令就是我们android 设备与 需要移植的第三方的3G设备之间的 最终通信的桥梁

具体实现存在与reference-ril文件中的atchannel.c 中,最终编译成第三方的动态库。

实现:

前文中知道当3G设备通过usb-modeswitch之后出现的/dev/ttyUSB*时,reference-ril.c中的mainLoop 就会检测到,然后跳出loop:

static void *mainLoop(void *param)
{
    int fd;
    int ret;

...

 else if (s_device_path != NULL) {
                fd = open (s_device_path, O_RDWR);
                if ( fd >= 0 && !memcmp( s_device_path, "/dev/tty", 8 ) ) {   //可以看到这里的筛选
                    /* disable echo on serial ports */
                    struct termios  ios;
                    tcgetattr( fd, &ios );
                    ios.c_lflag = 0;  /* disable ECHO, ICANON, etc... */
                   if( cfsetispeed( &ios, B115200) != 0 )
                       ALOGE("Failed to set in speed");
                   if ( cfsetospeed( &ios, B115200) != 0 )
                       ALOGE("Failed to set out speed");
                    tcsetattr( fd, TCSANOW, &ios );
   ALOGI("[%s] jscese _display in reference listener device insert  path== %s \n",__func__,s_device_path);

                }
            }

            if (fd < 0) {
                perror ("opening AT interface. retrying...");
                sleep(10);
                /* never returns */
            }
        }

        s_closed = 0;
        ret = at_open(fd, onUnsolicited); // 这里初始化,传了上面的设备的文件描述符fd,打开 AT 返回值的读取

        if (ret < 0) {
            ALOGE ("AT error %d on at_open\n", ret);
            return 0;
        }

        RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0); //这里会调用到initializeCallback 函数进行初始化AT指令的发送

        // Give initializeCallback a chance to dispatched, since
        // we don't presently have a cancellation mechanism
        sleep(1);
        waitForClose();
        ALOGI("Re-opening after close");
    }
}

前文at_open 干了啥都有分析,这里就不提了,解析下initializeCallback函数:

/**
 * Initialize everything that can be configured while we're still in
 * AT+CFUN=0
 */
static void initializeCallback(void *param)
{
    ATResponse *p_response = NULL;
    int err;

    setRadioState (RADIO_STATE_OFF);

    at_handshake();

    /* note: we don't check errors here. Everything important will
       be handled in onATTimeout and onATReaderClosed */

    /*  atchannel is tolerant of echo but it must */
    /*  have verbose result codes */
    at_send_command("ATE0Q0V1", NULL); //决定是否回显字符 ATE0就是不回显,ATE1反之

    /*  No auto-answer */
    at_send_command("ATS0=0", NULL);   //自动应答,很明显这里不自动

    /*  Extended errors */
    at_send_command("AT+CMEE=1", NULL); //报告移动设备的错误。这个命令决定允许或不允许用结果码 “+CME ERROR:<xxx>”或者 “+CMS  ERROR:<xxx>”代替简单的“ERROR”。

    /*  Network registration events */
    err = at_send_command("AT+CREG=2", &p_response);  //网络注册。获得手机的注册状态

    ALOGI("[%s] jscese AT  Network registration events err== %d \n",__func__,err);

    /* some handsets -- in tethered mode -- don't support CREG=2 */
    if (err < 0 || p_response->success == 0) {
        at_send_command("AT+CREG=1", NULL);
    }

    at_response_free(p_response);

    /*  GPRS registration events */
    at_send_command("AT+CGREG=1", NULL); //初始化GPRS模块

    /*  Call Waiting notifications */
    at_send_command("AT+CCWA=1", NULL); //呼叫等待

    /*  Alternating voice/data off */
    at_send_command("AT+CMOD=0", NULL); // 配置交替模式呼叫 single mode
...

#endif /* USE_TI_COMMANDS */

    /* assume radio is off on error */
    if (isRadioOn() > 0) {
        setRadioState (RADIO_STATE_SIM_NOT_READY);
    }
    ALOGI("[%s] jscese ============= AT  INIT OVER =============\n",__func__);
}

可以看到AT指令的组成 大部分使用 AT+*** 组成,具体支持那些AT指令,需要看对应芯片的AT手册,那样才是最权威可靠的因为不同厂家的会有出入,而且还有一些自定义AT指令!

atchannel.c中实现at_send_command ,最终调用到的地方:

**
 * Internal send_command implementation
 * Doesn't lock or call the timeout callback
 *
 * timeoutMsec == 0 means infinite timeout
 */

static int at_send_command_full_nolock (const char *command, ATCommandType type,
                    const char *responsePrefix, const char *smspdu,
                    long long timeoutMsec, ATResponse **pp_outResponse)
{
    int err = 0;

...

    err = writeline (command); //写命令,上面有提到,往初始化AT时传进来的fd,我这里也就是dev/ttyUSB2

...

    sp_response = at_response_new();  //置空 全局的response,这个指针由processLine(line)函数引导去维护,processLine用来处理at_open 时开启的readerLoop 中读取到的response

...

    while (sp_response->finalResponse == NULL && s_readerClosed == 0) { //等待一下 response
        if (timeoutMsec != 0) {
#ifdef USE_NP
            err = pthread_cond_timeout_np(&s_commandcond, &s_commandmutex, timeoutMsec);
#else
            err = pthread_cond_timedwait(&s_commandcond, &s_commandmutex, &ts);
#endif /*USE_NP*/
        } else {
            err = pthread_cond_wait(&s_commandcond, &s_commandmutex);
        }

        if (err == ETIMEDOUT) {
            err = AT_ERROR_TIMEOUT;
            goto error;
        }
    }

    if (pp_outResponse == NULL) {
        at_response_free(sp_response);
    } else {
        /* line reader stores intermediate responses in reverse order */
        reverseIntermediates(sp_response);
        *pp_outResponse = sp_response;
    }

    sp_response = NULL;  // 重置

...

 }

}

再往下最终就可以看到 write 以及 read 代表设备文件/dev/ttyUSB* 的fd了.

shell调试:

可使用 cat /dev/ttyUSB*  &

查询这个设备文件的值

echo “AT+**”  > /dev/ttyUSB*   写入指令

时间: 2024-10-29 04:39:04

Android——4.2 - 3G移植之路之 AT 通信 (四)的相关文章

Android——4.2 - 3G移植之路之 APN (五)

APN,这东西对于刚接触的人来说并非那么好理解.对于3G移植上网不可缺少,这里记录一下. 撰写不易,转载请注明出处:http://blog.csdn.net/jscese/article/details/41248939 概念: APN(Access Point Name),也就是 接入点 ,移动设备使用数据流量上网必须配置的一个參数,代表以何种方式来连接服务台开启数据流量功能. 一般有訪问WAP或者connect 因特网,国内的运营商2G,3G标识例如以下: 移动公司:2G:GSM.3G:TD

Android——4.2 - 3G移植之路之usb-modeswitch (二)

在前文Android--4.2 - 3G移植之路之libusb (一)  中有解析到libusb 这个动态库的移植,目的就是为了 usb-modeswitch 服务. usb-modeswitch的作用就是转换usb型的设备状态,也是3G 移植中重要的准备工作! 撰写不易,转载请注明出处:http://blog.csdn.net/jscese/article/details/39271443 一.Kernel配置: usb-modeswitch需要kernel中的驱动支持,需要配置serial驱

Android——4.2 - 3G移植之路之libusb (一)

前段时间往smart TV上移植3G模块,发现移植3G的百度谷歌一搜,基本全是linux开发板上的, 我在这里记录一下 我移植 的全过程,让他人少走弯路,有什么建议或者不对的欢迎留言- 撰写不易,转载请注明出处:http://blog.csdn.net/jscese/article/details/39057033 一.设备识别 目前的3G模块都是usb接口的,插在android系统中都会默认识别为usb storage 设备,会尝试通过Vold 挂载为usb 存储设备! 所以必须要把设备类型转

Android——4.2 - 3G移植之路之 reference-ril .pppd 拨号上网 (三)

Android的RIL机制中的 reference-ril.c 即为厂商提供的驱动接口.这个驱动源代码各个厂商都是有提供的,网上也有下载.我如今用的就是huawei wcdma的.最后编译成libreference-ril.so.关于这个接口驱动在RIL中所扮演的角色可參考Android--RIL 机制源代码分析 android 4.2自带pppd源代码在/external/ppp/pppd中.相同,kernel中也是须要打开对point-to-point 的支持,在network suppor

将 Android* Bullet 物理引擎移植至英特尔&#174; 架构

简介 由于目前的移动设备上能够使用更高的计算性能,移动游戏现在也可以提供震撼的画面和真实物理(realistic physics). 枪战游戏中的手雷爆炸效果和赛车模拟器中的汽车漂移效果等便是由物理引擎所提供,其核心是物理模拟. 一般而言,物理模拟决定了游戏引擎的性能. 一款游戏成功与否通常取决于物理引擎计算物理模型的速度和准确度. 本文将介绍如何构建 Android 版 Bullet 物理引擎并将其移至到基于英特尔? 凌动 SoC 的平台. Bullet 物理 Bullet 物理库是一个实时物

Android Vector曲折的兼容之路

Android Vector曲折的兼容之路 两年前写书的时候,就在研究Android L提出的Vector,可研究下来发现,完全不具备兼容性,相信这也是它没有被广泛使用的一个原因,经过Google的不懈努力,现在Vector终于迎来了它的春天. 在文章后面,会给出本文的Demo和效果图,并开源在Github Vector Drawable Android 5.0发布的时候,Google提供了Vector的支持.Vector Drawable相对于普通的Drawable来说,有以下几个好处: Ve

Android安卓书籍推荐《Android驱动开发与移植实战详解》下载

百度云下载地址:点我 Android凭借其开源性.优异的用户体验和极为方便的开发方式,赢得了广大用户和开发者的青睐,目前已经发展成为市场占有率很高的智能手机操作系统. <Android驱动开发与移植实战详解>分为18章,依次讲解了Android系统的基本知识, Linux内核的基本知识,分析了Android系统的源码,深入分析HAL层的基本知识,GoldFish下的驱动.MSM内核和驱动.OMAP内核和驱动.显示系统驱动.输入系统驱动.振动器系统驱动.音频系统驱动和视频输出系统驱动,多媒体框架

Android深度探索(卷1)HAL与驱动开发 第四章 源代码的下载和编译 读书笔记

Android深度探索(卷1)HAL与驱动开发 第四章 源代码的下载和编译 读书笔记     本章学习了使用git下载两套源代码并搭建两个开发环境.分别为Android源代码和Linux内核源代码.Android源代码中包含了HAL(即硬件抽象层) 的代码,并学习了如何搭建这两种开发环境. Android 的移植的本质就是Linux内核的移植,Linux内核的移植主要是Linux驱动的移植.而开发和测试Linux驱动就需要安装以上两个开发环境. 搭建两套环境的具体步骤如下: 一.下载编译和测试A

全栈JavaScript之路( 二十四 )DOM2、DOM3, 不涉及XML命名空间的扩展

(一)DocumentType 类型的变化新增三个属性: publicId,systemId,internalSubset(内部子集) <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" [<!ELEMENT name (#PCDATA)>] > 通过, document.doc