SIM Programming with the .NET Compact Framework

 

Andreas Sjöström
Businessanyplace.net

May 2003

Applies to:
    Microsoft® .NET Compact Framework
    Microsoft Windows® Powered Pocket PC Phone

Summary: Learn how to use the SIM Manager API, the Interop Services of the Compact Framework and the .NET development environment to create a connected application for the Pocket PC Phone. (6 printed pages)

Download sim_programming.exe

Contents

SIM Cards
SIM Manager API
Calling Windows API Using Compact Framework
SIM Anyplace Sample
Code Walkthrough
Conclusion

SIM Cards

The Pocket PC Phone's built-in phone capabilities make it a premier citizen of the world of mobile phones, and you can take advantage of this when creating new connected applications. Like all mobile phones, it needs a Subscriber Identity Module, or SIM card, to make calls—except emergency calls, which can be made without one. As an example, a connected application could take advantage of the security capabilities of SIM cards by checking a user's Personal Identification Number code (PIN) before initiating a connection.

The SIM card holds the phone number of the mobile phone and identity of the operator who provided it. In addition, it stores phone numbers with names attached to them and as well as a number of Short Message Service messages. The SIM card holds not only memory but also a Central Processing Unit that enables the card to handle security and encryption. You usually need to "log on" to your SIM card using your PIN code.

SIM Manager API

On the Pocket PC Phone you can access the information on the SIM card using a number of Windows CE API calls with the collective name SIM Manager. Following are the SIM Manager APIs (grouped by functionality):

Table 1. SIM Manager APIs

The session starts with a call to SimInitialize that returns a SIM handle that is needed in all subsequent calls to the SIM Manager API functions. The session is terminated by passing this handle to SimDeinitialize.

Calling Windows API Using Compact Framework

With the SDE (Smart Device Extensions) and Compact Framework we can make Microsoft® Windows® API calls, such as accessing the SIM Manager API using the Interop(erability) Services.

SIM Anyplace Sample

This is a sample application for the Pocket PC Phone created with Microsoft Visual Studio® .NET, C#, SDE and .NET CF. It shows how to access the SIM card using the SIM Manager API. The application consists of one form:

The use of this sample is just to get some general information from the SIM card by tapping the Get SIM Information button, but by using the structure of the sample it can be extended to include more of the SIM Manager API functionality.

Code Walkthrough

To use the Interop Services in the Compact Framework, the following code was added:

using System.Runtime.InteropServices;

A class (SIMWrap) was created to hold the prototypes for the Windows APIs, and the ones needed in the sample are:

[DllImport("cellcore.dll")]
public static extern int SimInitialize(uint dwFlags,
  int lpfnCallBack, uint dwParam, ref int lphSim);

 [DllImport("cellcore.dll")]
public static extern int SimGetPhonebookStatus(int hSim,
  uint dwLocation, ref uint lpdwUsed, ref uint lpdwTotal);

[DllImport("cellcore.dll")]
public static extern int SimGetDevCaps(int hSim,
  uint dwCapsType, ref SimCaps lpSimCaps);

[DllImport("cellcore.dll")]
public static extern int SimGetSmsStorageStatus(int hSim,
  uint dwStorage, ref uint lpdwUsed, ref uint lpdwTotal );

[DllImport("cellcore.dll")]
public static extern int SimDeinitialize(int hSim);

Each prototype has a DllImport attribute pointing to the DLL (Dynamic Link Library) where the function is implemented (in this case the cellcore.dll). When creating these prototypes, the Visual Studio .NET help file has a nice table with type mappings (in the index, look for "platform invoke" and "data types"). For example, the native type "DWORD" maps to the managed type "UInt32" that is a "unit" in C#.

The call to get the capabilities of the SIM card (SimGetDevCaps) includes a structure passed by reference (lpSimCaps) as the last parameter. The native (C++) structure looks like this:

typedef struct simcaps_tag {
  DWORD  cbSize;
  DWORD  dwParams;
  DWORD  dwPBStorages;
  DWORD  dwMinPBIndex;
  DWORD  dwMaxPBIndex;
  DWORD  dwMaxPBEAddressLength;
  DWORD  dwMaxPBETextLength;
  DWORD  dwLockFacilities;
  DWORD  dwReadMsgStorages;
  DWORD  dwWriteMsgStorages;
  DWORD  dwNumLockingPwdLengths;
  SIMLOCKINGPWDLENGTH  rgLockingPwdLengths[SIM_NUMLOCKFACILITIES];
} SIMCAPS, FAR *LPSIMCAPS;

