Version 0.1.0 from FTP
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@4 2fbb986a-6c06-0410-b554-c9c1f0a7f128
This commit is contained in:
parent
30f86c22db
commit
802b2d14e0
55
Makefile
Executable file
55
Makefile
Executable file
@ -0,0 +1,55 @@
|
||||
#
|
||||
# libpri: An implementation of Primary Rate ISDN
|
||||
#
|
||||
# Written by Mark Spencer <markster@linux-support.net>
|
||||
#
|
||||
# Copyright (C) 2001, Linux Support Services, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the 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.
|
||||
#
|
||||
TOBJS=testpri.o
|
||||
STATIC_LIBRARY=libpri.a
|
||||
DYNAMIC_LIBRARY=libpri.so.1.0
|
||||
STATIC_OBJS=pri.o q921.o prisched.o q931.o
|
||||
DYNAMIC_OBJS=pri.lo q921.lo prisched.lo q931.lo
|
||||
CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g
|
||||
|
||||
all: $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
|
||||
|
||||
install: $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
|
||||
mkdir -p /usr/lib
|
||||
mkdir -p /usr/include
|
||||
install -m 644 libpri.h /usr/include
|
||||
install -m 755 $(DYNAMIC_LIBRARY) /usr/lib
|
||||
( cd /usr/lib ; ln -sf libpri.so.1 libpri.so )
|
||||
install -m 644 $(STATIC_LIBRARY) /usr/lib
|
||||
/sbin/ldconfig
|
||||
|
||||
%.lo : %.c
|
||||
$(CC) -fPIC $(CFLAGS) -o $@ -c $<
|
||||
|
||||
$(STATIC_LIBRARY): $(STATIC_OBJS)
|
||||
ar rcs $(STATIC_LIBRARY) $(STATIC_OBJS)
|
||||
ranlib $(STATIC_LIBRARY)
|
||||
|
||||
$(DYNAMIC_LIBRARY): $(DYNAMIC_OBJS)
|
||||
$(CC) -shared -Wl,-soname,libpri.so.1 -o $@ $(DYNAMIC_OBJS)
|
||||
/sbin/ldconfig -n .
|
||||
ln -sf libpri.so.1 libpri.so
|
||||
|
||||
clean:
|
||||
rm -f *.o *.so *.lo
|
||||
rm -f testpri $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)
|
31
README
Executable file
31
README
Executable file
@ -0,0 +1,31 @@
|
||||
libpri: An implementation of Primate Rate ISDN
|
||||
|
||||
Written by Mark Spencer <markster@linux-support.net>
|
||||
|
||||
What is libpri?
|
||||
===============
|
||||
|
||||
libpri is a C implementation of the Primary Rate ISDN specification. It was
|
||||
based on the Bellcore specification SR-NWT-002343 for National ISDN. As of
|
||||
May 12, 2001, it has been tested work with NI-2, Nortel DMS-100, and Lucent 5E Custom protocols on switches from Nortel and Lucent.
|
||||
|
||||
What is the license for libpri?
|
||||
===============================
|
||||
libpri is distributed under the terms of the GNU General Public License, which permit its use and linking with other GPL'd software only.
|
||||
|
||||
If you wish to use libpri in an application for which the GPL is not appropriate (e.g. a proprietary embedded system), licenses for libpri under more flexible terms can be readily obtained through Linux Support Services, Inc. at reasonable cost.
|
||||
|
||||
How do I report bugs or contribute?
|
||||
===================================
|
||||
For now, contact the author directly. In the future if there is sufficient interest, we will setup a mailing list.
|
||||
|
||||
Does anything use this library so far?
|
||||
======================================
|
||||
Yes, the Asterisk Open Source PBX does. http://www.asteriskpbx.com
|
||||
|
||||
Also, the Zapata library has hooks for it. http://www.zapatatelephony.org
|
||||
|
||||
Special thanks
|
||||
==============
|
||||
Special thanks to Jim Dixon <jim@lambdatel.com> for his help in testing and fixing the implementation.
|
||||
|
10
TODO
Executable file
10
TODO
Executable file
@ -0,0 +1,10 @@
|
||||
General:
|
||||
-- D-Channel Backup
|
||||
-- Test against 4e
|
||||
|
||||
Q.921:
|
||||
-- Support unnumbered information frames
|
||||
|
||||
Q.931:
|
||||
-- Locking Shift IE
|
||||
-- Implement the 11 missing Q.931 timers
|
254
libpri.h
Executable file
254
libpri.h
Executable file
@ -0,0 +1,254 @@
|
||||
/*
|
||||
* libpri: An implementation of Primary Rate ISDN
|
||||
*
|
||||
* Written by Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* Copyright (C) 2001, Linux Support Services, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the 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 _PRI_H
|
||||
#define _PRI_H
|
||||
|
||||
/* Node types */
|
||||
#define PRI_NETWORK 1
|
||||
#define PRI_CPE 2
|
||||
|
||||
/* Debugging */
|
||||
#define PRI_DEBUG_Q921_RAW (1 << 0) /* Show raw HDLC frames */
|
||||
#define PRI_DEBUG_Q921_DUMP (1 << 1) /* Show each interpreted Q.921 frame */
|
||||
#define PRI_DEBUG_Q921_STATE (1 << 2) /* Debug state machine changes */
|
||||
#define PRI_DEBUG_CONFIG (1 << 3) /* Display error events on stdout */
|
||||
#define PRI_DEBUG_Q931_DUMP (1 << 5) /* Show interpreted Q.931 frames */
|
||||
#define PRI_DEBUG_Q931_STATE (1 << 6) /* Debug Q.931 state machine changes */
|
||||
|
||||
#define PRI_DEBUG_ALL (0xffff) /* Everything */
|
||||
|
||||
/* Switch types */
|
||||
#define PRI_SWITCH_UNKNOWN 0
|
||||
#define PRI_SWITCH_NI2 1 /* National ISDN 2 */
|
||||
#define PRI_SWITCH_DMS100 2 /* DMS 100 */
|
||||
#define PRI_SWITCH_LUCENT5E 3 /* Lucent 5E */
|
||||
#define PRI_SWITCH_ATT4ESS 4 /* AT&T 4ESS */
|
||||
|
||||
/* PRI D-Channel Events */
|
||||
#define PRI_EVENT_DCHAN_UP 1 /* D-channel is up */
|
||||
#define PRI_EVENT_DCHAN_DOWN 2 /* D-channel is down */
|
||||
#define PRI_EVENT_RESTART 3 /* B-channel is restarted */
|
||||
#define PRI_EVENT_CONFIG_ERR 4 /* Configuration Error Detected */
|
||||
#define PRI_EVENT_RING 5 /* Incoming call */
|
||||
#define PRI_EVENT_HANGUP 6 /* Call got hung up */
|
||||
#define PRI_EVENT_RINGING 7 /* Call is ringing (alerting) */
|
||||
#define PRI_EVENT_ANSWER 8 /* Call has been answered */
|
||||
|
||||
/* Simple states */
|
||||
#define PRI_STATE_DOWN 0
|
||||
#define PRI_STATE_UP 1
|
||||
|
||||
/* Dialing plan */
|
||||
#define PRI_INTERNATIONAL_ISDN 0x11
|
||||
#define PRI_NATIONAL_ISDN 0x21
|
||||
#define PRI_LOCAL_ISDN 0x41
|
||||
#define PRI_PRIVATE 0x49
|
||||
#define PRI_UNKNOWN 0x0
|
||||
|
||||
/* Presentation */
|
||||
#define PRES_ALLOWED_USER_NUMBER_NOT_SCREENED 0x00
|
||||
#define PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN 0x01
|
||||
#define PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN 0x02
|
||||
#define PRES_ALLOWED_NETWORK_NUMBER 0x03
|
||||
#define PRES_PROHIB_USER_NUMBER_NOT_SCREENED 0x20
|
||||
#define PRES_PROHIB_USER_NUMBER_PASSED_SCREEN 0x21
|
||||
#define PRES_PROHIB_USER_NUMBER_FAILED_SCREEN 0x22
|
||||
#define PRES_PROHIB_NETWORK_NUMBER 0x23
|
||||
#define PRES_NUMBER_NOT_AVAILABLE 0x43
|
||||
|
||||
/* Causes for disconnection */
|
||||
#define PRI_CAUSE_UNALLOCATED 1
|
||||
#define PRI_CAUSE_NO_ROUTE_TRANSIT_NET 2
|
||||
#define PRI_CAUSE_NO_ROUTE_DESTINATION 3
|
||||
#define PRI_CAUSE_CHANNEL_UNACCEPTABLE 6
|
||||
#define PRI_CAUSE_CALL_AWARDED_DELIVERED 7
|
||||
#define PRI_CAUSE_NORMAL_CLEARING 16
|
||||
#define PRI_CAUSE_USER_BUSY 17
|
||||
#define PRI_CAUSE_NO_USER_RESPONSE 18
|
||||
#define PRI_CAUSE_NO_ANSWER 19
|
||||
#define PRI_CAUSE_CALL_REJECTED 21
|
||||
#define PRI_CAUSE_DESTINATION_OUT_OF_ORDER 27
|
||||
#define PRI_CAUSE_INVALID_NUMBER_FORMAT 28
|
||||
#define PRI_CAUSE_RESPONSE_TO_STATUS_ENQUIRY 30
|
||||
#define PRI_CAUSE_NORMAL_UNSPECIFIED 31
|
||||
#define PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION 34
|
||||
#define PRI_CAUSE_NORMAL_TEMPORARY_FAILURE 41
|
||||
#define PRI_CAUSE_SWITCH_CONGESTION 42
|
||||
#define PRI_CAUSE_ACCESS_INFO_DISCARDED 43
|
||||
#define PRI_CAUSE_REQUESTED_CHAN_UNAVAIL 44
|
||||
#define PRI_CAUSE_BEARERCAPABILITY_NOTAUTH 57
|
||||
#define PRI_CAUSE_BEARERCAPABILITY_NOTIMPL 65
|
||||
#define PRI_CAUSE_INVALID_CALL_REFERENCE 81
|
||||
#define PRI_CAUSE_INCOMPATIBLE_DESTINATION 88
|
||||
#define PRI_CAUSE_MANDATORY_IE_MISSING 96
|
||||
#define PRI_CAUSE_MESSAGE_TYPE_NONEXIST 97
|
||||
#define PRI_CAUSE_IE_NONEXIST 99
|
||||
#define PRI_CAUSE_INVALID_IE_CONTENTS 100
|
||||
#define PRI_CAUSE_WRONG_CALL_STATE 101
|
||||
#define PRI_CAUSE_RECOVERY_ON_TIMER_EXPIRE 102
|
||||
#define PRI_CAUSE_PROTOCOL_ERROR 111
|
||||
#define PRI_CAUSE_INTERWORKING 127
|
||||
|
||||
/* Transmit capabilities */
|
||||
#define PRI_TRANS_CAP_SPEECH 0x0
|
||||
#define PRI_TRANS_CAP_DIGITAL 0x80
|
||||
#define PRI_TRANS_CAP_AUDIO 0x10
|
||||
|
||||
|
||||
typedef struct q931_call q931_call;
|
||||
|
||||
typedef struct pri_event_generic {
|
||||
/* Events with no additional information fall in this category */
|
||||
int e;
|
||||
} pri_event_generic;
|
||||
|
||||
typedef struct pri_event_error {
|
||||
int e;
|
||||
char err[256];
|
||||
} pri_event_error;
|
||||
|
||||
typedef struct pri_event_restart {
|
||||
int e;
|
||||
int channel;
|
||||
} pri_event_restart;
|
||||
|
||||
typedef struct pri_event_ringing {
|
||||
int e;
|
||||
int channel;
|
||||
int cref;
|
||||
q931_call *call;
|
||||
} pri_event_ringing;
|
||||
|
||||
typedef struct pri_event_answer {
|
||||
int e;
|
||||
int channel;
|
||||
int cref;
|
||||
q931_call *call;
|
||||
} pri_event_answer;
|
||||
|
||||
typedef struct pri_event_ring {
|
||||
int e;
|
||||
int channel; /* Channel requested */
|
||||
int callingpres; /* Presentation of Calling CallerID */
|
||||
int callingplan; /* Dialing plan of Calling entity */
|
||||
char callingnum[256]; /* Calling number */
|
||||
int calledplan; /* Dialing plan of Called number */
|
||||
char callednum[256]; /* Called number */
|
||||
int flexible; /* Are we flexible with our channel selection? */
|
||||
int cref; /* Call Reference Number */
|
||||
int ctype; /* Call type (see PRI_TRANS_CAP_* */
|
||||
q931_call *call; /* Opaque call pointer */
|
||||
} pri_event_ring;
|
||||
|
||||
typedef struct pri_event_hangup {
|
||||
int e;
|
||||
int channel; /* Channel requested */
|
||||
int cause;
|
||||
int cref;
|
||||
q931_call *call; /* Opaque call pointer */
|
||||
} pri_event_hangup;
|
||||
|
||||
typedef union {
|
||||
int e;
|
||||
pri_event_generic gen; /* Generic view */
|
||||
pri_event_restart restart; /* Restart view */
|
||||
pri_event_error err; /* Error view */
|
||||
pri_event_ring ring; /* Ring */
|
||||
pri_event_hangup hangup; /* Hang up */
|
||||
pri_event_ringing ringing; /* Ringing */
|
||||
pri_event_ringing answer; /* Answer */
|
||||
} pri_event;
|
||||
|
||||
struct pri;
|
||||
|
||||
|
||||
/* Create a D-channel on a given file descriptor. The file descriptor must be a
|
||||
channel operating in HDLC mode with FCS computed by the fd's driver. Also it
|
||||
must be NON-BLOCKING! Frames received on the fd should include FCS. Nodetype
|
||||
must be one of PRI_NETWORK or PRI_CPE. switchtype should be PRI_SWITCH_* */
|
||||
extern struct pri *pri_new(int fd, int nodetype, int switchtype);
|
||||
|
||||
/* Set debug parameters on PRI -- see above debug definitions */
|
||||
extern void pri_set_debug(struct pri *pri, int debug);
|
||||
|
||||
/* Run PRI on the given D-channel, taking care of any events that
|
||||
need to be handled. If block is set, it will block until an event
|
||||
occurs which needs to be handled */
|
||||
extern pri_event *pri_dchannel_run(struct pri *pri, int block);
|
||||
|
||||
/* Check for an outstanding event on the PRI */
|
||||
pri_event *pri_check_event(struct pri *pri);
|
||||
|
||||
/* Give a name to a given event ID */
|
||||
extern char *pri_event2str(int id);
|
||||
|
||||
/* Give a name toa node type */
|
||||
extern char *pri_node2str(int id);
|
||||
|
||||
/* Give a name to a switch type */
|
||||
extern char *pri_switch2str(int id);
|
||||
|
||||
/* Print an event */
|
||||
extern void pri_dump_event(struct pri *pri, pri_event *e);
|
||||
|
||||
/* Turn an event ID into a string */
|
||||
extern char *pri_event2str(int e);
|
||||
|
||||
/* Turn presentation into a string */
|
||||
extern char *pri_pres2str(int pres);
|
||||
|
||||
/* Turn numbering plan into a string */
|
||||
extern char *pri_plan2str(int plan);
|
||||
|
||||
/* Turn cause into a string */
|
||||
extern char *pri_cause2str(int cause);
|
||||
|
||||
/* Acknowledge a call and place it on the given channel. Set info to non-zero if there
|
||||
is in-band data available on the channel */
|
||||
extern int pri_acknowledge(struct pri *pri, q931_call *call, int channel, int info);
|
||||
|
||||
/* Answer the call on the given channel (ignored if you called acknowledge already).
|
||||
Set non-isdn to non-zero if you are not connecting to ISDN equipment */
|
||||
extern int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn);
|
||||
|
||||
/* Release/Reject a call */
|
||||
extern int pri_release(struct pri *pri, q931_call *call, int cause);
|
||||
|
||||
/* Hangup / Disconnect a call */
|
||||
extern int pri_disconnect(struct pri *pri, q931_call *call, int cause);
|
||||
|
||||
/* Create a new call */
|
||||
extern q931_call *pri_new_call(struct pri *pri);
|
||||
|
||||
/* How long until you need to poll for a new event */
|
||||
extern struct timeval *pri_schedule_next(struct pri *pri);
|
||||
|
||||
/* Run any pending schedule events */
|
||||
extern int pri_schedule_run(struct pri *pri);
|
||||
|
||||
extern int pri_call(struct pri *pri, q931_call *c, int transmode, int channel,
|
||||
int exclusive, int nonisdn, char *caller, int callerplan, int callerpres,
|
||||
char *called,int calledplan);
|
||||
#endif
|
90
pri_internal.h
Executable file
90
pri_internal.h
Executable file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* libpri: An implementation of Primary Rate ISDN
|
||||
*
|
||||
* Written by Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* Copyright (C) 2001, Linux Support Services, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the 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 _PRI_INTERNAL_H
|
||||
#define _PRI_INTERNAL_H
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
struct pri_sched {
|
||||
struct timeval when;
|
||||
void (*callback)(void *data);
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct q921_frame;
|
||||
enum q931_state;
|
||||
enum q931_mode;
|
||||
|
||||
/* No more than 128 scheduled events */
|
||||
#define MAX_SCHED 128
|
||||
|
||||
struct pri {
|
||||
int fd; /* File descriptor for D-Channel */
|
||||
struct pri_sched pri_sched[MAX_SCHED]; /* Scheduled events */
|
||||
int debug; /* Debug stuff */
|
||||
int state; /* State of D-channel */
|
||||
int switchtype; /* Switch type */
|
||||
int localtype; /* Local network type (unknown, network, cpe) */
|
||||
int remotetype; /* Remote network type (unknown, network, cpe) */
|
||||
|
||||
/* Q.921 State */
|
||||
int q921_state;
|
||||
int window; /* Max window size */
|
||||
int v_s; /* Next N(S) for transmission */
|
||||
int v_a; /* Last acknowledged frame */
|
||||
int v_r; /* Next frame expected to be received */
|
||||
int v_na; /* What we've told our peer we've acknowledged */
|
||||
int solicitfbit; /* Have we sent an I or S frame with the F-bit set? */
|
||||
int retrans; /* Retransmissions */
|
||||
|
||||
int cref; /* Next call reference value */
|
||||
|
||||
int busy; /* Peer is busy */
|
||||
|
||||
/* Various timers */
|
||||
int sabme_timer; /* SABME retransmit */
|
||||
int t203_timer; /* Max idle time */
|
||||
int t200_timer; /* T-200 retransmission timer */
|
||||
|
||||
/* Used by scheduler */
|
||||
struct timeval tv;
|
||||
pri_event ev; /* Static event thingy */
|
||||
|
||||
/* Q.921 Re-transmission queue */
|
||||
struct q921_frame *txqueue;
|
||||
|
||||
/* Q.931 calls */
|
||||
q931_call *calls;
|
||||
};
|
||||
|
||||
extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data);
|
||||
|
||||
extern int pri_schedule_run(struct pri *pri);
|
||||
|
||||
extern void pri_schedule_del(struct pri *pri, int ev);
|
||||
|
||||
extern pri_event *pri_mkerror(struct pri *pri, char *errstr);
|
||||
|
||||
#endif
|
153
pri_q921.h
Executable file
153
pri_q921.h
Executable file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* libpri: An implementation of Primary Rate ISDN
|
||||
*
|
||||
* Written by Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* Copyright (C) 2001, Linux Support Services, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the 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 _PRI_Q921_H
|
||||
#define _PRI_Q921_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <endian.h>
|
||||
|
||||
/* Timer values */
|
||||
|
||||
#define T_WAIT_MIN 2000
|
||||
#define T_WAIT_MAX 10000
|
||||
#define T_200 1000 /* 1 second between SABME's */
|
||||
#define T_203 10000 /* 10 seconds with no packets max */
|
||||
|
||||
#define Q921_FRAMETYPE_MASK 0x3
|
||||
|
||||
#define Q921_FRAMETYPE_U 0x3
|
||||
#define Q921_FRAMETYPE_I 0x0
|
||||
#define Q921_FRAMETYPE_S 0x1
|
||||
|
||||
|
||||
typedef struct q921_header {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
u_int8_t sapi:6; /* Service Access Point Indentifier (always 0 for PRI) (0) */
|
||||
u_int8_t c_r:1; /* Command/Response (0 if CPE, 1 if network) */
|
||||
u_int8_t ea1:1; /* Extended Address (0) */
|
||||
u_int8_t tei:7; /* Terminal Endpoint Identifier (0) */
|
||||
u_int8_t ea2:1; /* Extended Address Bit (1) */
|
||||
#else
|
||||
u_int8_t ea1:1; /* Extended Address (0) */
|
||||
u_int8_t c_r:1; /* Command/Response (0 if CPE, 1 if network) */
|
||||
u_int8_t sapi:6; /* Service Access Point Indentifier (always 0 for PRI) (0) */
|
||||
u_int8_t ea2:1; /* Extended Address Bit (1) */
|
||||
u_int8_t tei:7; /* Terminal Endpoint Identifier (0) */
|
||||
#endif
|
||||
u_int8_t data[0]; /* Further data */
|
||||
} q921_header;
|
||||
|
||||
/* A Supervisory Format frame */
|
||||
typedef struct q921_s {
|
||||
struct q921_header h; /* Header */
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
u_int8_t x0:4; /* Unused */
|
||||
u_int8_t ss:2; /* Supervisory frame bits */
|
||||
u_int8_t ft:2; /* Frame type bits (01) */
|
||||
u_int8_t n_r:7; /* Number Received */
|
||||
u_int8_t p_f:1; /* Poll/Final bit */
|
||||
#else
|
||||
u_int8_t ft:2; /* Frame type bits (01) */
|
||||
u_int8_t ss:2; /* Supervisory frame bits */
|
||||
u_int8_t x0:4; /* Unused */
|
||||
u_int8_t p_f:1; /* Poll/Final bit */
|
||||
u_int8_t n_r:7; /* Number Received */
|
||||
#endif
|
||||
u_int8_t data[0]; /* Any further data */
|
||||
u_int8_t fcs[2]; /* At least an FCS */
|
||||
} q921_s;
|
||||
|
||||
/* An Unnumbered Format frame */
|
||||
typedef struct q921_u {
|
||||
struct q921_header h; /* Header */
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
u_int8_t m3:3; /* Top 3 modifier bits */
|
||||
u_int8_t p_f:1; /* Poll/Final bit */
|
||||
u_int8_t m2:2; /* Two more modifier bits */
|
||||
u_int8_t ft:2; /* Frame type bits (11) */
|
||||
#else
|
||||
u_int8_t ft:2; /* Frame type bits (11) */
|
||||
u_int8_t m2:2; /* Two more modifier bits */
|
||||
u_int8_t p_f:1; /* Poll/Final bit */
|
||||
u_int8_t m3:3; /* Top 3 modifier bits */
|
||||
#endif
|
||||
u_int8_t data[0]; /* Any further data */
|
||||
u_int8_t fcs[2]; /* At least an FCS */
|
||||
} q921_u;
|
||||
|
||||
/* An Information frame */
|
||||
typedef struct q921_i {
|
||||
struct q921_header h; /* Header */
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
u_int8_t n_s:7; /* Number sent */
|
||||
u_int8_t ft:1; /* Frame type (0) */
|
||||
u_int8_t n_r:7; /* Number received */
|
||||
u_int8_t p_f:1; /* Poll/Final bit */
|
||||
#else
|
||||
u_int8_t ft:1; /* Frame type (0) */
|
||||
u_int8_t n_s:7; /* Number sent */
|
||||
u_int8_t p_f:1; /* Poll/Final bit */
|
||||
u_int8_t n_r:7; /* Number received */
|
||||
#endif
|
||||
u_int8_t data[0]; /* Any further data */
|
||||
u_int8_t fcs[2]; /* At least an FCS */
|
||||
} q921_i;
|
||||
|
||||
typedef union {
|
||||
u_int8_t raw[0];
|
||||
q921_u u;
|
||||
q921_s s;
|
||||
q921_i i;
|
||||
struct q921_header h;
|
||||
} q921_h;
|
||||
|
||||
typedef struct q921_frame {
|
||||
struct q921_frame *next; /* Next in list */
|
||||
int len; /* Length of header + body */
|
||||
q921_i h;
|
||||
} q921_frame;
|
||||
|
||||
#define Q921_INC(j) (j) = ((j) + 1) % 128
|
||||
|
||||
typedef enum q921_state {
|
||||
Q921_LINK_CONNECTION_RELEASED, /* Also known as TEI_ASSIGNED */
|
||||
Q921_LINK_CONNECTION_ESTABLISHED,
|
||||
Q921_AWAITING_ESTABLISH,
|
||||
Q921_AWAITING_RELEASE
|
||||
} q921_state;
|
||||
|
||||
/* Dumps a *known good* Q.921 packet */
|
||||
extern void q921_dump(q921_h *h, int len, int showraw, int txrx);
|
||||
|
||||
/* Bring up the D-channel */
|
||||
extern void q921_start(struct pri *pri);
|
||||
|
||||
extern void q921_reset(struct pri *pri);
|
||||
|
||||
extern pri_event *q921_receive(struct pri *pri, q921_h *h, int len);
|
||||
|
||||
extern int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr);
|
||||
|
||||
#endif
|
190
pri_q931.h
Executable file
190
pri_q931.h
Executable file
@ -0,0 +1,190 @@
|
||||
/*
|
||||
* libpri: An implementation of Primary Rate ISDN
|
||||
*
|
||||
* Written by Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* Copyright (C) 2001, Linux Support Services, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the 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 _PRI_Q931_H
|
||||
#define _PRI_Q931_H
|
||||
|
||||
typedef enum q931_state {
|
||||
/* User states */
|
||||
U0_NULL_STATE,
|
||||
U1_CALL_INITIATED,
|
||||
U2_OVERLAP_SENDING,
|
||||
U3_OUTGOING_CALL_PROCEEDING,
|
||||
U4_CALL_DELIVERED,
|
||||
U6_CALL_PRESENT,
|
||||
U7_CALL_RECEIVED,
|
||||
U8_CONNECT_REQUEST,
|
||||
U9_INCOMING_CALL_PROCEEDING,
|
||||
U10_ACTIVE,
|
||||
U11_DISCONNECT_REQUEST,
|
||||
U12_DISCONNECT_INDICATION,
|
||||
U15_SUSPEND_REQUEST,
|
||||
U17_RESUME_REQUEST,
|
||||
U19_RELEASE_REQUEST,
|
||||
U25_OVERLAP_RECEIVING,
|
||||
/* Network states */
|
||||
N0_NULL_STATE,
|
||||
N1_CALL_INITIATED,
|
||||
N2_OVERLAP_SENDING,
|
||||
N3_OUTGOING_CALL_PROCEEDING,
|
||||
N4_CALL_DELIVERED,
|
||||
N6_CALL_PRESENT,
|
||||
N7_CALL_RECEIVED,
|
||||
N8_CONNECT_REQUEST,
|
||||
N9_INCOMING_CALL_PROCEEDING,
|
||||
N10_ACTIVE,
|
||||
N11_DISCONNECT_REQUEST,
|
||||
N12_DISCONNECT_INDICATION,
|
||||
N15_SUSPEND_REQUEST,
|
||||
N17_RESUME_REQUEST,
|
||||
N19_RELEASE_REQUEST,
|
||||
N22_CALL_ABORT,
|
||||
N25_OVERLAP_RECEIVING
|
||||
} q931_state;
|
||||
|
||||
typedef enum q931_mode {
|
||||
UNKNOWN_MODE,
|
||||
CIRCUIT_MODE,
|
||||
PACKET_MODE
|
||||
} q931_mode;
|
||||
|
||||
typedef struct q931_h {
|
||||
unsigned char raw[0];
|
||||
u_int8_t pd; /* Protocol Discriminator */
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
u_int8_t x0:4;
|
||||
u_int8_t crlen:4;
|
||||
#else
|
||||
u_int8_t crlen:4;
|
||||
u_int8_t x0:4;
|
||||
#endif
|
||||
u_int8_t contents[0];
|
||||
u_int8_t crv[3];
|
||||
} q931_h;
|
||||
|
||||
|
||||
/* Message type header */
|
||||
typedef struct q931_mh {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
u_int8_t f:1;
|
||||
u_int8_t msg:7;
|
||||
#else
|
||||
u_int8_t msg:7;
|
||||
u_int8_t f:1;
|
||||
#endif
|
||||
u_int8_t data[0];
|
||||
} q931_mh;
|
||||
|
||||
/* Information element format */
|
||||
typedef struct q931_ie {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
u_int8_t f:1;
|
||||
u_int8_t ie:7;
|
||||
#else
|
||||
u_int8_t ie:7;
|
||||
u_int8_t f:1;
|
||||
#endif
|
||||
u_int8_t len;
|
||||
u_int8_t data[0];
|
||||
} q931_ie;
|
||||
|
||||
#define Q931_RES_HAVEEVENT (1 << 0)
|
||||
#define Q931_RES_INERRROR (1 << 1)
|
||||
|
||||
#define Q931_PROTOCOL_DISCRIMINATOR 0x08
|
||||
|
||||
/* Q.931 / National ISDN Message Types */
|
||||
|
||||
/* Call Establishment Messages */
|
||||
#define Q931_ALERTING 0x01
|
||||
#define Q931_CALL_PROCEEDING 0x02
|
||||
#define Q931_CONNECT 0x07
|
||||
#define Q931_CONNECT_ACKNOWLEDGE 0x0f
|
||||
#define Q931_PROGRESS 0x03
|
||||
#define Q931_SETUP 0x05
|
||||
|
||||
/* Call Disestablishment Messages */
|
||||
#define Q931_DISCONNECT 0x45
|
||||
#define Q931_RELEASE 0x4d
|
||||
#define Q931_RELEASE_COMPLETE 0x5a
|
||||
#define Q931_RESTART 0x46
|
||||
#define Q931_RESTART_ACKNOWLEDGE 0x4e
|
||||
|
||||
/* Miscellaneous Messages */
|
||||
#define Q931_STATUS 0x7d
|
||||
#define Q931_STATUS_ENQUIRY 0x75
|
||||
|
||||
/* Maintenance messages (codeset 0 only) */
|
||||
#define NATIONAL_SERVICE 0x0f
|
||||
#define NATIONAL_SERVICE_ACKNOWLEDGE 0x07
|
||||
|
||||
/* Special codeset 0 IE */
|
||||
#define NATIONAL_CHANGE_STATUS 0x1
|
||||
|
||||
/* Q.931 / National ISDN Information Elements */
|
||||
#define Q931_LOCKING_SHIFT 0x90
|
||||
#define Q931_BEARER_CAPABILITY 0x04
|
||||
#define Q931_CAUSE 0x08
|
||||
#define Q931_CALL_STATE 0x14
|
||||
#define Q931_CHANNEL_IDENT 0x18
|
||||
#define Q931_PROGRESS_INDICATOR 0x1e
|
||||
#define Q931_NETWORK_SPEC_FAC 0x20
|
||||
#define Q931_INFORMATION_RATE 0x40
|
||||
#define Q931_TRANSIT_DELAY 0x42
|
||||
#define Q931_TRANS_DELAY_SELECT 0x43
|
||||
#define Q931_BINARY_PARAMETERS 0x44
|
||||
#define Q931_WINDOW_SIZE 0x45
|
||||
#define Q931_PACKET_SIZE 0x46
|
||||
#define Q931_CLOSED_USER_GROUP 0x47
|
||||
#define Q931_REVERSE_CHARGE_INDIC 0x4a
|
||||
#define Q931_CALLING_PARTY_NUMBER 0x6c
|
||||
#define Q931_CALLING_PARTY_SUBADDR 0x6d
|
||||
#define Q931_CALLED_PARTY_NUMBER 0x70
|
||||
#define Q931_CALLED_PARTY_SUBADDR 0x71
|
||||
#define Q931_REDIRECTING_NUMBER 0x74
|
||||
#define Q931_REDIRECTING_SUBADDR 0x75
|
||||
#define Q931_TRANSIT_NET_SELECT 0x78
|
||||
#define Q931_RESTART_INDICATOR 0x79
|
||||
#define Q931_LOW_LAYER_COMPAT 0x7c
|
||||
#define Q931_HIGH_LAYER_COMPAT 0x7d
|
||||
|
||||
extern int q931_receive(struct pri *pri, q931_h *h, int len);
|
||||
|
||||
extern int q931_alerting(struct pri *pri, q931_call *call, int channel, int info);
|
||||
|
||||
extern int q931_call_proceeding(struct pri *pri, q931_call *call);
|
||||
|
||||
extern int q931_connect(struct pri *pri, q931_call *call, int channel, int nonisdn);
|
||||
|
||||
extern int q931_release(struct pri *pri, q931_call *call, int cause);
|
||||
|
||||
extern int q931_disconnect(struct pri *pri, q931_call *call, int cause);
|
||||
|
||||
extern q931_call *q931_new_call(struct pri *pri);
|
||||
|
||||
extern int q931_setup(struct pri *pri, q931_call *c, int transmode, int channel, int exclusive,
|
||||
int nonisdn, char *caller, int callerplan, int callerpres, char *called,
|
||||
int calledplan);
|
||||
|
||||
#endif
|
100
prisched.c
Executable file
100
prisched.c
Executable file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* libpri: An implementation of Primary Rate ISDN
|
||||
*
|
||||
* Written by Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* Copyright (C) 2001, Linux Support Services, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the 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 "libpri.h"
|
||||
#include "pri_internal.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
static int maxsched = 0;
|
||||
|
||||
/* Scheduler routines */
|
||||
int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data)
|
||||
{
|
||||
int x;
|
||||
struct timeval tv;
|
||||
for (x=1;x<MAX_SCHED;x++)
|
||||
if (!pri->pri_sched[x].callback)
|
||||
break;
|
||||
if (x == MAX_SCHED) {
|
||||
fprintf(stderr, "No more room in scheduler\n");
|
||||
return -1;
|
||||
}
|
||||
if (x > maxsched)
|
||||
maxsched = x;
|
||||
gettimeofday(&tv, NULL);
|
||||
tv.tv_sec += ms / 1000;
|
||||
tv.tv_usec += (ms % 1000) * 1000;
|
||||
if (tv.tv_usec > 1000000)
|
||||
tv.tv_usec -= 1000000;
|
||||
pri->pri_sched[x].when = tv;
|
||||
pri->pri_sched[x].callback = function;
|
||||
pri->pri_sched[x].data = data;
|
||||
return x;
|
||||
}
|
||||
|
||||
struct timeval *pri_schedule_next(struct pri *pri)
|
||||
{
|
||||
struct timeval *closest = NULL;
|
||||
int x;
|
||||
for (x=1;x<MAX_SCHED;x++) {
|
||||
if (pri->pri_sched[x].callback &&
|
||||
(!closest || (closest->tv_sec > pri->pri_sched[x].when.tv_sec) ||
|
||||
((closest->tv_sec == pri->pri_sched[x].when.tv_sec) &&
|
||||
(closest->tv_usec > pri->pri_sched[x].when.tv_usec))))
|
||||
closest = &pri->pri_sched[x].when;
|
||||
}
|
||||
return closest;
|
||||
}
|
||||
|
||||
int pri_schedule_run(struct pri *pri)
|
||||
{
|
||||
struct timeval tv;
|
||||
int x;
|
||||
int p = 0;
|
||||
void (*callback)(void *);
|
||||
void *data;
|
||||
gettimeofday(&tv, NULL);
|
||||
for (x=1;x<MAX_SCHED;x++) {
|
||||
if (pri->pri_sched[x].callback &&
|
||||
((pri->pri_sched[x].when.tv_sec < tv.tv_sec) ||
|
||||
((pri->pri_sched[x].when.tv_sec == tv.tv_sec) &&
|
||||
(pri->pri_sched[x].when.tv_usec <= tv.tv_usec)))) {
|
||||
p++;
|
||||
callback = pri->pri_sched[x].callback;
|
||||
data = pri->pri_sched[x].data;
|
||||
pri->pri_sched[x].callback = NULL;
|
||||
pri->pri_sched[x].data = NULL;
|
||||
callback(data);
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void pri_schedule_del(struct pri *pri,int id)
|
||||
{
|
||||
if ((id >= MAX_SCHED) || (id < 0))
|
||||
fprintf(stderr, "Asked to delete sched id %d???\n", id);
|
||||
pri->pri_sched[id].callback = NULL;
|
||||
}
|
Loading…
Reference in New Issue
Block a user