1/*
2 *
3 Copyright (c) Eicon Networks, 2000.
4 *
5 This source file is supplied for the use with
6 Eicon Networks range of DIVA Server Adapters.
7 *
8 Eicon File Revision :    1.9
9 *
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14 *
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
17 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License for more details.
19 *
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 */
25#include "platform.h"
26#include "kst_ifc.h"
27#include "di_defs.h"
28#include "maintidi.h"
29#include "pc.h"
30#include "man_defs.h"
31
32
33extern void diva_mnt_internal_dprintf(dword drv_id, dword type, char *p, ...);
34
35#define MODEM_PARSE_ENTRIES  16 /* amount of variables of interest */
36#define FAX_PARSE_ENTRIES    12 /* amount of variables of interest */
37#define LINE_PARSE_ENTRIES   15 /* amount of variables of interest */
38#define STAT_PARSE_ENTRIES   70 /* amount of variables of interest */
39
40/*
41  LOCAL FUNCTIONS
42*/
43static int DivaSTraceLibraryStart(void *hLib);
44static int DivaSTraceLibraryStop(void *hLib);
45static int SuperTraceLibraryFinit(void *hLib);
46static void *SuperTraceGetHandle(void *hLib);
47static int SuperTraceMessageInput(void *hLib);
48static int SuperTraceSetAudioTap(void *hLib, int Channel, int on);
49static int SuperTraceSetBChannel(void *hLib, int Channel, int on);
50static int SuperTraceSetDChannel(void *hLib, int on);
51static int SuperTraceSetInfo(void *hLib, int on);
52static int SuperTraceClearCall(void *hLib, int Channel);
53static int SuperTraceGetOutgoingCallStatistics(void *hLib);
54static int SuperTraceGetIncomingCallStatistics(void *hLib);
55static int SuperTraceGetModemStatistics(void *hLib);
56static int SuperTraceGetFaxStatistics(void *hLib);
57static int SuperTraceGetBLayer1Statistics(void *hLib);
58static int SuperTraceGetBLayer2Statistics(void *hLib);
59static int SuperTraceGetDLayer1Statistics(void *hLib);
60static int SuperTraceGetDLayer2Statistics(void *hLib);
61
62/*
63  LOCAL FUNCTIONS
64*/
65static int ScheduleNextTraceRequest(diva_strace_context_t *pLib);
66static int process_idi_event(diva_strace_context_t *pLib,
67			     diva_man_var_header_t *pVar);
68static int process_idi_info(diva_strace_context_t *pLib,
69			    diva_man_var_header_t *pVar);
70static int diva_modem_event(diva_strace_context_t *pLib, int Channel);
71static int diva_fax_event(diva_strace_context_t *pLib, int Channel);
72static int diva_line_event(diva_strace_context_t *pLib, int Channel);
73static int diva_modem_info(diva_strace_context_t *pLib,
74			   int Channel,
75			   diva_man_var_header_t *pVar);
76static int diva_fax_info(diva_strace_context_t *pLib,
77			 int Channel,
78			 diva_man_var_header_t *pVar);
79static int diva_line_info(diva_strace_context_t *pLib,
80			  int Channel,
81			  diva_man_var_header_t *pVar);
82static int diva_ifc_statistics(diva_strace_context_t *pLib,
83			       diva_man_var_header_t *pVar);
84static diva_man_var_header_t *get_next_var(diva_man_var_header_t *pVar);
85static diva_man_var_header_t *find_var(diva_man_var_header_t *pVar,
86				       const char *name);
87static int diva_strace_read_int(diva_man_var_header_t *pVar, int *var);
88static int diva_strace_read_uint(diva_man_var_header_t *pVar, dword *var);
89static int diva_strace_read_asz(diva_man_var_header_t *pVar, char *var);
90static int diva_strace_read_asc(diva_man_var_header_t *pVar, char *var);
91static int diva_strace_read_ie(diva_man_var_header_t *pVar,
92			       diva_trace_ie_t *var);
93static void diva_create_parse_table(diva_strace_context_t *pLib);
94static void diva_trace_error(diva_strace_context_t *pLib,
95			     int error, const char *file, int line);
96static void diva_trace_notify_user(diva_strace_context_t *pLib,
97				   int Channel,
98				   int notify_subject);
99static int diva_trace_read_variable(diva_man_var_header_t *pVar,
100				    void *variable);
101
102/*
103  Initialize the library and return context
104  of the created trace object that will represent
105  the IDI adapter.
106  Return 0 on error.
107*/
108diva_strace_library_interface_t *DivaSTraceLibraryCreateInstance(int Adapter,
109								 const diva_trace_library_user_interface_t *user_proc,
110								 byte *pmem) {
111	diva_strace_context_t *pLib = (diva_strace_context_t *)pmem;
112	int i;
113
114	if (!pLib) {
115		return NULL;
116	}
117
118	pmem += sizeof(*pLib);
119	memset(pLib, 0x00, sizeof(*pLib));
120
121	pLib->Adapter  = Adapter;
122
123	/*
124	  Set up Library Interface
125	*/
126	pLib->instance.hLib                                = pLib;
127	pLib->instance.DivaSTraceLibraryStart              = DivaSTraceLibraryStart;
128	pLib->instance.DivaSTraceLibraryStop               = DivaSTraceLibraryStop;
129	pLib->instance.DivaSTraceLibraryFinit              = SuperTraceLibraryFinit;
130	pLib->instance.DivaSTraceMessageInput              = SuperTraceMessageInput;
131	pLib->instance.DivaSTraceGetHandle                 = SuperTraceGetHandle;
132	pLib->instance.DivaSTraceSetAudioTap               = SuperTraceSetAudioTap;
133	pLib->instance.DivaSTraceSetBChannel               = SuperTraceSetBChannel;
134	pLib->instance.DivaSTraceSetDChannel               = SuperTraceSetDChannel;
135	pLib->instance.DivaSTraceSetInfo                   = SuperTraceSetInfo;
136	pLib->instance.DivaSTraceGetOutgoingCallStatistics = \
137		SuperTraceGetOutgoingCallStatistics;
138	pLib->instance.DivaSTraceGetIncomingCallStatistics = \
139		SuperTraceGetIncomingCallStatistics;
140	pLib->instance.DivaSTraceGetModemStatistics        = \
141		SuperTraceGetModemStatistics;
142	pLib->instance.DivaSTraceGetFaxStatistics          = \
143		SuperTraceGetFaxStatistics;
144	pLib->instance.DivaSTraceGetBLayer1Statistics      = \
145		SuperTraceGetBLayer1Statistics;
146	pLib->instance.DivaSTraceGetBLayer2Statistics      = \
147		SuperTraceGetBLayer2Statistics;
148	pLib->instance.DivaSTraceGetDLayer1Statistics      = \
149		SuperTraceGetDLayer1Statistics;
150	pLib->instance.DivaSTraceGetDLayer2Statistics      = \
151		SuperTraceGetDLayer2Statistics;
152	pLib->instance.DivaSTraceClearCall                 = SuperTraceClearCall;
153
154
155	if (user_proc) {
156		pLib->user_proc_table.user_context      = user_proc->user_context;
157		pLib->user_proc_table.notify_proc       = user_proc->notify_proc;
158		pLib->user_proc_table.trace_proc        = user_proc->trace_proc;
159		pLib->user_proc_table.error_notify_proc = user_proc->error_notify_proc;
160	}
161
162	if (!(pLib->hAdapter = SuperTraceOpenAdapter(Adapter))) {
163		diva_mnt_internal_dprintf(0, DLI_ERR, "Can not open XDI adapter");
164		return NULL;
165	}
166	pLib->Channels = SuperTraceGetNumberOfChannels(pLib->hAdapter);
167
168	/*
169	  Calculate amount of parte table entites necessary to translate
170	  information from all events of onterest
171	*/
172	pLib->parse_entries = (MODEM_PARSE_ENTRIES + FAX_PARSE_ENTRIES + \
173			       STAT_PARSE_ENTRIES + \
174			       LINE_PARSE_ENTRIES + 1) * pLib->Channels;
175	pLib->parse_table = (diva_strace_path2action_t *)pmem;
176
177	for (i = 0; i < 30; i++) {
178		pLib->lines[i].pInterface     = &pLib->Interface;
179		pLib->lines[i].pInterfaceStat = &pLib->InterfaceStat;
180	}
181
182	pLib->e.R = &pLib->RData;
183
184	pLib->req_busy = 1;
185	pLib->rc_ok    = ASSIGN_OK;
186
187	diva_create_parse_table(pLib);
188
189	return ((diva_strace_library_interface_t *)pLib);
190}
191
192static int DivaSTraceLibraryStart(void *hLib) {
193	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
194
195	return (SuperTraceASSIGN(pLib->hAdapter, pLib->buffer));
196}
197
198/*
199  Return (-1) on error
200  Return (0) if was initiated or pending
201  Return (1) if removal is complete
202*/
203static int DivaSTraceLibraryStop(void *hLib) {
204	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
205
206	if (!pLib->e.Id) { /* Was never started/assigned */
207		return (1);
208	}
209
210	switch (pLib->removal_state) {
211	case 0:
212		pLib->removal_state = 1;
213		ScheduleNextTraceRequest(pLib);
214		break;
215
216	case 3:
217		return (1);
218	}
219
220	return (0);
221}
222
223static int SuperTraceLibraryFinit(void *hLib) {
224	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
225	if (pLib) {
226		if (pLib->hAdapter) {
227			SuperTraceCloseAdapter(pLib->hAdapter);
228		}
229		return (0);
230	}
231	return (-1);
232}
233
234static void *SuperTraceGetHandle(void *hLib) {
235	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
236
237	return (&pLib->e);
238}
239
240/*
241  After library handle object is gone in signaled state
242  this function should be called and will pick up incoming
243  IDI messages (return codes and indications).
244*/
245static int SuperTraceMessageInput(void *hLib) {
246	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
247	int ret = 0;
248	byte Rc, Ind;
249
250	if (pLib->e.complete == 255) {
251		/*
252		  Process return code
253		*/
254		pLib->req_busy = 0;
255		Rc             = pLib->e.Rc;
256		pLib->e.Rc     = 0;
257
258		if (pLib->removal_state == 2) {
259			pLib->removal_state = 3;
260			return (0);
261		}
262
263		if (Rc != pLib->rc_ok) {
264			int ignore = 0;
265			/*
266			  Auto-detect amount of events/channels and features
267			*/
268			if (pLib->general_b_ch_event == 1) {
269				pLib->general_b_ch_event = 2;
270				ignore = 1;
271			} else if (pLib->general_fax_event == 1) {
272				pLib->general_fax_event = 2;
273				ignore = 1;
274			} else if (pLib->general_mdm_event == 1) {
275				pLib->general_mdm_event = 2;
276				ignore = 1;
277			} else if ((pLib->ChannelsTraceActive < pLib->Channels) && pLib->ChannelsTraceActive) {
278				pLib->ChannelsTraceActive = pLib->Channels;
279				ignore = 1;
280			} else if (pLib->ModemTraceActive < pLib->Channels) {
281				pLib->ModemTraceActive = pLib->Channels;
282				ignore = 1;
283			} else if (pLib->FaxTraceActive < pLib->Channels) {
284				pLib->FaxTraceActive = pLib->Channels;
285				ignore = 1;
286			} else if (pLib->audio_trace_init == 2) {
287				ignore = 1;
288				pLib->audio_trace_init = 1;
289			} else if (pLib->eye_pattern_pending) {
290				pLib->eye_pattern_pending =  0;
291				ignore = 1;
292			} else if (pLib->audio_tap_pending) {
293				pLib->audio_tap_pending = 0;
294				ignore = 1;
295			}
296
297			if (!ignore) {
298				return (-1); /* request failed */
299			}
300		} else {
301			if (pLib->general_b_ch_event == 1) {
302				pLib->ChannelsTraceActive = pLib->Channels;
303				pLib->general_b_ch_event = 2;
304			} else if (pLib->general_fax_event == 1) {
305				pLib->general_fax_event = 2;
306				pLib->FaxTraceActive = pLib->Channels;
307			} else if (pLib->general_mdm_event == 1) {
308				pLib->general_mdm_event = 2;
309				pLib->ModemTraceActive = pLib->Channels;
310			}
311		}
312		if (pLib->audio_trace_init == 2) {
313			pLib->audio_trace_init = 1;
314		}
315		pLib->rc_ok = 0xff; /* default OK after assign was done */
316		if ((ret = ScheduleNextTraceRequest(pLib))) {
317			return (-1);
318		}
319	} else {
320		/*
321		  Process indication
322		  Always 'RNR' indication if return code is pending
323		*/
324		Ind         = pLib->e.Ind;
325		pLib->e.Ind = 0;
326		if (pLib->removal_state) {
327			pLib->e.RNum	= 0;
328			pLib->e.RNR	= 2;
329		} else if (pLib->req_busy) {
330			pLib->e.RNum	= 0;
331			pLib->e.RNR	= 1;
332		} else {
333			if (pLib->e.complete != 0x02) {
334				/*
335				  Look-ahead call, set up buffers
336				*/
337				pLib->e.RNum       = 1;
338				pLib->e.R->P       = (byte *)&pLib->buffer[0];
339				pLib->e.R->PLength = (word)(sizeof(pLib->buffer) - 1);
340
341			} else {
342				/*
343				  Indication reception complete, process it now
344				*/
345				byte *p = (byte *)&pLib->buffer[0];
346				pLib->buffer[pLib->e.R->PLength] = 0; /* terminate I.E. with zero */
347
348				switch (Ind) {
349				case MAN_COMBI_IND: {
350					int total_length    = pLib->e.R->PLength;
351					word  this_ind_length;
352
353					while (total_length > 3 && *p) {
354						Ind = *p++;
355						this_ind_length = (word)p[0] | ((word)p[1] << 8);
356						p += 2;
357
358						switch (Ind) {
359						case MAN_INFO_IND:
360							if (process_idi_info(pLib, (diva_man_var_header_t *)p)) {
361								return (-1);
362							}
363							break;
364						case MAN_EVENT_IND:
365							if (process_idi_event(pLib, (diva_man_var_header_t *)p)) {
366								return (-1);
367							}
368							break;
369						case MAN_TRACE_IND:
370							if (pLib->trace_on == 1) {
371								/*
372								  Ignore first trace event that is result of
373								  EVENT_ON operation
374								*/
375								pLib->trace_on++;
376							} else {
377								/*
378								  Delivery XLOG buffer to application
379								*/
380								if (pLib->user_proc_table.trace_proc) {
381									(*(pLib->user_proc_table.trace_proc))(pLib->user_proc_table.user_context,
382													      &pLib->instance, pLib->Adapter,
383													      p, this_ind_length);
384								}
385							}
386							break;
387						default:
388							diva_mnt_internal_dprintf(0, DLI_ERR, "Unknown IDI Ind (DMA mode): %02x", Ind);
389						}
390						p += (this_ind_length + 1);
391						total_length -= (4 + this_ind_length);
392					}
393				} break;
394				case MAN_INFO_IND:
395					if (process_idi_info(pLib, (diva_man_var_header_t *)p)) {
396						return (-1);
397					}
398					break;
399				case MAN_EVENT_IND:
400					if (process_idi_event(pLib, (diva_man_var_header_t *)p)) {
401						return (-1);
402					}
403					break;
404				case MAN_TRACE_IND:
405					if (pLib->trace_on == 1) {
406						/*
407						  Ignore first trace event that is result of
408						  EVENT_ON operation
409						*/
410						pLib->trace_on++;
411					} else {
412						/*
413						  Delivery XLOG buffer to application
414						*/
415						if (pLib->user_proc_table.trace_proc) {
416							(*(pLib->user_proc_table.trace_proc))(pLib->user_proc_table.user_context,
417											      &pLib->instance, pLib->Adapter,
418											      p, pLib->e.R->PLength);
419						}
420					}
421					break;
422				default:
423					diva_mnt_internal_dprintf(0, DLI_ERR, "Unknown IDI Ind: %02x", Ind);
424				}
425			}
426		}
427	}
428
429	if ((ret = ScheduleNextTraceRequest(pLib))) {
430		return (-1);
431	}
432
433	return (ret);
434}
435
436/*
437  Internal state machine responsible for scheduling of requests
438*/
439static int ScheduleNextTraceRequest(diva_strace_context_t *pLib) {
440	char name[64];
441	int ret = 0;
442	int i;
443
444	if (pLib->req_busy) {
445		return (0);
446	}
447
448	if (pLib->removal_state == 1) {
449		if (SuperTraceREMOVE(pLib->hAdapter)) {
450			pLib->removal_state = 3;
451		} else {
452			pLib->req_busy = 1;
453			pLib->removal_state = 2;
454		}
455		return (0);
456	}
457
458	if (pLib->removal_state) {
459		return (0);
460	}
461
462	if (!pLib->general_b_ch_event) {
463		if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, "State\\B Event", pLib->buffer))) {
464			return (-1);
465		}
466		pLib->general_b_ch_event = 1;
467		pLib->req_busy = 1;
468		return (0);
469	}
470
471	if (!pLib->general_fax_event) {
472		if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, "State\\FAX Event", pLib->buffer))) {
473			return (-1);
474		}
475		pLib->general_fax_event = 1;
476		pLib->req_busy = 1;
477		return (0);
478	}
479
480	if (!pLib->general_mdm_event) {
481		if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, "State\\Modem Event", pLib->buffer))) {
482			return (-1);
483		}
484		pLib->general_mdm_event = 1;
485		pLib->req_busy = 1;
486		return (0);
487	}
488
489	if (pLib->ChannelsTraceActive < pLib->Channels) {
490		pLib->ChannelsTraceActive++;
491		sprintf(name, "State\\B%d\\Line", pLib->ChannelsTraceActive);
492		if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, name, pLib->buffer))) {
493			pLib->ChannelsTraceActive--;
494			return (-1);
495		}
496		pLib->req_busy = 1;
497		return (0);
498	}
499
500	if (pLib->ModemTraceActive < pLib->Channels) {
501		pLib->ModemTraceActive++;
502		sprintf(name, "State\\B%d\\Modem\\Event", pLib->ModemTraceActive);
503		if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, name, pLib->buffer))) {
504			pLib->ModemTraceActive--;
505			return (-1);
506		}
507		pLib->req_busy = 1;
508		return (0);
509	}
510
511	if (pLib->FaxTraceActive < pLib->Channels) {
512		pLib->FaxTraceActive++;
513		sprintf(name, "State\\B%d\\FAX\\Event", pLib->FaxTraceActive);
514		if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, name, pLib->buffer))) {
515			pLib->FaxTraceActive--;
516			return (-1);
517		}
518		pLib->req_busy = 1;
519		return (0);
520	}
521
522	if (!pLib->trace_mask_init) {
523		word tmp = 0x0000;
524		if (SuperTraceWriteVar(pLib->hAdapter,
525				       pLib->buffer,
526				       "Trace\\Event Enable",
527				       &tmp,
528				       0x87, /* MI_BITFLD */
529					sizeof(tmp))) {
530			return (-1);
531		}
532		pLib->trace_mask_init = 1;
533		pLib->req_busy = 1;
534		return (0);
535	}
536
537	if (!pLib->audio_trace_init) {
538		dword tmp = 0x00000000;
539		if (SuperTraceWriteVar(pLib->hAdapter,
540				       pLib->buffer,
541				       "Trace\\AudioCh# Enable",
542				       &tmp,
543				       0x87, /* MI_BITFLD */
544					sizeof(tmp))) {
545			return (-1);
546		}
547		pLib->audio_trace_init = 2;
548		pLib->req_busy = 1;
549		return (0);
550	}
551
552	if (!pLib->bchannel_init) {
553		dword tmp = 0x00000000;
554		if (SuperTraceWriteVar(pLib->hAdapter,
555				       pLib->buffer,
556				       "Trace\\B-Ch# Enable",
557				       &tmp,
558				       0x87, /* MI_BITFLD */
559					sizeof(tmp))) {
560			return (-1);
561		}
562		pLib->bchannel_init = 1;
563		pLib->req_busy = 1;
564		return (0);
565	}
566
567	if (!pLib->trace_length_init) {
568		word tmp = 30;
569		if (SuperTraceWriteVar(pLib->hAdapter,
570				       pLib->buffer,
571				       "Trace\\Max Log Length",
572				       &tmp,
573				       0x82, /* MI_UINT */
574					sizeof(tmp))) {
575			return (-1);
576		}
577		pLib->trace_length_init = 1;
578		pLib->req_busy = 1;
579		return (0);
580	}
581
582	if (!pLib->trace_on) {
583		if (SuperTraceTraceOnRequest(pLib->hAdapter,
584					     "Trace\\Log Buffer",
585					     pLib->buffer)) {
586			return (-1);
587		}
588		pLib->trace_on = 1;
589		pLib->req_busy = 1;
590		return (0);
591	}
592
593	if (pLib->trace_event_mask != pLib->current_trace_event_mask) {
594		if (SuperTraceWriteVar(pLib->hAdapter,
595				       pLib->buffer,
596				       "Trace\\Event Enable",
597				       &pLib->trace_event_mask,
598				       0x87, /* MI_BITFLD */
599					sizeof(pLib->trace_event_mask))) {
600			return (-1);
601		}
602		pLib->current_trace_event_mask = pLib->trace_event_mask;
603		pLib->req_busy = 1;
604		return (0);
605	}
606
607	if ((pLib->audio_tap_pending >= 0) && (pLib->audio_tap_mask != pLib->current_audio_tap_mask)) {
608		if (SuperTraceWriteVar(pLib->hAdapter,
609				       pLib->buffer,
610				       "Trace\\AudioCh# Enable",
611				       &pLib->audio_tap_mask,
612				       0x87, /* MI_BITFLD */
613					sizeof(pLib->audio_tap_mask))) {
614			return (-1);
615		}
616		pLib->current_audio_tap_mask = pLib->audio_tap_mask;
617		pLib->audio_tap_pending = 1;
618		pLib->req_busy = 1;
619		return (0);
620	}
621
622	if ((pLib->eye_pattern_pending >= 0) && (pLib->audio_tap_mask != pLib->current_eye_pattern_mask)) {
623		if (SuperTraceWriteVar(pLib->hAdapter,
624				       pLib->buffer,
625				       "Trace\\EyeCh# Enable",
626				       &pLib->audio_tap_mask,
627				       0x87, /* MI_BITFLD */
628					sizeof(pLib->audio_tap_mask))) {
629			return (-1);
630		}
631		pLib->current_eye_pattern_mask = pLib->audio_tap_mask;
632		pLib->eye_pattern_pending = 1;
633		pLib->req_busy = 1;
634		return (0);
635	}
636
637	if (pLib->bchannel_trace_mask != pLib->current_bchannel_trace_mask) {
638		if (SuperTraceWriteVar(pLib->hAdapter,
639				       pLib->buffer,
640				       "Trace\\B-Ch# Enable",
641				       &pLib->bchannel_trace_mask,
642				       0x87, /* MI_BITFLD */
643					sizeof(pLib->bchannel_trace_mask))) {
644			return (-1);
645		}
646		pLib->current_bchannel_trace_mask = pLib->bchannel_trace_mask;
647		pLib->req_busy = 1;
648		return (0);
649	}
650
651	if (!pLib->trace_events_down) {
652		if (SuperTraceTraceOnRequest(pLib->hAdapter,
653					     "Events Down",
654					     pLib->buffer)) {
655			return (-1);
656		}
657		pLib->trace_events_down = 1;
658		pLib->req_busy = 1;
659		return (0);
660	}
661
662	if (!pLib->l1_trace) {
663		if (SuperTraceTraceOnRequest(pLib->hAdapter,
664					     "State\\Layer1",
665					     pLib->buffer)) {
666			return (-1);
667		}
668		pLib->l1_trace = 1;
669		pLib->req_busy = 1;
670		return (0);
671	}
672
673	if (!pLib->l2_trace) {
674		if (SuperTraceTraceOnRequest(pLib->hAdapter,
675					     "State\\Layer2 No1",
676					     pLib->buffer)) {
677			return (-1);
678		}
679		pLib->l2_trace = 1;
680		pLib->req_busy = 1;
681		return (0);
682	}
683
684	for (i = 0; i < 30; i++) {
685		if (pLib->pending_line_status & (1L << i)) {
686			sprintf(name, "State\\B%d", i + 1);
687			if (SuperTraceReadRequest(pLib->hAdapter, name, pLib->buffer)) {
688				return (-1);
689			}
690			pLib->pending_line_status &= ~(1L << i);
691			pLib->req_busy = 1;
692			return (0);
693		}
694		if (pLib->pending_modem_status & (1L << i)) {
695			sprintf(name, "State\\B%d\\Modem", i + 1);
696			if (SuperTraceReadRequest(pLib->hAdapter, name, pLib->buffer)) {
697				return (-1);
698			}
699			pLib->pending_modem_status &= ~(1L << i);
700			pLib->req_busy = 1;
701			return (0);
702		}
703		if (pLib->pending_fax_status & (1L << i)) {
704			sprintf(name, "State\\B%d\\FAX", i + 1);
705			if (SuperTraceReadRequest(pLib->hAdapter, name, pLib->buffer)) {
706				return (-1);
707			}
708			pLib->pending_fax_status &= ~(1L << i);
709			pLib->req_busy = 1;
710			return (0);
711		}
712		if (pLib->clear_call_command & (1L << i)) {
713			sprintf(name, "State\\B%d\\Clear Call", i + 1);
714			if (SuperTraceExecuteRequest(pLib->hAdapter, name, pLib->buffer)) {
715				return (-1);
716			}
717			pLib->clear_call_command &= ~(1L << i);
718			pLib->req_busy = 1;
719			return (0);
720		}
721	}
722
723	if (pLib->outgoing_ifc_stats) {
724		if (SuperTraceReadRequest(pLib->hAdapter,
725					  "Statistics\\Outgoing Calls",
726					  pLib->buffer)) {
727			return (-1);
728		}
729		pLib->outgoing_ifc_stats = 0;
730		pLib->req_busy = 1;
731		return (0);
732	}
733
734	if (pLib->incoming_ifc_stats) {
735		if (SuperTraceReadRequest(pLib->hAdapter,
736					  "Statistics\\Incoming Calls",
737					  pLib->buffer)) {
738			return (-1);
739		}
740		pLib->incoming_ifc_stats = 0;
741		pLib->req_busy = 1;
742		return (0);
743	}
744
745	if (pLib->modem_ifc_stats) {
746		if (SuperTraceReadRequest(pLib->hAdapter,
747					  "Statistics\\Modem",
748					  pLib->buffer)) {
749			return (-1);
750		}
751		pLib->modem_ifc_stats = 0;
752		pLib->req_busy = 1;
753		return (0);
754	}
755
756	if (pLib->fax_ifc_stats) {
757		if (SuperTraceReadRequest(pLib->hAdapter,
758					  "Statistics\\FAX",
759					  pLib->buffer)) {
760			return (-1);
761		}
762		pLib->fax_ifc_stats = 0;
763		pLib->req_busy = 1;
764		return (0);
765	}
766
767	if (pLib->b1_ifc_stats) {
768		if (SuperTraceReadRequest(pLib->hAdapter,
769					  "Statistics\\B-Layer1",
770					  pLib->buffer)) {
771			return (-1);
772		}
773		pLib->b1_ifc_stats = 0;
774		pLib->req_busy = 1;
775		return (0);
776	}
777
778	if (pLib->b2_ifc_stats) {
779		if (SuperTraceReadRequest(pLib->hAdapter,
780					  "Statistics\\B-Layer2",
781					  pLib->buffer)) {
782			return (-1);
783		}
784		pLib->b2_ifc_stats = 0;
785		pLib->req_busy = 1;
786		return (0);
787	}
788
789	if (pLib->d1_ifc_stats) {
790		if (SuperTraceReadRequest(pLib->hAdapter,
791					  "Statistics\\D-Layer1",
792					  pLib->buffer)) {
793			return (-1);
794		}
795		pLib->d1_ifc_stats = 0;
796		pLib->req_busy = 1;
797		return (0);
798	}
799
800	if (pLib->d2_ifc_stats) {
801		if (SuperTraceReadRequest(pLib->hAdapter,
802					  "Statistics\\D-Layer2",
803					  pLib->buffer)) {
804			return (-1);
805		}
806		pLib->d2_ifc_stats = 0;
807		pLib->req_busy = 1;
808		return (0);
809	}
810
811	if (!pLib->IncomingCallsCallsActive) {
812		pLib->IncomingCallsCallsActive = 1;
813		sprintf(name, "%s", "Statistics\\Incoming Calls\\Calls");
814		if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, name, pLib->buffer))) {
815			pLib->IncomingCallsCallsActive = 0;
816			return (-1);
817		}
818		pLib->req_busy = 1;
819		return (0);
820	}
821	if (!pLib->IncomingCallsConnectedActive) {
822		pLib->IncomingCallsConnectedActive = 1;
823		sprintf(name, "%s", "Statistics\\Incoming Calls\\Connected");
824		if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, name, pLib->buffer))) {
825			pLib->IncomingCallsConnectedActive = 0;
826			return (-1);
827		}
828		pLib->req_busy = 1;
829		return (0);
830	}
831	if (!pLib->OutgoingCallsCallsActive) {
832		pLib->OutgoingCallsCallsActive = 1;
833		sprintf(name, "%s", "Statistics\\Outgoing Calls\\Calls");
834		if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, name, pLib->buffer))) {
835			pLib->OutgoingCallsCallsActive = 0;
836			return (-1);
837		}
838		pLib->req_busy = 1;
839		return (0);
840	}
841	if (!pLib->OutgoingCallsConnectedActive) {
842		pLib->OutgoingCallsConnectedActive = 1;
843		sprintf(name, "%s", "Statistics\\Outgoing Calls\\Connected");
844		if ((ret = SuperTraceTraceOnRequest(pLib->hAdapter, name, pLib->buffer))) {
845			pLib->OutgoingCallsConnectedActive = 0;
846			return (-1);
847		}
848		pLib->req_busy = 1;
849		return (0);
850	}
851
852	return (0);
853}
854
855static int process_idi_event(diva_strace_context_t *pLib,
856			     diva_man_var_header_t *pVar) {
857	const char *path = (char *)&pVar->path_length + 1;
858	char name[64];
859	int i;
860
861	if (!strncmp("State\\B Event", path, pVar->path_length)) {
862		dword ch_id;
863		if (!diva_trace_read_variable(pVar, &ch_id)) {
864			if (!pLib->line_init_event && !pLib->pending_line_status) {
865				for (i = 1; i <= pLib->Channels; i++) {
866					diva_line_event(pLib, i);
867				}
868				return (0);
869			} else if (ch_id && ch_id <= pLib->Channels) {
870				return (diva_line_event(pLib, (int)ch_id));
871			}
872			return (0);
873		}
874		return (-1);
875	}
876
877	if (!strncmp("State\\FAX Event", path, pVar->path_length)) {
878		dword ch_id;
879		if (!diva_trace_read_variable(pVar, &ch_id)) {
880			if (!pLib->pending_fax_status && !pLib->fax_init_event) {
881				for (i = 1; i <= pLib->Channels; i++) {
882					diva_fax_event(pLib, i);
883				}
884				return (0);
885			} else if (ch_id && ch_id <= pLib->Channels) {
886				return (diva_fax_event(pLib, (int)ch_id));
887			}
888			return (0);
889		}
890		return (-1);
891	}
892
893	if (!strncmp("State\\Modem Event", path, pVar->path_length)) {
894		dword ch_id;
895		if (!diva_trace_read_variable(pVar, &ch_id)) {
896			if (!pLib->pending_modem_status && !pLib->modem_init_event) {
897				for (i = 1; i <= pLib->Channels; i++) {
898					diva_modem_event(pLib, i);
899				}
900				return (0);
901			} else if (ch_id && ch_id <= pLib->Channels) {
902				return (diva_modem_event(pLib, (int)ch_id));
903			}
904			return (0);
905		}
906		return (-1);
907	}
908
909	/*
910	  First look for Line Event
911	*/
912	for (i = 1; i <= pLib->Channels; i++) {
913		sprintf(name, "State\\B%d\\Line", i);
914		if (find_var(pVar, name)) {
915			return (diva_line_event(pLib, i));
916		}
917	}
918
919	/*
920	  Look for Moden Progress Event
921	*/
922	for (i = 1; i <= pLib->Channels; i++) {
923		sprintf(name, "State\\B%d\\Modem\\Event", i);
924		if (find_var(pVar, name)) {
925			return (diva_modem_event(pLib, i));
926		}
927	}
928
929	/*
930	  Look for Fax Event
931	*/
932	for (i = 1; i <= pLib->Channels; i++) {
933		sprintf(name, "State\\B%d\\FAX\\Event", i);
934		if (find_var(pVar, name)) {
935			return (diva_fax_event(pLib, i));
936		}
937	}
938
939	/*
940	  Notification about loss of events
941	*/
942	if (!strncmp("Events Down", path, pVar->path_length)) {
943		if (pLib->trace_events_down == 1) {
944			pLib->trace_events_down = 2;
945		} else {
946			diva_trace_error(pLib, 1, "Events Down", 0);
947		}
948		return (0);
949	}
950
951	if (!strncmp("State\\Layer1", path, pVar->path_length)) {
952		diva_strace_read_asz(pVar, &pLib->lines[0].pInterface->Layer1[0]);
953		if (pLib->l1_trace == 1) {
954			pLib->l1_trace = 2;
955		} else {
956			diva_trace_notify_user(pLib, 0, DIVA_SUPER_TRACE_INTERFACE_CHANGE);
957		}
958		return (0);
959	}
960	if (!strncmp("State\\Layer2 No1", path, pVar->path_length)) {
961		char *tmp = &pLib->lines[0].pInterface->Layer2[0];
962		dword l2_state;
963		if (diva_strace_read_uint(pVar, &l2_state))
964			return -1;
965
966		switch (l2_state) {
967		case 0:
968			strcpy(tmp, "Idle");
969			break;
970		case 1:
971			strcpy(tmp, "Layer2 UP");
972			break;
973		case 2:
974			strcpy(tmp, "Layer2 Disconnecting");
975			break;
976		case 3:
977			strcpy(tmp, "Layer2 Connecting");
978			break;
979		case 4:
980			strcpy(tmp, "SPID Initializing");
981			break;
982		case 5:
983			strcpy(tmp, "SPID Initialised");
984			break;
985		case 6:
986			strcpy(tmp, "Layer2 Connecting");
987			break;
988
989		case  7:
990			strcpy(tmp, "Auto SPID Stopped");
991			break;
992
993		case  8:
994			strcpy(tmp, "Auto SPID Idle");
995			break;
996
997		case  9:
998			strcpy(tmp, "Auto SPID Requested");
999			break;
1000
1001		case  10:
1002			strcpy(tmp, "Auto SPID Delivery");
1003			break;
1004
1005		case 11:
1006			strcpy(tmp, "Auto SPID Complete");
1007			break;
1008
1009		default:
1010			sprintf(tmp, "U:%d", (int)l2_state);
1011		}
1012		if (pLib->l2_trace == 1) {
1013			pLib->l2_trace = 2;
1014		} else {
1015			diva_trace_notify_user(pLib, 0, DIVA_SUPER_TRACE_INTERFACE_CHANGE);
1016		}
1017		return (0);
1018	}
1019
1020	if (!strncmp("Statistics\\Incoming Calls\\Calls", path, pVar->path_length) ||
1021	    !strncmp("Statistics\\Incoming Calls\\Connected", path, pVar->path_length)) {
1022		return (SuperTraceGetIncomingCallStatistics(pLib));
1023	}
1024
1025	if (!strncmp("Statistics\\Outgoing Calls\\Calls", path, pVar->path_length) ||
1026	    !strncmp("Statistics\\Outgoing Calls\\Connected", path, pVar->path_length)) {
1027		return (SuperTraceGetOutgoingCallStatistics(pLib));
1028	}
1029
1030	return (-1);
1031}
1032
1033static int diva_line_event(diva_strace_context_t *pLib, int Channel) {
1034	pLib->pending_line_status |= (1L << (Channel - 1));
1035	return (0);
1036}
1037
1038static int diva_modem_event(diva_strace_context_t *pLib, int Channel) {
1039	pLib->pending_modem_status |= (1L << (Channel - 1));
1040	return (0);
1041}
1042
1043static int diva_fax_event(diva_strace_context_t *pLib, int Channel) {
1044	pLib->pending_fax_status |= (1L << (Channel - 1));
1045	return (0);
1046}
1047
1048/*
1049  Process INFO indications that arrive from the card
1050  Uses path of first I.E. to detect the source of the
1051  infication
1052*/
1053static int process_idi_info(diva_strace_context_t *pLib,
1054			    diva_man_var_header_t *pVar) {
1055	const char *path = (char *)&pVar->path_length + 1;
1056	char name[64];
1057	int i, len;
1058
1059	/*
1060	  First look for Modem Status Info
1061	*/
1062	for (i = pLib->Channels; i > 0; i--) {
1063		len = sprintf(name, "State\\B%d\\Modem", i);
1064		if (!strncmp(name, path, len)) {
1065			return (diva_modem_info(pLib, i, pVar));
1066		}
1067	}
1068
1069	/*
1070	  Look for Fax Status Info
1071	*/
1072	for (i = pLib->Channels; i > 0; i--) {
1073		len = sprintf(name, "State\\B%d\\FAX", i);
1074		if (!strncmp(name, path, len)) {
1075			return (diva_fax_info(pLib, i, pVar));
1076		}
1077	}
1078
1079	/*
1080	  Look for Line Status Info
1081	*/
1082	for (i = pLib->Channels; i > 0; i--) {
1083		len = sprintf(name, "State\\B%d", i);
1084		if (!strncmp(name, path, len)) {
1085			return (diva_line_info(pLib, i, pVar));
1086		}
1087	}
1088
1089	if (!diva_ifc_statistics(pLib, pVar)) {
1090		return (0);
1091	}
1092
1093	return (-1);
1094}
1095
1096/*
1097  MODEM INSTANCE STATE UPDATE
1098
1099  Update Modem Status Information and issue notification to user,
1100  that will inform about change in the state of modem instance, that is
1101  associuated with this channel
1102*/
1103static int diva_modem_info(diva_strace_context_t *pLib,
1104			   int Channel,
1105			   diva_man_var_header_t *pVar) {
1106	diva_man_var_header_t *cur;
1107	int i, nr = Channel - 1;
1108
1109	for (i  = pLib->modem_parse_entry_first[nr];
1110	     i <= pLib->modem_parse_entry_last[nr]; i++) {
1111		if ((cur = find_var(pVar, pLib->parse_table[i].path))) {
1112			if (diva_trace_read_variable(cur, pLib->parse_table[i].variable)) {
1113				diva_trace_error(pLib, -3, __FILE__, __LINE__);
1114				return (-1);
1115			}
1116		} else {
1117			diva_trace_error(pLib, -2, __FILE__, __LINE__);
1118			return (-1);
1119		}
1120	}
1121
1122	/*
1123	  We do not use first event to notify user - this is the event that is
1124	  generated as result of EVENT ON operation and is used only to initialize
1125	  internal variables of application
1126	*/
1127	if (pLib->modem_init_event & (1L << nr)) {
1128		diva_trace_notify_user(pLib, nr, DIVA_SUPER_TRACE_NOTIFY_MODEM_CHANGE);
1129	} else {
1130		pLib->modem_init_event |= (1L << nr);
1131	}
1132
1133	return (0);
1134}
1135
1136static int diva_fax_info(diva_strace_context_t *pLib,
1137			 int Channel,
1138			 diva_man_var_header_t *pVar) {
1139	diva_man_var_header_t *cur;
1140	int i, nr = Channel - 1;
1141
1142	for (i  = pLib->fax_parse_entry_first[nr];
1143	     i <= pLib->fax_parse_entry_last[nr]; i++) {
1144		if ((cur = find_var(pVar, pLib->parse_table[i].path))) {
1145			if (diva_trace_read_variable(cur, pLib->parse_table[i].variable)) {
1146				diva_trace_error(pLib, -3, __FILE__, __LINE__);
1147				return (-1);
1148			}
1149		} else {
1150			diva_trace_error(pLib, -2, __FILE__, __LINE__);
1151			return (-1);
1152		}
1153	}
1154
1155	/*
1156	  We do not use first event to notify user - this is the event that is
1157	  generated as result of EVENT ON operation and is used only to initialize
1158	  internal variables of application
1159	*/
1160	if (pLib->fax_init_event & (1L << nr)) {
1161		diva_trace_notify_user(pLib, nr, DIVA_SUPER_TRACE_NOTIFY_FAX_CHANGE);
1162	} else {
1163		pLib->fax_init_event |= (1L << nr);
1164	}
1165
1166	return (0);
1167}
1168
1169/*
1170  LINE STATE UPDATE
1171  Update Line Status Information and issue notification to user,
1172  that will inform about change in the line state.
1173*/
1174static int diva_line_info(diva_strace_context_t *pLib,
1175			  int Channel,
1176			  diva_man_var_header_t *pVar) {
1177	diva_man_var_header_t *cur;
1178	int i, nr = Channel - 1;
1179
1180	for (i = pLib->line_parse_entry_first[nr];
1181	     i <= pLib->line_parse_entry_last[nr]; i++) {
1182		if ((cur = find_var(pVar, pLib->parse_table[i].path))) {
1183			if (diva_trace_read_variable(cur, pLib->parse_table[i].variable)) {
1184				diva_trace_error(pLib, -3, __FILE__, __LINE__);
1185				return (-1);
1186			}
1187		} else {
1188			diva_trace_error(pLib, -2 , __FILE__, __LINE__);
1189			return (-1);
1190		}
1191	}
1192
1193	/*
1194	  We do not use first event to notify user - this is the event that is
1195	  generated as result of EVENT ON operation and is used only to initialize
1196	  internal variables of application
1197
1198	  Exception is is if the line is "online". In this case we have to notify
1199	  user about this confition.
1200	*/
1201	if (pLib->line_init_event & (1L << nr)) {
1202		diva_trace_notify_user(pLib, nr, DIVA_SUPER_TRACE_NOTIFY_LINE_CHANGE);
1203	} else {
1204		pLib->line_init_event |= (1L << nr);
1205		if (strcmp(&pLib->lines[nr].Line[0], "Idle")) {
1206			diva_trace_notify_user(pLib, nr, DIVA_SUPER_TRACE_NOTIFY_LINE_CHANGE);
1207		}
1208	}
1209
1210	return (0);
1211}
1212
1213/*
1214  Move position to next vatianle in the chain
1215*/
1216static diva_man_var_header_t *get_next_var(diva_man_var_header_t *pVar) {
1217	byte *msg = (byte *)pVar;
1218	byte *start;
1219	int msg_length;
1220
1221	if (*msg != ESC) return NULL;
1222
1223	start = msg + 2;
1224	msg_length = *(msg + 1);
1225	msg = (start + msg_length);
1226
1227	if (*msg != ESC) return NULL;
1228
1229	return ((diva_man_var_header_t *)msg);
1230}
1231
1232/*
1233  Move position to variable with given name
1234*/
1235static diva_man_var_header_t *find_var(diva_man_var_header_t *pVar,
1236				       const char *name) {
1237	const char *path;
1238
1239	do {
1240		path = (char *)&pVar->path_length + 1;
1241
1242		if (!strncmp(name, path, pVar->path_length)) {
1243			break;
1244		}
1245	} while ((pVar = get_next_var(pVar)));
1246
1247	return (pVar);
1248}
1249
1250static void diva_create_line_parse_table(diva_strace_context_t *pLib,
1251					 int Channel) {
1252	diva_trace_line_state_t *pLine = &pLib->lines[Channel];
1253	int nr = Channel + 1;
1254
1255	if ((pLib->cur_parse_entry + LINE_PARSE_ENTRIES) >= pLib->parse_entries) {
1256		diva_trace_error(pLib, -1, __FILE__, __LINE__);
1257		return;
1258	}
1259
1260	pLine->ChannelNumber = nr;
1261
1262	pLib->line_parse_entry_first[Channel] = pLib->cur_parse_entry;
1263
1264	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1265		"State\\B%d\\Framing", nr);
1266	pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->Framing[0];
1267
1268	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1269		"State\\B%d\\Line", nr);
1270	pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->Line[0];
1271
1272	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1273		"State\\B%d\\Layer2", nr);
1274	pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->Layer2[0];
1275
1276	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1277		"State\\B%d\\Layer3", nr);
1278	pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->Layer3[0];
1279
1280	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1281		"State\\B%d\\Remote Address", nr);
1282	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1283		&pLine->RemoteAddress[0];
1284
1285	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1286		"State\\B%d\\Remote SubAddr", nr);
1287	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1288		&pLine->RemoteSubAddress[0];
1289
1290	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1291		"State\\B%d\\Local Address", nr);
1292	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1293		&pLine->LocalAddress[0];
1294
1295	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1296		"State\\B%d\\Local SubAddr", nr);
1297	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1298		&pLine->LocalSubAddress[0];
1299
1300	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1301		"State\\B%d\\BC", nr);
1302	pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->call_BC;
1303
1304	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1305		"State\\B%d\\HLC", nr);
1306	pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->call_HLC;
1307
1308	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1309		"State\\B%d\\LLC", nr);
1310	pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->call_LLC;
1311
1312	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1313		"State\\B%d\\Charges", nr);
1314	pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->Charges;
1315
1316	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1317		"State\\B%d\\Call Reference", nr);
1318	pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->CallReference;
1319
1320	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1321		"State\\B%d\\Last Disc Cause", nr);
1322	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1323		&pLine->LastDisconnecCause;
1324
1325	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1326		"State\\B%d\\User ID", nr);
1327	pLib->parse_table[pLib->cur_parse_entry++].variable = &pLine->UserID[0];
1328
1329	pLib->line_parse_entry_last[Channel] = pLib->cur_parse_entry - 1;
1330}
1331
1332static void diva_create_fax_parse_table(diva_strace_context_t *pLib,
1333					int Channel) {
1334	diva_trace_fax_state_t *pFax = &pLib->lines[Channel].fax;
1335	int nr = Channel + 1;
1336
1337	if ((pLib->cur_parse_entry + FAX_PARSE_ENTRIES) >= pLib->parse_entries) {
1338		diva_trace_error(pLib, -1, __FILE__, __LINE__);
1339		return;
1340	}
1341	pFax->ChannelNumber = nr;
1342
1343	pLib->fax_parse_entry_first[Channel] = pLib->cur_parse_entry;
1344
1345	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1346		"State\\B%d\\FAX\\Event", nr);
1347	pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Event;
1348
1349	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1350		"State\\B%d\\FAX\\Page Counter", nr);
1351	pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Page_Counter;
1352
1353	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1354		"State\\B%d\\FAX\\Features", nr);
1355	pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Features;
1356
1357	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1358		"State\\B%d\\FAX\\Station ID", nr);
1359	pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Station_ID[0];
1360
1361	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1362		"State\\B%d\\FAX\\Subaddress", nr);
1363	pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Subaddress[0];
1364
1365	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1366		"State\\B%d\\FAX\\Password", nr);
1367	pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Password[0];
1368
1369	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1370		"State\\B%d\\FAX\\Speed", nr);
1371	pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Speed;
1372
1373	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1374		"State\\B%d\\FAX\\Resolution", nr);
1375	pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Resolution;
1376
1377	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1378		"State\\B%d\\FAX\\Paper Width", nr);
1379	pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Paper_Width;
1380
1381	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1382		"State\\B%d\\FAX\\Paper Length", nr);
1383	pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Paper_Length;
1384
1385	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1386		"State\\B%d\\FAX\\Scanline Time", nr);
1387	pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Scanline_Time;
1388
1389	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1390		"State\\B%d\\FAX\\Disc Reason", nr);
1391	pLib->parse_table[pLib->cur_parse_entry++].variable = &pFax->Disc_Reason;
1392
1393	pLib->fax_parse_entry_last[Channel] = pLib->cur_parse_entry - 1;
1394}
1395
1396static void diva_create_modem_parse_table(diva_strace_context_t *pLib,
1397					  int Channel) {
1398	diva_trace_modem_state_t *pModem = &pLib->lines[Channel].modem;
1399	int nr = Channel + 1;
1400
1401	if ((pLib->cur_parse_entry + MODEM_PARSE_ENTRIES) >= pLib->parse_entries) {
1402		diva_trace_error(pLib, -1, __FILE__, __LINE__);
1403		return;
1404	}
1405	pModem->ChannelNumber = nr;
1406
1407	pLib->modem_parse_entry_first[Channel] = pLib->cur_parse_entry;
1408
1409	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1410		"State\\B%d\\Modem\\Event", nr);
1411	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->Event;
1412
1413	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1414		"State\\B%d\\Modem\\Norm", nr);
1415	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->Norm;
1416
1417	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1418		"State\\B%d\\Modem\\Options", nr);
1419	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->Options;
1420
1421	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1422		"State\\B%d\\Modem\\TX Speed", nr);
1423	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->TxSpeed;
1424
1425	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1426		"State\\B%d\\Modem\\RX Speed", nr);
1427	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->RxSpeed;
1428
1429	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1430		"State\\B%d\\Modem\\Roundtrip ms", nr);
1431	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->RoundtripMsec;
1432
1433	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1434		"State\\B%d\\Modem\\Symbol Rate", nr);
1435	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->SymbolRate;
1436
1437	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1438		"State\\B%d\\Modem\\RX Level dBm", nr);
1439	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->RxLeveldBm;
1440
1441	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1442		"State\\B%d\\Modem\\Echo Level dBm", nr);
1443	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->EchoLeveldBm;
1444
1445	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1446		"State\\B%d\\Modem\\SNR dB", nr);
1447	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->SNRdb;
1448
1449	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1450		"State\\B%d\\Modem\\MAE", nr);
1451	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->MAE;
1452
1453	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1454		"State\\B%d\\Modem\\Local Retrains", nr);
1455	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->LocalRetrains;
1456
1457	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1458		"State\\B%d\\Modem\\Remote Retrains", nr);
1459	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->RemoteRetrains;
1460
1461	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1462		"State\\B%d\\Modem\\Local Resyncs", nr);
1463	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->LocalResyncs;
1464
1465	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1466		"State\\B%d\\Modem\\Remote Resyncs", nr);
1467	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->RemoteResyncs;
1468
1469	sprintf(pLib->parse_table[pLib->cur_parse_entry].path,
1470		"State\\B%d\\Modem\\Disc Reason", nr);
1471	pLib->parse_table[pLib->cur_parse_entry++].variable = &pModem->DiscReason;
1472
1473	pLib->modem_parse_entry_last[Channel] = pLib->cur_parse_entry - 1;
1474}
1475
1476static void diva_create_parse_table(diva_strace_context_t *pLib) {
1477	int i;
1478
1479	for (i = 0; i < pLib->Channels; i++) {
1480		diva_create_line_parse_table(pLib, i);
1481		diva_create_modem_parse_table(pLib, i);
1482		diva_create_fax_parse_table(pLib, i);
1483	}
1484
1485	pLib->statistic_parse_first = pLib->cur_parse_entry;
1486
1487	/*
1488	  Outgoing Calls
1489	*/
1490	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1491	       "Statistics\\Outgoing Calls\\Calls");
1492	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1493		&pLib->InterfaceStat.outg.Calls;
1494
1495	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1496	       "Statistics\\Outgoing Calls\\Connected");
1497	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1498		&pLib->InterfaceStat.outg.Connected;
1499
1500	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1501	       "Statistics\\Outgoing Calls\\User Busy");
1502	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1503		&pLib->InterfaceStat.outg.User_Busy;
1504
1505	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1506	       "Statistics\\Outgoing Calls\\No Answer");
1507	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1508		&pLib->InterfaceStat.outg.No_Answer;
1509
1510	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1511	       "Statistics\\Outgoing Calls\\Wrong Number");
1512	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1513		&pLib->InterfaceStat.outg.Wrong_Number;
1514
1515	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1516	       "Statistics\\Outgoing Calls\\Call Rejected");
1517	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1518		&pLib->InterfaceStat.outg.Call_Rejected;
1519
1520	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1521	       "Statistics\\Outgoing Calls\\Other Failures");
1522	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1523		&pLib->InterfaceStat.outg.Other_Failures;
1524
1525	/*
1526	  Incoming Calls
1527	*/
1528	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1529	       "Statistics\\Incoming Calls\\Calls");
1530	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1531		&pLib->InterfaceStat.inc.Calls;
1532
1533	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1534	       "Statistics\\Incoming Calls\\Connected");
1535	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1536		&pLib->InterfaceStat.inc.Connected;
1537
1538	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1539	       "Statistics\\Incoming Calls\\User Busy");
1540	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1541		&pLib->InterfaceStat.inc.User_Busy;
1542
1543	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1544	       "Statistics\\Incoming Calls\\Call Rejected");
1545	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1546		&pLib->InterfaceStat.inc.Call_Rejected;
1547
1548	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1549	       "Statistics\\Incoming Calls\\Wrong Number");
1550	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1551		&pLib->InterfaceStat.inc.Wrong_Number;
1552
1553	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1554	       "Statistics\\Incoming Calls\\Incompatible Dst");
1555	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1556		&pLib->InterfaceStat.inc.Incompatible_Dst;
1557
1558	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1559	       "Statistics\\Incoming Calls\\Out of Order");
1560	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1561		&pLib->InterfaceStat.inc.Out_of_Order;
1562
1563	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1564	       "Statistics\\Incoming Calls\\Ignored");
1565	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1566		&pLib->InterfaceStat.inc.Ignored;
1567
1568	/*
1569	  Modem Statistics
1570	*/
1571	pLib->mdm_statistic_parse_first = pLib->cur_parse_entry;
1572
1573	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1574	       "Statistics\\Modem\\Disc Normal");
1575	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1576		&pLib->InterfaceStat.mdm.Disc_Normal;
1577
1578	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1579	       "Statistics\\Modem\\Disc Unspecified");
1580	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1581		&pLib->InterfaceStat.mdm.Disc_Unspecified;
1582
1583	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1584	       "Statistics\\Modem\\Disc Busy Tone");
1585	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1586		&pLib->InterfaceStat.mdm.Disc_Busy_Tone;
1587
1588	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1589	       "Statistics\\Modem\\Disc Congestion");
1590	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1591		&pLib->InterfaceStat.mdm.Disc_Congestion;
1592
1593	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1594	       "Statistics\\Modem\\Disc Carr. Wait");
1595	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1596		&pLib->InterfaceStat.mdm.Disc_Carr_Wait;
1597
1598	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1599	       "Statistics\\Modem\\Disc Trn Timeout");
1600	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1601		&pLib->InterfaceStat.mdm.Disc_Trn_Timeout;
1602
1603	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1604	       "Statistics\\Modem\\Disc Incompat.");
1605	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1606		&pLib->InterfaceStat.mdm.Disc_Incompat;
1607
1608	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1609	       "Statistics\\Modem\\Disc Frame Rej.");
1610	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1611		&pLib->InterfaceStat.mdm.Disc_Frame_Rej;
1612
1613	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1614	       "Statistics\\Modem\\Disc V42bis");
1615	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1616		&pLib->InterfaceStat.mdm.Disc_V42bis;
1617
1618	pLib->mdm_statistic_parse_last  = pLib->cur_parse_entry - 1;
1619
1620	/*
1621	  Fax Statistics
1622	*/
1623	pLib->fax_statistic_parse_first = pLib->cur_parse_entry;
1624
1625	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1626	       "Statistics\\FAX\\Disc Normal");
1627	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1628		&pLib->InterfaceStat.fax.Disc_Normal;
1629
1630	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1631	       "Statistics\\FAX\\Disc Not Ident.");
1632	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1633		&pLib->InterfaceStat.fax.Disc_Not_Ident;
1634
1635	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1636	       "Statistics\\FAX\\Disc No Response");
1637	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1638		&pLib->InterfaceStat.fax.Disc_No_Response;
1639
1640	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1641	       "Statistics\\FAX\\Disc Retries");
1642	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1643		&pLib->InterfaceStat.fax.Disc_Retries;
1644
1645	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1646	       "Statistics\\FAX\\Disc Unexp. Msg.");
1647	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1648		&pLib->InterfaceStat.fax.Disc_Unexp_Msg;
1649
1650	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1651	       "Statistics\\FAX\\Disc No Polling.");
1652	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1653		&pLib->InterfaceStat.fax.Disc_No_Polling;
1654
1655	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1656	       "Statistics\\FAX\\Disc Training");
1657	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1658		&pLib->InterfaceStat.fax.Disc_Training;
1659
1660	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1661	       "Statistics\\FAX\\Disc Unexpected");
1662	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1663		&pLib->InterfaceStat.fax.Disc_Unexpected;
1664
1665	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1666	       "Statistics\\FAX\\Disc Application");
1667	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1668		&pLib->InterfaceStat.fax.Disc_Application;
1669
1670	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1671	       "Statistics\\FAX\\Disc Incompat.");
1672	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1673		&pLib->InterfaceStat.fax.Disc_Incompat;
1674
1675	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1676	       "Statistics\\FAX\\Disc No Command");
1677	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1678		&pLib->InterfaceStat.fax.Disc_No_Command;
1679
1680	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1681	       "Statistics\\FAX\\Disc Long Msg");
1682	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1683		&pLib->InterfaceStat.fax.Disc_Long_Msg;
1684
1685	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1686	       "Statistics\\FAX\\Disc Supervisor");
1687	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1688		&pLib->InterfaceStat.fax.Disc_Supervisor;
1689
1690	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1691	       "Statistics\\FAX\\Disc SUB SEP PWD");
1692	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1693		&pLib->InterfaceStat.fax.Disc_SUB_SEP_PWD;
1694
1695	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1696	       "Statistics\\FAX\\Disc Invalid Msg");
1697	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1698		&pLib->InterfaceStat.fax.Disc_Invalid_Msg;
1699
1700	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1701	       "Statistics\\FAX\\Disc Page Coding");
1702	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1703		&pLib->InterfaceStat.fax.Disc_Page_Coding;
1704
1705	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1706	       "Statistics\\FAX\\Disc App Timeout");
1707	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1708		&pLib->InterfaceStat.fax.Disc_App_Timeout;
1709
1710	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1711	       "Statistics\\FAX\\Disc Unspecified");
1712	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1713		&pLib->InterfaceStat.fax.Disc_Unspecified;
1714
1715	pLib->fax_statistic_parse_last  = pLib->cur_parse_entry - 1;
1716
1717	/*
1718	  B-Layer1"
1719	*/
1720	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1721	       "Statistics\\B-Layer1\\X-Frames");
1722	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1723		&pLib->InterfaceStat.b1.X_Frames;
1724
1725	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1726	       "Statistics\\B-Layer1\\X-Bytes");
1727	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1728		&pLib->InterfaceStat.b1.X_Bytes;
1729
1730	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1731	       "Statistics\\B-Layer1\\X-Errors");
1732	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1733		&pLib->InterfaceStat.b1.X_Errors;
1734
1735	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1736	       "Statistics\\B-Layer1\\R-Frames");
1737	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1738		&pLib->InterfaceStat.b1.R_Frames;
1739
1740	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1741	       "Statistics\\B-Layer1\\R-Bytes");
1742	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1743		&pLib->InterfaceStat.b1.R_Bytes;
1744
1745	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1746	       "Statistics\\B-Layer1\\R-Errors");
1747	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1748		&pLib->InterfaceStat.b1.R_Errors;
1749
1750	/*
1751	  B-Layer2
1752	*/
1753	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1754	       "Statistics\\B-Layer2\\X-Frames");
1755	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1756		&pLib->InterfaceStat.b2.X_Frames;
1757
1758	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1759	       "Statistics\\B-Layer2\\X-Bytes");
1760	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1761		&pLib->InterfaceStat.b2.X_Bytes;
1762
1763	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1764	       "Statistics\\B-Layer2\\X-Errors");
1765	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1766		&pLib->InterfaceStat.b2.X_Errors;
1767
1768	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1769	       "Statistics\\B-Layer2\\R-Frames");
1770	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1771		&pLib->InterfaceStat.b2.R_Frames;
1772
1773	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1774	       "Statistics\\B-Layer2\\R-Bytes");
1775	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1776		&pLib->InterfaceStat.b2.R_Bytes;
1777
1778	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1779	       "Statistics\\B-Layer2\\R-Errors");
1780	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1781		&pLib->InterfaceStat.b2.R_Errors;
1782
1783	/*
1784	  D-Layer1
1785	*/
1786	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1787	       "Statistics\\D-Layer1\\X-Frames");
1788	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1789		&pLib->InterfaceStat.d1.X_Frames;
1790
1791	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1792	       "Statistics\\D-Layer1\\X-Bytes");
1793	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1794		&pLib->InterfaceStat.d1.X_Bytes;
1795
1796	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1797	       "Statistics\\D-Layer1\\X-Errors");
1798	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1799		&pLib->InterfaceStat.d1.X_Errors;
1800
1801	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1802	       "Statistics\\D-Layer1\\R-Frames");
1803	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1804		&pLib->InterfaceStat.d1.R_Frames;
1805
1806	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1807	       "Statistics\\D-Layer1\\R-Bytes");
1808	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1809		&pLib->InterfaceStat.d1.R_Bytes;
1810
1811	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1812	       "Statistics\\D-Layer1\\R-Errors");
1813	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1814		&pLib->InterfaceStat.d1.R_Errors;
1815
1816	/*
1817	  D-Layer2
1818	*/
1819	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1820	       "Statistics\\D-Layer2\\X-Frames");
1821	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1822		&pLib->InterfaceStat.d2.X_Frames;
1823
1824	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1825	       "Statistics\\D-Layer2\\X-Bytes");
1826	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1827		&pLib->InterfaceStat.d2.X_Bytes;
1828
1829	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1830	       "Statistics\\D-Layer2\\X-Errors");
1831	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1832		&pLib->InterfaceStat.d2.X_Errors;
1833
1834	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1835	       "Statistics\\D-Layer2\\R-Frames");
1836	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1837		&pLib->InterfaceStat.d2.R_Frames;
1838
1839	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1840	       "Statistics\\D-Layer2\\R-Bytes");
1841	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1842		&pLib->InterfaceStat.d2.R_Bytes;
1843
1844	strcpy(pLib->parse_table[pLib->cur_parse_entry].path,
1845	       "Statistics\\D-Layer2\\R-Errors");
1846	pLib->parse_table[pLib->cur_parse_entry++].variable = \
1847		&pLib->InterfaceStat.d2.R_Errors;
1848
1849
1850	pLib->statistic_parse_last  = pLib->cur_parse_entry - 1;
1851}
1852
1853static void diva_trace_error(diva_strace_context_t *pLib,
1854			     int error, const char *file, int line) {
1855	if (pLib->user_proc_table.error_notify_proc) {
1856		(*(pLib->user_proc_table.error_notify_proc))(\
1857			pLib->user_proc_table.user_context,
1858			&pLib->instance, pLib->Adapter,
1859			error, file, line);
1860	}
1861}
1862
1863/*
1864  Delivery notification to user
1865*/
1866static void diva_trace_notify_user(diva_strace_context_t *pLib,
1867				   int Channel,
1868				   int notify_subject) {
1869	if (pLib->user_proc_table.notify_proc) {
1870		(*(pLib->user_proc_table.notify_proc))(pLib->user_proc_table.user_context,
1871						       &pLib->instance,
1872						       pLib->Adapter,
1873						       &pLib->lines[Channel],
1874						       notify_subject);
1875	}
1876}
1877
1878/*
1879  Read variable value to they destination based on the variable type
1880*/
1881static int diva_trace_read_variable(diva_man_var_header_t *pVar,
1882				    void *variable) {
1883	switch (pVar->type) {
1884	case 0x03: /* MI_ASCIIZ - syting                               */
1885		return (diva_strace_read_asz(pVar, (char *)variable));
1886	case 0x04: /* MI_ASCII  - string                               */
1887		return (diva_strace_read_asc(pVar, (char *)variable));
1888	case 0x05: /* MI_NUMBER - counted sequence of bytes            */
1889		return (diva_strace_read_ie(pVar, (diva_trace_ie_t *)variable));
1890	case 0x81: /* MI_INT    - signed integer                       */
1891		return (diva_strace_read_int(pVar, (int *)variable));
1892	case 0x82: /* MI_UINT   - unsigned integer                     */
1893		return (diva_strace_read_uint(pVar, (dword *)variable));
1894	case 0x83: /* MI_HINT   - unsigned integer, hex representetion */
1895		return (diva_strace_read_uint(pVar, (dword *)variable));
1896	case 0x87: /* MI_BITFLD - unsigned integer, bit representation */
1897		return (diva_strace_read_uint(pVar, (dword *)variable));
1898	}
1899
1900	/*
1901	  This type of variable is not handled, indicate error
1902	  Or one problem in management interface, or in application recodeing
1903	  table, or this application should handle it.
1904	*/
1905	return (-1);
1906}
1907
1908/*
1909  Read signed integer to destination
1910*/
1911static int diva_strace_read_int(diva_man_var_header_t *pVar, int *var) {
1912	byte *ptr = (char *)&pVar->path_length;
1913	int value;
1914
1915	ptr += (pVar->path_length + 1);
1916
1917	switch (pVar->value_length) {
1918	case 1:
1919		value = *(char *)ptr;
1920		break;
1921
1922	case 2:
1923		value = (short)GET_WORD(ptr);
1924		break;
1925
1926	case 4:
1927		value = (int)GET_DWORD(ptr);
1928		break;
1929
1930	default:
1931		return (-1);
1932	}
1933
1934	*var = value;
1935
1936	return (0);
1937}
1938
1939static int diva_strace_read_uint(diva_man_var_header_t *pVar, dword *var) {
1940	byte *ptr = (char *)&pVar->path_length;
1941	dword value;
1942
1943	ptr += (pVar->path_length + 1);
1944
1945	switch (pVar->value_length) {
1946	case 1:
1947		value = (byte)(*ptr);
1948		break;
1949
1950	case 2:
1951		value = (word)GET_WORD(ptr);
1952		break;
1953
1954	case 3:
1955		value  = (dword)GET_DWORD(ptr);
1956		value &= 0x00ffffff;
1957		break;
1958
1959	case 4:
1960		value = (dword)GET_DWORD(ptr);
1961		break;
1962
1963	default:
1964		return (-1);
1965	}
1966
1967	*var = value;
1968
1969	return (0);
1970}
1971
1972/*
1973  Read zero terminated ASCII string
1974*/
1975static int diva_strace_read_asz(diva_man_var_header_t *pVar, char *var) {
1976	char *ptr = (char *)&pVar->path_length;
1977	int length;
1978
1979	ptr += (pVar->path_length + 1);
1980
1981	if (!(length = pVar->value_length)) {
1982		length = strlen(ptr);
1983	}
1984	memcpy(var, ptr, length);
1985	var[length] = 0;
1986
1987	return (0);
1988}
1989
1990/*
1991  Read counted (with leading length byte) ASCII string
1992*/
1993static int diva_strace_read_asc(diva_man_var_header_t *pVar, char *var) {
1994	char *ptr = (char *)&pVar->path_length;
1995
1996	ptr += (pVar->path_length + 1);
1997	memcpy(var, ptr + 1, *ptr);
1998	var[(int)*ptr] = 0;
1999
2000	return (0);
2001}
2002
2003/*
2004  Read one information element - i.e. one string of byte values with
2005  one length byte in front
2006*/
2007static int diva_strace_read_ie(diva_man_var_header_t *pVar,
2008			       diva_trace_ie_t *var) {
2009	char *ptr = (char *)&pVar->path_length;
2010
2011	ptr += (pVar->path_length + 1);
2012
2013	var->length = *ptr;
2014	memcpy(&var->data[0], ptr + 1, *ptr);
2015
2016	return (0);
2017}
2018
2019static int SuperTraceSetAudioTap(void *hLib, int Channel, int on) {
2020	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2021
2022	if ((Channel < 1) || (Channel > pLib->Channels)) {
2023		return (-1);
2024	}
2025	Channel--;
2026
2027	if (on) {
2028		pLib->audio_tap_mask |=  (1L << Channel);
2029	} else {
2030		pLib->audio_tap_mask &= ~(1L << Channel);
2031	}
2032
2033	/*
2034	  EYE patterns have TM_M_DATA set as additional
2035	  condition
2036	*/
2037	if (pLib->audio_tap_mask) {
2038		pLib->trace_event_mask |= TM_M_DATA;
2039	} else {
2040		pLib->trace_event_mask &= ~TM_M_DATA;
2041	}
2042
2043	return (ScheduleNextTraceRequest(pLib));
2044}
2045
2046static int SuperTraceSetBChannel(void *hLib, int Channel, int on) {
2047	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2048
2049	if ((Channel < 1) || (Channel > pLib->Channels)) {
2050		return (-1);
2051	}
2052	Channel--;
2053
2054	if (on) {
2055		pLib->bchannel_trace_mask |=  (1L << Channel);
2056	} else {
2057		pLib->bchannel_trace_mask &= ~(1L << Channel);
2058	}
2059
2060	return (ScheduleNextTraceRequest(pLib));
2061}
2062
2063static int SuperTraceSetDChannel(void *hLib, int on) {
2064	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2065
2066	if (on) {
2067		pLib->trace_event_mask |= (TM_D_CHAN | TM_C_COMM | TM_DL_ERR | TM_LAYER1);
2068	} else {
2069		pLib->trace_event_mask &= ~(TM_D_CHAN | TM_C_COMM | TM_DL_ERR | TM_LAYER1);
2070	}
2071
2072	return (ScheduleNextTraceRequest(pLib));
2073}
2074
2075static int SuperTraceSetInfo(void *hLib, int on) {
2076	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2077
2078	if (on) {
2079		pLib->trace_event_mask |= TM_STRING;
2080	} else {
2081		pLib->trace_event_mask &= ~TM_STRING;
2082	}
2083
2084	return (ScheduleNextTraceRequest(pLib));
2085}
2086
2087static int SuperTraceClearCall(void *hLib, int Channel) {
2088	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2089
2090	if ((Channel < 1) || (Channel > pLib->Channels)) {
2091		return (-1);
2092	}
2093	Channel--;
2094
2095	pLib->clear_call_command |= (1L << Channel);
2096
2097	return (ScheduleNextTraceRequest(pLib));
2098}
2099
2100/*
2101  Parse and update cumulative statistice
2102*/
2103static int diva_ifc_statistics(diva_strace_context_t *pLib,
2104			       diva_man_var_header_t *pVar) {
2105	diva_man_var_header_t *cur;
2106	int i, one_updated = 0, mdm_updated = 0, fax_updated = 0;
2107
2108	for (i  = pLib->statistic_parse_first; i <= pLib->statistic_parse_last; i++) {
2109		if ((cur = find_var(pVar, pLib->parse_table[i].path))) {
2110			if (diva_trace_read_variable(cur, pLib->parse_table[i].variable)) {
2111				diva_trace_error(pLib, -3 , __FILE__, __LINE__);
2112				return (-1);
2113			}
2114			one_updated = 1;
2115			if ((i >= pLib->mdm_statistic_parse_first) && (i <= pLib->mdm_statistic_parse_last)) {
2116				mdm_updated = 1;
2117			}
2118			if ((i >= pLib->fax_statistic_parse_first) && (i <= pLib->fax_statistic_parse_last)) {
2119				fax_updated = 1;
2120			}
2121		}
2122	}
2123
2124	/*
2125	  We do not use first event to notify user - this is the event that is
2126	  generated as result of EVENT ON operation and is used only to initialize
2127	  internal variables of application
2128	*/
2129	if (mdm_updated) {
2130		diva_trace_notify_user(pLib, 0, DIVA_SUPER_TRACE_NOTIFY_MDM_STAT_CHANGE);
2131	} else if (fax_updated) {
2132		diva_trace_notify_user(pLib, 0, DIVA_SUPER_TRACE_NOTIFY_FAX_STAT_CHANGE);
2133	} else if (one_updated) {
2134		diva_trace_notify_user(pLib, 0, DIVA_SUPER_TRACE_NOTIFY_STAT_CHANGE);
2135	}
2136
2137	return (one_updated ? 0 : -1);
2138}
2139
2140static int SuperTraceGetOutgoingCallStatistics(void *hLib) {
2141	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2142	pLib->outgoing_ifc_stats = 1;
2143	return (ScheduleNextTraceRequest(pLib));
2144}
2145
2146static int SuperTraceGetIncomingCallStatistics(void *hLib) {
2147	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2148	pLib->incoming_ifc_stats = 1;
2149	return (ScheduleNextTraceRequest(pLib));
2150}
2151
2152static int SuperTraceGetModemStatistics(void *hLib) {
2153	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2154	pLib->modem_ifc_stats = 1;
2155	return (ScheduleNextTraceRequest(pLib));
2156}
2157
2158static int SuperTraceGetFaxStatistics(void *hLib) {
2159	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2160	pLib->fax_ifc_stats = 1;
2161	return (ScheduleNextTraceRequest(pLib));
2162}
2163
2164static int SuperTraceGetBLayer1Statistics(void *hLib) {
2165	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2166	pLib->b1_ifc_stats = 1;
2167	return (ScheduleNextTraceRequest(pLib));
2168}
2169
2170static int SuperTraceGetBLayer2Statistics(void *hLib) {
2171	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2172	pLib->b2_ifc_stats = 1;
2173	return (ScheduleNextTraceRequest(pLib));
2174}
2175
2176static int SuperTraceGetDLayer1Statistics(void *hLib) {
2177	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2178	pLib->d1_ifc_stats = 1;
2179	return (ScheduleNextTraceRequest(pLib));
2180}
2181
2182static int SuperTraceGetDLayer2Statistics(void *hLib) {
2183	diva_strace_context_t *pLib = (diva_strace_context_t *)hLib;
2184	pLib->d2_ifc_stats = 1;
2185	return (ScheduleNextTraceRequest(pLib));
2186}
2187
2188dword DivaSTraceGetMemotyRequirement(int channels) {
2189	dword parse_entries = (MODEM_PARSE_ENTRIES + FAX_PARSE_ENTRIES + \
2190			       STAT_PARSE_ENTRIES + \
2191			       LINE_PARSE_ENTRIES + 1) * channels;
2192	return (sizeof(diva_strace_context_t) + \
2193		(parse_entries * sizeof(diva_strace_path2action_t)));
2194}
2195