aboutsummaryrefslogblamecommitdiffstats
path: root/drivers/isdn/hardware/eicon/maintidi.c
blob: 2ee789f958672d9448347323f69e24a65d833da6 (plain) (tree)
1
2
3
4
5
6
7
8
9

  
                                    
  

                                              
  
                             
  



                                                                     
  



                                                                         
  


                                                                  









                     
                                                                              






                                                                     



















                                                                  

  





































                                                                          

  








                                                                                                                      











                                          

                                  
                                                                  

                                                                                    







                                                                                    
                                                    
                                                              
                                                    
                                                              
                                             
                                                              
                                           
                                                              
                                               
                                                              
                                               
                                                              
                                               
                                                              
                                               









                                                                                       

                                                                                  

                            
                                                                       

          


                                                                        
                                                                          


                                                                        





                                                                     
                                 



                                   
                                      
 
                                                         

 

                                                                    
 
                                                                





                                        


                                                                    
 


                                                           
 




                                               
 


                           
 
                   

 

                                                                    

                                     
                                                               





                           

                                                                    
 
                          


  





                                                                    
                    
                     
 






                                            
 



                                                

                                        

























                                                                                                               




                                                               




































































































































                                                                                                                                                 








                                                     


                                                                  







                             








                                                       
 


                                  
 
                                        
                                                                                                       


                                             

                                   
         
 
                                       
                                                                                                         


                                            

                                   
         
 
                                       
                                                                                                           


                                            

                                   
         


                                                         
                                                                             









                                                                                           
                                                                                  









                                                                                           
                                                                              









                                                                                           





                                                             








                                          





                                                                








                                           





                                                             








                                        





                                                               







                                            


                                                                 







                                                                       





                                                                          







                                                                                                       





                                                                        








                                                                                                           





                                                                        








                                                                             





                                                                             







                                                                              


                                                             







                                            


                                                             







                                    


                                                                 








                                                            

                                                                                        






                                                                

                                                                                        






                                                                 

                                                                                        






                                                               

                                                                                           








                                                               


                                                                       







                                             


                                                                       







                                             


                                                              







                                          


                                                            







                                        


                                                                 







                                       


                                                                 







                                       


                                                                 







                                       


                                                                 








                                                   
                                                                         








                                                                                           
                                                                             








                                                                                           
                                                                         








                                                                                           
                                                                             










                                                                                           


                                                           



                                                                  













                                                                                   

                                                                    













                                                                                 

                                                                      













                                                                                     

          

                                   
                                               

                                                     




                                                          

                                       
                                               


                                                             



                 

                            
                                               


                                                           



                 

                                           



                                                               
                                                                    




                                                                 
                                                                                  


                                           
                                                                                           



                                                                     
                                                                  


                                                           

                                   











































                                                            



                                           
                                                                                           




                                                                                     

                                                                                         


                                                                                     

                                                                                         




                    

                                                                      


                   

                                                                       


                   

                                                                     



                   






                                                          



                      

                                          
                                              
                                                            
                                                
                                                                



                 

                                  
                                              
                                                          
                                                
                                                              



                 

                                   
                                              
                                                     
                                                
                                                               


                 
                                               






                           









                                                                       


                                                    



                                                                                           


                                            
                                                                       




                                    



                                                                                  
                                                  
                                                                                       






                                                     



                                                       


                                                  



                                                                                           


                                            
                                                                       




                                    



                                                                                  
                                                
                                                                                     







                                                   







                                                                

                                




                                                                                           


                                            
                                                                        




                                    


                                                                                  
 


                                                                                 
                                                 
                                                                                      

                                                    

                                                                                              






                   




                                                                         




                                     

                                   


                                     
                                              


  




                                                                   

            
                                                      
 
                                                              

                              
                                              



                      



                                                                     

                                                                                  
                                                               






                                                                      

                                                              

                                                                                 

                                                              

                                                                              

                                                              

                                                                                

                                                              

                                                                                

                                                              
                                                               
                                         
 

                                                              
                                                               
                                            
 

                                                              
                                                               
                                        
 

                                                              
                                                               
                                           
 

                                                              

                                                                              

                                                              

                                                                               

                                                              

                                                                               

                                                              

                                                                              

                                                              

                                                                                    

                                                              
                                                               
                                           
 

                                                              




                                                                                



                                                                    

                                                                                 
                                                               





                                                                     

                                                              

                                                                           

                                                              

                                                                                  

                                                              

                                                                              

                                                              

                                                                                   

                                                              

                                                                                   

                                                              

                                                                                 

                                                              

                                                                           

                                                              

                                                                                

                                                              

                                                                                 

                                                              

                                                                                  

                                                              

                                                                                   

                                                              




                                                                                 



                                                                       

                                                                                   
                                                               





                                                                       

                                                              

                                                                             

                                                              

                                                                            

                                                              

                                                                               

                                                              

                                                                               

                                                              

                                                                               

                                                              

                                                                                     

                                                              

                                                                                  

                                                              

                                                                                  

                                                              

                                                                                    

                                                              

                                                                             

                                                              

                                                                           

                                                              

                                                                                     

                                                              

                                                                                      

                                                              

                                                                                    

                                                              

                                                                                     

                                                              




                                                                                  
                                                                  


                                              


                                                       




                                                            



                                                             
                                                               
                                                
 

                                                             
                                                               
                                                    
 

                                                             
                                                               
                                                    
 

                                                             
                                                               
                                                    
 

                                                             
                                                               
                                                       
 

                                                             
                                                               
                                                        
 

                                                             
                                                               
                                                         

          



                                                             
                                                               
                                               
 

                                                             
                                                               
                                                   
 

                                                             
                                                               
                                                   
 

                                                             
                                                               
                                                       
 

                                                             
                                                               
                                                      
 

                                                               
                                                               
                                                          
 

                                                             
                                                               
                                                      
 

                                                             
                                                               
                                                 

          

                          

                                                                

                                                             
                                                               
                                                     
 

                                                             
                                                               
                                                          
 

                                                             
                                                               
                                                        
 

                                                             
                                                               
                                                         
 

                                                             
                                                               
                                                        
 

                                                             
                                                               
                                                          
 

                                                             
                                                               
                                                       
 

                                                             
                                                               
                                                        
 

                                                             
                                                               
                                                     



                                                                    

                        

                                                                

                                                             
                                                               
                                                     
 

                                                             
                                                               
                                                        
 

                                                             
                                                               
                                                          
 

                                                             
                                                               
                                                      
 

                                                             
                                                               
                                                        
 

                                                             
                                                               
                                                         
 

                                                             
                                                               
                                                       
 

                                                             
                                                               
                                                         
 

                                                             
                                                               
                                                          
 

                                                             
                                                               
                                                       
 

                                                             
                                                               
                                                         
 

                                                             
                                                               
                                                       
 

                                                             
                                                               
                                                         
 

                                                             
                                                               
                                                          
 

                                                             
                                                               
                                                          
 

                                                             
                                                               
                                                          
 

                                                             
                                                               
                                                          
 

                                                             
                                                               
                                                          



                                                                    



                                                             
                                                               
                                                 
 

                                                             
                                                               
                                                
 

                                                             
                                                               
                                                 
 

                                                             
                                                               
                                                 
 

                                                             
                                                               
                                                
 

                                                             
                                                               
                                                 

          



                                                             
                                                               
                                                 
 

                                                             
                                                               
                                                
 

                                                             
                                                               
                                                 
 

                                                             
                                                               
                                                 
 

                                                             
                                                               
                                                
 

                                                             
                                                               
                                                 

          



                                                             
                                                               
                                                 
 

                                                             
                                                               
                                                
 

                                                             
                                                               
                                                 
 

                                                             
                                                               
                                                 
 

                                                             
                                                               
                                                
 

                                                             
                                                               
                                                 

          



                                                             
                                                               
                                                 
 

                                                             
                                                               
                                                
 

                                                             
                                                               
                                                 
 

                                                             
                                                               
                                                 
 

                                                             
                                                               
                                                
 

                                                             
                                                               
                                                 




                                                                

                                                                     

                                                              


                                                           



         




                                                               

                                                                                          



                                                                             



         



                                                                    
                             













                                                                                


          



                                                                             



                    



                                                                        




                                       


                                     
 


                                             
 


                                            
 

                            






                     

                                                                           




                                       


                                     
 


                                            
 



                                               
 


                                              
 

                            







                     



                                                                         




                                             
                                     
         
                                 





                        



                                                                         

                                       
                                   





                           





                                                                    



                                       
                                             



                   

                                                                    











                                                          








                                                       
 
                                                

 

                                                                    











                                                              
                                                

 

                                                                    






                                                                                           
                                                

 

                                                                    






                                                     
                                                

 

                                                                    







                                                          
                                                


  




                                                             


                                                                                      


                                                                                           


                                            





                                                                                                              



                 









                                                                                         




                                      

                                                                    
                                     
                                                

 

                                                                    
                                     
                                                

 

                                                                    
                                  
                                                

 

                                                                    
                                
                                                

 

                                                                    
                               
                                                

 

                                                                    
                               
                                                

 

                                                                    
                               
                                                

 

                                                                    
                               
                                                

 





                                                                          
 
/*
 *
 Copyright (c) Eicon Networks, 2000.
 *
 This source file is supplied for the use with
 Eicon Networks range of DIVA Server Adapters.
 *
 Eicon File Revision :    1.9
 *
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2, or (at your option)
 any later version.
 *
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 See the GNU General Public License for more details.
 *
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */
#include "platform.h"
#include "kst_ifc.h"
#include "di_defs.h"
#include "maintidi.h"
#include "pc.h"
#include "man_defs.h"


extern void diva_mnt_internal_dprintf(dword drv_id, dword type, char *p, ...);

#define MODEM_PARSE_ENTRIES  16 /* amount of variables of interest */
#define FAX_PARSE_ENTRIES    12 /* amount of variables of interest */
#define LINE_PARSE_ENTRIES   15 /* amount of variables of interest */
#define STAT_PARSE_ENTRIES   70 /* amount of variables of interest */

/*
  LOCAL FUNCTIONS
*/
static int DivaSTraceLibraryStart(void *hLib);
static int DivaSTraceLibraryStop(void *hLib);
static int SuperTraceLibraryFinit(void *hLib);
static void *SuperTraceGetHandle(void *hLib);
static int SuperTraceMessageInput(void *hLib);
static int SuperTraceSetAudioTap(void *hLib, int Channel, int on);
static int SuperTraceSetBChannel(void *hLib, int Channel, int on);
static int SuperTraceSetDChannel(void *hLib, int on);
static int SuperTraceSetInfo(void *hLib, int on);
static int SuperTraceClearCall(void *hLib, int Channel);
static int SuperTraceGetOutgoingCallStatistics(void *hLib);
static int SuperTraceGetIncomingCallStatistics(void *hLib);
static int SuperTraceGetModemStatistics(void *hLib);
static int SuperTraceGetFaxStatistics(void *hLib);
static int SuperTraceGetBLayer1Statistics(void *hLib);
static int SuperTraceGetBLayer2Statistics(void *hLib);
static int SuperTraceGetDLayer1Statistics(void *hLib);
static int SuperTraceGetDLayer2Statistics(void *hLib);

/*
  LOCAL FUNCTIONS
*/
static int ScheduleNextTraceRequest(diva_strace_context_t *pLib);
static int process_idi_event(diva_strace_context_t *pLib,
			     diva_man_var_header_t *pVar);
static int process_idi_info(diva_strace_context_t *pLib,
			    diva_man_var_header_t *pVar);
static int diva_modem_event(diva_strace_context_t *pLib, int Channel);
static int diva_fax_event(diva_strace_context_t *pLib, int Channel);
static int diva_line_event(diva_strace_context_t *pLib, int Channel);
static int diva_modem_info(diva_strace_context_t *pLib,
			   int Channel,
			   diva_man_var_header_t *pVar);
static int diva_fax_info(diva_strace_context_t *pLib,
			 int Channel,
			 diva_man_var_header_t *pVar);
static int diva_line_info(diva_strace_context_t *pLib,
			  int Channel,
			  diva_man_var_header_t *pVar);
static int diva_ifc_statistics(diva_strace_context_t *pLib,
			       diva_man_var_header_t *pVar);
static diva_man_var_header_t *get_next_var(diva_man_var_header_t *pVar);
static diva_man_var_header_t *find_var(diva_man_var_header_t *pVar,
				       const char *name);
static int diva_strace_read_int(diva_man_var_header_t *pVar, int *var);
static int diva_strace_read_uint(diva_man_var_header_t *pVar, dword *var);
static int diva_strace_read_asz(diva_man_var_header_t *pVar, char *var);
static int diva_strace_read_asc(diva_man_var_header_t *pVar, char *var);
static int diva_strace_read_ie(diva_man_var_header_t *pVar,
			       diva_trace_ie_t *var);
static void diva_create_parse_table(diva_strace_context_t *pLib);
static void diva_trace_error(diva_strace_context_t *pLib,
			     int error, const char *file, int line);
static void diva_trace_notify_user(diva_strace_context_t *pLib,
				   int Channel,
				   int notify_subject);
static int diva_trace_read_variable(diva_man_var_header_t *pVar,
				    void *variable);

/*
  Initialize the library and return context
  of the created trace object that will represent
  the IDI adapter.
  Return 0 on error.
*/
diva_strace_library_interface_t *DivaSTraceLibraryCreateInstance(int Adapter,
								 const diva_trace_library_user_interface_t *user_proc,
								 byte *pmem) {
	diva_strace_context_t *pLib = (diva_strace_context_t *)pmem;
	int i;

	if (!pLib) {
		return NULL;
	}

	pmem += sizeof(*pLib);
	memset(pLib, 0x00, sizeof(*pLib));

	pLib->Adapter  = Adapter;

	/*
	  Set up Library Interface
	*/
	pLib->instance.hLib                                = pLib;
	pLib->instance.DivaSTraceLibraryStart              = DivaSTraceLibraryStart;
	pLib->instance.DivaSTraceLibraryStop               = DivaSTraceLibraryStop;
	pLib->instance.DivaSTraceLibraryFinit              = SuperTraceLibraryFinit;
	pLib->instance.DivaSTraceMessageInput              = SuperTraceMessageInput;
	pLib->instance.DivaSTraceGetHandle                 = SuperTraceGetHandle;
	pLib->instance.DivaSTraceSetAudioTap               = SuperTraceSetAudioTap;
	pLib->instance.DivaSTraceSetBChannel               = SuperTraceSetBChannel;
	pLib->instance.DivaSTraceSetDChannel               = SuperTraceSetDChannel;
	pLib->instance.DivaSTraceSetInfo                   = SuperTraceSetInfo;
	pLib->instance.DivaSTraceGetOutgoingCallStatistics = \
		SuperTraceGetOutgoingCallStatistics;
	pLib->instance.DivaSTraceGetIncomingCallStatistics = \
		SuperTraceGetIncomingCallStatistics;
	pLib->instance.DivaSTraceGetModemStatistics        = \
		SuperTraceGetModemStatistics;
	pLib->instance.DivaSTraceGetFaxStatistics          = \
		SuperTraceGetFaxStatistics;
	pLib->instance.DivaSTraceGetBLayer1Statistics      = \
		SuperTraceGetBLayer1Statistics;
	pLib->instance.DivaSTraceGetBLayer2Statistics      = \
		SuperTraceGetBLayer2Statistics;
	pLib->instance.DivaSTraceGetDLayer1Statistics      = \
		SuperTraceGetDLayer1Statistics;
	pLib->instance.DivaSTraceGetDLayer2Statistics      = \
		SuperTraceGetDLayer2Statistics;
	pLib->instance.DivaSTraceClearCall                 = SuperTraceClearCall;


	if (user_proc) {
		pLib->user_proc_table.user_context      = user_proc->user_context;
		pLib->user_proc_table.notify_proc       = user_proc->notify_proc;
		pLib->user_proc_table.trace_proc        = user_proc->trace_proc;
		pLib->user_proc_table.error_notify_proc = user_proc->error_notify_proc;
	}

	if (!(pLib->hAdapter = SuperTraceOpenAdapter(Adapter))) {
		diva_mnt_internal_dprintf(0, DLI_ERR, "Can not open XDI adapter");
		return NULL;
	}
	pLib->Channels = SuperTraceGetNumberOfChannels(pLib->hAdapter);

	/*
	  Calculate amount of parte table entites necessary to translate
	  information from all events of onterest
	*/
	pLib->parse_entries = (MODEM_PARSE_ENTRIES + FAX_PARSE_ENTRIES + \
			       STAT_PARSE_ENTRIES + \
			       LINE_PARSE_ENTRIES + 1) * pLib->Channels;
	pLib->parse_table = (diva_strace_path2action_t *)pmem;

	for (i = 0; i < 30; i++) {
		pLib->lines[i].pInterface     = &pLib->Interface;
		pLib->lines[i].pInterfaceStat = &pLib->InterfaceStat;
	}

	pLib->e.R = &pLib->RData;

	pLib->req_busy = 1;
	pLib->rc_ok    = ASSIGN_OK;

	diva_create_parse_table(pLib);

	return ((diva_strace_library_interface_t *)pLib);
}

static int DivaSTraceLibraryStart(void *hLib) {
	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;

	return (SuperTraceASSIGN(pLib->hAdapter, pLib->buffer));
}

/*
  Return (-1) on error
  Return (0) if was initiated or pending
  Return (1) if removal is complete
*/
static int DivaSTraceLibraryStop(void *hLib) {
	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;

	if (!pLib->e.Id) { /* Was never started/assigned */
		return (1);
	}

	switch (pLib->removal_state) {
	case 0:
		pLib->removal_state = 1;
		ScheduleNextTraceRequest(pLib);
		break;

	case 3:
		return (1);
	}

	return (0);
}

static int SuperTraceLibraryFinit(void *hLib) {
	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
	if (pLib) {
		if (pLib->hAdapter) {
			SuperTraceCloseAdapter(pLib->hAdapter);
		}
		return (0);
	}
	return (-1);
}

static void *SuperTraceGetHandle(void *hLib) {
	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;

	return (&pLib->e);
}

/*
  After library handle object is gone in signaled state
  this function should be called and will pick up incoming
  IDI messages (return codes and indications).
*/
static int SuperTraceMessageInput(void *hLib) {
	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
	int ret = 0;
	byte Rc, Ind;

	if (pLib->e.complete == 255) {
		/*
		  Process return code
		*/
		pLib->req_busy = 0;
		Rc             = pLib->e.Rc;
		pLib->e.Rc     = 0;

		if (pLib->removal_state == 2) {
			pLib->removal_state = 3;
			return (0);
		}

		if (Rc != pLib->rc_ok) {
			int ignore = 0;
			/*
			  Auto-detect amount of events/channels and features
			*/
			if (pLib->general_b_ch_event == 1) {
				pLib->general_b_ch_event = 2;
				ignore = 1;
			} else if (pLib->general_fax_event == 1) {
				pLib->general_fax_event = 2;
				ignore = 1;
			} else if (pLib->general_mdm_event == 1) {
				pLib->general_mdm_event = 2;
				ignore = 1;
			} else if ((pLib->ChannelsTraceActive < pLib->Channels) && pLib->ChannelsTraceActive) {
				pLib->ChannelsTraceActive = pLib->Channels;
				ignore = 1;
			} else if (pLib->ModemTraceActive < pLib->Channels) {
				pLib->ModemTraceActive = pLib->Channels;
				ignore = 1;
			} else if (pLib->FaxTraceActive < pLib->Channels) {
				pLib->FaxTraceActive = pLib->Channels;
				ignore = 1;
			} else if (pLib->audio_trace_init == 2) {
				ignore = 1;
				pLib->audio_trace_init = 1;
			} else if (pLib->eye_pattern_pending) {
				pLib->eye_pattern_pending =  0;
				ignore = 1;
			} else if (pLib->audio_tap_pending) {
				pLib->audio_tap_pending = 0;
				ignore = 1;
			}

			if (!ignore) {
				return (-1); /* request failed */
			}
		} else {
			if (pLib->general_b_ch_event == 1) {
				pLib->ChannelsTraceActive = pLib->Channels;
				pLib->general_b_ch_event = 2;
			} else if (pLib->general_fax_event == 1) {
				pLib->general_fax_event = 2;
				pLib->FaxTraceActive = pLib->Channels;
			} else if (pLib->general_mdm_event == 1) {
				pLib->general_mdm_event = 2;
				pLib->ModemTraceActive = pLib->Channels;
			}
		}
		if (pLib->audio_trace_init == 2) {
			pLib->audio_trace_init = 1;
		}
		pLib->rc_ok = 0xff; /* default OK after assign was done */
		if ((ret = ScheduleNextTraceRequest(pLib))) {
			return (-1);
		}
	} else {
		/*
		  Process indication
		  Always 'RNR' indication if return code is pending
		*/
		Ind         = pLib->e.Ind;
		pLib->e.Ind = 0;
		if (pLib->removal_state) {
			pLib->e.RNum	= 0;
			pLib->e.RNR	= 2;
		} else if (pLib->req_busy) {
			pLib->e.RNum	= 0;
			pLib->e.RNR	= 1;
		} else {
			if (pLib->e.complete != 0x02) {
				/*
				  Look-ahead call, set up buffers
				*/
				pLib->e.RNum       = 1;
				pLib->e.R->P       = (byte *)&pLib->buffer[0];
				pLib->e.R->PLength = (word)(sizeof(pLib->buffer) - 1);

			} else {
				/*
				  Indication reception complete, process it now
				*/
				byte *p = (byte *)&pLib->buffer[0];
				pLib->buffer[pLib->e.R->PLength] = 0; /* terminate I.E. with zero */

				switch (Ind) {
				case MAN_COMBI_IND: {
					int total_length    = pLib->e.R->PLength;
					word  this_ind_length;

					while (total_length > 3 && *p) {
						Ind = *p++;
						this_ind_length = (word)p[0] | ((word)p[1] << 8);
						p += 2;

						switch (Ind) {
						case MAN_INFO_IND:
							if (process_idi_info(pLib, (diva_man_var_header_t *)p)) {
								return (-1);
							}
							break;
						case MAN_EVENT_IND:
							if (process_idi_event(pLib, (diva_man_var_header_t *)p)) {
								return (-1);
							}
							break;
						case MAN_TRACE_IND:
							if (pLib->trace_on == 1) {
								/*
								  Ignore first trace event that is result of
								  EVENT_ON operation
								*/
								pLib->trace_on++;
							} else {
								/*
								  Delivery XLOG buffer to application
								*/
								if (pLib->user_proc_table.trace_proc) {
									(*(pLib->user_proc_table.trace_proc))(pLib->user_proc_table.user_context,
													      &pLib->instance, pLib->Adapter,
													      p, this_ind_length);
								}
							}
							break;
						default:
							diva_mnt_internal_dprintf(0, DLI_ERR, "Unknown IDI Ind (DMA mode): %02x", Ind);
						}
						p += (this_ind_length + 1);
						total_length -= (4 + this_ind_length);
					}
				} break;
				case MAN_INFO_IND:
					if (process_idi_info(pLib, (diva_man_var_header_t *)p)) {
						return (-1);
					}
					break;
				case MAN_EVENT_IND:
					if (process_idi_event(pLib, (diva_man_var_header_t *)p)) {
						return (-1);
					}
					break;
				case MAN_TRACE_IND:
					if (pLib->trace_on == 1) {
						/*
						  Ignore first trace event that is result of
						  EVENT_ON operation
						*/
						pLib->trace_on++;
					} else {
						/*
						  Delivery XLOG buffer to application
						*/
						if (pLib->user_proc_table.trace_proc) {
							(*(pLib->user_proc_table.trace_proc))(pLib->user_proc_table.user_context,
											      &pLib->instance, pLib->Adapter,
											      p, pLib->e.R->PLength);
						}
					}
					break;
				default:
					diva_mnt_internal_dprintf(0, DLI_ERR, "Unknown IDI Ind: %02x", Ind);
				}
			}
		}
	}

	if ((ret = ScheduleNextTraceRequest(pLib))) {
		return (-1);
	}

	return (ret);
}

/*
  Internal state machine responsible for scheduling of requests
*/
static int ScheduleNextTraceRequest(diva_strace_context_t *pLib) {
	char name[64];
	int ret = 0;
	int i;

	if (pLib->req_busy) {
		return (0);
	}

	if (pLib->removal_state == 1) {
		if (SuperTraceREMOVE(pLib->hAdapter)) {
			pLib->removal_state = 3;
		} else {
			pLib->req_busy = 1;
			pLib->removal_state = 2;
		}
		return (0);
	}

	if (pLib->removal_state) {
		return (0);
	}

	if (!pLib->general_b_ch_event) {
		if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, "State\\B Event", pLib->buffer))) {
			return (-1);
		}
		pLib->general_b_ch_event = 1;
		pLib->req_busy = 1;
		return (0);
	}

	if (!pLib->general_fax_event) {
		if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, "State\\FAX Event", pLib->buffer))) {
			return (-1);
		}
		pLib->general_fax_event = 1;
		pLib->req_busy = 1;
		return (0);
	}

	if (!pLib->general_mdm_event) {
		if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, "State\\Modem Event", pLib->buffer))) {
			return (-1);
		}
		pLib->general_mdm_event = 1;
		pLib->req_busy = 1;
		return (0);
	}

	if (pLib->ChannelsTraceActive < pLib->Channels) {
		pLib->ChannelsTraceActive++;
		sprintf(name, "State\\B%d\\Line", pLib->ChannelsTraceActive);
		if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, name, pLib->buffer))) {
			pLib->ChannelsTraceActive--;
			return (-1);
		}
		pLib->req_busy = 1;
		return (0);
	}

	if (pLib->ModemTraceActive < pLib->Channels) {
		pLib->ModemTraceActive++;
		sprintf(name, "State\\B%d\\Modem\\Event", pLib->ModemTraceActive);
		if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, name, pLib->buffer))) {
			pLib->ModemTraceActive--;
			return (-1);
		}
		pLib->req_busy = 1;
		return (0);
	}

	if (pLib->FaxTraceActive < pLib->Channels) {
		pLib->FaxTraceActive++;
		sprintf(name, "State\\B%d\\FAX\\Event", pLib->FaxTraceActive);
		if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, name, pLib->buffer))) {
			pLib->FaxTraceActive--;
			return (-1);
		}
		pLib->req_busy = 1;
		return (0);
	}

	if (!pLib->trace_mask_init) {
		word tmp = 0x0000;
		if (SuperTraceWriteVar(pLib->hAdapter,
				       pLib->buffer,
				       "Trace\\Event Enable",
				       &tmp,
				       0x87, /* MI_BITFLD */
					sizeof(tmp))) {
			return (-1);
		}
		pLib->trace_mask_init = 1;
		pLib->req_busy = 1;
		return (0);
	}

	if (!pLib->audio_trace_init) {
		dword tmp = 0x00000000;
		if (SuperTraceWriteVar(pLib->hAdapter,
				       pLib->buffer,
				       "Trace\\AudioCh# Enable",
				       &tmp,
				       0x87, /* MI_BITFLD */
					sizeof(tmp))) {
			return (-1);
		}
		pLib->audio_trace_init = 2;
		pLib->req_busy = 1;
		return (0);
	}

	if (!pLib->bchannel_init) {
		dword tmp = 0x00000000;
		if (SuperTraceWriteVar(pLib->hAdapter,
				       pLib->buffer,
				       "Trace\\B-Ch# Enable",
				       &tmp,
				       0x87, /* MI_BITFLD */
					sizeof(tmp))) {
			return (-1);
		}
		pLib->bchannel_init = 1;
		pLib->req_busy = 1;
		return (0);
	}

	if (!pLib->trace_length_init) {
		word tmp = 30;
		if (SuperTraceWriteVar(pLib->hAdapter,
				       pLib->buffer,
				       "Trace\\Max Log Length",
				       &tmp,
				       0x82, /* MI_UINT */
					sizeof(tmp))) {
			return (-1);
		}
		pLib->trace_length_init = 1;
		pLib->req_busy = 1;
		return (0);
	}

	if (!pLib->trace_on) {
		if (SuperTraceTraceOnRequest(pLib->hAdapter,
					     "Trace\\Log Buffer",
					     pLib->buffer)) {
			return (-1);
		}
		pLib->trace_on = 1;
		pLib->req_busy = 1;
		return (0);
	}

	if (pLib->trace_event_mask != pLib->current_trace_event_mask) {
		if (SuperTraceWriteVar(pLib->hAdapter,
				       pLib->buffer,
				       "Trace\\Event Enable",
				       &pLib->trace_event_mask,
				       0x87, /* MI_BITFLD */
					sizeof(pLib->trace_event_mask))) {
			return (-1);
		}
		pLib->current_trace_event_mask = pLib->trace_event_mask;
		pLib->req_busy = 1;
		return (0);
	}

	if ((pLib->audio_tap_pending >= 0) && (pLib->audio_tap_mask != pLib->current_audio_tap_mask)) {
		if (SuperTraceWriteVar(pLib->hAdapter,
				       pLib->buffer,
				       "Trace\\AudioCh# Enable",
				       &pLib->audio_tap_mask,
				       0x87, /* MI_BITFLD */
					sizeof(pLib->audio_tap_mask))) {
			return (-1);
		}
		pLib->current_audio_tap_mask = pLib->audio_tap_mask;
		pLib->audio_tap_pending = 1;
		pLib->req_busy = 1;
		return (0);
	}

	if ((pLib->eye_pattern_pending >= 0) && (pLib->audio_tap_mask != pLib->current_eye_pattern_mask)) {
		if (SuperTraceWriteVar(pLib->hAdapter,
				       pLib->buffer,
				       "Trace\\EyeCh# Enable",
				       &pLib->audio_tap_mask,
				       0x87, /* MI_BITFLD */
					sizeof(pLib->audio_tap_mask))) {
			return (-1);
		}
		pLib->current_eye_pattern_mask = pLib->audio_tap_mask;
		pLib->eye_pattern_pending = 1;
		pLib->req_busy = 1;
		return (0);
	}

	if (pLib->bchannel_trace_mask != pLib->current_bchannel_trace_mask) {
		if (SuperTraceWriteVar(pLib->hAdapter,
				       pLib->buffer,
				       "Trace\\B-Ch# Enable",
				       &pLib->bchannel_trace_mask,
				       0x87, /* MI_BITFLD */
					sizeof(pLib->bchannel_trace_mask))) {
			return (-1);
		}
		pLib->current_bchannel_trace_mask = pLib->bchannel_trace_mask;
		pLib->req_busy = 1;
		return (0);
	}

	if (!pLib->trace_events_down) {
		if (SuperTraceTraceOnRequest(pLib->hAdapter,
					     "Events Down",
					     pLib->buffer)) {
			return (-1);
		}
		pLib->trace_events_down = 1;
		pLib->req_busy = 1;
		return (0);
	}

	if (!pLib->l1_trace) {
		if (SuperTraceTraceOnRequest(pLib->hAdapter,
					     "State\\Layer1",
					     pLib->buffer)) {
			return (-1);
		}
		pLib->l1_trace = 1;
		pLib->req_busy = 1;
		return (0);
	}

	if (!pLib->l2_trace) {
		if (SuperTraceTraceOnRequest(pLib->hAdapter,
					     "State\\Layer2 No1",
					     pLib->buffer)) {
			return (-1);
		}
		pLib->l2_trace = 1;
		pLib->req_busy = 1;
		return (0);
	}

	for (i = 0; i < 30; i++) {
		if (pLib->pending_line_status & (1L << i)) {
			sprintf(name, "State\\B%d", i + 1);
			if (SuperTraceReadRequest(pLib->hAdapter, name, pLib->buffer)) {
				return (-1);
			}
			pLib->pending_line_status &= ~(1L << i);
			pLib->req_busy = 1;
			return (0);
		}
		if (pLib->pending_modem_status & (1L << i)) {
			sprintf(name, "State\\B%d\\Modem", i + 1);
			if (SuperTraceReadRequest(pLib->hAdapter, name, pLib->buffer)) {
				return (-1);
			}
			pLib->pending_modem_status &= ~(1L << i);
			pLib->req_busy = 1;
			return (0);
		}
		if (pLib->pending_fax_status & (1L << i)) {
			sprintf(name, "State\\B%d\\FAX", i + 1);
			if (SuperTraceReadRequest(pLib->hAdapter, name, pLib->buffer)) {
				return (-1);
			}
			pLib->pending_fax_status &= ~(1L << i);
			pLib->req_busy = 1;
			return (0);
		}
		if (pLib->clear_call_command & (1L << i)) {
			sprintf(name, "State\\B%d\\Clear Call", i + 1);
			if (SuperTraceExecuteRequest(pLib->hAdapter, name, pLib->buffer)) {
				return (-1);
			}
			pLib->clear_call_command &= ~(1L << i);
			pLib->req_busy = 1;
			return (0);
		}
	}

	if (pLib->outgoing_ifc_stats) {
		if (SuperTraceReadRequest(pLib->hAdapter,
					  "Statistics\\Outgoing Calls",
					  pLib->buffer)) {
			return (-1);
		}
		pLib->outgoing_ifc_stats = 0;
		pLib->req_busy = 1;
		return (0);
	}

	if (pLib->incoming_ifc_stats) {
		if (SuperTraceReadRequest(pLib->hAdapter,
					  "Statistics\\Incoming Calls",
					  pLib->buffer)) {
			return (-1);
		}
		pLib->incoming_ifc_stats = 0;
		pLib->req_busy = 1;
		return (0);
	}

	if (pLib->modem_ifc_stats) {
		if (SuperTraceReadRequest(pLib->hAdapter,
					  "Statistics\\Modem",
					  pLib->buffer)) {
			return (-1);
		}
		pLib->modem_ifc_stats = 0;
		pLib->req_busy = 1;
		return (0);
	}

	if (pLib->fax_ifc_stats) {
		if (SuperTraceReadRequest(pLib->hAdapter,
					  "Statistics\\FAX",
					  pLib->buffer)) {
			return (-1);
		}
		pLib->fax_ifc_stats = 0;
		pLib->req_busy = 1;
		return (0);
	}

	if (pLib->b1_ifc_stats) {
		if (SuperTraceReadRequest(pLib->hAdapter,
					  "Statistics\\B-Layer1",
					  pLib->buffer)) {
			return (-1);
		}
		pLib->b1_ifc_stats = 0;
		pLib->req_busy = 1;
		return (0);
	}

	if (pLib->b2_ifc_stats) {
		if (SuperTraceReadRequest(pLib->hAdapter,
					  "Statistics\\B-Layer2",
					  pLib->buffer)) {
			return (-1);
		}
		pLib->b2_ifc_stats = 0;
		pLib->req_busy = 1;
		return (0);
	}

	if (pLib->d1_ifc_stats) {
		if (SuperTraceReadRequest(pLib->hAdapter,
					  "Statistics\\D-Layer1",
					  pLib->buffer)) {
			return (-1);
		}
		pLib->d1_ifc_stats = 0;
		pLib->req_busy = 1;
		return (0);
	}

	if (pLib->d2_ifc_stats) {
		if (SuperTraceReadRequest(pLib->hAdapter,
					  "Statistics\\D-Layer2",
					  pLib->buffer)) {
			return (-1);
		}
		pLib->d2_ifc_stats = 0;
		pLib->req_busy = 1;
		return (0);
	}

	if (!pLib->IncomingCallsCallsActive) {
		pLib->IncomingCallsCallsActive = 1;
		sprintf(name, "%s", "Statistics\\Incoming Calls\\Calls");
		if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, name, pLib->buffer))) {
			pLib->IncomingCallsCallsActive = 0;
			return (-1);
		}
		pLib->req_busy = 1;
		return (0);
	}
	if (!pLib->IncomingCallsConnectedActive) {
		pLib->IncomingCallsConnectedActive = 1;
		sprintf(name, "%s", "Statistics\\Incoming Calls\\Connected");
		if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, name, pLib->buffer))) {
			pLib->IncomingCallsConnectedActive = 0;
			return (-1);
		}
		pLib->req_busy = 1;
		return (0);
	}
	if (!pLib->OutgoingCallsCallsActive) {
		pLib->OutgoingCallsCallsActive = 1;
		sprintf(name, "%s", "Statistics\\Outgoing Calls\\Calls");
		if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, name, pLib->buffer))) {
			pLib->OutgoingCallsCallsActive = 0;
			return (-1);
		}
		pLib->req_busy = 1;
		return (0);
	}
	if (!pLib->OutgoingCallsConnectedActive) {
		pLib->OutgoingCallsConnectedActive = 1;
		sprintf(name, "%s", "Statistics\\Outgoing Calls\\Connected");
		if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, name, pLib->buffer))) {
			pLib->OutgoingCallsConnectedActive = 0;
			return (-1);
		}
		pLib->req_busy = 1;
		return (0);
	}

	return (0);
}

static int process_idi_event(diva_strace_context_t *pLib,
			     diva_man_var_header_t *pVar) {
	const char *path = (char *)&pVar->path_length + 1;
	char name[64];
	int i;

	if (!strncmp("State\\B Event", path, pVar->path_length)) {
		dword ch_id;
		if (!diva_trace_read_variable(pVar, &ch_id)) {
			if (!pLib->line_init_event && !pLib->pending_line_status) {
				for (i = 1; i <= pLib->Channels; i++) {
					diva_line_event(pLib, i);
				}
				return (0);
			} else if (ch_id && ch_id <= pLib->Channels) {
				return (diva_line_event(pLib, (int)ch_id));
			}
			return (0);
		}
		return (-1);
	}

	if (!strncmp("State\\FAX Event", path, pVar->path_length)) {
		dword ch_id;
		if (!diva_trace_read_variable(pVar, &ch_id)) {
			if (!pLib->pending_fax_status && !pLib->fax_init_event) {
				for (i = 1; i <= pLib->Channels; i++) {
					diva_fax_event(pLib, i);
				}
				return (0);
			} else if (ch_id && ch_id <= pLib->Channels) {
				return (diva_fax_event(pLib, (int)ch_id));
			}
			return (0);
		}
		return (-1);
	}

	if (!strncmp("State\\Modem Event", path, pVar->path_length)) {
		dword ch_id;
		if (!diva_trace_read_variable(pVar, &ch_id)) {
			if (!pLib->pending_modem_status && !pLib->modem_init_event) {
				for (i = 1; i <= pLib->Channels; i++) {
					diva_modem_event(pLib, i);
				}
				return (0);
			} else if (ch_id && ch_id <= pLib->Channels) {
				return (diva_modem_event(pLib, (int)ch_id));
			}
			return (0);
		}
		return (-1);
	}

	/*
	  First look for Line Event
	*/
	for (i = 1; i <= pLib->Channels; i++) {
		sprintf(name, "State\\B%d\\Line", i);
		if (find_var(pVar, name)) {
			return (diva_line_event(pLib, i));
		}
	}

	/*
	  Look for Moden Progress Event
	*/
	for (i = 1; i <= pLib->Channels; i++) {
		sprintf(name, "State\\B%d\\Modem\\Event", i);
		if (find_var(pVar, name)) {
			return (diva_modem_event(pLib, i));
		}
	}

	/*
	  Look for Fax Event
	*/
	for (i = 1; i <= pLib->Channels; i++) {
		sprintf(name, "State\\B%d\\FAX\\Event", i);
		if (find_var(pVar, name)) {
			return (diva_fax_event(pLib, i));
		}
	}

	/*
	  Notification about loss of events
	*/
	if (!strncmp("Events Down", path, pVar->path_length)) {
		if (pLib->trace_events_down == 1) {
			pLib->trace_events_down = 2;
		} else {
			diva_trace_error(pLib, 1, "Events Down", 0);
		}
		return (0);
	}

	if (!strncmp("State\\Layer1", path, pVar->path_length)) {
		diva_strace_read_asz(pVar, &pLib->lines[0].pInterface->Layer1[0]);
		if (pLib->l1_trace == 1) {
			pLib->l1_trace = 2;
		} else {
			diva_trace_notify_user(pLib, 0, DIVA_SUPER_TRACE_INTERFACE_CHANGE);
		}
		return (0);
	}
	if (!strncmp("State\\Layer2 No1", path, pVar->path_length)) {
		char *tmp = &pLib->lines[0].pInterface->Layer2[0];
		dword l2_state;
		if (diva_strace_read_uint(pVar, &l2_state))
			return -1;

		switch (l2_state) {
		case 0:
			strcpy(tmp, "Idle");
			break;
		case 1:
			strcpy(tmp, "Layer2 UP");
			break;
		case 2:
			strcpy(tmp, "Layer2 Disconnecting");
			break;
		case 3:
			strcpy(tmp, "Layer2 Connecting");
			break;
		case 4:
			strcpy(tmp, "SPID Initializing");
			break;
		case 5:
			strcpy(tmp, "SPID Initialised");
			break;
		case 6:
			strcpy(tmp, "Layer2 Connecting");
			break;

		case  7:
			strcpy(tmp, "Auto SPID Stopped");
			break;

		case  8:
			strcpy(tmp, "Auto SPID Idle");
			break;

		case  9:
			strcpy(tmp, "Auto SPID Requested");
			break;

		case  10:
			strcpy(tmp, "Auto SPID Delivery");
			break;

		case 11:
			strcpy(tmp, "Auto SPID Complete");
			break;

		default:
			sprintf(tmp, "U:%d", (int)l2_state);
		}
		if (pLib->l2_trace == 1) {
			pLib->l2_trace = 2;
		} else {
			diva_trace_notify_user(pLib, 0, DIVA_SUPER_TRACE_INTERFACE_CHANGE);
		}
		return (0);
	}

	if (!strncmp("Statistics\\Incoming Calls\\Calls", path, pVar->path_length) ||
	    !strncmp("Statistics\\Incoming Calls\\Connected", path, pVar->path_length)) {
		return (SuperTraceGetIncomingCallStatistics(pLib));
	}

	if (!strncmp("Statistics\\Outgoing Calls\\Calls", path, pVar->path_length) ||
	    !strncmp("Statistics\\Outgoing Calls\\Connected", path, pVar->path_length)) {
		return (SuperTraceGetOutgoingCallStatistics(pLib));
	}

	return (-1);
}

static int diva_line_event(diva_strace_context_t *pLib, int Channel) {
	pLib->pending_line_status |= (1L << (Channel - 1));
	return (0);
}

static int diva_modem_event(diva_strace_context_t *pLib, int Channel) {
	pLib->pending_modem_status |= (1L << (Channel - 1));
	return (0);
}

static int diva_fax_event(diva_strace_context_t *pLib, int Channel) {
	pLib->pending_fax_status |= (1L << (Channel - 1));
	return (0);
}

/*
  Process INFO indications that arrive from the card
  Uses path of first I.E. to detect the source of the
  infication
*/
static int process_idi_info(diva_strace_context_t *pLib,
			    diva_man_var_header_t *pVar) {
	const char *path = (char *)&pVar->path_length + 1;
	char name[64];
	int i, len;

	/*
	  First look for Modem Status Info
	*/
	for (i = pLib->Channels; i > 0; i--) {
		len = sprintf(name, "State\\B%d\\Modem", i);
		if (!strncmp(name, path, len)) {
			return (diva_modem_info(pLib, i, pVar));
		}
	}

	/*
	  Look for Fax Status Info
	*/
	for (i = pLib->Channels; i > 0; i--) {
		len = sprintf(name, "State\\B%d\\FAX", i);
		if (!strncmp(name, path, len)) {
			return (diva_fax_info(pLib, i, pVar));
		}
	}

	/*
	  Look for Line Status Info
	*/
	for (i = pLib->Channels; i > 0; i--) {
		len = sprintf(name, "State\\B%d", i);
		if (!strncmp(name, path, len)) {
			return (diva_line_info(pLib, i, pVar));
		}
	}

	if (!diva_ifc_statistics(pLib, pVar)) {
		return (0);
	}

	return (-1);
}

/*
  MODEM INSTANCE STATE UPDATE

  Update Modem Status Information and issue notification to user,
  that will inform about change in the state of modem instance, that is
  associuated with this channel
*/
static int diva_modem_info(diva_strace_context_t *pLib,
			   int Channel,
			   diva_man_var_header_t *pVar) {
	diva_man_var_header_t *cur;
	int i, nr = Channel - 1;

	for (i  = pLib->modem_parse_entry_first[nr];
	     i <= pLib->modem_parse_entry_last[nr]; i++) {
		if ((cur = find_var(pVar, pLib->parse_table[i].path))) {
			if (diva_trace_read_variable(cur, pLib->parse_table[i].variable)) {
				diva_trace_error(pLib, -3, __FILE__, __LINE__);
				return (-1);
			}
		} else {
			diva_trace_error(pLib, -2, __FILE__, __LINE__);
			return (-1);
		}
	}

	/*
	  We do not use first event to notify user - this is the event that is
	  generated as result of EVENT ON operation and is used only to initialize
	  internal variables of application
	*/
	if (pLib->modem_init_event & (1L << nr)) {
		diva_trace_notify_user(pLib, nr, DIVA_SUPER_TRACE_NOTIFY_MODEM_CHANGE);
	} else {
		pLib->modem_init_event |= (1L << nr);
	}

	return (0);
}

static int diva_fax_info(diva_strace_context_t *pLib,
			 int Channel,
			 diva_man_var_header_t *pVar) {
	diva_man_var_header_t *cur;
	int i, nr = Channel - 1;

	for (i  = pLib->fax_parse_entry_first[nr];
	     i <= pLib->fax_parse_entry_last[nr]; i++) {
		if ((cur = find_var(pVar, pLib->parse_table[i].path))) {
			if (diva_trace_read_variable(cur, pLib->parse_table[i].variable)) {
				diva_trace_error(pLib, -3, __FILE__, __LINE__);
				return (-1);
			}
		} else {
			diva_trace_error(pLib, -2, __FILE__, __LINE__);
			return (-1);
		}
	}

	/*
	  We do not use first event to notify user - this is the event that is
	  generated as result of EVENT ON operation and is used only to initialize
	  internal variables of application
	*/
	if (pLib->fax_init_event & (1L << nr)) {
		diva_trace_notify_user(pLib, nr, DIVA_SUPER_TRACE_NOTIFY_FAX_CHANGE);
	} else {
		pLib->fax_init_event |= (1L << nr);
	}

	return (0);
}

/*
  LINE STATE UPDATE
  Update Line Status Information and issue notification to user,
  that will inform about change in the line state.
*/
static int diva_line_info(diva_strace_context_t *pLib,
			  int Channel,
			  diva_man_var_header_t *pVar) {
	diva_man_var_header_t *cur;
	int i, nr = Channel - 1;

	for (i = pLib->line_parse_entry_first[nr];
	     i <= pLib->line_parse_entry_last[nr]; i++) {
		if ((cur = find_var(pVar, pLib->parse_table[i].path))) {
			if (diva_trace_read_variable(cur, pLib->parse_table[i].variable)) {
				diva_trace_error(pLib, -3, __FILE__, __LINE__);
				return (-1);
			}
		} else {
			diva_trace_error(pLib, -2 , __FILE__, __LINE__);
			return (-1);
		}
	}

	/*
	  We do not use first event to notify user - this is the event that is
	  generated as result of EVENT ON operation and is used only to initialize
	  internal variables of application

	  Exception is is if the line is "online". In this case we have to notify
	  user about this confition.
	*/
	if (pLib->line_init_event & (1L << nr)) {
		diva_trace_notify_user(pLib, nr, DIVA_SUPER_TRACE_NOTIFY_LINE_CHANGE);
	} else {
		pLib->line_init_event |= (1L << nr);
		if (strcmp(&pLib->lines[nr].Line[0], "Idle")) {
			diva_trace_notify_user(pLib, nr, DIVA_SUPER_TRACE_NOTIFY_LINE_CHANGE);
		}
	}

	return (0);
}

/*
  Move position to next vatianle in the chain
*/
static diva_man_var_header_t *get_next_var(diva_man_var_header_t *pVar) {
	byte *msg = (byte *)pVar;
	byte *start;
	int msg_length;

	if (*msg != ESC) return NULL;

	start = msg + 2;
	msg_length = *(msg + 1);
	msg = (start + msg_length);

	if (*msg != ESC) return NULL;

	return ((diva_man_var_header_t *)msg);
}

/*
  Move position to variable with given name
*/
static diva_man_var_header_t *find_var(diva_man_var_header_t *pVar,
				       const char *name) {
	const char *path;

	do {
		path = (char *)&pVar->path_length + 1;

		if (!strncmp(name, path, pVar->path_length)) {
			break;
		}
	} while ((pVar = get_next_var(pVar)));

	return (pVar);
}

static void diva_create_line_parse_table(diva_strace_context_t *pLib,
					 int Channel) {
	diva_trace_line_state_t *pLine = &pLib->lines[Channel];
	int nr = Channel + 1;

	if ((pLib->cur_parse_entry + LINE_PARSE_ENTRIES) >= pLib->parse_entries) {
		diva_trace_error(pLib, -1, __FILE__, __LINE__);
		return;
	}

	pLine->ChannelNumber = nr;

	pLib->line_parse_entry_first[Channel] = pLib->cur_parse_entry;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Framing", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->Framing[0];

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Line", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->Line[0];

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Layer2", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->Layer2[0];

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Layer3", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->Layer3[0];

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Remote Address", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLine->RemoteAddress[0];

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Remote SubAddr", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLine->RemoteSubAddress[0];

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Local Address", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLine->LocalAddress[0];

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Local SubAddr", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLine->LocalSubAddress[0];

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\BC", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->call_BC;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\HLC", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->call_HLC;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\LLC", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->call_LLC;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Charges", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->Charges;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Call Reference", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->CallReference;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Last Disc Cause", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLine->LastDisconnecCause;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\User ID", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->UserID[0];

	pLib->line_parse_entry_last[Channel] = pLib->cur_parse_entry - 1;
}

static void diva_create_fax_parse_table(diva_strace_context_t *pLib,
					int Channel) {
	diva_trace_fax_state_t *pFax = &pLib->lines[Channel].fax;
	int nr = Channel + 1;

	if ((pLib->cur_parse_entry + FAX_PARSE_ENTRIES) >= pLib->parse_entries) {
		diva_trace_error(pLib, -1, __FILE__, __LINE__);
		return;
	}
	pFax->ChannelNumber = nr;

	pLib->fax_parse_entry_first[Channel] = pLib->cur_parse_entry;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\FAX\\Event", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Event;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\FAX\\Page Counter", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Page_Counter;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\FAX\\Features", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Features;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\FAX\\Station ID", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Station_ID[0];

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\FAX\\Subaddress", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Subaddress[0];

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\FAX\\Password", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Password[0];

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\FAX\\Speed", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Speed;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\FAX\\Resolution", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Resolution;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\FAX\\Paper Width", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Paper_Width;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\FAX\\Paper Length", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Paper_Length;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\FAX\\Scanline Time", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Scanline_Time;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\FAX\\Disc Reason", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Disc_Reason;

	pLib->fax_parse_entry_last[Channel] = pLib->cur_parse_entry - 1;
}

static void diva_create_modem_parse_table(diva_strace_context_t *pLib,
					  int Channel) {
	diva_trace_modem_state_t *pModem = &pLib->lines[Channel].modem;
	int nr = Channel + 1;

	if ((pLib->cur_parse_entry + MODEM_PARSE_ENTRIES) >= pLib->parse_entries) {
		diva_trace_error(pLib, -1, __FILE__, __LINE__);
		return;
	}
	pModem->ChannelNumber = nr;

	pLib->modem_parse_entry_first[Channel] = pLib->cur_parse_entry;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Modem\\Event", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->Event;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Modem\\Norm", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->Norm;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Modem\\Options", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->Options;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Modem\\TX Speed", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->TxSpeed;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Modem\\RX Speed", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->RxSpeed;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Modem\\Roundtrip ms", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->RoundtripMsec;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Modem\\Symbol Rate", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->SymbolRate;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Modem\\RX Level dBm", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->RxLeveldBm;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Modem\\Echo Level dBm", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->EchoLeveldBm;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Modem\\SNR dB", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->SNRdb;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Modem\\MAE", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->MAE;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Modem\\Local Retrains", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->LocalRetrains;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Modem\\Remote Retrains", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->RemoteRetrains;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Modem\\Local Resyncs", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->LocalResyncs;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Modem\\Remote Resyncs", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->RemoteResyncs;

	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
		"State\\B%d\\Modem\\Disc Reason", nr);
	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->DiscReason;

	pLib->modem_parse_entry_last[Channel] = pLib->cur_parse_entry - 1;
}

static void diva_create_parse_table(diva_strace_context_t *pLib) {
	int i;

	for (i = 0; i < pLib->Channels; i++) {
		diva_create_line_parse_table(pLib, i);
		diva_create_modem_parse_table(pLib, i);
		diva_create_fax_parse_table(pLib, i);
	}

	pLib->statistic_parse_first = pLib->cur_parse_entry;

	/*
	  Outgoing Calls
	*/
	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\Outgoing Calls\\Calls");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.outg.Calls;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\Outgoing Calls\\Connected");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.outg.Connected;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\Outgoing Calls\\User Busy");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.outg.User_Busy;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\Outgoing Calls\\No Answer");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.outg.No_Answer;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\Outgoing Calls\\Wrong Number");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.outg.Wrong_Number;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\Outgoing Calls\\Call Rejected");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.outg.Call_Rejected;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\Outgoing Calls\\Other Failures");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.outg.Other_Failures;

	/*
	  Incoming Calls
	*/
	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\Incoming Calls\\Calls");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.inc.Calls;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\Incoming Calls\\Connected");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.inc.Connected;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\Incoming Calls\\User Busy");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.inc.User_Busy;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\Incoming Calls\\Call Rejected");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.inc.Call_Rejected;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\Incoming Calls\\Wrong Number");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.inc.Wrong_Number;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\Incoming Calls\\Incompatible Dst");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.inc.Incompatible_Dst;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\Incoming Calls\\Out of Order");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.inc.Out_of_Order;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\Incoming Calls\\Ignored");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.inc.Ignored;

	/*
	  Modem Statistics
	*/
	pLib->mdm_statistic_parse_first = pLib->cur_parse_entry;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\Modem\\Disc Normal");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.mdm.Disc_Normal;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\Modem\\Disc Unspecified");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.mdm.Disc_Unspecified;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\Modem\\Disc Busy Tone");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.mdm.Disc_Busy_Tone;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\Modem\\Disc Congestion");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.mdm.Disc_Congestion;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\Modem\\Disc Carr. Wait");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.mdm.Disc_Carr_Wait;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\Modem\\Disc Trn Timeout");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.mdm.Disc_Trn_Timeout;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\Modem\\Disc Incompat.");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.mdm.Disc_Incompat;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\Modem\\Disc Frame Rej.");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.mdm.Disc_Frame_Rej;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\Modem\\Disc V42bis");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.mdm.Disc_V42bis;

	pLib->mdm_statistic_parse_last  = pLib->cur_parse_entry - 1;

	/*
	  Fax Statistics
	*/
	pLib->fax_statistic_parse_first = pLib->cur_parse_entry;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\FAX\\Disc Normal");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.fax.Disc_Normal;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\FAX\\Disc Not Ident.");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.fax.Disc_Not_Ident;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\FAX\\Disc No Response");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.fax.Disc_No_Response;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\FAX\\Disc Retries");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.fax.Disc_Retries;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\FAX\\Disc Unexp. Msg.");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.fax.Disc_Unexp_Msg;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\FAX\\Disc No Polling.");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.fax.Disc_No_Polling;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\FAX\\Disc Training");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.fax.Disc_Training;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\FAX\\Disc Unexpected");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.fax.Disc_Unexpected;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\FAX\\Disc Application");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.fax.Disc_Application;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\FAX\\Disc Incompat.");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.fax.Disc_Incompat;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\FAX\\Disc No Command");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.fax.Disc_No_Command;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\FAX\\Disc Long Msg");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.fax.Disc_Long_Msg;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\FAX\\Disc Supervisor");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.fax.Disc_Supervisor;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\FAX\\Disc SUB SEP PWD");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.fax.Disc_SUB_SEP_PWD;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\FAX\\Disc Invalid Msg");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.fax.Disc_Invalid_Msg;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\FAX\\Disc Page Coding");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.fax.Disc_Page_Coding;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\FAX\\Disc App Timeout");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.fax.Disc_App_Timeout;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\FAX\\Disc Unspecified");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.fax.Disc_Unspecified;

	pLib->fax_statistic_parse_last  = pLib->cur_parse_entry - 1;

	/*
	  B-Layer1"
	*/
	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\B-Layer1\\X-Frames");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.b1.X_Frames;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\B-Layer1\\X-Bytes");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.b1.X_Bytes;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\B-Layer1\\X-Errors");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.b1.X_Errors;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\B-Layer1\\R-Frames");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.b1.R_Frames;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\B-Layer1\\R-Bytes");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.b1.R_Bytes;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\B-Layer1\\R-Errors");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.b1.R_Errors;

	/*
	  B-Layer2
	*/
	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\B-Layer2\\X-Frames");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.b2.X_Frames;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\B-Layer2\\X-Bytes");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.b2.X_Bytes;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\B-Layer2\\X-Errors");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.b2.X_Errors;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\B-Layer2\\R-Frames");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.b2.R_Frames;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\B-Layer2\\R-Bytes");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.b2.R_Bytes;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\B-Layer2\\R-Errors");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.b2.R_Errors;

	/*
	  D-Layer1
	*/
	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\D-Layer1\\X-Frames");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.d1.X_Frames;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\D-Layer1\\X-Bytes");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.d1.X_Bytes;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\D-Layer1\\X-Errors");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.d1.X_Errors;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\D-Layer1\\R-Frames");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.d1.R_Frames;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\D-Layer1\\R-Bytes");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.d1.R_Bytes;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\D-Layer1\\R-Errors");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.d1.R_Errors;

	/*
	  D-Layer2
	*/
	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\D-Layer2\\X-Frames");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.d2.X_Frames;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\D-Layer2\\X-Bytes");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.d2.X_Bytes;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\D-Layer2\\X-Errors");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.d2.X_Errors;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\D-Layer2\\R-Frames");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.d2.R_Frames;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\D-Layer2\\R-Bytes");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.d2.R_Bytes;

	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
	       "Statistics\\D-Layer2\\R-Errors");
	pLib->parse_table[pLib->cur_parse_entry++].variable = \
		&pLib->InterfaceStat.d2.R_Errors;


	pLib->statistic_parse_last  = pLib->cur_parse_entry - 1;
}

static void diva_trace_error(diva_strace_context_t *pLib,
			     int error, const char *file, int line) {
	if (pLib->user_proc_table.error_notify_proc) {
		(*(pLib->user_proc_table.error_notify_proc))(\
			pLib->user_proc_table.user_context,
			&pLib->instance, pLib->Adapter,
			error, file, line);
	}
}

/*
  Delivery notification to user
*/
static void diva_trace_notify_user(diva_strace_context_t *pLib,
				   int Channel,
				   int notify_subject) {
	if (pLib->user_proc_table.notify_proc) {
		(*(pLib->user_proc_table.notify_proc))(pLib->user_proc_table.user_context,
						       &pLib->instance,
						       pLib->Adapter,
						       &pLib->lines[Channel],
						       notify_subject);
	}
}

/*
  Read variable value to they destination based on the variable type
*/
static int diva_trace_read_variable(diva_man_var_header_t *pVar,
				    void *variable) {
	switch (pVar->type) {
	case 0x03: /* MI_ASCIIZ - syting                               */
		return (diva_strace_read_asz(pVar, (char *)variable));
	case 0x04: /* MI_ASCII  - string                               */
		return (diva_strace_read_asc(pVar, (char *)variable));
	case 0x05: /* MI_NUMBER - counted sequence of bytes            */
		return (diva_strace_read_ie(pVar, (diva_trace_ie_t *)variable));
	case 0x81: /* MI_INT    - signed integer                       */
		return (diva_strace_read_int(pVar, (int *)variable));
	case 0x82: /* MI_UINT   - unsigned integer                     */
		return (diva_strace_read_uint(pVar, (dword *)variable));
	case 0x83: /* MI_HINT   - unsigned integer, hex representetion */
		return (diva_strace_read_uint(pVar, (dword *)variable));
	case 0x87: /* MI_BITFLD - unsigned integer, bit representation */
		return (diva_strace_read_uint(pVar, (dword *)variable));
	}

	/*
	  This type of variable is not handled, indicate error
	  Or one problem in management interface, or in application recodeing
	  table, or this application should handle it.
	*/
	return (-1);
}

/*
  Read signed integer to destination
*/
static int diva_strace_read_int(diva_man_var_header_t *pVar, int *var) {
	byte *ptr = (char *)&pVar->path_length;
	int value;

	ptr += (pVar->path_length + 1);

	switch (pVar->value_length) {
	case 1:
		value = *(char *)ptr;
		break;

	case 2:
		value = (short)GET_WORD(ptr);
		break;

	case 4:
		value = (int)GET_DWORD(ptr);
		break;

	default:
		return (-1);
	}

	*var = value;

	return (0);
}

static int diva_strace_read_uint(diva_man_var_header_t *pVar, dword *var) {
	byte *ptr = (char *)&pVar->path_length;
	dword value;

	ptr += (pVar->path_length + 1);

	switch (pVar->value_length) {
	case 1:
		value = (byte)(*ptr);
		break;

	case 2:
		value = (word)GET_WORD(ptr);
		break;

	case 3:
		value  = (dword)GET_DWORD(ptr);
		value &= 0x00ffffff;
		break;

	case 4:
		value = (dword)GET_DWORD(ptr);
		break;

	default:
		return (-1);
	}

	*var = value;

	return (0);
}

/*
  Read zero terminated ASCII string
*/
static int diva_strace_read_asz(diva_man_var_header_t *pVar, char *var) {
	char *ptr = (char *)&pVar->path_length;
	int length;

	ptr += (pVar->path_length + 1);

	if (!(length = pVar->value_length)) {
		length = strlen(ptr);
	}
	memcpy(var, ptr, length);
	var[length] = 0;

	return (0);
}

/*
  Read counted (with leading length byte) ASCII string
*/
static int diva_strace_read_asc(diva_man_var_header_t *pVar, char *var) {
	char *ptr = (char *)&pVar->path_length;

	ptr += (pVar->path_length + 1);
	memcpy(var, ptr + 1, *ptr);
	var[(int)*ptr] = 0;

	return (0);
}

/*
  Read one information element - i.e. one string of byte values with
  one length byte in front
*/
static int diva_strace_read_ie(diva_man_var_header_t *pVar,
			       diva_trace_ie_t *var) {
	char *ptr = (char *)&pVar->path_length;

	ptr += (pVar->path_length + 1);

	var->length = *ptr;
	memcpy(&var->data[0], ptr + 1, *ptr);

	return (0);
}

static int SuperTraceSetAudioTap(void *hLib, int Channel, int on) {
	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;

	if ((Channel < 1) || (Channel > pLib->Channels)) {
		return (-1);
	}
	Channel--;

	if (on) {
		pLib->audio_tap_mask |=  (1L << Channel);
	} else {
		pLib->audio_tap_mask &= ~(1L << Channel);
	}

	/*
	  EYE patterns have TM_M_DATA set as additional
	  condition
	*/
	if (pLib->audio_tap_mask) {
		pLib->trace_event_mask |= TM_M_DATA;
	} else {
		pLib->trace_event_mask &= ~TM_M_DATA;
	}

	return (ScheduleNextTraceRequest(pLib));
}

static int SuperTraceSetBChannel(void *hLib, int Channel, int on) {
	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;

	if ((Channel < 1) || (Channel > pLib->Channels)) {
		return (-1);
	}
	Channel--;

	if (on) {
		pLib->bchannel_trace_mask |=  (1L << Channel);
	} else {
		pLib->bchannel_trace_mask &= ~(1L << Channel);
	}

	return (ScheduleNextTraceRequest(pLib));
}

static int SuperTraceSetDChannel(void *hLib, int on) {
	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;

	if (on) {
		pLib->trace_event_mask |= (TM_D_CHAN | TM_C_COMM | TM_DL_ERR | TM_LAYER1);
	} else {
		pLib->trace_event_mask &= ~(TM_D_CHAN | TM_C_COMM | TM_DL_ERR | TM_LAYER1);
	}

	return (ScheduleNextTraceRequest(pLib));
}

static int SuperTraceSetInfo(void *hLib, int on) {
	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;

	if (on) {
		pLib->trace_event_mask |= TM_STRING;
	} else {
		pLib->trace_event_mask &= ~TM_STRING;
	}

	return (ScheduleNextTraceRequest(pLib));
}

static int SuperTraceClearCall(void *hLib, int Channel) {
	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;

	if ((Channel < 1) || (Channel > pLib->Channels)) {
		return (-1);
	}
	Channel--;

	pLib->clear_call_command |= (1L << Channel);

	return (ScheduleNextTraceRequest(pLib));
}

/*
  Parse and update cumulative statistice
*/
static int diva_ifc_statistics(diva_strace_context_t *pLib,
			       diva_man_var_header_t *pVar) {
	diva_man_var_header_t *cur;
	int i, one_updated = 0, mdm_updated = 0, fax_updated = 0;

	for (i  = pLib->statistic_parse_first; i <= pLib->statistic_parse_last; i++) {
		if ((cur = find_var(pVar, pLib->parse_table[i].path))) {
			if (diva_trace_read_variable(cur, pLib->parse_table[i].variable)) {
				diva_trace_error(pLib, -3 , __FILE__, __LINE__);
				return (-1);
			}
			one_updated = 1;
			if ((i >= pLib->mdm_statistic_parse_first) && (i <= pLib->mdm_statistic_parse_last)) {
				mdm_updated = 1;
			}
			if ((i >= pLib->fax_statistic_parse_first) && (i <= pLib->fax_statistic_parse_last)) {
				fax_updated = 1;
			}
		}
	}

	/*
	  We do not use first event to notify user - this is the event that is
	  generated as result of EVENT ON operation and is used only to initialize
	  internal variables of application
	*/
	if (mdm_updated) {
		diva_trace_notify_user(pLib, 0, DIVA_SUPER_TRACE_NOTIFY_MDM_STAT_CHANGE);
	} else if (fax_updated) {
		diva_trace_notify_user(pLib, 0, DIVA_SUPER_TRACE_NOTIFY_FAX_STAT_CHANGE);
	} else if (one_updated) {
		diva_trace_notify_user(pLib, 0, DIVA_SUPER_TRACE_NOTIFY_STAT_CHANGE);
	}

	return (one_updated ? 0 : -1);
}

static int SuperTraceGetOutgoingCallStatistics(void *hLib) {
	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
	pLib->outgoing_ifc_stats = 1;
	return (ScheduleNextTraceRequest(pLib));
}

static int SuperTraceGetIncomingCallStatistics(void *hLib) {
	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
	pLib->incoming_ifc_stats = 1;
	return (ScheduleNextTraceRequest(pLib));
}

static int SuperTraceGetModemStatistics(void *hLib) {
	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
	pLib->modem_ifc_stats = 1;
	return (ScheduleNextTraceRequest(pLib));
}

static int SuperTraceGetFaxStatistics(void *hLib) {
	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
	pLib->fax_ifc_stats = 1;
	return (ScheduleNextTraceRequest(pLib));
}

static int SuperTraceGetBLayer1Statistics(void *hLib) {
	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
	pLib->b1_ifc_stats = 1;
	return (ScheduleNextTraceRequest(pLib));
}

static int SuperTraceGetBLayer2Statistics(void *hLib) {
	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
	pLib->b2_ifc_stats = 1;
	return (ScheduleNextTraceRequest(pLib));
}

static int SuperTraceGetDLayer1Statistics(void *hLib) {
	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
	pLib->d1_ifc_stats = 1;
	return (ScheduleNextTraceRequest(pLib));
}

static int SuperTraceGetDLayer2Statistics(void *hLib) {
	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
	pLib->d2_ifc_stats = 1;
	return (ScheduleNextTraceRequest(pLib));
}

dword DivaSTraceGetMemotyRequirement(int channels) {
	dword parse_entries = (MODEM_PARSE_ENTRIES + FAX_PARSE_ENTRIES + \
			       STAT_PARSE_ENTRIES + \
			       LINE_PARSE_ENTRIES + 1) * channels;
	return (sizeof(diva_strace_context_t) + \
		(parse_entries * sizeof(diva_strace_path2action_t)));
}