Communicating Through an Open Call

< BACK  NEXT >
[oR]

Once a call has been made, an application can hand over a voice call to the user to complete, or for a data call it can start transferring data. The format of the data depends on the media selected to transfer the data, and this dictates the API functions used to send and receive data. For example, if you were writing a Windows CE device to send recorded voice through a telephone call you might use the Wave audio API functions. In the example presented in this chapter, a serial communications handle is obtained from TAPI to allow ReadFile and WriteFile to be used to read and send digital data. This technique would allow you to use TAPI to make a telephone call to a modem on a remote computer, and then once connected, use ReadFile and WriteFile to communicate with a computer.

Obtaining a Communications Port Handle

In Chapter 9 ("Serial Communications"), the function CreateFile was called to open a serial port and obtain a file handle, and then ReadFile and WriteFile were used to transfer data. Finally, CloseHandle was called to close the port. Instead of calling CreateFile directly, you can make a call using a modem on a communications port using TAPI, and then call the lineGetID ( Table 11.8) function to obtain a file handle.

Table 11.8. lineGetID Obtains a handle for the given media format
lineGetID
HLINE hLine Handle to an open line obtained by calling lineOpen.
DWORD dwAddressID Address ID on open line, use 0.
HCALL hCall Handle to a call.
DWORD dwSelect Constant specifying which of hLine, dwAddressID, and hCall to use:
LINECALLSELECT_LINE use hLine
LINECALLSELECT_ADDRESS use dwAddressID
LINECALLSELECT_CALL use hCall
LPVARSTRING lpDeviceID Pointer to a DWORD in which the data associated with the request is returned.
LPCTSTR lpszDeviceClass String containing the media format for which the handle is to be returned. For example, "comm/datamodem" for a serial communications handle for a modem connection.
LONG Return Value Zero for success, or a LINERR_ value indicating an error. These errors are defined in tapi.h.

Data for a given media format can be obtained for an open line, an address on that line, or an open call handle. In the example given below in Listing 11.5a, a handle to an open line is passed and the file handle for the serial communications device is returned in lpVarString, a pointer to a VARSTRING structure. TAPI allows a communications handle to be returned for an open line, not just a line with an open telephone call. This allows data to be transferred between an application and a modem device before the call is made.

Listing 11.5a Getting a communications port handle
 HANDLE GetCommPort() {   DWORD dwSize = sizeof(VARSTRING) + 1024;   DWORD dwReturn;   LPVARSTRING lpVarString =       (LPVARSTRING)LocalAlloc(LPTR, dwSize);   if(lpVarString == NULL)     return NULL;   lpVarString->dwTotalSize = dwSize;   dwReturn = lineGetID(g_hLine, // handle to open line     0,                          // address ID ignored     NULL,                       // call handle ignored     // we're only passing a line handle     LINECALLSELECT_LINE,     lpVarString,     _T("comm/datamodem"));   if(dwReturn != 0)   {     cout   _T("Could not get line ID")   endl;     return NULL;   }   LPHANDLE lpHandle = (HANDLE*)((LPBYTE)       lpVarString + lpVarString->dwStringOffset);   HANDLE hComm = *lpHandle;   cout   _T("Port handle: ")   (DWORD)hComm   endl;   cout   _T("Communications port: ")          (LPTSTR)((LPBYTE)lpVarString +         lpVarString->dwStringOffset +         sizeof(HANDLE))          endl;   return hComm; } 

The VARSTRING structure allows variable amounts of data to be returned from lineGetID; this data can either be binary or string. The format of the data depends on the media format that is requested, and the data is returned at the end of the VARSTRING structure. The members in VARSTRING allow negotiation of the required size of the structure in the same way the structure LINETRANSLATEOUTPUT was used in Listing 11.3b. The VARSTRING member dwTotalSize is set to the actual size of the structure on calling lineGetID, and the dwNeededSize returns the actual number of bytes required to return all the data. In Listing 11.5a the application assumes that the size of the structure passed in is sufficient for the data returned. In a production system the size should be checked and negotiated.

The VARSTRING structure returns two pieces of information for the "comm/modem" media data type:

  • HANDLE A file handle through which data can be transferred using ReadFile and WriteFile

  • LPTSTR The name of the device associated with the call as a NULL-terminated string

The VARSTRING member dwStringOffset specifies where to start looking for the returned data. The following lines of code obtain a pointer to the first byte of data in the VARSTRING structure, cast this to a HANDLE*, and assign it to lpHandle. Then, the contents of the pointer's destination is copied into the hComm variable:

 LPHANDLE lpHandle = (HANDLE*)((LPBYTE)     lpVarString + lpVarString->dwStringOffset); HANDLE hComm = *lpHandle; 

The device's name follows the handle, and a pointer to this name is returned with the following code, which adds the size of a HANDLE to the dwStringOffset:

 cout   _T("Communications port: ")        (LPTSTR)((LPBYTE)lpVarString +       lpVarString->dwStringOffset +       sizeof(HANDLE))        endl; 

Sending and Receiving Data

Once the handle has been obtained from lineGetID, the functions ReadFile and WriteFile can be used. These are described in Chapter 9 ("Serial Communications"). In Listing 11.5b the SendAndReceive function is passed a string to the written to the communications port (in lpszSend) using WriteFile. This is converted from Unicode to ANSI. The function then goes on to read returned data from the communications port using ReadFile. This is converted into Unicode and returned in the szReceive parameter.

Listing 11.5b Sending and receiving data
 BOOL SendAndReceive(HANDLE hComm, LPTSTR lpszSend,     LPTSTR lpszReceive) {   DWORD dwBytesWritten, dwBytesRead;   DWORD dwBytesToWrite;   char szmbsSend[1024], szmbsReceive[1024];   dwBytesToWrite = wcstombs(szmbsSend, lpszSend, 1024);   if(!WriteFile(hComm, szmbsSend, dwBytesToWrite,       &dwBytesWritten, NULL))   {     cout   _T("Could not write file: ")            GetLastError()   endl;     return FALSE;   }   if(!ReadFile(hComm, szmbsReceive, 1024,       &dwBytesRead, NULL))   {     cout   _T("Could not read file: ")            GetLastError()   endl;     return FALSE;   }   lpszReceive[dwBytesRead] = '\0';   mbstowcs(lpszReceive, szmbsReceive, 1024);   cout   _T("Bytes Read: ")   dwBytesRead   endl;   cout   lpszReceive  endl;   return TRUE; } void Listing11_5() {   HANDLE hComm;   TCHAR szReceive[1024];   if(g_hLine == NULL)   {     cout   _T("No open line")   endl;     return;   }   hComm = GetCommPort();   SendAndReceive(hComm, _T("\n"), szReceive); } 

The function Listing11_5 in Listing 11.5b shows how the GetCommPort function can be called to obtain a serial communications port handle. Next, a call is made to SendAndReceive, which will send a new line character to the connected host and wait for data to come back. Notice that CloseHandle is not called doing so will terminate the call, which may not be desirable. The handle will be closed by TAPI when a lineClose function call is executed.


< BACK  NEXT >


Windows CE 3. 0 Application Programming
Windows CE 3.0: Application Programming (Prentice Hall Series on Microsoft Technologies)
ISBN: 0130255920
EAN: 2147483647
Year: 2002
Pages: 181

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net