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.
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?)