xref: /openbmc/linux/drivers/isdn/mISDN/dsp_tones.c (revision b627b4ed)
1 /*
2  * Audio support data for ISDN4Linux.
3  *
4  * Copyright Andreas Eversberg (jolly@eversberg.eu)
5  *
6  * This software may be used and distributed according to the terms
7  * of the GNU General Public License, incorporated herein by reference.
8  *
9  */
10 
11 #include <linux/mISDNif.h>
12 #include <linux/mISDNdsp.h>
13 #include "core.h"
14 #include "dsp.h"
15 
16 
17 #define DATA_S sample_silence
18 #define SIZE_S (&sizeof_silence)
19 #define DATA_GA sample_german_all
20 #define SIZE_GA (&sizeof_german_all)
21 #define DATA_GO sample_german_old
22 #define SIZE_GO (&sizeof_german_old)
23 #define DATA_DT sample_american_dialtone
24 #define SIZE_DT (&sizeof_american_dialtone)
25 #define DATA_RI sample_american_ringing
26 #define SIZE_RI (&sizeof_american_ringing)
27 #define DATA_BU sample_american_busy
28 #define SIZE_BU (&sizeof_american_busy)
29 #define DATA_S1 sample_special1
30 #define SIZE_S1 (&sizeof_special1)
31 #define DATA_S2 sample_special2
32 #define SIZE_S2 (&sizeof_special2)
33 #define DATA_S3 sample_special3
34 #define SIZE_S3 (&sizeof_special3)
35 
36 /***************/
37 /* tones loops */
38 /***************/
39 
40 /* all tones are alaw encoded */
41 /* the last sample+1 is in phase with the first sample. the error is low */
42 
43 static u8 sample_german_all[] = {
44 	0x80, 0xab, 0x81, 0x6d, 0xfd, 0xdd, 0x5d, 0x9d,
45 	0x4d, 0xd1, 0x89, 0x88, 0xd0, 0x4c, 0x9c, 0x5c,
46 	0xdc, 0xfc, 0x6c,
47 	0x80, 0xab, 0x81, 0x6d, 0xfd, 0xdd, 0x5d, 0x9d,
48 	0x4d, 0xd1, 0x89, 0x88, 0xd0, 0x4c, 0x9c, 0x5c,
49 	0xdc, 0xfc, 0x6c,
50 	0x80, 0xab, 0x81, 0x6d, 0xfd, 0xdd, 0x5d, 0x9d,
51 	0x4d, 0xd1, 0x89, 0x88, 0xd0, 0x4c, 0x9c, 0x5c,
52 	0xdc, 0xfc, 0x6c,
53 	0x80, 0xab, 0x81, 0x6d, 0xfd, 0xdd, 0x5d, 0x9d,
54 	0x4d, 0xd1, 0x89, 0x88, 0xd0, 0x4c, 0x9c, 0x5c,
55 	0xdc, 0xfc, 0x6c,
56 };
57 static u32 sizeof_german_all = sizeof(sample_german_all);
58 
59 static u8 sample_german_old[] = {
60 	0xec, 0x68, 0xe1, 0x6d, 0x6d, 0x91, 0x51, 0xed,
61 	0x6d, 0x01, 0x1e, 0x10, 0x0c, 0x90, 0x60, 0x70,
62 	0x8c,
63 	0xec, 0x68, 0xe1, 0x6d, 0x6d, 0x91, 0x51, 0xed,
64 	0x6d, 0x01, 0x1e, 0x10, 0x0c, 0x90, 0x60, 0x70,
65 	0x8c,
66 	0xec, 0x68, 0xe1, 0x6d, 0x6d, 0x91, 0x51, 0xed,
67 	0x6d, 0x01, 0x1e, 0x10, 0x0c, 0x90, 0x60, 0x70,
68 	0x8c,
69 	0xec, 0x68, 0xe1, 0x6d, 0x6d, 0x91, 0x51, 0xed,
70 	0x6d, 0x01, 0x1e, 0x10, 0x0c, 0x90, 0x60, 0x70,
71 	0x8c,
72 };
73 static u32 sizeof_german_old = sizeof(sample_german_old);
74 
75 static u8 sample_american_dialtone[] = {
76 	0x2a, 0x18, 0x90, 0x6c, 0x4c, 0xbc, 0x4c, 0x6c,
77 	0x10, 0x58, 0x32, 0xb9, 0x31, 0x2d, 0x8d, 0x0d,
78 	0x8d, 0x2d, 0x31, 0x99, 0x0f, 0x28, 0x60, 0xf0,
79 	0xd0, 0x50, 0xd0, 0x30, 0x60, 0x08, 0x8e, 0x67,
80 	0x09, 0x19, 0x21, 0xe1, 0xd9, 0xb9, 0x29, 0x67,
81 	0x83, 0x02, 0xce, 0xbe, 0xee, 0x1a, 0x1b, 0xef,
82 	0xbf, 0xcf, 0x03, 0x82, 0x66, 0x28, 0xb8, 0xd8,
83 	0xe0, 0x20, 0x18, 0x08, 0x66, 0x8f, 0x09, 0x61,
84 	0x31, 0xd1, 0x51, 0xd1, 0xf1, 0x61, 0x29, 0x0e,
85 	0x98, 0x30, 0x2c, 0x8c, 0x0c, 0x8c, 0x2c, 0x30,
86 	0xb8, 0x33, 0x59, 0x11, 0x6d, 0x4d, 0xbd, 0x4d,
87 	0x6d, 0x91, 0x19,
88 };
89 static u32 sizeof_american_dialtone = sizeof(sample_american_dialtone);
90 
91 static u8 sample_american_ringing[] = {
92 	0x2a, 0xe0, 0xac, 0x0c, 0xbc, 0x4c, 0x8c, 0x90,
93 	0x48, 0xc7, 0xc1, 0xed, 0xcd, 0x4d, 0xcd, 0xed,
94 	0xc1, 0xb7, 0x08, 0x30, 0xec, 0xcc, 0xcc, 0x8c,
95 	0x10, 0x58, 0x1a, 0x99, 0x71, 0xed, 0x8d, 0x8d,
96 	0x2d, 0x41, 0x89, 0x9e, 0x20, 0x70, 0x2c, 0xec,
97 	0x2c, 0x70, 0x20, 0x86, 0x77, 0xe1, 0x31, 0x11,
98 	0xd1, 0xf1, 0x81, 0x09, 0xa3, 0x56, 0x58, 0x00,
99 	0x40, 0xc0, 0x60, 0x38, 0x46, 0x43, 0x57, 0x39,
100 	0xd9, 0x59, 0x99, 0xc9, 0x77, 0x2f, 0x2e, 0xc6,
101 	0xd6, 0x28, 0xd6, 0x36, 0x26, 0x2e, 0x8a, 0xa3,
102 	0x43, 0x63, 0x4b, 0x4a, 0x62, 0x42, 0xa2, 0x8b,
103 	0x2f, 0x27, 0x37, 0xd7, 0x29, 0xd7, 0xc7, 0x2f,
104 	0x2e, 0x76, 0xc8, 0x98, 0x58, 0xd8, 0x38, 0x56,
105 	0x42, 0x47, 0x39, 0x61, 0xc1, 0x41, 0x01, 0x59,
106 	0x57, 0xa2, 0x08, 0x80, 0xf0, 0xd0, 0x10, 0x30,
107 	0xe0, 0x76, 0x87, 0x21, 0x71, 0x2d, 0xed, 0x2d,
108 	0x71, 0x21, 0x9f, 0x88, 0x40, 0x2c, 0x8c, 0x8c,
109 	0xec, 0x70, 0x98, 0x1b, 0x59, 0x11, 0x8d, 0xcd,
110 	0xcd, 0xed, 0x31, 0x09, 0xb6, 0xc0, 0xec, 0xcc,
111 	0x4c, 0xcc, 0xec, 0xc0, 0xc6, 0x49, 0x91, 0x8d,
112 	0x4d, 0xbd, 0x0d, 0xad, 0xe1,
113 };
114 static u32 sizeof_american_ringing = sizeof(sample_american_ringing);
115 
116 static u8 sample_american_busy[] = {
117 	0x2a, 0x00, 0x6c, 0x4c, 0x4c, 0x6c, 0xb0, 0x66,
118 	0x99, 0x11, 0x6d, 0x8d, 0x2d, 0x41, 0xd7, 0x96,
119 	0x60, 0xf0, 0x70, 0x40, 0x58, 0xf6, 0x53, 0x57,
120 	0x09, 0x89, 0xd7, 0x5f, 0xe3, 0x2a, 0xe3, 0x5f,
121 	0xd7, 0x89, 0x09, 0x57, 0x53, 0xf6, 0x58, 0x40,
122 	0x70, 0xf0, 0x60, 0x96, 0xd7, 0x41, 0x2d, 0x8d,
123 	0x6d, 0x11, 0x99, 0x66, 0xb0, 0x6c, 0x4c, 0x4c,
124 	0x6c, 0x00, 0x2a, 0x01, 0x6d, 0x4d, 0x4d, 0x6d,
125 	0xb1, 0x67, 0x98, 0x10, 0x6c, 0x8c, 0x2c, 0x40,
126 	0xd6, 0x97, 0x61, 0xf1, 0x71, 0x41, 0x59, 0xf7,
127 	0x52, 0x56, 0x08, 0x88, 0xd6, 0x5e, 0xe2, 0x2a,
128 	0xe2, 0x5e, 0xd6, 0x88, 0x08, 0x56, 0x52, 0xf7,
129 	0x59, 0x41, 0x71, 0xf1, 0x61, 0x97, 0xd6, 0x40,
130 	0x2c, 0x8c, 0x6c, 0x10, 0x98, 0x67, 0xb1, 0x6d,
131 	0x4d, 0x4d, 0x6d, 0x01,
132 };
133 static u32 sizeof_american_busy = sizeof(sample_american_busy);
134 
135 static u8 sample_special1[] = {
136 	0x2a, 0x2c, 0xbc, 0x6c, 0xd6, 0x71, 0xbd, 0x0d,
137 	0xd9, 0x80, 0xcc, 0x4c, 0x40, 0x39, 0x0d, 0xbd,
138 	0x11, 0x86, 0xec, 0xbc, 0xec, 0x0e, 0x51, 0xbd,
139 	0x8d, 0x89, 0x30, 0x4c, 0xcc, 0xe0, 0xe1, 0xcd,
140 	0x4d, 0x31, 0x88, 0x8c, 0xbc, 0x50, 0x0f, 0xed,
141 	0xbd, 0xed, 0x87, 0x10, 0xbc, 0x0c, 0x38, 0x41,
142 	0x4d, 0xcd, 0x81, 0xd8, 0x0c, 0xbc, 0x70, 0xd7,
143 	0x6d, 0xbd, 0x2d,
144 };
145 static u32 sizeof_special1 = sizeof(sample_special1);
146 
147 static u8 sample_special2[] = {
148 	0x2a, 0xcc, 0x8c, 0xd7, 0x4d, 0x2d, 0x18, 0xbc,
149 	0x10, 0xc1, 0xbd, 0xc1, 0x10, 0xbc, 0x18, 0x2d,
150 	0x4d, 0xd7, 0x8c, 0xcc, 0x2a, 0xcd, 0x8d, 0xd6,
151 	0x4c, 0x2c, 0x19, 0xbd, 0x11, 0xc0, 0xbc, 0xc0,
152 	0x11, 0xbd, 0x19, 0x2c, 0x4c, 0xd6, 0x8d, 0xcd,
153 	0x2a, 0xcc, 0x8c, 0xd7, 0x4d, 0x2d, 0x18, 0xbc,
154 	0x10, 0xc1, 0xbd, 0xc1, 0x10, 0xbc, 0x18, 0x2d,
155 	0x4d, 0xd7, 0x8c, 0xcc, 0x2a, 0xcd, 0x8d, 0xd6,
156 	0x4c, 0x2c, 0x19, 0xbd, 0x11, 0xc0, 0xbc, 0xc0,
157 	0x11, 0xbd, 0x19, 0x2c, 0x4c, 0xd6, 0x8d, 0xcd,
158 };
159 static u32 sizeof_special2 = sizeof(sample_special2);
160 
161 static u8 sample_special3[] = {
162 	0x2a, 0xbc, 0x18, 0xcd, 0x11, 0x2c, 0x8c, 0xc1,
163 	0x4d, 0xd6, 0xbc, 0xd6, 0x4d, 0xc1, 0x8c, 0x2c,
164 	0x11, 0xcd, 0x18, 0xbc, 0x2a, 0xbd, 0x19, 0xcc,
165 	0x10, 0x2d, 0x8d, 0xc0, 0x4c, 0xd7, 0xbd, 0xd7,
166 	0x4c, 0xc0, 0x8d, 0x2d, 0x10, 0xcc, 0x19, 0xbd,
167 	0x2a, 0xbc, 0x18, 0xcd, 0x11, 0x2c, 0x8c, 0xc1,
168 	0x4d, 0xd6, 0xbc, 0xd6, 0x4d, 0xc1, 0x8c, 0x2c,
169 	0x11, 0xcd, 0x18, 0xbc, 0x2a, 0xbd, 0x19, 0xcc,
170 	0x10, 0x2d, 0x8d, 0xc0, 0x4c, 0xd7, 0xbd, 0xd7,
171 	0x4c, 0xc0, 0x8d, 0x2d, 0x10, 0xcc, 0x19, 0xbd,
172 };
173 static u32 sizeof_special3 = sizeof(sample_special3);
174 
175 static u8 sample_silence[] = {
176 	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
177 	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
178 	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
179 	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
180 	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
181 	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
182 	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
183 	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
184 	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
185 	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
186 	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
187 	0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
188 };
189 static u32 sizeof_silence = sizeof(sample_silence);
190 
191 struct tones_samples {
192 	u32 *len;
193 	u8 *data;
194 };
195 static struct
196 tones_samples samples[] = {
197 	{&sizeof_german_all, sample_german_all},
198 	{&sizeof_german_old, sample_german_old},
199 	{&sizeof_american_dialtone, sample_american_dialtone},
200 	{&sizeof_american_ringing, sample_american_ringing},
201 	{&sizeof_american_busy, sample_american_busy},
202 	{&sizeof_special1, sample_special1},
203 	{&sizeof_special2, sample_special2},
204 	{&sizeof_special3, sample_special3},
205 	{NULL, NULL},
206 };
207 
208 /***********************************
209  * generate ulaw from alaw samples *
210  ***********************************/
211 
212 void
213 dsp_audio_generate_ulaw_samples(void)
214 {
215 	int i, j;
216 
217 	i = 0;
218 	while (samples[i].len) {
219 		j = 0;
220 		while (j < (*samples[i].len)) {
221 			samples[i].data[j] =
222 				dsp_audio_alaw_to_ulaw[samples[i].data[j]];
223 			j++;
224 		}
225 		i++;
226 	}
227 }
228 
229 
230 /****************************
231  * tone sequence definition *
232  ****************************/
233 
234 static struct pattern {
235 	int tone;
236 	u8 *data[10];
237 	u32 *siz[10];
238 	u32 seq[10];
239 } pattern[] = {
240 	{TONE_GERMAN_DIALTONE,
241 	{DATA_GA, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
242 	{SIZE_GA, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
243 	{1900, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
244 
245 	{TONE_GERMAN_OLDDIALTONE,
246 	{DATA_GO, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
247 	{SIZE_GO, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
248 	{1998, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
249 
250 	{TONE_AMERICAN_DIALTONE,
251 	{DATA_DT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
252 	{SIZE_DT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
253 	{8000, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
254 
255 	{TONE_GERMAN_DIALPBX,
256 	{DATA_GA, DATA_S, DATA_GA, DATA_S, DATA_GA, DATA_S, NULL, NULL, NULL, NULL},
257 	{SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, NULL, NULL, NULL, NULL},
258 	{2000, 2000, 2000, 2000, 2000, 12000, 0, 0, 0, 0} },
259 
260 	{TONE_GERMAN_OLDDIALPBX,
261 	{DATA_GO, DATA_S, DATA_GO, DATA_S, DATA_GO, DATA_S, NULL, NULL, NULL, NULL},
262 	{SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, NULL, NULL, NULL, NULL},
263 	{2000, 2000, 2000, 2000, 2000, 12000, 0, 0, 0, 0} },
264 
265 	{TONE_AMERICAN_DIALPBX,
266 	{DATA_DT, DATA_S, DATA_DT, DATA_S, DATA_DT, DATA_S, NULL, NULL, NULL, NULL},
267 	{SIZE_DT, SIZE_S, SIZE_DT, SIZE_S, SIZE_DT, SIZE_S, NULL, NULL, NULL, NULL},
268 	{2000, 2000, 2000, 2000, 2000, 12000, 0, 0, 0, 0} },
269 
270 	{TONE_GERMAN_RINGING,
271 	{DATA_GA, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
272 	{SIZE_GA, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
273 	{8000, 32000, 0, 0, 0, 0, 0, 0, 0, 0} },
274 
275 	{TONE_GERMAN_OLDRINGING,
276 	{DATA_GO, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
277 	{SIZE_GO, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
278 	{8000, 40000, 0, 0, 0, 0, 0, 0, 0, 0} },
279 
280 	{TONE_AMERICAN_RINGING,
281 	{DATA_RI, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
282 	{SIZE_RI, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
283 	{8000, 32000, 0, 0, 0, 0, 0, 0, 0, 0} },
284 
285 	{TONE_GERMAN_RINGPBX,
286 	{DATA_GA, DATA_S, DATA_GA, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL},
287 	{SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL},
288 	{4000, 4000, 4000, 28000, 0, 0, 0, 0, 0, 0} },
289 
290 	{TONE_GERMAN_OLDRINGPBX,
291 	{DATA_GO, DATA_S, DATA_GO, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL},
292 	{SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL},
293 	{4000, 4000, 4000, 28000, 0, 0, 0, 0, 0, 0} },
294 
295 	{TONE_AMERICAN_RINGPBX,
296 	{DATA_RI, DATA_S, DATA_RI, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL},
297 	{SIZE_RI, SIZE_S, SIZE_RI, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL},
298 	{4000, 4000, 4000, 28000, 0, 0, 0, 0, 0, 0} },
299 
300 	{TONE_GERMAN_BUSY,
301 	{DATA_GA, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
302 	{SIZE_GA, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
303 	{4000, 4000, 0, 0, 0, 0, 0, 0, 0, 0} },
304 
305 	{TONE_GERMAN_OLDBUSY,
306 	{DATA_GO, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
307 	{SIZE_GO, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
308 	{1000, 5000, 0, 0, 0, 0, 0, 0, 0, 0} },
309 
310 	{TONE_AMERICAN_BUSY,
311 	{DATA_BU, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
312 	{SIZE_BU, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
313 	{4000, 4000, 0, 0, 0, 0, 0, 0, 0, 0} },
314 
315 	{TONE_GERMAN_HANGUP,
316 	{DATA_GA, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
317 	{SIZE_GA, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
318 	{4000, 4000, 0, 0, 0, 0, 0, 0, 0, 0} },
319 
320 	{TONE_GERMAN_OLDHANGUP,
321 	{DATA_GO, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
322 	{SIZE_GO, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
323 	{1000, 5000, 0, 0, 0, 0, 0, 0, 0, 0} },
324 
325 	{TONE_AMERICAN_HANGUP,
326 	{DATA_DT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
327 	{SIZE_DT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
328 	{8000, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
329 
330 	{TONE_SPECIAL_INFO,
331 	{DATA_S1, DATA_S2, DATA_S3, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL},
332 	{SIZE_S1, SIZE_S2, SIZE_S3, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL},
333 	{2666, 2666, 2666, 8002, 0, 0, 0, 0, 0, 0} },
334 
335 	{TONE_GERMAN_GASSENBESETZT,
336 	{DATA_GA, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
337 	{SIZE_GA, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
338 	{2000, 2000, 0, 0, 0, 0, 0, 0, 0, 0} },
339 
340 	{TONE_GERMAN_AUFSCHALTTON,
341 	{DATA_GO, DATA_S, DATA_GO, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL},
342 	{SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL},
343 	{1000, 5000, 1000, 17000, 0, 0, 0, 0, 0, 0} },
344 
345 	{0,
346 	{NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
347 	{NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
348 	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
349 };
350 
351 /******************
352  * copy tone data *
353  ******************/
354 
355 /* an sk_buff is generated from the number of samples needed.
356  * the count will be changed and may begin from 0 each pattern period.
357  * the clue is to precalculate the pointers and legths to use only one
358  * memcpy per function call, or two memcpy if the tone sequence changes.
359  *
360  * pattern - the type of the pattern
361  * count - the sample from the beginning of the pattern (phase)
362  * len - the number of bytes
363  *
364  * return - the sk_buff with the sample
365  *
366  * if tones has finished (e.g. knocking tone), dsp->tones is turned off
367  */
368 void dsp_tone_copy(struct dsp *dsp, u8 *data, int len)
369 {
370 	int index, count, start, num;
371 	struct pattern *pat;
372 	struct dsp_tone *tone = &dsp->tone;
373 
374 	/* if we have no tone, we copy silence */
375 	if (!tone->tone) {
376 		memset(data, dsp_silence, len);
377 		return;
378 	}
379 
380 	/* process pattern */
381 	pat = (struct pattern *)tone->pattern;
382 		/* points to the current pattern */
383 	index = tone->index; /* gives current sequence index */
384 	count = tone->count; /* gives current sample */
385 
386 	/* copy sample */
387 	while (len) {
388 		/* find sample to start with */
389 		while (42) {
390 			/* warp arround */
391 			if (!pat->seq[index]) {
392 				count = 0;
393 				index = 0;
394 			}
395 			/* check if we are currently playing this tone */
396 			if (count < pat->seq[index])
397 				break;
398 			if (dsp_debug & DEBUG_DSP_TONE)
399 				printk(KERN_DEBUG "%s: reaching next sequence "
400 					"(index=%d)\n", __func__, index);
401 			count -= pat->seq[index];
402 			index++;
403 		}
404 		/* calculate start and number of samples */
405 		start = count % (*(pat->siz[index]));
406 		num = len;
407 		if (num+count > pat->seq[index])
408 			num = pat->seq[index] - count;
409 		if (num+start > (*(pat->siz[index])))
410 			num = (*(pat->siz[index])) - start;
411 		/* copy memory */
412 		memcpy(data, pat->data[index]+start, num);
413 		/* reduce length */
414 		data += num;
415 		count += num;
416 		len -= num;
417 	}
418 	tone->index = index;
419 	tone->count = count;
420 
421 	/* return sk_buff */
422 	return;
423 }
424 
425 
426 /*******************************
427  * send HW message to hfc card *
428  *******************************/
429 
430 static void
431 dsp_tone_hw_message(struct dsp *dsp, u8 *sample, int len)
432 {
433 	struct sk_buff *nskb;
434 
435 	/* unlocking is not required, because we don't expect a response */
436 	nskb = _alloc_mISDN_skb(PH_CONTROL_REQ,
437 		(len)?HFC_SPL_LOOP_ON:HFC_SPL_LOOP_OFF, len, sample,
438 		GFP_ATOMIC);
439 	if (nskb) {
440 		if (dsp->ch.peer) {
441 			if (dsp->ch.recv(dsp->ch.peer, nskb))
442 				dev_kfree_skb(nskb);
443 		} else
444 			dev_kfree_skb(nskb);
445 	}
446 }
447 
448 
449 /*****************
450  * timer expires *
451  *****************/
452 void
453 dsp_tone_timeout(void *arg)
454 {
455 	struct dsp *dsp = arg;
456 	struct dsp_tone *tone = &dsp->tone;
457 	struct pattern *pat = (struct pattern *)tone->pattern;
458 	int index = tone->index;
459 
460 	if (!tone->tone)
461 		return;
462 
463 	index++;
464 	if (!pat->seq[index])
465 		index = 0;
466 	tone->index = index;
467 
468 	/* set next tone */
469 	if (pat->data[index] == DATA_S)
470 		dsp_tone_hw_message(dsp, NULL, 0);
471 	else
472 		dsp_tone_hw_message(dsp, pat->data[index], *(pat->siz[index]));
473 	/* set timer */
474 	init_timer(&tone->tl);
475 	tone->tl.expires = jiffies + (pat->seq[index] * HZ) / 8000;
476 	add_timer(&tone->tl);
477 }
478 
479 
480 /********************
481  * set/release tone *
482  ********************/
483 
484 /*
485  * tones are relaized by streaming or by special loop commands if supported
486  * by hardware. when hardware is used, the patterns will be controlled by
487  * timers.
488  */
489 int
490 dsp_tone(struct dsp *dsp, int tone)
491 {
492 	struct pattern *pat;
493 	int i;
494 	struct dsp_tone *tonet = &dsp->tone;
495 
496 	tonet->software = 0;
497 	tonet->hardware = 0;
498 
499 	/* we turn off the tone */
500 	if (!tone) {
501 		if (dsp->features.hfc_loops)
502 		if (timer_pending(&tonet->tl))
503 			del_timer(&tonet->tl);
504 		if (dsp->features.hfc_loops)
505 			dsp_tone_hw_message(dsp, NULL, 0);
506 		tonet->tone = 0;
507 		return 0;
508 	}
509 
510 	pat = NULL;
511 	i = 0;
512 	while (pattern[i].tone) {
513 		if (pattern[i].tone == tone) {
514 			pat = &pattern[i];
515 			break;
516 		}
517 		i++;
518 	}
519 	if (!pat) {
520 		printk(KERN_WARNING "dsp: given tone 0x%x is invalid\n", tone);
521 		return -EINVAL;
522 	}
523 	if (dsp_debug & DEBUG_DSP_TONE)
524 		printk(KERN_DEBUG "%s: now starting tone %d (index=%d)\n",
525 			__func__, tone, 0);
526 	tonet->tone = tone;
527 	tonet->pattern = pat;
528 	tonet->index = 0;
529 	tonet->count = 0;
530 
531 	if (dsp->features.hfc_loops) {
532 		tonet->hardware = 1;
533 		/* set first tone */
534 		dsp_tone_hw_message(dsp, pat->data[0], *(pat->siz[0]));
535 		/* set timer */
536 		if (timer_pending(&tonet->tl))
537 			del_timer(&tonet->tl);
538 		init_timer(&tonet->tl);
539 		tonet->tl.expires = jiffies + (pat->seq[0] * HZ) / 8000;
540 		add_timer(&tonet->tl);
541 	} else {
542 		tonet->software = 1;
543 	}
544 
545 	return 0;
546 }
547 
548 
549 
550 
551 
552