And as SIM_NUMLOCKFACILITIES equals 10, the Compact Framework version of the same structure looks like this:

[StructLayout(LayoutKind.Sequential)]
public struct SimCaps 
{
  public uint cbSize;
  public uint dwParams;
  public uint dwPBStorages;
  public uint dwMinPBIndex;
  public uint dwMaxPBIndex;
  public uint dwMaxPBEAddressLength;
  public uint dwMaxPBETextLength;
  public uint dwLockFacilities;
  public uint dwReadMsgStorages;
  public uint dwWriteMsgStorages;
  public uint dwNumLockingPwdLengths;
  public SimLockingPwdLength rgLockingPwdLengths0;
  public SimLockingPwdLength rgLockingPwdLengths1;
  public SimLockingPwdLength rgLockingPwdLengths2;
  public SimLockingPwdLength rgLockingPwdLengths3;
  public SimLockingPwdLength rgLockingPwdLengths4;
  public SimLockingPwdLength rgLockingPwdLengths5;
  public SimLockingPwdLength rgLockingPwdLengths6;
  public SimLockingPwdLength rgLockingPwdLengths7;
  public SimLockingPwdLength rgLockingPwdLengths8;
  public SimLockingPwdLength rgLockingPwdLengths9;
}

Note that even if the MarchalAsAttribute class is not supported in the Compact Framework (beta 1), the same structure almost can be accomplished by adding the array as members with an additional suffix (0-9). Actually, those members are another structure (SimLockingPwdLength).

When the declarations are in place, the code behind the Get SIM Information button looks like this:

SimWrap.SimCaps simCaps = new SimWrap.SimCaps();
int hSim = 0;
uint phoneUsed = 0;
uint phoneTotal = 0;
uint smsUsed = 0;
uint smsTotal = 0;

// Empty ListView
lvwItems.Items.Clear();

// Start SIM Manager session (get handle)
SimWrap.SimInitialize(0, 0, 0, ref hSim);

// Get Phonebook status (used, total)
SimWrap.SimGetPhonebookStatus(hSim, SimWrap.SIM_PBSTORAGE_SIM,
  ref phoneUsed, ref phoneTotal);
AddToListView("Total phonebook size:", phoneTotal.ToString());
AddToListView("Phonebook entries:", phoneUsed.ToString());

// Get SIM capabilities
SimWrap.SimGetDevCaps(hSim, SimWrap.SIM_CAPSTYPE_ALL, ref simCaps);
AddToListView("Max. length of name:",
  simCaps.dwMaxPBETextLength.ToString());
AddToListView("Max. length of phone number:",
  simCaps.dwMaxPBEAddressLength.ToString());

// Get Messages (SMS) status (used, total)
SimWrap.SimGetSmsStorageStatus(hSim, SimWrap.SIM_SMSSTORAGE_SIM,
  ref smsUsed, ref smsTotal);
AddToListView("SMS message storage capacity:", smsTotal.ToString());
AddToListView("SMS messages:", smsUsed.ToString());

// End SIM Manager session
SimWrap.SimDeinitialize(hSim);

After the ListView is empty and the SIM Manager handle (hSim) is retrieved (SimInitialize), each of the static methods on the SIM Wrapper class (SimWrap) is called resulting in an API call. The variables passed by reference get the return values and are added to the ListView using the code:

private void AddToListView(string Item, string Value)
{
  ListViewItem lvi = new ListViewItem(Item);
  lvi.SubItems.Add(Value);
  lvwItems.Items.Add(lvi);
}

Finally, the SIM Manager handle (hSim) is released with the call to SimDeinitialize.

Conclusion

As the Pocket PC Phone is a premier citizen of the world of mobile phones, we can take advantage of its capabilities, like SIM cards, when we create great, connected applications. With the SIM Manager API, the Interop Services of the Compact Framework, and the .NET development environment, we have the tools to get going.