HengFeng

--博观而约取,厚积而薄发
  博客园  :: 首页  :: 新随笔  :: 联系 :: 管理

【原创】高通QSC60X0 ATCoP学习小结

Posted on 2009-12-05 14:25  hengfeng  阅读(2875)  评论(1编辑  收藏  举报

一,基本流程  

  ATCoP(AT Command Processor)是高通平台上对于AT命令处理的模块。基本上它遵循以下过程:

  串口(sio)接收到串口发送过来的字符串--> AT Command Parser --> 产生一个重要的Token结构,它包含了命令名称,接收到的参数,以及response的buffer--> 之后AT Command ProcessorProcess 通过Token里面的信息查调用相应的AT 命令处理函数 -->处理完成后产生相应的response给TE。

 

二,具体代码实现

例子1 . 我们在USB MODEM上需要实现一个对PIN码校验的功能,即UIM的PIN功能开启以后,需要在PC端提示用户输入PIN码,但连续输入3次错误后需输入PUK解锁。

  我们不需要修改高通默认的处理流程,只要在command table中添加相应的命令、处理函数:

    { "+CPIN",         READ_ONLY|RESTRICTED,
      SPECIAL_NONE,    0,    NULL,    NULL,
      dsat707_exec_CPIN_cmd,            NULL },

  其中+CPIN就是我们定义的一个AT命令,dsat707_exec_CPIN_cmd就是对应的处理函数。

  我们设想的+CPIN功能是:

    A. 查询命令: AT+CPIN? 

      返回: READY          表示UIM没有

           UIM PIN         表示UIM开启了PIN码功能,用户插入USB MODEM后需要输PIN码

         UIM PUK        表示连续3次输入错误PIN,需要输入PUK解锁

         VERIFIED       表示PIN码输入正确

         UNBLOCKED  表示PUK输入正确,解锁成功
         BLOCKED      如果是返回这个,很不幸的告诉你,你的卡GAME OVER! 

    B. 设置命令: AT+CPIN=1234     用户输入PIN码验证

            AT+CPIN=12345678,1234  用户输入PUK以及新PIN码来解锁

 

  OK,知道了具体的需求,就可以在处理函数dsat707_exec_CPIN_cmd中实现了:

  首先判读接收到的+CPIN是什么格式的,是查询命令,设置命令,还是其他。我们可以通过Token结构中的tok_ptr->op参数来判断,如果tok_ptr->op == (NA|QU)表示查询命令;tok_ptr->op == (NA|EQ|AR)表示设置命令。

  

  在查询命令中,我们只要通过获得UIM卡的PIN状态,把相应的状态以字符串的形式告诉PC端就可以了。当然可以在这里调用GSDI 的接口来查询PIN状态,但是在dsatme_init_me中已经向GSDI注册了一个回调函数:gsdi_pin_event_cb_func。 一旦GSDI检测到PIN码状态发生改变时,就会调用这个回调函数。所以我们可以定义一个全局变量,在回调函数中设置这个全局变量,之后在dsat707_exec_CPIN_cmd中判断这个全局变量,发送相应字符串。

 

  在设置命令中,我们要限制用户只能在UIM PIN和UIM PUK 这两种状态才允许执行。在这里遇到了一个很大的难题,就是我们可以容易的通过GSDI的接口来解PIN和解PUK,但是要如何告知其他的service以及UI我们已经解锁了呢?? 可以采用一种“笨”办法,就是不通过直接调用GSDI接口来解PIN,而是模拟出一连串的按键,发送给UI解锁。比如接收到AT+CPIN=1234后,我们可以连续发送1,2,3,4,SEL一共5个KEY EVENT给UI,这样就如同用户在手机上按键解锁了。

  

 

例子2,来电---ATCoP中对同步事件的处理

  同步事件的处理,我的理解就是ATCoP在其他task注册了一个同步事件的回调函数,一旦同步事件发生时,其他task就会调用这个回调函数来通知ATCoP调用相应的同步事件处理函数。一个典型的例子就是来电过程的处理:

 

  1. dsatcmif_init_cmif -> cmif_register_cb_func---向CM task注册来电,或者对方应答回调

      /* Register the CM call event callback function */
      cm_status = cm_mm_client_call_reg (
                                       dsatcm_client_id,
                                       cmif_call_event_cb_func,
                                       CM_CLIENT_EVENT_REG,
                                       CM_CALL_EVENT_INCOM,
                                       CM_CALL_EVENT_CONNECT,  
                                       NULL
                                      );

 

  2. 一旦有来电消息,cmif_call_event_cb_func构造事件的命令放入cmd buffer
       cmd_buf->hdr.cmd_id = DS_AT_CM_CALL_INFO_CMD;
          cmd_buf->cmd.call_event.event_info = *event_ptr;
          cmd_buf->cmd.call_event.event      = event;
      ds_put_cmd(cmd_buf);---->调用(void)rex_set_sigs( &ds_tcb, DS_CMD_Q_SIG );通知ds_task来处理

 

  3. 在 ds_task 中调用 dsi_process_cmds()处理命令

 

  4.   调用dsat_process_async_cmd( cmd_ptr );
    (1). 查找表async_event_table  event_handler_func_ptr =  async_event_table[i].event_handler[operating_mode];

    (2). 调用相应的处理函数result_code = event_handler_func_ptr( dsatcmdp_at_state, cmd_ptr );

    (3). 这里调用dsatcmif_cm_call_event_handler

    (4). 调用来电处理函数 ,在这个函数里面会主动发送"Ring"字符串来通知PC端由来电了。

        result = dsatvoice_call_event_incom(&cmd_ptr->cmd.call_event.event_info);