--- linux/drivers/isdn/isdn_tty.c 2005-02-03 02:37:38.000000000 +0100 +++ linux/drivers/isdn/isdn_tty.c 2005-02-05 06:56:02.000000000 +0100 @@ -2,6 +2,7 @@ * * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel). * + * 08/2002 Addition of +I commands by Birger Harzenetter (wimpy@yeti.dk) * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg * @@ -189,7 +190,7 @@ info = &dev->mdm.info[midx]; #ifdef CONFIG_ISDN_AUDIO ifmt = 1; - + if ((info->vonline) && (!info->emu.vpar[4])) isdn_audio_calc_dtmf(info, skb->data, skb->len, ifmt); if ((info->vonline & 1) && (info->emu.vpar[1])) @@ -468,7 +469,7 @@ return; if ((info->emu.mdmreg[REG_CTS] & BIT_CTS) != 0) info->msr &= ~UART_MSR_CTS; - info->lsr &= ~UART_LSR_TEMT; + info->lsr &= ~UART_LSR_TEMT; /* info->xmit_count is modified here and in isdn_tty_write(). * So we return here if isdn_tty_write() is in the * critical section. @@ -597,15 +598,15 @@ #ifdef CONFIG_ISDN_AUDIO if (si == 1) { switch(l2) { - case ISDN_PROTO_L2_MODEM: + case ISDN_PROTO_L2_MODEM: usg = ISDN_USAGE_MODEM; break; #ifdef CONFIG_ISDN_TTY_FAX - case ISDN_PROTO_L2_FAX: + case ISDN_PROTO_L2_FAX: usg = ISDN_USAGE_FAX; break; #endif - case ISDN_PROTO_L2_TRANS: + case ISDN_PROTO_L2_TRANS: default: usg = ISDN_USAGE_VOICE; break; @@ -636,7 +637,7 @@ } usg = isdn_calc_usage(si, l2); #ifdef CONFIG_ISDN_AUDIO - if ((si == 1) && + if ((si == 1) && (l2 != ISDN_PROTO_L2_MODEM) #ifdef CONFIG_ISDN_TTY_FAX && (l2 != ISDN_PROTO_L2_FAX) @@ -783,7 +784,7 @@ } /* - * Begin of a CAPI like interface, currently used only for + * Begin of a CAPI like interface, currently used only for * supplementary service (CAPI 2.0 part III) */ #include "avmb1/capicmd.h" /* this should be moved in a common place */ @@ -799,7 +800,7 @@ isdn_tty_suspend(char *id, modem_info * info, atemu * m) { isdn_ctrl cmd; - + int l; if (!info) @@ -855,7 +856,7 @@ } usg = isdn_calc_usage(si, l2); #ifdef CONFIG_ISDN_AUDIO - if ((si == 1) && + if ((si == 1) && (l2 != ISDN_PROTO_L2_MODEM) #ifdef CONFIG_ISDN_TTY_FAX && (l2 != ISDN_PROTO_L2_FAX) @@ -949,7 +950,7 @@ } usg = isdn_calc_usage(si, l2); #ifdef CONFIG_ISDN_AUDIO - if ((si == 1) && + if ((si == 1) && (l2 != ISDN_PROTO_L2_MODEM) #ifdef CONFIG_ISDN_TTY_FAX && (l2 != ISDN_PROTO_L2_FAX) @@ -1234,7 +1235,7 @@ } else if (TTY_IS_FCLASS1(info)) { int cc = isdn_tty_handleDLEdown(info, m, c); - + if (info->vonline & 4) { /* ETX seen */ isdn_ctrl c; @@ -1922,6 +1923,10 @@ m->profile[23] = 0; m->pmsn[0] = '\0'; m->plmsn[0] = '\0'; + strcpy(m->iprefix,"00"); + strcpy(m->nprefix,"0" ); + strcpy(m->prnum ,"0" ); + strcpy(m->nanum ,"0" ); } #ifdef CONFIG_ISDN_AUDIO @@ -2226,8 +2231,10 @@ info->drv_index = idx; dev->m_idx[idx] = info->line; dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE; - dev->usage[idx] |= isdn_calc_usage(si1, info->emu.mdmreg[REG_L2PROT]); + dev->usage[idx] |= isdn_calc_usage(si1, info->emu.mdmreg[REG_L2PROT]); strcpy(dev->num[idx], nr); + dev->numtyp[idx] = setup->plan; + dev->screen[idx] = setup->screen; strcpy(info->emu.cpn, eaz); info->emu.mdmreg[REG_SI1I] = si2bit[si1]; info->emu.mdmreg[REG_PLAN] = setup->plan; @@ -2270,8 +2277,8 @@ info->emu.charge = (unsigned) simple_strtoul(c->parm.num, &e, 10); if (e == (char *)c->parm.num) info->emu.charge = 0; - - break; + + break; case ISDN_STAT_BSENT: #ifdef ISDN_TTY_STAT_DEBUG printk(KERN_DEBUG "tty_STAT_BSENT ttyI%d\n", info->line); @@ -2298,7 +2305,7 @@ printk(KERN_DEBUG "tty_STAT_DISPLAY ttyI%d\n", info->line); #endif /* Signal display to tty-device */ - if ((info->emu.mdmreg[REG_DISPLAY] & BIT_DISPLAY) && + if ((info->emu.mdmreg[REG_DISPLAY] & BIT_DISPLAY) && !(info->emu.mdmreg[REG_RESPNUM] & BIT_RESPNUM)) { isdn_tty_at_cout("\r\n", info); isdn_tty_at_cout("DISPLAY: ", info); @@ -2322,9 +2329,9 @@ printk(KERN_DEBUG "tty_STAT_DHUP ttyI%d\n", info->line); #endif if (TTY_IS_ACTIVE(info)) { - if (info->dialing == 1) + if (info->dialing == 1) isdn_tty_modem_result(RESULT_BUSY, info); - if (info->dialing > 1) + if (info->dialing > 1) isdn_tty_modem_result(RESULT_NO_CARRIER, info); info->dialing = 0; #ifdef ISDN_DEBUG_MODEM_HUP @@ -2416,7 +2423,7 @@ #ifdef CONFIG_ISDN_TTY_FAX case ISDN_STAT_FAXIND: if (TTY_IS_ACTIVE(info)) { - isdn_tty_fax_command(info, c); + isdn_tty_fax_command(info, c); } break; #endif @@ -2612,6 +2619,24 @@ */ static void +isdn_tty_modem_result_prCGPN(char *num, unsigned char typ, unsigned char pi, modem_info * info) +{ + atemu *m = &info->emu; + + typ=(typ>>4)&7; + pi=(pi>>5)&3; + isdn_tty_at_cout("\r\nCALLER NUMBER: ", info); + if (pi==1) isdn_tty_at_cout(m->prnum, info); + else if (pi==2) isdn_tty_at_cout(m->nanum, info); + else + { + if (typ==1 && m->iprefix[0]) isdn_tty_at_cout(m->iprefix, info); + if (typ==2 && m->nprefix[0]) isdn_tty_at_cout(m->nprefix, info); + isdn_tty_at_cout(num, info); + } +} + +static void isdn_tty_modem_result(int code, modem_info * info) { atemu *m = &info->emu; @@ -2695,8 +2720,8 @@ return; /* print CID, _before_ _every_ ring */ if (!(m->mdmreg[REG_CIDONCE] & BIT_CIDONCE)) { - isdn_tty_at_cout("\r\nCALLER NUMBER: ", info); - isdn_tty_at_cout(dev->num[info->drv_index], info); + isdn_tty_modem_result_prCGPN(dev->num[info->drv_index], + dev->numtyp[info->drv_index], dev->screen[info->drv_index], info); if (m->mdmreg[REG_CDN] & BIT_CDN) { isdn_tty_at_cout("\r\nCALLED NUMBER: ", info); isdn_tty_at_cout(info->emu.cpn, info); @@ -2723,9 +2748,8 @@ /* Print CID only once, _after_ 1st RING */ if ((m->mdmreg[REG_CIDONCE] & BIT_CIDONCE) && (m->mdmreg[REG_RINGCNT] == 1)) { - isdn_tty_at_cout("\r\n", info); - isdn_tty_at_cout("CALLER NUMBER: ", info); - isdn_tty_at_cout(dev->num[info->drv_index], info); + isdn_tty_modem_result_prCGPN(dev->num[info->drv_index], + dev->numtyp[info->drv_index], dev->screen[info->drv_index], info); if (m->mdmreg[REG_CDN] & BIT_CDN) { isdn_tty_at_cout("\r\nCALLED NUMBER: ", info); isdn_tty_at_cout(info->emu.cpn, info); @@ -2824,22 +2848,65 @@ * Get phone-number from modem-commandbuffer */ static void -isdn_tty_getdial(char *p, char *q,int cnt) +isdn_tty_getdial(char *p, char *q, int max) { - int first = 1; + int first = 0; int limit = ISDN_MSNLEN - 1; /* MUST match the size of interface var to avoid buffer overflow */ + char *oq = q; - while (strchr(" 0123456789,#.*WPTS-", *p) && *p && --cnt>0) { - if ((*p >= '0' && *p <= '9') || ((*p == 'S') && first) || - (*p == '*') || (*p == '#')) { - *q++ = *p; - limit--; + max--; + while (*p && (max > 0)) { + switch (*p) { + case '0':// normal digits + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '*': + case '#': + first=first | 31; + if (limit-->0) *q++=*p; + else *oq=0; + break; + // prefixes - as first char only + case '+':// no further prefixes + if (first & 1) *oq=0; + else {*q++=*p;limit--;} + first=15; + break; + case 'S':// no other prefixes + if (first) *oq=0; + else {*q++=*p;limit--;} + first=15; + break; + case 'D':// only one of these + case 'R':if (first & 2) *oq=0; + else {*q++=*p;limit--;} + first=first | 2; + break; + case '.':// subadress - only once! + if (limit-->0) *q++=*p; + else *oq=0; + if (first!=31) *oq=0; + first=63; + break; + case ' ':// ignore dialling method prefixes and + case '-':// 'optical' formatting + case 'W': + case ',': + case '(': + case ')': + case 'T': + case 'P':; } - if(!limit) - break; + max--; p++; - first = 0; } *q = 0; } @@ -2951,7 +3018,7 @@ case ISDN_PROTO_L2_V11096: case ISDN_PROTO_L2_V11019: case ISDN_PROTO_L2_V11038: - info->xmit_size /= 10; + info->xmit_size /= 10; } break; case 'C': @@ -3145,7 +3212,7 @@ case ISDN_PROTO_L2_V11096: case ISDN_PROTO_L2_V11019: case ISDN_PROTO_L2_V11038: - info->xmit_size /= 10; + info->xmit_size /= 10; } break; case REG_SI1I: @@ -3365,6 +3432,7 @@ default: PARSE_ERROR1; } + if (*p[0]==';') p[0]++; return 0; } #ifdef CONFIG_ISDN_TTY_FAX @@ -3375,6 +3443,93 @@ } /* + * Parse AT+I.. commands + */ +static int +isdn_tty_cmd_PLUSI(char **p, modem_info * info) +{ +#define PARAMLEN 8 + atemu *m = &info->emu; + static char *icmd[] = + {"NNP", "NIP", "NNA", "NPR", NULL}; + int i, pp=0; + char param[PARAMLEN], reqtyp=0; + + i = 0; + while (icmd[i]) { + if (!strncmp(icmd[i], p[0], strlen(icmd[i]))) { + p[0] += strlen(icmd[i]); + break; + } + i++; + } + switch (*p[0]) { + case '?': + reqtyp=1; + p[0]++; + break; + case '=': + reqtyp=2; + p[0]++; + if (*p[0]=='?') { + reqtyp=3; + p[0]++; + } else { + while(*p[0] && *p[0]!=';' && pp(PARAMLEN-1)) PARSE_ERROR1; + param[pp]=0; + } + break; + default: + PARSE_ERROR1; + } + switch (100*reqtyp+i) { + case 100: + isdn_tty_at_cout("\r\n", info); + isdn_tty_at_cout(m->nprefix, info); + break; + case 101: + isdn_tty_at_cout("\r\n", info); + isdn_tty_at_cout(m->iprefix, info); + break; + case 102: + isdn_tty_at_cout("\r\n", info); + isdn_tty_at_cout(m->nanum, info); + break; + case 103: + isdn_tty_at_cout("\r\n", info); + isdn_tty_at_cout(m->prnum, info); + break; + case 200: + strncpy(m->nprefix,param,PARAMLEN); + break; + case 201: + strncpy(m->iprefix,param,PARAMLEN); + break; + case 202: + strncpy(m->nanum,param,PARAMLEN); + break; + case 203: + strncpy(m->prnum,param,PARAMLEN); + break; + case 300: + case 301: + case 302: + case 303: + isdn_tty_at_cout("\r\n", info); + break; + default: + PARSE_ERROR1; + } + if (*p[0]==';') p[0]++; + return 0; +} + +/* * Parse AT+V.. commands */ static int @@ -3515,7 +3670,7 @@ m->vpar[1] = par1; m->vpar[2] = par2; break; - } else + } else if (*p[0] == '?') { p[0]++; isdn_tty_at_cout("\r\n<0-31>,<0-255>", @@ -3649,6 +3804,7 @@ default: PARSE_ERROR1; } + if (*p[0]==';') p[0]++; return 0; } #endif /* CONFIG_ISDN_AUDIO */ @@ -3839,6 +3995,11 @@ p++; isdn_tty_send_msg(info, m, p); break; + case 'I': /* ISDN configuration */ + p++; + if (isdn_tty_cmd_PLUSI(&p, info)) + return; + break; default: PARSE_ERROR; } --- linux/include/linux/isdn.h 2005-02-03 02:36:58.000000000 +0100 +++ linux/include/linux/isdn.h 2005-02-03 03:15:02.000000000 +0100 @@ -5,7 +5,7 @@ * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.de) * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) - * + * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * @@ -214,7 +214,7 @@ /* Until now unused */ #define ISDN_SERVICE_VOICE 1 -#define ISDN_SERVICE_AB 1<<1 +#define ISDN_SERVICE_AB 1<<1 #define ISDN_SERVICE_X21 1<<2 #define ISDN_SERVICE_G4 1<<3 #define ISDN_SERVICE_BTX 1<<4 @@ -248,7 +248,7 @@ #define ISDN_TIMER_MODEMPLUS 2 #define ISDN_TIMER_MODEMRING 4 #define ISDN_TIMER_MODEMXMIT 8 -#define ISDN_TIMER_NETDIAL 16 +#define ISDN_TIMER_NETDIAL 16 #define ISDN_TIMER_NETHANGUP 32 #define ISDN_TIMER_CARRIER 256 /* Wait for Carrier */ #define ISDN_TIMER_FAST (ISDN_TIMER_MODEMREAD | ISDN_TIMER_MODEMPLUS | \ @@ -284,7 +284,7 @@ /* Principles when extending structures for generic encapsulation protocol ("concap") support: - - Stuff which is hardware specific (here i4l-specific) goes in + - Stuff which is hardware specific (here i4l-specific) goes in the netdev -> local structure (here: isdn_net_local) - Stuff which is encapsulation protocol specific goes in the structure which holds the linux device structure (here: isdn_net_device) @@ -354,7 +354,7 @@ struct sk_buff_head super_tx_queue; /* List of supervisory frames to */ /* be transmitted asap */ atomic_t frame_cnt; /* number of frames currently */ - /* queued in HL driver */ + /* queued in HL driver */ /* Ptr to orig. hard_header_cache */ spinlock_t xmit_lock; /* used to protect the xmit path of */ /* a particular channel (including */ @@ -464,6 +464,10 @@ int carrierwait; /* Seconds of carrier waiting */ char mdmcmd[255]; /* Modem-Commandbuffer */ unsigned int charge; /* Charge units of current connection */ + char iprefix[8]; /* international prefix */ + char nprefix[8]; /* national prefix */ + char prnum[8]; /* presentation restricted */ + char nanum[8]; /* unknown number */ } atemu; /* Private data (similar to async_struct in ) */ @@ -615,6 +619,9 @@ int drvmap[ISDN_MAX_CHANNELS]; /* Map minor->driver-index */ int usage[ISDN_MAX_CHANNELS]; /* Used by tty/ip/voice */ char num[ISDN_MAX_CHANNELS][ISDN_MSNLEN]; + unsigned char numtyp[ISDN_MAX_CHANNELS]; /* type of number (and plan) + to make above unabigous */ + unsigned char screen[ISDN_MAX_CHANNELS]; /* Just to get the PI(ATM) */ /* Remote number of active ch.*/ int m_idx[ISDN_MAX_CHANNELS]; /* Index for mdm.... */ driver *drv[ISDN_MAX_DRIVERS]; /* Array of drivers */