none
請教如何對Windows Mobile 6讀取及寫入AT Command,另外,有辦法能監聽到AT Command嗎? RRS feed

  • 問題

  • 我的第一個目的是希望能對WM6讀取以及寫入AT Command
    但是,在網路上找了許多方法都不曾成功;所以,想來這邊請教一下

    以下是我測試的片段程式碼(CHT9100,WM6)

    (1)我嘗試用RIL_GetSerialPortHandle拿到HANDLE
    再以WriteFile做寫入,但是為什麼ReadFile讀取卻總是失敗,讀的到字串長度nRead總是等於0?

    //初始化RIL
    hr_callinfo= RIL_Initialize(dwIndex,//(RILRESULTCALLBACK)
          ResultProc,//(RILNOTIFYCALLBACK)
          NotifyProc,
          RIL_NCLASS_ALL,NULL,&m_hRil); 
    HANDLE hCom = NULL; 

    //得到RIL的SerialPortHandle
    ////////////////////////////////////////////////////////////////////
    if (RIL_GetSerialPortHandle(m_hRil,&hCom)<0)  
    {
      printf("RIL_GetSerialPortHandle ERROR\n");
    }
    ///////////////////////////////////////////////////////////////////
    //設定COM port
    DCB dcb;

    if (!GetCommState(hCom, &dcb)) //若以CreateFile的方法,這邊GetCommState會失敗
     { 
       printf("GetCommStat ERROR\n");
     } 
     dcb.BaudRate= CBR_115200;
     dcb.ByteSize= 8;
     dcb.fParity= false;
     dcb.StopBits= ONESTOPBIT;
     
     if (!SetCommState(hCom, &dcb))
     { 
       printf("SetCommState ERROR\n");
     } 
     if (!EscapeCommFunction(hCom, SETDTR))
     { 
       printf("EscapeCommFunction ERROR\n");
     }
    //設定Timeouts
     COMMTIMEOUTS to;  
     if (!GetCommTimeouts(hCom, &to))
     { 
       printf("GetCommTimeouts ERROR\n");
     }
     
     to.ReadIntervalTimeout= 0;
     to.ReadTotalTimeoutConstant= 200;
     to.ReadTotalTimeoutMultiplier= 0;
     to.WriteTotalTimeoutConstant= 20000;
     to.WriteTotalTimeoutMultiplier= 0;
     if (!SetCommTimeouts(hCom, &to))
     { 
       printf("SetCommTimeouts ERROR\n"); 
     } 
     if (!SetCommMask(hCom, EV_RXCHAR))
     { 
       printf("SetCommMask ERROR\n"); 
     }
     BYTE comdevcmd[2]= {0x84, 0x00}; //從網路上找到的,不清楚這邊設定是否正確(從何處可得到這個代碼?)
     int bufpos;
     char buf[256];
     if (!DeviceIoControl (hCom,0xAAAA5679L, comdevcmd,sizeof(comdevcmd),0,0,0,0)) //第二個參數0xAAAA5679L同樣也是不確定,但是加上這個參數才會成功執行DeviceIoControl
     { 
      DWORD dw = GetLastError(); 
      printf("DeviceIoControl failed with error %d.", dw); 
     }
     bufpos = 0;
     char outbuf[100];
     DWORD nWritten,nRead;

     strcpy(outbuf,"AT+GMI\r");
     
     if (!WriteFile(hCom, outbuf, strlen(outbuf), &nWritten, NULL))
     { 
       printf("WriteFile ERROR\n");
     }
     
     if (nWritten != strlen(outbuf))
     { 
       printf("Write ERROR\n"); 
     }
      
     /* 這段註解掉,因為呼叫了就會block在這裡
    DWORD event1;
     if (!WaitCommEvent(hCom, &event1, NULL))   
     { 
       printf("WaitCommEvent ERROR\n"); 
     }
    */
    Sleep(500);

    while(1)

       if (!ReadFile(hCom, buf+bufpos, 256 - bufpos, &nRead, NULL))
       { 
         printf("ReadFile ERROR\n");
       } 
       printf("%d================================\n",nRead);
       //在這裡總是會讀不到東西

       if (nRead == 0) break;  
     
       bufpos += nRead;  
     
       if (bufpos >= 256)
         break;   
    }

    (2)我嘗試直接用CreateFile的方法去得到Handle(分隔線SerialPortHandle那段改成下面代碼)hCom=CreateFile(L"RIL1:",GENERIC_READ|GENERIC_WRITE,0,0 ,OPEN_EXISTING,0,0);

    但是目前都是在GetCommState就會失敗

    除了RIL1:還測試了其他的COM port name
    我從HKEY_LOCAL_MACHINE\Drivers\Active中找到可能可以送AT Command的port,一一測試
    COM1:   (Serial_IR)
    COM3:   (IrCOMM)
    COM6:   (Serial)
    COM7:   (SERIAL_BTUR)
    RIL1:     (RIL)
    但結果都是一樣

    想請教我用CreateFile的方法哪裡出錯了呢?

    ===

    另外,第二個目的

    想請問有什麼方法可以監聽AT Command呢?(因為有比RIL更底層的東西,所以才想去監聽AT Command)

    最後,希望有人能提供在WM上對AT Command操作的簡單sample code,讓我能夠學習一下
    網上也survey了不少卻總是都沒有解決這個問題

    先謝謝了

    • 已編輯 wscheng 2010年7月20日 下午 12:09
    2010年6月5日 下午 03:18

