Thursday 3 April 2008

Making Powerful and Power Saving Windows Mobile and Pocket PC applications

POWER CONSCIOUS APPS

coming soon.....

Difference Between CE5.0 6.0 and 7.0

what are the major difference between Windows mobile 5.0 / 6.0 and 7.0 ??

Windows Mobile 5.0 Windows mobile 6.0 Windows mobile 7.0

coming soon.....

Minimizing the Delay of the Battery Level Indicator

Minimizing the Delay of the Battery Level Indicator on a Windows Mobile Powered Device esp for smartphone.

The BatteryEarly and BatteryLate values under the HKEY_LOCAL_MACHINE\Software\Microsoft\ssupdate registry key control polling of the battery. Place the code to set or clear the BatteryEarly and BatteryLate values code in the Platform.reg file. Turn off battery polling by clearing both the BatteryEarly and BatteryLate values.
The following code example shows how to turn off battery polling.
Copy Code
[HKEY_LOCAL_MACHINE\Software\Microsoft\ssupdate]
"BatteryEarly"=dword:0
"BatteryLate"=dword:0
After specifying the BatteryEarly and BatteryLate values, you must force the shell to update.

hevent = CreateEvent(NULL, FALSE, FALSE, TEXT("SSUpdatePower"));
SetEvent(hevent);
CloseHandle(hevent);


or you can use BatteryPDDGetStatus in the battery driver this can be called once you call GetSystemPowerStatusEx2
for example:
GetSystemPowerStatusEx2 ( &sysPowerStatus, sizeof( sysPowerStatus ), TRUE );//this will call BatteryPDDGetStatus

handle the battery indication stuff in the BatteryPDDGetStatus and after that you must refresh MDD power level cache this you can do by calling:
PowerPolicyNotify ( PPN_POWERCHANGE, 0 );//update cache so that icon is displayed without delay

To be Continued ........will write more in detail later

Tuesday 8 January 2008

Windows CE 5.0 device driver development-Part 2

How ca we build a driver for Device manufacturer specific functionalities and use it from an apps without using device IOCTLs:



1. lets make a folder DeviceFunc

2. make a new file DeviceFunc.cpp in the above folder

lets edit this as this will be our main device driver source file.



#include



#ifdef __cplusplusextern "C"

{

#endif



void GreenLEDControl(BOOL OnOff )

{

RETAILMSG (1, (TEXT(" Green LED is currently=%d\r\n"), OnOff ));

}

void

(BOOL OnOff )

{

RETAILMSG (1, (TEXT(" RED LED is currently=%d\r\n"), OnOff ));

}

void BacklightControl(BOOL OnOff )

{

RETAILMSG (1, (TEXT(" Backlight is currently =%d\r\n"), OnOff ));

}

void WirelessControl(BOOL OnOff )

{

RETAILMSG (1, (TEXT(" Wireless is currently=%d\r\n"), OnOff ));

}

void DisplayControl(BOOL OnOff )

{

RETAILMSG (1, (TEXT(" Display is currently=%d\r\n"), OnOff ));

}

#ifdef __cplusplus

}

#endif



BOOL WINAPI DllEntry( HANDLE hinstDLL, DWORD Op, LPVOID lpvReserved )

{

return TRUE;
}



now we have the code lets make a def file which will export these functions:



LIBRARY DeviceFunc
EXPORTS

GreenLEDControl

RedLEDControl

BacklightControl

WirelessControl

DisplayControl



and now lets make a sources file:



TARGETNAME=DeviceFunc



RELEASETYPE=PLATFORM



TARGETTYPE=DYNLINK


TARGETLIBS= \$(_COMMONSDKROOT\lib\$(_CPUINDPATH\coredll.lib \

$(_COMMONOAKROOT)\lib\$(_CPUINDPATH)\ceddk.lib


DEFFILE=DeviceFunc.def


DLLENTRY=DllEntry


SOURCES= DeviceFunc.cpp





now we have made copy a makefile from a standard wince driver directory and compile the folder.

you will get a DeviceFunc.dll file.



Now to the next step, how can we access these exported functions on our device by other drivers\applications:



Lets first take an app implementation:

typedef void (*PFN_BacklightControl)(BOOL fOn);

HINSTANCE gDeviceFuncDll = NULL;

gDeviceFuncDll =LoadLibrary(TEXT("DeviceFunc.dll"));

pfnBrightnessUp = (PFN_BacklightControl)GetProcAddress(gDeviceFuncDll , TEXT("BacklightControl"));

Windows CE 5.0 device driver development-Part 1-Basics

A driver is simply a DLL (dynamic link library), DLL’s are loaded into a parent process address space, the parent process can then call any of the interfaces exposed from the DLL – the driver is typically loaded by it’s parent process through a call to LoadLibrary( ); or LoadDriver( ); - LoadDriver not only loads the DLL into the parent process address space but will also make sure the DLL isn’t paged out.



On Windows CE, stream drivers are opened just like files, and are opened using a unique three letter prefix (e.g. BKL,COM,TST,PWR).


The core stream interface entry points are:

XXX_Open (Device Manager)

XXX_Close (Device Manager)

XXX_Read (Device Manager)

XXX_Write (Device Manager)




1. Choose a unique three letter identifier for your driver. lets choose it as TST.

2. name the driver - here we will name it as TestDriver

3. Next, you will need to implement the required entry points.

lets see required functions for a complete stream driver:


//TestDriver.c by Umesh Jagga
#include


//This function initializes a device. It is called by Device Manager.
//This function is required by drivers loaded by ActivateDeviceEx, ActivateDevice, or

//RegisterDevice.
DWORD TST_Init(LPCTSTR pContext, LPCVOID lpvBusContext);


//This function de-initializes a device. It is called by Device Manager
BOOL TST_Deinit( DWORD hDeviceContext );


//This function opens a device for reading, writing, or both. An application indirectly invokes

//this function when it calls the CreateFile function to open special device file names.
DWORD TST_Open( DWORD hDeviceContext, DWORD AccessCode, DWORD ShareMode );

//This function closes a device context created by the hOpenContext parameter.

//An application calls the CloseHandle function to stop using a stream interface driver. The hFile

//parameter specifies the handle associated with the device context. In response to

//CloseHandle, the operating system invokes XXX_Close.

BOOL TST_Close( DWORD hOpenContext );

//This function sends a command to a device.

//An application uses the DeviceIoControl function to specify an operation to perform. The

//operating system, in turn, invokes the XXX_IOControl function

BOOL TST_IOControl( DWORD hOpenContext, DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut );void USB_PowerUp( DWORD hDeviceContext );



void TST_PowerDown( DWORD hDeviceContext );


//This function reads data from the device identified by the open context

//an application calls the ReadFile function to read from the device, the operating system

//invokes this function.


DWORD TST_Read( DWORD hOpenContext, LPVOID pBuffer, DWORD Count );

//This function writes data to the device.

//After an application uses the WriteFile function to write to the device, the operating system,

//invokes this function.

DWORD TST_Write( DWORD hOpenContext, LPCVOID pBuffer, DWORD Count );

//This function moves the data pointer in the device.

//After an application calls the SetFilePointer function to move the data pointer in the device,

//the operating system invokes this function.
//If your device is capable of opening more than once, this function modifies only the data

//pointer for the instance specified by hOpenContext.
DWORD TST_Seek( DWORD hOpenContext, long Amount, WORD Type );



//If the function is used, it is called by the system when processes and threads are initialized

//and terminated, or on calls to the LoadLibrary and FreeLibrary functions.

//Direct entry point for a DLL.

//If you use the C Runtime in your application, it is responsible for performing any initialization

//of the C Runtime at process attach, and for deinitializing the C Runtime at process detach

// ----------------------------------------------------
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID pReserved )

{

switch(ul_reason_for_call)

{

case DLL_PROCESS_ATTACH:

OutputDebugString(L"TestDriver - DLL_PROCESS_ATTACH\n");

break;

case DLL_PROCESS_DETACH:

OutputDebugString(L"TestDriver - DLL_PROCESS_DETACH\n");

break;

case DLL_THREAD_ATTACH:

OutputDebugString(L"TestDriver - DLL_THREAD_ATTACH\n");

break;

case DLL_THREAD_DETACH:

OutputDebugString(L"TestDriver - DLL_THREAD_DETACH\n");

break;

default:

break;

}

return TRUE;

}

// Driver Init...

DWORD TST_Init( LPCTSTR pContext, LPCVOID lpvBusContext)

{

OutputDebugString(L"TestDriver - TST_Init - Context: ");

OutputDebugString(pContext);

OutputDebugString(L"TestDriver - ~ TST_Init\n");

return 0x1234;

}

BOOL TST_Deinit( DWORD hDeviceContext )

{

OutputDebugString(L"TestDriver - TST_Deinit\n");
OutputDebugString(L"TestDriver - ~ TST_Deinit\n");

return TRUE;


}
// Driver Open

DWORD TST_Open( DWORD hDeviceContext, DWORD AccessCode, DWORD ShareMode )

{

OutputDebugString(L"TestDriver - TST_Open\n");

OutputDebugString(L"hDeviceContext - ");

OutputDebugString(L"TestDriver - ~ TST_Open\n");

return 0x5678;

}

BOOL TST_Close( DWORD hOpenContext )

{

OutputDebugString(L"TestDriver - TST_Close\n");

OutputDebugString(L"hOpenContext - ");

OutputDebugString(L"\n");

OutputDebugString(L"TestDriver - ~ TST_Close\n");

return TRUE;

}

BOOL TST_IOControl( DWORD hOpenContext, DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut )

{

OutputDebugString(L"TestDriver - TST_IOControl\n");

OutputDebugString(L"hOpenContext - ");

OutputDebugString(L"\n");

switch (dwCode) {

case IOCTL_DRIVER_TST:

{

OutputDebugString(L"DRIVER TST IOCTL...\n");

}

break;

default:

OutputDebugString(L"Unknown IOCTL\n");

break;

}

OutputDebugString(L"TestDriver - ~ TST_IOControl\n");

return TRUE;

}

void TST_PowerUp( DWORD hDeviceContext )

{

OutputDebugString(L"TestDriver - TST_PowerUp\n");

OutputDebugString(L"hDeviceContext - ");

OutputDebugString(L"\n");
OutputDebugString(L"TestDriver - ~ TST_PowerUp\n");

}
void TST_PowerDown( DWORD hDeviceContext )

{

OutputDebugString(L"TestDriver - TST_PowerDown\n");

OutputDebugString(L"hDeviceContext - ");

OutputDebugString(L"\n");
OutputDebugString(L"TestDriver - ~ TST_PowerDown\n");

}
DWORD TST_Read( DWORD hOpenContext, LPVOID pBuffer, DWORD Count )

{

OutputDebugString(L"TestDriver - TST_Read\n");

OutputDebugString(L"hOpenContext - ");

OutputDebugString(L"\n");

OutputDebugString(L"TestDriver - ~ TST_Read\n");
return 1;

}


DWORD TST_Write( DWORD hOpenContext, LPCVOID pBuffer, DWORD Count )

{

OutputDebugString(L"TestDriver - TST_Write\n");

OutputDebugString(L"hOpenContext - ");

OutputDebugString(L"\n");

OutputDebugString(L"TestDriver - ~ TST_Write\n");
return 1;

}


DWORD TST_Seek( DWORD hOpenContext, long Amount, WORD Type )

{

OutputDebugString(L"TestDriver - TST_Seek\n");

OutputDebugString(L"hOpenContext - ");
OutputDebugString(L"TestDriver - ~ TST_Seek\n");
return 0;

}

//end of TestDriver.c by umesh Jagga









now lets write a testdriver.def file. This is the definition file that is passed
to the linker. This file contains the exported function names.


Note: the DLL filename and def filename should be same.

LIBRARY TestDriver
EXPORTS

TST_Init

TST_Deinit

TST_Open

TST_Close

TST_IOControl

TST_PowerUp

TST_PowerDown

TST_Read

TST_Write

TST_Seek

now lets write a sources file:

TARGETNAME=TestDriver





TARGETTYPE=DYNLINK

TARGETLIBS=$(_COMMONSDKROOT)\lib\$(_CPUINDPATH)\coredll.lib

SOURCES=TestDriver.c


now we need to put the registry and bib file entries.

you will need to create the registry entries for this driver so that the
driver can be loaded by Device.exe.

lets put this in platform.bib and platform.reg files.

addin platform.reg file:

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\TestDriver]

"Dll" = "TestDriver.Dll"

"Prefix" = "TST"

"Order" = dword:0

"FriendlyName" = "Umesh TestDriver"

"Ioctl" = dword:0


add the below in platform.bib file
TestDriver.dll $(_FLATRELEASEDIR)\TestDriver.dll NK SH

Just for reference:


Device Driver Loading Process:


Kernel---loads---> Device.exe (I/O Resource Manager)-------Loads------>
-------->REGENUM.DLL(registryenumerator,its reentrant)

-----------------loads-----------


REGENUM.DLL(ISA) PCIBUS.DLL

Now we know the concept of device driver lets proceed to step2...

making a custom device driver for your device for customized functionality........

Memory allocation check???

Q. How can I determine how much memory my application can allocate without severely impacting other applications?

A. you could use GlobalMemoryStatus for this.

usage:
MEMORYSTATUS gMemStatus;
GlobalMemoryStatus(&gMemStatus);

if (gMemStatus.dwMemoryLoad < somevalue)
{
//do.... LocalAlloc
} else
{
//do not allocate anything u want.,........like free memory close other apps and try again...
}

Monday 7 January 2008

ShellExecuteEx

Its better to use shellexecuteEx to launch apps.
The device can have lot of flexibility from where we launch the apps from.

the example given below shows how we could read from the registry and run the apps programmatically on windows mobile devices.

SHELLEXECUTEINFO sei;
HKEY hKey;
TCHAR szKeyName[250], szApplName[250], szApplDir[250], szApplParam[250];

RegOpenKeyEx(HKEY_LOCAL_MACHINE, , 0, 0, &hKey);

dwcbData=sizeof(szApplName)*sizeof(TCHAR);
rc = RegQueryValueEx (hKey, szKeyName, 0, &dwType, (LPBYTE)szApplName, &dwcbData);

if (rc != ERROR_SUCCESS)
{
//do something
}

dwcbData=sizeof(szApplParam)*sizeof(TCHAR);
rc = RegQueryValueEx (hKey, szKeyName, 0, &dwType, (LPBYTE)szApplParam, &dwcbData);


dwcbData=sizeof(szApplDir)*sizeof(TCHAR);
rc = RegQueryValueEx (hKey, szKeyName, 0, &dwType, (LPBYTE)szApplDir, &dwcbData);

RegCloseKey (hKey);
if()
{
wcscpy(szApplName, _T(""));
wcscpy(szApplParam, _T(""));
wcscpy(szApplDir, _T(""));
}

memset(&sei, 0, sizeof(sei));
sei.cbSize = sizeof(sei);
sei.hwnd = NULL;
sei.lpFile = szApplName;
sei.lpParameters = szApplParam;
sei.lpDirectory = szApplDir;
sei.nShow = SW_SHOWNORMAL;

ShellExecuteEx(&sei) ; //parse application szDirNameText to szDirName