📄 eicon_idi.c
字号:
if (InMask == 0) { if (InBuf.Len >= InBuf.Size) { Event = EVENT_EOD; break; } if ((chan->fax2.Dle != _DLE_) && *InBuf.Next == _DLE_) { chan->fax2.Dle = _DLE_; InBuf.Next++; InBuf.Len++; if (InBuf.Len >= InBuf.Size) { Event = EVENT_EOD; break; } } if (chan->fax2.Dle == _DLE_) { chan->fax2.Dle = 0; if (*InBuf.Next == _ETX_) { Event = EVENT_EOP; break; } else if (*InBuf.Next == _DLE_) { /* do nothing */ } else { eicon_log(ccard, 1, "idi_err: Ch%d: unknown DLE escape %02x found\n", chan->No, *InBuf.Next); InBuf.Next++; InBuf.Len++; if (InBuf.Len >= InBuf.Size) { Event = EVENT_EOD; break; } } } InBuf.Len++; InData = *InBuf.Next++; InMask = (chan->fax->bor) ? 0x80 : 0x01; } while (InMask) { LineData >>= 1; LineDataLen++; if (InData & InMask) LineData |= 0x80000000; if (chan->fax->bor) InMask >>= 1; else InMask <<= 1; if ((LineDataLen >= T4_EOL_BITSIZE) && ((LineData & T4_EOL_MASK_DWORD) == T4_EOL_DWORD)) { Event = EVENT_EOL; if (LineDataLen > T4_EOL_BITSIZE) { Byte = (__u8) ((LineData & ~T4_EOL_MASK_DWORD) >> (32 - LineDataLen)); if (Byte == 0) { if (! chan->fax2.NullByteExist) { chan->fax2.NullBytesPos = LineBuf.Len; chan->fax2.NullByteExist = 1; } } else { chan->fax2.NullByteExist = 0; } if (LineBuf.Len < LineBuf.Size) { *LineBuf.Next++ = Byte; LineBuf.Len++; } } LineDataLen = 0; break; } if (LineDataLen >= T4_EOL_BITSIZE + 8) { Byte = (__u8) ((LineData & ~T4_EOL_MASK_DWORD) >> (32 - T4_EOL_BITSIZE - 8)); LineData &= T4_EOL_MASK_DWORD; LineDataLen = T4_EOL_BITSIZE; if (Byte == 0) { if (! chan->fax2.NullByteExist) { chan->fax2.NullBytesPos = LineBuf.Len; chan->fax2.NullByteExist = 1; } } else { chan->fax2.NullByteExist = 0; } if (LineBuf.Len < LineBuf.Size) { *LineBuf.Next++ = Byte; LineBuf.Len++; } } } if (Event != EVENT_NONE) break; } if ((Event != EVENT_EOL) && (Event != EVENT_EOP)) break; if ((Event == EVENT_EOP) && (LineDataLen > 0)) { LineData >>= 32 - LineDataLen; LineDataLen = 0; while (LineData != 0) { Byte = (__u8) LineData; LineData >>= 8; if (Byte == 0) { if (! chan->fax2.NullByteExist) { chan->fax2.NullBytesPos = LineBuf.Len; chan->fax2.NullByteExist = 1; } } else { chan->fax2.NullByteExist = 0; } if (LineBuf.Len < LineBuf.Size) { *LineBuf.Next++ = Byte; LineBuf.Len++; } } } if (chan->fax2.NullByteExist) { if (chan->fax2.NullBytesPos == 0) { LineBuf.Len = 0; } else { LineBuf.Len = chan->fax2.NullBytesPos + 1; } } if (LineBuf.Len > 0) { if (OutBuf.Len + LineBuf.Len + SFF_LEN_FLD_SIZE > OutBuf.Size) { ret = idi_fax_send_outbuf(ccard, chan, &OutBuf); } if (LineBuf.Len <= 216) { *OutBuf.Next++ = (__u8) LineBuf.Len; OutBuf.Len++; } else { *OutBuf.Next++ = 0; *((__u16 *) OutBuf.Next)++ = (__u16) LineBuf.Len; OutBuf.Len += 3; } memcpy(OutBuf.Next, LineBuf.Data, LineBuf.Len); OutBuf.Next += LineBuf.Len; OutBuf.Len += LineBuf.Len; } LineBuf.Len = 0; LineBuf.Next = LineBuf.Data; chan->fax2.NullByteExist = 0; if (Event == EVENT_EOP) break; Event = EVENT_NONE; } if (Event == EVENT_EOP) { chan->fax2.Eop = 1; chan->fax2.PageCount++; cmd.driver = ccard->myid; cmd.command = ISDN_STAT_FAXIND; cmd.arg = chan->No; chan->fax->r_code = ISDN_TTY_FAX_EOP; ccard->interface.statcallb(&cmd); } if (OutBuf.Len > 0) { ret = idi_fax_send_outbuf(ccard, chan, &OutBuf); } chan->fax2.LineLen = LineBuf.Len; chan->fax2.LineData = LineData; chan->fax2.LineDataLen = LineDataLen;# undef EVENT_NONE# undef EVENT_EOD# undef EVENT_EOL# undef EVENT_EOP if (ret >= 0) dev_kfree_skb(skb); if (ret == 0) ret = 1; return(ret);}voididi_fax_hangup(eicon_card *ccard, eicon_chan *chan){ isdn_ctrl cmd; if (!chan->fax) { eicon_log(ccard, 1, "idi_fax: hangup with NULL fax struct, ERROR\n"); return; } if ((chan->fax->direction == ISDN_TTY_FAX_CONN_OUT) && (chan->fax->code == 0)) { cmd.driver = ccard->myid; cmd.command = ISDN_STAT_FAXIND; cmd.arg = chan->No; chan->fax->r_code = ISDN_TTY_FAX_PTS; ccard->interface.statcallb(&cmd); } if ((chan->fax->code > 1) && (chan->fax->code < 120)) chan->fax->code += 120; eicon_log(ccard, 8, "idi_fax: Ch%d: Hangup (code=%d)\n", chan->No, chan->fax->code); chan->fax->r_code = ISDN_TTY_FAX_HNG; cmd.driver = ccard->myid; cmd.command = ISDN_STAT_FAXIND; cmd.arg = chan->No; ccard->interface.statcallb(&cmd);}#endif /******** FAX ********/intidi_send_udata(eicon_card *card, eicon_chan *chan, int UReq, u_char *buffer, int len){ struct sk_buff *skb; struct sk_buff *skb2; eicon_REQ *reqbuf; eicon_chan_ptr *chan2; if ((chan->fsm_state == EICON_STATE_NULL) || (chan->fsm_state == EICON_STATE_LISTEN)) { eicon_log(card, 1, "idi_snd: Ch%d: send udata on state %d !\n", chan->No, chan->fsm_state); return -ENODEV; } eicon_log(card, 8, "idi_snd: Ch%d: udata 0x%x: %d %d %d %d\n", chan->No, UReq, buffer[0], buffer[1], buffer[2], buffer[3]); skb = alloc_skb(sizeof(eicon_REQ) + len + 1, GFP_ATOMIC); skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); if ((!skb) || (!skb2)) { eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in send_udata()\n", chan->No); if (skb) dev_kfree_skb(skb); if (skb2) dev_kfree_skb(skb2); return -ENOMEM; } chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr)); chan2->ptr = chan; reqbuf = (eicon_REQ *)skb_put(skb, 1 + len + sizeof(eicon_REQ)); reqbuf->Req = N_UDATA; reqbuf->ReqCh = chan->e.IndCh; reqbuf->ReqId = 1; reqbuf->XBuffer.length = len + 1; reqbuf->XBuffer.P[0] = UReq; memcpy(&reqbuf->XBuffer.P[1], buffer, len); reqbuf->Reference = 1; /* Net Entity */ skb_queue_tail(&chan->e.X, skb); skb_queue_tail(&card->sndq, skb2); eicon_schedule_tx(card); return (0);}voididi_audio_cmd(eicon_card *ccard, eicon_chan *chan, int cmd, u_char *value){ u_char buf[6]; struct enable_dtmf_s *dtmf_buf = (struct enable_dtmf_s *)buf; if ((!ccard) || (!chan)) return; memset(buf, 0, 6); switch(cmd) { case ISDN_AUDIO_SETDD: if (value[0]) { dtmf_buf->tone = (__u16) (value[1] * 5); dtmf_buf->gap = (__u16) (value[1] * 5); idi_send_udata(ccard, chan, DSP_UDATA_REQUEST_ENABLE_DTMF_RECEIVER, buf, 4); } else { idi_send_udata(ccard, chan, DSP_UDATA_REQUEST_DISABLE_DTMF_RECEIVER, buf, 0); } break; }}voididi_parse_udata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int len){ isdn_ctrl cmd; eicon_dsp_ind *p = (eicon_dsp_ind *) (&buffer[1]); static char *connmsg[] = {"", "V.21", "V.23", "V.22", "V.22bis", "V.32bis", "V.34", "V.8", "Bell 212A", "Bell 103", "V.29 Leased", "V.33 Leased", "V.90", "V.21 CH2", "V.27ter", "V.29", "V.33", "V.17"}; static u_char dtmf_code[] = { '1','4','7','*','2','5','8','0','3','6','9','#','A','B','C','D' }; if ((!ccard) || (!chan)) return; switch (buffer[0]) { case DSP_UDATA_INDICATION_SYNC: eicon_log(ccard, 16, "idi_ind: Ch%d: UDATA_SYNC time %d\n", chan->No, p->time); break; case DSP_UDATA_INDICATION_DCD_OFF: eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DCD_OFF time %d\n", chan->No, p->time); break; case DSP_UDATA_INDICATION_DCD_ON: if ((chan->l2prot == ISDN_PROTO_L2_MODEM) && (chan->fsm_state == EICON_STATE_WMCONN)) { chan->fsm_state = EICON_STATE_ACTIVE; cmd.driver = ccard->myid; cmd.command = ISDN_STAT_BCONN; cmd.arg = chan->No; sprintf(cmd.parm.num, "%d/%s", p->speed, connmsg[p->norm]); ccard->interface.statcallb(&cmd); } eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DCD_ON time %d\n", chan->No, p->time); eicon_log(ccard, 8, "idi_ind: Ch%d: %d %d %d %d\n", chan->No, p->norm, p->options, p->speed, p->delay); break; case DSP_UDATA_INDICATION_CTS_OFF: eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_CTS_OFF time %d\n", chan->No, p->time); break; case DSP_UDATA_INDICATION_CTS_ON: eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_CTS_ON time %d\n", chan->No, p->time); eicon_log(ccard, 8, "idi_ind: Ch%d: %d %d %d %d\n", chan->No, p->norm, p->options, p->speed, p->delay); break; case DSP_UDATA_INDICATION_DISCONNECT: eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DISCONNECT cause %d\n", chan->No, buffer[1]); break; case DSP_UDATA_INDICATION_DTMF_DIGITS_RECEIVED: eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DTMF_REC '%c'\n", chan->No, dtmf_code[buffer[1]]); cmd.driver = ccard->myid; cmd.command = ISDN_STAT_AUDIO; cmd.parm.num[0] = ISDN_AUDIO_DTMF; cmd.parm.num[1] = dtmf_code[buffer[1]]; cmd.arg = chan->No; ccard->interface.statcallb(&cmd); break; default: eicon_log(ccard, 8, "idi_ind: Ch%d: UNHANDLED UDATA Indication 0x%02x\n", chan->No, buffer[0]); }}voideicon_parse_trace(eicon_card *ccard, unsigned char *buffer, int len){ int i,j,n; int buflen = len * 3 + 30; char *p; struct trace_s { unsigned long time; unsigned short size; unsigned short code; unsigned char data[1]; } *q; if (!(p = kmalloc(buflen, GFP_ATOMIC))) { eicon_log(ccard, 1, "idi_err: Ch??: could not allocate trace buffer\n"); return; } memset(p, 0, buflen); q = (struct trace_s *)buffer; if (DebugVar & 512) { if ((q->code == 3) || (q->code == 4)) { n = (short) *(q->data); if (n) { j = sprintf(p, "DTRC:"); for (i = 0; i < n; i++) { j += sprintf(p + j, "%02x ", q->data[i+2]); } j += sprintf(p + j, "\n"); } } } else { j = sprintf(p, "XLOG: %lx %04x %04x ", q->time, q->size, q->code); for (i = 0; i < q->size; i++) { j += sprintf(p + j, "%02x ", q->data[i]); } j += sprintf(p + j, "\n"); } if (strlen(p)) eicon_putstatus(ccard, p); kfree(p);}voididi_handle_ind(eicon_card *ccard, struct sk_buff *skb){ int tmp; char tnum[64]; int dlev; int free_buff; ulong flags; struct sk_buff *skb2; eicon_IND *ind = (eicon_IND *)skb->data; eicon_chan *chan; idi_ind_message message; isdn_ctrl cmd; if (!ccard) { eicon_log(ccard, 1, "idi_err: Ch??: null card in handle_ind\n"); dev_kfree_skb(skb); return; } if ((chan = ccard->IdTable[ind->IndId]) == NULL) { eicon_log(ccard, 1, "idi_err: Ch??: null chan in handle_ind\n"); dev_kfree_skb(skb); return; } if ((ind->Ind != 8) && (ind->Ind != 0xc)) dlev = 144; else dlev = 128; eicon_log(ccard, dlev, "idi_hdl: Ch%d: Ind=%x Id=%x Ch=%x MInd=%x MLen=%x Len=%x\n", chan->No, ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length); free_buff = 1; /* Signal Layer */ if (chan->e.D3Id == ind->IndId) { idi_IndParse(ccard, chan, &message, ind->RBuffer.P, ind->RBuffer.length); switch(ind->Ind) { case HANGUP: eicon_log(ccard, 8, "idi_ind: Ch%d: Hangup\n", chan->No); while((skb2 = skb_dequeue(&chan->e.X))) { dev_kfree_skb(skb2); } spin_lock_irqsave(&eicon_lock, flags); chan->queued = 0; chan->pqueued = 0; chan->waitq = 0; chan->waitpq = 0; spin_unlock_irqrestore(&eicon_lock, flags); if (message.e_cau[0] & 0x7f) { cmd.driver = ccard->myid; cmd.arg = chan->No; sprintf(cmd.parm.num,"E%02x%02x", chan->cause[0]&0x7f, message.e_cau[0]&0x7f); cmd.command = ISDN_STAT_CAUSE; ccard->interface.statcallb(&cmd); } chan->cause[0] = 0; if (((chan->fsm_state == EICON_STATE_ACTIVE) || (chan->fsm_state == EICON_STATE_WMCONN)) || ((chan->l2prot == ISDN_PROTO_L2_FAX) && (chan->fsm_state == EICON_STATE_OBWAIT))) { chan->fsm_state = EICON_STATE_NULL; } else { if (chan->e.B2Id) idi_do_req(ccard, chan, REMOVE, 1); chan->statectrl &= ~WAITING_FOR_HANGUP; chan->statectrl &= ~IN_HOLD; if (chan->statectrl & HAVE_CONN_REQ) { eicon_log(ccard, 32, "idi_req: Ch%d: queueing delayed conn_req\n", chan->No); chan->statectrl &= ~HAVE_CONN_REQ; if ((chan->tskb1) && (chan->tskb2)) { skb_queue_tail(&chan->e.X, chan->tskb1); skb_queue_tail(&ccard->sndq, chan->tskb2); eicon_schedule_tx(ccard); } chan->tskb1 = NULL; chan->tskb2 = NULL; } else { chan->fsm_state = EICON_STATE_NULL; cmd.driver = ccard->myid; cmd.arg = chan->No; cmd.command = ISDN_STAT_DHUP; ccard->interface.statcallb(&cmd); eicon_idi_listen_req(ccard, chan);#ifdef CONFIG_ISDN_TTY_FAX chan->fax = 0;#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -