Add a support layer for the ISDN CAPI (http://www.capi.org/), which should
make it pretty simple to write drivers for cards which conform to CAPI. This code was originally written by Juha-Matti Liukkonen <jml@cubical.fi> of Cubical Solutions Ltd. for FreeBSD, and was now adapted to NetBSD by myself for the same company.
This commit is contained in:
parent
0553a30d48
commit
6a7a858eb2
|
@ -0,0 +1,136 @@
|
|||
/* $NetBSD: i4b_capi.h,v 1.1 2003/09/25 15:34:38 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Cubical Solutions Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* capi/capi.h The CAPI device interface.
|
||||
*
|
||||
* $FreeBSD: src/sys/i4b/capi/capi.h,v 1.1 2001/05/25 08:39:31 hm Exp $
|
||||
*/
|
||||
|
||||
#ifndef _I4B_CAPI_H_
|
||||
#define _I4B_CAPI_H_
|
||||
|
||||
/*
|
||||
// CAPI driver context: B channels and controller softcs.
|
||||
*/
|
||||
|
||||
#define INVALID -1
|
||||
|
||||
enum capi_b_state {
|
||||
B_FREE, /* 0: channel free, ncci invalid */
|
||||
B_CONNECT_CONF, /* 1: wait for CONNECT_CONF */
|
||||
B_CONNECT_IND, /* 2: IND got, wait for appl RESP */
|
||||
B_CONNECT_ACTIVE_IND, /* 3: wait for CONNECT_ACTIVE_IND */
|
||||
B_CONNECT_B3_CONF, /* 4: wait for CONNECT_B3_CONF */
|
||||
B_CONNECT_B3_IND, /* 5: wait for CONNECT_B3_IND */
|
||||
B_CONNECT_B3_ACTIVE_IND, /* 6: wait for CONNECT_B3_ACTIVE_IND */
|
||||
B_CONNECTED, /* 7: channel connected & in use */
|
||||
B_DISCONNECT_CONF, /* 8: wait for DISCONNECT_CONF */
|
||||
B_DISCONNECT_B3_CONF, /* 9: wait for DISCONNECT_B3_CONF */
|
||||
B_DISCONNECT_IND, /* 10: wait for DISCONNECT_IND */
|
||||
};
|
||||
|
||||
typedef struct capi_bchan
|
||||
{
|
||||
/* Channel state */
|
||||
|
||||
int ncci;
|
||||
#define CAPI_CTRL_MASK 0x000000ff
|
||||
#define CAPI_PLCI_MASK 0x0000ffff
|
||||
#define CAPI_NCCI_MASK 0xffff0000
|
||||
u_int16_t msgid;
|
||||
int busy;
|
||||
enum capi_b_state state;
|
||||
|
||||
struct ifqueue tx_queue;
|
||||
struct ifqueue rx_queue;
|
||||
int rxcount;
|
||||
int txcount;
|
||||
|
||||
/* The rest is needed for i4b integration */
|
||||
int bprot;
|
||||
int cdid;
|
||||
|
||||
struct mbuf *in_mbuf;
|
||||
isdn_link_t capi_isdn_linktab;
|
||||
|
||||
const struct isdn_l4_driver_functions *l4_driver;
|
||||
void *l4_driver_softc;
|
||||
} capi_bchan_t;
|
||||
|
||||
enum capi_c_state {
|
||||
C_DOWN, /* controller uninitialized */
|
||||
C_READY, /* controller initialized but not listening */
|
||||
C_UP, /* controller listening */
|
||||
};
|
||||
|
||||
typedef struct capi_softc {
|
||||
int sc_unit; /* index in capi_sc[] */
|
||||
int card_type; /* CARD_TYPEC_xxx, filled by ll driver */
|
||||
int sc_nbch; /* number of b channels on this controller */
|
||||
int sc_enabled; /* is daemon connected TRUE/FALSE */
|
||||
int sc_msgid; /* next CAPI message id */
|
||||
int capi_bri; /* bri identifier */
|
||||
char sc_profile[64];/* CAPI profile data */
|
||||
enum capi_c_state sc_state;
|
||||
|
||||
capi_bchan_t sc_bchan[MAX_BCHAN];
|
||||
|
||||
/* Link layer driver context holder and methods */
|
||||
void *ctx;
|
||||
|
||||
int (*load)(struct capi_softc *, int, u_int8_t *);
|
||||
int (*reg_appl)(struct capi_softc *, int, int);
|
||||
int (*rel_appl)(struct capi_softc *, int);
|
||||
int (*send)(struct capi_softc *, struct mbuf *);
|
||||
} capi_softc_t;
|
||||
|
||||
extern int ncapi;
|
||||
|
||||
#define CARD_TYPEC_CAPI_UNK 0
|
||||
#define CARD_TYPEC_AVM_T1_PCI 1
|
||||
#define CARD_TYPEC_AVM_B1_PCI 2
|
||||
#define CARD_TYPEC_AVM_B1_ISA 3
|
||||
|
||||
/*
|
||||
// CAPI upcalls for the link layer.
|
||||
*/
|
||||
|
||||
#define I4BCAPI_APPLID 1
|
||||
|
||||
extern int capi_ll_attach(capi_softc_t *, const char *, const char *);
|
||||
extern int capi_ll_control(capi_softc_t *, int op, int arg);
|
||||
extern int capi_ll_detach(capi_softc_t *);
|
||||
|
||||
#define CAPI_CTRL_READY 0 /* ctrl ready, value=TRUE/FALSE */
|
||||
#define CAPI_CTRL_PROFILE 1 /* set CAPI profile */
|
||||
#define CAPI_CTRL_NEW_NCCI 2 /* new ncci value, assign bchan */
|
||||
#define CAPI_CTRL_FREE_NCCI 3 /* free ncci value, clear bchan */
|
||||
|
||||
extern int capi_ll_receive(capi_softc_t *, struct mbuf *);
|
||||
|
||||
extern int capi_start_tx(void *, int bchan);
|
||||
|
||||
#endif /* _I4B_CAPI_H_ */
|
|
@ -0,0 +1,424 @@
|
|||
/* $NetBSD: i4b_capi_l4if.c,v 1.1 2003/09/25 15:34:38 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Cubical Solutions Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* capi/capi_l4if.c The CAPI i4b L4/device interface.
|
||||
*
|
||||
* $FreeBSD: src/sys/i4b/capi/capi_l4if.c,v 1.4 2002/04/04 21:03:20 jhb Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/callout.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include <netisdn/i4b_debug.h>
|
||||
#include <netisdn/i4b_ioctl.h>
|
||||
#include <netisdn/i4b_cause.h>
|
||||
#include <netisdn/i4b_l3l4.h>
|
||||
#include <netisdn/i4b_mbuf.h>
|
||||
#include <netisdn/i4b_global.h>
|
||||
#include <netisdn/i4b_l4.h>
|
||||
#include <netisdn/i4b_capi.h>
|
||||
#include <netisdn/i4b_capi_msgs.h>
|
||||
|
||||
static void n_connect_request(call_desc_t *);
|
||||
static void n_connect_response(call_desc_t *, int response, int cause);
|
||||
static void n_disconnect_request(call_desc_t *, int cause);
|
||||
static void n_alert_request(call_desc_t *);
|
||||
static void n_mgmt_command(struct isdn_l3_driver *, int cmd, void *parm);
|
||||
static int n_download(void *, int, struct isdn_dr_prot *);
|
||||
|
||||
static int ncapi = 0;
|
||||
|
||||
/*
|
||||
// i4b_capi_{ret,set}_linktab
|
||||
// i4b driver glue.
|
||||
//
|
||||
// i4b_capi_bch_config
|
||||
// Called by i4b driver to flush + {en,dis}able a channel.
|
||||
//
|
||||
// i4b_capi_bch_start_tx
|
||||
// Called by i4b driver to transmit a queued mbuf.
|
||||
//
|
||||
// i4b_capi_bch_stat
|
||||
// Called by i4b driver to obtain statistics information.
|
||||
*/
|
||||
|
||||
static isdn_link_t *
|
||||
i4b_capi_ret_linktab(void *token, int channel)
|
||||
{
|
||||
capi_softc_t *sc = token;
|
||||
|
||||
return &sc->sc_bchan[channel].capi_isdn_linktab;
|
||||
}
|
||||
|
||||
static void
|
||||
i4b_capi_set_link(void *token, int channel,
|
||||
const struct isdn_l4_driver_functions *l4_driver, void *l4_inst)
|
||||
{
|
||||
capi_softc_t *sc = token;
|
||||
|
||||
sc->sc_bchan[channel].l4_driver = l4_driver;
|
||||
sc->sc_bchan[channel].l4_driver_softc = l4_inst;
|
||||
}
|
||||
|
||||
static void
|
||||
i4b_capi_bch_config(void *token, int chan, int bprot, int activate)
|
||||
{
|
||||
capi_softc_t *sc = token;
|
||||
|
||||
i4b_Bcleanifq(&sc->sc_bchan[chan].tx_queue);
|
||||
sc->sc_bchan[chan].tx_queue.ifq_maxlen = IFQ_MAXLEN;
|
||||
sc->sc_bchan[chan].txcount = 0;
|
||||
|
||||
/* The telephony drivers use rx_queue for receive. */
|
||||
i4b_Bcleanifq(&sc->sc_bchan[chan].rx_queue);
|
||||
sc->sc_bchan[chan].rx_queue.ifq_maxlen = IFQ_MAXLEN;
|
||||
sc->sc_bchan[chan].rxcount = 0;
|
||||
|
||||
/* HDLC frames are put to in_mbuf */
|
||||
i4b_Bfreembuf(sc->sc_bchan[chan].in_mbuf);
|
||||
sc->sc_bchan[chan].in_mbuf = NULL;
|
||||
|
||||
/* Because of the difference, we need to remember the protocol. */
|
||||
sc->sc_bchan[chan].bprot = bprot;
|
||||
sc->sc_bchan[chan].busy = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
i4b_capi_bch_start_tx(void *token, int chan)
|
||||
{
|
||||
capi_softc_t *sc = token;
|
||||
int s;
|
||||
|
||||
s = splnet();
|
||||
|
||||
if (sc->sc_bchan[chan].state != B_CONNECTED) {
|
||||
splx(s);
|
||||
printf("capi%d: start_tx on unconnected channel\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sc->sc_bchan[chan].busy) {
|
||||
splx(s);
|
||||
return;
|
||||
}
|
||||
|
||||
capi_start_tx(sc, chan);
|
||||
|
||||
splx(s);
|
||||
}
|
||||
|
||||
static void
|
||||
i4b_capi_bch_stat(void *token, int chan, bchan_statistics_t *bsp)
|
||||
{
|
||||
capi_softc_t *sc = token;
|
||||
int s = splnet();
|
||||
|
||||
bsp->outbytes = sc->sc_bchan[chan].txcount;
|
||||
bsp->inbytes = sc->sc_bchan[chan].rxcount;
|
||||
|
||||
sc->sc_bchan[chan].txcount = 0;
|
||||
sc->sc_bchan[chan].rxcount = 0;
|
||||
|
||||
splx(s);
|
||||
}
|
||||
|
||||
int capi_start_tx(void *token, int chan)
|
||||
{
|
||||
capi_softc_t *sc = token;
|
||||
struct mbuf *m_b3;
|
||||
int sent = 0;
|
||||
|
||||
IF_DEQUEUE(&sc->sc_bchan[chan].tx_queue, m_b3);
|
||||
while (m_b3) {
|
||||
struct mbuf *m = m_b3->m_next;
|
||||
|
||||
sc->sc_bchan[chan].txcount += m_b3->m_len;
|
||||
capi_data_b3_req(sc, chan, m_b3);
|
||||
sent++;
|
||||
|
||||
m_b3 = m;
|
||||
}
|
||||
|
||||
if (sc->sc_bchan[chan].l4_driver) {
|
||||
capi_bchan_t *bch = &sc->sc_bchan[chan];
|
||||
|
||||
/* Notify i4b driver of activity, and if the queue is drained. */
|
||||
if (sent)
|
||||
(*bch->l4_driver->bch_activity)(bch->l4_driver_softc, ACT_TX);
|
||||
|
||||
if (IF_QEMPTY(&bch->tx_queue))
|
||||
(*bch->l4_driver->bch_tx_queue_empty)(bch->l4_driver_softc);
|
||||
}
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
static const struct isdn_l4_bchannel_functions
|
||||
capi_l4_driver = {
|
||||
i4b_capi_bch_config,
|
||||
i4b_capi_bch_start_tx,
|
||||
i4b_capi_bch_stat
|
||||
};
|
||||
|
||||
/*
|
||||
// n_mgmt_command
|
||||
// i4b L4 management command.
|
||||
*/
|
||||
|
||||
static void
|
||||
n_mgmt_command(struct isdn_l3_driver *l3, int op, void *arg)
|
||||
{
|
||||
capi_softc_t *sc = l3->l1_token;
|
||||
|
||||
#if 0
|
||||
printf("capi%d: mgmt command %d\n", sc->sc_unit, op);
|
||||
#endif
|
||||
|
||||
switch(op) {
|
||||
case CMR_DOPEN:
|
||||
sc->sc_enabled = 1;
|
||||
break;
|
||||
|
||||
case CMR_DCLOSE:
|
||||
sc->sc_enabled = 0;
|
||||
break;
|
||||
|
||||
case CMR_SETTRACE:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// n_connect_request
|
||||
// i4b L4 wants to connect. We assign a B channel to the call,
|
||||
// send a CAPI_CONNECT_REQ, and set the channel to B_CONNECT_CONF.
|
||||
*/
|
||||
|
||||
static void
|
||||
n_connect_request(call_desc_t *cd)
|
||||
{
|
||||
capi_softc_t *sc;
|
||||
int bch, s;
|
||||
|
||||
sc = cd->l3drv->l1_token;
|
||||
bch = cd->channelid;
|
||||
|
||||
s = splnet();
|
||||
|
||||
if ((bch < 0) || (bch >= sc->sc_nbch))
|
||||
for (bch = 0; bch < sc->sc_nbch; bch++)
|
||||
if (sc->sc_bchan[bch].state == B_FREE)
|
||||
break;
|
||||
|
||||
if (bch == sc->sc_nbch) {
|
||||
splx(s);
|
||||
printf("capi%d: no free B channel\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
cd->channelid = bch;
|
||||
|
||||
capi_connect_req(sc, cd);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
/*
|
||||
// n_connect_response
|
||||
// i4b L4 answers a call. We send a CONNECT_RESP with the proper
|
||||
// Reject code, and set the channel to B_CONNECT_B3_IND or B_FREE,
|
||||
// depending whether we answer or not.
|
||||
*/
|
||||
|
||||
static void
|
||||
n_connect_response(call_desc_t *cd, int response, int cause)
|
||||
{
|
||||
capi_softc_t *sc;
|
||||
int bch, s;
|
||||
|
||||
sc = cd->l3drv->l1_token;
|
||||
bch = cd->channelid;
|
||||
|
||||
T400_stop(cd);
|
||||
|
||||
cd->response = response;
|
||||
cd->cause_out = cause;
|
||||
|
||||
s = splnet();
|
||||
capi_connect_resp(sc, cd);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
/*
|
||||
// n_disconnect_request
|
||||
// i4b L4 wants to disconnect. We send a DISCONNECT_REQ and
|
||||
// set the channel to B_DISCONNECT_CONF.
|
||||
*/
|
||||
|
||||
static void
|
||||
n_disconnect_request(call_desc_t *cd, int cause)
|
||||
{
|
||||
capi_softc_t *sc;
|
||||
int bch, s;
|
||||
|
||||
sc = cd->l3drv->l1_token;
|
||||
bch = cd->channelid;
|
||||
|
||||
cd->cause_out = cause;
|
||||
|
||||
s = splnet();
|
||||
capi_disconnect_req(sc, cd);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
/*
|
||||
// n_alert_request
|
||||
// i4b L4 wants to alert an incoming call. We send ALERT_REQ.
|
||||
*/
|
||||
|
||||
static void
|
||||
n_alert_request(call_desc_t *cd)
|
||||
{
|
||||
capi_softc_t *sc;
|
||||
int s;
|
||||
|
||||
sc = cd->l3drv->l1_token;
|
||||
|
||||
s = splnet();
|
||||
capi_alert_req(sc, cd);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
/*
|
||||
// n_download
|
||||
// L4 -> firmware download
|
||||
*/
|
||||
|
||||
static int
|
||||
n_download(void *token, int numprotos, struct isdn_dr_prot *protocols)
|
||||
{
|
||||
capi_softc_t *sc = token;
|
||||
|
||||
if (sc->load) {
|
||||
(*sc->load)(sc, protocols[0].bytecount,
|
||||
protocols[0].microcode);
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
static const struct isdn_l3_driver_functions
|
||||
capi_l3_functions = {
|
||||
i4b_capi_ret_linktab,
|
||||
i4b_capi_set_link,
|
||||
n_connect_request,
|
||||
n_connect_response,
|
||||
n_disconnect_request,
|
||||
n_alert_request,
|
||||
n_download,
|
||||
NULL,
|
||||
n_mgmt_command
|
||||
};
|
||||
|
||||
/*
|
||||
// capi_ll_attach
|
||||
// Called by a link layer driver at boot time.
|
||||
*/
|
||||
|
||||
int
|
||||
capi_ll_attach(capi_softc_t *sc, const char *devname, const char *cardname)
|
||||
{
|
||||
struct isdn_l3_driver *l3drv;
|
||||
int i;
|
||||
|
||||
/* Unit state */
|
||||
|
||||
sc->sc_enabled = 0;
|
||||
sc->sc_state = C_DOWN;
|
||||
sc->sc_msgid = 0;
|
||||
|
||||
for (i = 0; i < sc->sc_nbch; i++) {
|
||||
sc->sc_bchan[i].ncci = INVALID;
|
||||
sc->sc_bchan[i].msgid = 0;
|
||||
sc->sc_bchan[i].busy = 0;
|
||||
sc->sc_bchan[i].state = B_FREE;
|
||||
|
||||
memset(&sc->sc_bchan[i].tx_queue, 0, sizeof(struct ifqueue));
|
||||
memset(&sc->sc_bchan[i].rx_queue, 0, sizeof(struct ifqueue));
|
||||
sc->sc_bchan[i].tx_queue.ifq_maxlen = IFQ_MAXLEN;
|
||||
sc->sc_bchan[i].rx_queue.ifq_maxlen = IFQ_MAXLEN;
|
||||
|
||||
sc->sc_bchan[i].txcount = 0;
|
||||
sc->sc_bchan[i].rxcount = 0;
|
||||
|
||||
sc->sc_bchan[i].cdid = CDID_UNUSED;
|
||||
sc->sc_bchan[i].bprot = BPROT_NONE;
|
||||
sc->sc_bchan[i].in_mbuf = NULL;
|
||||
|
||||
sc->sc_bchan[i].capi_isdn_linktab.l1token = sc;
|
||||
sc->sc_bchan[i].capi_isdn_linktab.channel = i;
|
||||
sc->sc_bchan[i].capi_isdn_linktab.bchannel_driver = &capi_l4_driver;
|
||||
sc->sc_bchan[i].capi_isdn_linktab.tx_queue = &sc->sc_bchan[i].tx_queue;
|
||||
sc->sc_bchan[i].capi_isdn_linktab.rx_queue = &sc->sc_bchan[i].rx_queue;
|
||||
sc->sc_bchan[i].capi_isdn_linktab.rx_mbuf = &sc->sc_bchan[i].in_mbuf;
|
||||
}
|
||||
|
||||
l3drv = isdn_attach_bri(devname, cardname, sc, &capi_l3_functions);
|
||||
|
||||
l3drv->tei = -1;
|
||||
l3drv->dl_est = DL_DOWN;
|
||||
l3drv->nbch = sc->sc_nbch;
|
||||
|
||||
sc->sc_unit = ncapi++;
|
||||
sc->capi_bri = l3drv->bri;
|
||||
|
||||
isdn_bri_ready(l3drv->bri);
|
||||
|
||||
printf("capi%d: card type %d attached\n", sc->sc_unit, sc->card_type);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// capi_ll_detach
|
||||
*/
|
||||
|
||||
int
|
||||
capi_ll_detach(capi_softc_t *sc)
|
||||
{
|
||||
|
||||
/* TODO */
|
||||
return(0);
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
/* $NetBSD: i4b_capi_llif.c,v 1.1 2003/09/25 15:34:38 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Cubical Solutions Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* capi/capi_llif.c The i4b CAPI link layer interface.
|
||||
*
|
||||
* $FreeBSD: src/sys/i4b/capi/capi_llif.c,v 1.1 2001/05/25 08:39:31 hm Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/callout.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include <netisdn/i4b_debug.h>
|
||||
#include <netisdn/i4b_ioctl.h>
|
||||
#include <netisdn/i4b_cause.h>
|
||||
#include <netisdn/i4b_l3l4.h>
|
||||
#include <netisdn/i4b_mbuf.h>
|
||||
#include <netisdn/i4b_global.h>
|
||||
#include <netisdn/i4b_l4.h>
|
||||
#include <netisdn/i4b_capi.h>
|
||||
#include <netisdn/i4b_capi_msgs.h>
|
||||
|
||||
/*
|
||||
// capi_ll_control
|
||||
// CAPI link layer control routine. Called by a link layer
|
||||
// driver when its state changes.
|
||||
*/
|
||||
|
||||
int
|
||||
capi_ll_control(capi_softc_t *sc, int op, int arg)
|
||||
{
|
||||
switch (op) {
|
||||
case CAPI_CTRL_READY:
|
||||
if (arg) {
|
||||
sc->sc_state = C_READY;
|
||||
|
||||
/*
|
||||
* Register our CAPI ApplId and send CAPI_LISTEN_REQ
|
||||
* with CIP Mask value 1 (match all).
|
||||
*/
|
||||
|
||||
sc->reg_appl(sc, I4BCAPI_APPLID, sc->sc_nbch);
|
||||
capi_listen_req(sc, 0x10007);
|
||||
|
||||
} else {
|
||||
sc->sc_state = C_DOWN;
|
||||
/* XXX go through cds and notify L4 of pdeact? XXX */
|
||||
}
|
||||
break;
|
||||
|
||||
case CAPI_CTRL_PROFILE:
|
||||
bcopy((char*) arg, &sc->sc_profile, sizeof(sc->sc_profile));
|
||||
break;
|
||||
|
||||
case CAPI_CTRL_NEW_NCCI:
|
||||
case CAPI_CTRL_FREE_NCCI:
|
||||
/* We ignore the controller's NCCI notifications. */
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("capi%d: unknown control %d\n", sc->sc_unit, op);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
// i4b_capi_handlers
|
||||
// Array of message-handler pairs used to dispatch CAPI
|
||||
// messages sent to I4BCAPI_APPLID.
|
||||
*/
|
||||
|
||||
static struct capi_cmdtab {
|
||||
u_int16_t cmd;
|
||||
void (*handler)(capi_softc_t *, struct mbuf *);
|
||||
} i4b_capi_handlers[] = {
|
||||
{ CAPI_LISTEN_CONF, capi_listen_conf },
|
||||
{ CAPI_INFO_IND, capi_info_ind },
|
||||
{ CAPI_ALERT_CONF, capi_alert_conf },
|
||||
{ CAPI_CONNECT_CONF, capi_connect_conf },
|
||||
{ CAPI_CONNECT_IND, capi_connect_ind },
|
||||
{ CAPI_CONNECT_ACTIVE_IND, capi_connect_active_ind },
|
||||
{ CAPI_CONNECT_B3_CONF, capi_connect_b3_conf },
|
||||
{ CAPI_CONNECT_B3_IND, capi_connect_b3_ind },
|
||||
{ CAPI_CONNECT_B3_ACTIVE_IND, capi_connect_b3_active_ind },
|
||||
{ CAPI_DATA_B3_CONF, capi_data_b3_conf },
|
||||
{ CAPI_DATA_B3_IND, capi_data_b3_ind },
|
||||
{ CAPI_DISCONNECT_B3_IND, capi_disconnect_b3_ind },
|
||||
{ CAPI_DISCONNECT_CONF, capi_disconnect_conf },
|
||||
{ CAPI_DISCONNECT_IND, capi_disconnect_ind },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
/*
|
||||
// capi_ll_receive
|
||||
// CAPI link layer receive upcall. Called by a link layer
|
||||
// driver to dispatch incoming CAPI messages.
|
||||
*/
|
||||
|
||||
int
|
||||
capi_ll_receive(capi_softc_t *sc, struct mbuf *m)
|
||||
{
|
||||
u_int8_t *p = mtod(m, u_int8_t*);
|
||||
u_int16_t len, applid, msgid, cmd;
|
||||
|
||||
capimsg_getu16(p + 0, &len);
|
||||
capimsg_getu16(p + 2, &applid);
|
||||
capimsg_getu16(p + 4, &cmd);
|
||||
capimsg_getu16(p + 6, &msgid);
|
||||
|
||||
#if 0
|
||||
printf("capi%d: ll_receive hdr %04x %04x %04x %04x\n", sc->sc_unit,
|
||||
len, applid, cmd, msgid);
|
||||
#endif
|
||||
|
||||
if (applid == I4BCAPI_APPLID) {
|
||||
struct capi_cmdtab *e;
|
||||
for (e = i4b_capi_handlers; e->cmd && e->cmd != cmd; e++);
|
||||
if (e->cmd) (*e->handler)(sc, m);
|
||||
else printf("capi%d: unknown message %04x\n", sc->sc_unit, cmd);
|
||||
|
||||
} else {
|
||||
/* XXX we could handle arbitrary ApplIds here XXX */
|
||||
printf("capi%d: message %04x for unknown applid %d\n", sc->sc_unit,
|
||||
cmd, applid);
|
||||
}
|
||||
|
||||
if (m->m_next) {
|
||||
i4b_Bfreembuf(m->m_next);
|
||||
m->m_next = NULL;
|
||||
}
|
||||
i4b_Dfreembuf(m);
|
||||
return(0);
|
||||
}
|
|
@ -0,0 +1,977 @@
|
|||
/* $NetBSD: i4b_capi_msgs.c,v 1.1 2003/09/25 15:34:38 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Cubical Solutions Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* capi/capi_msgs.c The CAPI i4b message handlers.
|
||||
*
|
||||
* $FreeBSD: src/sys/i4b/capi/capi_msgs.c,v 1.2 2001/10/21 08:51:54 hm Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/callout.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include <netisdn/i4b_debug.h>
|
||||
#include <netisdn/i4b_ioctl.h>
|
||||
#include <netisdn/i4b_cause.h>
|
||||
#include <netisdn/i4b_l3l4.h>
|
||||
#include <netisdn/i4b_mbuf.h>
|
||||
#include <netisdn/i4b_global.h>
|
||||
#include <netisdn/i4b_l4.h>
|
||||
#include <netisdn/i4b_capi.h>
|
||||
#include <netisdn/i4b_capi_msgs.h>
|
||||
|
||||
/*
|
||||
// Administrative messages:
|
||||
// ------------------------
|
||||
*/
|
||||
|
||||
void capi_listen_req(capi_softc_t *sc, u_int32_t CIP)
|
||||
{
|
||||
struct mbuf *m = i4b_Dgetmbuf(8 + 18);
|
||||
u_int8_t *msg;
|
||||
u_int16_t msgid;
|
||||
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for listen_req\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
msgid = sc->sc_msgid++;
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, I4BCAPI_APPLID);
|
||||
msg = capimsg_setu16(msg, CAPI_LISTEN_REQ);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, 1); /* Controller */
|
||||
msg = capimsg_setu32(msg, 0); /* Info mask */
|
||||
msg = capimsg_setu32(msg, CIP);
|
||||
msg = capimsg_setu32(msg, 0);
|
||||
msg = capimsg_setu8(msg, 0);
|
||||
msg = capimsg_setu8(msg, 0);
|
||||
|
||||
sc->send(sc, m);
|
||||
}
|
||||
|
||||
void capi_listen_conf(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
struct isdn_l3_driver *l3drv;
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
u_int16_t Info;
|
||||
|
||||
capimsg_getu16(msg + 12, &Info);
|
||||
|
||||
if (Info == 0) {
|
||||
/* We are now listening. */
|
||||
|
||||
sc->sc_state = C_UP;
|
||||
l3drv = isdn_find_l3_by_bri(sc->capi_bri);
|
||||
l3drv->dl_est = DL_UP;
|
||||
|
||||
i4b_l4_l12stat(l3drv, 1, 1);
|
||||
i4b_l4_l12stat(l3drv, 2, 1);
|
||||
|
||||
} else {
|
||||
/* XXX sc->sc_state = C_DOWN ? XXX */
|
||||
printf("capi%d: can't listen, info=%04x\n", sc->sc_unit, Info);
|
||||
}
|
||||
}
|
||||
|
||||
void capi_info_ind(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
struct mbuf *m = i4b_Dgetmbuf(8 + 4);
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
u_int16_t applid, msgid;
|
||||
u_int32_t PLCI;
|
||||
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for info_resp\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
msg = capimsg_getu16(msg + 2, &applid);
|
||||
msg = capimsg_getu16(msg + 2, &msgid);
|
||||
msg = capimsg_getu32(msg, &PLCI);
|
||||
|
||||
/* i4b_l4_info_ind() */
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, applid);
|
||||
msg = capimsg_setu16(msg, CAPI_INFO_RESP);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, PLCI);
|
||||
|
||||
sc->send(sc, m);
|
||||
}
|
||||
|
||||
void capi_alert_req(capi_softc_t *sc, call_desc_t *cd)
|
||||
{
|
||||
struct mbuf *m = i4b_Dgetmbuf(8 + 5);
|
||||
u_int8_t *msg;
|
||||
u_int16_t msgid;
|
||||
u_int32_t PLCI;
|
||||
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for alert_req\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
|
||||
PLCI = (sc->sc_bchan[cd->channelid].ncci & CAPI_PLCI_MASK);
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, I4BCAPI_APPLID);
|
||||
msg = capimsg_setu16(msg, CAPI_ALERT_REQ);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, PLCI);
|
||||
msg = capimsg_setu8(msg, 0);
|
||||
|
||||
sc->send(sc, m);
|
||||
}
|
||||
|
||||
void capi_alert_conf(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
u_int16_t Info;
|
||||
|
||||
msg = capimsg_getu16(msg + 12, &Info);
|
||||
|
||||
if (Info) {
|
||||
printf("capi%d: can't alert, info=%04x\n", sc->sc_unit, Info);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// Outgoing call setup:
|
||||
// --------------------
|
||||
//
|
||||
// CAPI_CONNECT_REQ -->
|
||||
// <-- CAPI_CONNECT_CONF
|
||||
// (notify Layer 4)
|
||||
// <-- CAPI_CONNECT_ACTIVE_IND
|
||||
// CAPI_CONNECT_ACTIVE_RESP -->
|
||||
// CAPI_CONNECT_B3_REQ -->
|
||||
// <-- CAPI_CONNECT_B3_CONF
|
||||
// <-- CAPI_CONNECT_B3_ACTIVE_IND
|
||||
// CAPI_CONNECT_B3_ACTIVE_RESP -->
|
||||
// (notify Layer 4)
|
||||
*/
|
||||
|
||||
void capi_connect_req(capi_softc_t *sc, call_desc_t *cd)
|
||||
{
|
||||
struct isdn_l3_driver *l3drv;
|
||||
struct mbuf *m;
|
||||
u_int8_t *msg;
|
||||
u_int16_t msgid;
|
||||
int slen = strlen(cd->src_telno);
|
||||
int dlen = strlen(cd->dst_telno);
|
||||
|
||||
m = i4b_Dgetmbuf(8 + 27 + slen + dlen);
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for connect_req\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
l3drv = isdn_find_l3_by_bri(sc->capi_bri);
|
||||
|
||||
cd->crflag = CRF_ORIG;
|
||||
|
||||
sc->sc_bchan[cd->channelid].cdid = cd->cdid;
|
||||
sc->sc_bchan[cd->channelid].bprot = cd->bprot;
|
||||
sc->sc_bchan[cd->channelid].state = B_CONNECT_CONF;
|
||||
msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
|
||||
l3drv->bch_state[cd->channelid] = BCH_ST_RSVD;
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, I4BCAPI_APPLID);
|
||||
msg = capimsg_setu16(msg, CAPI_CONNECT_REQ);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, 1); /* Controller */
|
||||
|
||||
switch (cd->bprot) {
|
||||
case BPROT_NONE:
|
||||
msg = capimsg_setu16(msg, 0x0010); /* Telephony */
|
||||
break;
|
||||
|
||||
case BPROT_RHDLC:
|
||||
msg = capimsg_setu16(msg, 0x0002); /* Unrestricted digital */
|
||||
break;
|
||||
|
||||
default:
|
||||
msg = capimsg_setu16(msg, 0x0002); /* Unrestricted digital */
|
||||
}
|
||||
|
||||
msg = capimsg_setu8(msg, 1 + dlen);
|
||||
msg = capimsg_setu8(msg, 0x80);
|
||||
strncpy(msg, cd->dst_telno, dlen);
|
||||
|
||||
msg = capimsg_setu8(msg + dlen, 2 + slen);
|
||||
msg = capimsg_setu8(msg, 0x00);
|
||||
msg = capimsg_setu8(msg, 0x80); /* Presentation and screening indicator */
|
||||
strncpy(msg, cd->src_telno, slen);
|
||||
|
||||
msg = capimsg_setu8(msg + slen, 0); /* Called & */
|
||||
msg = capimsg_setu8(msg, 0); /* Calling party subaddress */
|
||||
|
||||
msg = capimsg_setu8(msg, 15); /* B protocol */
|
||||
if (cd->bprot == BPROT_NONE)
|
||||
msg = capimsg_setu16(msg, 1); /* B1 protocol = transparent */
|
||||
else
|
||||
msg = capimsg_setu16(msg, 0); /* B1 protocol = HDLC */
|
||||
msg = capimsg_setu16(msg, 1); /* B2 protocol = transparent */
|
||||
msg = capimsg_setu16(msg, 0); /* B3 protocol = transparent */
|
||||
msg = capimsg_setu8(msg, 0); /* B1 parameters */
|
||||
msg = capimsg_setu8(msg, 0); /* B2 parameters */
|
||||
msg = capimsg_setu8(msg, 0); /* B3 parameters */
|
||||
|
||||
msg = capimsg_setu8(msg, 0); /* Bearer Capability */
|
||||
msg = capimsg_setu8(msg, 0); /* Low Layer Compatibility */
|
||||
msg = capimsg_setu8(msg, 0); /* High Layer Compatibility */
|
||||
msg = capimsg_setu8(msg, 0); /* Additional Info */
|
||||
|
||||
sc->send(sc, m);
|
||||
}
|
||||
|
||||
void capi_connect_conf(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
call_desc_t *cd;
|
||||
u_int16_t msgid;
|
||||
u_int32_t PLCI;
|
||||
u_int16_t Info;
|
||||
int bch;
|
||||
|
||||
msg = capimsg_getu16(msg + 6, &msgid);
|
||||
msg = capimsg_getu32(msg, &PLCI);
|
||||
msg = capimsg_getu16(msg, &Info);
|
||||
|
||||
for (bch = 0; bch < sc->sc_nbch; bch++)
|
||||
if ((sc->sc_bchan[bch].state == B_CONNECT_CONF) &&
|
||||
(sc->sc_bchan[bch].msgid == msgid))
|
||||
break;
|
||||
|
||||
if ((bch == sc->sc_nbch) ||
|
||||
(cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
|
||||
printf("capi%d: can't find channel for connect_conf PLCI %x\n",
|
||||
sc->sc_unit, PLCI);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Info == 0) {
|
||||
sc->sc_bchan[bch].state = B_CONNECT_ACTIVE_IND;
|
||||
sc->sc_bchan[bch].ncci = PLCI;
|
||||
|
||||
i4b_l4_proceeding_ind(cd);
|
||||
|
||||
} else {
|
||||
struct isdn_l3_driver *l3drv;
|
||||
|
||||
l3drv = isdn_find_l3_by_bri(sc->capi_bri);
|
||||
SET_CAUSE_TV(cd->cause_out, CAUSET_I4B, CAUSE_I4B_L1ERROR);
|
||||
i4b_l4_disconnect_ind(cd);
|
||||
freecd_by_cd(cd);
|
||||
|
||||
sc->sc_bchan[bch].state = B_FREE;
|
||||
|
||||
l3drv->bch_state[bch] = BCH_ST_FREE;
|
||||
|
||||
printf("capi%d: can't connect out, info=%04x\n", sc->sc_unit, Info);
|
||||
}
|
||||
}
|
||||
|
||||
void capi_connect_active_ind(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
struct mbuf *m = i4b_Dgetmbuf(8 + 4);
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
call_desc_t *cd;
|
||||
u_int16_t applid, msgid;
|
||||
u_int32_t PLCI;
|
||||
int bch;
|
||||
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for active_ind\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
msg = capimsg_getu16(msg + 2, &applid);
|
||||
msg = capimsg_getu16(msg + 2, &msgid);
|
||||
msg = capimsg_getu32(msg, &PLCI);
|
||||
|
||||
for (bch = 0; bch < sc->sc_nbch; bch++)
|
||||
if ((sc->sc_bchan[bch].state == B_CONNECT_ACTIVE_IND) &&
|
||||
(sc->sc_bchan[bch].ncci == PLCI))
|
||||
break;
|
||||
|
||||
if ((bch == sc->sc_nbch) ||
|
||||
(cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
|
||||
printf("capi%d: can't find channel for active_resp, PLCI %x\n",
|
||||
sc->sc_unit, PLCI);
|
||||
return;
|
||||
}
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, applid);
|
||||
msg = capimsg_setu16(msg, CAPI_CONNECT_ACTIVE_RESP);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, PLCI);
|
||||
|
||||
sc->send(sc, m);
|
||||
|
||||
if (cd->crflag == CRF_ORIG) {
|
||||
capi_connect_b3_req(sc, cd);
|
||||
|
||||
} else {
|
||||
sc->sc_bchan[bch].state = B_CONNECT_B3_IND;
|
||||
}
|
||||
}
|
||||
|
||||
void capi_connect_b3_req(capi_softc_t *sc, call_desc_t *cd)
|
||||
{
|
||||
struct mbuf *m = i4b_Dgetmbuf(8 + 5);
|
||||
u_int8_t *msg;
|
||||
u_int16_t msgid;
|
||||
u_int32_t PLCI;
|
||||
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for connect_b3_req\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_bchan[cd->channelid].state = B_CONNECT_B3_CONF;
|
||||
msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
|
||||
PLCI = (sc->sc_bchan[cd->channelid].ncci & CAPI_PLCI_MASK);
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, I4BCAPI_APPLID);
|
||||
msg = capimsg_setu16(msg, CAPI_CONNECT_B3_REQ);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, PLCI);
|
||||
msg = capimsg_setu8(msg, 0); /* NCPI */
|
||||
|
||||
sc->send(sc, m);
|
||||
}
|
||||
|
||||
void capi_connect_b3_conf(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
call_desc_t *cd;
|
||||
u_int16_t msgid;
|
||||
u_int32_t NCCI;
|
||||
u_int16_t Info;
|
||||
int bch;
|
||||
|
||||
msg = capimsg_getu16(msg + 6, &msgid);
|
||||
msg = capimsg_getu32(msg, &NCCI);
|
||||
msg = capimsg_getu16(msg, &Info);
|
||||
|
||||
for (bch = 0; bch < sc->sc_nbch; bch++)
|
||||
if ((sc->sc_bchan[bch].state == B_CONNECT_B3_CONF) &&
|
||||
(sc->sc_bchan[bch].ncci == (NCCI & CAPI_PLCI_MASK)))
|
||||
break;
|
||||
|
||||
if ((bch == sc->sc_nbch) ||
|
||||
(cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
|
||||
printf("capi%d: can't find channel for connect_b3_conf NCCI %x\n",
|
||||
sc->sc_unit, NCCI);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Info == 0) {
|
||||
sc->sc_bchan[bch].ncci = NCCI;
|
||||
sc->sc_bchan[bch].state = B_CONNECT_B3_ACTIVE_IND;
|
||||
|
||||
} else {
|
||||
struct isdn_l3_driver *l3drv;
|
||||
|
||||
l3drv = isdn_find_l3_by_bri(sc->capi_bri);
|
||||
|
||||
SET_CAUSE_TV(cd->cause_in, CAUSET_I4B, CAUSE_I4B_OOO); /* XXX */
|
||||
i4b_l4_disconnect_ind(cd);
|
||||
freecd_by_cd(cd);
|
||||
|
||||
l3drv->bch_state[bch] = BCH_ST_RSVD;
|
||||
|
||||
printf("capi%d: can't connect_b3 out, info=%04x\n", sc->sc_unit, Info);
|
||||
|
||||
capi_disconnect_req(sc, cd);
|
||||
}
|
||||
}
|
||||
|
||||
void capi_connect_b3_active_ind(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
struct mbuf *m = i4b_Dgetmbuf(8 + 4);
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
call_desc_t *cd;
|
||||
u_int16_t applid, msgid;
|
||||
u_int32_t NCCI;
|
||||
int bch;
|
||||
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for b3_active_ind\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
msg = capimsg_getu16(msg + 2, &applid);
|
||||
msg = capimsg_getu16(msg + 2, &msgid);
|
||||
msg = capimsg_getu32(msg, &NCCI);
|
||||
|
||||
for (bch = 0; bch < sc->sc_nbch; bch++)
|
||||
if ((sc->sc_bchan[bch].state == B_CONNECT_B3_ACTIVE_IND) &&
|
||||
(sc->sc_bchan[bch].ncci == NCCI))
|
||||
break;
|
||||
|
||||
if ((bch == sc->sc_nbch) ||
|
||||
(cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
|
||||
printf("capi%d: can't find channel for b3_active_resp NCCI %x\n",
|
||||
sc->sc_unit, NCCI);
|
||||
return;
|
||||
}
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, I4BCAPI_APPLID);
|
||||
msg = capimsg_setu16(msg, CAPI_CONNECT_B3_ACTIVE_RESP);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, NCCI);
|
||||
|
||||
sc->send(sc, m);
|
||||
|
||||
sc->sc_bchan[bch].state = B_CONNECTED;
|
||||
|
||||
i4b_l4_connect_active_ind(cd);
|
||||
}
|
||||
|
||||
/*
|
||||
// Incoming call setup:
|
||||
// --------------------
|
||||
//
|
||||
// <-- CAPI_CONNECT_IND
|
||||
// (consult Layer 4)
|
||||
// CAPI_CONNECT_RESP -->
|
||||
// <-- CAPI_CONNECT_ACTIVE_IND
|
||||
// CAPI_CONNECT_ACTIVE_RESP -->
|
||||
// <-- CAPI_CONNECT_B3_IND
|
||||
// CAPI_CONNECT_B3_RESP -->
|
||||
// <-- CAPI_CONNECT_B3_ACTIVE_IND
|
||||
// CAPI_CONNECT_B3_ACTIVE_RESP -->
|
||||
// (notify Layer 4)
|
||||
*/
|
||||
|
||||
void capi_connect_ind(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
call_desc_t *cd;
|
||||
u_int16_t applid, msgid;
|
||||
u_int32_t PLCI;
|
||||
u_int16_t CIP;
|
||||
u_int8_t x, y, z;
|
||||
int bch;
|
||||
|
||||
if ((cd = reserve_cd()) == NULL) {
|
||||
printf("capi%d: can't get cd for connect_ind\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
cd->bri = sc->capi_bri;
|
||||
cd->channelexcl = 0;
|
||||
|
||||
for (bch = 0; bch < sc->sc_nbch; bch++)
|
||||
if (sc->sc_bchan[bch].state == B_FREE)
|
||||
break;
|
||||
|
||||
sc->sc_bchan[bch].state = B_CONNECT_IND;
|
||||
cd->channelid = bch; /* XXX CHAN_ANY XXX */
|
||||
|
||||
cd->crflag = CRF_DEST;
|
||||
cd->cr = get_rand_cr(sc->sc_unit);
|
||||
cd->scr_ind = SCR_NONE;
|
||||
cd->prs_ind = PRS_NONE;
|
||||
cd->bprot = BPROT_NONE;
|
||||
cd->ilt = NULL;
|
||||
cd->display[0] = '\0';
|
||||
cd->datetime[0] = '\0';
|
||||
|
||||
msg = capimsg_getu16(msg + 2, &applid);
|
||||
msg = capimsg_getu16(msg + 2, &msgid);
|
||||
msg = capimsg_getu32(msg, &PLCI);
|
||||
msg = capimsg_getu16(msg, &CIP);
|
||||
|
||||
cd->event = (int) msgid; /* XXX overload */
|
||||
cd->Q931state = (int) PLCI; /* XXX overload */
|
||||
|
||||
switch (CIP) {
|
||||
case 0x0010:
|
||||
case 0x0001: cd->bprot = BPROT_NONE; break;
|
||||
case 0x0002: cd->bprot = BPROT_RHDLC; break;
|
||||
default:
|
||||
#if 0
|
||||
NDBGL4(L4_CAPIDBG, "capi%d: unknown CIP = %d", sc->sc_unit, CIP);
|
||||
#endif
|
||||
cd->bprot = BPROT_NONE;
|
||||
}
|
||||
|
||||
msg = capimsg_getu8(msg, &x); /* Called party struct len */
|
||||
if (x) {
|
||||
msg = capimsg_getu8(msg, &y); /* Numbering plan */
|
||||
z = x - 1;
|
||||
if (z >= TELNO_MAX) z = (TELNO_MAX-1);
|
||||
strncpy(cd->dst_telno, msg, z);
|
||||
msg += x;
|
||||
x = z;
|
||||
}
|
||||
cd->dst_telno[x] = '\0';
|
||||
|
||||
msg = capimsg_getu8(msg, &x); /* Calling party struct len */
|
||||
if (x) {
|
||||
msg = capimsg_getu8(msg, &y); /* Numbering plan */
|
||||
msg = capimsg_getu8(msg, &y); /* Screening/Presentation */
|
||||
if ((y & 0x80) == 0) { /* screening used */
|
||||
cd->scr_ind = (y & 3) + SCR_USR_NOSC;
|
||||
cd->prs_ind = ((y >> 5) & 3) + PRS_ALLOWED;
|
||||
}
|
||||
z = x - 2;
|
||||
if (z >= TELNO_MAX) z = (TELNO_MAX-1);
|
||||
strncpy(cd->src_telno, msg, z);
|
||||
msg += x;
|
||||
x = z;
|
||||
}
|
||||
cd->src_telno[x] = '\0';
|
||||
|
||||
i4b_l4_connect_ind(cd);
|
||||
}
|
||||
|
||||
void capi_connect_resp(capi_softc_t *sc, call_desc_t *cd)
|
||||
{
|
||||
struct isdn_l3_driver *l3drv;
|
||||
struct mbuf *m;
|
||||
u_int8_t *msg;
|
||||
u_int16_t msgid;
|
||||
u_int32_t PLCI;
|
||||
int dlen = strlen(cd->dst_telno);
|
||||
|
||||
m = i4b_Dgetmbuf(8 + 21 + dlen);
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for connect_resp\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
l3drv = isdn_find_l3_by_bri(sc->capi_bri);
|
||||
|
||||
msgid = (u_int16_t) cd->event;
|
||||
PLCI = (u_int32_t) cd->Q931state;
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, I4BCAPI_APPLID);
|
||||
msg = capimsg_setu16(msg, CAPI_CONNECT_RESP);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, PLCI);
|
||||
|
||||
switch (cd->response) {
|
||||
case SETUP_RESP_ACCEPT:
|
||||
sc->sc_bchan[cd->channelid].cdid = cd->cdid;
|
||||
sc->sc_bchan[cd->channelid].ncci = PLCI;
|
||||
sc->sc_bchan[cd->channelid].state = B_CONNECT_ACTIVE_IND;
|
||||
l3drv->bch_state[cd->channelid] = BCH_ST_USED;
|
||||
msg = capimsg_setu16(msg, 0); /* Accept the call */
|
||||
break;
|
||||
|
||||
case SETUP_RESP_REJECT:
|
||||
sc->sc_bchan[cd->channelid].state = B_FREE;
|
||||
l3drv->bch_state[cd->channelid] = BCH_ST_FREE;
|
||||
msg = capimsg_setu16(msg, 2); /* Reject, normal call clearing */
|
||||
break;
|
||||
|
||||
case SETUP_RESP_DNTCRE:
|
||||
sc->sc_bchan[cd->channelid].state = B_FREE;
|
||||
l3drv->bch_state[cd->channelid] = BCH_ST_FREE;
|
||||
if (sc->sc_nbch == 30) {
|
||||
/* With PRI, we can't really ignore calls -- normal clearing */
|
||||
msg = capimsg_setu16(msg, (0x3480|CAUSE_Q850_NCCLR));
|
||||
} else {
|
||||
msg = capimsg_setu16(msg, 1); /* Ignore */
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
sc->sc_bchan[cd->channelid].state = B_FREE;
|
||||
l3drv->bch_state[cd->channelid] = BCH_ST_FREE;
|
||||
msg = capimsg_setu16(msg, (0x3480|CAUSE_Q850_CALLREJ));
|
||||
}
|
||||
|
||||
msg = capimsg_setu8(msg, 15); /* B protocol */
|
||||
if (cd->bprot == BPROT_NONE)
|
||||
msg = capimsg_setu16(msg, 1); /* B1 protocol = transparent */
|
||||
else
|
||||
msg = capimsg_setu16(msg, 0); /* B1 protocol = HDLC */
|
||||
msg = capimsg_setu16(msg, 1); /* B2 protocol = transparent */
|
||||
msg = capimsg_setu16(msg, 0); /* B3 protocol = transparent */
|
||||
msg = capimsg_setu8(msg, 0); /* B1 parameters */
|
||||
msg = capimsg_setu8(msg, 0); /* B2 parameters */
|
||||
msg = capimsg_setu8(msg, 0); /* B3 parameters */
|
||||
|
||||
msg = capimsg_setu8(msg, 1 + dlen);
|
||||
msg = capimsg_setu8(msg, 0x80); /* Numbering plan */
|
||||
strncpy(msg, cd->dst_telno, dlen);
|
||||
msg = capimsg_setu8(msg + dlen, 0); /* Connected subaddress */
|
||||
msg = capimsg_setu8(msg, 0); /* Low Layer Compatibility */
|
||||
msg = capimsg_setu8(msg, 0); /* Additional Info */
|
||||
|
||||
sc->send(sc, m);
|
||||
}
|
||||
|
||||
void capi_connect_b3_ind(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
struct mbuf *m = i4b_Dgetmbuf(8 + 7);
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
u_int16_t applid, msgid;
|
||||
u_int32_t NCCI;
|
||||
int bch;
|
||||
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for connect_b3_resp\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
msg = capimsg_getu16(msg + 2, &applid);
|
||||
msg = capimsg_getu16(msg + 2, &msgid);
|
||||
msg = capimsg_getu32(msg, &NCCI);
|
||||
|
||||
for (bch = 0; bch < sc->sc_nbch; bch++)
|
||||
if ((sc->sc_bchan[bch].state == B_CONNECT_B3_IND) &&
|
||||
(sc->sc_bchan[bch].ncci == (NCCI & CAPI_PLCI_MASK)))
|
||||
break;
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, applid);
|
||||
msg = capimsg_setu16(msg, CAPI_CONNECT_B3_RESP);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, NCCI);
|
||||
|
||||
if (bch == sc->sc_nbch) {
|
||||
printf("capi%d: can't get cd for connect_b3_resp NCCI %x\n",
|
||||
sc->sc_unit, NCCI);
|
||||
msg = capimsg_setu16(msg, 8); /* Reject, destination OOO */
|
||||
|
||||
} else {
|
||||
sc->sc_bchan[bch].ncci = NCCI;
|
||||
sc->sc_bchan[bch].state = B_CONNECT_B3_ACTIVE_IND;
|
||||
msg = capimsg_setu16(msg, 0); /* Accept */
|
||||
}
|
||||
|
||||
msg = capimsg_setu8(msg, 0); /* NCPI */
|
||||
|
||||
sc->send(sc, m);
|
||||
}
|
||||
|
||||
/*
|
||||
// Data transfer:
|
||||
// --------------
|
||||
*/
|
||||
|
||||
void capi_data_b3_req(capi_softc_t *sc, int chan, struct mbuf *m_b3)
|
||||
{
|
||||
struct mbuf *m = i4b_Dgetmbuf(8 + 14);
|
||||
u_int8_t *msg;
|
||||
u_int16_t msgid;
|
||||
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for data_b3_req\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
msgid = sc->sc_bchan[chan].msgid = sc->sc_msgid++;
|
||||
sc->sc_bchan[chan].busy = 1;
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, I4BCAPI_APPLID);
|
||||
msg = capimsg_setu16(msg, CAPI_DATA_B3_REQ);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, sc->sc_bchan[chan].ncci);
|
||||
msg = capimsg_setu32(msg, (u_int32_t) m_b3->m_data); /* Pointer */
|
||||
msg = capimsg_setu16(msg, m_b3->m_len);
|
||||
msg = capimsg_setu16(msg, chan);
|
||||
msg = capimsg_setu16(msg, 0); /* Flags */
|
||||
|
||||
m->m_next = m_b3;
|
||||
|
||||
sc->send(sc, m);
|
||||
}
|
||||
|
||||
void capi_data_b3_conf(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
u_int32_t NCCI;
|
||||
u_int16_t handle;
|
||||
u_int16_t Info;
|
||||
|
||||
msg = capimsg_getu32(msg + 8, &NCCI);
|
||||
msg = capimsg_getu16(msg, &handle);
|
||||
msg = capimsg_getu16(msg, &Info);
|
||||
|
||||
if (Info == 0) {
|
||||
sc->sc_bchan[handle].busy = 0;
|
||||
capi_start_tx(sc, handle);
|
||||
|
||||
} else {
|
||||
printf("capi%d: data_b3_conf NCCI %x handle %x info=%04x\n",
|
||||
sc->sc_unit, NCCI, handle, Info);
|
||||
}
|
||||
}
|
||||
|
||||
void capi_data_b3_ind(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
struct mbuf *m = i4b_Dgetmbuf(8 + 6);
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
u_int16_t applid, msgid;
|
||||
u_int32_t NCCI;
|
||||
u_int16_t handle;
|
||||
int bch;
|
||||
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for data_b3_resp\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
msg = capimsg_getu16(msg + 2, &applid);
|
||||
msg = capimsg_getu16(msg + 2, &msgid);
|
||||
msg = capimsg_getu32(msg, &NCCI);
|
||||
msg = capimsg_getu16(msg + 6, &handle);
|
||||
|
||||
for (bch = 0; bch < sc->sc_nbch; bch++)
|
||||
if ((sc->sc_bchan[bch].state == B_CONNECTED) &&
|
||||
(sc->sc_bchan[bch].ncci == NCCI))
|
||||
break;
|
||||
|
||||
if (bch == sc->sc_nbch) {
|
||||
printf("capi%d: can't find channel for data_b3_ind NCCI %x\n",
|
||||
sc->sc_unit, NCCI);
|
||||
|
||||
} else {
|
||||
if (sc->sc_bchan[bch].bprot == BPROT_RHDLC) {
|
||||
/* HDLC drivers use rx_mbuf */
|
||||
|
||||
sc->sc_bchan[bch].in_mbuf = m_in->m_next;
|
||||
sc->sc_bchan[bch].rxcount += m_in->m_next->m_len;
|
||||
m_in->m_next = NULL; /* driver frees */
|
||||
|
||||
(*sc->sc_bchan[bch].l4_driver->bch_rx_data_ready)(
|
||||
sc->sc_bchan[bch].l4_driver_softc);
|
||||
|
||||
} else {
|
||||
/* Telephony drivers use rx_queue */
|
||||
|
||||
if (!IF_QFULL(&sc->sc_bchan[bch].rx_queue)) {
|
||||
IF_ENQUEUE(&sc->sc_bchan[bch].rx_queue, m_in->m_next);
|
||||
sc->sc_bchan[bch].rxcount += m_in->m_next->m_len;
|
||||
m_in->m_next = NULL; /* driver frees */
|
||||
}
|
||||
|
||||
(*sc->sc_bchan[bch].l4_driver->bch_rx_data_ready)(
|
||||
sc->sc_bchan[bch].l4_driver_softc);
|
||||
}
|
||||
}
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, I4BCAPI_APPLID);
|
||||
msg = capimsg_setu16(msg, CAPI_DATA_B3_RESP);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, NCCI);
|
||||
msg = capimsg_setu16(msg, handle);
|
||||
|
||||
sc->send(sc, m);
|
||||
}
|
||||
|
||||
/*
|
||||
// Connection teardown:
|
||||
// --------------------
|
||||
*/
|
||||
|
||||
void capi_disconnect_req(capi_softc_t *sc, call_desc_t *cd)
|
||||
{
|
||||
struct isdn_l3_driver *l3drv;
|
||||
struct mbuf *m = i4b_Dgetmbuf(8 + 5);
|
||||
u_int8_t *msg;
|
||||
u_int16_t msgid;
|
||||
u_int32_t PLCI;
|
||||
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for disconnect_req\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
l3drv = isdn_find_l3_by_bri(sc->capi_bri);
|
||||
|
||||
sc->sc_bchan[cd->channelid].state = B_DISCONNECT_CONF;
|
||||
l3drv->bch_state[cd->channelid] = BCH_ST_RSVD;
|
||||
msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
|
||||
PLCI = (sc->sc_bchan[cd->channelid].ncci & CAPI_PLCI_MASK);
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, I4BCAPI_APPLID);
|
||||
msg = capimsg_setu16(msg, CAPI_DISCONNECT_REQ);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, PLCI);
|
||||
msg = capimsg_setu8(msg, 0); /* Additional Info */
|
||||
|
||||
sc->send(sc, m);
|
||||
}
|
||||
|
||||
void capi_disconnect_conf(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
struct isdn_l3_driver *l3drv;
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
call_desc_t *cd;
|
||||
u_int32_t PLCI;
|
||||
int bch;
|
||||
|
||||
msg = capimsg_getu32(msg + 8, &PLCI);
|
||||
|
||||
for (bch = 0; bch < sc->sc_nbch; bch++)
|
||||
if ((sc->sc_bchan[bch].state == B_DISCONNECT_CONF) &&
|
||||
((sc->sc_bchan[bch].ncci & CAPI_PLCI_MASK) == PLCI))
|
||||
break;
|
||||
|
||||
if (bch == sc->sc_nbch) {
|
||||
printf("capi%d: can't find channel for disconnect_conf PLCI %x\n",
|
||||
sc->sc_unit, PLCI);
|
||||
return;
|
||||
}
|
||||
|
||||
cd = cd_by_cdid(sc->sc_bchan[bch].cdid);
|
||||
if (!cd) {
|
||||
printf("capi%d: can't find cd for disconnect_conf PLCI %x\n",
|
||||
sc->sc_unit, PLCI);
|
||||
} else {
|
||||
i4b_l4_disconnect_ind(cd);
|
||||
freecd_by_cd(cd);
|
||||
}
|
||||
|
||||
l3drv = isdn_find_l3_by_bri(sc->capi_bri);
|
||||
|
||||
sc->sc_bchan[bch].state = B_FREE;
|
||||
l3drv->bch_state[bch] = BCH_ST_FREE;
|
||||
}
|
||||
|
||||
void capi_disconnect_b3_ind(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
struct mbuf *m = i4b_Dgetmbuf(8 + 4);
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
u_int16_t applid, msgid;
|
||||
u_int32_t NCCI;
|
||||
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for disconnect_b3_resp\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
msg = capimsg_getu16(msg + 2, &applid);
|
||||
msg = capimsg_getu16(msg + 2, &msgid);
|
||||
msg = capimsg_getu32(msg, &NCCI);
|
||||
|
||||
/* XXX update bchan state? XXX */
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, applid);
|
||||
msg = capimsg_setu16(msg, CAPI_DISCONNECT_B3_RESP);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, NCCI);
|
||||
|
||||
sc->send(sc, m);
|
||||
}
|
||||
|
||||
void capi_disconnect_ind(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
struct isdn_l3_driver *l3drv;
|
||||
struct mbuf *m = i4b_Dgetmbuf(8 + 4);
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
call_desc_t *cd;
|
||||
u_int16_t applid, msgid;
|
||||
u_int32_t PLCI;
|
||||
u_int16_t Reason;
|
||||
int bch;
|
||||
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for disconnect_resp\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
msg = capimsg_getu16(msg + 2, &applid);
|
||||
msg = capimsg_getu16(msg + 2, &msgid);
|
||||
msg = capimsg_getu32(msg, &PLCI);
|
||||
msg = capimsg_getu16(msg, &Reason);
|
||||
|
||||
for (bch = 0; bch < sc->sc_nbch; bch++)
|
||||
if ((sc->sc_bchan[bch].state != B_FREE) &&
|
||||
((sc->sc_bchan[bch].ncci & CAPI_PLCI_MASK) == PLCI))
|
||||
break;
|
||||
|
||||
if (bch < sc->sc_nbch) {
|
||||
/* We may not have a bchan assigned if call was ignored. */
|
||||
|
||||
cd = cd_by_cdid(sc->sc_bchan[bch].cdid);
|
||||
sc->sc_bchan[bch].state = B_DISCONNECT_IND;
|
||||
} else
|
||||
cd = NULL;
|
||||
|
||||
if (cd) {
|
||||
if ((Reason & 0xff00) == 0x3400) {
|
||||
SET_CAUSE_TV(cd->cause_in, CAUSET_Q850, (Reason & 0x7f));
|
||||
} else {
|
||||
SET_CAUSE_TV(cd->cause_in, CAUSET_I4B, CAUSE_I4B_NORMAL);
|
||||
}
|
||||
|
||||
i4b_l4_disconnect_ind(cd);
|
||||
freecd_by_cd(cd);
|
||||
|
||||
sc->sc_bchan[bch].state = B_FREE;
|
||||
l3drv = isdn_find_l3_by_bri(sc->capi_bri);
|
||||
l3drv->bch_state[bch] = BCH_ST_FREE;
|
||||
}
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, applid);
|
||||
msg = capimsg_setu16(msg, CAPI_DISCONNECT_RESP);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, PLCI);
|
||||
|
||||
sc->send(sc, m);
|
||||
}
|
|
@ -0,0 +1,382 @@
|
|||
/* $NetBSD: i4b_capi_msgs.h,v 1.1 2003/09/25 15:34:38 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Cubical Solutions Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* capi/capi_msgs.h The CAPI i4b message and handler declarations.
|
||||
*
|
||||
* $FreeBSD: src/sys/i4b/capi/capi_msgs.h,v 1.1 2001/05/25 08:39:31 hm Exp $
|
||||
*/
|
||||
|
||||
#ifndef _I4B_CAPI_MSGS_H_
|
||||
#define _I4B_CAPI_MSGS_H_
|
||||
|
||||
/* CAPI commands */
|
||||
|
||||
#define CAPI_ALERT 0x01
|
||||
#define CAPI_CONNECT 0x02
|
||||
#define CAPI_CONNECT_ACTIVE 0x03
|
||||
#define CAPI_CONNECT_B3 0x82
|
||||
#define CAPI_CONNECT_B3_ACTIVE 0x83
|
||||
#define CAPI_CONNECT_B3_T90_ACTIVE 0x88
|
||||
#define CAPI_DATA_B3 0x86
|
||||
#define CAPI_DISCONNECT_B3 0x84
|
||||
#define CAPI_DISCONNECT 0x04
|
||||
#define CAPI_FACILITY 0x80
|
||||
#define CAPI_INFO 0x08
|
||||
#define CAPI_LISTEN 0x05
|
||||
#define CAPI_MANUFACTURER 0xff
|
||||
#define CAPI_RESET_B3 0x87
|
||||
#define CAPI_SELECT_B_PROTOCOL 0x41
|
||||
|
||||
/* CAPI subcommands */
|
||||
|
||||
#define CAPI_REQ 0x80
|
||||
#define CAPI_CONF 0x81
|
||||
#define CAPI_IND 0x82
|
||||
#define CAPI_RESP 0x83
|
||||
|
||||
/* CAPI combined commands */
|
||||
|
||||
#define CAPICMD(cmd,subcmd) (((subcmd)<<8)|(cmd))
|
||||
|
||||
#define CAPI_DISCONNECT_REQ CAPICMD(CAPI_DISCONNECT,CAPI_REQ)
|
||||
#define CAPI_DISCONNECT_CONF CAPICMD(CAPI_DISCONNECT,CAPI_CONF)
|
||||
#define CAPI_DISCONNECT_IND CAPICMD(CAPI_DISCONNECT,CAPI_IND)
|
||||
#define CAPI_DISCONNECT_RESP CAPICMD(CAPI_DISCONNECT,CAPI_RESP)
|
||||
|
||||
#define CAPI_ALERT_REQ CAPICMD(CAPI_ALERT,CAPI_REQ)
|
||||
#define CAPI_ALERT_CONF CAPICMD(CAPI_ALERT,CAPI_CONF)
|
||||
|
||||
#define CAPI_CONNECT_REQ CAPICMD(CAPI_CONNECT,CAPI_REQ)
|
||||
#define CAPI_CONNECT_CONF CAPICMD(CAPI_CONNECT,CAPI_CONF)
|
||||
#define CAPI_CONNECT_IND CAPICMD(CAPI_CONNECT,CAPI_IND)
|
||||
#define CAPI_CONNECT_RESP CAPICMD(CAPI_CONNECT,CAPI_RESP)
|
||||
|
||||
#define CAPI_CONNECT_ACTIVE_REQ CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_REQ)
|
||||
#define CAPI_CONNECT_ACTIVE_CONF CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_CONF)
|
||||
#define CAPI_CONNECT_ACTIVE_IND CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_IND)
|
||||
#define CAPI_CONNECT_ACTIVE_RESP CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_RESP)
|
||||
|
||||
#define CAPI_SELECT_B_PROTOCOL_REQ CAPICMD(CAPI_SELECT_B_PROTOCOL,CAPI_REQ)
|
||||
#define CAPI_SELECT_B_PROTOCOL_CONF CAPICMD(CAPI_SELECT_B_PROTOCOL,CAPI_CONF)
|
||||
|
||||
#define CAPI_CONNECT_B3_REQ CAPICMD(CAPI_CONNECT_B3,CAPI_REQ)
|
||||
#define CAPI_CONNECT_B3_CONF CAPICMD(CAPI_CONNECT_B3,CAPI_CONF)
|
||||
#define CAPI_CONNECT_B3_IND CAPICMD(CAPI_CONNECT_B3,CAPI_IND)
|
||||
#define CAPI_CONNECT_B3_RESP CAPICMD(CAPI_CONNECT_B3,CAPI_RESP)
|
||||
|
||||
#define CAPI_CONNECT_B3_ACTIVE_REQ CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_REQ)
|
||||
#define CAPI_CONNECT_B3_ACTIVE_CONF CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_CONF)
|
||||
#define CAPI_CONNECT_B3_ACTIVE_IND CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_IND)
|
||||
#define CAPI_CONNECT_B3_ACTIVE_RESP CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_RESP)
|
||||
|
||||
#define CAPI_CONNECT_B3_T90_ACTIVE_IND CAPICMD(CAPI_CONNECT_B3_T90_ACTIVE,CAPI_IND)
|
||||
#define CAPI_CONNECT_B3_T90_ACTIVE_RESP CAPICMD(CAPI_CONNECT_B3_T90_ACTIVE,CAPI_RESP)
|
||||
|
||||
#define CAPI_DATA_B3_REQ CAPICMD(CAPI_DATA_B3,CAPI_REQ)
|
||||
#define CAPI_DATA_B3_CONF CAPICMD(CAPI_DATA_B3,CAPI_CONF)
|
||||
#define CAPI_DATA_B3_IND CAPICMD(CAPI_DATA_B3,CAPI_IND)
|
||||
#define CAPI_DATA_B3_RESP CAPICMD(CAPI_DATA_B3,CAPI_RESP)
|
||||
|
||||
#define CAPI_DISCONNECT_B3_REQ CAPICMD(CAPI_DISCONNECT_B3,CAPI_REQ)
|
||||
#define CAPI_DISCONNECT_B3_CONF CAPICMD(CAPI_DISCONNECT_B3,CAPI_CONF)
|
||||
#define CAPI_DISCONNECT_B3_IND CAPICMD(CAPI_DISCONNECT_B3,CAPI_IND)
|
||||
#define CAPI_DISCONNECT_B3_RESP CAPICMD(CAPI_DISCONNECT_B3,CAPI_RESP)
|
||||
|
||||
#define CAPI_RESET_B3_REQ CAPICMD(CAPI_RESET_B3,CAPI_REQ)
|
||||
#define CAPI_RESET_B3_CONF CAPICMD(CAPI_RESET_B3,CAPI_CONF)
|
||||
#define CAPI_RESET_B3_IND CAPICMD(CAPI_RESET_B3,CAPI_IND)
|
||||
#define CAPI_RESET_B3_RESP CAPICMD(CAPI_RESET_B3,CAPI_RESP)
|
||||
|
||||
#define CAPI_LISTEN_REQ CAPICMD(CAPI_LISTEN,CAPI_REQ)
|
||||
#define CAPI_LISTEN_CONF CAPICMD(CAPI_LISTEN,CAPI_CONF)
|
||||
|
||||
#define CAPI_MANUFACTURER_REQ CAPICMD(CAPI_MANUFACTURER,CAPI_REQ)
|
||||
#define CAPI_MANUFACTURER_CONF CAPICMD(CAPI_MANUFACTURER,CAPI_CONF)
|
||||
#define CAPI_MANUFACTURER_IND CAPICMD(CAPI_MANUFACTURER,CAPI_IND)
|
||||
#define CAPI_MANUFACTURER_RESP CAPICMD(CAPI_MANUFACTURER,CAPI_RESP)
|
||||
|
||||
#define CAPI_FACILITY_REQ CAPICMD(CAPI_FACILITY,CAPI_REQ)
|
||||
#define CAPI_FACILITY_CONF CAPICMD(CAPI_FACILITY,CAPI_CONF)
|
||||
#define CAPI_FACILITY_IND CAPICMD(CAPI_FACILITY,CAPI_IND)
|
||||
#define CAPI_FACILITY_RESP CAPICMD(CAPI_FACILITY,CAPI_RESP)
|
||||
|
||||
#define CAPI_INFO_REQ CAPICMD(CAPI_INFO,CAPI_REQ)
|
||||
#define CAPI_INFO_CONF CAPICMD(CAPI_INFO,CAPI_CONF)
|
||||
#define CAPI_INFO_IND CAPICMD(CAPI_INFO,CAPI_IND)
|
||||
#define CAPI_INFO_RESP CAPICMD(CAPI_INFO,CAPI_RESP)
|
||||
|
||||
/* CAPI message access helpers */
|
||||
|
||||
/*
|
||||
* CAPI message header:
|
||||
* word Length
|
||||
* word ApplId
|
||||
* byte Command
|
||||
* byte Subcommand
|
||||
* word MsgId
|
||||
*
|
||||
* Note that in the following, Controller/PLCI/NCCI is coded as follows:
|
||||
* bits 0..6 = controller, bit 7 = ext/int, bits 8..15 = PLCI, and
|
||||
* bits 16..31 = NCCI value.
|
||||
*
|
||||
* ALERT_REQ, 01 80:
|
||||
* dword PLCI
|
||||
* struct Additional Info
|
||||
*
|
||||
* ALERT_CONF, 01 81:
|
||||
* dword PLCI
|
||||
* word Info (0 = OK, other = cause)
|
||||
*
|
||||
* CONNECT_REQ, 02 80:
|
||||
* dword controller
|
||||
* word CIP
|
||||
* struct Called party number
|
||||
* struct Calling party number
|
||||
* struct Called party subaddress
|
||||
* struct Calling party subaddress
|
||||
* struct Bearer Capability
|
||||
* struct Low Layer Compatibility
|
||||
* struct High Layer Compatibility
|
||||
* struct Additional Info
|
||||
*
|
||||
* CONNECT_CONF, 02 81:
|
||||
* dword PLCI
|
||||
* word Info (0 = OK, other = cause)
|
||||
*
|
||||
* CONNECT_IND, 02 82:
|
||||
* dword PLCI
|
||||
* word CIP
|
||||
* struct Called party number
|
||||
* struct Calling party number
|
||||
* struct Called party subaddress
|
||||
* struct Calling party subaddress
|
||||
* struct Bearer Capability
|
||||
* struct Low Layer Compatibility
|
||||
* struct High Layer Compatibility
|
||||
* struct Additional Info
|
||||
* struct Second Calling party number
|
||||
*
|
||||
* CONNECT_RESP, 02 83:
|
||||
* dword PLCI
|
||||
* word Reject (0 = accept, 1 = ignore, 2 = reject/normal clearing)
|
||||
* struct B protocol
|
||||
* struct Connected number
|
||||
* struct Connected subaddress
|
||||
* struct Low Layer Compatibility
|
||||
* struct Additional Info
|
||||
*
|
||||
* CONNECT_ACTIVE_IND, 03 82:
|
||||
* dword PLCI
|
||||
* struct Connected number
|
||||
* struct Connected subaddress
|
||||
* struct Low Layer Compatibility
|
||||
*
|
||||
* CONNECT_ACTIVE_RESP, 03 83:
|
||||
* dword PLCI
|
||||
*
|
||||
* CONNECT_B3_REQ, 82 80:
|
||||
* dword PLCI
|
||||
* struct NCPI
|
||||
*
|
||||
* CONNECT_B3_CONF, 82 81:
|
||||
* dword NCCI
|
||||
* word Info (0 = connected, other = cause)
|
||||
*
|
||||
* CONNECT_B3_IND, 82 82:
|
||||
* dword NCCI
|
||||
* struct NCPI
|
||||
*
|
||||
* CONNECT_B3_RESP, 82 83:
|
||||
* dword NCCI
|
||||
* word Reject (0 = accept, 2 = reject/normal clearing)
|
||||
* struct NCPI
|
||||
*
|
||||
* CONNECT_B3_ACTIVE_IND, 83 82:
|
||||
* dword NCCI
|
||||
* struct NCPI
|
||||
*
|
||||
* CONNECT_B3_ACTIVE_RESP, 83 83:
|
||||
* dword NCCI
|
||||
*
|
||||
* DATA_B3_REQ, 86 80:
|
||||
* dword NCCI
|
||||
* dword Data pointer
|
||||
* word Data length
|
||||
* word Data handle (packet id)
|
||||
* word Flags (02 = more)
|
||||
*
|
||||
* DATA_B3_CONF, 86 81:
|
||||
* dword NCCI
|
||||
* word Data handle (packet id)
|
||||
* word Info (0 = OK, other = cause)
|
||||
*
|
||||
* DATA_B3_IND, 86 82:
|
||||
* dword NCCI
|
||||
* dword Data pointer
|
||||
* word Data length
|
||||
* word Data handle (packet id)
|
||||
* word Flags (02 = more)
|
||||
*
|
||||
* DATA_B3_RESP, 86 83:
|
||||
* dword NCCI
|
||||
* word Data handle (packet id)
|
||||
*
|
||||
* DISCONNECT_B3_REQ, 84 80:
|
||||
* dword NCCI
|
||||
* struct NCPI
|
||||
*
|
||||
* DISCONNECT_B3_CONF, 84 81:
|
||||
* dword NCCI
|
||||
* word Info (0 = OK, other = cause)
|
||||
*
|
||||
* DISCONNECT_B3_IND, 84 82:
|
||||
* dword NCCI
|
||||
* word Reason
|
||||
* struct NCPI
|
||||
*
|
||||
* DISCONNECT_B3_RESP, 84 83:
|
||||
* dword NCCI
|
||||
*
|
||||
* DISCONNECT_REQ, 04 80:
|
||||
* dword PLCI
|
||||
* struct Additional Info
|
||||
*
|
||||
* DISCONNECT_CONF, 04 81:
|
||||
* dword PLCI
|
||||
* word Info (0 = OK, other = cause)
|
||||
*
|
||||
* DISCONNECT_IND, 04 82:
|
||||
* dword PLCI
|
||||
* word Reason
|
||||
*
|
||||
* DISCONNECT_RESP, 04 83:
|
||||
* dword PLCI
|
||||
*
|
||||
* LISTEN_REQ, 05 80:
|
||||
* dword Controller
|
||||
* dword Info mask (bits 0..9 used)
|
||||
* dword CIP Mask (bit 0 = any match)
|
||||
* dword CIP Mask 2 (bit 0 = any match)
|
||||
* struct Calling party number
|
||||
* struct Calling party subaddress
|
||||
*
|
||||
* LISTEN_CONF, 05 81:
|
||||
* dword Controller
|
||||
* word Info (0 = OK, other = cause)
|
||||
*
|
||||
* INFO_REQ, 08 80:
|
||||
* dword Controller/PLCI
|
||||
* struct Called party number
|
||||
* struct Additional Info
|
||||
*
|
||||
* INFO_CONF, 08 81:
|
||||
* dword Controller/PLCI
|
||||
* word Info (0 = OK, other = cause)
|
||||
*
|
||||
* INFO_IND, 08 82:
|
||||
* dword Controller/PLCI
|
||||
* word Info number
|
||||
* struct Info element
|
||||
*
|
||||
* INFO_RESP, 08 83:
|
||||
* dword Controller/PLCI
|
||||
*/
|
||||
|
||||
#define CAPIMSG_LEN(msg) (msg[0]|(msg[1]<<8))
|
||||
#define CAPIMSG_DATALEN(msg) (msg[16]|(msg[17]<<8))
|
||||
|
||||
static __inline u_int8_t* capimsg_getu8(u_int8_t *msg, u_int8_t *val)
|
||||
{
|
||||
*val = *msg;
|
||||
return (msg + 1);
|
||||
}
|
||||
|
||||
static __inline u_int8_t* capimsg_getu16(u_int8_t *msg, u_int16_t *val)
|
||||
{
|
||||
*val = (msg[0]|(msg[1]<<8));
|
||||
return (msg + 2);
|
||||
}
|
||||
|
||||
static __inline u_int8_t* capimsg_getu32(u_int8_t *msg, u_int32_t *val)
|
||||
{
|
||||
*val = (msg[0]|(msg[1]<<8)|(msg[2]<<16)|(msg[3]<<24));
|
||||
return (msg + 4);
|
||||
}
|
||||
|
||||
static __inline u_int8_t* capimsg_setu8(u_int8_t *msg, u_int8_t val)
|
||||
{
|
||||
msg[0] = val;
|
||||
return (msg + 1);
|
||||
}
|
||||
|
||||
static __inline u_int8_t* capimsg_setu16(u_int8_t *msg, u_int16_t val)
|
||||
{
|
||||
msg[0] = (val & 0xff);
|
||||
msg[1] = (val >> 8) & 0xff;
|
||||
return (msg + 2);
|
||||
}
|
||||
|
||||
static __inline u_int8_t* capimsg_setu32(u_int8_t *msg, u_int32_t val)
|
||||
{
|
||||
msg[0] = (val & 0xff);
|
||||
msg[1] = (val >> 8) & 0xff;
|
||||
msg[2] = (val >> 16) & 0xff;
|
||||
msg[3] = (val >> 24) & 0xff;
|
||||
return (msg + 4);
|
||||
}
|
||||
|
||||
/*
|
||||
// CAPI message handlers called by higher layers
|
||||
*/
|
||||
|
||||
extern void capi_listen_req(capi_softc_t *sc, u_int32_t CIP);
|
||||
extern void capi_alert_req(capi_softc_t *sc, call_desc_t *cd);
|
||||
extern void capi_connect_req(capi_softc_t *sc, call_desc_t *cd);
|
||||
extern void capi_connect_b3_req(capi_softc_t *sc, call_desc_t *cd);
|
||||
extern void capi_connect_resp(capi_softc_t *sc, call_desc_t *cd);
|
||||
extern void capi_data_b3_req(capi_softc_t *sc, int chan, struct mbuf *m);
|
||||
extern void capi_disconnect_req(capi_softc_t *sc, call_desc_t *cd);
|
||||
|
||||
/*
|
||||
// CAPI message handlers called by the receive routine
|
||||
*/
|
||||
|
||||
extern void capi_listen_conf(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_info_ind(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_alert_conf(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_connect_conf(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_connect_active_ind(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_connect_b3_conf(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_connect_b3_active_ind(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_connect_ind(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_connect_b3_ind(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_data_b3_conf(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_data_b3_ind(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_disconnect_conf(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_disconnect_b3_ind(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_disconnect_ind(capi_softc_t *sc, struct mbuf *m);
|
||||
|
||||
#endif /* _I4B_CAPI_MSGS_H_ */
|
Loading…
Reference in New Issue