Merge branch 'capi' of ssh://git.misdn.eu/mISDNuser-devel into capi

This commit is contained in:
Karsten Keil 2011-12-09 13:55:34 +01:00
commit ab44464d37
7 changed files with 445 additions and 43 deletions

View File

@ -175,6 +175,18 @@ void SendCmsgAnswer2Application(struct mApplication *appl, struct mc_buf *mc, __
SendCmsg2Application(appl, mc);
}
struct lPLCI *get_lPLCI4plci(struct mApplication *appl, uint32_t id)
{
struct lController *lc;
struct mPLCI *plci;
lc = get_lController(appl, id & 0x7f);
if (!lc)
return NULL;
plci = getPLCI4Id(lc->Contr, id & 0xFFFF);
return get_lPLCI4Id(plci, appl->AppId);
}
#define CapiFacilityNotSupported 0x300b
static int FacilityMessage(struct mApplication *appl, struct pController *pc, struct mc_buf *mc)

View File

@ -11,15 +11,16 @@
* this package for more details.
*/
#include <stdlib.h>
#include <fcntl.h>
#include <stdio.h>
#include <getopt.h>
#include <string.h>
#include <stdarg.h>
#include <sys/un.h>
#include <fcntl.h>
#include <errno.h>
#include <poll.h>
#include <mISDN/q931.h>
#include <string.h>
#include "m_capi.h"
#include "mc_buffer.h"
#include "m_capi_sock.h"
@ -30,6 +31,14 @@
/* should be moved to capi_debug.h */
#include <capi_debug.h>
/* for some reasons when _XOPEN_SOURCE 600 was defined lot of other things are not longer
* defined so use this as workaround
*/
extern int grantpt(int fd);
extern int unlockpt(int fd);
extern int ptsname_r(int fd, char *buf, size_t buflen);
#ifndef DEF_CONFIG_FILE
#define DEF_CONFIG_FILE "/etc/capi20.conf"
#endif
@ -369,38 +378,126 @@ struct BInstance *ControllerSelChannel(struct pController *pc, int nr, int proto
return bi;
}
static int Create_tty(struct BInstance *bi)
{
int ret, pmod;
ret = posix_openpt(O_RDWR | O_NOCTTY);
if (ret < 0) {
eprint("Cannot open terminal - %s\n", strerror(errno));
} else {
bi->tty = ret;
ret = grantpt(bi->tty);
if (ret < 0) {
eprint("Error on grantpt - %s\n", strerror(errno));
close(bi->tty);
bi->tty = -1;
} else {
ret = unlockpt(bi->tty);
if (ret < 0) {
eprint("Error on unlockpt - %s\n", strerror(errno));
close(bi->tty);
bi->tty = -1;
} else {
/* packet mode */
pmod = 1;
ret = ioctl(bi->tty, TIOCPKT, &pmod);
if (ret < 0) {
eprint("Cannot set packet mode - %s\n", strerror(errno));
close(bi->tty);
bi->tty = -1;
}
}
}
}
return ret;
}
static int recvBchannel(struct BInstance *);
static int recv_tty(struct BInstance *bi)
{
int ret, maxl;
struct mc_buf *mc;
mc = alloc_mc_buf();
if (!mc)
return -ENOMEM;
if (!bi)
return -EINVAL;
mc->rp = mc->rb + 8;
maxl = MC_RB_SIZE - 8;
ret = read(bi->tty, mc->rp, maxl);
if (ret < 0) {
wprint("Error on reading from tty %d errno %d - %s\n", bi->tty, errno, strerror(errno));
ret = -errno;
} else if (ret == 0) {
/* closed */
wprint("Read 0 bytes from tty %d\n", bi->tty);
ret = -ECONNABORTED;
} else if (ret == maxl) {
eprint("Message too big %d ctrl %02x (%02x%02x%02x%02x%02x%02x%02x%02x)\n",
ret, mc->rp[0], mc->rp[1], mc->rp[2], mc->rp[3], mc->rp[4], mc->rp[5], mc->rp[6], mc->rp[7], mc->rp[8]);
ret = -EMSGSIZE;
}
if (ret > 0) {
mc->len = ret;
/* Fake length of DATA_B3 REQ to pass offset check */
capimsg_setu16(mc->rb, 0, 22);
mc->cmsg.Command = CAPI_DATA_TTY;
mc->cmsg.Subcommand = CAPI_REQ;
ret = bi->from_up(bi, mc);
}
if (ret != 0) /* if message is not queued or freed */
free_mc_buf(mc);
return ret;
}
static void *BCthread(void *arg)
{
struct BInstance *bi = arg;
unsigned char cmd;
int ret;
int ret, i;
bi->running = 1;
while (bi->running) {
ret = poll(bi->pfd, 2, -1);
ret = poll(bi->pfd, bi->pcnt, -1);
if (ret < 0) {
wprint("Bchannel%d Error on poll - %s\n", bi->nr, strerror(errno));
continue;
}
for (i = 1; i < bi->pcnt; i++) {
if (bi->pfd[i].revents & POLLIN) {
switch(i) {
case 1:
ret = recvBchannel(bi);
break;
case 2:
ret = recv_tty(bi);
break;
default:
wprint("Bchannel%d poll idx %d not handled\n", bi->nr, i);
}
}
}
if (bi->pfd[0].revents & POLLIN) {
ret = recvBchannel(bi);
} else if (bi->pfd[1].revents & POLLIN) {
ret = read(bi->pfd[1].fd, &cmd, 1);
ret = read(bi->pfd[0].fd, &cmd, 1);
if (cmd == 42) {
bi->running = 0;
}
} else {
wprint("Bchannel%d no POLLIN event\n", bi->nr);
}
}
return NULL;
}
static int CreateBchannelThread(struct BInstance *bi)
static int CreateBchannelThread(struct BInstance *bi, int pcnt)
{
int ret;
int ret, i;
ret = pipe(bi->cpipe);
if (ret) {
@ -417,10 +514,11 @@ static int CreateBchannelThread(struct BInstance *bi)
eprint("error - %s\n", strerror(errno));
return ret;
}
bi->pfd[0].fd = bi->fd;
bi->pfd[0].fd = bi->cpipe[0];
bi->pfd[0].events = POLLIN | POLLPRI;
bi->pfd[1].fd = bi->cpipe[0];
bi->pfd[1].fd = bi->fd;
bi->pfd[1].events = POLLIN | POLLPRI;
bi->pcnt = pcnt;
ret = pthread_create(&bi->tid, NULL, BCthread, bi);
if (ret) {
eprint("Cannot create thread error - %s\n", strerror(errno));
@ -429,7 +527,8 @@ static int CreateBchannelThread(struct BInstance *bi)
bi->cpipe[0] = -1;
bi->cpipe[1] = -1;
bi->pfd[0].fd = -1;
bi->pfd[1].fd = -1;
for (i = 1; i < bi->pcnt; i++)
bi->pfd[i].fd = -1;
} else
iprint("Created Bchannel tread %d\n", (int)bi->tid);
return ret;
@ -437,7 +536,7 @@ static int CreateBchannelThread(struct BInstance *bi)
static int StopBchannelThread(struct BInstance *bi)
{
int ret;
int ret, i;
unsigned char cmd;
if (bi->running) {
@ -453,7 +552,9 @@ static int StopBchannelThread(struct BInstance *bi)
close(bi->cpipe[0]);
close(bi->cpipe[1]);
bi->pfd[0].fd = -1;
bi->pfd[1].fd = -1;
for (i = 1; i < bi->pcnt; i++)
bi->pfd[i].fd = -1;
bi->pcnt = 0;
bi->cpipe[0] = -1;
bi->cpipe[1] = -1;
}
@ -496,11 +597,15 @@ int OpenBInstance(struct BInstance *bi, struct lPLCI *lp, enum BType btype)
bi->from_up = ncciB3Data;
break;
#ifdef USE_SOFTFAX
case BType_Fax:
case BType_Fax:
bi->from_down = FaxRecvBData;
bi->from_up = FaxB3Message;
break;
#endif
case BType_tty:
bi->from_down = recvBdirect;
bi->from_up = ncciB3Data;
break;
default:
eprint("Error unnkown BType %d\n", btype);
close(sk);
@ -538,10 +643,33 @@ int OpenBInstance(struct BInstance *bi, struct lPLCI *lp, enum BType btype)
bi->UpId = 0;
bi->DownId = 0;
}
} else {
ret = CreateBchannelThread(bi);
} else if (btype == BType_Fax) {
ret = CreateBchannelThread(bi, 2);
if (ret < 0) {
eprint("Error while creating B-channel thread)\n");
eprint("Error while creating B%d-channel thread\n", bi->nr);
close(sk);
bi->fd = -1;
bi->lp = NULL;
} else {
ret = 0;
bi->UpId = 0;
bi->DownId = 0;
}
} else if (btype == BType_tty) {
ret = Create_tty(bi);
if (ret < 0) {
eprint("Error while creating B%d-channel tty\n", bi->nr);
close(sk);
bi->fd = -1;
bi->lp = NULL;
return ret;
} else {
bi->pfd[2].fd = bi->tty;
bi->pfd[2].events = POLLIN | POLLPRI;
ret = CreateBchannelThread(bi, 3);
}
if (ret < 0) {
eprint("Error while creating B%d-channel thread\n", bi->nr);
close(sk);
bi->fd = -1;
bi->lp = NULL;
@ -570,6 +698,11 @@ int CloseBInstance(struct BInstance *bi)
StopBchannelThread(bi);
break;
#endif
case BType_tty:
StopBchannelThread(bi);
if (bi->tty > -1)
close(bi->tty);
bi->tty = -1;
default:
break;
}
@ -915,6 +1048,70 @@ static void misdn_manufacturer_req(int fd, struct mc_buf *mc)
eprint("error send %d/%d - %s\n", ret, 10, strerror(errno));
}
static void mIcapi_userflag(int fd, int idx, struct mc_buf *mc)
{
int ret;
struct mApplication *appl = pollinfo[idx].data;
uint32_t sf, cf, uf = 0xffffffff;
CAPIMSG_SETSUBCOMMAND(mc->rb, CAPI_CONF);
capimsg_setu16(mc->rb, 0, 12);
if (appl) {
uf = appl->UserFlags;
sf = CAPIMSG_U32(mc->rb, 8);
cf = CAPIMSG_U32(mc->rb, 12);
if (cf)
uf &= ~cf;
if (sf)
uf |= sf;
iprint("UserFlags old=%x new=%x\n", appl->UserFlags, uf);
appl->UserFlags = uf;
}
capimsg_setu32(mc->rb, 8, uf);
ret = send(fd, mc->rb, 12, 0);
if (ret != 12)
eprint("error send %d/%d - %s\n", ret, 12, strerror(errno));
}
static void mIcapi_ttyname(int fd, int idx, struct mc_buf *mc)
{
int ret, ml, l = 0;
struct mApplication *appl = pollinfo[idx].data;
struct lPLCI *lp;
uint32_t ncci = 0;
char name[80];
CAPIMSG_SETSUBCOMMAND(mc->rb, CAPI_CONF);
if (appl) {
ncci = CAPIMSG_U32(mc->rb, 8);
ml = CAPIMSG_U32(mc->rb, 12);
if (appl->UserFlags & CAPIFLAG_HIGHJACKING) {
lp = get_lPLCI4plci(appl, ncci);
if (lp->BIlink && lp->BIlink->tty > -1) {
ret = ptsname_r(lp->BIlink->tty, name, 80);
if (ret)
eprint("NCCI %06x: error to get ptsname for %d - %s\n",
ncci, lp->BIlink->tty, strerror(errno));
else
l = strlen(name);
} else
eprint("NCCI %06x: do not find lPLCI for NCCI\n", ncci);
}
}
if (l >= ml)
l = 0;
if (l) {
iprint("NCCI %06x: ttyname set to %s\n", ncci, name);
memcpy(&mc->rb[8], name, l);
} else
wprint("NCCI %06x: ttyname requested but not available\n", ncci);
mc->rb[8 + l] = 0;
capimsg_setu16(mc->rb, 0, l + 8);
ret = send(fd, mc->rb, l + 8, 0);
if (ret != l + 8)
eprint("error send %d/%d - %s\n", ret, 12, strerror(errno));
}
static int main_recv(int fd, int idx)
{
int ret, len, cmd, dl;
@ -980,6 +1177,12 @@ static int main_recv(int fd, int idx)
case MIC_MANUFACTURER_REQ:
misdn_manufacturer_req(fd, mc);
break;
case MIC_USERFLAG_REQ:
mIcapi_userflag(fd, idx, mc);
break;
case MIC_TTYNAME_REQ:
mIcapi_ttyname(fd, idx, mc);
break;
default:
if (pollinfo[idx].type == PIT_Application)
ret = PutMessageApplication(pollinfo[idx].data, mc);
@ -1236,6 +1439,7 @@ int main(int argc, char *argv[])
pc->BInstances[j].nr = j;
pc->BInstances[j].pc = pc;
pc->BInstances[j].fd = -1;
pc->BInstances[j].tty = -1;
sem_init(&pc->BInstances[j].wait, 0, 0);
}
pc->profile.ncontroller = i + 1;

View File

@ -1642,6 +1642,7 @@ static int lPLCILinkUp(struct lPLCI *lp)
int proto = -1, ret = 0, act_l1;
struct mISDNhead mh;
enum BType btype = BType_None;
struct mApplication *ap = lp->lc->Appl;
mh.id = 1;
mh.prim = 0;
@ -1716,6 +1717,9 @@ static int lPLCILinkUp(struct lPLCI *lp)
if (ret)
return ret;
if (ap->UserFlags & CAPIFLAG_HIGHJACKING) {
btype = BType_tty;
}
dprint(MIDEBUG_PLCI, "lPLCILinkUp B1(%x) B2(%x) B3(%x) ch(%d) proto(%x)\n",
lp->Bprotocol.B1, lp->Bprotocol.B2, lp->Bprotocol.B3, lp->chid.nr, proto);

View File

@ -61,7 +61,8 @@ typedef int (BDataTrans_t)(struct BInstance *, struct mc_buf *);
enum BType {
BType_None = 0,
BType_Direct = 1,
BType_Fax = 2
BType_Fax = 2,
BType_tty = 3
};
struct BInstance {
@ -69,6 +70,7 @@ struct BInstance {
int usecnt;
int proto;
int fd;
int tty;
enum BType type;
uint16_t DownId; /* Ids for send down messages */
uint16_t UpId; /* Ids for send up messages */
@ -78,7 +80,8 @@ struct BInstance {
BDataTrans_t *from_down;
BDataTrans_t *from_up;
pthread_t tid;
struct pollfd pfd[2];
struct pollfd pfd[4];
int pcnt;
int cpipe[2];
sem_t wait;
unsigned int running:1;
@ -154,6 +157,7 @@ struct mApplication {
int MaxB3Con;
int MaxB3Blk;
int MaxB3Size;
uint32_t UserFlags;
};
struct mApplication *RegisterApplication(uint16_t, uint32_t, uint32_t, uint32_t);
@ -217,6 +221,7 @@ struct mNCCI *getNCCI4addr(struct lPLCI *, uint32_t, int);
void lPLCIDelNCCI(struct mNCCI *);
struct mNCCI *ConnectB3Request(struct lPLCI *, struct mc_buf *);
void B3ReleaseLink(struct lPLCI *, struct BInstance *);
struct lPLCI *get_lPLCI4plci(struct mApplication *, uint32_t);
#define GET_NCCI_EXACT 1
#define GET_NCCI_ONLY_PLCI 2
@ -265,6 +270,7 @@ struct mNCCI {
unsigned char up_header[30];
unsigned int dtmflisten:1;
unsigned int l1direct:1;
unsigned int l1trans:1;
unsigned int l2trans:1;
unsigned int l3trans:1;
unsigned int dlbusy:1;
@ -362,6 +368,11 @@ void mCapi_message2str(struct mc_buf *);
#define CAPI_B3_DATA_IND_HEADER_SIZE ((4 == sizeof(void *)) ? 22 : 30)
#define CAPIFLAG_HIGHJACKING 1
#define CAPI_DATA_TTY 0xe0
/* some helper */
static inline int capiEncodeWord(unsigned char *p, uint16_t i)
{

View File

@ -37,6 +37,8 @@ extern "C" {
#define MIC_VERSION_REQ CAPICMD(0xf4, 0xff)
#define MIC_GET_MANUFACTURER_REQ CAPICMD(0xf5, 0xff)
#define MIC_MANUFACTURER_REQ CAPICMD(0xf6, 0xff)
#define MIC_USERFLAG_REQ CAPICMD(0xf7, 0xff)
#define MIC_TTYNAME_REQ CAPICMD(0xf8, 0xff)
#ifdef __cplusplus

View File

@ -422,6 +422,87 @@ static unsigned misdnGetProfile(int nHandle, unsigned nController, unsigned char
return err;
}
static int misdnFlagReq(uint16_t ApplId, uint32_t set_f, uint32_t clr_f)
{
unsigned char anBuf[100];
int ret, fd;
fd = capi_applid2fd(ApplId);
if (fd < 0)
return -1;
misdnSetHeader(anBuf, 16, ApplId, MIC_USERFLAG_REQ, 0);
capimsg_setu32(anBuf, 8, set_f);
capimsg_setu32(anBuf, 12, clr_f);
ret = misdnRemoteCommand(fd, anBuf, 16, MIC_USERFLAG_REQ);
if (ret == 12)
ret = CAPIMSG_U32(anBuf, 8);
else
ret = -1;
return ret;
}
static int misdnGetFlags(unsigned nApplId, unsigned *pnFlagsPtr)
{
int ret;
ret = misdnFlagReq(nApplId, 0, 0);
if (ret < 0)
*pnFlagsPtr = 0;
else {
*pnFlagsPtr = ret;
ret = 0;
}
return ret;
}
static int misdnSetFlags(unsigned nApplId, unsigned nFlags)
{
int ret;
ret = misdnFlagReq(nApplId, nFlags, 0);
if (ret >= 0)
ret = 0;
return ret;
}
static int misdnClearFlags(unsigned nApplId, unsigned nFlags)
{
int ret;
ret = misdnFlagReq(nApplId, 0, nFlags);
if (ret >= 0)
ret = 0;
return ret;
}
static char *misdnGetTtyDeviceName(unsigned nApplId,unsigned nNcci, char *pnBuffer, size_t nSize)
{
unsigned char *anBuf;
int ret, fd;
fd = capi_applid2fd(nApplId);
if (fd < 0)
return NULL;
if (nSize > 64)
nSize = 64;
anBuf = malloc(nSize + 12);
if (!anBuf)
return NULL;
misdnSetHeader(anBuf, 16, nApplId, MIC_TTYNAME_REQ, 0);
capimsg_setu32(anBuf, 8, nNcci);
capimsg_setu32(anBuf, 12, nSize & 0xff);
ret = misdnRemoteCommand(fd, anBuf, 16, MIC_TTYNAME_REQ);
if (ret > 8) {
ret = ret - 8;
memcpy(pnBuffer, &anBuf[8], ret);
pnBuffer[ret] = 0;
} else
return NULL;
free(anBuf);
return pnBuffer;
}
/** Module operations structure */
static struct sModuleOperations sRemoteCapi = {
misdnIsInstalled,
@ -434,10 +515,10 @@ static struct sModuleOperations sRemoteCapi = {
misdnGetSerialNumber,
misdnGetProfile,
NULL,
NULL,
NULL,
NULL,
NULL,
misdnGetFlags,
misdnSetFlags,
misdnClearFlags,
misdnGetTtyDeviceName,
NULL,
NULL
};

View File

@ -378,7 +378,7 @@ static void ncci_n0_dl_establish_ind_conf(struct FsmInst *fi, int event, void *a
FsmEvent(&ncci->ncci_m, EV_NC_CONNECT_B3_IND, arg);
}
static void ncci_dl_establish_conf(struct FsmInst *fi, int event, void *arg)
static void ncci_dl_establish_ind_conf(struct FsmInst *fi, int event, void *arg)
{
struct mNCCI *ncci = fi->userdata;
struct mc_buf *mc = arg;
@ -453,7 +453,8 @@ static struct FsmNode fn_ncci_list[] = {
{ST_NCCI_N_2, EV_AP_DISCONNECT_B3_REQ, ncci_disconnect_b3_req},
{ST_NCCI_N_2, EV_NC_DISCONNECT_B3_IND, ncci_disconnect_b3_ind},
{ST_NCCI_N_2, EV_NC_DISCONNECT_B3_CONF, ncci_disconnect_b3_conf},
{ST_NCCI_N_2, EV_DL_ESTABLISH_CONF, ncci_dl_establish_conf},
{ST_NCCI_N_2, EV_DL_ESTABLISH_CONF, ncci_dl_establish_ind_conf},
{ST_NCCI_N_2, EV_DL_ESTABLISH_IND, ncci_dl_establish_ind_conf},
{ST_NCCI_N_2, EV_DL_RELEASE_IND, ncci_dl_release_ind_conf},
{ST_NCCI_N_2, EV_AP_MANUFACTURER_REQ, ncci_manufacturer_req},
{ST_NCCI_N_2, EV_AP_RELEASE, ncci_appl_release_disc},
@ -551,7 +552,11 @@ struct mNCCI *ncciCreate(struct lPLCI *lp)
nc->window = lp->lc->Appl->MaxB3Blk;
pthread_mutex_init(&nc->lock, NULL);
switch (lp->Bprotocol.B1) {
case 0:
nc->l1trans = 0;
break;
case 1:
nc->l1trans = 1;
if (!lp->l1dtmf) {
nc->flowmode = flmPHDATA;
nc->l1direct = 1;
@ -567,12 +572,18 @@ struct mNCCI *ncciCreate(struct lPLCI *lp)
break;
}
if (lp->Bprotocol.B2 == 0) { /* X.75 has own flowctrl */
if (lp->Bprotocol.B2 == 1) { /* X.75 has own flowctrl */
nc->l2trans = 1;
if (lp->Bprotocol.B1 == 0) {
nc->l1direct = 1;
nc->flowmode = flmPHDATA;
}
} else {
nc->l2trans = 1;
if (lp->Bprotocol.B1 == 0) { // HDLC
nc->l1direct = 1;
nc->flowmode = flmPHDATA;
}
}
if (lp->Bprotocol.B3 == 0) {
nc->l3trans = 1;
@ -788,19 +799,44 @@ static uint16_t ncciDataReq(struct mNCCI *ncci, struct mc_buf *mc)
AnswerDataB3Req(ncci, mc, CapiMessageNotSupportedInCurrentState);
return 0;
}
if (ncci->xmit_handles[ncci->iidx].pkt) {
if (ncci->BIlink->tty > -1) {
/* We have a packet from pseudo tty */
if (ncci->xmit_handles[ncci->iidx].pkt) {
wprint("NCCI %06x: tty CapiSendQueueFull\n", ncci->ncci);
/* TODO FLOW CONTROL */
pthread_mutex_unlock(&ncci->lock);
free_mc_buf(mc);
return 0;
}
len = mc->len;
if (*mc->rp == 0) {
len--;
mc->rp++;
dhexprint(MIDEBUG_NCCI_DATA, "Queued Data: ", mc->rp, len);
} else {
/* TODO FLOW CONTROL */
wprint("NCCI %06x: tty got ctrl %02x\n", ncci->ncci, *mc->rp);
pthread_mutex_unlock(&ncci->lock);
free_mc_buf(mc);
return 0;
}
ncci->xmit_handles[ncci->iidx].DataHandle = 0;
ncci->xmit_handles[ncci->iidx].MsgId = 0;
off = 8;
} else if (ncci->xmit_handles[ncci->iidx].pkt) {
wprint("NCCI %06x: CapiSendQueueFull\n", ncci->ncci);
pthread_mutex_unlock(&ncci->lock);
AnswerDataB3Req(ncci, mc, CapiSendQueueFull);
return 0;
} else {
len = CAPIMSG_DATALEN(mc->rb);
ncci->xmit_handles[ncci->iidx].DataHandle = CAPIMSG_REQ_DATAHANDLE(mc->rb);
ncci->xmit_handles[ncci->iidx].MsgId = CAPIMSG_MSGID(mc->rb);
mc->rp = mc->rb + off;
}
len = CAPIMSG_DATALEN(mc->rb);
ncci->xmit_handles[ncci->iidx].pkt = mc;
ncci->xmit_handles[ncci->iidx].DataHandle = CAPIMSG_REQ_DATAHANDLE(mc->rb);
ncci->xmit_handles[ncci->iidx].MsgId = CAPIMSG_MSGID(mc->rb);
ncci->xmit_handles[ncci->iidx].dlen = len;
ncci->xmit_handles[ncci->iidx].sent = 0;
mc->rp = mc->rb + off;
mc->len = len;
ncci->xmit_handles[ncci->iidx].sp = mc->rp;
@ -838,6 +874,23 @@ static int ncciDataInd(struct mNCCI *ncci, int pr, struct mc_buf *mc)
wprint("NCCI %06x: : frame with %d bytes dropped BIlink gone\n", ncci->ncci, dlen);
return -EINVAL;
}
if (ncci->BIlink->tty > -1) {
/* transfer via a pseudo tty */
pthread_mutex_unlock(&ncci->lock);
hh++;
mc->rp = (unsigned char *)hh;
ret = write(ncci->BIlink->tty, mc->rp, dlen);
if (ret != dlen)
wprint("NCCI %06x: frame with %d bytes only %d bytes were written to tty - %s\n",
ncci->ncci, dlen, ret, strerror(errno));
else {
dprint(MIDEBUG_NCCI, "NCCI %06x: frame with %d bytes was written to tty\n",
ncci->ncci, dlen);
dhexprint(MIDEBUG_NCCI_DATA, "Data: ", mc->rp, dlen);
}
free_mc_buf(mc);
return 0;
}
for (i = 0; i < ncci->window; i++) {
if (ncci->recv_handles[i] == 0)
break;
@ -871,7 +924,7 @@ static int ncciDataInd(struct mNCCI *ncci, int pr, struct mc_buf *mc)
pthread_mutex_unlock(&ncci->lock);
if (ret != tot) {
wprint("NCCI %06x: : frame with %d + %d bytes only %d bytes are sent - %s\n",
wprint("NCCI %06x: frame with %d + %d bytes only %d bytes are sent - %s\n",
ncci->ncci, dlen, CAPI_B3_DATA_IND_HEADER_SIZE, ret, strerror(errno));
ret = -EINVAL;
} else
@ -884,7 +937,7 @@ static int ncciDataInd(struct mNCCI *ncci, int pr, struct mc_buf *mc)
static void ncciDataConf(struct mNCCI *ncci, struct mc_buf *mc)
{
int i;
int i, do_answer = 1;
struct mISDNhead *hh;
hh = (struct mISDNhead *)mc->rb;
@ -895,6 +948,14 @@ static void ncciDataConf(struct mNCCI *ncci, struct mc_buf *mc)
}
pthread_mutex_lock(&ncci->lock);
if (!ncci->BIlink) {
pthread_mutex_unlock(&ncci->lock);
wprint("NCCI %06x: ack dropped BIlink gone\n", ncci->ncci);
free_mc_buf(mc);
return;
}
if (ncci->BIlink->tty > -1)
do_answer = 0;
for (i = 0; i < ncci->window; i++) {
if (ncci->xmit_handles[i].PktId == hh->id) {
if (ncci->xmit_handles[i].pkt)
@ -917,7 +978,8 @@ static void ncciDataConf(struct mNCCI *ncci, struct mc_buf *mc)
ncci->xmit_handles[i].PktId = 0;
ncci->dlbusy = 0;
pthread_mutex_unlock(&ncci->lock);
AnswerDataB3Req(ncci, mc, CapiNoError);
if (do_answer)
AnswerDataB3Req(ncci, mc, CapiNoError);
SendDataB3Down(ncci, 0);
return;
}
@ -1043,8 +1105,15 @@ static int ncciSendMessage(struct mNCCI *ncci, uint8_t cmd, uint8_t subcmd, stru
free_mc_buf(mc);
ret = CapiNoError;
}
} else if (cmd == CAPI_DATA_TTY) {
if (ncci->ncci_m.state == ST_NCCI_N_ACT) {
ret = ncciDataReq(ncci, mc);
} else {
ret = CapiMessageNotSupportedInCurrentState;
wprint("NCCI %06x: DATA_TTY_REQ - but but NCCI state %s\n", ncci->ncci,
str_st_ncci[ncci->ncci_m.state]);
}
} else {
// capi_message2cmsg(cmsg, skb->data);
ret = ncciGetCmsg(ncci, cmd, subcmd, mc);
}
return ret;
@ -1052,7 +1121,22 @@ static int ncciSendMessage(struct mNCCI *ncci, uint8_t cmd, uint8_t subcmd, stru
int ncciB3Data(struct BInstance *bi, struct mc_buf *mc)
{
return ncciSendMessage(bi->b3data, mc->cmsg.Command, mc->cmsg.Subcommand, mc);
struct mNCCI *ncci = bi->b3data;
if (mc->cmsg.Command == CAPI_CONNECT_B3 && mc->cmsg.Subcommand == CAPI_REQ) {
if (ncci)
wprint("NCCI %06x: already assigned\n", ncci->ncci);
else {
ncci = ConnectB3Request(bi->lp, mc);
bi->b3data = ncci;
}
}
if (!ncci) {
wprint("No NCCI asigned for PCLI %04x\n", bi->lp->plci);
return -EINVAL;
}
return ncciSendMessage(ncci, mc->cmsg.Command, mc->cmsg.Subcommand, mc);
}
int ncciB3Message(struct mNCCI *ncci, struct mc_buf *mc)
@ -1197,9 +1281,12 @@ int recvBdirect(struct BInstance *bi, struct mc_buf *mc)
bi->b3data = ncci;
}
FsmEvent(&ncci->ncci_m, EV_DL_ESTABLISH_CONF, mc);
mc->len = 520;
memset(&mc->rb[8], 0x55, 512);
ncciDataInd(ncci, hh->prim, mc);
if (ncci->l1trans) {
/* prefill FIFO 64 ms */
mc->len = 520;
memset(&mc->rb[8], 0x55, 512);
ncciDataInd(ncci, hh->prim, mc);
}
ret = 0;
break;
case PH_ACTIVATE_IND:
@ -1211,7 +1298,8 @@ int recvBdirect(struct BInstance *bi, struct mc_buf *mc)
return -ENOMEM;
} else
bi->b3data = ncci;
}
} else
dprint(MIDEBUG_NCCI, "NCCI %06x: %s on existing NCCIx\n", ncci->ncci, _mi_msg_type2str(hh->prim));
FsmEvent(&ncci->ncci_m, EV_DL_ESTABLISH_IND, mc);
ret = 1;
break;