📄 eicon_idi.c
字号:
if (chan->fax->r_compression != 0) { /* telling fake compression in second DIS message */ chan->fax->r_compression = 0; cmd.driver = ccard->myid; cmd.command = ISDN_STAT_FAXIND; cmd.arg = chan->No; chan->fax->r_code = ISDN_TTY_FAX_DIS; ccard->interface.statcallb(&cmd); } cmd.driver = ccard->myid; cmd.command = ISDN_STAT_FAXIND; cmd.arg = chan->No; chan->fax->r_code = ISDN_TTY_FAX_SENT; /* OK message */ ccard->interface.statcallb(&cmd); } else if (chan->fax->phase == ISDN_FAX_PHASE_D) { if ((chan->fax->code == EDATA_T30_MCF) && (chan->fax->fet != 2)) { 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); } switch(chan->fax->fet) { case 0: /* new page */ /* stay in phase D , wait on cmd +FDT */ break; case 1: /* new document */ /* link-level switch to phase B */ break; case 2: /* session end */ default: /* send_edata produces error on some */ /* fax-machines here, so we don't */ /* idi_send_edata(ccard, chan); */ break; } } } if (chan->fax->direction == ISDN_TTY_FAX_CONN_IN) { idi_parse_edata(ccard, chan, buffer, len); if ((chan->fax->code == EDATA_T30_DCS) && (chan->fax->phase == ISDN_FAX_PHASE_A)) { idi_reset_fax_stat(chan); cmd.driver = ccard->myid; cmd.command = ISDN_STAT_BCONN; cmd.arg = chan->No; strcpy(cmd.parm.num, ""); ccard->interface.statcallb(&cmd); cmd.driver = ccard->myid; cmd.command = ISDN_STAT_FAXIND; cmd.arg = chan->No; chan->fax->r_code = ISDN_TTY_FAX_FCON_I; ccard->interface.statcallb(&cmd); } else if ((chan->fax->code == EDATA_T30_TRAIN_OK) && (chan->fax->phase == ISDN_FAX_PHASE_A)) { cmd.driver = ccard->myid; cmd.command = ISDN_STAT_FAXIND; cmd.arg = chan->No; chan->fax->r_code = ISDN_TTY_FAX_RID; ccard->interface.statcallb(&cmd); cmd.driver = ccard->myid; cmd.command = ISDN_STAT_FAXIND; cmd.arg = chan->No; chan->fax->r_code = ISDN_TTY_FAX_TRAIN_OK; ccard->interface.statcallb(&cmd); } else if ((chan->fax->code == EDATA_T30_TRAIN_OK) && (chan->fax->phase == ISDN_FAX_PHASE_B)) { cmd.driver = ccard->myid; cmd.command = ISDN_STAT_FAXIND; cmd.arg = chan->No; chan->fax->r_code = ISDN_TTY_FAX_TRAIN_OK; ccard->interface.statcallb(&cmd); } else if (chan->fax->phase == ISDN_FAX_PHASE_C) { switch(chan->fax->code) { case EDATA_T30_TRAIN_OK: idi_send_edata(ccard, chan); break; case EDATA_T30_MPS: chan->fax->fet = 0; idi_edata_rcveop(ccard, chan); break; case EDATA_T30_EOM: chan->fax->fet = 1; idi_edata_rcveop(ccard, chan); break; case EDATA_T30_EOP: chan->fax->fet = 2; idi_edata_rcveop(ccard, chan); break; } } }}voidfax_put_rcv(eicon_card *ccard, eicon_chan *chan, u_char *Data, int len){ struct sk_buff *skb; skb = alloc_skb(len + MAX_HEADER_LEN, GFP_ATOMIC); if (!skb) { eicon_log(ccard, 1, "idi_err: Ch%d: alloc_skb failed in fax_put_rcv()\n", chan->No); return; } skb_reserve(skb, MAX_HEADER_LEN); memcpy(skb_put(skb, len), Data, len); ccard->interface.rcvcallb_skb(ccard->myid, chan->No, skb);}voididi_faxdata_rcv(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb){ eicon_OBJBUFFER InBuf; eicon_OBJBUFFER LineBuf; unsigned int Length = 0; unsigned int aLength = 0; unsigned int ObjectSize = 0; unsigned int ObjHeadLen = 0; unsigned int ObjDataLen = 0; __u8 Recordtype; __u8 PageHeaderLen; __u8 Event; eicon_sff_pagehead *ob_page; __u16 Cl2Eol = 0x8000;# define EVENT_NONE 0# define EVENT_NEEDDATA 1 if (!chan->fax) { eicon_log(ccard, 1, "idi_fax: rcvdata with NULL fax struct, ERROR\n"); return; } if (chan->fax->direction == ISDN_TTY_FAX_CONN_IN) { InBuf.Data = skb->data; InBuf.Size = skb->len; InBuf.Len = 0; InBuf.Next = InBuf.Data; LineBuf.Data = chan->fax2.abLine; LineBuf.Size = sizeof(chan->fax2.abLine); LineBuf.Len = chan->fax2.LineLen; LineBuf.Next = LineBuf.Data + LineBuf.Len; Event = EVENT_NONE; while (Event == EVENT_NONE) { switch(chan->fax2.NextObject) { case FAX_OBJECT_DOCU: Length = LineBuf.Len + (InBuf.Size - InBuf.Len); if (Length < sizeof(eicon_sff_dochead)) { Event = EVENT_NEEDDATA; break; } ObjectSize = sizeof(eicon_sff_dochead); Length = ObjectSize; if (LineBuf.Len < Length) { Length -= LineBuf.Len; LineBuf.Len = 0; LineBuf.Next = LineBuf.Data; InBuf.Len += Length; InBuf.Next += Length; } else { LineBuf.Len -= Length; LineBuf.Next = LineBuf.Data + LineBuf.Len; memmove(LineBuf.Data, LineBuf.Data + Length, LineBuf.Len); } chan->fax2.PrevObject = FAX_OBJECT_DOCU; chan->fax2.NextObject = FAX_OBJECT_PAGE; break; case FAX_OBJECT_PAGE: Length = LineBuf.Len + (InBuf.Size - InBuf.Len); if (Length < 2) { Event = EVENT_NEEDDATA; break; } if (LineBuf.Len == 0) { *LineBuf.Next++ = *InBuf.Next++; LineBuf.Len++; InBuf.Len++; } if (LineBuf.Len == 1) { *LineBuf.Next++ = *InBuf.Next++; LineBuf.Len++; InBuf.Len++; } PageHeaderLen = *(LineBuf.Data + 1); ObjectSize = (PageHeaderLen == 0) ? 2 : sizeof(eicon_sff_pagehead); if (Length < ObjectSize) { Event = EVENT_NEEDDATA; break; } Length = ObjectSize; /* extract page dimensions */ if (LineBuf.Len < Length) { aLength = Length - LineBuf.Len; memcpy(LineBuf.Next, InBuf.Next, aLength); LineBuf.Next += aLength; InBuf.Next += aLength; LineBuf.Len += aLength; InBuf.Len += aLength; } if (Length > 2) { ob_page = (eicon_sff_pagehead *)LineBuf.Data; switch(ob_page->linelength) { case 2048: chan->fax->r_width = 1; break; case 2432: chan->fax->r_width = 2; break; case 1216: chan->fax->r_width = 3; break; case 864: chan->fax->r_width = 4; break; case 1728: default: chan->fax->r_width = 0; } switch(ob_page->pagelength) { case 1143: case 2287: chan->fax->r_length = 0; break; case 1401: case 2802: chan->fax->r_length = 1; break; default: chan->fax->r_length = 2; } eicon_log(ccard, 128, "rSFF-Head: linelength = %d\n", ob_page->linelength); eicon_log(ccard, 128, "rSFF-Head: pagelength = %d\n", ob_page->pagelength); } LineBuf.Len -= Length; LineBuf.Next = LineBuf.Data + LineBuf.Len; memmove(LineBuf.Data, LineBuf.Data + Length, LineBuf.Len); chan->fax2.PrevObject = FAX_OBJECT_PAGE; chan->fax2.NextObject = FAX_OBJECT_LINE; break; case FAX_OBJECT_LINE: Length = LineBuf.Len + (InBuf.Size - InBuf.Len); if (Length < 1) { Event = EVENT_NEEDDATA; break; } if (LineBuf.Len == 0) { *LineBuf.Next++ = *InBuf.Next++; LineBuf.Len++; InBuf.Len++; } Recordtype = *LineBuf.Data; if (Recordtype == 0) { /* recordtype pixel row (2 byte length) */ ObjHeadLen = 3; if (Length < ObjHeadLen) { Event = EVENT_NEEDDATA; break; } while (LineBuf.Len < ObjHeadLen) { *LineBuf.Next++ = *InBuf.Next++; LineBuf.Len++; InBuf.Len++; } ObjDataLen = *((__u16*) (LineBuf.Data + 1)); ObjectSize = ObjHeadLen + ObjDataLen; if (Length < ObjectSize) { Event = EVENT_NEEDDATA; break; } } else if ((Recordtype >= 1) && (Recordtype <= 216)) { /* recordtype pixel row (1 byte length) */ ObjHeadLen = 1; ObjDataLen = Recordtype; ObjectSize = ObjHeadLen + ObjDataLen; if (Length < ObjectSize) { Event = EVENT_NEEDDATA; break; } } else if ((Recordtype >= 217) && (Recordtype <= 253)) { /* recordtype empty lines */ ObjHeadLen = 1; ObjDataLen = 0; ObjectSize = ObjHeadLen + ObjDataLen; LineBuf.Len--; LineBuf.Next = LineBuf.Data + LineBuf.Len; memmove(LineBuf.Data, LineBuf.Data + 1, LineBuf.Len); break; } else if (Recordtype == 254) { /* recordtype page header */ chan->fax2.PrevObject = FAX_OBJECT_LINE; chan->fax2.NextObject = FAX_OBJECT_PAGE; break; } else { /* recordtype user information */ ObjHeadLen = 2; if (Length < ObjHeadLen) { Event = EVENT_NEEDDATA; break; } while (LineBuf.Len < ObjHeadLen) { *LineBuf.Next++ = *InBuf.Next++; LineBuf.Len++; InBuf.Len++; } ObjDataLen = *(LineBuf.Data + 1); ObjectSize = ObjHeadLen + ObjDataLen; if (ObjDataLen == 0) { /* illegal line coding */ LineBuf.Len -= ObjHeadLen; LineBuf.Next = LineBuf.Data + LineBuf.Len; memmove(LineBuf.Data, LineBuf.Data + ObjHeadLen, LineBuf.Len); break; } else { /* user information */ if (Length < ObjectSize) { Event = EVENT_NEEDDATA; break; } Length = ObjectSize; if (LineBuf.Len < Length) { Length -= LineBuf.Len; LineBuf.Len = 0; LineBuf.Next = LineBuf.Data; InBuf.Len += Length; InBuf.Next += Length; } else { LineBuf.Len -= Length; LineBuf.Next = LineBuf.Data + LineBuf.Len; memmove(LineBuf.Data, LineBuf.Data + Length, LineBuf.Len); } } break; } Length = ObjectSize; if (LineBuf.Len > ObjHeadLen) { fax_put_rcv(ccard, chan, LineBuf.Data + ObjHeadLen, (LineBuf.Len - ObjHeadLen)); } Length -= LineBuf.Len; LineBuf.Len = 0; LineBuf.Next = LineBuf.Data; if (Length > 0) { fax_put_rcv(ccard, chan, InBuf.Next, Length); InBuf.Len += Length; InBuf.Next += Length; } fax_put_rcv(ccard, chan, (__u8 *)&Cl2Eol, sizeof(Cl2Eol)); break; } /* end of switch (chan->fax2.NextObject) */ } /* end of while (Event==EVENT_NONE) */ if (InBuf.Len < InBuf.Size) { Length = InBuf.Size - InBuf.Len; if ((LineBuf.Len + Length) > LineBuf.Size) { eicon_log(ccard, 1, "idi_fax: Ch%d: %d bytes dropping, small buffer\n", chan->No, Length); } else { memcpy(LineBuf.Next, InBuf.Next, Length); LineBuf.Len += Length; } } chan->fax2.LineLen = LineBuf.Len; } else { /* CONN_OUT */ /* On CONN_OUT we do not need incoming data, drop it */ /* maybe later for polling */ }# undef EVENT_NONE# undef EVENT_NEEDDATA return;}intidi_fax_send_outbuf(eicon_card *ccard, eicon_chan *chan, eicon_OBJBUFFER *OutBuf){ struct sk_buff *skb; skb = alloc_skb(OutBuf->Len, GFP_ATOMIC); if (!skb) { eicon_log(ccard, 1, "idi_err: Ch%d: alloc_skb failed in fax_send_outbuf()\n", chan->No); return(-1); } memcpy(skb_put(skb, OutBuf->Len), OutBuf->Data, OutBuf->Len); OutBuf->Len = 0; OutBuf->Next = OutBuf->Data; return(idi_send_data(ccard, chan, 0, skb, 1, 0));}intidi_faxdata_send(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb){ isdn_ctrl cmd; eicon_OBJBUFFER InBuf; __u8 InData; __u8 InMask; eicon_OBJBUFFER OutBuf; eicon_OBJBUFFER LineBuf; __u32 LineData; unsigned int LineDataLen; __u8 Byte; __u8 Event; int ret = 1;# define EVENT_NONE 0# define EVENT_EOD 1# define EVENT_EOL 2# define EVENT_EOP 3 if ((!ccard) || (!chan)) return -1; if (!chan->fax) { eicon_log(ccard, 1, "idi_fax: senddata with NULL fax struct, ERROR\n"); return -1; } if (chan->fax->direction == ISDN_TTY_FAX_CONN_IN) { /* Simply ignore any data written in data mode when receiving a fax. */ /* This is not completely correct because only XON's should come here. */ dev_kfree_skb(skb); return 1; } if (chan->fax->phase != ISDN_FAX_PHASE_C) { dev_kfree_skb(skb); return 1; } if (chan->queued + skb->len > 1200) return 0; if (chan->pqueued > 1) return 0; InBuf.Data = skb->data; InBuf.Size = skb->len; InBuf.Len = 0; InBuf.Next = InBuf.Data; InData = 0; InMask = 0; LineBuf.Data = chan->fax2.abLine; LineBuf.Size = sizeof(chan->fax2.abLine); LineBuf.Len = chan->fax2.LineLen; LineBuf.Next = LineBuf.Data + LineBuf.Len; LineData = chan->fax2.LineData; LineDataLen = chan->fax2.LineDataLen; OutBuf.Data = chan->fax2.abFrame; OutBuf.Size = sizeof(chan->fax2.abFrame); OutBuf.Len = 0; OutBuf.Next = OutBuf.Data; Event = EVENT_NONE; chan->fax2.Eop = 0; for (;;) { for (;;) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -