Hi
I want to make a call with my mda without using the RAS dialer. Direct access to the COM-ports does not work, as described in the document "Serial Communications". But that documents mentions that TAPI calls are possible with an xda.
It says:
"If you´ve establised a call, TAPI returns a handle for further data-i/o..."
Is there an example how to make a call using TAPI especially how to get that data-handle. And furthermore can I use that handle with WriteFile / ReadFile as I would use a handle to a COM-Port?
I did this for a terminal emulator I wrote. I pass a string to these functions which is COM1: for serial, TAPI for modem or RAS for TCPIP RAS.
I have simply copied some of my code here, work through it as if lpszPortName = "TAPI" and you should make sense of it. Once you have the port handle hPort which is returned by the Connected response of the TAPI call back function, then you can read and write as if that were a serial/file handle.
Cheers
Paul
#include <windows.h>
#include <string.h>
#include <tapi.h>
#include "toolbox.h"
//Initilise the port either the TAPI or COMM port as requested by lpszPortName
BOOL PortInitialize (LPTSTR lpszPortName)
{
DWORD dwError;
BOOL RetValue;
HKEY hKey;
DWORD RegKeyDisp, RegKeyType, RegKeySize;
DWORD dwTapiNumDevs;
LONG lTapiReturn;
char PrintString[80];
TCHAR TempString[20];
char CharString[20];
LINEDEVCAPS TapiLineDevCaps;
static DWORD dwLocalAPIVersion;
LINEEXTENSIONID LineExtensionID;
LINECALLPARAMS LineCallParams;
static DWORD ChoosenDevice;
TCHAR DialNumber[30];
#ifdef _WIN32_WCE_EMULATION
if (wcscmp(lpszPortName, TEXT("TAPI")) != 0)
return TRUE; //If running under emulator then unable to emulate
#endif //the serial port, so in this 'test' mode just echo.
if (COMMPORTSHUT == TRUE) //If this is True then we are shutting down the program
return TRUE; //So don't try to re-open port as it gets stuck in an infinate loop
if (wcscmp(lpszPortName, TEXT("TAPI")) == 0)
{
#ifdef DEBUGVERSION
VTPrint("Entering (TAPI)PortInitilize\r\n" , 0);
#endif
//Retrive the telephone number from the registry
// Fill in the Modem Telephone number
wcscpy(DialNumber, TEXT("T"));
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
TEXT("Software\\PVG\\Terminal\\Settings"),
0, NULL, 0,0, NULL, &hKey, &RegKeyDisp) == ERROR_SUCCESS)
{
//Retrive the telephone number
RegKeyType = REG_SZ;
RegKeySize = sizeof(DialNumber);
RegQueryValueEx(hKey, TEXT("Telephone"),
NULL, &RegKeyType,
(PBYTE)DialNumber + sizeof(TCHAR),
&RegKeySize);
RegCloseKey(hKey);
}
//Confirm there is a telephone number
if (*(DialNumber + 1) == 0)
{
VTPrint("No Telephone Number\r\n", 0);
return FALSE;
}
// Use TAPI to open a DATAMODEM communication channel
if (ghLineApp == NULL)
{
#ifdef DEBUGVERSION
VTPrint("Tapi - LineInitialise\r\n",0);
#endif
memset(&TapiLineDevCaps, 0, sizeof(TapiLineDevCaps));
lTapiReturn = lineInitialize(&ghLineApp, hInst, TapiCallBackFunction, NULL, &dwTapiNumDevs);
if (lTapiReturn)
{
wsprintf (TempString,TEXT("%d"), lTapiReturn);
WideCharToMultiByte(CP_ACP, 0, TempString, -1, CharString, 20, NULL, NULL);
VTPrint("TAPI failed to initialise\n\rError Code = ",0);
VTPrint(CharString, 0);
VTPrint("\n\r",0);
TAPIShutdown();
return FALSE;
}
//Loop through devices to find one that can do data at 9600 baud (GSM)
for (ChoosenDevice=0 ; ChoosenDevice < dwTapiNumDevs ; ChoosenDevice++)
{
TapiLineDevCaps.dwTotalSize = sizeof(TapiLineDevCaps);
//Ask for at least TAPI Version 1.4
lTapiReturn = lineNegotiateAPIVersion(ghLineApp, ChoosenDevice, 0x00010004,
0x00010004, &dwLocalAPIVersion, &LineExtensionID);
#ifdef DEBUGVERSION
if (lTapiReturn)
{
wsprintf (TempString,TEXT("%d"), lTapiReturn);
WideCharToMultiByte(CP_ACP, 0, TempString, -1, CharString, 20, NULL, NULL);
VTPrint("TAPI failed to negotiate API Version\n\rError Code = ",0);
VTPrint(CharString, 0);
VTPrint("\n\r",0);
}
#endif
if (!(lTapiReturn))
{
lTapiReturn=lineGetDevCaps(ghLineApp, ChoosenDevice, dwLocalAPIVersion, 0, &TapiLineDevCaps);
#ifdef DEBUGVERSION
if (lTapiReturn)
{
wsprintf (TempString,TEXT("%d"), lTapiReturn);
WideCharToMultiByte(CP_ACP, 0, TempString, -1, CharString, 20, NULL, NULL);
VTPrint("TAPI failed to get device capibility\n\rError Code = ",0);
VTPrint(CharString, 0);
VTPrint("\n\r",0);
}
else
#endif
#ifndef DEBUGVERSION
if (!(lTapiReturn))
#endif
{
if ((TapiLineDevCaps.dwBearerModes & LINEBEARERMODE_VOICE) &&
(TapiLineDevCaps.dwMaxRate >= 9600) &&
(TapiLineDevCaps.dwMediaModes & LINEMEDIAMODE_DATAMODEM))
break;
}
}
}
if (!((TapiLineDevCaps.dwBearerModes & LINEBEARERMODE_VOICE) ||
(TapiLineDevCaps.dwMaxRate >= 9600) ||
(TapiLineDevCaps.dwMediaModes & LINEMEDIAMODE_DATAMODEM)))
{
VTPrint("Unable to find a modem device\r\n", 0);
TAPIShutdown();
lineShutdown(ghLineApp);
ghLineApp = NULL;
return FALSE;
}
//Now we have found a device capable of a dial up modem
strcpy(PrintString, "TAPI Initilised (");
wsprintf (TempString,TEXT("%d"), ChoosenDevice);
WideCharToMultiByte(CP_ACP, 0, TempString, -1, CharString, 20, NULL, NULL);
strcat(PrintString, CharString);
strcat(PrintString, "/");
wsprintf (TempString,TEXT("%d"), dwTapiNumDevs);
WideCharToMultiByte(CP_ACP, 0, TempString, -1, CharString, 3, NULL, NULL);
strcat(PrintString, CharString);
strcat(PrintString, ")\n\r");
VTPrint(PrintString, 0);
}
//Open the TAPI line device
if (ghLine == NULL)
{
#ifdef DEBUGVERSION
VTPrint("TAPI - Obtaining line handle\r\n", 0);
#endif
lTapiReturn = lineOpen(ghLineApp, ChoosenDevice, &ghLine, dwLocalAPIVersion, 0 , 0,
LINECALLPRIVILEGE_NONE, LINEMEDIAMODE_DATAMODEM, 0);
if (lTapiReturn)
{
wsprintf (TempString,TEXT("%d"), lTapiReturn);
WideCharToMultiByte(CP_ACP, 0, TempString, -1, CharString, 20, NULL, NULL);
VTPrint("TAPI failed to Open Line\n\rError Code = ",0);
VTPrint(CharString, 0);
VTPrint("\n\r",0);
TAPIShutdown();
return FALSE;
}
//Request specific notification messages
lTapiReturn = lineSetStatusMessages(ghLine, LINEDEVSTATE_RINGING | LINEDEVSTATE_CONNECTED |
LINEDEVSTATE_DISCONNECTED | LINEDEVSTATE_OUTOFSERVICE |
LINEDEVSTATE_MAINTENANCE | LINEDEVSTATE_CLOSE |
LINEDEVSTATE_REINIT, LINEADDRESSSTATE_OTHER);
if (lTapiReturn)
{
wsprintf (TempString,TEXT("%d"), lTapiReturn);
WideCharToMultiByte(CP_ACP, 0, TempString, -1, CharString, 20, NULL, NULL);
VTPrint("TAPI failed to Set Status Messages\n\rError Code = ",0);
VTPrint(CharString, 0);
VTPrint("\n\r",0);
TAPIShutdown();
return FALSE;
}
//Configure line device for a data modem
memset(&LineCallParams, 0, sizeof(LineCallParams));
LineCallParams.dwTotalSize = sizeof(LineCallParams);
LineCallParams.dwBearerMode = LINEBEARERMODE_VOICE;
LineCallParams.dwMediaMode = LINEMEDIAMODE_DATAMODEM;
//Expect the line to start out idle (we don't want to break into a current call)
LineCallParams.dwCallParamFlags = LINECALLPARAMFLAGS_IDLE;
//If multiple addresses on the line, use the first address
LineCallParams.dwAddressMode = LINEADDRESSMODE_ADDRESSID;
LineCallParams.dwAddressID = 0;
}
//Make the call
if (ghCall == NULL)
{
#ifdef DEBUGVERSION
VTPrint("TAPI Making the call\r\n", 0);
#endif
lTapiReturn = lineMakeCall(ghLine, &ghCall, DialNumber, 0, &LineCallParams);
if (lTapiReturn < 0)
{
wsprintf (TempString,TEXT("%d"), lTapiReturn);
WideCharToMultiByte(CP_ACP, 0, TempString, -1, CharString, 20, NULL, NULL);
VTPrint("TAPI failed to Make the Call\n\rError Code = ",0);
VTPrint(CharString, 0);
VTPrint("\n\r",0);
TAPIShutdown();
ghCall = NULL;
return FALSE;
}
}
VTPrint("Call Initiated\r\n",0);
return TRUE;
}
if (wcscmp(lpszPortName, TEXT("RAS")) != 0)
{
{
// Open the serial port.
hPort = CreateFile (lpszPortName, // Pointer to the name of the port
GENERIC_READ | GENERIC_WRITE,
// Access (read-write) mode
0, // Share mode
NULL, // Pointer to the security attribute
OPEN_EXISTING,// How to open the serial port
0, // Port attributes
NULL); // Handle to port with attribute
// to copy
// If it fails to open the port, return FALSE.
if ( hPort == INVALID_HANDLE_VALUE )
{
// Could not open the port.
COMMPORTSHUT=TRUE;
MessageBox (hMainWnd, TEXT("Unable to open the port"),
TEXT("Error"), MB_OK);
dwError = GetLastError ();
return FALSE;
}
}
RetValue=InitiliseCommHandle();
return RetValue;
}
return TRUE;
}
//Initilise the communication handle, this occurs once a communication channel has been
//opened, either direct to a serial port or via TAPI
BOOL InitiliseCommHandle(void)
{
DWORD dwError,
dwThreadID;
DCB PortDCB;
COMMTIMEOUTS CommTimeouts;
#ifdef DEBUGVERSION
char SendString[40];
sprintf(SendString, "Handle = %d\r\n", hPort);
VTPrint(SendString,0);
#endif
// Get the default port setting information.
PortDCB.DCBlength = sizeof (DCB);
GetCommState (hPort, &PortDCB);
// Change the DCB structure settings.
if (wcscmp(COMMPORTNAME, TEXT("TAPI")) == 0)
{
//TAPI (modem) Settings
PortDCB.BaudRate = 19200; // Current baud
PortDCB.ByteSize = 8; // Number of bits/byte, 4-8
PortDCB.Parity = NOPARITY; // Parity odd,even,mark,space
}
else
{
//Standard Serial Port Settings
PortDCB.BaudRate = 1200; // Current baud
PortDCB.ByteSize = 7; // Number of bits/byte, 4-8
PortDCB.Parity = EVENPARITY; // Parity odd,even,mark,space
}
PortDCB.fBinary = TRUE; // Binary mode; no EOF check
PortDCB.fParity = TRUE; // Enable parity checking
PortDCB.fOutxCtsFlow = FALSE; // CTS output flow control
PortDCB.fRtsControl = RTS_CONTROL_HANDSHAKE;
PortDCB.fOutxDsrFlow = FALSE; // No DSR output flow control
PortDCB.fDtrControl = DTR_CONTROL_ENABLE; //DTR output ON
PortDCB.fDsrSensitivity = FALSE; // DSR sensitivity
PortDCB.fTXContinueOnXoff = TRUE; // XOFF continues Tx
PortDCB.fOutX = FALSE; // No XON/XOFF out flow control
PortDCB.fInX = FALSE; // No XON/XOFF in flow control
PortDCB.fErrorChar = FALSE; // Disable error replacement
PortDCB.fNull = FALSE; // Disable null stripping
PortDCB.fAbortOnError = FALSE; // Do not abort reads/writes on
// error
PortDCB.StopBits = ONESTOPBIT; // 0,1,2 = 1, 1.5, 2
// Configure the port according to the specifications of the DCB
// structure.
if (!SetCommState (hPort, &PortDCB))
{
MessageBox (hMainWnd, TEXT("Unable to configure the port"),
TEXT("Error"), MB_OK);
dwError = GetLastError ();
return FALSE;
}
// Retrieve the time-out parameters for all read and write operations
// on the port.
GetCommTimeouts (hPort, &CommTimeouts);
// Change the COMMTIMEOUTS structure settings.
CommTimeouts.ReadIntervalTimeout = MAXDWORD;
CommTimeouts.ReadTotalTimeoutMultiplier = 0;
CommTimeouts.ReadTotalTimeoutConstant = 0;
CommTimeouts.WriteTotalTimeoutMultiplier = 20;
CommTimeouts.WriteTotalTimeoutConstant = 1000;
// Set the time-out parameters for all read and write operations
// on the port.
if (!SetCommTimeouts (hPort, &CommTimeouts))
{
// Could set the timeouts.
MessageBox (hMainWnd, TEXT("Unable to set the port time-out parameters"),
TEXT("Error"), MB_OK);
dwError = GetLastError ();
return FALSE;
}
if (wcscmp(COMMPORTNAME, TEXT("TAPI")) != 0)
{
// Direct the port to perform extended functions SETDTR and SETRTS
// SETDTR: Sends the DTR (data-terminal-ready) signal.
// SETRTS: Sends the RTS (request-to-send) signal.
// EscapeCommFunction (hPort, SETDTR);
// EscapeCommFunction (hPort, SETRTS);
//Use the Swap Comms routine to set the serial port to the last open state
//This is a little messy to set the port first of all and then change some
//of the settings here
SwapComms(CurrentController);
}
// Create a read thread for reading data from the communication port.
if (hReadThread = CreateThread (NULL, 0, PortReadThread, 0, 0,
&dwThreadID))
{
CloseHandle (hReadThread);
}
else
{
// Could not create the read thread.
MessageBox (hMainWnd, TEXT("Unable to create the read thread"),
TEXT("Error"), MB_OK);
dwError = GetLastError ();
return FALSE;
}
return TRUE;
}
//TAPI sends status messages to this function.
void CALLBACK TapiCallBackFunction(DWORD dwdevice, DWORD dwMsg, DWORD dwCallbackInstance,
DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
{
DWORD lTapiReturn, dwStructSize;
VARSTRING *pvs, *pvsOld;
#ifdef DEBUGVERSION
char SendString[40];
#endif
pvs = NULL;
dwStructSize = sizeof (VARSTRING);
switch(dwMsg)
{
case LINE_CALLSTATE:
switch(dwParam1)
{
case LINECALLSTATE_IDLE:
if (hPort != INVALID_HANDLE_VALUE)
{
VTPrint("Line Idle\n\r",0);
//Change MENU back to COMM mode
ControllerMenu(TRUE);
//Shutdown TAPI
hPort = INVALID_HANDLE_VALUE;
lineDeallocateCall(ghCall);
ghCall = NULL;
ghLine = NULL;
}
break;
case LINECALLSTATE_CONNECTED:
//If a handle is already present then don't re-open
//This needs doing as multiple connected events can occur on connection
if (hPort != INVALID_HANDLE_VALUE)
break;
//Spin round loop till the structure is big enough
do
{ pvsOld = pvs;
if (NULL == (pvs = realloc (pvs, dwStructSize)))
break;
pvs->dwTotalSize = dwStructSize;
if (lTapiReturn = lineGetID (NULL, 0, ghCall, LINECALLSELECT_CALL,
pvs, TEXT("comm/datamodem")))
break;
}
while ((dwStructSize = pvs->dwNeededSize) > pvs->dwTotalSize) ;
if (pvs == NULL)
{
if (pvsOld)
free (pvsOld);
VTPrint("Failed to allocate port handle memory\n\r", 0);
TAPIShutdown();
break;
}
if (lTapiReturn)
{
free(pvs);
VTPrint("Failed to obtain port handle\n\r", 0);
TAPIShutdown();
break;
}
hPort = * (HANDLE*) ((char*) pvs + pvs->dwStringOffset);
free(pvs);
//Change Menu to Modem Mode
ControllerMenu(FALSE);
VTPrint("Connected\n\r", 0);
InitiliseCommHandle();
break;
case LINECALLSTATE_DIALING:
//VTPrint("Dialling\n\r", 0);
break;
case LINECALLSTATE_PROCEEDING:
//VTPrint("Waiting for an answer\n\r", 0);
break;
case LINECALLSTATE_DISCONNECTED:
ControllerMenu(TRUE);
//Change Menu to COMM mode
switch (dwParam2)
{
case LINEDISCONNECTMODE_UNREACHABLE:
VTPrint("Unreachable\r\n",0);
hPort = INVALID_HANDLE_VALUE;
break;
case LINEDISCONNECTMODE_BUSY:
VTPrint("Line Busy\n\r", 0);
break;
}
TAPIShutdown();
}
break;
default:
break;
}
}
[/code]
BOOL TAPIShutdown()
//Do the TAPI Shutdown Process
{
static bShuttingDown = FALSE;
//If we are not initilised then Shutdown unnecessary
if (ghLineApp == NULL)
return TRUE;
//Prevent Shutdown re-entrancy problems
if (bShuttingDown)
return TRUE;
bShuttingDown=TRUE;
if (ghCall != NULL)
lineDrop(ghCall, NULL, 0);
bShuttingDown = FALSE;
return TRUE;
}
Thanks for code posted. It is very helpful.
But I don't quite understand the logic how the "hPort" is created when receiveing a "CONNECTED" message callback.
Can you explain a little bit more?
- David
The handle to the port (hPort) is contained at the end of a variable length string (VARSTRING) that is returned from the call to LineGetID.
The fiddly thing about it is you give LineGetID a pointer to a VARSTRING called pvs and you have to fill in one of the member variables of pvs with the size allocated ( pvs->dwTotalSize ) to the variable length string.
Since I don't know how much to allocate to the VARSTRING, initially I just allocate enough memory from a sizeof(VARSTRING) result. Maybe you could just allocate a set size and not bother with the looping back, I think it is better to ask the system how much memory it wants as LineGetID may need more memory in later versions of the operating system.
Then you pass the VARSTRING with it's size stored in dwTotalSize to the function LineGetID.
The LineGetID function then fills in dwNeededSize with the size of the VARSTRING it needed to complete. That is why I loop back and re-allocate the VARSTRING to a new (bigger) size if NeededSize is greater than TotalSize.
Once the LineGetID function succeeds with a big enough VARSTRING then the Port Handle is at the end of the VARSTRING, as it is a variable length string you have to do maths to say the Port Handle is at the Address of the string PLUS the offset to the actural data wanted i.e. pvs + pvs->dwStringOffset The maths must be done with char* byte sizes and the final result is a handle, hence the casting HANDLE* on the final result.
Once the Port Handle is stored in hPort, the memory allocated to pvs is freed.
One other thing I noticed is that you can get multiple CONNECTED events, that is why I just exit the CONNECTED event if there is already a valid handle
I hope that makes sense.
Cheers
Paul
Do you have sample for the answering part?
thanks,
- David
No, sorry I have only ever written programs to dial out.
Hi,
I tried the sample code posted in this thread. It works only if I used
LineCallParams.dwBearerMode = LINEBEARERMODE_VOICE;
LineCallParams.dwMediaMode = LINEMEDIAMODE_INTERACTIVEVOICE;
combination. I got the RING message. However, the original:
LineCallParams.dwBearerMode = LINEBEARERMODE_VOICE;
LineCallParams.dwMediaMode = LINEMEDIAMODE_DATAMODEM;
didn't seem to work.
Do I miss something? (I think I have successfully killed the cprog.exe already)
Thanks,
- David
That means you are making a voice call.
So is the problem that you can not make a data(modem) type call ?
Check that you have data enabled on your SIM and also that under Settings -> Connections -> CSD Line Type it is set correctly. In the UK it is 9600 bps(v.32) and Non-tranparent, but I was told it is v110 is the states.
Let me know how you get on.
Is there any chance that somebody could compile this TAPI code as an object I could consume in C#? I have tried, but I am not even able to compile the example in C++... it's just not my world!
I would be eternally gratefull - and I bet a whole bunch of other guys who just want to quickly establish a data connection over GSM from C# (or VB?) would be also! It should have been in the phone.dll if you ask me!
compiled sample
Hey could somebody compile the tapi code for me in eVc++ or MFC ?? because i am really struggling. Plus what is toolbox.h i dont seem to have it ?? can somebody please help ??
thanks guys
This is an old post of mine, don't worry about Toolbox.h that was for the program I was writing and it has nothing to do with Tapi.
This sample code was not meant to compile, after you you won't have function VTPrint but I hope you can guess that just shows text. It was just posted to demonstate the order of functions needed to get a modem connection.
I built all this Tapi code into a DLL and I have it all presented with the eVC 3.0 build files in this post, this code will compile as presented and is just a zip of all the project files of a single sample application.
http://forum.xda-developers.com/viewtopic.php?t=18978
Have a look there.
Cheers
Paul
during a data call when using TAPI can u make some kind of AT command request ??? and retrieve the data from that answer ??? And do i need some TAPI app on the remote unit to send the data back ?
i am trying to access a remote unit ( GPS RX and GSM TX )
I don't really understand your question that well.
But AT commands have nothing to do with TAPI, so any question saying can TAPI send an AT command for etc -- The answer must be no.
All TAPI does is gives a Handle that can be used with ReadFile and WriteFile for receiving and sending data over the modem.
So TAPI will dial a number and establish a DataModem connection, then on Connect it can provide the handle for you to direct read/write requests to. Once the link is established you just treat the handle as if it was a file handle returned from a CreateFile command.
As said earlier all this has nothing to do with AT commands.
During a data call should ic onnect via COM 1 or COM 9 if i'm using TAPI ?? Would you have any sample code i could have a look at ? I'm a bit lost at the moment .... with LineGetID too ...
you can't use COM2 or COM9 via TAPI cause COM2 and COM9 masked by RIL
about lineGetID look http://forum.xda-developers.com/viewtopic.php?t=9761
ok thanks - so if i cant use COM1 or COM9 in this case then i'm guessing that i shall pass a string (lpszPortName) just like the example on this post.
Code:
// Open the serial port.
hPort = CreateFile (lpszPortName, // Pointer to the name of the port
GENERIC_READ | GENERIC_WRITE,
// Access (read-write) mode
0, // Share mode
NULL, // Pointer to the security attribute
OPEN_EXISTING,// How to open the serial port
0, // Port attributes
NULL); // Handle to port with attribute
// to copy
But what should the string lpszPortName be initialized to ? Or am i totally wrong ?[/quote]
L"COM9:" for COM9
but not with TAPI
with TAPI you have not open any COM-ports
you must use lineGetID
Code:
//PART 7 - TIMEOUT AND DCB SETTINGS
PortDCB.BaudRate = 115200;
PortDCB.fBinary = TRUE;
PortDCB.fParity = FALSE;
PortDCB.fOutxCtsFlow = FALSE;
PortDCB.fOutxDsrFlow = FALSE;
PortDCB.fDtrControl = DTR_CONTROL_ENABLE;
PortDCB.fDsrSensitivity = FALSE;
PortDCB.fTXContinueOnXoff = FALSE;
PortDCB.fOutX = FALSE;
PortDCB.fInX = FALSE;
PortDCB.fErrorChar = FALSE;
PortDCB.fNull = FALSE;
PortDCB.fRtsControl = RTS_CONTROL_DISABLE;
PortDCB.fAbortOnError = FALSE;
PortDCB.ByteSize = 8;
PortDCB.Parity = NOPARITY;
PortDCB.StopBits = ONESTOPBIT;
if (!SetCommState (hPort, &PortDCB))
{
MessageBox (_T("unable to configure com port "));
return FALSE;
}
GetCommTimeouts (hPort, &CommTimeouts);
CommTimeouts.ReadIntervalTimeout = MAXDWORD;
CommTimeouts.ReadTotalTimeoutMultiplier = 0;
CommTimeouts.ReadTotalTimeoutConstant = 0;
CommTimeouts.WriteTotalTimeoutMultiplier = 20;
CommTimeouts.WriteTotalTimeoutConstant = 1000;
if (!SetCommTimeouts (hPort, &CommTimeouts))
{
MessageBox (_T("unable to set comport parameters"));
return FALSE;
}
Are the COM and Timeout settings necessary when using TAPI ? because i am getting an error message at the !setCommState function.
I use lineGetID to retrieve the Handle to the Comm then i try to use readFile but the operation is unsuccesful.
Anyhelp from out there ? thanks.
Are you sure that you call lineGetID only after connection?
Maybe you are right. I just do lineMakeCall then do lineGetId without waiting for a LINECALLSTATE_CONNECTED message.
I think its because i have troubles implementing the lineCallBackFunc() i dont understand the parameters that need to be passed to it.
Code:
void CALLBACK lineCallbackFunc(
DWORD dwDevice, DWORD dwMsg, DWORD dwCallbackInstance,
DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
{
Anyhelp for this ?? Cheers.
I made a Today Plugin with option to change the heigh. It run OK when I make option in Today seting. But I want to show option dialog by tap in to my Today Item and change Option from that.
There is the code in WndPro
//Our main WndProc. Does everything after initialization.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
switch (message)
{
case WM_TIMER:
//Recalculate and paint the time for the count down.
TimeUpdate(hWnd);
return TRUE;
case WM_ERASEBKGND:
//We return true here since we handle our own background painting.
return TRUE;
case WM_TODAYCUSTOM_CLEARCACHE :
//We have no cache to clear so we ignore this message.
break;
case WM_TODAYCUSTOM_QUERYREFRESHCACHE:
//If the cyp member is set to 0 then you must set it to your windows height.
//This makes sure the shell gives you a certain amout of room for your painting.
if (g_bDayView)
{
g_ItemHeight = 26;
}
if (g_bMonthView)
{
g_ItemHeight = 105;
}
if (g_bClockView)
{
g_ItemHeight = 100;
}
//g_curTime = 0;
if (((TODAYLISTITEM*)wParam)->cyp == 0)
{
((TODAYLISTITEM*)wParam)->cyp = g_ItemHeight; //the shell draws a line at the bottom of our window.
return 1;
}
break;
case WM_PAINT:
//Paint like you would in any other application.
hdc = BeginPaint(hWnd, &ps);
PaintAll(hWnd, hdc);
EndPaint(hWnd, &ps);
break;
case WM_LBUTTONUP:
g_stylusPt.x = LOWORD(lParam); g_stylusPt.y = HIWORD(lParam);
if((g_stylusPt.x < 32)&&(g_stylusPt.y < 32))
DialogBox(g_hInstance, (LPCTSTR)IDD_TODAY_CUSTOM, hWnd, (DLGPROC)CustomItemOptionsDlgProc);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Click to expand...
Click to collapse
And there is the code in Custom Dialog
BOOL WINAPI CustomItemOptionsDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
SHINITDLGINFO shidi;
HWND hCurrentRadioButton;
switch (message)
{
case WM_INITDIALOG:
// Create a Done button and size it.
shidi.dwMask = SHIDIM_FLAGS;
shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN;
shidi.hDlg = hDlg;
SHInitDialog(&shidi);
// select both as the radio button default
if(!g_bUserSet)
{
CheckRadioButton(hDlg, IDC_CLOCK_VIEW, IDC_MONTH_VIEW, IDC_DAY_VIEW);
}
// determine what the current config is and preserve it
else
{
if(g_bDayView)
{
CheckRadioButton(hDlg, IDC_CLOCK_VIEW, IDC_MONTH_VIEW, IDC_DAY_VIEW);
}
if(g_bMonthView)
{
CheckRadioButton(hDlg, IDC_CLOCK_VIEW, IDC_DAY_VIEW, IDC_MONTH_VIEW);
}
if(g_bClockView)
{
CheckRadioButton(hDlg, IDC_DAY_VIEW, IDC_MONTH_VIEW, IDC_CLOCK_VIEW);
}
}
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK)
{
// check to see if both is checked
hCurrentRadioButton = GetDlgItem(hDlg, IDC_DAY_VIEW);
if(BST_CHECKED == SendMessage(hCurrentRadioButton, BM_GETCHECK, NULL, NULL))
{
g_bDayView = TRUE;
g_bMonthView = FALSE;
g_bClockView = FALSE;
}
// check to see if only program is checked
hCurrentRadioButton = GetDlgItem(hDlg, IDC_MONTH_VIEW);
if(BST_CHECKED == SendMessage(hCurrentRadioButton, BM_GETCHECK, NULL, NULL))
{
g_bDayView = FALSE;
g_bMonthView = TRUE;
g_bClockView = FALSE;
}
// check to see if only storage is checked
hCurrentRadioButton = GetDlgItem(hDlg, IDC_CLOCK_VIEW);
if(BST_CHECKED == SendMessage(hCurrentRadioButton, BM_GETCHECK, NULL, NULL))
{
g_bDayView = FALSE;
g_bMonthView = FALSE;
g_bClockView = TRUE;
}
g_bUserSet = TRUE;
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
Click to expand...
Click to collapse
It shows Dialog, change all value of variable. But the Today Item's is not change.
Could anyone tell me how to do.
Thanks
Try this...
Instead of your line:
Code:
if (((TODAYLISTITEM*)wParam)->cyp == 0)
check for cyp not being set to desired height (g_ItemHeight), i.e.:
Code:
if (((TODAYLISTITEM*)wParam)->cyp != g_ItemHeight)
That should work for you.
It works OK
Thank you very, very much
nncuong said:
It works OK
Thank you very, very much
Click to expand...
Click to collapse
My pleasure
Does someone know this? I want to unregister from the GSM network, but not enter the flightmode (I still need SIM access, and it should be fast). The following code works fine on a S100 (WM2003), but the 9100 (WM5) refuses to unregister. Registering works fine on both devices.
Code:
GsmControl::GsmControl()
{
errorMsg = TEXT("No ERROR/SUCCESS message to display.");
hLineApp = NULL;
hLine = NULL;
LineInitializeExParams.dwTotalSize = sizeof(LineInitializeExParams);
LineInitializeExParams.dwNeededSize = 0;
LineInitializeExParams.dwUsedSize = 0;
LineInitializeExParams.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT;
LineInitializeExParams.Handles.hEvent = NULL;
LineInitializeExParams.dwCompletionKey = 0;
dwLineAPIVersion = TAPI_CURRENT_VERSION;
GsmInitialize();
}
HRESULT GsmControl::GsmInitialize()
// Initializes TAPI interface
{
res = lineInitializeEx(&hLineApp, NULL, NULL, NULL, &dwNumDevs, &dwLineAPIVersion, &LineInitializeExParams);
res = lineOpen(hLineApp, 0, &hLine, dwLineAPIVersion, 0, 0, LINECALLPRIVILEGE_MONITOR, 0, NULL);
return res;
}
HRESULT GsmControl::GsmLineUnregister()
{
res = lineUnregister(hLine);
// res = lineSetEquipmentState(hLine, LINEEQUIPSTATE_NOTXRX); /* Edit: This is commented out, as I don't want any kind of flightmode behaviour */
return res;
}
HRESULT GsmControl::GsmLineRegister()
{
// lineSetEquipmentState(hLine, LINEEQUIPSTATE_FULL); /* Edit: This is commented out, as I don't want any kind of flightmode behaviour */
res = lineRegister(hLine, LINEREGMODE_AUTOMATIC, NULL, 0);
if ( res != 0 ) //FAILED(res) )
{
errorMsg = TEXT("ERROR GsmLineRegister - lineRegister\n");
} else {
errorMsg = TEXT("SUCCESS GsmLineRegister - lineRegister");
}
return res;
}
Whats the return value of the lineUnregister() call?
Sorry, I have a problem getting the value. It's larger than zero.
Shouldn't the following code open a message window that says "GsmLineUnregister returned X"?
Code:
LPTSTR lpText = new WCHAR[1024];
swprintf(lpText, TEXT("GsmLineUnregister returned $d"), gsmCtrl->GsmLineUnregister());
MessageBox(NULL, lpText, TEXT("Deva Daemon"), MB_ICONINFORMATION);
Edit: I'm making too many mistakes lately. I also commented out lineSetEquipmentState, as that's how I want it to work but it doesn't (on a 9100)
OK, I've got it now. lineUnregister returns '11'.
Edit: It's not stable, it seems to return quite all kinds of values larger than ten. Each value is larger than its predecessor. After a reboot, I got a 12, and then again increasing numbers (19, 25, 29, 31). It doesn't seem to make any sense.
(Will I ever manage to write a post with no edits this week?)
I'm try write a application to addjust LCD backlight.But it failed at the
first step Create file.GetLastError return 161.
Somesone can tell me what's wrong with it?
Sorry for my poor english.
thx
Below is my code
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
TCHAR *pszDevice=_T("\\\\.\\LCD");
HANDLE hLCD=NULL;
hLCD=CreateFileW(pszDevice,
GENERIC_READ,
FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
0,
NULL);
DWORD dwError=GetLastError();
if(INVALID_HANDLE_VALUE!=hLCD)
{
MessageBox(NULL,_T("Got Lcd"),_T("MyMessage"),MB_OK);
}
CloseHandle(hLCD);
return 0;
}
Hi ft1860!
I don't think you can do it that way, although I never tried it. You should check out power management API:
http://msdn.microsoft.com/library/d...pplicationsToTurnSmartphoneBacklightOffOn.asp
This example is for smartphones but should work on a PPC just as well.
P.S.:
Error 161 is "The specified path is invalid" so you should check the device name (no idea what that might be).
levenum said:
Hi ft1860!
I don't think you can do it that way, although I never tried it. You should check out power management API:
http://msdn.microsoft.com/library/d...pplicationsToTurnSmartphoneBacklightOffOn.asp
This example is for smartphones but should work on a PPC just as well.
P.S.:
Error 161 is "The specified path is invalid" so you should check the device name (no idea what that might be).
Click to expand...
Click to collapse
hi levenum
Thanks your comment,but according to this document
http://windowssdk.msdn.microsoft.co...r/base/ioctl_video_set_display_brightness.asp
It say we can set the current AC and DC backlight levels by invoke DeviceIoControl with IOCTL_VIDEO_SET_DISPLAY_BRIGHTNESS parameter.
So first I must create a handle of LCD,but I cann't open it successfully,
why?
oh,I make a mistake
IOCTL_VIDEO_SET_DISPLAY_BRIGHTNESS is Win32 function.
On smart device,I should use SetPowerRequirement to set the backlight.
But when I invoke SetPowerRequirement on my Universal with D0 or D4,it say success ,but nothing happened.
maybe you have to access backlight by BKL1: device.
CreateFile(L"BKL1:", ....
or write the brightness value into registry.. that works for sure.
buzz
buzz_lightyear said:
maybe you have to access backlight by BKL1: device.
CreateFile(L"BKL1:", ....
or write the brightness value into registry.. that works for sure.
buzz
Click to expand...
Click to collapse
Thanks
I'll try it.
It seem that SetPowerRequirement D0-D4 just Open or close backlight,
but what I want is adjust the backlight's brightness.
ft1860 said:
It seem that SetPowerRequirement D0-D4 just Open or close backlight,
but what I want is adjust the backlight's brightness.
Click to expand...
Click to collapse
then just do it through registry.
buzz
buzz_lightyear said:
ft1860 said:
It seem that SetPowerRequirement D0-D4 just Open or close backlight,
but what I want is adjust the backlight's brightness.
Click to expand...
Click to collapse
then just do it through registry.
buzz
Click to expand...
Click to collapse
oh,thanks
It almost work.
It works fine on my Universal,but it doesn't work on my x50v with WM5.
I should not debug it on my x50v,there is so many bugs in Dell's WM5 update.
Another question is how to get the max brightness value.On my Universal it is 10,but on my x50v it is 8;
below is my new code
#include <WinReg.h>
#include <pm.h>
TCHAR tszAppName[] = TEXT("PMSAMPLE");
TCHAR tszTitle[] = TEXT("Power Manager Sample");
HINSTANCE g_hInst = NULL; // Local copy of hInstance
HANDLE g_hEventShutDown = NULL;
HANDLE g_hPowerNotificationThread = NULL;
HWND g_hSystemState = NULL;
//***************************************************************************
// Function Name: SetBacklightRequirement
//
// Purpose: Sets or releases the device power requirement to keep the
// backlight at D0
//
// Arguments:
// IN BOOL fBacklightOn - TRUE to leave the backlight on
//
void SetBacklightRequirement(BOOL fBacklightOn)
{
// the name of the backlight device
TCHAR tszBacklightName[] = TEXT("BKL1:");
static HANDLE s_hBacklightReq = NULL;
if (fBacklightOn)
{
if (NULL == s_hBacklightReq)
{
// Set the requirement that the backlight device must remain
// in device state D0 (full power)
s_hBacklightReq = SetPowerRequirement(tszBacklightName, D4,
POWER_NAME, NULL, 0);
if (!s_hBacklightReq)
{
RETAILMSG(1, (L"SetPowerRequirement failed: %X\n",
GetLastError()));
}
}
}
else
{
if (s_hBacklightReq)
{
if (ERROR_SUCCESS != ReleasePowerRequirement(s_hBacklightReq))
{
RETAILMSG(1, (L"ReleasePowerRequirement failed: %X\n",
GetLastError()));
}
s_hBacklightReq = NULL;
}
}
}
#define REG_BACKLIGHT L"ControlPanel\\Backlight"
//#define REG_VAL_BATT_TO L"BatteryTimeout"
//#define REG_VAL_AC_TO L"ACTimeout"
#define REG_VAL_BN L"BrightNess"
#define REG_VAL_ACBN L"ACBrightness"
unsigned int OldBattBN=0;
unsigned int OldACBN=0;
void RegOptionBL( DWORD dw1,DWORD dw2)
{
HKEY hKey = 0;
DWORD dwSize;
HANDLE hBL;
static bool bOpened=false;
if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_CURRENT_USER,REG_BACKLIGHT, 0, 0, &hKey ) )
{
if( !bOpened )
{
bOpened=true;
dwSize = 4;
RegQueryValueEx( hKey, REG_VAL_BN,NULL,NULL,(unsigned char*)&OldBattBN,&dwSize );
dwSize = 4;
RegQueryValueEx( hKey, REG_VAL_ACBN,NULL,NULL,(unsigned char*) &OldACBN,&dwSize );
// dwSize = 4;
// dwValue = 0xefff ;
// RegSetValueEx( hKey,REG_VAL_BATT_TO,NULL,REG_DWORD,(unsigned char *)&dwValue,dwSize );
// dwSize = 4;
// dwValue = 0xefff ;
// RegSetValueEx( hKey,REG_VAL_AC_TO,NULL,REG_DWORD,(unsigned char *)&dwValue,dwSize );
dwSize = 4;
RegSetValueEx( hKey,REG_VAL_BN,NULL,REG_DWORD,(unsigned char *)&dw1,dwSize );
dwSize = 4;
RegSetValueEx( hKey,REG_VAL_ACBN,NULL,REG_DWORD,(unsigned char *)&dw2,dwSize );
}
else
{
if (OldBattBN)
{
dwSize = 4;
RegSetValueEx( hKey,REG_VAL_BN,NULL,REG_DWORD,(unsigned char *)&OldBattBN,dwSize );
}
if (OldACBN)
{
OldACBN = 4;
RegSetValueEx( hKey,REG_VAL_ACBN,NULL,REG_DWORD,(unsigned char *)&OldACBN,dwSize );
}
}
RegCloseKey( hKey );
hBL = CreateEvent( NULL, FALSE, FALSE,L"BackLightChangeEvent" );
if( hBL )
{
SetEvent(hBL);
CloseHandle( hBL );
}
}
}
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
int nResult = 0;
// Create mutex to track whether or not an application is already running
HANDLE hMutex = CreateMutex(0, 0, _T("_PMSAMPLE_EXE_MUTEX_"));
// check the result code
if (NULL != hMutex)
{
if (ERROR_ALREADY_EXISTS != GetLastError())
{
SetBacklightRequirement(TRUE);
RegOptionBL(8,8);
Sleep(5000);
RegOptionBL(-1,-1);
SetBacklightRequirement(FALSE);
}
else
{
}
CloseHandle(hMutex);
}
return ( nResult >= 0 );
}