[zaptel-commits] kpfleming: branch kpfleming/dtmf-twister r3482 - /team/kpfleming/dtmf-twister/
SVN commits to the Zaptel project
zaptel-commits at lists.digium.com
Fri Dec 14 13:53:19 CST 2007
Author: kpfleming
Date: Fri Dec 14 13:53:18 2007
New Revision: 3482
URL: http://svn.digium.com/view/zaptel?view=rev&rev=3482
Log:
allow loading of DTMF and MF tones via ZT_LOADZONE ioctl
Modified:
team/kpfleming/dtmf-twister/zaptel-base.c
Modified: team/kpfleming/dtmf-twister/zaptel-base.c
URL: http://svn.digium.com/view/zaptel/team/kpfleming/dtmf-twister/zaptel-base.c?view=diff&rev=3482&r1=3481&r2=3482
==============================================================================
--- team/kpfleming/dtmf-twister/zaptel-base.c (original)
+++ team/kpfleming/dtmf-twister/zaptel-base.c Fri Dec 14 13:53:18 2007
@@ -2566,80 +2566,118 @@
/* No more than 64 subtones */
#define MAX_TONES 64
+/* The tones to be loaded can (will) be a mix of regular tones,
+ DTMF tones and MF tones. We need to load DTMF and MF tones
+ a bit differently than regular tones because their storage
+ format is much simpler (an array structure field of the zone
+ structure, rather an array of pointers).
+*/
static int ioctl_load_zone(unsigned long data)
{
- struct zt_tone *samples[MAX_TONES];
- short next[MAX_TONES];
+ struct zt_tone *samples[MAX_TONES] = { NULL, };
+ short next[MAX_TONES] = { 0, };
struct zt_tone_def_header th;
+ struct zt_tone_def td;
+ struct zt_zone *z;
+ struct zt_tone *t;
void *slab, *ptr;
- long size;
- struct zt_zone *z;
- struct zt_tone_def td;
- struct zt_tone *t;
int x;
- int space;
+ size_t space;
+ size_t size;
int res;
+ int dtmf_length = DEFAULT_DTMF_LENGTH;
+ int mf_length = DEFAULT_MFV1_LENGTH;
- /* XXX Unnecessary XXX */
- memset(samples, 0, sizeof(samples));
- /* XXX Unnecessary XXX */
- memset(next, 0, sizeof(next));
- if (copy_from_user(&th, (struct zt_tone_def_header *)data, sizeof(th)))
+ if (copy_from_user(&th, (struct zt_tone_def_header *) data, sizeof(th)))
return -EFAULT;
+
+ data += sizeof(th);
+
if ((th.count < 0) || (th.count > MAX_TONES)) {
printk("Too many tones included\n");
return -EINVAL;
}
- space = size = sizeof(struct zt_zone) +
- th.count * sizeof(struct zt_tone);
- if ((size > MAX_SIZE) || (size < 0))
+
+ space = size = sizeof(*z) + th.count * sizeof(*t);
+
+ if (size > MAX_SIZE)
return -E2BIG;
- ptr = slab = (char *)kmalloc(size, GFP_KERNEL);
- if (!slab)
+
+ if (!(z = ptr = slab = kmalloc(size, GFP_KERNEL)))
return -ENOMEM;
- /* Zero it out for simplicity */
+
memset(slab, 0, size);
- /* Grab the zone */
- z = (struct zt_zone *)slab;
+
+ ptr += sizeof(*z);
+ space -= sizeof(*z);
+
strncpy(z->name, th.name, sizeof(z->name) - 1);
- for (x=0;x<ZT_MAX_CADENCE;x++)
+
+ for (x = 0; x < ZT_MAX_CADENCE; x++)
z->ringcadence[x] = th.ringcadence[x];
- data += sizeof(struct zt_tone_def_header);
- ptr += sizeof(struct zt_zone);
- space -= sizeof(struct zt_zone);
- for (x=0;x<th.count;x++) {
- if (space < sizeof(struct zt_tone)) {
- /* Check space for zt_tone struct */
+
+ /* if the DTMF and/or MF tone lengths have been adjusted via SET_DIALPARAMS,
+ respect that for tones in this zone as well */
+ if (default_zone) {
+ dtmf_length = tone_zones[default_zone]->dtmf[0].tonesamples;
+ mf_length = tone_zones[default_zone]->mf[0].tonesamples;
+ }
+
+ for (x = 0; x < th.count; x++) {
+ enum {
+ REGULAR_TONE,
+ DTMF_TONE,
+ MF_TONE,
+ } tone_type;
+
+ if (space < sizeof(*t)) {
kfree(slab);
printk("Insufficient tone zone space\n");
return -EINVAL;
}
- if (copy_from_user(&td, (struct zt_tone_def *)data, sizeof(struct zt_tone_def))) {
+
+ if (copy_from_user(&td, (struct zt_tone_def *) data, sizeof(td))) {
kfree(slab);
return -EFAULT;
}
- /* Index the current sample */
- samples[x] = t = (struct zt_tone *)ptr;
- /* Remember which sample is next */
- next[x] = td.next;
- /* Make sure the "next" one is sane */
- if ((next[x] >= th.count) || (next[x] < 0)) {
- printk("Invalid 'next' pointer: %d\n", next[x]);
+
+ data += sizeof(td);
+
+ if ((td.tone > 0) && (td.tone < ZT_TONE_MAX)) {
+ tone_type = REGULAR_TONE;
+
+ t = samples[x] = ptr;
+
+ space -= sizeof(*t);
+ ptr += sizeof(*t);
+
+ /* Remember which sample is next */
+ next[x] = td.next;
+
+ /* Make sure the "next" one is sane */
+ if ((next[x] >= th.count) || (next[x] < 0)) {
+ printk("Invalid 'next' pointer: %d\n", next[x]);
+ kfree(slab);
+ return -EINVAL;
+ }
+ } 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 {
+ printk("Invalid tone (%d) defined\n", td.tone);
kfree(slab);
return -EINVAL;
}
- if (td.tone >= ZT_TONE_MAX) {
- printk("Too many tones defined\n");
- /* Make sure it's sane */
- kfree(slab);
- return -EINVAL;
- }
- /* Update pointers to account for zt_tone header */
- space -= sizeof(struct zt_tone);
- ptr += sizeof(struct zt_tone);
- data += sizeof(struct zt_tone_def);
- /* Fill in tonedata, datalen, and tonesamples fields */
- t->tonesamples = td.samples;
+
t->fac1 = td.fac1;
t->init_v2_1 = td.init_v2_1;
t->init_v3_1 = td.init_v3_1;
@@ -2647,18 +2685,37 @@
t->init_v2_2 = td.init_v2_2;
t->init_v3_2 = td.init_v3_2;
t->modulate = td.modulate;
- t->next = NULL; /* XXX Unnecessary XXX */
- if (!z->tones[td.tone])
- z->tones[td.tone] = t;
- }
- for (x=0;x<th.count;x++)
- /* Set "next" pointers */
- samples[x]->next = samples[next[x]];
-
- /* Actually register zone */
- res = zt_register_tone_zone(th.zone, z);
- if (res)
+
+ switch (tone_type) {
+ case REGULAR_TONE:
+ t->tonesamples = td.samples;
+ if (!z->tones[td.tone])
+ z->tones[td.tone] = t;
+ break;
+ case DTMF_TONE:
+ t->tonesamples = dtmf_length;
+ z->dtmf_continuous[td.tone] = *t;
+ z->dtmf_continuous[td.tone].next = &z->dtmf_continuous[td.tone];
+ break;
+ case MF_TONE:
+ t->tonesamples = mf_length;
+ /* 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];
+ break;
+ }
+ }
+
+ for (x = 0; x < th.count; x++) {
+ if (samples[x] && next[x])
+ samples[x]->next = samples[next[x]];
+ }
+
+ if ((res = zt_register_tone_zone(th.zone, z)))
kfree(slab);
+
return res;
}
More information about the zaptel-commits
mailing list