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

📄 ixjunix.cxx

📁 sloedgy open sip stack source code
💻 CXX
📖 第 1 页 / 共 5 页
字号:
 * Revision 1.19  1999/11/18 11:45:40  robertj
 * Added missing function from recent tone enhancements.
 *
 * Revision 1.18  1999/11/16 12:44:46  robertj
 * Added more tone generation functions.
 *
 * Revision 1.17  1999/11/06 13:01:48  craigs
 * Fixed problems with GSM emulation mode
 *
 * Revision 1.16  1999/11/06 05:44:08  robertj
 * Fixed problem with read/write locking up when stopping codec.
 *
 * Revision 1.15  1999/11/06 03:45:27  robertj
 * Added volume control functions.
 *
 * Revision 1.14  1999/11/05 10:56:25  craigs
 * New implementation for new channel breakdown
 *
 * Revision 1.13  1999/11/02 01:22:55  robertj
 * Added return values to new tone functions and added GetCallerID() function
 *
 * Revision 1.12  1999/11/01 23:20:49  craigs
 * Added country code initialisation and DTMF tone playing
 *
 * Revision 1.11  1999/11/01 09:28:36  robertj
 * Added flunction to enabled/disable DTM detection
 *
 * Revision 1.10  1999/10/30 15:10:36  craigs
 * Removed checks for return status from DSP start and stop functions
 *
 * Revision 1.9  1999/10/30 15:03:10  robertj
 * Fixed conditions under which codec start stops are not called.
 *
 * Revision 1.8  1999/10/30 13:29:45  robertj
 * Fixed "lock up" problem, added function to get line status.
 *
 * Revision 1.7  1999/10/30 07:21:46  craigs
 * Removed interlock between hookstate and audio path select as Quicknet has updated the driver
 *
 * Revision 1.6  1999/10/30 06:41:06  craigs
 * Fixed problem with badly named devices using ordinals to open
 *
 * Revision 1.5  1999/10/29 02:28:02  robertj
 * Added backward compatibility code so can use simple number for device name.
 *
 * Revision 1.4  1999/10/28 12:47:23  robertj
 * *** empty log message ***
 *
 * Revision 1.3  1999/10/28 12:38:14  robertj
 * Changed AEC to enum for specific values.
 *
 * Revision 1.2  1999/10/26 07:13:44  craigs
 * Fixed problem where handset is reported off-hook when phone not selected for audio path
 *
 * Revision 1.1  1999/10/24 14:43:20  robertj
 * Added platform independent support for Quicknet xJACK cards.
 *
 */

#include <ptlib.h>

#ifdef __GNUC__
#pragma implementation "ixjlid.h"
#endif

#include <lids/ixjlid.h>

#ifdef HAS_IXJ

#include <sys/time.h>
#include <math.h>

#define new PNEW

#ifndef TELEPHONY_VERSION
#if   !defined(PHONE_VAD)
#warning Using extremely old telephony.h, please upgrade!
#define TELEPHONY_VERSION 1000  // Version in 2.2.16 kernel
#elif !defined(IXJCTL_VMWI)
#warning Using very old telephony.h, please upgrade!
#define TELEPHONY_VERSION 2000  // Version in 2.2.18 kernel
#else
#warning Using old telephony.h, please upgrade!
#define TELEPHONY_VERSION 3000  // Version in CVS before addition of TELEPHONY_VERSION
#endif
#endif


#define	IsLineJACK()	(dwCardType == LineJACK)

#define	FLASH_TIME	1000
#define	MANUAL_FLASH		// undefine to use FLASH exception

#ifdef P_LINUX

#ifdef _DEBUG

static int traced_ioctl(const char * str, int fd, int code)
{
  PTRACE(6,"IXJ\tIOCTL(" << fd << ", " << str << ")");
  int val = ::ioctl(fd,code);
  PTRACE(6,"IXJ\tIOCTL value = " << val);
  return val;
}

static int traced_ioctl(const char * str, int fd, int code , unsigned long arg)
{
  PTRACE(6,"IXJ\tIOCTL(" << fd << ", " << str << ", " << (void *)arg << ")");
  int val = ::ioctl(fd,code,arg);
  PTRACE(6,"IXJ\tIOCTL value = " << val);
  return val;
}

