⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ixjwin32.cxx

📁 sloedgy open sip stack source code
💻 CXX
📖 第 1 页 / 共 5 页
字号:
 * Revision 1.4  1999/10/28 12:21:34  robertj
 * Added AEC support and speakerphone switching button.
 *
 * Revision 1.3  1999/10/27 06:30:31  robertj
 * Added CancelIO command when closing channel.
 *
 * Revision 1.2  1999/10/24 14:51:41  robertj
 * Removed EnableDetectDTMF() as unix ioctl does not exist.
 *
 * Revision 1.1  1999/10/24 12:59:41  robertj
 * Added platform independent support for Quicknet xJACK cards.
 *
 */

#include <ptlib.h>

#include <lids/ixjlid.h>

////////////////////////////////////////////////
/// Get rid of LNK4221: no public symbols found; 
/// archive member will be inaccessible
const char * ixjwin32_file_content = NULL;
////////////////////////////////////////////////

#if HAS_IXJ

#include <lids/QTIoctl.h>
#include <lids/ixjDefs.h>

#pragma comment(lib, "winmm.lib")

#define NEW_DRIVER_VERSION ((5<<24)|(5<<16)|141)

#define new PNEW


static enum {
  IsWindows9x,
  IsWindowsNT,
  IsWindows2k
} GetOperatingSystem()
{
  static OSVERSIONINFO version;
  if (version.dwOSVersionInfoSize == 0) {
    version.dwOSVersionInfoSize = sizeof(version);
    GetVersionEx(&version);
  }
  if (version.dwPlatformId != VER_PLATFORM_WIN32_NT)
    return IsWindows9x;
  if (version.dwMajorVersion < 5)
    return IsWindowsNT;
  return IsWindows2k;
}

#define IsLineJACK() (dwCardType == 3)


/////////////////////////////////////////////////////////////////////////////

OpalIxJDevice::OpalIxJDevice()
{
  hDriver = INVALID_HANDLE_VALUE;
  driverVersion = 0;
  readStopped = writeStopped = TRUE;
  readFrameSize = writeFrameSize = 480;  // 30 milliseconds of 16 bit PCM data
  readCodecType = writeCodecType = P_MAX_INDEX;
  currentHookState = lastHookState = FALSE;
  inRawMode = FALSE;
  enabledAudioLine = UINT_MAX;
  exclusiveAudioMode = TRUE;
  lastDTMFDigit = 0;
  hReadEvent = hWriteEvent = NULL;
}


BOOL OpalIxJDevice::Open(const PString & device)
{
  Close();

  PTRACE(3, "xJack\tOpening IxJ device \"" << device << '"');

  DWORD dwDeviceId = device.AsUnsigned(16);

  PString devicePath;
  const char * DevicePathPrefix = "\\\\.\\QTJACKDevice";

  switch (GetOperatingSystem()) {
    case IsWindows2k :
      DevicePathPrefix = "\\\\.\\QTIWDMDevice";
      // Flow into NT case

    case IsWindowsNT :
      if (dwDeviceId < 100) {
        devicePath = device.Left(device.Find(' '));
        if (strspn(devicePath, "0123456789") == strlen(devicePath))
          devicePath = DevicePathPrefix + devicePath;
      }
      else {
        PStringArray allDevices = GetDeviceNames();
        for (PINDEX dev = 0; dev < allDevices.GetSize(); dev++) {
          PString thisDevice = allDevices[dev];
          if (thisDevice.Find(device) != P_MAX_INDEX) {
            devicePath = thisDevice.Left(thisDevice.Find(' '));
            break;
          }
        }
      }
      timeBeginPeriod(2);
      break;

    case IsWindows9x :
      devicePath = "\\\\.\\Qtipj.vxd";
  }

  hDriver = CreateFile(devicePath,
                       GENERIC_READ | GENERIC_WRITE,
                       FILE_SHARE_WRITE,
                       NULL,
                       OPEN_EXISTING,
                       FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
                       NULL);
  if (hDriver == INVALID_HANDLE_VALUE) {
    osError = ::GetLastError()|PWIN32ErrorFlag;
    return FALSE;
  }

  if (GetOperatingSystem() == IsWindows9x) {
    DWORD dwResult = 0;
    if (!IoControl(IOCTL_Device_Open, dwDeviceId, &dwResult) || dwResult == 0) {
      CloseHandle(hDriver);
      hDriver = INVALID_HANDLE_VALUE;
      osError = ENOENT;
      return FALSE;
    }
    deviceName = psprintf("%08X", dwDeviceId);
  }
  else {
    dwDeviceId = GetSerialNumber();
    if (dwDeviceId == 0) {
      CloseHandle(hDriver);
      hDriver = INVALID_HANDLE_VALUE;
      osError = ENOENT;
      return FALSE;
    }

    deviceName = devicePath;
  }

  dwCardType = dwDeviceId >> 28;

  IoControl(IOCTL_Codec_SetKHz, 8000);
  IoControl(IOCTL_Idle_SetMasterGain, 15);
  IoControl(IOCTL_Filter_EnableDTMFDetect);
  IoControl(IOCTL_Speakerphone_AECOn);

  DWORD ver = 0;
  IoControl(IOCTL_VxD_GetVersion, 0, &ver);
  driverVersion = ((ver&0xff)<<24)|((ver&0xff00)<<8)|((ver>>16)&0xffff);

  PTRACE(2, "xJack\tOpened IxJ device \"" << GetDescription() << "\" version "
         << ((driverVersion>>24)&0xff  ) << '.'
         << ((driverVersion>>16)&0xff  ) << '.'
         << ( driverVersion     &0xffff));

  os_handle = 1;

  return TRUE;
}


BOOL OpalIxJDevice::Close()
{
  if (!IsOpen())
    return FALSE;

  RingLine(0, 0);
  StopReadCodec(0);
  StopWriteCodec(0);
  StopRawCodec(0);
  SetLineToLineDirect(0, 1, TRUE); // Back to pass through mode

  if (GetOperatingSystem() == IsWindows9x)
    IoControl(IOCTL_Device_Close);
  else
    timeEndPeriod(2);

  deviceName = PString();

  if (hReadEvent != NULL) {
    CloseHandle(hReadEvent);
    hReadEvent = NULL;
  }
  if (hWriteEvent != NULL) {
    CloseHandle(hWriteEvent);
    hWriteEvent = NULL;
  }

  BOOL ok = CloseHandle(hDriver);
  hDriver = INVALID_HANDLE_VALUE;
  os_handle = -1;
  return ok;
}


PString OpalIxJDevice::GetDeviceType() const
{
  return OPAL_IXJ_TYPE_NAME;
}


PString OpalIxJDevice::GetDeviceName() const
{
  return deviceName;
}


PString OpalIxJDevice::GetDescription() const
{
  PStringStream name;

  name << "Internet ";

  switch (dwCardType) {
    case 0 :
    case 1 :
      name << "PhoneJACK";
      break;
    case 3 :
      name << "LineJACK";
      break;
    case 4 :
      name << "PhoneJACK-Lite";
      break;
    case 5 :
      name << "PhoneJACK-PCI";
      break;
    case 6 :
      name << "PhoneCARD";
      break;
    default :
      name << "xJACK";
  }

  name << " (" << deviceName << ')';

  return name;
}


PStringArray OpalIxJDevice::GetAllNames() const
{
  return GetDeviceNames();
}


unsigned OpalIxJDevice::GetLineCount()
{
  return IsLineJACK() ? NumLines : 1;
}


BOOL OpalIxJDevice::IsLinePresent(unsigned line, BOOL force)
{
  if (line >= GetLineCount())
    return FALSE;

  if (line != PSTNLine)
    return FALSE;

  int oldSlicState = -1;

  DWORD dwResult = 0;
  do {
    if (!IoControl(IOCTL_DevCtrl_GetLineTestResult, 0, &dwResult))
      return FALSE;
    if (dwResult == 0xffffffff || force) {
      if (dwResult == LINE_TEST_OK) {
        IoControl(IOCTL_DevCtrl_GetPotsToSlic, 0, &dwResult);
        oldSlicState = dwResult;
      }
      IoControl(IOCTL_DevCtrl_LineTest);
      dwResult = LINE_TEST_TESTING;
      force = FALSE;
    }
  } while (dwResult == LINE_TEST_TESTING);

  if (oldSlicState >= 0)
    IoControl(IOCTL_DevCtrl_SetPotsToSlic, oldSlicState);

  return dwResult == LINE_TEST_OK;
}


