diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/digits.h | 13 | ||||
-rw-r--r-- | kernel/wcusb.c | 2 | ||||
-rw-r--r-- | kernel/zaptel-base.c | 303 | ||||
-rw-r--r-- | kernel/zaptel.h | 102 |
4 files changed, 300 insertions, 120 deletions
diff --git a/kernel/digits.h b/kernel/digits.h index eba09dd..9f4ea9b 100644 --- a/kernel/digits.h +++ b/kernel/digits.h @@ -15,14 +15,14 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Use DTMF/MFv1 tables */ #ifndef _DIGITS_H #define _DIGITS_H #define DEFAULT_DTMF_LENGTH 100 * ZT_CHUNKSIZE -#define DEFAULT_MFV1_LENGTH 60 * ZT_CHUNKSIZE +#define DEFAULT_MFR1_LENGTH 68 * ZT_CHUNKSIZE +#define DEFAULT_MFR2_LENGTH 100 * ZT_CHUNKSIZE #define PAUSE_LENGTH 500 * ZT_CHUNKSIZE /* At the end of silence, the tone stops */ @@ -31,8 +31,13 @@ static struct zt_tone dtmf_silence = { }; /* At the end of silence, the tone stops */ -static struct zt_tone mfv1_silence = { - .tonesamples = DEFAULT_MFV1_LENGTH, +static struct zt_tone mfr1_silence = { + .tonesamples = DEFAULT_MFR1_LENGTH, +}; + +/* At the end of silence, the tone stops */ +static struct zt_tone mfr2_silence = { + .tonesamples = DEFAULT_MFR2_LENGTH, }; /* A pause in the dialing */ diff --git a/kernel/wcusb.c b/kernel/wcusb.c index 51eaca7..15205a4 100644 --- a/kernel/wcusb.c +++ b/kernel/wcusb.c @@ -393,7 +393,7 @@ loop_start: } if (debug) printk("wcusb: got digit %d\n", d->scanned_event); if (digit != 'z') { - d->tone = zt_dtmf_tone(&p->chan, digit); + d->tone = zt_mf_tone(&p->chan, digit, p->chan.digitmode); if (!d->tone) { printk("wcusb: Didn't get a tone structure\n"); goto func_end; diff --git a/kernel/zaptel-base.c b/kernel/zaptel-base.c index f98494d..c4b4ccf 100644 --- a/kernel/zaptel-base.c +++ b/kernel/zaptel-base.c @@ -116,7 +116,7 @@ static char *zt_txlevelnames[] = { EXPORT_SYMBOL(zt_transcode_fops); EXPORT_SYMBOL(zt_init_tone_state); -EXPORT_SYMBOL(zt_dtmf_tone); +EXPORT_SYMBOL(zt_mf_tone); EXPORT_SYMBOL(zt_register); EXPORT_SYMBOL(zt_unregister); EXPORT_SYMBOL(__zt_mulaw); @@ -301,14 +301,17 @@ of the next sample chunk's data (next time around the world). */ #define DIGIT_MODE_DTMF 0 -#define DIGIT_MODE_MFV1 1 +#define DIGIT_MODE_MFR1 1 #define DIGIT_MODE_PULSE 2 +#define DIGIT_MODE_MFR2_FWD 3 +#define DIGIT_MODE_MFR2_REV 4 #include "digits.h" static struct zt_dialparams global_dialparams = { .dtmf_tonelen = DEFAULT_DTMF_LENGTH, - .mfv1_tonelen = DEFAULT_MFV1_LENGTH, + .mfv1_tonelen = DEFAULT_MFR1_LENGTH, + .mfr2_tonelen = DEFAULT_MFR2_LENGTH, }; static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data, int unit); @@ -372,8 +375,9 @@ struct zt_zone { unavailable */ struct zt_tone dtmf[16]; /* DTMF tones for this zone, with desired length */ struct zt_tone dtmf_continuous[16]; /* DTMF tones for this zone, continuous play */ - struct zt_tone mf[15]; /* MF tones for this zone, with desired length */ - struct zt_tone mf_continuous[15]; /* MF tones for this zone, continuous play */ + struct zt_tone mfr1[15]; /* MFR1 tones for this zone, with desired length */ + struct zt_tone mfr2_fwd[15]; /* MFR2 FWD tones for this zone, with desired length */ + struct zt_tone mfr2_rev[15]; /* MFR2 REV tones for this zone, with desired length */ }; static struct zt_span *spans[ZT_MAX_SPANS]; @@ -1163,22 +1167,29 @@ static int start_tone(struct zt_chan *chan, int tone) res = -ENOSYS; } else /* Note that no tone zone exists at the moment */ res = -ENODATA; - } else if (tone >= ZT_TONE_DTMF_BASE && tone <= ZT_TONE_DTMF_MAX) { - /* ZT_SENDTONE should never be used on a channel configured for pulse dialing */ - chan->dialing = 1; - res = 0; - if ((chan->digitmode == DIGIT_MODE_DTMF) && - (tone >= ZT_TONE_DTMF_BASE) && - (tone <= ZT_TONE_DTMF_MAX)) - chan->curtone = &chan->curzone->dtmf_continuous[tone - ZT_TONE_DTMF_BASE]; - else if ((chan->digitmode == DIGIT_MODE_MFV1) && - (tone >= ZT_TONE_MF_BASE) && - (tone <= ZT_TONE_MF_MAX)) - chan->curtone = &chan->curzone->mf_continuous[tone - ZT_TONE_MF_BASE]; - else { - chan->dialing = 0; + } else if (chan->digitmode == DIGIT_MODE_DTMF) { + if ((tone >= ZT_TONE_DTMF_BASE) && (tone <= ZT_TONE_DTMF_MAX)) { + chan->dialing = 1; + res = 0; + tone -= ZT_TONE_DTMF_BASE; + if (chan->curzone) { + /* Have a tone zone */ + if (chan->curzone->dtmf_continuous[tone].tonesamples) { + chan->curtone = &chan->curzone->dtmf_continuous[tone]; + res = 0; + } else { + /* Indicate that zone is loaded but no such tone exists */ + res = -ENOSYS; + } + } else { + /* Note that no tone zone exists at the moment */ + res = -ENODATA; + } + } else { res = -EINVAL; - } + }; + } else { + res = -EINVAL; } if (chan->curtone) @@ -2680,7 +2691,9 @@ static int ioctl_load_zone(unsigned long data) enum { REGULAR_TONE, DTMF_TONE, - MF_TONE, + MFR1_TONE, + MFR2_FWD_TONE, + MFR2_REV_TONE, } tone_type; if (space < sizeof(*t)) { @@ -2716,15 +2729,23 @@ static int ioctl_load_zone(unsigned long data) } else if ((td.tone >= ZT_TONE_DTMF_BASE) && (td.tone <= ZT_TONE_DTMF_MAX)) { tone_type = DTMF_TONE; - td.tone -= ZT_TONE_DTMF_BASE; t = &z->dtmf[td.tone]; - } else if ((td.tone >= ZT_TONE_MF_BASE) && - (td.tone <= ZT_TONE_MF_MAX)) { - tone_type = MF_TONE; - - td.tone -= ZT_TONE_MF_BASE; - t = &z->mf[td.tone]; + } else if ((td.tone >= ZT_TONE_MFR1_BASE) && + (td.tone <= ZT_TONE_MFR1_MAX)) { + tone_type = MFR1_TONE; + td.tone -= ZT_TONE_MFR1_BASE; + t = &z->mfr1[td.tone]; + } else if ((td.tone >= ZT_TONE_MFR2_FWD_BASE) && + (td.tone <= ZT_TONE_MFR2_FWD_MAX)) { + tone_type = MFR2_FWD_TONE; + td.tone -= ZT_TONE_MFR2_FWD_BASE; + t = &z->mfr2_fwd[td.tone]; + } else if ((td.tone >= ZT_TONE_MFR2_REV_BASE) && + (td.tone <= ZT_TONE_MFR2_REV_MAX)) { + tone_type = MFR2_REV_TONE; + td.tone -= ZT_TONE_MFR2_REV_BASE; + t = &z->mfr2_rev[td.tone]; } else { printk("Invalid tone (%d) defined\n", td.tone); kfree(slab); @@ -2751,14 +2772,26 @@ static int ioctl_load_zone(unsigned long data) z->dtmf_continuous[td.tone] = *t; z->dtmf_continuous[td.tone].next = &z->dtmf_continuous[td.tone]; break; - case MF_TONE: - t->tonesamples = global_dialparams.mfv1_tonelen; - t->next = &mfv1_silence; - /* Special case for K/P tone */ - if (td.tone == 10) - t->tonesamples *= 5 / 3; - z->mf_continuous[td.tone] = *t; - z->mf_continuous[td.tone].next = &z->mf_continuous[td.tone]; + case MFR1_TONE: + switch (td.tone + ZT_TONE_MFR1_BASE) { + case ZT_TONE_MFR1_KP: + case ZT_TONE_MFR1_ST: + case ZT_TONE_MFR1_STP: + case ZT_TONE_MFR1_ST2P: + case ZT_TONE_MFR1_ST3P: + /* signaling control tones are always 100ms */ + t->tonesamples = 100 * ZT_CHUNKSIZE; + break; + default: + t->tonesamples = global_dialparams.mfv1_tonelen; + break; + } + t->next = &mfr1_silence; + break; + case MFR2_FWD_TONE: + case MFR2_REV_TONE: + t->tonesamples = global_dialparams.mfr2_tonelen; + t->next = &dtmf_silence; break; } } @@ -2790,51 +2823,134 @@ void zt_init_tone_state(struct zt_tone_state *ts, struct zt_tone *zt) ts->modulate = zt->modulate; } -struct zt_tone *zt_dtmf_tone(const struct zt_chan *chan, char digit) +struct zt_tone *zt_mf_tone(const struct zt_chan *chan, char digit, int digitmode) { - struct zt_tone *z; + unsigned int tone_index; - switch (chan->digitmode) { + switch (digitmode) { case DIGIT_MODE_DTMF: - z = &chan->curzone->dtmf[0]; - break; - case DIGIT_MODE_MFV1: - z = &chan->curzone->mf[0]; - break; - default: - z = NULL; - } - - switch (digit) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return z + (digit - '0'); - case '*': - return z + 10; - case '#': - return z + 11; - case 'A': - case 'B': - case 'C': - return z + (digit + 12 - 'A'); - case 'D': - if (chan->digitmode == DIGIT_MODE_MFV1) + switch (digit) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + tone_index = ZT_TONE_DTMF_0 + (digit - '0'); + break; + case '*': + tone_index = ZT_TONE_DTMF_s; + break; + case '#': + tone_index = ZT_TONE_DTMF_p; + break; + case 'A': + case 'B': + case 'C': + case 'D': + tone_index = ZT_TONE_DTMF_A + (digit - 'A'); + case 'W': + return &tone_pause; + default: return NULL; - else - return z + (digit + 12 - 'A'); - case 'W': - return &tone_pause; + } + return &chan->curzone->dtmf[tone_index - ZT_TONE_DTMF_BASE]; + case DIGIT_MODE_MFR1: + switch (digit) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + tone_index = ZT_TONE_MFR1_0 + (digit - '0'); + break; + case '*': + tone_index = ZT_TONE_MFR1_KP; + break; + case '#': + tone_index = ZT_TONE_MFR1_ST; + break; + case 'A': + tone_index = ZT_TONE_MFR1_STP; + break; + case 'B': + tone_index = ZT_TONE_MFR1_ST2P; + break; + case 'C': + tone_index = ZT_TONE_MFR1_ST3P; + break; + case 'W': + return &tone_pause; + default: + return NULL; + } + return &chan->curzone->mfr1[tone_index - ZT_TONE_MFR1_BASE]; + case DIGIT_MODE_MFR2_FWD: + switch (digit) { + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + tone_index = ZT_TONE_MFR2_FWD_1 + (digit - '1'); + break; + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + tone_index = ZT_TONE_MFR2_FWD_10 + (digit - 'A'); + break; + case 'W': + return &tone_pause; + default: + return NULL; + } + return &chan->curzone->mfr2_fwd[tone_index - ZT_TONE_MFR2_FWD_BASE]; + case DIGIT_MODE_MFR2_REV: + switch (digit) { + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + tone_index = ZT_TONE_MFR2_REV_1 + (digit - '1'); + break; + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + tone_index = ZT_TONE_MFR2_REV_10 + (digit - 'A'); + break; + case 'W': + return &tone_pause; + default: + return NULL; + } + return &chan->curzone->mfr2_rev[tone_index - ZT_TONE_MFR2_REV_BASE]; + default: + return NULL; } - - return NULL; } static void __do_dtmf(struct zt_chan *chan) @@ -2850,7 +2966,15 @@ static void __do_dtmf(struct zt_chan *chan) chan->tonep = 0; break; case 'M': - chan->digitmode = DIGIT_MODE_MFV1; + chan->digitmode = DIGIT_MODE_MFR1; + chan->tonep = 0; + break; + case 'F': + chan->digitmode = DIGIT_MODE_MFR2_FWD; + chan->tonep = 0; + break; + case 'R': + chan->digitmode = DIGIT_MODE_MFR2_REV; chan->tonep = 0; break; case 'P': @@ -2866,7 +2990,7 @@ static void __do_dtmf(struct zt_chan *chan) return; } } else { - chan->curtone = zt_dtmf_tone(chan, c); + chan->curtone = zt_mf_tone(chan, c, chan->digitmode); chan->tonep = 0; if (chan->curtone) { zt_init_tone_state(&chan->ts, chan->curtone); @@ -3713,6 +3837,8 @@ static int zt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd return -EINVAL; if ((tdp.mfv1_tonelen > 4000) || (tdp.mfv1_tonelen < 10)) return -EINVAL; + if ((tdp.mfr2_tonelen > 4000) || (tdp.mfr2_tonelen < 10)) + return -EINVAL; global_dialparams = tdp; @@ -3724,19 +3850,28 @@ static int zt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd if (!z) continue; - for (i = 0; i < sizeof(z->dtmf) / sizeof(z->dtmf[0]); i++) + for (i = 0; i < sizeof(z->dtmf) / sizeof(z->dtmf[0]); i++) { z->dtmf[i].tonesamples = tdp.dtmf_tonelen * ZT_CHUNKSIZE; + } - for (i = 0; i < sizeof(z->mf) / sizeof(z->mf[0]); i++) - z->mf[i].tonesamples = tdp.mfv1_tonelen * ZT_CHUNKSIZE; + /* for MFR1, we only adjust the length of the digits */ + for (i = ZT_TONE_MFR1_0; i <= ZT_TONE_MFR1_9; i++) { + z->mfr1[i - ZT_TONE_MFR1_BASE].tonesamples = tdp.mfv1_tonelen * ZT_CHUNKSIZE; + } - /* Special case for K/P tone */ - z->mf[10].tonesamples *= 5 / 3; + for (i = 0; i < sizeof(z->mfr2_fwd) / sizeof(z->mfr2_fwd[0]); i++) { + z->mfr2_fwd[i].tonesamples = tdp.mfr2_tonelen * ZT_CHUNKSIZE; + } + + for (i = 0; i < sizeof(z->mfr2_rev) / sizeof(z->mfr2_rev[0]); i++) { + z->mfr2_rev[i].tonesamples = tdp.mfr2_tonelen * ZT_CHUNKSIZE; + } } write_unlock(&zone_lock); dtmf_silence.tonesamples = tdp.dtmf_tonelen * ZT_CHUNKSIZE; - mfv1_silence.tonesamples = tdp.mfv1_tonelen * ZT_CHUNKSIZE; + mfr1_silence.tonesamples = tdp.mfv1_tonelen * ZT_CHUNKSIZE; + mfr2_silence.tonesamples = tdp.mfr2_tonelen * ZT_CHUNKSIZE; break; case ZT_GET_DIALPARAMS: diff --git a/kernel/zaptel.h b/kernel/zaptel.h index b37a2c3..e0db194 100644 --- a/kernel/zaptel.h +++ b/kernel/zaptel.h @@ -351,7 +351,7 @@ char netdev_name[16]; /*name for the hdlc network device*/ typedef struct zt_sfconfig { int chan; /* Channel we're applying this to (0 to use name) */ -char name[40]; /* Name of channel to use */ +char name[40]; /* Name of channel to use */ long rxp1; /* receive tone det. p1 */ long rxp2; /* receive tone det. p2 */ long rxp3; /* receive tone det. p3 */ @@ -371,14 +371,13 @@ int readbufs; /* How many read buffers are full (read-only) */ int writebufs; /* How many write buffers are full (read-only) */ } ZT_BUFFERINFO; -typedef struct zt_dialparams -{ -int mfv1_tonelen; /* MF tone length (KP = this * 5/3) */ -int dtmf_tonelen; /* DTMF tone length */ -int reserved[4]; /* Reserved for future expansion -- always set to 0 */ +typedef struct zt_dialparams { + int mfv1_tonelen; /* MF R1 tone length for digits */ + int dtmf_tonelen; /* DTMF tone length */ + int mfr2_tonelen; /* MF R2 tone length */ + int reserved[3]; /* Reserved for future expansion -- always set to 0 */ } ZT_DIAL_PARAMS; - typedef struct zt_dynamic_span { char driver[20]; /* Which low-level driver to use */ char addr[40]; /* Destination address */ @@ -387,7 +386,7 @@ typedef struct zt_dynamic_span { int spanno; /* Span number (filled in by zaptel) */ } ZT_DYNAMIC_SPAN; -/* Define the max # of outgoing DTMF or MFv1 digits to queue in-kernel */ +/* Define the max # of outgoing DTMF, MFR1 or MFR2 digits to queue in-kernel */ #define ZT_MAX_DTMF_BUF 256 #define ZT_DIAL_OP_APPEND 1 @@ -398,10 +397,9 @@ typedef struct zt_dynamic_span { #define ZT_LAW_MULAW 1 /* Mu-law */ #define ZT_LAW_ALAW 2 /* A-law */ -typedef struct zt_dialoperation -{ -int op; -char dialstr[ZT_MAX_DTMF_BUF]; +typedef struct zt_dialoperation { + int op; + char dialstr[ZT_MAX_DTMF_BUF]; } ZT_DIAL_OPERATION; @@ -804,7 +802,9 @@ struct zt_hwgain{ #define ZT_TONE_MAX 16 #define ZT_TONE_DTMF_BASE 64 -#define ZT_TONE_MF_BASE 80 +#define ZT_TONE_MFR1_BASE 80 +#define ZT_TONE_MFR2_FWD_BASE 96 +#define ZT_TONE_MFR2_REV_BASE 112 enum { ZT_TONE_DTMF_0 = ZT_TONE_DTMF_BASE, @@ -828,24 +828,64 @@ enum { #define ZT_TONE_DTMF_MAX ZT_TONE_DTMF_D enum { - ZT_TONE_MF_0 = ZT_TONE_MF_BASE, - ZT_TONE_MF_1, - ZT_TONE_MF_2, - ZT_TONE_MF_3, - ZT_TONE_MF_4, - ZT_TONE_MF_5, - ZT_TONE_MF_6, - ZT_TONE_MF_7, - ZT_TONE_MF_8, - ZT_TONE_MF_9, - ZT_TONE_MF_s, - ZT_TONE_MF_p, - ZT_TONE_MF_A, - ZT_TONE_MF_B, - ZT_TONE_MF_C, + ZT_TONE_MFR1_0 = ZT_TONE_MFR1_BASE, + ZT_TONE_MFR1_1, + ZT_TONE_MFR1_2, + ZT_TONE_MFR1_3, + ZT_TONE_MFR1_4, + ZT_TONE_MFR1_5, + ZT_TONE_MFR1_6, + ZT_TONE_MFR1_7, + ZT_TONE_MFR1_8, + ZT_TONE_MFR1_9, + ZT_TONE_MFR1_KP, + ZT_TONE_MFR1_ST, + ZT_TONE_MFR1_STP, + ZT_TONE_MFR1_ST2P, + ZT_TONE_MFR1_ST3P, +}; + +#define ZT_TONE_MFR1_MAX ZT_TONE_MFR1_ST3P + +enum { + ZT_TONE_MFR2_FWD_1 = ZT_TONE_MFR2_FWD_BASE, + ZT_TONE_MFR2_FWD_2, + ZT_TONE_MFR2_FWD_3, + ZT_TONE_MFR2_FWD_4, + ZT_TONE_MFR2_FWD_5, + ZT_TONE_MFR2_FWD_6, + ZT_TONE_MFR2_FWD_7, + ZT_TONE_MFR2_FWD_8, + ZT_TONE_MFR2_FWD_9, + ZT_TONE_MFR2_FWD_10, + ZT_TONE_MFR2_FWD_11, + ZT_TONE_MFR2_FWD_12, + ZT_TONE_MFR2_FWD_13, + ZT_TONE_MFR2_FWD_14, + ZT_TONE_MFR2_FWD_15, +}; + +#define ZT_TONE_MFR2_FWD_MAX ZT_TONE_MFR2_FWD_15 + +enum { + ZT_TONE_MFR2_REV_1 = ZT_TONE_MFR2_REV_BASE, + ZT_TONE_MFR2_REV_2, + ZT_TONE_MFR2_REV_3, + ZT_TONE_MFR2_REV_4, + ZT_TONE_MFR2_REV_5, + ZT_TONE_MFR2_REV_6, + ZT_TONE_MFR2_REV_7, + ZT_TONE_MFR2_REV_8, + ZT_TONE_MFR2_REV_9, + ZT_TONE_MFR2_REV_10, + ZT_TONE_MFR2_REV_11, + ZT_TONE_MFR2_REV_12, + ZT_TONE_MFR2_REV_13, + ZT_TONE_MFR2_REV_14, + ZT_TONE_MFR2_REV_15, }; -#define ZT_TONE_MF_MAX ZT_TONE_MF_C +#define ZT_TONE_MFR2_REV_MAX ZT_TONE_MFR2_REV_15 #define ZT_MAX_CADENCE 16 @@ -1770,8 +1810,8 @@ void zt_alarm_notify(struct zt_span *span); /* Initialize a tone state */ void zt_init_tone_state(struct zt_tone_state *ts, struct zt_tone *zt); -/* Get a given DTMF or MF tone struct, suitable for zt_tone_nextsample. */ -struct zt_tone *zt_dtmf_tone(const struct zt_chan *chan, char digit); +/* Get a given MF tone struct, suitable for zt_tone_nextsample. */ +struct zt_tone *zt_mf_tone(const struct zt_chan *chan, char digit, int digitmode); /* Echo cancel a receive and transmit chunk for a given channel. This should be called by the low-level driver as close to the interface |