[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