Version 0.1.0 from FTP

git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@4 2fbb986a-6c06-0410-b554-c9c1f0a7f128
remotes/origin/1.0
Mark Spencer 24 years ago
parent 30f86c22db
commit 802b2d14e0

@ -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)

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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…
Cancel
Save