Merged latest changes from trunk.

This commit is contained in:
MelwareDE 2011-10-01 16:32:26 +00:00
parent e25f33a595
commit 2384c8d7cc
67 changed files with 11736 additions and 1175 deletions

31
CHANGES
View File

@ -1,6 +1,37 @@
CHANGES
=======
HEAD
------------------
- added dialplan variables ISDNPI1 and ISDNPI2
- Support for 'divastreaming' available (Diva 4PRI PCI, Diva 2PRI PCI,
Diva 4PRI HS PCIe, Diva 2PRI HS PCIe, Diva 1PRI HS PCIe,
Diva 8PRI PCIe FS, Diva 4PRI PCIe FS)
- Fixed memory leak in chat_play if using with 's' option
- Add 'econtransitconn' configurations parameter. Allows to preserve
EC for transit connections
- added variable DISCONNECT_IND_REASON to get real reason code from CAPI
- added capicommand(keypad)
- added log of FACILITY_IND for call deflect suplementary service
- malloc,strdup,free -> ast_(malloc,strdup,free)
- Use Diva streaming for NULL PLCI and for resource PLCI
- Resolved http://www.ipphoneforum.eu/showthread.php?t=220051
- Use Diva QSIG CAPI extensions for processing of Calling Party Name
- Add Slinear
- Add HD voice using G.722, Siren7, Siren14 and Slinear16
- added faxdestination= to capi.conf to configure custom context,exten,prio.
- allow capicommand option separator "|" and ",".
- Add MWI server
- Add MWI client
- Improved call distribution algorithm for outgoing calls
- Add 'capi ifcstate', 'capi exec', 'capi show resources' and
'chat manage remove' CLI commands
- Add AMI 'Capichat[List,Mute,Unmute,Remove]' and 'CapiCommand' actions and
Capichat[List,ListComplete,Join,Leave,End] events
- Add device state events for char rooms (capichat:[roomname]) and for
interface state (ISDN/I[N]/congestion)
- Add access to Diva trace driver
chan_capi-1.1.5
------------------
- corrected check for Info value on CONNECT_B3_CONF

View File

@ -18,6 +18,10 @@
OSNAME=${shell uname}
DIVA_STREAMING=0
DIVA_STATUS=0
DIVA_VERBOSE=0
USE_OWN_LIBCAPI=yes
.EXPORT_ALL_VARIABLES:
@ -78,6 +82,16 @@ INCLUDE=
LIBLINUX=-lcapi20
endif
ifeq (${DIVA_STREAMING},1)
INCLUDE += -I./divastreaming -I./divastreaming/..
endif
ifeq (${DIVA_STATUS},1)
INCLUDE += -I./divastatus -I./divastatus/..
endif
INCLUDE += -I./divaverbose
DEBUG=-g #-pg
INCLUDE+= -I$(ASTERISK_HEADER_DIR)
ifndef C4B
@ -100,6 +114,20 @@ CFLAGS+=$(OPTIMIZE)
CFLAGS+=-O2
CFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi)
CFLAGS+=$(shell if uname -m | grep -q "ppc\|arm\|s390"; then echo "-fsigned-char"; fi)
ifeq (${DIVA_STREAMING},1)
CFLAGS += -DDIVA_STREAMING=1
endif
ifeq (${DIVA_STATUS},1)
CFLAGS += -DDIVA_STATUS=1
CFLAGS+=$(shell echo '\#include <sys/inotify.h>' > /tmp/test.c 2>/dev/null && \
echo 'int main(int argc,char**argv){if(inotify_init()>=0)return 0; return 1;}' >> /tmp/test.c 2>/dev/null && \
$(CC) /tmp/test.c -o /tmp/test && /tmp/test >/dev/null 2>&1 && echo '-DCC_USE_INOTIFY=1'; rm -f /tmp/test.c /tmp/test)
endif
ifeq (${DIVA_VERBOSE},1)
CFLAGS += -DDIVA_VERBOSE=1
endif
LIBS=-ldl -lpthread -lm
CC=gcc
@ -109,12 +137,32 @@ SHAREDOS=chan_capi.so
OBJECTS=chan_capi.o chan_capi_utils.o chan_capi_rtp.o chan_capi_command.o xlaw.o dlist.o \
chan_capi_qsig_core.o chan_capi_qsig_ecma.o chan_capi_qsig_asn197ade.o \
chan_capi_qsig_asn197no.o chan_capi_supplementary.o chan_capi_chat.o
chan_capi_qsig_asn197no.o chan_capi_supplementary.o chan_capi_chat.o \
chan_capi_mwi.o chan_capi_cli.o chan_capi_ami.o chan_capi_management_common.o \
chan_capi_devstate.o
ifeq (${USE_OWN_LIBCAPI},yes)
OBJECTS += libcapi20/convert.o libcapi20/capi20.o libcapi20/capifunc.o
endif
ifeq (${DIVA_STREAMING},1)
OBJECTS += divastreaming/diva_streaming_idi_host_ifc_impl.o \
divastreaming/diva_streaming_idi_host_rx_ifc_impl.o \
divastreaming/diva_streaming_manager.o \
divastreaming/diva_streaming_messages.o \
divastreaming/segment_alloc.o \
divastreaming/chan_capi_divastreaming_utils.o \
divastreaming/runtime.o
endif
ifeq (${DIVA_STATUS},1)
OBJECTS += divastatus/divastatus.o
endif
ifeq (${DIVA_VERBOSE},1)
OBJECTS += divaverbose/divaverbose.o
endif
CFLAGS+=-Wno-missing-prototypes -Wno-missing-declarations
CFLAGS+=-DCRYPTO
@ -131,6 +179,15 @@ clean:
rm -f config.h
rm -f *.so *.o
rm -f libcapi20/*.o
rm -f divastreaming/*.o
rm -f divastatus/*.o
rm -f divaverbose/*.o
distclean: clean
rm -f $(MODULES_DIR)/$(SHAREDOS)
sysclean: distclean
rm -f $(MODULES_DIR)/*.so
config.h:
./create_config.sh "$(ASTERISK_HEADER_DIR)"

118
README
View File

@ -98,6 +98,7 @@ The Dial string
(Useful if additional digits should be send afterwards or together
with 'b' to get the dialtone and then send the number, e.g., if
no progress tones are available)
'c' : do not send sending complete
's' : activate 'stay-online': do not disconnect CAPI connection on hangup.
This is needed to give additional commands like CCBS after hangup.
To really hang up the CAPI connection, use either capicommand(hangup)
@ -138,6 +139,16 @@ capi show channels:
capi chatinfo:
Show status of CAPI CHAT.
capi ifcstate:
Show state of interfaces. (Diva only, chan_capi
compiled with 'make DIVA_STATUS=1')
capi show resources:
Show resources in use.
capi exec:
'capi exec CHANNEL command,parameter1,parameter2,....,parameterN'
Exec capicommand 'command' for selected channel.
CAPI command application
========================================
@ -148,27 +159,27 @@ With this application, special CAPI commands and features can be used.
Call Deflection:
Forwards an unanswered call to another number.
Example:
exten => s,1,capicommand(deflect|12345678)
exten => s,1,capicommand(deflect,12345678)
Fax receive:
Receives a fax using CAPI.
Example:
exten => s,1,capicommand(receivefax|/tmp/${UNIQUEID}|+49 6137 555123|Asterisk|kX)
exten => s,1,capicommand(receivefax,/tmp/${UNIQUEID},+49 6137 555123,Asterisk,kX)
(more see below)
Fax send:
Sends a fax using CAPI.
Example:
exten => s,1,capicommand(sendfax|/path/to/faxfile.sff|+49 6137 555123|Asterisk)
exten => s,1,capicommand(sendfax,/path/to/faxfile.sff,+49 6137 555123,Asterisk)
(more see below)
Enable/Disable echosquelch:
Enables or disable a very primitive echo suppressor.
Disable this option before you start recording voicemail or your files may get choppy.
Example:
exten => s,1,capicommand(echosquelch|yes)
exten => s,1,capicommand(echosquelch,yes)
or
exten => s,1,capicommand(echosquelch|no)
exten => s,1,capicommand(echosquelch,no)
Enable/Disable echocancel:
Enables or disables echo-cancel provided by CAPI driver/hardware.
@ -176,9 +187,22 @@ Enable/Disable echocancel:
by a non-CAPI application. After hangup, this setting is restored to the value
set in capi.conf.
Example:
exten => s,1,capicommand(echocancel|yes)
exten => s,1,capicommand(echocancel,yes)
or
exten => s,1,capicommand(echocancel|no)
exten => s,1,capicommand(echocancel,no)
By default chan_capi deactivates echo-cancel for transit connections
(Dial command called from existing call). You can use 'econtransitconn'
configurations parameter (capi.conf) to change this behavior:
econtransitconn=0 ; Deactivate EC on transit connections
econtransitconn=1 ; Deactivate EC on secondary call of transit connection only
econtransitconn=2 ; Deactivate EC on primary call of transit connection only
econtransitconn=3 ; Do not deactivate EC on transit connections
Send Keypad Facility:
Send Keypad Faciliaty information.
Example:
exten => s,1,capicommand(keypad,<digits>)
Malicious Call Identification:
Reports a call of malicious nature.
@ -193,18 +217,18 @@ Hold:
Example:
exten => s,1,capicommand(hold)
or
exten => s,1,capicommand(hold|MYHOLDVAR)
exten => s,1,capicommand(hold,MYHOLDVAR)
Holdtype:
Sets the type of 'hold'. When Asterisk wants to put the call on hold, the specified method
will be used.
Example:
exten => s,1,capicommand(holdtype|local) ;no hold, Asterisk can play MOH
exten => s,1,capicommand(holdtype,local) ;no hold, Asterisk can play MOH
or
exten => s,1,capicommand(holdtype|hold) ;ISDN-HOLD
exten => s,1,capicommand(holdtype,hold) ;ISDN-HOLD
or
; not yet implemented
exten => s,1,capicommand(holdtype|notify) ;notify the peer only, Asterisk can play MOH
exten => s,1,capicommand(holdtype,notify) ;notify the peer only, Asterisk can play MOH
Retrieve:
@ -213,12 +237,12 @@ Retrieve:
Example:
exten => s,1,capicommand(retrieve)
or
exten => s,1,capicommand(retrieve|${MYHOLDVAR})
exten => s,1,capicommand(retrieve,${MYHOLDVAR})
ECT:
Explicit Call Transfer of the call on hold (must put call on hold first!)
Example:
exten => s,1,capicommand(ect|${MYHOLDVAR})
exten => s,1,capicommand(ect,${MYHOLDVAR})
or
[macro-capiect]
exten => s,1,capicommand(ect)
@ -228,13 +252,13 @@ ECT:
exten => s,3,Dial(CAPI/contr1/1234,60,M(capiect))
Note: Normaly a PBX needs 'implicit call transfer', which is done by default
with this command. But if the line needs real 'explicit call transfer', use
exten => s,1,capicommand(ect|x)
exten => s,1,capicommand(ect,x)
instead.
3PTY:
Initiates a Three-Party Conference (must have one call on hold and one active call!).
Example:
exten => s,1,capicommand(3pty_begin|${MYHOLDVAR})
exten => s,1,capicommand(3pty_begin,${MYHOLDVAR})
or
[macro-capi3pty]
exten => s,1,capicommand(3pty_begin)
@ -261,9 +285,9 @@ Set local party to 'busy' or 'free':
about the status of the extension who started the callback.
By default, chan_capi assumes 'free', but you can change that
with:
exten => s,1,capicommand(ccpartybusy|${CCLINKAGEID}|yes)
exten => s,1,capicommand(ccpartybusy,${CCLINKAGEID},yes)
or
exten => s,1,capicommand(ccpartybusy|${CCLINKAGEID}|no)
exten => s,1,capicommand(ccpartybusy,${CCLINKAGEID},no)
Call completion on subscriber busy (CCBS):
To receive a callback when the dialed and busy party becomes free, aka
@ -273,7 +297,7 @@ Call completion on subscriber busy (CCBS):
exten => s,2,Dial(CAPI/contr1/123456,60,g) ;'g' to go-on with the dialplan on busy.
exten => s,3,NoOp(${CCLINKAGEID}) ;if this variable now contains a number, CCBS is possible.
;here you can ask the caller if CCBS shall be activated...
exten => s,4,capicommand(ccbs|${CCLINKAGEID}|<context>|<exten>|<priority>)
exten => s,4,capicommand(ccbs,${CCLINKAGEID},<context>,<exten>,<priority>)
exten => s,5,NoOp(${CCBSSTATUS}) ;if CCBS was successfully enabled, it is set to "ACTIVATED".
If the remote party becomes 'non-busy', the network initiates the callback that will be
sent to the provided context/exten/priority. Of course, this only happens if your local
@ -285,15 +309,15 @@ Call completion on subscriber busy (CCBS):
Deactivate CCBS:
To deactivate a previously activated CCBS, use the following command:
Example:
exten => s,1,capicommand(ccbsstop|${CCLINKAGEID})
exten => s,1,capicommand(ccbsstop,${CCLINKAGEID})
Chat (MeetMe/Conference):
See also README.media for details!
If the CAPI card/driver supports it, the caller can be put into a chat-room:
(This uses the DSPs onboard a Dialogic(R) Diva(R) Rev.2 Media Board.)
exten => s,1,capicommand(chat|<roomname>|<options>|controller)
exten => s,1,capicommand(chat,<roomname>,<options>,controller)
Example:
exten => s,1,capicommand(chat|salesmeeting|m|1,3-6)
exten => s,1,capicommand(chat,salesmeeting,m,1,3-6)
Possible options:
'm' = The first caller will get music-on-hold until second caller arrives.
'h<sec>' = Hangup after <sec> seconds if caller is alone in conference.
@ -372,19 +396,19 @@ Short HOWTO of capicommand(receivefax...) and capicommand(sendfax...):
For those of you who have a CAPI card with an on-board DSP (like Dialogic(R) Diva(R) Media Boards),
this allows you to receive/send faxes.
capicommand(receivefax|<filename>[|<stationid>|<headline>|<options>]):
capicommand(receivefax,<filename>[,<stationid>,<headline>,<options>]):
-------------------------------------------------------------------------
If you want to answer a channel in fax mode, use capicommand(receivefax|...)
If you want to answer a channel in fax mode, use capicommand(receivefax,...)
instead of Answer(). If you use Answer(), you will be in voice mode.
If the hardware DSP detects fax tone, you can switch from voice to fax mode
by calling capicommand(receivefax|...).
by calling capicommand(receivefax,...).
The parameter <filename> is mandatory and the parameters <stationid>,
<headline> and <options> are optional.
By default, if fax reception was not successful, the file is deleted. If you want even
partly received or broken fax files, use 'k' for "keep bad fax" in the <options>:
capicommand(receivefax|/tmp/${UNIQUEID}|+123456789||k)
capicommand(receivefax,/tmp/${UNIQUEID},+123456789,,k)
You can activate extended fax support by 'X' in the <options>:
capicommand(receivefax|/tmp/${UNIQUEID}|+123456789||X)
capicommand(receivefax,/tmp/${UNIQUEID},+123456789,X)
Please read details on extended fax options in README.Diva.fax.
To enable fax tone detection and redirect to extension 'fax', use config variable
@ -402,11 +426,11 @@ exten => 124,1,Goto(handle_fax,s,1)
exten => fax,1,Goto(handle_fax,s,1)
[handle_fax]
exten => s,1,capicommand(receivefax|/tmp/${UNIQUEID}[|<stationid>|<headline>|<options>])
exten => s,1,capicommand(receivefax,/tmp/${UNIQUEID}[,<stationid>,<headline>,<options>])
exten => s,2,Hangup()
exten => h,1,deadagi,fax.php // Run sfftobmp and mail it.
The output of capicommand(receivefax|...) is a SFF file.
The output of capicommand(receivefax,...) is a SFF file.
Use sfftobmp to convert it.
With a Dialogic(R) Diva(R) Media Board, the following features are provided:
- fax up to 33600
@ -415,12 +439,12 @@ With a Dialogic(R) Diva(R) Media Board, the following features are provided:
- JPEG Compression is disabled (not tested yet)
See README.Diva.fax for more details and description of all options.
capicommand(sendfax|<filename>[|<stationid>|<headline>|<options>]):
capicommand(sendfax,<filename>[,<stationid>,<headline>,<options>]):
------------------------------------------------------------
To send a fax, you can use the same mechanism like with receivefax.
Just replace the <filename> with the path to the .SFF file to send.
You can activate extended fax support by 'X' in the <options>:
capicommand(sendfax|/tmp/${UNIQUEID}|+123456789||X)
capicommand(sendfax,/tmp/${UNIQUEID},+123456789,,X)
Please read details on extended fax options in README.Diva.fax.
After disconnect of a fax connection, the following variables
@ -472,7 +496,7 @@ BCHANNELINFO
'2' : neither B nor D-channel is used (e.g., call waiting)
Call-Waiting: an incoming call with BCHANNELINFO not '0' cannot be accepted.
Another connection must be dropped before accepting or use
capicommand(deflect|<number>) to initiate call deflection to another destination.
capicommand(deflect,<number>) to initiate call deflection to another destination.
CALLEDTON
Incoming calls: 'type of number' value of the called number is saved in this variable on
@ -509,7 +533,7 @@ CAPI_CIP
instead of transfercapability.
CCBSSTATUS
When using capicommand(ccbs|....), this variable is set to either "ERROR" or
When using capicommand(ccbs,....), this variable is set to either "ERROR" or
"ACTIVATED".
CCLINKAGEID
@ -522,8 +546,15 @@ CONNECTEDNUMBER
Can be set before answering and if set, the content is used for
IE 'Connected Number' on answering.
DISCONNECT_IND_REASON
When CAPI reports DISCONNECT_IND, some CAPI reason codes are not set
in HANGUPCAUSE, because they are not valid cause codes. To also
get those CAPI reason codes, you can check this variable on hangup.
This is e.g. useful for reason 0x3301, which tells that the ISDN
connection is physically broken (cable).
FAXEXTEN
If chan_capi sends the call to extensions 'fax', the original extension number
If chan_capi sends the call to configured fax extension, the original extension number
is saved in this variable.
PRI_CAUSE
@ -542,4 +573,25 @@ REDIRECTIONNUMBER
If an outgoing call is redirected, this variable may be set to the
new destination.
ISDNPI1 and ISDNPI2
The two values of the information element PI (Progress Indicator).
Asterisk outgoing calls
==========================================================
Distribution of outgoing calls is controlled by two
configuration variables (capi.conf, controller specific).
hlimit - Number of reserved channels. If number of free
channels is below the one specified by 'hlimit' value then
no new outgoing calls are delivered to this controller.
slimit - If value is set for multiple belonging to same dialout group
controllers then the outgoing calls are distributd as follows:
Calls are delivered to the controller with smalest (in group)
number and the amount of free channels bigger then or equal to
one speciefied by 'slimit'. After amount of free channels for all
included in the group controllers is decreased below one specified
by 'slimit' value calls are distributed in rount robin fashion
between all (in group) controllers.

74
README.Diva.HDAudio Normal file
View File

@ -0,0 +1,74 @@
+===================================================================+
| HD Audio (Hight Definition Audio) |
+===================================================================+
+-------------------------------------------------------------------+
| Supported HD Audio vocoders |
+-------------------------------------------------------------------+
Diva provides support for following HD Audio vocoders:
g722, ssiren7 siren14 and slin16
+-------------------------------------------------------------------+
| Supported Diva Hardware |
+-------------------------------------------------------------------+
HD Audio support is provided by:
Diva 4PRI PCI
Diva 2PRI PCI
Diva 4PRI PCIe HS
Diva 2PRI PCIe HS
Diva 1PRI PCIe HS
Diva 8PRI PCIe FS 4LANE
Diva 4PRI PCIe FS 4LANE
+-------------------------------------------------------------------+
| HD Audio over ISDN support |
+-------------------------------------------------------------------+
To activate support for HD Audio please allow all or one of HD Audio
codecs for one or more CAPI controllers. You can do it by Diva WEB
configuration or by edit of 'capi.conf'.
Diva hardware will use BC/HLC/LLC method to agree on HD Audio
format with opposite side. In addition Diva hardware will
perform analysis of B-channel data to determine if HD Audio
format is signaled in band.
Dependent on this procedire Diva will use HD Audio format
or change to G.711 if HD Audio is not supported by opposite side.
Diva hardware will always convert media to one requested by chan_capi format.
Following conversions are performed automatically:
G.711 <-> HD Audio in case chan_capi uses HD Audio but opposite side not
HD Audio <-> G.711/GSM/... in case opposite side uses HD Audio but
chan_capi uses other codec
Examples of HD Audio operation:
G.722 <-> SLINEAR16
G.722 <-> siren14
G.722 <-> siren7
G.722 <-> G.722
Using automatic convertion this is possible always use HD Audio on internel (IP) network and do not case
about used on the line (ISDN) format.
+-------------------------------------------------------------------+
| HD Audio support for IP conference endpoints |
+-------------------------------------------------------------------+
To activate HD Audio support for IP conferencing please add one or
mode HD Audio codecs to codeclist of capi command 'resource'.
Please read README.media for details on 'resource'
+-------------------------------------------------------------------+
| Conferencing between HD and NB Audio endpoints |
+-------------------------------------------------------------------+
In case of conference with HD and NB (Narrow Band) Audio endpoints
the quelity of HD endpoints is preserved

View File

@ -212,7 +212,7 @@ Reception of fax documents
You can use the Dialogic (R) Diva(R) chan_capi configuration to activate fax support ("Fax detection" and "Fax detection time").
The reception of the fax message is started using 'receivefax' capi command:
capicommand(receivefax|<filename>[|<stationid>|<headline>|<options>])
capicommand(receivefax,<filename>[,<stationid>,<headline>,<options>])
Parameters:
'filename' - Contains the full path and file name for the resulting fax file, mandatory
@ -256,15 +256,15 @@ exten => fax,1,Goto(handle_fax,s,1) ; Fax calling tone detected, change to
exten => i,1,Hangup() ; Received unexpected event
[handle_fax]
exten => s,1,capicommand(receivefax|/tmp/${UNIQUEID}[|<stationid>|<headline>|<options>])
exten => s,1,capicommand(receivefax,/tmp/${UNIQUEID}[,<stationid>,<headline>,<options>])
exten => s,n,Hangup()
exten => h,1,deadagi,fax.php ; Run sfftobmp and mail it
Example with Clear Channel fax support:
[handle_fax]
exten => s,1,capicommand(resource|1-4) ; Assign resource PLCI (use controllers 1 to 4)
exten => s,n,capicommand(receivefax|/tmp/${UNIQUEID}[|<stationid>|<headline>|<options>])
exten => s,1,capicommand(resource,1-4) ; Assign resource PLCI (use controllers 1 to 4)
exten => s,n,capicommand(receivefax,/tmp/${UNIQUEID}[,<stationid>,<headline>,<options>])
exten => s,n,Hangup()
exten => h,1,deadagi,fax.php ; Run sfftobmp and mail it
@ -274,7 +274,7 @@ Transmission of fax documents
The transmission of the fax message is started using 'sendfax' capi command:
capicommand(sendfax|<filename>[|<stationid>|<headline>|<options>])
capicommand(sendfax,<filename>[,<stationid>,<headline>,<options>])
Parameters:
'filename' - Contains the full path and file name to be sent, mandatory
@ -309,7 +309,7 @@ Example:
exten => 1,1,Dial(capi/ISDN1/1234512345,20,G(handle_sendfax,s,1))
[handle_sendfax]
exten => s,1,capicommand(sendfax|/tmp/sendfax001.sff|1234 1234 1234|Outgoing Fax)
exten => s,1,capicommand(sendfax,/tmp/sendfax001.sff,1234 1234 1234,Outgoing Fax)
exten => s,n,deadagi,faxlog.php ; Log result and schedule restart if necessary
exten => s,n,Hangup
@ -317,8 +317,8 @@ exten => s,n,Hangup
Example with Clear Channel fax support:
[handle_sendfax]
exten => s,1,capicommand(resource|1-4) ; Assign resource PLCI
exten => s,n,capicommand(sendfax|/tmp/sendfax001.sff|1234 1234 1234|Outgoing Fax)
exten => s,1,capicommand(resource,1-4) ; Assign resource PLCI
exten => s,n,capicommand(sendfax,/tmp/sendfax001.sff,1234 1234 1234,Outgoing Fax)
exten => s,n,deadagi,faxlog.php ; Log result and schedule restart if necessary
exten => s,n,Hangup

View File

@ -1,4 +1,4 @@
+===================================================================+
+===================================================================+
| QSIG Abstraction |
+===================================================================+
@ -14,6 +14,13 @@ equipment Dialogic(R) Diva(R) interfaces as well.
The coding of the messages and the type of the transfer invoked, depends
on the QSIG dialect and on the vendor-specific implementation of QSIG dialect.
+-------------------------------------------------------------------+
| Use Diva QSIG abstraction with chan_capi |
+-------------------------------------------------------------------+
To use Diva QSIG abstraction please add 'divaqsig=1' to configuration
of CAPI controller (capi.conf).
+-------------------------------------------------------------------+
| QSIG abstraction |
+-------------------------------------------------------------------+
@ -21,6 +28,14 @@ on the QSIG dialect and on the vendor-specific implementation of QSIG dialect.
Dialogic(R) Diva(R) System Release Software abstraction allows to write
QSIG applications independent of the used QSIG dialect.
Name and Display information elements
Name (Calling Pary Name, Called Party Name, Connected Party Name,
Busy Party Name) and Display information elementss are converted to protocol
independent format and delivered to (received from) application using
Diva manufacturer extensions. Information elements encoded as facility array
(for example in CONNECT_REQ) are converted in accordance with rules of active
QSIG protocol.
Unassisted call transfer:
The application can use CAPI call deflection. The Diva System Release software
will automatically translate the call deflection request in the appropriate
@ -143,7 +158,7 @@ ECT Example:
/////////////////////////////////////////////////////////////////////
[macro-capiect]
; Activate suppressor of ambient noise for consultation call
exten => s,1,capicommand(noisesuppressor|yes)
exten => s,1,capicommand(noisesuppressor,yes)
; Invoke ECT command
exten => s,n,capicommand(ect)
@ -157,7 +172,7 @@ exten => 12345,n,Playback(demo-enterkeywords,noanswer,us)
; Accept incoming call
exten => 12345,n,Answer
; Activate suppressor of ambient noises for incoming call
exten => 12345,n,capicommand(noisesuppressor|yes)
exten => 12345,n,capicommand(noisesuppressor,yes)
; Save PLCI of incoming call to CAPIPLCI variable
exten => 12345,n,capicommand(getplci)
; Set CAPIECTPLCI variable to PLCI of incoming call

81
README.Diva.streaming Normal file
View File

@ -0,0 +1,81 @@
+===================================================================+
| Diva streaming |
+-------------------------------------------------------------------+
| |
| What is Diva streaming |
| How to activate Diva streaming support in chan_capi |
| Performance metrics on chan_capi |
| Supported hardware |
| |
+===================================================================+
+-------------------------------------------------------------------+
| WHAT IS DIVA STREAMING |
+-------------------------------------------------------------------+
Diva streaming is one extension to Diva IDI interface which provides:
Reduction of host load
Reduction of delay and delay variance of data stream
This achieved by:
Use of individual and independent logical BUS master DMA channel
for every data stream (for every PLCI)
Data transfer without copy operations and without system calls/context switches
Available for user mode and for kernel mode applications
+-------------------------------------------------------------------+
| HOW TO ACTIVATE DIVA STREAMING SUPPORT IN CHAN_CAPI |
+-------------------------------------------------------------------+
To activate Diva streaming support in chan_capi please compile
chan_capi with MAKE variable DIVA_STREAMING set to one:
make DIVA_STREAMING=1
and install new chan_capi module:
make install DIVA_STREAMING=1
chan_capi automatically detects if Diva streaming is supported by available Diva hardware.
You can disable use of Diva streaming at run time (without need to re-compile of chan_capi)
if you set "nodivastreaming" variable in "[general]" section of "capi.conf" to one:
[general]
nodivastreaming=1
+-------------------------------------------------------------------+
| PERFORMANCE METRICS ON CHAN_CAPI |
+-------------------------------------------------------------------+
Hardware: 8 x 2.8GHz Xeon, 8GByte memory, Debian lenny 64Bit
Diva hardware: Dialogic Diva V-8PRI PCIe FS v1
Test: 240 channels GSM voice streaming
Voice transcoding by Asterisk and data exchange using CAPI:
System load 50%
Voice delay (additional): 20 mSec, delay variance 10mSec
Voice transcoding by Astrisk and data exchange using Diva streaming:
System load 10%
Voice delay (additional): 2 mSec, delay variance 1 mSec
Voice transcoding by Diva and data exchange using Diva streaming:
System load 2%
Voice delay (additional): 2 mSec, delay variance 1 mSec
+-------------------------------------------------------------------+
| SUPPORTED HARDWARE |
+-------------------------------------------------------------------+
Diva streaming is supported by following hardware:
Dialogic Diva V-4PRI/E1/T1-120 PCI v1
Dialogic Diva 4PRI/E1/T1-120 PCI v1
Dialogic Diva V-2PRI/E1/T1-60 PCI v1
Dialogic Diva 2PRI/E1/T1-60 PCI v1
Dialogic Diva V-4PRI PCIe HS v1
Dialogic Diva V-2PRI PCIe HS v1
Dialogic Diva V-1PRI PCIe HS v1
Dialogic Diva V-4PRI PCIe FS v1
Dialogic Diva V-8PRI PCIe FS v1

160
README.ami Normal file
View File

@ -0,0 +1,160 @@
+===================================================================+
| AMI commands and events |
| |
| Device state events |
+===================================================================+
+-------------------------------------------------------------------+
| Action CapichatList |
+-------------------------------------------------------------------+
List all users in conference or in all conferences
Conference: Capi chat room name
If Conference is not provided then command lists all users in all capi chat rooms.
List of users is delicered as serie of CapichatList events.
List of users starts ends with CapichatListComplete event.
+-------------------------------------------------------------------+
| Action CapichatMute |
+-------------------------------------------------------------------+
Mute all regular users if conference or mute selected user.
Conference: Conference room to mute
Member: User to mute (Channel name)
Path: Path to mute (Rx or Tx)
If only Conference provided then entire room is muted.
If only Member provided then only selected user is muted.
If Path not provided then Tx path is assumed.
Path is valid only if Member iss provided.
If mute only one member this command is alias for capicommand
txdgain,-128
+-------------------------------------------------------------------+
| Action CapichatUnmute |
+-------------------------------------------------------------------+
Mute all regular users if conference or mute selected user.
Conference: Conference room to unmute
Member: User to mute (Channel name)
Path: Path to mute (Rx or Tx)
If only Conference provided then entire room is muted.
If only Member provided then only selected user is muted.
If Path not provided then Tx path is assumed.
Path is valid only if Member iss provided.
If unmute only one member this command is alias for capicommand
txdgain,0
+-------------------------------------------------------------------+
| Action CapichatRemove |
+-------------------------------------------------------------------+
Remove member from conference
Conference: Conference room name
Member: User to remove (Channel name)
+-------------------------------------------------------------------+
| Action CapiCommand |
+-------------------------------------------------------------------+
Execute any of supported capicommand commands (echocance,
noisesuppressor, ...).
Channel: Channel name
Command: capicomand command
+-------------------------------------------------------------------+
| Event CapichatList |
+-------------------------------------------------------------------+
Provided information about state of conference member.
Event: CapichatList
ActionID: Action ID as used in CapichatList request.
Conference: Conference room name
UserNumber: User in conference
CallerIDNum: CID
CallerIDName: CID name
Channel: Channel name
Admin: Yes/No
Role: Listen onlys/Talk and listen/Talk only
MarkedUser: Yes/No
Muted: No/By self/By admin/
Talking: Yes/No/Not monitored
Domain: TDM/IP
DTMF: %s\r\n"
EchoCancel: Yes/No
NoiseSupp: Yes/No
RxAGC: Yes/No
TxAGC: Yes/No
RxGain: Gain value in dB
TxGain: Gain value in dB
+-------------------------------------------------------------------+
| Event CapichatListComplet |
+-------------------------------------------------------------------+
Terminates serie of CapichatList events.
ListItems: Mumber of CapichatList events preceeding to this event
+-------------------------------------------------------------------+
| Event CapichatJoin |
+-------------------------------------------------------------------+
User joined conference
Channel: User name (Channel name)
Uniqueid: Unique channel ID
Conference: Conference room name
Conferencenum: Conference room number
CallerIDnum: CID
CallerIDname: CID name
+-------------------------------------------------------------------+
| Event CapichatLeave |
+-------------------------------------------------------------------+
User leaved conference
Channel: User name (Channel name)
Uniqueid: Unique channel ID
Conference: Conference room name
Conferencenum: Conference room number
CallerIDnum: CID
CallerIDname: CID name
Duration: Time user spend in conference, sec.
+-------------------------------------------------------------------+
| Event CapichatEnd |
+-------------------------------------------------------------------+
Last user leaved conference
Conference: Conference room name
+-------------------------------------------------------------------+
| Device state event ISDN/I[N]/congestion |
+-------------------------------------------------------------------+
Device state event ISDN/I[N]/congestion, where [N] is CAPI controller
number.
Provides state of CAPI interface.
+-------------------------------------------------------------------+
| Device state event capichat:[room] |
+-------------------------------------------------------------------+
Device state event capichat:[room], where [room] is the conference
name.
Provides state of Capichat conference room.

View File

@ -21,11 +21,11 @@ Supported hardware:
feature only together with RTP.
Syntax:
noisesuppressor|yes,no
noisesuppressor,[yes|no]
Syntax example:
s,n,capicommand(noisesuppressor|yes)
s,n,capicommand(noisesuppressor|no)
s,n,capicommand(noisesuppressor,yes)
s,n,capicommand(noisesuppressor,no)
IVR example:
/////////////////////////////////////////////////////////////////////
@ -36,9 +36,9 @@ exten => s,1,Set(TIMEOUT(digit)=5) ; Set Digit Timeout to 5 seconds
exten => s,n,Set(TIMEOUT(response)=10) ; Set Response Timeout to 10 seconds
exten => s,n(restart),BackGround(demo-instruct) ; Play some instructions
exten => s,n,WaitExten ; Wait for an extension to be dialed.
exten => 1,1,capicommand(noisesuppressor|yes)
exten => 1,1,capicommand(noisesuppressor,yes)
exten => 1,n,Goto(s,restart)
exten => 2,1,capicommand(noisesuppressor|no)
exten => 2,1,capicommand(noisesuppressor,no)
exten => 2,n,Goto(s,restart)
exten => 99,1,Echo
exten => i,1,Playback(invalid)
@ -49,7 +49,7 @@ exten => h,1,Hangup
PBX Example:
/////////////////////////////////////////////////////////////////////
[macro-capinoisesuppressor]
exten => s,1,capicommand(noisesuppressor|yes)
exten => s,1,capicommand(noisesuppressor,yes)
[isdn-in]
exten => 12345,1,Progress()
@ -58,7 +58,7 @@ exten => 12345,n,Set(TIMEOUT(response)=5) ; Set Response Timeout to 10 seconds
exten => 12345,n,Playback(demo-enterkeywords,noanswer,us)
exten => 12345,n,Answer
exten => 12345,n,Wait(2)
exten => 12345,n,capicommand(noisesuppressor|yes)
exten => 12345,n,capicommand(noisesuppressor,yes)
exten => 12345,n,Dial(DIALOGICDIVA/ISDN1/100,10,M(capinoisesuppressor))
exten => 12345,n,Hangup()
/////////////////////////////////////////////////////////////////////
@ -79,14 +79,14 @@ Supported hardware:
Requires one Dialogic(R) Diva(R) Media Board equipped with DSPs.
Syntax:
clamping|N
clamping,N
N - estimated duration of DTMF tones to be suppressed in ms
0 - deactivate clamping
1 ... 250 - activate clamping
Syntax example:
s,n,capicommand(clamping|100)
s,n,capicommand(clamping|0)
s,n,capicommand(clamping,100)
s,n,capicommand(clamping,0)
IVR example:
/////////////////////////////////////////////////////////////////////
@ -97,9 +97,9 @@ exten => s,1,Set(TIMEOUT(digit)=5) ; Set Digit Timeout to 5 seconds
exten => s,n,Set(TIMEOUT(response)=10) ; Set Response Timeout to 10 seconds
exten => s,n(restart),BackGround(demo-instruct) ; Play some instructions
exten => s,n,WaitExten ; Wait for an extension to be dialed.
exten => 1,1,capicommand(clamping|100)
exten => 1,1,capicommand(clamping,100)
exten => 1,n,Goto(s,restart)
exten => 2,1,capicommand(clamping|0)
exten => 2,1,capicommand(clamping,0)
exten => 2,n,Goto(s,restart)
exten => 99,1,Echo
exten => i,1,Playback(invalid)
@ -110,7 +110,7 @@ exten => h,1,Hangup
PBX Example:
/////////////////////////////////////////////////////////////////////
[macro-capiclamping]
exten => s,1,capicommand(clamping|100)
exten => s,1,capicommand(clamping,100)
[isdn-in]
exten => 12345,1,Progress()
@ -119,7 +119,7 @@ exten => 12345,n,Set(TIMEOUT(response)=5) ; Set Response Timeout to 10 seconds
exten => 12345,n,Playback(demo-enterkeywords,noanswer,us)
exten => 12345,n,Answer
exten => 12345,n,Wait(2)
exten => 12345,n,capicommand(clamping|100)
exten => 12345,n,capicommand(clamping,100)
exten => 12345,n,Dial(DIALOGICDIVA/ISDN1/100,10,M(capiclamping))
exten => 12345,n,Hangup()
/////////////////////////////////////////////////////////////////////
@ -140,11 +140,11 @@ Supported hardware:
Requires one Diva Media Board equipped with DSPs.
Syntax:
rxagc|yes,no
rxagc,[yes|no]
Syntax example:
s,n,capicommand(rxagc|yes)
s,n,capicommand(rxagc|no)
s,n,capicommand(rxagc,yes)
s,n,capicommand(rxagc,no)
IVR example:
/////////////////////////////////////////////////////////////////////
@ -155,9 +155,9 @@ exten => s,1,Set(TIMEOUT(digit)=5) ; Set Digit Timeout to 5 seconds
exten => s,n,Set(TIMEOUT(response)=10) ; Set Response Timeout to 10 seconds
exten => s,n(restart),BackGround(demo-instruct) ; Play some instructions
exten => s,n,WaitExten ; Wait for an extension to be dialed.
exten => 1,1,capicommand(rxagc|yes)
exten => 1,1,capicommand(rxagc,yes)
exten => 1,n,Goto(s,restart)
exten => 2,1,capicommand(rxagc|no)
exten => 2,1,capicommand(rxagc,no)
exten => 2,n,Goto(s,restart)
exten => 99,1,Echo
exten => i,1,Playback(invalid)
@ -168,7 +168,7 @@ exten => h,1,Hangup
PBX Example:
/////////////////////////////////////////////////////////////////////
[macro-capirxagc]
exten => s,1,capicommand(rxagc|yes)
exten => s,1,capicommand(rxagc,yes)
[isdn-in]
exten => 12345,1,Progress()
@ -177,7 +177,7 @@ exten => 12345,n,Set(TIMEOUT(response)=5) ; Set Response Timeout to 10 seconds
exten => 12345,n,Playback(demo-enterkeywords,noanswer,us)
exten => 12345,n,Answer
exten => 12345,n,Wait(2)
exten => 12345,n,capicommand(rxagc|yes)
exten => 12345,n,capicommand(rxagc,yes)
exten => 12345,n,Dial(DIALOGICDIVA/ISDN1/100,10,M(capirxagc))
exten => 12345,n,Hangup()
/////////////////////////////////////////////////////////////////////
@ -198,11 +198,11 @@ Supported hardware:
Requires one Diva Media Board equipped with DSPs.
Syntax:
txagc|yes,no
txagc,[yes|no]
Syntax example:
s,n,capicommand(txagc|yes)
s,n,capicommand(txagc|no)
s,n,capicommand(txagc,yes)
s,n,capicommand(txagc,no)
IVR example:
See rxagc
@ -226,14 +226,14 @@ Supported hardware:
Requires one Diva Media Board equipped with DSPs.
Syntax:
rxdgain|N
rxdgain,N
N - gain in dBm, float
-127 ... +6 - gain
-128 or less - infinite attenuation
Syntax example:
s,n,capicommand(rxdgain|5.5)
s,n,capicommand(rxdgain|-14.2)
s,n,capicommand(rxdgain,5.5)
s,n,capicommand(rxdgain,-14.2)
IVR example:
/////////////////////////////////////////////////////////////////////
@ -244,9 +244,9 @@ exten => s,1,Set(TIMEOUT(digit)=5) ; Set Digit Timeout to 5 seconds
exten => s,n,Set(TIMEOUT(response)=10) ; Set Response Timeout to 10 seconds
exten => s,n(restart),BackGround(demo-instruct) ; Play some instructions
exten => s,n,WaitExten ; Wait for an extension to be dialed.
exten => 1,1,capicommand(rxdgain|5.5)
exten => 1,1,capicommand(rxdgain,5.5)
exten => 1,n,Goto(s,restart)
exten => 2,1,capicommand(rxdgain|-70)
exten => 2,1,capicommand(rxdgain,-70)
exten => 2,n,Goto(s,restart)
exten => 99,1,Echo
exten => i,1,Playback(invalid)
@ -270,12 +270,12 @@ Supported hardware:
Requires one Diva Media Board equipped with DSPs.
incSyntax:
rxdgain|N
rxdgain,N
N - gain increment in dBm, float
Syntax example:
s,n,capicommand(incrxdgain|2.5) // add 2.5 dBm to actiall gain
s,n,capicommand(incrxdgain|-2.5) // substract 2.5 dBm from actual gain
s,n,capicommand(incrxdgain,2.5) // add 2.5 dBm to actiall gain
s,n,capicommand(incrxdgain,-2.5) // substract 2.5 dBm from actual gain
IVR example:
/////////////////////////////////////////////////////////////////////
@ -286,9 +286,9 @@ exten => s,1,Set(TIMEOUT(digit)=5) ; Set Digit Timeout to 5 seconds
exten => s,n,Set(TIMEOUT(response)=10) ; Set Response Timeout to 10 seconds
exten => s,n(restart),BackGround(demo-instruct) ; Play some instructions
exten => s,n,WaitExten ; Wait for an extension to be dialed.
exten => 1,1,capicommand(incrxdgain|2.5)
exten => 1,1,capicommand(incrxdgain,2.5)
exten => 1,n,Goto(s,restart)
exten => 2,1,capicommand(incrxdgain|-2.5)
exten => 2,1,capicommand(incrxdgain,-2.5)
exten => 2,n,Goto(s,restart)
exten => 99,1,Echo
exten => i,1,Playback(invalid)
@ -312,14 +312,14 @@ Supported hardware:
Requires one Diva Media Board equipped with DSPs.
Syntax:
txdgain|N
txdgain,N
N - gain in dBm, float
-127 ... +6 - gain
-128 or less - infinite attenuation
Syntax example:
s,n,capicommand(txdgain|5.5)
s,n,capicommand(txdgain|-14.2)
s,n,capicommand(txdgain,5.5)
s,n,capicommand(txdgain,-14.2)
IVR example:
/////////////////////////////////////////////////////////////////////
@ -330,9 +330,9 @@ exten => s,1,Set(TIMEOUT(digit)=5) ; Set Digit Timeout to 5 seconds
exten => s,n,Set(TIMEOUT(response)=10) ; Set Response Timeout to 10 seconds
exten => s,n(restart),BackGround(demo-instruct) ; Play some instructions
exten => s,n,WaitExten ; Wait for an extension to be dialed.
exten => 1,1,capicommand(txdgain|5.5)
exten => 1,1,capicommand(txdgain,5.5)
exten => 1,n,Goto(s,restart)
exten => 2,1,capicommand(txdgain|-70)
exten => 2,1,capicommand(txdgain,-70)
exten => 2,n,Goto(s,restart)
exten => 99,1,Echo
exten => i,1,Playback(invalid)
@ -356,12 +356,12 @@ Supported hardware:
Requires one Diva Media Board equipped with DSPs.
incSyntax:
rxtgain|N
rxtgain,N
N - gain increment in dBm, float
Syntax example:
s,n,capicommand(inctxdgain|2.5) // add 2.5 dBm to actiall gain
s,n,capicommand(inctxdgain|-2.5) // substract 2.5 dBm from actual gain
s,n,capicommand(inctxdgain,2.5) // add 2.5 dBm to actiall gain
s,n,capicommand(inctxdgain,-2.5) // substract 2.5 dBm from actual gain
IVR example:
/////////////////////////////////////////////////////////////////////
@ -372,9 +372,9 @@ exten => s,1,Set(TIMEOUT(digit)=5) ; Set Digit Timeout to 5 seconds
exten => s,n,Set(TIMEOUT(response)=10) ; Set Response Timeout to 10 seconds
exten => s,n(restart),BackGround(demo-instruct) ; Play some instructions
exten => s,n,WaitExten ; Wait for an extension to be dialed.
exten => 1,1,capicommand(inctxdgain|2.5)
exten => 1,1,capicommand(inctxdgain,2.5)
exten => 1,n,Goto(s,restart)
exten => 2,1,capicommand(inctxdgain|-2.5)
exten => 2,1,capicommand(inctxdgain,-2.5)
exten => 2,n,Goto(s,restart)
exten => 99,1,Echo
exten => i,1,Playback(invalid)
@ -404,15 +404,15 @@ Supported hardware:
Requires one Diva Media Board equipped with DSPs.
Syntax:
pitchcontrol|RxN|TxN - set Rx and Tx rate to different values
pitchcontrol|N - set Rx and Tx rate to same value
pitchcontrol,RxN,TxN - set Rx and Tx rate to different values
pitchcontrol,N - set Rx and Tx rate to same value
pitchcontrol - deactivate rate control
RxN, TxN, N - rate in the range 1250 ... 51200 Hz.
Syntax example:
s,n,capicommand(pitchcontrol|8200,8100) ; Set Rx rate to 8200 Hz and Tx rate to 8100 Hz
s,n,capicommand(pitchcontrol|8400) ; Set Rx and Tx rate to 8400 Hz
s,n,capicommand(pitchcontrol,8200,8100) ; Set Rx rate to 8200 Hz and Tx rate to 8100 Hz
s,n,capicommand(pitchcontrol,8400) ; Set Rx and Tx rate to 8400 Hz
IVR example:
/////////////////////////////////////////////////////////////////////
@ -423,9 +423,9 @@ exten => s,1,Set(TIMEOUT(digit)=5) ; Set Digit Timeout to 5 seconds
exten => s,n,Set(TIMEOUT(response)=10) ; Set Response Timeout to 10 seconds
exten => s,n(restart),BackGround(demo-instruct) ; Play some instructions
exten => s,n,WaitExten ; Wait for an extension to be dialed.
exten => 1,1,capicommand(pitchcontrol|8200)
exten => 1,1,capicommand(pitchcontrol,8200)
exten => 1,n,Goto(s,restart)
exten => 2,1,capicommand(pitchcontrol|8000)
exten => 2,1,capicommand(pitchcontrol,8000)
exten => 2,n,Goto(s,restart)
exten => 99,1,Echo
exten => i,1,Playback(invalid)
@ -455,14 +455,14 @@ Supported hardware:
Requires one Diva Media Board equipped with DSPs.
Syntax:
incpitchcontrol|RxN|TxN - change Rx and Tx rate using different values
incpitchcontrol|N - change Rx and Tx rate using same value
incpitchcontrol,RxN,TxN - change Rx and Tx rate using different values
incpitchcontrol,N - change Rx and Tx rate using same value
RxN, TxN, N - rate change in Hz
Syntax example:
s,n,capicommand(incpitchcontrol|100) // Increase Rx and Tx rate by 100 Hz
s,n,capicommand(incpitchcontrol|-100) // Decrease Rx and Tx rate by 100 Hz
s,n,capicommand(incpitchcontrol,100) // Increase Rx and Tx rate by 100 Hz
s,n,capicommand(incpitchcontrol,-100) // Decrease Rx and Tx rate by 100 Hz
IVR example:
/////////////////////////////////////////////////////////////////////
@ -473,9 +473,9 @@ exten => s,1,Set(TIMEOUT(digit)=5) ; Set Digit Timeout to 5 seconds
exten => s,n,Set(TIMEOUT(response)=10) ; Set Response Timeout to 10 seconds
exten => s,n(restart),BackGround(demo-instruct) ; Play some instructions
exten => s,n,WaitExten ; Wait for an extension to be dialed.
exten => 1,1,capicommand(incpitchcontrol|100)
exten => 1,1,capicommand(incpitchcontrol,100)
exten => 1,n,Goto(s,restart)
exten => 2,1,capicommand(incpitchcontrol|100)
exten => 2,1,capicommand(incpitchcontrol,100)
exten => 2,n,Goto(s,restart)
exten => 99,1,Echo
exten => i,1,Playback(invalid)
@ -501,11 +501,11 @@ Supported hardware:
Requires one Diva Media Board equipped with DSPs.
Syntax:
mftonedetection|yes,no
mftonedetection,[yes|no]
Syntax example:
s,n,capicommand(mftonedetection|yes)
s,n,capicommand(mftonedetection|no)
s,n,capicommand(mftonedetection,yes)
s,n,capicommand(mftonedetection,no)
IVR example:
/////////////////////////////////////////////////////////////////////
@ -516,9 +516,9 @@ exten => s,1,Set(TIMEOUT(digit)=5) ; Set Digit Timeout to 5 seconds
exten => s,n,Set(TIMEOUT(response)=10) ; Set Response Timeout to 10 seconds
exten => s,n(restart),BackGround(demo-instruct) ; Play some instructions
exten => s,n,WaitExten ; Wait for an extension to be dialed.
exten => 1,1,capicommand(mftonedetection|yes)
exten => 1,1,capicommand(mftonedetection,yes)
exten => 1,n,Goto(s,restart)
exten => 2,1,capicommand(mftonedetection|no)
exten => 2,1,capicommand(mftonedetection,no)
exten => 2,n,Goto(s,restart)
exten => 99,1,Echo
exten => i,1,Playback(invalid)
@ -542,11 +542,11 @@ Supported hardware:
Requires one Diva Media Board equipped with DSPs.
Syntax:
pulsedetection|yes,no
pulsedetection,[yes|no]
Syntax example:
s,n,capicommand(pulsedetection|yes)
s,n,capicommand(pulsedetection|no)
s,n,capicommand(pulsedetection,yes)
s,n,capicommand(pulsedetection,no)
IVR example:
/////////////////////////////////////////////////////////////////////
@ -557,9 +557,9 @@ exten => s,1,Set(TIMEOUT(digit)=5) ; Set Digit Timeout to 5 seconds
exten => s,n,Set(TIMEOUT(response)=10) ; Set Response Timeout to 10 seconds
exten => s,n(restart),BackGround(demo-instruct) ; Play some instructions
exten => s,n,WaitExten ; Wait for an extension to be dialed.
exten => 1,1,capicommand(pulsedetection|yes)
exten => 1,1,capicommand(pulsedetection,yes)
exten => 1,n,Goto(s,restart)
exten => 2,1,capicommand(pulsedetection|no)
exten => 2,1,capicommand(pulsedetection,no)
exten => 2,n,Goto(s,restart)
exten => 99,1,Echo
exten => i,1,Playback(invalid)
@ -584,7 +584,7 @@ Supported hardware:
Requires one Diva Media Board equipped with DSPs.
Syntax:
sendtone|N
sendtone,N
stoptone
N - tone to be sent
@ -633,7 +633,7 @@ stoptone
0xCB - Tone Alerting Signal (for Caller ID in PSTN)
Syntax example:
s,n,capicommand(sendtone|0x83) ; Send PABX internal dial tone
s,n,capicommand(sendtone,0x83) ; Send PABX internal dial tone
s,n,capicommand(stoptone) ; stop tone transmission
IVR example
@ -645,7 +645,7 @@ exten => s,1,Set(TIMEOUT(digit)=5) ; Set Digit Timeout to 5 seconds
exten => s,n,Set(TIMEOUT(response)=10) ; Set Response Timeout to 10 seconds
exten => s,n(restart),BackGround(demo-instruct) ; Play some instructions
exten => s,n,WaitExten ; Wait for an extension to be dialed.
exten => 1,1,capicommand(sendtone|0x83)
exten => 1,1,capicommand(sendtone,0x83)
exten => 1,n,Goto(s,restart)
exten => 2,1,capicommand(stoptone)
exten => 2,n,Goto(s,restart)
@ -673,7 +673,7 @@ Supported hardware:
Not available if RTP is active.
Syntax:
starttonedetection|N
starttonedetection,N
stoptonedetection
N - Extension number to be used in case a tone is detected.
@ -729,7 +729,7 @@ stoptonedetection
0xCB - Tone Alerting Signal detected (for Caller ID in PSTN)
Syntax example:
s,n,capicommand(starttonedetection|98) ; Change to extension 98 after detection of tone
s,n,capicommand(starttonedetection,98) ; Change to extension 98 after detection of tone
s,n,capicommand(stoptonedetection) ; Disable detection of tones
IVR example:
@ -746,7 +746,7 @@ exten => s,n,WaitExten ; Wait for an extension to be dialed.
exten => 1,1,Set(TIMEOUT(digit)=1)
exten => 1,n,Set(TIMEOUT(response)=5)
exten => 1,n,capicommand(starttonedetection|98) ; Change to 98 once tone is detected
exten => 1,n,capicommand(starttonedetection,98) ; Change to 98 once tone is detected
exten => 1,n,Goto(s,restart)
; Continue after detection of the tone
@ -786,13 +786,13 @@ Description:
independent from the dialplan.
Syntax:
vc|command|key|param|param1|...|paranN
Add to menu: on detection of key execute command using parameters param1|...|paramN
vc,command,key,param,param1,...,paranN
Add to menu: on detection of key execute command using parameters param1,...,paramN
vc|command|key
vc,command,key
Add to menu: on detection of key execute command without parameters
vc|command
vc,command
Remove all instances of command from menu
vc
@ -800,12 +800,12 @@ vc
In case one command will use a key that is already in use, then a new command will overwrite
the existing command:
exten => s,n,capicommand(vc|txagc|3|yes)
exten => s,n,capicommand(vc|inctxdgain|3|1.5)
exten => s,n,capicommand(vc,txagc,3,yes)
exten => s,n,capicommand(vc,inctxdgain,3,1.5)
is equivalent to:
exten => s,n,capicommand(vc|inctxdgain|3|1.5)
exten => s,n,capicommand(vc,inctxdgain,3,1.5)
It is better to use only one digit as key for commands in menu if using the menu for IVR and
voice mailbox. This provides short response time.
@ -814,8 +814,8 @@ In case the menu is used for conference or for connection between two parties, i
two or three digits for the key. This will prevent an activation by accidentally pressing a key.
Syntax example:
exten => s,n,capicommand(vc|inctxdgain|5|1.5) ; Execute inctxdgain|1.5 if received DTMF digit 5
exten => s,n,capicommand(vc|txagc|3|yes) ; Execute txagc|yes if received DTMF digit 3
exten => s,n,capicommand(vc,inctxdgain,5,1.5) ; Execute inctxdgain,1.5 if received DTMF digit 5
exten => s,n,capicommand(vc,txagc,3,yes) ; Execute txagc,yes if received DTMF digit 3
IVR Example:
/////////////////////////////////////////////////////////////////////
@ -823,14 +823,14 @@ IVR Example:
exten => _X.,1,Answer
exten => _X.,n,Goto(s,1)
exten => s,1,Wait(1)
exten => s,n,capicommand(vc|sendtone|1|0x82)
exten => s,n,capicommand(vc|stoptone|2)
exten => s,n,capicommand(vc|txagc|3|yes)
exten => s,n,capicommand(vc|txagc|4|no)
exten => s,n,capicommand(vc|inctxdgain|5|1.5)
exten => s,n,capicommand(vc|inctxdgain|7|-2.5)
exten => s,n,capicommand(vc|incpitchcontrol|8|0|100)
exten => s,n,capicommand(vc|incpitchcontrol|9|0|-400)
exten => s,n,capicommand(vc,sendtone,1,0x82)
exten => s,n,capicommand(vc,stoptone,2)
exten => s,n,capicommand(vc,txagc,3,yes)
exten => s,n,capicommand(vc,txagc,4,no)
exten => s,n,capicommand(vc,inctxdgain,5,1.5)
exten => s,n,capicommand(vc,inctxdgain,7,-2.5)
exten => s,n,capicommand(vc,incpitchcontrol,8,0,100)
exten => s,n,capicommand(vc,incpitchcontrol,9,0,-400)
exten => s,n(restart),Playback(demo-instruct)
exten => s,n,Goto(s,restart)
exten => s,n,Hangup
@ -870,7 +870,7 @@ Supported hardware:
Diva
Syntax:
capicommand(chat|<roomname>|<options>|controller)
capicommand(chat,<roomname>,<options>,controller)
roomname - conference room name
options
m - The first caller will get music-on-hold until the second caller arrives
@ -880,12 +880,12 @@ capicommand(chat|<roomname>|<options>|controller)
controller - CAPI controller
Syntax example:
exten => s,n,capicommand(chat|test|m|1)
exten => s,n,capicommand(chat|test|m|1,3)
exten => s,n,capicommand(chat|test|m|1-4)
exten => s,n,capicommand(chat|test|m|1-4,7)
exten => s,n,capicommand(chat|test|m|1-4,7-10)
exten => s,n,capicommand(chat|test|mh300|1-4)
exten => s,n,capicommand(chat,test,m,1)
exten => s,n,capicommand(chat,test,m,1,3)
exten => s,n,capicommand(chat,test,m,1-4)
exten => s,n,capicommand(chat,test,m,1-4,7)
exten => s,n,capicommand(chat,test,m,1-4,7-10)
exten => s,n,capicommand(chat,test,mh300,1-4)
IVR example:
/////////////////////////////////////////////////////////////////////
@ -898,21 +898,21 @@ exten => s,n(restart),BackGround(demo-instruct) ; Play some instructions
exten => s,n,WaitExten ; Wait for an extension to be dialed, use to select conference room
; You can create macro to set up vc menu
exten => 1,1,capicommand(clamping|100) ; Activate suppression of DTMF tones
exten => 1,n,capicommand(vc|incrxdgain|0|1.5) ; Install voice command menu for volume control, '0' to increase volume
exten => 1,n,capicommand(vc|incrxdgain|1|-1.5) ; Install voice command menu for volume control, '1' to decrease volume
exten => 1,n,capicommand(vc|txdgain|2|-128) ; Install voice command menu for volume control, '2' to mute tx path
exten => 1,n,capicommand(vc|txdgain|3|0) ; Install voice command menu for volume control, '3' to activate tx path
exten => 1,n,capicommand(chat|test1|m|1-4) ; Create/enter conference room 'test1'
exten => 1,1,capicommand(clamping,100) ; Activate suppression of DTMF tones
exten => 1,n,capicommand(vc,incrxdgain,0,1.5) ; Install voice command menu for volume control, '0' to increase volume
exten => 1,n,capicommand(vc,incrxdgain,1,-1.5) ; Install voice command menu for volume control, '1' to decrease volume
exten => 1,n,capicommand(vc,txdgain,2,-128) ; Install voice command menu for volume control, '2' to mute tx path
exten => 1,n,capicommand(vc,txdgain,3,0) ; Install voice command menu for volume control, '3' to activate tx path
exten => 1,n,capicommand(chat,test1,m,1-4) ; Create/enter conference room 'test1'
exten => 2,1,capicommand(clamping|100) ; Activate suppression of DTMF tones
exten => 2,n,capicommand(txdgain|-128) ; Deactivate tx path
exten => 2,n,capicommand(vc|incrxdgain|0|1.5) ; Install voice command menu for volume control, '0' to increase volume
exten => 2,n,capicommand(vc|incrxdgain|1|-1.5) ; Install voice command menu for volume control, '1' to decrease volume
exten => 2,n,capicommand(vc|txdgain|2|-128) ; Install voice command menu for volume control, '2' to mute tx path
exten => 2,n,capicommand(vc|txdgain|3|0) ; Install voice command menu for volume control, '3' to activate tx path
exten => 2,n,capicommand(chat|test1|m|1-4) ; Create/enter conference room 'test1
exten => 2,n,capicommand(chat|test2|m|1-4) ; Create/enter conference room 'test2'
exten => 2,1,capicommand(clamping,100) ; Activate suppression of DTMF tones
exten => 2,n,capicommand(txdgain,-128) ; Deactivate tx path
exten => 2,n,capicommand(vc,incrxdgain,0,1.5) ; Install voice command menu for volume control, '0' to increase volume
exten => 2,n,capicommand(vc,incrxdgain,1,-1.5) ; Install voice command menu for volume control, '1' to decrease volume
exten => 2,n,capicommand(vc,txdgain,2,-128) ; Install voice command menu for volume control, '2' to mute tx path
exten => 2,n,capicommand(vc,txdgain,3,0) ; Install voice command menu for volume control, '3' to activate tx path
exten => 2,n,capicommand(chat,test1,m,1-4) ; Create/enter conference room 'test1
exten => 2,n,capicommand(chat,test2,m,1-4) ; Create/enter conference room 'test2'
exten => i,1,Playback(invalid)
exten => i,n,Goto(s,restart)
@ -1006,32 +1006,35 @@ Supported hardware:
Syntax:
capicommand(ressource|controller)
capicommand(ressource,controller[,codeclist])
controller - CAPI controller
codeclist - separated by '+' character list of supported codecs, optional
codec oder codec1+codec2+...+codecN
Syntax example:
exten => s,n,capicommand(resource|1)
exten => s,n,capicommand(resource|1,3)
exten => s,n,capicommand(resource|1-4)
exten => s,n,capicommand(resource|1-4,7)
exten => s,n,capicommand(resource|1-4,7-10)
exten => s,n,capicommand(resource,1)
exten => s,n,capicommand(resource,1,3)
exten => s,n,capicommand(resource,1-4)
exten => s,n,capicommand(resource,1-4,7)
exten => s,n,capicommand(resource,1-4,7-10)
exten => s,n,capicommand(resource,1-4,7-10,gsm)
exten => s,n,capicommand(resource,1-4,7-10,alaw+ulaw+gsm+g722)
IVR example:
/////////////////////////////////////////////////////////////////////
[isdn-in]
exten => _X.,1,Answer ; Answer the line
exten => _X.,n,Goto(s,1)
exten => s,1,capicommand(resource|1-4) ; Create DSP resource on CAPI controllers 1-4 for IP members,
exten => s,1,capicommand(resource,1-4) ; Create DSP resource on CAPI controllers 1-4 for IP members,
; ignore command for E.1/T.1/S0/POTS members
exten => s,n,capicommand(clamping|100) ; Activate suppression of DTMF tones
exten => s,n,capicommand(rxagc|yes) ; Activate Rx AGC
exten => s,n,capicommand(noisesuppressor|yes) ; Activate suppression of ambient noises
exten => s,n,capicommand(vc|incrxdgain|0|1.5) ; Install voice command menu for volume control, '0' to increase volume
exten => s,n,capicommand(vc|incrxdgain|1|-1.5) ; Install voice command menu for volume control, '1' to decrease volume
exten => s,n,capicommand(vc|txdgain|2|-128) ; Install voice command menu for volume control, '2' to mute tx path
exten => s,n,capicommand(vc|txdgain|3|0) ; Install voice command menu for volume control, '3' to activate tx path
exten => s,n,capicommand(chat|test1|m|1-4) ; Craete/enter conference toom 'test1', controller field is ignored if
exten => s,n,capicommand(clamping,100) ; Activate suppression of DTMF tones
exten => s,n,capicommand(rxagc,yes) ; Activate Rx AGC
exten => s,n,capicommand(noisesuppressor,yes) ; Activate suppression of ambient noises
exten => s,n,capicommand(vc,incrxdgain,0,1.5) ; Install voice command menu for volume control, '0' to increase volume
exten => s,n,capicommand(vc,incrxdgain,1,-1.5) ; Install voice command menu for volume control, '1' to decrease volume
exten => s,n,capicommand(vc,txdgain,2,-128) ; Install voice command menu for volume control, '2' to mute tx path
exten => s,n,capicommand(vc,txdgain,3,0) ; Install voice command menu for volume control, '3' to activate tx path
exten => s,n,capicommand(chat,test1,m,1-4) ; Craete/enter conference toom 'test1', controller field is ignored if
; media processing resource is assigned by 'resource' command or for
; E.1/T.1/S0/POTS members
@ -1071,14 +1074,14 @@ Direction:
Note:
The voice stream of regular users is active by default. If the conference mode was changed to half duplex
('chat_mute|yes'), then new regular users are created with a deactivated voice stream until the conference
mode is changed back to full duplex ('chat_mute|no')
('chat_mute,yes'), then new regular users are created with a deactivated voice stream until the conference
mode is changed back to full duplex ('chat_mute,no')
Supported hardware:
Diva
Syntax:
capicommand(chat_mute|<action>[|<roomname>])
capicommand(chat_mute,<action>[,<roomname>])
action - mandatory
yes - Change conference mode to half duplex, deactivate voice stream from regular
users to conference.
@ -1090,32 +1093,32 @@ capicommand(chat_mute|<action>[|<roomname>])
functionality of a common conference operator.
Syntax example:
exten => s,n,capicommand(chat_mute|yes)
exten => s,n,capicommand(char_mute|no)
exten => s,n,capicommand(chat_mute|yes|test_room)
exten => s,n,capicommand(char_mute|no|test_room)
exten => s,n,capicommand(chat_mute,yes)
exten => s,n,capicommand(char_mute,no)
exten => s,n,capicommand(chat_mute,yes,test_room)
exten => s,n,capicommand(char_mute,no,test_room)
Conference example:
/////////////////////////////////////////////////////////////////////
[isdn-in]
exten => 1291,1,Answer ; Accept call
exten => 1291,n,capicommand(resource|1-4) ; assign resource PLCI if call from IP
exten => 1291,n,capicommand(clamping|200) ; Activate DTMF suppression
exten => 1291,n,capicommand(vc|chat_mute|0|yes) ; Voice command, key 0 - change to half duplex mode
exten => 1291,n,capicommand(vc|chat_mute|1|no) ; Voice command, key 0 - change to full duplex mode
exten => 1291,n,capicommand(chat|test_chat|mo|1-4) ; Add to conference as operator
exten => 1291,n,capicommand(resource,1-4) ; assign resource PLCI if call from IP
exten => 1291,n,capicommand(clamping,200) ; Activate DTMF suppression
exten => 1291,n,capicommand(vc,chat_mute,0,yes) ; Voice command, key 0 - change to half duplex mode
exten => 1291,n,capicommand(vc,chat_mute,1,no) ; Voice command, key 0 - change to full duplex mode
exten => 1291,n,capicommand(chat,test_chat,mo,1-4) ; Add to conference as operator
exten => 1291,n,Hangup()
exten => 1292,1,Answer ; Accept call
exten => 1292,n,capicommand(resource|1-4) ; Assign resource PLCI if call from IP
exten => 1292,n,capicommand(clamping|200) ; Activate DTMF suppression
exten => 1292,n,capicommand(chat|test_chat|m|1-4) ; Add to conference as regular user
exten => 1292,n,capicommand(resource,1-4) ; Assign resource PLCI if call from IP
exten => 1292,n,capicommand(clamping,200) ; Activate DTMF suppression
exten => 1292,n,capicommand(chat,test_chat,m,1-4) ; Add to conference as regular user
exten => 1292,n,Hangup()
exten => 1293,1,Answer ; Accept call
exten => 1293,n,capicommand(resource|1-4) ; Assign resource PLCI if call from IP
exten => 1293,n,capicommand(clamping|200) ; Activate DTMF suppression
exten => 1293,n,capicommand(chat|test_chat|ml|1-4) ; Add to conference as listener
exten => 1293,n,capicommand(resource,1-4) ; Assign resource PLCI if call from IP
exten => 1293,n,capicommand(clamping,200) ; Activate DTMF suppression
exten => 1293,n,capicommand(chat,test_chat,ml,1-4) ; Add to conference as listener
exten => 1293,n,Hangup()
exten => _X.,1,Answer
@ -1142,7 +1145,7 @@ Supported hardware:
Diva
Syntax:
capicommand(chat_play|<roomname>|<options>|<filename>|controller)
capicommand(chat_play,<roomname>,<options>,<filename>,controller)
roomname - conference room name
options
m - The caller will get music-on-hold while message is played
@ -1151,22 +1154,22 @@ capicommand(chat_play|<roomname>|<options>|<filename>|controller)
controller - CAPI controller
Syntax example:
exten => s,n,capicommand(chat|test|m|/tmp/file.alaw|1)
exten => s,n,capicommand(chat|test||/tmp/file.alaw|1-4,7-10)
exten => s,n,capicommand(chat,test,m,/tmp/file.alaw,1)
exten => s,n,capicommand(chat,test,,/tmp/file.alaw,1-4,7-10)
IVR example:
/////////////////////////////////////////////////////////////////////
[isdn-in]
exten => _X.,1,Answer ; Answer the line
exten => _X.,n,Goto(s,1)
exten => s,1,capicommand(clamping|100) ; Activate suppression of DTMF tones
exten => s,1,capicommand(clamping,100) ; Activate suppression of DTMF tones
exten => s,n,Playback(record-name) ; Ask for name
exten => s,n,capicommand(rxagc|yes) ; Activate Rx AGC
exten => s,n,capicommand(rxagc,yes) ; Activate Rx AGC
exten => s,n,Record(/tmp/${UNIQUEID}-info:alaw) ; Record message
exten => s,n,capicommand(rxagc|no) ; Deactivate Rx AGC
exten => s,n,capicommand(chat_play|test|m|/tmp/${UNIQUEID}-info.alaw|1-4) ; Play message to conference,
exten => s,n,capicommand(rxagc,no) ; Deactivate Rx AGC
exten => s,n,capicommand(chat_play,test,m,/tmp/${UNIQUEID}-info.alaw,1-4) ; Play message to conference,
; play music on hold to caller
exten => s,n,capicommand(chat|test|m|1-4) ; Create/enter conference room 'test'
exten => s,n,capicommand(chat,test,m,1-4) ; Create/enter conference room 'test'
/////////////////////////////////////////////////////////////////////
@ -1181,7 +1184,7 @@ Supported hardware:
Diva
Syntax:
capicommand(chat_command|<options>|<roomname>)
capicommand(chat_command,<options>,<roomname>)
options - mandatory
r - Remove newest user from conference.
Command does not apply to calling member and be used by operators only.
@ -1194,9 +1197,9 @@ capicommand(chat_command|<options>|<roomname>)
roomname - optional, room caller assigned to is used if not present
Syntax example:
exten => s,n,capicommand(chat_command|r)
exten => s,n,capicommand(chat_command|lo|test)
exten => s,n,capicommand(chat_command|a|test)
exten => s,n,capicommand(chat_command,r)
exten => s,n,capicommand(chat_command,lo,test)
exten => s,n,capicommand(chat_command,a,test)
Conference example:
/////////////////////////////////////////////////////////////////////
@ -1205,15 +1208,15 @@ exten => _X.,1,Answer
exten => _X.,n,Authenticate(12345)
exten => _X.,n,Playback(vm-rec-name)
exten => _X.,n,Record(/tmp/name${UNIQUEID}.alaw,5,15) ; Record name
exten => _X.,n,capicommand(chat_play|c1||/tmp/name${UNIQUEID}.alaw|1-4) ; Play name to conference
exten => _X.,n,capicommand(resource|1-4) ; Create resource PLCI if call from IP
exten => _X.,n,capicommand(clamping|200) ; Activate suppression of DTMF codes
exten => _X.,n,capicommand(vc|chat_mute|1|yes) ; Voice command, key 1 - mute all members except operators
exten => _X.,n,capicommand(vc|chat_mute|2|no) ; Voice command, key 2 - unmute all members except operators
exten => _X.,n,capicommand(vc|chat_command|0|a|c1) ; Voice command, key 0 - remove all members from conference
exten => _X.,n,capicommand(vc|noisesuppressor|3|yes) ; Voice command, key 3 - turn noise suppression on
exten => _X.,n,capicommand(vc|noisesuppressor|4|no) ; Voice command, key 4 - turn noise suppression off
exten => _X.,n,capicommand(chat|c1|mo|1-4) ; Add caller to conference as operator
exten => _X.,n,capicommand(chat_play,c1,,/tmp/name${UNIQUEID}.alaw,1-4) ; Play name to conference
exten => _X.,n,capicommand(resource,1-4) ; Create resource PLCI if call from IP
exten => _X.,n,capicommand(clamping,200) ; Activate suppression of DTMF codes
exten => _X.,n,capicommand(vc,chat_mute,1,yes) ; Voice command, key 1 - mute all members except operators
exten => _X.,n,capicommand(vc,chat_mute,2,no) ; Voice command, key 2 - unmute all members except operators
exten => _X.,n,capicommand(vc,chat_command,0,a,c1) ; Voice command, key 0 - remove all members from conference
exten => _X.,n,capicommand(vc,noisesuppressor,3,yes) ; Voice command, key 3 - turn noise suppression on
exten => _X.,n,capicommand(vc,noisesuppressor,4,no) ; Voice command, key 4 - turn noise suppression off
exten => _X.,n,capicommand(chat,c1,mo,1-4) ; Add caller to conference as operator
/////////////////////////////////////////////////////////////////////
@ -1253,11 +1256,11 @@ Supported hardware:
Diva Media Boards equipped with DSPs.
Syntax:
echocancel|yes,no
echocancel,[yes|no]
Syntax example:
s,n,capicommand(echocancel|yes)
s,n,capicommand(echocancel|no)
s,n,capicommand(echocancel,yes)
s,n,capicommand(echocancel,no)
IVR example:
/////////////////////////////////////////////////////////////////////
@ -1268,9 +1271,9 @@ exten => s,1,Set(TIMEOUT(digit)=5) ; Set Digit Timeout to 5 seconds
exten => s,n,Set(TIMEOUT(response)=10) ; Set Response Timeout to 10 seconds
exten => s,n(restart),BackGround(demo-instruct) ; Play some instructions
exten => s,n,WaitExten ; Wait for an extension to be dialed.
exten => 1,1,capicommand(echocancel|yes)
exten => 1,1,capicommand(echocancel,yes)
exten => 1,n,Goto(s,restart)
exten => 2,1,capicommand(echocancel|no)
exten => 2,1,capicommand(echocancel,no)
exten => 2,n,Goto(s,restart)
exten => 99,1,Echo
exten => i,1,Playback(invalid)
@ -1281,13 +1284,13 @@ exten => h,1,Hangup
PBX Example:
/////////////////////////////////////////////////////////////////////
[macro-capiechocancel]
exten => s,1,capicommand(echocancel|yes)
exten => s,1,capicommand(echocancel,yes)
[isdn-in]
exten => 12345,1,Progress()
exten => 12345,n,Set(TIMEOUT(digit)=1) ; Set Digit Timeout to 5 seconds
exten => 12345,n,Set(TIMEOUT(response)=5) ; Set Response Timeout to 10 seconds
exten => 12345,n,capicommand(echocancel|yes)
exten => 12345,n,capicommand(echocancel,yes)
exten => 12345,n,Playback(demo-enterkeywords,noanswer,us)
exten => 12345,n,Answer
exten => 12345,n,Wait(2)

93
README.mwi Normal file
View File

@ -0,0 +1,93 @@
+===================================================================+
| Message Waiting Indication (MWI) |
+===================================================================+
+-------------------------------------------------------------------+
| Control MWI indicators (MWI Server) |
+-------------------------------------------------------------------+
Using Asterisk 1.6 or newer it is possible to provide information about state of user
mailbox to ISDN phone.
Dependent on the state of mailbox this is possible to send MWI Activate or MWI deactivate
request to activate or to deactivate Message Waiting Indicator on the phone.
To activate MWI function on CAPI controller please provide in the configuration of this
controller the list of mailboxes to be monitored:
mwimailbox=mailbox1[:controlling user number1[:controlling user provided number1]][@context1], ...
The use of parameters can differ from PBX to PBX and even from PBX installation to PBX installation.
Following description apply to common use of parameters.
Where:
mailbox - Number of mailbox. Used to subsscribe to mailbox (voicemail.conf
and at same time used by PBX to address the MWI indicator on device.
controlling user number - Number where mailbox can be accessed (often same as mailbox)
controlling user provided number - Password, used by PBX to check permissions
Additional configuration parameters depends on type of PBX used and on the PBX installation:
mwifacptynrtype - type of MWI facility party number, 0 - unknown (default), 1 - public
mwifacptynrton - MWI facility party number type of number and numbering plan identification
(coding as for byte 0 of the calling party number). This byte is only valid
if byte mwifacptynrtype contains the value 1. Set to 0 by default.
mwifacptynrpres - MWI facility party number type presentation and screening indicator
(coding as for byte 1 of the calling party number). This byte is only valid
if byte mwifacptynrtype contains the value 1. Setr to 0 by default.
mwibasicservice - MWI basic Service, coded in accordance with ETS 300 196 [D.5]. Set to 1 (voice)
by default.
mwiinvocation - MWI invocation mode, 0 - deffered, 1 - immediate, 2 - combined,
65535 - suppres invocation code. Set to 2 by default.
Example:
[ISDN1]
controller=1
mwimailbox=12345:12345:221122@other,12347:12348,12349
activates monitoring of the mailboxes: 12345@other, 12347@default and 12349@default and sending
of MWI requests using CAPI controller 1.
+-------------------------------------------------------------------+
| Direct control MWI indicators (MWI Server) |
+-------------------------------------------------------------------+
This is possible to send MWI Activate and MWI deactivate messages
directly from dialplan using capicommand(mwi, ...).
This can be necessary if testing the system, if voice mailbox is managed
by other software (not by asterisk) or to verify MWI parameters.
capicommand(mwi,xmit,activate, ...) where parameters are:
CAPI controller, MWI basic service,Number Of Messages, Message Status, Message Reference, Invocation Mode,
Facility Number Type, Type of Number, Presentation and Screening,Mailbox,
Facility Number Type, Type of Number, Presentation and Screening, Controlling User Number,
Facility Number Type, Type of Number, Presentaation and Screening, Controlling User Provided Number
capicommand(mwi,xmit,deactivate, ...) where parameters are:
CAPI controller, MWI basic service, Invocation Mode,
Facility Number Type, Type of Number, Presentation and Screening,Mailbox,
Facility Number Type, Type of Number, Presentation and Screening, Controlling User Number
Example:
exten => _X.,n,capicommand(mwi,xmit,activate,1|1|1|0|0|2|1|0|0|42|1|0|0|41||||)
exten => _X.,n,capicommand(mwi,xmit,deactivate|1|1|2|1|0|0|41|1|0|0|41)
Please refer to COMMON-ISDN-API Version 2.0 Part III Supplementary Services for more details
on parameters.
+-------------------------------------------------------------------+
| Receive MWI messages (MWI Client) |
+-------------------------------------------------------------------+
Upon reception of MWI Activate messages from network chan_capi automatically
generates Asterisk MWI events for mailbox N@CAPI_Remote, where N is the
received as part of MWI Activate message Calling Party Number.
+-------------------------------------------------------------------+
| Notes |
+-------------------------------------------------------------------+
PBX often use one separate BRI trunk for transferring of MWI information (only MWI requests are transmitted
this trunk).
Certain PBX require up to 15 seconds until MWI information is processed.

View File

@ -58,7 +58,7 @@ The QSIG support includes:
its subchannels
- Simple Call Transfer
With capicommand(qsig_ct|src-id|dst-id), you can transfer an inbound call back to the qsig switch.
With capicommand(qsig_ct,src-id,dst-id), you can transfer an inbound call back to the qsig switch.
The B-channel of this call will be relased, so that the line is free for a next call.
Unfortunately, the call will be completely released by the switch if the target is busy.
If you need to know whether your target is busy, you can use the call transfer feature below.

View File

@ -41,6 +41,8 @@ faxdetect=off ;enable faxdetection and redirection to EXTEN 'fax' for incomin
;outgoing calls. (default='off', possible values: 'incoming','outgoing','both')
faxdetecttime=0 ;Only detect faxes during the first 'n' seconds of the call.
;(default '0' meaning for the whole duration of the call)
faxdestination=custom-fax,fax,1 ;Set custom context, exten and priority to jump to on faxdetect.
;Default is "<current-context>,fax,1".
accountcode= ;PBX accountcode to use in CDRs
;amaflags=default;AMA flags for CDR ('default', 'omit', 'billing', or 'documentation')
context=isdn-in ;context for incoming calls
@ -76,4 +78,23 @@ devices=2 ;number of concurrent calls (B-Channels) on this controller
;mohinterpret=default ;Asterisk 1.4: default music on hold class when placed on hold.
;qsig=1 ;enable use of Q.SIG extensions. ECMA Variant
;qsig_prnum=1234 ;enable inbound bridging - this should be an QSIG-network-wide unique number
;divaqsig=on ;enable Diva QSIG and protocol independent implementation
;mwifacptynrtype=0;type of MWI facility party number, 0 - unknown (default), 1 - public
;mwifacptynrton=0 ;MWI facility party number type of number and numbering plan identification
; (coding as for byte 0 of the calling party number).
; This byte is only valid if byte mwifacptynrtype contains the value 1
;mwifacptynrpres=0;MWI facility party number type presentation and screening indicator
; (coding as for byte 1 of the calling party number).
; This byte is only valid if byte mwifacptynrtype contains the value 1
;mwibasicservice=1;MWI basic Service, coded in accordance with ETS 300 196 [D.5]
;mwiinvocation=2 ;MWI invocation mode, 0 - deferred, 1 - immediate, 2 - combined,
; 65535 - suppres invocation code
;mwimailbox=12345 ;',' separated list of mailboxes for MWI in format:
; mailbox[:controlling user number[:controlling user provided number]][@context]
;hlimit=10 ;Do not use this controller for outgoing calls if less than 'hlimit' free channels is
;left on this controller.
;slimit=10 ;Try to use for outgoing calls other controller in group if less than 'slimit' free
;channels is left on this controller. Always try to 'fill up' the controller with
;smalest number in group. Create call if less than 'slimit' free channels left and
;no other controller with respect to free channel count was found in group.

File diff suppressed because it is too large Load Diff

View File

@ -49,11 +49,17 @@
#ifndef _PBX_CAPI_H
#define _PBX_CAPI_H
#ifdef DIVA_STREAMING
struct _diva_stream_scheduling_entry;
#endif
struct _pbx_capi_conference_bridge;
#define CAPI_MAX_CONTROLLERS 64
#define CAPI_MAX_B3_BLOCKS 7
/* was : 130 bytes Alaw = 16.25 ms audio not suitable for VoIP */
/* now : 160 bytes Alaw = 20 ms audio */
/* now : 640 bytes slinear 16000Hz = 20 ms audio */
/* you can tune this to your need. higher value == more latency */
#define CAPI_MAX_B3_BLOCK_SIZE 160
@ -66,17 +72,25 @@
#define CAPI_MAX_FACILITYDATAARRAY_SIZE 300
#define COMMANDSEPARATOR "|,"
#ifdef CC_AST_HAS_FORMAT_T
typedef format_t cc_format_t;
#else
typedef int cc_format_t;
#endif
/* some helper functions */
static inline void write_capi_word(void *m, unsigned short val)
{
((unsigned char *)m)[0] = val & 0xff;
((unsigned char *)m)[1] = (val >> 8) & 0xff;
}
static inline unsigned short read_capi_word(void *m)
static inline unsigned short read_capi_word(const void *m)
{
unsigned short val;
val = ((unsigned char *)m)[0] | (((unsigned char *)m)[1] << 8);
val = ((const unsigned char *)m)[0] | (((const unsigned char *)m)[1] << 8);
return (val);
}
static inline void write_capi_dword(void *m, unsigned int val)
@ -86,12 +100,12 @@ static inline void write_capi_dword(void *m, unsigned int val)
((unsigned char *)m)[2] = (val >> 16) & 0xff;
((unsigned char *)m)[3] = (val >> 24) & 0xff;
}
static inline unsigned int read_capi_dword(void *m)
static inline unsigned int read_capi_dword(const void *m)
{
unsigned int val;
val = ((unsigned char *)m)[0] | (((unsigned char *)m)[1] << 8) |
(((unsigned char *)m)[2] << 16) | (((unsigned char *)m)[3] << 24);
val = ((const unsigned char *)m)[0] | (((const unsigned char *)m)[1] << 8) |
(((const unsigned char *)m)[2] << 16) | (((const unsigned char *)m)[3] << 24);
return (val);
}
@ -223,6 +237,16 @@ typedef struct fax3proto3 B3_PROTO_FAXG3;
#define EC_ECHOCANCEL_PATH_IP 2 /* Activate EC for IP */
#define EC_ECHOCANCEL_PATH_BITS (EC_ECHOCANCEL_PATH_IFC | EC_ECHOCANCEL_PATH_IP)
/*
Control EC on transit connectionss
*/
#define EC_ECHOCANCEL_TRANSIT_OFF 0 /* EC deactivated on transit connection, default */
#define EC_ECHOCANCEL_TRANSIT_A 1 /* EC activated on side A of transsit connection */
#define EC_ECHOCANCEL_TRANSIT_B 2 /* EC activated on side B of transsit connection */
#define EC_ECHOCANCEL_TRANSIT_AB (EC_ECHOCANCEL_TRANSIT_A | EC_ECHOCANCEL_TRANSIT_B)
#define EC_ECHOCANCEL_TRANSIT_BITS (EC_ECHOCANCEL_TRANSIT_A | EC_ECHOCANCEL_TRANSIT_B)
#define CC_HOLDTYPE_LOCAL 0
#define CC_HOLDTYPE_HOLD 1
#define CC_HOLDTYPE_NOTIFY 2
@ -289,6 +313,9 @@ struct cc_capi_gains {
#define CAPI_ISDN_STATE_PBX_DONT 0x40000000
#define CAPI_ISDN_STATE_PBX 0x80000000
#define CAPI_ISDN_STATE2_PROCEEDING 0x00000001
#define CAPI_ISDN_STATE2_PROCEEDING_PENDING 0x00000002
#define CAPI_CHANNELTYPE_B 0
#define CAPI_CHANNELTYPE_D 1
#define CAPI_CHANNELTYPE_NULL 2
@ -377,6 +404,7 @@ struct capi_pvt {
/* the state of the line */
unsigned int isdnstate;
unsigned int isdnstate2;
int cause;
/* which b-protocol is active */
@ -455,6 +483,10 @@ struct capi_pvt {
unsigned int FaxState;
/* Window for fax detection */
unsigned int faxdetecttime;
/* custom fax context,exten,prio */
char faxcontext[AST_MAX_EXTENSION+1];
char faxexten[AST_MAX_EXTENSION+1];
int faxpriority;
/* handle for CCBS/CCNR callback */
unsigned int ccbsnrhandle;
@ -474,6 +506,7 @@ struct capi_pvt {
float txmin;
unsigned short divaAudioFlags;
unsigned short divaDataStubAudioFlags;
unsigned short divaDigitalRxGain;
float divaDigitalRxGainDB;
unsigned short divaDigitalTxGain;
@ -513,17 +546,14 @@ struct capi_pvt {
#else
struct ast_rtp *rtp;
#endif
#ifdef CC_AST_HAS_FORMAT_T
format_t capability;
#else
int capability;
#endif
cc_format_t capability;
int rtpcodec;
int codec;
unsigned int timestamp;
/* Q.SIG features */
int qsigfeat;
int divaqsig;
struct cc_qsig_data qsig_data;
/* Resource PLCI data */
@ -533,7 +563,14 @@ struct capi_pvt {
struct capi_pvt *line_plci;
/* Resource PLCI data data if line */
struct capi_pvt *data_plci;
#ifdef DIVA_STREAMING
struct _diva_stream_scheduling_entry* diva_stream_entry;
#endif
/* Connection between two conference rooms. NULL PLCI */
int virtualBridgePeer;
struct capi_pvt *bridgePeer;
/*! Next channel in list */
struct capi_pvt *next;
};
@ -580,9 +617,14 @@ struct cc_capi_conf {
int bridge;
int amaflags;
int qsigfeat;
int divaqsig;
struct cc_capi_qsig_conf qsigconf;
unsigned int faxsetting;
unsigned int faxdetecttime;
/* custom fax context,exten,prio */
char faxcontext[AST_MAX_EXTENSION+1];
char faxexten[AST_MAX_EXTENSION+1];
int faxpriority;
ast_group_t callgroup;
ast_group_t pickupgroup;
ast_group_t group;
@ -600,8 +642,38 @@ struct cc_capi_conf {
char mohinterpret[MAX_MUSICCLASS];
#endif
int echocancelpath;
int econtransitconn;
int mwifacptynrtype;
int mwifacptynrton;
int mwifacptynrpres;
int mwibasicservice;
int mwiinvocation;
char* mwimailbox;
int hlimit;
int slimit;
};
struct cc_capi_controller;
struct _cc_capi_mwi_mailbox;
typedef struct _cc_capi_mwi_mailbox {
AST_LIST_ENTRY(_cc_capi_mwi_mailbox) link;
const struct cc_capi_controller *controller;
unsigned short basicService;
unsigned short invocationMode;
unsigned char *mailboxNumber;
char *mailboxContext;
unsigned char *controllingUserNumber;
unsigned char *controllingUserProvidedNumber;
#if defined(CC_AST_HAS_EVENT_MWI)
struct ast_event_sub* mwiSubscribtion;
#else
void* mwiSubscribtion;
#endif
} cc_capi_mwi_mailbox_t;
struct cc_capi_controller {
/* which controller is this? */
int controller;
@ -611,6 +683,13 @@ struct cc_capi_controller {
int nbchannels;
/* free bchans */
int nfreebchannels;
/* Controller considered BUSY amount if free channels below
of this level */
int nfreebchannelsHardThr;
/* If amount of free channels is below this level then
try to allocate call on other controler in group
where this level is not reached or difference is less */
int nfreebchannelsSoftThr;
/* features: */
int broadband;
int dtmf;
@ -634,21 +713,18 @@ struct cc_capi_controller {
int divaExtendedFeaturesAvailable;
int ecPath;
int ecOnTransit;
int fax_t30_extended;
#ifdef DIVA_STREAMING
int divaStreaming;
#endif
AST_LIST_HEAD_NOLOCK(, _cc_capi_mwi_mailbox) mwiSubscribtions;
#ifdef DIVA_STATUS
int interfaceState;
int hwState;
#endif
};
/* ETSI 300 102-1 information element identifiers */
#define CAPI_ETSI_IE_CAUSE 0x08
#define CAPI_ETSI_IE_PROGRESS_INDICATOR 0x1e
#define CAPI_ETSI_IE_CALLED_PARTY_NUMBER 0x70
#define CAPI_ETSI_IE_FACILITY 0x1c
/* ETIS 300 102-1 message types */
#define CAPI_ETSI_ALERTING 0x01
#define CAPI_ETSI_SETUP_ACKKNOWLEDGE 0x0d
#define CAPI_ETSI_DISCONNECT 0x45
/* ETSI 300 102-1 Numbering Plans */
#define CAPI_ETSI_NPLAN_SUBSCRIBER 0x40
#define CAPI_ETSI_NPLAN_NATIONAL 0x20
@ -701,7 +777,7 @@ extern void cc_start_b3(struct capi_pvt *i);
extern unsigned char capi_tcap_is_digital(unsigned short tcap);
extern void capi_queue_cause_control(struct capi_pvt *i, int control);
extern void capidev_handle_connection_conf(struct capi_pvt **i, unsigned int PLCI,
unsigned short wInfo, unsigned short wMsgNum);
unsigned short wInfo, unsigned short wMsgNum, struct ast_channel** interface_owner);
extern void capi_wait_for_answered(struct capi_pvt *i);
extern int capi_wait_for_b3_up(struct capi_pvt *i);
extern void capi_activehangup(struct capi_pvt *i, int state);
@ -712,6 +788,51 @@ extern char chatinfo_usage[];
typedef int (*pbx_capi_command_proc_t)(struct ast_channel *, char *);
pbx_capi_command_proc_t pbx_capi_lockup_command_by_name(const char* name);
/*!
* \brief returns list of supported by this controller RTP codecs
*/
cc_format_t pbx_capi_get_controller_codecs(int controller);
_cstruct diva_get_b1_conf(struct capi_pvt *i);
/*!
\brief &capi_controllers[controller]
*/
const struct cc_capi_controller *pbx_capi_get_controller(int controller);
/*!
\brief capi_num_controllers
*/
int pbx_capi_get_num_controllers(void);
/*!
\brief tdesc
*/
const char* pbx_capi_get_module_description(void);
/*!
\brief cc_mutex_lock(&iflock)
*/
void pbx_capi_lock_interfaces(void);
/*!
\brief cc_mutex_unlock(&iflock)
*/
void pbx_capi_unlock_interfaces(void);
/*!
\brief Exec cappicommand using CLI
*/
int pbx_capi_cli_exec_capicommand(struct ast_channel *chan, const char *data);
/*!
\brief EC control
*/
void capi_echo_canceller(struct capi_pvt *i, int function);
#ifdef DIVA_STREAMING
struct _diva_streaming_vector;
void capidev_handle_data_b3_indication_vector (struct capi_pvt *i,
struct _diva_streaming_vector* vind,
int vind_nr);
/*!
* \brief Return true if Diva streaming supported by CAPI controller
*/
int pbx_capi_streaming_supported (struct capi_pvt *i);
#endif
/* DIVA specific MANUFACTURER definitions */
#define _DI_MANU_ID 0x44444944
@ -719,5 +840,16 @@ pbx_capi_command_proc_t pbx_capi_lockup_command_by_name(const char* name);
#define _DI_DSP_CTRL 0x0003
#define _DI_OPTIONS_REQUEST 0x0009
#if (!defined(CC_AST_HAS_VERSION_1_4) && !defined(CC_AST_HAS_VERSION_1_6) && !defined(CC_AST_HAS_VERSION_1_8))
#define ast_malloc(__x__) malloc((__x__))
#define ast_free(__x__) free((__x__))
#define ast_strdup(__x__) strdup((__x__))
#define ast_channel_trylock(__x__) ast_mutex_trylock(&(__x__)->lock)
#define ast_channel_unlock(__x__) ast_mutex_unlock(&(__x__)->lock)
#define ast_devstate_prov_add(__a__,__b__) (-1)
#define ast_devstate_prov_del(__x__) do{}while(0)
#endif
#endif

441
chan_capi_ami.c Normal file
View File

@ -0,0 +1,441 @@
/*
*
Copyright (c) Dialogic (R) 2009 - 2010
*
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters.
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
* Based on apps/app_meetme.c
*
*/
#include <stdio.h>
#include "chan_capi_platform.h"
#include "chan_capi20.h"
#include "chan_capi.h"
#include "chan_capi_qsig.h"
#include "chan_capi_utils.h"
#include "chan_capi_chat.h"
#include "chan_capi_management_common.h"
#include "asterisk/manager.h"
#ifdef CC_AST_HAS_VERSION_1_6
#define CC_AMI_ACTION_NAME_CHATLIST "CapichatList"
#define CC_AMI_ACTION_NAME_CHATMUTE "CapichatMute"
#define CC_AMI_ACTION_NAME_CHATUNMUTE "CapichatUnmute"
#define CC_AMI_ACTION_NAME_CHATREMOVE "CapichatRemove"
#define CC_AMI_ACTION_NAME_CAPICOMMAND "CapiCommand"
/*
LOCALS
*/
static int pbx_capi_ami_capichat_list(struct mansession *s, const struct message *m);
static int pbx_capi_ami_capichat_mute(struct mansession *s, const struct message *m);
static int pbx_capi_ami_capichat_unmute(struct mansession *s, const struct message *m);
static int pbx_capi_ami_capichat_remove(struct mansession *s, const struct message *m);
static int pbx_capi_ami_capichat_control(struct mansession *s, const struct message *m, int chatMute);
static int pbx_capi_ami_capicommand(struct mansession *s, const struct message *m);
static int capiChatListRegistered;
static int capiChatMuteRegistered;
static int capiChatUnmuteRegistered;
static int capiChatRemoveRegistered;
static int capiCommandRegistered;
static char mandescr_capichatlist[] =
"Description: Lists all users in a particular CapiChat conference.\n"
"CapichatList will follow as separate events, followed by a final event called\n"
"CapichatListComplete.\n"
"Variables:\n"
" *ActionId: <id>\n"
" *Conference: <confname>\n";
static char mandescr_capichatmute[] =
"Description: Mutes user in a particular CapiChat conference.\n"
"Variables:\n"
" *ActionId: <id>\n"
" *Conference: <confname>\n"
" *Member: <membername>\n"
" *Path: <Rx or Tx>\n";
static char mandescr_capichatunmute[] =
"Description: Unmutes user in a particular CapiChat conference.\n"
"Variables:\n"
" *ActionId: <id>\n"
" *Conference: <confname>\n"
" *Member: <membername>\n"
" *Path: <Rx or Tx>\n";
static char mandescr_capichatremove[] =
"Description: Removes user in a particular CapiChat conference.\n"
"Variables:\n"
" *ActionId: <id>\n"
" *Conference: <confname>\n"
" *Member: <membername>\n";
static char mandescr_capicommand[] =
"Description: Exec capicommand.\n"
"Variables:\n"
" *ActionId: <id>\n"
" *Channel: <channame>\n"
" *Capicommand: <capicommand>\n";
void pbx_capi_ami_register(void)
{
capiChatListRegistered = ast_manager_register2(CC_AMI_ACTION_NAME_CHATLIST,
EVENT_FLAG_REPORTING,
pbx_capi_ami_capichat_list,
"List participants in a conference",
mandescr_capichatlist) == 0;
capiChatMuteRegistered = ast_manager_register2(CC_AMI_ACTION_NAME_CHATMUTE,
EVENT_FLAG_CALL,
pbx_capi_ami_capichat_mute,
"Mute a conference user",
mandescr_capichatmute) == 0;
capiChatUnmuteRegistered = ast_manager_register2(CC_AMI_ACTION_NAME_CHATUNMUTE,
EVENT_FLAG_CALL,
pbx_capi_ami_capichat_unmute,
"Unmute a conference user",
mandescr_capichatunmute) == 0;
capiChatRemoveRegistered = ast_manager_register2(CC_AMI_ACTION_NAME_CHATREMOVE,
EVENT_FLAG_CALL,
pbx_capi_ami_capichat_remove,
"Remove a conference user",
mandescr_capichatremove) == 0;
capiCommandRegistered = ast_manager_register2(CC_AMI_ACTION_NAME_CAPICOMMAND,
EVENT_FLAG_CALL,
pbx_capi_ami_capicommand,
"Exec capicommand",
mandescr_capicommand) == 0;
}
void pbx_capi_ami_unregister(void)
{
if (capiChatListRegistered != 0)
ast_manager_unregister(CC_AMI_ACTION_NAME_CHATLIST);
if (capiChatMuteRegistered != 0)
ast_manager_unregister(CC_AMI_ACTION_NAME_CHATMUTE);
if (capiChatUnmuteRegistered != 0)
ast_manager_unregister(CC_AMI_ACTION_NAME_CHATUNMUTE);
if (capiChatRemoveRegistered != 0)
ast_manager_unregister(CC_AMI_ACTION_NAME_CHATREMOVE);
if (capiCommandRegistered != 0)
ast_manager_unregister(CC_AMI_ACTION_NAME_CAPICOMMAND);
}
static int pbx_capi_ami_capichat_list(struct mansession *s, const struct message *m) {
const char *actionid = astman_get_header(m, "ActionID");
const char *conference = astman_get_header(m, "Conference");
char idText[80] = "";
int total = 0;
const struct capichat_s *capiChatRoom;
if (!ast_strlen_zero(actionid))
snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
if (pbx_capi_chat_get_room_c(NULL) == NULL) {
astman_send_error(s, m, "No active conferences.");
return 0;
}
astman_send_listack(s, m, CC_AMI_ACTION_NAME_CHATLIST" user list will follow", "start");
/* Find the right conference */
pbx_capi_lock_chat_rooms();
for (capiChatRoom = pbx_capi_chat_get_room_c(NULL), total = 0;
capiChatRoom != NULL;
capiChatRoom = pbx_capi_chat_get_room_c(capiChatRoom)) {
const char* roomName = pbx_capi_chat_get_room_name(capiChatRoom);
/* If we ask for one particular, and this isn't it, skip it */
if (!ast_strlen_zero(conference) && strcmp(roomName, conference))
continue;
{
unsigned int roomNumber = pbx_capi_chat_get_room_number(capiChatRoom);
struct ast_channel *c = pbx_capi_chat_get_room_channel(capiChatRoom);
const struct capi_pvt* i = pbx_capi_chat_get_room_interface_c(capiChatRoom);
int isMemberOperator = pbx_capi_chat_is_member_operator(capiChatRoom);
int isCapiChatRoomMuted = pbx_capi_chat_is_room_muted(capiChatRoom);
int isCapiChatMemberMuted = pbx_capi_chat_is_member_muted(capiChatRoom);
int isCapiChatMemberListener = pbx_capi_chat_is_member_listener(capiChatRoom);
int isCapiChatMostRecentMember = pbx_capi_chat_is_most_recent_user(capiChatRoom);
const char* mutedVisualName = "No";
char* cidVisual;
char* callerNameVisual;
if ((c == NULL) || (i == NULL))
continue;
cidVisual = ast_strdup(pbx_capi_get_cid (c, "<unknown>"));
callerNameVisual = ast_strdup(pbx_capi_get_callername (c, "<no name>"));
if (isCapiChatMemberListener || isCapiChatRoomMuted || isCapiChatMemberMuted) {
if (isMemberOperator) {
if (isCapiChatMemberMuted)
mutedVisualName = "By self";
} else if (isCapiChatMemberListener || isCapiChatRoomMuted) {
mutedVisualName = "By admin";
} else {
mutedVisualName = "By self";
}
}
total++;
astman_append(s,
"Event: "CC_AMI_ACTION_NAME_CHATLIST"\r\n"
"%s"
"Conference: %s/%u\r\n"
"UserNumber: %d\r\n"
"CallerIDNum: %s\r\n"
"CallerIDName: %s\r\n"
"Channel: %s\r\n"
"Admin: %s\r\n"
"Role: %s\r\n"
"MarkedUser: %s\r\n"
"Muted: %s\r\n"
"Talking: %s\r\n"
"Domain: %s\r\n"
"DTMF: %s\r\n"
"EchoCancel: %s\r\n"
"NoiseSupp: %s\r\n"
"RxAGC: %s\r\n"
"TxAGC: %s\r\n"
"RxGain: %.1f%s\r\n"
"TxGain: %.1f%s\r\n"
"\r\n",
idText,
roomName,
roomNumber,
total,
(cidVisual != 0) ? cidVisual : "?",
(callerNameVisual != 0) ? callerNameVisual : "?",
c->name,
(isMemberOperator != 0) ? "Yes" : "No",
(isCapiChatMemberListener != 0) ? "Listen only" : "Talk and listen" /* "Talk only" */,
(isCapiChatMostRecentMember != 0) ? "Yes" : "No",
mutedVisualName,
/* "Yes" "No" */ "Not monitored",
(i->channeltype == CAPI_CHANNELTYPE_B) ? "TDM" : "IP",
(i->isdnstate & CAPI_ISDN_STATE_DTMF) ? "Y" : "N",
(i->isdnstate & CAPI_ISDN_STATE_EC) ? "Y" : "N",
(i->divaAudioFlags & 0x0080) ? "Y" : "N", /* Noise supression */
(i->divaAudioFlags & 0x0008) ? "Y" : "N", /* Rx AGC */
(i->divaAudioFlags & 0x0004) ? "Y" : "N", /* Tx AGC */
i->divaDigitalRxGainDB, "dB",
i->divaDigitalTxGainDB, "dB");
ast_free (cidVisual);
ast_free (callerNameVisual);
}
}
pbx_capi_unlock_chat_rooms();
/* Send final confirmation */
astman_append(s,
"Event: "CC_AMI_ACTION_NAME_CHATLIST"Complete\r\n"
"EventList: Complete\r\n"
"ListItems: %d\r\n"
"%s"
"\r\n", total, idText);
return 0;
}
static int pbx_capi_ami_capichat_mute(struct mansession *s, const struct message *m)
{
return pbx_capi_ami_capichat_control(s, m, 1);
}
static int pbx_capi_ami_capichat_unmute(struct mansession *s, const struct message *m)
{
return pbx_capi_ami_capichat_control(s, m, 0);
}
static int pbx_capi_ami_capichat_control(struct mansession *s, const struct message *m, int chatMute)
{
const char *roomName = astman_get_header(m, "Conference");
const char *userName = astman_get_header(m, "Member");
const char *voicePath = astman_get_header(m, "Path");
const char* capiCommand;
int ret;
if (ast_strlen_zero(roomName)) {
astman_send_error(s, m, "Capi Chat conference not specified");
return 0;
}
if (ast_strlen_zero(userName)) {
char* param = ast_strdupa((chatMute != 0) ? "yes" : "no");
int ret = pbx_capi_chat_mute(NULL, param);
if (ret == 0) {
astman_send_ack(s, m, (chatMute != 0) ? "Conference muted" : "Conference unmuted");
} else {
astman_send_error(s, m, "Failed to change mode of Capi Chat conference");
}
return 0;
}
if ((voicePath != NULL) && (strcmp(voicePath, "Rx") == 0)) {
capiCommand = (chatMute != 0) ? "rxdgain,-128" : "rxdgain,0";
} else {
capiCommand = (chatMute != 0) ? "txdgain,-128" : "txdgain,0";
}
ret = pbx_capi_management_capicommand(userName, capiCommand);
switch (ret) {
case 0:
astman_send_ack(s, m, (chatMute != 0) ? "User muted" : "User unmuted");
break;
case -4:
astman_send_error(s, m, "User not found");
break;
default:
astman_send_error(s, m, "Command error");
break;
}
return 0;
}
static int pbx_capi_ami_capichat_remove(struct mansession *s, const struct message *m)
{
const char *roomName = astman_get_header(m, "Conference");
const char *userName = astman_get_header(m, "Member");
int ret;
if (ast_strlen_zero(roomName)) {
astman_send_error(s, m, "Capi Chat conference not specified");
return 0;
}
if (ast_strlen_zero(userName)) {
astman_send_error(s, m, "Capi Chat member not specified");
return 0;
}
ret = pbx_capi_chat_remove_user (roomName, userName);
if (ret == 0) {
astman_send_ack(s, m, "Member removed");
} else {
astman_send_error(s, m, "Member not found");
}
return 0;
}
static int pbx_capi_ami_capicommand(struct mansession *s, const struct message *m)
{
const char *requiredChannelName = astman_get_header(m, "Channel");
const char *chancapiCommand = astman_get_header(m, "Command");
int ret = pbx_capi_management_capicommand(requiredChannelName, chancapiCommand);
switch (ret) {
case 0:
astman_send_ack(s, m, "OK");
break;
case -2:
astman_send_error(s, m, "Channel name not specified");
break;
case -3:
astman_send_error(s, m, "Capi command name not specified");
break;
case -4:
astman_send_error(s, m, "Channel not found");
break;
case -1:
default:
astman_send_error(s, m, "Command error");
break;
}
return 0;
}
#else
void pbx_capi_ami_register(void)
{
}
void pbx_capi_ami_unregister(void)
{
}
#endif
void pbx_capi_chat_join_event(struct ast_channel* c, const struct capichat_s * room)
{
#ifdef CC_AST_HAS_VERSION_1_8
ast_manager_event(c,
#else
manager_event(
#endif
EVENT_FLAG_CALL, "CapichatJoin",
"Channel: %s\r\n"
"Uniqueid: %s\r\n"
"Conference: %s\r\n"
"Conferencenum: %u\r\n"
"CallerIDnum: %s\r\n"
"CallerIDname: %s\r\n",
c->name, c->uniqueid,
pbx_capi_chat_get_room_name(room),
pbx_capi_chat_get_room_number(room),
pbx_capi_get_cid (c, "<unknown>"),
pbx_capi_get_callername (c, "<no name>"));
}
void pbx_capi_chat_leave_event(struct ast_channel* c,
const struct capichat_s *room,
long duration)
{
#ifdef CC_AST_HAS_VERSION_1_8
ast_manager_event(c,
#else
manager_event(
#endif
EVENT_FLAG_CALL, "CapichatLeave",
"Channel: %s\r\n"
"Uniqueid: %s\r\n"
"Conference: %s\r\n"
"Conferencenum: %u\r\n"
"CallerIDNum: %s\r\n"
"CallerIDName: %s\r\n"
"Duration: %ld\r\n",
c->name, c->uniqueid,
pbx_capi_chat_get_room_name(room),
pbx_capi_chat_get_room_number(room),
pbx_capi_get_cid (c, "<unknown>"),
pbx_capi_get_callername (c, "<no name>"),
duration);
}
void pbx_capi_chat_conference_end_event(const char* roomName)
{
manager_event(EVENT_FLAG_CALL, "CapichatEnd", "Conference: %s\r\n", roomName);
}

40
chan_capi_ami.h Normal file
View File

@ -0,0 +1,40 @@
/*
*
Copyright (c) Dialogic (R) 2009 - 2010
*
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters.
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
* Based on apps/app_meetme.c
*
*/
#ifndef __CC_AMI_INTERFACE_H__
#define __CC_AMI_INTERFACE_H__
void pbx_capi_ami_register(void);
void pbx_capi_ami_unregister(void);
struct capichat_s;
void pbx_capi_chat_join_event(struct ast_channel* c, const struct capichat_s * room);
void pbx_capi_chat_leave_event(struct ast_channel* c,
const struct capichat_s *room,
long duration);
void pbx_capi_chat_conference_end_event(const char* roomName);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -15,6 +15,7 @@
/*
* prototypes
*/
extern void pbx_capi_chat_init_module(void);
extern int pbx_capi_chat(struct ast_channel *c, char *param);
extern int pbx_capi_chat_associate_resource_plci(struct ast_channel *c, char *param);
extern struct capi_pvt* pbx_check_resource_plci(struct ast_channel *c);
@ -26,5 +27,25 @@ extern int pbxcli_capi_chatinfo(int fd, int argc, char *argv[]);
extern int pbx_capi_chat_command (struct ast_channel *c, char *param);
extern int pbx_capi_chat_mute(struct ast_channel *c, char *param);
extern int pbx_capi_chat_play(struct ast_channel *c, char *param);
extern int pbx_capi_chat_connect(struct ast_channel *c, char *param);
int pbx_capi_chat_remove_user(const char* room, const char* name);
struct capichat_s;
const struct capichat_s *pbx_capi_chat_get_room_c(const struct capichat_s * room);
const char* pbx_capi_chat_get_room_name(const struct capichat_s * room);
unsigned int pbx_capi_chat_get_room_number(const struct capichat_s * room);
unsigned int pbx_capi_chat_get_room_members(const struct capichat_s * room);
struct ast_channel *pbx_capi_chat_get_room_channel(const struct capichat_s * room);
const struct capi_pvt* pbx_capi_chat_get_room_interface_c(const struct capichat_s * room);
int pbx_capi_chat_is_member_operator(const struct capichat_s * room);
int pbx_capi_chat_is_room_muted(const struct capichat_s * room);
int pbx_capi_chat_is_member_muted(const struct capichat_s * room);
int pbx_capi_chat_is_member_listener(const struct capichat_s * room);
int pbx_capi_chat_is_most_recent_user(const struct capichat_s * room);
unsigned int pbx_capi_chat_get_room_group (const struct capichat_s * room);
unsigned int pbx_capi_chat_get_room_group_members (const struct capichat_s * room);
void pbx_capi_lock_chat_rooms(void);
void pbx_capi_unlock_chat_rooms(void);
#endif

842
chan_capi_cli.c Normal file
View File

@ -0,0 +1,842 @@
/*
* An implementation of Common ISDN API 2.0 for Asterisk
*
* Copyright (C) 2005-2010 Cytronics & Melware
*
* Armin Schindler <armin@melware.de>
*
* Reworked, but based on the work of
* Copyright (C) 2002-2005 Junghanns.NET GmbH
*
* Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
*
* This program is free software and may be modified and
* distributed under the terms of the GNU Public License.
*/
#include <stdio.h>
#include "chan_capi_platform.h"
#include "chan_capi20.h"
#include "chan_capi.h"
#include "chan_capi_qsig.h"
#include "chan_capi_utils.h"
#include "chan_capi_chat.h"
#include "chan_capi_cli.h"
#include "chan_capi_management_common.h"
#ifdef DIVA_STREAMING
#include "platform.h"
#include "chan_capi_divastreaming_utils.h"
#endif
#ifdef DIVA_STATUS
#include "divastatus_ifc.h"
#endif
#ifdef DIVA_VERBOSE
#include "divaverbose.h"
#endif
/*
* usages
*/
static char info_usage[] =
"Usage: " CC_MESSAGE_NAME " info\n"
" Show info about B channels on controllers.\n";
static char show_channels_usage[] =
"Usage: " CC_MESSAGE_NAME " show channels\n"
" Show info about B channels.\n";
static char show_resources_usage[] =
"Usage: " CC_MESSAGE_NAME " show ressources\n"
" Show info about used by channels resources.\n";
static char show_bridges_usage[] =
"Usage: " CC_MESSAGE_NAME " show bridges\n"
" Show info about used conference bridges.\n";
static char debug_usage[] =
"Usage: " CC_MESSAGE_NAME " debug\n"
" Enables dumping of " CC_MESSAGE_BIGNAME " packets for debugging purposes\n";
static char no_debug_usage[] =
"Usage: " CC_MESSAGE_NAME " no debug\n"
" Disables dumping of " CC_MESSAGE_BIGNAME " packets for debugging purposes\n";
static char qsig_debug_usage[] =
"Usage: " CC_MESSAGE_NAME " qsig debug\n"
" Enables dumping of QSIG facilities for debugging purposes\n";
static char qsig_no_debug_usage[] =
"Usage: " CC_MESSAGE_NAME " qsig no debug\n"
" Disables dumping of QSIG facilities for debugging purposes\n";
static char show_exec_usage[] =
"Usage: " CC_MESSAGE_NAME " info\n"
" Exec chancapi command on selected interface (exec interface command parameters).\n";
static char show_chat_manage_usage[] =
"Usage: " CC_MESSAGE_NAME " chat manage\n"
" Manage chat conference (chat manage room member command parameters).\n";
#ifndef CC_AST_HAS_VERSION_1_6
static
#endif
char chatinfo_usage[] =
"Usage: " CC_MESSAGE_NAME " chatinfo\n"
" Show info about chat status.\n";
#define CC_CLI_TEXT_INFO "Show " CC_MESSAGE_BIGNAME " info"
#define CC_CLI_TEXT_SHOW_CHANNELS "Show B-channel info"
#define CC_CLI_TEXT_DEBUG "Enable " CC_MESSAGE_BIGNAME " debugging"
#define CC_CLI_TEXT_NO_DEBUG "Disable " CC_MESSAGE_BIGNAME " debugging"
#define CC_CLI_TEXT_QSIG_DEBUG "Enable QSIG debugging"
#define CC_CLI_TEXT_QSIG_NO_DEBUG "Disable QSIG debugging"
#define CC_CLI_TEXT_CHATINFO "Show " CC_MESSAGE_BIGNAME " chat info"
#define CC_CLI_TEXT_SHOW_RESOURCES "Show used resources"
#define CC_CLI_TEXT_SHOW_BRIDGES "Show used conference bridges"
#define CC_CLI_TEXT_EXEC_CAPICOMMAND "Exec command"
#define CC_CLI_TEXT_CHAT_MANAGE "Manager chat conference"
/*
* helper functions to convert conf value to string
*/
static char *show_bproto(int bproto)
{
switch(bproto) {
case CC_BPROTO_TRANSPARENT:
return "trans";
case CC_BPROTO_FAXG3:
case CC_BPROTO_FAX3_BASIC:
return " fax ";
case CC_BPROTO_RTP:
return " rtp ";
case CC_BPROTO_VOCODER:
return " vocoder ";
}
return " ??? ";
}
static char *show_state(int state)
{
switch(state) {
case CAPI_STATE_ALERTING:
return "Ring ";
case CAPI_STATE_CONNECTED:
return "Conn ";
case CAPI_STATE_DISCONNECTING:
return "discP";
case CAPI_STATE_DISCONNECTED:
return "Disc ";
case CAPI_STATE_CONNECTPENDING:
return "Dial ";
case CAPI_STATE_ANSWERING:
return "Answ ";
case CAPI_STATE_DID:
return "DIDin";
case CAPI_STATE_INCALL:
return "icall";
case CAPI_STATE_ONHOLD:
return "Hold ";
}
return "-----";
}
static char *show_isdnstate(unsigned int isdnstate, char *str)
{
str[0] = '\0';
if (isdnstate & CAPI_ISDN_STATE_PBX)
strcat(str, "*");
if (isdnstate & CAPI_ISDN_STATE_LI)
strcat(str, "G");
if (isdnstate & CAPI_ISDN_STATE_B3_UP)
strcat(str, "B");
if (isdnstate & CAPI_ISDN_STATE_B3_PEND)
strcat(str, "b");
if (isdnstate & CAPI_ISDN_STATE_PROGRESS)
strcat(str, "P");
if (isdnstate & CAPI_ISDN_STATE_HOLD)
strcat(str, "H");
if (isdnstate & CAPI_ISDN_STATE_ECT)
strcat(str, "T");
if (isdnstate & CAPI_ISDN_STATE_3PTY)
strcat(str, "3");
if (isdnstate & (CAPI_ISDN_STATE_SETUP | CAPI_ISDN_STATE_SETUP_ACK))
strcat(str, "S");
return str;
}
/*
* do command capi show channels
*/
#ifdef CC_AST_HAS_VERSION_1_6
static char *pbxcli_capi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#else
static int pbxcli_capi_show_channels(int fd, int argc, char *argv[])
#endif
{
struct capi_pvt *i;
char iochar;
char i_state[80];
char b3q[32];
int required_args;
int provided_args;
const char* required_channel_name = NULL;
#ifdef CC_AST_HAS_VERSION_1_6
int fd = a->fd;
if (cmd == CLI_INIT) {
e->command = CC_MESSAGE_NAME " show channels";
e->usage = show_channels_usage;
return NULL;
} else if (cmd == CLI_GENERATE)
return NULL;
required_args = e->args;
provided_args = a->argc;
if (required_args < provided_args) {
required_channel_name = a->argv[required_args];
}
#else
required_args = 3;
provided_args = argc;
if (required_args < provided_args) {
required_channel_name = argv[required_args];
}
#endif
ast_cli(fd, CC_MESSAGE_BIGNAME " B-channel information:\n");
ast_cli(fd, "Line-Name NTmode state i/o bproto isdnstate ton number\n");
ast_cli(fd, "----------------------------------------------------------------\n");
pbx_capi_lock_interfaces();
for (i = capi_iflist; i; i = i->next) {
if (i->channeltype != CAPI_CHANNELTYPE_B)
continue;
if ((required_channel_name != NULL) && (strcmp(required_channel_name, i->vname) != 0))
continue;
if ((i->state == 0) || (i->state == CAPI_STATE_DISCONNECTED))
iochar = '-';
else if (i->outgoing)
iochar = 'O';
else
iochar = 'I';
if (capidebug) {
snprintf(b3q, sizeof(b3q), " B3q=%d B3count=%d",
i->B3q, i->B3count);
} else {
b3q[0] = '\0';
}
ast_cli(fd,
"%-16s %s %s %c %s %-10s 0x%02x '%s'->'%s'%s\n",
i->vname,
i->ntmode ? "yes":"no ",
show_state(i->state),
iochar,
show_bproto(i->bproto),
show_isdnstate(i->isdnstate, i_state),
i->cid_ton,
i->cid,
i->dnid,
b3q
);
}
pbx_capi_unlock_interfaces();
#ifdef CC_AST_HAS_VERSION_1_6
return CLI_SUCCESS;
#else
return RESULT_SUCCESS;
#endif
}
/*
* do command capi show resources
*/
#ifdef CC_AST_HAS_VERSION_1_6
static char *pbxcli_capi_show_resources(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#else
static int pbxcli_capi_show_resources(int fd, int argc, char *argv[])
#endif
{
int ifc_type;
const struct capi_pvt *i;
int required_args;
int provided_args;
const char* required_channel_name = NULL;
struct {
const struct capi_pvt *head;
void (*lock_proc)(void);
void (*unlock_proc)(void);
} data[2];
data[0].head = capi_iflist;
data[0].lock_proc = pbx_capi_lock_interfaces;
data[0].unlock_proc = pbx_capi_unlock_interfaces;
data[1].head = pbx_capi_get_nulliflist();
data[1].lock_proc = pbx_capi_nulliflist_lock;
data[1].unlock_proc = pbx_capi_nulliflist_unlock;
#ifdef CC_AST_HAS_VERSION_1_6
int fd = a->fd;
if (cmd == CLI_INIT) {
e->command = CC_MESSAGE_NAME " show resources";
e->usage = show_resources_usage;
return NULL;
} else if (cmd == CLI_GENERATE)
return NULL;
required_args = e->args;
provided_args = a->argc;
if (required_args < provided_args) {
required_channel_name = a->argv[required_args];
}
#else
required_args = 3;
provided_args = argc;
if (required_args < provided_args) {
required_channel_name = argv[required_args];
}
#endif
ast_cli(fd, CC_MESSAGE_BIGNAME " resources in use:\n");
ast_cli(fd, "%-40s %-6s %-4s %-10s %-9s %-5s %-5s %-6s %-6s %-6s %-7s\n",
"Line-Name", "Domain", "DTMF", "EchoCancel", "NoiseSupp", "RxAGC", "TxAGC", "RxGain", "TxGain", "CAPI", "Queue");
ast_cli(fd, "-----------------------------------------------------------------------------------------------------------------\n");
for (ifc_type = 0; ifc_type < sizeof(data)/sizeof(data[0]); ifc_type++) {
data[ifc_type].lock_proc();
for (i = data[ifc_type].head; i; i = i->next) {
unsigned int queueDepth = 0;
char* name;
if (((i->used == 0) && (i->channeltype != CAPI_CHANNELTYPE_NULL)) || ((i->channeltype != CAPI_CHANNELTYPE_B) &&
(i->channeltype != CAPI_CHANNELTYPE_NULL)))
continue;
if (i->data_plci != 0)
continue;
name = ast_strdup(i->vname);
if ((i->channeltype == CAPI_CHANNELTYPE_NULL) && (name != NULL)) {
char* p = strstr(name, "-DATAPLCI");
if (p != NULL)
*p = 0;
}
if ((required_channel_name != NULL) &&
(strcmp(required_channel_name, (name == 0) ? i->vname : name) != 0)) {
ast_free(name);
continue;
}
#ifdef DIVA_STREAMING
queueDepth = capi_DivaStreamingGetStreamInUse(i->line_plci == NULL ? i : i->line_plci);
#endif
ast_cli(fd, "%-40s %-6s %-4s %-10s %-9s %-5s %-5s %-.1f%-3s %-.1f%-3s%5d %7u\n",
(name == 0) ? i->vname : name,
(i->channeltype == CAPI_CHANNELTYPE_B) ? "TDM" : "IP",
(i->isdnstate & CAPI_ISDN_STATE_DTMF) ? "Y" : "N",
(i->isdnstate & CAPI_ISDN_STATE_EC) ? "Y" : "N",
(i->divaAudioFlags & 0x0080) ? "Y" : "N", /* Noise supression */
(i->divaAudioFlags & 0x0008) ? "Y" : "N", /* Rx AGC */
(i->divaAudioFlags & 0x0004) ? "Y" : "N", /* Tx AGC */
i->divaDigitalRxGainDB, "dB",
i->divaDigitalTxGainDB, "dB",
i->controller,
queueDepth);
ast_free (name);
}
data[ifc_type].unlock_proc();
}
#ifdef CC_AST_HAS_VERSION_1_6
return CLI_SUCCESS;
#else
return RESULT_SUCCESS;
#endif
}
/*
* do command capi show bridges
*/
#ifdef CC_AST_HAS_VERSION_1_6
static char *pbxcli_capi_show_bridges(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#else
static int pbxcli_capi_show_bridges(int fd, int argc, char *argv[])
#endif
{
const struct capichat_s *capiChatRoom;
int required_args;
int provided_args;
#ifdef CC_AST_HAS_VERSION_1_6
int fd = a->fd;
if (cmd == CLI_INIT) {
e->command = CC_MESSAGE_NAME " show bridges";
e->usage = show_bridges_usage;
return NULL;
} else if (cmd == CLI_GENERATE)
return NULL;
required_args = e->args;
provided_args = a->argc;
#else
required_args = 3;
provided_args = argc;
#endif
ast_cli(fd, CC_MESSAGE_BIGNAME " conference bridges in use:\n");
ast_cli(fd, "%-17s %-5s %-7s %-4s %-11s\n",
"Bridge", "Group", "Members", "CAPI", "Queue depth");
ast_cli(fd, "----------------------------------------------------------------------------------------------------------\n");
pbx_capi_lock_chat_rooms();
for (capiChatRoom = pbx_capi_chat_get_room_c(NULL);
capiChatRoom != NULL;
capiChatRoom = pbx_capi_chat_get_room_c(capiChatRoom)) {
const struct capi_pvt* i = pbx_capi_chat_get_room_interface_c(capiChatRoom);
if ((i->virtualBridgePeer == 0) || (i->bridgePeer == 0)) {
continue;
}
{
unsigned int groupNumber = pbx_capi_chat_get_room_group (capiChatRoom);
if (groupNumber > 0) {
const char* roomName = pbx_capi_chat_get_room_name(capiChatRoom);
unsigned int groupNumber = pbx_capi_chat_get_room_group(capiChatRoom);
unsigned int groupUsers = pbx_capi_chat_get_room_group_members(capiChatRoom);
unsigned int queueDepth = 0;
#ifdef DIVA_STREAMING
queueDepth = capi_DivaStreamingGetStreamInUse(i);
#endif
ast_cli(fd, "%-17s %5u %7u %4d %11d\n",
roomName, groupNumber, groupUsers, i->controller, queueDepth);
}
}
}
pbx_capi_unlock_chat_rooms();
#ifdef CC_AST_HAS_VERSION_1_6
return CLI_SUCCESS;
#else
return RESULT_SUCCESS;
#endif
}
/*
* do command capi info
*/
#ifdef CC_AST_HAS_VERSION_1_6
static char *pbxcli_capi_info(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#else
static int pbxcli_capi_info(int fd, int argc, char *argv[])
#endif
{
int i = 0, capi_num_controllers = pbx_capi_get_num_controllers();
#ifdef CC_AST_HAS_VERSION_1_6
int fd = a->fd;
if (cmd == CLI_INIT) {
e->command = CC_MESSAGE_NAME " info";
e->usage = info_usage;
return NULL;
} else if (cmd == CLI_GENERATE)
return NULL;
if (a->argc != e->args)
return CLI_SHOWUSAGE;
#else
if (argc != 2)
return RESULT_SHOWUSAGE;
#endif
ast_cli(fd, "%s www.chan-capi.org\n", pbx_capi_get_module_description());
for (i = 1; i <= capi_num_controllers; i++) {
const struct cc_capi_controller *capiController = pbx_capi_get_controller(i);
if (capiController != NULL) {
ast_cli(fd, "Contr%d: %d B channels total, %d B channels free.%s\n",
i, capiController->nbchannels,
capiController->nfreebchannels,
(capiController->used) ? "":" (unused)");
}
}
#ifdef CC_AST_HAS_VERSION_1_6
return CLI_SUCCESS;
#else
return RESULT_SUCCESS;
#endif
}
/*
* enable debugging
*/
#ifdef CC_AST_HAS_VERSION_1_6
static char *pbxcli_capi_do_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#else
static int pbxcli_capi_do_debug(int fd, int argc, char *argv[])
#endif
{
#ifdef CC_AST_HAS_VERSION_1_6
int fd = a->fd;
if (cmd == CLI_INIT) {
e->command = CC_MESSAGE_NAME " debug";
e->usage = debug_usage;
return NULL;
} else if (cmd == CLI_GENERATE)
return NULL;
if (a->argc != e->args)
return CLI_SHOWUSAGE;
#else
if (argc != 2)
return RESULT_SHOWUSAGE;
#endif
capidebug = 1;
ast_cli(fd, CC_MESSAGE_BIGNAME " Message Debugging Enabled\n");
#ifdef CC_AST_HAS_VERSION_1_6
return CLI_SUCCESS;
#else
return RESULT_SUCCESS;
#endif
}
/*
* disable debugging
*/
#ifdef CC_AST_HAS_VERSION_1_6
static char *pbxcli_capi_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#else
static int pbxcli_capi_no_debug(int fd, int argc, char *argv[])
#endif
{
#ifdef CC_AST_HAS_VERSION_1_6
int fd = a->fd;
if (cmd == CLI_INIT) {
e->command = CC_MESSAGE_NAME " no debug";
e->usage = no_debug_usage;
return NULL;
} else if (cmd == CLI_GENERATE)
return NULL;
if (a->argc != e->args)
return CLI_SHOWUSAGE;
#else
if (argc != 3)
return RESULT_SHOWUSAGE;
#endif
capidebug = 0;
ast_cli(fd, CC_MESSAGE_BIGNAME " Message Debugging Disabled\n");
#ifdef CC_AST_HAS_VERSION_1_6
return CLI_SUCCESS;
#else
return RESULT_SUCCESS;
#endif
}
/*
* enable QSIG debugging
*/
#ifdef CC_AST_HAS_VERSION_1_6
static char *pbxcli_capi_qsig_do_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#else
static int pbxcli_capi_qsig_do_debug(int fd, int argc, char *argv[])
#endif
{
#ifdef CC_AST_HAS_VERSION_1_6
int fd = a->fd;
if (cmd == CLI_INIT) {
e->command = CC_MESSAGE_NAME " qsig debug";
e->usage = qsig_debug_usage;
return NULL;
} else if (cmd == CLI_GENERATE)
return NULL;
if (a->argc != e->args)
return CLI_SHOWUSAGE;
#else
if (argc != 3)
return RESULT_SHOWUSAGE;
#endif
capiqsigdebug = 1;
ast_cli(fd, "QSIG Debugging Enabled\n");
#ifdef CC_AST_HAS_VERSION_1_6
return CLI_SUCCESS;
#else
return RESULT_SUCCESS;
#endif
}
/*
* disable QSIG debugging
*/
#ifdef CC_AST_HAS_VERSION_1_6
static char *pbxcli_capi_qsig_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#else
static int pbxcli_capi_qsig_no_debug(int fd, int argc, char *argv[])
#endif
{
#ifdef CC_AST_HAS_VERSION_1_6
int fd = a->fd;
if (cmd == CLI_INIT) {
e->command = CC_MESSAGE_NAME " qsig no debug";
e->usage = qsig_no_debug_usage;
return NULL;
} else if (cmd == CLI_GENERATE)
return NULL;
if (a->argc != e->args)
return CLI_SHOWUSAGE;
#else
if (argc != 4)
return RESULT_SHOWUSAGE;
#endif
capiqsigdebug = 0;
ast_cli(fd, "QSIG Debugging Disabled\n");
#ifdef CC_AST_HAS_VERSION_1_6
return CLI_SUCCESS;
#else
return RESULT_SUCCESS;
#endif
}
/*
* exec capi command
*/
#ifdef CC_AST_HAS_VERSION_1_6
static char *pbxcli_capi_exec_capicommand(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#else
static int pbxcli_capi_exec_capicommand(int fd, int argc, char *argv[])
#endif
{
int required_args = 4;
int provided_args;
const char* requiredChannelName = NULL;
const char* chancapiCommand = NULL;
int ret;
#ifdef CC_AST_HAS_VERSION_1_6
if (cmd == CLI_INIT) {
e->command = CC_MESSAGE_NAME " exec";
e->usage = show_exec_usage;
return NULL;
} else if (cmd == CLI_GENERATE) {
return NULL;
}
provided_args = a->argc;
if (provided_args < required_args) {
return CLI_SHOWUSAGE;
}
requiredChannelName = a->argv[2];
chancapiCommand = a->argv[3];
#else
provided_args = argc;
if (provided_args < required_args) {
return RESULT_SHOWUSAGE;
}
requiredChannelName = argv[2];
chancapiCommand = argv[3];
#endif
ret = pbx_capi_management_capicommand(requiredChannelName, chancapiCommand);
#ifdef CC_AST_HAS_VERSION_1_6
return ((ret == 0) ? CLI_SUCCESS : CLI_FAILURE);
#else
return ((ret == 0) ? RESULT_SUCCESS : RESULT_FAILURE);
#endif
}
/*
* exec capi command
*/
#ifdef CC_AST_HAS_VERSION_1_6
static char *pbxcli_capi_chat_manage_capicommand(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#else
static int pbxcli_capi_chat_manage_capicommand(int fd, int argc, char *argv[])
#endif
{
int required_args = 6;
int provided_args;
const char* roomName = NULL;
const char* memberName = NULL;
const char* chatCommand = NULL;
const char* commandParameters = NULL;
#ifdef CC_AST_HAS_VERSION_1_8
const char * const *cli_argv;
#elif (defined(CC_AST_HAS_VERSION_1_6) && !defined(CC_AST_HAS_VERSION_1_8))
char **cli_argv;
#else
char * const *cli_argv;
#endif
int ret = -1;
#ifdef CC_AST_HAS_VERSION_1_6
if (cmd == CLI_INIT) {
e->command = CC_MESSAGE_NAME " chat manage";
e->usage = show_chat_manage_usage;
return NULL;
} else if (cmd == CLI_GENERATE) {
return NULL;
}
provided_args = a->argc;
cli_argv = a->argv;
if (provided_args < required_args) {
return CLI_SHOWUSAGE;
}
#else
provided_args = argc;
cli_argv = argv;
if (provided_args < required_args) {
return RESULT_SHOWUSAGE;
}
#endif
roomName = cli_argv[3];
memberName = cli_argv[4];
chatCommand = cli_argv[5];
if (provided_args > required_args)
commandParameters = cli_argv[6];
if (strcmp(chatCommand, "remove") == 0) {
ret = pbx_capi_chat_remove_user (roomName, memberName);
}
#ifdef CC_AST_HAS_VERSION_1_6
return ((ret == 0) ? CLI_SUCCESS : CLI_FAILURE);
#else
return ((ret == 0) ? RESULT_SUCCESS : RESULT_FAILURE);
#endif
}
/*
* define commands
*/
#ifdef CC_AST_HAS_VERSION_1_6
static struct ast_cli_entry cc_cli_cmd[] = {
AST_CLI_DEFINE(pbxcli_capi_info, CC_CLI_TEXT_INFO),
AST_CLI_DEFINE(pbxcli_capi_show_channels, CC_CLI_TEXT_SHOW_CHANNELS),
AST_CLI_DEFINE(pbxcli_capi_do_debug, CC_CLI_TEXT_DEBUG),
AST_CLI_DEFINE(pbxcli_capi_no_debug, CC_CLI_TEXT_NO_DEBUG),
AST_CLI_DEFINE(pbxcli_capi_qsig_do_debug, CC_CLI_TEXT_QSIG_DEBUG),
AST_CLI_DEFINE(pbxcli_capi_qsig_no_debug, CC_CLI_TEXT_QSIG_NO_DEBUG),
AST_CLI_DEFINE(pbxcli_capi_chatinfo, CC_CLI_TEXT_CHATINFO),
#ifdef DIVA_STATUS
AST_CLI_DEFINE(pbxcli_capi_ifc_status, CC_CLI_TEXT_IFC_STATUSINFO),
#endif
#ifdef DIVA_VERBOSE
AST_CLI_DEFINE(pbxcli_capi_do_verbose, CC_CLI_TEXT_CAPI_DO_VERBOSE),
AST_CLI_DEFINE(pbxcli_capi_no_verbose, CC_CLI_TEXT_CAPI_NO_VERBOSE),
#endif
AST_CLI_DEFINE(pbxcli_capi_show_resources, CC_CLI_TEXT_SHOW_RESOURCES),
AST_CLI_DEFINE(pbxcli_capi_exec_capicommand, CC_CLI_TEXT_EXEC_CAPICOMMAND),
AST_CLI_DEFINE(pbxcli_capi_chat_manage_capicommand, CC_CLI_TEXT_CHAT_MANAGE),
AST_CLI_DEFINE(pbxcli_capi_show_bridges, CC_CLI_TEXT_SHOW_BRIDGES),
};
#else
static struct ast_cli_entry cli_info =
{ { CC_MESSAGE_NAME, "info", NULL }, pbxcli_capi_info, CC_CLI_TEXT_INFO, info_usage };
static struct ast_cli_entry cli_show_channels =
{ { CC_MESSAGE_NAME, "show", "channels", NULL }, pbxcli_capi_show_channels, CC_CLI_TEXT_SHOW_CHANNELS, show_channels_usage };
static struct ast_cli_entry cli_debug =
{ { CC_MESSAGE_NAME, "debug", NULL }, pbxcli_capi_do_debug, CC_CLI_TEXT_DEBUG, debug_usage };
static struct ast_cli_entry cli_no_debug =
{ { CC_MESSAGE_NAME, "no", "debug", NULL }, pbxcli_capi_no_debug, CC_CLI_TEXT_NO_DEBUG, no_debug_usage };
static struct ast_cli_entry cli_qsig_debug =
{ { CC_MESSAGE_NAME, "qsig", "debug", NULL }, pbxcli_capi_qsig_do_debug, CC_CLI_TEXT_QSIG_DEBUG, qsig_debug_usage };
static struct ast_cli_entry cli_qsig_no_debug =
{ { CC_MESSAGE_NAME, "qsig", "no", "debug", NULL }, pbxcli_capi_qsig_no_debug, CC_CLI_TEXT_QSIG_NO_DEBUG, qsig_no_debug_usage };
static struct ast_cli_entry cli_chatinfo =
{ { CC_MESSAGE_NAME, "chatinfo", NULL }, pbxcli_capi_chatinfo, CC_CLI_TEXT_CHATINFO, chatinfo_usage };
#ifdef DIVA_STATUS
static struct ast_cli_entry cli_ifcstate =
{ { CC_MESSAGE_NAME, "ifcstate", NULL }, pbxcli_capi_ifc_status, CC_CLI_TEXT_IFC_STATUSINFO, diva_status_ifc_state_usage };
#endif
#ifdef DIVA_VERBOSE
static struct ast_cli_entry cli_verbose =
{ { CC_MESSAGE_NAME, "verbose", NULL }, pbxcli_capi_do_verbose, CC_CLI_TEXT_CAPI_DO_VERBOSE, capi_do_verbose_usage };
static struct ast_cli_entry cli_no_verbose =
{ { CC_MESSAGE_NAME, "no", "verbose", NULL }, pbxcli_capi_no_verbose, CC_CLI_TEXT_CAPI_NO_VERBOSE, capi_no_verbose_usage };
#endif
static struct ast_cli_entry cli_show_resources =
{ { CC_MESSAGE_NAME, "show", "resources", NULL }, pbxcli_capi_show_resources, CC_CLI_TEXT_SHOW_RESOURCES, show_resources_usage };
static struct ast_cli_entry cli_exec_capicommand =
{ { CC_MESSAGE_NAME, "exec", NULL }, pbxcli_capi_exec_capicommand, CC_CLI_TEXT_CHAT_MANAGE, show_exec_usage };
static struct ast_cli_entry cli_chat_manage =
{ { CC_MESSAGE_NAME, "chat", "manage", NULL }, pbxcli_capi_chat_manage_capicommand, CC_CLI_TEXT_EXEC_CAPICOMMAND, show_chat_manage_usage };
static struct ast_cli_entry cli_show_bridges =
{ { CC_MESSAGE_NAME, "show", "bridges", NULL }, pbxcli_capi_show_bridges, CC_CLI_TEXT_SHOW_BRIDGES, show_bridges_usage };
#endif
void pbx_capi_cli_register(void)
{
#ifdef CC_AST_HAS_VERSION_1_6
ast_cli_register_multiple(cc_cli_cmd, sizeof(cc_cli_cmd)/ sizeof(struct ast_cli_entry));
#else
ast_cli_register(&cli_info);
ast_cli_register(&cli_show_channels);
ast_cli_register(&cli_debug);
ast_cli_register(&cli_no_debug);
ast_cli_register(&cli_qsig_debug);
ast_cli_register(&cli_qsig_no_debug);
ast_cli_register(&cli_chatinfo);
#ifdef DIVA_STATUS
ast_cli_register(&cli_ifcstate);
#endif
#ifdef DIVA_VERBOSE
ast_cli_register(&cli_verbose);
ast_cli_register(&cli_no_verbose);
#endif
ast_cli_register(&cli_show_resources);
ast_cli_register(&cli_exec_capicommand);
ast_cli_register(&cli_chat_manage);
ast_cli_register(&cli_show_bridges);
#endif
}
void pbx_capi_cli_unregister(void)
{
#ifdef CC_AST_HAS_VERSION_1_6
ast_cli_unregister_multiple(cc_cli_cmd, sizeof(cc_cli_cmd)/ sizeof(struct ast_cli_entry));
#else
ast_cli_unregister(&cli_info);
ast_cli_unregister(&cli_show_channels);
ast_cli_unregister(&cli_debug);
ast_cli_unregister(&cli_no_debug);
ast_cli_unregister(&cli_qsig_debug);
ast_cli_unregister(&cli_qsig_no_debug);
ast_cli_unregister(&cli_chatinfo);
#ifdef DIVA_STATUS
ast_cli_unregister(&cli_ifcstate);
#endif
#ifdef DIVA_VERBOSE
ast_cli_unregister(&cli_verbose);
ast_cli_unregister(&cli_no_verbose);
#endif
ast_cli_unregister(&cli_show_resources);
ast_cli_unregister(&cli_exec_capicommand);
ast_cli_unregister(&cli_chat_manage);
ast_cli_unregister(&cli_show_bridges);
#endif
}

25
chan_capi_cli.h Normal file
View File

@ -0,0 +1,25 @@
/*
* An implementation of Common ISDN API 2.0 for Asterisk
*
* Copyright (C) 2005-2010 Cytronics & Melware
*
* Armin Schindler <armin@melware.de>
*
* Reworked, but based on the work of
* Copyright (C) 2002-2005 Junghanns.NET GmbH
*
* Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
*
* This program is free software and may be modified and
* distributed under the terms of the GNU Public License.
*/
#ifndef __CC_CLI_IFC_H__
#define __CC_CLI_IFC_H__
void pbx_capi_cli_register(void);
void pbx_capi_cli_unregister(void);
#endif

View File

@ -60,11 +60,11 @@ typedef struct _pbx_capi_voice_command {
* LOCALS
*/
static const char* pbx_capi_voicecommand_digits = "1234567890ABCD*#";
static int pbx_capi_command_nop (struct ast_channel *c, char *param);
static pbx_capi_voice_command_t* pbx_capi_find_command (struct capi_pvt *i, const char* name);
static pbx_capi_voice_command_t* pbx_capi_find_command_by_key (struct capi_pvt *i, const char* key);
static pbx_capi_voice_command_t* pbx_capi_voicecommand_find_digit_command (diva_entity_queue_t* q, const char* digits, int length, int* info);
static void pbx_capi_voicecommand_insert_command (diva_entity_queue_t* q, pbx_capi_voice_command_t* cmd);
static int pbx_capi_command_nop(struct ast_channel *c, char *param);
static pbx_capi_voice_command_t* pbx_capi_find_command(struct capi_pvt *i, const char* name);
static pbx_capi_voice_command_t* pbx_capi_find_command_by_key(struct capi_pvt *i, const char* key);
static pbx_capi_voice_command_t* pbx_capi_voicecommand_find_digit_command(diva_entity_queue_t* q, const char* digits, int length, int* info);
static void pbx_capi_voicecommand_insert_command(diva_entity_queue_t* q, pbx_capi_voice_command_t* cmd);
/*
@ -101,17 +101,18 @@ int pbx_capi_voicecommand(struct ast_channel *c, char *param)
}
command[0] = param;
command[1] = strchr (command[0], '|');
command[1] = strchr(command[0], '|');
if (command[1] == 0) {
/*
* Remove command
*/
cc_mutex_lock(&i->lock);
while ((cmd = pbx_capi_find_command (i, command[0])) != 0) {
cc_verbose(2, 0, VERBOSE_PREFIX_4"%s: voicecommand:%s removed\n", i->vname, cmd->command_name);
diva_q_remove (&i->channel_command_q, &cmd->link);
free (cmd);
while ((cmd = pbx_capi_find_command(i, command[0])) != 0) {
cc_verbose(2, 0, VERBOSE_PREFIX_4"%s: voicecommand:%s removed\n",
i->vname, cmd->command_name);
diva_q_remove(&i->channel_command_q, &cmd->link);
ast_free (cmd);
}
cc_mutex_unlock(&i->lock);
} else {
@ -148,7 +149,7 @@ int pbx_capi_voicecommand(struct ast_channel *c, char *param)
}
}
cmd = malloc(sizeof(*cmd));
cmd = ast_malloc(sizeof(*cmd));
if (cmd == NULL) {
cc_log(LOG_WARNING, CC_MESSAGE_NAME " can not allocate memory for voice command\n");
return -1;
@ -166,7 +167,7 @@ int pbx_capi_voicecommand(struct ast_channel *c, char *param)
cmd->channel_command_digits[length] = 0;
cmd->length = length;
cmd->pbx_capi_command = pbx_capi_lockup_command_by_name (cmd->command_name);
cmd->pbx_capi_command = pbx_capi_lockup_command_by_name(cmd->command_name);
if ( cmd->pbx_capi_command == 0) {
cmd->pbx_capi_command = pbx_capi_command_nop; /* accept unknown commands for compatibility reason */
}
@ -180,14 +181,14 @@ int pbx_capi_voicecommand(struct ast_channel *c, char *param)
pbx_capi_voice_command_t* present_cmd;
cc_mutex_lock(&i->lock);
if ((present_cmd = pbx_capi_find_command_by_key (i, cmd->command_name)) != 0) {
diva_q_remove (&i->channel_command_q, &present_cmd->link);
if ((present_cmd = pbx_capi_find_command_by_key(i, cmd->command_name)) != 0) {
diva_q_remove(&i->channel_command_q, &present_cmd->link);
}
pbx_capi_voicecommand_insert_command (&i->channel_command_q, cmd);
pbx_capi_voicecommand_insert_command(&i->channel_command_q, cmd);
cc_mutex_unlock(&i->lock);
if (present_cmd != 0) {
free (present_cmd);
ast_free (present_cmd);
}
}
}
@ -235,7 +236,7 @@ int pbx_capi_voicecommand_cleanup(struct capi_pvt *i)
while ((link = diva_q_get_head(&i->channel_command_q)) != NULL) {
diva_q_remove(&i->channel_command_q, link);
free(link);
ast_free(link);
}
i->channel_command_digit = 0;

139
chan_capi_devstate.c Normal file
View File

@ -0,0 +1,139 @@
/*
*
Copyright (c) Dialogic (R) 2009 - 2010
*
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters.
*
Dialogic (R) File Revision : 1.9
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <stdio.h>
#include "chan_capi_platform.h"
#include "chan_capi20.h"
#include "chan_capi.h"
#include "chan_capi_qsig.h"
#include "chan_capi_utils.h"
#include "chan_capi_chat.h"
#include "chan_capi_devstate.h"
/*
LOCALS
*/
static
#ifdef CC_AST_HAS_VERSION_1_6
enum ast_device_state
#else
int
#endif
pbx_capi_chat_room_state(const char *data);
static int capiChatProviderRegistered;
void pbx_capi_register_device_state_providers(void)
{
int i, capi_num_controllers;
capiChatProviderRegistered = (ast_devstate_prov_add("Capichat", pbx_capi_chat_room_state) == 0);
/*
Set initial device state for all supported interface
*/
for (i = 1, capi_num_controllers = pbx_capi_get_num_controllers();
i <= capi_num_controllers;
i++) {
const struct cc_capi_controller *capiController = pbx_capi_get_controller(i);
if (capiController != NULL) {
pbx_capi_ifc_state_event(capiController, 0);
}
}
}
void pbx_capi_unregister_device_state_providers(void)
{
if (capiChatProviderRegistered != 0) {
ast_devstate_prov_del("Capichat");
}
}
/*!
* \brief Read conference room state
*/
static
#ifdef CC_AST_HAS_VERSION_1_6
enum ast_device_state
#else
int
#endif
pbx_capi_chat_room_state(const char *data)
{
const struct capichat_s *room;
#ifdef CC_AST_HAS_VERSION_1_6
enum ast_device_state ret = AST_DEVICE_NOT_INUSE;
#else
int ret = AST_DEVICE_NOT_INUSE;
#endif
if (data == 0)
return AST_DEVICE_INVALID;
pbx_capi_lock_chat_rooms();
for (room = pbx_capi_chat_get_room_c(NULL);
room != 0;
room = pbx_capi_chat_get_room_c(room)) {
if (strcmp(data, pbx_capi_chat_get_room_name(room)) == 0) {
ret = AST_DEVICE_INUSE;
break;
}
}
pbx_capi_unlock_chat_rooms();
return ret;
}
/*!
* \brief Conference room state change
*/
void pbx_capi_chat_room_state_event(const char* roomName, int inUse)
{
if (capiChatProviderRegistered != 0) {
#ifdef CC_AST_HAS_VERSION_1_6
ast_devstate_changed((inUse != 0) ? AST_DEVICE_INUSE : AST_DEVICE_NOT_INUSE, "capichat:%s", roomName);
#else
ast_device_state_changed("capichat:%s", roomName);
#endif
}
}
void pbx_capi_ifc_state_event(const struct cc_capi_controller* capiController, int channelsChanged)
{
if ((channelsChanged == 0) ||
(capiController->nbchannels == capiController->nfreebchannels) ||
(capiController->nfreebchannels == 0) ||
((capiController->nfreebchannels < capiController->nfreebchannelsHardThr) &&
(capiController->nfreebchannels - channelsChanged >= capiController->nfreebchannelsHardThr)) ||
((capiController->nfreebchannels >= capiController->nfreebchannelsHardThr) &&
(capiController->nfreebchannels - channelsChanged < capiController->nfreebchannelsHardThr))) {
#ifdef CC_AST_HAS_VERSION_1_6
ast_devstate_changed(AST_DEVICE_UNKNOWN, CC_MESSAGE_BIGNAME"/I%d/congestion", capiController->controller);
#else
ast_device_state_changed (CC_MESSAGE_BIGNAME"/I%d/congestion", capiController->controller);
#endif
}
}

34
chan_capi_devstate.h Normal file
View File

@ -0,0 +1,34 @@
/*
*
Copyright (c) Dialogic (R) 2009 - 2010
*
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters.
*
Dialogic (R) File Revision : 1.9
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __CC_DEVICE_STATE_PROVIDER_INTERFACE_H__
#define __CC_DEVICE_STATE_PROVIDER_INTERFACE_H__
void pbx_capi_register_device_state_providers(void);
void pbx_capi_unregister_device_state_providers(void);
void pbx_capi_chat_room_state_event(const char* roomName, int inUse);
void pbx_capi_ifc_state_event(const struct cc_capi_controller* capiController, int channelsChanged);
#endif

View File

@ -0,0 +1,147 @@
/*
*
Copyright (c) Dialogic (R) 2009 - 2010
*
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters.
*
Dialogic (R) File Revision : 1.9
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <stdio.h>
#include "chan_capi_platform.h"
#include "chan_capi20.h"
#include "chan_capi.h"
#include "chan_capi_qsig.h"
#include "chan_capi_utils.h"
#include "chan_capi_chat.h"
/*
LOCALS
*/
static int pbx_capi_get_all_locks (struct capi_pvt *i, struct ast_channel** usedChannel);
/*!
\brief Execute any capicommand
\note Called from CLI or from AMI context
*/
int pbx_capi_management_capicommand(const char *requiredChannelName, const char *chancapiCommand) {
int ifc_type, retry_search, search_loops;
struct capi_pvt *i;
struct {
struct capi_pvt *head;
void (*lock_proc)(void);
void (*unlock_proc)(void);
} data[2];
data[0].head = capi_iflist;
data[0].lock_proc = pbx_capi_lock_interfaces;
data[0].unlock_proc = pbx_capi_unlock_interfaces;
data[1].head = (struct capi_pvt*)pbx_capi_get_nulliflist();
data[1].lock_proc = pbx_capi_nulliflist_lock;
data[1].unlock_proc = pbx_capi_nulliflist_unlock;
if (ast_strlen_zero(requiredChannelName)) {
return -2;
}
if (ast_strlen_zero(chancapiCommand)) {
return -3;
}
if (strcmp(requiredChannelName, "none") == 0) {
int ret = (pbx_capi_cli_exec_capicommand(NULL, chancapiCommand) == 0) ? 0 : -1;
return (ret);
}
for (ifc_type = 0; ifc_type < sizeof(data)/sizeof(data[0]); ifc_type++) {
search_loops = 10;
do {
data[ifc_type].lock_proc();
for (i = data[ifc_type].head, retry_search = 0; i != 0; i = i->next) {
struct ast_channel* c = NULL;
if ((i->used == 0) || ((i->channeltype != CAPI_CHANNELTYPE_B) &&
(i->channeltype != CAPI_CHANNELTYPE_NULL)))
continue;
if (i->data_plci != 0)
continue;
if (pbx_capi_get_all_locks (i, &c) != 0) {
retry_search = 1;
break;
}
if ((!ast_strlen_zero(c->name) && (strcmp(requiredChannelName, c->name) == 0)) ||
strcmp(requiredChannelName, i->vname) == 0) {
struct ast_channel* usedChannel = c;
int ret;
data[ifc_type].unlock_proc();
if (i->channeltype != CAPI_CHANNELTYPE_NULL) {
ret = (pbx_capi_cli_exec_capicommand(usedChannel, chancapiCommand) == 0) ? 0 : -1;
cc_mutex_unlock(&i->lock);
ast_channel_unlock(c);
} else {
ast_channel_unlock(c);
ret = (pbx_capi_cli_exec_capicommand(usedChannel, chancapiCommand) == 0) ? 0 : -1;
cc_mutex_unlock(&i->lock);
}
return ret;
}
cc_mutex_unlock(&i->lock);
ast_channel_unlock(c);
}
data[ifc_type].unlock_proc();
if (retry_search != 0) {
usleep (100);
}
} while((retry_search != 0) && (search_loops-- > 0));
}
return -4;
}
/*!
* \brief Try to take all locks. Called with false lock order
* one of the list locks (iflock or nullif_lock) taken
* Used by CLI/AMI
*/
static int pbx_capi_get_all_locks (struct capi_pvt *i, struct ast_channel** usedChannel)
{
struct ast_channel* c = (i->channeltype != CAPI_CHANNELTYPE_NULL) ? i->owner : i->used;
if (c != 0) {
if (ast_channel_trylock(c) == 0) {
if (ast_mutex_trylock(&i->lock) == 0) {
struct ast_channel* cref = (i->channeltype != CAPI_CHANNELTYPE_NULL) ? i->owner : i->used;
if (cref == c) {
*usedChannel = c;
return (0);
} else {
ast_mutex_unlock(&i->lock);
ast_channel_unlock (c);
}
} else {
ast_channel_unlock (c);
}
}
}
return (-1);
}

View File

@ -0,0 +1,31 @@
/*
*
Copyright (c) Dialogic (R) 2009 - 2010
*
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters.
*
Dialogic (R) File Revision : 1.9
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __CC_MANAGEMENT_COMMON_INTERFACE_H__
#define __CC_MANAGEMENT_COMMON_INTERFACE_H__
int pbx_capi_management_capicommand(const char *requiredChannelName, const char *chancapiCommand);
#endif

532
chan_capi_mwi.c Normal file
View File

@ -0,0 +1,532 @@
/*
*
Copyright (c) Dialogic(R), 2010
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <stdio.h>
#include "chan_capi_platform.h"
#include "chan_capi20.h"
#include "chan_capi.h"
#include "chan_capi_utils.h"
#if defined(CC_AST_HAS_EVENT_MWI)
#include <asterisk/event.h>
#endif
#include "chan_capi_mwi.h"
/*
LOCALS
*/
static unsigned char* time2X208(time_t t);
#if defined(CC_AST_HAS_EVENT_MWI)
static void pbx_capi_mwi_event(const struct ast_event *event, void *userdata);
#endif
/*
MWI command parameters of pbx_capi_mwi
*/
typedef enum _mwiAddSubscribtionParams {
mwiAddSubscribtionController = 1,
mwiAddSubscribtionReceivingUserNumber_TypeOfFacilityPartyNumber,
mwiAddSubscribtionReceivingUserNumber_TypeOfNumberAndNumberingPlan,
mwiAddSubscribtionReceivingUserNumber_PresentationAndScreening,
mwiAddSubscribtionReceivingUserNumber,
mwiAddSubscribtionControllingUserNumber_TypeOfFacilityPartyNumber,
mwiAddSubscribtionControllingUserNumber_TypeOfNumberAndNumberingPlan,
mwiAddSubscribtionControllingUserNumber_PresentationAndScreening,
mwiAddSubscribtionControllingUserNumber,
mwiAddSubscribtionControllingUserProvidedNumber_TypeOfFacilityPartyNumber,
mwiAddSubscribtionControllingUserProvidedNumber_TypeOfNumberAndNumberingPlan,
mwiAddSubscribtionControllingUserProvidedNumber_PresentationAndScreening,
mwiAddSubscribtionControllingUserProvidedNumber,
mwiAddSubscribtionMax
} mwiAddSubscribtionParams_t;
typedef enum _mwiRemoveSubscribtionParam {
mwiRemoveSubscribtionController = 1,
mwiRemoveSubscribtionReceivingUserNumber,
mwiRemoveSubscribtionMax
} mwiRemoveSubscribtionParam_t;
typedef enum _mwiXmitActivateParams {
mwiXmitActivate = 1,
mwiXmitActivateController,
mwiXmitActivateBasicService,
mwiXmitActivateNumberOfMessages,
mwiXmitActivateMessageStatus,
mwiXmitActivateMessageReference,
mwiXmitActivateInvocationMode,
mwiXmitActivateReceivingUserNumber_TypeOfFacilityPartyNumber,
mwiXmitActivateReceivingUserNumber_TypeOfNumberAndNumberingPlan,
mwiXmitActivateReceivingUserNumber_PresentationAndScreening,
mwiXmitActivateReceivingUserNumber,
mwiXmitActivateControllingUserNumber_TypeOfFacilityPartyNumber,
mwiXmitActivateControllingUserNumber_TypeOfNumberAndNumberingPlan,
mwiXmitActivateControllingUserNumber_PresentationAndScreening,
mwiXmitActivateControllingUserNumber,
mwiXmitActivateControllingUserProvidedNumber_TypeOfFacilityPartyNumber,
mwiXmitActivateControllingUserProvidedNumber_TypeOfNumberAndNumberingPlan,
mwiXmitActivateControllingUserProvidedNumber_PresentationAndScreening,
mwiXmitActivateControllingUserProvidedNumber,
mwiXmitActivatesMax
} mwiXmitActivateParams_t;
typedef enum _mwiXmitDeactivateParams {
mwiXmitDeactivate = 1,
mwiXmitDeactivateController,
mwiXmitDeactivateBasicService,
mwiXmitDeactivateInvocationMode,
mwiXmitDeactivateReceivingUserNumber_TypeOfFacilityPartyNumber,
mwiXmitDeactivateReceivingUserNumber_TypeOfNumberAndNumberingPlan,
mwiXmitDeactivateReceivingUserNumber_PresentationAndScreening,
mwiXmitDeactivateReceivingUserNumber,
mwiXmitDeactivateControllingUserNumber_TypeOfFacilityPartyNumber,
mwiXmitDeactivateControllingUserNumber_TypeOfNumberAndNumberingPlan,
mwiXmitDeactivateControllingUserNumber_PresentationAndScreening,
mwiXmitDeactivateControllingUserNumber,
mwiXmitDeactivateMax
} mwiXmitDeactivateParams_t;
/*
add|controller|fpn|ton|pres|receivingUserNumber|fpn|ton|pres|controllingUserNumber|fpn|ton|pres|controllingUserProvidedNumber
remove|conntroller|receivingUserNumber
xmit|activate|controller|basicService|numberOfMessages|messageStatus|messageReference|invocationMode|
fpn|ton|pres|receivingUserNumber|fpn|ton|pres|controllingUserNumber|fpn|ton|pres|controllingUserProvidedNumber
xmit|deactivate|controller|basicService|invocationMode|fpn|ton|pres|receivingUserNumber|fpn|ton|pres|controllingUserNumber
add - add MWI subscription
remoce - remove MWI subscription
xmit - xmit MWI activate or deactivate
*/
int pbx_capi_mwi(struct ast_channel *c, char *info)
{
const char* params[MAX((MAX(mwiAddSubscribtionMax, mwiXmitActivatesMax)),(MAX(mwiRemoveSubscribtionMax, mwiXmitDeactivateMax)))];
int ret = -1;
int i;
for (i = 0; i < sizeof(params)/sizeof(params[0]); i++) {
params[i] = strsep (&info, COMMANDSEPARATOR);
}
if (params[0] == NULL)
return (-1);
if (strcmp(params[0], "add") == 0) {
} else if (strcmp (params[0], "remove") == 0) {
} else if (strcmp (params[0], "xmit") == 0) {
if (strcmp (params[mwiXmitActivate], "activate") == 0) {
int unit;
if (params[mwiXmitActivateController] != 0 && params[mwiXmitActivateController][0] != 0) {
unit = atoi(params[mwiXmitActivateController]);
} else {
struct capi_pvt *i = CC_CHANNEL_PVT(c);
unit = (i != 0) ? i->controller : 0;
}
if (pbx_capi_get_controller(unit) != 0 && params[mwiXmitActivateReceivingUserNumber] != 0) {
unsigned short basicService = params[mwiXmitActivateBasicService] != 0 ? (unsigned short)atoi(params[mwiXmitActivateBasicService]) : 1;
unsigned short numberOfMessages = params[mwiXmitActivateNumberOfMessages] != 0 ? (unsigned int)atoi(params[mwiXmitActivateNumberOfMessages]) : 1;
unsigned short messageStatus = params[mwiXmitActivateMessageStatus] != 0 ? (unsigned short)atoi(params[mwiXmitActivateMessageStatus]) : 0;
unsigned short messageReference = params[mwiXmitActivateMessageReference] != 0 ? (unsigned short)atoi(params[mwiXmitActivateMessageReference]) : 0;
unsigned short invocationMode = params[mwiXmitActivateInvocationMode] != 0 ? (unsigned short)atoi(params[mwiXmitActivateInvocationMode]) : 2;
unsigned char ReceivingUserNumber_TypeOfFacilityPartyNumber = params[mwiXmitActivateReceivingUserNumber_TypeOfFacilityPartyNumber] != 0 ?
(unsigned char)atoi(params[mwiXmitActivateReceivingUserNumber_TypeOfFacilityPartyNumber]) : 0;
unsigned char ReceivingUserNumber_TypeOfNumberAndNumberingPlan = params[mwiXmitActivateReceivingUserNumber_TypeOfNumberAndNumberingPlan] != 0 ?
(((unsigned char)atoi(params[mwiXmitActivateReceivingUserNumber_TypeOfNumberAndNumberingPlan])) & ~0x80) : 0;
unsigned char ReceivingUserNumber_PresentationAndScreening = params[mwiXmitActivateReceivingUserNumber_PresentationAndScreening] != 0 ?
(((unsigned char)atoi(params[mwiXmitActivateReceivingUserNumber_PresentationAndScreening])) & ~0x80) : 0;
const char* ReceivingUserNumber = params[mwiXmitActivateReceivingUserNumber];
unsigned char ControllingUserNumber_TypeOfFacilityPartyNumber = params[mwiXmitActivateControllingUserNumber_TypeOfFacilityPartyNumber] != 0 ?
(unsigned char)atoi(params[mwiXmitActivateControllingUserNumber_TypeOfFacilityPartyNumber]) : 0;
unsigned char ControllingUserNumber_TypeOfNumberAndNumberingPlan = params[mwiXmitActivateControllingUserNumber_TypeOfNumberAndNumberingPlan] != 0 ?
(((unsigned char)atoi(params[mwiXmitActivateControllingUserNumber_TypeOfNumberAndNumberingPlan])) & ~0x80) : 0;
unsigned char ControllingUserNumber_PresentationAndScreening = params[mwiXmitActivateControllingUserNumber_PresentationAndScreening] != 0 ?
(((unsigned char)atoi(params[mwiXmitActivateControllingUserNumber_PresentationAndScreening])) & ~0x80) : 0;
const char* ControllingUserNumber = params[mwiXmitActivateControllingUserNumber];
unsigned char ControllingUserProvidedNumber_TypeOfFacilityPartyNumber = params[mwiXmitActivateControllingUserProvidedNumber_TypeOfFacilityPartyNumber] != 0 ?
(unsigned char)atoi(params[mwiXmitActivateControllingUserProvidedNumber_TypeOfFacilityPartyNumber]) : 0;
unsigned char ControllingUserProvidedNumber_TypeOfNumberAndNumberingPlan = params[mwiXmitActivateControllingUserProvidedNumber_TypeOfNumberAndNumberingPlan] != 0 ?
(((unsigned char)atoi(params[mwiXmitActivateControllingUserProvidedNumber_TypeOfNumberAndNumberingPlan])) & ~0x80) : 0;
unsigned char ControllingUserProvidedNumber_PresentationAndScreening = params[mwiXmitActivateControllingUserProvidedNumber_PresentationAndScreening] != 0 ?
(((unsigned char)atoi(params[mwiXmitActivateControllingUserProvidedNumber_PresentationAndScreening])) & ~0x80) : 0;
const char* ControllingUserProvidedNumber = params[mwiXmitActivateControllingUserProvidedNumber];
unsigned char *facilityReceivingUserNumber = pbx_capi_build_facility_number (ReceivingUserNumber_TypeOfFacilityPartyNumber,
ReceivingUserNumber_TypeOfNumberAndNumberingPlan,
ReceivingUserNumber_PresentationAndScreening,
ReceivingUserNumber);
unsigned char *facilityControllingUserNumber = pbx_capi_build_facility_number (ControllingUserNumber_TypeOfFacilityPartyNumber,
ControllingUserNumber_TypeOfNumberAndNumberingPlan,
ControllingUserNumber_PresentationAndScreening,
ControllingUserNumber);
unsigned char *facilityControllingUserProvidedNumber = pbx_capi_build_facility_number (ControllingUserProvidedNumber_TypeOfFacilityPartyNumber,
ControllingUserProvidedNumber_TypeOfNumberAndNumberingPlan,
ControllingUserProvidedNumber_PresentationAndScreening,
ControllingUserProvidedNumber);
unsigned char* t = time2X208(time(NULL));
ret = pbx_capi_xmit_mwi(pbx_capi_get_controller(unit),
basicService,
numberOfMessages,
messageStatus,
messageReference,
invocationMode,
facilityReceivingUserNumber,
facilityControllingUserNumber,
facilityControllingUserProvidedNumber,
t);
ast_free(facilityReceivingUserNumber);
ast_free(facilityControllingUserNumber);
ast_free(facilityControllingUserProvidedNumber);
ast_free(t);
}
} else if (strcmp (params[mwiXmitDeactivate], "deactivate") == 0) {
int unit;
if (params[mwiXmitDeactivateController] != 0 && params[mwiXmitDeactivateController][0] != 0) {
unit = atoi(params[mwiXmitDeactivateController]);
} else {
struct capi_pvt *i = CC_CHANNEL_PVT(c);
unit = (i != 0) ? i->controller : 0;
}
if (pbx_capi_get_controller(unit) != 0 && params[mwiXmitDeactivateReceivingUserNumber] != 0) {
unsigned short basicService = params[mwiXmitDeactivateBasicService] != 0 ? (unsigned short)atoi(params[mwiXmitDeactivateBasicService]) : 1;
unsigned short invocationMode = params[mwiXmitDeactivateInvocationMode] != 0 ? (unsigned short)atoi(params[mwiXmitDeactivateInvocationMode]) : 2;
unsigned char ReceivingUserNumber_TypeOfFacilityPartyNumber = params[mwiXmitDeactivateReceivingUserNumber_TypeOfFacilityPartyNumber] != 0 ?
(unsigned char)atoi(params[mwiXmitDeactivateReceivingUserNumber_TypeOfFacilityPartyNumber]) : 0;
unsigned char ReceivingUserNumber_TypeOfNumberAndNumberingPlan = params[mwiXmitDeactivateReceivingUserNumber_TypeOfNumberAndNumberingPlan] != 0 ?
(((unsigned char)atoi(params[mwiXmitDeactivateReceivingUserNumber_TypeOfNumberAndNumberingPlan])) & ~0x80) : 0;
unsigned char ReceivingUserNumber_PresentationAndScreening = params[mwiXmitDeactivateReceivingUserNumber_PresentationAndScreening] != 0 ?
(((unsigned char)atoi(params[mwiXmitDeactivateReceivingUserNumber_PresentationAndScreening])) & ~0x80) : 0;
const char* ReceivingUserNumber = params[mwiXmitDeactivateReceivingUserNumber];
unsigned char ControllingUserNumber_TypeOfFacilityPartyNumber = params[mwiXmitDeactivateControllingUserNumber_TypeOfFacilityPartyNumber] != 0 ?
(unsigned char)atoi(params[mwiXmitDeactivateControllingUserNumber_TypeOfFacilityPartyNumber]) : 0;
unsigned char ControllingUserNumber_TypeOfNumberAndNumberingPlan = params[mwiXmitDeactivateControllingUserNumber_TypeOfNumberAndNumberingPlan] != 0 ?
(((unsigned char)atoi(params[mwiXmitDeactivateControllingUserNumber_TypeOfNumberAndNumberingPlan])) & ~0x80) : 0;
unsigned char ControllingUserNumber_PresentationAndScreening = params[mwiXmitDeactivateControllingUserNumber_PresentationAndScreening] != 0 ?
(((unsigned char)atoi(params[mwiXmitDeactivateControllingUserNumber_PresentationAndScreening])) & ~0x80) : 0;
const char* ControllingUserNumber = params[mwiXmitDeactivateControllingUserNumber];
unsigned char *facilityReceivingUserNumber = pbx_capi_build_facility_number (ReceivingUserNumber_TypeOfFacilityPartyNumber,
ReceivingUserNumber_TypeOfNumberAndNumberingPlan,
ReceivingUserNumber_PresentationAndScreening,
ReceivingUserNumber);
unsigned char *facilityControllingUserNumber = pbx_capi_build_facility_number (ControllingUserNumber_TypeOfFacilityPartyNumber,
ControllingUserNumber_TypeOfNumberAndNumberingPlan,
ControllingUserNumber_PresentationAndScreening,
ControllingUserNumber);
ret = pbx_capi_xmit_mwi_deactivate(pbx_capi_get_controller(unit),
basicService, invocationMode, facilityReceivingUserNumber, facilityControllingUserNumber);
ast_free (facilityReceivingUserNumber);
ast_free (facilityControllingUserNumber);
}
}
}
return (ret);
}
int pbx_capi_xmit_mwi(
const struct cc_capi_controller *controller,
unsigned short basicService,
unsigned int numberOfMessages,
unsigned short messageStatus,
unsigned short messageReference,
unsigned short invocationMode,
const unsigned char* receivingUserNumber,
const unsigned char* controllingUserNumber,
const unsigned char* controllingUserProvidedNumber,
const unsigned char* timeX208)
{
MESSAGE_EXCHANGE_ERROR error;
_cword messageNumber = get_capi_MessageNumber();
error = capi_sendf(NULL, 0, CAPI_FACILITY_REQ, controller->controller, messageNumber,
"w(w(wdwwwssssd))",
0x0003, /* Suppl. Service */
0x0013, /* MWI Activate */
basicService, /* Basic Service */
numberOfMessages, /* Number of messages */
messageStatus, /* Added messages */
messageReference, /* Message reference */
invocationMode, /* Invocation mode */
receivingUserNumber, /* Receiving user number */
controllingUserNumber, /* Controlling user number */
controllingUserProvidedNumber, /* Controlling user provided number */
timeX208, /* time */
messageNumber);
return ((error == CapiNoError) ? 0 : -1);
}
int pbx_capi_xmit_mwi_deactivate(
const struct cc_capi_controller *controller,
unsigned short basicService,
unsigned short invocationMode,
const unsigned char* receivingUserNumber,
const unsigned char* controllingUserNumber)
{
MESSAGE_EXCHANGE_ERROR error;
_cword messageNumber = get_capi_MessageNumber();
error = capi_sendf(NULL, 0, CAPI_FACILITY_REQ, controller->controller, messageNumber,
"w(w(wwss))",
0x0003, /* Suppl. Service */
0x0014, /* MWI Activate */
basicService, /* Basic Service */
invocationMode, /* Invocation mode */
receivingUserNumber, /* Receiving user number */
controllingUserNumber /* Controlling user number */);
return ((error == CapiNoError) ? 0 : -1);
}
static unsigned char* time2X208 (time_t t) {
unsigned char* ret = 0;
#if defined(CC_AST_HAS_VERSION_1_6)
unsigned char tX208[] = { 0x0c, 0x32, 0x30, 0x30, 0x31, 0x30, 0x35, 0x31, 0x31, 0x30, 0x39, 0x33, 0x36, 0x00 };
struct timeval tv = {
.tv_sec = t,
};
struct ast_tm tm;
ast_localtime(&tv, &tm, "utc");
ast_strftime((char*)&tX208[1], sizeof(tX208)-1, "%Y%d%m%H%M", &tm);
ret = ast_malloc (sizeof(tX208));
if (ret != 0)
memcpy (ret, tX208, sizeof(tX208));
#endif
return (ret);
}
#if defined(CC_AST_HAS_EVENT_MWI)
static void pbx_capi_mwi_event(const struct ast_event *event, void *userdata)
{
cc_capi_mwi_mailbox_t* mwiSubscribtion = userdata;
/* const char *mbox_context; */
const char *mbox_number;
int num_messages, num_old_messages;
unsigned char* t;
int ret;
mbox_number = ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX);
if (ast_strlen_zero(mbox_number)) {
return;
}
/*
mbox_context = ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT);
if (ast_strlen_zero(mbox_context)) {
return;
}
*/
num_messages = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
num_old_messages = ast_event_get_ie_uint(event, AST_EVENT_IE_OLDMSGS);
t = time2X208 (time(NULL));
cc_verbose (4, 0, "CAPI%d MWI event for '%s@%s' %d messages\n",
mwiSubscribtion->controller->controller,
mwiSubscribtion->mailboxNumber+4,
mwiSubscribtion->mailboxContext,
num_messages);
if ((num_messages != 0) || (num_old_messages != 0)) {
ret = pbx_capi_xmit_mwi(mwiSubscribtion->controller,
mwiSubscribtion->basicService,
num_messages,
0,
0,
mwiSubscribtion->invocationMode,
mwiSubscribtion->mailboxNumber,
mwiSubscribtion->controllingUserNumber,
mwiSubscribtion->controllingUserProvidedNumber,
t);
} else {
ret = pbx_capi_xmit_mwi_deactivate(mwiSubscribtion->controller,
mwiSubscribtion->basicService,
mwiSubscribtion->invocationMode,
mwiSubscribtion->mailboxNumber,
mwiSubscribtion->controllingUserNumber);
}
ast_free(t);
}
#endif
void pbx_capi_register_mwi(struct cc_capi_controller *controller)
{
cc_capi_mwi_mailbox_t* mwiSubscribtion;
AST_LIST_TRAVERSE(&controller->mwiSubscribtions, mwiSubscribtion, link) {
#if defined(CC_AST_HAS_EVENT_MWI)
mwiSubscribtion->mwiSubscribtion = ast_event_subscribe(AST_EVENT_MWI, pbx_capi_mwi_event,
#ifdef CC_AST_HAS_VERSION_1_8
"CHAN_CAPI mbox event",
#endif
mwiSubscribtion,
AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, &mwiSubscribtion->mailboxNumber[4],
AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, mwiSubscribtion->mailboxContext,
AST_EVENT_IE_END);
#endif
if (mwiSubscribtion->mwiSubscribtion == 0) {
cc_log(LOG_WARNING, "CAPI%d failed to activate MWI subscribtion for '%s@%s'\n",
mwiSubscribtion->controller->controller,
&mwiSubscribtion->mailboxNumber[4],
mwiSubscribtion->mailboxContext);
}
}
}
void pbx_capi_refresh_mwi(struct cc_capi_controller *controller)
{
cc_capi_mwi_mailbox_t* mwiSubscribtion;
AST_LIST_TRAVERSE(&controller->mwiSubscribtions, mwiSubscribtion, link) {
if (mwiSubscribtion->mwiSubscribtion != 0) {
#if defined(CC_AST_HAS_EVENT_MWI)
struct ast_event *event = ast_event_get_cached(AST_EVENT_MWI,
AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, &mwiSubscribtion->mailboxNumber[4],
AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, mwiSubscribtion->mailboxContext,
AST_EVENT_IE_END);
if (event != 0) {
pbx_capi_mwi_event(event, mwiSubscribtion);
ast_event_destroy(event);
}
#endif
}
}
}
void pbx_capi_unregister_mwi(struct cc_capi_controller *controller)
{
cc_capi_mwi_mailbox_t* mwiSubscribtion;
AST_LIST_TRAVERSE(&controller->mwiSubscribtions, mwiSubscribtion, link) {
if (mwiSubscribtion->mwiSubscribtion != 0) {
#if defined(CC_AST_HAS_EVENT_MWI)
ast_event_unsubscribe(mwiSubscribtion->mwiSubscribtion);
#endif
mwiSubscribtion->mwiSubscribtion = 0;
}
}
}
void pbx_capi_cleanup_mwi(struct cc_capi_controller *controller)
{
cc_capi_mwi_mailbox_t* mwiSubscribtion;
pbx_capi_unregister_mwi(controller);
while ((mwiSubscribtion = AST_LIST_REMOVE_HEAD(&controller->mwiSubscribtions, link)) != 0) {
ast_free (mwiSubscribtion->mailboxNumber);
ast_free (mwiSubscribtion->mailboxContext);
ast_free (mwiSubscribtion->controllingUserNumber);
ast_free (mwiSubscribtion->controllingUserProvidedNumber);
ast_free (mwiSubscribtion);
}
}
unsigned char* pbx_capi_build_facility_number(
unsigned char mwifacptynrtype,
unsigned char mwifacptynrton,
unsigned char mwifacptynrpres,
const char* number)
{
unsigned char* fnr = 0;
if (number != 0) {
fnr = ast_malloc (strlen(number)+7);
if (fnr != 0) {
fnr[0] = strlen(number) + 3;
fnr[1] = mwifacptynrtype;
fnr[2] = mwifacptynrton;
fnr[3] = mwifacptynrpres | 0x80;
strcpy((char*)&fnr[4], number);
}
}
return (fnr);
}
/*
Init MWI subscriptions
*/
void pbx_capi_init_mwi_server (
struct cc_capi_controller *mwiController,
const struct cc_capi_conf *conf) {
if ((mwiController != 0) && (conf->mwimailbox != 0)) {
char* mailboxList = conf->mwimailbox;
char* mailboxMember;
while ((mailboxMember = strsep (&mailboxList, ",")) != 0) {
/*
Mailbox format: extension[:extension1[:extension2]][@context]
*/
char* mailboxNumbers = strsep(&mailboxMember, "@");
const char* mailboxContext = (mailboxMember != 0) ? mailboxMember : "default";
const char* mailboxNumber = strsep (&mailboxNumbers, ":");
const char* controllingUserNumber = strsep (&mailboxNumbers, ":");
const char* controllingUserProvidedNumber = mailboxNumbers;
if ((mailboxNumber != 0) && (*mailboxNumber != 0)) {
cc_capi_mwi_mailbox_t* mwiSubscribtion = ast_malloc(sizeof(*mwiSubscribtion));
if (mwiSubscribtion != 0) {
mwiSubscribtion->mailboxNumber = pbx_capi_build_facility_number(conf->mwifacptynrtype, conf->mwifacptynrton, conf->mwifacptynrpres, mailboxNumber);
mwiSubscribtion->mailboxContext = ast_strdup(mailboxContext);
mwiSubscribtion->controllingUserNumber = pbx_capi_build_facility_number(conf->mwifacptynrtype, conf->mwifacptynrton, conf->mwifacptynrpres, controllingUserNumber);
mwiSubscribtion->controllingUserProvidedNumber = pbx_capi_build_facility_number(conf->mwifacptynrtype, conf->mwifacptynrton, conf->mwifacptynrpres, controllingUserProvidedNumber);
mwiSubscribtion->controller = mwiController;
mwiSubscribtion->mwiSubscribtion = 0;
mwiSubscribtion->basicService = conf->mwibasicservice;
mwiSubscribtion->invocationMode = conf->mwiinvocation;
if ((mwiSubscribtion->mailboxNumber == 0) || (mwiSubscribtion->mailboxContext == 0) ||
((mwiSubscribtion->controllingUserNumber == 0) && (controllingUserNumber != 0)) ||
((mwiSubscribtion->controllingUserProvidedNumber == 0) && (controllingUserProvidedNumber != 0))) {
ast_free(mwiSubscribtion->mailboxNumber);
ast_free(mwiSubscribtion->mailboxContext);
ast_free(mwiSubscribtion->controllingUserNumber);
ast_free(mwiSubscribtion->controllingUserProvidedNumber);
ast_free(mwiSubscribtion);
} else {
cc_verbose (4, 0, "CAPI%d add MWI subscribtion for '%s@%s' user '%s' control '%s'\n",
mwiSubscribtion->controller->controller,
mwiSubscribtion->mailboxNumber + 4,
mwiSubscribtion->mailboxContext,
(mwiSubscribtion->controllingUserNumber != 0) ? (char*)mwiSubscribtion->controllingUserNumber+4 : "",
(mwiSubscribtion->controllingUserProvidedNumber != 0) ? (char*)mwiSubscribtion->controllingUserProvidedNumber+4 : "");
memset(&mwiSubscribtion->link, 0x00, sizeof(mwiSubscribtion->link));
AST_LIST_INSERT_TAIL(&mwiController->mwiSubscribtions, mwiSubscribtion, link);
}
}
}
}
}
}

56
chan_capi_mwi.h Normal file
View File

@ -0,0 +1,56 @@
/*
*
Copyright (c) Dialogic(R), 2010
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __CHAN_CAPI_MWI_H__
#define __CHAN_CAPI_MWI_H__
extern int pbx_capi_mwi(struct ast_channel *c, char *info);
extern int pbx_capi_xmit_mwi(
const struct cc_capi_controller *controller,
unsigned short basicService,
unsigned int numberOfMessages,
unsigned short messageStatus,
unsigned short messageReference,
unsigned short invocationMode,
const unsigned char* receivingUserNumber,
const unsigned char* controllingUserNumber,
const unsigned char* controllingUserProvidedNumber,
const unsigned char* timeX208);
extern int pbx_capi_xmit_mwi_deactivate(
const struct cc_capi_controller *controller,
unsigned short basicService,
unsigned short invocationMode,
const unsigned char* receivingUserNumber,
const unsigned char* controllingUserNumber);
extern void pbx_capi_register_mwi(struct cc_capi_controller *controller);
extern void pbx_capi_refresh_mwi(struct cc_capi_controller *controller);
extern void pbx_capi_unregister_mwi(struct cc_capi_controller *controller);
extern void pbx_capi_cleanup_mwi(struct cc_capi_controller *controller);
extern unsigned char* pbx_capi_build_facility_number(
unsigned char mwifacptynrtype,
unsigned char mwifacptynrton,
unsigned char mwifacptynrpres,
const char* number);
void pbx_capi_init_mwi_server (
struct cc_capi_controller *mwiController,
const struct cc_capi_conf *conf);
#endif

View File

@ -1,3 +1,23 @@
/*
*
Copyright (c) Dialogic(R), 2010
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __CHAN_CAPI_PLATFORM_H__
#define __CHAN_CAPI_PLATFORM_H__

View File

@ -190,7 +190,7 @@ struct rose_component {
} while (0)
#define free_null(x) { free(x); x = NULL; }
#define free_null(x) { ast_free(x); x = NULL; }
/* Common QSIG structs */

View File

@ -146,7 +146,7 @@ unsigned int cc_qsig_asn197ade_get_pns(unsigned char *data, int *idx, struct asn
myidx += res;
if (strlen(buf)) {
ns->partyNumber = strdup(buf);
ns->partyNumber = ast_strdup(buf);
}
/* get screening indicator */
@ -170,7 +170,7 @@ unsigned int cc_qsig_asn197ade_get_pns(unsigned char *data, int *idx, struct asn
myidx += res;
if (strlen(buf)) {
ns->partyNumber = strdup(buf);
ns->partyNumber = ast_strdup(buf);
}
/* get screening indicator */

View File

@ -222,7 +222,7 @@ unsigned char *cc_qsig_asn1_oid2str(unsigned char *data, int size)
*s++ = 0;
s = buf;
return (unsigned char *) strdup((char*)s);
return (unsigned char *) ast_strdup((char*)s);
}
@ -580,7 +580,7 @@ signed int cc_qsig_identifyinvoke(struct cc_qsig_invokedata *invoke, int protoco
oidstr = cc_qsig_asn1_oid2str(invoke->oid_bin, invoke->oid_len);
if (oidstr) {
cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: INVOKE OP (%s)\n", oidstr);
free(oidstr);
ast_free(oidstr);
} else {
cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: INVOKE OP (unknown - OID not displayable)\n");
}
@ -614,7 +614,7 @@ signed int cc_qsig_identifyinvoke(struct cc_qsig_invokedata *invoke, int protoco
oidstr = cc_qsig_asn1_oid2str(invoke->oid_bin, invoke->oid_len);
if (oidstr) {
cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: INVOKE OP (%s)\n", oidstr);
free(oidstr);
ast_free(oidstr);
} else {
cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: INVOKE OP (unknown - OID not displayable)\n");
}
@ -698,16 +698,16 @@ static void pbx_capi_qsig_handle_ctc(struct cc_qsig_invokedata *invoke, struct c
switch (ii->state) {
case CAPI_STATE_ALERTING:
cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: peer is in state ALERTING, PATH REPLACE follows after CONNECT...\n");
ii->qsig_data.pr_propose_cid = strdup("123"); /* HACK: need an dynamic ID */
ii->qsig_data.pr_propose_pn = strdup(i->qsig_data.if_pr_propose_pn);
ii->qsig_data.pr_propose_cid = ast_strdup("123"); /* HACK: need an dynamic ID */
ii->qsig_data.pr_propose_pn = ast_strdup(i->qsig_data.if_pr_propose_pn);
ii->qsig_data.pr_propose_doinboundbridge = 1;
i->qsig_data.pr_propose_doinboundbridge = 1;
i->qsig_data.partner_plci = ii->PLCI;
break;
case CAPI_STATE_CONNECTED:
cc_qsig_verbose( 1, VERBOSE_PREFIX_3 "QSIG: peer is CONNECTED...\n");
i->qsig_data.pr_propose_cid = strdup("123"); /* HACK: need an dynamic ID */
i->qsig_data.pr_propose_pn = strdup(i->qsig_data.if_pr_propose_pn);
i->qsig_data.pr_propose_cid = ast_strdup("123"); /* HACK: need an dynamic ID */
i->qsig_data.pr_propose_pn = ast_strdup(i->qsig_data.if_pr_propose_pn);
ii->qsig_data.pr_propose_doinboundbridge = 1;
ii->qsig_data.partner_plci = i->PLCI;
@ -1003,7 +1003,7 @@ unsigned int cc_qsig_add_call_setup_data(unsigned char *data, struct capi_pvt *i
}
cc_qsig_build_facility_struct(data, &dataidx, protocolvar, APDUINTERPRETATION_IGNORE, &nfe);
cc_qsig_encode_ecma_name_invoke(data, &dataidx, &invoke, i, 0, i->owner->cid.cid_name);
cc_qsig_encode_ecma_name_invoke(data, &dataidx, &invoke, i, 0, pbx_capi_get_connectedname (i->owner, ""));
cc_qsig_add_invoke(data, &dataidx, &invoke, i);
if (add_externalinfo) {
@ -1203,7 +1203,7 @@ int pbx_capi_qsig_ct(struct ast_channel *c, char *param)
return -1;
}
marker = strsep(&param, "|");
marker = strsep(&param, COMMANDSEPARATOR);
callmark = atoi(marker);
cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * QSIG_CT: using call marker %i(%s)\n", callmark, marker);
@ -1330,6 +1330,7 @@ void cc_pbx_qsig_conf_interface_value(struct cc_capi_conf *conf, struct ast_vari
}
CONF_INTEGER(conf->qsigfeat, "qsig")
CONF_TRUE(conf->divaqsig, "divaqsig", 1)
CONF_STRING(conf->qsigconf.if_pr_propose_pn, "qsig_prnum")
@ -1351,15 +1352,15 @@ static void qsig_cleanup_channel(struct capi_pvt *i)
i->qsig_data.pr_propose_sentback = 0;
i->qsig_data.pr_propose_doinboundbridge = 0;
if (i->qsig_data.pr_propose_cid) {
free(i->qsig_data.pr_propose_cid);
ast_free(i->qsig_data.pr_propose_cid);
i->qsig_data.pr_propose_cid = NULL;
}
if (i->qsig_data.pr_propose_pn) {
free(i->qsig_data.pr_propose_pn);
ast_free(i->qsig_data.pr_propose_pn);
i->qsig_data.pr_propose_pn = NULL;
}
if (i->qsig_data.dnameid) {
free(i->qsig_data.dnameid);
ast_free(i->qsig_data.dnameid);
i->qsig_data.dnameid = NULL;
}
@ -1528,8 +1529,8 @@ void pbx_capi_qsig_handle_info_indication(_cmsg *CMSG, unsigned int PLCI, unsign
ii->qsig_data.pr_propose_sentback = 1;
} else { /* Path Replacement has to be sent back after Connect on second line */
ii->qsig_data.pr_propose_sendback = 1;
ii->qsig_data.pr_propose_cid = strdup(i->qsig_data.pr_propose_cid);
ii->qsig_data.pr_propose_pn = strdup(i->qsig_data.pr_propose_pn);
ii->qsig_data.pr_propose_cid = ast_strdup(i->qsig_data.pr_propose_cid);
ii->qsig_data.pr_propose_pn = ast_strdup(i->qsig_data.pr_propose_pn);
ii->qsig_data.pr_propose_active = 1;
}
} else
@ -1537,9 +1538,9 @@ void pbx_capi_qsig_handle_info_indication(_cmsg *CMSG, unsigned int PLCI, unsign
free(i->qsig_data.pr_propose_cid);
ast_free(i->qsig_data.pr_propose_cid);
i->qsig_data.pr_propose_cid = NULL;
free(i->qsig_data.pr_propose_pn);
ast_free(i->qsig_data.pr_propose_pn);
i->qsig_data.pr_propose_pn = NULL;
}
@ -1553,9 +1554,9 @@ void pbx_capi_qsig_handle_info_indication(_cmsg *CMSG, unsigned int PLCI, unsign
ast_channel_masquerade(ii->owner, chanx);
}
free(i->qsig_data.pr_propose_cid);
ast_free(i->qsig_data.pr_propose_cid);
i->qsig_data.pr_propose_cid = NULL;
free(i->qsig_data.pr_propose_pn);
ast_free(i->qsig_data.pr_propose_pn);
i->qsig_data.pr_propose_pn = NULL;
}
@ -1612,9 +1613,9 @@ void pbx_capi_qsig_handle_info_indication(_cmsg *CMSG, unsigned int PLCI, unsign
);
i->qsig_data.pr_propose_sendback = 0;
free(i->qsig_data.pr_propose_cid);
ast_free(i->qsig_data.pr_propose_cid);
i->qsig_data.pr_propose_cid = NULL;
free(i->qsig_data.pr_propose_pn);
ast_free(i->qsig_data.pr_propose_pn);
i->qsig_data.pr_propose_pn = NULL;
i->qsig_data.pr_propose_sentback = 1;
@ -1640,9 +1641,9 @@ void pbx_capi_qsig_handle_info_indication(_cmsg *CMSG, unsigned int PLCI, unsign
"()(()()()s)", fac );
i->qsig_data.pr_propose_sendback = 0;
free(i->qsig_data.pr_propose_cid);
ast_free(i->qsig_data.pr_propose_cid);
i->qsig_data.pr_propose_cid = NULL;
free(i->qsig_data.pr_propose_pn);
ast_free(i->qsig_data.pr_propose_pn);
i->qsig_data.pr_propose_pn = NULL;
i->qsig_data.pr_propose_sentback = 1;

View File

@ -75,16 +75,20 @@ void cc_qsig_op_ecma_isdn_namepres(struct cc_qsig_invokedata *invoke, struct cap
switch (invoke->type) {
case 0: /* Calling Name */
i->owner->cid.cid_name = strdup(callername); /* Save name to callerid */
#ifdef CC_AST_HAS_VERSION_1_8
ast_set_callerid(i->owner, NULL, callername, NULL);
#else
i->owner->cid.cid_name = ast_strdup(callername); /* Save name to callerid */
#endif
break;
case 1: /* Called Name */
case 2: /* Connected Name */
case 3: /* Busy Name */
if (i->qsig_data.dnameid) { /* this facility may come more than once - if so, then update this value */
cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * deleting previously received name.\n", nametype, namelength, callername);
free(i->qsig_data.dnameid);
ast_free(i->qsig_data.dnameid);
}
i->qsig_data.dnameid = strdup(callername); /* save name as destination in qsig specific fields */
i->qsig_data.dnameid = ast_strdup(callername); /* save name as destination in qsig specific fields */
/* there's no similarly field in asterisk */
break;
default:
@ -112,7 +116,7 @@ void cc_qsig_op_ecma_isdn_namepres(struct cc_qsig_invokedata *invoke, struct cap
* returns
* always 0
*/
int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, int nametype, char * name)
int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, int nametype, const char * name)
{
unsigned char namebuf[51];
unsigned char data[255];
@ -382,40 +386,47 @@ void cc_qsig_encode_ecma_calltransfer(unsigned char * buf, unsigned int *idx, st
if (param) { /* got Call Transfer Parameters */
if (info) {
cid = strsep(&param, "|");
cid = strsep(&param, COMMANDSEPARATOR);
cidlen = strlen(cid);
if (cidlen > 20) /* HACK: stop action here, maybe we have invalid data */
cidlen = 20;
} else {
char *tmp = strsep(&param, "|");
char *tmp = strsep(&param, COMMANDSEPARATOR);
tmp = NULL;
cid = strsep(&param, "|");
cid = strsep(&param, COMMANDSEPARATOR);
cidlen = strlen(cid);
if (cidlen > 20) /* HACK: stop action here, maybe we have invalid data */
cidlen = 20;
ccanswer = strsep(&param, "|");
ccanswer = strsep(&param, COMMANDSEPARATOR);
if (ccanswer[0])
icanswer = ccanswer[0] - 0x30;
}
} else {
/* cid = strdup(i->owner->cid.cid_num);*/ /* Here we get the Asterisk extension */
/* cid = ast_strdup(i->owner->cid.cid_num);*/ /* Here we get the Asterisk extension */
if (info) { /* info is >0 on outbound channel (second facility) */
struct capi_pvt *ii = capi_find_interface_by_plci(i->qsig_data.partner_plci);
cid = strdup(i->cid);
cid = ast_strdup(i->cid);
cidlen = strlen(cid);
if (ii) {
/* send callers name to user B */
#ifdef CC_AST_HAS_VERSION_1_8
if (ii->owner->caller.id.name.valid ) {
name = ast_strdupa(S_COR(ii->owner->caller.id.name.valid, ii->owner->caller.id.name.str, ""));
namelength = strlen(name);
}
#else
if (ii->owner->cid.cid_name) {
name = ast_strdupa(ii->owner->cid.cid_name);
namelength = strlen(name);
}
#endif
}
} else { /* have to build first facility - send destination number back to inbound channel */
struct capi_pvt *ii = capi_find_interface_by_plci(i->qsig_data.partner_plci);
cid = strdup(ii->dnid);
cid = ast_strdup(ii->dnid);
cidlen = strlen(cid);
if (ii) {
@ -479,7 +490,7 @@ void cc_qsig_encode_ecma_calltransfer(unsigned char * buf, unsigned int *idx, st
cc_qsig_verbose( 0, VERBOSE_PREFIX_4 " * Sending QSIG_CT: %i->%s\n", info, cid);
if (cid)
free(cid);
ast_free(cid);
}
@ -552,7 +563,7 @@ unsigned int cc_qsig_decode_ecma_calltransfer(struct cc_qsig_invokedata *invoke,
if (data[myidx] == ASN1_TC_APPLICATION) {
myidx++;
/* TODO: check size -> could be bigger than 256 bytes - MSB is set then */
ctc->basicCallInfoElements = malloc(data[myidx]);
ctc->basicCallInfoElements = ast_malloc(data[myidx]);
if (ctc->basicCallInfoElements) {
memcpy(ctc->basicCallInfoElements, &data[myidx+1], data[myidx] );
} else {
@ -566,7 +577,7 @@ unsigned int cc_qsig_decode_ecma_calltransfer(struct cc_qsig_invokedata *invoke,
if (data[myidx] != ASN1_ENUMERATED) { /* Maybe we get an name (OPTIONAL) */
myidx += cc_qsig_asn197no_get_name(ct_name, ASN197NO_NAME_STRSIZE+1, &namelength, &myidx, data );
if (namelength)
ctc->redirectionName = strdup(ct_name);
ctc->redirectionName = ast_strdup(ct_name);
}
}
@ -607,12 +618,12 @@ void cc_qsig_encode_ecma_sscalltransfer(unsigned char * buf, unsigned int *idx,
char c[255];
int ix = 0;
cidsrc = strsep(&param, "|");
cidsrc = strsep(&param, COMMANDSEPARATOR);
srclen = strlen(cidsrc);
if (srclen > 20) /* HACK: stop action here, maybe we have invalid data */
srclen = 20;
ciddst = strsep(&param, "|");
ciddst = strsep(&param, COMMANDSEPARATOR);
dstlen = strlen(ciddst);
if (dstlen > 20) /* HACK: stop action here, maybe we have invalid data */
dstlen = 20;
@ -718,8 +729,8 @@ void cc_qsig_op_ecma_isdn_prpropose(struct cc_qsig_invokedata *invoke, struct ca
}
i->qsig_data.pr_propose_cid = strdup(callid);
i->qsig_data.pr_propose_pn = strdup(reroutingnr);
i->qsig_data.pr_propose_cid = ast_strdup(callid);
i->qsig_data.pr_propose_pn = ast_strdup(reroutingnr);
cc_qsig_verbose( 0, VERBOSE_PREFIX_4 " * Got QSIG_PATHREPLACEMENT_PROPOSE Call identity: %s, Party number: %s (%i)\n", callid, reroutingnr, temp);

View File

@ -53,7 +53,7 @@ struct cc_qsig_ccbsreq {
*/
extern void cc_qsig_op_ecma_isdn_namepres(struct cc_qsig_invokedata *invoke, struct capi_pvt *i);
extern int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, int nametype, char *name);
extern int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, int nametype, const char *name);
extern int cc_qsig_encode_ecma_isdn_leginfo3_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, char *name);

View File

@ -155,19 +155,32 @@ _cstruct capi_rtp_ncpi(struct capi_pvt *i)
*/
int capi_alloc_rtp(struct capi_pvt *i)
{
#ifdef CC_AST_HAS_AST_SOCKADDR
struct ast_sockaddr addr;
struct ast_sockaddr us;
#else
struct ast_hostent ahp;
struct hostent *hp;
struct in_addr addr;
struct sockaddr_in us;
#endif
#ifndef CC_AST_HAS_VERSION_1_4
char temp[MAXHOSTNAMELEN];
#endif
#ifdef CC_AST_HAS_AST_SOCKADDR
ast_sockaddr_parse(&addr, "localhost:0", 0);
#else
hp = ast_gethostbyname("localhost", &ahp);
memcpy(&addr, hp->h_addr, sizeof(addr));
#endif
#ifdef CC_AST_HAS_RTP_ENGINE_H
#ifdef CC_AST_HAS_AST_SOCKADDR
i->rtp = ast_rtp_instance_new(NULL, NULL, &addr, NULL);
#else
i->rtp = ast_rtp_instance_new(NULL, NULL, (struct sockaddr_in *)&addr, NULL);
#endif
#else
i->rtp = ast_rtp_new_with_bindaddr(NULL, NULL, 0, 0, addr);
#endif
@ -185,12 +198,16 @@ int capi_alloc_rtp(struct capi_pvt *i)
#endif
cc_verbose(2, 1, VERBOSE_PREFIX_4 "%s: alloc rtp socket on %s:%d\n",
i->vname,
#ifdef CC_AST_HAS_AST_SOCKADDR
ast_sockaddr_stringify(&us), ntohs(ast_sockaddr_port(&us)));
#else
#ifdef CC_AST_HAS_VERSION_1_4
ast_inet_ntoa(us.sin_addr),
#else
ast_inet_ntoa(temp, sizeof(temp), us.sin_addr),
#endif
ntohs(us.sin_port));
#endif
i->timestamp = 0;
return 0;
}
@ -200,14 +217,16 @@ int capi_alloc_rtp(struct capi_pvt *i)
*/
int capi_write_rtp(struct capi_pvt *i, struct ast_frame *f)
{
#ifdef CC_AST_HAS_AST_SOCKADDR
struct ast_sockaddr us;
#else
struct sockaddr_in us;
socklen_t uslen = sizeof(us);
#endif
int len;
socklen_t uslen;
unsigned int *rtpheader;
unsigned char buf[256];
uslen = sizeof(us);
if (!(i->rtp)) {
cc_log(LOG_ERROR, "rtp struct is NULL\n");
return -1;
@ -228,12 +247,16 @@ int capi_write_rtp(struct capi_pvt *i, struct ast_frame *f)
}
while(1) {
#ifdef CC_AST_HAS_AST_SOCKADDR
len = ast_recvfrom(ast_rtp_instance_fd(i->rtp, 0), buf, sizeof(buf), 0, &us);
#else
#ifdef CC_AST_HAS_RTP_ENGINE_H
len = recvfrom(ast_rtp_instance_fd(i->rtp, 0),
buf, sizeof(buf), 0, (struct sockaddr *)&us, &uslen);
#else
len = recvfrom(ast_rtp_fd(i->rtp),
buf, sizeof(buf), 0, (struct sockaddr *)&us, &uslen);
#endif
#endif
if (len <= 0)
break;
@ -281,7 +304,11 @@ int capi_write_rtp(struct capi_pvt *i, struct ast_frame *f)
struct ast_frame *capi_read_rtp(struct capi_pvt *i, unsigned char *buf, int len)
{
struct ast_frame *f;
#ifdef CC_AST_HAS_AST_SOCKADDR
struct ast_sockaddr us;
#else
struct sockaddr_in us;
#endif
if (!(i->owner))
return NULL;
@ -299,10 +326,14 @@ struct ast_frame *capi_read_rtp(struct capi_pvt *i, unsigned char *buf, int len)
ast_rtp_set_peer(i->rtp, &us);
#endif
#ifdef CC_AST_HAS_AST_SOCKADDR
if (len != ast_sendto(ast_rtp_instance_fd(i->rtp, 0), buf, len, 0, &us))
#else
#ifdef CC_AST_HAS_RTP_ENGINE_H
if (len != sendto(ast_rtp_instance_fd(i->rtp, 0), buf, len, 0, (struct sockaddr *)&us, sizeof(us)))
#else
if (len != sendto(ast_rtp_fd(i->rtp), buf, len, 0, (struct sockaddr *)&us, sizeof(us)))
#endif
#endif
{
cc_verbose(4, 1, VERBOSE_PREFIX_3 "%s: RTP sendto error\n",
@ -425,12 +456,43 @@ void voice_over_ip_profile(struct cc_capi_controller *cp)
}
if (payload1 & 0x00040000) {
cp->rtpcodec |= AST_FORMAT_G729A;
cc_verbose(3, 0, "G.729");
cc_verbose(3, 0, "G.729 ");
}
if (payload1 & (1U << 27)) {
cp->rtpcodec |= AST_FORMAT_ILBC;
cc_verbose(3, 0, "iLBC");
cc_verbose(3, 0, "iLBC ");
}
#ifdef AST_FORMAT_G722
if (payload1 & (1U << 9)) {
cp->rtpcodec |= AST_FORMAT_G722;
cc_verbose(3, 0, "G.722 ");
}
#endif
#if defined(AST_FORMAT_SIREN7) && defined(AST_FORMAT_SIREN14)
if (payload1 & (1U << 24)) {
#ifdef AST_FORMAT_SIREN7
cp->rtpcodec |= AST_FORMAT_SIREN7;
cc_verbose(3, 0, "siren7 ");
#endif
#ifdef AST_FORMAT_SIREN14
cp->rtpcodec |= AST_FORMAT_SIREN14;
cc_verbose(3, 0, "siren14 ");
#endif
}
#endif
#if defined(AST_FORMAT_SLINEAR) || defined(AST_FORMAT_SLINEAR16)
if (payload1 & (1U << 1)) {
#if defined(AST_FORMAT_SLINEAR)
cp->rtpcodec |= AST_FORMAT_SLINEAR;
cc_verbose(3, 0, "slin ");
#endif
#if defined(AST_FORMAT_SLINEAR16)
cp->rtpcodec |= AST_FORMAT_SLINEAR16;
cc_verbose(3, 0, "slin16 ");
#endif
}
#endif
cc_verbose(3, 0, "\n");
}

View File

@ -18,6 +18,9 @@
#include "chan_capi.h"
#include "chan_capi_supplementary.h"
#include "chan_capi_utils.h"
#if defined(CC_AST_HAS_EVENT_MWI)
#include <asterisk/event.h>
#endif
#define CCBSNR_TYPE_CCBS 1
@ -65,7 +68,7 @@ static void del_old_ccbsnr(void)
} else {
tmp->next = ccbsnr->next;
}
free(ccbsnr);
ast_free(ccbsnr);
break;
}
tmp = ccbsnr;
@ -86,7 +89,7 @@ void cleanup_ccbsnr(void)
while (ccbsnr) {
tmp = ccbsnr;
ccbsnr = ccbsnr->next;
free(tmp);
ast_free(tmp);
}
cc_mutex_unlock(&ccbsnr_lock);
}
@ -122,7 +125,7 @@ static void new_ccbsnr_id(char type, unsigned int plci,
char buffer[CAPI_MAX_STRING];
struct ccbsnr_s *ccbsnr;
ccbsnr = malloc(sizeof(struct ccbsnr_s));
ccbsnr = ast_malloc(sizeof(struct ccbsnr_s));
if (ccbsnr == NULL) {
cc_log(LOG_ERROR, "Unable to allocate CCBS/CCNR struct.\n");
return;
@ -259,7 +262,7 @@ static void del_ccbsnr_ref(unsigned int plci, _cword ref)
} else {
tmp->next = ccbsnr->next;
}
free(ccbsnr);
ast_free(ccbsnr);
cc_verbose(1, 1, VERBOSE_PREFIX_3 CC_MESSAGE_NAME
": PLCI=%#x CCBS/CCNR removed ref=0x%04x\n", plci, ref);
break;
@ -319,7 +322,7 @@ static void del_ccbsnr_id(unsigned int plci, _cword id)
} else {
tmp->next = ccbsnr->next;
}
free(ccbsnr);
ast_free(ccbsnr);
cc_verbose(1, 1, VERBOSE_PREFIX_3 CC_MESSAGE_NAME ": PLCI=%#x CCBS/CCNR removed "
"id=0x%04x state=%d\n", plci, id, oldstate);
} else {
@ -399,14 +402,24 @@ static void ccbsnr_remote_user_free(_cmsg *CMSG, char type, unsigned int PLCI, _
c->priority = ccbsnr->priority;
#ifdef CC_AST_HAS_VERSION_1_8
/*! \todo verify if necessary/complete */
c->connected.id.number.valid = 1;
ast_free (c->connected.id.number.str);
c->connected.id.number.str = ast_strdup(handlename);
ast_free (c->dialed.number.str);
c->dialed.number.str = ast_strdup (ccbsnr->exten);
#else
if (c->cid.cid_num) {
free(c->cid.cid_num);
ast_free(c->cid.cid_num);
}
c->cid.cid_num = strdup(handlename);
c->cid.cid_num = ast_strdup(handlename);
if (c->cid.cid_dnid) {
free(c->cid.cid_dnid);
ast_free(c->cid.cid_dnid);
}
c->cid.cid_dnid = strdup(ccbsnr->exten);
c->cid.cid_dnid = ast_strdup(ccbsnr->exten);
#endif
#ifndef CC_AST_HAS_EXT2_CHAN_ALLOC
cc_copy_string(c->context, ccbsnr->context, sizeof(c->context));
@ -561,6 +574,87 @@ int handle_facility_indication_supplementary(
cc_verbose(1, 1, VERBOSE_PREFIX_3 "contr%d: PLCI=%#x CCBS B-free ref=0x%04x\n",
PLCI & 0xff, PLCI, infoword);
break;
case 0x8014: {/* MWI indication, stateless */
const unsigned char* info = &FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[4];
unsigned short basicService = read_capi_word(info); info += 2;
unsigned int numberOfMessages = read_capi_dword(info); info += 4;
unsigned short messageStatus = read_capi_word(info); info += 2;
unsigned short messageReference = read_capi_word(info); info += 2;
char controllingUserNumberName[AST_MAX_EXTENSION];
char controllingUserProvidedNumberName[AST_MAX_EXTENSION];
char mwiTimeName[AST_MAX_EXTENSION];
char mailboxName[AST_MAX_EXTENSION];
if (info[0] > 3) {
memcpy(controllingUserNumberName,
&info[4],
MIN(AST_MAX_EXTENSION-1, info[0] - 3));
controllingUserNumberName[MIN(AST_MAX_EXTENSION-1, info[0] - 3)] = 0;
} else {
controllingUserNumberName[0] = 0;
}
info += info[0] + 1;
if (info[0] > 3) {
memcpy(controllingUserProvidedNumberName,
&info[4],
MIN(AST_MAX_EXTENSION-1, info[0] - 3));
controllingUserProvidedNumberName[MIN(AST_MAX_EXTENSION-1, info[0] - 3)] = 0;
} else {
controllingUserProvidedNumberName[0] = 0;
}
info += info[0] + 1;
if (info[0] != 0) {
memcpy(mwiTimeName, &info[1], MIN(AST_MAX_EXTENSION-1, info[0]));
mwiTimeName[MIN(AST_MAX_EXTENSION-1, info[0])] = 0;
} else {
mwiTimeName[0] = 0;
}
info += info[0] + 1;
if (info[0] > 1) {
memcpy(mailboxName, &info[2], MIN(AST_MAX_EXTENSION-1, info[0]));
mailboxName[MIN(AST_MAX_EXTENSION-1, info[0]-1)] = 0;
} else {
mailboxName[0] = 0;
}
if (messageStatus == 0 || messageStatus == 1) {
cc_verbose(4, 0, VERBOSE_PREFIX_4 "CAPI%u Rx MWI %s for '%s@CAPI_Remote %s %s time '%s' %d messages ref %d service %d\n",
PLCI & 0xff,
messageStatus == 0 ? "add" : "del", mailboxName, controllingUserNumberName, controllingUserProvidedNumberName,
mwiTimeName, numberOfMessages, messageReference, basicService);
if (messageStatus == 0 && mailboxName[0] != 0) {
#if defined(CC_AST_HAS_EVENT_MWI)
struct ast_event *event;
if ((event = ast_event_new(AST_EVENT_MWI,
AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailboxName,
AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, "CAPI_Remote",
AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, MAX(1,numberOfMessages),
AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, 0,
AST_EVENT_IE_END))) {
ast_event_queue_and_cache(event);
}
#endif
}
} else {
cc_verbose(4, 0, VERBOSE_PREFIX_1 "CAPI%u Rx MWI %s for '%s@default %s %s time '%s' service %d\n",
messageStatus == 0 ? "add" : "del", mailboxName, controllingUserNumberName, controllingUserProvidedNumberName,
mwiTimeName, basicService);
}
} return ret;
case 0x8000: /* Hold notification */
if ((i->isdnstate & CAPI_ISDN_STATE_EC) != 0) {
cc_verbose(4, 0, VERBOSE_PREFIX_1 "%s: EC reset\n", i->vname);
capi_echo_canceller(i, EC_FUNCTION_DISABLE);
capi_echo_canceller(i, EC_FUNCTION_ENABLE);
}
return ret;
default:
break;
}
if (!i) {
@ -618,6 +712,11 @@ int handle_facility_indication_supplementary(
i->vname, PLCI, infoword);
show_capi_info(i, infoword);
break;
case 0x000d: /* CD */
cc_verbose(1, 1, VERBOSE_PREFIX_3 "%s: PLCI=%#x CD Service Reason=0x%04x\n",
i->vname, PLCI, infoword);
show_capi_info(i, infoword);
break;
case 0x8013: /* CCBS info retain */
cc_verbose(1, 1, VERBOSE_PREFIX_3 "%s: PLCI=%#x CCBS unique id=0x%04x\n",
i->vname, PLCI, infoword);
@ -649,7 +748,7 @@ int handle_facility_indication_supplementary(
* CAPI FACILITY_CONF supplementary
*/
void handle_facility_confirmation_supplementary(
_cmsg *CMSG, unsigned int PLCI, unsigned int NCCI, struct capi_pvt **i)
_cmsg *CMSG, unsigned int PLCI, unsigned int NCCI, struct capi_pvt **i, struct ast_channel** interface_owner)
{
_cword function;
_cword serviceinfo;
@ -694,7 +793,7 @@ void handle_facility_confirmation_supplementary(
case 0x0012: /* CCBS call */
cc_verbose(2, 1, VERBOSE_PREFIX_3 "%s: CCBS call confirmation (0x%04x) (PLCI=%#x)\n",
name, serviceinfo, PLCI);
capidev_handle_connection_conf(i, PLCI, FACILITY_CONF_INFO(CMSG), HEADER_MSGNUM(CMSG));
capidev_handle_connection_conf(i, PLCI, FACILITY_CONF_INFO(CMSG), HEADER_MSGNUM(CMSG), interface_owner);
break;
default:
cc_verbose(3, 1, VERBOSE_PREFIX_3 "%s: unhandled FACILITY_CONF supplementary function %04x\n",
@ -712,7 +811,7 @@ int pbx_capi_ccpartybusy(struct ast_channel *c, char *data)
struct ccbsnr_s *ccbsnr;
char partybusy = 0;
slinkageid = strsep(&data, "|");
slinkageid = strsep(&data, COMMANDSEPARATOR);
yesno = data;
if (slinkageid) {
@ -806,9 +905,9 @@ int pbx_capi_ccbs(struct ast_channel *c, char *data)
MESSAGE_EXCHANGE_ERROR error;
unsigned int ccbsnrstate;
slinkageid = strsep(&data, "|");
context = strsep(&data, "|");
exten = strsep(&data, "|");
slinkageid = strsep(&data, COMMANDSEPARATOR);
context = strsep(&data, COMMANDSEPARATOR);
exten = strsep(&data, COMMANDSEPARATOR);
priority = data;
if (slinkageid) {

View File

@ -19,7 +19,8 @@ extern void ListenOnSupplementary(unsigned controller);
extern int handle_facility_indication_supplementary(
_cmsg *CMSG, unsigned int PLCI, unsigned int NCCI, struct capi_pvt *i);
extern void handle_facility_confirmation_supplementary(
_cmsg *CMSG, unsigned int PLCI, unsigned int NCCI, struct capi_pvt **i);
_cmsg *CMSG, unsigned int PLCI, unsigned int NCCI, struct capi_pvt **i,
struct ast_channel** interface_owner);
extern int pbx_capi_ccbs(struct ast_channel *c, char *data);
extern int pbx_capi_ccbsstop(struct ast_channel *c, char *data);
extern int pbx_capi_ccpartybusy(struct ast_channel *c, char *data);

View File

@ -17,6 +17,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include "chan_capi_platform.h"
#include "xlaw.h"
@ -26,6 +27,22 @@
#include "chan_capi_utils.h"
#include "chan_capi_supplementary.h"
#ifdef DIVA_STREAMING
#include "platform.h"
#include "diva_streaming_result.h"
#include "diva_streaming_messages.h"
#include "diva_streaming_vector.h"
#include "diva_streaming_manager.h"
#include "chan_capi_divastreaming_utils.h"
#endif
#ifdef DIVA_STATUS
#include "divastatus_ifc.h"
#define CC_HW_STATE_OK(__x__) ((pbx_capi_get_controller((__x__)) == NULL) || \
(pbx_capi_get_controller((__x__))->hwState != (int)DivaStatusHardwareStateERROR))
#else
#define CC_HW_STATE_OK(__x__) (1)
#endif
int capidebug = 0;
char *emptyid = "\0";
@ -123,7 +140,7 @@ void capi_remove_nullif(struct capi_pvt *i)
cc_mutex_destroy(&i->lock);
ast_cond_destroy(&i->event_trigger);
controller_nullplcis[i->controller - 1]--;
free(i);
ast_free(i);
break;
}
tmp = ii;
@ -158,7 +175,7 @@ struct capi_pvt *capi_mknullif(struct ast_channel *c, unsigned long long control
controllermask);
/* find the next controller of mask with least plcis used */
for (contrcount = 0; contrcount < maxcontr; contrcount++) {
if ((controllermask & (1ULL << contrcount)) != 0) {
if (((controllermask & (1ULL << contrcount)) != 0) && CC_HW_STATE_OK(contrcount + 1)) {
if (controller_nullplcis[contrcount] < channelcount) {
channelcount = controller_nullplcis[contrcount];
controller = contrcount + 1;
@ -166,7 +183,7 @@ struct capi_pvt *capi_mknullif(struct ast_channel *c, unsigned long long control
}
}
tmp = malloc(sizeof(struct capi_pvt));
tmp = ast_malloc(sizeof(struct capi_pvt));
if (!tmp) {
return NULL;
}
@ -175,13 +192,15 @@ struct capi_pvt *capi_mknullif(struct ast_channel *c, unsigned long long control
cc_mutex_init(&tmp->lock);
ast_cond_init(&tmp->event_trigger, NULL);
snprintf(tmp->name, sizeof(tmp->name) - 1, "%s-NULLPLCI", c->name);
snprintf(tmp->name, sizeof(tmp->name) - 1, "%s-NULLPLCI", (c != 0) ? c->name : "BRIDGE");
snprintf(tmp->vname, sizeof(tmp->vname) - 1, "%s", tmp->name);
tmp->channeltype = CAPI_CHANNELTYPE_NULL;
tmp->used = c;
tmp->peer = c;
if (c == NULL)
tmp->virtualBridgePeer = 1;
tmp->cip = CAPI_CIPI_SPEECH;
tmp->transfercapability = PRI_TRANS_CAP_SPEECH;
@ -198,9 +217,11 @@ struct capi_pvt *capi_mknullif(struct ast_channel *c, unsigned long long control
tmp->txgain = 1.0;
capi_gains(&tmp->g, 1.0, 1.0);
if (!(capi_create_reader_writer_pipe(tmp))) {
free(tmp);
return NULL;
if (c != 0) {
if (!(capi_create_reader_writer_pipe(tmp))) {
ast_free(tmp);
return NULL;
}
}
tmp->bproto = CC_BPROTO_TRANSPARENT;
@ -219,19 +240,45 @@ struct capi_pvt *capi_mknullif(struct ast_channel *c, unsigned long long control
tmp->state = CAPI_STATE_CONNECTPENDING;
tmp->MessageNumber = get_capi_MessageNumber();
capi_sendf(NULL, 0, CAPI_CONNECT_REQ, controller, tmp->MessageNumber,
#ifdef DIVA_STREAMING
tmp->diva_stream_entry = 0;
if (pbx_capi_streaming_supported (tmp) != 0) {
capi_DivaStreamingOn(tmp, 1, tmp->MessageNumber);
}
#endif
if (c == NULL) {
cc_mutex_lock(&tmp->lock);
}
capi_sendf((c != NULL) ? NULL : tmp, c == NULL, CAPI_CONNECT_REQ, controller, tmp->MessageNumber,
"w()()()()(www()()()())()()()((wwbbb)()()())",
0, 1,1,0, 3,0,0,0,0);
cc_verbose(3, 1, VERBOSE_PREFIX_4 "%s: created null-interface on controller %d.\n",
tmp->vname, tmp->controller);
if (c == NULL) {
cc_mutex_unlock(&tmp->lock);
if (tmp->PLCI == 0) {
cc_log(LOG_WARNING, "%s: failed to create\n", tmp->vname);
capi_remove_nullif(tmp);
tmp = NULL;
}
}
if (tmp != NULL) {
cc_verbose(3, 1, VERBOSE_PREFIX_4 "%s: created null-interface on controller %d.\n",
tmp->vname, tmp->controller);
}
return tmp;
}
struct capi_pvt *capi_mkresourceif(struct ast_channel *c, unsigned long long controllermask, struct capi_pvt *data_plci_ifc) {
struct capi_pvt *capi_mkresourceif(
struct ast_channel *c,
unsigned long long controllermask,
struct capi_pvt *data_plci_ifc,
cc_format_t codecs,
int all)
{
struct capi_pvt *data_ifc /*, *line_ifc */;
unsigned int controller = 1;
int fmt = 0;
if (data_plci_ifc == 0) {
int contrcount;
@ -244,7 +291,7 @@ struct capi_pvt *capi_mkresourceif(struct ast_channel *c, unsigned long long con
/* find the next controller of mask with least plcis used */
for (contrcount = 0; contrcount < maxcontr; contrcount++) {
if ((controllermask & (1ULL << contrcount)) != 0) {
if (((controllermask & (1ULL << contrcount)) != 0) && CC_HW_STATE_OK(contrcount + 1)) {
if (controller_nullplcis[contrcount] < channelcount) {
channelcount = controller_nullplcis[contrcount];
controller = contrcount + 1;
@ -253,9 +300,13 @@ struct capi_pvt *capi_mkresourceif(struct ast_channel *c, unsigned long long con
}
} else {
controller = data_plci_ifc->controller;
codecs = (all != 0) ? pbx_capi_get_controller_codecs (controller) : codecs;
fmt = pbx_capi_get_controller_codecs (controller) & codecs & c->nativeformats;
if (fmt != 0)
fmt = ast_best_codec(fmt);
}
data_ifc = malloc(sizeof(struct capi_pvt));
data_ifc = ast_malloc(sizeof(struct capi_pvt));
if (data_ifc == 0) {
return NULL;
}
@ -282,7 +333,8 @@ struct capi_pvt *capi_mkresourceif(struct ast_channel *c, unsigned long long con
data_ifc->ecTail = EC_DEFAULT_TAIL;
data_ifc->isdnmode = CAPI_ISDNMODE_MSN;
data_ifc->ecSelector = FACILITYSELECTOR_ECHO_CANCEL;
data_ifc->capability = capi_capability;
data_ifc->capability = (fmt != 0 && data_plci_ifc != 0) ? fmt : capi_capability;
data_ifc->codec = (fmt != 0 && data_plci_ifc != 0) ? fmt : data_ifc->codec;
data_ifc->rxgain = 1.0;
data_ifc->txgain = 1.0;
@ -290,7 +342,7 @@ struct capi_pvt *capi_mkresourceif(struct ast_channel *c, unsigned long long con
if (data_plci_ifc == 0) {
if (!(capi_create_reader_writer_pipe(data_ifc))) {
free(data_ifc);
ast_free(data_ifc);
return NULL;
}
} else {
@ -298,7 +350,7 @@ struct capi_pvt *capi_mkresourceif(struct ast_channel *c, unsigned long long con
data_ifc->writerfd = -1;
}
data_ifc->bproto = CC_BPROTO_TRANSPARENT;
data_ifc->bproto = (fmt != 0 && data_plci_ifc != 0) ? CC_BPROTO_VOCODER : CC_BPROTO_TRANSPARENT;
data_ifc->doB3 = CAPI_B3_DONT;
data_ifc->smoother = ast_smoother_new(CAPI_MAX_B3_BLOCK_SIZE);
data_ifc->isdnstate |= CAPI_ISDN_STATE_PBX;
@ -315,18 +367,31 @@ struct capi_pvt *capi_mkresourceif(struct ast_channel *c, unsigned long long con
data_ifc->MessageNumber = get_capi_MessageNumber();
cc_mutex_lock(&data_ifc->lock);
#ifdef DIVA_STREAMING
data_ifc->diva_stream_entry = 0;
if (data_plci_ifc == 0) {
capi_DivaStreamingStreamNotUsed(data_ifc, 1, data_ifc->MessageNumber);
} else {
if (pbx_capi_streaming_supported (data_ifc) != 0) {
capi_DivaStreamingOn(data_ifc, 1, data_ifc->MessageNumber);
}
}
#endif
capi_sendf(data_ifc,
1,
CAPI_MANUFACTURER_REQ,
controller,
data_ifc->MessageNumber,
"dw(wbb(www()()()()))",
"dw(wbb(wwws()()()))",
_DI_MANU_ID,
_DI_ASSIGN_PLCI,
(data_plci_ifc == 0) ? 4 : 5, /* data */
(data_plci_ifc == 0) ? 0 : (unsigned char)(data_plci_ifc->PLCI >> 8), /* bchannel */
1, /* connect */
1, 1, 0);
(data_ifc->bproto == CC_BPROTO_VOCODER) ? 0x1f : 1, 1, 0,
diva_get_b1_conf(data_ifc));
cc_mutex_unlock(&data_ifc->lock);
if (data_plci_ifc != 0) {
@ -529,7 +594,11 @@ MESSAGE_EXCHANGE_ERROR capidev_check_wait_get_cmsg(_cmsg *CMSG)
struct timeval tv;
tv.tv_sec = 0;
#ifdef DIVA_STREAMING
tv.tv_usec = 5000;
#else
tv.tv_usec = 500000;
#endif
Info = capi20_waitformessage(capi_ApplID, &tv);
@ -906,6 +975,8 @@ char *capi_info_string(unsigned int info)
return "No call suspended";
case 0x34D6:
return "Call having the requested call identity has been cleared";
case 0x34D7:
return "User not a member of CUG";
case 0x34D8:
return "Incompatible destination";
case 0x34DB:
@ -1339,6 +1410,7 @@ int capi_write_frame(struct capi_pvt *i, struct ast_frame *f)
struct ast_frame *fsmooth;
int txavg=0;
int ret = 0;
int B3Blocks = 1;
if (unlikely(!i)) {
cc_log(LOG_ERROR, "channel has no interface\n");
@ -1395,24 +1467,49 @@ int capi_write_frame(struct capi_pvt *i, struct ast_frame *f)
}
return capi_write_rtp(i, f);
}
if (unlikely(i->B3count >= CAPI_MAX_B3_BLOCKS)) {
cc_verbose(3, 1, VERBOSE_PREFIX_4 "%s: B3count is full, dropping packet.\n",
i->vname);
return 0;
}
if (i->bproto == CC_BPROTO_VOCODER) {
buf = &(i->send_buffer[(i->send_buffer_handle % CAPI_MAX_B3_BLOCKS) *
(CAPI_MAX_B3_BLOCK_SIZE + AST_FRIENDLY_OFFSET)]);
i->send_buffer_handle++;
if (i->bproto == CC_BPROTO_VOCODER || (i->line_plci != 0 && i->line_plci->bproto == CC_BPROTO_VOCODER)) {
#ifdef DIVA_STREAMING
capi_DivaStreamLock();
if (i->diva_stream_entry != 0) {
int written = 0, ready = 0;
memcpy (buf, f->FRAME_DATA_PTR, f->datalen);
B3Blocks = 0;
if ((ready = (i->diva_stream_entry->diva_stream_state == DivaStreamActive)) &&
(i->diva_stream_entry->diva_stream->get_tx_free (i->diva_stream_entry->diva_stream) > 2*CAPI_MAX_B3_BLOCK_SIZE+128)) {
written = i->diva_stream_entry->diva_stream->write (i->diva_stream_entry->diva_stream, 8U << 8 | DIVA_STREAM_MESSAGE_TX_IDI_REQUEST, f->FRAME_DATA_PTR, f->datalen);
i->diva_stream_entry->diva_stream->flush_stream(i->diva_stream_entry->diva_stream);
}
capi_DivaStreamUnLock ();
error = capi_sendf(NULL, 0, CAPI_DATA_B3_REQ, i->NCCI, get_capi_MessageNumber(),
"dwww", buf, f->datalen, i->send_buffer_handle, 0);
error = written != f->datalen;
if (unlikely(error != 0)) {
cc_verbose(3, 1, VERBOSE_PREFIX_4 "%s: stream is %s, dropping packet.\n", i->vname, (ready != 0) ? "full" : "not ready");
}
} else
#endif
{
#ifdef DIVA_STREAMING
capi_DivaStreamUnLock ();
#endif
buf = &(i->send_buffer[(i->send_buffer_handle % CAPI_MAX_B3_BLOCKS) *
(CAPI_MAX_B3_BLOCK_SIZE + AST_FRIENDLY_OFFSET)]);
i->send_buffer_handle++;
memcpy (buf, f->FRAME_DATA_PTR, f->datalen);
error = capi_sendf(NULL, 0, CAPI_DATA_B3_REQ, i->NCCI, get_capi_MessageNumber(),
"dwww", buf, f->datalen, i->send_buffer_handle, 0);
}
if (likely(error == 0)) {
cc_mutex_lock(&i->lock);
i->B3count++;
i->B3count += B3Blocks;
i->B3q -= f->datalen;
if (i->B3q < 0)
i->B3q = 0;
@ -1460,10 +1557,31 @@ int capi_write_frame(struct capi_pvt *i, struct ast_frame *f)
}
}
error = 1;
error = 1;
if (i->B3q > 0) {
error = capi_sendf(NULL, 0, CAPI_DATA_B3_REQ, i->NCCI, get_capi_MessageNumber(),
"dwww", buf, fsmooth->datalen, i->send_buffer_handle, 0);
#if defined(DIVA_STREAMING)
if (i->diva_stream_entry != 0) {
int written = 0, ready = 0;
B3Blocks = 0;
capi_DivaStreamLock();
if ((ready = (i->diva_stream_entry->diva_stream_state == DivaStreamActive)) &&
(i->diva_stream_entry->diva_stream->get_tx_free (i->diva_stream_entry->diva_stream) > 2*CAPI_MAX_B3_BLOCK_SIZE+128)) {
written = i->diva_stream_entry->diva_stream->write (i->diva_stream_entry->diva_stream, 8U << 8 | DIVA_STREAM_MESSAGE_TX_IDI_REQUEST, buf, fsmooth->datalen);
i->diva_stream_entry->diva_stream->flush_stream(i->diva_stream_entry->diva_stream);
}
capi_DivaStreamUnLock ();
error = written != fsmooth->datalen;
if (unlikely(error != 0)) {
cc_verbose(3, 1, VERBOSE_PREFIX_4 "%s: stream is %s, dropping packet.\n", i->vname, (ready != 0) ? "full" : "not ready");
}
} else
#endif
{
error = capi_sendf(NULL, 0, CAPI_DATA_B3_REQ, i->NCCI, get_capi_MessageNumber(),
"dwww", buf, fsmooth->datalen, i->send_buffer_handle, 0);
}
} else {
cc_verbose(3, 1, VERBOSE_PREFIX_4 "%s: too much voice to send for NCCI=%#x\n",
i->vname, i->NCCI);
@ -1471,7 +1589,7 @@ int capi_write_frame(struct capi_pvt *i, struct ast_frame *f)
if (likely(!error)) {
cc_mutex_lock(&i->lock);
i->B3count++;
i->B3count += B3Blocks;
i->B3q -= fsmooth->datalen;
if (i->B3q < 0)
i->B3q = 0;
@ -1481,3 +1599,97 @@ int capi_write_frame(struct capi_pvt *i, struct ast_frame *f)
return ret;
}
/*
ast_channel_lock(chan) to be held while
while accessing returned pointer
*/
const char* pbx_capi_get_cid(const struct ast_channel* c, const char* notAvailableVisual)
{
const char* cid;
#ifdef CC_AST_HAS_VERSION_1_8
cid = S_COR(c->caller.id.number.valid, c->caller.id.number.str, notAvailableVisual);
#else
cid = c->cid.cid_num;
#endif
return (cid);
}
/*
ast_channel_lock(chan) to be held while
while accessing returned pointer
*/
const char* pbx_capi_get_callername(const struct ast_channel* c, const char* notAvailableVisual)
{
const char* name;
#ifdef CC_AST_HAS_VERSION_1_8
name = S_COR(c->caller.id.name.valid, c->caller.id.name.str, notAvailableVisual);
#else
name = (c->cid.cid_name) ? c->cid.cid_name : notAvailableVisual;
#endif
return (name);
}
/*
ast_channel_lock(chan) to be held while
while accessing returned pointer
*/
const char* pbx_capi_get_connectedname(const struct ast_channel* c, const char* notAvailableVisual)
{
const char* name;
#ifdef CC_AST_HAS_VERSION_1_8
name = S_COR(c->connected.id.name.valid, c->connected.id.name.str, notAvailableVisual);
#else
name = (c->cid.cid_name) ? c->cid.cid_name : notAvailableVisual;
#endif
return (name);
}
const struct capi_pvt *pbx_capi_get_nulliflist(void)
{
return nulliflist;
}
void pbx_capi_nulliflist_lock(void)
{
cc_mutex_lock(&nullif_lock);
}
void pbx_capi_nulliflist_unlock(void)
{
cc_mutex_unlock(&nullif_lock);
}
/*!
\brief get list of controllers. Stop parsing
after non digit detected after separator
character or end of string is reached
*/
char* pbx_capi_strsep_controller_list (char** param)
{
char *src, *p;
if ((param == NULL) || (*param == NULL) || (**param == 0))
return NULL;
if (strchr(*param, '|') != NULL)
return (strsep(param, "|"));
src = *param;
p = src - 1;
do {
p = strchr(p+1, ',');
} while ((p != NULL) && (isdigit(p[1]) != 0));
if (p != NULL)
*p++ = 0;
*param = p;
return src;
}

View File

@ -54,11 +54,15 @@ extern int cc_add_peer_link_id(struct ast_channel *c);
extern struct ast_channel *cc_get_peer_link_id(const char *p);
extern void capi_remove_nullif(struct capi_pvt *i);
extern struct capi_pvt *capi_mknullif(struct ast_channel *c, unsigned long long controllermask);
struct capi_pvt *capi_mkresourceif(struct ast_channel *c, unsigned long long controllermask, struct capi_pvt *data_plci_ifc);
struct capi_pvt *capi_mkresourceif(struct ast_channel *c, unsigned long long controllermask, struct capi_pvt *data_plci_ifc, cc_format_t codecs, int all);
extern int capi_create_reader_writer_pipe(struct capi_pvt *i);
extern struct ast_frame *capi_read_pipeframe(struct capi_pvt *i);
extern int capi_write_frame(struct capi_pvt *i, struct ast_frame *f);
extern int capi_verify_resource_plci(const struct capi_pvt *i);
extern const char* pbx_capi_get_cid (const struct ast_channel* c, const char *notAvailableVisual);
extern const char* pbx_capi_get_callername (const struct ast_channel* c, const char *notAvailableVisual);
const char* pbx_capi_get_connectedname (const struct ast_channel* c, const char *notAvailableVisual);
char* pbx_capi_strsep_controller_list (char** param);
#define capi_number(data, strip) \
capi_number_func(data, strip, alloca(AST_MAX_EXTENSION))
@ -77,4 +81,17 @@ extern MESSAGE_EXCHANGE_ERROR capi_sendf(
struct capi_pvt *capii, int waitconf,
_cword command, _cdword Id, _cword Number, char * format, ...);
/*!
\brief nulliflist
*/
const struct capi_pvt *pbx_capi_get_nulliflist(void);
/*!
\brief cc_mutex_lock(&nullif_lock)
*/
void pbx_capi_nulliflist_lock(void);
/*!
\brief cc_mutex_unlock(&nullif_lock)
*/
void pbx_capi_nulliflist_unlock(void);
#endif

View File

@ -50,8 +50,16 @@ echo "#define CHAN_CAPI_CONFIG_H" >>$CONFIGFILE
echo >>$CONFIGFILE
case "$AVERSIONNUM" in
108*)
echo "#define CC_AST_HAS_VERSION_1_6" >>$CONFIGFILE
echo "#define CC_AST_HAS_VERSION_1_8" >>$CONFIGFILE
echo "#define CC_AST_HAS_EVENT_MWI" >>$CONFIGFILE
echo " * found Asterisk version 1.8"
VER=1_8
;;
106*)
echo "#define CC_AST_HAS_VERSION_1_6" >>$CONFIGFILE
echo "#define CC_AST_HAS_EVENT_MWI" >>$CONFIGFILE
echo " * found Asterisk version 1.6"
VER=1_6
;;
@ -235,6 +243,15 @@ check_version_onesix()
echo "#undef CC_AST_HAS_RTP_ENGINE_H" >>$CONFIGFILE
echo " * no rtp_engine.h"
fi
if [ -f $INCLUDEDIR/netsock2.h ]; then
if grep -q "struct ast_sockaddr " $INCLUDEDIR/netsock2.h; then
echo "#define CC_AST_HAS_AST_SOCKADDR" >>$CONFIGFILE
echo " * found ast_sockaddr structure"
else
echo "#undef CC_AST_HAS_AST_SOCKADDR" >>$CONFIGFILE
echo " * no ast_sockaddr structure"
fi
fi
}
case $VER in
@ -250,6 +267,10 @@ case $VER in
echo "Using Asterisk 1.6 API"
check_version_onesix
;;
1_8)
echo "Using Asterisk 1.8 API"
check_version_onesix
;;
*)
echo >&2 "Asterisk version invalid."
exit 1

675
divastatus/divastatus.c Normal file
View File

@ -0,0 +1,675 @@
/*
*
Copyright (c) Dialogic(R), 2010
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*! \file
* \brief Implements to access Diva management file system
*
* \par Access to Diva hardware state
* divalogd captures information from Diva management and exports
* it CVS file format.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include "divastreaming/platform.h"
#include "chan_capi_platform.h"
#include "chan_capi20.h"
#include "chan_capi.h"
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "dlist.h"
#include "divastatus_parameters.h"
#include "divastatus_ifc.h"
#include "divastatus.h"
#ifdef CC_USE_INOTIFY
#include <fcntl.h>
#include <sys/inotify.h>
#endif
typedef const char* pcchar;
static pcchar DIVA_STATUS_PATH = "/usr/lib/eicon/divas/registry/ifc";
static pcchar DIVA_STATUS_FILE = "ifcstate";
static pcchar DIVA_INFO_FILE = "info";
static pcchar DIVA_CONFIG_FILE = "info/Config";
static pcchar DIVA_SERIAL_FILE = "serial";
static pcchar DIVA_READ_ALARM_FILE = "info/Red Alarm";
static pcchar DIVA_YELLOW_ALARM_FILE = "info/Yellow Alarm";
static pcchar DIVA_BLUE_ALARM_FILE = "info/Blue Alarm";
/*
LOCALS
*/
struct _diva_status_ifc;
static int diva_status_active(void);
static int diva_status_get_controller_state(int controller, diva_status_ifc_state_t *state);
static char* diva_status_read_file(unsigned int controller, const char* fileName);
static void diva_status_create_wd(int* wd, int controller, const char* fileName, int isDir);
static diva_status_interface_state_t diva_status_get_interface_state_from_idi_state (const diva_status_ifc_state_t* state);
static diva_status_hardware_state_t diva_status_get_hw_state_from_idi_state (const diva_status_ifc_state_t* state);
static int diva_status_map_CAPI2XDI(int capiController);
static void diva_status_process_event(struct _diva_status_ifc *controllerState, int initialStateIndex, int newStateIndex);
#ifdef CC_USE_INOTIFY
static pcchar DIVA_DIVA_FS_PATH = "/usr/lib/eicon/divas/registry/ifc";
static void diva_status_cleanup_wd(int wd);
static int divaFsWd = -1; /*! \brief Diva fs state */
#endif
#ifdef CC_AST_HAS_VERSION_1_6
static
#endif
char diva_status_ifc_state_usage[] =
"Usage: " CC_MESSAGE_NAME " ifcstate\n"
" Show info about interfaces.\n";
static int inotifyFd = -1; /*! \brief inotify descriptor */
static diva_entity_queue_t controller_q; /*! \brief Active controllers. \note List changed only while CAPI thread is not running */
typedef struct _diva_status_ifc {
diva_entity_link_t link;
int capiController;
int idiController;
diva_status_ifc_state_t state[2];
int currentState;
int ifstateWd;
int infoWd;
diva_status_changed_cb_proc_t status_changed_notify_proc; /*! \brief Notify about interface state change */
diva_hwstatus_changed_cb_proc_t hw_status_changed_notify_proc; /*! \brief Notify about hardware state change */
time_t changeTime; /*! \brief Time interface state changed */
time_t unavailableChangeTime; /*! \brief Time interface state changed to unavailable */
time_t hwChangeTime; /*! \brief Time hardware state changed */
time_t unavailableHwChangeTime; /*! \brief Time hardware state changed to unavailable */
} diva_status_ifc_t;
diva_status_interface_state_t diva_status_init_interface(int controller,
diva_status_hardware_state_t* hwState,
diva_status_changed_cb_proc_t fn,
diva_hwstatus_changed_cb_proc_t hwfn)
{
int idiController = diva_status_map_CAPI2XDI(controller);
diva_status_ifc_t* controllerState = idiController > 0 ? (ast_malloc(sizeof(*controllerState))) : 0;
diva_status_interface_state_t ret = DivaStatusInterfaceStateNotAvailable;
if (controllerState != 0) {
controllerState->capiController = controller;
controllerState->idiController = idiController;
controllerState->status_changed_notify_proc = fn;
controllerState->hw_status_changed_notify_proc = hwfn;
controllerState->ifstateWd = -1;
controllerState->infoWd = -1;
diva_status_create_wd(&controllerState->ifstateWd, idiController, DIVA_STATUS_FILE, 0);
diva_status_create_wd(&controllerState->infoWd, idiController, DIVA_INFO_FILE, 1);
controllerState->currentState = 0;
controllerState->changeTime = time(NULL);
diva_status_get_controller_state(idiController, &controllerState->state[controllerState->currentState]);
diva_q_add_tail(&controller_q, &controllerState->link);
ret = diva_status_get_interface_state_from_idi_state(&controllerState->state[controllerState->currentState]);
*hwState = diva_status_get_hw_state_from_idi_state(&controllerState->state[controllerState->currentState]);
}
return ret;
}
void diva_status_cleanup_interface (int controller)
{
diva_entity_link_t* link;
for (link = diva_q_get_head(&controller_q); link != 0; link = diva_q_get_next(link)) {
diva_status_ifc_t *controllerState = DIVAS_CONTAINING_RECORD(link, diva_status_ifc_t, link);
if (controllerState->capiController == controller) {
diva_q_remove(&controller_q, link);
#ifdef CC_USE_INOTIFY
if (controllerState->ifstateWd >= 0)
inotify_rm_watch(inotifyFd, controllerState->ifstateWd);
if (controllerState->infoWd >= 0)
inotify_rm_watch(inotifyFd, controllerState->infoWd);
#endif
ast_free (controllerState);
break;
}
}
#ifdef CC_USE_INOTIFY
if (diva_q_get_head(&controller_q) == 0) {
if (divaFsWd >= 0) {
inotify_rm_watch(inotifyFd, divaFsWd);
divaFsWd = -1;
}
if (inotifyFd >= 0) {
close(inotifyFd);
inotifyFd = -1;
}
}
#endif
}
int diva_status_get_waitable_object(void)
{
return inotifyFd;
}
void diva_status_process_events(void)
{
diva_entity_link_t* link;
/*
Polling
*/
for (link = diva_q_get_head(&controller_q); link != 0; link = diva_q_get_next(link)) {
diva_status_ifc_t *controllerState = DIVAS_CONTAINING_RECORD(link, diva_status_ifc_t, link);
if ((controllerState->ifstateWd < 0) || (controllerState->infoWd < 0)) {
int currentState = controllerState->currentState;
diva_status_create_wd(&controllerState->ifstateWd, controllerState->idiController, DIVA_STATUS_FILE, 0);
diva_status_create_wd(&controllerState->infoWd, controllerState->idiController, DIVA_INFO_FILE, 1);
controllerState->currentState = (controllerState->currentState + 1) % 2;
diva_status_get_controller_state(controllerState->idiController, &controllerState->state[controllerState->currentState]);
diva_status_process_event(controllerState, currentState, controllerState->currentState);
}
}
/*
Events
*/
#ifdef CC_USE_INOTIFY
if (inotifyFd >= 0 && divaFsWd >= 0) {
unsigned char buffer[1024];
int length;
int i;
while ((length = read(inotifyFd, buffer, sizeof(buffer))) > 0) {
i = 0;
while (i < length) {
struct inotify_event *event = (struct inotify_event*)&buffer[i];
if ((event->mask & (IN_IGNORED|IN_DELETE_SELF|IN_UNMOUNT|IN_Q_OVERFLOW)) != 0) {
diva_status_cleanup_wd((event->mask & IN_IGNORED) == 0 ? event->wd : -1);
break;
}
if (event->wd != divaFsWd) {
for (link = diva_q_get_head(&controller_q); link != 0; link = diva_q_get_next(link)) {
diva_status_ifc_t *controllerState = DIVAS_CONTAINING_RECORD(link, diva_status_ifc_t, link);
if ((controllerState->ifstateWd == event->wd) || (controllerState->infoWd == event->wd)) {
int currentState = controllerState->currentState;
controllerState->currentState = (controllerState->currentState + 1) % 2;
diva_status_get_controller_state(controllerState->idiController, &controllerState->state[controllerState->currentState]);
diva_status_process_event(controllerState, currentState, controllerState->currentState);
}
}
}
i += sizeof(*event) + event->len;
}
}
}
#endif
}
#ifdef CC_USE_INOTIFY
static void diva_status_cleanup_wd(int wd)
{
diva_entity_link_t* link;
for (link = diva_q_get_head(&controller_q); link != 0; link = diva_q_get_next(link)) {
diva_status_ifc_t *controllerState = DIVAS_CONTAINING_RECORD(link, diva_status_ifc_t, link);
if ((controllerState->ifstateWd >= 0) && (wd != controllerState->ifstateWd)) {
inotify_rm_watch(inotifyFd, controllerState->ifstateWd);
}
controllerState->ifstateWd = -1;
if ((controllerState->infoWd >= 0) && (wd != controllerState->infoWd)) {
inotify_rm_watch(inotifyFd, controllerState->infoWd);
}
controllerState->infoWd = -1;
}
if ((divaFsWd >= 0) && (wd != divaFsWd)) {
inotify_rm_watch(inotifyFd, divaFsWd);
}
divaFsWd = -1;
}
#endif
static void diva_status_process_event(diva_status_ifc_t *controllerState, int initialStateIndex, int newStateIndex)
{
diva_status_ifc_state_t* initialState = &controllerState->state[initialStateIndex];
diva_status_ifc_state_t* newState = &controllerState->state[newStateIndex];
diva_status_interface_state_t initialIfcState = diva_status_get_interface_state_from_idi_state (initialState);
diva_status_interface_state_t newIfcState = diva_status_get_interface_state_from_idi_state (newState);
diva_status_hardware_state_t initalHwState = diva_status_get_hw_state_from_idi_state(initialState);
diva_status_hardware_state_t newHwState = diva_status_get_hw_state_from_idi_state(newState);
time_t t = time(NULL);
if (initialIfcState != newIfcState) {
controllerState->changeTime = t;
if (newIfcState == DivaStatusInterfaceStateERROR)
controllerState->unavailableChangeTime = t;
controllerState->status_changed_notify_proc(controllerState->capiController, newIfcState);
}
if (initalHwState != newHwState) {
controllerState->hwChangeTime = t;
if (newHwState == DivaStatusHardwareStateERROR)
controllerState->unavailableHwChangeTime = t;
controllerState->hw_status_changed_notify_proc(controllerState->capiController, newHwState);
}
}
static void diva_status_create_wd(int* wd, int controller, const char* fileName, int isDir)
{
#ifdef CC_USE_INOTIFY
if (inotifyFd < 0) {
inotifyFd = inotify_init();
if (inotifyFd >= 0)
fcntl(inotifyFd, F_SETFL, O_NONBLOCK);
}
if (inotifyFd >= 0 && divaFsWd < 0) {
divaFsWd = inotify_add_watch (inotifyFd, DIVA_DIVA_FS_PATH, IN_DELETE_SELF | IN_UNMOUNT | IN_IGNORED);
}
if (*wd >= 0)
return;
if (inotifyFd >= 0 && divaFsWd >= 0) {
int name_len = strlen(DIVA_STATUS_PATH) + strlen(fileName) + 32;
char name[name_len];
snprintf(name, name_len, "%s/adapter%u/%s", DIVA_STATUS_PATH, controller, fileName);
name[name_len-1] = 0;
*wd = inotify_add_watch (inotifyFd, name,
IN_CLOSE_WRITE | IN_DELETE_SELF | IN_IGNORED | ((isDir != 0) ? IN_DELETE : 0));
return;
}
#else
*wd = -1;
#endif
}
/*!
\brief Check divalogd is available
*/
static int diva_status_active(void)
{
struct stat v;
return ((stat(DIVA_STATUS_PATH, &v) == 0 && S_ISDIR(v.st_mode) != 0) ? 0 : -1);
}
static char* diva_status_read_file(unsigned int controller, const char* fileName)
{
int name_len = strlen(DIVA_STATUS_PATH) + strlen(fileName) + 32;
char name[name_len];
struct stat v;
int fd;
int length;
char *data, *p;
snprintf(name, name_len, "%s/adapter%u/%s", DIVA_STATUS_PATH, controller, fileName);
name[name_len-1] = 0;
fd = open(name, O_RDONLY);
if (fd < 0)
return 0;
if (fstat(fd, &v) != 0 || v.st_size == 0) {
close(fd);
return 0;
}
length = MIN(v.st_size, 16U*1024U);
data = ast_malloc(length+1);
if (data == 0) {
close (fd);
return 0;
}
if (read(fd, data, length) != length) {
ast_free(data);
close(fd);
return (0);
}
close (fd);
data[length] = 0;
while (((p = strchr(data, '\n')) != 0) || ((p = strchr(data, '\r')))) {
*p = 0;
}
return (data);
}
static int diva_status_get_controller_state(int controller, diva_status_ifc_state_t *state)
{
char *data, *p;
int i, pri;
const char* v;
memset (state, 0x00, sizeof(*state));
state->ifcType = DivaStatusIfcNotPri;
state->hwState = DivaStatusHwStateUnknown;
state->ifcL1State = DivaStatusIfcL2DoNotApply;
state->ifcL2State = DivaStatusIfcL2DoNotApply;
if (diva_status_active() != 0)
return -1;
if ((data = diva_status_read_file(controller, DIVA_CONFIG_FILE)) == 0)
return -1;
for (i = 0, pri = 0, p = data, v = strsep(&p, ",");
v != 0 && i < DivaStateIfcConfig_Max;
v = strsep(&p, ","), i++) {
if (v[0] == '\'' && v[strlen(v)-1] != '\'') {
const char *tmp;
do {
if ((p != 0) && (*p != 0))
p[-1] = ',';
tmp = strsep (&p, ",");
} while ((tmp != 0) && (tmp[strlen(tmp)-1] != '\''));
}
switch ((diva_state_ifc_config_parameters_t)i) {
case DivaStateIfcConfig_TYPE:
pri += (strcmp ("PRI", v) == 0);
break;
case DivaStateIfcConfig_PRI:
pri += (strcmp ("'YES'", v) == 0);
break;
default:
break;
}
}
ast_free(data);
state->ifcType = (pri == 2) ? DivaStatusIfcPri : DivaStatusIfcNotPri;
if ((data = diva_status_read_file(controller, DIVA_STATUS_FILE)) == 0)
return (-1);
for (i = 0, p = data, v = strsep (&p, ","); v != 0 && i < (int)DivaStateIfcState_Max; v = strsep (&p, ","), i++) {
if (v[0] == '\'' && v[strlen(v)-1] != '\'') {
const char *tmp;
do {
if ((p != 0) && (*p != 0))
p[-1] = ',';
tmp = strsep (&p, ",");
} while ((tmp != 0) && (tmp[strlen(tmp)-1] != '\''));
}
switch ((diva_state_ifcstate_parameters_t)i) {
case DivaStateIfcState_LAYER1_STATE:
if (state->ifcType == DivaStatusIfcPri) {
state->ifcL1State = (strcmp ("'Activated'", v) == 0) ? DivaStatusIfcL1OK : DivaStatusIfcL1Error;
}
break;
case DivaStateIfcState_LAYER2_STATE:
if (state->ifcType == DivaStatusIfcPri) {
state->ifcL2State = (strcmp ("'Layer2 UP'", v) == 0) ? DivaStatusIfcL2OK : DivaStatusIfcL2Error;
}
break;
case DivaStateIfcState_D1_X_FRAMES:
state->ifcTxDStatistics.Frames = (unsigned int)atol(v);
break;
case DivaStateIfcState_D1_X_BYTES:
state->ifcTxDStatistics.Bytes = (unsigned int)atol(v);
break;
case DivaStateIfcState_D1_X_ERRORS:
state->ifcTxDStatistics.Errors = (unsigned int)atol(v);
break;
case DivaStateIfcState_D1_R_FRAMES:
state->ifcRxDStatistics.Frames = (unsigned int)atol(v);
break;
case DivaStateIfcState_D1_R_BYTES:
state->ifcRxDStatistics.Bytes = (unsigned int)atol(v);
break;
case DivaStateIfcState_D1_R_ERRORS:
state->ifcRxDStatistics.Errors = (unsigned int)atol(v);
break;
case DivaStateIfcState_MAX_TEMPERATURE:
state->maxTemperature = (unsigned int)atoi(v);
break;
case DivaStateIfcState_TEMPERATURE:
state->currentTemperature = (unsigned int)atoi(v);
break;
case DivaStateIfcState_HARDWARE_STATE:
if (strcmp("'Active'", v) == 0)
state->hwState = DivaStateHwStateActive;
else if (strcmp("'Inactive'", v) == 0)
state->hwState = DivaStateHwStateInactive;
break;
default:
break;
}
}
ast_free (data);
if ((data = diva_status_read_file(controller, DIVA_READ_ALARM_FILE)) != 0) {
state->ifcAlarms.Red = strcmp("TRUE", data) == 0;
ast_free(data);
}
if ((data = diva_status_read_file(controller, DIVA_YELLOW_ALARM_FILE)) != 0) {
state->ifcAlarms.Yellow = strcmp("TRUE", data) == 0;
ast_free(data);
}
if ((data = diva_status_read_file(controller, DIVA_BLUE_ALARM_FILE)) != 0) {
state->ifcAlarms.Blue = strcmp("TRUE", data) == 0;
ast_free(data);
}
if ((data = diva_status_read_file(controller, DIVA_SERIAL_FILE)) != 0) {
state->serialNumber = (unsigned int)(atol(data)) & 0x00ffffff;
ast_free(data);
}
return (0);
}
/*
chan_capi interface
*/
diva_status_interface_state_t diva_status_get_interface_state(int controller)
{
diva_status_ifc_state_t state;
int ret;
ret = diva_status_get_controller_state(controller, &state);
if ((ret != 0) ||
(state.ifcType != DivaStatusIfcPri) ||
(state.ifcL1State == DivaStatusIfcL2DoNotApply) ||
(state.hwState == DivaStatusHwStateUnknown)) {
return (DivaStatusInterfaceStateNotAvailable);
}
if ((state.ifcAlarms.Red == 0) &&
(state.ifcAlarms.Yellow == 0) &&
(state.ifcAlarms.Blue == 0) &&
(state.hwState == DivaStateHwStateActive) &&
(state.ifcL1State == DivaStatusIfcL1OK)) {
return DivaStatusInterfaceStateOK;
}
return DivaStatusInterfaceStateERROR;
}
static diva_status_interface_state_t diva_status_get_interface_state_from_idi_state(const diva_status_ifc_state_t* state)
{
if ((state->ifcType != DivaStatusIfcPri) ||
(state->ifcL1State == DivaStatusIfcL2DoNotApply) ||
(state->hwState == DivaStatusHwStateUnknown)) {
return (DivaStatusInterfaceStateNotAvailable);
}
if ((state->ifcAlarms.Red == 0) &&
(state->ifcAlarms.Yellow == 0) &&
(state->ifcAlarms.Blue == 0) &&
(state->hwState == DivaStateHwStateActive) &&
(state->ifcL1State == DivaStatusIfcL1OK)) {
return DivaStatusInterfaceStateOK;
}
return DivaStatusInterfaceStateERROR;
}
static diva_status_hardware_state_t diva_status_get_hw_state_from_idi_state(const diva_status_ifc_state_t* state)
{
switch(state->hwState) {
case DivaStateHwStateActive:
return (DivaStatusHardwareStateOK);
case DivaStateHwStateInactive:
return (DivaStatusHardwareStateERROR);
case DivaStatusHwStateUnknown:
default:
return (DivaStatusHardwareStateUnknown);
}
}
/*!
\brief Map CAPI controller to Diva hardware
\note In most cases chan_capi uses 1:1 mappimg
between CAPI controller and Diva hardware
\todo Read CAPI2DIva mapping table from CAPI
*/
static int diva_status_map_CAPI2XDI(int capiController)
{
return ((capiController > 0) ? capiController : -1);
}
int diva_status_available(void)
{
return (diva_status_active());
}
const char* diva_status_interface_state_name(diva_status_interface_state_t state)
{
switch(state) {
case DivaStatusInterfaceStateOK:
return "active";
case DivaStatusInterfaceStateERROR:
return "inactive";
case DivaStatusInterfaceStateNotAvailable:
default:
return "unknown";
}
}
const char* diva_status_hw_state_name(diva_status_hardware_state_t hwState)
{
switch(hwState) {
case DivaStatusHardwareStateOK:
return "active";
case DivaStatusHardwareStateERROR:
return "not running";
case DivaStatusHardwareStateUnknown:
default:
return "unknown";
}
}
#ifdef CC_AST_HAS_VERSION_1_6
char *pbxcli_capi_ifc_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#else
int pbxcli_capi_ifc_status(int fd, int argc, char *argv[])
#endif
{
diva_entity_link_t* link;
#ifdef CC_AST_HAS_VERSION_1_6
int fd = a->fd;
if (cmd == CLI_INIT) {
e->command = CC_MESSAGE_NAME " ifcstate";
e->usage = diva_status_ifc_state_usage;
return NULL;
} else if (cmd == CLI_GENERATE)
return NULL;
if (a->argc != e->args)
return CLI_SHOWUSAGE;
#else
if (argc != 2)
return RESULT_SHOWUSAGE;
#endif
if ( diva_q_get_head(&controller_q) == NULL) {
ast_cli(fd, "There are no interraces in " CC_MESSAGE_NAME " instance.\n");
return RESULT_SUCCESS;
}
ast_cli(fd, CC_MESSAGE_NAME " interfaces\n");
ast_cli(fd, "%s %-9s%-4s%-4s%-4s%-7s%-5s%8s%12s%12s%12s%12s\n",
"INTERFACE", "State", "L1", "L2", "RED", "YELLOW", "BLUE", "D-Rx-Frames", "D-Rx-Bytes","D-Tx-Frames", "D-Tx-Bytes", "D-Errors");
for (link = diva_q_get_head(&controller_q); link != 0; link = diva_q_get_next(link)) {
diva_status_ifc_t *controllerState = DIVAS_CONTAINING_RECORD(link, diva_status_ifc_t, link);
diva_status_ifc_state_t* state = &controllerState->state[controllerState->currentState];
ast_cli(fd, "ISDN%-3d%-2s %-9s%-4s%-4s%-4s%-7s%-3s %12d %11d %11d %11d %11d\n",
controllerState->capiController, "",
diva_status_interface_state_name(diva_status_get_interface_state_from_idi_state (state)),
((state->ifcType == DivaStatusIfcPri) && (state->hwState == DivaStatusHardwareStateOK)) ?
(state->ifcL1State == DivaStatusIfcL1OK ? "On" : "Off") : "-",
((state->ifcType == DivaStatusIfcPri) && (state->hwState == DivaStatusHardwareStateOK)) ?
(state->ifcL2State == DivaStatusIfcL2OK ? "On" : "Off") : "-",
((state->ifcType == DivaStatusIfcPri) && (state->hwState == DivaStatusHardwareStateOK)) ?
(state->ifcAlarms.Red != 0 ? "On" : "Off") : "-",
((state->ifcType == DivaStatusIfcPri) && (state->hwState == DivaStatusHardwareStateOK)) ?
(state->ifcAlarms.Yellow != 0 ? "On" : "Off") : "-",
((state->ifcType == DivaStatusIfcPri) && (state->hwState == DivaStatusHardwareStateOK)) ?
(state->ifcAlarms.Blue != 0 ? "On" : "Off") : "-",
state->ifcRxDStatistics.Frames, state->ifcRxDStatistics.Bytes,
state->ifcTxDStatistics.Frames, state->ifcTxDStatistics.Bytes,
state->ifcRxDStatistics.Errors + state->ifcTxDStatistics.Errors
);
}
#ifdef CC_AST_HAS_VERSION_1_6
return CLI_SUCCESS;
#else
return RESULT_SUCCESS;
#endif
}

86
divastatus/divastatus.h Normal file
View File

@ -0,0 +1,86 @@
/*
*
Copyright (c) Dialogic(R), 2010
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*! \file
* \brief Declares interface to access diva management file system
*/
#ifndef __DIVA_STATUS_H__
#define __DIVA_STATUS_H__
typedef enum _diva_status_ifc_type {
DivaStatusIfcNotPri = 0,
DivaStatusIfcPri,
DivaStatusIfcBri,
DivaStatusIfcAnalog
} diva_status_ifc_type_t;
typedef struct _diva_status_ifc_alarms {
int Red;
int Blue;
int Yellow;
} diva_status_ifc_alarms_t;
typedef enum _diva_status_ifc_l1_state {
DivaStatusIfcL1DoNotApply = 0,
DivaStatusIfcL1OK,
DivaStatusIfcL1Error
} diva_status_ifc_l1_state_t;
typedef enum _diva_status_ifc_l2_state {
DivaStatusIfcL2DoNotApply = 0,
DivaStatusIfcL2OK,
DivaStatusIfcL2Error
} diva_status_ifc_l2_state_t;
typedef enum _diva_status_ifc_hw_state {
DivaStatusHwStateUnknown = 0,
DivaStateHwStateActive = 1,
DivaStateHwStateInactive = 2
} diva_status_ifc_hw_state_t;
typedef struct _diva_status_ifc_statistics {
unsigned int Frames;
unsigned int Bytes;
unsigned int Errors;
} diva_status_ifc_statistics_t;
typedef struct _diva_status_ifc_state {
diva_status_ifc_type_t ifcType;
diva_status_ifc_hw_state_t hwState;
diva_status_ifc_alarms_t ifcAlarms;
diva_status_ifc_l1_state_t ifcL1State;
diva_status_ifc_l2_state_t ifcL2State;
diva_status_ifc_statistics_t ifcRxDStatistics;
diva_status_ifc_statistics_t ifcTxDStatistics;
unsigned int serialNumber;
unsigned int maxTemperature;
unsigned int currentTemperature;
} diva_status_ifc_state_t;
#define DIVA_STATUS_EVENT_L1 0x00000001U
#define DIVA_STATUS_EVENT_L2 0x00000002U
#define DIVA_STATUS_EVENT_ALARMS 0x00000004U
#define DIVA_STATUS_EVENT_STATISTICS 0x00000008U
#endif

View File

@ -0,0 +1,97 @@
/*
*
Copyright (c) Dialogic(R), 2010
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*! \file
* \brief Interface to chan_capi
*/
#ifndef __DIVA_STATUS_IFC_H__
#define __DIVA_STATUS_IFC_H__
typedef enum _diva_status_interface_state {
DivaStatusInterfaceStateNotAvailable = 0,
DivaStatusInterfaceStateOK = 1,
DivaStatusInterfaceStateERROR = -1,
} diva_status_interface_state_t;
typedef enum _diva_status_hardware_state {
DivaStatusHardwareStateUnknown = 0, /*! /brief divalog is not running or old version of divalog */
DivaStatusHardwareStateOK = 1, /*! /brief hardware status veriefied and OK */
DivaStatusHardwareStateERROR = -1 /*! /brief hardware status verified and not OK */
} diva_status_hardware_state_t;
/*!
\brief Check if Diva interface is available
*/
int diva_status_available(void);
typedef void (*diva_status_changed_cb_proc_t)(int controller, diva_status_interface_state_t state);
typedef void (*diva_hwstatus_changed_cb_proc_t)(int controller, diva_status_hardware_state_t hwstate);
/*!
\brief activate event based status notifications
\param fn called if interface state changes, includes hardware state
\param hwfn called if hardware status changed, hardware state only, used for processing of IP media streams by resource/chat commands
*/
diva_status_interface_state_t diva_status_init_interface(int controller,
diva_status_hardware_state_t* hwState,
diva_status_changed_cb_proc_t fn,
diva_hwstatus_changed_cb_proc_t hwfn);
/*!
\brief deactivate event based status notifications
*/
void diva_status_cleanup_interface(int controller);
/*!
\brief retrieve file handle to be used in async
I/O operations
*/
int diva_status_get_waitable_object(void);
/*!
\brief process status change events
*/
void diva_status_process_events(void);
/*!
\brief Retrieve state of interface
DivaStatusInterfaceStateNotAvailable - ignore state
DivaStatusInterfaceStateOK - interface state verified and OK
DivaStatusInterfaceStateERROR - interface state verified and
can not be used to create calls
*/
diva_status_interface_state_t diva_status_get_interface_state(int controller);
const char* diva_status_interface_state_name(diva_status_interface_state_t state);
const char* diva_status_hw_state_name(diva_status_hardware_state_t hwState);
#ifdef CC_AST_HAS_VERSION_1_6
char *pbxcli_capi_ifc_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
#else
int pbxcli_capi_ifc_status(int fd, int argc, char *argv[]);
#endif
#define CC_CLI_TEXT_IFC_STATUSINFO "Show " CC_MESSAGE_BIGNAME " interface info"
#ifndef CC_AST_HAS_VERSION_1_6
extern char diva_status_ifc_state_usage[];
#endif
#endif

View File

@ -0,0 +1,134 @@
/*
*
Copyright (c) Dialogic(R), 2010
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __DIVA_STATUS_PARAMETERS_H__
#define __DIVA_STATUS_PARAMETERS_H__
/*! \brief ifcstate
*/
typedef enum _diva_state_ifcstate_parameters {
DivaStateIfcState_LAYER1_STATE = 0,
DivaStateIfcState_LAYER2_STATE,
DivaStateIfcState_INC_CALLS,
DivaStateIfcState_INC_CONNECTED,
DivaStateIfcState_INC_USER_BUSY,
DivaStateIfcState_INC_CALL_REJECTED,
DivaStateIfcState_INC_WRONG_NUMBER,
DivaStateIfcState_INC_INCOMPATIBLE_DST,
DivaStateIfcState_INC_OUT_OF_ORDER,
DivaStateIfcState_INC_IGNORED,
DivaStateIfcState_OUT_CALLS,
DivaStateIfcState_OUT_CONNECTED,
DivaStateIfcState_OUT_USER_BUSY,
DivaStateIfcState_OUT_NO_ANSWER,
DivaStateIfcState_OUT_WRONG_NUMBER,
DivaStateIfcState_OUT_CALL_REJECTED,
DivaStateIfcState_OUT_OTHER_FAILURES,
DivaStateIfcState_MDM_DISC_NORMAL,
DivaStateIfcState_MDM_DISC_UNSPECIFIED,
DivaStateIfcState_MDM_DISC_BUSY_TONE,
DivaStateIfcState_MDM_DISC_CONGESTION,
DivaStateIfcState_MDM_DISC_CARR_WAIT,
DivaStateIfcState_MDM_DISC_TRN_TIMEOUT,
DivaStateIfcState_MDM_DISC_INCOMPAT,
DivaStateIfcState_MDM_DISC_FRAME_REJ,
DivaStateIfcState_MDM_DISC_V42BIS,
DivaStateIfcState_FAX_DISC_NORMAL,
DivaStateIfcState_FAX_DISC_NOT_IDENT,
DivaStateIfcState_FAX_DISC_NO_RESPONSE,
DivaStateIfcState_FAX_DISC_RETRIES,
DivaStateIfcState_FAX_DISC_UNEXP_MSG,
DivaStateIfcState_FAX_DISC_NO_POLLING,
DivaStateIfcState_FAX_DISC_TRAINING,
DivaStateIfcState_FAX_DISC_UNEXPECTED,
DivaStateIfcState_FAX_DISC_APPLICATION,
DivaStateIfcState_FAX_DISC_INCOMPAT,
DivaStateIfcState_FAX_DISC_NO_COMMAND,
DivaStateIfcState_FAX_DISC_LONG_MSG,
DivaStateIfcState_FAX_DISC_SUPERVISOR,
DivaStateIfcState_FAX_DISC_SUB_SEP_PWD,
DivaStateIfcState_FAX_DISC_INVALID_MSG,
DivaStateIfcState_FAX_DISC_PAGE_CODING,
DivaStateIfcState_FAX_DISC_APP_TIMEOUT,
DivaStateIfcState_FAX_DISC_UNSPECIFIED,
DivaStateIfcState_B1_X_FRAMES,
DivaStateIfcState_B1_X_BYTES,
DivaStateIfcState_B1_X_ERRORS,
DivaStateIfcState_B1_R_FRAMES,
DivaStateIfcState_B1_R_BYTES,
DivaStateIfcState_B1_R_ERRORS,
DivaStateIfcState_B2_X_FRAMES,
DivaStateIfcState_B2_X_BYTES,
DivaStateIfcState_B2_X_ERRORS,
DivaStateIfcState_B2_R_FRAMES,
DivaStateIfcState_B2_R_BYTES,
DivaStateIfcState_B2_R_ERRORS,
DivaStateIfcState_D1_X_FRAMES,
DivaStateIfcState_D1_X_BYTES,
DivaStateIfcState_D1_X_ERRORS,
DivaStateIfcState_D1_R_FRAMES,
DivaStateIfcState_D1_R_BYTES,
DivaStateIfcState_D1_R_ERRORS,
DivaStateIfcState_D2_X_FRAMES,
DivaStateIfcState_D2_X_BYTES,
DivaStateIfcState_D2_X_ERRORS,
DivaStateIfcState_D2_R_FRAMES,
DivaStateIfcState_D2_R_BYTES,
DivaStateIfcState_D2_R_ERRORS,
DivaStateIfcState_INITIAL_TEMPERATURE,
DivaStateIfcState_MIN_TEMPERATURE,
DivaStateIfcState_MAX_TEMPERATURE,
DivaStateIfcState_TEMPERATURE,
DivaStateIfcState_DSPSTATE,
DivaStateIfcState_FAX_TX_PAGES_TOTAL,
DivaStateIfcState_FAX_TX_PAGES_RETRAIN,
DivaStateIfcState_FAX_TX_PAGES_REJECT,
DivaStateIfcState_FAX_RX_PAGES_TOTAL,
DivaStateIfcState_FAX_RX_PAGES_RETRAIN,
DivaStateIfcState_FAX_RX_PAGES_REJECT,
DivaStateIfcState_OUT_ABANDONED,
DivaStateIfcState_IN_ABANDONED,
DivaStateIfcState_HARDWARE_STATE,
DivaStateIfcState_Max
} diva_state_ifcstate_parameters_t;
typedef enum diva_state_ifc_config_parameters {
DivaStateIfcConfig_TYPE = 0,
DivaStateIfcConfig_CHANNELS,
DivaStateIfcConfig_PROTOCOL,
DivaStateIfcConfig_NT_MODE,
DivaStateIfcConfig_POINTTOPOINT,
DivaStateIfcConfig_INTERFACENR,
DivaStateIfcConfig_BOARDREVISION,
DivaStateIfcConfig_SUBFUNCTION,
DivaStateIfcConfig_SUBDEVICE,
DivaStateIfcConfig_PROTOCOLBUILD,
DivaStateIfcConfig_DSPCODEBUILD,
DivaStateIfcConfig_ANALOGCHANNELS,
DivaStateIfcConfig_PRI,
DivaStateIfcConfig_PCIDMA,
DivaStateIfcConfig_ADAPTERTYPE,
DivaStateIfcConfig_LAW,
DivaStateIfcConfig_Max
} diva_state_ifc_config_parameters_t;
#endif

View File

@ -0,0 +1,431 @@
/*
*
Copyright (c) Dialogic(R), 2010-2011
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*! \file
* \brief Implements to access Diva streaming
*
*/
#include <stdio.h>
#include "chan_capi_platform.h"
#include "chan_capi20.h"
#include "chan_capi.h"
#include "chan_capi_utils.h"
#include "platform.h"
#include "diva_streaming_result.h"
#include "diva_streaming_messages.h"
#include "diva_streaming_vector.h"
#include "diva_streaming_manager.h"
#include "chan_capi_divastreaming_utils.h"
/*
LOCALS
*/
static int diva_streaming_disabled;
AST_MUTEX_DEFINE_STATIC(stream_write_lock);
static diva_entity_queue_t diva_streaming_new; /* protected by stream_write_lock, new streams */
int capi_DivaStreamingSupported (unsigned controller)
{
MESSAGE_EXCHANGE_ERROR error;
int waitcount = 50;
unsigned char manbuf[CAPI_MANUFACTURER_LEN];
_cmsg CMSG;
int ret = 0;
if (capi20_get_manufacturer(controller, manbuf) == NULL) {
goto done;
}
if ((strstr((char *)manbuf, "Eicon") == 0) &&
(strstr((char *)manbuf, "Dialogic") == 0)) {
goto done;
}
error = capi_sendf (NULL, 0, CAPI_MANUFACTURER_REQ, controller, get_capi_MessageNumber(),
"dw(bs)", _DI_MANU_ID, _DI_STREAM_CTRL, 2, "");
if (error)
goto done;
while (waitcount) {
error = capidev_check_wait_get_cmsg(&CMSG);
if (IS_MANUFACTURER_CONF(&CMSG) && (CMSG.ManuID == _DI_MANU_ID) &&
((CMSG.Class & 0xffff) == _DI_STREAM_CTRL)) {
error = (MESSAGE_EXCHANGE_ERROR)(CMSG.Class >> 16);
ret = (error == 0);
break;
}
usleep(30000);
waitcount--;
}
done:
return ret;
}
static int divaStreamingMessageRx (void* user_context, dword message, dword length, const struct _diva_streaming_vector* v, dword nr_v)
{
diva_stream_scheduling_entry_t* pE = (diva_stream_scheduling_entry_t*)user_context;
dword message_type = (message & 0xff);
if (message_type == 0) { /* IDI message */
dword offset = 0;
diva_streaming_vector_t vind[8];
byte Ind = 0;
int vind_nr = 0;
int process_indication;
do {
vind_nr = sizeof(vind)/sizeof(vind[0]);
offset = diva_streaming_get_indication_data (offset, message, length, v, nr_v, &Ind, vind, &vind_nr);
process_indication = (diva_streaming_idi_supported_ind (Ind, vind_nr != 0, vind_nr != 0 ? (byte*)vind->data : (byte*)"") != 0);
if (likely(process_indication != 0)) {
if (likely(Ind == 8)) {
if (likely(pE->i != 0 && pE->i->NCCI != 0)) {
if (pE->i->virtualBridgePeer != 0) {
if (pE->i->bridgePeer != 0) {
struct capi_pvt* bridgePeer = pE->i->bridgePeer;
if (bridgePeer->NCCI != 0 && bridgePeer->diva_stream_entry != 0 &&
bridgePeer->diva_stream_entry->diva_stream_state == DivaStreamActive &&
bridgePeer->diva_stream_entry->diva_stream->get_tx_in_use (bridgePeer->diva_stream_entry->diva_stream) < 512 &&
bridgePeer->diva_stream_entry->diva_stream->get_tx_free (bridgePeer->diva_stream_entry->diva_stream) >
2*CAPI_MAX_B3_BLOCK_SIZE+128) {
dword i = 0, k = 0, b3len;
byte b3buf[CAPI_MAX_B3_BLOCK_SIZE];
b3len = diva_streaming_read_vector_data(vind, vind_nr, &i, &k, b3buf, CAPI_MAX_B3_BLOCK_SIZE);
bridgePeer->diva_stream_entry->diva_stream->write (bridgePeer->diva_stream_entry->diva_stream,
8U << 8 | DIVA_STREAM_MESSAGE_TX_IDI_REQUEST,
b3buf, b3len);
bridgePeer->diva_stream_entry->diva_stream->flush_stream(bridgePeer->diva_stream_entry->diva_stream);
} else {
if (bridgePeer->NCCI != 0 && bridgePeer->diva_stream_entry != 0 &&
bridgePeer->diva_stream_entry->diva_stream_state == DivaStreamActive) {
DBG_ERR(("%s PLCI %04x discarded bridge packet free: %u in use: %u",
pE->i->name, pE->i->PLCI & 0xffffU,
bridgePeer->diva_stream_entry->diva_stream->get_tx_free (bridgePeer->diva_stream_entry->diva_stream),
bridgePeer->diva_stream_entry->diva_stream->get_tx_in_use (bridgePeer->diva_stream_entry->diva_stream)))
}
}
}
} else {
capidev_handle_data_b3_indication_vector (pE->i, vind, vind_nr);
}
}
} else {
dword i = 0, k = 0;
word data_length;
byte ind_data_buffer[2048+512];
data_length = (word)diva_streaming_read_vector_data (vind, vind_nr, &i, &k, ind_data_buffer, sizeof(ind_data_buffer));
DBG_TRC(("Ind: %02x length:%u", Ind, data_length))
}
}
} while (offset != 0);
} else if (message_type == 0xff) { /* System message */
switch ((byte)(message >> 8)) {
case DIVA_STREAM_MESSAGE_INIT: /* Stream active */
if (pE->PLCI == 0 && pE->i != 0) {
pE->PLCI = pE->i->PLCI;
}
cc_verbose(3, 0, VERBOSE_PREFIX_2 "%s: stream active (PLCI=%#x)\n", pE->vname, pE->PLCI);
if (pE->diva_stream_state == DivaStreamCreated) {
pE->diva_stream_state = DivaStreamActive;
} else if (pE->diva_stream_state == DivaStreamCancelSent) {
pE->diva_stream->release_stream(pE->diva_stream);
pE->i = 0;
pE->diva_stream_state = DivaStreamDisconnectSent;
}
break;
case DIVA_STREAM_MESSAGE_RX_TX_ACK: /* Resolved Tx flow control */
/* cc_verbose(4, 1, "%s: stream tx ack (PLCI=%#x)\n", pE->vname, pE->PLCI); */
break;
case DIVA_STREAM_MESSAGE_SYNC_ACK: /* Sync ack request acknowledge */
cc_verbose(4, 1, "%s: stream sync ack (PLCI=%#x, sequence=%08x)\n", pE->vname, pE->PLCI, length);
break;
case DIVA_STREAM_MESSAGE_RELEASE_ACK: /* Release stream acknowledge */
pE->diva_stream_state = DivaStreamDisconnected;
pE->diva_stream = 0;
cc_verbose(3, 0, VERBOSE_PREFIX_2 "%s: stream released (PLCI=%#x)\n", pE->vname, pE->PLCI);
break;
case DIVA_STREAM_MESSAGE_INIT_ERROR: /* Failed to initialize stream */
pE->diva_stream_state = DivaStreamDisconnected;
pE->diva_stream = 0;
cc_verbose(3, 0, VERBOSE_PREFIX_2 "%s: stream init error (PLCI=%#x, error=%d)\n", pE->vname, pE->PLCI, length);
break;
default:
cc_verbose(3, 0, VERBOSE_PREFIX_2 "%s: stream unknown system message (PLCI=%#x, message=%08x)\n", pE->vname, pE->PLCI, message);
break;
}
} else {
cc_verbose(3, 0, VERBOSE_PREFIX_2 "%s: unknown stream message (PLCI=%#x, message=%08x)\n", pE->vname, pE->PLCI, message);
}
return (0);
}
/*
* Create Diva stream
*
*/
void capi_DivaStreamingOn(struct capi_pvt *i, byte streamCommand, _cword messageNumber)
{
diva_stream_scheduling_entry_t* pE;
int ret;
char trace_ident[8];
unsigned int effectivePLCI;
if (diva_streaming_disabled)
return;
pE = ast_malloc (sizeof(*pE));
if (pE == 0)
return;
snprintf (trace_ident, sizeof(trace_ident), "C%02x", (byte)i->PLCI);
trace_ident[sizeof(trace_ident)-1] = 0;
cc_mutex_lock(&stream_write_lock);
ret = diva_stream_create (&pE->diva_stream, NULL, 255, divaStreamingMessageRx, pE, trace_ident);
if (ret == 0) {
static byte addie[] = { 0x2d /* UID */, 0x01, 0x00, 0x04 /* BC */, 0x04, 0x0, 0x0, 0x0, 0x00 /* 0x20 DMA polling */, 0 /* END */};
byte* description = (byte*)pE->diva_stream->description (pE->diva_stream, addie, (byte)sizeof(addie));
MESSAGE_EXCHANGE_ERROR error;
description[1] = streamCommand;
description[3] |= 0x01;
if (streamCommand == 0) {
messageNumber = get_capi_MessageNumber();
effectivePLCI = i->PLCI;
} else {
/*
PLCI still not assigned. Send to controller and tag with message number
where command receives effective
*/
effectivePLCI = i->controller;
}
error = capi_sendf (NULL, 0, CAPI_MANUFACTURER_REQ, effectivePLCI, messageNumber,
"dws", _DI_MANU_ID, _DI_STREAM_CTRL, description);
if (error == 0) {
pE->diva_stream_state = DivaStreamCreated;
pE->PLCI = i->PLCI;
pE->i = i;
i->diva_stream_entry = pE;
memcpy (pE->vname, i->vname, MIN(sizeof(pE->vname), sizeof(i->vname)));
pE->vname[sizeof(pE->vname)-1] = 0;
pE->rx_flow_control = 0;
pE->tx_flow_control = 0;
diva_q_add_tail (&diva_streaming_new, &pE->link);
} else {
pE->diva_stream->release (pE->diva_stream);
ast_free (pE);
}
}
cc_mutex_unlock(&stream_write_lock);
}
/*
* Remove stream info
*
* To remove stream from one active connection:
* remove stream info
* disconnect B3
* remove stream
* select_b
*/
void capi_DivaStreamingRemoveInfo(struct capi_pvt *i)
{
byte description[] = { 2, 0, 0 };
MESSAGE_EXCHANGE_ERROR error;
int send;
cc_mutex_lock(&stream_write_lock);
send = i->diva_stream_entry != 0;
cc_mutex_unlock(&stream_write_lock);
if (send != 0)
error = capi_sendf (NULL, 0, CAPI_MANUFACTURER_REQ, i->PLCI, get_capi_MessageNumber(),
"dws", _DI_MANU_ID, _DI_STREAM_CTRL, description);
}
/*!
* \brief Send empty stream to inform no Diva streaming is used for this PLCI
*/
void capi_DivaStreamingStreamNotUsed(struct capi_pvt *i, byte streamCommand, _cword messageNumber)
{
byte description[] = { 0x04, 0x00, 0x02, 0x00, 0x00 };
unsigned int effectivePLCI;
MESSAGE_EXCHANGE_ERROR error;
description[1] = streamCommand;
if (streamCommand == 0) {
messageNumber = get_capi_MessageNumber();
effectivePLCI = i->PLCI;
} else {
/*
PLCI still not assigned. Send to controller and tag with message number
where command receives effective
*/
effectivePLCI = i->controller;
}
error = capi_sendf (NULL, 0, CAPI_MANUFACTURER_REQ, effectivePLCI, messageNumber,
"dws", _DI_MANU_ID, _DI_STREAM_CTRL, description);
}
void capi_DivaStreamingRemove(struct capi_pvt *i)
{
diva_stream_scheduling_entry_t* pE = i->diva_stream_entry;
int send_cancel = 0;
cc_mutex_lock(&stream_write_lock);
pE = i->diva_stream_entry;
if (pE != 0) {
i->diva_stream_entry = 0;
pE->i = 0;
if (pE->diva_stream_state == DivaStreamCreated) {
if (i->NCCI != 0) {
/*
If NCCI is not sen then this is no possibility to send cancel request
to queued in the IDI L2 streaming info. But in user mode this is OK,
if removing PLCI CAPI removes networking entity and this operation
causes cancellation of create streaming request.
Timeout is only for the rare case where create streaming request was newer
sent to hardware.
*/
send_cancel = 1;
}
pE->diva_stream_state = DivaStreamCancelSent;
pE->cancel_start = time(NULL) + 5;
DBG_LOG(("stream cancelled [%p]", pE->diva_stream))
} else if (pE->diva_stream_state == DivaStreamActive) {
pE->diva_stream->release_stream(pE->diva_stream);
pE->diva_stream_state = DivaStreamDisconnectSent;
}
}
cc_mutex_unlock(&stream_write_lock);
if (send_cancel != 0) {
static byte data[] = { 0x8 /* CONTROL */, 0x01 /* CANCEL */};
MESSAGE_EXCHANGE_ERROR error;
error = capi_sendf(NULL, 0, CAPI_DATA_B3_REQ, i->NCCI, get_capi_MessageNumber(),
"dwww", data, sizeof(data), 0, 1U << 4);
if (likely(error == 0)) {
cc_mutex_lock(&i->lock);
i->B3count++;
cc_mutex_unlock(&i->lock);
}
}
}
/*
This is only one used to access streaming scheduling list routine.
This ensures list can be accessed w/o anly locks
To ensure exclusive access scheduling queue is static function variable
*/
void divaStreamingWakeup (void)
{
static diva_entity_queue_t active_streams;
diva_entity_link_t* link;
time_t current_time = time (NULL);
cc_mutex_lock(&stream_write_lock);
while ((link = diva_q_get_head (&diva_streaming_new)) != 0) {
diva_stream_scheduling_entry_t* pE = DIVAS_CONTAINING_RECORD(link, diva_stream_scheduling_entry_t, link);
diva_q_remove (&diva_streaming_new, &pE->link);
diva_q_add_tail (&active_streams, &pE->link);
}
cc_mutex_unlock(&stream_write_lock);
for (link = diva_q_get_head (&active_streams); likely(link != 0);) {
diva_entity_link_t* next = diva_q_get_next(link);
diva_stream_scheduling_entry_t* pE = DIVAS_CONTAINING_RECORD(link, diva_stream_scheduling_entry_t, link);
cc_mutex_lock(&stream_write_lock);
pE->diva_stream->wakeup (pE->diva_stream);
if (unlikely(pE->diva_stream_state == DivaStreamCancelSent && pE->cancel_start < current_time)) {
DBG_LOG(("stream reclaimed [%p]", pE->diva_stream))
pE->diva_stream->release (pE->diva_stream);
pE->diva_stream_state = DivaStreamDisconnected;
pE->diva_stream = 0;
}
if (unlikely(pE->diva_stream == 0)) {
diva_q_remove (&active_streams, &pE->link);
if (pE->i != 0) {
pE->i->diva_stream_entry = 0;
}
ast_free (pE);
}
cc_mutex_unlock(&stream_write_lock);
link = next;
}
}
unsigned int capi_DivaStreamingGetStreamInUse(const struct capi_pvt* i)
{
unsigned int ret = 0;
capi_DivaStreamLock();
if ((i != NULL) && (i->diva_stream_entry != NULL) &&
(i->diva_stream_entry->diva_stream_state == DivaStreamActive) &&
(i->diva_stream_entry->diva_stream != NULL)) {
ret = i->diva_stream_entry->diva_stream->get_tx_in_use (i->diva_stream_entry->diva_stream);
}
capi_DivaStreamUnLock();
return (ret);
}
void capi_DivaStreamLock(void)
{
cc_mutex_lock(&stream_write_lock);
}
void capi_DivaStreamUnLock(void)
{
cc_mutex_unlock(&stream_write_lock);
}
void capi_DivaStreamingDisable (void) {
diva_streaming_disabled = 1;
}

View File

@ -0,0 +1,36 @@
#ifndef __DIVA_CAPI_STREAMING_UTILS_H__
#define __DIVA_CAPI_STREAMING_UTILS_H__
extern int capi_DivaStreamingSupported(unsigned controller);
extern void capi_DivaStreamingOn(struct capi_pvt *i, unsigned char streamCommand, _cword messageNumber);
extern void capi_DivaStreamingStreamNotUsed(struct capi_pvt *i, byte streamCommand, _cword messageNumber);
extern void capi_DivaStreamingRemoveInfo(struct capi_pvt *i);
extern void capi_DivaStreamingRemove(struct capi_pvt *i);
extern void divaStreamingWakeup(void);
extern unsigned int capi_DivaStreamingGetStreamInUse(const struct capi_pvt* i);
extern void capi_DivaStreamLock(void);
extern void capi_DivaStreamUnLock (void);
extern void capi_DivaStreamingDisable (void);
typedef enum _diva_stream_state {
DivaStreamCreated = 0,
DivaStreamActive = 1,
DivaStreamCancelSent = 2,
DivaStreamDisconnectSent = 3,
DivaStreamDisconnected = 4
} diva_stream_state_t;
typedef struct _diva_stream_scheduling_entry {
diva_entity_link_t link;
struct _diva_stream *diva_stream;
diva_stream_state_t diva_stream_state;
struct capi_pvt *i;
int rx_flow_control;
int tx_flow_control;
char vname[CAPI_MAX_STRING]; /* Cached from capi_pvt */
dword PLCI; /* Cached from capi_pvt */
time_t cancel_start;
} diva_stream_scheduling_entry_t;
#endif

40
divastreaming/debuglib.h Normal file
View File

@ -0,0 +1,40 @@
/*
*
Copyright (c) Dialogic (R) 2009 - 2010
*
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters.
*
Dialogic (R) File Revision : 1.9
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __DIVA_STREAMING_DEBUGLIB_H__
#define __DIVA_STREAMING_DEBUGLIB_H__
void diva_runtime_error_message (const char* fmt, ...);
void diva_runtime_log_message (const char* fmt, ...);
void diva_runtime_trace_message (const char* fmt, ...);
void diva_runtime_binary_message (const void* data, unsigned long length);
#define DBG_ERR(__x__) do { diva_runtime_error_message __x__; } while (0);
#define DBG_LOG(__x__) do { diva_runtime_log_message __x__; } while (0);
#define DBG_TRC(__x__) do { diva_runtime_trace_message __x__; } while (0);
#define DBG_BLK(__x__) do { diva_runtime_binary_message __x__; } while (0);
#define dbg_init(__a__, __b__, __c__) do { static int initialized; if (initialized == 0) { initialized = 1; diva_runtime_log_message("%s %s %u", __a__, __b__, __c__); } } while (0)
#endif

View File

@ -0,0 +1,46 @@
/*
*
Copyright (c) Dialogic (R) 2009 - 2010
*
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters.
*
Dialogic (R) File Revision : 1.9
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __DIVA_SEGMENT_ALLOC_H__
#define __DIVA_SEGMENT_ALLOC_H__
struct _diva_segment_alloc;
struct _diva_segment_alloc_access;
typedef struct _diva_segment_alloc_access {
void (*release)(struct _diva_segment_alloc** ifc);
void* (*segment_alloc)(struct _diva_segment_alloc* ifc, dword* lo, dword* hi);
void (*segment_free)(struct _diva_segment_alloc* ifc, void* addr, dword lo, dword hi);
dword (*get_segment_length)(struct _diva_segment_alloc* ifc);
void* (*map_address)(struct _diva_segment_alloc* ifc, dword lo, dword hi, int map_host);
void* (*umap_address)(struct _diva_segment_alloc* ifc, dword lo, dword hi, void* local);
int (*write_address)(struct _diva_segment_alloc* ifc, dword lo, dword hi, dword data);
void (*resource_removed)(struct _diva_segment_alloc* ifc);
} diva_segment_alloc_access_t;
int diva_create_segment_alloc (void* os_context, struct _diva_segment_alloc** segment_alloc);
int diva_destroy_segment_alloc (struct _diva_segment_alloc** segment_alloc);
diva_segment_alloc_access_t* diva_get_segment_alloc_ifc (struct _diva_segment_alloc* segment_alloc);
#endif

View File

@ -0,0 +1,83 @@
/*
*
Copyright (c) Dialogic (R) 2009 - 2010
*
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters.
*
Dialogic (R) File Revision : 1.9
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __DIVA_STREAMING_IDI_HOST_IFC__
#define __DIVA_STREAMING_IDI_HOST_IFC__
/*
Write data from host to remote side
*/
struct _diva_stream;
struct _diva_segment_alloc_ifc;
struct _diva_streaming_idi_host_ifc_w;
struct _diva_streaming_idi_host_ifc_w_access;
struct _diva_streaming_idi_host_ifc_r;
struct _diva_streaming_idi_host_ifc_r_access;
typedef struct _diva_streaming_idi_host_ifc_w_access {
int (*release)(struct _diva_streaming_idi_host_ifc_w* ifc);
diva_streaming_idi_result_t (*release_stream)(struct _diva_streaming_idi_host_ifc_w* ifc);
int (*write_message)(struct _diva_streaming_idi_host_ifc_w* ifc,
dword info, const void* data, dword data_length);
int (*ack)(struct _diva_streaming_idi_host_ifc_w* ifc, dword length);
int (*ack_rx)(struct _diva_streaming_idi_host_ifc_w* ifc, dword length, int flush_ack);
int (*write)(struct _diva_streaming_idi_host_ifc_w* ifc, const void* data, dword data_length);
int (*write_indirect)(struct _diva_streaming_idi_host_ifc_w* ifc, dword lo, dword hi, dword length);
int (*update_remote)(struct _diva_streaming_idi_host_ifc_w* ifc);
dword (*get_in_use)(const struct _diva_streaming_idi_host_ifc_w* ifc);
dword (*get_free)(const struct _diva_streaming_idi_host_ifc_w* ifc);
dword (*get_length)(const struct _diva_streaming_idi_host_ifc_w* ifc);
byte (*description)(struct _diva_streaming_idi_host_ifc_w* ifc, byte* dst, byte max_length);
int (*init)(struct _diva_streaming_idi_host_ifc_w* ifc, dword version, dword counter, dword info);
diva_streaming_idi_result_t (*sync)(struct _diva_streaming_idi_host_ifc_w* ifc, dword ident);
diva_streaming_idi_result_t (*trace_ident)(struct _diva_streaming_idi_host_ifc_w* ifc);
} diva_streaming_idi_host_ifc_w_access_t;
int diva_streaming_idi_host_ifc_create (struct _diva_streaming_idi_host_ifc_w** ifc,
dword number_segments,
struct _diva_segment_alloc* segment_alloc,
const char* trace_ident);
struct _diva_streaming_idi_host_ifc_w_access* diva_streaming_idi_host_ifc_get_access (
struct _diva_streaming_idi_host_ifc_w* ifc);
typedef struct _diva_streaming_idi_host_ifc_r_access {
int (*release)(struct _diva_streaming_idi_host_ifc_r* ifc);
int (*wakeup)(struct _diva_streaming_idi_host_ifc_r* ifc);
byte (*description)(struct _diva_streaming_idi_host_ifc_r* ifc, byte* dst, byte max_length);
} diva_streaming_idi_host_ifc_r_access_t;
int diva_streaming_idi_host_rx_ifc_create (struct _diva_streaming_idi_host_ifc_r** ifc,
dword number_segments,
struct _diva_segment_alloc* segment_alloc,
struct _diva_streaming_idi_host_ifc_w* tx,
struct _diva_streaming_idi_host_ifc_w_access* tx_ifc,
diva_streaming_idi_rx_notify_user_proc_t notify_user_proc,
void* user_context,
struct _diva_stream* diva_streaming_manager_ifc,
const char* trace_ident);
struct _diva_streaming_idi_host_ifc_r_access* diva_streaming_idi_host_rx_ifc_get_access (
struct _diva_streaming_idi_host_ifc_r* ifc);
#endif

View File

@ -0,0 +1,441 @@
/*
*
Copyright (c) Dialogic (R) 2009 - 2010
*
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters.
*
Dialogic (R) File Revision : 1.9
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*
* vim:ts=2:
*/
#include "platform.h"
#include "pc.h"
#include "diva_streaming_result.h"
#include "diva_streaming_vector.h"
#include "diva_streaming_messages.h"
#include "diva_streaming_manager.h"
#include "diva_streaming_result.h"
#include "diva_segment_alloc_ifc.h"
#include "diva_streaming_idi_host_ifc.h"
#include "diva_streaming_idi_host_ifc_impl.h"
#include "spi_descriptor.h"
static int diva_streaming_idi_host_ifc_cleanup (struct _diva_streaming_idi_host_ifc_w* ifc);
static int write_message (struct _diva_streaming_idi_host_ifc_w* ifc,
dword info,
const void* data,
dword data_length);
static byte description (diva_streaming_idi_host_ifc_w_t* ifc, byte* dst, byte max_length);
static int init (struct _diva_streaming_idi_host_ifc_w* ifc, dword version, dword counter, dword info);
static diva_streaming_idi_result_t sync_req (struct _diva_streaming_idi_host_ifc_w* ifc, dword ident);
static int ack_data (struct _diva_streaming_idi_host_ifc_w* ifc, dword length);
static int ack_rx_data (struct _diva_streaming_idi_host_ifc_w* ifc, dword length, int flush_ack);
static int write_data (struct _diva_streaming_idi_host_ifc_w* ifc, const void* data, dword data_length);
static int write_indirect (struct _diva_streaming_idi_host_ifc_w* ifc, dword lo, dword hi, dword length);
static int update_remote (struct _diva_streaming_idi_host_ifc_w* ifc);
static dword get_in_use (const struct _diva_streaming_idi_host_ifc_w* ifc);
static dword get_free (const struct _diva_streaming_idi_host_ifc_w* ifc);
static dword get_length (const struct _diva_streaming_idi_host_ifc_w* ifc);
static void write_buffer (diva_streaming_idi_host_ifc_w_t* ifc, const void* data, dword data_length);
static void update_write_buffer (diva_streaming_idi_host_ifc_w_t* ifc);
static diva_streaming_idi_result_t set_trace_ident (struct _diva_streaming_idi_host_ifc_w* ifc);
static diva_streaming_idi_result_t release_stream (struct _diva_streaming_idi_host_ifc_w* ifc);
int diva_streaming_idi_host_ifc_create (struct _diva_streaming_idi_host_ifc_w** ifc,
dword number_segments,
struct _diva_segment_alloc* segment_alloc,
const char* trace_ident) {
struct _diva_streaming_idi_host_ifc_w* ifc_w = *ifc;
diva_segment_alloc_access_t* segment_alloc_access = diva_get_segment_alloc_ifc (segment_alloc);
dword i;
int free_ifc = 0;
if (ifc_w == 0) {
ifc_w = diva_os_malloc (0, sizeof(*ifc_w));
free_ifc = 1;
}
if (ifc_w == 0) {
DBG_ERR(("failed to create idi w interface [%s]", trace_ident))
return (-1);
}
memset (ifc_w, 0x00, sizeof(*ifc_w));
memcpy(ifc_w->trace_ident, trace_ident, MIN(strlen(trace_ident), DIVA_STREAMING_MAX_TRACE_IDENT_LENGTH));
ifc_w->trace_ident[DIVA_STREAMING_MAX_TRACE_IDENT_LENGTH] = 0;
ifc_w->nr_segments = MIN(number_segments, DIVA_STREAMING_IDI_HOST_IFC_MAX_SEGMENTS);
ifc_w->segment_alloc = segment_alloc;
ifc_w->free_ifc = free_ifc;
for (i = 0; i < ifc_w->nr_segments; i++) {
ifc_w->segments[i] = (*(segment_alloc_access->segment_alloc))(segment_alloc,
&ifc_w->segment_lo[i],
&ifc_w->segment_hi[i]);
if (ifc_w->segments[i] == 0) {
DBG_ERR(("failed to alloc segment [%s]", trace_ident))
diva_streaming_idi_host_ifc_cleanup (ifc_w);
return (-1);
}
DBG_TRC(("alloc %p %08x:%08x [%s]", ifc_w->segments[i], ifc_w->segment_lo[i], ifc_w->segment_hi[i], trace_ident))
ifc_w->segment_length[i] = (*(segment_alloc_access->get_segment_length))(segment_alloc);
if (i == 0) {
*(volatile dword*)(ifc_w->segments[i]+ifc_w->segment_length[i]-sizeof(dword)) = 0;
}
ifc_w->state.length += ifc_w->segment_length[i];
}
ifc_w->ack_rx = 0;
ifc_w->state.used_length = 0;
ifc_w->state.free_length = ifc_w->state.length;
ifc_w->state.write_buffer = 0;
ifc_w->state.write_buffer_position = 0;
ifc_w->state.write_buffer_free = ifc_w->segment_length[ifc_w->state.write_buffer];
ifc_w->state.acknowledge_buffer = 0;
ifc_w->state.acknowledge_buffer_position = 0;
ifc_w->remote.written = 0;
ifc_w->access.release = diva_streaming_idi_host_ifc_cleanup;
ifc_w->access.release_stream = release_stream;
ifc_w->access.write_message = write_message;
ifc_w->access.ack = ack_data;
ifc_w->access.ack_rx = ack_rx_data;
ifc_w->access.write = write_data;
ifc_w->access.write_indirect = write_indirect;
ifc_w->access.update_remote = update_remote;
ifc_w->access.get_in_use = get_in_use;
ifc_w->access.get_free = get_free;
ifc_w->access.get_length = get_length;
ifc_w->access.description = description;
ifc_w->access.init = init;
ifc_w->access.sync = sync_req;
ifc_w->access.trace_ident = set_trace_ident;
*ifc = ifc_w;
return (0);
}
struct _diva_streaming_idi_host_ifc_w_access* diva_streaming_idi_host_ifc_get_access (
struct _diva_streaming_idi_host_ifc_w* ifc) {
return (&ifc->access);
}
static int diva_streaming_idi_host_ifc_cleanup (struct _diva_streaming_idi_host_ifc_w* ifc) {
diva_segment_alloc_access_t* segment_alloc_access = diva_get_segment_alloc_ifc (ifc->segment_alloc);
dword i;
for (i = 0; i < ifc->nr_segments; i++) {
if (ifc->segments[i] != 0) {
(*(segment_alloc_access->segment_free))(ifc->segment_alloc,
ifc->segments[i],
ifc->segment_lo[i],
ifc->segment_hi[i]);
}
}
if (ifc->remote_counter_mapped_base != 0) {
segment_alloc_access->umap_address (ifc->segment_alloc, ifc->remote_counter_base, 0, ifc->remote_counter_mapped_base);
}
if (ifc->free_ifc != 0) {
diva_os_free (0, ifc);
}
return (0);
}
static void update_write_buffer (diva_streaming_idi_host_ifc_w_t* ifc) {
if (ifc->state.write_buffer_free == 0) {
ifc->state.write_buffer++;
if (ifc->state.write_buffer >= ifc->nr_segments) {
ifc->state.write_buffer = 0;
}
ifc->state.write_buffer_free = ifc->segment_length[ifc->state.write_buffer];
ifc->state.write_buffer_position = 0;
}
}
static void write_buffer (diva_streaming_idi_host_ifc_w_t* ifc, const void* data, dword data_length) {
const byte* src = (const byte*)data;
dword to_write = data_length;
while (data_length != 0) {
dword to_copy = MIN(ifc->state.write_buffer_free, data_length);
memcpy (ifc->segments[ifc->state.write_buffer]+ifc->state.write_buffer_position, src, to_copy);
src += to_copy;
ifc->state.write_buffer_position += to_copy;
ifc->state.write_buffer_free -= to_copy;
data_length -= to_copy;
update_write_buffer (ifc);
}
ifc->state.free_length -= to_write;
ifc->state.used_length += to_write;
ifc->remote.written += ((int32)to_write);
}
static void align_write_buffer (diva_streaming_idi_host_ifc_w_t* ifc, dword data_length) {
dword to_write = data_length;
while (data_length != 0) {
dword to_copy = MIN(ifc->state.write_buffer_free, data_length);
ifc->state.write_buffer_position += to_copy;
ifc->state.write_buffer_free -= to_copy;
data_length -= to_copy;
update_write_buffer (ifc);
}
ifc->state.free_length -= to_write;
ifc->state.used_length += to_write;
ifc->remote.written += ((int32)to_write);
}
static int write_message (struct _diva_streaming_idi_host_ifc_w* ifc,
dword info,
const void* data,
dword data_length) {
dword idi_header_length = ((info & 0xff) == DIVA_STREAM_MESSAGE_TX_IDI_REQUEST && (info & DIVA_STREAMING_IDI_SYSTEM_MESSAGE) == 0) ? (sizeof(diva_spi_msg_hdr_t)+1) : 0;
dword length = data_length + idi_header_length + 2 * sizeof(dword); /* data length + message length + info */
dword required_length = (length + 31) & ~31;
byte tmp[sizeof(dword)+1];
byte Req = 0;
if (required_length > get_free (ifc)) {
return (0);
}
WRITE_DWORD(tmp, data_length + idi_header_length + sizeof(dword)); /* Write message length without length dword */
write_buffer (ifc, tmp, sizeof(dword));
if ((info & DIVA_STREAMING_IDI_SYSTEM_MESSAGE) == 0) {
switch (info & 0xff) {
case DIVA_STREAM_MESSAGE_TX_IDI_REQUEST: {
dword ack_info = (word)ifc->ack_rx;
Req = (byte)(info >> 8);
info = DIVA_STREAMING_IDI_TX_REQUEST | (ack_info << 8);
ifc->ack_rx -= ack_info;
} break;
}
}
WRITE_DWORD(tmp, info);
write_buffer (ifc, tmp, sizeof(dword)); /* Write info */
if (idi_header_length != 0) {
diva_spi_msg_hdr_t* hdr = (diva_spi_msg_hdr_t*)tmp;
dword message_length = data_length + idi_header_length;
byte* message_data = (byte*)&hdr[1];
hdr->Id = 0;
hdr->Ind = Req;
hdr->length_lo = (byte)message_length;
hdr->length_hi = (byte)(message_length >> 8);
message_data[0] = 0;
write_buffer (ifc, hdr, idi_header_length);
}
write_buffer (ifc, data, data_length); /* Write data */
align_write_buffer (ifc, required_length - length); /* Move to next message */
return (data_length);
}
static int ack_data (struct _diva_streaming_idi_host_ifc_w* ifc, dword length) {
if (length > get_in_use (ifc)) {
DBG_ERR(("ack error ack:%u in use:%u free:%u [%s]", length, get_in_use (ifc), ifc->state.free_length, ifc->trace_ident))
return (-1);
}
ifc->state.free_length += length;
ifc->state.used_length -= length;
return (0);
}
static int ack_rx_data (struct _diva_streaming_idi_host_ifc_w* ifc, dword length, int flush_ack) {
flush_ack |= (ifc->ack_rx != 0);
ifc->ack_rx += length;
while (flush_ack != 0 && ifc->ack_rx != 0 && get_free (ifc) > 128) {
dword info = (word)ifc->ack_rx;
ifc->ack_rx -= info;
info = ((dword)DIVA_STREAMING_IDI_RX_ACK_MSG) | (info << 8) | DIVA_STREAMING_IDI_SYSTEM_MESSAGE;
write_message (ifc, info, 0, 0);
update_remote (ifc);
}
return (0);
}
static byte description (diva_streaming_idi_host_ifc_w_t* ifc, byte* dst, byte max_length) {
byte length = 0;
dword i;
DBG_TRC(("tx description %u segments [%s]", ifc->nr_segments, ifc->trace_ident))
dst[length++] = (byte)(ifc->nr_segments);
for (i = 0; i < ifc->nr_segments; i++) {
DBG_TRC((" tx lo[%u] %08x [%s]", i, ifc->segment_lo[i], ifc->trace_ident))
WRITE_DWORD(&dst[length], ifc->segment_lo[i]);
length += sizeof(dword);
}
for (i = 0; i < ifc->nr_segments; i++) {
DBG_TRC((" tx hi[%u] %08x [%s]", i, ifc->segment_hi[i], ifc->trace_ident))
WRITE_DWORD(&dst[length], ifc->segment_hi[i]);
length += sizeof(dword);
}
for (i = 0; i < ifc->nr_segments; i++) {
DBG_TRC((" length[%u] %u [%s]", i, ifc->segment_length[i], ifc->trace_ident))
WRITE_DWORD(&dst[length], ifc->segment_length[i]);
length += sizeof(dword);
}
return (length);
}
static int init (struct _diva_streaming_idi_host_ifc_w* ifc, dword version, dword counter, dword info) {
diva_segment_alloc_access_t* segment_alloc_access = diva_get_segment_alloc_ifc (ifc->segment_alloc);
if ((info & DIVA_STREAMING_MANAGER_TX_COUNTER_IN_TX_PAGE) != 0) {
ifc->segment_length[0] -= sizeof(dword);
ifc->state.length -= sizeof(dword);
ifc->state.write_buffer_free -= sizeof(dword);
ifc->state.free_length -= sizeof(dword);
ifc->remote_counter_mapped = (dword*)(ifc->segments[0]+ifc->segment_length[0]);
ifc->remote_counter_mapped_base = 0;
} else {
ifc->remote_counter_offset = counter % (4*1024);
ifc->remote_counter_base = counter - ifc->remote_counter_offset;
ifc->remote_counter_mapped_base = segment_alloc_access->map_address (ifc->segment_alloc,
ifc->remote_counter_base, 0,
(info & DIVA_STREAMING_MANAGER_HOST_USER_MODE_STREAM) != 0);
if (ifc->remote_counter_mapped_base != 0) {
byte* p = ifc->remote_counter_mapped_base;
ifc->remote_counter_mapped = (dword*)&p[ifc->remote_counter_offset];
} else {
DBG_TRC(("stream uses system call [%s]", ifc->trace_ident))
}
}
return (0);
}
static diva_streaming_idi_result_t sync_req (struct _diva_streaming_idi_host_ifc_w* ifc, dword ident) {
if (get_free (ifc) > 128) {
dword data[2];
DBG_TRC(("sync request %08x [%s]", ident, ifc->trace_ident))
data[0] = ident;
data[1] = 0;
write_message (ifc, DIVA_STREAMING_IDI_SYNC_REQ|DIVA_STREAMING_IDI_SYSTEM_MESSAGE, data, sizeof(data));
update_remote (ifc);
return (DivaStreamingIdiResultOK);
} else {
return (DivaStreamingIdiResultBusy);
}
}
static diva_streaming_idi_result_t set_trace_ident (struct _diva_streaming_idi_host_ifc_w* ifc) {
if (get_free (ifc) > 128) {
dword data[2];
DBG_TRC(("set trace ident [%s]", ifc->trace_ident))
memcpy (data, ifc->trace_ident, sizeof(data[0]));
data[1] = 0;
write_message (ifc, DIVA_STREAMING_IDI_SET_DEBUG_IDENT|DIVA_STREAMING_IDI_SYSTEM_MESSAGE, data, sizeof(data));
update_remote (ifc);
return (DivaStreamingIdiResultOK);
} else {
return (DivaStreamingIdiResultBusy);
}
}
static diva_streaming_idi_result_t release_stream (struct _diva_streaming_idi_host_ifc_w* ifc) {
dword data[1];
int ret;
DBG_LOG(("stream release [%s]", ifc->trace_ident))
data[0] = 0;
ret = write_message (ifc, DIVA_STREAMING_IDI_RELEASE|DIVA_STREAMING_IDI_SYSTEM_MESSAGE, data, sizeof(data));
update_remote (ifc);
return (ret != 0 ? DivaStreamingIdiResultOK : DivaStreamingIdiResultBusy);
}
static int write_data (struct _diva_streaming_idi_host_ifc_w* ifc, const void* data, dword data_length) {
return (-1);
}
static int write_indirect (struct _diva_streaming_idi_host_ifc_w* ifc, dword lo, dword hi, dword length) {
return (-1);
}
static int update_remote (struct _diva_streaming_idi_host_ifc_w* ifc) {
int ret = 0;
if (ifc->remote_counter_mapped != 0) {
ifc->remote_counter_mapped[0] = ifc->remote.written;
} else {
diva_segment_alloc_access_t* segment_alloc_access = diva_get_segment_alloc_ifc (ifc->segment_alloc);
ret = segment_alloc_access->write_address (ifc->segment_alloc,
ifc->remote_counter_base + ifc->remote_counter_offset,
0,
ifc->remote.written);
}
return (ret);
}
static dword get_in_use (const struct _diva_streaming_idi_host_ifc_w* ifc) {
return (ifc->state.used_length);
}
static dword get_free (const struct _diva_streaming_idi_host_ifc_w* ifc) {
return (ifc->state.free_length);
}
static dword get_length (const struct _diva_streaming_idi_host_ifc_w* ifc) {
return (ifc->state.length);
}

View File

@ -0,0 +1,75 @@
/*
*
Copyright (c) Dialogic (R) 2009 - 2010
*
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters.
*
Dialogic (R) File Revision : 1.9
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __DIVA_STREAMING_IDI_HOST_IFC_IMPL_H__
#define __DIVA_STREAMING_IDI_HOST_IFC_IMPL_H__
struct _diva_segment_alloc_ifc;
struct _diva_streaming_idi_host_ifc_w_access;
struct _diva_streaming_idi_host_ifc_w;
#define DIVA_STREAMING_IDI_HOST_IFC_MAX_SEGMENTS 8
typedef struct _diva_streaming_idi_host_ifc_w {
struct _diva_streaming_idi_host_ifc_w_access access;
byte* segments[DIVA_STREAMING_IDI_HOST_IFC_MAX_SEGMENTS]; /**< buffer segments */
dword segment_length[DIVA_STREAMING_IDI_HOST_IFC_MAX_SEGMENTS]; /**< length of every segment */
dword segment_lo[DIVA_STREAMING_IDI_HOST_IFC_MAX_SEGMENTS];
dword segment_hi[DIVA_STREAMING_IDI_HOST_IFC_MAX_SEGMENTS];
dword nr_segments; /**< number of available segments */
struct _diva_segment_alloc* segment_alloc;
struct {
dword length; /**< overall length including all segments */
dword used_length; /**< overall written and not acknowledged */
dword free_length; /**< overall length available */
dword write_buffer; /**< current write segment buffer */
dword write_buffer_position; /**< position in write segment */
dword write_buffer_free; /**< free space in write segment */
dword acknowledge_buffer; /**< acknowledge segment */
dword acknowledge_buffer_position; /**< position in acknowledge segment */
dword acknowledge_buffer_free;
} state;
struct {
int32 written; /**< incremented every time data written by amount of data written in the buffer and
written to opposite side */
} remote;
dword remote_counter_base; /* Remote counter page BUS address */
dword remote_counter_offset; /* Remote counter offset from page start */
void* remote_counter_mapped_base; /* Remote counter page BUS address mapped */
volatile dword* remote_counter_mapped; /* Remote counter mapped */
dword ack_rx;
int free_ifc;
char trace_ident[DIVA_STREAMING_MAX_TRACE_IDENT_LENGTH+1];
} diva_streaming_idi_host_ifc_w_t;
#endif

View File

@ -0,0 +1,400 @@
/*
*
Copyright (c) Dialogic (R) 2009 - 2010
*
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters.
*
Dialogic (R) File Revision : 1.9
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*
* vim:ts=2:
*/
#include "platform.h"
#include "pc.h"
#include "diva_streaming_vector.h"
#include "diva_streaming_messages.h"
#include "diva_streaming_result.h"
#include "diva_streaming_manager.h"
#include "diva_streaming_result.h"
#include "diva_segment_alloc_ifc.h"
#include "diva_streaming_idi_host_ifc.h"
#include "diva_streaming_idi_host_rx_ifc_impl.h"
/*
* LOCALS
*/
static void update_buffer (struct _diva_streaming_idi_host_ifc_r* ifc);
static void align_buffer (struct _diva_streaming_idi_host_ifc_r* ifc, dword length, diva_streaming_vector_t* v, dword* nr_v);
static int diva_streaming_idi_host_rx_data (struct _diva_streaming_idi_host_ifc_r* ifc, dword length);
static dword copy_message_data (byte* dst, const diva_streaming_vector_t* v, dword nr_v);
static int diva_streaming_idi_host_rx_process_message (struct _diva_streaming_idi_host_ifc_r* ifc,
dword message,
dword data_length,
const diva_streaming_vector_t* v, dword nr_v);
static byte description (diva_streaming_idi_host_ifc_r_t* ifc, byte* dst, byte max_length);
static int diva_streaming_idi_host_rx_ifc_rx (struct _diva_streaming_idi_host_ifc_r* ifc);
static int diva_streaming_idi_host_rx_ifc_cleanup (struct _diva_streaming_idi_host_ifc_r* ifc);
int diva_streaming_idi_host_rx_ifc_create (struct _diva_streaming_idi_host_ifc_r** ifc,
dword number_segments,
struct _diva_segment_alloc* segment_alloc,
struct _diva_streaming_idi_host_ifc_w* tx,
struct _diva_streaming_idi_host_ifc_w_access* tx_ifc,
diva_streaming_idi_rx_notify_user_proc_t notify_user_proc,
void* user_context,
struct _diva_stream* diva_streaming_manager_ifc,
const char* trace_ident) {
struct _diva_streaming_idi_host_ifc_r* ifc_r = *ifc;
diva_segment_alloc_access_t* segment_access = diva_get_segment_alloc_ifc (segment_alloc);
dword i;
int free_ifc = 0;
if (ifc_r == 0) {
ifc_r = diva_os_malloc (0, sizeof(*ifc_r));
free_ifc = 1;
}
if (ifc_r == 0) {
DBG_ERR(("failed to create idi r interface [%s]", trace_ident))
return (-1);
}
memset (ifc_r, 0x00, sizeof(*ifc_r));
memcpy(ifc_r->trace_ident, trace_ident, MIN(strlen(trace_ident), DIVA_STREAMING_MAX_TRACE_IDENT_LENGTH));
ifc_r->trace_ident[DIVA_STREAMING_MAX_TRACE_IDENT_LENGTH] = 0;
ifc_r->nr_segments = MIN(number_segments, DIVA_STREAMING_IDI_HOST_RX_IFC_MAX_SEGMENTS);
ifc_r->segment_alloc = segment_alloc;
ifc_r->free_ifc = free_ifc;
ifc_r->diva_streaming_manager_ifc = diva_streaming_manager_ifc;
for (i = 0; i < ifc_r->nr_segments; i++) {
ifc_r->segments[i] = (*(segment_access->segment_alloc))(segment_alloc,
&ifc_r->segment_lo[i],
&ifc_r->segment_hi[i]);
if (ifc_r->segments[i] == 0) {
DBG_ERR(("failed to alloc segment [%s]", trace_ident))
diva_streaming_idi_host_rx_ifc_cleanup (ifc_r);
return (-1);
}
DBG_TRC(("alloc %p %08x:%08x [%s]", ifc_r->segments[i], ifc_r->segment_lo[i], ifc_r->segment_hi[i], trace_ident))
ifc_r->segment_length[i] = (*(segment_access->get_segment_length))(segment_alloc);
if (i == 0) {
ifc_r->remote_counter = (int32*)ifc_r->segments[i];
ifc_r->segments[i] += sizeof(dword);
ifc_r->segment_length[i] -= sizeof(dword);
}
ifc_r->state.length += ifc_r->segment_length[i];
}
ifc_r->remote_counter[0] = 0;
ifc_r->tx = tx;
ifc_r->tx_ifc = tx_ifc;
ifc_r->notify_user_proc = notify_user_proc;
ifc_r->user_context = user_context;
ifc_r->current_segment = 0;
ifc_r->current_pos = 0;
ifc_r->current_free = ifc_r->segment_length[ifc_r->current_segment];
ifc_r->access.release = diva_streaming_idi_host_rx_ifc_cleanup;
ifc_r->access.wakeup = diva_streaming_idi_host_rx_ifc_rx;
ifc_r->access.description = description;
*ifc = ifc_r;
return (0);
}
struct _diva_streaming_idi_host_ifc_r_access* diva_streaming_idi_host_rx_ifc_get_access (
struct _diva_streaming_idi_host_ifc_r* ifc) {
return (&ifc->access);
}
static int diva_streaming_idi_host_rx_ifc_cleanup (struct _diva_streaming_idi_host_ifc_r* ifc) {
diva_segment_alloc_access_t* segment_access = diva_get_segment_alloc_ifc (ifc->segment_alloc);
dword i;
for (i = 0; i < ifc->nr_segments; i++) {
if (ifc->segments[i] != 0) {
(*(segment_access->segment_free))(ifc->segment_alloc,
ifc->segments[i] - ((i == 0) ? sizeof(dword) : 0),
ifc->segment_lo[i],
ifc->segment_hi[i]);
}
}
if (ifc->free_ifc != 0) {
diva_os_free (0, ifc);
}
return (0);
}
/*
* Receive data
*/
static int diva_streaming_idi_host_rx_ifc_rx (struct _diva_streaming_idi_host_ifc_r* ifc) {
int32 local_counter;
int32 length;
int ret = 0;
int msg_count = 0, ack_ret;
do {
local_counter = ifc->remote_counter[0];
length = local_counter - ifc->local_counter;
if (length != 0) {
ret += length;
ifc->local_counter = local_counter;
ack_ret = diva_streaming_idi_host_rx_data (ifc, length);
if (ifc->released == DIVA_STREAM_MESSAGE_RELEASE_ACK || ifc->released == DIVA_STREAM_MESSAGE_INIT_ERROR) {
if (ifc->notify_user_proc (ifc->user_context, ((dword)ifc->released) << 8 | 0xffU, ifc->released_info, 0, 0) == 0) {
ifc->diva_streaming_manager_ifc->release(ifc->diva_streaming_manager_ifc);
} else {
ifc->released = DIVA_STREAM_MESSAGE_RELEASED;
}
return (0);
}
ifc->tx_ifc->ack_rx (ifc->tx, length, msg_count != 0 || ack_ret == 0);
msg_count++;
}
} while(length != 0);
return (ret);
}
static void update_buffer (struct _diva_streaming_idi_host_ifc_r* ifc) {
if (ifc->current_free == 0) {
ifc->current_segment++;
if (ifc->current_segment >= ifc->nr_segments) {
ifc->current_segment = 0;
}
ifc->current_free = ifc->segment_length[ifc->current_segment];
ifc->current_pos = 0;
}
}
static void align_buffer (struct _diva_streaming_idi_host_ifc_r* ifc, dword length, diva_streaming_vector_t* v, dword* nr_v) {
while (length != 0) {
dword to_copy = MIN(ifc->current_free, length);
if (v != 0) {
v[*nr_v].data = ifc->segments[ifc->current_segment] + ifc->current_pos;
v[*nr_v].length = to_copy;
nr_v[0]++;
}
ifc->current_pos += to_copy;
ifc->current_free -= to_copy;
length -= to_copy;
update_buffer (ifc);
}
}
static dword copy_message_data (byte* dst, const diva_streaming_vector_t* v, dword nr_v) {
dword i, length;
for (i = 0, length = 0; i < nr_v; i++) {
memcpy (&dst[length], v[i].data, v[i].length);
length += v[i].length;
}
return (length);
}
/*
Return one if processed DIVA_STREAMING_IDI_TX_ACK_MSG
*/
static int diva_streaming_idi_host_rx_process_message (struct _diva_streaming_idi_host_ifc_r* ifc,
dword message,
dword data_length,
const diva_streaming_vector_t* v, dword nr_v) {
int ret = 0;
switch (message) {
case DIVA_STREAMING_IDI_TX_INIT_MSG: /* Initialization */
if (data_length != (DIVA_STREAMING_IDI_TX_INIT_MSG_LENGTH - sizeof(dword) - sizeof(word))) {
DBG_ERR(("wrong message length %02x %u [%s]", DIVA_STREAMING_IDI_TX_INIT_MSG, data_length, ifc->trace_ident))
return (0);
}
{
dword counter;
dword info;
byte version;
copy_message_data (ifc->system_message, v, nr_v);
version = ifc->system_message[0];
counter = READ_DWORD(&ifc->system_message[1]);
info = READ_DWORD(&ifc->system_message[5]);
DBG_TRC(("version:%u counter:%08x info:%08x [%s]", version, counter, info, ifc->trace_ident))
ifc->tx_ifc->init (ifc->tx, version, counter, info);
ifc->tx_ifc->trace_ident (ifc->tx);
ifc->notify_user_proc (ifc->user_context, DIVA_STREAM_MESSAGE_INIT << 8 | 0xffU, 0, 0, 0);
}
break;
case DIVA_STREAMING_IDI_TX_ACK_MSG:
if (data_length < (DIVA_STREAMING_IDI_TX_ACK_MSG_LENGTH - sizeof(dword) - sizeof(word))) {
DBG_ERR(("wrong message length %02x %u [%s]", DIVA_STREAMING_IDI_TX_ACK_MSG, data_length, ifc->trace_ident))
return (0);
}
copy_message_data (ifc->system_message, v, nr_v);
DBG_TRC(("Ind:%02x %u seq:%u [%s]",
DIVA_STREAMING_IDI_TX_ACK_MSG,
((word)ifc->system_message[0]) | (((word)ifc->system_message[1]) << 8),
ifc->system_message[2],
ifc->trace_ident))
ifc->tx_ifc->ack (ifc->tx, ((word)ifc->system_message[0]) | (((word)ifc->system_message[1]) << 8));
ret = 1;
ifc->notify_user_proc (ifc->user_context, DIVA_STREAM_MESSAGE_RX_TX_ACK << 8 | 0xffU, 0, 0, 0);
break;
case DIVA_STREAMING_IDI_TX_SYNC_ACK:
if (data_length != (DIVA_STREAMING_IDI_TX_SYNC_ACK_LENGTH - sizeof(dword) - sizeof(word))) {
DBG_ERR(("wrong message length %02x %u [%s]", DIVA_STREAMING_IDI_TX_SYNC_ACK, data_length, ifc->trace_ident))
return (0);
}
copy_message_data (ifc->system_message, v, nr_v);
{
dword ident = READ_DWORD(&ifc->system_message[0]);
DBG_TRC(("sync ack %08x [%s]", ident, ifc->trace_ident))
ifc->notify_user_proc (ifc->user_context, DIVA_STREAM_MESSAGE_SYNC_ACK << 8 | 0xffU, ident, 0, 0);
}
break;
case DIVA_STREAMING_IDI_RELEASE_ACK:
if (data_length != (DIVA_STREAMING_IDI_RELEASE_ACK_LENGTH - sizeof(dword) - sizeof(word))) {
DBG_ERR(("wrong message length %02x %u [%s]", DIVA_STREAMING_IDI_RELEASE_ACK, data_length, ifc->trace_ident))
return (0);
}
DBG_LOG(("stream release ack [%s]", ifc->trace_ident))
ifc->released = DIVA_STREAM_MESSAGE_RELEASE_ACK;
ifc->released_info = 0;
break;
case DIVA_STREAMING_IDI_TX_INIT_ERROR:
if (data_length < DIVA_STREAMING_IDI_TX_INIT_ERROR_LENGTH - sizeof(dword) - sizeof(word) || data_length >= sizeof(ifc->system_message)) {
DBG_ERR(("wrong message length %02x %u [%s]", DIVA_STREAMING_IDI_TX_INIT_ERROR, data_length, ifc->trace_ident))
}
copy_message_data (ifc->system_message, v, nr_v);
{
dword error = READ_DWORD(&ifc->system_message[0]);
DBG_LOG(("stream init error %08x [%s]", error, ifc->trace_ident))
ifc->released = DIVA_STREAM_MESSAGE_INIT_ERROR;
ifc->released_info = error;
}
break;
default:
DBG_ERR(("unknown message %08x %u [%s]", message, data_length, ifc->trace_ident))
break;
}
return (ret);
}
/*
Return one of only one system ack tx message was processed
*/
static int diva_streaming_idi_host_rx_data (struct _diva_streaming_idi_host_ifc_r* ifc, dword length) {
diva_streaming_vector_t v[DIVA_STREAMING_IDI_HOST_RX_IFC_MAX_SEGMENTS+2];
dword nr_v;
int msg_count = 0, ack_msg = 0;
while (length != 0) {
dword hdr = *(dword*)(ifc->segments[ifc->current_segment] + ifc->current_pos);
dword data_length_lo = hdr & 0xffU;
dword data_length_hi = (hdr >> 8) & 0xffU;
dword data_length = data_length_lo | (data_length_hi << 8);
dword message_length = ((data_length + (sizeof(dword)-1)) & ~(sizeof(dword)-1));
dword message_type = (hdr >> 16) & 0xff;
dword message = (hdr >> 24) & 0xff;
length -= (message_length + sizeof(dword)-1) & ~(sizeof(dword)-1);
nr_v = 0;
if (message_type != 0xff && (message & 0x0f) == 0x0f) {
/*
Tx ack sent as part of IDI N_COMBI_IND message
*/
byte tmp[sizeof(dword)+sizeof(word)];
dword tx_ack;
align_buffer (ifc, sizeof(dword)+sizeof(word), v, &nr_v); /* Header */
copy_message_data (tmp, v, nr_v);
tx_ack = ((dword)tmp[4]) | (((dword)tmp[5]) << 8);
if (tx_ack != 0) {
ifc->tx_ifc->ack (ifc->tx, tx_ack);
ifc->notify_user_proc (ifc->user_context, DIVA_STREAM_MESSAGE_RX_TX_ACK << 8 | 0xffU, 0, 0, 0);
}
nr_v = 0;
} else {
align_buffer (ifc, sizeof(dword)+sizeof(word), 0, 0); /* Header */
}
align_buffer (ifc, data_length - sizeof(dword) - sizeof(word), v, &nr_v);
if (message_type == 0xff) {
ack_msg |= diva_streaming_idi_host_rx_process_message (ifc, message, data_length - sizeof(dword) - sizeof(word), v, nr_v);
if (ifc->released != 0)
return (1);
} else if (nr_v != 0) {
ifc->notify_user_proc (ifc->user_context, message << 8, data_length - sizeof(dword) - sizeof(word), v, nr_v);
}
align_buffer (ifc, message_length - data_length, 0, 0);
msg_count++;
}
return (msg_count == 1 && ack_msg != 0);
}
static byte description (diva_streaming_idi_host_ifc_r_t* ifc, byte* dst, byte max_length) {
byte length = 0;
dword i;
DBG_TRC(("rx description %u segments [%s]", ifc->nr_segments, ifc->trace_ident))
for (i = 0; i < ifc->nr_segments; i++) {
DBG_TRC((" rx lo[%u] %08x [%s]", i, ifc->segment_lo[i], ifc->trace_ident))
WRITE_DWORD(&dst[length], ifc->segment_lo[i]);
length += sizeof(dword);
}
for (i = 0; i < ifc->nr_segments; i++) {
DBG_TRC((" rx hi[%u] %08x [%s]", i, ifc->segment_hi[i], ifc->trace_ident))
WRITE_DWORD(&dst[length], ifc->segment_hi[i]);
length += sizeof(dword);
}
return (length);
}

View File

@ -0,0 +1,76 @@
/*
*
Copyright (c) Dialogic (R) 2009 - 2010
*
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters.
*
Dialogic (R) File Revision : 1.9
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __DIVA_STREAMING_IDI_HOST_RX_IFC_IMPL_H__
#define __DIVA_STREAMING_IDI_HOST_RX_IFC_IMPL_H__
struct _diva_segment_alloc_ifc;
struct _diva_streaming_idi_host_ifc_r_access;
struct _diva_streaming_idi_host_ifc_r;
#define DIVA_STREAMING_IDI_HOST_RX_IFC_MAX_SEGMENTS 8
typedef struct _diva_streaming_idi_host_ifc_r {
struct _diva_streaming_idi_host_ifc_r_access access;
byte* segments[DIVA_STREAMING_IDI_HOST_RX_IFC_MAX_SEGMENTS]; /**< buffer segments */
dword segment_length[DIVA_STREAMING_IDI_HOST_RX_IFC_MAX_SEGMENTS]; /**< length of every segment */
dword segment_lo[DIVA_STREAMING_IDI_HOST_RX_IFC_MAX_SEGMENTS];
dword segment_hi[DIVA_STREAMING_IDI_HOST_RX_IFC_MAX_SEGMENTS];
dword nr_segments; /**< number of available segments */
volatile int32* remote_counter; /**< updated by remote side, located at begin of first segment */
volatile int32 local_counter;
dword current_segment;
dword current_pos;
dword current_free;
struct _diva_segment_alloc* segment_alloc;
struct _diva_streaming_idi_host_ifc_w* tx;
struct _diva_streaming_idi_host_ifc_w_access* tx_ifc;
diva_streaming_idi_rx_notify_user_proc_t notify_user_proc;
void* user_context;
byte system_message[512];
int free_ifc;
struct {
dword length; /**< overall length including all segments */
} state;
struct _diva_stream* diva_streaming_manager_ifc;
dword released;
dword released_info;
char trace_ident[DIVA_STREAMING_MAX_TRACE_IDENT_LENGTH+1];
} diva_streaming_idi_host_ifc_r_t;
#endif

View File

@ -0,0 +1,370 @@
/*
*
Copyright (c) Dialogic (R) 2009 - 2010
*
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters.
*
Dialogic (R) File Revision : 1.9
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "platform.h"
#include "pc.h"
#include "diva_streaming_result.h"
#include "diva_streaming_vector.h"
#include "diva_streaming_manager.h"
#include "diva_streaming_messages.h"
#include "diva_segment_alloc_ifc.h"
#include "diva_streaming_idi_host_ifc.h"
typedef struct _diva_stream_manager {
diva_stream_t ifc;
int user_segment_alloc;
struct _diva_segment_alloc* segment_alloc;
diva_segment_alloc_access_t* segment_alloc_ifc;
struct _diva_streaming_idi_host_ifc_w* tx;
struct _diva_streaming_idi_host_ifc_w_access* tx_ifc;
struct _diva_streaming_idi_host_ifc_r* rx;
struct _diva_streaming_idi_host_ifc_r_access* rx_ifc;
diva_streaming_idi_rx_notify_user_proc_t rx_proc;
void* rx_proc_context;
byte description[0xff-32];
char trace_ident[DIVA_STREAMING_MAX_TRACE_IDENT_LENGTH+1];
} diva_stream_manager_t;
/*
* LOCALS
*/
static int message_input_proc (void* user_context, dword message, dword length, const diva_streaming_vector_t* v, dword nr_v);
static diva_streaming_idi_result_t diva_stream_manager_release (struct _diva_stream* ifc);
static diva_streaming_idi_result_t diva_stream_manager_release_stream (struct _diva_stream* ifc);
static diva_streaming_idi_result_t diva_stream_manager_write (struct _diva_stream* ifc, dword message, const void* data, dword length);
static diva_streaming_idi_result_t diva_stream_manager_wakeup (struct _diva_stream* ifc);
static const byte* diva_stream_manager_description (struct _diva_stream* ifc, const byte* addie, byte addielen);
static diva_streaming_idi_result_t diva_stream_manager_sync_req (struct _diva_stream* ifc, dword ident);
static diva_streaming_idi_result_t diva_stream_flush (struct _diva_stream* ifc);
static dword diva_stream_get_tx_free (const struct _diva_stream* ifc);
static dword diva_stream_get_tx_in_use (const struct _diva_stream* ifc);
static void diva_notify_os_resource_removed (struct _diva_stream* ifc);
diva_streaming_idi_result_t diva_stream_create (struct _diva_stream** ifc,
void* os_context,
dword length,
diva_streaming_idi_rx_notify_user_proc_t rx,
void* rx_context,
const char* trace_ident) {
return (diva_stream_create_with_user_segment_alloc (ifc, os_context, length, rx, rx_context, trace_ident, 0));
}
diva_streaming_idi_result_t diva_stream_create_with_user_segment_alloc (struct _diva_stream** ifc,
void* os_context,
dword length,
diva_streaming_idi_rx_notify_user_proc_t rx,
void* rx_context,
const char* trace_ident,
struct _diva_segment_alloc* user_segment_alloc) {
diva_stream_manager_t* pI;
diva_streaming_idi_result_t ret = DivaStreamingIdiResultError;
#ifdef DIVA_USERMODE
dbg_init ("DIVA STREAM", "109-1", 0);
#endif
pI = diva_os_malloc (0, sizeof(*pI));
if (pI != 0) {
memset (pI, 0x00, sizeof(*pI));
memcpy(pI->trace_ident, trace_ident, MIN(strlen(trace_ident), DIVA_STREAMING_MAX_TRACE_IDENT_LENGTH));
pI->trace_ident[DIVA_STREAMING_MAX_TRACE_IDENT_LENGTH] = 0;
if (user_segment_alloc != 0) {
pI->segment_alloc = user_segment_alloc;
pI->user_segment_alloc = 1;
ret = 0;
} else {
ret = diva_create_segment_alloc (os_context, &pI->segment_alloc);
pI->user_segment_alloc = 0;
}
if (ret == 0) {
dword number_segments = length/4096 + ((length%4096) != 0);
pI->segment_alloc_ifc = diva_get_segment_alloc_ifc (pI->segment_alloc);
ret = diva_streaming_idi_host_ifc_create (&pI->tx, number_segments, pI->segment_alloc, trace_ident);
if (ret == 0) {
pI->tx_ifc = diva_streaming_idi_host_ifc_get_access (pI->tx);
ret = diva_streaming_idi_host_rx_ifc_create (&pI->rx, number_segments, pI->segment_alloc, pI->tx, pI->tx_ifc, message_input_proc, pI, &pI->ifc, trace_ident);
if (ret == 0) {
pI->rx_ifc = diva_streaming_idi_host_rx_ifc_get_access (pI->rx);
pI->ifc.release = diva_stream_manager_release;
pI->ifc.release_stream = diva_stream_manager_release_stream;
pI->ifc.write = diva_stream_manager_write;
pI->ifc.wakeup = diva_stream_manager_wakeup;
pI->ifc.description = diva_stream_manager_description;
pI->ifc.sync = diva_stream_manager_sync_req;
pI->ifc.flush_stream = diva_stream_flush;
pI->ifc.get_tx_free = diva_stream_get_tx_free;
pI->ifc.get_tx_in_use = diva_stream_get_tx_in_use;
pI->ifc.notify_os_resource_removed = diva_notify_os_resource_removed;
pI->rx_proc = rx;
pI->rx_proc_context = rx_context;
*ifc = &pI->ifc;
ret = DivaStreamingIdiResultOK;
} else {
DBG_ERR(("failed to create rx stream [%s]", trace_ident))
}
} else {
DBG_ERR(("failed to create tx stream [%s]", trace_ident))
}
} else {
DBG_ERR(("failed to create segment alloc [%s]", trace_ident))
}
}
if (ret != 0)
diva_stream_manager_release (&pI->ifc);
return (ret);
}
static int message_input_proc (void* user_context, dword message, dword length, const diva_streaming_vector_t* v, dword nr_v) {
diva_stream_manager_t* pI = (diva_stream_manager_t*)user_context;
return (pI->rx_proc (pI->rx_proc_context, message, length, v, nr_v));
}
static diva_streaming_idi_result_t diva_stream_manager_release (struct _diva_stream* ifc) {
if (ifc != 0) {
diva_stream_manager_t* pI = DIVAS_CONTAINING_RECORD(ifc, diva_stream_manager_t, ifc);
if (pI->rx != 0)
pI->rx_ifc->release (pI->rx);
if (pI->tx != 0)
pI->tx_ifc->release (pI->tx);
if (pI->segment_alloc != 0 && pI->user_segment_alloc == 0)
pI->segment_alloc_ifc->release (&pI->segment_alloc);
diva_os_free (0, pI);
}
return (DivaStreamingIdiResultOK);
}
static diva_streaming_idi_result_t diva_stream_manager_release_stream (struct _diva_stream* ifc) {
if (ifc != 0) {
diva_stream_manager_t* pI = DIVAS_CONTAINING_RECORD(ifc, diva_stream_manager_t, ifc);
return (pI->tx_ifc->release_stream (pI->tx));
}
return (DivaStreamingIdiResultError);
}
static diva_streaming_idi_result_t diva_stream_manager_write (struct _diva_stream* ifc, dword message, const void* data, dword length) {
diva_stream_manager_t* pI = DIVAS_CONTAINING_RECORD(ifc, diva_stream_manager_t, ifc);
return (pI->tx_ifc->write_message (pI->tx, message, data, length));
}
static diva_streaming_idi_result_t diva_stream_manager_wakeup (struct _diva_stream* ifc) {
diva_stream_manager_t* pI = DIVAS_CONTAINING_RECORD(ifc, diva_stream_manager_t, ifc);
return (pI->rx_ifc->wakeup (pI->rx));
}
const byte* diva_stream_manager_description (struct _diva_stream* ifc, const byte* addie, byte addielen) {
diva_stream_manager_t* pI = DIVAS_CONTAINING_RECORD(ifc, diva_stream_manager_t, ifc);
byte length = 4, len_tx, len_rx;
len_tx = pI->tx_ifc->description (pI->tx, &pI->description[length], sizeof(pI->description)-length);
if (len_tx != 0) {
length += len_tx;
len_rx = pI->rx_ifc->description (pI->rx, &pI->description[length], sizeof(pI->description)-length);
if (len_rx != 0) {
length += len_rx;
pI->description[0] = length-1; /* Structure length */
pI->description[1] = 0; /* Request */
pI->description[2] = len_rx+len_tx+1; /* Structure length */
pI->description[3] = 0; /* Version */
if (addie != 0 && addielen != 0) {
byte* description = &pI->description[0];
byte* start = &description[3];
start[0] |= 2U;
start = start + start[-1];
memcpy (start, addie, addielen);
start += addielen;
*start++ = 0;
description[2] += addielen+1;
description[0] += addielen+1;
length += addielen+1;
}
DBG_TRC(("description length %u [%s]", length, pI->trace_ident))
DBG_BLK(((void*)pI->description, length))
return (&pI->description[0]);
}
}
return (0);
}
static diva_streaming_idi_result_t diva_stream_manager_sync_req (struct _diva_stream* ifc, dword ident) {
diva_stream_manager_t* pI = DIVAS_CONTAINING_RECORD(ifc, diva_stream_manager_t, ifc);
return (pI->tx_ifc->sync (pI->tx, ident));
}
static diva_streaming_idi_result_t diva_stream_flush (struct _diva_stream* ifc) {
diva_stream_manager_t* pI = DIVAS_CONTAINING_RECORD(ifc, diva_stream_manager_t, ifc);
return (pI->tx_ifc->update_remote (pI->tx) == 0 ? DivaStreamingIdiResultOK : DivaStreamingIdiResultError);
}
static dword diva_stream_get_tx_free (const struct _diva_stream* ifc) {
diva_stream_manager_t* pI = DIVAS_CONTAINING_RECORD(ifc, diva_stream_manager_t, ifc);
return (pI->tx_ifc->get_free (pI->tx));
}
static dword diva_stream_get_tx_in_use (const struct _diva_stream* ifc) {
const diva_stream_manager_t* pI = DIVAS_CONTAINING_RECORD(ifc, const diva_stream_manager_t, ifc);
return (pI->tx_ifc->get_in_use (pI->tx));
}
static void diva_notify_os_resource_removed (struct _diva_stream* ifc) {
diva_stream_manager_t* pI = DIVAS_CONTAINING_RECORD(ifc, diva_stream_manager_t, ifc);
if (pI->segment_alloc != 0) {
pI->segment_alloc_ifc->resource_removed (pI->segment_alloc);
}
}
dword diva_streaming_read_vector_data (const diva_streaming_vector_t* v, int nr_v, dword *vector_offset, dword *vector_position, byte* dst, dword length) {
dword to_copy;
dword count;
for (count = 0; vector_offset[0] < ((dword)nr_v) && length != 0;) {
to_copy = MIN((v[vector_offset[0]].length - vector_position[0]), length);
if (dst != 0) {
const byte* tmp = v[vector_offset[0]].data;
memcpy (dst, &tmp[vector_position[0]], to_copy);
dst += to_copy;
}
length -= to_copy;
count += to_copy;
if (v[vector_offset[0]].length == vector_position[0]+to_copy) {
vector_offset[0]++;
vector_position[0]=0;
} else {
vector_position[0] += to_copy;
}
}
return (count);
}
dword diva_streaming_get_indication_data (dword handle, dword message, dword length, const diva_streaming_vector_t* v, int nr_v, byte* pInd, diva_streaming_vector_t* vind, int *pvind_nr) {
dword vector_offset = (byte)handle;
dword vector_position = handle >> 8;
byte Ind = (byte)(message >> 8);
byte header[4];
dword indication_data_length;
int dst_nr_v = *pvind_nr;
int i;
if ((Ind & 0x0f) == 8 /* N_DATA */) {
*pInd = Ind;
for (i = 0; i < nr_v; i++) {
vind[i] = v[i];
}
*pvind_nr = nr_v;
return (0);
}
/*
Combined indication
data[0] = Ind;
data[1] = IndCh;
data[2] = (byte)length;
data[3] = (byte)(length >> 8);
*/
if (vector_offset >= ((dword)nr_v) || vector_position >= v[vector_offset].length) {
DBG_ERR(("%s at %d wrong combined indication format", __FILE__, __LINE__))
*pInd = 0;
return (0);
}
{
const byte* tmp = v[vector_offset].data;
if (tmp[vector_position] == 0) {
DBG_ERR(("%s at %d wrong combined indication format", __FILE__, __LINE__))
*pInd = 0;
return (0);
}
}
if (diva_streaming_read_vector_data (v, nr_v, &vector_offset, &vector_position, header, sizeof(header)) != sizeof(header)) {
DBG_ERR(("%s at %d wrong combined indication format", __FILE__, __LINE__))
*pInd = 0;
return (0);
}
indication_data_length = ((word)header[2] | (word)header[3] << 8);
for (i = 0; i < dst_nr_v && indication_data_length != 0; i++) {
const byte* tmp = v[vector_offset].data;
vind[i].data = &tmp[vector_position];
vind[i].length = MIN((v[vector_offset].length - vector_position), indication_data_length);
*pvind_nr = i + 1;
indication_data_length -= vind[i].length;
if (diva_streaming_read_vector_data (v, nr_v, &vector_offset, &vector_position, 0, vind[i].length) != vind[i].length) {
DBG_ERR(("%s at %d wrong combined indication format", __FILE__, __LINE__))
*pInd = 0;
return (0);
}
}
if (indication_data_length != 0) {
DBG_ERR(("%s at %d wrong combined indication format", __FILE__, __LINE__))
*pInd = 0;
return (0);
}
*pInd = header[0];
{
const byte* tmp = v[vector_offset].data;
if (tmp[vector_position] == 0) {
return (0);
}
}
return (vector_offset | (vector_position << 8));
}

View File

@ -0,0 +1,84 @@
/*
*
Copyright (c) Dialogic (R) 2009 - 2010
*
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters.
*
Dialogic (R) File Revision : 1.9
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __DIVA_STREAMING_MANAGER_H__
#define __DIVA_STREAMING_MANAGER_H__
struct _diva_streaming_vector;
struct _diva_segment_alloc;
typedef struct _diva_stream {
diva_streaming_idi_result_t (*release)(struct _diva_stream* ifc); /**< destroy stream */
diva_streaming_idi_result_t (*release_stream)(struct _diva_stream* ifc); /**< destroy stream */
diva_streaming_idi_result_t (*write)(struct _diva_stream* ifc, dword message, const void* data, dword length); /**< write data to stream */
diva_streaming_idi_result_t (*wakeup)(struct _diva_stream* ifc);
const byte* (*description)(struct _diva_stream* ifc, const byte* addie, byte addielength);
diva_streaming_idi_result_t (*sync)(struct _diva_stream* ifc, dword ident);
diva_streaming_idi_result_t (*flush_stream)(struct _diva_stream* ifc);
dword (*get_tx_free)(const struct _diva_stream* ifc);
dword (*get_tx_in_use)(const struct _diva_stream* ifc);
void (*notify_os_resource_removed)(struct _diva_stream* ifc);
} diva_stream_t;
/*
Message field length one byte
*/
#define DIVA_STREAM_MESSAGE_TX_DATA 0x00000000 /** Tx data */
#define DIVA_STREAM_MESSAGE_TX_DATA_ACK 0x00000001 /** Tx data with ack */
#define DIVA_STREAM_MESSAGE_TX_IDI_REQUEST 0x00000002 /** Tx IDI request, request is passed in bits 8...15 */
#define DIVA_STREAM_MESSAGE_RX_DATA 0x00000000 /** Received data */
#define DIVA_STREAM_MESSAGE_RX_TX_FREE 0x00000001 /** Tx space available */
#define DIVA_STREAM_MESSAGE_RX_TX_ACK 0x00000002 /** Received Tx Ack message */
#define DIVA_STREAM_MESSAGE_INIT 0x00000003 /** Stream init complete */
#define DIVA_STREAM_MESSAGE_SYNC_ACK 0x00000004 /** Received stream sync ack */
#define DIVA_STREAM_MESSAGE_RELEASE_ACK 0x00000005 /** Received stream release acknowledge */
#define DIVA_STREAM_MESSAGE_INIT_ERROR 0x00000007 /** Stream init error */
#define DIVA_STREAM_MESSAGE_RELEASED 0x00000008 /** Not message, used internally */
#define DIVA_STREAMING_MANAGER_HOST_USER_MODE_STREAM 0x40000000U
#define DIVA_STREAMING_MANAGER_TX_COUNTER_IN_TX_PAGE 0x20000000U /* Tx counter is located at end of TX page */
diva_streaming_idi_result_t diva_stream_create_with_user_segment_alloc (struct _diva_stream** ifc,
void* os_context,
dword length,
diva_streaming_idi_rx_notify_user_proc_t rx,
void* rx_context,
const char* trace_ident,
struct _diva_segment_alloc* user_segment_alloc);
diva_streaming_idi_result_t diva_stream_create (struct _diva_stream** ifc,
void* os_context,
dword length,
diva_streaming_idi_rx_notify_user_proc_t rx,
void* rx_context,
const char* trace_ident);
dword diva_streaming_read_vector_data (const diva_streaming_vector_t* v, int nr_v, dword *vector_offset, dword *vector_position, byte* dst, dword length);
dword diva_streaming_get_indication_data (dword handle, dword message, dword length, const diva_streaming_vector_t* v, int nr_v, byte* pInd, diva_streaming_vector_t* vind, int *pvind_nr);
#endif

View File

@ -0,0 +1,71 @@
/*
*
Copyright (c) Dialogic (R) 2009 - 2010
*
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters.
*
Dialogic (R) File Revision : 1.9
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "platform.h"
#include "pc.h"
#include "diva_streaming_messages.h"
int diva_streaming_idi_supported_ind (byte idiInd, dword length, const byte* data) {
byte Ind = idiInd & 0x0f;
if (likely(Ind == N_DATA))
return (1);
if (Ind == N_UDATA && length != 0) {
switch (*data) {
case UDATA_INDICATION_DTMF_DIGITS_SENT:
case UDATA_INDICATION_DTMF_DIGITS_RECEIVED:
case UDATA_INDICATION_MIXER_TAP_DATA:
case UDATA_INDICATION_RTCP_PACKET:
case UDATA_INDICATION_RTCP_GENERATED:
case UDATA_INDICATION_RTCP_ACCEPTED:
case UDATA_INDICATION_FEC_PACKET:
return (1);
}
}
return (0);
}
int diva_streaming_idi_supported_req (byte idiReq, dword length, const byte* data) {
byte Req = idiReq & 0x0f;
if (likely(Req == N_DATA))
return (1);
if (Req == N_UDATA && length != 0) {
switch (*data) {
case UDATA_REQUEST_SEND_DTMF_DIGITS:
case UDATA_REQUEST_MIXER_TAP_DATA:
case UDATA_REQUEST_RTCP_PACKET:
case UDATA_REQUEST_RTCP_GENERATE:
case UDATA_REQUEST_RTCP_ACCEPT:
case UDATA_REQUEST_FEC_PACKET:
return (1);
}
}
return (0);
}

View File

@ -0,0 +1,101 @@
/*
*
Copyright (c) Dialogic (R) 2009 - 2010
*
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters.
*
Dialogic (R) File Revision : 1.9
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __DIVA_STREAMING_MESSAGES_H__
#define __DIVA_STREAMING_MESSAGES_H__
/*
* Tx direction (to IDI)
*/
#define DIVA_STREAMING_IDI_SYSTEM_MESSAGE 0x80000000U
#define DIVA_STREAMING_IDI_RX_ACK_MSG 0x02 /* Ack processed by host data */
#define DIVA_STREAMING_IDI_SYNC_REQ 0x03 /* Sync request */
#define DIVA_STREAMING_IDI_RELEASE 0x04 /* Release stream */
#define DIVA_STREAMING_IDI_SET_DEBUG_IDENT 0x05 /* Set debug ident */
#define DIVA_STREAMING_IDI_TX_REQUEST 0x07
/*
* Rx direction (to host)
*/
#define DIVA_STREAMING_IDI_TX_INIT_MSG 0x01 /* Init message, created version, counter address */
#define DIVA_STREAMING_IDI_TX_INIT_MSG_LENGTH 15
#define DIVA_STREAMING_IDI_TX_ACK_MSG 0x02 /* Ack processed by tx data */
#define DIVA_STREAMING_IDI_TX_ACK_MSG_LENGTH 0x09
#define DIVA_STREAMING_IDI_TX_SYNC_ACK 0x03 /* Sync request acknowledge */
#define DIVA_STREAMING_IDI_TX_SYNC_ACK_LENGTH 0x0a
#define DIVA_STREAMING_IDI_RELEASE_ACK 0x04
#define DIVA_STREAMING_IDI_RELEASE_ACK_LENGTH 0x08
#define DIVA_STREAMING_IDI_TX_INIT_ERROR 0x05
#define DIVA_STREAMING_IDI_TX_INIT_ERROR_LENGTH 0x0a
#ifndef UDATA_REQUEST_SEND_DTMF_DIGITS
#define UDATA_REQUEST_SEND_DTMF_DIGITS 16
#endif
#ifndef UDATA_INDICATION_DTMF_DIGITS_SENT
#define UDATA_INDICATION_DTMF_DIGITS_SENT 16
#endif
#ifndef UDATA_INDICATION_DTMF_DIGITS_RECEIVED
#define UDATA_INDICATION_DTMF_DIGITS_RECEIVED 17
#endif
#ifndef UDATA_REQUEST_MIXER_TAP_DATA
#define UDATA_REQUEST_MIXER_TAP_DATA 27
#endif
#ifndef UDATA_INDICATION_MIXER_TAP_DATA
#define UDATA_INDICATION_MIXER_TAP_DATA 27
#endif
#ifndef UDATA_REQUEST_RTCP_PACKET
#define UDATA_REQUEST_RTCP_PACKET 67
#endif
#ifndef UDATA_INDICATION_RTCP_PACKET
#define UDATA_INDICATION_RTCP_PACKET 67
#endif
#ifndef UDATA_REQUEST_RTCP_GENERATE
#define UDATA_REQUEST_RTCP_GENERATE 68
#endif
#ifndef UDATA_INDICATION_RTCP_GENERATED
#define UDATA_INDICATION_RTCP_GENERATED 68
#endif
#ifndef UDATA_REQUEST_RTCP_ACCEPT
#define UDATA_REQUEST_RTCP_ACCEPT 69
#endif
#ifndef UDATA_INDICATION_RTCP_ACCEPTED
#define UDATA_INDICATION_RTCP_ACCEPTED 69
#endif
#ifndef UDATA_REQUEST_FEC_PACKET
#define UDATA_REQUEST_FEC_PACKET 70
#endif
#ifndef UDATA_INDICATION_FEC_PACKET
#define UDATA_INDICATION_FEC_PACKET 70
#endif
int diva_streaming_idi_supported_ind (byte idiInd, dword length, const byte* data);
int diva_streaming_idi_supported_req (byte idiReq, dword length, const byte* data);
#endif

View File

@ -0,0 +1,36 @@
/*
*
Copyright (c) Dialogic (R) 2009 - 2010
*
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters.
*
Dialogic (R) File Revision : 1.9
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __DIVA_STREAMING_RESULT_H__
#define __DIVA_STREAMING_RESULT_H__
typedef enum {
DivaStreamingIdiResultOK = 0,
DivaStreamingIdiResultError = -1,
DivaStreamingIdiResultBusy = -2
} diva_streaming_idi_result_t;
#endif

View File

@ -0,0 +1,36 @@
/*
*
Copyright (c) Dialogic (R) 2009 - 2010
*
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters.
*
Dialogic (R) File Revision : 1.9
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __DIVA_STREAMING_VECTOR_H__
#define __DIVA_STREAMING_VECTOR_H__
typedef struct _diva_streaming_vector {
const void* data;
dword length;
} diva_streaming_vector_t;
typedef int (*diva_streaming_idi_rx_notify_user_proc_t)(void* user_context, dword message, dword length, const struct _diva_streaming_vector* v, dword nr_v);
#endif

932
divastreaming/pc.h Executable file
View File

@ -0,0 +1,932 @@
/*
*
Copyright (c) Dialogic (R) 2009 - 2010
*
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters.
*
Dialogic (R) File Revision : 1.9
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef PC_H_INCLUDED /* { */
#define PC_H_INCLUDED
/*------------------------------------------------------------------*/
/* buffer definition */
/*------------------------------------------------------------------*/
typedef struct {
word length; /* length of data/parameter field */
byte P[270]; /* data/parameter field */
} PBUFFER;
/*------------------------------------------------------------------*/
/* dual port ram structure */
/*------------------------------------------------------------------*/
struct dual
{
byte Req; /* request register */
byte ReqId; /* request task/entity identification */
byte Rc; /* return code register */
byte RcId; /* return code task/entity identification */
byte Ind; /* Indication register */
byte IndId; /* Indication task/entity identification */
byte IMask; /* Interrupt Mask Flag */
byte RNR; /* Receiver Not Ready (set by PC) */
byte XLock; /* XBuffer locked Flag */
byte Int; /* ISDN-S interrupt */
byte ReqCh; /* Channel field for layer-3 Requests */
byte RcCh; /* Channel field for layer-3 Returncodes */
byte IndCh; /* Channel field for layer-3 Indications */
byte MInd; /* more data indication field */
word MLength; /* more data total packet length */
byte ReadyInt; /* request field for ready interrupt */
byte SWReg; /* Software register for special purposes */
byte Reserved[11]; /* reserved space */
byte InterfaceType; /* interface type 1=16K interface */
word Signature; /* ISDN-S adapter Signature (GD) */
PBUFFER XBuffer; /* Transmit Buffer */
PBUFFER RBuffer; /* Receive Buffer */
};
/*------------------------------------------------------------------*/
/* SWReg Values (0 means no command) */
/*------------------------------------------------------------------*/
#define SWREG_DIE_WITH_LEDON 0x01
#define SWREG_HALT_CPU 0x02 /* Push CPU into a while(1) loop */
/*------------------------------------------------------------------*/
/* Id Fields Coding */
/*------------------------------------------------------------------*/
#define IDI_ID_MASK 0xe0 /* Mask for the ID field */
#define GL_ERR_ID 0x1f /* ID for error reporting on global requests*/
#define DSIG_ID 0x00 /* ID for D-channel signaling */
#define NL_ID 0x20 /* ID for network-layer access (B or D) */
#define BLLC_ID 0x60 /* ID for B-channel link level access */
#define TASK_ID 0x80 /* ID for dynamic user tasks */
#define TIMER_ID 0xa0 /* ID for timer task */
#define TEL_ID 0xc0 /* ID for telephone support */
#define MAN_ID 0xe0 /* ID for management */
/*------------------------------------------------------------------*/
/* ASSIGN and REMOVE requests are the same for all entities */
/*------------------------------------------------------------------*/
#define ASSIGN 0x01
#define UREMOVE 0xfe /* without return code */
#define REMOVE 0xff
/*------------------------------------------------------------------*/
/* Timer Interrupt Task Interface */
/*------------------------------------------------------------------*/
#define ASSIGN_TIM 0x01
#define REMOVE_TIM 0xff
/*------------------------------------------------------------------*/
/* dynamic user task interface */
/*------------------------------------------------------------------*/
#define ASSIGN_TSK 0x01
#define REMOVE_TSK 0xff
#define LOAD 0xf0
#define RELOCATE 0xf1
#define START 0xf2
#define LOAD2 0xf3
#define RELOCATE2 0xf4
/*------------------------------------------------------------------*/
/* dynamic user task messages */
/*------------------------------------------------------------------*/
#define TSK_B2 0x0000
#define TSK_WAKEUP 0x2000
#define TSK_TIMER 0x4000
#define TSK_TSK 0x6000
#define TSK_PC 0xe000
/*------------------------------------------------------------------*/
/* LL management primitives */
/*------------------------------------------------------------------*/
#define ASSIGN_LL 1 /* assign logical link */
#define REMOVE_LL 0xff /* remove logical link */
/*------------------------------------------------------------------*/
/* LL service primitives */
/*------------------------------------------------------------------*/
#define LL_UDATA 1 /* link unit data request/indication */
#define LL_ESTABLISH 2 /* link establish request/indication */
#define LL_RELEASE 3 /* link release request/indication */
#define LL_DATA 4 /* data request/indication */
#define LL_LOCAL 5 /* switch to local operation (COM only) */
#define LL_DATA_PEND 5 /* data pending indication (SDLC SHM only) */
#define LL_REMOTE 6 /* switch to remote operation (COM only) */
#define LL_TEST 8 /* link test request */
#define LL_MDATA 9 /* more data request/indication */
#define LL_BUDATA 10 /* broadcast unit data request/indication */
#define LL_XID 12 /* XID command request/indication */
#define LL_XID_R 13 /* XID response request/indication */
/*------------------------------------------------------------------*/
/* NL service primitives */
/*------------------------------------------------------------------*/
#define N_MDATA 1 /* more data to come REQ/IND */
#define N_CONNECT 2 /* OSI N-CONNECT REQ/IND */
#define N_CONNECT_ACK 3 /* OSI N-CONNECT CON/RES */
#define N_DISC 4 /* OSI N-DISC REQ/IND */
#define N_DISC_ACK 5 /* OSI N-DISC CON/RES */
#define N_RESET 6 /* OSI N-RESET REQ/IND */
#define N_RESET_ACK 7 /* OSI N-RESET CON/RES */
#define N_DATA 8 /* OSI N-DATA REQ/IND */
#define N_EDATA 9 /* OSI N-EXPEDITED DATA REQ/IND */
#define N_UDATA 10 /* OSI D-UNIT-DATA REQ/IND */
#define N_BDATA 11 /* BROADCAST-DATA REQ/IND */
#define N_DATA_ACK 12 /* data ack ind for D-bit procedure */
#define N_EDATA_ACK 13 /* data ack ind for INTERRUPT */
#define N_XON 15 /* clear RNR state */
#define N_COMBI_IND N_XON /* combined indication */
#define N_Q_BIT 0x10 /* Q-bit for req/ind */
#define N_M_BIT 0x20 /* M-bit for req/ind */
#define N_D_BIT 0x40 /* D-bit for req/ind */
/*------------------------------------------------------------------*/
/* Signaling management primitives */
/*------------------------------------------------------------------*/
#define ASSIGN_SIG 1 /* assign signaling task */
#define UREMOVE_SIG 0xfe /* remove signaling task without return code*/
#define REMOVE_SIG 0xff /* remove signaling task */
/*------------------------------------------------------------------*/
/* Signaling service primitives */
/*------------------------------------------------------------------*/
#define CALL_REQ 1 /* call request */
#define CALL_CON 1 /* call confirmation */
#define CALL_IND 2 /* incoming call connected */
#define LISTEN_REQ 2 /* listen request */
#define HANGUP 3 /* hangup request/indication */
#define SUSPEND 4 /* call suspend request/confirm */
#define RESUME 5 /* call resume request/confirm */
#define SUSPEND_REJ 6 /* suspend rejected indication */
#define USER_DATA 8 /* user data for user to user signaling */
#define CONGESTION 9 /* network congestion indication */
#define INDICATE_REQ 10 /* request to indicate an incoming call */
#define INDICATE_IND 10 /* indicates that there is an incoming call */
#define CALL_RES 11 /* accept an incoming call */
#define CALL_ALERT 12 /* send ALERT for incoming call */
#define INFO_REQ 13 /* INFO request */
#define INFO_IND 13 /* INFO indication */
#define REJECT 14 /* reject an incoming call */
#define RESOURCES 15 /* reserve B-Channel hardware resources */
#define HW_CTRL 16 /* B-Channel hardware IOCTL req/ind */
#define TEL_CTRL 16 /* Telephone control request/indication */
#define STATUS_REQ 17 /* Request D-State (returned in INFO_IND) */
#define FAC_REG_REQ 18 /* 1TR6 connection independent fac reg */
#define FAC_REG_ACK 19 /* 1TR6 fac registration acknowledge */
#define FAC_REG_REJ 20 /* 1TR6 fac registration reject */
#define CALL_COMPLETE 21/* send a CALL_PROC for incoming call */
#define SW_CTRL 22 /* extended software features */
#define REGISTER_REQ 23 /* Q.931 connection independent reg req */
#define REGISTER_IND 24 /* Q.931 connection independent reg ind */
#define FACILITY_REQ 25 /* Q.931 connection independent fac req */
#define FACILITY_IND 26 /* Q.931 connection independent fac ind */
#define NCR_INFO_REQ 27 /* INFO_REQ with NULL CR */
#define GCR_MIM_REQ 28 /* MANAGEMENT_INFO_REQ with global CR */
#define SIG_CTRL 29 /* Control for Signalling Hardware */
#define DSP_CTRL 30 /* Control for DSPs */
#define LAW_REQ 31 /* Law config request for (returns info_i) */
#define SPID_CTRL 32 /* Request/indication SPID related */
#define NCR_FACILITY 33 /* Request/indication with NULL/DUMMY CR */
#define CALL_HOLD 34 /* Request/indication to hold a CALL */
#define CALL_RETRIEVE 35 /* Request/indication to retrieve a CALL */
#define CALL_HOLD_ACK 36 /* OK of hold a CALL */
#define CALL_RETRIEVE_ACK 37 /* OK of retrieve a CALL */
#define CALL_HOLD_REJ 38 /* Reject of hold a CALL */
#define CALL_RETRIEVE_REJ 39 /* Reject of retrieve a call */
#define GCR_RESTART 40 /* Send/Receive Restart message */
#define S_SERVICE 41 /* Send/Receive Supplementary Service */
#define S_SERVICE_REJ 42 /* Reject Supplementary Service indication */
#define S_SUPPORTED 43 /* Req/Ind to get Supported Services */
#define STATUS_ENQ 44 /* Req to send the D-ch request if !state0 */
#define CALL_GUARD 45 /* Req/Ind to use the FLAGS_CALL_OUTCHECK */
#define CALL_GUARD_HP 46 /* Call Guard function to reject a call */
#define CALL_GUARD_IF 47 /* Call Guard function, inform the appl */
#define SSEXT_REQ 48 /* Supplem.Serv./QSIG specific request */
#define SSEXT_IND 49 /* Supplem.Serv./QSIG specific indication */
/* reserved commands for the US protocols */
#define INT_3PTY_NIND 50 /* US specific indication */
#define INT_CF_NIND 51 /* US specific indication */
#define INT_3PTY_DROP 52 /* US specific indication */
#define INT_MOVE_CONF 53 /* US specific indication */
#define INT_MOVE_RC 54 /* US specific indication */
#define INT_MOVE_FLIPPED_CONF 55 /* US specific indication */
#define INT_X5NI_OK 56 /* internal transfer OK indication */
#define INT_XDMS_START 57 /* internal transfer OK indication */
#define INT_XDMS_STOP 58 /* internal transfer finish indication */
#define INT_XDMS_STOP2 59 /* internal transfer send FA */
#define INT_CUSTCONF_REJ 60 /* internal conference reject */
#define INT_CUSTXFER 61 /* internal transfer request */
#define INT_CUSTX_NIND 62 /* internal transfer ack */
#define INT_CUSTXREJ_NIND 63 /* internal transfer rej */
#define INT_X5NI_CF_XFER 64 /* internal transfer OK indication */
#define VSWITCH_REQ 65 /* communication between protocol and */
#define VSWITCH_IND 66 /* capifunctions for D-CH-switching */
#define MWI_POLL 67 /* Message Waiting Status Request fkt */
#define CALL_PEND_NOTIFY 68 /* notify capi to set new listen */
#define DO_NOTHING 69 /* dont do somethin if you get this */
#define INT_CT_REJ 70 /* ECT rejected internal command */
#define CALL_HOLD_COMPLETE 71 /* In NT Mode indicate hold complete */
#define CALL_RETRIEVE_COMPLETE 72 /* In NT Mode indicate retrieve complete */
#define RESERVE_REQ 73 /* Request to reserve resources */
#define RESERVE_IND 73 /* Indication for granted resources */
/*------------------------------------------------------------------*/
/* management service primitives */
/*------------------------------------------------------------------*/
#define MAN_READ 2
#define MAN_WRITE 3
#define MAN_EXECUTE 4
#define MAN_EVENT_ON 5
#define MAN_EVENT_OFF 6
#define MAN_LOCK 7
#define MAN_UNLOCK 8
#define MAN_INFO_IND 2
#define MAN_EVENT_IND 3
#define MAN_TRACE_IND 4
#define MAN_COMBI_IND 9
#define MAN_ESC 0x80
/*------------------------------------------------------------------*/
/* return code coding */
/*------------------------------------------------------------------*/
#define UNKNOWN_COMMAND 0x01 /* unknown command */
#define WRONG_COMMAND 0x02 /* wrong command */
#define WRONG_ID 0x03 /* unknown task/entity id */
#define WRONG_CH 0x04 /* wrong task/entity id */
#define UNKNOWN_IE 0x05 /* unknown information el. */
#define WRONG_IE 0x06 /* wrong information el. */
#define OUT_OF_RESOURCES 0x07 /* ISDN-S card out of res. */
#define OUT_OF_LICENSES 0x08 /* ISDN-S card out of res. */
#define ISDN_GUARD_REJ 0x09 /* ISDN-Guard SuppServ rej */
#define N_FLOW_CONTROL 0x10 /* Flow-Control, retry */
#define ASSIGN_RC 0xe0 /* ASSIGN acknowledgement */
#define ASSIGN_OK 0xef /* ASSIGN OK */
#define OK_FC 0xfc /* Flow-Control RC */
#define READY_INT 0xfd /* Ready interrupt */
#define TIMER_INT 0xfe /* timer interrupt */
#define OK 0xff /* command accepted */
/*------------------------------------------------------------------*/
/* information elements */
/*------------------------------------------------------------------*/
#define SHIFT 0x90 /* codeset shift */
#define MORE 0xa0 /* more data */
#define SDNCMPL 0xa1 /* sending complete */
#define CL 0xb0 /* congestion level */
/* codeset 0 */
#define SMSG 0x00 /* segmented message */
#define BC 0x04 /* Bearer Capability */
#define CAU 0x08 /* cause */
#define CAD 0x0c /* Connected address */
#define CAI 0x10 /* call identity */
#define CHI 0x18 /* channel identification */
#define LLI 0x19 /* logical link id */
#define CHA 0x1a /* charge advice */
#define FTY 0x1c /* Facility */
#define DT 0x29 /* ETSI date/time */
#define KEY 0x2c /* keypad information element */
#define UID 0x2d /* User id information element */
#define DSP 0x28 /* display */
#define SIG 0x34 /* signalling hardware control */
#define OAD 0x6c /* origination address */
#define OSA 0x6d /* origination sub-address */
#define CPN 0x70 /* called party number */
#define DSA 0x71 /* destination sub-address */
#define RDX 0x73 /* redirecting number extended */
#define RDN 0x74 /* redirecting number */
#define RIN 0x76 /* redirection number */
#define IUP 0x76 /* VN6 rerouter->PCS (codeset 6) */
#define IPU 0x77 /* VN6 PCS->rerouter (codeset 6) */
#define RI 0x79 /* restart indicator */
#if defined(MIE)
#undef MIE
#endif
#define MIE 0x7a /* management info element */
#define LLC 0x7c /* low layer compatibility */
#define HLC 0x7d /* high layer compatibility */
#define UUI 0x7e /* user user information */
#define ESC 0x7f /* escape extension */
#define DLC 0x20 /* data link layer configuration */
#define NLC 0x21 /* network layer configuration */
#define REDIRECT_IE 0x22 /* redirection request/indication data */
#define REDIRECT_NET_IE 0x23 /* redirection network override data */
/* codeset 6 */
#define SIN 0x01 /* service indicator */
#define CIF 0x02 /* charging information */
#define DATE 0x03 /* date */
#define CPS 0x07 /* called party status */
#define OLINE 0x01 /* codeset 6, ANI II used in US networks - e.g. verizon - feature group D */
/*------------------------------------------------------------------*/
/* ESC information elements */
/*------------------------------------------------------------------*/
#define MSGTYPEIE 0x7a /* Messagetype info element */
#define CRIE 0x7b /* INFO info element */
#define CODESET6IE 0xec /* Tunnel for Codeset 6 IEs */
#define VSWITCHIE 0xed /* VSwitch info element */
#define SSEXTIE 0xee /* Supplem. Service info element */
#define PROFILEIE 0xef /* Profile info element */
/*------------------------------------------------------------------*/
/* Extended cause codes */
/*------------------------------------------------------------------*/
#define GUARD_ERROR 0x05
#define L1_ERROR 0x08
#define TEI_ERROR 0x09
#define L2_ERROR 0x0a
#define L3_ERROR 0x0b
#define OUT_OF_RESOURCES_ERROR 0x0c
#define OUT_OF_LICENSES_ERROR 0x0d
/*------------------------------------------------------------------*/
/* Supplementary Services Misc Defines */
/* some defines that are only used in protocol are defined in q931.h*/
/*------------------------------------------------------------------*/
#define SSTRANSPORT 0x000d
#define HOLD_NOTIFY 0x00
#define RETRIEVE_NOTIFY 0x01
#define SCS7IE_IND 0x02
#define SCNT_IND 0x03
#define CARDIDENT_IND 0x04
#define LINKIDENT_IND 0x05
#define SSTUNNEL 0x000f
#define SSIDENTIFIER 0x0010
#define CQ_PRIDENT 0x0011
#define CQ_PRCALLDETAILS 0x0012
/*------------------------------------------------------------------*/
/* TEL_CTRL contents */
/*------------------------------------------------------------------*/
#define RING_ON 0x01
#define RING_OFF 0x02
#define HANDS_FREE_ON 0x03
#define HANDS_FREE_OFF 0x04
#define ON_HOOK 0x80
#define OFF_HOOK 0x90
/* operation values used by ETSI supplementary services */
#define THREE_PTY_BEGIN 0x04
#define THREE_PTY_END 0x05
#define ECT_EXECUTE 0x06
#define ACTIVATION_DIVERSION 0x07
#define DEACTIVATION_DIVERSION 0x08
#define CALL_DEFLECTION 0x0D
#define INTERROGATION_DIVERSION 0x0B
#define INTERROGATION_SERV_USR_NR 0x11
#define ACTIVATION_MWI 0x20
#define DEACTIVATION_MWI 0x21
#define MWI_INDICATION 0x22
#define MWI_RESPONSE 0x23
#define CONF_BEGIN 0x28
#define CONF_ADD 0x29
#define CONF_SPLIT 0x2a
#define CONF_DROP 0x2b
#define CONF_ISOLATE 0x2c
#define CONF_REATTACH 0x2d
#define CONF_PARTYDISC 0x2e
#define CCBS_INFO_RETAIN 0x2f
#define CCBS_ERASECALLLINKAGEID 0x30
#define CCBS_STOP_ALERTING 0x31
#define CCBS_REQUEST 0x32
#define CCBS_DEACTIVATE 0x33
#define CCBS_INTERROGATE 0x34
#define CCBS_STATUS 0x35
#define CCBS_ERASE 0x36
#define CCBS_B_FREE 0x37
#define CCNR_INFO_RETAIN 0x38
#define CCBS_REMOTE_USER_FREE 0x39
#define CCNR_REQUEST 0x3a
#define CCNR_INTERROGATE 0x3b
#define CCBS_IN_SET_CB 0x3c
#define CCBS_IN_CLEAR_CB 0x3d
#define CCBS_IN_AVAILABLE 0x3e
#define GET_SUPPORTED_SERVICES 0xff
#define DIVERSION_PROCEDURE_CFU 0x70
#define DIVERSION_PROCEDURE_CFB 0x71
#define DIVERSION_PROCEDURE_CFNR 0x72
#define DIVERSION_DEACTIVATION_CFU 0x80
#define DIVERSION_DEACTIVATION_CFB 0x81
#define DIVERSION_DEACTIVATION_CFNR 0x82
#define DIVERSION_INTERROGATE_NUM 0x11
#define DIVERSION_INTERROGATE_CFU 0x60
#define DIVERSION_INTERROGATE_CFB 0x61
#define DIVERSION_INTERROGATE_CFNR 0x62
/* Service Masks */
#define SMASK_HOLD_RETRIEVE 0x00000001
#define SMASK_TERMINAL_PORTABILITY 0x00000002
#define SMASK_ECT 0x00000004
#define SMASK_3PTY 0x00000008
#define SMASK_CALL_FORWARDING 0x00000010
#define SMASK_CALL_DEFLECTION 0x00000020
#define SMASK_MCID 0x00000040
#define SMASK_CCBS 0x00000080
#define SMASK_MWI 0x00000100
#define SMASK_CCNR 0x00000200
#define SMASK_CONF 0x00000400
/* ----------------------------------------------
Types of transfers used to transfer the
information in the 'struct RC->Reserved2[8]'
The information is transferred as 2 dwords
(2 4Byte unsigned values)
First of them is the transfer type.
2^32-1 possible messages are possible in this way.
The context of the second one had no meaning
---------------------------------------------- */
#define DIVA_RC_TYPE_NONE 0x00000000
#define DIVA_RC_TYPE_REMOVE_COMPLETE 0x00000008
#define DIVA_RC_TYPE_STREAM_PTR 0x00000009
#define DIVA_RC_TYPE_CMA_PTR 0x0000000a
#define DIVA_RC_TYPE_OK_FC 0x0000000b
#define DIVA_RC_TYPE_RX_DMA 0x0000000c
/* ------------------------------------------------------
IO Control codes for IN BAND SIGNALING
------------------------------------------------------ */
#define CTRL_L1_SET_SIG_ID 5
#define CTRL_L1_SET_DAD 6
#define CTRL_L1_RESOURCES 7
/* ------------------------------------------------------ */
/* ------------------------------------------------------
Layer 2 types
------------------------------------------------------ */
#define X75T 1 /* x.75 for ttx */
#define TRF 2 /* transparent with hdlc framing */
#define TRF_IN 3 /* transparent with hdlc fr. inc. */
#define SDLC 4 /* sdlc, sna layer-2 */
#define X75 5 /* x.75 for btx */
#define LAPD 6 /* lapd (Q.921) */
#define X25_L2 7 /* x.25 layer-2 */
#define V120_L2 8 /* V.120 layer-2 protocol */
#define V42_IN 9 /* V.42 layer-2 protocol, incomming */
#define V42 10 /* V.42 layer-2 protocol */
#define MDM_ATP 11 /* AT Parser built in the L2 */
#define X75_V42BIS 12 /* x.75 with V.42bis */
#define RTPL2_IN 13 /* RTP layer-2 protocol, incomming */
#define RTPL2 14 /* RTP layer-2 protocol */
#define V120_V42BIS 15 /* V.120 asynchronous mode supporting V.42bis compression */
#define T38 16 /* T38 layer-2 protocol */
#define T38_IN 17 /* T38 layer-2 protocol */
#define LISTENER 27 /* Layer 2 to listen line */
#define MTP2 28 /* MTP2 Layer 2 */
#define PIAFS_CRC 29 /* PIAFS Layer 2 with CRC calculation at L2 */
/* ------------------------------------------------------
PIAFS DLC DEFINITIONS
------------------------------------------------------ */
#define PIAFS_64K 0x01
#define PIAFS_VARIABLE_SPEED 0x02
#define PIAFS_CHINESE_SPEED 0x04
#define PIAFS_UDATA_ABILITY_ID 0x80
#define PIAFS_UDATA_ABILITY_DCDON 0x01
#define PIAFS_UDATA_ABILITY_DDI 0x80
/*
DLC of PIAFS :
Byte | 8 7 6 5 4 3 2 1
-----+--------------------------------------------------------
0 | 0 0 1 0 0 0 0 0 Data Link Configuration
1 | X X X X X X X X Length of IE (at least 15 Bytes)
2 | 0 0 0 0 0 0 0 0 max. information field, LOW byte (not used, fix 73 Bytes)
3 | 0 0 0 0 0 0 0 0 max. information field, HIGH byte (not used, fix 73 Bytes)
4 | 0 0 0 0 0 0 0 0 address A (not used)
5 | 0 0 0 0 0 0 0 0 address B (not used)
6 | 0 0 0 0 0 0 0 0 Mode (not used, fix 128)
7 | 0 0 0 0 0 0 0 0 Window Size (not used, fix 127)
8 | X X X X X X X X XID Length, Low Byte (at least 7 Bytes)
9 | X X X X X X X X XID Length, High Byte
10 | 0 0 0 0 0 C V S PIAFS Protocol Speed configuration -> Note(1)
| S = 0 -> Protocol Speed is 32K
| S = 1 -> Protocol Speed is 64K
| V = 0 -> Protocol Speed is fixed
| V = 1 -> Protocol Speed is variable
| C = 0 -> speed setting according to standard
| C = 1 -> speed setting for chinese implementation
11 | 0 0 0 0 0 0 R T P0 - V42bis Compression enable/disable, Low Byte
| T = 0 -> Transmit Direction enable
| T = 1 -> Transmit Direction disable
| R = 0 -> Receive Direction enable
| R = 1 -> Receive Direction disable
13 | 0 0 0 0 0 0 0 0 P0 - V42bis Compression enable/disable, High Byte
14 | X X X X X X X X P1 - V42bis Dictionary Size, Low Byte
15 | X X X X X X X X P1 - V42bis Dictionary Size, High Byte
16 | X X X X X X X X P2 - V42bis String Length, Low Byte
17 | X X X X X X X X P2 - V42bis String Length, High Byte
18 | X X X X X X X X PIAFS extension length
19 | 1 0 0 0 0 0 0 0 PIAFS extension Id (0x80) - UDATA abilities
20 | U 0 0 0 0 0 0 D UDATA abilities -> Note (2)
| up to now the following Bits are defined:
| D - signal DCD ON
| U - use extensive UDATA control communication
| for DDI test application
+ Note (1): ----------+------+-----------------------------------------+
| PIAFS Protocol | Bit | |
| Speed configuration | S | Bit 1 - Protocol Speed |
| | | 0 - 32K |
| | | 1 - 64K (default) |
| | V | Bit 2 - Variable Protocol Speed |
| | | 0 - Speed is fix |
| | | 1 - Speed is variable (default) |
| | | OVERWRITES 32k Bit 1 |
| | C | Bit 3 0 - Speed Settings according to |
| | | PIAFS specification |
| | | 1 - Speed setting for chinese |
| | | PIAFS implementation |
| | | Explanation for chinese speed settings: |
| | | if Bit 3 is set the following |
| | | rules apply: |
| | | Bit1=0 Bit2=0: 32k fix |
| | | Bit1=1 Bit2=0: 64k fix |
| | | Bit1=0 Bit2=1: PIAFS is trying |
| | | to negotiate 32k is that is |
| | | not possible it tries to |
| | | negotiate 64k |
| | | Bit1=1 Bit2=1: PIAFS is trying |
| | | to negotiate 64k is that is |
| | | not possible it tries to |
| | | negotiate 32k |
+ Note (2): ----------+------+-----------------------------------------+
| PIAFS | Bit | this byte defines the usage of UDATA |
| Implementation | | control communication |
| UDATA usage | D | Bit 1 - DCD-ON signalling |
| | | 0 - no DCD-ON is signalled |
| | | (default) |
| | | 1 - DCD-ON will be signalled |
| | U | Bit 8 - DDI test application UDATA |
| | | control communication |
| | | 0 - no UDATA control |
| | | communication (default) |
| | | sets as well the DCD-ON |
| | | signalling |
| | | 1 - UDATA control communication |
| | | ATTENTION: Do not use these |
| | | setting if you |
| | | are not really |
| | | that you need it |
| | | and you know |
| | | exactly what you |
| | | are doing. |
| | | You can easily |
| | | disable any |
| | | data transfer. |
+---------------------+------+-----------------------------------------+
*/
/* ------------------------------------------------------
LISTENER DLC DEFINITIONS
------------------------------------------------------ */
#define LISTENER_FEATURE_MASK_CUMMULATIVE 0x0001
/* ------------------------------------------------------
LISTENER META-FRAME CODE/PRIMITIVE DEFINITIONS
------------------------------------------------------ */
#define META_CODE_LL_UDATA_RX 0x01
#define META_CODE_LL_UDATA_TX 0x02
#define META_CODE_LL_DATA_RX 0x03
#define META_CODE_LL_DATA_TX 0x04
#define META_CODE_LL_MDATA_RX 0x05
#define META_CODE_LL_MDATA_TX 0x06
#define META_CODE_EMPTY 0x10
#define META_CODE_LOST_FRAMES 0x11
#define META_FLAG_TRUNCATED 0x0001
/*------------------------------------------------------------------*/
/* CAPI-like profile to indicate features on LAW_REQ */
/* Please note: ANY ADDITIONS/CHANGES MUST be documented in */
/* LEODMS://process_docs/hardware/HWInfoStruct.html */
/*------------------------------------------------------------------*/
#define GL_INTERNAL_CONTROLLER_SUPPORTED 0x00000001L
#define GL_EXTERNAL_EQUIPMENT_SUPPORTED 0x00000002L
#define GL_HANDSET_SUPPORTED 0x00000004L
#define GL_DTMF_SUPPORTED 0x00000008L
#define GL_SUPPLEMENTARY_SERVICES_SUPPORTED 0x00000010L
#define GL_CHANNEL_ALLOCATION_SUPPORTED 0x00000020L
#define GL_BCHANNEL_OPERATION_SUPPORTED 0x00000040L
#define GL_LINE_INTERCONNECT_SUPPORTED 0x00000080L
#define GL_BROADBAND_EXTENSIONS_SUPPORTED 0x00000100L
#define GL_ECHO_CANCELLER_SUPPORTED 0x00000200L
#define B1_HDLC_SUPPORTED 0x00000001L
#define B1_TRANSPARENT_SUPPORTED 0x00000002L
#define B1_V110_ASYNC_SUPPORTED 0x00000004L
#define B1_V110_SYNC_SUPPORTED 0x00000008L
#define B1_T30_SUPPORTED 0x00000010L
#define B1_HDLC_INVERTED_SUPPORTED 0x00000020L
#define B1_TRANSPARENT_R_SUPPORTED 0x00000040L
#define B1_MODEM_ALL_NEGOTIATE_SUPPORTED 0x00000080L
#define B1_MODEM_ASYNC_SUPPORTED 0x00000100L
#define B1_MODEM_SYNC_HDLC_SUPPORTED 0x00000200L
#define B2_X75_SUPPORTED 0x00000001L
#define B2_TRANSPARENT_SUPPORTED 0x00000002L
#define B2_SDLC_SUPPORTED 0x00000004L
#define B2_LAPD_SUPPORTED 0x00000008L
#define B2_T30_SUPPORTED 0x00000010L
#define B2_PPP_SUPPORTED 0x00000020L
#define B2_TRANSPARENT_NO_CRC_SUPPORTED 0x00000040L
#define B2_MODEM_EC_COMPRESSION_SUPPORTED 0x00000080L
#define B2_X75_V42BIS_SUPPORTED 0x00000100L
#define B2_V120_ASYNC_SUPPORTED 0x00000200L
#define B2_V120_ASYNC_V42BIS_SUPPORTED 0x00000400L
#define B2_V120_BIT_TRANSPARENT_SUPPORTED 0x00000800L
#define B2_LAPD_FREE_SAPI_SEL_SUPPORTED 0x00001000L
#define B3_TRANSPARENT_SUPPORTED 0x00000001L
#define B3_T90NL_SUPPORTED 0x00000002L
#define B3_ISO8208_SUPPORTED 0x00000004L
#define B3_X25_DCE_SUPPORTED 0x00000008L
#define B3_T30_SUPPORTED 0x00000010L
#define B3_T30_WITH_EXTENSIONS_SUPPORTED 0x00000020L
#define B3_RESERVED_SUPPORTED 0x00000040L
#define B3_MODEM_SUPPORTED 0x00000080L
#define MANUFACTURER_FEATURE_SLAVE_CODEC 0x00000001L
#define MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS 0x00000002L
#define MANUFACTURER_FEATURE_HARDDTMF 0x00000004L
#define MANUFACTURER_FEATURE_SOFTDTMF_SEND 0x00000008L
#define MANUFACTURER_FEATURE_DTMF_PARAMETERS 0x00000010L
#define MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE 0x00000020L
#define MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD 0x00000040L
#define MANUFACTURER_FEATURE_V18 0x00000080L
#define MANUFACTURER_FEATURE_MIXER_CH_CH 0x00000100L
#define MANUFACTURER_FEATURE_MIXER_CH_PC 0x00000200L
#define MANUFACTURER_FEATURE_MIXER_PC_CH 0x00000400L
#define MANUFACTURER_FEATURE_MIXER_PC_PC 0x00000800L
#define MANUFACTURER_FEATURE_ECHO_CANCELLER 0x00001000L
#define MANUFACTURER_FEATURE_RTP 0x00002000L
#define MANUFACTURER_FEATURE_T38 0x00004000L
#define MANUFACTURER_FEATURE_TRANSP_DELIVERY_CONF 0x00008000L
#define MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL 0x00010000L
#define MANUFACTURER_FEATURE_OOB_CHANNEL 0x00020000L
#define MANUFACTURER_FEATURE_IN_BAND_CHANNEL 0x00040000L
#define MANUFACTURER_FEATURE_IN_BAND_FEATURE 0x00080000L
#define MANUFACTURER_FEATURE_PIAFS 0x00100000L
#define MANUFACTURER_FEATURE_DTMF_TONE 0x00200000L
#define MANUFACTURER_FEATURE_FAX_PAPER_FORMATS 0x00400000L
#define MANUFACTURER_FEATURE_OK_FC_LABEL 0x00800000L
#define MANUFACTURER_FEATURE_VOWN 0x01000000L
#define MANUFACTURER_FEATURE_XCONNECT 0x02000000L
#define MANUFACTURER_FEATURE_DMACONNECT 0x04000000L
#define MANUFACTURER_FEATURE_AUDIO_TAP 0x08000000L
#define MANUFACTURER_FEATURE_FAX_NONSTANDARD 0x10000000L
#define MANUFACTURER_FEATURE_SS7 0x20000000L
#define MANUFACTURER_FEATURE_MADAPTER 0x40000000L
#define MANUFACTURER_FEATURE_MEASURE 0x80000000L
#define MANUFACTURER_FEATURE2_LISTENING 0x00000001L
#define MANUFACTURER_FEATURE2_SS_DIFFCONTPOSSIBLE 0x00000002L
#define MANUFACTURER_FEATURE2_GENERIC_TONE 0x00000004L
#define MANUFACTURER_FEATURE2_COLOR_FAX 0x00000008L
#define MANUFACTURER_FEATURE2_SS_ECT_DIFFCONTPOSSIBLE 0x00000010L
#define MANUFACTURER_FEATURE2_TRANSPARENT_N_RESET 0x00000020L
/*
Following four bits are reserved for vendor specific extensions
Vendor specific extension allows values from 0x01 to 0x0e
*/
#define MANUFACTURER_FEATURE2_VENDOR_MASK_FIRST_BIT 6 /* 0x00000040L */
#define MANUFACTURER_FEATURE2_VENDOR_BITS 0x0000000fL
#define MANUFACTURER_FEATURE2_VENDOR_MASK \
(MANUFACTURER_FEATURE2_VENDOR_BITS << MANUFACTURER_FEATURE2_VENDOR_MASK_FIRST_BIT)
#define MANUFACTURER_FEATURE2_CAPTARIS_ADAPTER \
(0x00000001L << MANUFACTURER_FEATURE2_VENDOR_MASK_FIRST_BIT)
#define MANUFACTURER_FEATURE2_DIALING_CHARS_ACCEPTED 0x00000400L
#define MANUFACTURER_FEATURE2_NULL_PLCI 0x00000800L
#define MANUFACTURER_FEATURE2_X25_REVERSE_RESTART 0x00001000L
#define MANUFACTURER_FEATURE2_SOFTIP 0x00002000L
#define MANUFACTURER_FEATURE2_CLEAR_CHANNEL 0x00004000L
#define MANUFACTURER_FEATURE2_LINE_SIDE_T38 0x00008000L
#define MANUFACTURER_FEATURE2_RTP_LINE 0x00010000L
#define MANUFACTURER_FEATURE2_NO_CLOCK_LINE 0x00020000L
#define MANUFACTURER_FEATURE2_TRANSCODING 0x00040000L
#define MANUFACTURER_FEATURE2_MODEM_V34_V90 0x00080000L
#define MANUFACTURER_FEATURE2_PLUGIN_MODULATION 0x00100000L
#define MANUFACTURER_FEATURE2_FAX_V34 0x00200000L
#define MANUFACTURER_FEATURE2_MODEM_V34_LOW 0x00400000L
#define MANUFACTURER_FEATURE2_STREAMING_IDI 0x00800000L
#define RTP_PRIM_PAYLOAD_PCMU_8000 0
#define RTP_PRIM_PAYLOAD_1016_8000 1
#define RTP_PRIM_PAYLOAD_LINEAR16_8000 1
#define RTP_PRIM_PAYLOAD_G726_32_8000 2
#define RTP_PRIM_PAYLOAD_GSM_8000 3
#define RTP_PRIM_PAYLOAD_G723_8000 4
#define RTP_PRIM_PAYLOAD_DVI4_8000 5
#define RTP_PRIM_PAYLOAD_DVI4_16000 6
#define RTP_PRIM_PAYLOAD_LPC_8000 7
#define RTP_PRIM_PAYLOAD_PCMA_8000 8
#define RTP_PRIM_PAYLOAD_G722_16000 9
#define RTP_PRIM_PAYLOAD_QCELP_8000 12
#define RTP_PRIM_PAYLOAD_G728_8000 14
#define RTP_PRIM_PAYLOAD_G729_8000 18
#define RTP_PRIM_PAYLOAD_RTAUDIO_8000 26
#define RTP_PRIM_PAYLOAD_ILBC_8000 27
#define RTP_PRIM_PAYLOAD_AMR_NB_8000 28
#define RTP_PRIM_PAYLOAD_T38 29
#define RTP_PRIM_PAYLOAD_GSM_HR_8000 30
#define RTP_PRIM_PAYLOAD_GSM_EFR_8000 31
#define RTP_ADD_PAYLOAD_BASE 32
#define RTP_ADD_PAYLOAD_RED 32
#define RTP_ADD_PAYLOAD_CN_8000 33
#define RTP_ADD_PAYLOAD_DTMF 34
#define RTP_ADD_PAYLOAD_FEC 35
#define RTP_PRIM_PAYLOAD_PCMU_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_PCMU_8000)
#define RTP_PRIM_PAYLOAD_1016_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_1016_8000)
#define RTP_PRIM_PAYLOAD_LINEAR16_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_LINEAR16_8000)
#define RTP_PRIM_PAYLOAD_G726_32_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_G726_32_8000)
#define RTP_PRIM_PAYLOAD_GSM_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_GSM_8000)
#define RTP_PRIM_PAYLOAD_G723_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_G723_8000)
#define RTP_PRIM_PAYLOAD_DVI4_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_DVI4_8000)
#define RTP_PRIM_PAYLOAD_DVI4_16000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_DVI4_16000)
#define RTP_PRIM_PAYLOAD_LPC_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_LPC_8000)
#define RTP_PRIM_PAYLOAD_PCMA_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_PCMA_8000)
#define RTP_PRIM_PAYLOAD_G722_16000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_G722_16000)
#define RTP_PRIM_PAYLOAD_QCELP_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_QCELP_8000)
#define RTP_PRIM_PAYLOAD_G728_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_G728_8000)
#define RTP_PRIM_PAYLOAD_G729_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_G729_8000)
#define RTP_PRIM_PAYLOAD_RTAUDIO_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_RTAUDIO_8000)
#define RTP_PRIM_PAYLOAD_ILBC_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_ILBC_8000)
#define RTP_PRIM_PAYLOAD_AMR_NB_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_AMR_NB_8000)
#define RTP_PRIM_PAYLOAD_T38_SUPPORTED (1L << RTP_PRIM_PAYLOAD_T38)
#define RTP_PRIM_PAYLOAD_GSM_HR_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_GSM_HR_8000)
#define RTP_PRIM_PAYLOAD_GSM_EFR_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_GSM_EFR_8000)
#define RTP_ADD_PAYLOAD_RED_SUPPORTED (1L << (RTP_ADD_PAYLOAD_RED - RTP_ADD_PAYLOAD_BASE))
#define RTP_ADD_PAYLOAD_CN_8000_SUPPORTED (1L << (RTP_ADD_PAYLOAD_CN_8000 - RTP_ADD_PAYLOAD_BASE))
#define RTP_ADD_PAYLOAD_DTMF_SUPPORTED (1L << (RTP_ADD_PAYLOAD_DTMF - RTP_ADD_PAYLOAD_BASE))
#define RTP_ADD_PAYLOAD_FEC_SUPPORTED (1L << (RTP_ADD_PAYLOAD_FEC - RTP_ADD_PAYLOAD_BASE))
/*------------------------------------------------------------------*/
/* Definitions to indicate Layer 1/2/3 status on STATUS_REQ */
/*------------------------------------------------------------------*/
#define CST_STATE_LAYER_MASK 0xe000
#define CST_STATE_UP_BIT 0x1000
#define CST_STATE_UP_INSTANCES_MASK 0x0fff
#define CST_STATE_PROTOCOL_MASK 0xe03f
#define CST_STATE_LEVEL_MASK 0x0fc0
#define CST_STATE_LAYER_D_L1 0x0000
#define CST_STATE_LAYER_D_L2 0x2000
#define CST_STATE_LAYER_D_L3 0x4000
#define CST_STATE_LAYER_B_L1 0x8000
#define CST_STATE_LAYER_B_L2 0xa000
#define CST_STATE_LAYER_B_L3 0xc000
#define CST_STATE_I430(level) (CST_STATE_LAYER_D_L1 | 0x00 | ((level) << 6))
#define CST_STATE_I431(level) (CST_STATE_LAYER_D_L1 | 0x01 | ((level) << 6))
#define CST_STATE_Q921(level) (CST_STATE_LAYER_D_L2 | 0x00 | ((level) << 6))
#define CST_STATE_Q931(level) (CST_STATE_LAYER_D_L3 | 0x00 | ((level) << 6))
#define CST_STATE_CAS(level) (CST_STATE_LAYER_D_L3 | 0x01 | ((level) << 6))
#define CST_STATE_HDLC(level) (CST_STATE_LAYER_B_L1 | 0x00 | ((level) << 6))
#define CST_STATE_V110(level) (CST_STATE_LAYER_B_L1 | 0x01 | ((level) << 6))
#define CST_STATE_X75(level) (CST_STATE_LAYER_B_L2 | 0x00 | ((level) << 6))
#define CST_STATE_X25(level) (CST_STATE_LAYER_B_L3 | 0x00 | ((level) << 6))
#define CST_STATE_I430_INACTIVE (CST_STATE_I430(0x00)) /* ITU-T I.430: F1 */
#define CST_STATE_I430_TE_SENSING (CST_STATE_I430(0x04)) /* ITU-T I.430: F2 */
#define CST_STATE_I430_TE_SENSING_LOW_POWER (CST_STATE_I430(0x05)) /* ITU-T I.430: F2, low power mode */
#define CST_STATE_I430_DEACTIVATED (CST_STATE_I430(0x08)) /* ITU-T I.430: F3/G1 */
#define CST_STATE_I430_DEACTIVATED_LOW_POWER (CST_STATE_I430(0x09)) /* ITU-T I.430: F3/G1, low power mode */
#define CST_STATE_I430_TE_AWAITING_SIGNAL (CST_STATE_I430(0x10)) /* ITU-T I.430: F4 */
#define CST_STATE_I430_NT_PENDING_ACTIVATION (CST_STATE_I430(0x11)) /* ITU-T I.430: G2 */
#define CST_STATE_I430_TE_IDENTIFYING_INPUT (CST_STATE_I430(0x20)) /* ITU-T I.430: F5 */
#define CST_STATE_I430_TE_SYNCHRONIZED (CST_STATE_I430(0x22)) /* ITU-T I.430: F6 */
#define CST_STATE_I430_ACTIVATED (CST_STATE_LAYER_D_L1 | CST_STATE_UP_BIT) /* ITU-T I.430: F7/G3 */
#define CST_STATE_I430_NT_PENDING_DEACTIVATION (CST_STATE_I430(0x1f)) /* ITU-T I.430: G4 */
#define CST_STATE_I430_TE_LOSS_OF_FRAMING (CST_STATE_I430(0x21)) /* ITU-T I.430: F8 */
#define CST_STATE_I431_INACTIVE (CST_STATE_I431(0x00)) /* ITU-T I.431: F0/G0 */
#define CST_STATE_I431_OPERATIONAL (CST_STATE_LAYER_D_L1 | CST_STATE_UP_BIT) /* ITU-T I.431: F1/G1 */
#define CST_STATE_I431_REMOTE_ALARM (CST_STATE_I431(0x26)) /* ITU-T I.431: F2/G2, FC1, yellow alarm */
#define CST_STATE_I431_LOSS_OF_SIGNAL (CST_STATE_I431(0x14)) /* ITU-T I.431: F3/G3, FC2, red alarm */
#define CST_STATE_I431_LOSS_OF_FRAMING (CST_STATE_I431(0x24)) /* ITU-T I.431: F4/G4, FC3, blue alarm */
#define CST_STATE_I431_REMOTE_ALARM_CRC_ERR (CST_STATE_I431(0x25)) /* ITU-T I.431: F5/G5, FC4, yellow alarm, CRC errors */
#define CST_STATE_I431_POWER_ON (CST_STATE_I431(0x01)) /* ITU-T I.431: F6/G6 */
#define CST_STATE_I431_LOSS_OF_DOUBLEFRAMING (CST_STATE_I431(0x27)) /* */
#define CST_STATE_I431_LOSS_OF_MULTIFRAMING (CST_STATE_I431(0x28)) /* */
#define CST_STATE_I431_TS16_LOSS_OF_SIGNAL (CST_STATE_I431(0x2e)) /* All zeroes in timeslot 16 */
#define CST_STATE_I431_TS16_REMOTE_ALARM (CST_STATE_I431(0x36)) /* Remote alarm bit RS1.2 set in timeslot 16 */
#define CST_STATE_I431_TS16_ALARM_INDICATION (CST_STATE_I431(0x30)) /* Less than 4 zeroes in 2 consecutive multiframes */
#define CST_STATE_I431_TS16_LOSS_OF_MULTIFRAMING (CST_STATE_I431(0x38)) /* CAS framing pattern lost */
#define CST_STATE_I431_EXCESSIVE_ZEROES_DETECTED (CST_STATE_I431(0x1e)) /* More than 3 (HDB3) or 15 (AMI) consecutive zeroes */
#define CST_STATE_I431_TRANSMIT_LINE_SHORT (CST_STATE_I431(0x0d)) /* */
#define CST_STATE_I431_TRANSMIT_LINE_OPEN (CST_STATE_I431(0x0e)) /* */
#define CST_STATE_Q921_TEI_UNASSIGNED (CST_STATE_Q921(0x00)) /* ITU-T Q.921: 4.3 State 1/B.2 State 1 */
#define CST_STATE_Q921_ASSIGN_AWAITING_TEI (CST_STATE_Q921(0x08)) /* ITU-T Q.921: B.2 State 2 */
#define CST_STATE_Q921_ESTABLISH_AWAITING_TEI (CST_STATE_Q921(0x09)) /* ITU-T Q.921: B.2 State 3 */
#define CST_STATE_Q921_TEI_ASSIGNED (CST_STATE_Q921(0x10)) /* ITU-T Q.921: B.2 State 4 */
#define CST_STATE_Q921_AWAITING_ESTABLISHMENT (CST_STATE_Q921(0x20)) /* ITU-T Q.921: 4.3 State 2/B.2 State 5 */
#define CST_STATE_Q921_AWAITING_RELEASE (CST_STATE_Q921(0x3f)) /* ITU-T Q.921: 4.3 State 3/B.2 State 6 */
#define CST_STATE_Q921_MULTIPLE_FRAME_ESTABLISHED (CST_STATE_LAYER_D_L2 | CST_STATE_UP_BIT) /* ITU-T Q.921: 4.3 State 4/B.2 State 7 */
#define CST_STATE_Q921_TIMER_RECOVERY (CST_STATE_Q921(0x21)) /* ITU-T Q.921: B.2 State 8 */
#define CST_STATE_Q931_NULL (CST_STATE_Q931(0x00)) /* ITU-T Q.931: U0/N0 */
#define CST_STATE_Q931_CALL_INITIATED (CST_STATE_Q931(0x01)) /* ITU-T Q.931: U1/N1 */
#define CST_STATE_Q931_OVERLAP_SENDING (CST_STATE_Q931(0x02)) /* ITU-T Q.931: U2/N2 */
#define CST_STATE_Q931_OUTGOING_CALL_PROCEEDING (CST_STATE_Q931(0x03)) /* ITU-T Q.931: U3/N3 */
#define CST_STATE_Q931_CALL_DELIVERED (CST_STATE_Q931(0x04)) /* ITU-T Q.931: U4/N4 */
#define CST_STATE_Q931_CALL_PRESENT (CST_STATE_Q931(0x06)) /* ITU-T Q.931: U6/N6 */
#define CST_STATE_Q931_CALL_RECEIVED (CST_STATE_Q931(0x07)) /* ITU-T Q.931: U7/N7 */
#define CST_STATE_Q931_CONNECT_REQUEST (CST_STATE_Q931(0x08)) /* ITU-T Q.931: U8/N8 */
#define CST_STATE_Q931_INCOMING_CALL_PROCEEDING (CST_STATE_Q931(0x09)) /* ITU-T Q.931: U9/N9 */
#define CST_STATE_Q931_ACTIVE (CST_STATE_LAYER_D_L3 | CST_STATE_UP_BIT) /* ITU-T Q.931: U10/N10 */
#define CST_STATE_Q931_DISCONNECT_REQUEST (CST_STATE_Q931(0x0b)) /* ITU-T Q.931: U11/N11 */
#define CST_STATE_Q931_DISCONNECT_INDICATION (CST_STATE_Q931(0x0c)) /* ITU-T Q.931: U12/N12 */
#define CST_STATE_Q931_SUSPEND_REQUEST (CST_STATE_Q931(0x0f)) /* ITU-T Q.931: U15/N15 */
#define CST_STATE_Q931_RESUME_REQUEST (CST_STATE_Q931(0x11)) /* ITU-T Q.931: U17/N17 */
#define CST_STATE_Q931_RELEASE_REQUEST (CST_STATE_Q931(0x13)) /* ITU-T Q.931: U19/N19 */
#define CST_STATE_Q931_CALL_ABORT (CST_STATE_Q931(0x16)) /* ITU-T Q.931: N22 */
#define CST_STATE_Q931_OVERLAP_RECEIVING (CST_STATE_Q931(0x19)) /* ITU-T Q.931: U25/N25 */
#define CST_STATE_CAS_NULL (CST_STATE_CAS(0x00)) /* like ITU-T Q.931: U0/N0 */
#define CST_STATE_CAS_CALL_INITIATED (CST_STATE_CAS(0x01)) /* like ITU-T Q.931: U1/N1 */
#define CST_STATE_CAS_OVERLAP_SENDING (CST_STATE_CAS(0x02)) /* like ITU-T Q.931: U2/N2 */
#define CST_STATE_CAS_OUTGOING_CALL_PROCEEDING (CST_STATE_CAS(0x03)) /* like ITU-T Q.931: U3/N3 */
#define CST_STATE_CAS_CALL_DELIVERED (CST_STATE_CAS(0x04)) /* like ITU-T Q.931: U4/N4 */
#define CST_STATE_CAS_CALL_PRESENT (CST_STATE_CAS(0x06)) /* like ITU-T Q.931: U6/N6 */
#define CST_STATE_CAS_CALL_RECEIVED (CST_STATE_CAS(0x07)) /* like ITU-T Q.931: U7/N7 */
#define CST_STATE_CAS_CONNECT_REQUEST (CST_STATE_CAS(0x08)) /* like ITU-T Q.931: U8/N8 */
#define CST_STATE_CAS_INCOMING_CALL_PROCEEDING (CST_STATE_CAS(0x09)) /* like ITU-T Q.931: U9/N9 */
#define CST_STATE_CAS_ACTIVE (CST_STATE_LAYER_D_L3 | CST_STATE_UP_BIT) /* like ITU-T Q.931: U10/N10 */
#define CST_STATE_CAS_DISCONNECT_REQUEST (CST_STATE_CAS(0x0b)) /* like ITU-T Q.931: U11/N11 */
#define CST_STATE_CAS_DISCONNECT_INDICATION (CST_STATE_CAS(0x0c)) /* like ITU-T Q.931: U12/N12 */
#define CST_STATE_CAS_SUSPEND_REQUEST (CST_STATE_CAS(0x0f)) /* like ITU-T Q.931: U15/N15 */
#define CST_STATE_CAS_RESUME_REQUEST (CST_STATE_CAS(0x11)) /* like ITU-T Q.931: U17/N17 */
#define CST_STATE_CAS_RELEASE_REQUEST (CST_STATE_CAS(0x13)) /* like ITU-T Q.931: U19/N19 */
#define CST_STATE_CAS_CALL_ABORT (CST_STATE_CAS(0x16)) /* like ITU-T Q.931: N22 */
#define CST_STATE_CAS_OVERLAP_RECEIVING (CST_STATE_CAS(0x19)) /* like ITU-T Q.931: U25/N25 */
#define CST_STATE_CAS_LINE_IN_USE (CST_STATE_CAS(0x3b)) /* */
#define CST_STATE_CAS_LOCAL_REMOTE_BLOCKING (CST_STATE_CAS(0x3c)) /* */
#define CST_STATE_CAS_LOCAL_BLOCKING (CST_STATE_CAS(0x3d)) /* */
#define CST_STATE_CAS_REMOTE_BLOCKING (CST_STATE_CAS(0x3e)) /* */
#define CST_STATE_X75_IDLE (CST_STATE_X75(0x00)) /* */
#define CST_STATE_X75_AWAITING_ESTABLISHMENT (CST_STATE_X75(0x20)) /* */
#define CST_STATE_X75_AWAITING_RELEASE (CST_STATE_X75(0x3f)) /* */
#define CST_STATE_X75_ESTABLISHED (CST_STATE_LAYER_B_L2 | CST_STATE_UP_BIT) /* */
#define CST_STATE_X25_PACKET_LAYER_READY (CST_STATE_X25(0x01)) /* ITU-T X.25: r1 */
#define CST_STATE_X25_DTE_RESTART_REQUEST (CST_STATE_X25(0x02)) /* ITU-T X.25: r2 */
#define CST_STATE_X25_DCE_RESTART_INDICATION (CST_STATE_X25(0x03)) /* ITU-T X.25: r3 */
#define CST_STATE_X25_READY (CST_STATE_X25(0x04)) /* ITU-T X.25: p1 */
#define CST_STATE_X25_DTE_WAITING (CST_STATE_X25(0x05)) /* ITU-T X.25: p2 */
#define CST_STATE_X25_DCE_WAITING (CST_STATE_X25(0x06)) /* ITU-T X.25: p3 */
#define CST_STATE_X25_DATA_TRANSFER (CST_STATE_LAYER_B_L3 | CST_STATE_UP_BIT) /* ITU-T X.25: p4 */
#define CST_STATE_X25_CALL_COLLISION (CST_STATE_X25(0x08)) /* ITU-T X.25: p5 */
#define CST_STATE_X25_DTE_CLEAR_REQUEST (CST_STATE_X25(0x09)) /* ITU-T X.25: p6 */
#define CST_STATE_X25_DCE_CLEAR_INDICATION (CST_STATE_X25(0x0a)) /* ITU-T X.25: p7 */
#define CST_STATE_X25_FLOW_CONTROL_READY (CST_STATE_X25(0x0b)) /* ITU-T X.25: d1 */
#define CST_STATE_X25_DTE_RESET_REQUEST (CST_STATE_X25(0x0c)) /* ITU-T X.25: d2 */
#define CST_STATE_X25_DCE_RESET_REQUEST (CST_STATE_X25(0x0d)) /* ITU-T X.25: d3 */
/*------------------------------------------------------------------*/
/* virtual switching definitions */
#define VSJOIN 1
#define VSTRANSPORT 2
#define VSGETPARAMS 3
#define VSCAD 1
#define VSRXCPNAME 2
#define VSCALLSTAT 3
#define VSINVOKEID 4
#define VSCLMRKS 5
#define VSTBCTIDENT 6
#define VSETSILINKID 7
#define VSSAMECONTROLLER 8
#define VSCTBYREROUTEID 9
/* Errorcodes for VSLINKID begin */
#define VSLINKIDRRWC 1
#define VSLINKIDREJECT 2
#define VSLINKIDTIMEOUT 3
#define VSLINKIDFAILCOUNT 4
#define VSLINKIDERROR 5
/* Errorcodes for VSLINKID end */
/* -----------------------------------------------------------**
** The PROTOCOL_FEATURE_STRING in feature.h (included **
** in prstart.sx and astart.sx) defines capabilities and **
** features of the actual protocol code. It's used as a bit **
** mask. **
** The following Bits are defined: **
** -----------------------------------------------------------*/
#define PROTCAP_TELINDUS 0x0001 /* Telindus Variant of protocol code */
#define PROTCAP_MAN_IF 0x0002 /* Management interface implemented */
#define PROTCAP_V_42 0x0004 /* V42 implemented */
#define PROTCAP_V90D 0x0008 /* V.90D (implies up to 384k DSP code) */
#define PROTCAP_EXTD_FAX 0x0010 /* Extended FAX (ECM, 2D, T6, Polling) */
#define PROTCAP_EXTD_RXFC 0x0020 /* RxFC (Extd Flow Control), OOB Chnl */
#define PROTCAP_VOIP 0x0040 /* VoIP (implies up to 512k DSP code) */
#define PROTCAP_CMA_ALLPR 0x0080 /* CMA support for all NL primitives */
#define PROTCAP_64BIT_DMA 0x0100 /* 64 Bit addresses on PCI BUS DMA */
#define PROTCAP_FREE9 0x0200 /* not used */
#define PROTCAP_FREE10 0x0400 /* not used */
#define PROTCAP_FREE11 0x0800 /* not used */
#define PROTCAP_FREE12 0x1000 /* not used */
#define PROTCAP_FREE13 0x2000 /* not used */
#define PROTCAP_FREE14 0x4000 /* not used */
#define PROTCAP_EXTENSION 0x8000 /* used for future extentions */
/* -----------------------------------------------------------* */
/* Onhook data transmission ETS30065901 */
/* Message Type */
#define CALLING_NUMBER_DELIVERY 0x04
#define CALL_SETUP 0x80
#define MESSAGE_WAITING_INDICATOR 0x82
/*#define RESERVED84 0x84*/
/*#define RESERVED85 0x85*/
#define ADVICE_OF_CHARGE 0x86
/*1111 0001
to
1111 1111
F1H - Reserved for network operator use
to
FFH*/
/* Parameter Types */
#define DATE_AND_TIME 1
#define CLI_PARAMETER_TYPE 2
#define CALLED_DIRECTORY_NUMBER_PARAMETER_TYPE 3
#define REASON_FOR_ABSENCE_OF_CLI_PARAMETER_TYPE 4
#define CALL_QUALIFIER 6
#define NAME_PARAMETER_TYPE 7
#define REASON_FOR_ABSENCE_OF_CALLING_PARTY_NAME_PARAMETER_TYPE 8
#define VISUAL_INDICATOR_PARAMETER_TYPE 0xb
#define COMPLEMENTARY_CLI_PARAMETER_TYPE 0x10
#define CALL_TYPE_PARAMETER_TYPE 0x11
#define FIRST_CALLED_LINE_DIRECTORY_NUMBER_PARAMETER_TYPE 0x12
#define NETWORK_MESSAGE_SYSTEM_STATUS_PARAMETER_TYPE 0x13
#define FORWARDED_CALL_TYPE_PARAMETER_TYPE 0x15
#define TYPE_OF_CALLING_USER_PARAMETER_TYPE 0x16
#define REDIRECTING_NUMBER_PARAMETER_TYPE 0x1a
#define EXTENSION_FOR_NETWORK_OPERATOR_USE_PARAMETER_TYPE 0xe0
/* -----------------------------------------------------------* */
#else
#endif /* PC_H_INCLUDED } */

98
divastreaming/platform.h Normal file
View File

@ -0,0 +1,98 @@
/*
*
Copyright (c) Dialogic (R) 2009 - 2010
*
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters.
*
Dialogic (R) File Revision : 1.9
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __DIVA_OS_STREAMING_PLATFORM_H__
#define __DIVA_OS_STREAMING_PLATFORM_H__
#define DIVA_USERMODE 1
#define LINUX 1
#if !defined(__i386__)
#define READ_WORD(w) ( ((byte *)(w))[0] + \
(((byte *)(w))[1]<<8) )
#define READ_DWORD(w) ( ((byte *)(w))[0] + \
(((byte *)(w))[1]<<8) + \
(((byte *)(w))[2]<<16) + \
(((byte *)(w))[3]<<24) )
#define WRITE_WORD(b,w) do{ ((byte*)(b))[0]=(byte)(w); \
((byte*)(b))[1]=(byte)((w)>>8); }while(0)
#define WRITE_DWORD(b,w) do{ ((byte*)(b))[0]=(byte)(w); \
((byte*)(b))[1]=(byte)((w)>>8); \
((byte*)(b))[2]=(byte)((w)>>16); \
((byte*)(b))[3]=(byte)((w)>>24); }while(0)
#else
#define READ_WORD(w) (*(word *)(w))
#define READ_DWORD(w) (*(dword *)(w))
#define WRITE_WORD(b,w) do{ *(word *)(b)=(w); }while(0)
#define WRITE_DWORD(b,w) do{ *(dword *)(b)=(w); }while(0)
#endif
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned int dword;
typedef signed int int32;
typedef unsigned long long qword;
#ifndef likely
#define likely(__x__) (!!(__x__))
#endif
#ifndef unlikely
#define unlikely(__x__) (!!(__x__))
#endif
#ifndef MIN
#define MIN(a,b) ((a)>(b) ? (b) : (a))
#endif
#ifndef MAX
#define MAX(a,b) ((a)>(b) ? (a) : (b))
#endif
#define DIVAS_CONTAINING_RECORD(address, type, field) \
((type *)((char*)(address) - (char*)(&((type *)0)->field)))
#define DIVA_STREAMING_MAX_TRACE_IDENT_LENGTH 4
void* diva_os_malloc (unsigned long flags, unsigned long size);
void diva_os_free (unsigned long flags, void* ptr);
#define _DI_STREAM_CTRL 0x0014
#include <string.h>
#include "debuglib.h"
#define DIVA_SHARED_SEGMENT_ALLOC 1
/*
DIVA_SHARED_SEGMENT_LOCK used to lock shared segment alloc instance. Locked instance is newer freed
due to reference counter newer receives zero. This allows to maintain permenently mapped pool of pages
and to reduce overall system load.
Causes memory load if application is stopped, but memory and mapped resources are freed by OS.
*/
#define DIVA_SHARED_SEGMENT_LOCK 1
#endif

105
divastreaming/runtime.c Normal file
View File

@ -0,0 +1,105 @@
/*
*
Copyright (c) Dialogic (R) 2009 - 2011
*
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters.
*
Dialogic (R) File Revision : 1.9
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <stdio.h>
#include "platform.h"
#include <malloc.h>
#include "chan_capi_platform.h"
#include "chan_capi20.h"
#include "chan_capi.h"
#include "chan_capi_utils.h"
void* diva_os_malloc (unsigned long flags, unsigned long size) {
void* ret = 0;
if (size != 0) {
ret = ast_malloc (size);
}
return (ret);
}
void diva_os_free (unsigned long flags, void* ptr) {
if (ptr != 0) {
ast_free (ptr);
}
}
void diva_runtime_error_message (const char* fmt, ...) {
char tmp[512];
va_list ap;
va_start(ap, fmt);
vsnprintf(tmp, sizeof(tmp), fmt, ap);
va_end(ap);
tmp[sizeof(tmp)-1]=0;
cc_log(LOG_ERROR, "%s\n", tmp);
}
void diva_runtime_log_message (const char* fmt, ...) {
char tmp[512];
va_list ap;
va_start(ap, fmt);
vsnprintf(tmp, sizeof(tmp), fmt, ap);
va_end(ap);
tmp[sizeof(tmp)-1]=0;
cc_verbose(4, 0, "%s\n", tmp);
}
void diva_runtime_trace_message (const char* fmt, ...) {
char tmp[512];
va_list ap;
va_start(ap, fmt);
vsnprintf(tmp, sizeof(tmp), fmt, ap);
va_end(ap);
tmp[sizeof(tmp)-1]=0;
cc_verbose(4, 1, "%s\n", tmp);
}
void diva_runtime_binary_message (const void* data, unsigned long data_length) {
static const char hex_digit_table[0x10] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
word i, j;
char *p;
char hex_line[50];
const byte *buffer = data;
word length = (word)data_length;
for (i = 0; i < length; i += 16) {
p = hex_line;
for (j = 0; (j < 16) && (i+j < length); j++) {
*(p++) = ' ';
*(p++) = hex_digit_table[buffer[i+j] >> 4];
*(p++) = hex_digit_table[buffer[i+j] & 0xf];
}
*p = '\0';
cc_verbose(4, 1, "[%02x]%s\n", (unsigned int) i, hex_line);
}
}

View File

@ -0,0 +1,440 @@
/*
*
Copyright (c) Dialogic (R) 2009 - 2010
*
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters.
*
Dialogic (R) File Revision : 1.9
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*
* vim:ts=2:
*/
#include "platform.h"
#include "dlist.h"
#include "diva_segment_alloc_ifc.h"
#ifdef DIVA_USERMODE
#include "xdi_msg.h"
#else
#include "pc.h"
#include "di_defs.h"
#include "divasync.h"
#endif
#include "debuglib.h"
#if defined(LINUX) && defined(DIVA_USERMODE)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#endif
typedef struct _diva_map_entry {
diva_entity_link_t link;
int entry_nr;
dword dma_lo;
dword dma_hi;
void* mem;
} diva_map_entry_t;
typedef struct _diva_segment_alloc {
diva_segment_alloc_access_t ifc;
#if defined(DIVA_USERMODE)
#if defined(LINUX)
int fd;
int fd_mem;
int fd_xdi;
#endif
#else
DESCRIPTOR* d;
#endif
diva_entity_queue_t free_q;
diva_entity_queue_t busy_q;
#if !defined(DIVA_USERMODE)
IDI_SYNC_REQ syncReq;
#endif
} diva_segment_alloc_t;
/*
* LOCALS
*/
static void release_proc(struct _diva_segment_alloc**);
static void* segment_alloc_proc(struct _diva_segment_alloc*, dword* lo, dword* hi);
static void segment_free_proc(struct _diva_segment_alloc*, void* addr, dword lo, dword hi);
static dword get_segment_length_proc(struct _diva_segment_alloc*);
#if defined(DIVA_USERMODE)
static int map_entry (struct _diva_segment_alloc* pI, diva_map_entry_t* pE);
#endif
static void* map_address (struct _diva_segment_alloc* ifc, dword lo, dword hi, int map_host);
static void* umap_address (struct _diva_segment_alloc* ifc, dword lo, dword hi, void* local);
static int write_address (struct _diva_segment_alloc* ifc, dword lo, dword hi, dword data);
static void resource_removed (struct _diva_segment_alloc* ifc);
#if !defined(DIVA_USERMODE)
static void diva_segment_allloc_resource_removed_request(ENTITY* e) { }
static DESCRIPTOR diva_segment_alloc_resource_removed_descriptor =
{ 0, 0, 0, diva_segment_allloc_resource_removed_request };
#endif
static diva_segment_alloc_access_t ifc_ref = {
release_proc,
segment_alloc_proc,
segment_free_proc,
get_segment_length_proc,
map_address,
umap_address,
write_address,
resource_removed
};
#if defined(DIVA_SHARED_SEGMENT_ALLOC)
static struct _diva_segment_alloc* shared_segment_alloc;
static int shared_segment_alloc_count;
#endif
int diva_create_segment_alloc (void* os_context, struct _diva_segment_alloc** segment_alloc)
{
diva_segment_alloc_t* pI = diva_os_malloc(0, sizeof(*pI));
#if defined(DIVA_SHARED_SEGMENT_ALLOC)
if (shared_segment_alloc != 0) {
shared_segment_alloc_count++;
*segment_alloc = shared_segment_alloc;
DBG_TRC(("shared %d segment alloc [%p]", shared_segment_alloc_count, pI))
return (0);
}
#endif
pI = diva_os_malloc(0, sizeof(*pI));
if (pI != 0) {
memset (pI, 0x00, sizeof(*pI));
pI->ifc = ifc_ref;
diva_q_init (&pI->free_q);
diva_q_init (&pI->busy_q);
#if defined(DIVA_USERMODE) /* { */
#if defined(LINUX) /* { */
pI->fd = open ("/dev/DivasMAP", O_RDWR | O_NONBLOCK); /** \todo use hardware related DMA entry, needs update of XDI driver */
pI->fd_mem = open ("/dev/mem", O_RDWR | O_NONBLOCK); /* /dev/mem is optional */
pI->fd_xdi = open ("/dev/DivasXDI", O_RDWR | O_NONBLOCK); /* /dev/mem is optional */
if (pI->fd >= 0 && (pI->fd_mem >= 0 || pI->fd_xdi >= 0)) {
*segment_alloc = pI;
} else {
diva_destroy_segment_alloc (&pI);
pI = 0;
}
#endif /* } */
#else /* } { */
pI->d = (DESCRIPTOR*)os_context;
*segment_alloc = pI;
#endif /* } */
}
if (pI != 0) {
#if defined(DIVA_SHARED_SEGMENT_ALLOC)
shared_segment_alloc = pI;
shared_segment_alloc_count = 1;
#if defined(DIVA_SHARED_SEGMENT_LOCK)
shared_segment_alloc_count++;
#endif
#endif
DBG_TRC(("created segment alloc [%p]", pI))
}
return ((pI != 0) ? 0 : -1);
}
int diva_destroy_segment_alloc (struct _diva_segment_alloc** segment_alloc) {
diva_segment_alloc_t* pI = (segment_alloc != 0) ? *segment_alloc : 0;
#if defined(DIVA_SHARED_SEGMENT_ALLOC)
shared_segment_alloc_count--;
if (shared_segment_alloc_count > 0) {
if (segment_alloc != 0)
*segment_alloc = 0;
DBG_TRC(("unshare %d segment alloc [%p]", shared_segment_alloc_count, segment_alloc))
return (0);
}
#endif
DBG_TRC(("destroy segment alloc [%p]", segment_alloc))
if (pI != 0) {
diva_entity_link_t* link;
shared_segment_alloc = 0;
shared_segment_alloc_count = 0;
while ((link = diva_q_get_head (&pI->busy_q)) != 0) {
diva_q_remove (&pI->busy_q, link);
diva_q_add_tail (&pI->free_q, link);
}
while ((link = diva_q_get_head (&pI->free_q)) != 0) {
diva_map_entry_t* pE = DIVAS_CONTAINING_RECORD(link, diva_map_entry_t, link);
#if defined(DIVA_USERMODE)
#if defined(LINUX)
munmap (pE->mem, 4*1024);
#endif
#else
pI->syncReq.diva_xdi_streaming_mapping_req.Req = 0;
pI->syncReq.diva_xdi_streaming_mapping_req.Rc = IDI_SYNC_REQ_PROCESS_STREAMING_MAPPING;
pI->syncReq.diva_xdi_streaming_mapping_req.info.request = IDI_SYNC_REQ_PROCESS_STREAMING_MAPPING_FREE_COMMAND;
pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_lo = pE->dma_lo;
pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_hi = pE->dma_hi;
pI->syncReq.diva_xdi_streaming_mapping_req.info.addr = pE->mem;
pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_handle = pE->entry_nr;
pI->d->request((ENTITY*)&pI->syncReq);
#endif
diva_q_remove (&pI->free_q, link);
diva_os_free (0, pE);
}
#if defined(DIVA_USERMODE)
#if defined(LINUX)
if (pI->fd >= 0)
close (pI->fd);
if (pI->fd_mem >= 0)
close (pI->fd_mem);
if (pI->fd_xdi >= 0)
close (pI->fd_xdi);
#endif
#else
#endif
diva_os_free (0, pI);
*segment_alloc = 0;
}
return (0);
}
void release_proc(struct _diva_segment_alloc** pI) {
diva_destroy_segment_alloc (pI);
}
void* segment_alloc_proc(struct _diva_segment_alloc* pI, dword* lo, dword* hi) {
diva_entity_link_t* link = diva_q_get_head(&pI->free_q);
void* addr = 0;
if (link != 0) {
diva_map_entry_t* pE = DIVAS_CONTAINING_RECORD(link, diva_map_entry_t, link);
diva_q_remove (&pI->free_q, link);
diva_q_add_tail (&pI->busy_q, link);
*lo = pE->dma_lo;
*hi = pE->dma_hi;
return (pE->mem);
} else if ((link = diva_os_malloc (0, sizeof(diva_map_entry_t))) != 0) {
diva_map_entry_t* pE = (diva_map_entry_t*)link;
#if defined(DIVA_USERMODE)
#if defined(LINUX)
dword data[5];
int ret;
data[0] = DIVA_XDI_UM_CMD_CREATE_XDI_DESCRIPTORS;
data[1] = 1;
{ int tmp = write (pI->fd, data, 2*sizeof(dword)); tmp++; }
ret = read (pI->fd, data, sizeof(data));
if (ret == sizeof(data) || ret == (sizeof(data)-sizeof(data[0]))) {
if (data[0] == DIVA_XDI_UM_CMD_CREATE_XDI_DESCRIPTORS && data[1] == 1) {
pE->dma_lo = data[3];
pE->dma_hi = (data[2] == 8) ? data[4] : 0;
if (map_entry(pI, pE) == 0) {
diva_q_add_tail (&pI->busy_q, &pE->link);
*lo = pE->dma_lo;
*hi = pE->dma_hi;
addr = pE->mem;
} else {
diva_os_free (0, pE);
}
}
}
#endif
#else
pI->syncReq.diva_xdi_streaming_mapping_req.Req = 0;
pI->syncReq.diva_xdi_streaming_mapping_req.Rc = IDI_SYNC_REQ_PROCESS_STREAMING_MAPPING;
pI->syncReq.diva_xdi_streaming_mapping_req.info.request = IDI_SYNC_REQ_PROCESS_STREAMING_MAPPING_ALLOC_COMMAND;
pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_lo = 0;
pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_hi = 0;
pI->syncReq.diva_xdi_streaming_mapping_req.info.addr = 0;
pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_handle = -1;
pI->d->request((ENTITY*)&pI->syncReq);
if (pI->syncReq.diva_xdi_streaming_mapping_req.info.request == IDI_SYNC_REQ_PROCESS_STREAMING_COMMAND_OK &&
pI->syncReq.diva_xdi_streaming_mapping_req.info.addr != 0) {
pE->entry_nr = pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_handle;
pE->dma_lo = pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_lo;
pE->dma_hi = pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_hi;
pE->mem = pI->syncReq.diva_xdi_streaming_mapping_req.info.addr;
*lo = pE->dma_lo;
*hi = pE->dma_hi;
addr = pE->mem;
memset (addr, 0x00, 4*1024);
diva_q_add_tail (&pI->busy_q, &pE->link);
} else {
diva_os_free (0, pE);
}
#endif
}
return (addr);
}
#if defined(DIVA_USERMODE)
static int map_entry (struct _diva_segment_alloc* pI, diva_map_entry_t* pE) {
void* addr;
if (pE->dma_hi != 0) {
qword i = ((qword)pE->dma_lo) | (((qword)pE->dma_hi) << 32);
#if defined(LINUX)
addr = mmap (0, 4*1024, PROT_READ|PROT_WRITE, MAP_SHARED, pI->fd, i);
#endif
} else {
#if defined(LINUX)
addr = mmap (0, 4*1024, PROT_READ|PROT_WRITE, MAP_SHARED, pI->fd, pE->dma_lo);
#endif
}
if (addr == 0 || addr == ((void*)-1)) {
DBG_ERR(("failed to map %08x:%08x [%p]", pE->dma_lo, pE->dma_hi, pI))
return (-1);
}
pE->mem = addr;
return (0);
}
#endif
static void* map_address (struct _diva_segment_alloc* pI, dword lo, dword hi, int map_host) {
void* ret = 0;
#if defined(DIVA_USERMODE)
#if defined(LINUX)
qword addr = ((qword)lo) | (((qword)hi) << 32);
int effective_map_fd = (map_host == 0) ? pI->fd_mem : pI->fd;
if (effective_map_fd >= 0) {
ret = mmap (0, 4*1024, PROT_READ|PROT_WRITE, MAP_SHARED, effective_map_fd, addr);
if (ret == ((void*)-1)) {
ret = 0;
}
}
#endif
#else
pI->syncReq.diva_xdi_streaming_mapping_req.Req = 0;
pI->syncReq.diva_xdi_streaming_mapping_req.Rc = IDI_SYNC_REQ_PROCESS_STREAMING_MAPPING;
pI->syncReq.diva_xdi_streaming_mapping_req.info.request = IDI_SYNC_REQ_PROCESS_STREAMING_SYSTEM_MAP_COMMAND;
pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_lo = 0;
pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_hi = 0;
pI->syncReq.diva_xdi_streaming_mapping_req.info.addr = 0;
pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_handle = -1;
pI->d->request((ENTITY*)&pI->syncReq);
if (pI->syncReq.diva_xdi_streaming_mapping_req.info.request == IDI_SYNC_REQ_PROCESS_STREAMING_COMMAND_OK) {
byte* p = pI->syncReq.diva_xdi_streaming_mapping_req.info.addr;
dword offset = lo - pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_lo;
pI->syncReq.diva_xdi_streaming_mapping_req.info.addr = 0;
pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_lo = 0;
pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_hi = 0;
ret = p + offset;
}
#endif
return (ret);
}
static void* umap_address (struct _diva_segment_alloc* ifc, dword lo, dword hi, void* local) {
#if defined(DIVA_USERMODE)
#if defined(LINUX)
munmap (local, 4*1024);
#endif
#else
#endif
return (0);
}
static int write_address (struct _diva_segment_alloc* pI, dword lo, dword hi, dword data) {
diva_xdi_direct_access_cmd_t cmd;
int ret;
if (unlikely(pI->fd_xdi < 0))
return (-1);
cmd.hdr.ident = DIVA_XDI_DIRECT_ACCESS_CMD_IDENT;
cmd.hdr.cmd = DIVA_XDI_DIRECT_ACCESS_CMD_WRITE_BY_ADDRESS;
cmd.cmd.write_by_address.address = lo;
cmd.cmd.write_by_address.value = data;
ret = write (pI->fd_xdi, &cmd, sizeof(cmd.hdr)+sizeof(cmd.cmd.write_by_address)) ==
sizeof(cmd.hdr)+sizeof(cmd.cmd.write_by_address) ? 0 : -1;
return (ret);
}
static void resource_removed (struct _diva_segment_alloc* pI) {
#if defined(DIVA_USERMODE)
#else
pI->d = &diva_segment_alloc_resource_removed_descriptor;
#endif
}
void segment_free_proc(struct _diva_segment_alloc* pI, void* addr, dword lo, dword hi) {
diva_entity_link_t* link;
for (link = diva_q_get_head(&pI->busy_q); link != 0; link = diva_q_get_next(link)) {
diva_map_entry_t* pE = DIVAS_CONTAINING_RECORD(link, diva_map_entry_t, link);
if (pE->mem == addr && pE->dma_lo == lo && pE->dma_hi == hi) {
diva_q_remove (&pI->busy_q, link);
diva_q_add_tail (&pI->free_q, link);
return;
}
}
DBG_ERR(("segment not found: %p %08x:%08x [%p]", addr, lo, hi, pI))
}
dword get_segment_length_proc(struct _diva_segment_alloc* pI) {
return (4*1024);
}
diva_segment_alloc_access_t* diva_get_segment_alloc_ifc (struct _diva_segment_alloc* segment_alloc) {
return ((segment_alloc != 0) ? &segment_alloc->ifc : 0);
}

View File

@ -0,0 +1,134 @@
/*
*
Copyright (c) Dialogic (R) 2009 - 2010
*
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters.
*
Dialogic (R) File Revision : 1.9
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __DIVA_SPI_DESCRIPTOR_H__
#define __DIVA_SPI_DESCRIPTOR_H__
#define MAX_SPI_DESCRIPTOR_LENGTH (4*1024)
#define MAX_XCONN_PER_DSP_DESCRIPTORS 8
#define SMALL_FLAT_RX_BUFFER_LENGTH 128
/*
SPI descriptor is always transferred in two parts:
byte* msg;
xmit(&msg[4], length-4);
xmit(msg, 4);
The second transfer is used as indication about end of the
descriptor transfer.
*/
typedef struct _diva_spi_msg_hdr {
byte length_lo; /* Total transfer length, includes the the length of the header, lo byte */
byte length_hi; /* Total transfer length, includes the length of the header, h byte */
byte Id; /* IDI Id. 0xff in case of the system message */
byte Ind; /* Ind */
} diva_spi_msg_hdr_t;
typedef struct _diva_spi_msg {
diva_spi_msg_hdr_t hdr;
byte data[MAX_SPI_DESCRIPTOR_LENGTH-sizeof(diva_spi_msg_hdr_t)];
} diva_spi_msg_t;
/*
System messages:
if Id == 0xff then system message
if (length_hi & 0x80) then system message is chained after the message
Messages:
byte - message type
byte - message length without this byte and the length byte
body - sequence of bytes, depends on the type of message
*/
/*
Used for comminication with
monitor task
*/
typedef struct _diva_dsp_monitor_message_hdr {
byte length_lo; /* Total transfer length, includes the the length of the header, lo byte */
byte length_hi; /* Total transfer length, includes the length of the header, h byte */
byte message_lo;
byte message_hi;
} diva_dsp_monitor_message_hdr_t;
typedef struct _diva_dsp_monitor_message {
diva_dsp_monitor_message_hdr_t hdr;
byte data[MAX_SPI_DESCRIPTOR_LENGTH-sizeof(diva_dsp_monitor_message_hdr_t)];
} diva_dsp_monitor_message_t;
/*
Format of the request:
length_lo
length_hi - set to "data_length + 5"
Id
Req - Stored in the Ind field
RegCh - Req Ch stored in the first byte of data field
data - first byte of data
*/
/*
Format of the return code without extended info:
length_lo
length_hi - set to 6
Id
Rc - Stored in the Ind field
RcCh - RcCh stored in the first byte of data field
type - Type. Set to zero for RC, stored in the second byte of data field
Format of the return code with extended info:
length_lo
length_hi - set to 14
Id
Rc - Stored in the Ind field
RcCh - RcCh stored in the first byte of data field
type - Type. Set to zero for RC, stored in the second byte of data field
dword - extended info type (bytes 2,3,4,5 of data field)
dword - extended info (bytes 6,7,8,9 of data field)
*/
/*
Format of the indication:
length_lo
length_hi - set to "data_lengt + 6"
Id
Ind - Stored in the Ind field
IndCh - IndCh stored in the first byte of data field
type - Type. Set to one for IND, stored in the second byte of data field
data - first byte of data, starts at third data byte
*/
typedef struct _diva_xconn_msg_hdr {
word counter;
word length;
} diva_xconn_msg_hdr_t;
typedef struct _diva_xconn_msg {
diva_xconn_msg_hdr_t hdr;
byte data[MAX_SPI_DESCRIPTOR_LENGTH-sizeof(diva_xconn_msg_hdr_t)];
} diva_xconn_msg_t;
#endif

338
divastreaming/xdi_msg.h Executable file
View File

@ -0,0 +1,338 @@
/*
*
Copyright (c) Dialogic(R), 2010-2011
Copyright 2000-2003 by Armin Schindler (mac@melware.de)
Copyright 2000-2003 Cytronics & Melware (info@melware.de)
*
This source file is supplied for the use with
Dialogic range of Adapters.
*
Dialogic(R) File Revision : 2.1
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __DIVA_XDI_UM_CFG_MESSSGE_H__
#define __DIVA_XDI_UM_CFG_MESSAGE_H__
/*
Definition of commands for user mode configuration
utility to XDI device driver
*/
/*
XDI WRITE command
*/
#define DIVA_XDI_IO_CMD_WRITE_MSG 0x3701
/*
XDI READ command
*/
#define DIVA_XDI_IO_CMD_READ_MSG 0x3702
/*
Definition of messages used to communicate between
XDI device driver and user mode configuration utility
*/
/*
As acknowledge one DWORD - card ordinal will be read from the card
*/
#define DIVA_XDI_UM_CMD_GET_CARD_ORDINAL 0
/*
no acknowledge will be generated, memory block will be written in the
memory at given offset
*/
#define DIVA_XDI_UM_CMD_WRITE_SDRAM_BLOCK 1
/*
no acknowledge will be genatated, FPGA will be programmed
*/
#define DIVA_XDI_UM_CMD_WRITE_FPGA 2
/*
As acknowledge block of SDRAM will be read in the user buffer
*/
#define DIVA_XDI_UM_CMD_READ_SDRAM 3
/*
As acknowledge dword with serial number will be read in the user buffer
*/
#define DIVA_XDI_UM_CMD_GET_SERIAL_NR 4
/*
As acknowledge struct consisting from 9 dwords with PCI info.
dword[0...7] = 8 PCI BARS
dword[9] = IRQ
*/
#define DIVA_XDI_UM_CMD_GET_PCI_HW_CONFIG 5
/*
Reset of the board + activation of primary
boot loader
*/
#define DIVA_XDI_UM_CMD_RESET_ADAPTER 6
/*
Called after code download to start adapter
at specified address
Start does set new set of features due to fact that we not know
if protocol features have changed
*/
#define DIVA_XDI_UM_CMD_START_ADAPTER 7
/*
Stop adapter, called if user
wishes to stop adapter without unload
of the driver, to reload adapter with
different protocol
*/
#define DIVA_XDI_UM_CMD_STOP_ADAPTER 8
/*
Get state of current adapter
Acknowledge is one dword with following values:
0 - adapter ready for download
1 - adapter running
2 - adapter dead
3 - out of service, driver should be restarted or hardware problem
*/
#define DIVA_XDI_UM_CMD_GET_CARD_STATE 9
/*
Reads XLOG entry from the card
*/
#define DIVA_XDI_UM_CMD_READ_XLOG_ENTRY 10
/*
Set untranslated protocol code features
*/
#define DIVA_XDI_UM_CMD_SET_PROTOCOL_FEATURES 11
/*
Start adapter test procedure
*/
#define DIVA_XDI_UM_CMD_ADAPTER_TEST 12
/*
Alloc DMA descriptor
*/
#define DIVA_XDI_UM_CMD_ALLOC_DMA_DESCRIPTOR 14
/*
Get hardware information structure
*/
#define DIVA_XDI_UM_CMD_GET_HW_INFO_STRUCT 15
/*
Change XDI driver protocol code version
*/
#define DIVA_XDI_UM_CMD_SET_PROTOCOL_CODE_VERSION 17
/*
Init VIDI, read VIDI info from driver
*/
#define DIVA_XDI_UM_CMD_INIT_VIDI 18
/*
Select VIDI mode
*/
#define DIVA_XDI_UM_CMD_SET_VIDI_MODE 19
typedef struct _diva_xdi_um_cfg_cmd_set_vidi_mode {
dword vidi_mode;
} diva_xdi_um_cfg_cmd_set_vidi_mode_t;
typedef struct _diva_xdi_um_cfg_cmd_data_init_vidi {
dword req_magic_lo;
dword req_magic_hi;
dword ind_magic_lo;
dword ind_magic_hi;
dword dma_segment_length;
dword dma_req_buffer_length;
dword dma_ind_buffer_length;
dword dma_ind_remote_counter_offset;
} diva_xdi_um_cfg_cmd_data_init_vidi_t;
/*
Get clock memory info
*/
#define DIVA_XDI_UM_CMD_GET_CLOCK_MEMORY_INFO 20
/*
Read PLX register
*/
#define DIVA_XDI_UM_CMD_READ_WRITE_PLX_REGISTER 21
/*
Create DMA descriptor
*/
#define DIVA_XDI_UM_CMD_CREATE_XDI_DESCRIPTORS 22
/*
Clock interrupt
*/
#define DIVA_XDI_UM_CMD_CLOCK_INTERRUPT_CONTROL 23
/*
Clock interrupt data
*/
#define DIVA_XDI_UM_CMD_CLOCK_INTERRUPT_DATA 24
/*
BAR Access
*/
#define DIVA_XDI_UM_CMD_BAR_ACCESS 25
typedef struct _diva_xdi_um_cfg_cmd_get_clock_memory_info {
dword bus_addr_lo;
dword bus_addr_hi;
dword length;
} diva_xdi_um_cfg_cmd_get_clock_memory_info_t;
typedef struct _diva_xdi_um_cfg_cmd_data_alloc_dma_descriptor {
dword nr;
dword low;
dword high;
} diva_xdi_um_cfg_cmd_data_alloc_dma_descriptor_t;
typedef struct _diva_xdi_um_cfg_cmd_data_adapter_test {
dword test_command;
} diva_xdi_um_cfg_cmd_data_adapter_test_t;
typedef struct _diva_xdi_um_cfg_cmd_data_set_features {
dword features;
} diva_xdi_um_cfg_cmd_data_set_features_t;
typedef struct _diva_xdi_um_cfg_cmd_data_start {
dword offset;
dword features;
} diva_xdi_um_cfg_cmd_data_start_t;
typedef struct _diva_xdi_um_cfg_cmd_data_write_sdram {
dword ram_number;
dword offset;
dword length;
} diva_xdi_um_cfg_cmd_data_write_sdram_t;
typedef struct _diva_xdi_um_cfg_cmd_data_write_fpga {
dword fpga_number;
dword image_length;
} diva_xdi_um_cfg_cmd_data_write_fpga_t;
typedef struct _diva_xdi_um_cfg_cmd_data_read_sdram {
dword ram_number;
dword offset;
dword length;
} diva_xdi_um_cfg_cmd_data_read_sdram_t;
typedef struct _diva_xdi_um_cfg_cmd_data_set_protocol_code_version {
dword version;
} diva_xdi_um_cfg_cmd_data_set_protocol_code_version_t;
typedef struct _diva_xdi_um_cfg_cmd_read_write_plx_register {
byte write;
byte offset;
byte length;
dword value;
} diva_xdi_um_cfg_cmd_read_write_plx_register_t;
typedef struct _diva_xdi_um_cfg_cmd_clock_interrupt_control {
dword command;
} diva_xdi_um_cfg_cmd_clock_interrupt_control_t;
typedef struct _diva_xdi_um_cfg_cmd_get_clock_interrupt_data {
dword state;
dword clock;
dword errors;
} diva_xdi_um_cfg_cmd_get_clock_interrupt_data_t;
#define DIVA_BAR_ACCESS_TYPE_READ 0x00
#define DIVA_BAR_ACCESS_TYPE_WRITE 0x01
#define DIVA_BAR_ACCESS_TYPE_SINGLE 0x02
#define DIVA_BAR_ACCESS_TYPE_BYTE 0x04
#define DIVA_BAR_ACCESS_TYPE_WORD 0x08
#define DIVA_BAR_ACCESS_TYPE_DWORD 0x10
#define DIVA_BAR_ACCESS_TYPE_WRITE_READ 0x20
typedef struct _diva_xdi_um_bar_access_data {
byte bar;
byte access_type;
word length;
dword offset;
dword data;
} diva_xdi_um_bar_access_data_t;
typedef union _diva_xdi_um_cfg_cmd_data {
diva_xdi_um_cfg_cmd_data_write_sdram_t write_sdram;
diva_xdi_um_cfg_cmd_data_write_fpga_t write_fpga;
diva_xdi_um_cfg_cmd_data_read_sdram_t read_sdram;
diva_xdi_um_cfg_cmd_data_start_t start;
diva_xdi_um_cfg_cmd_data_set_features_t features;
diva_xdi_um_cfg_cmd_data_adapter_test_t test;
diva_xdi_um_cfg_cmd_data_alloc_dma_descriptor_t dma;
diva_xdi_um_cfg_cmd_data_set_protocol_code_version_t protocol_code_version;
diva_xdi_um_cfg_cmd_data_init_vidi_t vidi;
diva_xdi_um_cfg_cmd_set_vidi_mode_t vidi_mode;
diva_xdi_um_cfg_cmd_get_clock_memory_info_t clock_memory;
diva_xdi_um_cfg_cmd_read_write_plx_register_t plx_register;
diva_xdi_um_cfg_cmd_clock_interrupt_control_t clock_interrupt_control;
diva_xdi_um_cfg_cmd_get_clock_interrupt_data_t clock_interrupt_data;
diva_xdi_um_bar_access_data_t bar_access_data;
} diva_xdi_um_cfg_cmd_data_t;
typedef struct _diva_xdi_um_cfg_cmd {
dword adapter; /* Adapter number 1...N */
dword command;
diva_xdi_um_cfg_cmd_data_t command_data;
dword data_length; /* Plain binary data will follow */
} diva_xdi_um_cfg_cmd_t;
typedef struct _diva_xdi_io_cmd {
unsigned int length;
void * cmd;
} diva_xdi_io_cmd;
/*
* Diva direct interface access commands
*/
#define DIVA_XDI_DIRECT_ACCESS_CMD_IDENT 0x1234abcd
typedef struct _diva_xdi_direct_access_cmd_hdr {
dword ident;
dword cmd;
} diva_xdi_direct_access_cmd_hdr_t;
#define DIVA_XDI_DIRECT_ACCESS_CMD_WRITE_BY_ADDRESS 1
typedef struct _diva_xdi_direct_access_write_by_address {
dword address;
dword value;
} diva_xdi_direct_access_write_by_address_t;
typedef struct _diva_xdi_direct_access_cmd {
diva_xdi_direct_access_cmd_hdr_t hdr;
union {
diva_xdi_direct_access_write_by_address_t write_by_address;
} cmd;
} diva_xdi_direct_access_cmd_t;
#endif

208
divaverbose/divaverbose.c Normal file
View File

@ -0,0 +1,208 @@
/*
*
Copyright (c) Dialogic(R), 2011
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*! \file
* \brief Implements interface to diva trace system
*/
#include <stdio.h>
#include "chan_capi20.h"
#include "chan_capi.h"
#ifdef CC_AST_HAS_VERSION_1_4
#include <asterisk.h>
#endif
#include <asterisk/logger.h>
#include <asterisk/module.h>
#include <asterisk/cli.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "divaverbose.h"
static int verbose_registered;
AST_MUTEX_DEFINE_STATIC(dbgIfcLock);
static volatile int divaDbgIfc = -1;
#ifdef CC_AST_HAS_VERSION_1_6
static
#endif
char capi_do_verbose_usage[] =
"Usage: " CC_MESSAGE_NAME " verbose\n"
" Connect to debug driver.\n";
#ifdef CC_AST_HAS_VERSION_1_6
static
#endif
char capi_no_verbose_usage[] =
"Usage: " CC_MESSAGE_NAME " no verbose\n"
" Disconnect from debug driver.\n";
static void open_diva_mnt(void)
{
cc_mutex_lock(&dbgIfcLock);
if (divaDbgIfc < 0) {
divaDbgIfc = open("/dev/DivasDBGIFC", O_WRONLY);
}
cc_mutex_unlock(&dbgIfcLock);
}
#if (!defined(CC_AST_HAS_VERSION_1_4) && !defined(CC_AST_HAS_VERSION_1_6) && !defined(CC_AST_HAS_VERSION_1_8))
static void diva_verbose_write (const char *info, int opos, int replacelast, int complete)
#else
static void diva_verbose_write (const char *info)
#endif
{
if (divaDbgIfc < 0) {
open_diva_mnt();
}
if (divaDbgIfc >= 0) {
write (divaDbgIfc, info, strlen(info));
}
}
static int diva_verbose_start(void)
{
if (verbose_registered == 0) {
verbose_registered = (ast_register_verbose(diva_verbose_write) == 0);
}
return ((verbose_registered != 0) ? 0 : -1);
}
static int diva_verbose_stop(void)
{
if (verbose_registered != 0) {
verbose_registered = !(ast_unregister_verbose(diva_verbose_write) == 0);
}
if ((verbose_registered == 0) && (divaDbgIfc >= 0)) {
close(divaDbgIfc);
divaDbgIfc = -1;
}
return ((verbose_registered == 0) ? 0 : -1);
}
/*
* enable debugging
*/
#ifdef CC_AST_HAS_VERSION_1_6
char *pbxcli_capi_do_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#else
int pbxcli_capi_do_verbose(int fd, int argc, char *argv[])
#endif
{
int ret;
#ifdef CC_AST_HAS_VERSION_1_6
int fd = a->fd;
if (cmd == CLI_INIT) {
e->command = CC_MESSAGE_NAME " verbose";
e->usage = capi_do_verbose_usage;
return NULL;
} else if (cmd == CLI_GENERATE)
return NULL;
if (a->argc != e->args)
return CLI_SHOWUSAGE;
#else
if (argc != 2)
return RESULT_SHOWUSAGE;
#endif
ret = diva_verbose_start();
if (ret == 0) {
ast_cli(fd, CC_MESSAGE_BIGNAME " Message Verboser Enabled\n");
} else {
ast_cli(fd, CC_MESSAGE_BIGNAME " Failed to enable Message Verboser\n");
}
#ifdef CC_AST_HAS_VERSION_1_6
return ((ret == 0) ? CLI_SUCCESS : CLI_FAILURE);
#else
return ((ret == 0) ? RESULT_SUCCESS : RESULT_FAILURE);
#endif
}
/*
* disable debugging
*/
#ifdef CC_AST_HAS_VERSION_1_6
char *pbxcli_capi_no_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#else
int pbxcli_capi_no_verbose(int fd, int argc, char *argv[])
#endif
{
int ret;
#ifdef CC_AST_HAS_VERSION_1_6
int fd = a->fd;
if (cmd == CLI_INIT) {
e->command = CC_MESSAGE_NAME " no verbose";
e->usage = capi_no_verbose_usage;
return NULL;
} else if (cmd == CLI_GENERATE)
return NULL;
if (a->argc != e->args)
return CLI_SHOWUSAGE;
#else
if (argc != 3)
return RESULT_SHOWUSAGE;
#endif
ret = diva_verbose_stop();
if (ret == 0) {
ast_cli(fd, CC_MESSAGE_BIGNAME " Message Verboser Disabled\n");
} else {
ast_cli(fd, CC_MESSAGE_BIGNAME " Failed to disable Message Verboser\n");
}
#ifdef CC_AST_HAS_VERSION_1_6
return ((ret == 0) ? CLI_SUCCESS : CLI_FAILURE);
#else
return ((ret == 0) ? RESULT_SUCCESS : RESULT_FAILURE);
#endif
}
void diva_verbose_load(void)
{
divaDbgIfc = -1;
open_diva_mnt();
if (divaDbgIfc >= 0) {
diva_verbose_start();
}
}
void diva_verbose_unload(void)
{
if (verbose_registered != 0) {
verbose_registered = !(ast_unregister_verbose(diva_verbose_write) == 0);
}
if (verbose_registered != 0)
cc_mutex_lock(&dbgIfcLock);
if (divaDbgIfc >= 0) {
close(divaDbgIfc);
divaDbgIfc = -1;
}
if (verbose_registered != 0)
cc_mutex_unlock(&dbgIfcLock);
}

58
divaverbose/divaverbose.h Normal file
View File

@ -0,0 +1,58 @@
/*
*
Copyright (c) Dialogic(R), 2011
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*! \file
* \brief Declares interface to diva trace system
*/
#ifndef __DIVA_VERBOSER_H__
#define __DIVA_VERBOSER_H__
#ifdef DIVA_VERBOSE
void diva_verbose_load(void);
void diva_verbose_unload(void);
#ifdef CC_AST_HAS_VERSION_1_6
char *pbxcli_capi_do_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
char *pbxcli_capi_no_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
#else
int pbxcli_capi_do_verbose(int fd, int argc, char *argv[]);
int pbxcli_capi_no_verbose(int fd, int argc, char *argv[]);
#endif
#define CC_CLI_TEXT_CAPI_DO_VERBOSE "Connect " CC_MESSAGE_BIGNAME " to debug driver"
#define CC_CLI_TEXT_CAPI_NO_VERBOSE "Disconnect " CC_MESSAGE_BIGNAME " from debug driver"
#ifndef CC_AST_HAS_VERSION_1_6
extern char capi_do_verbose_usage[];
extern char capi_no_verbose_usage[];
#endif
#else
#define diva_verbose_load() do{}while(0)
#define diva_verbose_unload() do{}while(0)
#endif
#endif

View File

@ -395,7 +395,11 @@ static unsigned char *cpars[] = {
/*39 CONNECT_ACTIVE_RESP*/ (unsigned char*)"\x03\x01",
/*3a DISCONNECT_RESP*/ (unsigned char*)"\x03\x01",
/*3b*/ 0,
#if 0
/*3c MANUFACTURER_IND*/ (unsigned char*)"\x03\x2b\x15\x22\x2a\x01",
#else
/*3c MANUFACTURER_IND dw(...)*/ (unsigned char*)"\x03\x2b\x24\x2a\x01",
#endif
/*3d*/ 0,
/*3e INFO_RESP*/ (unsigned char*)"\x03\x01",
/*3f FACILITY_RESP*/ (unsigned char*)"\x03\x20\x1f\x01",