Microsoft Radio Interface Layer

 

Microsoft Radio Interface Layer

Cellcore

Microsoft Radio Interface Layer - dmg - ICE BOY

上面是 Windows CE Communication_Services 的架構圖。

Microsoft Radio Interface Layer - dmg - ICE BOY

CellCore represents a strategic wireless architecture for products based on Windows CE. The intent of the architecture is to provide a core set of services that will abstract a variety of underlying airlinks for both voice and data services.

Radio Interface Layer

Windows CE 5.0 Driver managed by device.exe process. The built-in driver would load in boot time and record in [HKEY_LOCAL_MACHINE/Drivers/BuiltIn/DriverName].

Microsoft Radio Interface Layer - dmg - ICE BOY

What is a RIL driver?

§The “Radio Interface Layer” (RIL) driver is the interface between the system software and the radio stack.

The Radio Interface Layer (RIL) provides an interface that handles the communication between the CellCore system software and the radio hardware. The RIL provides an abstraction layer that enables you to create a single driver that can be implemented on different radios. The RIL abstracts the details of the hardware dependent components of a device to enable OEMs to integrate a variety of modems into their equipment, offering an opportunity for product differentiation. This single driver then allows all of the radios to work under a single set of CellCore components.

Radio interface Layer is a special driver. The RIL driver services system requests for radio functionality (voice, data, SMS, etc.), and notifies the system of changes in the radio state (coverage, signal strength, incoming calls, etc.).

In order to enable your radio hardware to communicate with the Radio Interface Layer (RIL), the ODM/OEM needs to implement a hardware-specific RIL driver. RIL its work is to translate the radio function to the corresponding AT Command to Modem and get the response from Modem. It is a bridge between Microsoft AP and Radio Modem. In the Pocket PC Phone or SmartPhone point, Modem (MT) is a radio device and its work is to communicate to network.

IOControl

BOOL IOControl(

 DWORD dwInst,

DWORD dwIoControlCode,

LPVOID lpInBuf,

DWORD nInBufSize,

LPVOID lpOutBuf,

DWORD nOutBufSize,

LPDWORD lpBytesReturned

);我們可以自己定義資料結構,並且在使用時傳入 lpInBuf 和 nInBufSize 來傳遞我們要傳的資料。RIL 也是使用 IO CONTROL code 來決定要執行的功能,使用 dwIoControlCode 來判斷要呼叫的 function。

下面一般的應用程式呼叫順序:

RIL function -> RIL IO Control code -> RIL internal function

而 RIL internal function 會再轉換為相對應的 AT Command 或者是相對應的 RPC 呼叫。

Device Power State

Device power state definitions are statically predefined. Power Manager passes a device state to a driver, and the driver is responsible for mapping the state to its device capabilities, and then performing the applicable state transition on the device.

Microsoft Radio Interface Layer - dmg - ICE BOY

Device power state Registry key Description

 

Full on

D0

 

 

 

Device is on and running. It is receiving full power from the system and is delivering full functionality to the user.

 

Low on

D1

 

 

 

Device is fully functional at a lower power or performance state than D0. D1 is applicable when the device is being used, but peak performance is unnecessary and power is at a premium.

 

Standby

D2

 

 

 

Device is partially powered, with automatic wakeup on request.

 

Sleep

D3

 

 

 

Device is partially powered, with device-initiated wakeup, if available. A device in state D3 is sleeping but capable of raising the system power state on its own. It consumes only enough power to be able to do so; which must be less than or equal to the amount of power used in state D2.

 

Off

D4

 

 

 

Device has no power. A device in state D4 should not be consuming any significant power. Some peripheral busses require static terminations that intrinsically use non-zero power when a device is physically connected to the bus. A device on such a bus can still support D4.

當 Data 還在傳輸,或者是正在通話時,我們應該設定 device 不會進入 suspend mode,而是進入 Unattended mode(Backlight off 的狀態)。我們可以使用 PowerPolicyNotify() 來進行 Power state 的轉換,如下面的例子:

PowerPolicyNotify(PPN_UNATTENDEDMODE, TRUE);

如果要取得當時的 Power State,可以使用 GetSystemPowerState():

TCHAR szPowerState[100]= {0};

DWORD dwPowerFlag = 0;

if (GetSystemPowerState(szPowerState, 100, &dwPowerFlag) == ERROR_SUCCESS)

{

if (dwPowerFlag & POWER_STATE_UNATTENDED) // check current power state

{

// Do something

}

}

Multiplexer Protocol

GSM 07.10 define a multiplexer protocol, provide multiple virtual connection over a  serial asynchronous interface between an MS and a TE. There are three Operating Options:

 

  • Basic
  • Advanced without Error Recovery
  • Advanced with Error Recovery (ABM)

The main advantage of the multiplexer is that it allows AT commands to be sent to the modem without interrupting the data stream during an active data connection. This simplifies the handling of voice calls and SMS during a data connection.

 

Microsoft Radio Interface Layer - dmg - ICE BOY

RIL Modules

All of the RIL functions could be broken down by groups.

 

Group

 

 

Description

Network ServicesOperator selection, signal status, available operators
Call Control Dial, Hangup,Hold, Transfer
Supplemental Services Call waiting, call forwarding, call meter
SMS Send, receive, SMSC selection
Data Connection Virtual serial port, bearer service types, transparent data/online mode change
Interface Functions Initialization, notification registration
GPRS Functions Selecting GPRS profiles, attaching, context activating
HSCSD FunctionsHSCSD Functions

 

 

Security Functions Locking, unlocking, passwords
Phonebook Functions Accessing the SIM phonebooks
SIM SMS Functions Accessing SMS messages from the SIM
SIM Record Access Access individual files on the SIM
SIM Toolkit 2.0 Support

 

 

Microsoft handles short messages is different to phonebook. Microsoft would read the SIM card phoebook records and make the mirror records in its memory. However, Microsft privode functions to read and write the short message storage in SIM Card, but it could not make the mirror records in the memory.

RIL consists of two modules: the RIL proxy and the RIL driver.

Microsoft Radio Interface Layer - dmg - ICE BOY

RIL Proxy

The proxy layer is a Windows CE-based dynamic-link library (DLL) that manages callback notifications and inter-process function calls into the driver layer. CellCore modules use the RIL application programming interface (API) by linking to this proxy DLL.

The RIL proxy is provided by Microsoft. You have to write a customized RIL driver to work with your radio hardware.  RIL Proxy translates RIL_XXXX function to RIL_IOCTL_XXX calls into RIL_IOControl in RIL driver. Example: RIL_Dial results in RIL_IOControl (IOCTL_RIL_DIAL, …). RIL Proxy also responsible for calling back into client processes for notifications and asynchronous RIL function results.

Notification Class

#define RIL_NCLASS_FUNCRESULT (0x00000000) // @constdefine API call results

#define RIL_NCLASS_CALLCTRL (0x00010000) // @constdefine Call control notifications

#define RIL_NCLASS_MESSAGE (0x00020000) // @constdefine Messaging notifications

#define RIL_NCLASS_NETWORK (0x00040000) // @constdefine Network-related notifications

#define RIL_NCLASS_SUPSERVICE (0x00080000) // @constdefine Supplementary service notifications

#define RIL_NCLASS_PHONEBOOK (0x00100000) // @constdefine Phonebook notifications

#define RIL_NCLASS_SIMTOOLKIT (0x00200000) // @constdefine SIM Toolkit notifications

#define RIL_NCLASS_MISC (0x00400000) // @constdefine Miscellaneous notifications

#define RIL_NCLASS_RADIOSTATE (0x00800000) // @constdefine Notifications Pertaining to changes in Radio State

#define RIL_NCLASS_DEVSPECIFIC (0x80000000) // @constdefine Reserved for device specific notifications

#define RIL_NCLASS_ALL (0x00ff0000) // @constdefine All notification classes (except DevSpecifc)

Enable RIL Proxy logging

如果需要 RIL Proxy 的 debug message,在 registry 加上:

[HKEY_LOCAL_MACHINE/Software/Microsoft/RIL]

"RILProxyLogNormal"=dword:1

"RILProxyLogDetail"=dword:1

RIL Driver

The RIL allows hardware abstraction by accepting service requests from the upper layers, mainly TAPI and ExTAPI and converts those requests into commands supported by the modem, exchanging information over a modem / host processor interface.

There are three modes modem-serial implement:

 

  • One UART, One COM - It imposes throughput constraints on 2.5G and 3G systems as the modem must be periodically switched between data and command mode.

     

     

  • One UART, Two COM - a single UART addressable via two logical / virtual serial ports.

     

     

  • Two UART, Two COM

     

     

Microsoft Radio Interface Layer - dmg - ICE BOY

 

The following table shows the RIL driver entry points (From MSDN):

Function Description

 

RIL_Init

 

Called by system during boot to start the RIL driver. This function creates the worker threads, initializes global data structures, initialize COM ports, and so on. It also launches the thread that performs radio initialization and sets the RILDrv_Present event to notify the RIL proxy that the driver was loaded and initialized successfully.

 

 

RIL_Deinit

 

Called before driver is unloaded. This function performs cleanup and clears the RILDrv_Present event to inform the RIL proxy that the driver was unloaded.

 

RIL_Open

 

Called by the proxy each time a client calls RIL_Initialize. This function prepares RIL for use by a new client.

 

RIL_Close

 

Called by the proxy each time a client calls RIL_Deinitialize. This function frees any resources that were used by a previous client.

 

 

RIL_Read

 

Reads data from the device identified by the open context. This function should return zero (0).

 

RIL_Write

 

Writes data to the device. This function should return zero (0).

 

RIL_Seek

 

Moves the data pointer in the device. This function should return -1.

 

 

RIL_PowerUp

 

Restores power to the device. This function should return a value of void. The implementation of this function is optional.

 

RIL_PowerDown

 

Suspends power to the device. This function should return a value of void. The implementation of this function is optional.

Most of the RIL API function calls pass through the RIL_IOControl function.

The RIL driver layer is implemented as a Windows CE device driver that is managed by the Device Manager (Device.exe). The RIL driver services system requests for radio functionality including voice, data, Short Message Service (SMS), and other functionality, and notifies the system of changes in the radio state, such as coverage, signal strength, and incoming calls.

Most of the RIL API function calls pass through the RIL_IOControl function. Typically this is implemented in a switch : case expression. The following code example shows how this is written.

switch (dwCode)

{

// RIL_GetSubscriberNumbers()

case IOCTL_RIL_GETSUBSCRIBERNUMBERS:

result = RILDrv_GetSubscriberNumbers(...);

break;

// RIL_GetOperatorList()

case IOCTL_RIL_GETOPERATORLIST:

result = RILDrv_GetOperatorList(…);

break;

}在更底層的實作上,通常會使用一個 Command Thread 和一個 Response Thread 來處理。

Microsoft Radio Interface Layer - dmg - ICE BOY

在放入 command Queue 之前,如果需要 parser,會指定一個 parser function。下面是一個範例:

if (!QueueCmd(PRIORITY_PORT, pHandle, "AT+CPAS/r", CMDOPT_NONE, APIID_GETLINESTATUS, ParseGetLineStatusRsp, NULL, hr)) {

hr = E_FAIL;

goto Error;

}Note:目前已有 Radio device 嘗試使用 share memory 的方式來實作,這樣就不用使用 serial port driver,而是使用 function call (RPC) 的方式來呼叫 radio 端的功能,這樣子效率會比使用 serial driver 的方式更好。

Note: AT Command 的回應可以分為二類,unsolicited 與 solicited。如果這二類的 AT Command 都是一樣的回應,那麼 unsolicited 的 AT Command 的 parser 會先 parse Modem 的回應,然後後面的 OK 才會被 solicited 的 AT Command 的 parser 再分析。

For Windows CE

To enable your radio hardware to communicate with the RIL, you need to implement a hardware-specific RIL driver.

The RIL driver architecture is based on the Windows CE standard MDD/PDD driver model. It is divided into two major sections, the MDD and PDD layers. The following illustration shows the RIL architecture.

The MDD (Model Device Driver) layer is independent of the radio stack. It contains code that interfaces with the RIL Proxy and code that implements any radio stack independent features in the RIL driver.

PDD (Platform Dependent Driver) layer is radio stack dependent. It contains code specific to implementation of RIL APIs for a specific radio stack. This is the layer that must implemented by OEMs. To further ease the implementation task the PDD layer itself can be separated into a layer that contains code common to a category of radios and code for a specific radio in that category. For example, the previous illustration shows a PDD layer that is separated into code common to AT based radio stacks and code for a specific AT based radio.

Although the RIL driver is divided, into 2 major parts, the output of the build process is still a single DLL.

For Windows Mobile

The Radio Interface Layer (RIL) proxy consists of a dynamic-link library (DLL) that manages callback notifications and inter-process function calls into the driver layer. CellCore modules or applications need to link to this DLL to use the RIL API. The RIL Proxy is loaded separately by each RIL client and maintains handles to the RIL driver for each client.

Microsoft Radio Interface Layer - dmg - ICE BOY

To use the RIL, the module only needs to use functions specified in the proxy header file (ril.h) and then link with the proxy DLL (ril.dll). Each module needs a RIL instance handle that will be used for all the RIL operations. This function RIL_Initialize() returns this handle.

When a module first registers with the RIL, it passes in two callback functions. There are two kinds of callbacks needed to be assigned as parameters of RIL_Initialize function result callback:

  • function result callback - called by the proxy after an asynchronous RIL function call
  • notification callback - called by the proxy when an unsolicited notification is received

For example, when the phone receives a new incoming call, the RIL uses the unsolicited notification callback to notify each module about the incoming call. When a module calls the RIL to get the signal strength, the function call immediately returns a response identifier.

 

In Windows Mobile 7,如果使用 serial port/AT Command 的組合,微軟將不同 radio stack 的 AT Command 包裝起來,RIL driver 將會分成二個主要的部份,MDD 和 PDD layer。

Function

Call Control Functions

Function GSM Comments
RIL_Dial D +FCLASS Dials a number
RIL_Answer A Answers an incoming call
RIL_Hangup H End all voice and data calls
RIL_SendDTMF +VTS Sends DTMF tones
RIL_GetCallList +CLCC Retrieves list of active calls and their status
RIL_ManageCalls +CHLD Changes call status (hold, conference, etc)
RIL_TransferCall +CTFR Explicitly transfers a call
RIL_GetLineStatus +CPAS Gets line status
RIL_SendFlash

 

 

Send CDMA hook flash

Call Control Notifications

dwCode GSM Comments
RIL_NOTIFY_RING RILRINGINFO Structure

 

Incoming call

 

RIL_NOTIFY_CONNECT RILCONNECTINFO Structure

 

Call connected

 

RIL_NOTIFY_DISCONNECT RIL_DISCINIT_*Constant Call disconnected
RIL_NOTIFY_CALLSTATECHANGED NULL Call state of one or more calls may have changed

Supplemental Service Notifications

dwCode GSM Comments
RIL_NOTIFY_CALLERID

 

 

( RILREMOTEPARTYINFO * )

 

 

The remote address of the incoming call

 

 

RIL_NOTIFY_DIALEDID

 

 

( RILREMOTEPARTYINFO * )

 

 

The destination address of the outgoing call

 

 

RIL_NOTIFY_CALLWAITING

 

 

( RILCALLWAITINGINFO * )

 

 

Call waiting notification

 

 

RIL_NOTIFY_SUPSERVICEDATA

 

 

( RILSUPSERVICEDATA * )

 

 

Incoming USSD message

 

 

Supplememtal Service

Function GSM Comments
RIL_SetCallerIDSettings +CLIP CallerID settings
RIL_GetHideIDSettings +CLIR Hides own number from recipient
RIL_SetHideIDStatus +CLIR Hides own number from recipient
RIL_GetDialedIDSettings +COLP Dialed number on an outgoing call
RIL_SetDialedIDSettings +COLP Dialed number on an outgoing call
RIL_GetClosedGroupSettings +CCUG Closed user group settings
RIL_AddCallForwarding +CCFC Add a number to the call forwarding list
RIL_RemoveCallForwarding +CCFC Remove a number from the call forwarding list
RIL_SetCallForwardStatus +CCFC Enable/disable call forwarding
RIL_GetCallWaitingSettings +CCWA Call waiting settings
RIL_SetCallWaitingStatus +CCWA Call waiting settings
RIL_CancelSupServiceDataSession +CUSD Cancel a USSD session
RIL_SendSupServiceData +CUSD Send a USSD message

Diagram

Voice Call Dial

Microsoft Radio Interface Layer - dmg - ICE BOY

 

  1. Application calls the Assisted TAPI API tapiRequestMakeCall. tapiRequestMakeCall( )
  2. TAPI forwards the request to the registered RequestMakeCall handler. RequestMakeCall( )
  3. The Phone Shell informs the Phone UI that a call setup attempt is in progress. The customer will see the standard call setup UI.
  4. The Phone Shell instructs TAPI to place a call by calling lineMakeCall. lineMakeCall( )
  5. TAPI forwards the call to the appropriate TSP. TSPI_lineMakeCall( )
  6.  The TSP will examine its current state, and if appropriate, instruct RIL to place the indicated call. RIL_Dial( )
  7. The RIL implementation will place a voice call by sending the appropriate commands to the GSM module: ATD+{phone number}
  8. The RIL implementation will receive an indication from the module that the call setup has succeeded. RIL would use AT+CPAS or AT+CLCC to get the call status.
  9. Once it determines that the call setup has succeeded, RIL will send a notification to the TSP indicating that the call is in the connected state.
  10. Upon receiving an indication from RIL that the call has been connected, the TSP will notify the Audio Driver to configure the audio routing and levels to connect the audio path to the appropriate audio devices.
  11. The TSP will send a sequence of LINE_CALLSTATE and LINE_LINEDEVSTATE messages to TAPI indicating the progress of the call.
  12. TAPI will forward a similar sequence of LINE_CALLSTATE and LINE_LINEDEVSTATE messages to the Phone Shell.
  13. The Phone Shell will then indicate to the customer that the call has succeeded and begin the call timer. At this point the audio path is connected, the UI has been updated to show that the call is connected, and the call is in progress.
  14. The Phone Shell will broadcast a notification to all currently running applications indicating that the device state has changed, and we are currently in a call.

 

Audio Routing and Volume

Microsoft Radio Interface Layer - dmg - ICE BOY

 

  1. The customer indicates to the UI the desire to switch into Speakerphone mode. The Phone Shell UI sends this notification to the Phone Shell.
  2. The Phone Shell calls TAPI to instruct it to change the active hook switch device. phoneSetHookswitch();
  3. TAPI passes the request along to the TSP: TSPI_phoneSetHookSwitch();
  4. The TSP sends a message to RIL instructing it to change the currently active source.
  5. RIL will then send the proper command to the GSM module, instructing it to select the appropriate audio source. AT+VLS=?? <Manufacturer specific value>
  6. Now that the speakerphone hook switch device has been enabled, the TSP will send a PHONE_STATE message to TAPI, indicating the new state of the hook switch. The TSP will also implicitly change the state of the hook switch for the handset (the previous hook switch device), changing it to ONHOOK. This will generate a second PHONE_STATE message.
  7. TAPI will forward the PHONE_STATE message to all interested open handles.
  8. Deciding that the volume was not loud enough, the customer changes the volume of the speakerphone.
  9. To adjust the volume of the Speakerphone hook switch device, the phone shell will call TAPI. phoneSetVolume();
  10. TAPI forwards the call to the TSP: TSPI_phoneSetVolume();
  11. The TSP calls RIL to set the new volume of the device.
  12. RIL sends the appropriate AT command to the module to set the new volume level.
  13. The hardware device responsible for recognizing the insertion of the headset plug, activates an interrupt which is handled by RIL.
  14. RIL sends a notification message to the TSP informing it of the change in input device. It is assumed that the change in input device has already taken place, either entirely in hardware, or handled by RIL before the notification is sent to the TSP.
  15. The TSP sends a PHONE_STATE notification to TAPI indicating that the state of the HEADSET hook switch has changed.
  16. TAPI forwards the PHONE_STATE message to all interested open handles.
  17. The Phone Shell instructs the UI to indicate the presence of a headset device.

     

     

 

Disconnecting a RIL Voice Call

To hang up a Radio Interface Layer (RIL) voice call or to use remote disconnect, the cellular telephony service provider (TSP) and the RIL driver complete the following steps:

 

  1. The radio detects a remote disconnect and generates a RIL_NOTIFY_DISCONNECT constant with the lpData parameter set to RIL_DISCINIT_REMOTE.
  2. TAPI calls RIL_GetCallList to determine which call state has just changed. The return value should be RIL_RESULT_OK with lpData = NULL. This indicates that there are no calls in the call list. This step may occur multiple times.
  3. The TSP calls RIL_SetAudioDevices to set RIL_AUDIO_NONE as the device for both Tx and Rx audio. The return value should be RIL_RESULT_OK.
  4. Connection Manager obtains the mute state by calling RIL_GetAudioMuting. The return value should be RIL_RESULT_OK - FALSE (not muted).

     

     

 

Data Connection

Microsoft Radio Interface Layer - dmg - ICE BOY

The process of establishing a PPP connection is started with a call to the RasDial API. RasDial causes PPP to initiate a connection through TAPI. GPRS is similar to circuit switch data call and TAPI is used but with additional DevConfig fields. GPRS data call looks like a quickly setup RAS connection.

TAPI will then call the TSP, which will in turn call RIL_Dial to initiate a data call to the specified number.

Once the call is connected, PPP will call lineGetID to get the comm. handle from the TAPI line device. The TSP will call RIL to retrieve this handle. RIL will return a handle to a virtual serial port. The virtual serial port is an integral part of RIL, and acts as the sink for data from the module. PPP will then begin reads and writes on the virtual serial port to establish the PPP connection.

Notice, For GPRS calls, Microsoft relies on the radio stack to automatically GPRS attach whenever the device registers on the network. In the boot time, MMI (AP) would send the initial string to Modem and Modem would proceed a combine attach (GSM and GPRS).

Microsoft code never expects to deactivate a GPRS context using an AT command. Instead, when the PPP server sees a link down from the client, the PPP server should deactivate the GPRS context.

相關的設定

Emergency Call

 Windows Mobile 照下列的順序來讀取 Emergency call 的號碼:

 

  • Read registry key - Path: HKEY_LOCAL_MACHINE/Security Multi_SZ: Ecall and
  • Read registry key - Path: HKEY_LOCAL_MACHINE/Security Multi_SZ: EcallWithSIM - if SIM is present on the device, or
  • Read registry key - Path: HKEY_LOCAL_MACHINE/Security Multi_SZ: EcallWithoutSIM - if SIM is not present on the device, and
  • Constant "112" and
  • EF-ECC records from SIM, if SIM is present.

 

Dialer auto hide after dialing

Windows Mobile 的預設值是一般的電話會自動隱藏,但是 Voice Mail, Emergency call 並不會,如果都要設成自動隱藏,可以做這樣的設定:

[HKEY_LOCAL_MACHINE/Security/Phone/Skin/Dialer/Portrait/Other]

"dialpadFlags"=dword:2

[HKEY_LOCAL_MACHINE/Security/Phone/Skin/Dialer/Landscape/Other]

"dialpadFlags"=dword:2

[HKEY_LOCAL_MACHINE/Security/Phone/Skin/Dialer/Square/Other]

"dialpadFlags"=dword:2

Manual and Preferred Network Selection setting

可以 Disable manual and preferred network selection:

[HKEY_LOCAL_MACHINE/Security/Phone]

"ManualDisable"=dword:1

"PreferredDisable"=dword:1

設定 Call Waiting tone and Busy tone 的方法

[HKEY_CURRENT_USER/ControlPanel/Sounds/BusyTone]

"Sound"="busytone.wav"

[HKEY_CURRENT_USER/ControlPanel/Sounds/CallWaiting]

"Sound"="waiting.wav"

Fixed Dialing Number

從 Phone Setting 中移除微軟內建 FDN 程式的設定:

[HKEY_LOCAL_MACHINE/ControlPanel/FixedDialing]

"DisableMenu"=dword:1

Voice Mail

設定號碼

微軟使用下列的設定紀錄號碼,但是如果使用者沒有設定,只會在開機時讀取 SIM card 的 Mailbox 欄位以決定是否更新。

[HKEY_CURRENT_USER/Software/Microsoft/VMail/PhoneNumber1] -> 通常使用這個

[HKEY_CURRENT_USER/Software/Microsoft/VMail/PhoneNumber2]

另外一個設定是關於 new voice mail indicator display:

[HKEY_CURRENT_USER/Software/Microsoft/VMail/DialMonitored]

當沒有 Voice Mail 號碼的設定時:

[HKEY_LOCAL_MACHINE/Security/ResOver]

"55"="Please configure voicemail"在規範上 2G SIM 與 USIM 是不同的欄位:

2G: 6F17 (28439)

3G: 6FC7(28615)

可以使用 +CRSM 指令來進行讀寫的動作。要注意的是,泛亞 SIM Card 並不支援,所以回傳的值為空字串,微軟仍然會用登錄檔 (Reg) 記錄但是設定時如果改變 Voice Mail 會有警告。

T-Mobile UK Voice Mail

T-Mobile UK 要撥打 222 來取得 Voice Mail 的存取權和設定,而號碼通常是以英國國碼 +44 為開頭的號碼。根據 T-Mobile UK 的要求,使用者應該在尚未取得 Voice Mail 設定以前,先撥 222 來取得資料。在這裡假定在尚未取得資料前,SIM Card 所記錄的資料為空白,我們就可以使用下列的推測性做法。

推測性做法:

 

  • 在 GetCurrentOperatorName 取得 Operator Name 時,如果在 T-Mobile UK 的服務範圍,讀取 reg 中目前的 voice mail 設定,如果 voice mail 的欄位是空白,則使用 +CRSM 寫入 222

 

Common PCN Handset Specification (CPHS)

The Common PCN Handset Specification (CPHS), developed by the PCN Association, defines additional terminal and SIM functionality to the standard GSM specifications.

  1. EF-MBN (Mail Box Number)
  2. EF-VMWF (Voice Message Waiting Flags)
  3. EF-CCF(Call Forwarding Flags)
  4. EF-CSP (Customer Service Profile)
  5. EF-ONS (Operator Name String)
  6. EF-PLMNSel (PLMN Selector)
  7. ALS (Alternate Line Service)
  8. EF-MSISDN

但是,並不是所有的 SIM card 都支援此一標準。

 

微軟內有欄位可以分辨 CPHS SIM or USIM:

[HKEY_LOCAL_MACHINE/Comm/Cellular/SIM]

"UseCPHSFiles"=dword:00 代表不是 CPHS SIM,而 1 代表是,通常 RIL 需要填入資訊到這個 REG 的欄位內。

Customer Service Profiile (CSP)

Further information about CSP and CPHS can be found here.

使用 +CRSM 讀取 CSP (6F15) on GSM/PCS-Sims。

Service Provider Name (SPN)

有一些 SIM 有配置 EF SPN filed ,而讀取 SIM card 建立在 AT+CRSM 上的能力。

當註冊在 Home PLMN 時,要做以下的處理:

 

  1. The SP Name shall be displayed
  2. Display of the PLMN Name is optional (i.e. the Service Provider name shall be displayed either in parallel to the PLMN Name or instead of the PLMN Name).

如果是處於漫遊的情況,處理的方式則是相反。

 

根據 3GPP spc3 22.101 Annex A.4,有規範 Service Provider Name indication 的使用,但是目前並沒有電信系統商的 SIM card 有跟著這部份的規範走。

Enhanced Network Selection (ENS)

Enhanced Network Selection (sometimes referred to as Enhanced Network Service, or simply ENS) extends GSM by making it possible for a GSM cellular device (e.g., handset) to be "homed" OTA (over the air) to different networks.

