extractedLnx/linux-2.6.4/drivers/isdn/hardware/eicon/i4l_idi.c_idi_IndParse.c
static void
idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsigned char *buffer, int len)
{
int i,j;
int pos = 0;
int codeset = 0;
int wlen = 0;
int lock = 0;
__u8 w;
__u16 code;
isdn_ctrl cmd;
memset(message, 0, sizeof(idi_ind_message));
if ((!len) || (!buffer[pos])) return;
while(pos <= len) {
w = buffer[pos++];
if (!w) return;
if (w & 0x80) {
wlen = 0;
}
else {
wlen = buffer[pos++];
}
if (pos > len) return;
if (lock & 0x80) lock &= 0x7f;
else codeset = lock;
if((w&0xf0) == SHIFT) {
codeset = w;
if(!(codeset & 0x08)) lock = codeset & 7;
codeset &= 7;
lock |= 0x80;
}
else {
if (w==ESC && wlen >=2) {
code = buffer[pos++]|0x800;
wlen--;
}
else code = w;
code |= (codeset<<8);
if (pos + wlen > len) {
eicon_log(ccard, 1, "idi_err: Ch%d: IElen %d of %x exceeds Ind_Length (+%d)\n", chan->No,
wlen, code, (pos + wlen) - len);
return;
}
switch(code) {
case OAD:
if (wlen > sizeof(message->oad)) {
pos += wlen;
break;
}
j = 1;
if (wlen) {
message->plan = buffer[pos++];
if (message->plan &0x80)
message->screen = 0;
else {
message->screen = buffer[pos++];
j = 2;
}
}
for(i=0; i < wlen-j; i++)
message->oad[i] = buffer[pos++];
eicon_log(ccard, 2, "idi_inf: Ch%d: OAD=(0x%02x,0x%02x) %s\n", chan->No,
message->plan, message->screen, message->oad);
break;
case RDN:
if (wlen > sizeof(message->rdn)) {
pos += wlen;
break;
}
j = 1;
if (wlen) {
if (!(buffer[pos++] & 0x80)) {
pos++;
j = 2;
}
}
for(i=0; i < wlen-j; i++)
message->rdn[i] = buffer[pos++];
eicon_log(ccard, 2, "idi_inf: Ch%d: RDN= %s\n", chan->No,
message->rdn);
break;
case CPN:
if (wlen > sizeof(message->cpn)) {
pos += wlen;
break;
}
for(i=0; i < wlen; i++)
message->cpn[i] = buffer[pos++];
eicon_log(ccard, 2, "idi_inf: Ch%d: CPN=(0x%02x) %s\n", chan->No,
(__u8)message->cpn[0], message->cpn + 1);
break;
case DSA:
if (wlen > sizeof(message->dsa)) {
pos += wlen;
break;
}
pos += 2;
for(i=0; i < wlen-2; i++)
message->dsa[i] = buffer[pos++];
eicon_log(ccard, 2, "idi_inf: Ch%d: DSA=%s\n", chan->No, message->dsa);
break;
case OSA:
if (wlen > sizeof(message->osa)) {
pos += wlen;
break;
}
pos += 2;
for(i=0; i < wlen-2; i++)
message->osa[i] = buffer[pos++];
eicon_log(ccard, 2, "idi_inf: Ch%d: OSA=%s\n", chan->No, message->osa);
break;
case CAD:
pos += wlen;
eicon_log(ccard, 2, "idi_inf: Ch%d: Connected Address in ind, len:%x\n",
chan->No, wlen);
break;
case BC:
if (wlen > sizeof(message->bc)) {
pos += wlen;
break;
}
for(i=0; i < wlen; i++)
message->bc[i] = buffer[pos++];
eicon_log(ccard, 4, "idi_inf: Ch%d: BC = 0x%02x 0x%02x 0x%02x\n", chan->No,
message->bc[0],message->bc[1],message->bc[2]);
break;
case 0x800|BC:
if (wlen > sizeof(message->e_bc)) {
pos += wlen;
break;
}
for(i=0; i < wlen; i++)
message->e_bc[i] = buffer[pos++];
eicon_log(ccard, 4, "idi_inf: Ch%d: ESC/BC=%d\n", chan->No, message->bc[0]);
break;
case LLC:
if (wlen > sizeof(message->llc)) {
pos += wlen;
break;
}
for(i=0; i < wlen; i++)
message->llc[i] = buffer[pos++];
eicon_log(ccard, 4, "idi_inf: Ch%d: LLC=%d %d %d %d ...\n", chan->No, message->llc[0],
message->llc[1],message->llc[2],message->llc[3]);
break;
case HLC:
if (wlen > sizeof(message->hlc)) {
pos += wlen;
break;
}
for(i=0; i < wlen; i++)
message->hlc[i] = buffer[pos++];
eicon_log(ccard, 4, "idi_inf: Ch%d: HLC=%x %x %x %x %x ...\n", chan->No,
message->hlc[0], message->hlc[1],
message->hlc[2], message->hlc[3], message->hlc[4]);
break;
case DSP:
case 0x600|DSP:
if (wlen > sizeof(message->display)) {
pos += wlen;
break;
}
for(i=0; i < wlen; i++)
message->display[i] = buffer[pos++];
eicon_log(ccard, 4, "idi_inf: Ch%d: Display: %s\n", chan->No,
message->display);
break;
case 0x600|KEY:
if (wlen > sizeof(message->keypad)) {
pos += wlen;
break;
}
for(i=0; i < wlen; i++)
message->keypad[i] = buffer[pos++];
eicon_log(ccard, 4, "idi_inf: Ch%d: Keypad: %s\n", chan->No,
message->keypad);
break;
case NI:
case 0x600|NI:
if (wlen) {
switch(buffer[pos] & 127) {
case 0:
eicon_log(ccard, 4, "idi_inf: Ch%d: User suspended.\n", chan->No);
break;
case 1:
eicon_log(ccard, 4, "idi_inf: Ch%d: User resumed.\n", chan->No);
break;
case 2:
eicon_log(ccard, 4, "idi_inf: Ch%d: Bearer service change.\n", chan->No);
break;
default:
eicon_log(ccard, 4, "idi_inf: Ch%d: Unknown Notification %x.\n",
chan->No, buffer[pos] & 127);
}
pos += wlen;
}
break;
case PI:
case 0x600|PI:
if (wlen > 1) {
switch(buffer[pos+1] & 127) {
case 1:
eicon_log(ccard, 4, "idi_inf: Ch%d: Call is not end-to-end ISDN.\n", chan->No);
break;
case 2:
eicon_log(ccard, 4, "idi_inf: Ch%d: Destination address is non ISDN.\n", chan->No);
break;
case 3:
eicon_log(ccard, 4, "idi_inf: Ch%d: Origination address is non ISDN.\n", chan->No);
break;
case 4:
eicon_log(ccard, 4, "idi_inf: Ch%d: Call has returned to the ISDN.\n", chan->No);
break;
case 5:
eicon_log(ccard, 4, "idi_inf: Ch%d: Interworking has occurred.\n", chan->No);
break;
case 8:
eicon_log(ccard, 4, "idi_inf: Ch%d: In-band information available.\n", chan->No);
break;
default:
eicon_log(ccard, 4, "idi_inf: Ch%d: Unknown Progress %x.\n",
chan->No, buffer[pos+1] & 127);
}
}
pos += wlen;
break;
case CAU:
if (wlen > sizeof(message->cau)) {
pos += wlen;
break;
}
for(i=0; i < wlen; i++)
message->cau[i] = buffer[pos++];
memcpy(&chan->cause, &message->cau, 2);
eicon_log(ccard, 4, "idi_inf: Ch%d: CAU=%d %d\n", chan->No,
message->cau[0],message->cau[1]);
break;
case 0x800|CAU:
if (wlen > sizeof(message->e_cau)) {
pos += wlen;
break;
}
for(i=0; i < wlen; i++)
message->e_cau[i] = buffer[pos++];
eicon_log(ccard, 4, "idi_inf: Ch%d: ECAU=%d %d\n", chan->No,
message->e_cau[0],message->e_cau[1]);
break;
case 0x800|CHI:
if (wlen > sizeof(message->e_chi)) {
pos += wlen;
break;
}
for(i=0; i < wlen; i++)
message->e_chi[i] = buffer[pos++];
eicon_log(ccard, 4, "idi_inf: Ch%d: ESC/CHI=%d\n", chan->No,
message->e_cau[0]);
break;
case 0x800|0x7a:
pos ++;
message->e_mt=buffer[pos++];
eicon_log(ccard, 4, "idi_inf: Ch%d: EMT=0x%x\n", chan->No, message->e_mt);
break;
case DT:
if (wlen > sizeof(message->dt)) {
pos += wlen;
break;
}
for(i=0; i < wlen; i++)
message->dt[i] = buffer[pos++];
eicon_log(ccard, 4, "idi_inf: Ch%d: DT: %02d.%02d.%02d %02d:%02d:%02d\n", chan->No,
message->dt[2], message->dt[1], message->dt[0],
message->dt[3], message->dt[4], message->dt[5]);
break;
case 0x600|SIN:
if (wlen > sizeof(message->sin)) {
pos += wlen;
break;
}
for(i=0; i < wlen; i++)
message->sin[i] = buffer[pos++];
eicon_log(ccard, 2, "idi_inf: Ch%d: SIN=%d %d\n", chan->No,
message->sin[0],message->sin[1]);
break;
case 0x600|CPS:
eicon_log(ccard, 2, "idi_inf: Ch%d: Called Party Status in ind\n", chan->No);
pos += wlen;
break;
case 0x600|CIF:
for (i = 0; i < wlen; i++)
if (buffer[pos + i] != '0') break;
memcpy(&cmd.parm.num, &buffer[pos + i], wlen - i);
cmd.parm.num[wlen - i] = 0;
eicon_log(ccard, 2, "idi_inf: Ch%d: CIF=%s\n", chan->No, cmd.parm.num);
pos += wlen;
cmd.driver = ccard->myid;
cmd.command = ISDN_STAT_CINF;
cmd.arg = chan->No;
ccard->interface.statcallb(&cmd);
break;
case 0x600|DATE:
eicon_log(ccard, 2, "idi_inf: Ch%d: Date in ind\n", chan->No);
pos += wlen;
break;
case 0xa1:
eicon_log(ccard, 2, "idi_inf: Ch%d: Sending Complete in ind.\n", chan->No);
pos += wlen;
break;
case 0xe08:
case 0xe7a:
case 0xe04:
case 0xe00:
/* *** TODO *** */
case CHA:
/* Charge advice */
case FTY:
case 0x600|FTY:
case CHI:
case 0x800:
/* Not yet interested in this */
pos += wlen;
break;
case 0x880:
/* Managment Information Element */
if (!manbuf) {
eicon_log(ccard, 1, "idi_err: manbuf not allocated\n");
}
else {
memcpy(&manbuf->data[manbuf->pos], &buffer[pos], wlen);
manbuf->length[manbuf->count] = wlen;
manbuf->count++;
manbuf->pos += wlen;
}
pos += wlen;
break;
default:
pos += wlen;
eicon_log(ccard, 6, "idi_inf: Ch%d: unknown information element 0x%x in ind, len:%x\n",
chan->No, code, wlen);
}
}
}
}
Generated by GNU enscript 1.6.4.