diff options
author | kpfleming <kpfleming@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2008-03-21 23:30:41 +0000 |
---|---|---|
committer | kpfleming <kpfleming@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2008-03-21 23:30:41 +0000 |
commit | 57544543646a83e92555be35b6096928d41b721e (patch) | |
tree | 9bbfb63133ea8454d6968122a860a68ca46577fd /kernel/zaptel-base.c | |
parent | 9b0ddb179b1216d03a2d0e7d884342fbef2246a0 (diff) |
add MF R2 tone generation, and along the way do a lot of cleanup of the tone building and playback code
git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.4@4063 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'kernel/zaptel-base.c')
-rw-r--r-- | kernel/zaptel-base.c | 303 |
1 files changed, 219 insertions, 84 deletions
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: |