C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
TAPI
Александр
Отправлено: 14.05.2004, 15:08


Не зарегистрирован







если ли у кгого рабочий пример использования TAPI (версия 2), когда можно получить handle открытого через TAPI com-порта и работать с ним уже как просто с com-портом, а не с TAPI-устройством?

ниже мой пример.
инициализация tapi проходит нормально, а вот WriteFile по полученному handle от com-порта возвращает ошибку.
в упор не ясно почему.

CODE

#include <windows.h>
#include <tapi.h>

#include <iostream>
#include <iomanip>

#include <cstdio>

#include "io.hpp"

std::ostream& os = std::cerr;

const std::string getSystemMessage( int error )
{
  LPVOID lpMsgBuf;

  FormatMessage(
     FORMAT_MESSAGE_ALLOCATE_BUFFER |
     FORMAT_MESSAGE_FROM_SYSTEM |
     FORMAT_MESSAGE_IGNORE_INSERTS,
     NULL,
     error,
     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
     (LPTSTR) &lpMsgBuf,
     0,
     NULL
  );

  std::string msg;

  if (lpMsgBuf)
     msg.assign((const char*)lpMsgBuf);

  LocalFree(lpMsgBuf);

  return msg;
}

// WINAPI WinMain(HINSTANCE self, HINSTANCE parent, LPSTR cmdLine, int show)
int main( int argc, char* argv[] )
{
  HLINE line;
  DWORD numDevs;
  DWORD apiVersion = MAKELONG( 1, 4 );
 
  char lineInitializeExParamsRaw[ 10240 ];
  LINEINITIALIZEEXPARAMS* lineInitializeExParams = (LINEINITIALIZEEXPARAMS *)lineInitializeExParamsRaw;
 
  HANDLE event;
 
  LONG result;
  int i;
 
  lineInitializeExParams->dwTotalSize = sizeof lineInitializeExParamsRaw;
  lineInitializeExParams->dwOptions = LINEINITIALIZEEXOPTION_USEEVENT;
 
  result = lineInitializeEx( &line, NULL, NULL, "Dialing", &numDevs, &apiVersion, lineInitializeExParams );

  if( result ) {
     std::cerr << "lineInitializeEx(): " << ext::Hex(8) << result << std::endl;
     exit( 1 );
  }

  event = lineInitializeExParams->Handles.hEvent;
 
  os << "available devices: " << std::dec << numDevs << std::endl;
 
  for( i = 0; i < numDevs; i++ ) {
     char lineDevCapsRaw[ 10240 ];
     LINEDEVCAPS* lineDevCaps = (LINEDEVCAPS *)lineDevCapsRaw;
     DWORD extVersion = 0;
     char buf[ 1024 ];
     
     os << std::endl;
     
     lineDevCaps->dwTotalSize = sizeof lineDevCapsRaw;
     
     os << "Quering device " << i << std::dec << std::endl;
     
     if( result = lineGetDevCaps( line, i, apiVersion, extVersion, lineDevCaps ) ) {
        os <<  "lineGetDevCaps(): " << ext::Hex(8) << result << std::endl;
        continue;
     }

     os << "Needed size: " << lineDevCaps->dwNeededSize << std::endl;

     os << lineDevCaps->dwLineNameSize << ", " <<
           std::string( (char *)lineDevCaps + lineDevCaps->dwLineNameOffset, lineDevCaps->dwLineNameSize ) << std::endl;
  }

  int device = 1;
 
  std::cin >> device;
 
  if( result = lineConfigDialog( device, NULL, NULL ) ) {
     std::cerr << "lineConfigDialog(): " << ext::Hex(8) << result << std::endl;
     exit( 1 );
  }

  HLINE link;

  if( result = lineOpen( line, device, &link, apiVersion, 0, NULL, LINECALLPRIVILEGE_OWNER, LINEMEDIAMODE_DATAMODEM, NULL ) ) {
     std::cerr << "lineOpen(): " << ext::Hex(8) << result << std::endl;
     exit( 1 );
  }

  char deviceIdRaw[ 10240 ];
  VARSTRING* deviceId = (VARSTRING *)deviceIdRaw;
 
  char deviceClass[ 1024 ] = "comm/datamodem";
 
  deviceId->dwTotalSize = sizeof deviceIdRaw;

  struct CommDatamodemInfo {
     HANDLE handle;
     CHAR deviceName[1];
  } *commDatamodemInfo;
   
  if( result = lineGetID( link, 0, NULL, LINECALLSELECT_LINE, deviceId, deviceClass ) ) {
     std::cerr << "lineGetID(): " << ext::Hex(8) << result << std::endl;
     exit( 1 );
  }

  os << "Device class: " << deviceClass << std::endl;

  commDatamodemInfo = (CommDatamodemInfo *)( (char *)deviceId + deviceId->dwStringOffset );
 
  os << "Modem: " << commDatamodemInfo->deviceName << std::endl;
  os << "HANDLE: " << ext::Hex(8) << commDatamodemInfo->handle << std::endl;
 
  DWORD bytes;
  char msg[1024] = "Yes!\n\r";
 
  char readBuf[ 1024 ];
  OVERLAPPED overlapped;
  memset( (void *)&overlapped, 0, sizeof overlapped );
  if( !( overlapped.hEvent = CreateEvent( NULL, TRUE, TRUE, NULL ) ) ) {
     os << "CreateEvent(): " << ext::Hex(8) << GetLastError() << ", " << getSystemMessage( GetLastError() ) << std::endl;
     exit( 1 );
  }
 
  if( !WriteFile( commDatamodemInfo->handle, msg, strlen( msg ), &bytes, &overlapped ) ) {
     os << "WriteFile(): " << ext::Hex(8) << GetLastError() << ", " << getSystemMessage( GetLastError() ) << std::endl;
     exit( 1 );
  }
 
  lineClose( link );
   
  lineShutdown( line );

  return 0;
}
** Дмитрий
Отправлено: 21.05.2004, 20:54