所有回覆

  • 你是希望可以直接控制 phone 的 baseband modem?
    典型的 GSM modem 都會提供 MUX 以便讓一個 physical Serial Port 可以分出好幾個 Virtual COM Port 來用. MUX 的標準其實就是 G.710 and etc 等等的。
    RIL driver <==> MUX driver <==> Serail Driver<---> GSM baseband
    而由 RIL_GetSerialPortHandle 取得的 COM port 其實是 MUX 分出來的一個 Virtual COM port
    ( [HKEY_LOCAL_MACHINE\Software\Microsoft\RIL\DataPort] 所指定的 COM port)
    所以你找到的那些 command 也就是對 MUX driver 做的一些 special command,這些 command 其實會因 MUX driver 而異。
    然而 CHT 9100 的 baseband 應該是用 Qualcomm 的 MSM 6275,好像後來這些 3G baseband 因應 3G 的 high bandwidth,慢慢地都改用 USB 而不是用 Serial Port 來傳輸,當然 MUX 的 design 也完全跟過去 Serial Port based 的大不相同,更甚者有些 3G 的 RIL driver 也不再是用 AT command 來跟 baseband 溝通了。
    簡單的說,除非你可以 access MUX driver source code,或是花時間去 reverse engineering,不然要透過 MUX export 出來的 dataport 來 inject AT command 不太容易。
    假如要做 RIL 相關研究,建議弄套 PB 6.0,然後找個外接 GSM/3G modem 或是 development kit 會比較容易點。

    • 已標示為解答 Lolota Lee 2010年6月11日 上午 10:22
    • 已取消標示為解答 wscheng 2010年7月20日 上午 11:58
    2010年6月8日 上午 08:35
  • 雖然仍在研究中 但先感謝解答

    2010年7月11日 上午 10:19


  • 以下程式在TOSHIBA G810上測試,是C#的程式
    COM6是7500 VSP Modem
    COM9是GPS
    在COM9是可以成功讀取到字元,但是在COM6卻一直沒辦法讀取到東西會有TimeoutException

    using System;
    using System.Linq;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.IO.Ports;
    using System.Threading;


    namespace SerialTest
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }

            private void button1_Click(object sender, EventArgs e)
            {
                string[] ports = SerialPort.GetPortNames();
                for (int i = 0; i < ports.Length; i++)
                {
                    textBox1.Text += ports[i];
                    textBox1.Text += "\r\n";
                    comboBox1.Items.Add(ports[i]);
                }
            }

            private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
            {

            }

            private void button2_Click(object sender, EventArgs e)
            {
                if (comboBox1.Text != "")
                {
                    rPort = new SerialPort(comboBox1.Text.ToString(), 115200, Parity.None, 8, StopBits.One);
                    rPort.ReadTimeout = 1000;
                    try
                    {
                        if (!rPort.IsOpen)
                        {
                            rPort.Open();
                        }
                        if (!rPort.IsOpen) MessageBox.Show(comboBox1.Text + " Open Failed");

                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.ToString());
                    }
                    try
                    {
                        rcvThread = new Thread(new ThreadStart(ReceiveData));
                        rcvThread.Start();
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("after Open" + ex.ToString());
                    }
                }
                else MessageBox.Show("COM not selected!\n");
            }

            private void textBox1_TextChanged(object sender, EventArgs e)
            {

            }

            SerialPort rPort;
            Thread rcvThread;
            private void ReceiveData()
            {

                while (true)
                {
                    try
                    {
                        if (rPort.PortName == "COM6") //當是COM6的時候試著送AT Command
                        {
                            //MessageBox.Show("Write to COM6: AT\r\n");
                            rPort.WriteLine("AT");
                        }
                        String rstr = "";
                        rstr += rPort.ReadChar().ToString();
                        MessageBox.Show(rstr);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("Receive: " + ex);
                    }
                }
            }

        }
    }

    這支程式 小改自codeproject裡的程式
    http://www.codeproject.com/KB/windows/bth_serial_port.aspx

    但是,我嘗試了另外一套試用軟體卻可以在TOSHIBA G810成功抓取COM6的資料,也可以下AT command
    (而baud rate,parity,data bits的設定也都相同)
    http://www.tsreader.com/ztermppc/index.html

    想請問我的程式哪裡弄錯了嗎?

    另外,zTerm在CHT9100上並沒有辦法能對任何COM port下AT command
    有可能底層
    (1)真的不是用AT Command
    (2)COM port根本不給寫入
    (3)控制Serial Port的方法錯了
    2010年7月20日 上午 11:58
  • 另外,原本VC++的code跑在TOSHIBA G810的手機上,在在DeviceIoControl的地方失敗
    錯誤碼是87,就是The paramter is incorrectly!

    代表我的傳入參數有誤,請問在哪可以查到這些傳入的參數該塞什麼
    或是呼叫哪個function可以得到呢?

    if (!DeviceIoControl (hCom,0xAAAA5679L, comdevcmd,sizeof(comdevcmd),0,0,0,0)) //第二個參數0xAAAA5679L同樣也是不確定,但是加上這個參數才會成功執行DeviceIoControl
     { 
      DWORD dw = GetLastError(); 
      printf("DeviceIoControl failed with error %d.", dw); 
     } 

    ps.原本的CHT9100是可以成功的執行DeviceIoControl而不會有錯誤

    2010年7月20日 下午 12:06
  • 就像之前提到的,這些 MUX driver 都是各廠商個做個的,跟本沒有標準也沒有公開的資料可以查。
    所以在 Device A 可以 Support 的 IOCTL,在 Device B 沒 support,也是不意外的。
    而 ZTerm 可以收送,但你的 code 不行,有沒有可能是出在 Terminal character 0x0A, 0x0D or etc? 或是 Flow Control setting?

    2010年7月22日 上午 06:38