For ENS to work, both an ENS-capable device and an ENS SIM are needed.

  • Most mobile devices sold by Cingular from the end of 2004 should be ENS-capable.
  • ENS SIMs are marked "64K". (Prior SIMs are no more than 32K. There is no other benefit to the increased memory in the SIM.

 

Enhanced Operator Name String (EONS)

EONS is to define various operator names that are to be displayed for different PLMN identities. It also allows the display of a different operator name based on a subset of the registered network through the use of a range of LACs or a single LAC.

對於 RIL 而言,support EONS 建立在 AT+CRSM 上的能力。當 EONS 可以使用或者是有更新的時候,RIL 會 broadcast 一個 RIL_NOTIFY_EONS 訊息給上層的 AP 知道這個訊息, AP 可以使用 RIL_GetCurrentOperator() 來取得 operator name。

EONS 相關的設定是

[HKEY_LOCAL_MACHINE/Comm/Cellular/RIL]如果 EONSEnabled (REG_DWORD) 設為 1 ,表示有支援 EONS,如果設為 0 表示沒有支援。

推測性做法:

在 RIL client 取得 registration status 的時候,如果有發生 location update,就可以 broadcast 一個 RIL_NOTIFY_EONS 訊息給上層的 AP 知道這個訊息,而上層就可以使用 RIL_GetCurrentOperator() 來取得 operator name。

微軟有提供 sample code,但是無法確定實作是否完整。

GPRS/EDGE and DTM

只有系統商的 GRPS/EDGE radio system 支援 DTM,才能夠同時使用 voice/data。一般而言,為了方便區分我們通常會認為不支援。

要設定是否支援 Multiple GPRS contexts,設定如下:

[HKEY_LOCAL_MACHINE/Comm/Cellular/RIL]

"Contexts"=dword:1

Disconnect Button for GPRS in connection bubble

[HKEY_LOCAL_MACHINE/ControlPanel/Phone]

"Flags2"=dword:8值得注意的是,這也會讓使用者可以按 END Key 中斷 data connection,所以實務上很少使用

SMS and GPRS

Short messages could save in three storage space, TE, ME and SIM. In the feature phone, short messages usually store in the SIM, ME or both storage. However, Microsoft SmartPhone store short messages in TE.

A short message management is used for sending and receiving of short messages, status messages and getting cell broadcast. Microsoft already creates a message library to handle short message.

Microsoft Radio Interface Layer - dmg - ICE BOY

The SMS Provider that accepts the incoming message performs the following steps to process the message:

 

  1. Interprets the SMS message header
  2. Delivers the message to the subscribing application
  3. Removes the message from the SMS Store

     

     

 

If the incoming message is a multipart message, the corresponding SMS Provider begins reassembling the message when the last part of the multipart message arrives in the SMS Store. The corresponding SMS Provider uses the SMS Router Toolkit to reassemble the message.

The SMS Router uses SMS Providers to deliver, encode, decode, and receive SMS messages. SMS Providers correspond to SMS message types that are sent or received. An application can be registered to an SMS Provider, so that when an incoming SMS message matches the provider that it is registered with, the application can be invoked. Only one application can be registered to read messages from each provider. However, multiple applications can send SMS messages through a single SMS Provider.

The SMS Router has an SMS Store as a generic buffer or backup to keep copies of SMS messages that have been received. It stores SMS messages while they are being processed by the SMS Providers. The SMS Store can also be used in the event of an application failure or device shutdown. SMS messages are deleted from just the SMS Store only after an application has finished reading it.

Radio Interface Layer defines Message DCS Classes to use:

#define RIL_DCSMSGCLASS_0      (0x00000001)

#define RIL_DCSMSGCLASS_1      (0x00000002)

#define RIL_DCSMSGCLASS_2      (0x00000003)

#define RIL_DCSMSGCLASS_3      (0x00000004)In the spec, short message could have several classes, class 0 (display not auto saves), class1 (ME), class 2 (SIM), class 3 (TE) or no class. However, Mobile station still could design how to save the short message.

Microsoft Radio Interface Layer - dmg - ICE BOY

Microsoft Phone could choose using CSD or GPRS sending short message,depends on what AT Command you send to Modem.

#define RIL_MOSMSSERVICE_CIRCUIT        (0x00000001)

#define RIL_MOSMSSERVICE_GPRS           (0x00000002)

#define RIL_MOSMSSERVICE_CIRCUITPREFERRED  (0x00000004)

#define RIL_MOSMSSERVICE_GPRSPREFERRED     (0x00000008)

#define RIL_MOSMSSERVICE_ALL               (0x0000000f)Microsoft defines 5 const to record the parameter which users want to use CSD or GPRS to send SMS. RIL have two functions to do this thing, which is RIL_GetMOSMSService() and RIL_SetMOSMSService().

EMS (Enhanced Messaging Service)

Microsoft Radio Interface Layer - dmg - ICE BOY

Enhanced Messaging Service is based on standard mechanisms in GSM SMS messaging.

The first mechanism is called Transfer Protocol User Data Header (TP-UDH), which makes it possible to include binary data in a normal Short Message (SM) prior to the text message itself. The binary data is in the TP-UD field (message), which means that it consumes a part of the 140 bytes.

If PDA Phone or SmartPhone want to support to support EMS (Enhanced Messaging Service), the first condition is to support long short message. A part of the EMS standard is the support for concatenated messages, which means that the phone is able to automatically combine several messages both when creating and receiving EMS. The SMS standard allows up to 255 messages at 140 bytes each to be concatenated to one message up to about 38k bytes.

Microsoft Radio Interface Layer - dmg - ICE BOY

If Modem support long short message, the net step is MMI could identify enhanced message and receive/send correctly.

設定 EMS 的支援,可以設定如下:

[HKEY_CURRENT_USER/Software/Microsoft/SMS/TextShared]

"EMSHandlerInstalled"=dword:1

Cell Broadcast

RIL  必須要分析 +CBM 的回應值,並且正確的傳到 RIL Clients(總共長度為 88 octets):

88 octets | 1-2 serial number | 3-4 message ID | data coding scheme | page num | 7-88 content payload |

SMS/MMS Disable

The security policies are defined in secpol.h in <Adaptation Kit installation directory>/Public/OSSVCS/SDK/Inc and the security roles are defined in cfgmgr.h in <Adaptation Kit installation directory>/Public/OSSVCS/OAK/Inc.

MS 在 6.1 新增了一個設定,可以 disable 微軟預設的 SMS 程式。

[HKEY_LOCAL_MACHINE/Security/Policies/Policies]

"1033"=dword:0

相關資訊:微軟 LTK 有 SMS/MMS Disable 相關的測項,但是因為微軟測項本身的判斷仍然有問題,目前可以用 OEM Verify 來過這個測項。

SIM and STK

Microsoft Radio Interface Layer - dmg - ICE BOY

Microsoft provides a SIM Manager to handle the SIM function. SIM Manager use  SIMCALLBACK function when sending notifications.

SimGetPhonebookStatus function gets the status of a phonebook location. SimDeletePhonebookEntry deletes a phone book entry from the SIM card. SimReadPhonebookEntry and SimWritePhonebookEntry is used to read and write a phone book entry to the SIM card.

SimGetSmsStorageStatus function gets the status of an Short Message Service (SMS) storage location. SimReadMessage and SimWriteMessage is used to read and write SIM short message record. SimDeleteMessage is used to delete SIM short message records.

Microsoft use “SIM Lock” to indicate the PIN1 locked after three failed unlock attempts in the PIN1 unlock request. “SIM Lock” programmatically locks the SIM card after more than three failed unlock attempts. To prevent Denial of Service attacks or brute-force attacks against the SIM lock, unprivileged applications are prevented from accessing the SIM APIs. In addition, rogue applications cannot destroy the SIM by exceeding the maximum number of failed logon attempts.

The other meaning of SIM lock (choose an operator) is operator use SIM lock to lock the phone could only use the SIM card and could not switch to others.

SIM Application Toolkit

Terminal profile

SIM Application Toolkit need to verify the Terminal profile. MMI should keep a list which is the profile which would send to Modem and download to SIM.

Microsoft Radio Interface Layer - dmg - ICE BOY

Communication between RIL and SIM ToolKit

 

  •  

    CSimToolkit

     

  •  

    —CSimPolicy: ISimToolkitPolicy

     

  •  

    CSimUI: ISimToolkitUI, ISimToolkitUIv2

     

Microsoft Radio Interface Layer - dmg - ICE BOY

 

RIL communication to the SIM toolkit layer is mainly through the RIL_NOTIFY_SIMTOOLKITCMD event.

typedef struct rilsimtoolkitcmd_tag

{

DWORD cbSize; // Structure and details size

DWORD dwParams; // Bit field of valid parameters in the structure

DWORD dwId; // ID number of command

DWORD dwTag; // Command tag (with comprehension bit)

DWORD dwType; // Type of command (DISPLAY TEXT, etc.)

DWORD dwQualifier; // Command details qualifier

DWORD dwError; // Error when parsing command

DWORD dwDetailsOffset; // Offset to details command information

DWORD dwDetailsSize;

} RILSIMTOOLKITCMD;The RILSIMTOOLKITCMD encompasses the basic SIM Toolkit information common to most commands. More specific details for the command type are contained at the details offset. Each supported command type will have a specific details structure that is needs to be created and attached in the RIL_NOTIFY_SIMTOOLKITCMD notification.

SIM Contacts

When a SIM is removed from a Windows Mobile powered device, the SIM contacts still display in the Contacts list after the device reboots with no SIM. The SIM contacts remain in the pim.vol contacts database until the Windows Mobile powered device is powered up with a different SIM. This is a potential privacy issue for the user. When a user reboots the device with a new SIM, sync occurs and the device updates the old SIM's contacts database with the new SIM's contact list.

[HKEY_LOCAL_MACHINE/Software/Microsoft/SIMLang]

"PurgeSimContactsWhenNoSim"=dword:0001如果不顯示 SIM Contacts,可以用下列的設定:

[HKEY_CURRENT_USER/ControlPanel/Phone/ShowSIM]

Data Dormant

Windows Mobile powered devices enabled with 1x Evolution-Data Optimized (EVDO) wireless radio broadband should consider the overhead

cost when the Windows Mobile powered device switches between the active and dormant states.

If the Radio Interface Layer (RIL) aggressively enters the dormant state, for example, between each TCP packet, the device consumes more power and network resources. If the RIL waits too long to enter the dormant state, the device consumes power while it remains in the idle state.

For mobile operators that use Code-Division Multiple Access (CDMA) technologies, you can configure the radio and the RIL to determine when to enter the idle state through Microsoft Corporation technology. These mobile operators have specified that the tradeoff should be to go dormant when the radio has not seen data traffic for 10 to 20 seconds.

簡單的說,就是 Modem 的 RRC states 從 CELL_FASH 進入 CELL_PCH 狀態的時間提前,因此可以省下這一段時間的電能消耗。一般而言,這項特性要配合 Modem Fast Dormancy 的實作來使用。

Set Radio off

除了 AT Command +CFUN 之外,還要做下列的設定:

[HKEY_LOCAL_MACHINE/Software/Microsoft/RIL/LastEquipmentState]

Replacing Resover Strings

取代微軟的預設字串:

[HKEY_LOCAL_MACHINE/Security/ResOver]

"10" = "SIM Failure"下面是多國語言的寫法:

[HKEY_LOCAL_MACHINE/Security/ResOver/0409]

"10" = "SIM Failure"

撰寫 RIL 相關的程式

下面是載入 ril dll 與使用函式指標指向相關函式的範例程式:

g_hlibRIL = LoadLibrary(_T("ril.dll"));

if(g_hlibRIL)

{

(FARPROC&)lpRIL_Initialize = GetProcAddress( g_hlibRIL, _T("RIL_Initialize"));

if( lpRIL_Initialize==NULL )

{

goto Error;

}

(FARPROC&)lpRIL_Deinitialize = GetProcAddress(g_hlibRIL, _T("RIL_Deinitialize"));

if( lpRIL_Deinitialize==NULL )

{

goto Error;

}

}在呼叫一個 RIL 函式之後,我們需要將回傳值儲存為一個全域變數,並且使用這個全域變數作為比對 command ID 之用。

Dial Parser

微軟在 dpext.h 定義了幾個函式可以讓我們做一些 Dial Parser 的事情。

設定:

[HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/DialParser/]

"DLL-OEM"="DialParsExtOEM.dll"在微軟釋出的 sample 中,有關於如何撰寫 Dial Parser 的程式。

Lanuch program in start up

在 platform.reg 中,設定

[HKEY_LOCAL_MACHINE/Init]或者是在 platform.dat 中設定,例如下面 VoiceCommander 的例子:

{BEGIN MULTILANG}

Directory(LOC_%LANGID%_DIRWINSTMNPROG):-File("Voice Commander.lnk", "/Windows/VoiceCommander.lnk")

Directory(LOC_%LANGID%_DIRWINDOWSSTARTUP):-File("VCDaemon.lnk", "/Windows/VCDaemon.lnk")

Directory(LOC_%LANGID%_DIRWINDOWSHELP):-File("Voice Commander.lnk", "/Windows/VC.lnk")

{END MULTILANG}在設定時最好不要寫死,否則會在發行多國語言版本時,會有問題。

判斷 API 是否可用

使用 IsAPIReady(),例如當使用 FindWindow() 等 GUI 相關的函式時,要判斷

if(IsAPIReady(SH_SHELL))

{

//Do something

}

印出呼叫的應用程式

HANDLE processID = GetOwnerProcess();

TCHAR processName[1024];

GetModuleFileName( (HMODULE)processID, processName, 1024);

RETAILMSG(1,(TEXT("Process Name=[%s]/r/n"), processName));

Kill a process

下面是示範殺掉 cprog.exe 的函式:

void killAllCPROG()

{

TCHAR *ptchPhonePath = new TCHAR[MAX_PATH];

ZeroMemory(ptchPhonePath,sizeof(TCHAR)*MAX_PATH);

PROCESSENTRY32 pe32 = {0};

pe32.dwSize = sizeof(PROCESSENTRY32);

HANDLE hProcessShot = NULL;

TCHAR PhoneProName[] = TEXT("cprog.exe");

DWORD cprogID = 0;

HANDLE hcprogID = NULL;

hProcessShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

BOOL running = Process32First(hProcessShot, &pe32);

//Find cprog.exe and terminate it

while(running)

{

swprintf(ptchPhonePath,TEXT("%s"),pe32.szExeFile);

if (!wcscmp(ptchPhonePath, PhoneProName))

{

cprogID = pe32.th32ProcessID;

hcprogID = OpenProcess(0,false,cprogID);

TerminateProcess(hcprogID,0);

CloseHandle(hcprogID);

}

running = Process32Next(hProcessShot, &pe32);

}

delete[] ptchPhonePath;

ptchPhonePath = NULL;

CloseToolhelp32Snapshot(hProcessShot);

}

Call PIN1 code input screen

使用定義在 simsec.h 中的函式。

typedef HRESULT (*SIMFUN)(HWND hwndParent, DWORD dwStyle);

HMODULE h = LoadLibrary(TEXT("simsec.dll"));

SIMFUN SIMCheck = (SIMFUN)GetProcAddress(h, TEXT("SIMSecurityUnlockPhone"));

SIMCheck(NULL, SIMSEC_STYLE_EMERGENCY_CALL | SIMSEC_STYLE_AUTO_CLOSE | SIMSEC_STYLE_SHOW_ACCEPT);在解 dual SIM 的時候會用到,因為需要 RIL launch PIN1 code input screen。

Disable SIP auto–deployed

v_hevtKeyPressed = CreateEvent(NULL, FALSE, FALSE, TEXT("_KeyPress"));

SetEvent(v_hevtKeyPressed);

Popup a message to user

可以使用 SH_BOXEX 來彈出訊息給使用者,未使用的要填為零,下面是他的定義:

typedef struct _SH_BOXEX

{

DWORD cbSize; // Struct size

HWND hwndOwner; // Owner

DWORD dwStyle; // SHBEXF_* styles

UINT nTimeOut; // Timeout in ms if style includes SHBEXF_TIMED.

LPCTSTR pszTitle; // Title.

int nZOrderPri; // Z Order Priority

HINSTANCE hinst;

LPCTSTR pszTemplate;

LPCTSTR pszBannerKey;

int idrMenu;

SHB_HOOK_PROC pfnHook;

LPVOID pvUser;

LPARAM lReserved; // Reserved. Must be 0.

int nIDSelected;

HWND hwnd;

SHBEX_TYPE sbextype;

union

{

SHBEX_TEXTBOX_INFO ti; // Text box with one or two buttons

SHBEX_CLASSIC_MSGBOX_INFO cmi; // Classic Message Box info

SHBEX_CALL_ALERT_INFO cai; // Call Alert info

SHBEX_BUBBLE_INFO bi;

} info;

} SH_BOXEX, *PSH_BOXEX;SHBEX_BUBBLE_INFO 的資料:

typedef struct _SHBEX_BUBBLE_INFO

{

SHBEX_BUTTON_INFO bi; // Button info.

int iXPos; // position of the cartoon bubble

int iYPos;

int cxPos; // -1 for auto-calc

int cyPos; // -1 for auto-calc

POINT pt; // the place the bubble should stem from

DWORD dwOriginatingIcon; // Icon the bubble stems from. If specified, this info is used

// instead of pt.

DWORD dwAlign; // one of SHBOXALIGN

DWORD dwFlags; // SHBBIF_*

LPCTSTR pszContent;

HWND hwndContainer; // out: the container hwnd

COLORREF clrLeft; // For gradient fill when you have a title

COLORREF clrRight; // For gradient fill when you have a title

} SHBEX_BUBBLE_INFO;運作這個機制,就可以秀出一個 popup window 給使用者。

另外,也可以使用 Shell Notification 的方式來實作。下面是來自於微軟文件的示範:

static const GUID CLSID_SHNAPI_Test = {0x33765136, 0x8cb9, 0x449a, {0xb0, 0x20, 0x43, 0xed, 0x40, 0xa, 0xb8, 0xfc }};

void SHNotificationExample()

{

// This code will add an SHNotification notification

SHNOTIFICATIONDATA sn = {0};

SHNOTIFICATIONDATA sn2 = {0};

sn.cbStruct = sizeof(sn);

sn.dwID = 1;

sn.npPriority = SHNP_INFORM;

sn.csDuration = 15;

sn.hicon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_SAMPLEICON));

sn.clsid = CLSID_SHNAPI_Test;

sn.grfFlags = 0;

sn.pszTitle = TEXT("Sample Notification");

sn.pszHTML = TEXT("<html><body>This is <b>sample html</b> in a notification!</body></html>");

sn.rgskn[0].pszTitle = TEXT("Dismiss");

sn.rgskn[0].skc.wpCmd = 100;

//Add the notification to the tray

SHNotificationAdd(&sn);

//Put the data from an existing notification into a second SHNOTIFICATIONDATA struct

sn2.cbStruct = sizeof(sn2);

//Update the title, HTML, icon, and softkeys of the notification

sn2.pszTitle = TEXT("Updated - Sample Notification");

sn2.pszHTML = TEXT("<html><body>This notification has been <b>updated!</b></body></html>");

sn2.hicon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_SAMPLEICON2));

sn2.rgskn[0].pszTitle = TEXT("Disabled");

sn2.rgskn[0].skc.wpCmd = 100;

sn2.rgskn[0].skc.grfFlags = NOTIF_SOFTKEY_FLAGS_DISABLED;

//Remove the notification from the tray

SHNotificationRemove(&CLSID_SHNAPI_Test, 1);

//Add a new notification that utilizes the MRE functionality

sn.cbStruct = sizeof(sn);

sn.dwID = 1;

sn.npPriority = SHNP_INFORM;

sn.csDuration = 15;

sn.hicon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_SAMPLEICON));

sn.clsid = CLSID_SHNAPI_Test;

sn.grfFlags = SHNF_STRAIGHTTOTRAY;

sn.pszTodaySK = TEXT("New Task");

sn.pszTodayExec = TEXT("//windows//tasks.exe");

//Add the notification to the tray

SHNotificationAdd(&sn);

//Remove the notification from the tray

SHNotificationRemove(&CLSID_SHNAPI_Test, 1);

}

Push Mail

微軟 direct push mail 技術其實就是將用 exchange 搭建的服務器中的更新內容通知掌上設備,然後掌上設備自行進行同步,從而把郵件同步到手機。因為使用 direct 方式,所以,郵件透過服務器立刻就被推送到手機。

Microsoft Radio Interface Layer - dmg - ICE BOY

 

  1. 在使用者的手機透過無線區域網路或 GPRS 甚至於是 3G 連線到網際網路之後,此裝置便會經由 HTTPS 的加密連線與 Exchange Server 保持在連線狀態。
  2. 針對使用者個人信箱中的各項資料的改變,Exchange Server 將會與遠端連線的裝置維持在開啟的狀態下。
  3. 依照使用者行動裝置上的 ActiveSync 同步排程的設定,Exchange Server 將會把最新一次的更新資訊主動傳送到使用者的行動裝置中。
  4. 最後使用者行動裝置上的 Outlook,將接收到來自 Exchange Server 所發送的個人信箱最新訊息更新與通知,這一項更新類別包含了電子郵件、行事曆、聯絡人以及工作清單。

有關於 Push Mail 中的通知機制,基本上當使用者的手機在這一個時間點之內,所獲得最新郵件通知只有一封新郵件時,則系統將會呈現寄件者的名稱與郵件主旨,如果是發現同時擁有多封的新郵件,則系統只會告知您目前尚未讀取的郵件有幾封。

 

參考資料

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值