📄 ixjunix.cxx
字号:
/* * ixjunix.cxx * * QuickNet Internet Phone/Line JACK codec interface * * Open H323 Library * * Copyright (c) 1999-2000 Equivalence Pty. Ltd. * * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is Open H323 Library. * * The Initial Developer of the Original Code is Equivalence Pty. Ltd. * * Portions of this code were written with the assisance of funding from * Quicknet Technologies, Inc. http://www.quicknet.net. * * Contributor(s): ______________________________________. * * $Log: ixjunix.cxx,v $ * Revision 1.58 2000/07/03 10:33:38 craigs * Fixed autohook option to work with PhoneCARD * * Revision 1.57 2000/07/02 14:13:19 craigs * Added delay when reading from codec whilst writing stopped * * Revision 1.56 2000/06/22 02:46:16 craigs * Improved ring detection * * Revision 1.55 2000/06/17 04:11:13 craigs * Fixed problem with potential codec startup problem in Linux IXJ driver * Moved Linux specific variables to Linux specific section * * Revision 1.54 2000/05/29 01:56:36 craigs * Added timeout on WriteFrame to help avoid lockups * * Revision 1.53 2000/05/25 08:42:33 craigs * Added detection of bugus get_rec_vol in ixj driver * * Revision 1.52 2000/05/24 12:44:41 craigs * Fixed compile warnings * * Revision 1.51 2000/05/24 06:43:16 craigs * Added routines to get xJack volume * Fixed problem with receiving G>723.1 NULL frames * * Revision 1.50 2000/05/22 14:26:38 craigs * Added read/write interlock to avoid codec lockup due to writing whilst read not enabled * Added select before write to avoid EINTR under debugger * * Revision 1.49 2000/05/18 02:28:43 craigs * Removed possibly dangerous checkes for uninitialised return values from * ixj driver * * Revision 1.48 2000/05/02 04:32:27 robertj * Fixed copyright notice comment. * * Revision 1.47 2000/04/17 07:25:08 craigs * Fixed problems with incorrect caller ID parsing, and ensured that caller ID * is cleared after every call * * Revision 1.46 2000/04/17 00:58:01 craigs * Added support for latest Quicknet driver with caller ID transmission * * Revision 1.45 2000/04/13 23:08:01 craigs * Fixed problems with callerId not compiling on all systems * * Revision 1.44 2000/04/10 21:23:41 robertj * Removed "return" that disabled the dynamic changing of AEC levels. * * Revision 1.43 2000/04/06 19:29:04 craigs * Removed all vestiges of the old IXJ driver * * Revision 1.42 2000/04/05 18:25:00 robertj * Changed caller ID code for better portability. * * Revision 1.41 2000/04/05 18:15:18 craigs * Added locks to prevent problems with codec lockup during fast start * * Revision 1.40 2000/04/05 16:27:16 craigs * Added caller ID transmission, and started proper ring detection etc * * Revision 1.39 2000/04/05 04:09:49 robertj * Removed PCM as valid codec type. * * Revision 1.38 2000/04/04 08:22:14 rogerh * Wrap GetPayloadTypes() in #ifdef LINUX_TELEPHONY * * Revision 1.37 2000/04/04 01:34:03 craigs * Added better detection of open errors * Fixed problem with PlayTone * * Revision 1.36 2000/03/30 19:33:37 robertj * Added function to get available codecs from driver. * Fixed name strings for various card types. * * Revision 1.35 2000/03/28 05:24:08 craigs * Fixed problem with country code * * Revision 1.34 2000/03/28 04:02:53 craigs * Added code to stop codecs when PSTN line goes onhook * * Revision 1.33 2000/03/28 03:42:07 craigs * Added extra stuff to try and make tones work properly * * Revision 1.32 2000/03/21 03:23:46 craigs * Added GetLineCount function * * Revision 1.31 2000/03/08 00:25:52 robertj * Fixed correct setting of country DAA codes from T35 country code. * * Revision 1.30 2000/02/19 23:49:33 robertj * Fixed problem with unresolved SetRemoveDTMF function when not using linux telephony. * * Revision 1.29 2000/01/07 11:04:03 robertj * New telephony API compatibility * * Revision 1.28 2000/01/07 10:01:03 robertj * dditions and changes to line interface device base class. * * Revision 1.27 2000/01/04 00:21:55 craigs * Fixed sense of line test * * Revision 1.26 1999/12/29 01:18:07 craigs * Fixed problem with codecs other than G.711 not working after reorganisation * * Revision 1.25 1999/12/24 00:28:03 robertj * Changes to IXJ interface to follow LID abstraction * * Revision 1.24 1999/12/19 23:48:50 craigs * Added detection of multiple xJack cards * * Revision 1.23 1999/12/11 00:01:39 robertj * Added Wink indication function. * * Revision 1.22 1999/12/08 21:54:05 craigs * Removed extraneous DSP reset at the advice of Ed Okerson * * Revision 1.21 1999/11/29 04:50:11 robertj * Added adaptive threshold calculation to silence detection. * * Revision 1.20 1999/11/19 09:29:53 robertj * Fixed problems with aycnhronous shut down of logical channels. * * 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>#include "ixjlid.h"#include <sys/time.h>#define new PNEW#define IsLineJACK() (dwCardType==300)/////////////////////////////////////////////////////////////////////////////OpalIxJDevice::OpalIxJDevice(){ os_handle = -1; readStopped = writeStopped = TRUE; readFrameSize = writeFrameSize = 480; // 30 milliseconds of 16 bit PCM data readCodecType = writeCodecType = LINEAR16; aecLevel = AECOff; tonePlaying = FALSE; removeDTMF = FALSE;#ifdef IXJCTL_VMWI callerIdInfo.name[0] = '\0';#endif}BOOL OpalIxJDevice::Open(const PString & device){ Close(); if (!isdigit(device[0])) deviceName = device; else deviceName = psprintf("/dev/phone%u", device.AsUnsigned()); int new_handle = os_handle = ::open(deviceName, O_RDWR); if (!ConvertOSError(new_handle)) return FALSE; os_handle = new_handle; // determine if the card is a phonejack or linejack dwCardType = ::ioctl(os_handle, IXJCTL_CARDTYPE); char * str = ::getenv("IXJ_COUNTRY"); if (str != NULL) { if (isdigit(*str)) SetCountryCode((T35CountryCodes)atoi(str)); else OpalLineInterfaceDevice::SetCountryCode(PString(str)); } ::ioctl(os_handle, PHONE_CPT_STOP); ::ioctl(os_handle, IXJCTL_DSP_IDLE); ::ioctl(os_handle, PHONE_EXCEPTION); memset(&exceptionBits, 0, sizeof(exceptionBits)); return TRUE;}BOOL OpalIxJDevice::Close(){ if (!IsOpen()) return FALSE; StopReadCodec(0); StopWriteCodec(0); RingLine(0, 0); SetLineToLineDirect(0, 1, TRUE); deviceName = PString(); int stat = ::close(os_handle); os_handle = -1; return ConvertOSError(stat);}PString OpalIxJDevice::GetName() const{ switch (dwCardType) { case 100: return "PhoneJACK-ISA " + deviceName; case 300: return "LineJACK " + deviceName; case 400: return "PhoneJACK-Lite " + deviceName; case 500: return "PhoneJACK-PCI " + deviceName; case 600: return "PhoneCARD " + deviceName; } return "xJACK " + deviceName;}unsigned OpalIxJDevice::GetLineCount(){ return IsLineJACK() ? NumLines : 1;}BOOL OpalIxJDevice::IsLinePresent(unsigned line){ if (line != PSTNLine) return FALSE; return ::ioctl(os_handle, IXJCTL_PSTN_LINETEST) == 1;}BOOL OpalIxJDevice::IsLineOffHook(unsigned line){ int hook; if (line == POTSLine) { hook = ::ioctl(os_handle, PHONE_HOOKSTATE); if (ConvertOSError(hook)) return hook != 0; } else { hook = ::ioctl(os_handle, PHONE_PSTN_GET_STATE); if (ConvertOSError(hook)) return hook == PSTN_OFF_HOOK; } return FALSE;}BOOL OpalIxJDevice::SetLineOffHook(unsigned line, BOOL newState){ if (line != PSTNLine) return FALSE; if (newState == PSTN_ON_HOOK) { StopReadCodec(line); StopWriteCodec(line); } int state = newState ? PSTN_OFF_HOOK : PSTN_ON_HOOK; for (;;) { ::ioctl(os_handle, PHONE_PSTN_SET_STATE, state); int v = ::ioctl(os_handle, PHONE_PSTN_GET_STATE); if (v == state) break; } return TRUE;}void OpalIxJDevice::GetException(telephony_exception & exceptionBits){ fd_set fds; FD_ZERO(&fds); FD_SET(os_handle, &fds); struct timeval time; time.tv_sec = time.tv_usec = 0; ::select(os_handle+1, NULL, NULL, &fds, &time); if (FD_ISSET(os_handle, &fds)) exceptionBits.bytes = ::ioctl(os_handle, PHONE_EXCEPTION); else memset(&exceptionBits, 0, sizeof(exceptionBits));}BOOL OpalIxJDevice::GetRingState(){ if (exceptionBits.bits.pstn_ring == 0) GetException(exceptionBits); if (exceptionBits.bits.pstn_ring != 0) {cout << "Exception ring bit set" << endl; exceptionBits.bits.pstn_ring = 0; return TRUE; } return FALSE;}BOOL OpalIxJDevice::IsLineRinging(unsigned line, DWORD * /*cadence*/){ if (line != PSTNLine) return FALSE; if (GetRingState()) lastRingTime = 5000; BOOL stat = lastRingTime.IsRunning();// if (stat)// cout << "Line is ringing" << endl; return stat;}BOOL OpalIxJDevice::RingLine(unsigned line, DWORD cadence){ if (line != 0) return FALSE; if (cadence == 0) return ConvertOSError(::ioctl(os_handle, PHONE_RING_STOP)); //if (!ConvertOSError(::ioctl(os_handle, PHONE_RING_CADENCE, cadence))) // return FALSE; int stat; // Need to add something to set caller ID here#ifdef IXJCTL_VMWI if (callerIdInfo.name[0] != '\0') { stat = ::ioctl(os_handle, PHONE_RING_START, &callerIdInfo); SetCallerID(line, ""); } else#endif stat = ::ioctl(os_handle, PHONE_RING_START); return ConvertOSError(stat);}BOOL OpalIxJDevice::IsLineDisconnected(unsigned line){ fd_set fds; FD_ZERO(&fds); FD_SET(os_handle, &fds); struct timeval time; time.tv_sec = time.tv_usec = 0; ::select(os_handle+1, NULL, NULL, &fds, &time); if (FD_ISSET(os_handle, &fds)) { telephony_exception ixje; ixje.bytes = ::ioctl(os_handle, PHONE_EXCEPTION); if (ixje.bits.pstn_wink != 0) return TRUE; } return OpalLineInterfaceDevice::IsLineDisconnected(line);}BOOL OpalIxJDevice::SetLineToLineDirect(unsigned line1, unsigned line2, BOOL connect){ return FALSE;}BOOL OpalIxJDevice::IsLineToLineDirect(unsigned line1, unsigned line2){ return FALSE;}BOOL OpalIxJDevice::ConvertOSError(int err) { PChannel::Errors normalisedError; return PChannel::ConvertOSError(err, normalisedError, osError);}static const struct { RTP_DataFrame::PayloadTypes rtpType; PINDEX frameSize; int mode; int depth;} CodecInfo[] = { { RTP_DataFrame::L16_Mono, 480, LINEAR16, 1 }, { RTP_DataFrame::PCMU, 240, ULAW, 2 }, { RTP_DataFrame::PCMA, 240, ALAW, 2 }, { RTP_DataFrame::G728, 96, G728, 2 /* 5 */ }, { RTP_DataFrame::G729, 10, G729, 2 /* 8 */ }, { RTP_DataFrame::G7231, 24, G723_63, 2 /*10 */ }};PIntArray OpalIxJDevice::GetPayloadTypes() const{ PIntArray codecs; PINDEX idx = PARRAYSIZE(CodecInfo); while (idx-- > 1) { // Stop before we get to PCM phone_capability cap; cap.captype = codec; cap.cap = CodecInfo[idx].mode; if (::ioctl(os_handle, PHONE_CAPABILITIES_CHECK, &cap)) codecs.SetAt(codecs.GetSize(), CodecInfo[idx].rtpType); } return codecs;}BOOL OpalIxJDevice::SetReadCodec(unsigned, RTP_DataFrame::PayloadTypes rtpType){ { PWaitAndSignal mutex(toneMutex); if (tonePlaying) { tonePlaying = FALSE; ::ioctl(os_handle, PHONE_CPT_STOP); } } PWaitAndSignal mutex(readMutex); ::ioctl(os_handle, PHONE_REC_STOP); readStopped = TRUE; PINDEX codec; for (codec = 0; codec < PARRAYSIZE(CodecInfo); codec++) if (CodecInfo[codec].rtpType == rtpType) break; if (codec >= PARRAYSIZE(CodecInfo)) return FALSE; PTRACE(2, "IXJ\tSetting read codec to " << CodecInfo[codec].mode); readCodecType = CodecInfo[codec].mode; readFrameSize = CodecInfo[codec].frameSize; int stat = ::ioctl(os_handle, PHONE_REC_CODEC, CodecInfo[codec].mode); if (stat != 0) { PTRACE(1, "IXJ\tSecond try on set record codec"); stat = ::ioctl(os_handle, PHONE_REC_CODEC, CodecInfo[codec].mode); if (!ConvertOSError(stat)) return FALSE; } // PHONE_REC_DEPTH does not set return value ::ioctl(os_handle, PHONE_REC_DEPTH, CodecInfo[codec].depth);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -