📄 l3dss1.c
字号:
} return p + 3;}static u_charEncodeSyncParams(u_char si2, u_char ai){ switch (si2) { case 0: return ai + 2; // 1200 bit/s case 1: return ai + 24; // 1200/75 bit/s case 2: return ai + 23; // 75/1200 bit/s case 3: return ai + 3; // 2400 bit/s case 4: return ai + 5; // 4800 bit/s case 5: return ai + 8; // 9600 bit/s case 6: return ai + 9; // 14400 bit/s case 7: return ai + 11; // 19200 bit/s case 8: return ai + 14; // 48000 bit/s case 9: return ai + 15; // 56000 bit/s case 15: return ai + 40; // negotiate bit/s default: break; } return ai;}static u_charDecodeASyncParams(u_char si2, u_char * p){ u_char info; switch (p[5]) { case 66: // 1200 bit/s break; // si2 don't change case 88: // 1200/75 bit/s si2 += 1; break; case 87: // 75/1200 bit/s si2 += 2; break; case 67: // 2400 bit/s si2 += 3; break; case 69: // 4800 bit/s si2 += 4; break; case 72: // 9600 bit/s si2 += 5; break; case 73: // 14400 bit/s si2 += 6; break; case 75: // 19200 bit/s si2 += 7; break; } info = p[7] & 0x7f; if ((info & 16) && (!(info & 8))) // 7 data bits si2 += 32; // else 8 data bits if ((info & 96) == 96) // 2 stop bits si2 += 16; // else 1 stop bit if ((info & 2) && (!(info & 1))) // even parity si2 += 8; // else no parity return si2;}static u_charDecodeSyncParams(u_char si2, u_char info){ info &= 0x7f; switch (info) { case 40: // bit/s negotiation failed ai := 165 not 175! return si2 + 15; case 15: // 56000 bit/s failed, ai := 0 not 169 ! return si2 + 9; case 14: // 48000 bit/s return si2 + 8; case 11: // 19200 bit/s return si2 + 7; case 9: // 14400 bit/s return si2 + 6; case 8: // 9600 bit/s return si2 + 5; case 5: // 4800 bit/s return si2 + 4; case 3: // 2400 bit/s return si2 + 3; case 23: // 75/1200 bit/s return si2 + 2; case 24: // 1200/75 bit/s return si2 + 1; default: // 1200 bit/s return si2; }}static u_charDecodeSI2(struct sk_buff *skb){ u_char *p; //, *pend=skb->data + skb->len; if ((p = findie(skb->data, skb->len, 0x7c, 0))) { switch (p[4] & 0x0f) { case 0x01: if (p[1] == 0x04) // sync. Bitratenadaption return DecodeSyncParams(160, p[5]); // V.110/X.30 else if (p[1] == 0x06) // async. Bitratenadaption return DecodeASyncParams(192, p); // V.110/X.30 break; case 0x08: // if (p[5] == 0x02) // sync. Bitratenadaption if (p[1] > 3) return DecodeSyncParams(176, p[5]); // V.120 break; } } return 0;}#endifstatic voidl3dss1_setup_req(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb; u_char tmp[128]; u_char *p = tmp; u_char channel = 0; u_char send_keypad; u_char screen = 0x80; u_char *teln; u_char *msn; u_char *sub; u_char *sp; int l; MsgHead(p, pc->callref, MT_SETUP); teln = pc->para.setup.phone;#ifndef CONFIG_HISAX_NO_KEYPAD send_keypad = (strchr(teln,'*') || strchr(teln,'#')) ? 1 : 0; #else send_keypad = 0;#endif#ifndef CONFIG_HISAX_NO_SENDCOMPLETE if (!send_keypad) *p++ = 0xa1; /* complete indicator */#endif /* * Set Bearer Capability, Map info from 1TR6-convention to EDSS1 */ switch (pc->para.setup.si1) { case 1: /* Telephony */ *p++ = IE_BEARER; *p++ = 0x3; /* Length */ *p++ = 0x90; /* Coding Std. CCITT, 3.1 kHz audio */ *p++ = 0x90; /* Circuit-Mode 64kbps */ *p++ = 0xa3; /* A-Law Audio */ break; case 5: /* Datatransmission 64k, BTX */ case 7: /* Datatransmission 64k */ default: *p++ = IE_BEARER; *p++ = 0x2; /* Length */ *p++ = 0x88; /* Coding Std. CCITT, unrestr. dig. Inform. */ *p++ = 0x90; /* Circuit-Mode 64kbps */ break; } if (send_keypad) { *p++ = IE_KEYPAD; *p++ = strlen(teln); while (*teln) *p++ = (*teln++) & 0x7F; } /* * What about info2? Mapping to High-Layer-Compatibility? */ if ((*teln) && (!send_keypad)) { /* parse number for special things */ if (!isdigit(*teln)) { switch (0x5f & *teln) { case 'C': channel = 0x08; case 'P': channel |= 0x80; teln++; if (*teln == '1') channel |= 0x01; else channel |= 0x02; break; case 'R': screen = 0xA0; break; case 'D': screen = 0x80; break; default: if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "Wrong MSN Code"); break; } teln++; } } if (channel) { *p++ = IE_CHANNEL_ID; *p++ = 1; *p++ = channel; } msn = pc->para.setup.eazmsn; sub = NULL; sp = msn; while (*sp) { if ('.' == *sp) { sub = sp; *sp = 0; } else sp++; } if (*msn) { *p++ = IE_CALLING_PN; *p++ = strlen(msn) + (screen ? 2 : 1); /* Classify as AnyPref. */ if (screen) { *p++ = 0x01; /* Ext = '0'B, Type = '000'B, Plan = '0001'B. */ *p++ = screen; } else *p++ = 0x81; /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */ while (*msn) *p++ = *msn++ & 0x7f; } if (sub) { *sub++ = '.'; *p++ = IE_CALLING_SUB; *p++ = strlen(sub) + 2; *p++ = 0x80; /* NSAP coded */ *p++ = 0x50; /* local IDI format */ while (*sub) *p++ = *sub++ & 0x7f; } sub = NULL; sp = teln; while (*sp) { if ('.' == *sp) { sub = sp; *sp = 0; } else sp++; } if (!send_keypad) { *p++ = IE_CALLED_PN; *p++ = strlen(teln) + 1; /* Classify as AnyPref. */ *p++ = 0x81; /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */ while (*teln) *p++ = *teln++ & 0x7f; if (sub) { *sub++ = '.'; *p++ = IE_CALLED_SUB; *p++ = strlen(sub) + 2; *p++ = 0x80; /* NSAP coded */ *p++ = 0x50; /* local IDI format */ while (*sub) *p++ = *sub++ & 0x7f; } }#if EXT_BEARER_CAPS if ((pc->para.setup.si2 >= 160) && (pc->para.setup.si2 <= 175)) { // sync. Bitratenadaption, V.110/X.30 *p++ = IE_LLC; *p++ = 0x04; *p++ = 0x88; *p++ = 0x90; *p++ = 0x21; *p++ = EncodeSyncParams(pc->para.setup.si2 - 160, 0x80); } else if ((pc->para.setup.si2 >= 176) && (pc->para.setup.si2 <= 191)) { // sync. Bitratenadaption, V.120 *p++ = IE_LLC; *p++ = 0x05; *p++ = 0x88; *p++ = 0x90; *p++ = 0x28; *p++ = EncodeSyncParams(pc->para.setup.si2 - 176, 0); *p++ = 0x82; } else if (pc->para.setup.si2 >= 192) { // async. Bitratenadaption, V.110/X.30 *p++ = IE_LLC; *p++ = 0x06; *p++ = 0x88; *p++ = 0x90; *p++ = 0x21; p = EncodeASyncParams(p, pc->para.setup.si2 - 192);#ifndef CONFIG_HISAX_NO_LLC } else { switch (pc->para.setup.si1) { case 1: /* Telephony */ *p++ = IE_LLC; *p++ = 0x3; /* Length */ *p++ = 0x90; /* Coding Std. CCITT, 3.1 kHz audio */ *p++ = 0x90; /* Circuit-Mode 64kbps */ *p++ = 0xa3; /* A-Law Audio */ break; case 5: /* Datatransmission 64k, BTX */ case 7: /* Datatransmission 64k */ default: *p++ = IE_LLC; *p++ = 0x2; /* Length */ *p++ = 0x88; /* Coding Std. CCITT, unrestr. dig. Inform. */ *p++ = 0x90; /* Circuit-Mode 64kbps */ break; }#endif }#endif l = p - tmp; if (!(skb = l3_alloc_skb(l))) return; memcpy(skb_put(skb, l), tmp, l); L3DelTimer(&pc->timer); L3AddTimer(&pc->timer, T303, CC_T303); newl3state(pc, 1); l3_msg(pc->st, DL_DATA | REQUEST, skb);}static voidl3dss1_call_proc(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb = arg; int id, ret; if ((id = l3dss1_get_channel_id(pc, skb)) >= 0) { if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "setup answer with wrong chid %x", id); pc->para.cause = 100; l3dss1_status_send(pc, pr, NULL); return; } pc->para.bchannel = id; } else if (1 == pc->state) { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "setup answer wrong chid (ret %d)", id); if (id == -1) pc->para.cause = 96; else pc->para.cause = 100; l3dss1_status_send(pc, pr, NULL); return; } /* Now we are on none mandatory IEs */ ret = check_infoelements(pc, skb, ie_CALL_PROCEEDING); if (ERR_IE_COMPREHENSION == ret) { l3dss1_std_ie_err(pc, ret); return; } L3DelTimer(&pc->timer); newl3state(pc, 3); L3AddTimer(&pc->timer, T310, CC_T310); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3dss1_std_ie_err(pc, ret); L3L4(pc->st, CC_PROCEEDING | INDICATION, pc);}static voidl3dss1_setup_ack(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb = arg; int id, ret; if ((id = l3dss1_get_channel_id(pc, skb)) >= 0) { if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "setup answer with wrong chid %x", id); pc->para.cause = 100; l3dss1_status_send(pc, pr, NULL); return; } pc->para.bchannel = id; } else { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "setup answer wrong chid (ret %d)", id); if (id == -1) pc->para.cause = 96; else pc->para.cause = 100; l3dss1_status_send(pc, pr, NULL); return; } /* Now we are on none mandatory IEs */ ret = check_infoelements(pc, skb, ie_SETUP_ACKNOWLEDGE); if (ERR_IE_COMPREHENSION == ret) { l3dss1_std_ie_err(pc, ret); return; } L3DelTimer(&pc->timer); newl3state(pc, 2); L3AddTimer(&pc->timer, T304, CC_T304); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3dss1_std_ie_err(pc, ret); L3L4(pc->st, CC_MORE_INFO | INDICATION, pc);}static voidl3dss1_disconnect(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb = arg; u_char *p; int ret; u_char cause = 0; StopAllL3Timer(pc); if ((ret = l3dss1_get_cause(pc, skb))) { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "DISC get_cause ret(%d)", ret); if (ret < 0) cause = 96; else if (ret > 0) cause = 100; } if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) l3dss1_parse_facility(pc->st, pc, pc->callref, p); ret = check_infoelements(pc, skb, ie_DISCONNECT); if (ERR_IE_COMPREHENSION == ret) cause = 96; else if ((!cause) && (ERR_IE_UNRECOGNIZED == ret)) cause = 99; ret = pc->state; newl3state(pc, 12); if (cause) newl3state(pc, 19); if (11 != ret) L3L4(pc->st, CC_DISCONNECT | INDICATION, pc); else if (!cause) l3dss1_release_req(pc, pr, NULL); if (cause) { l3dss1_message_cause(pc, MT_RELEASE, cause); L3AddTimer(&pc->timer, T308, CC_T308_1); }}static voidl3dss1_connect(struct l3_process *pc, u_char pr, void *arg){ struct sk_buff *skb = arg; int ret; ret = check_infoelements(pc, skb, ie_CONNECT); if (ERR_IE_COMPREHENSION == ret) { l3dss1_std_ie_err(pc, ret); return; } L3DelTimer(&pc->timer); /* T310 */ newl3state(pc, 10); pc->para.chargeinfo = 0; /* here should inserted COLP handling KKe */ if (ret) l3dss1_std_ie_err(pc, ret); L3L4(pc->st, CC_SETUP | CONFIRM, pc);}static voidl3dss1_alerting(struct l3_process *pc, u_char pr, void *arg){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -