From 753a52aacd1403c8c20f26657f94093521ec0879 Mon Sep 17 00:00:00 2001 From: Mark Spencer Date: Fri, 13 Apr 2001 15:06:49 +0000 Subject: [PATCH] Version 0.1.0 from FTP git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@2 2fbb986a-6c06-0410-b554-c9c1f0a7f128 --- pri.c | 230 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100755 pri.c diff --git a/pri.c b/pri.c new file mode 100755 index 0000000..a507309 --- /dev/null +++ b/pri.c @@ -0,0 +1,230 @@ +/* + * libpri: An implementation of Primary Rate ISDN + * + * Written by Mark Spencer + * + * This program is confidential + * + * Copyright (C) 2001, Linux Support Services, Inc. + * All Rights Reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "libpri.h" +#include "pri_internal.h" +#include "pri_q921.h" +#include "pri_q931.h" + +char *pri_node2str(int node) +{ + switch(node) { + case PRI_UNKNOWN: + return "Unknown node type"; + case PRI_NETWORK: + return "Network"; + case PRI_CPE: + return "CPE"; + default: + return "Invalid value"; + } +} + +char *pri_switch2str(int sw) +{ + switch(sw) { + case PRI_SWITCH_NI2: + return "National ISDN"; + case PRI_SWITCH_DMS100: + return "Nortel DMS100"; + case PRI_SWITCH_LUCENT5E: + return "Lucent 5E"; + case PRI_SWITCH_ATT4ESS: + return "AT&T 4ESS"; + default: + return "Unknown switchtype"; + } +} + +struct pri *pri_new(int fd, int node, int switchtype) +{ + struct pri *p; + p = malloc(sizeof(struct pri)); + if (p) { + memset(p, 0, sizeof(struct pri)); + p->fd = fd; + p->localtype = node; + p->switchtype = switchtype; + p->cref = 1; + /* Start Q.921 layer */ + q921_start(p); + } + return p; +} + +char *pri_event2str(int id) +{ + switch(id) { + case PRI_EVENT_DCHAN_UP: + return "D-Channel Up"; + case PRI_EVENT_DCHAN_DOWN: + return "D-channel Down"; + case PRI_EVENT_RESTART: + return "Restart channel"; + case PRI_EVENT_RING: + return "Ring"; + case PRI_EVENT_CONFIG_ERR: + return "Configuration Error"; + default: + return "Unknown Event"; + } +} + +pri_event *pri_check_event(struct pri *pri) +{ + char buf[1024]; + int res; + pri_event *e; + res = read(pri->fd, buf, sizeof(buf)); + if (res < 0) { + if (errno != EAGAIN) + fprintf(stderr, "Read on %d failed: %s\n", pri->fd, strerror(errno)); + return NULL; + } + /* Receive the q921 packet */ + e = q921_receive(pri, (q921_h *)buf, res); + return e; +} + +static int wait_pri(struct pri *pri) +{ + struct timeval *tv; + fd_set fds; + int res; + FD_ZERO(&fds); + FD_SET(pri->fd, &fds); + tv = pri_schedule_next(pri); + res = select(pri->fd + 1, &fds, NULL, NULL, tv); + if (res < 0) + return -1; + return res; +} + +pri_event *pri_mkerror(struct pri *pri, char *errstr) +{ + /* Return a configuration error */ + pri->ev.err.e = PRI_EVENT_CONFIG_ERR; + strncpy(pri->ev.err.err, errstr, sizeof(pri->ev.err.err)); + return &pri->ev; +} + + +pri_event *pri_dchannel_run(struct pri *pri, int block) +{ + pri_event *e; + int res; + if (!pri) + return NULL; + if (block) { + do { + e = NULL; + res = wait_pri(pri); + /* Check for error / interruption */ + if (res < 0) + return NULL; + if (!res) + pri_schedule_run(pri); + else + e = pri_check_event(pri); + } while(!e); + } else { + e = pri_check_event(pri); + return e; + } + return e; +} + +void pri_set_debug(struct pri *pri, int debug) +{ + if (!pri) + return; + pri->debug = debug; +} + +int pri_acknowledge(struct pri *pri, q931_call *call, int channel, int info) +{ + if (!pri || !call) + return -1; + return q931_alerting(pri, call, channel, info); +} + +int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn) +{ + if (!pri || !call) + return -1; + return q931_connect(pri, call, channel, nonisdn); +} + +int pri_release(struct pri *pri, q931_call *call, int cause) +{ + if (!pri || !call) + return -1; + return q931_release(pri, call, cause); +} + +int pri_disconnect(struct pri *pri, q931_call *call, int cause) +{ + if (!pri || !call) + return -1; + return q931_disconnect(pri, call, cause); +} + +q931_call *pri_new_call(struct pri *pri) +{ + if (!pri) + return NULL; + return q931_new_call(pri); +} + +void pri_dump_event(struct pri *pri, pri_event *e) +{ + if (!pri || !e) + return; + printf("Event type: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e); + switch(e->gen.e) { + case PRI_EVENT_DCHAN_UP: + case PRI_EVENT_DCHAN_DOWN: + break; + case PRI_EVENT_CONFIG_ERR: + printf("Error: %s", e->err.err); + break; + case PRI_EVENT_RESTART: + printf("Restart on channel %d\n", e->restart.channel); + case PRI_EVENT_RING: + printf("Calling number: %s (%s, %s)\n", e->ring.callingnum, pri_plan2str(e->ring.callingplan), pri_pres2str(e->ring.callingpres)); + printf("Called number: %s (%s)\n", e->ring.callednum, pri_plan2str(e->ring.calledplan)); + printf("Channel: %d (%s) Reference number: %d\n", e->ring.channel, e->ring.flexible ? "Flexible" : "Not Flexible", e->ring.cref); + break; + case PRI_EVENT_HANGUP: + printf("Hangup, reference number: %d, reason: %s\n", e->hangup.cref, pri_cause2str(e->hangup.cause)); + break; + default: + printf("Don't know how to dump events of type %d\n", e->gen.e); + } +} + +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) +{ + if (!pri || !c) + return -1; + return q931_setup(pri, c, transmode, channel, exclusive, nonisdn, caller, callerplan, callerpres, called, calledplan); +}