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

📄 vblasterlid.cxx

📁 sloedgy open sip stack source code
💻 CXX
📖 第 1 页 / 共 3 页
字号:
/*
 * vblasterlid.cxx
 *
 * Creative Labs VOIP Blaster codec interface
 *
 * Open H323 Library
 *
 * Copyright (c) 2001 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.
 *
 * Contributor(s): ______________________________________.
 *
 * $Log: vblasterlid.cxx,v $
 * Revision 1.3  2007/06/04 16:06:30  joegenbaclor
 * *** empty log message ***
 *
 * Revision 1.2  2006/10/12 05:28:00  joegenbaclor
 * fixed compile error in VC 2005
 *
 * Revision 1.1  2006/06/26 03:03:21  joegenbaclor
 * I have decided to include the latest development realease  of OPAL tagged Deimos Devel 1 (June 8 2006) as inegrated classes to opensipstack to avoid future version conflicts due to the fast pace in OPAL development.   This move is also aimed to reduce the size of projects using OPAL componets such as the soon to be relased OpenSIPPhone.
 *
 * Revision 2.7  2004/10/06 13:03:42  rjongbloed
 * Added "configure" support for known LIDs
 * Changed LID GetName() function to be normalised against the GetAllNames()
 *   return values and fixed the pre-factory registration system.
 * Added a GetDescription() function to do what the previous GetName() did.
 *
 * Revision 2.6  2004/02/19 10:47:05  rjongbloed
 * Merged OpenH323 version 1.13.1 changes.
 *
 * Revision 2.5  2003/03/24 07:18:30  robertj
 * Added registration system for LIDs so can work with various LID types by
 *   name instead of class instance.
 *
 * Revision 2.4  2002/09/06 07:20:31  robertj
 * Fixed previous update, did not port properly.
 *
 * Revision 2.3  2002/09/04 06:01:49  robertj
 * Updated to OpenH323 v1.9.6
 *
 * Revision 2.2  2002/02/11 09:32:13  robertj
 * Updated to openH323 v1.8.0
 *
 * Revision 2.1  2002/01/22 06:28:43  robertj
 * Added voice blaster support
 *
 * Revision 1.9  2003/12/03 06:58:00  csoutheren
 * More vblaster implementation
 *
 * Revision 1.8  2003/11/10 12:38:20  csoutheren
 * Additional fixes for Fobbit Windows driver
 *
 * Revision 1.7  2002/09/03 06:25:00  robertj
 * Cosmetic change to formatting.
 *
 * Revision 1.6  2002/08/05 10:03:48  robertj
 * Cosmetic changes to normalise the usage of pragma interface/implementation.
 *
 * Revision 1.5  2002/07/09 00:39:08  robertj
 * Patches for latest fobbit driver, thanks Jian Yang
 *
 * Revision 1.4  2002/02/05 06:19:47  craigs
 * Changed to use OPAL define rather than strings
 *
 * Revision 1.3  2002/01/15 07:23:10  craigs
 * Added IsDevicePresent command
 *
 * Revision 1.2  2002/01/15 05:54:16  robertj
 * Added bad implementation for GetDeviceNames()
 *
 * Revision 1.1  2002/01/15 04:16:52  craigs
 * Initial version
 *
 */

#include <ptlib.h>

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

#include <lids/vblasterlid.h>

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

#if HAS_VBLASTER

#define   STARTUP_TIMEOUT   500
/*

  This code uses the VoIPBlaster interface as written by Dave Fobbitt (http://www.fobbit.com).
  All of the information about the VoIPBlaster command set and functions was derived directly
  from the code made available by Dave. This code requires Dave's USB drivers to be installed 
  as per the instructions on his site. Thanks to Dave for making this code available for
  general use.

  Introduction

  The interface to the VoIPBlaster (VB) is implemented using two pairs of read/write channels. These
  are implemented as four named pipes for Windows, or two sockets for Unix. One channel is used
  for sending commands to the VB and reading status, and the other channel is used for sending and
  receiving audio data.

  Initialisation:
    TBD
    
  Commands:
    There are 27 different comands recognised by the VB. Each command is one byte.

        COMMAND_PHONE_OFF  0x01     drop loop current
        COMMAND_PHONE_ON   0x02     used on startup
        COMMAND_RING_ON    0x03     start ringing
        COMMAND_RING_OFF   0x04     used on startup & to stop ringing
        COMMAND_VOUT_START 0x05     start audio output
        COMMAND_VOUT_STOP  0x06     stop audio output
        COMMAND_VINP_START 0x07     start audio input
        COMMAND_VINP_STOP  0x08     stop audio input
        COMMAND_UNKNOWN_1  0x09     Unknown (TESTSTART)
        COMMAND_UNKNOWN_2  0x0a     Unknown (TESTSTOP)
        COMMAND_UNKNOWN_3  0x0b     Unknown (SENDFAXTONE)
        COMMAND_0x0c       0x0c     Go offhook for headset
        COMMAND_0x0d       0x0d     Go onhook for headset
        COMMAND_SETUP_MODE 0x0e     Unknown(goto setup mode)
        COMMAND_VOUT_DONE  0x0f     voice in/out off, report output drained
        COMMAND_0x10       0x10     Unknown (used in file output, seems ok without)
        COMMAND_0x11       0x11     Unknown (used in file output, seems ok without)
        COMMAND_MUTE_ON    0x12     Audio mute on
        COMMAND_MUTE_OFF   0x13     Audio mute off
        COMMAND_VOL_0      0x34     Set volume (min)
        COMMAND_VOL_1      0x35     Set volume
        COMMAND_VOL_2      0x36     Set volume
        COMMAND_VOL_3      0x37     Set volume (default)
        COMMAND_VOL_4      0x38     Set volume
        COMMAND_VOL_5      0x39     Set volume
        COMMAND_VOL_6      0x3a     Set volume (max)

  Status:
    There are 11 different status responses sent by the VB. Each status is one byte.
        STATUS_NONE        0x00     No status
        STATUS_HOOK_OFF    0x01     Offhook
        STATUS_HOOK_ON     0x02     Onhook
        STATUS_DEBUG       0x00     Not used (DEBUG)
        STATUS_RINGDETECT  0x00     Not used (RINGDETECT)
        STATUS_RINGING_ON  0x05     Ring started 
        STATUS_RINGING_OFF 0x06     Ring stopped
        STATUS_HEADSET_IN  0x08     Headset plugged in
        STATUS_HEADSET_OUT 0x09     Headset unplugged
        STATUS_0x0a        0x0a     Unknown (setup accepted?)
        STATUS_VOUT_DONE   0x0c     Voice output done

  Voice:
    The VB will accept audio in G.723.1 format at either 6.4kbps frames (24 bytes) or 5.3 kbps
    frames (20 bytes). However, it only generates audio data at 5.3 kbps frames (20 bytes)

*/

static BYTE blasterInit1[] =
{
    0x3b,0x00,0x40,0x8b // first 2 bytes is length, second 2 bytes is command?
};

static BYTE blasterInit2[] =
{
    0x00,0x01,0x00,0x00,0x18,0x02,0x8f,0x00,
    0x10,0x00,0x28,0x40,0x03,0x1a,0x0d,0x0c,
    0xfa,0x43,0xfd,0xea,0x93,0xfe,0x1a,0x41,
    0x00,0x4a,0x93,0xfe,0x2a,0x40,0x00,0x1a,
    0x93,0xfe,0x3a,0x0a,0x00,0x1f,0x3c,0x00,
    0x8c,0x0d,0x03,0xa3,0x23,0xa2,0xdf,0x0d,
    0x0c,0x3a,0x40,0x00,0x2a,0x93,0xfe,0x4a,
    0x0a,0x00,0x0f
};

// this gets sent each time the voice output goes idle
static BYTE blasterInit3[] =
{
    0x75,0x58,0x9b,0x04,0x72,0x00,0x00,0x11,
    0xe0,0x00,0x65,0x82,0x00,0x90,0x00,0x1c,
    0x96,0xc1,0x0f,0xf2,0x3d,0x95,0x8e,0x5e,
    0xe7,0x66,0xef,0xd4,0xba,0x21,0x0d,0x30,
    0xcb,0x1e,0x52,0x35,0x9a,0xb6,0xff,0x7f,
    0x74,0x58,0x9b,0x04,0x68,0x08,0x00,0x99,
    0x52,0xfa,0x75,0xd7,0x72,0xba,0xdb,0x03,
    0x3d,0xdb,0x77,0xd0,0x77,0x03,0x1f,0x05
};

// some silence data, for now only used in 'vblast_ring' to kill the dialtone
static BYTE silence[] =
{
    0xd5,0x14,0x0a,0x0d,0x1a,0x00,0x00,0x0a,
    0x80,0x00,0xaf,0x06,0x00,0x00,0xfc,0x24,
    0x9b,0x70,0xcf,0xc0,0xa1,0x53,0x18,0x00,
    0x08,0x04,0xfe,0x50,0x8f,0x12,0x50,0x50,
    0x4b,0x32,0x56,0x77,0x15,0xe9,0x0f,0xe8,
    0xd5,0xc8,0xad,0x68,0xc8,0x74,0xe4,0x27,
    0x71,0xd8,0x87,0x34,0xad,0x60,0x07,0xa8,
    0xb6,0x64,0x0f,0x44,0x59,0x02,0xf4,0x00,
    0x0e,0x80,0xba,0x68,0x73,0x00,0xe0,0xdf,
    0x82,0xf4,0xa3,0x1f,0x18,0xb3,0x70,0x2e,
    0xdd,0x1c,0xb1,0x00,0x02,0xfc,0x07,0xde,
    0x09,0xc2,0x5e,0x82,0xaf,0xbc,0x5a,0x6c,
    0xa2,0x02,0xbb,0xac,0x65,0x47,0x99,0x74,
    0xfe,0xf4,0xe5,0xf7,0x70,0x90,0xe7,0x21,
    0x15,0x33,0x56,0x8a,0x77,0x50,0xb5,0x42,
    0x51,0x17,0xf2,0x4c,0xa8,0xfc,0x10,0x60,
    0x82,0x1e,0x50,0x2f,0xa4,0x57,0x31,0x1e,
    0xdd,0xc0,0xaf,0x6f,0x4d,0x1f,0xf5,0x08,
    0x18,0x90,0x15,0x7f,0x70,0x1e,0x60,0x3e,
    0x15,0xfb,0xa0,0x0d,0xbd,0x60,0x90,0x6d,
    0x65,0x43,0xb1,0xdc,0xc2,0xd5,0x19,0xe5,
    0xe1,0xe8,0x27,0xe4,0xcf,0x82,0x39,0xec,
    0x38,0x84,0x3b,0x75,0x51,0x3b,0xb1,0x70,
    0xde,0x68,0xba,0x06,0x79,0x0f,0x76,0x18,
    0x74,0x53,0x45,0x4f,0x83,0x52,0xa0,0xa0,
    0x5d,0xc1,0xed,0xc4,0x9f,0x77,0x27,0x36,
    0x83,0xf9,0x07,0x7f,0x28,0xf3,0x41,0x41,
    0x85,0x94,0x15,0xc0,0x45,0x13,0xee,0x30,
    0x54,0x8c,0xea,0x37,0x03,0xf8,0xae,0x1f,
    0x85,0xe7,0xed,0x21,0x58,0x01,0xff,0xe5,
    0x75,0xc3,0x09,0x05,0x12,0x00,0x26,0xa7,
    0x0b,0x26,0x9f,0x81,0x26,0x50,0x06,0x97,
    0x31,0xa4,0x3c,0xca,0x1d,0x97,0xc2,0x9d,
    0x42,0x6d,0xcf,0xae,0xe6,0xe5,0x27,0x04,
    0x03,0xc2,0x93,0x5d,0xa7,0x62,0xf1,0x87,
    0x5d,0x41,0xe5,0x0a,0x0a,0x70,0x69,0x3f,
    0xf1,0xf4,0xfe,0x0d,0x4e,0x27,0x97,0x5b,
    0xb0,0x0b,0xe5,0x78,0xa5,0x26,0x09,0x49,
    0x90,0xfc,0xf1,0x77,0x52,0x0c,0xdf,0xef,
    0x7f,0x8d,0x84,0x15,0x48,0xc7,0xff,0x5b,
};

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

OpalVoipBlasterDevice::OpalVoipBlasterDevice()
  : dtmfQueue(DTMFQueueSize)
{
  statusThread = NULL;
}

OpalVoipBlasterDevice::~OpalVoipBlasterDevice()
{
  Close();
}

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

  int deviceIndex = device.AsInteger();

  readStopped = writeStopped = TRUE;

  // open the lowlevel device
  if (!vBlaster.OpenCommand(deviceIndex)) {
    PTRACE(3, "vBlaster\tCould not open VoipBlaster device \"" << device << '"');
    return FALSE;
  }
  if (!vBlaster.OpenData()) {
    PTRACE(3, "vBlaster\tCould not open VoipBlaster data for device \"" << device << '"');
    return FALSE;
  }

  // put device into setup mode
  PTRACE(3, "vBlaster\tSending setup command");

  // put the handset on hook, which should stop all voice data
  vBlaster.WriteCommand(VoipBlasterInterface::Command_HS_ONHOOK); 

  // flush all input
  vBlaster.Flush(STARTUP_TIMEOUT);

  vBlaster.WriteCommand(VoipBlasterInterface::Command_SETUP_MODE); 

  // setup for incoming status
  hookState = FALSE;
  headset   = FALSE;
  ringOn    = TRUE;     // so we can detect ring off
  firstTime = FALSE;


  //vBlaster.Flush(STARTUP_TIMEOUT);

  vBlaster.WriteData(blasterInit1, sizeof(blasterInit1));

  //vBlaster.Flush(STARTUP_TIMEOUT);

  vBlaster.WriteData(blasterInit2, sizeof(blasterInit2));

  //vBlaster.Flush(STARTUP_TIMEOUT);

  int status = VoipBlasterInterface::Status_Empty;

  int i = 0;

  for ( i = 3; ringOn && i > 0; i--) {

    vBlaster.WriteCommand(VoipBlasterInterface::Command_VOL_3);
    vBlaster.WriteCommand(VoipBlasterInterface::Command_RING_OFF);
    vBlaster.WriteCommand(VoipBlasterInterface::Command_PHONE_ON);

    PTimer timer(2000);

    do {
      status = vBlaster.ReadStatus(STARTUP_TIMEOUT);
      if (status != VoipBlasterInterface::Status_Empty)
        HandleStatus(status);
    } while (ringOn && timer.IsRunning());
  }

  if (i == 0) {
    PTRACE(3, "vBlaster\tCould not initialise");
    return FALSE;
  }

  // set up thread to read status pipe
  statusRunning = TRUE;
  statusThread = PThread::Create(PCREATE_NOTIFIER(StatusHandler), 0,
                                 PThread::NoAutoDeleteThread,
                                 PThread::NormalPriority,
                                 "VbStatus:%x");

  // unmute output and set default value
  vBlaster.WriteCommand(VoipBlasterInterface::Command_VOL_3);
  vBlaster.WriteCommand(VoipBlasterInterface::Command_MUTE_OFF);
  vBlaster.WriteCommand(VoipBlasterInterface::Command_VOUT_STOP);
  vBlaster.WriteCommand(VoipBlasterInterface::Command_VINP_STOP);

  // save the device name
  deviceName = device;
  PTRACE(3, "vBlaster\tVoipBlaster device \"" << device << "\" opened");
  os_handle = deviceIndex;

  return TRUE;
}


BOOL OpalVoipBlasterDevice::Close()
{
  PWaitAndSignal m(vbMutex);

  if (!IsOpen())
    return FALSE;

  // flag the status thread to stop running on next status byte
  statusRunning = FALSE;

  // send a command to the phone stat will force a status byte to return
  vBlaster.WriteCommand(VoipBlasterInterface::Command_PHONE_OFF);
  vBlaster.WriteCommand(VoipBlasterInterface::Command_MUTE_OFF);

  vBlaster.WriteCommand(VoipBlasterInterface::Command_VOUT_DONE);
  vBlaster.WriteData   (blasterInit3, sizeof(blasterInit3));

  // close the device - this will stop the status thread for sure!
  vBlaster.CloseCommand();

  // wait for the status thread to terminate
  statusThread->WaitForTermination();
  delete statusThread;
  statusThread = NULL;

  deviceName = PString();

  os_handle = -1;
  return TRUE;
}


PString OpalVoipBlasterDevice::GetDeviceType() const
{
  return OPAL_VBLASTER_TYPE_NAME;
}


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


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


PString OpalVoipBlasterDevice::GetDescription() const
{
  return "Createive Labs VoIP Blaster (" + deviceName + ')';
}


void OpalVoipBlasterDevice::StatusHandler(PThread &, INT)
{
  while (statusRunning) {
    int status = vBlaster.ReadStatus();
    if (status != VoipBlasterInterface::Status_Empty)
      HandleStatus(status);
  }
}

void OpalVoipBlasterDevice::HandleStatus(int status)
{
  switch (status) {
    //case VoipBlasterInterface::Status_NONE:        // No status
    //  break;

    case VoipBlasterInterface::Status_HOOK_OFF:    // Offhook
      PTRACE(1, "VB\tHook off");
      hookState = TRUE;
      headset   = FALSE;
      break;

    case VoipBlasterInterface::Status_HOOK_ON:     // Onhook
      PTRACE(1, "VB\tHook on");
      hookState = FALSE;
      headset   = FALSE;
      break;

    case VoipBlasterInterface::Status_RINGING_ON:  // Ring started 
      PTRACE(1, "VB\tRing start");
      ringOn = TRUE;
      break;

    case VoipBlasterInterface::Status_RINGING_OFF: // Ring stopped
      PTRACE(1, "VB\tRing end");
      ringOn = FALSE;
      break;

    case VoipBlasterInterface::Status_HEADSET_IN:  // Headset plugged in
      PTRACE(1, "VB\tHeadset in");
      headset = TRUE;
      break;

    case VoipBlasterInterface::Status_HEADSET_OUT: // Headset unplugged
      PTRACE(1, "VB\tHeadset out");
      headset = FALSE;
      break;

    case VoipBlasterInterface::Status_0x0a:        // Unknown (setup accepted?)
      PTRACE(1, "VB\tStatus 0xa");

      // read 17 byte serial number
      BYTE serialNumber[17];
      memset(serialNumber, 0, sizeof(serialNumber));
      vBlaster.ReadData(serialNumber, sizeof(serialNumber), STARTUP_TIMEOUT);
      {
        PString str;
        for (int i = 0; i < sizeof(serialNumber); i++)
          str.sprintf("%02x ", serialNumber[i]);

⌨️ 快捷键说明

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