BOOL OpalIxJDevice::IsLineOffHook(unsigned line)
{
  if (line >= GetLineCount())
    return FALSE;

  DWORD dwResult = 0;

  if (line == PSTNLine) {
    if (!IoControl(IOCTL_DevCtrl_GetLineOnHook, 0, &dwResult))
      return FALSE;
    return dwResult == 0;
  }

  if (!IoControl(IsLineJACK() && IsLinePresent(PSTNLine)
                              ? IOCTL_DevCtrl_GetLinePhoneOnHook
			      : IOCTL_DevCtrl_GetOnHook, 0, &dwResult))
    return FALSE;

  BOOL newHookState = dwResult == 0;
  if (lastHookState != newHookState) {
    lastHookState = newHookState;
    hookTimeout = 250;
  }
  else {
    if (!hookTimeout.IsRunning())
      currentHookState = lastHookState;
  }

  return currentHookState;
}


BOOL OpalIxJDevice::SetLineOffHook(unsigned line, BOOL newState)
{
  if (line >= GetLineCount())
    return FALSE;

  if (line != PSTNLine)
    return FALSE;

  return IoControl(IOCTL_DevCtrl_LineSetOnHook, !newState);
}


BOOL OpalIxJDevice::HasHookFlash(unsigned line)
{
  if (line != POTSLine)
    return FALSE;

  DWORD dwResult;
  if (!IoControl(IOCTL_DevCtrl_GetFlashState, 0, &dwResult))
    return FALSE;

  if (lastFlashState == dwResult)
    return FALSE;

  lastFlashState = dwResult;
  return dwResult != 0;
}


BOOL OpalIxJDevice::IsLineRinging(unsigned line, DWORD * /*cadence*/)
{
  if (line >= GetLineCount())
    return FALSE;

  if (line != PSTNLine)
    return FALSE;

  if (ringTimeout.IsRunning())
    return TRUE;

  DWORD dwResult = 0;
  if (!IoControl(IOCTL_DevCtrl_LineGetRinging, 0, &dwResult) || dwResult == 0)
    return FALSE;

  ringTimeout = 2500;
  return TRUE;
}


BOOL OpalIxJDevice::RingLine(unsigned line, DWORD cadence)
{
  if (line >= GetLineCount())
    return FALSE;

  if (line != POTSLine)
    return FALSE;

  if (cadence == TRUE) {
    switch (countryCode) {
      case Australia :
        static unsigned AusRing[] = { 200, 400, 200, 2000 };
        return RingLine(line, PARRAYSIZE(AusRing), AusRing);
    }

    // United States ring pattern
    cadence = 0x00f;
  }

  IoControl(IOCTL_DevCtrl_SetPotsToSlic, 1);
  return IoControl(IOCTL_DevCtrl_SetRingPattern, cadence);
}


BOOL OpalIxJDevice::RingLine(unsigned line, PINDEX nCadence, unsigned * pattern)
{
  if (line >= GetLineCount())
    return FALSE;

  if (line != POTSLine)
    return FALSE;

  IoControl(IOCTL_DevCtrl_SetPotsToSlic, 1);


  DWORD dwReturn, dwSize;
  DWORD cadenceArray[10];
  cadenceArray[0] = (nCadence+1)/2; // Number of pairs
  cadenceArray[1] = (nCadence&1) == 0; // If odd then repeat last entry
  PINDEX i;
  for (i = 2; i < nCadence; i++)
    cadenceArray[i] = pattern[i-2];
  for (; i < PARRAYSIZE(cadenceArray); i++)
    cadenceArray[i] = 0;

  return IoControl(IOCTL_DevCtrl_SetRingCadence,
                   cadenceArray, sizeof(cadenceArray),
                   &dwReturn, sizeof(dwReturn), &dwSize);
}


BOOL OpalIxJDevice::IsLineDisconnected(unsigned line, BOOL checkForWink)
{
  if (line >= GetLineCount())
    return FALSE;

  if (line != PSTNLine)
    return !IsLineOffHook(line);

  if (checkForWink) {
    DWORD dwResult = 0;
    if (IoControl(IOCTL_DevCtrl_GetLineCallerOnHook, 0, &dwResult) && dwResult != 0) {
      PTRACE(3, "xJack\tDetected wink, line disconnected.");
      return TRUE;
    }
  }

/*  if ((IsToneDetected(line) & (DialTone|BusyTone)) != 0) { */
  if ((IsToneDetected(line) & BusyTone) != 0) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -