2008-07-27 01:56:38 +02:00
/*
* Audio support data for ISDN4Linux .
*
* Copyright Andreas Eversberg ( jolly @ eversberg . eu )
*
* This software may be used and distributed according to the terms
* of the GNU General Public License , incorporated herein by reference .
*
*/
# include <linux/mISDNif.h>
# include <linux/mISDNdsp.h>
# include "core.h"
# include "dsp.h"
# define DATA_S sample_silence
# define SIZE_S (&sizeof_silence)
# define DATA_GA sample_german_all
# define SIZE_GA (&sizeof_german_all)
# define DATA_GO sample_german_old
# define SIZE_GO (&sizeof_german_old)
# define DATA_DT sample_american_dialtone
# define SIZE_DT (&sizeof_american_dialtone)
# define DATA_RI sample_american_ringing
# define SIZE_RI (&sizeof_american_ringing)
# define DATA_BU sample_american_busy
# define SIZE_BU (&sizeof_american_busy)
# define DATA_S1 sample_special1
# define SIZE_S1 (&sizeof_special1)
# define DATA_S2 sample_special2
# define SIZE_S2 (&sizeof_special2)
# define DATA_S3 sample_special3
# define SIZE_S3 (&sizeof_special3)
/***************/
/* tones loops */
/***************/
/* all tones are alaw encoded */
/* the last sample+1 is in phase with the first sample. the error is low */
static u8 sample_german_all [ ] = {
0x80 , 0xab , 0x81 , 0x6d , 0xfd , 0xdd , 0x5d , 0x9d ,
0x4d , 0xd1 , 0x89 , 0x88 , 0xd0 , 0x4c , 0x9c , 0x5c ,
0xdc , 0xfc , 0x6c ,
0x80 , 0xab , 0x81 , 0x6d , 0xfd , 0xdd , 0x5d , 0x9d ,
0x4d , 0xd1 , 0x89 , 0x88 , 0xd0 , 0x4c , 0x9c , 0x5c ,
0xdc , 0xfc , 0x6c ,
0x80 , 0xab , 0x81 , 0x6d , 0xfd , 0xdd , 0x5d , 0x9d ,
0x4d , 0xd1 , 0x89 , 0x88 , 0xd0 , 0x4c , 0x9c , 0x5c ,
0xdc , 0xfc , 0x6c ,
0x80 , 0xab , 0x81 , 0x6d , 0xfd , 0xdd , 0x5d , 0x9d ,
0x4d , 0xd1 , 0x89 , 0x88 , 0xd0 , 0x4c , 0x9c , 0x5c ,
0xdc , 0xfc , 0x6c ,
} ;
static u32 sizeof_german_all = sizeof ( sample_german_all ) ;
static u8 sample_german_old [ ] = {
0xec , 0x68 , 0xe1 , 0x6d , 0x6d , 0x91 , 0x51 , 0xed ,
0x6d , 0x01 , 0x1e , 0x10 , 0x0c , 0x90 , 0x60 , 0x70 ,
0x8c ,
0xec , 0x68 , 0xe1 , 0x6d , 0x6d , 0x91 , 0x51 , 0xed ,
0x6d , 0x01 , 0x1e , 0x10 , 0x0c , 0x90 , 0x60 , 0x70 ,
0x8c ,
0xec , 0x68 , 0xe1 , 0x6d , 0x6d , 0x91 , 0x51 , 0xed ,
0x6d , 0x01 , 0x1e , 0x10 , 0x0c , 0x90 , 0x60 , 0x70 ,
0x8c ,
0xec , 0x68 , 0xe1 , 0x6d , 0x6d , 0x91 , 0x51 , 0xed ,
0x6d , 0x01 , 0x1e , 0x10 , 0x0c , 0x90 , 0x60 , 0x70 ,
0x8c ,
} ;
static u32 sizeof_german_old = sizeof ( sample_german_old ) ;
static u8 sample_american_dialtone [ ] = {
0x2a , 0x18 , 0x90 , 0x6c , 0x4c , 0xbc , 0x4c , 0x6c ,
0x10 , 0x58 , 0x32 , 0xb9 , 0x31 , 0x2d , 0x8d , 0x0d ,
0x8d , 0x2d , 0x31 , 0x99 , 0x0f , 0x28 , 0x60 , 0xf0 ,
0xd0 , 0x50 , 0xd0 , 0x30 , 0x60 , 0x08 , 0x8e , 0x67 ,
0x09 , 0x19 , 0x21 , 0xe1 , 0xd9 , 0xb9 , 0x29 , 0x67 ,
0x83 , 0x02 , 0xce , 0xbe , 0xee , 0x1a , 0x1b , 0xef ,
0xbf , 0xcf , 0x03 , 0x82 , 0x66 , 0x28 , 0xb8 , 0xd8 ,
0xe0 , 0x20 , 0x18 , 0x08 , 0x66 , 0x8f , 0x09 , 0x61 ,
0x31 , 0xd1 , 0x51 , 0xd1 , 0xf1 , 0x61 , 0x29 , 0x0e ,
0x98 , 0x30 , 0x2c , 0x8c , 0x0c , 0x8c , 0x2c , 0x30 ,
0xb8 , 0x33 , 0x59 , 0x11 , 0x6d , 0x4d , 0xbd , 0x4d ,
0x6d , 0x91 , 0x19 ,
} ;
static u32 sizeof_american_dialtone = sizeof ( sample_american_dialtone ) ;
static u8 sample_american_ringing [ ] = {
0x2a , 0xe0 , 0xac , 0x0c , 0xbc , 0x4c , 0x8c , 0x90 ,
0x48 , 0xc7 , 0xc1 , 0xed , 0xcd , 0x4d , 0xcd , 0xed ,
0xc1 , 0xb7 , 0x08 , 0x30 , 0xec , 0xcc , 0xcc , 0x8c ,
0x10 , 0x58 , 0x1a , 0x99 , 0x71 , 0xed , 0x8d , 0x8d ,
0x2d , 0x41 , 0x89 , 0x9e , 0x20 , 0x70 , 0x2c , 0xec ,
0x2c , 0x70 , 0x20 , 0x86 , 0x77 , 0xe1 , 0x31 , 0x11 ,
0xd1 , 0xf1 , 0x81 , 0x09 , 0xa3 , 0x56 , 0x58 , 0x00 ,
0x40 , 0xc0 , 0x60 , 0x38 , 0x46 , 0x43 , 0x57 , 0x39 ,
0xd9 , 0x59 , 0x99 , 0xc9 , 0x77 , 0x2f , 0x2e , 0xc6 ,
0xd6 , 0x28 , 0xd6 , 0x36 , 0x26 , 0x2e , 0x8a , 0xa3 ,
0x43 , 0x63 , 0x4b , 0x4a , 0x62 , 0x42 , 0xa2 , 0x8b ,
0x2f , 0x27 , 0x37 , 0xd7 , 0x29 , 0xd7 , 0xc7 , 0x2f ,
0x2e , 0x76 , 0xc8 , 0x98 , 0x58 , 0xd8 , 0x38 , 0x56 ,
0x42 , 0x47 , 0x39 , 0x61 , 0xc1 , 0x41 , 0x01 , 0x59 ,
0x57 , 0xa2 , 0x08 , 0x80 , 0xf0 , 0xd0 , 0x10 , 0x30 ,
0xe0 , 0x76 , 0x87 , 0x21 , 0x71 , 0x2d , 0xed , 0x2d ,
0x71 , 0x21 , 0x9f , 0x88 , 0x40 , 0x2c , 0x8c , 0x8c ,
0xec , 0x70 , 0x98 , 0x1b , 0x59 , 0x11 , 0x8d , 0xcd ,
0xcd , 0xed , 0x31 , 0x09 , 0xb6 , 0xc0 , 0xec , 0xcc ,
0x4c , 0xcc , 0xec , 0xc0 , 0xc6 , 0x49 , 0x91 , 0x8d ,
0x4d , 0xbd , 0x0d , 0xad , 0xe1 ,
} ;
static u32 sizeof_american_ringing = sizeof ( sample_american_ringing ) ;
static u8 sample_american_busy [ ] = {
0x2a , 0x00 , 0x6c , 0x4c , 0x4c , 0x6c , 0xb0 , 0x66 ,
0x99 , 0x11 , 0x6d , 0x8d , 0x2d , 0x41 , 0xd7 , 0x96 ,
0x60 , 0xf0 , 0x70 , 0x40 , 0x58 , 0xf6 , 0x53 , 0x57 ,
0x09 , 0x89 , 0xd7 , 0x5f , 0xe3 , 0x2a , 0xe3 , 0x5f ,
0xd7 , 0x89 , 0x09 , 0x57 , 0x53 , 0xf6 , 0x58 , 0x40 ,
0x70 , 0xf0 , 0x60 , 0x96 , 0xd7 , 0x41 , 0x2d , 0x8d ,
0x6d , 0x11 , 0x99 , 0x66 , 0xb0 , 0x6c , 0x4c , 0x4c ,
0x6c , 0x00 , 0x2a , 0x01 , 0x6d , 0x4d , 0x4d , 0x6d ,
0xb1 , 0x67 , 0x98 , 0x10 , 0x6c , 0x8c , 0x2c , 0x40 ,
0xd6 , 0x97 , 0x61 , 0xf1 , 0x71 , 0x41 , 0x59 , 0xf7 ,
0x52 , 0x56 , 0x08 , 0x88 , 0xd6 , 0x5e , 0xe2 , 0x2a ,
0xe2 , 0x5e , 0xd6 , 0x88 , 0x08 , 0x56 , 0x52 , 0xf7 ,
0x59 , 0x41 , 0x71 , 0xf1 , 0x61 , 0x97 , 0xd6 , 0x40 ,
0x2c , 0x8c , 0x6c , 0x10 , 0x98 , 0x67 , 0xb1 , 0x6d ,
0x4d , 0x4d , 0x6d , 0x01 ,
} ;
static u32 sizeof_american_busy = sizeof ( sample_american_busy ) ;
static u8 sample_special1 [ ] = {
0x2a , 0x2c , 0xbc , 0x6c , 0xd6 , 0x71 , 0xbd , 0x0d ,
0xd9 , 0x80 , 0xcc , 0x4c , 0x40 , 0x39 , 0x0d , 0xbd ,
0x11 , 0x86 , 0xec , 0xbc , 0xec , 0x0e , 0x51 , 0xbd ,
0x8d , 0x89 , 0x30 , 0x4c , 0xcc , 0xe0 , 0xe1 , 0xcd ,
0x4d , 0x31 , 0x88 , 0x8c , 0xbc , 0x50 , 0x0f , 0xed ,
0xbd , 0xed , 0x87 , 0x10 , 0xbc , 0x0c , 0x38 , 0x41 ,
0x4d , 0xcd , 0x81 , 0xd8 , 0x0c , 0xbc , 0x70 , 0xd7 ,
0x6d , 0xbd , 0x2d ,
} ;
static u32 sizeof_special1 = sizeof ( sample_special1 ) ;
static u8 sample_special2 [ ] = {
0x2a , 0xcc , 0x8c , 0xd7 , 0x4d , 0x2d , 0x18 , 0xbc ,
0x10 , 0xc1 , 0xbd , 0xc1 , 0x10 , 0xbc , 0x18 , 0x2d ,
0x4d , 0xd7 , 0x8c , 0xcc , 0x2a , 0xcd , 0x8d , 0xd6 ,
0x4c , 0x2c , 0x19 , 0xbd , 0x11 , 0xc0 , 0xbc , 0xc0 ,
0x11 , 0xbd , 0x19 , 0x2c , 0x4c , 0xd6 , 0x8d , 0xcd ,
0x2a , 0xcc , 0x8c , 0xd7 , 0x4d , 0x2d , 0x18 , 0xbc ,
0x10 , 0xc1 , 0xbd , 0xc1 , 0x10 , 0xbc , 0x18 , 0x2d ,
0x4d , 0xd7 , 0x8c , 0xcc , 0x2a , 0xcd , 0x8d , 0xd6 ,
0x4c , 0x2c , 0x19 , 0xbd , 0x11 , 0xc0 , 0xbc , 0xc0 ,
0x11 , 0xbd , 0x19 , 0x2c , 0x4c , 0xd6 , 0x8d , 0xcd ,
} ;
static u32 sizeof_special2 = sizeof ( sample_special2 ) ;
static u8 sample_special3 [ ] = {
0x2a , 0xbc , 0x18 , 0xcd , 0x11 , 0x2c , 0x8c , 0xc1 ,
0x4d , 0xd6 , 0xbc , 0xd6 , 0x4d , 0xc1 , 0x8c , 0x2c ,
0x11 , 0xcd , 0x18 , 0xbc , 0x2a , 0xbd , 0x19 , 0xcc ,
0x10 , 0x2d , 0x8d , 0xc0 , 0x4c , 0xd7 , 0xbd , 0xd7 ,
0x4c , 0xc0 , 0x8d , 0x2d , 0x10 , 0xcc , 0x19 , 0xbd ,
0x2a , 0xbc , 0x18 , 0xcd , 0x11 , 0x2c , 0x8c , 0xc1 ,
0x4d , 0xd6 , 0xbc , 0xd6 , 0x4d , 0xc1 , 0x8c , 0x2c ,
0x11 , 0xcd , 0x18 , 0xbc , 0x2a , 0xbd , 0x19 , 0xcc ,
0x10 , 0x2d , 0x8d , 0xc0 , 0x4c , 0xd7 , 0xbd , 0xd7 ,
0x4c , 0xc0 , 0x8d , 0x2d , 0x10 , 0xcc , 0x19 , 0xbd ,
} ;
static u32 sizeof_special3 = sizeof ( sample_special3 ) ;
static u8 sample_silence [ ] = {
0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a ,
0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a ,
0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a ,
0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a ,
0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a ,
0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a ,
0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a ,
0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a ,
0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a ,
0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a ,
0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a ,
0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a , 0x2a ,
} ;
static u32 sizeof_silence = sizeof ( sample_silence ) ;
struct tones_samples {
u32 * len ;
u8 * data ;
} ;
static struct
tones_samples samples [ ] = {
{ & sizeof_german_all , sample_german_all } ,
{ & sizeof_german_old , sample_german_old } ,
{ & sizeof_american_dialtone , sample_american_dialtone } ,
{ & sizeof_american_ringing , sample_american_ringing } ,
{ & sizeof_american_busy , sample_american_busy } ,
{ & sizeof_special1 , sample_special1 } ,
{ & sizeof_special2 , sample_special2 } ,
{ & sizeof_special3 , sample_special3 } ,
{ NULL , NULL } ,
} ;
/***********************************
* generate ulaw from alaw samples *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void
dsp_audio_generate_ulaw_samples ( void )
{
int i , j ;
i = 0 ;
while ( samples [ i ] . len ) {
j = 0 ;
while ( j < ( * samples [ i ] . len ) ) {
samples [ i ] . data [ j ] =
dsp_audio_alaw_to_ulaw [ samples [ i ] . data [ j ] ] ;
j + + ;
}
i + + ;
}
}
/****************************
* tone sequence definition *
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-12-12 21:15:17 -08:00
static struct pattern {
2008-07-27 01:56:38 +02:00
int tone ;
u8 * data [ 10 ] ;
u32 * siz [ 10 ] ;
u32 seq [ 10 ] ;
} pattern [ ] = {
{ TONE_GERMAN_DIALTONE ,
2008-12-12 21:11:28 -08:00
{ DATA_GA , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
{ SIZE_GA , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
2008-07-27 01:56:38 +02:00
{ 1900 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } } ,
{ TONE_GERMAN_OLDDIALTONE ,
2008-12-12 21:11:28 -08:00
{ DATA_GO , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
{ SIZE_GO , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
2008-07-27 01:56:38 +02:00
{ 1998 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } } ,
{ TONE_AMERICAN_DIALTONE ,
2008-12-12 21:11:28 -08:00
{ DATA_DT , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
{ SIZE_DT , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
2008-07-27 01:56:38 +02:00
{ 8000 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } } ,
{ TONE_GERMAN_DIALPBX ,
2009-05-22 11:04:56 +00:00
{ DATA_GA , DATA_S , DATA_GA , DATA_S , DATA_GA , DATA_S , NULL , NULL , NULL ,
NULL } ,
{ SIZE_GA , SIZE_S , SIZE_GA , SIZE_S , SIZE_GA , SIZE_S , NULL , NULL , NULL ,
NULL } ,
2008-07-27 01:56:38 +02:00
{ 2000 , 2000 , 2000 , 2000 , 2000 , 12000 , 0 , 0 , 0 , 0 } } ,
{ TONE_GERMAN_OLDDIALPBX ,
2009-05-22 11:04:56 +00:00
{ DATA_GO , DATA_S , DATA_GO , DATA_S , DATA_GO , DATA_S , NULL , NULL , NULL ,
NULL } ,
{ SIZE_GO , SIZE_S , SIZE_GO , SIZE_S , SIZE_GO , SIZE_S , NULL , NULL , NULL ,
NULL } ,
2008-07-27 01:56:38 +02:00
{ 2000 , 2000 , 2000 , 2000 , 2000 , 12000 , 0 , 0 , 0 , 0 } } ,
{ TONE_AMERICAN_DIALPBX ,
2009-05-22 11:04:56 +00:00
{ DATA_DT , DATA_S , DATA_DT , DATA_S , DATA_DT , DATA_S , NULL , NULL , NULL ,
NULL } ,
{ SIZE_DT , SIZE_S , SIZE_DT , SIZE_S , SIZE_DT , SIZE_S , NULL , NULL , NULL ,
NULL } ,
2008-07-27 01:56:38 +02:00
{ 2000 , 2000 , 2000 , 2000 , 2000 , 12000 , 0 , 0 , 0 , 0 } } ,
{ TONE_GERMAN_RINGING ,
2008-12-12 21:11:28 -08:00
{ DATA_GA , DATA_S , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
{ SIZE_GA , SIZE_S , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
2008-07-27 01:56:38 +02:00
{ 8000 , 32000 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } } ,
{ TONE_GERMAN_OLDRINGING ,
2008-12-12 21:11:28 -08:00
{ DATA_GO , DATA_S , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
{ SIZE_GO , SIZE_S , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
2008-07-27 01:56:38 +02:00
{ 8000 , 40000 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } } ,
{ TONE_AMERICAN_RINGING ,
2008-12-12 21:11:28 -08:00
{ DATA_RI , DATA_S , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
{ SIZE_RI , SIZE_S , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
2008-07-27 01:56:38 +02:00
{ 8000 , 32000 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } } ,
{ TONE_GERMAN_RINGPBX ,
2008-12-12 21:11:28 -08:00
{ DATA_GA , DATA_S , DATA_GA , DATA_S , NULL , NULL , NULL , NULL , NULL , NULL } ,
{ SIZE_GA , SIZE_S , SIZE_GA , SIZE_S , NULL , NULL , NULL , NULL , NULL , NULL } ,
2008-07-27 01:56:38 +02:00
{ 4000 , 4000 , 4000 , 28000 , 0 , 0 , 0 , 0 , 0 , 0 } } ,
{ TONE_GERMAN_OLDRINGPBX ,
2008-12-12 21:11:28 -08:00
{ DATA_GO , DATA_S , DATA_GO , DATA_S , NULL , NULL , NULL , NULL , NULL , NULL } ,
{ SIZE_GO , SIZE_S , SIZE_GO , SIZE_S , NULL , NULL , NULL , NULL , NULL , NULL } ,
2008-07-27 01:56:38 +02:00
{ 4000 , 4000 , 4000 , 28000 , 0 , 0 , 0 , 0 , 0 , 0 } } ,
{ TONE_AMERICAN_RINGPBX ,
2008-12-12 21:11:28 -08:00
{ DATA_RI , DATA_S , DATA_RI , DATA_S , NULL , NULL , NULL , NULL , NULL , NULL } ,
{ SIZE_RI , SIZE_S , SIZE_RI , SIZE_S , NULL , NULL , NULL , NULL , NULL , NULL } ,
2008-07-27 01:56:38 +02:00
{ 4000 , 4000 , 4000 , 28000 , 0 , 0 , 0 , 0 , 0 , 0 } } ,
{ TONE_GERMAN_BUSY ,
2008-12-12 21:11:28 -08:00
{ DATA_GA , DATA_S , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
{ SIZE_GA , SIZE_S , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
2008-07-27 01:56:38 +02:00
{ 4000 , 4000 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } } ,
{ TONE_GERMAN_OLDBUSY ,
2008-12-12 21:11:28 -08:00
{ DATA_GO , DATA_S , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
{ SIZE_GO , SIZE_S , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
2008-07-27 01:56:38 +02:00
{ 1000 , 5000 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } } ,
{ TONE_AMERICAN_BUSY ,
2008-12-12 21:11:28 -08:00
{ DATA_BU , DATA_S , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
{ SIZE_BU , SIZE_S , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
2008-07-27 01:56:38 +02:00
{ 4000 , 4000 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } } ,
{ TONE_GERMAN_HANGUP ,
2008-12-12 21:11:28 -08:00
{ DATA_GA , DATA_S , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
{ SIZE_GA , SIZE_S , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
2008-07-27 01:56:38 +02:00
{ 4000 , 4000 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } } ,
{ TONE_GERMAN_OLDHANGUP ,
2008-12-12 21:11:28 -08:00
{ DATA_GO , DATA_S , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
{ SIZE_GO , SIZE_S , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
2008-07-27 01:56:38 +02:00
{ 1000 , 5000 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } } ,
{ TONE_AMERICAN_HANGUP ,
2008-12-12 21:11:28 -08:00
{ DATA_DT , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
{ SIZE_DT , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
2008-07-27 01:56:38 +02:00
{ 8000 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } } ,
{ TONE_SPECIAL_INFO ,
2008-12-12 21:11:28 -08:00
{ DATA_S1 , DATA_S2 , DATA_S3 , DATA_S , NULL , NULL , NULL , NULL , NULL , NULL } ,
{ SIZE_S1 , SIZE_S2 , SIZE_S3 , SIZE_S , NULL , NULL , NULL , NULL , NULL , NULL } ,
2008-07-27 01:56:38 +02:00
{ 2666 , 2666 , 2666 , 8002 , 0 , 0 , 0 , 0 , 0 , 0 } } ,
{ TONE_GERMAN_GASSENBESETZT ,
2008-12-12 21:11:28 -08:00
{ DATA_GA , DATA_S , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
{ SIZE_GA , SIZE_S , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
2008-07-27 01:56:38 +02:00
{ 2000 , 2000 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } } ,
{ TONE_GERMAN_AUFSCHALTTON ,
2008-12-12 21:11:28 -08:00
{ DATA_GO , DATA_S , DATA_GO , DATA_S , NULL , NULL , NULL , NULL , NULL , NULL } ,
{ SIZE_GO , SIZE_S , SIZE_GO , SIZE_S , NULL , NULL , NULL , NULL , NULL , NULL } ,
2008-07-27 01:56:38 +02:00
{ 1000 , 5000 , 1000 , 17000 , 0 , 0 , 0 , 0 , 0 , 0 } } ,
{ 0 ,
2008-12-12 21:11:28 -08:00
{ NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
{ NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL } ,
2008-07-27 01:56:38 +02:00
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } } ,
} ;
/******************
* copy tone data *
* * * * * * * * * * * * * * * * * */
/* an sk_buff is generated from the number of samples needed.
* the count will be changed and may begin from 0 each pattern period .
* the clue is to precalculate the pointers and legths to use only one
* memcpy per function call , or two memcpy if the tone sequence changes .
*
* pattern - the type of the pattern
* count - the sample from the beginning of the pattern ( phase )
* len - the number of bytes
*
* return - the sk_buff with the sample
*
* if tones has finished ( e . g . knocking tone ) , dsp - > tones is turned off
*/
void dsp_tone_copy ( struct dsp * dsp , u8 * data , int len )
{
int index , count , start , num ;
struct pattern * pat ;
struct dsp_tone * tone = & dsp - > tone ;
/* if we have no tone, we copy silence */
if ( ! tone - > tone ) {
memset ( data , dsp_silence , len ) ;
return ;
}
/* process pattern */
pat = ( struct pattern * ) tone - > pattern ;
/* points to the current pattern */
index = tone - > index ; /* gives current sequence index */
count = tone - > count ; /* gives current sample */
/* copy sample */
while ( len ) {
/* find sample to start with */
while ( 42 ) {
/* warp arround */
if ( ! pat - > seq [ index ] ) {
count = 0 ;
index = 0 ;
}
/* check if we are currently playing this tone */
if ( count < pat - > seq [ index ] )
break ;
if ( dsp_debug & DEBUG_DSP_TONE )
printk ( KERN_DEBUG " %s: reaching next sequence "
" (index=%d) \n " , __func__ , index ) ;
count - = pat - > seq [ index ] ;
index + + ;
}
/* calculate start and number of samples */
start = count % ( * ( pat - > siz [ index ] ) ) ;
num = len ;
if ( num + count > pat - > seq [ index ] )
num = pat - > seq [ index ] - count ;
if ( num + start > ( * ( pat - > siz [ index ] ) ) )
num = ( * ( pat - > siz [ index ] ) ) - start ;
/* copy memory */
memcpy ( data , pat - > data [ index ] + start , num ) ;
/* reduce length */
data + = num ;
count + = num ;
len - = num ;
}
tone - > index = index ;
tone - > count = count ;
/* return sk_buff */
return ;
}
/*******************************
* send HW message to hfc card *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void
dsp_tone_hw_message ( struct dsp * dsp , u8 * sample , int len )
{
struct sk_buff * nskb ;
/* unlocking is not required, because we don't expect a response */
nskb = _alloc_mISDN_skb ( PH_CONTROL_REQ ,
2009-05-22 11:04:56 +00:00
( len ) ? HFC_SPL_LOOP_ON : HFC_SPL_LOOP_OFF , len , sample ,
2008-07-27 01:56:38 +02:00
GFP_ATOMIC ) ;
if ( nskb ) {
if ( dsp - > ch . peer ) {
if ( dsp - > ch . recv ( dsp - > ch . peer , nskb ) )
dev_kfree_skb ( nskb ) ;
} else
dev_kfree_skb ( nskb ) ;
}
}
/*****************
* timer expires *
* * * * * * * * * * * * * * * * */
void
dsp_tone_timeout ( void * arg )
{
struct dsp * dsp = arg ;
struct dsp_tone * tone = & dsp - > tone ;
struct pattern * pat = ( struct pattern * ) tone - > pattern ;
int index = tone - > index ;
if ( ! tone - > tone )
return ;
index + + ;
if ( ! pat - > seq [ index ] )
index = 0 ;
tone - > index = index ;
/* set next tone */
if ( pat - > data [ index ] = = DATA_S )
2008-12-12 21:11:28 -08:00
dsp_tone_hw_message ( dsp , NULL , 0 ) ;
2008-07-27 01:56:38 +02:00
else
dsp_tone_hw_message ( dsp , pat - > data [ index ] , * ( pat - > siz [ index ] ) ) ;
/* set timer */
init_timer ( & tone - > tl ) ;
tone - > tl . expires = jiffies + ( pat - > seq [ index ] * HZ ) / 8000 ;
add_timer ( & tone - > tl ) ;
}
/********************
* set / release tone *
* * * * * * * * * * * * * * * * * * * */
/*
* tones are relaized by streaming or by special loop commands if supported
* by hardware . when hardware is used , the patterns will be controlled by
* timers .
*/
int
dsp_tone ( struct dsp * dsp , int tone )
{
struct pattern * pat ;
int i ;
struct dsp_tone * tonet = & dsp - > tone ;
tonet - > software = 0 ;
tonet - > hardware = 0 ;
/* we turn off the tone */
if ( ! tone ) {
2009-05-22 11:04:56 +00:00
if ( dsp - > features . hfc_loops & & timer_pending ( & tonet - > tl ) )
2008-07-27 01:56:38 +02:00
del_timer ( & tonet - > tl ) ;
if ( dsp - > features . hfc_loops )
dsp_tone_hw_message ( dsp , NULL , 0 ) ;
tonet - > tone = 0 ;
return 0 ;
}
pat = NULL ;
i = 0 ;
while ( pattern [ i ] . tone ) {
if ( pattern [ i ] . tone = = tone ) {
pat = & pattern [ i ] ;
break ;
}
i + + ;
}
if ( ! pat ) {
printk ( KERN_WARNING " dsp: given tone 0x%x is invalid \n " , tone ) ;
return - EINVAL ;
}
if ( dsp_debug & DEBUG_DSP_TONE )
printk ( KERN_DEBUG " %s: now starting tone %d (index=%d) \n " ,
__func__ , tone , 0 ) ;
tonet - > tone = tone ;
tonet - > pattern = pat ;
tonet - > index = 0 ;
tonet - > count = 0 ;
if ( dsp - > features . hfc_loops ) {
tonet - > hardware = 1 ;
/* set first tone */
dsp_tone_hw_message ( dsp , pat - > data [ 0 ] , * ( pat - > siz [ 0 ] ) ) ;
/* set timer */
if ( timer_pending ( & tonet - > tl ) )
del_timer ( & tonet - > tl ) ;
init_timer ( & tonet - > tl ) ;
tonet - > tl . expires = jiffies + ( pat - > seq [ 0 ] * HZ ) / 8000 ;
add_timer ( & tonet - > tl ) ;
} else {
tonet - > software = 1 ;
}
return 0 ;
}