#define	IOCTL(fd,code)		traced_ioctl(#code, fd, code)
#define	IOCTL2(fd,code,arg)	traced_ioctl(#code, fd, code, (unsigned long)(arg))
#define	IOCTLP(fd,code,arg)	::ioctl(fd,code,arg)

#else

#define	IOCTL(fd,code)		::ioctl(fd,code)
#define	IOCTL2(fd,code,arg)	::ioctl(fd,code,arg)
#define	IOCTLP(fd,code,arg)	::ioctl(fd,code,arg)

#endif
#endif  // P_LINUX

#if TELEPHONY_VERSION < 3013
#define G729B 13
#endif


#ifdef P_FREEBSD
// BSD does not support return values from the ioctl() call
// except via the 3rd parameter.
// Also the 3rd parameter must be the 'address' of the data.

#ifdef _DEBUG

static int traced_bsd_ioctl(const char * str, int fd, int code , unsigned long arg = 0)
{
  int val = arg;
  int ret;
  PTRACE(6,"IXJ\tIOCTL(" << fd << ", " << str << ", " << (void *)arg << ")");
  ret = ::ioctl(fd,code, &arg);
  PTRACE(6,"IXJ\tIOCTL value = " << val);
  return ret;
}

#define	IOCTL(fd,code)		traced_bsd_ioctl(#code, fd, code)
#define	IOCTL2(fd,code,arg)	traced_bsd_ioctl(#code, fd, code, (unsigned long)(arg))
#define	IOCTLP(fd,code,arg)	::ioctl(fd,code,arg)

#else

static int bsd_ioctl(int fd, int code , unsigned long arg = 0)
{
  int val = arg;
  int ret;
  ret = ::ioctl(fd,code, &val);
  return ret;
}

#define	IOCTL(fd,code)		bsd_ioctl(fd,code,0)
#define	IOCTL2(fd,code,arg)	bsd_ioctl(fd,code,(unsigned long)(arg))
#define	IOCTLP(fd,code,arg)	::ioctl(fd,code,arg)

#endif
#endif  // P_FREEBSD

OpalIxJDevice::ExceptionInfo OpalIxJDevice::exceptionInfo[OpalIxJDevice::MaxIxjDevices];
PMutex                       OpalIxJDevice::exceptionMutex;
BOOL                         OpalIxJDevice::exceptionInit = FALSE;

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

/*

struct phone_except {
        unsigned int dtmf_ready:1;
        unsigned int hookstate:1;
        unsigned int flash:1;
        unsigned int pstn_ring:1;
        unsigned int caller_id:1;
        unsigned int pstn_wink:1;
        unsigned int f0:1;
        unsigned int f1:1;
        unsigned int f2:1;
        unsigned int f3:1;
        unsigned int fc0:1;
        unsigned int fc1:1;
        unsigned int fc2:1;
        unsigned int fc3:1;
        unsigned int reserved:18;
};

union telephony_exception {
        struct phone_except bits;
        unsigned int bytes;
};

*/