Не зарегистрирован







Дело в том, что при использовании TAPI порт открывается в асинхронном режиме, т. е. функция WriteFile возвращает значение до завершения операции записи в буфер порта. Естественно, что возвращаемое значение указывает на ошибку. Действовать в данном случае следует так:
bool WriteToPort(HANDLE hPort, BYTE * Buff, DWORD dwWriteSize)
{
//Для ReadFile
OVERLAPPED o;
FillMemory(&o,sizeof(OVERLAPPED),0);
o.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);

//Резульат работы WriteFile
BOOL fWriteStat = FALSE;

//Смещение в выходном буфере
DWORD dwTotal = 0;

//Число записанных байтов
DWORD dwBytesWritten = 0;

DWORD dwError;

fWriteStat = WriteFile(hPort,Buff,dwWriteSize,&dwBytesWritten,&o);

dwTotal = 0;
dwTotal += dwBytesWritten;
dwBytesWritten = 0;

if(!fWriteStat){
if(GetLastError() == ERROR_IO_PENDING){
while(!GetOverlappedResult(hPort,&o,&dwBytesWritten,TRUE)){
//Ждем завершения операции
dwError = GetLastError();
if(dwError == ERROR_IO_INCOMPLETE){
//Все путем
dwTotal += dwBytesWritten;
dwBytesWritten = 0;
continue;
}else{
//Если ошибка, то прерываем опрерацию
PurgeComm (hPort, PURGE_TXABORT|PURGE_RXABORT);
dwTotal = 0;
return false;
}
}
dwTotal += dwBytesWritten;
dwBytesWritten = 0;
//Запись куска завершена
MoveMemory(Buff,Buff + dwTotal,dwTotal);
}else{
//Если ошибка, то прерываем
PurgeComm (hPort, PURGE_TXABORT|PURGE_RXABORT);
dwTotal = 0;
return false;
}
}else{
//Если запись завершена
MoveMemory(Buff,Buff + dwTotal,dwTotal);
dwTotal = 0;
}

//Критическая секция на остановку
CloseHandle(o.hEvent);

//Критическая секция на остановку
return true;
}

Вернуться в Работа с внешними устройствами