我們現在的模塊用的是USB接口,然後模擬成一個COM6進行通信,在CE的: 控制面板->網絡連接 裏要新建一個連接,選擇“撥號連接”然後設置好區域代碼,還有附加解調器命令+CGDCON,"IP","CMNET",modem選擇,與modem的串口通信速率等信息,然後連接,這上可以實現上網。
添加的CE組件有:
CoreOS->Windwos CE devices->commuication services and newworking->networking-wide area network ->Dial up networking
->Autodail
->TAPI
->Virtual Private Networking(VPN)
我們現在要實現的功能是,讓用戶只點擊一個ICON,就能實現上網,不用這麼麻煩去設置。
我寫了一個應用,通過RAS 接口調用可以實現撥號上網功能,但是,必須指定一個已建立並設好參數的連接,
所以,還得在程序中創建一個網絡連接才行,因爲我們需要的簡化的其實就是讓用戶輸入附加撥號命令(+CGDCONT=1,"IP","CMNET"那麼一長串,其實只需要用戶輸入一個APN和一個電話號碼就OK了)。因爲針對不同的運營商,這個APN是不同的,所以這個要能給用戶設置。
查MSDN得知,調用RasSetEntryProperties加上RasSetEntryDialParams可以實現,但是這種方法貌似設置不了modem的串口屬性、附加撥號命令等一些信息,
用RasSetEntryProperties設置一個Entry的屬性的時候,如果Entry的參數中指定的EntryName已經存在了,那麼就更改已有的Entry的設置,如果不存在,則創建了一個新的Entry,這樣就實現了創建撥號連接的功能,
MSDN上關於RasSetEntryProperties函數中的倒數第二個參數的解釋說明是說它是一個指向包含設備配置信息的緩衝區的指針,是關於設modem的串口屬性、附加撥號命令等,
但是要查閱關於這個配置信息的更多詳細內容,就要看TAPI相關的lineGetDevConfig函數,但是TAPI相關知識是相當龐大的一個體系,因爲項目時間很緊,
直接在WINCE系統裏的控制面板下,進入“網絡和撥號連接”,手動新建一個能撥通上網的連接,我命名爲“3GCONNECT”
然後寫測試程序,調用RasGetEntryProperties()函數,在倒數第二個參數傳一個數組,然後打印出正確設置時的lpb裏面的值,結果如下:
- lpb 0x001aed00 "0" unsigned char[436]
[0x0] 0x30 '0' unsigned char
[0x1] 0x00 '' unsigned char
[0x2] 0x00 '' unsigned char //等待信用卡音頻信號時間
[0x3] 0x00 '' unsigned char
[0x4] 0x78 'x' unsigned char //120 秒這時間之內未建立連接,則取消撥號
[0x5] 0x00 '' unsigned char
[0x6] 0x00 '' unsigned char
[0x7] 0x00 '' unsigned char
[0x8] 0x00 '' unsigned char //串口參數:流控制,0 -- 無 0x20 軟件 0x10 硬件
[0x9] 0x01 'r' unsigned char
[0xa] 0x00 '' unsigned char
[0xb] 0x00 '' unsigned char
[0xc] 0x00 '' unsigned char //串口波特率 19200
[0xd] 0x4b 'K' unsigned char
[0xe] 0x00 '' unsigned char
[0xf] 0x00 '' unsigned char
[0x10] 0x00 '' unsigned char // 對應“設備屬性”對話框中的“手動撥號(用戶提供撥號串)”,
//如果爲0x04 表示選上此項
[0x11] 0x00 '' unsigned char
[0x12] 0x08 '' unsigned char //串口數據位 8位
[0x13] 0x00 '' unsigned char //停止位,00- 1位, 02 - 2位
[0x14] 0x00 '' unsigned char //奇偶校驗位,00-無,01奇數,02偶數,03標記,04空格
[0x15] 0x00 '' unsigned char
[0x16] 0x2b '+' unsigned char
[0x17] 0x00 '' unsigned char
[0x18] 0x43 'C' unsigned char
[0x19] 0x00 '' unsigned char
[0x1a] 0x47 'G' unsigned char
[0x1b] 0x00 '' unsigned char
[0x1c] 0x44 'D' unsigned char
[0x1d] 0x00 '' unsigned char
[0x1e] 0x43 'C' unsigned char
[0x1f] 0x00 '' unsigned char
[0x20] 0x4f 'O' unsigned char
[0x21] 0x00 '' unsigned char
[0x22] 0x4e 'N' unsigned char
[0x23] 0x00 '' unsigned char
[0x24] 0x54 'T' unsigned char
[0x25] 0x00 '' unsigned char
[0x26] 0x3d '=' unsigned char
[0x27] 0x00 '' unsigned char
[0x28] 0x31 '1' unsigned char
[0x29] 0x00 '' unsigned char
[0x2a] 0x2c ',' unsigned char
[0x2b] 0x00 '' unsigned char
[0x2c] 0x22 '"' unsigned char
[0x2d] 0x00 '' unsigned char
[0x2e] 0x49 'I' unsigned char
[0x2f] 0x00 '' unsigned char
[0x30] 0x50 'P' unsigned char
[0x31] 0x00 '' unsigned char
[0x32] 0x22 '"' unsigned char
[0x33] 0x00 '' unsigned char
[0x34] 0x2c ',' unsigned char
[0x35] 0x00 '' unsigned char
[0x36] 0x22 '"' unsigned char
[0x37] 0x00 '' unsigned char
[0x38] 0x43 'C' unsigned char
[0x39] 0x00 '' unsigned char
[0x3a] 0x4d 'M' unsigned char
[0x3b] 0x00 '' unsigned char
[0x3c] 0x4e 'N' unsigned char
[0x3d] 0x00 '' unsigned char
[0x3e] 0x45 'E' unsigned char
[0x3f] 0x00 '' unsigned char
[0x40] 0x54 'T' unsigned char
[0x41] 0x00 '' unsigned char
[0x42] 0x22 '"' unsigned char
[0x43] 0x00 '' unsigned char
[0x44] 0x00 '' unsigned char後面的全爲0
經過改不同的參數然後以上面的方法打出這個參數傳回來的值,總結出
所以總結出以下結構體:
typedef struct
{ //offerset
U16INT Reserved1; //0 一般爲0x30
U16INT WaitForCreditcard; //0x02 等待信用卡音頻信號時間,單位 ;秒
U16INT WaitForConnect; //0x04 這時間之內未建立連接,則取消撥號
U16INT Reserved2; //0x06 一般爲0
UINT8 Flowcontrol; // 0x08 串口參數:流控制,0 -- 無 0x20 軟件 0x10 硬件
UINT8 Unknow1; // 0x09 一般爲1,暫時還不知它是什麼作用
U16INT Reserved3; // 0x0a = 00
U16INT BaudRate; //0x0c 串口波特率例如 19200
U16INT Reserved4; // 0x0e =0
U16INT Configbit2; // 0x10 // 對應“設備屬性”對話框中的“手動撥號(用戶提供撥號串)”,如果爲0x04 表示選上此項
UINT8 DataBit; // 0x12 串口數據位 例如:8位
UINT8 StopBit; // 0x13 停止位00- 1位, 02 - 2位
UINT8 ParityBit; // 0x14 奇偶校驗位00-無,01奇數,02偶數,03標記,04空格
UINT8 Reserved5; // 0x15 i don't know it's function
TCHAR AttachedCmd[210]; // 0X16 從這開始是附加解調器命令,例如"+CGDCON=1,IP,COMNET"
//注意:本人使用的是wince6.0,所以這個長度爲436byte,其它平臺可能會不一樣,網上有牛人測出WM的是一百多的
}RASlpdInfo;
用這個結構在AttachedCmd中填入附加撥號命令,就可以了
DWORD dwSize,
dwError;
TCHAR szError[100];
RASlpdInfo lpb;
unsigned long lpbSize = sizeof(RASlpdInfo);
memset(&lpb,0,lpbSize);
RASENTRY RasEntry;
dwSize = sizeof (RASENTRY);
memset (&RasEntry, 0, dwSize);
RasEntry.dwSize = dwSize;
wcscpy(RasEntry.szDeviceName,L"CDMAModem");
wcscpy(RasEntry.szDeviceType,L"modem"); //#define RASDT_Modem TEXT("modem") // Ras.h
RasEntry.dwCountryCode = 86; //國家代碼
wcscpy(RasEntry.szAreaCode,L"10");
TCHAR szLocalPhoneNumber[RAS_MaxPhoneNumber + 1] = {0};
wsprintf(szLocalPhoneNumber,L"%s",LocNum); //-------------------容易出問題的地方
wcscpy(RasEntry.szLocalPhoneNumber,szLocalPhoneNumber );
RasEntry.dwfOptions= 4194304;//RASEO_ProhibitEAP|RASEO_RemoteDefaultGateway; ;//4194304;0x00400208;//
RasEntry.dwfNetProtocols= RASNP_Ip;//4; Negotiate TCP/IP
RasEntry.dwFramingProtocol= RASFP_Ppp;//1; // Point-to-Point Protocol (PPP)
lpb.Reserved1 = 0x30;
lpb.WaitForCreditcard = 0;
lpb.WaitForConnect =120;
lpb.Reserved2 = 0;
lpb.Flowcontrol = 0;
lpb.Unknow1 = 1;
lpb.Reserved3 = 0;
lpb.BaudRate = 19200;
lpb.Reserved4 = 0;
lpb.Configbit2 = 0;
lpb.DataBit = 8;
lpb.StopBit = 0;
lpb.ParityBit = 0;
TCHAR szATComd[420] = {0};
wsprintf(szATComd,L"+CGDCONT=1,$IP$,$%s$",lpszAPN);
szATComd[11] = 0x22; // 雙引號"
szATComd[14] = 0x22;
szATComd[16] = 0x22;
szATComd[22] = 0x22;
wcscpy(lpb.AttachedCmd,szATComd);
if (dwError = RasSetEntryProperties (NULL, lpszName,
&RasEntry, sizeof (RASENTRY),(LPBYTE)(&lpb), lpbSize))
{
wsprintf (szError, TEXT("Unable to create the phonebook entry.")
TEXT(" Error %ld"), dwError);
return FALSE;
}
注意,WINCE6.0調用了RasSetEntryProperties()之後,就可以在控制面板的連接管理裏看到這個連接圖標了,但是,如果是在WM系統,那就得再做下面的工作才能看得到圖標。
機器中控制面板的”管理現有連接“對應註冊表中
HKEY_LOCAL_MACHINE//Comm//ConnMgr//Providers//{7C4B7A38-5FF7-4bc1-80F6-5DA7870BB1AA}//Connections
[Connections]下的集合;
[Enabled]: 是否爲默認連接;
[RequirePW] 是否需要用戶名與密碼
[DestId]: 表示屬於哪種類型的連接;
[ConnectionGUID]:表示連接的標識ID,
拔號時獲得當前狀態
如果想在拔號時獲得當前狀態,可以這樣:
攔截PreTranslateMessage這個消息事件,截獲WM_RASDIALEVENT消息即可達到目的
BOOL CMy3GControlerDlg::PreTranslateMessage(MSG* pMsg)
{
if(pMsg->message == WM_RASDIALEVENT)
{
switch(pMsg->wParam)
{
case RASCS_OpenPort:
pShowstate->SetWindowTextW(_T("打開端口…"));
break;
case RASCS_PortOpened:
pShowstate->SetWindowTextW(_T("端口已打開…"));
break;
case RASCS_ConnectDevice:
break;
case RASCS_DeviceConnected:
pShowstate->SetWindowTextW(_T("設備已連接…"));
break;
case RASCS_Authenticate:
pShowstate->SetWindowTextW(_T("驗證用戶及密碼…"));
break;
case RASCS_Authenticated:
pShowstate->SetWindowTextW(_T("用戶及密碼已通過驗證"));
break;
case RASCS_Connected:
pShowstate->SetWindowTextW(_T("已連接"));
break;
case RASCS_Disconnected:
pShowstate->SetWindowTextW(_T("斷開連接"));
break;
default:
return (LRESULT)0;
}
}
return CDialog::PreTranslateMessage(pMsg);
}
RAS撥號的同步和異步問題
dwRet = RasDial(NULL,NULL,&rdParams,0L,NULL,&m_hRasConn);//同步
dwRet = RasDial(NULL,NULL,&rdParams,0L,RasDialFunc,&m_hRasConn);//異步回調 --只支持在PC
dwRet = RasDial(NULL,NULL,&rdParams,0xFFFFFFFF,this->m_hWnd,&m_hRasConn); //異步消息--支持PC、CE
如果同步,可用線程監視同步過程,
異步:只在使用了PreTranslateMessage才成功
所以,在CE系統裏,要實現連接狀態顯示,那就得使用
dwRet = RasDial(NULL,NULL,&rdParams,0xFFFFFFFF,this->m_hWnd,&m_hRasConn);
撥號連接
void DialRAS(LPVOID Hahandle,LPWSTR ConnectionName,LPWSTR PhoneNumber)
{
RASDIALPARAMS RasDialParams;
BOOL fPassword;
memset (&RasDialParams, 0, sizeof (RASDIALPARAMS));
RasDialParams.dwSize = sizeof(RASDIALPARAMS);
wcscpy(RasDialParams.szEntryName,ConnectionName); //已建連接的名字
TCHAR szLocalPhoneNumber[RAS_MaxPhoneNumber + 1] = {0};
wsprintf(szLocalPhoneNumber,L"%s",PhoneNumber);
wcscpy(RasDialParams.szPhoneNumber,szLocalPhoneNumber);
wcscpy(RasDialParams.szCallbackNumber, _T(""));
wcscpy(RasDialParams.szUserName, _T(""));
wcscpy(RasDialParams.szPassword, _T(""));
wcscpy(RasDialParams.szDomain, _T(""));
CMy3GControlerDlg* hthisp =(CMy3GControlerDlg*)Hahandle;
DWORD hRasRet = 0;
// Try to establish RAS connection.
hRasRet = RasDial (NULL, // Extension not supported
NULL, // Phone book is in registry
&RasDialParams, // RAS configuration for connection
0xFFFFFFFF, // Notifier type is a window handle
hthisp->m_hWnd, // Window receives notification message
&hRscon);
printf("hRasRet == %d ", hRasRet);
if ( hRasRet != 0) // Connection handle
{
printf("Could not connect using RAS, error == %d ", GetLastError());
}
}