void OpalIxJDevice::SignalHandler(int sig)
{
  // construct list of fds to check
  fd_set  efds;
  FD_ZERO(&efds);
  PINDEX i;
  int maxHandle = 0;
  for (i = 0; i < MaxIxjDevices; i++) 
    if (exceptionInfo[i].fd >= 0) {
      FD_SET(exceptionInfo[i].fd, &efds);
      if (exceptionInfo[i].fd > maxHandle)
        maxHandle = exceptionInfo[i].fd;
    }

  // do not delay
  struct timeval  tv;
  tv.tv_sec = tv.tv_usec = 0;

  // get exception status
  int stat = select(maxHandle+1, NULL, NULL, &efds, &tv);

  // check for exceptions
  if (stat > 0) {
    for (i = 0; i < MaxIxjDevices; i++) {
      if ((exceptionInfo[i].fd >= 0) && FD_ISSET(exceptionInfo[i].fd, &efds)) {

        ExceptionInfo & info = exceptionInfo[i];
        int fd                     = info.fd;
        telephony_exception & data = info.data;
        data.bytes = IOCTL(fd, PHONE_EXCEPTION);

        if (data.bits.dtmf_ready) {
          //printf("dtmf\n");
          char ch = IOCTL(fd, PHONE_GET_DTMF_ASCII);
          int p = info.dtmfIn;
          info.dtmf[p] = ch;
          p = (p + 1) % 16;
          if (p != info.dtmfOut)
            info.dtmfIn = p;
        }

        if (data.bits.pstn_ring) 
          info.hasRing = TRUE;

        if (data.bits.hookstate) {
          BOOL newHookState = (IOCTL(fd, PHONE_HOOKSTATE) & 1) != 0;
#ifdef MANUAL_FLASH
          if (newHookState != info.hookState) {
            timeval now;
            gettimeofday(&now, NULL);
            long diff = (now.tv_sec - info.lastHookChange.tv_sec) * 1000000;
            diff += now.tv_usec - info.lastHookChange.tv_usec;
            diff = (diff + 500) / 1000;
            if (newHookState && (diff < FLASH_TIME))
              info.hasFlash = TRUE;
            info.lastHookChange = now;
          }
#endif
          info.hookState = newHookState;
        }

#ifndef MANUAL_FLASH
        if (data.bits.flash) {
          info.hasFlash = TRUE;
          //printf("flash detected\n");
        }
#endif

        if (data.bits.pstn_wink)
          info.hasWink = TRUE;

        if (data.bits.f0) {
          //printf("Filter 0 trigger\n");
          info.filter[0] = TRUE;
        }
        if (data.bits.f1) {
          //printf("Filter 0 trigger\n");
          info.filter[1] = TRUE;
        }
        if (data.bits.f2) {
          //printf("Filter 0 trigger\n");
          info.filter[2] = TRUE;
        }
        if (data.bits.f3) {
          //printf("Filter 0 trigger\n");
          info.filter[3] = TRUE;
        }

#if TELEPHONY_VERSION >= 2000
        if (data.bits.fc0) {
          //printf("Cadence 0 trigger\n");
          info.cadence[0] = TRUE;
        }
        if (data.bits.fc1) {
          //printf("Cadence 1 trigger\n");
          info.cadence[1] = TRUE;
        }
        if (data.bits.fc2) {
          //printf("Cadence 2 trigger\n");
          info.cadence[2] = TRUE;
        }
        if (data.bits.fc3) {
          //printf("Cadence 3 trigger\n");
          info.cadence[3] = TRUE;
        }
#endif

#if TELEPHONY_VERSION >= 3000
        if (data.bits.caller_id) {
          ::ioctl(fd, IXJCTL_CID, &exceptionInfo[i].cid);
          info.hasCid = TRUE;
          //printf("caller ID signal\n");
        }
#endif
      }
    }
  }

  signal(SIGIO, &OpalIxJDevice::SignalHandler);
}

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

OpalIxJDevice::OpalIxJDevice()
{
  os_handle = -1;
  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;
  aecLevel = AECOff;
  tonePlaying = FALSE;
  removeDTMF = FALSE;
#if TELEPHONY_VERSION >= 3000
  memset(&callerIdInfo, 0, sizeof(callerIdInfo));
#endif
}


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

  // initialise the exception information, if required
  {
    PWaitAndSignal m(exceptionMutex);
    if (!exceptionInit) {
      PINDEX i;
      for (i = 0; i < MaxIxjDevices; i++)
        exceptionInfo[i].fd = -1;
      exceptionInit = TRUE;
    }
  }

  if (isdigit(device[0])) 
    deviceName = psprintf("/dev/phone%u", device.AsUnsigned());
  else {
    PINDEX pos = device.FindLast(' ');
    if (pos == P_MAX_INDEX)
      deviceName = device;
    else
      deviceName = device.Mid(pos+1).Trim();
  }

  int new_handle = os_handle = ::open(deviceName, O_RDWR);
  if (!ConvertOSError(new_handle))
    return FALSE;
  currentHookState = lastHookState = 
    (IOCTL(os_handle, PHONE_HOOKSTATE) != 0);

  // add the new handle to the exception info
  {
    PWaitAndSignal m(exceptionMutex);
    PINDEX i;
    for (i = 0; i < MaxIxjDevices; i++) 
      if (exceptionInfo[i].fd < 0) 
        break;
    PAssert(i < MaxIxjDevices, "too many IXJ devices open");

    ExceptionInfo & info = exceptionInfo[i];
    memset(&info, 0, sizeof(info));

    info.fd  = os_handle;
    info.hookState  = currentHookState;
    info.hasRing    = FALSE;
    info.hasWink    = FALSE;
    info.hasFlash   = FALSE;
    timerclear(&info.lastHookChange);

#if TELEPHONY_VERSION >= 3000
    info.hasCid     = FALSE;
#endif
    for (i = 0; i < 4; i++) {
      info.cadence[i] = FALSE;
      info.filter[i]  = FALSE;
    }

#ifdef IXJCTL_SIGCTL
    // enable all events except read/write
    IXJ_SIGDEF sigdef;

    sigdef.signal = SIGIO;
    sigdef.event = SIG_DTMF_READY; IOCTLP(os_handle, IXJCTL_SIGCTL, &sigdef);
    sigdef.event = SIG_HOOKSTATE;  IOCTLP(os_handle, IXJCTL_SIGCTL, &sigdef);
    sigdef.event = SIG_PSTN_RING;  IOCTLP(os_handle, IXJCTL_SIGCTL, &sigdef);
    sigdef.event = SIG_CALLER_ID;  IOCTLP(os_handle, IXJCTL_SIGCTL, &sigdef);
    sigdef.event = SIG_PSTN_WINK;  IOCTLP(os_handle, IXJCTL_SIGCTL, &sigdef);
    sigdef.event = SIG_F0;         IOCTLP(os_handle, IXJCTL_SIGCTL, &sigdef);
    sigdef.event = SIG_F1;         IOCTLP(os_handle, IXJCTL_SIGCTL, &sigdef);
    sigdef.event = SIG_F2;         IOCTLP(os_handle, IXJCTL_SIGCTL, &sigdef);
    sigdef.event = SIG_F3;         IOCTLP(os_handle, IXJCTL_SIGCTL, &sigdef);
    sigdef.event = SIG_FC0;        IOCTLP(os_handle, IXJCTL_SIGCTL, &sigdef);
    sigdef.event = SIG_FC1;        IOCTLP(os_handle, IXJCTL_SIGCTL, &sigdef);
    sigdef.event = SIG_FC2;        IOCTLP(os_handle, IXJCTL_SIGCTL, &sigdef);
    sigdef.event = SIG_FC3;        IOCTLP(os_handle, IXJCTL_SIGCTL, &sigdef);
#ifndef MANUAL_FLASH
    sigdef.event = SIG_FLASH;       IOCTLP(os_handle, IXJCTL_SIGCTL, &sigdef);
#endif

    sigdef.signal = 0;
    sigdef.event  = SIG_READ_READY;  IOCTLP(os_handle, IXJCTL_SIGCTL, &sigdef);
    sigdef.event  = SIG_WRITE_READY; IOCTLP(os_handle, IXJCTL_SIGCTL, &sigdef);
#ifdef MANUAL_FLASH
    sigdef.event = SIG_FLASH;       IOCTLP(os_handle, IXJCTL_SIGCTL, &sigdef);
#endif
#endif

    fcntl(os_handle, F_SETOWN, getpid());
    int f = fcntl(os_handle, F_GETFL);
    fcntl(os_handle, F_SETFL, f | FASYNC);
    signal(SIGIO, &OpalIxJDevice::SignalHandler);
  }

  os_handle = new_handle;

  // determine if the card is a phonejack or linejack
  dwCardType = IOCTL(os_handle, IXJCTL_CARDTYPE);
  switch (dwCardType) {
  case 3:
    dwCardType = PhoneJACK_PCI_TJ;
    break;
  case 0x100: 
  case 100:
    dwCardType = PhoneJACK;
    break;
  case 0x300:
  case 300:
    dwCardType = LineJACK;
    break;
  case 0x400:
  case 400:
    dwCardType = PhoneJACK_Lite;
    break;
  case 0x500:
  case 500: 
    dwCardType = PhoneJACK_PCI;
    break;
  case 0x600:
  case 600:
    dwCardType = PhoneCARD;

⌨️ 快捷键说明

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