Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Add mISDN DSP

Enable support for digital audio processing capability.
This module may be used for special applications that require
cross connecting of bchannels, conferencing, dtmf decoding
echo cancelation, tone generation, and Blowfish encryption and
decryption.
It may use hardware features if available.

Signed-off-by: Karsten Keil <kkeil@suse.de>

+6028
+18
drivers/isdn/mISDN/Kconfig
··· 7 7 help 8 8 Enable support for the modular ISDN driver. 9 9 10 + if MISDN != n 11 + 12 + config MISDN_DSP 13 + tristate "Digital Audio Processing of transparent data" 14 + depends on MISDN 15 + help 16 + Enable support for digital audio processing capability. 17 + This module may be used for special applications that require 18 + cross connecting of bchannels, conferencing, dtmf decoding 19 + echo cancelation, tone generation, and Blowfish encryption and 20 + decryption. 21 + It may use hardware features if available. 22 + E.g. it is required for PBX4Linux. Go to http://isdn.eversberg.eu 23 + and get more informations about this module and it's usage. 24 + If unsure, say 'N'. 25 + 26 + source "drivers/isdn/hardware/mISDN/Kconfig" 27 + endif #MISDN
+2
drivers/isdn/mISDN/Makefile
··· 3 3 # 4 4 5 5 obj-$(CONFIG_MISDN) += mISDN_core.o 6 + obj-$(CONFIG_MISDN_DSP) += mISDN_dsp.o 6 7 7 8 # multi objects 8 9 9 10 mISDN_core-objs := core.o fsm.o socket.o hwchannel.o stack.o layer1.o layer2.o tei.o timerdev.o 11 + mISDN_dsp-objs := dsp_core.o dsp_cmx.o dsp_tones.o dsp_dtmf.o dsp_audio.o dsp_blowfish.o dsp_pipeline.o dsp_hwec.o
+263
drivers/isdn/mISDN/dsp.h
··· 1 + /* 2 + * Audio support data for ISDN4Linux. 3 + * 4 + * Copyright 2002/2003 by 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 + #define DEBUG_DSP_CTRL 0x0001 12 + #define DEBUG_DSP_CORE 0x0002 13 + #define DEBUG_DSP_DTMF 0x0004 14 + #define DEBUG_DSP_CMX 0x0010 15 + #define DEBUG_DSP_TONE 0x0020 16 + #define DEBUG_DSP_BLOWFISH 0x0040 17 + #define DEBUG_DSP_DELAY 0x0100 18 + #define DEBUG_DSP_DTMFCOEFF 0x8000 /* heavy output */ 19 + 20 + /* options may be: 21 + * 22 + * bit 0 = use ulaw instead of alaw 23 + * bit 1 = enable hfc hardware accelleration for all channels 24 + * 25 + */ 26 + #define DSP_OPT_ULAW (1<<0) 27 + #define DSP_OPT_NOHARDWARE (1<<1) 28 + 29 + #include <linux/timer.h> 30 + #include <linux/workqueue.h> 31 + 32 + #include "dsp_ecdis.h" 33 + 34 + extern int dsp_options; 35 + extern int dsp_debug; 36 + extern int dsp_poll; 37 + extern int dsp_tics; 38 + extern spinlock_t dsp_lock; 39 + extern struct work_struct dsp_workq; 40 + extern u32 dsp_poll_diff; /* calculated fix-comma corrected poll value */ 41 + 42 + /*************** 43 + * audio stuff * 44 + ***************/ 45 + 46 + extern s32 dsp_audio_alaw_to_s32[256]; 47 + extern s32 dsp_audio_ulaw_to_s32[256]; 48 + extern s32 *dsp_audio_law_to_s32; 49 + extern u8 dsp_audio_s16_to_law[65536]; 50 + extern u8 dsp_audio_alaw_to_ulaw[256]; 51 + extern u8 dsp_audio_mix_law[65536]; 52 + extern u8 dsp_audio_seven2law[128]; 53 + extern u8 dsp_audio_law2seven[256]; 54 + extern void dsp_audio_generate_law_tables(void); 55 + extern void dsp_audio_generate_s2law_table(void); 56 + extern void dsp_audio_generate_seven(void); 57 + extern void dsp_audio_generate_mix_table(void); 58 + extern void dsp_audio_generate_ulaw_samples(void); 59 + extern void dsp_audio_generate_volume_changes(void); 60 + extern u8 dsp_silence; 61 + 62 + 63 + /************* 64 + * cmx stuff * 65 + *************/ 66 + 67 + #define MAX_POLL 256 /* maximum number of send-chunks */ 68 + 69 + #define CMX_BUFF_SIZE 0x8000 /* must be 2**n (0x1000 about 1/2 second) */ 70 + #define CMX_BUFF_HALF 0x4000 /* CMX_BUFF_SIZE / 2 */ 71 + #define CMX_BUFF_MASK 0x7fff /* CMX_BUFF_SIZE - 1 */ 72 + 73 + /* how many seconds will we check the lowest delay until the jitter buffer 74 + is reduced by that delay */ 75 + #define MAX_SECONDS_JITTER_CHECK 5 76 + 77 + extern struct timer_list dsp_spl_tl; 78 + extern u32 dsp_spl_jiffies; 79 + 80 + /* the structure of conferences: 81 + * 82 + * each conference has a unique number, given by user space. 83 + * the conferences are linked in a chain. 84 + * each conference has members linked in a chain. 85 + * each dsplayer points to a member, each member points to a dsplayer. 86 + */ 87 + 88 + /* all members within a conference (this is linked 1:1 with the dsp) */ 89 + struct dsp; 90 + struct dsp_conf_member { 91 + struct list_head list; 92 + struct dsp *dsp; 93 + }; 94 + 95 + /* the list of all conferences */ 96 + struct dsp_conf { 97 + struct list_head list; 98 + u32 id; 99 + /* all cmx stacks with the same ID are 100 + connected */ 101 + struct list_head mlist; 102 + int software; /* conf is processed by software */ 103 + int hardware; /* conf is processed by hardware */ 104 + /* note: if both unset, has only one member */ 105 + }; 106 + 107 + 108 + /************** 109 + * DTMF stuff * 110 + **************/ 111 + 112 + #define DSP_DTMF_NPOINTS 102 113 + 114 + #define ECHOCAN_BUFLEN (4*128) 115 + 116 + struct dsp_dtmf { 117 + int treshold; /* above this is dtmf (square of) */ 118 + int software; /* dtmf uses software decoding */ 119 + int hardware; /* dtmf uses hardware decoding */ 120 + int size; /* number of bytes in buffer */ 121 + signed short buffer[DSP_DTMF_NPOINTS]; 122 + /* buffers one full dtmf frame */ 123 + u8 lastwhat, lastdigit; 124 + int count; 125 + u8 digits[16]; /* just the dtmf result */ 126 + }; 127 + 128 + 129 + /****************** 130 + * pipeline stuff * 131 + ******************/ 132 + struct dsp_pipeline { 133 + rwlock_t lock; 134 + struct list_head list; 135 + int inuse; 136 + }; 137 + 138 + /*************** 139 + * tones stuff * 140 + ***************/ 141 + 142 + struct dsp_tone { 143 + int software; /* tones are generated by software */ 144 + int hardware; /* tones are generated by hardware */ 145 + int tone; 146 + void *pattern; 147 + int count; 148 + int index; 149 + struct timer_list tl; 150 + }; 151 + 152 + /***************** 153 + * general stuff * 154 + *****************/ 155 + 156 + struct dsp { 157 + struct list_head list; 158 + struct mISDNchannel ch; 159 + struct mISDNchannel *up; 160 + unsigned char name[64]; 161 + int b_active; 162 + int echo; /* echo is enabled */ 163 + int rx_disabled; /* what the user wants */ 164 + int rx_is_off; /* what the card is */ 165 + int tx_mix; 166 + struct dsp_tone tone; 167 + struct dsp_dtmf dtmf; 168 + int tx_volume, rx_volume; 169 + 170 + /* queue for sending frames */ 171 + struct work_struct workq; 172 + struct sk_buff_head sendq; 173 + int hdlc; /* if mode is hdlc */ 174 + int data_pending; /* currently an unconfirmed frame */ 175 + 176 + /* conference stuff */ 177 + u32 conf_id; 178 + struct dsp_conf *conf; 179 + struct dsp_conf_member 180 + *member; 181 + 182 + /* buffer stuff */ 183 + int rx_W; /* current write pos for data without timestamp */ 184 + int rx_R; /* current read pos for transmit clock */ 185 + int rx_init; /* if set, pointers will be adjusted first */ 186 + int tx_W; /* current write pos for transmit data */ 187 + int tx_R; /* current read pos for transmit clock */ 188 + int rx_delay[MAX_SECONDS_JITTER_CHECK]; 189 + int tx_delay[MAX_SECONDS_JITTER_CHECK]; 190 + u8 tx_buff[CMX_BUFF_SIZE]; 191 + u8 rx_buff[CMX_BUFF_SIZE]; 192 + int last_tx; /* if set, we transmitted last poll interval */ 193 + int cmx_delay; /* initial delay of buffers, 194 + or 0 for dynamic jitter buffer */ 195 + int tx_dejitter; /* if set, dejitter tx buffer */ 196 + int tx_data; /* enables tx-data of CMX to upper layer */ 197 + 198 + /* hardware stuff */ 199 + struct dsp_features features; 200 + int features_rx_off; /* set if rx_off is featured */ 201 + int pcm_slot_rx; /* current PCM slot (or -1) */ 202 + int pcm_bank_rx; 203 + int pcm_slot_tx; 204 + int pcm_bank_tx; 205 + int hfc_conf; /* unique id of current conference (or -1) */ 206 + 207 + /* encryption stuff */ 208 + int bf_enable; 209 + u32 bf_p[18]; 210 + u32 bf_s[1024]; 211 + int bf_crypt_pos; 212 + u8 bf_data_in[9]; 213 + u8 bf_crypt_out[9]; 214 + int bf_decrypt_in_pos; 215 + int bf_decrypt_out_pos; 216 + u8 bf_crypt_inring[16]; 217 + u8 bf_data_out[9]; 218 + int bf_sync; 219 + 220 + struct dsp_pipeline 221 + pipeline; 222 + }; 223 + 224 + /* functions */ 225 + 226 + extern void dsp_change_volume(struct sk_buff *skb, int volume); 227 + 228 + extern struct list_head dsp_ilist; 229 + extern struct list_head conf_ilist; 230 + extern void dsp_cmx_debug(struct dsp *dsp); 231 + extern void dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp); 232 + extern int dsp_cmx_conf(struct dsp *dsp, u32 conf_id); 233 + extern void dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb); 234 + extern void dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb); 235 + extern void dsp_cmx_send(void *arg); 236 + extern void dsp_cmx_transmit(struct dsp *dsp, struct sk_buff *skb); 237 + extern int dsp_cmx_del_conf_member(struct dsp *dsp); 238 + extern int dsp_cmx_del_conf(struct dsp_conf *conf); 239 + 240 + extern void dsp_dtmf_goertzel_init(struct dsp *dsp); 241 + extern void dsp_dtmf_hardware(struct dsp *dsp); 242 + extern u8 *dsp_dtmf_goertzel_decode(struct dsp *dsp, u8 *data, int len, 243 + int fmt); 244 + 245 + extern int dsp_tone(struct dsp *dsp, int tone); 246 + extern void dsp_tone_copy(struct dsp *dsp, u8 *data, int len); 247 + extern void dsp_tone_timeout(void *arg); 248 + 249 + extern void dsp_bf_encrypt(struct dsp *dsp, u8 *data, int len); 250 + extern void dsp_bf_decrypt(struct dsp *dsp, u8 *data, int len); 251 + extern int dsp_bf_init(struct dsp *dsp, const u8 *key, unsigned int keylen); 252 + extern void dsp_bf_cleanup(struct dsp *dsp); 253 + 254 + extern int dsp_pipeline_module_init(void); 255 + extern void dsp_pipeline_module_exit(void); 256 + extern int dsp_pipeline_init(struct dsp_pipeline *pipeline); 257 + extern void dsp_pipeline_destroy(struct dsp_pipeline *pipeline); 258 + extern int dsp_pipeline_build(struct dsp_pipeline *pipeline, const char *cfg); 259 + extern void dsp_pipeline_process_tx(struct dsp_pipeline *pipeline, u8 *data, 260 + int len); 261 + extern void dsp_pipeline_process_rx(struct dsp_pipeline *pipeline, u8 *data, 262 + int len); 263 +
+434
drivers/isdn/mISDN/dsp_audio.c
··· 1 + /* 2 + * Audio support data for mISDN_dsp. 3 + * 4 + * Copyright 2002/2003 by Andreas Eversberg (jolly@eversberg.eu) 5 + * Rewritten by Peter 6 + * 7 + * This software may be used and distributed according to the terms 8 + * of the GNU General Public License, incorporated herein by reference. 9 + * 10 + */ 11 + 12 + #include <linux/delay.h> 13 + #include <linux/mISDNif.h> 14 + #include <linux/mISDNdsp.h> 15 + #include "core.h" 16 + #include "dsp.h" 17 + 18 + /* ulaw[unsigned char] -> signed 16-bit */ 19 + s32 dsp_audio_ulaw_to_s32[256]; 20 + /* alaw[unsigned char] -> signed 16-bit */ 21 + s32 dsp_audio_alaw_to_s32[256]; 22 + 23 + s32 *dsp_audio_law_to_s32; 24 + EXPORT_SYMBOL(dsp_audio_law_to_s32); 25 + 26 + /* signed 16-bit -> law */ 27 + u8 dsp_audio_s16_to_law[65536]; 28 + EXPORT_SYMBOL(dsp_audio_s16_to_law); 29 + 30 + /* alaw -> ulaw */ 31 + u8 dsp_audio_alaw_to_ulaw[256]; 32 + /* ulaw -> alaw */ 33 + u8 dsp_audio_ulaw_to_alaw[256]; 34 + u8 dsp_silence; 35 + 36 + 37 + /***************************************************** 38 + * generate table for conversion of s16 to alaw/ulaw * 39 + *****************************************************/ 40 + 41 + #define AMI_MASK 0x55 42 + 43 + static inline unsigned char linear2alaw(short int linear) 44 + { 45 + int mask; 46 + int seg; 47 + int pcm_val; 48 + static int seg_end[8] = { 49 + 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF 50 + }; 51 + 52 + pcm_val = linear; 53 + if (pcm_val >= 0) { 54 + /* Sign (7th) bit = 1 */ 55 + mask = AMI_MASK | 0x80; 56 + } else { 57 + /* Sign bit = 0 */ 58 + mask = AMI_MASK; 59 + pcm_val = -pcm_val; 60 + } 61 + 62 + /* Convert the scaled magnitude to segment number. */ 63 + for (seg = 0; seg < 8; seg++) { 64 + if (pcm_val <= seg_end[seg]) 65 + break; 66 + } 67 + /* Combine the sign, segment, and quantization bits. */ 68 + return ((seg << 4) | 69 + ((pcm_val >> ((seg) ? (seg + 3) : 4)) & 0x0F)) ^ mask; 70 + } 71 + 72 + 73 + static inline short int alaw2linear(unsigned char alaw) 74 + { 75 + int i; 76 + int seg; 77 + 78 + alaw ^= AMI_MASK; 79 + i = ((alaw & 0x0F) << 4) + 8 /* rounding error */; 80 + seg = (((int) alaw & 0x70) >> 4); 81 + if (seg) 82 + i = (i + 0x100) << (seg - 1); 83 + return (short int) ((alaw & 0x80) ? i : -i); 84 + } 85 + 86 + static inline short int ulaw2linear(unsigned char ulaw) 87 + { 88 + short mu, e, f, y; 89 + static short etab[] = {0, 132, 396, 924, 1980, 4092, 8316, 16764}; 90 + 91 + mu = 255 - ulaw; 92 + e = (mu & 0x70) / 16; 93 + f = mu & 0x0f; 94 + y = f * (1 << (e + 3)); 95 + y += etab[e]; 96 + if (mu & 0x80) 97 + y = -y; 98 + return y; 99 + } 100 + 101 + #define BIAS 0x84 /*!< define the add-in bias for 16 bit samples */ 102 + 103 + static unsigned char linear2ulaw(short sample) 104 + { 105 + static int exp_lut[256] = { 106 + 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 107 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 108 + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 109 + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 110 + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 111 + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 112 + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 113 + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 114 + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 115 + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 116 + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 117 + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 118 + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 119 + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 120 + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 121 + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7}; 122 + int sign, exponent, mantissa; 123 + unsigned char ulawbyte; 124 + 125 + /* Get the sample into sign-magnitude. */ 126 + sign = (sample >> 8) & 0x80; /* set aside the sign */ 127 + if (sign != 0) 128 + sample = -sample; /* get magnitude */ 129 + 130 + /* Convert from 16 bit linear to ulaw. */ 131 + sample = sample + BIAS; 132 + exponent = exp_lut[(sample >> 7) & 0xFF]; 133 + mantissa = (sample >> (exponent + 3)) & 0x0F; 134 + ulawbyte = ~(sign | (exponent << 4) | mantissa); 135 + 136 + return ulawbyte; 137 + } 138 + 139 + static int reverse_bits(int i) 140 + { 141 + int z, j; 142 + z = 0; 143 + 144 + for (j = 0; j < 8; j++) { 145 + if ((i & (1 << j)) != 0) 146 + z |= 1 << (7 - j); 147 + } 148 + return z; 149 + } 150 + 151 + 152 + void dsp_audio_generate_law_tables(void) 153 + { 154 + int i; 155 + for (i = 0; i < 256; i++) 156 + dsp_audio_alaw_to_s32[i] = alaw2linear(reverse_bits(i)); 157 + 158 + for (i = 0; i < 256; i++) 159 + dsp_audio_ulaw_to_s32[i] = ulaw2linear(reverse_bits(i)); 160 + 161 + for (i = 0; i < 256; i++) { 162 + dsp_audio_alaw_to_ulaw[i] = 163 + linear2ulaw(dsp_audio_alaw_to_s32[i]); 164 + dsp_audio_ulaw_to_alaw[i] = 165 + linear2alaw(dsp_audio_ulaw_to_s32[i]); 166 + } 167 + } 168 + 169 + void 170 + dsp_audio_generate_s2law_table(void) 171 + { 172 + int i; 173 + 174 + if (dsp_options & DSP_OPT_ULAW) { 175 + /* generating ulaw-table */ 176 + for (i = -32768; i < 32768; i++) { 177 + dsp_audio_s16_to_law[i & 0xffff] = 178 + reverse_bits(linear2ulaw(i)); 179 + } 180 + } else { 181 + /* generating alaw-table */ 182 + for (i = -32768; i < 32768; i++) { 183 + dsp_audio_s16_to_law[i & 0xffff] = 184 + reverse_bits(linear2alaw(i)); 185 + } 186 + } 187 + } 188 + 189 + 190 + /* 191 + * the seven bit sample is the number of every second alaw-sample ordered by 192 + * aplitude. 0x00 is negative, 0x7f is positive amplitude. 193 + */ 194 + u8 dsp_audio_seven2law[128]; 195 + u8 dsp_audio_law2seven[256]; 196 + 197 + /******************************************************************** 198 + * generate table for conversion law from/to 7-bit alaw-like sample * 199 + ********************************************************************/ 200 + 201 + void 202 + dsp_audio_generate_seven(void) 203 + { 204 + int i, j, k; 205 + u8 spl; 206 + u8 sorted_alaw[256]; 207 + 208 + /* generate alaw table, sorted by the linear value */ 209 + for (i = 0; i < 256; i++) { 210 + j = 0; 211 + for (k = 0; k < 256; k++) { 212 + if (dsp_audio_alaw_to_s32[k] 213 + < dsp_audio_alaw_to_s32[i]) { 214 + j++; 215 + } 216 + } 217 + sorted_alaw[j] = i; 218 + } 219 + 220 + /* generate tabels */ 221 + for (i = 0; i < 256; i++) { 222 + /* spl is the source: the law-sample (converted to alaw) */ 223 + spl = i; 224 + if (dsp_options & DSP_OPT_ULAW) 225 + spl = dsp_audio_ulaw_to_alaw[i]; 226 + /* find the 7-bit-sample */ 227 + for (j = 0; j < 256; j++) { 228 + if (sorted_alaw[j] == spl) 229 + break; 230 + } 231 + /* write 7-bit audio value */ 232 + dsp_audio_law2seven[i] = j >> 1; 233 + } 234 + for (i = 0; i < 128; i++) { 235 + spl = sorted_alaw[i << 1]; 236 + if (dsp_options & DSP_OPT_ULAW) 237 + spl = dsp_audio_alaw_to_ulaw[spl]; 238 + dsp_audio_seven2law[i] = spl; 239 + } 240 + } 241 + 242 + 243 + /* mix 2*law -> law */ 244 + u8 dsp_audio_mix_law[65536]; 245 + 246 + /****************************************************** 247 + * generate mix table to mix two law samples into one * 248 + ******************************************************/ 249 + 250 + void 251 + dsp_audio_generate_mix_table(void) 252 + { 253 + int i, j; 254 + s32 sample; 255 + 256 + i = 0; 257 + while (i < 256) { 258 + j = 0; 259 + while (j < 256) { 260 + sample = dsp_audio_law_to_s32[i]; 261 + sample += dsp_audio_law_to_s32[j]; 262 + if (sample > 32767) 263 + sample = 32767; 264 + if (sample < -32768) 265 + sample = -32768; 266 + dsp_audio_mix_law[(i<<8)|j] = 267 + dsp_audio_s16_to_law[sample & 0xffff]; 268 + j++; 269 + } 270 + i++; 271 + } 272 + } 273 + 274 + 275 + /************************************* 276 + * generate different volume changes * 277 + *************************************/ 278 + 279 + static u8 dsp_audio_reduce8[256]; 280 + static u8 dsp_audio_reduce7[256]; 281 + static u8 dsp_audio_reduce6[256]; 282 + static u8 dsp_audio_reduce5[256]; 283 + static u8 dsp_audio_reduce4[256]; 284 + static u8 dsp_audio_reduce3[256]; 285 + static u8 dsp_audio_reduce2[256]; 286 + static u8 dsp_audio_reduce1[256]; 287 + static u8 dsp_audio_increase1[256]; 288 + static u8 dsp_audio_increase2[256]; 289 + static u8 dsp_audio_increase3[256]; 290 + static u8 dsp_audio_increase4[256]; 291 + static u8 dsp_audio_increase5[256]; 292 + static u8 dsp_audio_increase6[256]; 293 + static u8 dsp_audio_increase7[256]; 294 + static u8 dsp_audio_increase8[256]; 295 + 296 + static u8 *dsp_audio_volume_change[16] = { 297 + dsp_audio_reduce8, 298 + dsp_audio_reduce7, 299 + dsp_audio_reduce6, 300 + dsp_audio_reduce5, 301 + dsp_audio_reduce4, 302 + dsp_audio_reduce3, 303 + dsp_audio_reduce2, 304 + dsp_audio_reduce1, 305 + dsp_audio_increase1, 306 + dsp_audio_increase2, 307 + dsp_audio_increase3, 308 + dsp_audio_increase4, 309 + dsp_audio_increase5, 310 + dsp_audio_increase6, 311 + dsp_audio_increase7, 312 + dsp_audio_increase8, 313 + }; 314 + 315 + void 316 + dsp_audio_generate_volume_changes(void) 317 + { 318 + register s32 sample; 319 + int i; 320 + int num[] = { 110, 125, 150, 175, 200, 300, 400, 500 }; 321 + int denum[] = { 100, 100, 100, 100, 100, 100, 100, 100 }; 322 + 323 + i = 0; 324 + while (i < 256) { 325 + dsp_audio_reduce8[i] = dsp_audio_s16_to_law[ 326 + (dsp_audio_law_to_s32[i] * denum[7] / num[7]) & 0xffff]; 327 + dsp_audio_reduce7[i] = dsp_audio_s16_to_law[ 328 + (dsp_audio_law_to_s32[i] * denum[6] / num[6]) & 0xffff]; 329 + dsp_audio_reduce6[i] = dsp_audio_s16_to_law[ 330 + (dsp_audio_law_to_s32[i] * denum[5] / num[5]) & 0xffff]; 331 + dsp_audio_reduce5[i] = dsp_audio_s16_to_law[ 332 + (dsp_audio_law_to_s32[i] * denum[4] / num[4]) & 0xffff]; 333 + dsp_audio_reduce4[i] = dsp_audio_s16_to_law[ 334 + (dsp_audio_law_to_s32[i] * denum[3] / num[3]) & 0xffff]; 335 + dsp_audio_reduce3[i] = dsp_audio_s16_to_law[ 336 + (dsp_audio_law_to_s32[i] * denum[2] / num[2]) & 0xffff]; 337 + dsp_audio_reduce2[i] = dsp_audio_s16_to_law[ 338 + (dsp_audio_law_to_s32[i] * denum[1] / num[1]) & 0xffff]; 339 + dsp_audio_reduce1[i] = dsp_audio_s16_to_law[ 340 + (dsp_audio_law_to_s32[i] * denum[0] / num[0]) & 0xffff]; 341 + sample = dsp_audio_law_to_s32[i] * num[0] / denum[0]; 342 + if (sample < -32768) 343 + sample = -32768; 344 + else if (sample > 32767) 345 + sample = 32767; 346 + dsp_audio_increase1[i] = dsp_audio_s16_to_law[sample & 0xffff]; 347 + sample = dsp_audio_law_to_s32[i] * num[1] / denum[1]; 348 + if (sample < -32768) 349 + sample = -32768; 350 + else if (sample > 32767) 351 + sample = 32767; 352 + dsp_audio_increase2[i] = dsp_audio_s16_to_law[sample & 0xffff]; 353 + sample = dsp_audio_law_to_s32[i] * num[2] / denum[2]; 354 + if (sample < -32768) 355 + sample = -32768; 356 + else if (sample > 32767) 357 + sample = 32767; 358 + dsp_audio_increase3[i] = dsp_audio_s16_to_law[sample & 0xffff]; 359 + sample = dsp_audio_law_to_s32[i] * num[3] / denum[3]; 360 + if (sample < -32768) 361 + sample = -32768; 362 + else if (sample > 32767) 363 + sample = 32767; 364 + dsp_audio_increase4[i] = dsp_audio_s16_to_law[sample & 0xffff]; 365 + sample = dsp_audio_law_to_s32[i] * num[4] / denum[4]; 366 + if (sample < -32768) 367 + sample = -32768; 368 + else if (sample > 32767) 369 + sample = 32767; 370 + dsp_audio_increase5[i] = dsp_audio_s16_to_law[sample & 0xffff]; 371 + sample = dsp_audio_law_to_s32[i] * num[5] / denum[5]; 372 + if (sample < -32768) 373 + sample = -32768; 374 + else if (sample > 32767) 375 + sample = 32767; 376 + dsp_audio_increase6[i] = dsp_audio_s16_to_law[sample & 0xffff]; 377 + sample = dsp_audio_law_to_s32[i] * num[6] / denum[6]; 378 + if (sample < -32768) 379 + sample = -32768; 380 + else if (sample > 32767) 381 + sample = 32767; 382 + dsp_audio_increase7[i] = dsp_audio_s16_to_law[sample & 0xffff]; 383 + sample = dsp_audio_law_to_s32[i] * num[7] / denum[7]; 384 + if (sample < -32768) 385 + sample = -32768; 386 + else if (sample > 32767) 387 + sample = 32767; 388 + dsp_audio_increase8[i] = dsp_audio_s16_to_law[sample & 0xffff]; 389 + 390 + i++; 391 + } 392 + } 393 + 394 + 395 + /************************************** 396 + * change the volume of the given skb * 397 + **************************************/ 398 + 399 + /* this is a helper function for changing volume of skb. the range may be 400 + * -8 to 8, which is a shift to the power of 2. 0 == no volume, 3 == volume*8 401 + */ 402 + void 403 + dsp_change_volume(struct sk_buff *skb, int volume) 404 + { 405 + u8 *volume_change; 406 + int i, ii; 407 + u8 *p; 408 + int shift; 409 + 410 + if (volume == 0) 411 + return; 412 + 413 + /* get correct conversion table */ 414 + if (volume < 0) { 415 + shift = volume + 8; 416 + if (shift < 0) 417 + shift = 0; 418 + } else { 419 + shift = volume + 7; 420 + if (shift > 15) 421 + shift = 15; 422 + } 423 + volume_change = dsp_audio_volume_change[shift]; 424 + i = 0; 425 + ii = skb->len; 426 + p = skb->data; 427 + /* change volume */ 428 + while (i < ii) { 429 + *p = volume_change[*p]; 430 + p++; 431 + i++; 432 + } 433 + } 434 +
+65
drivers/isdn/mISDN/dsp_biquad.h
··· 1 + /* 2 + * SpanDSP - a series of DSP components for telephony 3 + * 4 + * biquad.h - General telephony bi-quad section routines (currently this just 5 + * handles canonic/type 2 form) 6 + * 7 + * Written by Steve Underwood <steveu@coppice.org> 8 + * 9 + * Copyright (C) 2001 Steve Underwood 10 + * 11 + * All rights reserved. 12 + * 13 + * This program is free software; you can redistribute it and/or modify 14 + * it under the terms of the GNU General Public License as published by 15 + * the Free Software Foundation; either version 2 of the License, or 16 + * (at your option) any later version. 17 + * 18 + * This program is distributed in the hope that it will be useful, 19 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 + * GNU General Public License for more details. 22 + * 23 + * You should have received a copy of the GNU General Public License 24 + * along with this program; if not, write to the Free Software 25 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 26 + * 27 + */ 28 + 29 + struct biquad2_state { 30 + int32_t gain; 31 + int32_t a1; 32 + int32_t a2; 33 + int32_t b1; 34 + int32_t b2; 35 + 36 + int32_t z1; 37 + int32_t z2; 38 + }; 39 + 40 + static inline void biquad2_init(struct biquad2_state *bq, 41 + int32_t gain, int32_t a1, int32_t a2, int32_t b1, int32_t b2) 42 + { 43 + bq->gain = gain; 44 + bq->a1 = a1; 45 + bq->a2 = a2; 46 + bq->b1 = b1; 47 + bq->b2 = b2; 48 + 49 + bq->z1 = 0; 50 + bq->z2 = 0; 51 + } 52 + 53 + static inline int16_t biquad2(struct biquad2_state *bq, int16_t sample) 54 + { 55 + int32_t y; 56 + int32_t z0; 57 + 58 + z0 = sample*bq->gain + bq->z1*bq->a1 + bq->z2*bq->a2; 59 + y = z0 + bq->z1*bq->b1 + bq->z2*bq->b2; 60 + 61 + bq->z2 = bq->z1; 62 + bq->z1 = z0 >> 15; 63 + y >>= 15; 64 + return y; 65 + }
+672
drivers/isdn/mISDN/dsp_blowfish.c
··· 1 + /* 2 + * Blowfish encryption/decryption for mISDN_dsp. 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 + * how to encode a sample stream to 64-bit blocks that will be encryped 18 + * 19 + * first of all, data is collected until a block of 9 samples are received. 20 + * of course, a packet may have much more than 9 sample, but is may have 21 + * not excacly the multiple of 9 samples. if there is a rest, the next 22 + * received data will complete the block. 23 + * 24 + * the block is then converted to 9 uLAW samples without the least sigificant 25 + * bit. the result is a 7-bit encoded sample. 26 + * 27 + * the samples will be reoganised to form 8 bytes of data: 28 + * (5(6) means: encoded sample no. 5, bit 6) 29 + * 30 + * 0(6) 0(5) 0(4) 0(3) 0(2) 0(1) 0(0) 1(6) 31 + * 1(5) 1(4) 1(3) 1(2) 1(1) 1(0) 2(6) 2(5) 32 + * 2(4) 2(3) 2(2) 2(1) 2(0) 3(6) 3(5) 3(4) 33 + * 3(3) 3(2) 3(1) 3(0) 4(6) 4(5) 4(4) 4(3) 34 + * 4(2) 4(1) 4(0) 5(6) 5(5) 5(4) 5(3) 5(2) 35 + * 5(1) 5(0) 6(6) 6(5) 6(4) 6(3) 6(2) 6(1) 36 + * 6(0) 7(6) 7(5) 7(4) 7(3) 7(2) 7(1) 7(0) 37 + * 8(6) 8(5) 8(4) 8(3) 8(2) 8(1) 8(0) 38 + * 39 + * the missing bit 0 of the last byte is filled with some 40 + * random noise, to fill all 8 bytes. 41 + * 42 + * the 8 bytes will be encrypted using blowfish. 43 + * 44 + * the result will be converted into 9 bytes. the bit 7 is used for 45 + * checksumme (CS) for sync (0, 1) and for the last bit: 46 + * (5(6) means: crypted byte 5, bit 6) 47 + * 48 + * 1 0(7) 0(6) 0(5) 0(4) 0(3) 0(2) 0(1) 49 + * 0 0(0) 1(7) 1(6) 1(5) 1(4) 1(3) 1(2) 50 + * 0 1(1) 1(0) 2(7) 2(6) 2(5) 2(4) 2(3) 51 + * 0 2(2) 2(1) 2(0) 3(7) 3(6) 3(5) 3(4) 52 + * 0 3(3) 3(2) 3(1) 3(0) 4(7) 4(6) 4(5) 53 + * CS 4(4) 4(3) 4(2) 4(1) 4(0) 5(7) 5(6) 54 + * CS 5(5) 5(4) 5(3) 5(2) 5(1) 5(0) 6(7) 55 + * CS 6(6) 6(5) 6(4) 6(3) 6(2) 6(1) 6(0) 56 + * 7(0) 7(6) 7(5) 7(4) 7(3) 7(2) 7(1) 7(0) 57 + * 58 + * the checksum is used to detect transmission errors and frame drops. 59 + * 60 + * synchronisation of received block is done by shifting the upper bit of each 61 + * byte (bit 7) to a shift register. if the rigister has the first five bits 62 + * (10000), this is used to find the sync. only if sync has been found, the 63 + * current block of 9 received bytes are decrypted. before that the check 64 + * sum is calculated. if it is incorrect the block is dropped. 65 + * this will avoid loud noise due to corrupt encrypted data. 66 + * 67 + * if the last block is corrupt, the current decoded block is repeated 68 + * until a valid block has been received. 69 + */ 70 + 71 + /* 72 + * some blowfish parts are taken from the 73 + * crypto-api for faster implementation 74 + */ 75 + 76 + struct bf_ctx { 77 + u32 p[18]; 78 + u32 s[1024]; 79 + }; 80 + 81 + static const u32 bf_pbox[16 + 2] = { 82 + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 83 + 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, 84 + 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 85 + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 86 + 0x9216d5d9, 0x8979fb1b, 87 + }; 88 + 89 + static const u32 bf_sbox[256 * 4] = { 90 + 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 91 + 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, 92 + 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 93 + 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 94 + 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 95 + 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, 96 + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 97 + 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, 98 + 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 99 + 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 100 + 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 101 + 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 102 + 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 103 + 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, 104 + 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 105 + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 106 + 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 107 + 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, 108 + 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 109 + 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, 110 + 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 111 + 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 112 + 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 113 + 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, 114 + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 115 + 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 116 + 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 117 + 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 118 + 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 119 + 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, 120 + 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 121 + 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, 122 + 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 123 + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 124 + 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 125 + 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 126 + 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 127 + 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, 128 + 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 129 + 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 130 + 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 131 + 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, 132 + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 133 + 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 134 + 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 135 + 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 136 + 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 137 + 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, 138 + 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 139 + 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 140 + 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 141 + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 142 + 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 143 + 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, 144 + 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 145 + 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 146 + 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 147 + 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 148 + 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 149 + 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, 150 + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 151 + 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, 152 + 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 153 + 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a, 154 + 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 155 + 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, 156 + 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 157 + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 158 + 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 159 + 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 160 + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 161 + 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, 162 + 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 163 + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 164 + 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 165 + 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 166 + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 167 + 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, 168 + 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 169 + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 170 + 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 171 + 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, 172 + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 173 + 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, 174 + 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 175 + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 176 + 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 177 + 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, 178 + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 179 + 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, 180 + 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 181 + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 182 + 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 183 + 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, 184 + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 185 + 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, 186 + 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 187 + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 188 + 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 189 + 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 190 + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 191 + 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, 192 + 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 193 + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 194 + 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 195 + 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 196 + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 197 + 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, 198 + 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 199 + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 200 + 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 201 + 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 202 + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 203 + 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, 204 + 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 205 + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 206 + 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 207 + 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, 208 + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 209 + 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, 210 + 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 211 + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 212 + 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 213 + 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, 214 + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 215 + 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, 216 + 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 217 + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7, 218 + 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 219 + 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, 220 + 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 221 + 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 222 + 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 223 + 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, 224 + 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 225 + 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 226 + 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 227 + 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 228 + 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 229 + 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, 230 + 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 231 + 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 232 + 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 233 + 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 234 + 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 235 + 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, 236 + 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 237 + 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, 238 + 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 239 + 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 240 + 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 241 + 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, 242 + 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 243 + 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, 244 + 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 245 + 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 246 + 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 247 + 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, 248 + 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 249 + 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, 250 + 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 251 + 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 252 + 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 253 + 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, 254 + 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 255 + 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 256 + 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 257 + 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 258 + 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 259 + 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, 260 + 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 261 + 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, 262 + 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 263 + 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 264 + 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 265 + 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 266 + 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 267 + 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 268 + 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 269 + 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 270 + 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 271 + 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, 272 + 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 273 + 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, 274 + 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 275 + 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 276 + 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 277 + 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, 278 + 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 279 + 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, 280 + 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 281 + 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0, 282 + 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 283 + 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, 284 + 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 285 + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 286 + 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 287 + 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, 288 + 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 289 + 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, 290 + 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 291 + 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 292 + 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 293 + 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, 294 + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 295 + 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, 296 + 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 297 + 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 298 + 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 299 + 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, 300 + 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 301 + 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, 302 + 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 303 + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 304 + 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 305 + 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, 306 + 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 307 + 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, 308 + 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 309 + 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 310 + 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 311 + 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, 312 + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 313 + 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, 314 + 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 315 + 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 316 + 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 317 + 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, 318 + 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 319 + 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, 320 + 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 321 + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 322 + 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 323 + 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, 324 + 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 325 + 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, 326 + 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 327 + 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 328 + 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 329 + 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, 330 + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 331 + 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, 332 + 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 333 + 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 334 + 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 335 + 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 336 + 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 337 + 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, 338 + 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 339 + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 340 + 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 341 + 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, 342 + 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 343 + 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, 344 + 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 345 + 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6, 346 + }; 347 + 348 + /* 349 + * Round loop unrolling macros, S is a pointer to a S-Box array 350 + * organized in 4 unsigned longs at a row. 351 + */ 352 + #define GET32_3(x) (((x) & 0xff)) 353 + #define GET32_2(x) (((x) >> (8)) & (0xff)) 354 + #define GET32_1(x) (((x) >> (16)) & (0xff)) 355 + #define GET32_0(x) (((x) >> (24)) & (0xff)) 356 + 357 + #define bf_F(x) (((S[GET32_0(x)] + S[256 + GET32_1(x)]) ^ \ 358 + S[512 + GET32_2(x)]) + S[768 + GET32_3(x)]) 359 + 360 + #define EROUND(a, b, n) do { b ^= P[n]; a ^= bf_F(b); } while (0) 361 + #define DROUND(a, b, n) do { a ^= bf_F(b); b ^= P[n]; } while (0) 362 + 363 + 364 + /* 365 + * encrypt isdn data frame 366 + * every block with 9 samples is encrypted 367 + */ 368 + void 369 + dsp_bf_encrypt(struct dsp *dsp, u8 *data, int len) 370 + { 371 + int i = 0, j = dsp->bf_crypt_pos; 372 + u8 *bf_data_in = dsp->bf_data_in; 373 + u8 *bf_crypt_out = dsp->bf_crypt_out; 374 + u32 *P = dsp->bf_p; 375 + u32 *S = dsp->bf_s; 376 + u32 yl, yr; 377 + u32 cs; 378 + u8 nibble; 379 + 380 + while (i < len) { 381 + /* collect a block of 9 samples */ 382 + if (j < 9) { 383 + bf_data_in[j] = *data; 384 + *data++ = bf_crypt_out[j++]; 385 + i++; 386 + continue; 387 + } 388 + j = 0; 389 + /* transcode 9 samples xlaw to 8 bytes */ 390 + yl = dsp_audio_law2seven[bf_data_in[0]]; 391 + yl = (yl<<7) | dsp_audio_law2seven[bf_data_in[1]]; 392 + yl = (yl<<7) | dsp_audio_law2seven[bf_data_in[2]]; 393 + yl = (yl<<7) | dsp_audio_law2seven[bf_data_in[3]]; 394 + nibble = dsp_audio_law2seven[bf_data_in[4]]; 395 + yr = nibble; 396 + yl = (yl<<4) | (nibble>>3); 397 + yr = (yr<<7) | dsp_audio_law2seven[bf_data_in[5]]; 398 + yr = (yr<<7) | dsp_audio_law2seven[bf_data_in[6]]; 399 + yr = (yr<<7) | dsp_audio_law2seven[bf_data_in[7]]; 400 + yr = (yr<<7) | dsp_audio_law2seven[bf_data_in[8]]; 401 + yr = (yr<<1) | (bf_data_in[0] & 1); 402 + 403 + /* fill unused bit with random noise of audio input */ 404 + /* encrypt */ 405 + 406 + EROUND(yr, yl, 0); 407 + EROUND(yl, yr, 1); 408 + EROUND(yr, yl, 2); 409 + EROUND(yl, yr, 3); 410 + EROUND(yr, yl, 4); 411 + EROUND(yl, yr, 5); 412 + EROUND(yr, yl, 6); 413 + EROUND(yl, yr, 7); 414 + EROUND(yr, yl, 8); 415 + EROUND(yl, yr, 9); 416 + EROUND(yr, yl, 10); 417 + EROUND(yl, yr, 11); 418 + EROUND(yr, yl, 12); 419 + EROUND(yl, yr, 13); 420 + EROUND(yr, yl, 14); 421 + EROUND(yl, yr, 15); 422 + yl ^= P[16]; 423 + yr ^= P[17]; 424 + 425 + /* calculate 3-bit checksumme */ 426 + cs = yl ^ (yl>>3) ^ (yl>>6) ^ (yl>>9) ^ (yl>>12) ^ (yl>>15) 427 + ^ (yl>>18) ^ (yl>>21) ^ (yl>>24) ^ (yl>>27) ^ (yl>>30) 428 + ^ (yr<<2) ^ (yr>>1) ^ (yr>>4) ^ (yr>>7) ^ (yr>>10) 429 + ^ (yr>>13) ^ (yr>>16) ^ (yr>>19) ^ (yr>>22) ^ (yr>>25) 430 + ^ (yr>>28) ^ (yr>>31); 431 + 432 + /* 433 + * transcode 8 crypted bytes to 9 data bytes with sync 434 + * and checksum information 435 + */ 436 + bf_crypt_out[0] = (yl>>25) | 0x80; 437 + bf_crypt_out[1] = (yl>>18) & 0x7f; 438 + bf_crypt_out[2] = (yl>>11) & 0x7f; 439 + bf_crypt_out[3] = (yl>>4) & 0x7f; 440 + bf_crypt_out[4] = ((yl<<3) & 0x78) | ((yr>>29) & 0x07); 441 + bf_crypt_out[5] = ((yr>>22) & 0x7f) | ((cs<<5) & 0x80); 442 + bf_crypt_out[6] = ((yr>>15) & 0x7f) | ((cs<<6) & 0x80); 443 + bf_crypt_out[7] = ((yr>>8) & 0x7f) | (cs<<7); 444 + bf_crypt_out[8] = yr; 445 + } 446 + 447 + /* write current count */ 448 + dsp->bf_crypt_pos = j; 449 + 450 + } 451 + 452 + 453 + /* 454 + * decrypt isdn data frame 455 + * every block with 9 bytes is decrypted 456 + */ 457 + void 458 + dsp_bf_decrypt(struct dsp *dsp, u8 *data, int len) 459 + { 460 + int i = 0; 461 + u8 j = dsp->bf_decrypt_in_pos; 462 + u8 k = dsp->bf_decrypt_out_pos; 463 + u8 *bf_crypt_inring = dsp->bf_crypt_inring; 464 + u8 *bf_data_out = dsp->bf_data_out; 465 + u16 sync = dsp->bf_sync; 466 + u32 *P = dsp->bf_p; 467 + u32 *S = dsp->bf_s; 468 + u32 yl, yr; 469 + u8 nibble; 470 + u8 cs, cs0, cs1, cs2; 471 + 472 + while (i < len) { 473 + /* 474 + * shift upper bit and rotate data to buffer ring 475 + * send current decrypted data 476 + */ 477 + sync = (sync<<1) | ((*data)>>7); 478 + bf_crypt_inring[j++ & 15] = *data; 479 + *data++ = bf_data_out[k++]; 480 + i++; 481 + if (k == 9) 482 + k = 0; /* repeat if no sync has been found */ 483 + /* check if not in sync */ 484 + if ((sync&0x1f0) != 0x100) 485 + continue; 486 + j -= 9; 487 + /* transcode receive data to 64 bit block of encrypted data */ 488 + yl = bf_crypt_inring[j++ & 15]; 489 + yl = (yl<<7) | bf_crypt_inring[j++ & 15]; /* bit7 = 0 */ 490 + yl = (yl<<7) | bf_crypt_inring[j++ & 15]; /* bit7 = 0 */ 491 + yl = (yl<<7) | bf_crypt_inring[j++ & 15]; /* bit7 = 0 */ 492 + nibble = bf_crypt_inring[j++ & 15]; /* bit7 = 0 */ 493 + yr = nibble; 494 + yl = (yl<<4) | (nibble>>3); 495 + cs2 = bf_crypt_inring[j++ & 15]; 496 + yr = (yr<<7) | (cs2 & 0x7f); 497 + cs1 = bf_crypt_inring[j++ & 15]; 498 + yr = (yr<<7) | (cs1 & 0x7f); 499 + cs0 = bf_crypt_inring[j++ & 15]; 500 + yr = (yr<<7) | (cs0 & 0x7f); 501 + yr = (yr<<8) | bf_crypt_inring[j++ & 15]; 502 + 503 + /* calculate 3-bit checksumme */ 504 + cs = yl ^ (yl>>3) ^ (yl>>6) ^ (yl>>9) ^ (yl>>12) ^ (yl>>15) 505 + ^ (yl>>18) ^ (yl>>21) ^ (yl>>24) ^ (yl>>27) ^ (yl>>30) 506 + ^ (yr<<2) ^ (yr>>1) ^ (yr>>4) ^ (yr>>7) ^ (yr>>10) 507 + ^ (yr>>13) ^ (yr>>16) ^ (yr>>19) ^ (yr>>22) ^ (yr>>25) 508 + ^ (yr>>28) ^ (yr>>31); 509 + 510 + /* check if frame is valid */ 511 + if ((cs&0x7) != (((cs2>>5)&4) | ((cs1>>6)&2) | (cs0 >> 7))) { 512 + if (dsp_debug & DEBUG_DSP_BLOWFISH) 513 + printk(KERN_DEBUG 514 + "DSP BLOWFISH: received corrupt frame, " 515 + "checksumme is not correct\n"); 516 + continue; 517 + } 518 + 519 + /* decrypt */ 520 + yr ^= P[17]; 521 + yl ^= P[16]; 522 + DROUND(yl, yr, 15); 523 + DROUND(yr, yl, 14); 524 + DROUND(yl, yr, 13); 525 + DROUND(yr, yl, 12); 526 + DROUND(yl, yr, 11); 527 + DROUND(yr, yl, 10); 528 + DROUND(yl, yr, 9); 529 + DROUND(yr, yl, 8); 530 + DROUND(yl, yr, 7); 531 + DROUND(yr, yl, 6); 532 + DROUND(yl, yr, 5); 533 + DROUND(yr, yl, 4); 534 + DROUND(yl, yr, 3); 535 + DROUND(yr, yl, 2); 536 + DROUND(yl, yr, 1); 537 + DROUND(yr, yl, 0); 538 + 539 + /* transcode 8 crypted bytes to 9 sample bytes */ 540 + bf_data_out[0] = dsp_audio_seven2law[(yl>>25) & 0x7f]; 541 + bf_data_out[1] = dsp_audio_seven2law[(yl>>18) & 0x7f]; 542 + bf_data_out[2] = dsp_audio_seven2law[(yl>>11) & 0x7f]; 543 + bf_data_out[3] = dsp_audio_seven2law[(yl>>4) & 0x7f]; 544 + bf_data_out[4] = dsp_audio_seven2law[((yl<<3) & 0x78) | 545 + ((yr>>29) & 0x07)]; 546 + 547 + bf_data_out[5] = dsp_audio_seven2law[(yr>>22) & 0x7f]; 548 + bf_data_out[6] = dsp_audio_seven2law[(yr>>15) & 0x7f]; 549 + bf_data_out[7] = dsp_audio_seven2law[(yr>>8) & 0x7f]; 550 + bf_data_out[8] = dsp_audio_seven2law[(yr>>1) & 0x7f]; 551 + k = 0; /* start with new decoded frame */ 552 + } 553 + 554 + /* write current count and sync */ 555 + dsp->bf_decrypt_in_pos = j; 556 + dsp->bf_decrypt_out_pos = k; 557 + dsp->bf_sync = sync; 558 + } 559 + 560 + 561 + /* used to encrypt S and P boxes */ 562 + static inline void 563 + encrypt_block(const u32 *P, const u32 *S, u32 *dst, u32 *src) 564 + { 565 + u32 yl = src[0]; 566 + u32 yr = src[1]; 567 + 568 + EROUND(yr, yl, 0); 569 + EROUND(yl, yr, 1); 570 + EROUND(yr, yl, 2); 571 + EROUND(yl, yr, 3); 572 + EROUND(yr, yl, 4); 573 + EROUND(yl, yr, 5); 574 + EROUND(yr, yl, 6); 575 + EROUND(yl, yr, 7); 576 + EROUND(yr, yl, 8); 577 + EROUND(yl, yr, 9); 578 + EROUND(yr, yl, 10); 579 + EROUND(yl, yr, 11); 580 + EROUND(yr, yl, 12); 581 + EROUND(yl, yr, 13); 582 + EROUND(yr, yl, 14); 583 + EROUND(yl, yr, 15); 584 + 585 + yl ^= P[16]; 586 + yr ^= P[17]; 587 + 588 + dst[0] = yr; 589 + dst[1] = yl; 590 + } 591 + 592 + /* 593 + * initialize the dsp for encryption and decryption using the same key 594 + * Calculates the blowfish S and P boxes for encryption and decryption. 595 + * The margin of keylen must be 4-56 bytes. 596 + * returns 0 if ok. 597 + */ 598 + int 599 + dsp_bf_init(struct dsp *dsp, const u8 *key, uint keylen) 600 + { 601 + short i, j, count; 602 + u32 data[2], temp; 603 + u32 *P = (u32 *)dsp->bf_p; 604 + u32 *S = (u32 *)dsp->bf_s; 605 + 606 + if (keylen < 4 || keylen > 56) 607 + return 1; 608 + 609 + /* Set dsp states */ 610 + i = 0; 611 + while (i < 9) { 612 + dsp->bf_crypt_out[i] = 0xff; 613 + dsp->bf_data_out[i] = dsp_silence; 614 + i++; 615 + } 616 + dsp->bf_crypt_pos = 0; 617 + dsp->bf_decrypt_in_pos = 0; 618 + dsp->bf_decrypt_out_pos = 0; 619 + dsp->bf_sync = 0x1ff; 620 + dsp->bf_enable = 1; 621 + 622 + /* Copy the initialization s-boxes */ 623 + for (i = 0, count = 0; i < 256; i++) 624 + for (j = 0; j < 4; j++, count++) 625 + S[count] = bf_sbox[count]; 626 + 627 + /* Set the p-boxes */ 628 + for (i = 0; i < 16 + 2; i++) 629 + P[i] = bf_pbox[i]; 630 + 631 + /* Actual subkey generation */ 632 + for (j = 0, i = 0; i < 16 + 2; i++) { 633 + temp = (((u32)key[j] << 24) | 634 + ((u32)key[(j + 1) % keylen] << 16) | 635 + ((u32)key[(j + 2) % keylen] << 8) | 636 + ((u32)key[(j + 3) % keylen])); 637 + 638 + P[i] = P[i] ^ temp; 639 + j = (j + 4) % keylen; 640 + } 641 + 642 + data[0] = 0x00000000; 643 + data[1] = 0x00000000; 644 + 645 + for (i = 0; i < 16 + 2; i += 2) { 646 + encrypt_block(P, S, data, data); 647 + 648 + P[i] = data[0]; 649 + P[i + 1] = data[1]; 650 + } 651 + 652 + for (i = 0; i < 4; i++) { 653 + for (j = 0, count = i * 256; j < 256; j += 2, count += 2) { 654 + encrypt_block(P, S, data, data); 655 + 656 + S[count] = data[0]; 657 + S[count + 1] = data[1]; 658 + } 659 + } 660 + 661 + return 0; 662 + } 663 + 664 + 665 + /* 666 + * turn encryption off 667 + */ 668 + void 669 + dsp_bf_cleanup(struct dsp *dsp) 670 + { 671 + dsp->bf_enable = 0; 672 + }
+1886
drivers/isdn/mISDN/dsp_cmx.c
··· 1 + /* 2 + * Audio crossconnecting/conferrencing (hardware level). 3 + * 4 + * Copyright 2002 by 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 + /* 12 + * The process of adding and removing parties to/from a conference: 13 + * 14 + * There is a chain of struct dsp_conf which has one or more members in a chain 15 + * of struct dsp_conf_member. 16 + * 17 + * After a party is added, the conference is checked for hardware capability. 18 + * Also if a party is removed, the conference is checked again. 19 + * 20 + * There are 3 different solutions: -1 = software, 0 = hardware-crossconnect 21 + * 1-n = hardware-conference. The n will give the conference number. 22 + * 23 + * Depending on the change after removal or insertion of a party, hardware 24 + * commands are given. 25 + * 26 + * The current solution is stored within the struct dsp_conf entry. 27 + */ 28 + 29 + /* 30 + * HOW THE CMX WORKS: 31 + * 32 + * There are 3 types of interaction: One member is alone, in this case only 33 + * data flow from upper to lower layer is done. 34 + * Two members will also exchange their data so they are crossconnected. 35 + * Three or more members will be added in a conference and will hear each 36 + * other but will not receive their own speech (echo) if not enabled. 37 + * 38 + * Features of CMX are: 39 + * - Crossconnecting or even conference, if more than two members are together. 40 + * - Force mixing of transmit data with other crossconnect/conference members. 41 + * - Echo generation to benchmark the delay of audio processing. 42 + * - Use hardware to minimize cpu load, disable FIFO load and minimize delay. 43 + * - Dejittering and clock generation. 44 + * 45 + * There are 2 buffers: 46 + * 47 + * 48 + * RX-Buffer 49 + * R W 50 + * | | 51 + * ----------------+-------------+------------------- 52 + * 53 + * The rx-buffer is a ring buffer used to store the received data for each 54 + * individual member. This is only the case if data needs to be dejittered 55 + * or in case of a conference where different clocks require reclocking. 56 + * The transmit-clock (R) will read the buffer. 57 + * If the clock overruns the write-pointer, we will have a buffer underrun. 58 + * If the write pointer always has a certain distance from the transmit- 59 + * clock, we will have a delay. The delay will dynamically be increased and 60 + * reduced. 61 + * 62 + * 63 + * TX-Buffer 64 + * R W 65 + * | | 66 + * -----------------+--------+----------------------- 67 + * 68 + * The tx-buffer is a ring buffer to queue the transmit data from user space 69 + * until it will be mixed or sent. There are two pointers, R and W. If the write 70 + * pointer W would reach or overrun R, the buffer would overrun. In this case 71 + * (some) data is dropped so that it will not overrun. 72 + * Additionally a dynamic dejittering can be enabled. this allows data from 73 + * user space that have jitter and different clock source. 74 + * 75 + * 76 + * Clock: 77 + * 78 + * A Clock is not required, if the data source has exactly one clock. In this 79 + * case the data source is forwarded to the destination. 80 + * 81 + * A Clock is required, because the data source 82 + * - has multiple clocks. 83 + * - has no usable clock due to jitter or packet loss (VoIP). 84 + * In this case the system's clock is used. The clock resolution depends on 85 + * the jiffie resolution. 86 + * 87 + * If a member joins a conference: 88 + * 89 + * - If a member joins, its rx_buff is set to silence and change read pointer 90 + * to transmit clock. 91 + * 92 + * The procedure of received data from card is explained in cmx_receive. 93 + * The procedure of received data from user space is explained in cmx_transmit. 94 + * The procedure of transmit data to card is cmx_send. 95 + * 96 + * 97 + * Interaction with other features: 98 + * 99 + * DTMF: 100 + * DTMF decoding is done before the data is crossconnected. 101 + * 102 + * Volume change: 103 + * Changing rx-volume is done before the data is crossconnected. The tx-volume 104 + * must be changed whenever data is transmitted to the card by the cmx. 105 + * 106 + * Tones: 107 + * If a tone is enabled, it will be processed whenever data is transmitted to 108 + * the card. It will replace the tx-data from the user space. 109 + * If tones are generated by hardware, this conference member is removed for 110 + * this time. 111 + * 112 + * Disable rx-data: 113 + * If cmx is realized in hardware, rx data will be disabled if requested by 114 + * the upper layer. If dtmf decoding is done by software and enabled, rx data 115 + * will not be diabled but blocked to the upper layer. 116 + * 117 + * HFC conference engine: 118 + * If it is possible to realize all features using hardware, hardware will be 119 + * used if not forbidden by control command. Disabling rx-data provides 120 + * absolutely traffic free audio processing. (except for the quick 1-frame 121 + * upload of a tone loop, only once for a new tone) 122 + * 123 + */ 124 + 125 + /* delay.h is required for hw_lock.h */ 126 + 127 + #include <linux/delay.h> 128 + #include <linux/mISDNif.h> 129 + #include <linux/mISDNdsp.h> 130 + #include "core.h" 131 + #include "dsp.h" 132 + /* 133 + * debugging of multi party conference, 134 + * by using conference even with two members 135 + */ 136 + 137 + /* #define CMX_CONF_DEBUG */ 138 + 139 + /*#define CMX_DEBUG * massive read/write pointer output */ 140 + /*#define CMX_TX_DEBUG * massive read/write on tx-buffer with content */ 141 + 142 + static inline int 143 + count_list_member(struct list_head *head) 144 + { 145 + int cnt = 0; 146 + struct list_head *m; 147 + 148 + list_for_each(m, head) 149 + cnt++; 150 + return cnt; 151 + } 152 + 153 + /* 154 + * debug cmx memory structure 155 + */ 156 + void 157 + dsp_cmx_debug(struct dsp *dsp) 158 + { 159 + struct dsp_conf *conf; 160 + struct dsp_conf_member *member; 161 + struct dsp *odsp; 162 + 163 + printk(KERN_DEBUG "-----Current DSP\n"); 164 + list_for_each_entry(odsp, &dsp_ilist, list) { 165 + printk(KERN_DEBUG "* %s echo=%d txmix=%d", 166 + odsp->name, odsp->echo, odsp->tx_mix); 167 + if (odsp->conf) 168 + printk(" (Conf %d)", odsp->conf->id); 169 + if (dsp == odsp) 170 + printk(" *this*"); 171 + printk("\n"); 172 + } 173 + printk(KERN_DEBUG "-----Current Conf:\n"); 174 + list_for_each_entry(conf, &conf_ilist, list) { 175 + printk(KERN_DEBUG "* Conf %d (%p)\n", conf->id, conf); 176 + list_for_each_entry(member, &conf->mlist, list) { 177 + printk(KERN_DEBUG 178 + " - member = %s (slot_tx %d, bank_tx %d, " 179 + "slot_rx %d, bank_rx %d hfc_conf %d)%s\n", 180 + member->dsp->name, member->dsp->pcm_slot_tx, 181 + member->dsp->pcm_bank_tx, member->dsp->pcm_slot_rx, 182 + member->dsp->pcm_bank_rx, member->dsp->hfc_conf, 183 + (member->dsp == dsp) ? " *this*" : ""); 184 + } 185 + } 186 + printk(KERN_DEBUG "-----end\n"); 187 + } 188 + 189 + /* 190 + * search conference 191 + */ 192 + static struct dsp_conf * 193 + dsp_cmx_search_conf(u32 id) 194 + { 195 + struct dsp_conf *conf; 196 + 197 + if (!id) { 198 + printk(KERN_WARNING "%s: conference ID is 0.\n", __func__); 199 + return NULL; 200 + } 201 + 202 + /* search conference */ 203 + list_for_each_entry(conf, &conf_ilist, list) 204 + if (conf->id == id) 205 + return conf; 206 + 207 + return NULL; 208 + } 209 + 210 + 211 + /* 212 + * add member to conference 213 + */ 214 + static int 215 + dsp_cmx_add_conf_member(struct dsp *dsp, struct dsp_conf *conf) 216 + { 217 + struct dsp_conf_member *member; 218 + 219 + if (!conf || !dsp) { 220 + printk(KERN_WARNING "%s: conf or dsp is 0.\n", __func__); 221 + return -EINVAL; 222 + } 223 + if (dsp->member) { 224 + printk(KERN_WARNING "%s: dsp is already member in a conf.\n", 225 + __func__); 226 + return -EINVAL; 227 + } 228 + 229 + if (dsp->conf) { 230 + printk(KERN_WARNING "%s: dsp is already in a conf.\n", 231 + __func__); 232 + return -EINVAL; 233 + } 234 + 235 + member = kzalloc(sizeof(struct dsp_conf_member), GFP_ATOMIC); 236 + if (!member) { 237 + printk(KERN_ERR "kmalloc struct dsp_conf_member failed\n"); 238 + return -ENOMEM; 239 + } 240 + member->dsp = dsp; 241 + /* clear rx buffer */ 242 + memset(dsp->rx_buff, dsp_silence, sizeof(dsp->rx_buff)); 243 + dsp->rx_init = 1; /* rx_W and rx_R will be adjusted on first frame */ 244 + dsp->rx_W = 0; 245 + dsp->rx_R = 0; 246 + 247 + list_add_tail(&member->list, &conf->mlist); 248 + 249 + dsp->conf = conf; 250 + dsp->member = member; 251 + 252 + return 0; 253 + } 254 + 255 + 256 + /* 257 + * del member from conference 258 + */ 259 + int 260 + dsp_cmx_del_conf_member(struct dsp *dsp) 261 + { 262 + struct dsp_conf_member *member; 263 + 264 + if (!dsp) { 265 + printk(KERN_WARNING "%s: dsp is 0.\n", 266 + __func__); 267 + return -EINVAL; 268 + } 269 + 270 + if (!dsp->conf) { 271 + printk(KERN_WARNING "%s: dsp is not in a conf.\n", 272 + __func__); 273 + return -EINVAL; 274 + } 275 + 276 + if (list_empty(&dsp->conf->mlist)) { 277 + printk(KERN_WARNING "%s: dsp has linked an empty conf.\n", 278 + __func__); 279 + return -EINVAL; 280 + } 281 + 282 + /* find us in conf */ 283 + list_for_each_entry(member, &dsp->conf->mlist, list) { 284 + if (member->dsp == dsp) { 285 + list_del(&member->list); 286 + dsp->conf = NULL; 287 + dsp->member = NULL; 288 + kfree(member); 289 + return 0; 290 + } 291 + } 292 + printk(KERN_WARNING 293 + "%s: dsp is not present in its own conf_meber list.\n", 294 + __func__); 295 + 296 + return -EINVAL; 297 + } 298 + 299 + 300 + /* 301 + * new conference 302 + */ 303 + static struct dsp_conf 304 + *dsp_cmx_new_conf(u32 id) 305 + { 306 + struct dsp_conf *conf; 307 + 308 + if (!id) { 309 + printk(KERN_WARNING "%s: id is 0.\n", 310 + __func__); 311 + return NULL; 312 + } 313 + 314 + conf = kzalloc(sizeof(struct dsp_conf), GFP_ATOMIC); 315 + if (!conf) { 316 + printk(KERN_ERR "kmalloc struct dsp_conf failed\n"); 317 + return NULL; 318 + } 319 + INIT_LIST_HEAD(&conf->mlist); 320 + conf->id = id; 321 + 322 + list_add_tail(&conf->list, &conf_ilist); 323 + 324 + return conf; 325 + } 326 + 327 + 328 + /* 329 + * del conference 330 + */ 331 + int 332 + dsp_cmx_del_conf(struct dsp_conf *conf) 333 + { 334 + if (!conf) { 335 + printk(KERN_WARNING "%s: conf is null.\n", 336 + __func__); 337 + return -EINVAL; 338 + } 339 + 340 + if (!list_empty(&conf->mlist)) { 341 + printk(KERN_WARNING "%s: conf not empty.\n", 342 + __func__); 343 + return -EINVAL; 344 + } 345 + list_del(&conf->list); 346 + kfree(conf); 347 + 348 + return 0; 349 + } 350 + 351 + 352 + /* 353 + * send HW message to hfc card 354 + */ 355 + static void 356 + dsp_cmx_hw_message(struct dsp *dsp, u32 message, u32 param1, u32 param2, 357 + u32 param3, u32 param4) 358 + { 359 + struct mISDN_ctrl_req cq; 360 + 361 + memset(&cq, 0, sizeof(cq)); 362 + cq.op = message; 363 + cq.p1 = param1 | (param2 << 8); 364 + cq.p2 = param3 | (param4 << 8); 365 + if (dsp->ch.peer) 366 + dsp->ch.peer->ctrl(dsp->ch.peer, CONTROL_CHANNEL, &cq); 367 + } 368 + 369 + 370 + /* 371 + * do hardware update and set the software/hardware flag 372 + * 373 + * either a conference or a dsp instance can be given 374 + * if only dsp instance is given, the instance is not associated with a conf 375 + * and therefore removed. if a conference is given, the dsp is expected to 376 + * be member of that conference. 377 + */ 378 + void 379 + dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp) 380 + { 381 + struct dsp_conf_member *member, *nextm; 382 + struct dsp *finddsp; 383 + int memb = 0, i, ii, i1, i2; 384 + int freeunits[8]; 385 + u_char freeslots[256]; 386 + int same_hfc = -1, same_pcm = -1, current_conf = -1, 387 + all_conf = 1; 388 + 389 + /* dsp gets updated (no conf) */ 390 + if (!conf) { 391 + if (!dsp) 392 + return; 393 + if (dsp_debug & DEBUG_DSP_CMX) 394 + printk(KERN_DEBUG "%s checking dsp %s\n", 395 + __func__, dsp->name); 396 + one_member: 397 + /* remove HFC conference if enabled */ 398 + if (dsp->hfc_conf >= 0) { 399 + if (dsp_debug & DEBUG_DSP_CMX) 400 + printk(KERN_DEBUG 401 + "%s removing %s from HFC conf %d " 402 + "because dsp is split\n", __func__, 403 + dsp->name, dsp->hfc_conf); 404 + dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_CONF_SPLIT, 405 + 0, 0, 0, 0); 406 + dsp->hfc_conf = -1; 407 + } 408 + /* process hw echo */ 409 + if (dsp->features.pcm_banks < 1) 410 + return; 411 + if (!dsp->echo) { 412 + /* NO ECHO: remove PCM slot if assigned */ 413 + if (dsp->pcm_slot_tx >= 0 || dsp->pcm_slot_rx >= 0) { 414 + if (dsp_debug & DEBUG_DSP_CMX) 415 + printk(KERN_DEBUG "%s removing %s from" 416 + " PCM slot %d (TX) %d (RX) because" 417 + " dsp is split (no echo)\n", 418 + __func__, dsp->name, 419 + dsp->pcm_slot_tx, dsp->pcm_slot_rx); 420 + dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_DISC, 421 + 0, 0, 0, 0); 422 + dsp->pcm_slot_tx = -1; 423 + dsp->pcm_bank_tx = -1; 424 + dsp->pcm_slot_rx = -1; 425 + dsp->pcm_bank_rx = -1; 426 + } 427 + return; 428 + } 429 + /* ECHO: already echo */ 430 + if (dsp->pcm_slot_tx >= 0 && dsp->pcm_slot_rx < 0 && 431 + dsp->pcm_bank_tx == 2 && dsp->pcm_bank_rx == 2) 432 + return; 433 + /* ECHO: if slot already assigned */ 434 + if (dsp->pcm_slot_tx >= 0) { 435 + dsp->pcm_slot_rx = dsp->pcm_slot_tx; 436 + dsp->pcm_bank_tx = 2; /* 2 means loop */ 437 + dsp->pcm_bank_rx = 2; 438 + if (dsp_debug & DEBUG_DSP_CMX) 439 + printk(KERN_DEBUG 440 + "%s refresh %s for echo using slot %d\n", 441 + __func__, dsp->name, 442 + dsp->pcm_slot_tx); 443 + dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_CONN, 444 + dsp->pcm_slot_tx, 2, dsp->pcm_slot_rx, 2); 445 + return; 446 + } 447 + /* ECHO: find slot */ 448 + dsp->pcm_slot_tx = -1; 449 + dsp->pcm_slot_rx = -1; 450 + memset(freeslots, 1, sizeof(freeslots)); 451 + list_for_each_entry(finddsp, &dsp_ilist, list) { 452 + if (finddsp->features.pcm_id == dsp->features.pcm_id) { 453 + if (finddsp->pcm_slot_rx >= 0 && 454 + finddsp->pcm_slot_rx < sizeof(freeslots)) 455 + freeslots[finddsp->pcm_slot_tx] = 0; 456 + if (finddsp->pcm_slot_tx >= 0 && 457 + finddsp->pcm_slot_tx < sizeof(freeslots)) 458 + freeslots[finddsp->pcm_slot_rx] = 0; 459 + } 460 + } 461 + i = 0; 462 + ii = dsp->features.pcm_slots; 463 + while (i < ii) { 464 + if (freeslots[i]) 465 + break; 466 + i++; 467 + } 468 + if (i == ii) { 469 + if (dsp_debug & DEBUG_DSP_CMX) 470 + printk(KERN_DEBUG 471 + "%s no slot available for echo\n", 472 + __func__); 473 + /* no more slots available */ 474 + return; 475 + } 476 + /* assign free slot */ 477 + dsp->pcm_slot_tx = i; 478 + dsp->pcm_slot_rx = i; 479 + dsp->pcm_bank_tx = 2; /* loop */ 480 + dsp->pcm_bank_rx = 2; 481 + if (dsp_debug & DEBUG_DSP_CMX) 482 + printk(KERN_DEBUG 483 + "%s assign echo for %s using slot %d\n", 484 + __func__, dsp->name, dsp->pcm_slot_tx); 485 + dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_CONN, 486 + dsp->pcm_slot_tx, 2, dsp->pcm_slot_rx, 2); 487 + return; 488 + } 489 + 490 + /* conf gets updated (all members) */ 491 + if (dsp_debug & DEBUG_DSP_CMX) 492 + printk(KERN_DEBUG "%s checking conference %d\n", 493 + __func__, conf->id); 494 + 495 + if (list_empty(&conf->mlist)) { 496 + printk(KERN_ERR "%s: conference whithout members\n", 497 + __func__); 498 + return; 499 + } 500 + member = list_entry(conf->mlist.next, struct dsp_conf_member, list); 501 + same_hfc = member->dsp->features.hfc_id; 502 + same_pcm = member->dsp->features.pcm_id; 503 + /* check all members in our conference */ 504 + list_for_each_entry(member, &conf->mlist, list) { 505 + /* check if member uses mixing */ 506 + if (member->dsp->tx_mix) { 507 + if (dsp_debug & DEBUG_DSP_CMX) 508 + printk(KERN_DEBUG 509 + "%s dsp %s cannot form a conf, because " 510 + "tx_mix is turned on\n", __func__, 511 + member->dsp->name); 512 + conf_software: 513 + list_for_each_entry(member, &conf->mlist, list) { 514 + dsp = member->dsp; 515 + /* remove HFC conference if enabled */ 516 + if (dsp->hfc_conf >= 0) { 517 + if (dsp_debug & DEBUG_DSP_CMX) 518 + printk(KERN_DEBUG 519 + "%s removing %s from HFC " 520 + "conf %d because not " 521 + "possible with hardware\n", 522 + __func__, 523 + dsp->name, 524 + dsp->hfc_conf); 525 + dsp_cmx_hw_message(dsp, 526 + MISDN_CTRL_HFC_CONF_SPLIT, 527 + 0, 0, 0, 0); 528 + dsp->hfc_conf = -1; 529 + } 530 + /* remove PCM slot if assigned */ 531 + if (dsp->pcm_slot_tx >= 0 || 532 + dsp->pcm_slot_rx >= 0) { 533 + if (dsp_debug & DEBUG_DSP_CMX) 534 + printk(KERN_DEBUG "%s removing " 535 + "%s from PCM slot %d (TX)" 536 + " slot %d (RX) because not" 537 + " possible with hardware\n", 538 + __func__, 539 + dsp->name, 540 + dsp->pcm_slot_tx, 541 + dsp->pcm_slot_rx); 542 + dsp_cmx_hw_message(dsp, 543 + MISDN_CTRL_HFC_PCM_DISC, 544 + 0, 0, 0, 0); 545 + dsp->pcm_slot_tx = -1; 546 + dsp->pcm_bank_tx = -1; 547 + dsp->pcm_slot_rx = -1; 548 + dsp->pcm_bank_rx = -1; 549 + } 550 + } 551 + conf->hardware = 0; 552 + conf->software = 1; 553 + return; 554 + } 555 + /* check if member has echo turned on */ 556 + if (member->dsp->echo) { 557 + if (dsp_debug & DEBUG_DSP_CMX) 558 + printk(KERN_DEBUG 559 + "%s dsp %s cannot form a conf, because " 560 + "echo is turned on\n", __func__, 561 + member->dsp->name); 562 + goto conf_software; 563 + } 564 + /* check if member has tx_mix turned on */ 565 + if (member->dsp->tx_mix) { 566 + if (dsp_debug & DEBUG_DSP_CMX) 567 + printk(KERN_DEBUG 568 + "%s dsp %s cannot form a conf, because " 569 + "tx_mix is turned on\n", 570 + __func__, member->dsp->name); 571 + goto conf_software; 572 + } 573 + /* check if member changes volume at an not suppoted level */ 574 + if (member->dsp->tx_volume) { 575 + if (dsp_debug & DEBUG_DSP_CMX) 576 + printk(KERN_DEBUG 577 + "%s dsp %s cannot form a conf, because " 578 + "tx_volume is changed\n", 579 + __func__, member->dsp->name); 580 + goto conf_software; 581 + } 582 + if (member->dsp->rx_volume) { 583 + if (dsp_debug & DEBUG_DSP_CMX) 584 + printk(KERN_DEBUG 585 + "%s dsp %s cannot form a conf, because " 586 + "rx_volume is changed\n", 587 + __func__, member->dsp->name); 588 + goto conf_software; 589 + } 590 + /* check if tx-data turned on */ 591 + if (member->dsp->tx_data) { 592 + if (dsp_debug & DEBUG_DSP_CMX) 593 + printk(KERN_DEBUG 594 + "%s dsp %s cannot form a conf, because " 595 + "tx_data is turned on\n", 596 + __func__, member->dsp->name); 597 + goto conf_software; 598 + } 599 + /* check if pipeline exists */ 600 + if (member->dsp->pipeline.inuse) { 601 + if (dsp_debug & DEBUG_DSP_CMX) 602 + printk(KERN_DEBUG 603 + "%s dsp %s cannot form a conf, because " 604 + "pipeline exists\n", __func__, 605 + member->dsp->name); 606 + goto conf_software; 607 + } 608 + /* check if encryption is enabled */ 609 + if (member->dsp->bf_enable) { 610 + if (dsp_debug & DEBUG_DSP_CMX) 611 + printk(KERN_DEBUG "%s dsp %s cannot form a " 612 + "conf, because encryption is enabled\n", 613 + __func__, member->dsp->name); 614 + goto conf_software; 615 + } 616 + /* check if member is on a card with PCM support */ 617 + if (member->dsp->features.pcm_id < 0) { 618 + if (dsp_debug & DEBUG_DSP_CMX) 619 + printk(KERN_DEBUG 620 + "%s dsp %s cannot form a conf, because " 621 + "dsp has no PCM bus\n", 622 + __func__, member->dsp->name); 623 + goto conf_software; 624 + } 625 + /* check if relations are on the same PCM bus */ 626 + if (member->dsp->features.pcm_id != same_pcm) { 627 + if (dsp_debug & DEBUG_DSP_CMX) 628 + printk(KERN_DEBUG 629 + "%s dsp %s cannot form a conf, because " 630 + "dsp is on a different PCM bus than the " 631 + "first dsp\n", 632 + __func__, member->dsp->name); 633 + goto conf_software; 634 + } 635 + /* determine if members are on the same hfc chip */ 636 + if (same_hfc != member->dsp->features.hfc_id) 637 + same_hfc = -1; 638 + /* if there are members already in a conference */ 639 + if (current_conf < 0 && member->dsp->hfc_conf >= 0) 640 + current_conf = member->dsp->hfc_conf; 641 + /* if any member is not in a conference */ 642 + if (member->dsp->hfc_conf < 0) 643 + all_conf = 0; 644 + 645 + memb++; 646 + } 647 + 648 + /* if no member, this is an error */ 649 + if (memb < 1) 650 + return; 651 + 652 + /* one member */ 653 + if (memb == 1) { 654 + if (dsp_debug & DEBUG_DSP_CMX) 655 + printk(KERN_DEBUG 656 + "%s conf %d cannot form a HW conference, " 657 + "because dsp is alone\n", __func__, conf->id); 658 + conf->hardware = 0; 659 + conf->software = 0; 660 + member = list_entry(conf->mlist.next, struct dsp_conf_member, 661 + list); 662 + dsp = member->dsp; 663 + goto one_member; 664 + } 665 + 666 + /* 667 + * ok, now we are sure that all members are on the same pcm. 668 + * now we will see if we have only two members, so we can do 669 + * crossconnections, which don't have any limitations. 670 + */ 671 + 672 + /* if we have only two members */ 673 + if (memb == 2) { 674 + member = list_entry(conf->mlist.next, struct dsp_conf_member, 675 + list); 676 + nextm = list_entry(member->list.next, struct dsp_conf_member, 677 + list); 678 + /* remove HFC conference if enabled */ 679 + if (member->dsp->hfc_conf >= 0) { 680 + if (dsp_debug & DEBUG_DSP_CMX) 681 + printk(KERN_DEBUG 682 + "%s removing %s from HFC conf %d because " 683 + "two parties require only a PCM slot\n", 684 + __func__, member->dsp->name, 685 + member->dsp->hfc_conf); 686 + dsp_cmx_hw_message(member->dsp, 687 + MISDN_CTRL_HFC_CONF_SPLIT, 0, 0, 0, 0); 688 + member->dsp->hfc_conf = -1; 689 + } 690 + if (nextm->dsp->hfc_conf >= 0) { 691 + if (dsp_debug & DEBUG_DSP_CMX) 692 + printk(KERN_DEBUG 693 + "%s removing %s from HFC conf %d because " 694 + "two parties require only a PCM slot\n", 695 + __func__, nextm->dsp->name, 696 + nextm->dsp->hfc_conf); 697 + dsp_cmx_hw_message(nextm->dsp, 698 + MISDN_CTRL_HFC_CONF_SPLIT, 0, 0, 0, 0); 699 + nextm->dsp->hfc_conf = -1; 700 + } 701 + /* if members have two banks (and not on the same chip) */ 702 + if (member->dsp->features.pcm_banks > 1 && 703 + nextm->dsp->features.pcm_banks > 1 && 704 + member->dsp->features.hfc_id != 705 + nextm->dsp->features.hfc_id) { 706 + /* if both members have same slots with crossed banks */ 707 + if (member->dsp->pcm_slot_tx >= 0 && 708 + member->dsp->pcm_slot_rx >= 0 && 709 + nextm->dsp->pcm_slot_tx >= 0 && 710 + nextm->dsp->pcm_slot_rx >= 0 && 711 + nextm->dsp->pcm_slot_tx == 712 + member->dsp->pcm_slot_rx && 713 + nextm->dsp->pcm_slot_rx == 714 + member->dsp->pcm_slot_tx && 715 + nextm->dsp->pcm_slot_tx == 716 + member->dsp->pcm_slot_tx && 717 + member->dsp->pcm_bank_tx != 718 + member->dsp->pcm_bank_rx && 719 + nextm->dsp->pcm_bank_tx != 720 + nextm->dsp->pcm_bank_rx) { 721 + /* all members have same slot */ 722 + if (dsp_debug & DEBUG_DSP_CMX) 723 + printk(KERN_DEBUG 724 + "%s dsp %s & %s stay joined on " 725 + "PCM slot %d bank %d (TX) bank %d " 726 + "(RX) (on different chips)\n", 727 + __func__, 728 + member->dsp->name, 729 + nextm->dsp->name, 730 + member->dsp->pcm_slot_tx, 731 + member->dsp->pcm_bank_tx, 732 + member->dsp->pcm_bank_rx); 733 + conf->hardware = 0; 734 + conf->software = 1; 735 + return; 736 + } 737 + /* find a new slot */ 738 + memset(freeslots, 1, sizeof(freeslots)); 739 + list_for_each_entry(dsp, &dsp_ilist, list) { 740 + if (dsp != member->dsp && 741 + dsp != nextm->dsp && 742 + member->dsp->features.pcm_id == 743 + dsp->features.pcm_id) { 744 + if (dsp->pcm_slot_rx >= 0 && 745 + dsp->pcm_slot_rx < 746 + sizeof(freeslots)) 747 + freeslots[dsp->pcm_slot_tx] = 0; 748 + if (dsp->pcm_slot_tx >= 0 && 749 + dsp->pcm_slot_tx < 750 + sizeof(freeslots)) 751 + freeslots[dsp->pcm_slot_rx] = 0; 752 + } 753 + } 754 + i = 0; 755 + ii = member->dsp->features.pcm_slots; 756 + while (i < ii) { 757 + if (freeslots[i]) 758 + break; 759 + i++; 760 + } 761 + if (i == ii) { 762 + if (dsp_debug & DEBUG_DSP_CMX) 763 + printk(KERN_DEBUG 764 + "%s no slot available for " 765 + "%s & %s\n", __func__, 766 + member->dsp->name, 767 + nextm->dsp->name); 768 + /* no more slots available */ 769 + goto conf_software; 770 + } 771 + /* assign free slot */ 772 + member->dsp->pcm_slot_tx = i; 773 + member->dsp->pcm_slot_rx = i; 774 + nextm->dsp->pcm_slot_tx = i; 775 + nextm->dsp->pcm_slot_rx = i; 776 + member->dsp->pcm_bank_rx = 0; 777 + member->dsp->pcm_bank_tx = 1; 778 + nextm->dsp->pcm_bank_rx = 1; 779 + nextm->dsp->pcm_bank_tx = 0; 780 + if (dsp_debug & DEBUG_DSP_CMX) 781 + printk(KERN_DEBUG 782 + "%s adding %s & %s to new PCM slot %d " 783 + "(TX and RX on different chips) because " 784 + "both members have not same slots\n", 785 + __func__, 786 + member->dsp->name, 787 + nextm->dsp->name, 788 + member->dsp->pcm_slot_tx); 789 + dsp_cmx_hw_message(member->dsp, MISDN_CTRL_HFC_PCM_CONN, 790 + member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx, 791 + member->dsp->pcm_slot_rx, member->dsp->pcm_bank_rx); 792 + dsp_cmx_hw_message(nextm->dsp, MISDN_CTRL_HFC_PCM_CONN, 793 + nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx, 794 + nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx); 795 + conf->hardware = 1; 796 + conf->software = 0; 797 + return; 798 + /* if members have one bank (or on the same chip) */ 799 + } else { 800 + /* if both members have different crossed slots */ 801 + if (member->dsp->pcm_slot_tx >= 0 && 802 + member->dsp->pcm_slot_rx >= 0 && 803 + nextm->dsp->pcm_slot_tx >= 0 && 804 + nextm->dsp->pcm_slot_rx >= 0 && 805 + nextm->dsp->pcm_slot_tx == 806 + member->dsp->pcm_slot_rx && 807 + nextm->dsp->pcm_slot_rx == 808 + member->dsp->pcm_slot_tx && 809 + member->dsp->pcm_slot_tx != 810 + member->dsp->pcm_slot_rx && 811 + member->dsp->pcm_bank_tx == 0 && 812 + member->dsp->pcm_bank_rx == 0 && 813 + nextm->dsp->pcm_bank_tx == 0 && 814 + nextm->dsp->pcm_bank_rx == 0) { 815 + /* all members have same slot */ 816 + if (dsp_debug & DEBUG_DSP_CMX) 817 + printk(KERN_DEBUG 818 + "%s dsp %s & %s stay joined on PCM " 819 + "slot %d (TX) %d (RX) on same chip " 820 + "or one bank PCM)\n", __func__, 821 + member->dsp->name, 822 + nextm->dsp->name, 823 + member->dsp->pcm_slot_tx, 824 + member->dsp->pcm_slot_rx); 825 + conf->hardware = 0; 826 + conf->software = 1; 827 + return; 828 + } 829 + /* find two new slot */ 830 + memset(freeslots, 1, sizeof(freeslots)); 831 + list_for_each_entry(dsp, &dsp_ilist, list) { 832 + if (dsp != member->dsp && 833 + dsp != nextm->dsp && 834 + member->dsp->features.pcm_id == 835 + dsp->features.pcm_id) { 836 + if (dsp->pcm_slot_rx >= 0 && 837 + dsp->pcm_slot_rx < 838 + sizeof(freeslots)) 839 + freeslots[dsp->pcm_slot_tx] = 0; 840 + if (dsp->pcm_slot_tx >= 0 && 841 + dsp->pcm_slot_tx < 842 + sizeof(freeslots)) 843 + freeslots[dsp->pcm_slot_rx] = 0; 844 + } 845 + } 846 + i1 = 0; 847 + ii = member->dsp->features.pcm_slots; 848 + while (i1 < ii) { 849 + if (freeslots[i1]) 850 + break; 851 + i1++; 852 + } 853 + if (i1 == ii) { 854 + if (dsp_debug & DEBUG_DSP_CMX) 855 + printk(KERN_DEBUG 856 + "%s no slot available " 857 + "for %s & %s\n", __func__, 858 + member->dsp->name, 859 + nextm->dsp->name); 860 + /* no more slots available */ 861 + goto conf_software; 862 + } 863 + i2 = i1+1; 864 + while (i2 < ii) { 865 + if (freeslots[i2]) 866 + break; 867 + i2++; 868 + } 869 + if (i2 == ii) { 870 + if (dsp_debug & DEBUG_DSP_CMX) 871 + printk(KERN_DEBUG 872 + "%s no slot available " 873 + "for %s & %s\n", 874 + __func__, 875 + member->dsp->name, 876 + nextm->dsp->name); 877 + /* no more slots available */ 878 + goto conf_software; 879 + } 880 + /* assign free slots */ 881 + member->dsp->pcm_slot_tx = i1; 882 + member->dsp->pcm_slot_rx = i2; 883 + nextm->dsp->pcm_slot_tx = i2; 884 + nextm->dsp->pcm_slot_rx = i1; 885 + member->dsp->pcm_bank_rx = 0; 886 + member->dsp->pcm_bank_tx = 0; 887 + nextm->dsp->pcm_bank_rx = 0; 888 + nextm->dsp->pcm_bank_tx = 0; 889 + if (dsp_debug & DEBUG_DSP_CMX) 890 + printk(KERN_DEBUG 891 + "%s adding %s & %s to new PCM slot %d " 892 + "(TX) %d (RX) on same chip or one bank " 893 + "PCM, because both members have not " 894 + "crossed slots\n", __func__, 895 + member->dsp->name, 896 + nextm->dsp->name, 897 + member->dsp->pcm_slot_tx, 898 + member->dsp->pcm_slot_rx); 899 + dsp_cmx_hw_message(member->dsp, MISDN_CTRL_HFC_PCM_CONN, 900 + member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx, 901 + member->dsp->pcm_slot_rx, member->dsp->pcm_bank_rx); 902 + dsp_cmx_hw_message(nextm->dsp, MISDN_CTRL_HFC_PCM_CONN, 903 + nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx, 904 + nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx); 905 + conf->hardware = 1; 906 + conf->software = 0; 907 + return; 908 + } 909 + } 910 + 911 + /* 912 + * if we have more than two, we may check if we have a conference 913 + * unit available on the chip. also all members must be on the same 914 + */ 915 + 916 + /* if not the same HFC chip */ 917 + if (same_hfc < 0) { 918 + if (dsp_debug & DEBUG_DSP_CMX) 919 + printk(KERN_DEBUG 920 + "%s conference %d cannot be formed, because " 921 + "members are on different chips or not " 922 + "on HFC chip\n", 923 + __func__, conf->id); 924 + goto conf_software; 925 + } 926 + 927 + /* for more than two members.. */ 928 + 929 + /* in case of hdlc, we change to software */ 930 + if (dsp->hdlc) 931 + goto conf_software; 932 + 933 + /* if all members already have the same conference */ 934 + if (all_conf) 935 + return; 936 + 937 + /* 938 + * if there is an existing conference, but not all members have joined 939 + */ 940 + if (current_conf >= 0) { 941 + join_members: 942 + list_for_each_entry(member, &conf->mlist, list) { 943 + /* join to current conference */ 944 + if (member->dsp->hfc_conf == current_conf) 945 + continue; 946 + /* get a free timeslot first */ 947 + memset(freeslots, 1, sizeof(freeslots)); 948 + list_for_each_entry(dsp, &dsp_ilist, list) { 949 + /* 950 + * not checking current member, because 951 + * slot will be overwritten. 952 + */ 953 + if ( 954 + dsp != member->dsp && 955 + /* dsp must be on the same PCM */ 956 + member->dsp->features.pcm_id == 957 + dsp->features.pcm_id) { 958 + /* dsp must be on a slot */ 959 + if (dsp->pcm_slot_tx >= 0 && 960 + dsp->pcm_slot_tx < 961 + sizeof(freeslots)) 962 + freeslots[dsp->pcm_slot_tx] = 0; 963 + if (dsp->pcm_slot_rx >= 0 && 964 + dsp->pcm_slot_rx < 965 + sizeof(freeslots)) 966 + freeslots[dsp->pcm_slot_rx] = 0; 967 + } 968 + } 969 + i = 0; 970 + ii = member->dsp->features.pcm_slots; 971 + while (i < ii) { 972 + if (freeslots[i]) 973 + break; 974 + i++; 975 + } 976 + if (i == ii) { 977 + /* no more slots available */ 978 + if (dsp_debug & DEBUG_DSP_CMX) 979 + printk(KERN_DEBUG 980 + "%s conference %d cannot be formed," 981 + " because no slot free\n", 982 + __func__, conf->id); 983 + goto conf_software; 984 + } 985 + if (dsp_debug & DEBUG_DSP_CMX) 986 + printk(KERN_DEBUG 987 + "%s changing dsp %s to HW conference " 988 + "%d slot %d\n", __func__, 989 + member->dsp->name, current_conf, i); 990 + /* assign free slot & set PCM & join conf */ 991 + member->dsp->pcm_slot_tx = i; 992 + member->dsp->pcm_slot_rx = i; 993 + member->dsp->pcm_bank_tx = 2; /* loop */ 994 + member->dsp->pcm_bank_rx = 2; 995 + member->dsp->hfc_conf = current_conf; 996 + dsp_cmx_hw_message(member->dsp, MISDN_CTRL_HFC_PCM_CONN, 997 + i, 2, i, 2); 998 + dsp_cmx_hw_message(member->dsp, 999 + MISDN_CTRL_HFC_CONF_JOIN, current_conf, 0, 0, 0); 1000 + } 1001 + return; 1002 + } 1003 + 1004 + /* 1005 + * no member is in a conference yet, so we find a free one 1006 + */ 1007 + memset(freeunits, 1, sizeof(freeunits)); 1008 + list_for_each_entry(dsp, &dsp_ilist, list) { 1009 + /* dsp must be on the same chip */ 1010 + if (dsp->features.hfc_id == same_hfc && 1011 + /* dsp must have joined a HW conference */ 1012 + dsp->hfc_conf >= 0 && 1013 + /* slot must be within range */ 1014 + dsp->hfc_conf < 8) 1015 + freeunits[dsp->hfc_conf] = 0; 1016 + } 1017 + i = 0; 1018 + ii = 8; 1019 + while (i < ii) { 1020 + if (freeunits[i]) 1021 + break; 1022 + i++; 1023 + } 1024 + if (i == ii) { 1025 + /* no more conferences available */ 1026 + if (dsp_debug & DEBUG_DSP_CMX) 1027 + printk(KERN_DEBUG 1028 + "%s conference %d cannot be formed, because " 1029 + "no conference number free\n", 1030 + __func__, conf->id); 1031 + goto conf_software; 1032 + } 1033 + /* join all members */ 1034 + current_conf = i; 1035 + goto join_members; 1036 + } 1037 + 1038 + 1039 + /* 1040 + * conf_id != 0: join or change conference 1041 + * conf_id == 0: split from conference if not already 1042 + */ 1043 + int 1044 + dsp_cmx_conf(struct dsp *dsp, u32 conf_id) 1045 + { 1046 + int err; 1047 + struct dsp_conf *conf; 1048 + struct dsp_conf_member *member; 1049 + 1050 + /* if conference doesn't change */ 1051 + if (dsp->conf_id == conf_id) 1052 + return 0; 1053 + 1054 + /* first remove us from current conf */ 1055 + if (dsp->conf_id) { 1056 + if (dsp_debug & DEBUG_DSP_CMX) 1057 + printk(KERN_DEBUG "removing us from conference %d\n", 1058 + dsp->conf->id); 1059 + /* remove us from conf */ 1060 + conf = dsp->conf; 1061 + err = dsp_cmx_del_conf_member(dsp); 1062 + if (err) 1063 + return err; 1064 + dsp->conf_id = 0; 1065 + 1066 + /* update hardware */ 1067 + dsp_cmx_hardware(NULL, dsp); 1068 + 1069 + /* conf now empty? */ 1070 + if (list_empty(&conf->mlist)) { 1071 + if (dsp_debug & DEBUG_DSP_CMX) 1072 + printk(KERN_DEBUG 1073 + "conference is empty, so we remove it.\n"); 1074 + err = dsp_cmx_del_conf(conf); 1075 + if (err) 1076 + return err; 1077 + } else { 1078 + /* update members left on conf */ 1079 + dsp_cmx_hardware(conf, NULL); 1080 + } 1081 + } 1082 + 1083 + /* if split */ 1084 + if (!conf_id) 1085 + return 0; 1086 + 1087 + /* now add us to conf */ 1088 + if (dsp_debug & DEBUG_DSP_CMX) 1089 + printk(KERN_DEBUG "searching conference %d\n", 1090 + conf_id); 1091 + conf = dsp_cmx_search_conf(conf_id); 1092 + if (!conf) { 1093 + if (dsp_debug & DEBUG_DSP_CMX) 1094 + printk(KERN_DEBUG 1095 + "conference doesn't exist yet, creating.\n"); 1096 + /* the conference doesn't exist, so we create */ 1097 + conf = dsp_cmx_new_conf(conf_id); 1098 + if (!conf) 1099 + return -EINVAL; 1100 + } else if (!list_empty(&conf->mlist)) { 1101 + member = list_entry(conf->mlist.next, struct dsp_conf_member, 1102 + list); 1103 + if (dsp->hdlc && !member->dsp->hdlc) { 1104 + if (dsp_debug & DEBUG_DSP_CMX) 1105 + printk(KERN_DEBUG 1106 + "cannot join transparent conference.\n"); 1107 + return -EINVAL; 1108 + } 1109 + if (!dsp->hdlc && member->dsp->hdlc) { 1110 + if (dsp_debug & DEBUG_DSP_CMX) 1111 + printk(KERN_DEBUG 1112 + "cannot join hdlc conference.\n"); 1113 + return -EINVAL; 1114 + } 1115 + } 1116 + /* add conference member */ 1117 + err = dsp_cmx_add_conf_member(dsp, conf); 1118 + if (err) 1119 + return err; 1120 + dsp->conf_id = conf_id; 1121 + 1122 + /* if we are alone, we do nothing! */ 1123 + if (list_empty(&conf->mlist)) { 1124 + if (dsp_debug & DEBUG_DSP_CMX) 1125 + printk(KERN_DEBUG 1126 + "we are alone in this conference, so exit.\n"); 1127 + /* update hardware */ 1128 + dsp_cmx_hardware(NULL, dsp); 1129 + return 0; 1130 + } 1131 + 1132 + /* update members on conf */ 1133 + dsp_cmx_hardware(conf, NULL); 1134 + 1135 + return 0; 1136 + } 1137 + 1138 + 1139 + /* 1140 + * audio data is received from card 1141 + */ 1142 + void 1143 + dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb) 1144 + { 1145 + u8 *d, *p; 1146 + int len = skb->len; 1147 + struct mISDNhead *hh = mISDN_HEAD_P(skb); 1148 + int w, i, ii; 1149 + 1150 + /* check if we have sompen */ 1151 + if (len < 1) 1152 + return; 1153 + 1154 + /* half of the buffer should be larger than maximum packet size */ 1155 + if (len >= CMX_BUFF_HALF) { 1156 + printk(KERN_ERR 1157 + "%s line %d: packet from card is too large (%d bytes). " 1158 + "please make card send smaller packets OR increase " 1159 + "CMX_BUFF_SIZE\n", __FILE__, __LINE__, len); 1160 + return; 1161 + } 1162 + 1163 + /* 1164 + * initialize pointers if not already - 1165 + * also add delay if requested by PH_SIGNAL 1166 + */ 1167 + if (dsp->rx_init) { 1168 + dsp->rx_init = 0; 1169 + if (dsp->features.unordered) { 1170 + dsp->rx_R = (hh->id & CMX_BUFF_MASK); 1171 + dsp->rx_W = (dsp->rx_R + dsp->cmx_delay) 1172 + & CMX_BUFF_MASK; 1173 + } else { 1174 + dsp->rx_R = 0; 1175 + dsp->rx_W = dsp->cmx_delay; 1176 + } 1177 + } 1178 + /* if frame contains time code, write directly */ 1179 + if (dsp->features.unordered) { 1180 + dsp->rx_W = (hh->id & CMX_BUFF_MASK); 1181 + /* printk(KERN_DEBUG "%s %08x\n", dsp->name, hh->id); */ 1182 + } 1183 + /* 1184 + * if we underrun (or maybe overrun), 1185 + * we set our new read pointer, and write silence to buffer 1186 + */ 1187 + if (((dsp->rx_W-dsp->rx_R) & CMX_BUFF_MASK) >= CMX_BUFF_HALF) { 1188 + if (dsp_debug & DEBUG_DSP_CMX) 1189 + printk(KERN_DEBUG 1190 + "cmx_receive(dsp=%lx): UNDERRUN (or overrun the " 1191 + "maximum delay), adjusting read pointer! " 1192 + "(inst %s)\n", (u_long)dsp, dsp->name); 1193 + /* flush buffer */ 1194 + if (dsp->features.unordered) { 1195 + dsp->rx_R = (hh->id & CMX_BUFF_MASK); 1196 + dsp->rx_W = (dsp->rx_R + dsp->cmx_delay) 1197 + & CMX_BUFF_MASK; 1198 + } else { 1199 + dsp->rx_R = 0; 1200 + dsp->rx_W = dsp->cmx_delay; 1201 + } 1202 + memset(dsp->rx_buff, dsp_silence, sizeof(dsp->rx_buff)); 1203 + } 1204 + /* if we have reached double delay, jump back to middle */ 1205 + if (dsp->cmx_delay) 1206 + if (((dsp->rx_W - dsp->rx_R) & CMX_BUFF_MASK) >= 1207 + (dsp->cmx_delay << 1)) { 1208 + if (dsp_debug & DEBUG_DSP_CMX) 1209 + printk(KERN_DEBUG 1210 + "cmx_receive(dsp=%lx): OVERRUN (because " 1211 + "twice the delay is reached), adjusting " 1212 + "read pointer! (inst %s)\n", 1213 + (u_long)dsp, dsp->name); 1214 + /* flush buffer */ 1215 + if (dsp->features.unordered) { 1216 + dsp->rx_R = (hh->id & CMX_BUFF_MASK); 1217 + dsp->rx_W = (dsp->rx_R + dsp->cmx_delay) 1218 + & CMX_BUFF_MASK; 1219 + } else { 1220 + dsp->rx_R = 0; 1221 + dsp->rx_W = dsp->cmx_delay; 1222 + } 1223 + memset(dsp->rx_buff, dsp_silence, sizeof(dsp->rx_buff)); 1224 + } 1225 + 1226 + /* show where to write */ 1227 + #ifdef CMX_DEBUG 1228 + printk(KERN_DEBUG 1229 + "cmx_receive(dsp=%lx): rx_R(dsp)=%05x rx_W(dsp)=%05x len=%d %s\n", 1230 + (u_long)dsp, dsp->rx_R, dsp->rx_W, len, dsp->name); 1231 + #endif 1232 + 1233 + /* write data into rx_buffer */ 1234 + p = skb->data; 1235 + d = dsp->rx_buff; 1236 + w = dsp->rx_W; 1237 + i = 0; 1238 + ii = len; 1239 + while (i < ii) { 1240 + d[w++ & CMX_BUFF_MASK] = *p++; 1241 + i++; 1242 + } 1243 + 1244 + /* increase write-pointer */ 1245 + dsp->rx_W = ((dsp->rx_W+len) & CMX_BUFF_MASK); 1246 + } 1247 + 1248 + 1249 + /* 1250 + * send (mixed) audio data to card and control jitter 1251 + */ 1252 + static void 1253 + dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members) 1254 + { 1255 + struct dsp_conf *conf = dsp->conf; 1256 + struct dsp *member, *other; 1257 + register s32 sample; 1258 + u8 *d, *p, *q, *o_q; 1259 + struct sk_buff *nskb, *txskb; 1260 + int r, rr, t, tt, o_r, o_rr; 1261 + int preload = 0; 1262 + struct mISDNhead *hh, *thh; 1263 + 1264 + /* don't process if: */ 1265 + if (!dsp->b_active) { /* if not active */ 1266 + dsp->last_tx = 0; 1267 + return; 1268 + } 1269 + if (dsp->pcm_slot_tx >= 0 && /* connected to pcm slot */ 1270 + dsp->tx_R == dsp->tx_W && /* AND no tx-data */ 1271 + !(dsp->tone.tone && dsp->tone.software)) { /* AND not soft tones */ 1272 + dsp->last_tx = 0; 1273 + return; 1274 + } 1275 + 1276 + #ifdef CMX_DEBUG 1277 + printk(KERN_DEBUG 1278 + "SEND members=%d dsp=%s, conf=%p, rx_R=%05x rx_W=%05x\n", 1279 + members, dsp->name, conf, dsp->rx_R, dsp->rx_W); 1280 + #endif 1281 + 1282 + /* preload if we have delay set */ 1283 + if (dsp->cmx_delay && !dsp->last_tx) { 1284 + preload = len; 1285 + if (preload < 128) 1286 + preload = 128; 1287 + } 1288 + 1289 + /* PREPARE RESULT */ 1290 + nskb = mI_alloc_skb(len + preload, GFP_ATOMIC); 1291 + if (!nskb) { 1292 + printk(KERN_ERR 1293 + "FATAL ERROR in mISDN_dsp.o: cannot alloc %d bytes\n", 1294 + len + preload); 1295 + return; 1296 + } 1297 + hh = mISDN_HEAD_P(nskb); 1298 + hh->prim = PH_DATA_REQ; 1299 + hh->id = 0; 1300 + dsp->last_tx = 1; 1301 + 1302 + /* set pointers, indexes and stuff */ 1303 + member = dsp; 1304 + p = dsp->tx_buff; /* transmit data */ 1305 + q = dsp->rx_buff; /* received data */ 1306 + d = skb_put(nskb, preload + len); /* result */ 1307 + t = dsp->tx_R; /* tx-pointers */ 1308 + tt = dsp->tx_W; 1309 + r = dsp->rx_R; /* rx-pointers */ 1310 + rr = (r + len) & CMX_BUFF_MASK; 1311 + 1312 + /* preload with silence, if required */ 1313 + if (preload) { 1314 + memset(d, dsp_silence, preload); 1315 + d += preload; 1316 + } 1317 + 1318 + /* PROCESS TONES/TX-DATA ONLY */ 1319 + if (dsp->tone.tone && dsp->tone.software) { 1320 + /* -> copy tone */ 1321 + dsp_tone_copy(dsp, d, len); 1322 + dsp->tx_R = 0; /* clear tx buffer */ 1323 + dsp->tx_W = 0; 1324 + goto send_packet; 1325 + } 1326 + /* if we have tx-data but do not use mixing */ 1327 + if (!dsp->tx_mix && t != tt) { 1328 + /* -> send tx-data and continue when not enough */ 1329 + #ifdef CMX_TX_DEBUG 1330 + sprintf(debugbuf, "TX sending (%04x-%04x)%p: ", t, tt, p); 1331 + #endif 1332 + while (r != rr && t != tt) { 1333 + #ifdef CMX_TX_DEBUG 1334 + if (strlen(debugbuf) < 48) 1335 + sprintf(debugbuf+strlen(debugbuf), " %02x", p[t]); 1336 + #endif 1337 + *d++ = p[t]; /* write tx_buff */ 1338 + t = (t+1) & CMX_BUFF_MASK; 1339 + r = (r+1) & CMX_BUFF_MASK; 1340 + } 1341 + if (r == rr) { 1342 + dsp->tx_R = t; 1343 + #ifdef CMX_TX_DEBUG 1344 + printk(KERN_DEBUG "%s\n", debugbuf); 1345 + #endif 1346 + goto send_packet; 1347 + } 1348 + } 1349 + #ifdef CMX_TX_DEBUG 1350 + printk(KERN_DEBUG "%s\n", debugbuf); 1351 + #endif 1352 + 1353 + /* PROCESS DATA (one member / no conf) */ 1354 + if (!conf || members <= 1) { 1355 + /* -> if echo is NOT enabled */ 1356 + if (!dsp->echo) { 1357 + /* -> send tx-data if available or use 0-volume */ 1358 + while (r != rr && t != tt) { 1359 + *d++ = p[t]; /* write tx_buff */ 1360 + t = (t+1) & CMX_BUFF_MASK; 1361 + r = (r+1) & CMX_BUFF_MASK; 1362 + } 1363 + if (r != rr) 1364 + memset(d, dsp_silence, (rr-r)&CMX_BUFF_MASK); 1365 + /* -> if echo is enabled */ 1366 + } else { 1367 + /* 1368 + * -> mix tx-data with echo if available, 1369 + * or use echo only 1370 + */ 1371 + while (r != rr && t != tt) { 1372 + *d++ = dsp_audio_mix_law[(p[t]<<8)|q[r]]; 1373 + t = (t+1) & CMX_BUFF_MASK; 1374 + r = (r+1) & CMX_BUFF_MASK; 1375 + } 1376 + while (r != rr) { 1377 + *d++ = q[r]; /* echo */ 1378 + r = (r+1) & CMX_BUFF_MASK; 1379 + } 1380 + } 1381 + dsp->tx_R = t; 1382 + goto send_packet; 1383 + } 1384 + /* PROCESS DATA (two members) */ 1385 + #ifdef CMX_CONF_DEBUG 1386 + if (0) { 1387 + #else 1388 + if (members == 2) { 1389 + #endif 1390 + /* "other" becomes other party */ 1391 + other = (list_entry(conf->mlist.next, 1392 + struct dsp_conf_member, list))->dsp; 1393 + if (other == member) 1394 + other = (list_entry(conf->mlist.prev, 1395 + struct dsp_conf_member, list))->dsp; 1396 + o_q = other->rx_buff; /* received data */ 1397 + o_rr = (other->rx_R + len) & CMX_BUFF_MASK; 1398 + /* end of rx-pointer */ 1399 + o_r = (o_rr - rr + r) & CMX_BUFF_MASK; 1400 + /* start rx-pointer at current read position*/ 1401 + /* -> if echo is NOT enabled */ 1402 + if (!dsp->echo) { 1403 + /* 1404 + * -> copy other member's rx-data, 1405 + * if tx-data is available, mix 1406 + */ 1407 + while (o_r != o_rr && t != tt) { 1408 + *d++ = dsp_audio_mix_law[(p[t]<<8)|o_q[o_r]]; 1409 + t = (t+1) & CMX_BUFF_MASK; 1410 + o_r = (o_r+1) & CMX_BUFF_MASK; 1411 + } 1412 + while (o_r != o_rr) { 1413 + *d++ = o_q[o_r]; 1414 + o_r = (o_r+1) & CMX_BUFF_MASK; 1415 + } 1416 + /* -> if echo is enabled */ 1417 + } else { 1418 + /* 1419 + * -> mix other member's rx-data with echo, 1420 + * if tx-data is available, mix 1421 + */ 1422 + while (r != rr && t != tt) { 1423 + sample = dsp_audio_law_to_s32[p[t]] + 1424 + dsp_audio_law_to_s32[q[r]] + 1425 + dsp_audio_law_to_s32[o_q[o_r]]; 1426 + if (sample < -32768) 1427 + sample = -32768; 1428 + else if (sample > 32767) 1429 + sample = 32767; 1430 + *d++ = dsp_audio_s16_to_law[sample & 0xffff]; 1431 + /* tx-data + rx_data + echo */ 1432 + t = (t+1) & CMX_BUFF_MASK; 1433 + r = (r+1) & CMX_BUFF_MASK; 1434 + o_r = (o_r+1) & CMX_BUFF_MASK; 1435 + } 1436 + while (r != rr) { 1437 + *d++ = dsp_audio_mix_law[(q[r]<<8)|o_q[o_r]]; 1438 + r = (r+1) & CMX_BUFF_MASK; 1439 + o_r = (o_r+1) & CMX_BUFF_MASK; 1440 + } 1441 + } 1442 + dsp->tx_R = t; 1443 + goto send_packet; 1444 + } 1445 + #ifdef DSP_NEVER_DEFINED 1446 + } 1447 + #endif 1448 + /* PROCESS DATA (three or more members) */ 1449 + /* -> if echo is NOT enabled */ 1450 + if (!dsp->echo) { 1451 + /* 1452 + * -> substract rx-data from conf-data, 1453 + * if tx-data is available, mix 1454 + */ 1455 + while (r != rr && t != tt) { 1456 + sample = dsp_audio_law_to_s32[p[t]] + *c++ - 1457 + dsp_audio_law_to_s32[q[r]]; 1458 + if (sample < -32768) 1459 + sample = -32768; 1460 + else if (sample > 32767) 1461 + sample = 32767; 1462 + *d++ = dsp_audio_s16_to_law[sample & 0xffff]; 1463 + /* conf-rx+tx */ 1464 + r = (r+1) & CMX_BUFF_MASK; 1465 + t = (t+1) & CMX_BUFF_MASK; 1466 + } 1467 + while (r != rr) { 1468 + sample = *c++ - dsp_audio_law_to_s32[q[r]]; 1469 + if (sample < -32768) 1470 + sample = -32768; 1471 + else if (sample > 32767) 1472 + sample = 32767; 1473 + *d++ = dsp_audio_s16_to_law[sample & 0xffff]; 1474 + /* conf-rx */ 1475 + r = (r+1) & CMX_BUFF_MASK; 1476 + } 1477 + /* -> if echo is enabled */ 1478 + } else { 1479 + /* 1480 + * -> encode conf-data, if tx-data 1481 + * is available, mix 1482 + */ 1483 + while (r != rr && t != tt) { 1484 + sample = dsp_audio_law_to_s32[p[t]] + *c++; 1485 + if (sample < -32768) 1486 + sample = -32768; 1487 + else if (sample > 32767) 1488 + sample = 32767; 1489 + *d++ = dsp_audio_s16_to_law[sample & 0xffff]; 1490 + /* conf(echo)+tx */ 1491 + t = (t+1) & CMX_BUFF_MASK; 1492 + r = (r+1) & CMX_BUFF_MASK; 1493 + } 1494 + while (r != rr) { 1495 + sample = *c++; 1496 + if (sample < -32768) 1497 + sample = -32768; 1498 + else if (sample > 32767) 1499 + sample = 32767; 1500 + *d++ = dsp_audio_s16_to_law[sample & 0xffff]; 1501 + /* conf(echo) */ 1502 + r = (r+1) & CMX_BUFF_MASK; 1503 + } 1504 + } 1505 + dsp->tx_R = t; 1506 + goto send_packet; 1507 + 1508 + send_packet: 1509 + /* 1510 + * send tx-data if enabled - don't filter, 1511 + * becuase we want what we send, not what we filtered 1512 + */ 1513 + if (dsp->tx_data) { 1514 + /* PREPARE RESULT */ 1515 + txskb = mI_alloc_skb(len, GFP_ATOMIC); 1516 + if (!txskb) { 1517 + printk(KERN_ERR 1518 + "FATAL ERROR in mISDN_dsp.o: " 1519 + "cannot alloc %d bytes\n", len); 1520 + } else { 1521 + thh = mISDN_HEAD_P(txskb); 1522 + thh->prim = DL_DATA_REQ; 1523 + thh->id = 0; 1524 + memcpy(skb_put(txskb, len), nskb->data+preload, len); 1525 + /* queue (trigger later) */ 1526 + skb_queue_tail(&dsp->sendq, txskb); 1527 + } 1528 + } 1529 + /* adjust volume */ 1530 + if (dsp->tx_volume) 1531 + dsp_change_volume(nskb, dsp->tx_volume); 1532 + /* pipeline */ 1533 + if (dsp->pipeline.inuse) 1534 + dsp_pipeline_process_tx(&dsp->pipeline, nskb->data, nskb->len); 1535 + /* crypt */ 1536 + if (dsp->bf_enable) 1537 + dsp_bf_encrypt(dsp, nskb->data, nskb->len); 1538 + /* queue and trigger */ 1539 + skb_queue_tail(&dsp->sendq, nskb); 1540 + schedule_work(&dsp->workq); 1541 + } 1542 + 1543 + u32 samplecount; 1544 + struct timer_list dsp_spl_tl; 1545 + u32 dsp_spl_jiffies; /* calculate the next time to fire */ 1546 + u32 dsp_start_jiffies; /* jiffies at the time, the calculation begins */ 1547 + struct timeval dsp_start_tv; /* time at start of calculation */ 1548 + 1549 + void 1550 + dsp_cmx_send(void *arg) 1551 + { 1552 + struct dsp_conf *conf; 1553 + struct dsp_conf_member *member; 1554 + struct dsp *dsp; 1555 + int mustmix, members; 1556 + s32 mixbuffer[MAX_POLL+100], *c; 1557 + u8 *p, *q; 1558 + int r, rr; 1559 + int jittercheck = 0, delay, i; 1560 + u_long flags; 1561 + struct timeval tv; 1562 + u32 elapsed; 1563 + s16 length; 1564 + 1565 + /* lock */ 1566 + spin_lock_irqsave(&dsp_lock, flags); 1567 + 1568 + if (!dsp_start_tv.tv_sec) { 1569 + do_gettimeofday(&dsp_start_tv); 1570 + length = dsp_poll; 1571 + } else { 1572 + do_gettimeofday(&tv); 1573 + elapsed = ((tv.tv_sec - dsp_start_tv.tv_sec) * 8000) 1574 + + ((s32)(tv.tv_usec / 125) - (dsp_start_tv.tv_usec / 125)); 1575 + dsp_start_tv.tv_sec = tv.tv_sec; 1576 + dsp_start_tv.tv_usec = tv.tv_usec; 1577 + length = elapsed; 1578 + } 1579 + if (length > MAX_POLL + 100) 1580 + length = MAX_POLL + 100; 1581 + /* printk(KERN_DEBUG "len=%d dsp_count=0x%x.%04x dsp_poll_diff=0x%x.%04x\n", 1582 + length, dsp_count >> 16, dsp_count & 0xffff, dsp_poll_diff >> 16, 1583 + dsp_poll_diff & 0xffff); 1584 + */ 1585 + 1586 + /* 1587 + * check if jitter needs to be checked 1588 + * (this is about every second = 8192 samples) 1589 + */ 1590 + samplecount += length; 1591 + if ((samplecount & 8191) < length) 1592 + jittercheck = 1; 1593 + 1594 + /* loop all members that do not require conference mixing */ 1595 + list_for_each_entry(dsp, &dsp_ilist, list) { 1596 + if (dsp->hdlc) 1597 + continue; 1598 + conf = dsp->conf; 1599 + mustmix = 0; 1600 + members = 0; 1601 + if (conf) { 1602 + members = count_list_member(&conf->mlist); 1603 + #ifdef CMX_CONF_DEBUG 1604 + if (conf->software && members > 1) 1605 + #else 1606 + if (conf->software && members > 2) 1607 + #endif 1608 + mustmix = 1; 1609 + } 1610 + 1611 + /* transmission required */ 1612 + if (!mustmix) { 1613 + dsp_cmx_send_member(dsp, length, mixbuffer, members); 1614 + 1615 + /* 1616 + * unused mixbuffer is given to prevent a 1617 + * potential null-pointer-bug 1618 + */ 1619 + } 1620 + } 1621 + 1622 + /* loop all members that require conference mixing */ 1623 + list_for_each_entry(conf, &conf_ilist, list) { 1624 + /* count members and check hardware */ 1625 + members = count_list_member(&conf->mlist); 1626 + #ifdef CMX_CONF_DEBUG 1627 + if (conf->software && members > 1) { 1628 + #else 1629 + if (conf->software && members > 2) { 1630 + #endif 1631 + /* check for hdlc conf */ 1632 + member = list_entry(conf->mlist.next, 1633 + struct dsp_conf_member, list); 1634 + if (member->dsp->hdlc) 1635 + continue; 1636 + /* mix all data */ 1637 + memset(mixbuffer, 0, length*sizeof(s32)); 1638 + list_for_each_entry(member, &conf->mlist, list) { 1639 + dsp = member->dsp; 1640 + /* get range of data to mix */ 1641 + c = mixbuffer; 1642 + q = dsp->rx_buff; 1643 + r = dsp->rx_R; 1644 + rr = (r + length) & CMX_BUFF_MASK; 1645 + /* add member's data */ 1646 + while (r != rr) { 1647 + *c++ += dsp_audio_law_to_s32[q[r]]; 1648 + r = (r+1) & CMX_BUFF_MASK; 1649 + } 1650 + } 1651 + 1652 + /* process each member */ 1653 + list_for_each_entry(member, &conf->mlist, list) { 1654 + /* transmission */ 1655 + dsp_cmx_send_member(member->dsp, length, 1656 + mixbuffer, members); 1657 + } 1658 + } 1659 + } 1660 + 1661 + /* delete rx-data, increment buffers, change pointers */ 1662 + list_for_each_entry(dsp, &dsp_ilist, list) { 1663 + if (dsp->hdlc) 1664 + continue; 1665 + p = dsp->rx_buff; 1666 + q = dsp->tx_buff; 1667 + r = dsp->rx_R; 1668 + /* move receive pointer when receiving */ 1669 + if (!dsp->rx_is_off) { 1670 + rr = (r + length) & CMX_BUFF_MASK; 1671 + /* delete rx-data */ 1672 + while (r != rr) { 1673 + p[r] = dsp_silence; 1674 + r = (r+1) & CMX_BUFF_MASK; 1675 + } 1676 + /* increment rx-buffer pointer */ 1677 + dsp->rx_R = r; /* write incremented read pointer */ 1678 + } 1679 + 1680 + /* check current rx_delay */ 1681 + delay = (dsp->rx_W-dsp->rx_R) & CMX_BUFF_MASK; 1682 + if (delay >= CMX_BUFF_HALF) 1683 + delay = 0; /* will be the delay before next write */ 1684 + /* check for lower delay */ 1685 + if (delay < dsp->rx_delay[0]) 1686 + dsp->rx_delay[0] = delay; 1687 + /* check current tx_delay */ 1688 + delay = (dsp->tx_W-dsp->tx_R) & CMX_BUFF_MASK; 1689 + if (delay >= CMX_BUFF_HALF) 1690 + delay = 0; /* will be the delay before next write */ 1691 + /* check for lower delay */ 1692 + if (delay < dsp->tx_delay[0]) 1693 + dsp->tx_delay[0] = delay; 1694 + if (jittercheck) { 1695 + /* find the lowest of all rx_delays */ 1696 + delay = dsp->rx_delay[0]; 1697 + i = 1; 1698 + while (i < MAX_SECONDS_JITTER_CHECK) { 1699 + if (delay > dsp->rx_delay[i]) 1700 + delay = dsp->rx_delay[i]; 1701 + i++; 1702 + } 1703 + /* 1704 + * remove rx_delay only if we have delay AND we 1705 + * have not preset cmx_delay 1706 + */ 1707 + if (delay && !dsp->cmx_delay) { 1708 + if (dsp_debug & DEBUG_DSP_CMX) 1709 + printk(KERN_DEBUG 1710 + "%s lowest rx_delay of %d bytes for" 1711 + " dsp %s are now removed.\n", 1712 + __func__, delay, 1713 + dsp->name); 1714 + r = dsp->rx_R; 1715 + rr = (r + delay) & CMX_BUFF_MASK; 1716 + /* delete rx-data */ 1717 + while (r != rr) { 1718 + p[r] = dsp_silence; 1719 + r = (r+1) & CMX_BUFF_MASK; 1720 + } 1721 + /* increment rx-buffer pointer */ 1722 + dsp->rx_R = r; 1723 + /* write incremented read pointer */ 1724 + } 1725 + /* find the lowest of all tx_delays */ 1726 + delay = dsp->tx_delay[0]; 1727 + i = 1; 1728 + while (i < MAX_SECONDS_JITTER_CHECK) { 1729 + if (delay > dsp->tx_delay[i]) 1730 + delay = dsp->tx_delay[i]; 1731 + i++; 1732 + } 1733 + /* 1734 + * remove delay only if we have delay AND we 1735 + * have enabled tx_dejitter 1736 + */ 1737 + if (delay && dsp->tx_dejitter) { 1738 + if (dsp_debug & DEBUG_DSP_CMX) 1739 + printk(KERN_DEBUG 1740 + "%s lowest tx_delay of %d bytes for" 1741 + " dsp %s are now removed.\n", 1742 + __func__, delay, 1743 + dsp->name); 1744 + r = dsp->tx_R; 1745 + rr = (r + delay) & CMX_BUFF_MASK; 1746 + /* delete tx-data */ 1747 + while (r != rr) { 1748 + q[r] = dsp_silence; 1749 + r = (r+1) & CMX_BUFF_MASK; 1750 + } 1751 + /* increment rx-buffer pointer */ 1752 + dsp->tx_R = r; 1753 + /* write incremented read pointer */ 1754 + } 1755 + /* scroll up delays */ 1756 + i = MAX_SECONDS_JITTER_CHECK - 1; 1757 + while (i) { 1758 + dsp->rx_delay[i] = dsp->rx_delay[i-1]; 1759 + dsp->tx_delay[i] = dsp->tx_delay[i-1]; 1760 + i--; 1761 + } 1762 + dsp->tx_delay[0] = CMX_BUFF_HALF; /* (infinite) delay */ 1763 + dsp->rx_delay[0] = CMX_BUFF_HALF; /* (infinite) delay */ 1764 + } 1765 + } 1766 + 1767 + /* if next event would be in the past ... */ 1768 + if ((s32)(dsp_spl_jiffies+dsp_tics-jiffies) <= 0) 1769 + dsp_spl_jiffies = jiffies + 1; 1770 + else 1771 + dsp_spl_jiffies += dsp_tics; 1772 + 1773 + dsp_spl_tl.expires = dsp_spl_jiffies; 1774 + add_timer(&dsp_spl_tl); 1775 + 1776 + /* unlock */ 1777 + spin_unlock_irqrestore(&dsp_lock, flags); 1778 + } 1779 + 1780 + /* 1781 + * audio data is transmitted from upper layer to the dsp 1782 + */ 1783 + void 1784 + dsp_cmx_transmit(struct dsp *dsp, struct sk_buff *skb) 1785 + { 1786 + u_int w, ww; 1787 + u8 *d, *p; 1788 + int space; /* todo: , l = skb->len; */ 1789 + #ifdef CMX_TX_DEBUG 1790 + char debugbuf[256] = ""; 1791 + #endif 1792 + 1793 + /* check if there is enough space, and then copy */ 1794 + w = dsp->tx_W; 1795 + ww = dsp->tx_R; 1796 + p = dsp->tx_buff; 1797 + d = skb->data; 1798 + space = ww-w; 1799 + if (space <= 0) 1800 + space += CMX_BUFF_SIZE; 1801 + /* write-pointer should not overrun nor reach read pointer */ 1802 + if (space-1 < skb->len) 1803 + /* write to the space we have left */ 1804 + ww = (ww - 1) & CMX_BUFF_MASK; 1805 + else 1806 + /* write until all byte are copied */ 1807 + ww = (w + skb->len) & CMX_BUFF_MASK; 1808 + dsp->tx_W = ww; 1809 + 1810 + /* show current buffer */ 1811 + #ifdef CMX_DEBUG 1812 + printk(KERN_DEBUG 1813 + "cmx_transmit(dsp=%lx) %d bytes to 0x%x-0x%x. %s\n", 1814 + (u_long)dsp, (ww-w)&CMX_BUFF_MASK, w, ww, dsp->name); 1815 + #endif 1816 + 1817 + /* copy transmit data to tx-buffer */ 1818 + #ifdef CMX_TX_DEBUG 1819 + sprintf(debugbuf, "TX getting (%04x-%04x)%p: ", w, ww, p); 1820 + #endif 1821 + while (w != ww) { 1822 + #ifdef CMX_TX_DEBUG 1823 + if (strlen(debugbuf) < 48) 1824 + sprintf(debugbuf+strlen(debugbuf), " %02x", *d); 1825 + #endif 1826 + p[w] = *d++; 1827 + w = (w+1) & CMX_BUFF_MASK; 1828 + } 1829 + #ifdef CMX_TX_DEBUG 1830 + printk(KERN_DEBUG "%s\n", debugbuf); 1831 + #endif 1832 + 1833 + } 1834 + 1835 + /* 1836 + * hdlc data is received from card and sent to all members. 1837 + */ 1838 + void 1839 + dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb) 1840 + { 1841 + struct sk_buff *nskb = NULL; 1842 + struct dsp_conf_member *member; 1843 + struct mISDNhead *hh; 1844 + 1845 + /* not if not active */ 1846 + if (!dsp->b_active) 1847 + return; 1848 + 1849 + /* check if we have sompen */ 1850 + if (skb->len < 1) 1851 + return; 1852 + 1853 + /* no conf */ 1854 + if (!dsp->conf) { 1855 + /* in case of hardware (echo) */ 1856 + if (dsp->pcm_slot_tx >= 0) 1857 + return; 1858 + if (dsp->echo) 1859 + nskb = skb_clone(skb, GFP_ATOMIC); 1860 + if (nskb) { 1861 + hh = mISDN_HEAD_P(nskb); 1862 + hh->prim = PH_DATA_REQ; 1863 + hh->id = 0; 1864 + skb_queue_tail(&dsp->sendq, nskb); 1865 + schedule_work(&dsp->workq); 1866 + } 1867 + return; 1868 + } 1869 + /* in case of hardware conference */ 1870 + if (dsp->conf->hardware) 1871 + return; 1872 + list_for_each_entry(member, &dsp->conf->mlist, list) { 1873 + if (dsp->echo || member->dsp != dsp) { 1874 + nskb = skb_clone(skb, GFP_ATOMIC); 1875 + if (nskb) { 1876 + hh = mISDN_HEAD_P(nskb); 1877 + hh->prim = PH_DATA_REQ; 1878 + hh->id = 0; 1879 + skb_queue_tail(&member->dsp->sendq, nskb); 1880 + schedule_work(&member->dsp->workq); 1881 + } 1882 + } 1883 + } 1884 + } 1885 + 1886 +
+1191
drivers/isdn/mISDN/dsp_core.c
··· 1 + /* 2 + * Author Andreas Eversberg (jolly@eversberg.eu) 3 + * Based on source code structure by 4 + * Karsten Keil (keil@isdn4linux.de) 5 + * 6 + * This file is (c) under GNU PUBLIC LICENSE 7 + * For changes and modifications please read 8 + * ../../../Documentation/isdn/mISDN.cert 9 + * 10 + * Thanks to Karsten Keil (great drivers) 11 + * Cologne Chip (great chips) 12 + * 13 + * This module does: 14 + * Real-time tone generation 15 + * DTMF detection 16 + * Real-time cross-connection and conferrence 17 + * Compensate jitter due to system load and hardware fault. 18 + * All features are done in kernel space and will be realized 19 + * using hardware, if available and supported by chip set. 20 + * Blowfish encryption/decryption 21 + */ 22 + 23 + /* STRUCTURE: 24 + * 25 + * The dsp module provides layer 2 for b-channels (64kbit). It provides 26 + * transparent audio forwarding with special digital signal processing: 27 + * 28 + * - (1) generation of tones 29 + * - (2) detection of dtmf tones 30 + * - (3) crossconnecting and conferences (clocking) 31 + * - (4) echo generation for delay test 32 + * - (5) volume control 33 + * - (6) disable receive data 34 + * - (7) pipeline 35 + * - (8) encryption/decryption 36 + * 37 + * Look: 38 + * TX RX 39 + * ------upper layer------ 40 + * | ^ 41 + * | |(6) 42 + * v | 43 + * +-----+-------------+-----+ 44 + * |(3)(4) | 45 + * | CMX | 46 + * | | 47 + * | +-------------+ 48 + * | | ^ 49 + * | | | 50 + * |+---------+| +----+----+ 51 + * ||(1) || |(2) | 52 + * || || | | 53 + * || Tones || | DTMF | 54 + * || || | | 55 + * || || | | 56 + * |+----+----+| +----+----+ 57 + * +-----+-----+ ^ 58 + * | | 59 + * v | 60 + * +----+----+ +----+----+ 61 + * |(5) | |(5) | 62 + * | | | | 63 + * |TX Volume| |RX Volume| 64 + * | | | | 65 + * | | | | 66 + * +----+----+ +----+----+ 67 + * | ^ 68 + * | | 69 + * v | 70 + * +----+-------------+----+ 71 + * |(7) | 72 + * | | 73 + * | Pipeline Processing | 74 + * | | 75 + * | | 76 + * +----+-------------+----+ 77 + * | ^ 78 + * | | 79 + * v | 80 + * +----+----+ +----+----+ 81 + * |(8) | |(8) | 82 + * | | | | 83 + * | Encrypt | | Decrypt | 84 + * | | | | 85 + * | | | | 86 + * +----+----+ +----+----+ 87 + * | ^ 88 + * | | 89 + * v | 90 + * ------card layer------ 91 + * TX RX 92 + * 93 + * Above you can see the logical data flow. If software is used to do the 94 + * process, it is actually the real data flow. If hardware is used, data 95 + * may not flow, but hardware commands to the card, to provide the data flow 96 + * as shown. 97 + * 98 + * NOTE: The channel must be activated in order to make dsp work, even if 99 + * no data flow to the upper layer is intended. Activation can be done 100 + * after and before controlling the setting using PH_CONTROL requests. 101 + * 102 + * DTMF: Will be detected by hardware if possible. It is done before CMX 103 + * processing. 104 + * 105 + * Tones: Will be generated via software if endless looped audio fifos are 106 + * not supported by hardware. Tones will override all data from CMX. 107 + * It is not required to join a conference to use tones at any time. 108 + * 109 + * CMX: Is transparent when not used. When it is used, it will do 110 + * crossconnections and conferences via software if not possible through 111 + * hardware. If hardware capability is available, hardware is used. 112 + * 113 + * Echo: Is generated by CMX and is used to check performane of hard and 114 + * software CMX. 115 + * 116 + * The CMX has special functions for conferences with one, two and more 117 + * members. It will allow different types of data flow. Receive and transmit 118 + * data to/form upper layer may be swithed on/off individually without loosing 119 + * features of CMX, Tones and DTMF. 120 + * 121 + * Echo Cancellation: Sometimes we like to cancel echo from the interface. 122 + * Note that a VoIP call may not have echo caused by the IP phone. The echo 123 + * is generated by the telephone line connected to it. Because the delay 124 + * is high, it becomes an echo. RESULT: Echo Cachelation is required if 125 + * both echo AND delay is applied to an interface. 126 + * Remember that software CMX always generates a more or less delay. 127 + * 128 + * If all used features can be realized in hardware, and if transmit and/or 129 + * receive data ist disabled, the card may not send/receive any data at all. 130 + * Not receiving is usefull if only announcements are played. Not sending is 131 + * usefull if an answering machine records audio. Not sending and receiving is 132 + * usefull during most states of the call. If supported by hardware, tones 133 + * will be played without cpu load. Small PBXs and NT-Mode applications will 134 + * not need expensive hardware when processing calls. 135 + * 136 + * 137 + * LOCKING: 138 + * 139 + * When data is received from upper or lower layer (card), the complete dsp 140 + * module is locked by a global lock. This lock MUST lock irq, because it 141 + * must lock timer events by DSP poll timer. 142 + * When data is ready to be transmitted down, the data is queued and sent 143 + * outside lock and timer event. 144 + * PH_CONTROL must not change any settings, join or split conference members 145 + * during process of data. 146 + * 147 + * HDLC: 148 + * 149 + * It works quite the same as transparent, except that HDLC data is forwarded 150 + * to all other conference members if no hardware bridging is possible. 151 + * Send data will be writte to sendq. Sendq will be sent if confirm is received. 152 + * Conference cannot join, if one member is not hdlc. 153 + * 154 + */ 155 + 156 + #include <linux/delay.h> 157 + #include <linux/mISDNif.h> 158 + #include <linux/mISDNdsp.h> 159 + #include <linux/module.h> 160 + #include <linux/vmalloc.h> 161 + #include "core.h" 162 + #include "dsp.h" 163 + 164 + const char *mISDN_dsp_revision = "2.0"; 165 + 166 + static int debug; 167 + static int options; 168 + static int poll; 169 + static int dtmfthreshold = 100; 170 + 171 + MODULE_AUTHOR("Andreas Eversberg"); 172 + module_param(debug, uint, S_IRUGO | S_IWUSR); 173 + module_param(options, uint, S_IRUGO | S_IWUSR); 174 + module_param(poll, uint, S_IRUGO | S_IWUSR); 175 + module_param(dtmfthreshold, uint, S_IRUGO | S_IWUSR); 176 + MODULE_LICENSE("GPL"); 177 + 178 + /*int spinnest = 0;*/ 179 + 180 + spinlock_t dsp_lock; /* global dsp lock */ 181 + struct list_head dsp_ilist; 182 + struct list_head conf_ilist; 183 + int dsp_debug; 184 + int dsp_options; 185 + int dsp_poll, dsp_tics; 186 + 187 + /* check if rx may be turned off or must be turned on */ 188 + static void 189 + dsp_rx_off_member(struct dsp *dsp) 190 + { 191 + struct mISDN_ctrl_req cq; 192 + int rx_off = 1; 193 + 194 + if (!dsp->features_rx_off) 195 + return; 196 + 197 + /* not disabled */ 198 + if (!dsp->rx_disabled) 199 + rx_off = 0; 200 + /* software dtmf */ 201 + else if (dsp->dtmf.software) 202 + rx_off = 0; 203 + /* echo in software */ 204 + else if (dsp->echo && dsp->pcm_slot_tx < 0) 205 + rx_off = 0; 206 + /* bridge in software */ 207 + else if (dsp->conf) { 208 + if (dsp->conf->software) 209 + rx_off = 0; 210 + } 211 + 212 + if (rx_off == dsp->rx_is_off) 213 + return; 214 + 215 + if (!dsp->ch.peer) { 216 + if (dsp_debug & DEBUG_DSP_CORE) 217 + printk(KERN_DEBUG "%s: no peer, no rx_off\n", 218 + __func__); 219 + return; 220 + } 221 + cq.op = MISDN_CTRL_RX_OFF; 222 + cq.p1 = rx_off; 223 + if (dsp->ch.peer->ctrl(dsp->ch.peer, CONTROL_CHANNEL, &cq)) { 224 + printk(KERN_DEBUG "%s: 2nd CONTROL_CHANNEL failed\n", 225 + __func__); 226 + return; 227 + } 228 + dsp->rx_is_off = rx_off; 229 + if (dsp_debug & DEBUG_DSP_CORE) 230 + printk(KERN_DEBUG "%s: %s set rx_off = %d\n", 231 + __func__, dsp->name, rx_off); 232 + } 233 + static void 234 + dsp_rx_off(struct dsp *dsp) 235 + { 236 + struct dsp_conf_member *member; 237 + 238 + if (dsp_options & DSP_OPT_NOHARDWARE) 239 + return; 240 + 241 + /* no conf */ 242 + if (!dsp->conf) { 243 + dsp_rx_off_member(dsp); 244 + return; 245 + } 246 + /* check all members in conf */ 247 + list_for_each_entry(member, &dsp->conf->mlist, list) { 248 + dsp_rx_off_member(member->dsp); 249 + } 250 + } 251 + 252 + static int 253 + dsp_control_req(struct dsp *dsp, struct mISDNhead *hh, struct sk_buff *skb) 254 + { 255 + struct sk_buff *nskb; 256 + int ret = 0; 257 + int cont; 258 + u8 *data; 259 + int len; 260 + 261 + if (skb->len < sizeof(int)) 262 + printk(KERN_ERR "%s: PH_CONTROL message too short\n", __func__); 263 + cont = *((int *)skb->data); 264 + len = skb->len - sizeof(int); 265 + data = skb->data + sizeof(int); 266 + 267 + switch (cont) { 268 + case DTMF_TONE_START: /* turn on DTMF */ 269 + if (dsp->hdlc) { 270 + ret = -EINVAL; 271 + break; 272 + } 273 + if (dsp_debug & DEBUG_DSP_CORE) 274 + printk(KERN_DEBUG "%s: start dtmf\n", __func__); 275 + if (len == sizeof(int)) { 276 + printk(KERN_NOTICE "changing DTMF Threshold " 277 + "to %d\n", *((int *)data)); 278 + dsp->dtmf.treshold = (*(int *)data) * 10000; 279 + } 280 + /* init goertzel */ 281 + dsp_dtmf_goertzel_init(dsp); 282 + 283 + /* check dtmf hardware */ 284 + dsp_dtmf_hardware(dsp); 285 + break; 286 + case DTMF_TONE_STOP: /* turn off DTMF */ 287 + if (dsp_debug & DEBUG_DSP_CORE) 288 + printk(KERN_DEBUG "%s: stop dtmf\n", __func__); 289 + dsp->dtmf.hardware = 0; 290 + dsp->dtmf.software = 0; 291 + break; 292 + case DSP_CONF_JOIN: /* join / update conference */ 293 + if (len < sizeof(int)) { 294 + ret = -EINVAL; 295 + break; 296 + } 297 + if (*((u32 *)data) == 0) 298 + goto conf_split; 299 + if (dsp_debug & DEBUG_DSP_CORE) 300 + printk(KERN_DEBUG "%s: join conference %d\n", 301 + __func__, *((u32 *)data)); 302 + ret = dsp_cmx_conf(dsp, *((u32 *)data)); 303 + /* dsp_cmx_hardware will also be called here */ 304 + dsp_rx_off(dsp); 305 + if (dsp_debug & DEBUG_DSP_CMX) 306 + dsp_cmx_debug(dsp); 307 + break; 308 + case DSP_CONF_SPLIT: /* remove from conference */ 309 + conf_split: 310 + if (dsp_debug & DEBUG_DSP_CORE) 311 + printk(KERN_DEBUG "%s: release conference\n", __func__); 312 + ret = dsp_cmx_conf(dsp, 0); 313 + /* dsp_cmx_hardware will also be called here */ 314 + if (dsp_debug & DEBUG_DSP_CMX) 315 + dsp_cmx_debug(dsp); 316 + dsp_rx_off(dsp); 317 + break; 318 + case DSP_TONE_PATT_ON: /* play tone */ 319 + if (dsp->hdlc) { 320 + ret = -EINVAL; 321 + break; 322 + } 323 + if (len < sizeof(int)) { 324 + ret = -EINVAL; 325 + break; 326 + } 327 + if (dsp_debug & DEBUG_DSP_CORE) 328 + printk(KERN_DEBUG "%s: turn tone 0x%x on\n", 329 + __func__, *((int *)skb->data)); 330 + ret = dsp_tone(dsp, *((int *)data)); 331 + if (!ret) { 332 + dsp_cmx_hardware(dsp->conf, dsp); 333 + dsp_rx_off(dsp); 334 + } 335 + if (!dsp->tone.tone) 336 + goto tone_off; 337 + break; 338 + case DSP_TONE_PATT_OFF: /* stop tone */ 339 + if (dsp->hdlc) { 340 + ret = -EINVAL; 341 + break; 342 + } 343 + if (dsp_debug & DEBUG_DSP_CORE) 344 + printk(KERN_DEBUG "%s: turn tone off\n", __func__); 345 + dsp_tone(dsp, 0); 346 + dsp_cmx_hardware(dsp->conf, dsp); 347 + dsp_rx_off(dsp); 348 + /* reset tx buffers (user space data) */ 349 + tone_off: 350 + dsp->rx_W = 0; 351 + dsp->rx_R = 0; 352 + break; 353 + case DSP_VOL_CHANGE_TX: /* change volume */ 354 + if (dsp->hdlc) { 355 + ret = -EINVAL; 356 + break; 357 + } 358 + if (len < sizeof(int)) { 359 + ret = -EINVAL; 360 + break; 361 + } 362 + dsp->tx_volume = *((int *)data); 363 + if (dsp_debug & DEBUG_DSP_CORE) 364 + printk(KERN_DEBUG "%s: change tx vol to %d\n", 365 + __func__, dsp->tx_volume); 366 + dsp_cmx_hardware(dsp->conf, dsp); 367 + dsp_dtmf_hardware(dsp); 368 + dsp_rx_off(dsp); 369 + break; 370 + case DSP_VOL_CHANGE_RX: /* change volume */ 371 + if (dsp->hdlc) { 372 + ret = -EINVAL; 373 + break; 374 + } 375 + if (len < sizeof(int)) { 376 + ret = -EINVAL; 377 + break; 378 + } 379 + dsp->rx_volume = *((int *)data); 380 + if (dsp_debug & DEBUG_DSP_CORE) 381 + printk(KERN_DEBUG "%s: change rx vol to %d\n", 382 + __func__, dsp->tx_volume); 383 + dsp_cmx_hardware(dsp->conf, dsp); 384 + dsp_dtmf_hardware(dsp); 385 + dsp_rx_off(dsp); 386 + break; 387 + case DSP_ECHO_ON: /* enable echo */ 388 + dsp->echo = 1; /* soft echo */ 389 + if (dsp_debug & DEBUG_DSP_CORE) 390 + printk(KERN_DEBUG "%s: enable cmx-echo\n", __func__); 391 + dsp_cmx_hardware(dsp->conf, dsp); 392 + dsp_rx_off(dsp); 393 + if (dsp_debug & DEBUG_DSP_CMX) 394 + dsp_cmx_debug(dsp); 395 + break; 396 + case DSP_ECHO_OFF: /* disable echo */ 397 + dsp->echo = 0; 398 + if (dsp_debug & DEBUG_DSP_CORE) 399 + printk(KERN_DEBUG "%s: disable cmx-echo\n", __func__); 400 + dsp_cmx_hardware(dsp->conf, dsp); 401 + dsp_rx_off(dsp); 402 + if (dsp_debug & DEBUG_DSP_CMX) 403 + dsp_cmx_debug(dsp); 404 + break; 405 + case DSP_RECEIVE_ON: /* enable receive to user space */ 406 + if (dsp_debug & DEBUG_DSP_CORE) 407 + printk(KERN_DEBUG "%s: enable receive to user " 408 + "space\n", __func__); 409 + dsp->rx_disabled = 0; 410 + dsp_rx_off(dsp); 411 + break; 412 + case DSP_RECEIVE_OFF: /* disable receive to user space */ 413 + if (dsp_debug & DEBUG_DSP_CORE) 414 + printk(KERN_DEBUG "%s: disable receive to " 415 + "user space\n", __func__); 416 + dsp->rx_disabled = 1; 417 + dsp_rx_off(dsp); 418 + break; 419 + case DSP_MIX_ON: /* enable mixing of tx data */ 420 + if (dsp->hdlc) { 421 + ret = -EINVAL; 422 + break; 423 + } 424 + if (dsp_debug & DEBUG_DSP_CORE) 425 + printk(KERN_DEBUG "%s: enable mixing of " 426 + "tx-data with conf mebers\n", __func__); 427 + dsp->tx_mix = 1; 428 + dsp_cmx_hardware(dsp->conf, dsp); 429 + dsp_rx_off(dsp); 430 + if (dsp_debug & DEBUG_DSP_CMX) 431 + dsp_cmx_debug(dsp); 432 + break; 433 + case DSP_MIX_OFF: /* disable mixing of tx data */ 434 + if (dsp->hdlc) { 435 + ret = -EINVAL; 436 + break; 437 + } 438 + if (dsp_debug & DEBUG_DSP_CORE) 439 + printk(KERN_DEBUG "%s: disable mixing of " 440 + "tx-data with conf mebers\n", __func__); 441 + dsp->tx_mix = 0; 442 + dsp_cmx_hardware(dsp->conf, dsp); 443 + dsp_rx_off(dsp); 444 + if (dsp_debug & DEBUG_DSP_CMX) 445 + dsp_cmx_debug(dsp); 446 + break; 447 + case DSP_TXDATA_ON: /* enable txdata */ 448 + dsp->tx_data = 1; 449 + if (dsp_debug & DEBUG_DSP_CORE) 450 + printk(KERN_DEBUG "%s: enable tx-data\n", __func__); 451 + dsp_cmx_hardware(dsp->conf, dsp); 452 + dsp_rx_off(dsp); 453 + if (dsp_debug & DEBUG_DSP_CMX) 454 + dsp_cmx_debug(dsp); 455 + break; 456 + case DSP_TXDATA_OFF: /* disable txdata */ 457 + dsp->tx_data = 0; 458 + if (dsp_debug & DEBUG_DSP_CORE) 459 + printk(KERN_DEBUG "%s: disable tx-data\n", __func__); 460 + dsp_cmx_hardware(dsp->conf, dsp); 461 + dsp_rx_off(dsp); 462 + if (dsp_debug & DEBUG_DSP_CMX) 463 + dsp_cmx_debug(dsp); 464 + break; 465 + case DSP_DELAY: /* use delay algorithm instead of dynamic 466 + jitter algorithm */ 467 + if (dsp->hdlc) { 468 + ret = -EINVAL; 469 + break; 470 + } 471 + if (len < sizeof(int)) { 472 + ret = -EINVAL; 473 + break; 474 + } 475 + dsp->cmx_delay = (*((int *)data)) << 3; 476 + /* miliseconds to samples */ 477 + if (dsp->cmx_delay >= (CMX_BUFF_HALF>>1)) 478 + /* clip to half of maximum usable buffer 479 + (half of half buffer) */ 480 + dsp->cmx_delay = (CMX_BUFF_HALF>>1) - 1; 481 + if (dsp_debug & DEBUG_DSP_CORE) 482 + printk(KERN_DEBUG "%s: use delay algorithm to " 483 + "compensate jitter (%d samples)\n", 484 + __func__, dsp->cmx_delay); 485 + break; 486 + case DSP_JITTER: /* use dynamic jitter algorithm instead of 487 + delay algorithm */ 488 + if (dsp->hdlc) { 489 + ret = -EINVAL; 490 + break; 491 + } 492 + dsp->cmx_delay = 0; 493 + if (dsp_debug & DEBUG_DSP_CORE) 494 + printk(KERN_DEBUG "%s: use jitter algorithm to " 495 + "compensate jitter\n", __func__); 496 + break; 497 + case DSP_TX_DEJITTER: /* use dynamic jitter algorithm for tx-buffer */ 498 + if (dsp->hdlc) { 499 + ret = -EINVAL; 500 + break; 501 + } 502 + dsp->tx_dejitter = 1; 503 + if (dsp_debug & DEBUG_DSP_CORE) 504 + printk(KERN_DEBUG "%s: use dejitter on TX " 505 + "buffer\n", __func__); 506 + break; 507 + case DSP_TX_DEJ_OFF: /* use tx-buffer without dejittering*/ 508 + if (dsp->hdlc) { 509 + ret = -EINVAL; 510 + break; 511 + } 512 + dsp->tx_dejitter = 0; 513 + if (dsp_debug & DEBUG_DSP_CORE) 514 + printk(KERN_DEBUG "%s: use TX buffer without " 515 + "dejittering\n", __func__); 516 + break; 517 + case DSP_PIPELINE_CFG: 518 + if (dsp->hdlc) { 519 + ret = -EINVAL; 520 + break; 521 + } 522 + if (len > 0 && ((char *)data)[len - 1]) { 523 + printk(KERN_DEBUG "%s: pipeline config string " 524 + "is not NULL terminated!\n", __func__); 525 + ret = -EINVAL; 526 + } else { 527 + dsp->pipeline.inuse = 1; 528 + dsp_cmx_hardware(dsp->conf, dsp); 529 + ret = dsp_pipeline_build(&dsp->pipeline, 530 + len > 0 ? (char *)data : NULL); 531 + dsp_cmx_hardware(dsp->conf, dsp); 532 + dsp_rx_off(dsp); 533 + } 534 + break; 535 + case DSP_BF_ENABLE_KEY: /* turn blowfish on */ 536 + if (dsp->hdlc) { 537 + ret = -EINVAL; 538 + break; 539 + } 540 + if (len < 4 || len > 56) { 541 + ret = -EINVAL; 542 + break; 543 + } 544 + if (dsp_debug & DEBUG_DSP_CORE) 545 + printk(KERN_DEBUG "%s: turn blowfish on (key " 546 + "not shown)\n", __func__); 547 + ret = dsp_bf_init(dsp, (u8 *)data, len); 548 + /* set new cont */ 549 + if (!ret) 550 + cont = DSP_BF_ACCEPT; 551 + else 552 + cont = DSP_BF_REJECT; 553 + /* send indication if it worked to set it */ 554 + nskb = _alloc_mISDN_skb(PH_CONTROL_IND, MISDN_ID_ANY, 555 + sizeof(int), &cont, GFP_ATOMIC); 556 + if (nskb) { 557 + if (dsp->up) { 558 + if (dsp->up->send(dsp->up, nskb)) 559 + dev_kfree_skb(nskb); 560 + } else 561 + dev_kfree_skb(nskb); 562 + } 563 + if (!ret) { 564 + dsp_cmx_hardware(dsp->conf, dsp); 565 + dsp_dtmf_hardware(dsp); 566 + dsp_rx_off(dsp); 567 + } 568 + break; 569 + case DSP_BF_DISABLE: /* turn blowfish off */ 570 + if (dsp->hdlc) { 571 + ret = -EINVAL; 572 + break; 573 + } 574 + if (dsp_debug & DEBUG_DSP_CORE) 575 + printk(KERN_DEBUG "%s: turn blowfish off\n", __func__); 576 + dsp_bf_cleanup(dsp); 577 + dsp_cmx_hardware(dsp->conf, dsp); 578 + dsp_dtmf_hardware(dsp); 579 + dsp_rx_off(dsp); 580 + break; 581 + default: 582 + if (dsp_debug & DEBUG_DSP_CORE) 583 + printk(KERN_DEBUG "%s: ctrl req %x unhandled\n", 584 + __func__, cont); 585 + ret = -EINVAL; 586 + } 587 + return ret; 588 + } 589 + 590 + static void 591 + get_features(struct mISDNchannel *ch) 592 + { 593 + struct dsp *dsp = container_of(ch, struct dsp, ch); 594 + struct mISDN_ctrl_req cq; 595 + 596 + if (dsp_options & DSP_OPT_NOHARDWARE) 597 + return; 598 + if (!ch->peer) { 599 + if (dsp_debug & DEBUG_DSP_CORE) 600 + printk(KERN_DEBUG "%s: no peer, no features\n", 601 + __func__); 602 + return; 603 + } 604 + memset(&cq, 0, sizeof(cq)); 605 + cq.op = MISDN_CTRL_GETOP; 606 + if (ch->peer->ctrl(ch->peer, CONTROL_CHANNEL, &cq) < 0) { 607 + printk(KERN_DEBUG "%s: CONTROL_CHANNEL failed\n", 608 + __func__); 609 + return; 610 + } 611 + if (cq.op & MISDN_CTRL_RX_OFF) 612 + dsp->features_rx_off = 1; 613 + if ((cq.op & MISDN_CTRL_HW_FEATURES_OP)) { 614 + cq.op = MISDN_CTRL_HW_FEATURES; 615 + *((u_long *)&cq.p1) = (u_long)&dsp->features; 616 + if (ch->peer->ctrl(ch->peer, CONTROL_CHANNEL, &cq)) { 617 + printk(KERN_DEBUG "%s: 2nd CONTROL_CHANNEL failed\n", 618 + __func__); 619 + } 620 + } else 621 + if (dsp_debug & DEBUG_DSP_CORE) 622 + printk(KERN_DEBUG "%s: features not supported for %s\n", 623 + __func__, dsp->name); 624 + } 625 + 626 + static int 627 + dsp_function(struct mISDNchannel *ch, struct sk_buff *skb) 628 + { 629 + struct dsp *dsp = container_of(ch, struct dsp, ch); 630 + struct mISDNhead *hh; 631 + int ret = 0; 632 + u8 *digits; 633 + int cont; 634 + struct sk_buff *nskb; 635 + u_long flags; 636 + 637 + hh = mISDN_HEAD_P(skb); 638 + switch (hh->prim) { 639 + /* FROM DOWN */ 640 + case (PH_DATA_CNF): 641 + dsp->data_pending = 0; 642 + /* trigger next hdlc frame, if any */ 643 + if (dsp->hdlc) { 644 + spin_lock_irqsave(&dsp_lock, flags); 645 + if (dsp->b_active) 646 + schedule_work(&dsp->workq); 647 + spin_unlock_irqrestore(&dsp_lock, flags); 648 + } 649 + break; 650 + case (PH_DATA_IND): 651 + case (DL_DATA_IND): 652 + if (skb->len < 1) { 653 + ret = -EINVAL; 654 + break; 655 + } 656 + if (dsp->rx_is_off) { 657 + if (dsp_debug & DEBUG_DSP_CORE) 658 + printk(KERN_DEBUG "%s: rx-data during rx_off" 659 + " for %s\n", 660 + __func__, dsp->name); 661 + } 662 + if (dsp->hdlc) { 663 + /* hdlc */ 664 + spin_lock_irqsave(&dsp_lock, flags); 665 + dsp_cmx_hdlc(dsp, skb); 666 + spin_unlock_irqrestore(&dsp_lock, flags); 667 + if (dsp->rx_disabled) { 668 + /* if receive is not allowed */ 669 + break; 670 + } 671 + hh->prim = DL_DATA_IND; 672 + if (dsp->up) 673 + return dsp->up->send(dsp->up, skb); 674 + break; 675 + } 676 + 677 + /* decrypt if enabled */ 678 + if (dsp->bf_enable) 679 + dsp_bf_decrypt(dsp, skb->data, skb->len); 680 + /* pipeline */ 681 + if (dsp->pipeline.inuse) 682 + dsp_pipeline_process_rx(&dsp->pipeline, skb->data, 683 + skb->len); 684 + /* change volume if requested */ 685 + if (dsp->rx_volume) 686 + dsp_change_volume(skb, dsp->rx_volume); 687 + 688 + /* check if dtmf soft decoding is turned on */ 689 + if (dsp->dtmf.software) { 690 + digits = dsp_dtmf_goertzel_decode(dsp, skb->data, 691 + skb->len, (dsp_options&DSP_OPT_ULAW)?1:0); 692 + while (*digits) { 693 + if (dsp_debug & DEBUG_DSP_DTMF) 694 + printk(KERN_DEBUG "%s: digit" 695 + "(%c) to layer %s\n", 696 + __func__, *digits, dsp->name); 697 + cont = DTMF_TONE_VAL | *digits; 698 + nskb = _alloc_mISDN_skb(PH_CONTROL_IND, 699 + MISDN_ID_ANY, sizeof(int), &cont, 700 + GFP_ATOMIC); 701 + if (nskb) { 702 + if (dsp->up) { 703 + if (dsp->up->send( 704 + dsp->up, nskb)) 705 + dev_kfree_skb(nskb); 706 + } else 707 + dev_kfree_skb(nskb); 708 + } 709 + digits++; 710 + } 711 + } 712 + /* we need to process receive data if software */ 713 + spin_lock_irqsave(&dsp_lock, flags); 714 + if (dsp->pcm_slot_tx < 0 && dsp->pcm_slot_rx < 0) { 715 + /* process data from card at cmx */ 716 + dsp_cmx_receive(dsp, skb); 717 + } 718 + spin_unlock_irqrestore(&dsp_lock, flags); 719 + 720 + if (dsp->rx_disabled) { 721 + /* if receive is not allowed */ 722 + break; 723 + } 724 + hh->prim = DL_DATA_IND; 725 + if (dsp->up) 726 + return dsp->up->send(dsp->up, skb); 727 + break; 728 + case (PH_CONTROL_IND): 729 + if (dsp_debug & DEBUG_DSP_DTMFCOEFF) 730 + printk(KERN_DEBUG "%s: PH_CONTROL INDICATION " 731 + "received: %x (len %d) %s\n", __func__, 732 + hh->id, skb->len, dsp->name); 733 + switch (hh->id) { 734 + case (DTMF_HFC_COEF): /* getting coefficients */ 735 + if (!dsp->dtmf.hardware) { 736 + if (dsp_debug & DEBUG_DSP_DTMFCOEFF) 737 + printk(KERN_DEBUG "%s: ignoring DTMF " 738 + "coefficients from HFC\n", 739 + __func__); 740 + break; 741 + } 742 + digits = dsp_dtmf_goertzel_decode(dsp, skb->data, 743 + skb->len, 2); 744 + while (*digits) { 745 + int k; 746 + struct sk_buff *nskb; 747 + if (dsp_debug & DEBUG_DSP_DTMF) 748 + printk(KERN_DEBUG "%s: digit" 749 + "(%c) to layer %s\n", 750 + __func__, *digits, dsp->name); 751 + k = *digits | DTMF_TONE_VAL; 752 + nskb = _alloc_mISDN_skb(PH_CONTROL_IND, 753 + MISDN_ID_ANY, sizeof(int), &k, 754 + GFP_ATOMIC); 755 + if (nskb) { 756 + if (dsp->up) { 757 + if (dsp->up->send( 758 + dsp->up, nskb)) 759 + dev_kfree_skb(nskb); 760 + } else 761 + dev_kfree_skb(nskb); 762 + } 763 + digits++; 764 + } 765 + break; 766 + case (HFC_VOL_CHANGE_TX): /* change volume */ 767 + if (skb->len != sizeof(int)) { 768 + ret = -EINVAL; 769 + break; 770 + } 771 + spin_lock_irqsave(&dsp_lock, flags); 772 + dsp->tx_volume = *((int *)skb->data); 773 + if (dsp_debug & DEBUG_DSP_CORE) 774 + printk(KERN_DEBUG "%s: change tx volume to " 775 + "%d\n", __func__, dsp->tx_volume); 776 + dsp_cmx_hardware(dsp->conf, dsp); 777 + dsp_dtmf_hardware(dsp); 778 + dsp_rx_off(dsp); 779 + spin_unlock_irqrestore(&dsp_lock, flags); 780 + break; 781 + default: 782 + if (dsp_debug & DEBUG_DSP_CORE) 783 + printk(KERN_DEBUG "%s: ctrl ind %x unhandled " 784 + "%s\n", __func__, hh->id, dsp->name); 785 + ret = -EINVAL; 786 + } 787 + break; 788 + case (PH_ACTIVATE_IND): 789 + case (PH_ACTIVATE_CNF): 790 + if (dsp_debug & DEBUG_DSP_CORE) 791 + printk(KERN_DEBUG "%s: b_channel is now active %s\n", 792 + __func__, dsp->name); 793 + /* bchannel now active */ 794 + spin_lock_irqsave(&dsp_lock, flags); 795 + dsp->b_active = 1; 796 + dsp->data_pending = 0; 797 + dsp->rx_init = 1; 798 + /* rx_W and rx_R will be adjusted on first frame */ 799 + dsp->rx_W = 0; 800 + dsp->rx_R = 0; 801 + memset(dsp->rx_buff, 0, sizeof(dsp->rx_buff)); 802 + dsp_cmx_hardware(dsp->conf, dsp); 803 + dsp_dtmf_hardware(dsp); 804 + dsp_rx_off(dsp); 805 + spin_unlock_irqrestore(&dsp_lock, flags); 806 + if (dsp_debug & DEBUG_DSP_CORE) 807 + printk(KERN_DEBUG "%s: done with activation, sending " 808 + "confirm to user space. %s\n", __func__, 809 + dsp->name); 810 + /* send activation to upper layer */ 811 + hh->prim = DL_ESTABLISH_CNF; 812 + if (dsp->up) 813 + return dsp->up->send(dsp->up, skb); 814 + break; 815 + case (PH_DEACTIVATE_IND): 816 + case (PH_DEACTIVATE_CNF): 817 + if (dsp_debug & DEBUG_DSP_CORE) 818 + printk(KERN_DEBUG "%s: b_channel is now inactive %s\n", 819 + __func__, dsp->name); 820 + /* bchannel now inactive */ 821 + spin_lock_irqsave(&dsp_lock, flags); 822 + dsp->b_active = 0; 823 + dsp->data_pending = 0; 824 + dsp_cmx_hardware(dsp->conf, dsp); 825 + dsp_rx_off(dsp); 826 + spin_unlock_irqrestore(&dsp_lock, flags); 827 + hh->prim = DL_RELEASE_CNF; 828 + if (dsp->up) 829 + return dsp->up->send(dsp->up, skb); 830 + break; 831 + /* FROM UP */ 832 + case (DL_DATA_REQ): 833 + case (PH_DATA_REQ): 834 + if (skb->len < 1) { 835 + ret = -EINVAL; 836 + break; 837 + } 838 + if (dsp->hdlc) { 839 + /* hdlc */ 840 + spin_lock_irqsave(&dsp_lock, flags); 841 + if (dsp->b_active) { 842 + skb_queue_tail(&dsp->sendq, skb); 843 + schedule_work(&dsp->workq); 844 + } 845 + spin_unlock_irqrestore(&dsp_lock, flags); 846 + return 0; 847 + } 848 + /* send data to tx-buffer (if no tone is played) */ 849 + if (!dsp->tone.tone) { 850 + spin_lock_irqsave(&dsp_lock, flags); 851 + dsp_cmx_transmit(dsp, skb); 852 + spin_unlock_irqrestore(&dsp_lock, flags); 853 + } 854 + break; 855 + case (PH_CONTROL_REQ): 856 + spin_lock_irqsave(&dsp_lock, flags); 857 + ret = dsp_control_req(dsp, hh, skb); 858 + spin_unlock_irqrestore(&dsp_lock, flags); 859 + break; 860 + case (DL_ESTABLISH_REQ): 861 + case (PH_ACTIVATE_REQ): 862 + if (dsp_debug & DEBUG_DSP_CORE) 863 + printk(KERN_DEBUG "%s: activating b_channel %s\n", 864 + __func__, dsp->name); 865 + if (dsp->dtmf.hardware || dsp->dtmf.software) 866 + dsp_dtmf_goertzel_init(dsp); 867 + get_features(ch); 868 + /* send ph_activate */ 869 + hh->prim = PH_ACTIVATE_REQ; 870 + if (ch->peer) 871 + return ch->recv(ch->peer, skb); 872 + break; 873 + case (DL_RELEASE_REQ): 874 + case (PH_DEACTIVATE_REQ): 875 + if (dsp_debug & DEBUG_DSP_CORE) 876 + printk(KERN_DEBUG "%s: releasing b_channel %s\n", 877 + __func__, dsp->name); 878 + spin_lock_irqsave(&dsp_lock, flags); 879 + dsp->tone.tone = 0; 880 + dsp->tone.hardware = 0; 881 + dsp->tone.software = 0; 882 + if (timer_pending(&dsp->tone.tl)) 883 + del_timer(&dsp->tone.tl); 884 + if (dsp->conf) 885 + dsp_cmx_conf(dsp, 0); /* dsp_cmx_hardware will also be 886 + called here */ 887 + skb_queue_purge(&dsp->sendq); 888 + spin_unlock_irqrestore(&dsp_lock, flags); 889 + hh->prim = PH_DEACTIVATE_REQ; 890 + if (ch->peer) 891 + return ch->recv(ch->peer, skb); 892 + break; 893 + default: 894 + if (dsp_debug & DEBUG_DSP_CORE) 895 + printk(KERN_DEBUG "%s: msg %x unhandled %s\n", 896 + __func__, hh->prim, dsp->name); 897 + ret = -EINVAL; 898 + } 899 + if (!ret) 900 + dev_kfree_skb(skb); 901 + return ret; 902 + } 903 + 904 + static int 905 + dsp_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg) 906 + { 907 + struct dsp *dsp = container_of(ch, struct dsp, ch); 908 + u_long flags; 909 + int err = 0; 910 + 911 + if (debug & DEBUG_DSP_CTRL) 912 + printk(KERN_DEBUG "%s:(%x)\n", __func__, cmd); 913 + 914 + switch (cmd) { 915 + case OPEN_CHANNEL: 916 + break; 917 + case CLOSE_CHANNEL: 918 + if (dsp->ch.peer) 919 + dsp->ch.peer->ctrl(dsp->ch.peer, CLOSE_CHANNEL, NULL); 920 + 921 + /* wait until workqueue has finished, 922 + * must lock here, or we may hit send-process currently 923 + * queueing. */ 924 + spin_lock_irqsave(&dsp_lock, flags); 925 + dsp->b_active = 0; 926 + spin_unlock_irqrestore(&dsp_lock, flags); 927 + /* MUST not be locked, because it waits until queue is done. */ 928 + cancel_work_sync(&dsp->workq); 929 + spin_lock_irqsave(&dsp_lock, flags); 930 + if (timer_pending(&dsp->tone.tl)) 931 + del_timer(&dsp->tone.tl); 932 + skb_queue_purge(&dsp->sendq); 933 + if (dsp_debug & DEBUG_DSP_CTRL) 934 + printk(KERN_DEBUG "%s: releasing member %s\n", 935 + __func__, dsp->name); 936 + dsp->b_active = 0; 937 + dsp_cmx_conf(dsp, 0); /* dsp_cmx_hardware will also be called 938 + here */ 939 + dsp_pipeline_destroy(&dsp->pipeline); 940 + 941 + if (dsp_debug & DEBUG_DSP_CTRL) 942 + printk(KERN_DEBUG "%s: remove & destroy object %s\n", 943 + __func__, dsp->name); 944 + list_del(&dsp->list); 945 + spin_unlock_irqrestore(&dsp_lock, flags); 946 + 947 + if (dsp_debug & DEBUG_DSP_CTRL) 948 + printk(KERN_DEBUG "%s: dsp instance released\n", 949 + __func__); 950 + vfree(dsp); 951 + module_put(THIS_MODULE); 952 + break; 953 + } 954 + return err; 955 + } 956 + 957 + static void 958 + dsp_send_bh(struct work_struct *work) 959 + { 960 + struct dsp *dsp = container_of(work, struct dsp, workq); 961 + struct sk_buff *skb; 962 + struct mISDNhead *hh; 963 + 964 + if (dsp->hdlc && dsp->data_pending) 965 + return; /* wait until data has been acknowledged */ 966 + 967 + /* send queued data */ 968 + while ((skb = skb_dequeue(&dsp->sendq))) { 969 + /* in locked date, we must have still data in queue */ 970 + if (dsp->data_pending) { 971 + if (dsp_debug & DEBUG_DSP_CORE) 972 + printk(KERN_DEBUG "%s: fifo full %s, this is " 973 + "no bug!\n", __func__, dsp->name); 974 + /* flush transparent data, if not acked */ 975 + dev_kfree_skb(skb); 976 + continue; 977 + } 978 + hh = mISDN_HEAD_P(skb); 979 + if (hh->prim == DL_DATA_REQ) { 980 + /* send packet up */ 981 + if (dsp->up) { 982 + if (dsp->up->send(dsp->up, skb)) 983 + dev_kfree_skb(skb); 984 + } else 985 + dev_kfree_skb(skb); 986 + } else { 987 + /* send packet down */ 988 + if (dsp->ch.peer) { 989 + dsp->data_pending = 1; 990 + if (dsp->ch.recv(dsp->ch.peer, skb)) { 991 + dev_kfree_skb(skb); 992 + dsp->data_pending = 0; 993 + } 994 + } else 995 + dev_kfree_skb(skb); 996 + } 997 + } 998 + } 999 + 1000 + static int 1001 + dspcreate(struct channel_req *crq) 1002 + { 1003 + struct dsp *ndsp; 1004 + u_long flags; 1005 + 1006 + if (crq->protocol != ISDN_P_B_L2DSP 1007 + && crq->protocol != ISDN_P_B_L2DSPHDLC) 1008 + return -EPROTONOSUPPORT; 1009 + ndsp = vmalloc(sizeof(struct dsp)); 1010 + if (!ndsp) { 1011 + printk(KERN_ERR "%s: vmalloc struct dsp failed\n", __func__); 1012 + return -ENOMEM; 1013 + } 1014 + memset(ndsp, 0, sizeof(struct dsp)); 1015 + if (dsp_debug & DEBUG_DSP_CTRL) 1016 + printk(KERN_DEBUG "%s: creating new dsp instance\n", __func__); 1017 + 1018 + /* default enabled */ 1019 + INIT_WORK(&ndsp->workq, (void *)dsp_send_bh); 1020 + skb_queue_head_init(&ndsp->sendq); 1021 + ndsp->ch.send = dsp_function; 1022 + ndsp->ch.ctrl = dsp_ctrl; 1023 + ndsp->up = crq->ch; 1024 + crq->ch = &ndsp->ch; 1025 + if (crq->protocol == ISDN_P_B_L2DSP) { 1026 + crq->protocol = ISDN_P_B_RAW; 1027 + ndsp->hdlc = 0; 1028 + } else { 1029 + crq->protocol = ISDN_P_B_HDLC; 1030 + ndsp->hdlc = 1; 1031 + } 1032 + if (!try_module_get(THIS_MODULE)) 1033 + printk(KERN_WARNING "%s:cannot get module\n", 1034 + __func__); 1035 + 1036 + sprintf(ndsp->name, "DSP_C%x(0x%p)", 1037 + ndsp->up->st->dev->id + 1, ndsp); 1038 + /* set frame size to start */ 1039 + ndsp->features.hfc_id = -1; /* current PCM id */ 1040 + ndsp->features.pcm_id = -1; /* current PCM id */ 1041 + ndsp->pcm_slot_rx = -1; /* current CPM slot */ 1042 + ndsp->pcm_slot_tx = -1; 1043 + ndsp->pcm_bank_rx = -1; 1044 + ndsp->pcm_bank_tx = -1; 1045 + ndsp->hfc_conf = -1; /* current conference number */ 1046 + /* set tone timer */ 1047 + ndsp->tone.tl.function = (void *)dsp_tone_timeout; 1048 + ndsp->tone.tl.data = (long) ndsp; 1049 + init_timer(&ndsp->tone.tl); 1050 + 1051 + if (dtmfthreshold < 20 || dtmfthreshold > 500) 1052 + dtmfthreshold = 200; 1053 + ndsp->dtmf.treshold = dtmfthreshold*10000; 1054 + 1055 + /* init pipeline append to list */ 1056 + spin_lock_irqsave(&dsp_lock, flags); 1057 + dsp_pipeline_init(&ndsp->pipeline); 1058 + list_add_tail(&ndsp->list, &dsp_ilist); 1059 + spin_unlock_irqrestore(&dsp_lock, flags); 1060 + 1061 + return 0; 1062 + } 1063 + 1064 + 1065 + static struct Bprotocol DSP = { 1066 + .Bprotocols = (1 << (ISDN_P_B_L2DSP & ISDN_P_B_MASK)) 1067 + | (1 << (ISDN_P_B_L2DSPHDLC & ISDN_P_B_MASK)), 1068 + .name = "dsp", 1069 + .create = dspcreate 1070 + }; 1071 + 1072 + static int dsp_init(void) 1073 + { 1074 + int err; 1075 + int tics; 1076 + 1077 + printk(KERN_INFO "DSP modul %s\n", mISDN_dsp_revision); 1078 + 1079 + dsp_options = options; 1080 + dsp_debug = debug; 1081 + 1082 + /* set packet size */ 1083 + dsp_poll = poll; 1084 + if (dsp_poll) { 1085 + if (dsp_poll > MAX_POLL) { 1086 + printk(KERN_ERR "%s: Wrong poll value (%d), use %d " 1087 + "maximum.\n", __func__, poll, MAX_POLL); 1088 + err = -EINVAL; 1089 + return err; 1090 + } 1091 + if (dsp_poll < 8) { 1092 + printk(KERN_ERR "%s: Wrong poll value (%d), use 8 " 1093 + "minimum.\n", __func__, dsp_poll); 1094 + err = -EINVAL; 1095 + return err; 1096 + } 1097 + dsp_tics = poll * HZ / 8000; 1098 + if (dsp_tics * 8000 != poll * HZ) { 1099 + printk(KERN_INFO "mISDN_dsp: Cannot clock every %d " 1100 + "samples (0,125 ms). It is not a multiple of " 1101 + "%d HZ.\n", poll, HZ); 1102 + err = -EINVAL; 1103 + return err; 1104 + } 1105 + } else { 1106 + poll = 8; 1107 + while (poll <= MAX_POLL) { 1108 + tics = poll * HZ / 8000; 1109 + if (tics * 8000 == poll * HZ) { 1110 + dsp_tics = tics; 1111 + dsp_poll = poll; 1112 + if (poll >= 64) 1113 + break; 1114 + } 1115 + poll++; 1116 + } 1117 + } 1118 + if (dsp_poll == 0) { 1119 + printk(KERN_INFO "mISDN_dsp: There is no multiple of kernel " 1120 + "clock that equals exactly the duration of 8-256 " 1121 + "samples. (Choose kernel clock speed like 100, 250, " 1122 + "300, 1000)\n"); 1123 + err = -EINVAL; 1124 + return err; 1125 + } 1126 + printk(KERN_INFO "mISDN_dsp: DSP clocks every %d samples. This equals " 1127 + "%d jiffies.\n", dsp_poll, dsp_tics); 1128 + 1129 + spin_lock_init(&dsp_lock); 1130 + INIT_LIST_HEAD(&dsp_ilist); 1131 + INIT_LIST_HEAD(&conf_ilist); 1132 + 1133 + /* init conversion tables */ 1134 + dsp_audio_generate_law_tables(); 1135 + dsp_silence = (dsp_options&DSP_OPT_ULAW)?0xff:0x2a; 1136 + dsp_audio_law_to_s32 = (dsp_options&DSP_OPT_ULAW)?dsp_audio_ulaw_to_s32: 1137 + dsp_audio_alaw_to_s32; 1138 + dsp_audio_generate_s2law_table(); 1139 + dsp_audio_generate_seven(); 1140 + dsp_audio_generate_mix_table(); 1141 + if (dsp_options & DSP_OPT_ULAW) 1142 + dsp_audio_generate_ulaw_samples(); 1143 + dsp_audio_generate_volume_changes(); 1144 + 1145 + err = dsp_pipeline_module_init(); 1146 + if (err) { 1147 + printk(KERN_ERR "mISDN_dsp: Can't initialize pipeline, " 1148 + "error(%d)\n", err); 1149 + return err; 1150 + } 1151 + 1152 + err = mISDN_register_Bprotocol(&DSP); 1153 + if (err) { 1154 + printk(KERN_ERR "Can't register %s error(%d)\n", DSP.name, err); 1155 + return err; 1156 + } 1157 + 1158 + /* set sample timer */ 1159 + dsp_spl_tl.function = (void *)dsp_cmx_send; 1160 + dsp_spl_tl.data = 0; 1161 + init_timer(&dsp_spl_tl); 1162 + dsp_spl_tl.expires = jiffies + dsp_tics; 1163 + dsp_spl_jiffies = dsp_spl_tl.expires; 1164 + add_timer(&dsp_spl_tl); 1165 + 1166 + return 0; 1167 + } 1168 + 1169 + 1170 + static void dsp_cleanup(void) 1171 + { 1172 + mISDN_unregister_Bprotocol(&DSP); 1173 + 1174 + if (timer_pending(&dsp_spl_tl)) 1175 + del_timer(&dsp_spl_tl); 1176 + 1177 + if (!list_empty(&dsp_ilist)) { 1178 + printk(KERN_ERR "mISDN_dsp: Audio DSP object inst list not " 1179 + "empty.\n"); 1180 + } 1181 + if (!list_empty(&conf_ilist)) { 1182 + printk(KERN_ERR "mISDN_dsp: Conference list not empty. Not " 1183 + "all memory freed.\n"); 1184 + } 1185 + 1186 + dsp_pipeline_module_exit(); 1187 + } 1188 + 1189 + module_init(dsp_init); 1190 + module_exit(dsp_cleanup); 1191 +
+303
drivers/isdn/mISDN/dsp_dtmf.c
··· 1 + /* 2 + * DTMF decoder. 3 + * 4 + * Copyright by Andreas Eversberg (jolly@eversberg.eu) 5 + * based on different decoders such as ISDN4Linux 6 + * 7 + * This software may be used and distributed according to the terms 8 + * of the GNU General Public License, incorporated herein by reference. 9 + * 10 + */ 11 + 12 + #include <linux/mISDNif.h> 13 + #include <linux/mISDNdsp.h> 14 + #include "core.h" 15 + #include "dsp.h" 16 + 17 + #define NCOEFF 8 /* number of frequencies to be analyzed */ 18 + 19 + /* For DTMF recognition: 20 + * 2 * cos(2 * PI * k / N) precalculated for all k 21 + */ 22 + static u64 cos2pik[NCOEFF] = 23 + { 24 + /* k << 15 (source: hfc-4s/8s documentation (www.colognechip.de)) */ 25 + 55960, 53912, 51402, 48438, 38146, 32650, 26170, 18630 26 + }; 27 + 28 + /* digit matrix */ 29 + static char dtmf_matrix[4][4] = 30 + { 31 + {'1', '2', '3', 'A'}, 32 + {'4', '5', '6', 'B'}, 33 + {'7', '8', '9', 'C'}, 34 + {'*', '0', '#', 'D'} 35 + }; 36 + 37 + /* dtmf detection using goertzel algorithm 38 + * init function 39 + */ 40 + void dsp_dtmf_goertzel_init(struct dsp *dsp) 41 + { 42 + dsp->dtmf.size = 0; 43 + dsp->dtmf.lastwhat = '\0'; 44 + dsp->dtmf.lastdigit = '\0'; 45 + dsp->dtmf.count = 0; 46 + } 47 + 48 + /* check for hardware or software features 49 + */ 50 + void dsp_dtmf_hardware(struct dsp *dsp) 51 + { 52 + int hardware = 1; 53 + 54 + if (!dsp->features.hfc_dtmf) 55 + hardware = 0; 56 + 57 + /* check for volume change */ 58 + if (dsp->tx_volume) { 59 + if (dsp_debug & DEBUG_DSP_DTMF) 60 + printk(KERN_DEBUG "%s dsp %s cannot do hardware DTMF, " 61 + "because tx_volume is changed\n", 62 + __func__, dsp->name); 63 + hardware = 0; 64 + } 65 + if (dsp->rx_volume) { 66 + if (dsp_debug & DEBUG_DSP_DTMF) 67 + printk(KERN_DEBUG "%s dsp %s cannot do hardware DTMF, " 68 + "because rx_volume is changed\n", 69 + __func__, dsp->name); 70 + hardware = 0; 71 + } 72 + /* check if encryption is enabled */ 73 + if (dsp->bf_enable) { 74 + if (dsp_debug & DEBUG_DSP_DTMF) 75 + printk(KERN_DEBUG "%s dsp %s cannot do hardware DTMF, " 76 + "because encryption is enabled\n", 77 + __func__, dsp->name); 78 + hardware = 0; 79 + } 80 + /* check if pipeline exists */ 81 + if (dsp->pipeline.inuse) { 82 + if (dsp_debug & DEBUG_DSP_DTMF) 83 + printk(KERN_DEBUG "%s dsp %s cannot do hardware DTMF, " 84 + "because pipeline exists.\n", 85 + __func__, dsp->name); 86 + hardware = 0; 87 + } 88 + 89 + dsp->dtmf.hardware = hardware; 90 + dsp->dtmf.software = !hardware; 91 + } 92 + 93 + 94 + /************************************************************* 95 + * calculate the coefficients of the given sample and decode * 96 + *************************************************************/ 97 + 98 + /* the given sample is decoded. if the sample is not long enough for a 99 + * complete frame, the decoding is finished and continued with the next 100 + * call of this function. 101 + * 102 + * the algorithm is very good for detection with a minimum of errors. i 103 + * tested it allot. it even works with very short tones (40ms). the only 104 + * disadvantage is, that it doesn't work good with different volumes of both 105 + * tones. this will happen, if accoustically coupled dialers are used. 106 + * it sometimes detects tones during speach, which is normal for decoders. 107 + * use sequences to given commands during calls. 108 + * 109 + * dtmf - points to a structure of the current dtmf state 110 + * spl and len - the sample 111 + * fmt - 0 = alaw, 1 = ulaw, 2 = coefficients from HFC DTMF hw-decoder 112 + */ 113 + 114 + u8 115 + *dsp_dtmf_goertzel_decode(struct dsp *dsp, u8 *data, int len, int fmt) 116 + { 117 + u8 what; 118 + int size; 119 + signed short *buf; 120 + s32 sk, sk1, sk2; 121 + int k, n, i; 122 + s32 *hfccoeff; 123 + s32 result[NCOEFF], tresh, treshl; 124 + int lowgroup, highgroup; 125 + s64 cos2pik_; 126 + 127 + dsp->dtmf.digits[0] = '\0'; 128 + 129 + /* Note: The function will loop until the buffer has not enough samples 130 + * left to decode a full frame. 131 + */ 132 + again: 133 + /* convert samples */ 134 + size = dsp->dtmf.size; 135 + buf = dsp->dtmf.buffer; 136 + switch (fmt) { 137 + case 0: /* alaw */ 138 + case 1: /* ulaw */ 139 + while (size < DSP_DTMF_NPOINTS && len) { 140 + buf[size++] = dsp_audio_law_to_s32[*data++]; 141 + len--; 142 + } 143 + break; 144 + 145 + case 2: /* HFC coefficients */ 146 + default: 147 + if (len < 64) { 148 + if (len > 0) 149 + printk(KERN_ERR "%s: coefficients have invalid " 150 + "size. (is=%d < must=%d)\n", 151 + __func__, len, 64); 152 + return dsp->dtmf.digits; 153 + } 154 + hfccoeff = (s32 *)data; 155 + for (k = 0; k < NCOEFF; k++) { 156 + sk2 = (*hfccoeff++)>>4; 157 + sk = (*hfccoeff++)>>4; 158 + if (sk > 32767 || sk < -32767 || sk2 > 32767 159 + || sk2 < -32767) 160 + printk(KERN_WARNING 161 + "DTMF-Detection overflow\n"); 162 + /* compute |X(k)|**2 */ 163 + result[k] = 164 + (sk * sk) - 165 + (((cos2pik[k] * sk) >> 15) * sk2) + 166 + (sk2 * sk2); 167 + } 168 + data += 64; 169 + len -= 64; 170 + goto coefficients; 171 + break; 172 + } 173 + dsp->dtmf.size = size; 174 + 175 + if (size < DSP_DTMF_NPOINTS) 176 + return dsp->dtmf.digits; 177 + 178 + dsp->dtmf.size = 0; 179 + 180 + /* now we have a full buffer of signed long samples - we do goertzel */ 181 + for (k = 0; k < NCOEFF; k++) { 182 + sk = 0; 183 + sk1 = 0; 184 + sk2 = 0; 185 + buf = dsp->dtmf.buffer; 186 + cos2pik_ = cos2pik[k]; 187 + for (n = 0; n < DSP_DTMF_NPOINTS; n++) { 188 + sk = ((cos2pik_*sk1)>>15) - sk2 + (*buf++); 189 + sk2 = sk1; 190 + sk1 = sk; 191 + } 192 + sk >>= 8; 193 + sk2 >>= 8; 194 + if (sk > 32767 || sk < -32767 || sk2 > 32767 || sk2 < -32767) 195 + printk(KERN_WARNING "DTMF-Detection overflow\n"); 196 + /* compute |X(k)|**2 */ 197 + result[k] = 198 + (sk * sk) - 199 + (((cos2pik[k] * sk) >> 15) * sk2) + 200 + (sk2 * sk2); 201 + } 202 + 203 + /* our (squared) coefficients have been calculated, we need to process 204 + * them. 205 + */ 206 + coefficients: 207 + tresh = 0; 208 + for (i = 0; i < NCOEFF; i++) { 209 + if (result[i] < 0) 210 + result[i] = 0; 211 + if (result[i] > dsp->dtmf.treshold) { 212 + if (result[i] > tresh) 213 + tresh = result[i]; 214 + } 215 + } 216 + 217 + if (tresh == 0) { 218 + what = 0; 219 + goto storedigit; 220 + } 221 + 222 + if (dsp_debug & DEBUG_DSP_DTMFCOEFF) 223 + printk(KERN_DEBUG "a %3d %3d %3d %3d %3d %3d %3d %3d" 224 + " tr:%3d r %3d %3d %3d %3d %3d %3d %3d %3d\n", 225 + result[0]/10000, result[1]/10000, result[2]/10000, 226 + result[3]/10000, result[4]/10000, result[5]/10000, 227 + result[6]/10000, result[7]/10000, tresh/10000, 228 + result[0]/(tresh/100), result[1]/(tresh/100), 229 + result[2]/(tresh/100), result[3]/(tresh/100), 230 + result[4]/(tresh/100), result[5]/(tresh/100), 231 + result[6]/(tresh/100), result[7]/(tresh/100)); 232 + 233 + /* calc digit (lowgroup/highgroup) */ 234 + lowgroup = -1; 235 + highgroup = -1; 236 + treshl = tresh >> 3; /* tones which are not on, must be below 9 dB */ 237 + tresh = tresh >> 2; /* touchtones must match within 6 dB */ 238 + for (i = 0; i < NCOEFF; i++) { 239 + if (result[i] < treshl) 240 + continue; /* ignore */ 241 + if (result[i] < tresh) { 242 + lowgroup = -1; 243 + highgroup = -1; 244 + break; /* noise inbetween */ 245 + } 246 + /* good level found. This is allowed only one time per group */ 247 + if (i < NCOEFF/2) { 248 + /* lowgroup */ 249 + if (lowgroup >= 0) { 250 + /* Bad. Another tone found. */ 251 + lowgroup = -1; 252 + break; 253 + } else 254 + lowgroup = i; 255 + } else { 256 + /* higroup */ 257 + if (highgroup >= 0) { 258 + /* Bad. Another tone found. */ 259 + highgroup = -1; 260 + break; 261 + } else 262 + highgroup = i-(NCOEFF/2); 263 + } 264 + } 265 + 266 + /* get digit or null */ 267 + what = 0; 268 + if (lowgroup >= 0 && highgroup >= 0) 269 + what = dtmf_matrix[lowgroup][highgroup]; 270 + 271 + storedigit: 272 + if (what && (dsp_debug & DEBUG_DSP_DTMF)) 273 + printk(KERN_DEBUG "DTMF what: %c\n", what); 274 + 275 + if (dsp->dtmf.lastwhat != what) 276 + dsp->dtmf.count = 0; 277 + 278 + /* the tone (or no tone) must remain 3 times without change */ 279 + if (dsp->dtmf.count == 2) { 280 + if (dsp->dtmf.lastdigit != what) { 281 + dsp->dtmf.lastdigit = what; 282 + if (what) { 283 + if (dsp_debug & DEBUG_DSP_DTMF) 284 + printk(KERN_DEBUG "DTMF digit: %c\n", 285 + what); 286 + if ((strlen(dsp->dtmf.digits)+1) 287 + < sizeof(dsp->dtmf.digits)) { 288 + dsp->dtmf.digits[strlen( 289 + dsp->dtmf.digits)+1] = '\0'; 290 + dsp->dtmf.digits[strlen( 291 + dsp->dtmf.digits)] = what; 292 + } 293 + } 294 + } 295 + } else 296 + dsp->dtmf.count++; 297 + 298 + dsp->dtmf.lastwhat = what; 299 + 300 + goto again; 301 + } 302 + 303 +
+110
drivers/isdn/mISDN/dsp_ecdis.h
··· 1 + /* 2 + * SpanDSP - a series of DSP components for telephony 3 + * 4 + * ec_disable_detector.h - A detector which should eventually meet the 5 + * G.164/G.165 requirements for detecting the 6 + * 2100Hz echo cancellor disable tone. 7 + * 8 + * Written by Steve Underwood <steveu@coppice.org> 9 + * 10 + * Copyright (C) 2001 Steve Underwood 11 + * 12 + * All rights reserved. 13 + * 14 + * This program is free software; you can redistribute it and/or modify 15 + * it under the terms of the GNU General Public License as published by 16 + * the Free Software Foundation; either version 2 of the License, or 17 + * (at your option) any later version. 18 + * 19 + * This program is distributed in the hope that it will be useful, 20 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 + * GNU General Public License for more details. 23 + * 24 + * You should have received a copy of the GNU General Public License 25 + * along with this program; if not, write to the Free Software 26 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 + * 28 + */ 29 + 30 + #include "dsp_biquad.h" 31 + 32 + struct ec_disable_detector_state { 33 + struct biquad2_state notch; 34 + int notch_level; 35 + int channel_level; 36 + int tone_present; 37 + int tone_cycle_duration; 38 + int good_cycles; 39 + int hit; 40 + }; 41 + 42 + 43 + #define FALSE 0 44 + #define TRUE (!FALSE) 45 + 46 + static inline void 47 + echo_can_disable_detector_init(struct ec_disable_detector_state *det) 48 + { 49 + /* Elliptic notch */ 50 + /* This is actually centred at 2095Hz, but gets the balance we want, due 51 + to the asymmetric walls of the notch */ 52 + biquad2_init(&det->notch, 53 + (int32_t) (-0.7600000*32768.0), 54 + (int32_t) (-0.1183852*32768.0), 55 + (int32_t) (-0.5104039*32768.0), 56 + (int32_t) (0.1567596*32768.0), 57 + (int32_t) (1.0000000*32768.0)); 58 + 59 + det->channel_level = 0; 60 + det->notch_level = 0; 61 + det->tone_present = FALSE; 62 + det->tone_cycle_duration = 0; 63 + det->good_cycles = 0; 64 + det->hit = 0; 65 + } 66 + /*- End of function --------------------------------------------------------*/ 67 + 68 + static inline int 69 + echo_can_disable_detector_update(struct ec_disable_detector_state *det, 70 + int16_t amp) 71 + { 72 + int16_t notched; 73 + 74 + notched = biquad2(&det->notch, amp); 75 + /* Estimate the overall energy in the channel, and the energy in 76 + the notch (i.e. overall channel energy - tone energy => noise). 77 + Use abs instead of multiply for speed (is it really faster?). 78 + Damp the overall energy a little more for a stable result. 79 + Damp the notch energy a little less, so we don't damp out the 80 + blip every time the phase reverses */ 81 + det->channel_level += ((abs(amp) - det->channel_level) >> 5); 82 + det->notch_level += ((abs(notched) - det->notch_level) >> 4); 83 + if (det->channel_level > 280) { 84 + /* There is adequate energy in the channel. 85 + Is it mostly at 2100Hz? */ 86 + if (det->notch_level*6 < det->channel_level) { 87 + /* The notch says yes, so we have the tone. */ 88 + if (!det->tone_present) { 89 + /* Do we get a kick every 450+-25ms? */ 90 + if (det->tone_cycle_duration >= 425*8 91 + && det->tone_cycle_duration <= 475*8) { 92 + det->good_cycles++; 93 + if (det->good_cycles > 2) 94 + det->hit = TRUE; 95 + } 96 + det->tone_cycle_duration = 0; 97 + } 98 + det->tone_present = TRUE; 99 + } else 100 + det->tone_present = FALSE; 101 + det->tone_cycle_duration++; 102 + } else { 103 + det->tone_present = FALSE; 104 + det->tone_cycle_duration = 0; 105 + det->good_cycles = 0; 106 + } 107 + return det->hit; 108 + } 109 + /*- End of function --------------------------------------------------------*/ 110 + /*- End of file ------------------------------------------------------------*/
+138
drivers/isdn/mISDN/dsp_hwec.c
··· 1 + /* 2 + * dsp_hwec.c: 3 + * builtin mISDN dsp pipeline element for enabling the hw echocanceller 4 + * 5 + * Copyright (C) 2007, Nadi Sarrar 6 + * 7 + * Nadi Sarrar <nadi@beronet.com> 8 + * 9 + * This program is free software; you can redistribute it and/or modify it 10 + * under the terms of the GNU General Public License as published by the Free 11 + * Software Foundation; either version 2 of the License, or (at your option) 12 + * any later version. 13 + * 14 + * This program is distributed in the hope that it will be useful, but WITHOUT 15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 17 + * more details. 18 + * 19 + * You should have received a copy of the GNU General Public License along with 20 + * this program; if not, write to the Free Software Foundation, Inc., 59 21 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22 + * 23 + * The full GNU General Public License is included in this distribution in the 24 + * file called LICENSE. 25 + * 26 + */ 27 + 28 + #include <linux/kernel.h> 29 + #include <linux/string.h> 30 + #include <linux/mISDNdsp.h> 31 + #include <linux/mISDNif.h> 32 + #include "core.h" 33 + #include "dsp.h" 34 + #include "dsp_hwec.h" 35 + 36 + static struct mISDN_dsp_element_arg args[] = { 37 + { "deftaps", "128", "Set the number of taps of cancellation." }, 38 + }; 39 + 40 + static struct mISDN_dsp_element dsp_hwec_p = { 41 + .name = "hwec", 42 + .new = NULL, 43 + .free = NULL, 44 + .process_tx = NULL, 45 + .process_rx = NULL, 46 + .num_args = sizeof(args) / sizeof(struct mISDN_dsp_element_arg), 47 + .args = args, 48 + }; 49 + struct mISDN_dsp_element *dsp_hwec = &dsp_hwec_p; 50 + 51 + void dsp_hwec_enable(struct dsp *dsp, const char *arg) 52 + { 53 + int deftaps = 128, 54 + len; 55 + struct mISDN_ctrl_req cq; 56 + 57 + if (!dsp) { 58 + printk(KERN_ERR "%s: failed to enable hwec: dsp is NULL\n", 59 + __func__); 60 + return; 61 + } 62 + 63 + if (!arg) 64 + goto _do; 65 + 66 + len = strlen(arg); 67 + if (!len) 68 + goto _do; 69 + 70 + { 71 + char _dup[len + 1]; 72 + char *dup, *tok, *name, *val; 73 + int tmp; 74 + 75 + strcpy(_dup, arg); 76 + dup = _dup; 77 + 78 + while ((tok = strsep(&dup, ","))) { 79 + if (!strlen(tok)) 80 + continue; 81 + name = strsep(&tok, "="); 82 + val = tok; 83 + 84 + if (!val) 85 + continue; 86 + 87 + if (!strcmp(name, "deftaps")) { 88 + if (sscanf(val, "%d", &tmp) == 1) 89 + deftaps = tmp; 90 + } 91 + } 92 + } 93 + 94 + _do: 95 + printk(KERN_DEBUG "%s: enabling hwec with deftaps=%d\n", 96 + __func__, deftaps); 97 + memset(&cq, 0, sizeof(cq)); 98 + cq.op = MISDN_CTRL_HFC_ECHOCAN_ON; 99 + cq.p1 = deftaps; 100 + if (!dsp->ch.peer->ctrl(&dsp->ch, CONTROL_CHANNEL, &cq)) { 101 + printk(KERN_DEBUG "%s: CONTROL_CHANNEL failed\n", 102 + __func__); 103 + return; 104 + } 105 + } 106 + 107 + void dsp_hwec_disable(struct dsp *dsp) 108 + { 109 + struct mISDN_ctrl_req cq; 110 + 111 + if (!dsp) { 112 + printk(KERN_ERR "%s: failed to disable hwec: dsp is NULL\n", 113 + __func__); 114 + return; 115 + } 116 + 117 + printk(KERN_DEBUG "%s: disabling hwec\n", __func__); 118 + memset(&cq, 0, sizeof(cq)); 119 + cq.op = MISDN_CTRL_HFC_ECHOCAN_OFF; 120 + if (!dsp->ch.peer->ctrl(&dsp->ch, CONTROL_CHANNEL, &cq)) { 121 + printk(KERN_DEBUG "%s: CONTROL_CHANNEL failed\n", 122 + __func__); 123 + return; 124 + } 125 + } 126 + 127 + int dsp_hwec_init(void) 128 + { 129 + mISDN_dsp_element_register(dsp_hwec); 130 + 131 + return 0; 132 + } 133 + 134 + void dsp_hwec_exit(void) 135 + { 136 + mISDN_dsp_element_unregister(dsp_hwec); 137 + } 138 +
+10
drivers/isdn/mISDN/dsp_hwec.h
··· 1 + /* 2 + * dsp_hwec.h 3 + */ 4 + 5 + extern struct mISDN_dsp_element *dsp_hwec; 6 + extern void dsp_hwec_enable(struct dsp *dsp, const char *arg); 7 + extern void dsp_hwec_disable(struct dsp *dsp); 8 + extern int dsp_hwec_init(void); 9 + extern void dsp_hwec_exit(void); 10 +
+348
drivers/isdn/mISDN/dsp_pipeline.c
··· 1 + /* 2 + * dsp_pipeline.c: pipelined audio processing 3 + * 4 + * Copyright (C) 2007, Nadi Sarrar 5 + * 6 + * Nadi Sarrar <nadi@beronet.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify it 9 + * under the terms of the GNU General Public License as published by the Free 10 + * Software Foundation; either version 2 of the License, or (at your option) 11 + * any later version. 12 + * 13 + * This program is distributed in the hope that it will be useful, but WITHOUT 14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 16 + * more details. 17 + * 18 + * You should have received a copy of the GNU General Public License along with 19 + * this program; if not, write to the Free Software Foundation, Inc., 59 20 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 + * 22 + * The full GNU General Public License is included in this distribution in the 23 + * file called LICENSE. 24 + * 25 + */ 26 + 27 + #include <linux/kernel.h> 28 + #include <linux/list.h> 29 + #include <linux/string.h> 30 + #include <linux/mISDNif.h> 31 + #include <linux/mISDNdsp.h> 32 + #include "dsp.h" 33 + #include "dsp_hwec.h" 34 + 35 + /* uncomment for debugging */ 36 + /*#define PIPELINE_DEBUG*/ 37 + 38 + struct dsp_pipeline_entry { 39 + struct mISDN_dsp_element *elem; 40 + void *p; 41 + struct list_head list; 42 + }; 43 + struct dsp_element_entry { 44 + struct mISDN_dsp_element *elem; 45 + struct device dev; 46 + struct list_head list; 47 + }; 48 + 49 + static LIST_HEAD(dsp_elements); 50 + 51 + /* sysfs */ 52 + static struct class *elements_class; 53 + 54 + static ssize_t 55 + attr_show_args(struct device *dev, struct device_attribute *attr, char *buf) 56 + { 57 + struct mISDN_dsp_element *elem = dev_get_drvdata(dev); 58 + ssize_t len = 0; 59 + int i = 0; 60 + 61 + *buf = 0; 62 + for (; i < elem->num_args; ++i) 63 + len = sprintf(buf, "%sName: %s\n%s%s%sDescription: %s\n" 64 + "\n", buf, 65 + elem->args[i].name, 66 + elem->args[i].def ? "Default: " : "", 67 + elem->args[i].def ? elem->args[i].def : "", 68 + elem->args[i].def ? "\n" : "", 69 + elem->args[i].desc); 70 + 71 + return len; 72 + } 73 + 74 + static struct device_attribute element_attributes[] = { 75 + __ATTR(args, 0444, attr_show_args, NULL), 76 + }; 77 + 78 + int mISDN_dsp_element_register(struct mISDN_dsp_element *elem) 79 + { 80 + struct dsp_element_entry *entry; 81 + int ret, i; 82 + 83 + if (!elem) 84 + return -EINVAL; 85 + 86 + entry = kzalloc(sizeof(struct dsp_element_entry), GFP_KERNEL); 87 + if (!entry) 88 + return -ENOMEM; 89 + 90 + entry->elem = elem; 91 + 92 + entry->dev.class = elements_class; 93 + dev_set_drvdata(&entry->dev, elem); 94 + snprintf(entry->dev.bus_id, BUS_ID_SIZE, elem->name); 95 + ret = device_register(&entry->dev); 96 + if (ret) { 97 + printk(KERN_ERR "%s: failed to register %s\n", 98 + __func__, elem->name); 99 + goto err1; 100 + } 101 + 102 + for (i = 0; i < (sizeof(element_attributes) 103 + / sizeof(struct device_attribute)); ++i) 104 + ret = device_create_file(&entry->dev, 105 + &element_attributes[i]); 106 + if (ret) { 107 + printk(KERN_ERR "%s: failed to create device file\n", 108 + __func__); 109 + goto err2; 110 + } 111 + 112 + list_add_tail(&entry->list, &dsp_elements); 113 + 114 + printk(KERN_DEBUG "%s: %s registered\n", __func__, elem->name); 115 + 116 + return 0; 117 + 118 + err2: 119 + device_unregister(&entry->dev); 120 + err1: 121 + kfree(entry); 122 + return ret; 123 + } 124 + EXPORT_SYMBOL(mISDN_dsp_element_register); 125 + 126 + void mISDN_dsp_element_unregister(struct mISDN_dsp_element *elem) 127 + { 128 + struct dsp_element_entry *entry, *n; 129 + 130 + if (!elem) 131 + return; 132 + 133 + list_for_each_entry_safe(entry, n, &dsp_elements, list) 134 + if (entry->elem == elem) { 135 + list_del(&entry->list); 136 + device_unregister(&entry->dev); 137 + kfree(entry); 138 + printk(KERN_DEBUG "%s: %s unregistered\n", 139 + __func__, elem->name); 140 + return; 141 + } 142 + printk(KERN_ERR "%s: element %s not in list.\n", __func__, elem->name); 143 + } 144 + EXPORT_SYMBOL(mISDN_dsp_element_unregister); 145 + 146 + int dsp_pipeline_module_init(void) 147 + { 148 + elements_class = class_create(THIS_MODULE, "dsp_pipeline"); 149 + if (IS_ERR(elements_class)) 150 + return PTR_ERR(elements_class); 151 + 152 + #ifdef PIPELINE_DEBUG 153 + printk(KERN_DEBUG "%s: dsp pipeline module initialized\n", __func__); 154 + #endif 155 + 156 + dsp_hwec_init(); 157 + 158 + return 0; 159 + } 160 + 161 + void dsp_pipeline_module_exit(void) 162 + { 163 + struct dsp_element_entry *entry, *n; 164 + 165 + dsp_hwec_exit(); 166 + 167 + class_destroy(elements_class); 168 + 169 + list_for_each_entry_safe(entry, n, &dsp_elements, list) { 170 + list_del(&entry->list); 171 + printk(KERN_WARNING "%s: element was still registered: %s\n", 172 + __func__, entry->elem->name); 173 + kfree(entry); 174 + } 175 + 176 + printk(KERN_DEBUG "%s: dsp pipeline module exited\n", __func__); 177 + } 178 + 179 + int dsp_pipeline_init(struct dsp_pipeline *pipeline) 180 + { 181 + if (!pipeline) 182 + return -EINVAL; 183 + 184 + INIT_LIST_HEAD(&pipeline->list); 185 + 186 + #ifdef PIPELINE_DEBUG 187 + printk(KERN_DEBUG "%s: dsp pipeline ready\n", __func__); 188 + #endif 189 + 190 + return 0; 191 + } 192 + 193 + static inline void _dsp_pipeline_destroy(struct dsp_pipeline *pipeline) 194 + { 195 + struct dsp_pipeline_entry *entry, *n; 196 + 197 + list_for_each_entry_safe(entry, n, &pipeline->list, list) { 198 + list_del(&entry->list); 199 + if (entry->elem == dsp_hwec) 200 + dsp_hwec_disable(container_of(pipeline, struct dsp, 201 + pipeline)); 202 + else 203 + entry->elem->free(entry->p); 204 + kfree(entry); 205 + } 206 + } 207 + 208 + void dsp_pipeline_destroy(struct dsp_pipeline *pipeline) 209 + { 210 + 211 + if (!pipeline) 212 + return; 213 + 214 + _dsp_pipeline_destroy(pipeline); 215 + 216 + #ifdef PIPELINE_DEBUG 217 + printk(KERN_DEBUG "%s: dsp pipeline destroyed\n", __func__); 218 + #endif 219 + } 220 + 221 + int dsp_pipeline_build(struct dsp_pipeline *pipeline, const char *cfg) 222 + { 223 + int len, incomplete = 0, found = 0; 224 + char *dup, *tok, *name, *args; 225 + struct dsp_element_entry *entry, *n; 226 + struct dsp_pipeline_entry *pipeline_entry; 227 + struct mISDN_dsp_element *elem; 228 + 229 + if (!pipeline) 230 + return -EINVAL; 231 + 232 + if (!list_empty(&pipeline->list)) 233 + _dsp_pipeline_destroy(pipeline); 234 + 235 + if (!cfg) 236 + return 0; 237 + 238 + len = strlen(cfg); 239 + if (!len) 240 + return 0; 241 + 242 + dup = kmalloc(len + 1, GFP_KERNEL); 243 + if (!dup) 244 + return 0; 245 + strcpy(dup, cfg); 246 + while ((tok = strsep(&dup, "|"))) { 247 + if (!strlen(tok)) 248 + continue; 249 + name = strsep(&tok, "("); 250 + args = strsep(&tok, ")"); 251 + if (args && !*args) 252 + args = 0; 253 + 254 + list_for_each_entry_safe(entry, n, &dsp_elements, list) 255 + if (!strcmp(entry->elem->name, name)) { 256 + elem = entry->elem; 257 + 258 + pipeline_entry = kmalloc(sizeof(struct 259 + dsp_pipeline_entry), GFP_KERNEL); 260 + if (!pipeline_entry) { 261 + printk(KERN_DEBUG "%s: failed to add " 262 + "entry to pipeline: %s (out of " 263 + "memory)\n", __func__, elem->name); 264 + incomplete = 1; 265 + goto _out; 266 + } 267 + pipeline_entry->elem = elem; 268 + 269 + if (elem == dsp_hwec) { 270 + /* This is a hack to make the hwec 271 + available as a pipeline module */ 272 + dsp_hwec_enable(container_of(pipeline, 273 + struct dsp, pipeline), args); 274 + list_add_tail(&pipeline_entry->list, 275 + &pipeline->list); 276 + } else { 277 + pipeline_entry->p = elem->new(args); 278 + if (pipeline_entry->p) { 279 + list_add_tail(&pipeline_entry-> 280 + list, &pipeline->list); 281 + #ifdef PIPELINE_DEBUG 282 + printk(KERN_DEBUG "%s: created " 283 + "instance of %s%s%s\n", 284 + __func__, name, args ? 285 + " with args " : "", args ? 286 + args : ""); 287 + #endif 288 + } else { 289 + printk(KERN_DEBUG "%s: failed " 290 + "to add entry to pipeline: " 291 + "%s (new() returned NULL)\n", 292 + __func__, elem->name); 293 + kfree(pipeline_entry); 294 + incomplete = 1; 295 + } 296 + } 297 + found = 1; 298 + break; 299 + } 300 + 301 + if (found) 302 + found = 0; 303 + else { 304 + printk(KERN_DEBUG "%s: element not found, skipping: " 305 + "%s\n", __func__, name); 306 + incomplete = 1; 307 + } 308 + } 309 + 310 + _out: 311 + if (!list_empty(&pipeline->list)) 312 + pipeline->inuse = 1; 313 + else 314 + pipeline->inuse = 0; 315 + 316 + #ifdef PIPELINE_DEBUG 317 + printk(KERN_DEBUG "%s: dsp pipeline built%s: %s\n", 318 + __func__, incomplete ? " incomplete" : "", cfg); 319 + #endif 320 + kfree(dup); 321 + return 0; 322 + } 323 + 324 + void dsp_pipeline_process_tx(struct dsp_pipeline *pipeline, u8 *data, int len) 325 + { 326 + struct dsp_pipeline_entry *entry; 327 + 328 + if (!pipeline) 329 + return; 330 + 331 + list_for_each_entry(entry, &pipeline->list, list) 332 + if (entry->elem->process_tx) 333 + entry->elem->process_tx(entry->p, data, len); 334 + } 335 + 336 + void dsp_pipeline_process_rx(struct dsp_pipeline *pipeline, u8 *data, int len) 337 + { 338 + struct dsp_pipeline_entry *entry; 339 + 340 + if (!pipeline) 341 + return; 342 + 343 + list_for_each_entry_reverse(entry, &pipeline->list, list) 344 + if (entry->elem->process_rx) 345 + entry->elem->process_rx(entry->p, data, len); 346 + } 347 + 348 +
+551
drivers/isdn/mISDN/dsp_tones.c
··· 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 + 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, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 242 + {SIZE_GA, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 243 + {1900, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, 244 + 245 + {TONE_GERMAN_OLDDIALTONE, 246 + {DATA_GO, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 247 + {SIZE_GO, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 248 + {1998, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, 249 + 250 + {TONE_AMERICAN_DIALTONE, 251 + {DATA_DT, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 252 + {SIZE_DT, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 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, 0, 0, 0, 0}, 257 + {SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, 0, 0, 0, 0}, 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, 0, 0, 0, 0}, 262 + {SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, 0, 0, 0, 0}, 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, 0, 0, 0, 0}, 267 + {SIZE_DT, SIZE_S, SIZE_DT, SIZE_S, SIZE_DT, SIZE_S, 0, 0, 0, 0}, 268 + {2000, 2000, 2000, 2000, 2000, 12000, 0, 0, 0, 0} }, 269 + 270 + {TONE_GERMAN_RINGING, 271 + {DATA_GA, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0}, 272 + {SIZE_GA, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0}, 273 + {8000, 32000, 0, 0, 0, 0, 0, 0, 0, 0} }, 274 + 275 + {TONE_GERMAN_OLDRINGING, 276 + {DATA_GO, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0}, 277 + {SIZE_GO, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0}, 278 + {8000, 40000, 0, 0, 0, 0, 0, 0, 0, 0} }, 279 + 280 + {TONE_AMERICAN_RINGING, 281 + {DATA_RI, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0}, 282 + {SIZE_RI, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0}, 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, 0, 0, 0, 0, 0, 0}, 287 + {SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, 0, 0, 0, 0, 0, 0}, 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, 0, 0, 0, 0, 0, 0}, 292 + {SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, 0, 0, 0, 0, 0, 0}, 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, 0, 0, 0, 0, 0, 0}, 297 + {SIZE_RI, SIZE_S, SIZE_RI, SIZE_S, 0, 0, 0, 0, 0, 0}, 298 + {4000, 4000, 4000, 28000, 0, 0, 0, 0, 0, 0} }, 299 + 300 + {TONE_GERMAN_BUSY, 301 + {DATA_GA, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0}, 302 + {SIZE_GA, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0}, 303 + {4000, 4000, 0, 0, 0, 0, 0, 0, 0, 0} }, 304 + 305 + {TONE_GERMAN_OLDBUSY, 306 + {DATA_GO, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0}, 307 + {SIZE_GO, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0}, 308 + {1000, 5000, 0, 0, 0, 0, 0, 0, 0, 0} }, 309 + 310 + {TONE_AMERICAN_BUSY, 311 + {DATA_BU, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0}, 312 + {SIZE_BU, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0}, 313 + {4000, 4000, 0, 0, 0, 0, 0, 0, 0, 0} }, 314 + 315 + {TONE_GERMAN_HANGUP, 316 + {DATA_GA, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0}, 317 + {SIZE_GA, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0}, 318 + {4000, 4000, 0, 0, 0, 0, 0, 0, 0, 0} }, 319 + 320 + {TONE_GERMAN_OLDHANGUP, 321 + {DATA_GO, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0}, 322 + {SIZE_GO, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0}, 323 + {1000, 5000, 0, 0, 0, 0, 0, 0, 0, 0} }, 324 + 325 + {TONE_AMERICAN_HANGUP, 326 + {DATA_DT, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 327 + {SIZE_DT, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 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, 0, 0, 0, 0, 0, 0}, 332 + {SIZE_S1, SIZE_S2, SIZE_S3, SIZE_S, 0, 0, 0, 0, 0, 0}, 333 + {2666, 2666, 2666, 8002, 0, 0, 0, 0, 0, 0} }, 334 + 335 + {TONE_GERMAN_GASSENBESETZT, 336 + {DATA_GA, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0}, 337 + {SIZE_GA, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0}, 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, 0, 0, 0, 0, 0, 0}, 342 + {SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, 0, 0, 0, 0, 0, 0}, 343 + {1000, 5000, 1000, 17000, 0, 0, 0, 0, 0, 0} }, 344 + 345 + {0, 346 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 347 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 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, 0, 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 +
+37
include/linux/mISDNdsp.h
··· 1 + #ifndef __mISDNdsp_H__ 2 + #define __mISDNdsp_H__ 3 + 4 + struct mISDN_dsp_element_arg { 5 + char *name; 6 + char *def; 7 + char *desc; 8 + }; 9 + 10 + struct mISDN_dsp_element { 11 + char *name; 12 + void *(*new)(const char *arg); 13 + void (*free)(void *p); 14 + void (*process_tx)(void *p, unsigned char *data, int len); 15 + void (*process_rx)(void *p, unsigned char *data, int len); 16 + int num_args; 17 + struct mISDN_dsp_element_arg 18 + *args; 19 + }; 20 + 21 + extern int mISDN_dsp_element_register(struct mISDN_dsp_element *elem); 22 + extern void mISDN_dsp_element_unregister(struct mISDN_dsp_element *elem); 23 + 24 + struct dsp_features { 25 + int hfc_id; /* unique id to identify the chip (or -1) */ 26 + int hfc_dtmf; /* set if HFCmulti card supports dtmf */ 27 + int hfc_loops; /* set if card supports tone loops */ 28 + int hfc_echocanhw; /* set if card supports echocancelation*/ 29 + int pcm_id; /* unique id to identify the pcm bus (or -1) */ 30 + int pcm_slots; /* number of slots on the pcm bus */ 31 + int pcm_banks; /* number of IO banks of pcm bus */ 32 + int unclocked; /* data is not clocked (has jitter/loss) */ 33 + int unordered; /* data is unordered (packets have index) */ 34 + }; 35 + 36 + #endif 37 +