summaryrefslogtreecommitdiff
path: root/kernel/zaptel-base.c
diff options
context:
space:
mode:
authorkpfleming <kpfleming@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2008-03-21 23:30:41 +0000
committerkpfleming <kpfleming@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2008-03-21 23:30:41 +0000
commit57544543646a83e92555be35b6096928d41b721e (patch)
tree9bbfb63133ea8454d6968122a860a68ca46577fd /kernel/zaptel-base.c
parent9b0ddb179b1216d03a2d0e7d884342fbef2246a0 (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.c303
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: